djblets.extensions.hooks¶
Base support and implementations for extension hooks.
Extension hooks allow applications to define formal ways to inject logic, behavior, or more into part of the application.
This module provides the base support for defining an extension hook, through
ExtensionHook
and ExtensionHookPoint
, along with
a utility mixin, AppliesToURLMixin
.
It also provides some built-in hooks for applications and extensions to use:
- class ExtensionHook(extension: Extension, *args, **kwargs)[source]¶
Bases:
object
The base class for a hook into some part of an application.
ExtensionHooks are classes that can hook into an
ExtensionHookPoint
to provide some level of functionality in an application. A consuming application should provide a subclass of ExtensionHook that will provide functions for getting data or anything else that’s needed. Extensions may then subclass or initialize that specific ExtensionHook.A base ExtensionHook subclass must use
ExtensionHookPoint
as a metaclass. All hooks deriving from that subclass will be registered along with that hook point.Example
from djblets.extensions.hooks import (ExtensionHook, ExtensionHookPoint) from myproject.nav import register_thing, unregister_thing_id class ThingHook(ExtensionHook, metaclass=ExtensionHookPoint): def initialize(self, thing_id): self.thing_id = thing_id register_thing(self.thing_id) def shutdown(self): unregister_thing(self.thing_id)
Changed in version 1.0: Starting with Djblets 1.0, extension hooks should implement the
initialize()
method to handle any initialization. It no longer needs to call the parentshutdown()
method, either. However, to retain compatibility with older versions, they may still override__init__()
and may call the parentshutdown()
. See those methods for more details.- extension¶
The parent extension, or another object that can act as a hook owner.
- hook_state¶
The state of the hook. This will be one of
HOOK_STATE_DISABLED
,HOOK_STATE_ENABLED
,HOOK_STATE_DISABLING
, orHOOK_STATE_ENABLING
.- Type:
- remove_hook: Callable[[ExtensionHook, ExtensionHook], None]¶
- __init__(extension: Extension, *args, **kwargs) None [source]¶
Initialize the ExtensionHook.
This is called when creating an instance of the hook. This will call
enable_hook()
with the provided arguments, beginning the internal initialization process. That will then callinitialize()
, which is responsible for any initialization of state in the subclass.Subclasses should override
initialize()
in order to provide any state initialization, rather than overriding this method.Changed in version 1.0: Prior to Djblets 1.0, initialization all happened in
__init__()
. Code that needs to remain compatible with older versions should continue to do so, but otherwise this code should move toinitialize()
.- Parameters:
extension (
djblets.extensions.extension.Extension
) – The parent extension, or another object that can act as a hook owner.start_enabled (
bool
, optional) – Whether to enable the hook once constructed. This defaults toTrue
.
- initialize(*args, **kwargs) None [source]¶
Initialize the extension hook’s state.
Extension subclasses can perform any custom initialization they need here.
Any additional arguments passed to the hook during construction will be passed to this as well.
While in this function,
hook_state
will be set toHOOK_STATE_ENABLING
.By default, this does nothing.
New in version 1.0.
- Parameters:
Example
class ThingHook(ExtensionHook, metaclass=ExtensionHookPoint): def initialize(self, thing_id): self.thing_id = thing_id register_thing(self.thing_id)
- shutdown() None [source]¶
Shut down the extension.
Extension subclasses can perform any custom cleanup they need here.
While in this function,
hook_state
will be set toHOOK_STATE_DISABLING
.Changed in version 1.0: This method used to be responsible both for internal cleanup and the cleanup of the subclass. Starting in Djblets 1.0, internal cleanup has moved to
disable_hook()
. Subclasses no longer need to call the parent method unless inheriting from a mixin or anotherExtensionHook
subclass, but should continue to do so if they need to retain compatibility with older versions.Example
class ThingHook(ExtensionHook, metaclass=ExtensionHookPoint): def shutdown(self): unregister_thing(self.thing_id)
- enable_hook(*args, **kwargs) None [source]¶
Enable the ExtensionHook, beginning the initialization process.
This will register the instance of the hook and begin its initialization. It takes the same parameters that would be given during construction of the hook, allowing disabled hooks to be created again with fresh state.
Subclasses should not override this process. They should instead implement
initialize()
to handle initialization of the state of the hook.New in version 1.0.
- disable_hook(call_shutdown: bool = True) None [source]¶
Disable the hook, unregistering it from the extension.
This will unregister the hook and uninitialize it, putting it into a disabled state.
Consumers can call this if they want to turn off hooks temporarily without reconstructing the instances later. It’s also called internally when shutting down an extension.
New in version 1.0.
- Parameters:
call_shutdown (
bool
, optional) – Whether to callshutdown()
. This should always beTrue
unless called internally.
- __annotations__ = {'remove_hook': "Callable[['ExtensionHook', ExtensionHook], None]"}¶
- class ExtensionHookPoint(name, bases, attrs)[source]¶
Bases:
type
A metaclass used for base Extension Hooks.
Base
ExtensionHook
classes useExtensionHookPoint
as a metaclass. This metaclass stores the list of registered hooks that anExtensionHook
will automatically register with.- add_hook(hook)[source]¶
Adds an ExtensionHook to the list of active hooks.
This is called automatically by
ExtensionHook
.
- remove_hook(hook)[source]¶
Removes an ExtensionHook from the list of active hooks.
This is called automatically by
ExtensionHook
.
- __annotations__ = {}¶
- class AppliesToURLMixin[source]¶
Bases:
object
A mixin for hooks to allow restricting to certain URLs.
This provides an
applies_to()
function for the hook that can be used by consumers to determine if the hook should apply to the current page.- initialize(apply_to: List[str] = [], *args, **kwargs) None [source]¶
Initialize the mixin for a hook.
- Parameters:
apply_to (
list
, optional) – A list of URL names that the hook will apply to by default.
- applies_to(request: HttpRequest) bool [source]¶
Return whether or not this hook applies to the page.
This will determine whether any of the URL names provided in
apply_to
matches the current requested page.- Parameters:
request (
django.http.HttpRequest
) – The request object.- Returns:
Whether this hook applies to the page currently being rendered.
- Return type:
- class DataGridColumnsHook(extension: Extension, *args, **kwargs)[source]¶
Bases:
ExtensionHook
Adds columns to a datagrid.
This hook allows an extension to register new columns to any datagrid. These columns can be added by the user, rearranged, and sorted, like any other column.
Each column must have an id already set, and it must be unique.
- hooks = []¶
- remove_hook: Callable[[ExtensionHook, ExtensionHook], None] = <bound method ExtensionHookPoint.remove_hook of <class 'djblets.extensions.hooks.DataGridColumnsHook'>>¶
- class URLHook(extension: Extension, *args, **kwargs)[source]¶
Bases:
ExtensionHook
Custom URL hook.
A hook that installs custom URLs. These URLs reside in a project-specified parent URL.
- shutdown() None [source]¶
Shut down the extension.
Extension subclasses can perform any custom cleanup they need here.
While in this function,
hook_state
will be set toHOOK_STATE_DISABLING
.Changed in version 1.0: This method used to be responsible both for internal cleanup and the cleanup of the subclass. Starting in Djblets 1.0, internal cleanup has moved to
disable_hook()
. Subclasses no longer need to call the parent method unless inheriting from a mixin or anotherExtensionHook
subclass, but should continue to do so if they need to retain compatibility with older versions.Example
class ThingHook(ExtensionHook, metaclass=ExtensionHookPoint): def shutdown(self): unregister_thing(self.thing_id)
- hooks = []¶
- remove_hook: Callable[[ExtensionHook, ExtensionHook], None] = <bound method ExtensionHookPoint.remove_hook of <class 'djblets.extensions.hooks.URLHook'>>¶
- class SignalHook(extension: Extension, *args, **kwargs)[source]¶
Bases:
ExtensionHook
Connects to a Django signal.
This will handle connecting to a signal, calling the specified callback when fired. It will disconnect from the signal when the extension is disabled.
The callback will also be passed an extension= keyword argument pointing to the extension instance.
- initialize(signal: Signal, callback: Callable, sender: Any = None, sandbox_errors: bool = True) None [source]¶
Initialize the hook.
- Parameters:
signal (
django.dispatch.Signal
) – The signal to connect to.callback (
callable
) – The function to call when the signal is fired.sender (
object
orclass
, optional) – The sender argument to pass to the signal connection. Seesend()
for more information.sandbox_errors (
bool
, optional) – IfTrue
, errors coming fromcallback
will be sandboxed, preventing them from reaching the code that fired the signal. The error will instead be logged and then ignored.
- hooks = []¶
- remove_hook: Callable[[ExtensionHook, ExtensionHook], None] = <bound method ExtensionHookPoint.remove_hook of <class 'djblets.extensions.hooks.SignalHook'>>¶
- class TemplateHook(extension: Extension, *args, **kwargs)[source]¶
Bases:
AppliesToURLMixin
,ExtensionHook
Custom templates hook.
A hook that renders a template at hook points defined in another template.
- initialize(name: str, template_name: Optional[str] = None, apply_to: List[str] = [], extra_context: Dict[str, Any] = {}, *args, **kwargs) None [source]¶
Initialize the hook.
- Parameters:
name (
str
) – The name of the template hook point that should render this template. This is application-specific.template_name (
str
, optional) – The name of the template to render.apply_to (
list
, optional) – The list of URL names where this template should render. By default, all templates containing the template hook point will render this template.extra_context (
dict
) – Extra context to include when rendering the template.*args (
tuple
) – Additional positional arguments for future expansion.**kwargs (
dict
) – Additional keyword arguments for future expansion.
- shutdown() None [source]¶
Shut down the extension.
Extension subclasses can perform any custom cleanup they need here.
While in this function,
hook_state
will be set toHOOK_STATE_DISABLING
.Changed in version 1.0: This method used to be responsible both for internal cleanup and the cleanup of the subclass. Starting in Djblets 1.0, internal cleanup has moved to
disable_hook()
. Subclasses no longer need to call the parent method unless inheriting from a mixin or anotherExtensionHook
subclass, but should continue to do so if they need to retain compatibility with older versions.Example
class ThingHook(ExtensionHook, metaclass=ExtensionHookPoint): def shutdown(self): unregister_thing(self.thing_id)
- render_to_string(request: HttpRequest, context: Context) str [source]¶
Render the content for the hook.
By default, this renders the provided template name to a string and returns it.
- Parameters:
request (
django.http.HttpRequest
) – The HTTP request.context (
django.template.Conetxt
) – The template render context.
- Returns:
Rendered content to include in the template.
- Return type:
- get_extra_context(request: HttpRequest, context: Context) Dict[str, Any] [source]¶
Return extra context for the hook.
Subclasses can override this to provide additional context dynamically beyond what’s passed in to the constructor.
By default, an empty dictionary is returned.
- Parameters:
request (
django.http.HttpRequest
) – The HTTP request.context (
django.template.Context
) – The template render context.
- Returns:
Additional context to include when rendering the template.
- Return type:
- classmethod by_name(name: str) List[TemplateHook] [source]¶
Return template hooks by name.
- Parameters:
name (
str
) – The name of the hook point.- Returns:
A list of all template hooks that are registered for the given name.
- Return type:
list
ofTemplateHook
- __annotations__ = {'_by_name': 'Dict[str, List[TemplateHook]]', 'extra_context': 'dict', 'name': 'str', 'remove_hook': "Callable[['ExtensionHook', ExtensionHook], None]", 'template_name': 'Optional[str]'}¶
- hooks = []¶
- class BaseRegistryHook(extension: Extension, *args, **kwargs)[source]¶
Bases:
ExtensionHook
A hook for registering an item with a registry.
This hook should not be used directly. Instead, it should be subclassed with the
registry
attribute set.Subclasses must use the
ExtensionHookPoint
metaclass.- initialize(item: Any) None [source]¶
Initialize the registry hook with the item.
- Parameters:
item (
object
) – The object to register.
- __annotations__ = {'registry': 'Optional[Registry]', 'remove_hook': "Callable[['ExtensionHook', ExtensionHook], None]"}¶
- class BaseRegistryMultiItemHook(extension: Extension, *args, **kwargs)[source]¶
Bases:
ExtensionHook
A hook for registering multiple items with a registry.
This hook should not be used directly. Instead, it should be subclassed with the
registry
attribute set.Subclasses must use the
ExtensionHookPoint
metaclass.- initialize(items: List[Any]) None [source]¶
Initialize the registry hook with the list of items.
- Parameters:
items (
list
) – The list of items to register.
- __annotations__ = {'registry': 'Optional[Registry]', 'remove_hook': "Callable[['ExtensionHook', ExtensionHook], None]"}¶