Renaming commands/parameters#
In certain cases, it may be desirable or even necessary for the names of the commands or parameters generated by Feud to be different to the names of the Python functions (and their parameters) that were used to generate the commands.
The rename()
operator can be used in these scenarios to rename commands
or parameters.
Examples#
Defining commands or parameters with reserved keywords#
Suppose we have the following command, sum
,
which takes a starting number from
, and an ending number to
,
and sums all numbers between and including the starting and ending number.
This might be called in the following way:
$ sum --from 1 --to 10
With generating code that might look like:
# sum.py
import feud
def sum(*, from: int, to: int):
"""Sums the numbers between and including a start and end number.
Parameters
----------
from:
Starting number.
to:
Ending number.
"""
print(sum(range(from, to + 1)))
if __name__ == "__main__":
feud.run(sum)
There are two problems here:
By naming the function
sum
, we are shadowing the in-built Python functionsum
. This is also an issue as our function actually relies on the in-built Pythonsum
function to actually do the addition.from
is also a reserved Python keyword which is used in module imports, and cannot be used as a function parameter.
We can use the rename()
decorator to rename both the command and parameter.
# sum.py
import feud
@feud.rename("sum", from_="from")
def sum_(*, from_: int, to: int):
"""Sums the numbers between and including a start and end number.
Parameters
----------
from_:
Starting number.
to:
Ending number.
"""
print(sum(range(from, to + 1)))
if __name__ == "__main__":
feud.run(sum_)
This gives us valid Python code, and also our expected CLI behaviour.
Defining hyphenated commands or parameters#
Suppose we have a command that should be called in the following way:
$ say-hi --welcome-message "Hello World!"
As Feud uses the parameter names present in the Python function signature as the parameter names for the generated CLI, this means that defining parameters with hyphens is usually not possible, as Python identifiers cannot have hyphens. Similarly, a function name cannot have a hyphen:
# hyphen.py
import feud
def say-hi(*, welcome-message: str):
print(welcome-message)
if __name__ == "__main__":
feud.run(say-hi)
We can use the rename()
decorator to rename both the command and parameter.
# hyphen.py
import feud
@feud.rename("say-hi", welcome_message="welcome-message")
def say_hi(*, welcome_message: str):
print(welcome_message)
if __name__ == "__main__":
feud.run(say_hi)
This gives us valid Python code, and also our expected CLI behaviour.
Special use case for maintaining group-level configurations#
Although command()
accepts a name
argument (passed to Click) that can be
used to rename a command, this can sometimes be undesirable in the case of Groups.
In the following example, although show_help_defaults
has been set to
False
at the group level (which would usually mean that all commands
defined within the group will not have their parameter defaults shown in
--help
), this has been overridden by the feud.command
call which
has show_help_defaults=True
by default.
class CLI(feud.Group, show_help_defaults=False):
@feud.command(name="my-func")
def my_func(*, opt: int = 1):
pass
Using @feud.rename("my-func")
instead of @feud.command(name="my-func")
would allow for the group-level configuration to be used, while still renaming
the function.
API reference#
- feud.decorators.rename(command=None, /, **params)#
Rename a command and/or its parameters.
Useful for command/parameter names that use hyphens, reserved Python keywords or in-built function names.
- Parameters:
- Return type:
Function decorated with command/parameter renaming metadata.
Examples
Renaming a command.
>>> import feud >>> @feud.rename("my-func") ... def my_func(arg_1: int, *, opt_1: str, opt_2: bool): ... pass
Renaming parameters.
>>> import feud >>> @feud.rename(arg_1="arg-1", opt_2="opt-2") ... def my_func(arg_1: int, *, opt_1: str, opt_2: bool): ... pass
Renaming a command and parameters.
>>> import feud >>> @feud.rename("my-func", arg_1="arg-1", opt_2="opt-2") ... def my_func(arg_1: int, *, opt_1: str, opt_2: bool): ... pass