_loader.py 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. from __future__ import annotations
  2. import importlib.metadata as importlib_metadata
  3. import os
  4. import warnings
  5. from typing import TYPE_CHECKING, Final, Iterable
  6. if TYPE_CHECKING:
  7. from . import PydanticPluginProtocol
  8. PYDANTIC_ENTRY_POINT_GROUP: Final[str] = 'pydantic'
  9. # cache of plugins
  10. _plugins: dict[str, PydanticPluginProtocol] | None = None
  11. # return no plugins while loading plugins to avoid recursion and errors while import plugins
  12. # this means that if plugins use pydantic
  13. _loading_plugins: bool = False
  14. def get_plugins() -> Iterable[PydanticPluginProtocol]:
  15. """Load plugins for Pydantic.
  16. Inspired by: https://github.com/pytest-dev/pluggy/blob/1.3.0/src/pluggy/_manager.py#L376-L402
  17. """
  18. disabled_plugins = os.getenv('PYDANTIC_DISABLE_PLUGINS')
  19. global _plugins, _loading_plugins
  20. if _loading_plugins:
  21. # this happens when plugins themselves use pydantic, we return no plugins
  22. return ()
  23. elif disabled_plugins in ('__all__', '1', 'true'):
  24. return ()
  25. elif _plugins is None:
  26. _plugins = {}
  27. # set _loading_plugins so any plugins that use pydantic don't themselves use plugins
  28. _loading_plugins = True
  29. try:
  30. for dist in importlib_metadata.distributions():
  31. for entry_point in dist.entry_points:
  32. if entry_point.group != PYDANTIC_ENTRY_POINT_GROUP:
  33. continue
  34. if entry_point.value in _plugins:
  35. continue
  36. if disabled_plugins is not None and entry_point.name in disabled_plugins.split(','):
  37. continue
  38. try:
  39. _plugins[entry_point.value] = entry_point.load()
  40. except (ImportError, AttributeError) as e:
  41. warnings.warn(
  42. f'{e.__class__.__name__} while loading the `{entry_point.name}` Pydantic plugin, '
  43. f'this plugin will not be installed.\n\n{e!r}'
  44. )
  45. finally:
  46. _loading_plugins = False
  47. return _plugins.values()