hooks - Hook manager¶
Overview¶
firebird.base.hooks
¶
This module provides a general framework for callbacks and "hookable" events, implementing a variation of the publish-subscribe pattern. It allows different parts of an application to register interest in events triggered by specific objects or classes and execute custom code (callbacks) when those events occur.
Architecture¶
The callback extension mechanism is based on the following:
- The
Event sourceprovides one or more "hookable events" that work like connection points. The event source represents "origin of event" and is always identified by class, class instance or name. Event sources that are identified by classes (or their instances) must be registered along with events they provide. Eventis typically linked to particular event source, but it's not mandatory and it's possible to define global events. Event is represented as value of any type, that must be unique in used context (particular event source or global). Each event should be properly documented along with required signature for callback function.Event provideris a class or function that implements the event for event source, and asks the hook_manager for list of event consumers (callbacks) registered for particular event and source.Event consumeris a function or class method that implements the callback for particular event. The callback must be registered in hook_manager before it could be called by event providers.
The architecture supports multiple usage strategies:
- If event provider uses class instance to identify the event source, it's possible to register callbacks to all instances (by registering to class), or particular instance(s).
- It's possible to register callback to particular instance by name, if instance is associated with name by register_name function.
- It's possible to register callback to ANY event from particular
source, or particular event from
ANYsource, or even toANYevent fromANYsource.
Example¶
from __future__ import annotations
from enum import Enum, auto
from firebird.base.types import *
from firebird.base.hooks import hook_manager
class MyEvents(Enum):
"Sample definition of events"
CREATE = auto()
ACTION = auto()
class MyHookable:
"Example of hookable class, i.e. a class that calls hooks registered for events."
def __init__(self, name: str):
self.name: str = name
for hook in hook_manager.get_callbacks(MyEvents.CREATE, self):
try:
hook(self, MyEvents.CREATE)
except Exception as e:
print(f"{self.name}.CREATE hook call outcome: ERROR ({e.args[0]})")
else:
print(f"{self.name}.CREATE hook call outcome: OK")
def action(self):
print(f"{self.name}.ACTION!")
for hook in hook_manager.get_callbacks(MyEvents.ACTION, self):
try:
hook(self, MyEvents.ACTION)
except Exception as e:
print(f"{self.name}.ACTION hook call outcome: ERROR ({e.args[0]})")
else:
print(f"{self.name}.ACTION hook call outcome: OK")
class MyHook:
"Example of hook implementation"
def __init__(self, name: str):
self.name: str = name
def callback(self, subject: MyHookable, event: MyEvents):
print(f"Hook {self.name} event {event.name} called by {subject.name}")
def err_callback(self, subject: MyHookable, event: MyEvents):
self.callback(subject, event)
raise Exception("Error in hook")
# Example code that installs and uses hooks
hook_manager.register_class(MyHookable, MyEvents)
hook_A: MyHook = MyHook('Hook-A')
hook_B: MyHook = MyHook('Hook-B')
hook_C: MyHook = MyHook('Hook-C')
print("Install hooks")
hook_manager.add_hook(MyEvents.CREATE, MyHookable, hook_A.callback)
hook_manager.add_hook(MyEvents.CREATE, MyHookable, hook_B.err_callback)
hook_manager.add_hook(MyEvents.ACTION, MyHookable, hook_C.callback)
print("Create event sources, emits CREATE")
src_A: MyHookable = MyHookable('Source-A')
src_B: MyHookable = MyHookable('Source-B')
print("Install instance hooks")
hook_manager.add_hook(MyEvents.ACTION, src_A, hook_A.callback)
hook_manager.add_hook(MyEvents.ACTION, src_B, hook_B.callback)
print("And action!")
src_A.action()
src_B.action()
Install hooks
Create event sources, emits CREATE
Hook Hook-A event CREATE called by Source-A
Source-A.CREATE hook call outcome: OK
Hook Hook-B event CREATE called by Source-A
Source-A.CREATE hook call outcome: ERROR (Error in hook)
Hook Hook-A event CREATE called by Source-B
Source-B.CREATE hook call outcome: OK
Hook Hook-B event CREATE called by Source-B
Source-B.CREATE hook call outcome: ERROR (Error in hook)
Install instance hooks
And action!
Source-A.ACTION!
Hook Hook-A event ACTION called by Source-A
Source-A.ACTION hook call outcome: OK
Hook Hook-C event ACTION called by Source-A
Source-A.ACTION hook call outcome: OK
Source-B.ACTION!
Hook Hook-B event ACTION called by Source-B
Source-B.ACTION hook call outcome: OK
Hook Hook-C event ACTION called by Source-B
Source-B.ACTION hook call outcome: OK
Flags¶
firebird.base.hooks.HookFlag
¶
Bases: Flag
Internal flags used by HookManager to optimize callback lookups.
These flags track the types of registrations present (e.g., if any
instance hooks, class hooks, or ANY_EVENT hooks exist) to potentially
speed up get_callbacks by avoiding unnecessary checks.
Source code in firebird/base/hooks.py
ANY_EVENT
class-attribute
instance-attribute
¶
A hook targets ANY event
ANY_SOURCE
class-attribute
instance-attribute
¶
A hook targets ANY source
CLASS
class-attribute
instance-attribute
¶
A hook targets a class (applies to all instances)
INSTANCE
class-attribute
instance-attribute
¶
A hook targets a specific object instance
NAME
class-attribute
instance-attribute
¶
A hook targets a registered instance name
NONE
class-attribute
instance-attribute
¶
NONE value
Functions¶
firebird.base.hooks.register_class
module-attribute
¶
Shortcut for hook_manager.register_class()
firebird.base.hooks.register_name
module-attribute
¶
shortcut for hook_manager.register_name()
- Modules hooks - Hook manager hooks Architecture
firebird.base.hooks.add_hook
module-attribute
¶
shortcut for hook_manager.add_hook()
firebird.base.hooks.get_callbacks
module-attribute
¶
shortcut for hook_manager.get_callbacks()
Classes¶
firebird.base.hooks.HookManager
¶
Bases: Singleton
Manages the registration and retrieval of hooks (callbacks).
This singleton class acts as the central registry for hookable classes, named instances, and the hooks themselves. It provides methods to add, remove, and retrieve callbacks based on event and source specifications.
Source code in firebird/base/hooks.py
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 | |
add_hook(event: Any, source: Any, callback: Callable) -> None
¶
Register a callback function (hook) for a specific event and source.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
Any
|
The event identifier the callback subscribes to. Can be |
required |
source
|
Any
|
The source of the event. Can be: |
required |
callback
|
Callable
|
The function or method to be called when the event occurs. |
required |
Important
The signature of the callback function must match the signature expected
by the code that triggers the event (the event provider). This framework
does not enforce signature matching; it's the responsibility of the event
provider and consumer documentation.
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
ValueError
|
If |
Source code in firebird/base/hooks.py
get_callbacks(event: Any, source: Any) -> list
¶
Return a list of all callbacks applicable to the specified event and source.
The method searches for matching hook registrations based on the provided
event and source, considering class hierarchy, registered names, and
the ANY sentinel for broader matches.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
Any
|
The specific event identifier being triggered. |
required |
source
|
Any
|
The source triggering the event. Can be: |
required |
Returns:
| Type | Description |
|---|---|
list
|
A list of |
list
|
is not guaranteed between different calls or manager states. |
Lookup Logic
The returned list aggregates callbacks from registrations matching:
- Specific Instance: Hooks registered for (
event,ANY,sourceinstance). - Specific Name: Hooks for (
event,ANY,sourcename) ifsourceinstance has a registered name. - Specific Class: Hooks for (
event,cls,ANY) for every classclsin thesourceinstance's Method Resolution Order (MRO) that is registered. - ANY Event on Instance: Hooks for (
ANY,ANY,sourceinstance). - ANY Event on Name: Hooks for (
ANY,ANY,sourcename`) if applicable. - ANY Event on Class: Hooks for (
ANY,cls,ANY) for applicable classesclsin the MRO. - ANY Source: Hooks for (
event,ANY,ANY) and (ANY,ANY,ANY).
Note
If source is a class or name directly, only relevant parts of the
above logic apply.
Source code in firebird/base/hooks.py
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 | |
register_class(cls: type, events: type[Enum] | set | None = None) -> None
¶
Register a class as being capable of generating hookable events.
Registration is necessary for validation when adding hooks and potentially for optimizing callback lookups.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cls
|
type
|
The class that acts as an event source. |
required |
events
|
type[Enum] | set | None
|
The set of events this class (and its instances) can trigger.
Can be specified using an |
None
|
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
Source code in firebird/base/hooks.py
register_name(instance: Any, name: str) -> None
¶
Associate a unique string name with an instance of a hookable class.
This allows registering hooks specifically for this named instance using
the name string as the source.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
instance
|
Any
|
An instance of a class previously registered via |
required |
name
|
str
|
A unique string name to assign to the instance. |
required |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
Source code in firebird/base/hooks.py
remove_all_hooks() -> None
¶
remove_hook(event: Any, source: Any, callback: Callable) -> None
¶
Remove a previously registered hook callback.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
Any
|
The event identifier used when registering the hook. |
required |
source
|
Any
|
The hookable class, instance, name, or |
required |
callback
|
Callable
|
The specific callback function instance that was registered. |
required |
Important
To successfully remove a hook, all arguments (event, source, callback)
must exactly match the values used in the original add_hook() call.
Comparing function objects requires using the same function object.
This method does nothing if no matching hook registration is found.
Source code in firebird/base/hooks.py
reset() -> None
¶
Removes all installed hooks and unregisters all hookable classes and instances.
Globals¶
firebird.base.hooks.hook_manager: HookManager
module-attribute
¶
Hook manager singleton instance.
- Modules hooks - Hook manager hooks Architecture
Dataclasses¶
firebird.base.hooks.Hook
dataclass
¶
Bases: Distinct
Represents a registered hook subscription.
Instances of this class store the details of a callback registered
for a specific event and source combination within the HookManager.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event
|
Any
|
The specific event this hook subscribes to (can be |
required |
cls
|
type
|
The specific class this hook targets. |
ANY
|
instance
|
Any
|
The specific instance or instance name this hook targets. |
ANY
|
callbacks
|
list[Callable]
|
A list of callable functions to be executed when the specified event occurs for the specified source. |
list()
|
Source code in firebird/base/hooks.py
callbacks: list[Callable]
class-attribute
instance-attribute
¶
A list of callable functions to be executed when the specified event occurs for the specified source.
cls: type
class-attribute
instance-attribute
¶
The specific class this hook targets. ANY if targeting an instance/name directly or globally.
event: Any
instance-attribute
¶
The specific event this hook subscribes to (can be ANY).
instance: Any
class-attribute
instance-attribute
¶
The specific instance or instance name this hook targets. ANY if targeting a class or globally.
get_key() -> Any
¶
Returns the unique key for this hook registration used by the Registry.
The key is a tuple of (event, class, instance/name).