summaryrefslogtreecommitdiff
path: root/docs/index.rst
diff options
context:
space:
mode:
authorArmin Ronacher <armin.ronacher@active-4.com>2014-06-30 22:50:56 +0200
committerArmin Ronacher <armin.ronacher@active-4.com>2014-06-30 22:50:56 +0200
commit1e6456bf54bb37743d22fe564b475f10bc13281e (patch)
tree3cf0c8cb8dd3688785ff73100f8bd8af98eb3105 /docs/index.rst
downloadpluginbase-0.1.tar.gz
Initial commit.0.1
Diffstat (limited to 'docs/index.rst')
-rw-r--r--docs/index.rst155
1 files changed, 155 insertions, 0 deletions
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..c4d4aec
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,155 @@
+PluginBase
+==========
+
+.. module:: pluginbase
+
+Ever tried creating a plugin system for a Python application and you
+discovered fighting against the import system? Me too. This is where
+PluginBase comes in.
+
+PluginBase is a module for Python which extends the import system for
+the most common form of plugin usage which is providing a consistent
+import experience for plugins from a variety of sources. Essentially it
+allows you to build very flexible plugin based applications which pull in
+plugins from bundled sources as well as application specific ones without
+bypassing the Python import system.
+
+How does it work? It's super simple:
+
+Step 1:
+
+ Create a "plugin base" object. It defines a pseudo package under
+ which all your plugins will reside. For instance it could be
+ ``yourapplication.plugins``::
+
+ from pluginbase import PluginBase
+ plugin_base = PluginBase(package='yourapplication.plugins')
+
+Step 2:
+
+ Now that you have a plugin base, you can define a plugin source
+ which is the list of all sources which provide plugins::
+
+ plugin_source = plugin_base.make_plugin_source(
+ searchpath=['./path/to/plugins', './path/to/more/plugins'])
+
+Step 3:
+
+ To import a plugin all you need to do is to use the regular import
+ system. The only change is that you need to import the plugin
+ source through the ``with`` statement::
+
+ with plugin_source:
+ from yourapplication.plugins import my_plugin
+ my_plugin.do_something_cool()
+
+Alternatively you can also import plugins programmatically instead of
+using the import statement::
+
+ my_plugin = plugin_source.load_plugin('my_plugin')
+
+Installation
+------------
+
+You can get the library directly from PyPI::
+
+ pip install pluginbase
+
+
+FAQ
+---
+
+Q: Why is there a plugin base and a plugin source class?
+
+ This decision was taken so that multiple applications can co-exist
+ together. For instance imagine you have an application that
+ implements a wiki but you want multiple instances of that wiki
+ to exist in the same Python interpreter. The plugin sources split
+ out the load paths of the different applications.
+
+ Each instance of the wiki would have its own plugin source and they
+ can work independently of each other.
+
+Q: Do plugins pollute ``sys.modules``?
+
+ While a plugin source is alive the plugins do indeed reside in
+ ``sys.modules``. This decision was make conciously so that as little
+ as possible of the Python library ecosystem breaks. However when the
+ plugin source gets garbage collected all loaded plugins will
+ also get garbage collected.
+
+Q: How does PluginBase deal with different versions of the same plugin?
+
+ Each plugin source works indepdenently of each other. The way this
+ works is by internally translating the module name. By default that
+ module name is a random number but it can also be forced to a hash of
+ a specific value to make it stable across restarts which allows
+ pickle and similar libraries to work.
+
+ This internal module renaming means that
+ ``yourapplication.module.foo`` will internally be called
+ ``pluginbase._internalspace._sp7...be4`` for instance. The same
+ plugin loaded from another plugin source will have a different
+ internal name.
+
+Q: What happens if a plugin wants to import other modules?
+
+ All fine. Plugins can import from itself as well as other plugins
+ that can be located.
+
+Q: Does PluginBase support pickle?
+
+ Yes, pickle works fine for plugins but it does require defining a
+ stable identifier when creating a plugin source. This could for
+ instance be a file system path::
+
+ plugin_source = base.make_plugin_source(
+ searchpath=[app.plugin_path],
+ identifier=app.config_filename)
+
+Q: What happens if I import from the plugin module without the
+plugin source activated through the ``with`` statement?
+
+ The import will fail with a descriptive error message explaining
+ that a plugin source needs to be activated.
+
+Q: Can I automatically discover all modules that are available?
+
+ Yes you can. Just use the :meth:`PluginSource.list_plugins` method
+ which returns a list of all plugins that a source can import.
+
+
+API
+---
+
+High Level
+``````````
+
+.. autoclass:: PluginBase
+ :members:
+
+.. autoclass:: PluginSource
+ :members:
+
+.. autofunction:: get_plugin_source
+
+Import Hook Control
+```````````````````
+
+.. autofunction:: pluginbase.import_hook.enable
+
+.. autofunction:: pluginbase.import_hook.disable
+
+.. data:: pluginbase.import_hook.enabled
+
+ Indicates if the import hook is currently active or not.
+
+Internals
+`````````
+
+.. autodata:: pluginbase._internalspace
+
+ This module is where pluginbase keeps track of all loaded plugins.
+ Generally one can completely ignore the existence of it, but in some
+ situations it might be useful to discover currently loaded modules
+ through this when debugging.