__init__.py 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. from functools import wraps
  2. class _PluginManager:
  3. def __init__(self):
  4. self._registered_plugins = []
  5. self._cached_base_callbacks = {}
  6. self._built_functions = {}
  7. def register(self, *plugins):
  8. """
  9. Makes it possible to register your plugin.
  10. """
  11. self._registered_plugins.extend(plugins)
  12. self._build_functions()
  13. def decorate(self, name=None):
  14. def decorator(callback):
  15. @wraps(callback)
  16. def wrapper(*args, **kwargs):
  17. return built_functions[public_name](*args, **kwargs)
  18. public_name = name or callback.__name__
  19. assert public_name not in self._built_functions
  20. built_functions = self._built_functions
  21. built_functions[public_name] = callback
  22. self._cached_base_callbacks[public_name] = callback
  23. return wrapper
  24. return decorator
  25. def _build_functions(self):
  26. for name, callback in self._cached_base_callbacks.items():
  27. for plugin in reversed(self._registered_plugins):
  28. # Need to reverse so the first plugin is run first.
  29. try:
  30. func = getattr(plugin, name)
  31. except AttributeError:
  32. pass
  33. else:
  34. callback = func(callback)
  35. self._built_functions[name] = callback
  36. plugin_manager = _PluginManager()