A powerful library for managing plugins in your Python application.
Project description
Extreme Plugin Manager
A library for effortlessly enabling and managing plugins in your Python application.
This library provides you with complete control over which objects your plugins can and can not access.
Additionally, this library provides powerful tools such as the ability to reroute all plugin STDOUT and easily spawn different types of background tasks.
Contents
Installation
pip install ExtremePluginManager
Usage
To start, you will simply need to instantiate the ExtremePluginManager
class like so:
import ExtremePluginManager
manager = ExtremePluginManager.ExtremePluginManager("plugins")
The ExtremePluginManager
Class
This class takes one mandatory, and several optional parameters.
plugin_directory: path
- The path to where plugins are to be stored (mandatory)create_dir: bool = False
- If the plugin directory does not exist and this isTrue
, it will be created, otherwiseValueError
will be raised.plugin_register_filename: str = "plugins.json"
- The name of the file to track which plugins are installed/enabled. This is automatically created in theplugin_directory
start_event: str = "on_start"
- The name of the plugin function which will be triggered when the plugin is loaded. This event is managed automatically.end_event: str = "on_stop"
- The name of the plugin function which will be triggered when the plugin is unloaded/stopped. This event is managed automatically.builtin_funcs: dict = None
- A dictionary of custom builtin values to pass into each plugin. The key is the code reference name and the value is the object itself. These values can be variables or pointers to functions. Plugins can not access any objects from your project outside this dictionary.
The ExtremePluginManager
class also contains helpful methods. Please only use getters/setters to update properties instead of the private attributes (prefixed with an underscore _
):
reload_plugins()
- Reloads all plugins from disk and triggers thestart_event
. This can be a useful tool for plugin developers as they can reload their plugin from inside your app instead of needing to close and re-open each time.on_plugin_load(plugin)
- This is an event which can be overridden. Each time a plugin reads the code file from disk and executes, this event is triggered.execute_event(event: str, *args, **kwargs)
- Calls the functionevent
in each plugin and passes in the*args
and**kwargs
parameters. This is how you trigger different plugin events. Plugins do not need to implement all of these functions, but you should keep a list of the available functions for your documentation.execute_end_event()
- Triggers theend_event
event for all pluginsexecute_start_event()
- Triggers thestart_event
event for all pluginssearch_by_id(plugin_id: str)
- Returns the plugin (as aPlugin
object) with the correspondingplugin_id
(set in the plugin config file)search_by_attribute(info_attribute: str, value, default=None)
- Returns a list of plugins (as aPlugin
object) which have the attributeinfo_attribute
with thevalue
. Usedefault
for a default value in the event not all plugins will have the attributeinstall_plugin(path: path, enable: bool = True, overwrite: bool = True)
- Installs the plugin at the specified path to the plugin directory. Ifenable
isTrue
then the plugin will also be enabled andstart_event
will be triggered. Ifoverwrite
is set toFalse
and a plugin already exists with the same name, an exception will be raised.uninstall_plugin(plugin_id: str, remove_files: bool = True)
- Uninstalls a plugin with the IDplugin_id
. Ifremove_files
isTrue
then the files will be deleted as well (this can not be undone). IfFalse
then the plugin file will remain but would have been removed from the registry so will not load until it is installed once again.create_template_plugin(plugin_id: str, enable: bool = True) -> str
- Creates a template plugin in the directory format. Both the filename and plugin ID will be set toplugin_id
. Ifenable
isTrue
then the template plugin will also be enabled. The full path to the plugin will then be returned.enable_plugin(plugin_id: str)
- Marks the plugin with the IDplugin_id
to enabled and triggers thestart_event
eventdisable_plugin(plugin_id: str)
- Marks the plugin with the IDplugin_id
to disabled and triggers theend_event
eventset_plugin_state(plugin_id: str, state: bool)
- Marks the plugin with the IDplugin_id
tostate
and triggers the corresponding eventget_plugin_register()
- Returns the current state of the plugin registerget_plugin_directory()
- Returns the path to the directory where the plugins are kept
The Plugin
Class
A plugin can be in a few different formats but regardless of the format, the Plugin
class exposes the same methods. Most of these methods are also available to the plugin code. You can obtain this instance by using one of the search functions in the ExtremePluginManager
class
reload()
- Reloads the plugin code but DOES NOT trigger thestart_event
read_file(self, path: path, encoding: str = "utf-8") -> str
- Reads the file located atpath
and returns the contents as a string (decoded withencoding
- used for plaintext files). Note thatpath
should be relative to the root directory of your plugin.read_file_bytes(self, path: path) -> bytes
- Reads the file located atpath
and returns as bytes (used for binary files). Note thatpath
should be relative to the root directory of your plugin.write_file(self, path: path, contents: str, encoding: str = "utf-8")
- Writescontents
to the files (encoded usingencoding
) to the file located atpath
. Note thatpath
should be relative to the root directory of your plugin.write_file_bytes(self, path: path, contents: bytes)
- Writescontents
into the file located atpath
(used for binary files). Note thatpath
should be relative to the root directory of your plugin.remove_file(self, path: path)
- Removes the file located atpath
. Note thatpath
should be relative to the root directory of your plugin.execute_event(event: str, *args, **kwargs)
- Executes the plugin function calledevent
passing in*args
and**kwargs
kill()
- This method prevents the plugin from having future events triggerd and will no longer be visible to plugin searches. This will trigger theend_event
The BaseThread
Class
This class extends the threadding.Thread
class but has three additional methods. This class is created when a plugin calls one of start_background_task
, start_delayed_task
, or start_interval_task
.
get_name() -> str
- Returns the name of the threadset_name(name: str)
- Sets the name of the threadkill()
- Terminates the thread immediately by raising aThreadKilledException
Plugin Conversions
Plugin formats can easily be converted between each other. The following conversion functions are availible:
import ExtremePluginManager
# convert directory format to zip format
# you can optionally specify `zip_format` parameter to set the resulting format
# can be "zip", "tar", "gztar","bztar", or "xztar".
ExtremePluginManager.converter.directory_to_zip("src_directory", "dst_zip")
# convert zip format to directory format
ExtremePluginManager.converter.zip_to_directory("dst_zip", "src_directory")
Plugin Creation Guide
It should be noted that the end_event
is automatically triggered when the application terminates.
In addition to the builtins you have provided in the constructor, the following builtins are available by default.
read_file(self, path: path, encoding: str = "utf-8") -> str
- Reads the file located atpath
and returns the contents as a string (decoded withencoding
- used for plaintext files). Note thatpath
should be relative to the root directory of your plugin.read_file_bytes(self, path: path) -> bytes
- Reads the file located atpath
and returns as bytes (used for binary files). Note thatpath
should be relative to the root directory of your plugin.write_file(self, path: path, contents: str, encoding: str = "utf-8")
- Writescontents
to the files (encoded usingencoding
) to the file located atpath
. Note thatpath
should be relative to the root directory of your plugin.write_file_bytes(self, path: path, contents: bytes)
- Writescontents
into the file located atpath
(used for binary files). Note thatpath
should be relative to the root directory of your plugin.remove_file(self, path: path)
- Removes the file located atpath
. Note thatpath
should be relative to the root directory of your plugin.info()
- Returns a dictionary representing the contents of the plugin'sinfo.json
plugin_manager
- An attribute which is a reference to theExtremePluginManager
which contains this objectplugin
- An attribute which is a reference to the actualPlugin
class instancestart_background_task(target: callable, *args, **kwargs)
- Calls the functiontarget
(please only pass in function references) with the parameters*args
, and**kwargs
to be run asynchronouslystart_delayed_task(delay: float, target: callable, *args, **kwargs)
- Calls the functiontarget
(please only pass in function references) with the parameters*args
, and**kwargs
to be run asynchronously afterdelay
seconds have passedstart_interval_task(interval: float, target: callable, *args, **kwargs)
- Calls the functiontarget
(please only pass in function references) with the parameters*args
, and**kwargs
to be run asynchronously everyinterval
seconds
Rerouting STDOUT
If you add a builtin with the reference name of print
which takes the parameters *args, sep=' ', end='\n', file=None
then all calls to print
will be sent here instead of the default function.
You can then do what you wish with the output.
Limitations
Currently, importing additional code files in your plugin is not supported. We are working on it.
If you attempt to reference a builtin value for your plugin with an IDE such as PyCharm
, it will flag the value as unknown. This is because we modify the Python compiler at runtime to know these values. We are also working on a fix for this too.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file ExtremePluginManager-1.0.0.tar.gz
.
File metadata
- Download URL: ExtremePluginManager-1.0.0.tar.gz
- Upload date:
- Size: 7.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.4.2 importlib_metadata/3.7.0 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.55.2 CPython/3.9.1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 991f978f28b9ad38b94884e800495244ed7e8d77796552bef7b335d47e3d848c |
|
MD5 | 705a73a209d8f992827a0066f7dd661b |
|
BLAKE2b-256 | 1cbb59ca1ac1d42f809d0cbcde5e12dd70dd4a26c430de418c37f0a35dca6eb1 |
File details
Details for the file ExtremePluginManager-1.0.0-py3-none-any.whl
.
File metadata
- Download URL: ExtremePluginManager-1.0.0-py3-none-any.whl
- Upload date:
- Size: 8.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.4.2 importlib_metadata/3.7.0 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.55.2 CPython/3.9.1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 88bbf288f2c12bcf50a2afa15317bc7c3c50345b849d2f1c1836e935dcf09f8e |
|
MD5 | bd8de179309720e9a8e853638b1099b4 |
|
BLAKE2b-256 | 6535ca523b0bf66106ea7e978a4e66342c1e843321549d02bf8be789f98e6564 |