pyitect package

Module contents

Pyitect is a pluginframe work

class pyitect.Version

Version class imported directly from semantic_version

see the python-semanticversion project for more information.

class pyitect.Spec

Spec class imported directly from semantic_version

see the python-semanticversion project for more information.

class pyitect.System(config, enable_yaml=False)[source]

A plugin system

It can scan dir trees to find plugins and their provided/needed components, and with a simple load call chain load all the plugins needed.

The system includes a simple event system and fires some events internal, here are their signatures:

‘plugin_found’: (path, plugin)

path (str): the full path to the folder containing the plugin

plugin (str): plugin version string (ie ‘plugin_name:version’)

‘plugin_loaded’: (plugin, plugin_required, component_needed)

plugin (str): plugin version string (ie ‘plugin_name:version’)

plugin_required (str): version string of the plugin that required the
loaded plugin (version string ie ‘plugin_name:version’)
component_needed (str): the name of the component needed by the
requesting plugin
‘component_loaded’: (component, plugin_required, plugin_loaded)

component (str): the name of the component loaded

plugin_required (str, None): version string of the plugin that
required the loaded component (version string ie ‘plugin_name:version’) (might be None)
plugin_loaded (str): version string of the plugin that the component
was loaded from (version string ie ‘plugin_name:version’)

Pyitect keeps track of all the instances of the System class in System.systems which is a map of object id’s to instances of System.

config

dict

A mapping of component names to version requirements

plugins

dict

A mapping of the plugins the system knows about. Maps names to dicts of Version s mapped to Plugin config objects

components

dict

A mapping of Component.key() s to loaded component objects

component_map

dict

A mapping of components the system knows about. Maps names to dicts of Version s mapped to Component config objects

loaded_plugins

dict

A mapping of Plugin.key() s to loaded plugin module objects

enabled_plugins

list

A list of Plugin.key() s of enabled plugins

using

list

A List of Component.key() s loaded by the system

events

dict

A mapping of event names to lists of callable objects

add_plugin(path)[source]

Adds a plugin form the provided path

Parameters:path (str) – path to a plugin folder
Rasies:
PyitectError: If no plugin exists at path PyitectDupError: if you try to add the same plugin twice
bind_event(event, function)[source]

Bind a callable object to the event name

a simple event system bound to the plugin system, bind a function on an event and when the event is fired all bound functions are called with the *args and **kwargs passed to the fire call

Parameters:
  • event (str) – name of event to bind to
  • function (callable) – Boject to be called when event fires
enable_plugins(*plugins)[source]

Take one or more Plugin s and map it’s components

Takes a plugins metadata and remembers it’s provided components so the system is awear of them

Parameters:

plugins (plugins) – One or more plugins to enable. Each argument can it self be a list or map of Plugin objects or a plain Plugin object

Raises:
  • TypeError – If you try to pass a non Plugin object
  • PyitectDubError – If you try to enable a plugin that provides duplicate conponent
  • PyitectOnEnableError – If There was an error in the on_enable
  • PyitectLoadError – If there was an error loading a plugin to call it’s on_enable
fire_event(event, *args, **kwargs)[source]

Call all functions bound to the event name

and pass all extra *args and **kwargs to the bound functions

Parameters:event (str) – name of event to fire
get_plugin_module(plugin, version=None)[source]

Fetch the loaded plugin module

if version is None searches for the highest version number plugin with it’s module loaded if it can’t find anything it raises a runtime error

Parameters:

plugin (str) – name of plugin to find version (None, str, Version): if provided load a spesfic version

Returns:

loaded module object

Raises:
  • TypeError – if provideing a version that is not either a str or a Version
  • PyitectError – if the Plugin can’t be found
  • PyitectLoadError – plugin module is not loaded yet
is_plugin(path)[source]

Test a path to see if it is a Plugin

Parameters:path (str) – path to test

Returns: true if there is a plugin in the folder pointed to by path

iter_component_providers(comp, subs=False, vers=False, reqs='*')[source]

An iterater function to interate providers of a component

Takes a conponent name and yeilds providers of the conponent

if subs is True yeilds providers of subtypes too

if vers is True yeilds all version of the provider not just the highest

reqs is a version requirement for the providers to meet. Defaults to any version

yeilds tuples that look like: (<component_name>, <plugin_name>, <version>)

Examples

>>> for t in iter_component_providers("foo", subs=True): print(t);
("foo", "foo_plugin", "0.1.0")
("foo", "foo_plugin2", "1.0.0")
("foo.a", "foo.a_plugin", "0.1.0")
("foo.a.b", "footastic", "10.0.0")
Parameters:
  • comp (str) – component name to use as a base
  • subs (bool) – should subtypes be yeilded too?
  • vers (bool) – should all version be yeilded not just the highest?
  • reqs (str, list, tuple) – version spec string or list there of all items are passed to a Spec
