Gather¶
Overview¶
The gather
package allows gathering up plugins.
Entry points¶
Gathering depends on
registering an entry point in the
package.
For example,
with
pyproject.toml
:
[project.entry-points.gather]
ignored = "<ROOT_PACKAGE>"
Putting the package name there is enough – gather
will automatically collect from any sub-modules,
recursing any number of levels.
These entry points are enough regardless of the plugin collector:
collectors will only collect their own plugins.
Collectors¶
A
Collector
represents a
“kind of plugin”.
It is an object,
usually defined at the top level of a module:
import gather
THINGS = gather.Collector()
Collecting all registered functions:
registered = THINGS.collect()
The return value is a dictionary, mapping names to sets of registered functions.
The function
gather.unique
takes a dictionary,
and returns a dictionary
mapping names to registered functions.
It will raise a
ValueError
if multiple functions are registered to the same name.
Registering¶
In order to register a function as a plugin, decorate it using the relevant collector:
@THINGS.register()
def some_function():
pass
The decorator always returns the function
without modification.
This allows,
for example,
using
some_function
in a unit test.
If an alternative name is needed for registration, one can be provided explicitly:
@THINGS.register(name='register_as_this_name')
def generic():
pass
Transforms¶
Depending on the collector,
it might expect some extra data.
This should be documented as part of the collector.
Supplying the data is done with the
transform
argument:
@THINGS.register(
name='register_as_this_name',
transform=things_transformer(flexibility=5),
)
def generic():
pass
The collector can define a transformer using
gather.Wrapper
:
def things_transformer(flexibility):
return gather.Wrapper.glue(flexibility)
When collecting,
the value in the mapping returned in
.collect()
will be an object.
The
.original
attribute will be the function.
The
.extra
will be the arguments given to the
glue
function:
in this case,
for
register_as_name
,
it will be
5
.
API¶
Plugins¶
Gather – Collect all your plugins
Gather allows a way to register plugins. It features the ability to register the plugins from any module, in any package, in any distribution. A given module can register plugins of multiple types.
In order to have anything registered from a package,
it needs to declare that it supports gather
in its package metadata.
For example,
with
pyproject.toml
:
[project.entry-points.gather]
ignored = "<ROOT_PACKAGE>"
The ROOT_PACKAGE
should point to the Python name of the package:
i.e., what users are expected to import
at the top-level.
Note that while having special facilities to run functions as subcommands, Gather can be used to collect anything.
- class gather.api.Collector(name=None, depth=1)[source]¶
A plugin collector.
A collector allows to register functions or classes by modules, and collect-ing them when they need to be used.
- collect()[source]¶
Collect all registered functions or classes.
Returns a dictionary mapping names to registered elements.
- register(name=None, transform=<function Collector.<lambda>>)[source]¶
Register a class or function
- Parameters:
name (str) – optional. Name to register the class or function as. (default is name of object)
transform (callable) – optional. A one-argument function. Will be called, and the return value used in collection. Default is identity function
This is meant to be used as a decoator:
@COLLECTOR.register() def specific_subcommand(args): pass @COLLECTOR.register(name='another_specific_name') def main(args): pass
Command dispatch¶
Registration and dispatch to sub-commands
- gather.commands.run(*, parser, argv=sys.argv, env=os.environ, sp_run=subprocess.run)[source]¶
Parse arguments and run the command.
Pass non-default args in testing scenarios.
- Parameters:
argv – sys.argv or something that looks like it
env – os.environ or something that looks like it
sp_run – subprocess.run or something that looks like it
- Returns:
Return value from dispatched command
- gather.commands.add_argument(*args, **kwargs)[source]¶
Add argument to a registered command.
See
argparse.ArgumentParser.add_argument
for a description of the argument semantics.
- gather.commands.make_command_register(collector)[source]¶
Return a decorator that registers a command.
- Parameters:
collector – Collector to add commands to
- Returns:
Callable that expects positional add_argument arguments, and returns a decorator that registers the function to the collector.
- gather.commands.set_parser(*, collected, parser=None)[source]¶
Set (or create) a parser.
The parser will dispatch to the functions collected. The parser will configure the argument parsing according to the function’s
add_argument
in the registration.- Parameters:
collected – Return value from
Collector.collected
parser – an argument parser
- Returns:
An argument parser