Dynamic Hooks and Filters Extension¶
The Dynamic Hooks/Filters extension allows registering callbacks from YAML instead of hardcoding registrations in plugin load(app) functions.
Overview¶
Key behavior:
Registers itself on
post_argument_parsingReads hook/filter config from YAML
Validates each callback against discovery registries
Validates configured parameters against the callback’s Pydantic parameter model
Registers validated callbacks into Cement’s hook/filter managers
Configuration Model¶
Workflow-aware structure (recommended)¶
vipr:
inference: # also works for other workflow sections
hooks:
HOOK_NAMESPACE:
- class: package.module.ClassName
method: method_name
enabled: true
weight: 0
parameters:
key: value
filters:
FILTER_NAMESPACE:
- class: package.module.ClassName
method: method_name
enabled: true
weight: 0
parameters:
key: value
Legacy fallback (still supported)¶
vipr:
hooks: {}
filters: {}
The extension aggregates hooks/filters across all vipr.<workflow>.hooks|filters sections and falls back to vipr.hooks|filters when no workflow sections are found.
Required Fields¶
Field |
Required |
Description |
|---|---|---|
|
yes |
Fully-qualified class path |
|
yes |
Method name on that class |
|
no |
Defaults to |
|
no |
Defaults to |
|
no |
Must match callback’s Pydantic parameter model |
Only class + method references are accepted. Standalone functions are not supported.
Examples¶
Example 1: Register a built-in normalizer filter¶
Decorator declaration (in code):
@discover_filter('INFERENCE_PREPROCESS_PRE_FILTER', enabled_in_config=False, weight=-10)
def normalize_filter(self, data, **kwargs):
return data
YAML activation:
vipr:
inference:
filters:
INFERENCE_PREPROCESS_PRE_FILTER:
- class: vipr.plugins.normalizers.log_normalizer.LogNormalizer
method: normalize_filter
enabled: true
weight: -10
Example 2: Register a hook with validated parameters¶
Decorator declaration (in code):
class MarginalDistributionsParams(BaseModel):
min_bins: int = 100
@discover_hook(
'INFERENCE_POSTPROCESS_PRE_PRE_FILTER_HOOK',
parameters=MarginalDistributionsParams,
enabled_in_config=False
)
def _create_marginal_distributions(self, app, data=None, **kwargs):
...
YAML activation:
vipr:
inference:
hooks:
INFERENCE_POSTPROCESS_PRE_PRE_FILTER_HOOK:
- class: vipr_reflectometry.flow_models.postprocess.marginal_distributions.MarginalDistributions
method: _create_marginal_distributions
enabled: true
weight: 0
parameters:
min_bins: 120
Example 3: Multiple callbacks with weights¶
vipr:
inference:
hooks:
INFERENCE_POSTPROCESS_PRE_PRE_FILTER_HOOK:
- class: vipr_reflectometry.flow_models.postprocess.basic_corner_plot.BasicCornerPlot
method: _create_basic_corner_plot
enabled: true
weight: 0
- class: vipr_reflectometry.flow_models.postprocess.cluster.clustering.hook.ClusterHook
method: _cluster_posterior_samples
enabled: true
weight: 1
parameters:
method: gmm
n_components: 5
n_init: 10
Security and Validation¶
1. Registry validation¶
A callback must exist in discovered hooks or filters (@discover_hook / @discover_filter).
2. Parameter schema validation¶
If YAML provides parameters, the target callback must expose an attached Pydantic model via discovery decorators. Unknown or invalid fields are rejected.
3. Content validation¶
The extension applies pattern checks to parameter values (for example shell-injection/path-traversal/python-injection patterns).
Plugin Availability Notes¶
Internal callbacks under
vipr.plugins.<name>...require the plugin to be enabled.Internal plugin config format is top-level:
plugin.normalizers:
enabled: true
For external packages (for example
vipr_reflectometry...), ensure the package is installed and importable in the active environment.
Troubleshooting¶
“Callback not in registry”¶
The configured class + method is not discovered.
Fix: add correct @discover_hook/@discover_filter declaration or update YAML path/method.
“Parameter validation failed”¶
YAML parameters do not match the callback’s Pydantic parameter model.
Fix: align parameter names/types with the discovered schema.
“Could not import class.method”¶
Import path is wrong or package/plugin is unavailable.
Fix: verify module path and install/enable the plugin.
“Dangerous pattern in parameter”¶
A parameter value matched a blocked security pattern.
Fix: review and sanitize the value.
Best Practices¶
Use class-method callbacks only.
Keep callback parameters defined via Pydantic models.
Use workflow-local config (
vipr.inference.hooks|filters) instead of global legacy structure.Use weights intentionally and document ordering in configs.
Prefer maintained example configs from plugin repositories when possible.