Raises:

TypeError – if comp or reqs are passed wrong

iter_component_subtypes(component)[source]

An iterater function to interate all known subtypes of a component

Takes a conponent name and yeilds all known conponent names that are subtypes not including the conponent name

Parameters:conponent (str) – the conponent name to act as a base
Raises:TypeError – if component is niether a Component instance nor a string
load(component, requires=None, request=None, bypass=False, subs=True, key=None, reverse=False)[source]

Load and return a component object

processes loading and returns the component by name, chain loading any required plugins to obtain dependencies. Uses the config that was provided on system creation to load correct versions, if there is a conflict throws a run time error. bypass lets the call bypass the system configuration

internaly uses iter_component_providers() to create list of viable components. basialy calls sorted(iter_component_providers(component subs=subs), key=key)[0] to get the component to use.

Parameters:
  • component (str) – Name of component to load
  • requires (dict, None) – A mapping of component names to version requierments to use during the load
  • request (str, None) – The name of the requesting plugin. None if not requested
  • bypass (bool) – Ignore the system configured version requierments
  • subs (bool) – should sub components be considered?
  • key (func, None) – Key function to use to compaire component provider tuples from iter_component_providers() in a sorted call.write the key func so that the item you want will be at index 0
  • reverse (bool) – reverse sorting of components
Returns:

the loaded component object

Raises:
  • TypeError – if thigns get passed worng
  • PyitectLoadError – if there is an exception druing load
load_component(component, plugin, version, requires=None, request=None)[source]

Loads a component

same end effect as load() but requires an explicit name, plugin, and version. no subtypes of the component are explored no other provider is considered

Parameters:
  • component (str) – component name to load
  • plugin (str) – plugin name to load form
  • version (str, Version) – Version to load
Raises:
load_plugin(plugin, version, requires=None, request=None, comp=None)[source]

Takes a plugin name and version and loads it’s module

finds the stored Plugin object takes a Plugin object and loads the module recursively loading declared dependencies

Parameters:
  • plugin (str) – plugin name
  • version (str, Version) – version to load
  • requires (dict, None) – a mapping of component names to version requierments to use during the load
  • request (str, None) – name of the version string of the plugin that requested a component from this plugin. None if not requested.
  • comp (str) – name of the component needed by teh requesting plugin. None if not requested.
Returns:

the loaded module object

Raises:
  • TypeError – if things get passed worng
  • PyitectLoadError – if there is an exception during the load
resolve_highest_match(component, plugin, spec)[source]

resolves the latest version of a component with requirements,

takes in a component name and some requierments and gets a valid plugin name and its highest version

Parameters:
  • component (str) – a component name
  • plugin (str) – a plugin name if it’s empty we default to alphabetical order
  • spec (Spec) – a SemVer version spec
Raises:

TypeError – if somthing isn’t the right type

resolve_providers(component, subs=True, key=None, reverse=False)[source]

Resolve what avalible component is used

will create a lost of a component and it’s subcomponents to sorted with sorted(component key=key) and return the first item

the default, and possibly undesierable behavior, is alphabetical order of component names

Parameters:key (func, None) – a key function to sort the componet types and subtypes that are valid so you can select the correct one
search(path)[source]

Search a path (dir or file) for a plugin in the case of a file it searches the containing dir.

Parameters:path (str) – the path to search
systems = []

A list of all System instances

unbind_event(event, function)[source]

Remove a function from an event

removes the function object from the list of callables to call when event fires. does nothing if function is not bound

Parameters:
  • event (str) – name of event bound to
  • function (callable) – object to unbind
class pyitect.Plugin(config, path)[source]

An object that can hold the metadata for a plugin

like its name, author, verison, and the file to be loaded ect. also stores the path to the plugin folder and provideds functionality to load the plugin module and run its on_enable function

name

str

plugin name

author

str

plugin author

version

Version

plugin vesion

file

str

relative path to the file to import to load the plugin

consumes

dict

a listing of the components consumed

provides

dict

a listing of the components provided

on_enable

None, str

either None or a str doted name of a function in the module

path

str

an absolute path to the plugin folder module (None, object): either None or the modlue object if the plugin has been loaded already

get_version_string()[source]

returns a version string

has_on_enable()[source]

returns True if it has an on_enable attribute that’s not None

key()[source]

return a key that can be used to identify the plugin

Returns:(name, author, version, path)
Return type:tuple
load()[source]

loads the plugin file and returns the resulting module

Raises:
run_on_enable()[source]

runs the function in the ‘on_enable’ if set

Raises:
  • TypeError – if the on_enable property is set wrong
  • PyitectOnEnableError – if there is an exception
  • acessing or calling the on_enable function
  • PyitectLoadError – If the module object is not loaded yet
class pyitect.Component(name, plugin, author, version, path)[source]

An object to hold metadata for a spesfic instance of a component

Holds the metadata needed to identify a instance of a component provided by a plugin

name

str

the component name provided

plugin

str

the name of the providing plugin

author

str

the author of the providing plugin

version

Version

the verison of the providing plugin

path

str

a doted name path to the component object from the top of the plugin module

key()[source]

returns a key to identify this component

Returns:(name, plugin, author, version, path)
Return type:tuple
pyitect.get_system()[source]

Fetch the global system instance

Raises:PyitectError – If the system isn’t built yet
pyitect.build_system(config, enable_yaml=False)[source]

Build a global system instance

Parameters:
  • config (dict) – A mapping of component names to version requirements
  • enable_yaml (bool) – Should the system support yaml config files?
Raises:

PyitectError – if the system is already built

pyitect.destroy_system()[source]

destroy the global system instance

does nothing if the system isn’t built

pyitect.issubcomponent(comp1, comp2)[source]

Check if comp1 is a subtype of comp2

Returns whether the Component passed as comp1 validates as a subtype of the Component passed as comp2.

if strings are passed as either peramater they are treated as Component names. if a Component instance is passed it’s name property is pulled.

Parameters:
  • comp1 (str, Component) – The Component or component name to check
  • comp2 (str, Component) – The Component or component name to compair to
pyitect.get_unique_name(*parts)[source]

Generate a fixed lenght unique name from parts

takes the parts turns them into strings and uses them in a sha1 hash

used internaly to ensure module object for plugins have unique names like so

get_unique_name(plugin.author, plugin.get_version_string())

Returns:name hash
Return type:str
pyitect.gen_version(version_str)[source]

Generates an Version object

takes a SemVer string and returns a Version if not a proper SemVer string it coerces it

Parameters:version_str (str) – version string to use
pyitect.expand_version_req(requires)[source]

Take a requierment and return the Spec and the plugin name

takes a requierment and pumps out a plugin name and a SemVer Spec requires is either a string of the form (“”, “*”, “plugin_name”, plugin_name:version_spec)

or a mapping with plugin and spec keys like so {“plugin”: “plugin_name”, “spec”: “>=1.0.0”} the spec key’s value can be a string of comma seperated version requierments or a list of strings of the same

Parameters:requires (str, mapping) – string or mapping object with plugin and spec keys

Examples

>>> expand_version_req("")
('', <Spec: (<SpecItem: * ''>,)>)
>>> expand_version_req("*")
('', <Spec: (<SpecItem: * ''>,)>)
>>> expand_version_req("plugin_name")
('plugin_name', <Spec: (<SpecItem: * ''>,)>)
>>> expand_version_req("plugin_name:>=1.0.0")
('plugin_name', <Spec: (<SpecItem: >= Version('1.0.0')>,)>)
>>> expand_version_req("plugin_name:>=1.0.0,<2.0.0")
('plugin_name', <Spec: (SpecItems... >= 1.0.0, < 2.0.0 )>)
>>> expand_version_req({"plugin": "plugin_name", "spec": ">=1.0.0"})
('plugin_name', <Spec: (<SpecItem: >= Version('1.0.0')>,)>)
Raises:
  • ValueError – when the requierment is of a bad form
  • TypeError – when the requiers objt is not a string or mapping
exception pyitect.PyitectError(*args, **kwargs)[source]

Wraps Exceptions for Chained trace backs

As Pyitect is intended for use across pyhton 2 and 3 a way was needed to Ensure that exceptions caused during the import of plugin modules tell why that import failed insed of just failed to import ‘bla’

This code is a modifed version of a CausedException class posed to ActiveState back in Sep. 2012 Licensed under MIT license

the ability handle trees of exceptions was removed

http://code.activestate.com/recipes/578252-python-exception-chains-or-trees/?in=user-4182236

exception pyitect.PyitectNotProvidedError(*args, **kwargs)[source]

Raised if a conponent is not provided

exception pyitect.PyitectNotMetError(*args, **kwargs)[source]

Raised if requierments are not met

exception pyitect.PyitectLoadError(*args, **kwargs)[source]

Raises if a plugins module is not yet loaded or fais to load

exception pyitect.PyitectOnEnableError(*args, **kwargs)[source]

Raised if and on_enable call failes

exception pyitect.PyitectDupError(*args, **kwargs)[source]

Raised if you try to add a duplicate plugin or duplicate component provider