pluginify.interfaces package#

Submodules#

pluginify.interfaces.base module#

Base classes for interfaces, plugins, and plugin validation machinery.

class pluginify.interfaces.base.BaseClassInterface[source]#

Bases: BaseInterface

Base class for class-based interfaces.

This class should not be instantiated directly. Instead, a package should implement custom interfaces that inherit from the children of this class. Those custom interfaces would then be accessed by importing them from <your_package>.interfaces. For example: ` from <your_package>.interfaces import algorithms ` will retrieve an instance of AlgorithmsInterface which will provide access to the <your_package> algorithm plugins.

get_plugin(name, rebuild_registries=None)[source]#

Retrieve a plugin from this interface by name.

Parameters:
  • name (str) –

    • The name the desired plugin.

  • rebuild_registries (bool (default=None)) –

    • Whether or not to rebuild the registries if get_plugin fails. If set to None, default to the value of ~/.config/pluginify/config.yaml:REBUILD_REGISTRIES. If that configuration variable is not set, we default to True. If specified, use the input value of rebuild_registries, which should be a boolean value. If rebuild registries is true and get_plugin fails, rebuild the plugin registry, call then call get_plugin once more with rebuild_registries toggled off, so it only gets rebuilt once.

Returns:

  • An object of type <interface>Plugin where <interface> is the name of

  • this interface.

Raises:

PluginError – If the specified plugin isn’t found within the interface.

get_plugins()[source]#

Retrieve all module plugins for this interface.

interface_type: str = 'class_based'#
name = 'BaseClassInterface'#
plugin_is_valid(plugin)[source]#

Check that an interface is valid.

Check that the requested interface function has the correct call signature. Return values should be as specified below, but are not programmatically verified.

Note this is currently only called via the tests/utils/test_interfaces.py script (which is not a valid pytest script, but called directly via the command line), via the test_interface method within this base interface.

Parameters:

plugin (PluginObject) – A plugin object coming from _plugin_module_to_obj that needs to be validated.

Returns:

True if valid, False if invalid

Return type:

bool

plugins_all_valid()[source]#

Test the current interface by validating every Plugin.

Return type:

True if all plugins are valid, False if any plugin is invalid.

required_args: dict[str, list[str]] = {}#
test_interface()[source]#

Test the current interface by validating each Plugin and testing each method.

Test this interface by opening every Plugin available to the interface, and validating each plugin by calling plugin_is_valid for each. Additionally, ensure all methods of this interface work as expected:

  • get_plugins

  • get_plugin

  • plugin_is_valid

  • plugins_all_valid

Returns:

  • A dictionary containing three keys

  • ’by_family’, ‘validity_check’, ‘func’, and ‘family’. The value for each

  • of these keys is a dictionary whose keys are the names of the Plugins.

  • - ‘by_family’ contains a dictionary of plugin names sorted by family.

  • - ‘validity_check’ contains a dict whose keys are plugin names and whose – values are bools where True indicates that the Plugin’s function is valid according to plugin_is_valid.

  • - ‘func’ contains a dict whose keys are plugin names and whose values are – the function for each Plugin.

  • - ‘family’ contains a dict whose keys are plugin names and whose values – are the contents of the ‘family’ attribute for each Plugin.

class pluginify.interfaces.base.BaseInterface[source]#

Bases: ABC

Base class for plugin interfaces.

This class should not be instantiated directly. Instead, a package should implement custom interfaces that inherit from the children of this class, such as BaseYamlInterface or BaseClassInterface. Those custom interfaces would then be accessed by importing them from <your_package>.interfaces. For example: ` from <your_package>.interfaces import algorithms ` will retrieve an instance of AlgorithmsInterface which will provide access to <your_package> algorithm plugins.

apiVersion = 'pluginify/v1'#
abstract get_plugin(name, rebuild_registries=True)[source]#

Abstract function for retrieving a plugin under a certain interface.

Parameters:
  • name (str or tuple(str)) –

    • The name of the yaml-based plugin. Either a single string or a tuple of strings for product plugins.

  • rebuild_registries (bool (default=True)) –

    • Whether or not to rebuild the registries if get_plugin fails. If set to true and get_plugin fails, rebuild the plugin registry, call then call get_plugin once more with rebuild_registries toggled off, so it only gets rebuilt once.

    • By default, the value of rebuild_registries is set to True if not explicitly set to False as an configuration variable under the name REBUILD_REGISTRIES in ~/.config/pluginify/config.yaml.

get_plugin_metadata(name)[source]#

Retrieve a plugin’s metadata.

Where the metadata of the plugin matches the plugin’s corresponding entry in the plugin registry.

Parameters:

name (str or tuple(str)) –

  • The name of the plugin whose metadata we want.

Returns:

metadata

  • A dictionary of metadata for the requested plugin.

Return type:

dict

abstract get_plugins()[source]#

Abstract function for retrieving all plugins under a certain interface.

interface_type: str = ''#
name = 'BaseInterface'#
property namespace#

Default namespace used for the plugin registry associated with this class.

