fix(validation)
This commit is contained in:
parent
2e826db3f4
commit
3be1324da3
6 changed files with 230 additions and 216 deletions
|
|
@ -6,106 +6,159 @@ Synopsis
|
||||||
|
|
||||||
A verification is a complementary validation to the type which allows the content of a variable to be validated more precisely.
|
A verification is a complementary validation to the type which allows the content of a variable to be validated more precisely.
|
||||||
|
|
||||||
A :term:`validator` is necessarily a Jinja type calculation.
|
The purpose of validation is to verify that the variable is of :ref:`good quality <data_quality>` and/or that the variable is :ref:`consistent <consistency>`.
|
||||||
|
|
||||||
|
.. glossary::
|
||||||
|
|
||||||
|
validator
|
||||||
|
|
||||||
|
A validator is a Jinja code that parses a variable's value and checks
|
||||||
|
that this value corresponds to some stated criteria.
|
||||||
|
This is a `validator` parameter of our variable, and another `jinja` sub-parameter
|
||||||
|
contains validation code for the variable's value.
|
||||||
|
|
||||||
|
.. seealso:: The tutorial with a real world sample :ref:`validators <tutorial_validators>`
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
Depending on the types of calculation, the parameters will be different:
|
Depending on the types of calculation, the parameters will be different:
|
||||||
|
|
||||||
.. list-table::
|
.. list-table::
|
||||||
:widths: 15 25 20 15
|
|
||||||
:header-rows: 1
|
:header-rows: 1
|
||||||
|
|
||||||
* - **Calculation type**
|
* - **Calculation type**
|
||||||
- **Parameter**
|
- **Comment**
|
||||||
- **Comments**
|
|
||||||
- **Sample**
|
* - **type**
|
||||||
|
|
||||||
* -
|
|
||||||
- **type**
|
|
||||||
|
|
||||||
`string`
|
`string`
|
||||||
|
- The value is `jinja`
|
||||||
`mandatory`
|
|
||||||
- Type of calculation, the only possible value is: jinja
|
* - **jinja**
|
||||||
- jinja
|
|
||||||
* - **jinja**
|
|
||||||
|
|
||||||
`string`
|
`string`
|
||||||
|
|
||||||
`mandatory`
|
`mandatory`
|
||||||
- Jinja template
|
- Please set a Jinja template.
|
||||||
- {% if rougail.variable == 'not_allowed' %}not allowed!{% endif %}
|
|
||||||
-
|
|
||||||
* - **params**
|
* - **params**
|
||||||
|
|
||||||
`list`
|
|
||||||
- Additional parameters passed to the Jinja template
|
|
||||||
-
|
|
||||||
-
|
|
||||||
|
|
||||||
There are two types of parameter:
|
`dict`
|
||||||
|
- Additional parameters passed to the Jinja template (see below).
|
||||||
|
|
||||||
|
* - **return_type**
|
||||||
|
|
||||||
|
`string`
|
||||||
|
- A validation could returns the error message directly, so return_type is `string` (the default behavior).
|
||||||
|
Or a `boolean`, in this case if it's return `true` this means that the value is not valid.
|
||||||
|
|
||||||
|
* - **description**
|
||||||
|
|
||||||
|
`string`
|
||||||
|
- Additional information for the :ref:`documentation <data_documentation>` and the error message in case of return_type is a boolean.
|
||||||
|
|
||||||
|
* - **warnings**
|
||||||
|
|
||||||
|
`boolean`
|
||||||
|
- If `true` the validation did not raise, it only display a warning.
|
||||||
|
|
||||||
|
|
||||||
|
Params
|
||||||
|
~~~~~~
|
||||||
|
|
||||||
|
There are two types of params:
|
||||||
|
|
||||||
|
- the standard parameters (string, boolean, integer, float or null), in this case just do: "key: value"
|
||||||
|
- advanced settings (with something like "key: {}":
|
||||||
|
|
||||||
- the standard parameters (string, boolean, integer, null), in this case just do: "key: value"
|
|
||||||
- advanced settings:
|
|
||||||
|
|
||||||
- parameter via a variable
|
- parameter via a variable
|
||||||
- parameter via an information
|
- parameter via an information
|
||||||
- parameter via a suffix: in the case of a variable in a dynamic family
|
- parameter via an identifier: in a dynamic family returns the current identifier
|
||||||
- parameter via an index: in the case of a :term:`follower` variable
|
- parameter via an index: in the case of a :term:`follower` variable returns the current index
|
||||||
|
- parameter via :ref:`the current namespace name <namespace>`
|
||||||
.. list-table::
|
|
||||||
:widths: 15 25 20 15
|
Variable params
|
||||||
|
"""""""""""""""
|
||||||
|
|
||||||
|
.. list-table::
|
||||||
:header-rows: 1
|
:header-rows: 1
|
||||||
|
|
||||||
* - **Parameter's type**
|
* - **Parameter**
|
||||||
- **Parameter**
|
|
||||||
- **Comments**
|
- **Comments**
|
||||||
- **Sample**
|
- **Sample**
|
||||||
* -
|
|
||||||
- **name**
|
* - **type**
|
||||||
|
|
||||||
`string`
|
`string`
|
||||||
|
- Type of parameter, which is variable.
|
||||||
`mandatory`
|
- variable
|
||||||
- Parameter's name
|
|
||||||
- my_param
|
* - **variable**
|
||||||
* -
|
|
||||||
- **type**
|
|
||||||
|
|
||||||
`string`
|
`string`
|
||||||
|
|
||||||
`mandatory`
|
`mandatory`
|
||||||
- Type of parameter, possible values are: variable, information, suffix or index
|
- Variable's path.
|
||||||
- suffix
|
|
||||||
* - Variable
|
|
||||||
- **variable**
|
|
||||||
|
|
||||||
`string`
|
|
||||||
|
|
||||||
`mandatory`
|
|
||||||
- variable's name
|
|
||||||
- rougail.variable
|
- rougail.variable
|
||||||
* - Variable (`mandatory`) information
|
|
||||||
- **propertyerror**
|
* - **propertyerror**
|
||||||
|
|
||||||
`boolean`
|
`boolean`
|
||||||
- If access to the variable is not possible due to a property
|
- If access to the variable is not possible due to a property
|
||||||
(for example `disabled`) by default an error is returned.
|
(for example `disabled`) by default an error is returned.
|
||||||
If the attribute is `False`, the parameter is not passed to the Jinja template.
|
If the attribute is `false`, the parameter is not passed to the Jinja template.
|
||||||
|
|
||||||
**Default value**: `True`
|
**Default value**: `false`
|
||||||
- True
|
- `true`
|
||||||
* - Information
|
|
||||||
- **information**
|
* - **optional**
|
||||||
|
|
||||||
|
`boolean`
|
||||||
|
- If the variable is not defined the value is always `null`.
|
||||||
|
|
||||||
|
**Default value**: `false`
|
||||||
|
- `true`
|
||||||
|
|
||||||
|
* - **whole**
|
||||||
|
|
||||||
|
`boolean`
|
||||||
|
- In :term:`dynamically built family` only the value of the current index is retrieve. If this parameter is set to `true` it returns all
|
||||||
|
If this parameter is set to `true`, it returns the set of values for all indices.
|
||||||
|
|
||||||
|
**Default value**: `false`
|
||||||
|
- `true`
|
||||||
|
|
||||||
|
Information params
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. list-table::
|
||||||
|
:header-rows: 1
|
||||||
|
|
||||||
|
* - **Parameter**
|
||||||
|
- **Comments**
|
||||||
|
- **Sample**
|
||||||
|
|
||||||
|
* - **type**
|
||||||
|
|
||||||
`string`
|
`string`
|
||||||
|
- Type of parameter, which is information
|
||||||
|
- information
|
||||||
|
|
||||||
|
* - **information**
|
||||||
|
|
||||||
|
`string`
|
||||||
|
|
||||||
`mandatory`
|
`mandatory`
|
||||||
- Name of the information whose value we want to retrieve.
|
- Name of the information whose value we want to retrieve.
|
||||||
- doc
|
- doc
|
||||||
|
|
||||||
|
* - **variable**
|
||||||
|
|
||||||
|
`string`
|
||||||
|
- By default, the information is a context information. It is possible to get a variable information. In this case just specify a path.
|
||||||
|
- rougail.variable
|
||||||
|
|
||||||
Samples
|
Samples
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
|
@ -116,23 +169,24 @@ Here is a simple example of validating values:
|
||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
|
||||||
---
|
%YAML 1.2
|
||||||
version: 1.1
|
---
|
||||||
my_variable:
|
version: 1.1
|
||||||
validators:
|
|
||||||
- type: jinja
|
my_variable:
|
||||||
jinja: |
|
validators:
|
||||||
{% if rougail.my_variable and not rougail.my_variable.islower() %}
|
- jinja: |-
|
||||||
{{ rougail.my_variable }} is not lowercase string
|
{% if my_variable is not none and not my_variable.islower() %}
|
||||||
{% endif %}
|
{{ my_variable }} is not lowercase string
|
||||||
|
{% endif %}
|
||||||
|
...
|
||||||
|
|
||||||
A verification function must take into account 2 important aspects:
|
A verification function must take into account 2 important aspects:
|
||||||
|
|
||||||
- the value may not be entered (even if the variable is mandatory), the None value must be taken into account
|
- the value may not be entered (even if the variable is mandatory), the None value must be taken into account
|
||||||
- if the value is invalid, a sentence must be returned with an explicit message.
|
- if return_type is `string` and the value is invalid, a sentence must be returned with an explicit message.
|
||||||
|
|
||||||
From now on only `None` and lowercase values will be allowed.
|
From now on only `null` and lowercase values will be allowed.
|
||||||
|
|
||||||
Checking values with warning
|
Checking values with warning
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
@ -141,17 +195,19 @@ In the constraint, it is possible to specify the error level and put it as a war
|
||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
|
||||||
---
|
%YAML 1.2
|
||||||
version: 1.1
|
---
|
||||||
my_variable:
|
version: 1.1
|
||||||
validators:
|
|
||||||
- type: jinja
|
my_variable:
|
||||||
jinja: |+
|
validators:
|
||||||
{% if rougail.my_variable and not rougail.my_variable.islower() %}
|
- jinja: |-
|
||||||
{{ rougail.my_variable }} is not lowercase string
|
{% if my_variable is not none and not my_variable.islower() %}
|
||||||
{% endif %}
|
{{ my_variable }} is not lowercase string
|
||||||
params:
|
{% endif %}
|
||||||
warnings_only: true
|
params:
|
||||||
|
warnings: true
|
||||||
|
...
|
||||||
|
|
||||||
In this case a value with a capital letter will be accepted, but a warning message will appear.
|
In this case a value with a capital letter will be accepted, but a warning message will appear.
|
||||||
|
|
||||||
|
|
@ -160,127 +216,88 @@ Verification with parameters
|
||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
|
||||||
---
|
%YAML 1.2
|
||||||
version: 1.1
|
---
|
||||||
my_hidden_variable:
|
version: 1.1
|
||||||
disabled: true
|
|
||||||
my_variable:
|
|
||||||
validators:
|
|
||||||
- type: jinja
|
|
||||||
jinja: |
|
|
||||||
{% if param1 is defined and rougail.my_variable == param1 %}
|
|
||||||
has same value as rougail.unknown_variable
|
|
||||||
{% endif %}
|
|
||||||
{% if param2 is defined and rougail.my_variable == param2 %}
|
|
||||||
has same value as rougail.my_hidden_variable
|
|
||||||
{% endif %}
|
|
||||||
params:
|
|
||||||
param1:
|
|
||||||
type: variable
|
|
||||||
variable: rougail.unknown_variable
|
|
||||||
optional: true
|
|
||||||
param2:
|
|
||||||
type: variable
|
|
||||||
variable: rougail.my_hidden_variable
|
|
||||||
propertyerror: false
|
|
||||||
|
|
||||||
An example with a suffix type parameter:
|
my_hidden_variable:
|
||||||
|
disabled: true
|
||||||
|
|
||||||
|
my_variable:
|
||||||
|
validators:
|
||||||
|
- type: jinja
|
||||||
|
jinja: |-
|
||||||
|
{% if param1 is defined and my_variable == param1 %}
|
||||||
|
has same value as unknown_variable
|
||||||
|
{% endif %}
|
||||||
|
{% if param2 is defined and my_variable == param2 %}
|
||||||
|
has same value as my_hidden_variable
|
||||||
|
{% endif %}
|
||||||
|
params:
|
||||||
|
param1:
|
||||||
|
variable: unknown_variable
|
||||||
|
optional: true
|
||||||
|
param2:
|
||||||
|
variable: my_hidden_variable
|
||||||
|
propertyerror: false
|
||||||
|
...
|
||||||
|
|
||||||
|
An example with an identifier type parameter:
|
||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
|
||||||
---
|
%YAML 1.2
|
||||||
version: 1.1
|
---
|
||||||
varname:
|
version: 1.1
|
||||||
multi: true
|
|
||||||
default:
|
|
||||||
- val1
|
|
||||||
- val2
|
|
||||||
my_dyn_family_:
|
|
||||||
type: dynamic
|
|
||||||
variable: rougail.varname
|
|
||||||
description: 'Describe '
|
|
||||||
my_dyn_var:
|
|
||||||
type: string
|
|
||||||
validators:
|
|
||||||
- type: jinja
|
|
||||||
jinja: |
|
|
||||||
{% if rougail.my_dyn_family_.my_dyn_var == param1 %}
|
|
||||||
forbidden!
|
|
||||||
{% endif %}
|
|
||||||
params:
|
|
||||||
param1:
|
|
||||||
type: suffix
|
|
||||||
|
|
||||||
In this example, we see a dynamic family. Two families will be created: `rougail.my_dyn_family_val1.my_dyn_var` and `rougail.my_dyn_family_val2.my_dyn_var`.
|
my_dyn_family_{{ identifier }}:
|
||||||
|
type: dynamic
|
||||||
|
dynamic:
|
||||||
|
- val1
|
||||||
|
- val2
|
||||||
|
description: 'Describe {{ identifier }}'
|
||||||
|
|
||||||
The value of the variable within this family cannot be equal to the value
|
my_dyn_var:
|
||||||
of the suffix (`val1` and `val2` respectively).
|
validators:
|
||||||
|
- jinja: |
|
||||||
|
{% if my_dyn_family_.my_dyn_var == param1 %}
|
||||||
|
forbidden!
|
||||||
|
{% endif %}
|
||||||
|
params:
|
||||||
|
param1:
|
||||||
|
type: identifier
|
||||||
|
...
|
||||||
|
|
||||||
|
In this example, we see a :term:`dynamically built family`. Two families will be created: `my_dyn_family_val1.my_dyn_var` and `my_dyn_family_val2.my_dyn_var`.
|
||||||
|
|
||||||
|
The value of the variable within this family cannot be equal to the value
|
||||||
|
of the identifier (`val1` and `val2` respectively).
|
||||||
|
|
||||||
An example with an index type parameter:
|
An example with an index type parameter:
|
||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
|
||||||
---
|
%YAML 1.2
|
||||||
version: 1.1
|
---
|
||||||
family:
|
version: 1.1
|
||||||
type: sequence
|
|
||||||
leader:
|
|
||||||
multi: true
|
|
||||||
default:
|
|
||||||
- val1
|
|
||||||
- val2
|
|
||||||
follower1:
|
|
||||||
type: integer
|
|
||||||
validators:
|
|
||||||
- type: jinja
|
|
||||||
jinja: |
|
|
||||||
{% if rougail.family.follower1 == param1 %}
|
|
||||||
forbidden!
|
|
||||||
{% endif %}
|
|
||||||
params:
|
|
||||||
param1:
|
|
||||||
type: index
|
|
||||||
|
|
||||||
Redefinition
|
family:
|
||||||
---------------
|
type: sequence
|
||||||
|
|
||||||
In a first dictionary, let's declare our variable and its verification function:
|
leader:
|
||||||
|
default:
|
||||||
|
- val1
|
||||||
|
- val2
|
||||||
|
|
||||||
.. code-block:: yaml
|
follower1:
|
||||||
|
type: integer
|
||||||
---
|
validators:
|
||||||
version: 1.1
|
- type: jinja
|
||||||
my_variable:
|
jinja: |-
|
||||||
validators:
|
{% if family.follower1 == param1 %}
|
||||||
- type: jinja
|
forbidden!
|
||||||
jinja: |
|
{% endif %}
|
||||||
{% if rougail.my_variable and not rougail.my_variable.islower() %}
|
params:
|
||||||
{{ rougail.my_variable }} is not lowercase string
|
param1:
|
||||||
{% endif %}
|
type: index
|
||||||
|
...
|
||||||
In a second dictionary it is possible to redefine the calculation:
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
---
|
|
||||||
version: 1.1
|
|
||||||
my_variable:
|
|
||||||
redefine: true
|
|
||||||
validators:
|
|
||||||
- type: jinja
|
|
||||||
jinja: |
|
|
||||||
{% if rougail.my_variable and ' ' in rougail.my_variable %}
|
|
||||||
{{ rougail.my_variable }} has a space
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
In this case only this validator will be executed.
|
|
||||||
|
|
||||||
Here is a third dictionary in which we remove the validation:
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
---
|
|
||||||
version: 1.1
|
|
||||||
my_variable:
|
|
||||||
redefine: true
|
|
||||||
validators:
|
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ Overall coherence
|
||||||
which will validate the value of a variable in relation to others.
|
which will validate the value of a variable in relation to others.
|
||||||
But it also depends on the availability of the variable depending on the context.
|
But it also depends on the availability of the variable depending on the context.
|
||||||
|
|
||||||
|
.. _consistency:
|
||||||
|
|
||||||
Consistency
|
Consistency
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
.. _data_documentation:
|
||||||
|
|
||||||
Data documentation
|
Data documentation
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,8 @@ It is possible to create subfamilies.
|
||||||
|
|
||||||
.. seealso:: :doc:`the family documentation <family>`
|
.. seealso:: :doc:`the family documentation <family>`
|
||||||
|
|
||||||
|
.. _dynamically_built_family:
|
||||||
|
|
||||||
The dynamically built family
|
The dynamically built family
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ Regexp type with calculation
|
||||||
A regexp variable
|
A regexp variable
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
We have already seen the :ref:`validator mechanism <tutorial_validator>` for managing the :ref:`quality of data values <data_quality>`.
|
We have already seen the :ref:`validator mechanism <tutorial_validators>` for managing the :ref:`quality of data values <data_quality>`.
|
||||||
|
|
||||||
This mechanism is undeniably interesting and powerful.
|
This mechanism is undeniably interesting and powerful.
|
||||||
But for strings that can be validated using a regular expression, it is preferable to use this type.
|
But for strings that can be validated using a regular expression, it is preferable to use this type.
|
||||||
|
|
@ -89,7 +89,7 @@ Why not offer a default value to the user?
|
||||||
|
|
||||||
If the user has a specific color in mind, they can specify it. Otherwise, Rougail will suggest a default value.
|
If the user has a specific color in mind, they can specify it. Otherwise, Rougail will suggest a default value.
|
||||||
|
|
||||||
We've already seen how to use :ref:`Jinja <tutorial_jinja>` for :ref:`validation <tutorial_validator>` and :ref:`access control <tutorial_disabled>` calculations.
|
We've already seen how to use :ref:`Jinja <tutorial_jinja>` for :ref:`validation <tutorial_validators>` and :ref:`access control <tutorial_disabled>` calculations.
|
||||||
|
|
||||||
We've also seen how to calculate the default value by :ref:`retrieving the value of another variable <tutorial_calc_variable>`.
|
We've also seen how to calculate the default value by :ref:`retrieving the value of another variable <tutorial_calc_variable>`.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
.. _tutorial_validator:
|
.. _tutorial_validators:
|
||||||
|
|
||||||
Validating a variable's value
|
Validating a variable's value
|
||||||
================================
|
================================
|
||||||
|
|
@ -49,15 +49,6 @@ It is possible, instead of creating a new type, to add custom validation of the
|
||||||
|
|
||||||
We call it a :term:`validator`.
|
We call it a :term:`validator`.
|
||||||
|
|
||||||
.. glossary::
|
|
||||||
|
|
||||||
validator
|
|
||||||
|
|
||||||
A validator is a Jinja code that parses a variable's value and checks
|
|
||||||
that this value corresponds to some stated criteria.
|
|
||||||
This is a `validator` parameter of our variable, and another `jinja` sub-parameter
|
|
||||||
contains validation code for the variable's value.
|
|
||||||
|
|
||||||
.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_170/firefox/60-dns_over_https.yml
|
.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_170/firefox/60-dns_over_https.yml
|
||||||
:language: yaml
|
:language: yaml
|
||||||
:caption: The :file:`firefox/60-dns_over_https.yml` with the jinja validator
|
:caption: The :file:`firefox/60-dns_over_https.yml` with the jinja validator
|
||||||
|
|
@ -68,6 +59,7 @@ Here we can see that the validation code is:
|
||||||
|
|
||||||
{{ _.custom_dns_url.startswith("http://") }}
|
{{ _.custom_dns_url.startswith("http://") }}
|
||||||
|
|
||||||
|
First of all, you can see that we use the path of the current variable for validation.
|
||||||
|
|
||||||
A validator can return a string, in fact it is its default behavior.
|
A validator can return a string, in fact it is its default behavior.
|
||||||
If it returns a string of characters, it indicates the validation error.
|
If it returns a string of characters, it indicates the validation error.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue