From 2e826db3f436f6f4fca9d8e3dae907f8328ea246 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Sun, 14 Jun 2026 21:45:36 +0200 Subject: [PATCH] doc(tutorial): redefine + regexp + auto_save --- docs/abstract.rst | 2 + docs/format_content/index.rst | 1 + docs/format_content/mutability.rst | 114 ++++++++++++++++++++ docs/format_content/variable.rst | 8 +- docs/structured_data/data_integrity.rst | 2 + docs/tutorial/auto_save.rst | 62 +++++++++++ docs/tutorial/choice.rst | 2 +- docs/tutorial/customtype.rst | 22 ++-- docs/tutorial/index.rst | 3 + docs/tutorial/redefine.rst | 110 ++++++++++++++++++++ docs/tutorial/regexp.rst | 126 +++++++++++++++++++++++ docs/tutorial/validators.rst | 4 +- docs/tutorial/variable_propertyerror.rst | 3 +- 13 files changed, 441 insertions(+), 18 deletions(-) create mode 100644 docs/format_content/mutability.rst create mode 100644 docs/tutorial/auto_save.rst create mode 100644 docs/tutorial/redefine.rst create mode 100644 docs/tutorial/regexp.rst diff --git a/docs/abstract.rst b/docs/abstract.rst index d4fa33e3a..4355349fd 100644 --- a/docs/abstract.rst +++ b/docs/abstract.rst @@ -243,6 +243,8 @@ The lifecycle of a variable includes the generic stages (for example, like in th Variable mutability --------------------- +.. _structured_data: + Structured data ~~~~~~~~~~~~~~~~ diff --git a/docs/format_content/index.rst b/docs/format_content/index.rst index cf585e30c..1c43fb9fd 100644 --- a/docs/format_content/index.rst +++ b/docs/format_content/index.rst @@ -12,6 +12,7 @@ The variable is described in Rougail format. variable family path + mutability calculation condition validation diff --git a/docs/format_content/mutability.rst b/docs/format_content/mutability.rst new file mode 100644 index 000000000..a5ff3e0bb --- /dev/null +++ b/docs/format_content/mutability.rst @@ -0,0 +1,114 @@ +.. _redefine: + +Redefine a variable +=================== + +We have already introduced the concept of :ref:`variable mutability `. +To summarize, an :term:`integrator` allows the :ref:`structured data ` to evolve at any time. + +.. glossary:: + + redefine + + A redefine is a redefinition of all or part of the parameters of a variable as it was previously defined. + +.. seealso:: + + See the tutorial with a real world sample :ref:`redefine `. + +Explicit redefine +~~~~~~~~~~~~~~~~~ + +The redefinition is explicit. +This means that if an :term:`integrator` defines the same tree twice for two variables, Rougail will consider that there is a naming conflict. + +To illustrate, we could create two :term:`structure files `: + +.. code-block:: yaml + + %YAML 1.2 + --- + version: 1.1 + + my_variable: # A description + ... + +.. code-block:: yaml + + %YAML 1.2 + --- + version: 1.1 + + my_variable: # A redefined description + ... + +And the name conflict is detected: + +.. code-block:: bash + :class: terminal + + $ rougail -m variable.yml redefine.yml + ERROR: variable "my_variable" define multiple time in "variable.yml" and "redefine.yml" + +So we have to explicit redefine a variable like this: + +.. code-block:: yaml + + %YAML 1.2 + --- + version: 1.1 + + my_variable: + redefine: true + description: A redefined description + ... + +Now we can see that the redefinition is correct: + +.. code-block:: bash + :class: terminal + + $rougail -m variable.yml redefine.yml -o doc + ┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━┓ + ┃ Variable ┃ Description ┃ + ┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━┩ + │ my_variable │ A redefined description. │ + │ string mandatory │ │ + └─────────────────────┴──────────────────────────┘ + +The new description has been taken into account. + +Unify +~~~~~ + +When redefining a variable, we define the list of parameters that we wish to redefine. + +In other words the variable is unify (combine) from multiple variables declarations. + +The old parameters that were present before the redefinition are still present. + +If we modify the `redefine.yml` :term:`structure file`: + +.. code-block:: yaml + + %YAML 1.2 + --- + version: 1.1 + + my_variable: + redefine: true + type: integer + ... + +.. code-block:: bash + :class: terminal + + $ rougail -m variable.yml redefine.yml -o doc + ┏━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┓ + ┃ Variable ┃ Description ┃ + ┡━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━┩ + │ my_variable │ A description. │ + │ integer mandatory │ │ + └──────────────────────┴────────────────┘ + +Here we can see that the variable has the original description, but the new type. diff --git a/docs/format_content/variable.rst b/docs/format_content/variable.rst index 76b8574c5..096104bf2 100644 --- a/docs/format_content/variable.rst +++ b/docs/format_content/variable.rst @@ -1,3 +1,5 @@ +.. _variable: + The variables ============== @@ -441,7 +443,7 @@ Specialized type * - secret - a secret (like a password, a private key, etc.) - .. seealso:: tutorial with a real world sample :doc:`secret type variable <../tutorial/redefine>` + .. seealso:: tutorial with a real world sample :ref:`secret type variable ` - `min_len`: minimum characters length for the secret (unlimited by default) `max_len`: maximum characters length for the secret (unlimited by default) @@ -582,7 +584,7 @@ Specialized type * - regexp - Validation with a regular expressions - .. seealso:: tutorial with a real world sample :doc:`regexp type variable <../tutorial/regexp>` + .. seealso:: tutorial with a real world sample :ref:`regexp type variable ` - - r"^#(?:[0-9a-f]{3}){1,2}$" @@ -593,7 +595,7 @@ If the `type` parameter is not set, Rougail has to define a logical type to vali - if `choices` or `regexp` parameter is set, Rougail will set the `choice` or `regexp` type -.. seealso:: tutorial with a real world sample :doc:`choice deducted type <../tutorial/choice>` or :doc:`regexp deducted type <../tutorial/regexp>` +.. seealso:: tutorial with a real world sample :doc:`choice deducted type <../tutorial/choice>` or :ref:`regexp deducted type ` - if a default value is define, Rougail will infers default value type and set a primitive type to the variable diff --git a/docs/structured_data/data_integrity.rst b/docs/structured_data/data_integrity.rst index ba4b24f0a..6a4587185 100644 --- a/docs/structured_data/data_integrity.rst +++ b/docs/structured_data/data_integrity.rst @@ -11,6 +11,8 @@ This means that the value must be: Isolated variable ----------------- +.. _data_quality: + Data quality ~~~~~~~~~~~~ diff --git a/docs/tutorial/auto_save.rst b/docs/tutorial/auto_save.rst new file mode 100644 index 000000000..9984030d1 --- /dev/null +++ b/docs/tutorial/auto_save.rst @@ -0,0 +1,62 @@ +Auto save value +=============== + +.. objectives:: Objectives + + A default value is a value that can be recalculated at different times. It can be useful to consider the default value as a modified value. + +.. prerequisites:: Prerequisites + + - We assume that Rougail's library is :ref:`installed ` on your computer. + + - It is possible to retrieve the current state of the various Rougail files manipulated in this tutorial step + by checking out the corresponding tag of the `rougail-tutorials` git repository. + Each tag corresponds to a stage of progress in the tutorial. + Of course, you can also decide to copy/paste or download the tutorial files contents while following the tutorial steps. + + If you want to follow this tutorial with the help of the corresponding :tutorial:`rougail-tutorials git repository `, + this workshop page corresponds to the tag :tutorial:`v1.1_210 ` + + :: + + git clone https://forge.cloud.silique.fr/stove/rougail-tutorials.git + git switch --detach v1.1_210 + +The :ref:`configuration` is loaded into :term:`Tiramisu`. In this case, the default values are cached upon the first access to the variable. However, sometimes this value will be recalculated. +If the default value is random, this can cause problems. Indeed, the value can change over time. + +The `auto_save` property allows you to say that the calculated value will be considered as modified (therefore not recalculated) on the first access to this variable. + +Remember, we just performed a random calculation for the variable `color`: + +.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_201/foxyproxy/00-foxyproxy.yml + :language: yaml + :caption: Calculate the default variable `color`. + +We just need to set the `auto_save` property to true on this variable: + +.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_210/foxyproxy/00-foxyproxy.yml + :language: yaml + :caption: Auto_save for the variable `color`. + +Test this variable with this Rougail CLI: + +.. raw:: html + :class: terminal + :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_210/config/02/cmd_ro.txt + +We have this output: + +.. raw:: html + :class: output + :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_210/config/02/output_ro.html + +As you can see, the value is the color of the modified variables. + +.. note:: + + We do not save this value. It is therefore stored in memory. When the Rougail CLI closes, this value is forgotten. It will be recalculated if you run the command again. + +.. keypoints:: Key points + + We can auto save a variable. diff --git a/docs/tutorial/choice.rst b/docs/tutorial/choice.rst index 459e930a7..fd0c6e591 100644 --- a/docs/tutorial/choice.rst +++ b/docs/tutorial/choice.rst @@ -31,7 +31,7 @@ In the firefox browser, the proxy mode can be set by this way: .. image:: images/firefox_02.png -A list of possible values for the `proxy_mode` variable ​​is proposed. +A list of possible values for the `proxy_mode` variable is proposed. With Rougail there is the possibility of defining a list of available values with the `choices` variable's parameter: diff --git a/docs/tutorial/customtype.rst b/docs/tutorial/customtype.rst index d91b8484a..e734aef44 100644 --- a/docs/tutorial/customtype.rst +++ b/docs/tutorial/customtype.rst @@ -1,3 +1,5 @@ +.. _tutorial_custom_type: + Custom type ============ @@ -206,21 +208,17 @@ Redefine default value in custom type variable git switch --detach v1.1_083 -In this section we are going to make an implicit redefinition of variables default values. +In this section we are going to make an implicit :ref:`redefinition ` of variables default values. -.. FIXME deplacer cette definition dans la page generique sur le redefine à venir +.. note:: -.. glossary:: + We've always said that the redefine is explicit. But there's an exception here. + There are two types of redefine for a custom type, an implicit and an explicit. + An implicit redefinition is a redefinition which has not been declared with the `redefine` attribute. + An explicit redefinition is a redefinition which has been declared with the `redefine: true` attribute. - redefine - - A redefine is a redefinition of all or part of the attributes of a variable as it was previously defined. - There are two types of redefine, an implicit and an explicit. - An implicit redefinition is a redefinition which has not been declared with the `redefine` attribute. - An explicit redefinition is a redefinition which has been declared with the `redefine: true` attribute. - - Only default values can be implicitly redefined (and only in the type definitions), all other attributes - need to be explicitely redefined. + Only default values can be implicitly redefined (and only in the type definitions), all other attributes + need to be explicitely redefined. In the type definition file, we are now setting default values for the `address` and `port` variables: diff --git a/docs/tutorial/index.rst b/docs/tutorial/index.rst index 073b91679..ae90706de 100644 --- a/docs/tutorial/index.rst +++ b/docs/tutorial/index.rst @@ -66,6 +66,9 @@ Let's dive into this **configuration options validation** use case. validators namespace sequence + regexp + auto_save underscore_parameter variable_propertyerror + redefine whatsnext diff --git a/docs/tutorial/redefine.rst b/docs/tutorial/redefine.rst new file mode 100644 index 000000000..f3ea5865e --- /dev/null +++ b/docs/tutorial/redefine.rst @@ -0,0 +1,110 @@ +.. _tutorial_redefine: + +Redefine variable +================= + +.. objectives:: Objectives + + When we said that a :ref:`variable is immutable ` when an :term:`integrator` defined it in structured data, we said that it had to be done explicitly. + Let's see how that works. + +.. prerequisites:: Prerequisites + + - We assume that Rougail's library is :ref:`installed ` on your computer. + + - It is possible to retrieve the current state of the various Rougail files manipulated in this tutorial step + by checking out the corresponding tag of the `rougail-tutorials` git repository. + Each tag corresponds to a stage of progress in the tutorial. + Of course, you can also decide to copy/paste or download the tutorial files contents while following the tutorial steps. + + If you want to follow this tutorial with the help of the corresponding :tutorial:`rougail-tutorials git repository `, + this workshop page corresponds to the tags :tutorial:`v1.1_240 ` to :tutorial:`v1.1_241 ` + + :: + + git clone https://forge.cloud.silique.fr/stove/rougail-tutorials.git + git switch --detach v1.1_240 + +Username is mandatory if a password is set +------------------------------------------ + +We now have two new variables following the same pattern as the :ref:`previous three one `: + +- A variable with the new type `unix_username` `username`, this variable is accessible in type HTTP, HTTPS/SSL, SOCKS4 or SOCKS5 +- A variable with the new type `secret` `password`, this variable is accessible in type HTTP, HTTPS/SSL, SOCKS4 or SOCKS5 + +Nothing really new from now. But we haven't said everything! +In fact, we have to deal with a new situation. We have three :ref:`coherence ` :ref:`configuration ` choices: + +- either we fill in the username/password pair +- we fill only the username +- or leave it blank + +Defining only a password makes no sense. + +There are several ways to solve this case. +Let's assume that if the :term:`operator` sets a password, they must also enter a username. The password can be `null`. + +In Rougail format, we would say that the password is :ref:`nullable ` and that the username has a :ref:`variable calculation ` to determine if it is :ref:`nullable `. +If the password is empty, the username is :ref:`nullable `; otherwise, it is not. + +Here's how to do it: + +.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_240/foxyproxy/00-foxyproxy.yml + :language: yaml + :caption: The :file:`foxyproxy/00-foxyproxy.yml` + +Now let's test with the following user data file: + +.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_240/config/02/config.yml + :linenos: + :language: yaml + :caption: The :file:`config/02/config.yml` user data + +If we launch the Rougail CLI: + +.. raw:: html + :class: terminal + :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_240/config/02/cmd_ro.txt + +We have this output: + +.. raw:: html + :class: output + :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_240/config/02/output_ro.html + +.. note:: + + The value of a variable of type secret is replaced by asterisks (`*`) when it is displayed. + +Redefine it to password is hidden if an username is not set +----------------------------------------------------------- + +.. type-along:: For those who follow the tutorial with the help of the git repository + + Now you need to checkout the :tutorial:`v1.1_241 ` version:: + + git switch --detach v1.1_241 + +Another solution is to say to ourselves: the username is never mandatory (just like the password) but the password is hidden if the username is empty. + +We could modify the structure file as we have been doing since the beginning of this tutorial. +Perhaps it's time to illustrate how to :term:`redefine` a variable. + +Redefine means that the variable is unify (combine) from multiple variables declarations. + +So we will create a new file with, inside, the same variable name. + +First of all, we will to redefine the mandatory attribute of the `username` variable. + +Secondly we will added a new calculation in the :ref:`hidden` parameters. + +Here is the final result of this file: + +.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_241/foxyproxy/10-redefine.yml + :language: yaml + :caption: The :file:`foxyproxy/10-redefine.yml` + +.. keypoints:: Key points + + Redefine a variable involves changing some of its parameters with new ones. diff --git a/docs/tutorial/regexp.rst b/docs/tutorial/regexp.rst new file mode 100644 index 000000000..ab95a27c2 --- /dev/null +++ b/docs/tutorial/regexp.rst @@ -0,0 +1,126 @@ +.. _tutorial_regexp: + +Regexp type with calculation +============================ + +.. objectives:: Objectives + + Regexp is a :ref:`variable specialize type ` which allows for easy validation of a variable from a regular expression. + +.. prerequisites:: Prerequisites + + - We assume that Rougail's library is :ref:`installed ` on your computer. + + - It is possible to retrieve the current state of the various Rougail files manipulated in this tutorial step + by checking out the corresponding tag of the `rougail-tutorials` git repository. + Each tag corresponds to a stage of progress in the tutorial. + Of course, you can also decide to copy/paste or download the tutorial files contents while following the tutorial steps. + + If you want to follow this tutorial with the help of the corresponding :tutorial:`rougail-tutorials git repository `, + this workshop page corresponds to the tags :tutorial:`v1.1_200 ` to :tutorial:`v1.1_201 ` + + :: + + git clone https://forge.cloud.silique.fr/stove/rougail-tutorials.git + git switch --detach v1.1_200 + +A regexp variable +----------------- + +We have already seen the :ref:`validator mechanism ` for managing the :ref:`quality of data values `. + +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. +In this specific case, nothing beats this particular type. + +Obviously, the values assigned to a regexp type variable must be of type string. + +Here we will add a `color` variable which will allow us to quickly identify the current proxy via a color code. The expected value is a hex color code (like those used in CSS or HTML). + +This regrex must validate that the string begins with a hash symbol (#) followed by a RGB triplet in hexadecimal format (so 3 or 6 lowercase hexadecimal digits (0–9, a–f)). + +Here are some examples: `#a3f09c` or `#a3f`. + +The regular expression is `^#(?:[0-9a-f]{3}){1,2}$`. + +Let's write this variable: + +.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_200/foxyproxy/00-foxyproxy.yml + :language: yaml + :caption: The regexp variable `color`. + +Now let's test with the following user data file: + +.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_200/config/02/config.yml + :linenos: + :language: yaml + :caption: The :file:`config/02/config.yml` user data + +With this Rougail CLI: + +.. raw:: html + :class: terminal + :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_200/config/02/cmd_ro.txt + +We have this output: + +.. raw:: html + :class: output + :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_200/config/02/output_ro.html + +What happens if the value is not valid? + +The value is invalid: + +.. raw:: html + :class: output + :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_200/config/03/output_ro.html + +Calculate a random color +------------------------ + +.. type-along:: For those who follow the tutorial with the help of the git repository + + Now you need to checkout the :tutorial:`v1.1_201 ` version:: + + git switch --detach v1.1_201 + +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. + +We've already seen how to use :ref:`Jinja ` for :ref:`validation ` and :ref:`access control ` calculations. + +We've also seen how to calculate the default value by :ref:`retrieving the value of another variable `. + +It's entirely possible to calculate the default value from a Jinja template: + +.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_201/foxyproxy/00-foxyproxy.yml + :language: yaml + :caption: Calculate the default variable `color`. + +Now let's test with the following user data file: + +.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_201/config/02/config.yml + :linenos: + :language: yaml + :caption: The :file:`config/02/config.yml` user data + +With this Rougail CLI: + +.. raw:: html + :class: terminal + :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_201/config/02/cmd_ro.txt + +We have this output: + +.. raw:: html + :class: output + :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_201/config/02/output_ro.html + +As you can see, Rougail offers a default value! + +.. keypoints:: Key points + + - We can easily create a variable that valid value via a regexp + - We can calculate a default value with Jinja template diff --git a/docs/tutorial/validators.rst b/docs/tutorial/validators.rst index 5e211cd98..0e42c1929 100644 --- a/docs/tutorial/validators.rst +++ b/docs/tutorial/validators.rst @@ -1,9 +1,11 @@ +.. _tutorial_validator: + Validating a variable's value ================================ .. objectives:: Objectives - We will see how to create strong validations for the values ​​of our variables, + We will see how to create strong validations for the values of our variables, that is, validations that go beyond those inherent in the initial type definition. .. prerequisites:: Prerequisites diff --git a/docs/tutorial/variable_propertyerror.rst b/docs/tutorial/variable_propertyerror.rst index a20c14375..50e295ab9 100644 --- a/docs/tutorial/variable_propertyerror.rst +++ b/docs/tutorial/variable_propertyerror.rst @@ -1,3 +1,5 @@ +.. _tutorial_var_propertyerror: + Variable calculation with propertyerror ======================================= @@ -68,7 +70,6 @@ If we launch the Rougail CLI: :class: terminal :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_230/config/02/cmd_ro.txt - We have this output: .. raw:: html