Step 5: Additional features

Step 5: Additional features

Finally, we include two additional parameters in our calculator.

  • The user can choose between addition and multiplication. The default operation is addition ("+").

  • The user can select the number of displayed digits, the default value is 3.

Note the following new features.

  • Parameter from a list of choices

    One can construct a parser of strings using the from_choices() static method of Param. The possible choices are displayed in the usage description when invoking the script help.

  • Default values

    Default values are given as strings, and they are parsed by configpile using the same parser used for other strings. Though if there is a problem, we do not report an error but rather throw an exception.

  • Environment variables

    Parameters can be set from environment variables, though this is disabled by default.

    Set the configpile.arg.Param.env_var_name field to enable this feature, and see how to use it in the sample executions below. Note that one can export DIGITS=10 in Bash scripts as well.

  • Validation

    By applying the validated() method on a parser, one can ensure that the final value in the configuration obeys constraints.

Code

"""
Calculator tutorial, step 5
"""
from dataclasses import dataclass
from math import prod
from typing import Sequence

from typing_extensions import Annotated

from configpile import Config, Param, Positional, parsers


@dataclass(frozen=True)
class Calc(Config):
    """
    Command-line tool that sums an arbitrary number of floating point values
    """

    #: Values to sum
    values: Annotated[
        Sequence[float],
        Param.append1(
            parsers.float_parser,
            positional=Positional.ZERO_OR_MORE,
            short_flag_name=None,
            long_flag_name=None,
        ),
    ]

    #: Operation to perform, either addition "+" or multiplication "*"
    operation: Annotated[
        str,
        Param.store(
            parsers.Parser.from_choices(["+", "*"]),
            default_value="+",
        ),
    ]

    #: Number of digits to display
    #:
    #: This number of digits can also be set with the environment variable
    #: ``DIGITS``
    digits: Annotated[
        int,
        Param.store(
            parsers.int_parser.validated(lambda i: i > 0, "Must be a positive integer"),
            default_value="3",
            env_var_name="DIGITS",
        ),
    ]


c = Calc.from_command_line_()
fmt_string = f"%.{c.digits}f"
if c.operation == "+":
    print(fmt_string % sum(c.values))
elif c.operation == "*":
    print(fmt_string % prod(c.values))

Executions

$ python ../../examples/calculator5.py --help
usage: ../../examples/calculator5.py [--operation {+,*}] [--digits DIGITS]
                                     values

Command-line tool that sums an arbitrary number of floating point values

optional arguments:
  values             Values to sum
  --operation {+,*}  Operation to perform, either addition "+" or multiplication "*"
  --digits DIGITS    Number of digits to display
                     
                     This number of digits can also be set with the environment variable
                     ``DIGITS``
$ python ../../examples/calculator5.py 1 2 3 4 --operation "*"
24.000
$ bash -c "DIGITS=10 python ../../examples/calculator5.py 1 2 3 4"
10.0000000000