Source code for videoflow.utils.plugins

'''
Third-party registration via ``importlib.metadata`` entry points.

Videoflow's extension points are plain dict/list registries with an explicit
``register_*()`` function, pre-seeded with the built-ins. That covers the common
case, where the code doing the registering is imported anyway (a component
module the worker loads via ``VF_NODE_CLASS`` registers its own payload codecs
on import).

It does not cover the case where nothing imports the extension first — a blob
store selected by URL scheme in a config file, say, or a host-side
``videoflow debug decode`` that must understand a vendor payload type without
knowing which package defines it. For those, a package declares an entry point
and videoflow imports it on demand.

Stdlib only, by design: an extension mechanism that needs its own dependency is
a worse trade than the ``if/elif`` it replaces.
'''
from __future__ import absolute_import, division, print_function

import logging
from importlib.metadata import entry_points

logger = logging.getLogger(__package__)

# Entry-point groups already loaded, so a miss on a repeatedly-consulted registry
# does not re-scan installed distributions every time.
_loaded : set[str] = set()

[docs] def load_plugin_group(group : str) -> None: ''' Imports every extension registered in the ``importlib.metadata`` entry-point group ``group``, so its ``register_*()`` side effects take hold. Idempotent: a group is scanned at most once per process. Each entry point may resolve to either a module (imported for its top-level ``register_*()`` calls) or a callable (imported and then called). A plugin that raises is logged and skipped rather than propagated — one broken third-party package must not stop a worker from starting, since the registration it was providing may not even be needed by this flow. - Arguments: - group: entry-point group name, e.g. ``'videoflow.blob_stores'``. ''' if group in _loaded: return _loaded.add(group) for ep in entry_points(group = group): try: loaded = ep.load() if callable(loaded): loaded() except Exception as e: # noqa: BLE001 — see docstring logger.warning(f'Failed to load videoflow plugin {ep.name!r} ' f'from group {group!r}: {type(e).__name__}: {e}')