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:

  1. By naming the function sum, we are shadowing the in-built Python function sum. This is also an issue as our function actually relies on the in-built Python sum function to actually do the addition.

  2. 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:
  • command (str | None) – New command name. If None, the command is not renamed.

  • **params (str) – Mapping of parameter names to new names. Parameter names must be defined in the decorated function signature.

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