Step 1: Simple calculator
Contents
Step 1: Simple calculator¶
We build a script that takes two floating-point values as an argument, adds them and displays them.
In the code below, we write our own Parser subclass to parse
floating-point numbers.
Let’s observe a few things.
On the code general structure:
The most used
configpileidentifiers are imported when writingfrom configpile import *; they are aliases of identifiers in subpackages (for exampleconfigpile.Configis an alias ofconfigpile.config.Config).The “configuration” is a dataclass using
dataclass(). It should be frozen because there is no reason not to.The “configuration” is also a subclass of
configpile.config.Config.The script help is given in the class docstring; argument descriptions are written using sphinx autodoc style comments (they start with
#:).
On the parser declaration:
A parser is a subclass of
configpile.parsers.Parser, which is generic: when declaring the inheritance relation, we specify what this parser returns: afloat.To subclass a parser, one only needs to implement the
parse()method.
On the parameter declarations:
The parameters are dataclass fields. They are automatically filled by
configpilewhen callingconfigpile.config.Config.from_command_line_()using the information given in the annotated type annotation.The extra information provided in the
typing.Annotatedwrapper is removed when type checking, and is used only byconfigpilewhen it performs its introspection. For mypy, the fieldsxandyhave typefloat.The extra information is of type
Param, and the concept is detailed in Params (parameters).Here, we instantiate a
Paramthrough theconfigpile.arg.Param.store()static method. This a kind of parameter that takes the last value provided. Note that we did not define a default value for the parameters, thus both of them will be required.The command-line flags
--xand--yare automatically deduced from the Python identifiers.
On the sample script executions:
Note that when the script is called with a
--helpargument, or when the configuration cannot be parsed, the script execution is aborted. Whenconfigpiledeals with a--helpargument, the script execution has an exit value of0, but when there is an error, the exit value will be positive to signal this fact.When several errors occur,
configpiledoes not stop at the first error encountered but accumulates them.
Code¶
"""
Calculator tutorial, step 1
"""
from dataclasses import dataclass
from typing_extensions import Annotated
from configpile import Config, Err, Param, Parser, Res
class FloatPT(Parser[float]):
"""
Parameter type that parses floats
"""
def parse(self, arg: str) -> Res[float]:
try:
return float(arg)
except ValueError as e:
return Err.make(str(e))
floatPT = FloatPT()
@dataclass(frozen=True)
class Calc(Config):
"""
Command-line tool that sums two floating point numbers
"""
#: First argument
x: Annotated[float, Param.store(floatPT)]
#: Second argument
y: Annotated[float, Param.store(floatPT)]
c = Calc.from_command_line_()
print(f"{c.x} + {c.y} = {c.x+c.y}")
Executions¶
Note that on the examples below, the path to the Python script is relative to the docs/source
folder.
$ python ../../examples/calculator1.py --help
usage: ../../examples/calculator1.py [--x X] [--y Y]
Command-line tool that sums two floating point numbers
required arguments:
--x X First argument
--y Y Second argument
$ python ../../examples/calculator1.py --x 1 --y 2
1.0 + 2.0 = 3.0
$ python ../../examples/calculator1.py --x asd --y zxc
Encountered errors:
0 In flag: --x
In param: x
could not convert string to float: 'asd'
1 In flag: --y
In param: y
could not convert string to float: 'zxc'
usage: ../../examples/calculator1.py [--x X] [--y Y]
Command-line tool that sums two floating point numbers
required arguments:
--x X First argument
--y Y Second argument