From b2d2e973b6b8727e00fd409b9e06d8e72b6ca708 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Tue, 11 Nov 2025 12:18:16 +0000 Subject: [PATCH] Deprecate warn_on_missing_entrypoint parameter This parameter can be easily replaced by an in-tree callback function. Signed-off-by: Stephen Finucane Change-Id: Ie7aad11d9a9c8b522de0a2b2a5101de406aa4f0c --- ...n_missing_entrypoint-d7e3bf2d4421f4cc.yaml | 8 ++++ stevedore/driver.py | 18 +++++++-- stevedore/hook.py | 16 ++++---- stevedore/named.py | 37 ++++++++++++------- 4 files changed, 55 insertions(+), 24 deletions(-) create mode 100644 releasenotes/notes/deprecate-warn_on_missing_entrypoint-d7e3bf2d4421f4cc.yaml diff --git a/releasenotes/notes/deprecate-warn_on_missing_entrypoint-d7e3bf2d4421f4cc.yaml b/releasenotes/notes/deprecate-warn_on_missing_entrypoint-d7e3bf2d4421f4cc.yaml new file mode 100644 index 0000000..ef7d33c --- /dev/null +++ b/releasenotes/notes/deprecate-warn_on_missing_entrypoint-d7e3bf2d4421f4cc.yaml @@ -0,0 +1,8 @@ +--- +deprecations: + - | + The ``warn_on_missing_entrypoint`` parameter to ``NamedExtensionManager``, + ``DriverManager``, and ``HookManager``, has been deprecated. Warnings were + already enabled by default. To disable them, instead set + ``on_load_failure_callback`` to ``None`` or provide a custom callback that + does not log warnings. diff --git a/stevedore/driver.py b/stevedore/driver.py index 31f074e..981a538 100644 --- a/stevedore/driver.py +++ b/stevedore/driver.py @@ -26,6 +26,8 @@ from .extension import ExtensionManager from .extension import ignore_conflicts from .extension import OnLoadFailureCallbackT from .named import NamedExtensionManager +from .named import OnMissingEntrypointsCallbackT +from .named import warning_on_missing_entrypoint if TYPE_CHECKING: from typing_extensions import Self @@ -52,11 +54,16 @@ class DriverManager(NamedExtensionManager[T]): an entrypoint can not be loaded. The arguments that will be provided when this is called (when an entrypoint fails to load) are (manager, entrypoint, exception) + :param on_missing_entrypoints_callback: Callback function that will be + called when one or more names cannot be found. The provided argument + will be a subset of the 'names' parameter. :param verify_requirements: **DEPRECATED** This is a no-op and will be removed in a future version. - :param warn_on_missing_entrypoint: Flag to control whether failing - to load a plugin is reported via a log mess. Only applies if - on_missing_entrypoints_callback is None. + :param warn_on_missing_entrypoint: **DEPRECATED** Flag to control whether + failing to load a plugin is reported via a log mess. Only applies if + on_missing_entrypoints_callback is None. Users should instead set + ``on_missing_entrypoints_callback`` to ``None`` if they wish to disable + logging. :param conflict_resolver: A callable that determines what to do in the event that there are multiple entrypoints in the same group with the same name. This is only used if retrieving entrypoint by name. @@ -70,8 +77,11 @@ class DriverManager(NamedExtensionManager[T]): invoke_args: tuple[Any, ...] | None = None, invoke_kwds: dict[str, Any] | None = None, on_load_failure_callback: 'OnLoadFailureCallbackT[T] | None' = None, + on_missing_entrypoints_callback: ( + OnMissingEntrypointsCallbackT | None + ) = warning_on_missing_entrypoint, verify_requirements: bool | None = None, - warn_on_missing_entrypoint: bool = True, + warn_on_missing_entrypoint: bool | None = None, *, conflict_resolver: 'ConflictResolverT[T]' = ignore_conflicts, ) -> None: diff --git a/stevedore/hook.py b/stevedore/hook.py index 3e92d60..b540c7f 100644 --- a/stevedore/hook.py +++ b/stevedore/hook.py @@ -45,9 +45,11 @@ class HookManager(NamedExtensionManager[T]): will be a subset of the 'names' parameter. :param verify_requirements: **DEPRECATED** This is a no-op and will be removed in a future version. - :param warn_on_missing_entrypoint: Flag to control whether failing - to load a plugin is reported via a log mess. Only applies if - on_missing_entrypoints_callback is None. + :param warn_on_missing_entrypoint: **DEPRECATED** Flag to control whether + failing to load a plugin is reported via a log mess. Only applies if + on_missing_entrypoints_callback is None. Users should instead set + ``on_missing_entrypoints_callback`` to ``None`` if they wish to disable + logging. :param conflict_resolver: A callable that determines what to do in the event that there are multiple entrypoints in the same group with the same name. This is only used if retrieving entrypoint by name. @@ -61,14 +63,14 @@ class HookManager(NamedExtensionManager[T]): invoke_args: tuple[Any, ...] | None = None, invoke_kwds: dict[str, Any] | None = None, on_load_failure_callback: 'OnLoadFailureCallbackT[T] | None' = None, + # NOTE(dhellmann): This default is different from the + # base class because for hooks it is less likely to + # be an error to have no entry points present. on_missing_entrypoints_callback: ( OnMissingEntrypointsCallbackT | None ) = None, verify_requirements: bool | None = None, - # NOTE(dhellmann): This default is different from the - # base class because for hooks it is less likely to - # be an error to have no entry points present. - warn_on_missing_entrypoint: bool = False, + warn_on_missing_entrypoint: bool | None = None, *, conflict_resolver: 'ConflictResolverT[T]' = ignore_conflicts, ): diff --git a/stevedore/named.py b/stevedore/named.py index 789b10a..b15039f 100644 --- a/stevedore/named.py +++ b/stevedore/named.py @@ -35,6 +35,10 @@ T = TypeVar('T') OnMissingEntrypointsCallbackT = Callable[[Iterable[str]], None] +def warning_on_missing_entrypoint(missing_names: Iterable[str]) -> None: + LOG.warning('Could not load {}'.format(', '.join(missing_names))) + + class NamedExtensionManager(ExtensionManager[T]): """Loads only the named extensions. @@ -65,9 +69,11 @@ class NamedExtensionManager(ExtensionManager[T]): will be a subset of the 'names' parameter. :param verify_requirements: **DEPRECATED** This is a no-op and will be removed in a future version. - :param warn_on_missing_entrypoint: Flag to control whether failing - to load a plugin is reported via a log mess. Only applies if - on_missing_entrypoints_callback is None. + :param warn_on_missing_entrypoint: **DEPRECATED** Flag to control whether + failing to load a plugin is reported via a log mess. Only applies if + on_missing_entrypoints_callback is None. Users should instead set + ``on_missing_entrypoints_callback`` to ``None`` if they wish to disable + logging. :param conflict_resolver: A callable that determines what to do in the event that there are multiple entrypoints in the same group with the same name. This is only used if retrieving entrypoint by name. @@ -85,17 +91,27 @@ class NamedExtensionManager(ExtensionManager[T]): on_load_failure_callback: 'OnLoadFailureCallbackT[T] | None' = None, on_missing_entrypoints_callback: ( OnMissingEntrypointsCallbackT | None - ) = None, + ) = warning_on_missing_entrypoint, verify_requirements: bool | None = None, - warn_on_missing_entrypoint: bool = True, + warn_on_missing_entrypoint: bool | None = None, *, conflict_resolver: 'ConflictResolverT[T]' = ignore_conflicts, ) -> None: self._names = names self._missing_names: set[str] = set() self._name_order = name_order + + if warn_on_missing_entrypoint is not None: + warnings.warn( + "The warn_on_missing_entrypoint option is deprecated for " + "removal. If you wish to disable warnings, you should instead " + "override 'on_missing_entrypoints_callback'", + DeprecationWarning, + ) + if not warn_on_missing_entrypoint: + on_missing_entrypoints_callback = None + self._on_missing_entrypoints_callback = on_missing_entrypoints_callback - self._warn_on_missing_entrypoint = warn_on_missing_entrypoint super().__init__( namespace, @@ -179,13 +195,8 @@ class NamedExtensionManager(ExtensionManager[T]): ) self._missing_names = set(self._names) - {e.name for e in extensions} - if self._missing_names: - if self._on_missing_entrypoints_callback: - self._on_missing_entrypoints_callback(self._missing_names) - elif self._warn_on_missing_entrypoint: - LOG.warning( - 'Could not load {}'.format(', '.join(self._missing_names)) - ) + if self._missing_names and self._on_missing_entrypoints_callback: + self._on_missing_entrypoints_callback(self._missing_names) return extensions