Add base classes for multi-commands.
Review Request #11882 — Created Nov. 24, 2021 and submitted — Latest diff uploaded
We'll soon be adding two new commands,
rbt api
andrbt review
, which
both want to implement additional subcommands (rbt api get
,
rbt review publish
, etc). This change adds the framework to do so,
consisting of two new base classes.SubCommand
should be inherited for
each subcommand offered, andMultiCommand
aggregates them together.
Arguments from theMultiCommand
are added in to the subcommand
parsers.The one tricky thing here was getting
--help
to do the right thing. In
the case ofMultiCommand
s, we need to actually parse the arguments in
order to get the right subparser, but doing so was enforcing any usage
requirements. It turns out that the correct fix here was to allow
add_help
to default toTrue
in the parser initialization. This
allows us to callparse_args
and have it not fail.I did also have to move the logging setup out of the
initialize
method, so that we wouldn't attach multiple log handlers.
Used this extensively with the upcoming review command.
rbtools/commands/__init__.py | |||
---|---|---|---|
Diff Revision 2 | Diff Revision 3 | ||
266 lines | |||
def add_to(self, parser, config={}, argv=[]):
|
|||
267 | 267 | ||
268 |
argv (list, deprecated):
|
268 |
argv (list, deprecated):
|
269 |
Unused legacy argument.
|
269 |
Unused legacy argument.
|
270 |
"""
|
270 |
"""
|
271 |
# First look for an existing group with the same name. This allows
|
271 |
# First look for an existing group with the same name. This allows
|
272 |
# a SubCommand to merge review groups with its parent MultiCommand.
|
272 |
# a BaseSubCommand to merge review groups with its parent
|
273 |
# BaseMultiCommand.
|
||
273 |
for group in parser._action_groups: |
274 |
for group in parser._action_groups: |
274 |
if group.title == self.name: |
275 |
if group.title == self.name: |
275 |
break
|
276 |
break
|
276 |
else: |
277 |
else: |
277 |
group = parser.add_argument_group(self.name, self.description) |
278 |
group = parser.add_argument_group(self.name, self.description) |
1177 lines | |||
def __init__(self, options, config, *args, **kwargs):
|
|||
1455 |
The parsed options.
|
1456 |
The parsed options.
|
1456 | 1457 | ||
1457 |
config (dict):
|
1458 |
config (dict):
|
1458 |
The loaded RBTools configuration.
|
1459 |
The loaded RBTools configuration.
|
1459 |
"""
|
1460 |
"""
|
1460 |
super(SubCommand, self).__init__(*args, **kwargs) |
1461 |
super(BaseSubCommand, self).__init__(*args, **kwargs) |
1461 |
self.options = options |
1462 |
self.options = options |
1462 |
self.config = config |
1463 |
self.config = config |
1463 | 1464 | ||
1464 | 1465 | ||
1465 |
class BaseMultiCommand(Command): |
1466 |
class BaseMultiCommand(Command): |
1466 |
"""Abstract base class for commands which offer subcommands. |
1467 |
"""Abstract base class for commands which offer subcommands. |
1467 | 1468 | ||
1468 |
Some commands (such as :command:`rbt review`) want to offer many
|
1469 |
Some commands (such as :command:`rbt review`) want to offer many
|
1469 |
subcommands.
|
1470 |
subcommands.
|
1470 |
"""
|
1471 |
"""
|
1471 | 1472 | ||
1472 |
#: The available subcommands.
|
1473 |
#: The available subcommands.
|
1473 |
#:
|
1474 |
#:
|
1474 |
#: This is a list of SubCommand sub classes.
|
1475 |
#: This is a list of BaseSubCommand sub classes.
|
1475 |
#:
|
1476 |
#:
|
1476 |
#: Type:
|
1477 |
#: Type:
|
1477 |
#: list
|
1478 |
#: list
|
1478 |
subcommands = {} |
1479 |
subcommands = {} |
1479 | 1480 | ||
73 lines | |||
def create_parser(self, config, argv=[]):
|
|||
1553 | 1554 | ||
1554 |
return parser |
1555 |
return parser |
1555 | 1556 | ||
1556 |
def initialize(self): |
1557 |
def initialize(self): |
1557 |
"""Initialize the command.""" |
1558 |
"""Initialize the command.""" |
1558 |
super(MultiCommand, self).initialize() |
1559 |
super(BaseMultiCommand, self).initialize() |
1559 | 1560 | ||
1560 |
command = self.options.command_cls(options=self.options, |
1561 |
command = self.options.command_cls(options=self.options, |
1561 |
config=self.config, |
1562 |
config=self.config, |
1562 |
transport_cls=self.transport_cls) |
1563 |
transport_cls=self.transport_cls) |
1563 |
command.stdout = self.stdout |
1564 |
command.stdout = self.stdout |
40 lines |