Skip to content

Commit

Permalink
Merge pull request #4 from piccolo-orm/aliases
Browse files Browse the repository at this point in the history
Aliases
  • Loading branch information
dantownsend committed May 13, 2021
2 parents 1195f92 + a6e5f0e commit 4d91abc
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 16 deletions.
30 changes: 30 additions & 0 deletions docs/src/cli.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,36 @@ You can also register coroutines, as well as normal functions:
cli.register(timer)
cli.run()
Aliases
-------

You can specify aliases for each command, which can make your CLI more
convenient to use. For example, an alias could be an abbreviation, or a common
mispelling.

.. code-block:: python
from targ import CLI
def add(a: int, b: int):
print(a + b)
if __name__ == "__main__":
cli = CLI()
cli.register(add, aliases=['+', 'sum'])
cli.run()
Both of the following will now work:

.. code-block:: bash
python main.py add 1 1
python main.py + 1 1
python main.py sum 1 1
Groups
------

Expand Down
2 changes: 1 addition & 1 deletion example_script.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ async def timer(seconds: int):
cli = CLI()
cli.register(say_hello)
cli.register(echo)
cli.register(add)
cli.register(add, aliases=["+"])
cli.register(print_pi)
cli.register(compound_interest)
cli.register(compound_interest_decimal)
Expand Down
24 changes: 9 additions & 15 deletions targ/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class Command:
command: t.Callable
group_name: t.Optional[str] = None
command_name: t.Optional[str] = None
aliases: t.List[str] = field(default_factory=list)

def __post_init__(self):
self.command_docstring: Docstring = parse(self.command.__doc__)
Expand Down Expand Up @@ -223,19 +224,6 @@ class CLI:
description: str = "Targ CLI"
commands: t.List[Command] = field(default_factory=list)

@property
def group_names(self) -> t.List[str]:
return [i.group_name for i in self.commands if i.group_name]

def command_exists(self, group_name: str, command_name: str) -> bool:
for command in self.commands:
if (
command.group_name == group_name
and command.command_name == command_name
):
return True
return False

def _validate_name(self, name: str) -> bool:
"""
Any custom names provided by user should not contain spaces (i.e.
Expand All @@ -250,7 +238,7 @@ def register(
command: t.Callable,
group_name: t.Optional[str] = None,
command_name: t.Optional[str] = None,
root=False,
aliases: t.List[str] = [],
):
"""
Register a function or coroutine as a CLI command.
Expand All @@ -266,6 +254,8 @@ def register(
By default, the name of the CLI command will be the same as the
function or coroutine which is being called. You can override this
here.
:param aliases:
The command can also be accessed using these aliases.
"""
if group_name and not self._validate_name(group_name):
Expand All @@ -279,6 +269,7 @@ def register(
command=command,
group_name=group_name,
command_name=command_name,
aliases=aliases,
)
)

Expand Down Expand Up @@ -314,7 +305,10 @@ def get_command(
self, command_name: str, group_name: t.Optional[str] = None
) -> t.Optional[Command]:
for command in self.commands:
if command.command_name == command_name:
if (
command.command_name == command_name
or command_name in command.aliases
):
if group_name and command.group_name != group_name:
continue
return command
Expand Down
25 changes: 25 additions & 0 deletions tests/test_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,3 +412,28 @@ def test_command(arg1: float, arg2: bool):
cli.run()
print_mock.assert_called_with(config.output)
print_mock.reset_mock()

@patch("targ.CLI.get_cleaned_args")
def test_aliases(self, get_cleaned_args):
"""
Make sure commands with aliases can be called correctlyy.
"""

def test_command():
print("Command called")

cli = CLI()
cli.register(test_command, aliases=["tc"])

with patch("builtins.print", side_effect=print_) as print_mock:

configs: t.List[Config] = [
Config(params=["test_command"], output="Command called"),
Config(params=["tc"], output="Command called"),
]

for config in configs:
get_cleaned_args.return_value = config.params
cli.run()
print_mock.assert_called_with(config.output)
print_mock.reset_mock()

0 comments on commit 4d91abc

Please sign in to comment.