1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
Writing Plugins
===============
Plugins can exist inside your
existing packages or in special namespace packages, which exist
only to house plugins.
The only requirement is that any package containing plugins be
designated a "namespace package", which is currently performed
in Python via the ``pkgutil.extend_path`` utility, seen below.
This allows the namespace to be provided in multiple places on
the python ``sys.path``, where ``import`` looks, and all the
contents will be combined.
Use a :term:`namespace package`
This allows multiple packages installed on your system to share
this name, so they may come from different installed projects
and all combine to provide a larger set of plugins.
Example
-------
::
# logfilter/__init__.py
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
::
# logfilter/hide_extra.py
from logfilter import Skip
def filter(log_entry):
level = log_entry.split(':', 1)[0]
if level != 'EXTRA':
return log_entry
else:
raise Skip()
Using the plugin
''''''''''''''''
In our log tool, we might load all the modules in the ``logfilter``
namespace, and then use them all to process each entry in our logs.
We don't need to know all the filters ahead of time, and other packages
can be installed on a user's system providing additional modules
in the namespace, which we never even knew about.
::
from straight.plugin import load
class Skip(Exception):
pass
plugins = load('logfilter')
def filter_entry(log_entry):
for plugin in plugins:
try:
log_entry = plugin.filter(log_entry)
except Skip:
pass
return log_entry
Distributing Plugins
''''''''''''''''''''
If you are writing plugins inside your own project to use, they'll be
distributed like any other modules in your package. There is no extra work
to do here.
However, if you want to release and distribute plugins on their own, you'll
need to tell your :term:`setup.py` about your :term:`namespace package`.
::
setup(
# ...
namespace_packages = ['logfilter.plugins']
)
This will make sure when your plugins are installed alongside the original
project, both are importable, even though they came from their own
distributions.
You can read more about this at the Distribute
`documentation on namespace packages <http://packages.python.org/distribute/setuptools.html#namespace-packages>`_.
|