|
Size: 2084
Comment: workin on it
|
Size: 2234
Comment:
|
| Deletions are marked like this. | Additions are marked like this. |
| Line 1: | Line 1: |
| == example == | = Example = This is a generalization of the technique used in setuptools so people can write plugins for commands. Let's take an example: you have a command where you create a list of files to build a file list (a manifest). You provide a default system to build this list but you know some people will probably provide other strategies to build that list. |
| Line 4: | Line 13: |
| So let's declare a user option, called "manifest-makers", where an ordered list of plugins name can be declared. We also declare a new attribute called `extensible_options`, to declare the list of options that are used to extend the command. |
|
| Line 5: | Line 20: |
| class MyCmd(sdist): | class MyCmd(Command): |
| Line 7: | Line 22: |
| # this is a regular user option manifest_makers = ['svn', 'template', 'hg'] |
user_options = [('manifest-makers', None, 'Plugins to build the manifest file')] |
| Line 10: | Line 25: |
| # this manages all extensions extensions = Extensible('manifest_makers') |
extensible_options = ['manifest-makers'] |
| Line 13: | Line 27: |
| def run(self): # this will build the filelist by running the plugins self.extensions.run('manifest_makers') |
def initialize_options(self): # this is a regular user option self.manifest_makers = ['svn', 'template', 'hg'] self.files = [] |
| Line 17: | Line 32: |
| def finalize_options(self): pass |
|
| Line 18: | Line 35: |
| dist = Distribution() cmd = MyCmd(dist) cmd.ensure_finalized() cmd.run() |
def run(self): # this will build the filelist by running the plugins self.run_extension('manifest-makers') |
| Line 25: | Line 41: |
| Notice that self.extensions.load(self) is implicitely called by Command. | What happened ? In the initialize options, we declared default values for the manifest_makers attribute : three plugins called 'svn', 'template' and 'hg'. |
| Line 27: | Line 44: |
| == code == | The Command will load these plugins using setuptools entry point called: "distutils.!MyCmd.manifest_makers". It will load them at the end of the option finalization. |
| Line 29: | Line 47: |
| Then, a new API called "run_extension" allows !MyCmd to run these plugins. Each plugin receives the command and the name of the option in argument and is free to work over the command and its distribution. For example, the signature for the svn plugin is : |
|
| Line 30: | Line 54: |
| """Extendable command""" import os import pkg_resources |
def svn(cmd, name): # work done here on the command }}} |
| Line 34: | Line 58: |
| class Extensible(object): | Read more about how to create plugins with entry points, and what they are, here : http://lucumr.pocoo.org/2006/7/30/setuptools-plugins |
| Line 36: | Line 60: |
| def __init__(self, *options): self.options = options self._ext = {} |
= Implementation = |
| Line 40: | Line 62: |
| def load(self, cmd): for opt in self.options: ep = ExtensionPoint(cmd, opt) ep.load() self._ext[opt] = ep def run(self, name): self._ext[name].run() class ExtensionPoint(object): def __init__(self, cmd, name): self.name = name self.cmd = cmd self.entries = [] def load(self, name=None): if name is None: name = self.cmd.get_command_name() entry_point = 'distutils.%s:%s' % (name, self.name) else: entry_point = name self._entries = [entry for entry in [self._load(ep) for ep in pkg_resources.iter_entry_points(entry_point)] if entry is not None] def _load(self, entry_point): values = getattr(self.cmd, self.name) if not isinstance((list, tuple), values): values = [values] entry_point = entry_point.load() if entry_point.name not in values: return None return entry_point def run(self): for ep in self._entries: entry_point(self.cmd, self.name) def apply(self, name=None): self.load(name) self.run() }}} |
* http://svn.plone.org/svn/collective/collective.releaser/branches/refactor/collective/releaser/commands/extendable.py * http://svn.plone.org/svn/collective/collective.releaser/branches/refactor/collective/releaser/tests/test_extendable.py |
Example
This is a generalization of the technique used in setuptools so people can write plugins for commands.
Let's take an example: you have a command where you create a list of files to build a file list (a manifest).
You provide a default system to build this list but you know some people will probably provide other strategies to build that list.
So let's declare a user option, called "manifest-makers", where an ordered list of plugins name can be declared.
We also declare a new attribute called extensible_options, to declare the list of options that are used to extend the command.
class MyCmd(Command):
user_options = [('manifest-makers', None,
'Plugins to build the manifest file')]
extensible_options = ['manifest-makers']
def initialize_options(self):
# this is a regular user option
self.manifest_makers = ['svn', 'template', 'hg']
self.files = []
def finalize_options(self):
pass
def run(self):
# this will build the filelist by running the plugins
self.run_extension('manifest-makers')What happened ? In the initialize options, we declared default values for the manifest_makers attribute : three plugins called 'svn', 'template' and 'hg'.
The Command will load these plugins using setuptools entry point called: "distutils.MyCmd.manifest_makers". It will load them at the end of the option finalization.
Then, a new API called "run_extension" allows MyCmd to run these plugins.
Each plugin receives the command and the name of the option in argument and is free to work over the command and its distribution.
For example, the signature for the svn plugin is :
def svn(cmd, name):
# work done here on the commandRead more about how to create plugins with entry points, and what they are, here : http://lucumr.pocoo.org/2006/7/30/setuptools-plugins
