DebenOldert 1 рік тому
батько
коміт
7231fa380d
4 змінених файлів з 97 додано та 2 видалено
  1. 1 0
      .gitignore
  2. 29 2
      README.md
  3. 0 0
      __init__.py
  4. 67 0
      pygin.py

+ 1 - 0
.gitignore

@@ -1,5 +1,6 @@
 # ---> VisualStudioCode
 .settings
+.vscode
 
 
 # ---> VisualStudio

+ 29 - 2
README.md

@@ -1,3 +1,30 @@
-# pygin
+# PyGin
+Load python files as plugins
 
-Load python files as plugins
+# Usage
+## Define a class as a plugin
+```python
+from lib.pygin import pygin
+
+@pygin.register
+class CustomPlugin:
+    ...
+
+```
+
+## Load a file as plugin
+```python
+from lib.pygin import pygin, exceptions
+
+name = 'custom_plugin'
+
+try:
+    instance = pygin.call(package='package.module',
+                          plugin=name,
+                          **kwargs)
+
+    instance.custom_function()
+
+except Exception as e:
+    raise Exception(name=name, exception=e) from e
+```

+ 0 - 0
__init__.py


+ 67 - 0
pygin.py

@@ -0,0 +1,67 @@
+import functools
+import importlib
+from collections import namedtuple
+from importlib import resources
+from typing import Type, Any, List
+
+# Basic structure for storing information about one plugin
+Plugin = namedtuple("Plugin", ("name", "func"))
+
+# Dictionary with information about all registered plugins
+_PLUGINS = {}
+
+# From https://realpython.com/python-import/#example-a-package-of-plugins
+
+
+def register(func):
+    """Decorator for registering a new plugin"""
+    package, _, plugin = func.__module__.rpartition(".")
+    pkg_info = _PLUGINS.setdefault(package, {})
+    pkg_info[plugin] = Plugin(name=plugin, func=func)
+    return func
+
+
+def names(package: str) -> List[str]:
+    """List all plugins in one package"""
+    _import_all(package)
+    return sorted(_PLUGINS[package])
+
+
+def get(package: str, plugin: str) -> Type[Any]:
+    """Get a given plugin"""
+    _import(package, plugin)
+    return _PLUGINS[package][plugin].func
+
+
+def call(package: str, plugin: str, *args, **kwargs) -> Any:
+    """Call the given plugin"""
+    plugin_func = get(package, plugin)
+    return plugin_func(*args, **kwargs)
+
+
+def _import(package: str, plugin: str) -> None:
+    """Import the given plugin file from a package"""
+    importlib.import_module(f"{package}.{plugin}")
+
+
+def _import_all(package: str) -> None:
+    """Import all plugins in a package"""
+    files = resources.contents(package)
+    plugins = [f[:-3] for f in files if f.endswith(".py") and f[0] != "_"]
+    for plugin in plugins:
+        _import(package, plugin)
+
+
+def names_factory(package: str):
+    """Create a names() function for one package"""
+    return functools.partial(names, package)
+
+
+def get_factory(package: str):
+    """Create a get() function for one package"""
+    return functools.partial(get, package)
+
+
+def call_factory(package: str):
+    """Create a call() function for one package"""
+    return functools.partial(call, package)