Skip to content

Commit 5e82567

Browse files
committed
feat: allow override of default_hook_policy via pm constructor
Signed-off-by: Frederico Araujo <frederico.araujo@ibm.com>
1 parent aae8916 commit 5e82567

2 files changed

Lines changed: 14 additions & 22 deletions

File tree

cpex/framework/manager.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ def __init__(
108108
timeout: int = DEFAULT_PLUGIN_TIMEOUT,
109109
observability: Optional[ObservabilityProvider] = None,
110110
hook_policies: Optional[dict[str, HookPayloadPolicy]] = None,
111+
default_hook_policy: Optional[str] = None,
111112
):
112113
"""Initialize the plugin executor.
113114
@@ -116,12 +117,16 @@ def __init__(
116117
timeout: Maximum execution time per plugin in seconds.
117118
observability: Optional observability provider implementing ObservabilityProvider protocol.
118119
hook_policies: Per-hook-type payload modification policies.
120+
default_hook_policy: Fallback hook policy ("allow", "denied") when a policy is not specified
121+
for a hook type (overrides `settings.default_hook_policy`).
119122
"""
120123
self.timeout = timeout
121124
self.config = config
122125
self.observability = observability
123126
self.hook_policies: dict[str, HookPayloadPolicy] = hook_policies or {}
124-
self.default_hook_policy = DefaultHookPolicy(settings.default_hook_policy)
127+
self.default_hook_policy = DefaultHookPolicy(
128+
default_hook_policy if default_hook_policy else settings.default_hook_policy
129+
)
125130
self._runtime_disabled: set[str] = set()
126131

127132
async def execute(
@@ -885,6 +890,7 @@ def __init__(
885890
timeout: int = DEFAULT_PLUGIN_TIMEOUT,
886891
observability: Optional[ObservabilityProvider] = None,
887892
hook_policies: Optional[dict[str, HookPayloadPolicy]] = None,
893+
default_hook_policy: Optional[str] = None,
888894
):
889895
"""Initialize plugin manager.
890896
@@ -903,6 +909,8 @@ def __init__(
903909
timeout: Maximum execution time per plugin in seconds.
904910
observability: Optional observability provider implementing ObservabilityProvider protocol.
905911
hook_policies: Per-hook-type payload modification policies (injected by gateway).
912+
default_hook_policy: Fallback hook policy ("allow", "deny") when a policy is not specified
913+
for a hook type (if set, takes precedence over `settings.default_hook_policy`).
906914
907915
Examples:
908916
>>> # Initialize with configuration file
@@ -929,11 +937,10 @@ def __init__(
929937
timeout=timeout,
930938
observability=observability,
931939
hook_policies=hook_policies,
940+
default_hook_policy=default_hook_policy,
932941
)
933-
elif hook_policies:
934-
# Allow hook policies to be injected after initial Borg creation.
935-
# This handles the case where the first PluginManager instantiation
936-
# (e.g. from a service) didn't have policies, but a later one does.
942+
elif hook_policies or default_hook_policy or observability:
943+
# Allow optional arguments to be injected after initial Borg creation.
937944
with self.__lock:
938945
executor = self._get_executor()
939946
# Only update timeout if caller provided a non-default value
@@ -945,13 +952,10 @@ def __init__(
945952
logger.warning(
946953
"PluginManager: hook_policies already set; ignoring new policies (call reset() first to replace them)"
947954
)
955+
if default_hook_policy:
956+
executor.default_hook_policy = DefaultHookPolicy(default_hook_policy)
948957
if observability and not executor.observability:
949958
executor.observability = observability
950-
elif self._executor is None:
951-
# Defensive initialization for unusual state transitions in tests.
952-
with self.__lock:
953-
if self._executor is None:
954-
self._executor = PluginExecutor(config=self._config, timeout=timeout, observability=observability)
955959

956960
def _get_executor(self) -> PluginExecutor:
957961
"""Get plugin executor, creating it lazily if necessary.

tests/unit/cpex/framework/test_manager_coverage.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -468,18 +468,6 @@ def test_second_instantiation_injects_observability(self):
468468

469469
assert pm2._executor.observability is mock_obs
470470

471-
def test_defensive_executor_init_when_none(self):
472-
"""When shared state exists but _executor is None (unusual test
473-
scenario), the defensive path creates a new PluginExecutor."""
474-
pm = PluginManager()
475-
# Simulate unusual state: shared state populated but executor nulled
476-
pm._executor = None
477-
478-
# Re-instantiate without hook_policies — triggers defensive path
479-
pm2 = PluginManager()
480-
assert pm2._executor is not None
481-
assert isinstance(pm2._executor, PluginExecutor)
482-
483471

484472
# ===========================================================================
485473
# PluginManager executor property and setter (lines 605, 615, 620)

0 commit comments

Comments
 (0)