aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElena ``of Valhalla'' Grandi <valhalla@trueelena.org>2022-02-22 17:45:23 +0100
committerElena ``of Valhalla'' Grandi <valhalla@trueelena.org>2022-02-22 17:45:23 +0100
commit85727f9bd9b36d4936d4d19514b7cdfe4fffca43 (patch)
treec4264ad79b0e16ef7210664675fbef5e33fa18d8
parent3195e3e213084f086dec5d81447e0db16d622337 (diff)
Subcommands
-rw-r--r--hazwaz/__init__.py2
-rw-r--r--hazwaz/command.py34
-rw-r--r--tests/test_command.py62
3 files changed, 87 insertions, 11 deletions
diff --git a/hazwaz/__init__.py b/hazwaz/__init__.py
index f5f0a6d..4986238 100644
--- a/hazwaz/__init__.py
+++ b/hazwaz/__init__.py
@@ -1 +1 @@
-from .command import MainCommand # noqa: F401
+from .command import MainCommand, Command # noqa: F401
diff --git a/hazwaz/command.py b/hazwaz/command.py
index c99e012..a8866ab 100644
--- a/hazwaz/command.py
+++ b/hazwaz/command.py
@@ -10,6 +10,7 @@ def _get_first_docstring_line(obj):
except (AttributeError, IndexError):
return None
+
def _get_remaining_docstring_lines(obj):
try:
return "\n".join(obj.__doc__.split('\n')[2:]).strip()
@@ -30,15 +31,15 @@ class MainCommand:
self.add_arguments(self.parser)
self.parser.set_defaults(func=self._main)
self.subparsers = self.parser.add_subparsers()
- for name, sub in self.commands:
+ for sub in self.commands:
sub_help = _get_first_docstring_line(sub)
+ sub_epilog = _get_remaining_docstring_lines(sub)
sub_parser = self.subparsers.add_parser(
- name,
- help=sub_help,
- description=sub.__doc__,
+ sub.name,
+ description=sub_help,
+ epilog=sub_epilog,
)
- for arg in sub.arguments:
- sub_parser.add_argument(*arg[0], **arg[1])
+ sub.add_arguments(sub_parser)
sub_parser.set_defaults(func=sub._main)
def _main(self, args):
@@ -60,9 +61,26 @@ class MainCommand:
def main(self):
self.args = self.parser.parse_args()
- if self.args.verbose:
- logger.setLevel(logging.VERBOSE)
if self.args.debug:
logger.setLevel(logging.DEBUG)
+ elif self.args.verbose:
+ logger.setLevel(logging.INFO)
+ else:
+ logger.setLevel(logging.WARNING)
self.args.func(self.args)
+
+
+class Command:
+ name = None
+
+ def __init__(self):
+ if self.name is None:
+ self.name = self.__class__.__name__.lower()
+
+ def _main(self, args):
+ self.args = args
+ self.main()
+
+ def add_arguments(self, parser):
+ pass
diff --git a/tests/test_command.py b/tests/test_command.py
index eed6e1f..d0b6437 100644
--- a/tests/test_command.py
+++ b/tests/test_command.py
@@ -6,19 +6,41 @@ import unittest
import hazwaz
+class MySubCommand(hazwaz.Command):
+ """
+ A subcommand.
+
+ This does very little.
+ """
+
+ def add_arguments(self, parser):
+ super().add_arguments(parser)
+ parser.add_argument(
+ "--bar",
+ action="store_true",
+ help="barfoo things"
+ )
+
+ def main(self):
+ print("Hello World")
+
+
class MyCommand(hazwaz.MainCommand):
"""
A command that does things.
This is a command, but honestly it doesn't really do anything.
"""
- commands = ()
+ commands = (
+ MySubCommand(),
+ )
def add_arguments(self, parser):
super().add_arguments(parser)
parser.add_argument(
"--foo",
- help="foobar things"
+ action="store_true",
+ help="foobar things",
)
@@ -68,12 +90,48 @@ class testCommand(unittest.TestCase):
self.assertIn("--verbose", cmd_help)
self.assertIn("--foo", cmd_help)
+ def test_subparser(self):
+ cmd = MyCommand()
+ sub_parser = cmd.subparsers.choices["mysubcommand"]
+ self.assertEqual(sub_parser.description, "A subcommand.")
+ self.assertEqual(
+ sub_parser.epilog,
+ "This does very little.",
+ )
+
def test_run(self):
cmd = MyCommand()
cmd_help = cmd.parser.format_help()
stream = self._run_with_argv(cmd, ["mycommand"])
self.assertEqual(stream["stdout"].getvalue(), cmd_help)
+ def test_run_with_option(self):
+ cmd = MyCommand()
+ cmd_help = cmd.parser.format_help()
+ stream = self._run_with_argv(cmd, [
+ "mycommand",
+ "--verbose",
+ ])
+ self.assertEqual(stream["stdout"].getvalue(), cmd_help)
+ stream = self._run_with_argv(cmd, [
+ "mycommand",
+ "--debug",
+ ])
+ self.assertEqual(stream["stdout"].getvalue(), cmd_help)
+
+ def test_run_subcommand(self):
+ cmd = MyCommand()
+ stream = self._run_with_argv(cmd, ["mycommand", "mysubcommand"])
+ self.assertEqual(stream["stdout"].getvalue(), "Hello World\n")
+
+ def test_run_subcommand_with_option(self):
+ cmd = MyCommand()
+ stream = self._run_with_argv(cmd, [
+ "mycommand",
+ "mysubcommand",
+ "--bar",
+ ])
+ self.assertEqual(stream["stdout"].getvalue(), "Hello World\n")
if __name__ == '__main__':