File: parameter_validators.rst

package info (click to toggle)
python-cyclopts 3.12.0-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 3,288 kB
  • sloc: python: 11,445; makefile: 24
file content (92 lines) | stat: -rw-r--r-- 3,767 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
.. _Parameter Validators:

====================
Parameter Validators
====================
In CLI applications, users have the freedom to input a wide range of data.
This flexibility can lead to inputs the application does not expect.
By coercing the input into a data type (like an :obj:`int`), we are already limiting the input to a certain degree (e.g. "foo" cannot be coerced into an integer).
To further restrict the user input, you can populate the :attr:`~.Parameter.validator` field of :class:`.Parameter`.

A validator is any callable object (such as a function) that has the signature:

.. code-block:: python

   def validator(type_, value: Any) -> None:
       pass  # Raise any exception here if ``value`` is invalid.

Validation happens **after** the data converter runs.
Any of :exc:`AssertionError`, :exc:`TypeError` or :exc:`ValidationError` will be promoted to a :exc:`cyclopts.ValidationError` so that the exception gets presented to the end-user in a nicer way.
More than one validator can be supplied as a list to the :attr:`~.Parameter.validator` field.

Cyclopts has some builtin common validators in the :ref:`cyclopts.validators <API Validators>` module.
See :ref:`Annotated Types` for common specific definitions provided as convenient pre-annotated types.

----
Path
----
The :class:`.Path` validator ensures certain properties
of the parsed :class:`pathlib.Path` object, such as asserting the file must exist.

.. code-block:: python

   from cyclopts import App, Parameter, validators
   from typing import Annotated
   from pathlib import Path

   app = App()

   @app.default()
   def foo(path: Annotated[Path, Parameter(validator=validators.Path(exists=True))]):
       print(f"File contents:\n{path.read_text()}")

   app()

.. code-block:: console

   $ echo Hello World > my_file.txt

   $ my-script my_file.txt
   File contents:
   Hello World

   $ my-script this_file_does_not_exist.txt
   ╭─ Error ────────────────────────────────────────────────────────────╮
   │ Invalid value "this_file_does_not_exist.txt" for "PATH".           │
   │ "this_file_does_not_exist.txt" does not exist.                     │
   ╰────────────────────────────────────────────────────────────────────╯

See :ref:`Annotated Path Types <Annotated Path Types>` for Annotated-Type equivalents of common Path converter/validators.

------
Number
------
The :class:`.Number` validator can set minimum and maximum input values.

.. code-block:: python

   from cyclopts import App, Parameter, validators
   from typing import Annotated

   app = App()

   @app.default()
   def foo(n: Annotated[int, Parameter(validator=validators.Number(gte=0, lt=16))]):
       print(f"Your number in hex is {str(hex(n))[2]}.")

   app()

.. code-block:: console

   $ my-script 0
   Your number in hex is 0.

   $ my-script 15
   Your number in hex is f.

   $ my-script 16
   ╭─ Error ────────────────────────────────────────────────────────────╮
   │ Invalid value "16" for "N". Must be < 16.                          │
   ╰────────────────────────────────────────────────────────────────────╯

See :ref:`Annotated Number Types <Annotated Number Types>` for Annotated-Type equivalents of common Number converter/validators.