By default, we use ‘pluginify.plugin_packages’ as the namespace for interface classes. However, if a user has developed interfaces in a separate namespace from pluginify, they can override this in their own classes by setting the namespace to search in.

property plugin_registry#

The plugin registry associated with this interface.

By default, we use ‘pluginify.plugin_packages’ as the namespace for interface classes. However, if a user has developed interfaces in a separate namespace from pluginify, they can override this in their own classes by setting the namespace to search in.

plugin_registry_module = <module 'pluginify.plugin_registry' from '/opt/hostedtoolcache/Python/3.11.15/x64/lib/python3.11/site-packages/pluginify/plugin_registry.py'>#
rebuild_registries = True#
class pluginify.interfaces.base.BaseYamlInterface[source]#

Bases: BaseInterface

Base class for yaml-based plugin interfaces.

This class should not be instantiated directly. Instead, a package should implement custom interfaces that inherit from the children of this class. Those custom interfaces would then be accessed by importing them from <your_package>.interfaces. For example: ` from <your_package>.interfaces import products ` will retrieve an instance of ProductsInterface which will provide access to the <your_package> products plugins.

get_plugin(name, rebuild_registries=None)[source]#

Get a plugin by its name.

This default method can be overridden to provide different search functionality for an interface. An example of this is in the ProductsInterface which uses a tuple containing ‘source_name’ and ‘name’.

Parameters:
  • name (str or tuple(str)) –

    • The name of the yaml-based plugin. Either a single string or a tuple of strings for product plugins.

  • rebuild_registries (bool (default=None)) –

    • Whether or not to rebuild the registries if get_plugin fails. If set to None, default to the value of ~/.config/pluginify/config.yaml:REBUILD_REGISTRIES. If that configuration variable is not set, we default to True. If specified, use the input value of rebuild_registries, which should be a boolean value. If rebuild registries is true and get_plugin fails, rebuild the plugin registry, call then call get_plugin once more with rebuild_registries toggled off, so it only gets rebuilt once.

get_plugins()[source]#

Retrieve all yaml plugin objects.

interface_type: str = 'yaml_based'#
name = 'BaseYamlInterface'#
plugin_is_valid(name)[source]#

Plugin is valid method.

plugins_all_valid()[source]#

Plugins all valid method.

test_interface()[source]#

Test interface method.

Note this is currently only called via the tests/utils/test_interfaces.py script (which is not a valid pytest script, but called directly via the command line.

use_pydantic = False#
abstract property validator#

The validator for plugin types that fall under this interface.

Abstract. This must be implemented by the final child node which inherits from this class.

class pluginify.interfaces.base.BaseYamlPlugin(*args, **kwargs)[source]#

Bases: dict

Base class for YAML plugins.

pluginify.interfaces.class_based_plugin module#

Implements a base class for class-based plugins.

The base class implemented here would expose the call signature of the child plugin class as __call__() while also providing hooks for pre- and post-processing.

The hooks are available as _pre_call() and _post_call(). They should be used to implement common functionality that all plugins of this type should posess but which we don’t want developers to need to implement. They are intended to be overridden by the child plugin-type class (e.g. BaseReaderPlugin). They should define what kwargs they accept when defined on the plugin-type class but should accept their arguments from **kwargs from __call__().

The call() method should be overridden on the actual plugin class. It should provide the data processing for the plugin. __call__()’s signature will be identical to that of call() except that call() should not accept **kwargs. That should be consumed by the hooks.

__call__() should not be overridden anywhere.

class pluginify.interfaces.class_based_plugin.BaseClassPlugin(module=None)[source]#

Bases: ABC

The base class for class-based plugins.

All plugins are required to carry the following class attributes:

  • interface: The interface type the plugin belongs to (e.g. ‘configs’, ‘data_modifiers’). This is typically provided by the interface-level plugin class and not the individual plugin class.

  • family: The family name of the plugin. This should be defined by the plugin class.

  • name: The specific name of the plugin. This should be defined by the plugin class.

Subclasses of this base class must also implement the following methods:

  • call(): The main method that performs the plugin’s functionality. This method should be implemented by the plugin class.

  • _pre_call(): A hook method that can be overridden to preprocess data before calling the main call() method. This method should accept the same arguments as call() via *args and **kwargs and should, typically, be implemented by the interface-level plugin class.

  • _post_call(): A hook method that can be overridden to post-process data after calling the main call() method. This method should accept the same arguments as call() via *args and **kwargs and should, typically, be implemented by the interface-level plugin class.

The purpose of _pre_call() and _post_call() is to allow for common functionality that all plugins of a certain type should possess, without requiring developers to implement this functionality in every plugin class. Initially, this will be used to convert inputs from DataTree to other formats and back to DataTree after processing, but it could be used for other common tasks as well.

abstract call(*args, **kwargs)[source]#

Callable method to be implemented by the plugin class.

data_tree = False#
required_attributes = ['interface', 'family', 'name']#
pluginify.interfaces.class_based_plugin.valid_str_attr(cls, attr_name: str)[source]#

Check that the given attribute is a non-empty string.

Module contents#

Initialization module for pluginify interfaces.