3
0
Fork 0

Allow specifying config object for Command constructor

might as well re-use config if available..not sure how often this will
happen in practice
This commit is contained in:
Lance Edgar 2023-11-20 22:29:11 -06:00
parent 34836b006d
commit d8252f029d
3 changed files with 63 additions and 11 deletions

View file

@ -50,6 +50,26 @@ class Command:
what actually happens when it runs. Top-level commands are mostly
a stub for sake of logically grouping the subcommands.
:param config: Optional config object to use.
Usually a command is being ran via actual command line, and
there is no config object yet so it must create one. (It does
this within its :meth:`run()` method.)
But if you already have a config object you can specify it here
and it will be used instead.
:param name: Optional value to assign to :attr:`name`. Usually
this is declared within the command class definition, but if
needed it can be provided dynamically.
:param stdout: Optional replacement to use for :attr:`stdout`.
:param stderr: Optional replacement to use for :attr:`stderr`.
:param subcommands: Optional dictionary to use for
:attr:`subcommands`, instead of loading those via entry points.
The base class serves as the primary ``wutta`` command for
WuttJamaican. Most apps will subclass this and register their own
top-level command, and create subcommands as needed.
@ -102,24 +122,46 @@ class Command:
.. attribute:: version
Version string for the app or primary command.
.. attribute:: stdout
Reference to file-like object which should be used for writing
to STDOUT. By default this is just ``sys.stdout``.
.. attribute:: stderr
Reference to file-like object which should be used for writing
to STDERR. By default this is just ``sys.stderr``.
.. attribute:: subcommands
Dictionary of available subcommand classes, keyed by subcommand
name. These are usually loaded from setuptools entry points.
"""
name = 'wutta'
version = __version__
description = "Wutta Software Framework"
def __init__(self, **kwargs):
def __init__(
self,
config=None,
name=None,
stdout=None,
stderr=None,
subcommands=None):
self.name = kwargs.get('name', self.name)
self.config = config
self.name = name or self.name
self.stdout = stdout or sys.stdout
self.stderr = stderr or sys.stderr
self.subcommands = subcommands or load_entry_points(f'{self.name}.commands')
self.stdout = kwargs.get('stdout', sys.stdout)
self.stderr = kwargs.get('stderr', sys.stderr)
self.subcommands = (kwargs.get('subcommands') or
load_entry_points(f'{self.name}.commands'))
def __str__(self):
return self.name
def sorted_subcommands(self):
"""
Get a sorted list of subcommand classes.
Get the list of subcommand classes, sorted by name.
"""
return [self.subcommands[name]
for name in sorted(self.subcommands)]
@ -201,9 +243,10 @@ also try: {self.name} <subcommand> -h
sys.exit(1)
# make the config object
from wuttjamaican.conf import make_config
self.config = make_config(args.config_paths,
plus_files=args.plus_config_paths)
if not self.config:
from wuttjamaican.conf import make_config
self.config = make_config(args.config_paths,
plus_files=args.plus_config_paths)
# invoke subcommand
log.debug("running command line: %s", sys.argv)

View file

@ -22,6 +22,14 @@
################################################################################
"""
WuttJamaican - app database
For convenience, from this ``wuttjamaican.db`` namespace you can
access the following:
* :class:`~wuttjamaican.db.sess.Session`
* :class:`~wuttjamaican.db.sess.short_session`
* :class:`~wuttjamaican.conf.get_setting`
* :class:`~wuttjamaican.conf.get_engines`
"""
from .sess import Session, short_session

View file

@ -15,6 +15,7 @@ class TestCommand(TestCase):
cmd = base.Command()
self.assertEqual(cmd.name, 'wutta')
self.assertIn('setup', cmd.subcommands)
self.assertEqual(str(cmd), 'wutta')
def test_sorted_subcommands(self):
cmd = base.Command(subcommands={'foo': 'FooSubcommand',