feat: library documentation
This commit is contained in:
parent
96975461d0
commit
1277cce9d9
9 changed files with 692 additions and 262 deletions
|
|
@ -70,7 +70,7 @@ Explained differently, Rougail allows you to easily implement an integration of
|
||||||
:titlesonly:
|
:titlesonly:
|
||||||
:caption: The library
|
:caption: The library
|
||||||
|
|
||||||
library
|
library/index
|
||||||
configuration
|
configuration
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
|
|
|
||||||
261
docs/library.rst
261
docs/library.rst
|
|
@ -1,261 +0,0 @@
|
||||||
`Rougail`'s library description
|
|
||||||
=================================
|
|
||||||
|
|
||||||
Rougail is a configuration management library that allows you to load variables in a simple and convenient way.
|
|
||||||
|
|
||||||
In the following examples, we will use a specific configuration of Rougail.
|
|
||||||
You will find all the configuraiton options in :doc:`configuration`.
|
|
||||||
|
|
||||||
To load the configuration you must import the `RougailConfig` class and set the `main_structural_directories` values:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from rougail import RougailConfig
|
|
||||||
|
|
||||||
RougailConfig['main_structural_directories'] = ['dict']
|
|
||||||
|
|
||||||
Let's convert a structure file
|
|
||||||
-------------------------------
|
|
||||||
|
|
||||||
As a reminder, a :term:`structure file` is a set of instructions that will allow us to create :term:`families` and :term:`variables`.
|
|
||||||
|
|
||||||
Let's start by creating a simple structure file.
|
|
||||||
|
|
||||||
Here is a first :file:`dict/00-base.yml` structure file:
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
%YAML 1.2
|
|
||||||
---
|
|
||||||
version: 1.1
|
|
||||||
|
|
||||||
my_variable:
|
|
||||||
default: my_value
|
|
||||||
...
|
|
||||||
|
|
||||||
Then, let's create the :term:`Tiramisu` objects via the following script:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
:caption: the `script.py` file content
|
|
||||||
|
|
||||||
from rougail import Rougail, RougailConfig
|
|
||||||
|
|
||||||
RougailConfig['main_structural_directories'] = ['dict']
|
|
||||||
rougail = Rougail()
|
|
||||||
config = rougail.get_config()
|
|
||||||
print(config.value.get())
|
|
||||||
|
|
||||||
.. demo:: Let's execute `script.py`:
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
$ python3 script.py
|
|
||||||
{'rougail.my_variable': 'my_value'}
|
|
||||||
|
|
||||||
The operator role
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
|
|
||||||
The :term:`operator` role corresponds to the :term:`tiramisu` settings:
|
|
||||||
|
|
||||||
.. image:: images/tiramisu_get_set.png
|
|
||||||
|
|
||||||
.. index:: questionary
|
|
||||||
|
|
||||||
But instead of coding in the end user developer way, the opterator will prefer using the Rougail CLI interface:
|
|
||||||
|
|
||||||
.. image:: images/QuestionaryChoice.png
|
|
||||||
|
|
||||||
|
|
||||||
The Rougail CLI can output a rather complete view of the dataset:
|
|
||||||
|
|
||||||
.. image:: images/UserDataOutput.png
|
|
||||||
|
|
||||||
Let's convert an extra structure file
|
|
||||||
---------------------------------------
|
|
||||||
|
|
||||||
.. index:: extras
|
|
||||||
|
|
||||||
The default namespace for variables and families is `rougail`. It is possible to define other namespaces. These additional namespaces are called `extras`.
|
|
||||||
|
|
||||||
.. FIXME: faire une page pour les extras
|
|
||||||
|
|
||||||
Additional namespaces are defined during configuration.
|
|
||||||
|
|
||||||
For example, here's how to add an `example` namespace:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
RougailConfig['extra_namespaces']['example'] = ['extras/']
|
|
||||||
|
|
||||||
Then let's create an extra :term:`structure file` :file:`extras/00-base.yml`:
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
:caption: the :file:`extras/00-base.yml` file content
|
|
||||||
---
|
|
||||||
version: '1.1'
|
|
||||||
my_variable_extra:
|
|
||||||
default: my_value_extra
|
|
||||||
|
|
||||||
Then, let's create the :term:`Tiramisu` objects via the following :file:`script.py` script:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
:caption: the :file:`script.py` file content
|
|
||||||
|
|
||||||
from rougail import Rougail, RougailConfig
|
|
||||||
|
|
||||||
RougailConfig['main_structural_directories'] = ['dict']
|
|
||||||
RougailConfig['extra_namespaces']['example'] = ['extras/']
|
|
||||||
rougail = Rougail()
|
|
||||||
config = rougail.get_config()
|
|
||||||
print(config.value.dict())
|
|
||||||
|
|
||||||
Let's execute `script.py`:
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
$ python3 script.py
|
|
||||||
{'rougail.my_variable': 'my_value', 'example.my_variable_extra': 'my_value_extra'}
|
|
||||||
|
|
||||||
Let's create a custom function
|
|
||||||
----------------------------------
|
|
||||||
|
|
||||||
We create the complementary :term:`structure file` named :file:`dict/01-function.yml` so that the `my_variable_jinja` variable is :term:`calculated`:
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
%YAML 1.2
|
|
||||||
---
|
|
||||||
version: 1.1
|
|
||||||
|
|
||||||
my_variable_jinja:
|
|
||||||
default:
|
|
||||||
type: jinja
|
|
||||||
jinja: "{{ return_no() }}"
|
|
||||||
...
|
|
||||||
|
|
||||||
Then let's define the :func:`return_no` function in :file:`functions.py`:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
:caption: the :file:`functions.py` content
|
|
||||||
|
|
||||||
def return_no():
|
|
||||||
return 'no'
|
|
||||||
|
|
||||||
Then, let's create the :term:`Tiramisu` objects via the following script:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
:caption: the `script.py` file content
|
|
||||||
|
|
||||||
from rougail import Rougail, RougailConfig
|
|
||||||
|
|
||||||
RougailConfig['main_structural_directories'] = ['dict']
|
|
||||||
RougailConfig['extra_namespaces']['example'] = ['extras/']
|
|
||||||
RougailConfig['functions_file'] = 'functions.py'
|
|
||||||
rougail = Rougail()
|
|
||||||
config = rougail.get_config()
|
|
||||||
print(config.value.dict())
|
|
||||||
|
|
||||||
Let's execute `script.py`:
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
$ python3 script.py
|
|
||||||
{'rougail.my_variable': 'my_value', 'rougail.my_variable_jinja': 'no', 'example.my_variable_extra': 'my_value_extra'}
|
|
||||||
|
|
||||||
The value of the `my_variable_extra` variable is calculated, and it's value comes from the :func:`return_no` function.
|
|
||||||
|
|
||||||
Create your own type
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
A variable has a type. This type enables the variable to define the values that are accepted by this variable.
|
|
||||||
|
|
||||||
There is a series of default types, but obviously not all cases are taken.
|
|
||||||
|
|
||||||
It's possible to create your own type.
|
|
||||||
|
|
||||||
Here an example to a lipogram option (in a string, we cannot use "e" character):
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
:caption: the `lipogram.py` file content
|
|
||||||
|
|
||||||
from tiramisu import StrOption
|
|
||||||
class LipogramOption(StrOption):
|
|
||||||
__slots__ = tuple()
|
|
||||||
_type = 'lipogram'
|
|
||||||
|
|
||||||
def validate(self,
|
|
||||||
value):
|
|
||||||
super().validate(value)
|
|
||||||
# verify that there is any 'e' in the sentense
|
|
||||||
if 'e' in value:
|
|
||||||
raise ValueError('Perec wrote a book without any "e", you could not do it in a simple sentence?')
|
|
||||||
|
|
||||||
To add the new lipogram type in Rougail:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
>>> from rougail import Rougail, RougailConfig
|
|
||||||
>>> RougailConfig['main_structural_directories'] = ['dict']
|
|
||||||
>>> RougailConfig['custom_types']['lipogram'] = LipogramOption
|
|
||||||
|
|
||||||
Now, we can use lipogram type.
|
|
||||||
Here is a :file:`dict/00-base.yml` structure file:
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
---
|
|
||||||
version: '1.1'
|
|
||||||
var:
|
|
||||||
type: lipogram
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
>>> rougail = Rougail()
|
|
||||||
>>> config = rougail.get_config()
|
|
||||||
>>> config.option('rougail.var').value.set('blah')
|
|
||||||
>>> config.option('rougail.var').value.set('I just want to add a quality string that has no bad characters')
|
|
||||||
[...]
|
|
||||||
tiramisu.error.ValueOptionError: "I just want to add a quality string that has no bad characters" is an invalid lipogram for "var", Perec wrote a book without any "e", you could not do it in a simple sentence?
|
|
||||||
|
|
||||||
Upgrade dictionnaries to upper version
|
|
||||||
----------------------------------------
|
|
||||||
|
|
||||||
All dictionnaries has a format version number.
|
|
||||||
When a new format version is proposed, it is possible to automatically convert the files to the new version.
|
|
||||||
|
|
||||||
We create a term:`structure file` named :file:`dict/01-upgrade.yml` with version 1.0:
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
---
|
|
||||||
version: '1.0'
|
|
||||||
my_variable:
|
|
||||||
multi: true
|
|
||||||
my_dyn_family:
|
|
||||||
type: "dynamic"
|
|
||||||
variable: my_variable
|
|
||||||
a_variable:
|
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
>>> from rougail import RougailUpgrade, RougailConfig
|
|
||||||
>>> RougailConfig['main_structural_directories'] = ['dict']
|
|
||||||
>>> upgrade = RougailUpgrade()
|
|
||||||
>>> upgrade.load_dictionaries('dict_converted')
|
|
||||||
|
|
||||||
The term:`structure file` named :file:`dict_converted/01-upgrade.yml` is in version 1.1:
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
version: '1.1'
|
|
||||||
my_variable:
|
|
||||||
multi: true
|
|
||||||
my_dyn_family:
|
|
||||||
type: dynamic
|
|
||||||
a_variable: null
|
|
||||||
dynamic:
|
|
||||||
type: variable
|
|
||||||
variable: my_variable
|
|
||||||
propertyerror: false
|
|
||||||
47
docs/library/custom_function.rst
Normal file
47
docs/library/custom_function.rst
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
Let's create a custom function
|
||||||
|
==============================
|
||||||
|
|
||||||
|
We create the complementary :term:`structure file` named :file:`dict/01-function.yml` so that the `my_variable_jinja` variable is :term:`calculated`:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
version: 1.1
|
||||||
|
|
||||||
|
my_variable_jinja:
|
||||||
|
default:
|
||||||
|
type: jinja
|
||||||
|
jinja: "{{ return_no() }}"
|
||||||
|
...
|
||||||
|
|
||||||
|
Then let's define the :func:`return_no` function in :file:`functions.py`:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:caption: the :file:`functions.py` content
|
||||||
|
|
||||||
|
def return_no():
|
||||||
|
return 'no'
|
||||||
|
|
||||||
|
Then, let's create the :term:`Tiramisu` objects via the following script:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:caption: the `script.py` file content
|
||||||
|
|
||||||
|
from rougail import Rougail, RougailConfig
|
||||||
|
|
||||||
|
RougailConfig['main_structural_directories'] = ['dict']
|
||||||
|
RougailConfig['extra_namespaces']['example'] = ['extras/']
|
||||||
|
RougailConfig['functions_file'] = 'functions.py'
|
||||||
|
rougail = Rougail()
|
||||||
|
config = rougail.get_config()
|
||||||
|
print(config.value.dict())
|
||||||
|
|
||||||
|
Let's execute `script.py`:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ python3 script.py
|
||||||
|
{'rougail.my_variable': 'my_value', 'rougail.my_variable_jinja': 'no', 'example.my_variable_extra': 'my_value_extra'}
|
||||||
|
|
||||||
|
The value of the `my_variable_extra` variable is calculated, and it's value comes from the :func:`return_no` function.
|
||||||
45
docs/library/extra.rst
Normal file
45
docs/library/extra.rst
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
Let's convert an extra namespace structural file
|
||||||
|
================================================
|
||||||
|
|
||||||
|
.. index:: extras
|
||||||
|
|
||||||
|
The default namespace for variables and families is `rougail`. It is possible to define other namespaces. These additional namespaces are called `extras`.
|
||||||
|
|
||||||
|
.. FIXME: faire une page pour les extras
|
||||||
|
|
||||||
|
Additional namespaces are defined during configuration.
|
||||||
|
|
||||||
|
For example, here's how to add an `example` namespace:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
RougailConfig['extra_namespaces']['example'] = ['extras/']
|
||||||
|
|
||||||
|
Then let's create an extra :term:`structure file` :file:`extras/00-base.yml`:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
:caption: the :file:`extras/00-base.yml` file content
|
||||||
|
---
|
||||||
|
version: '1.1'
|
||||||
|
my_variable_extra:
|
||||||
|
default: my_value_extra
|
||||||
|
|
||||||
|
Then, let's create the :term:`Tiramisu` objects via the following :file:`script.py` script:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:caption: the :file:`script.py` file content
|
||||||
|
|
||||||
|
from rougail import Rougail, RougailConfig
|
||||||
|
|
||||||
|
RougailConfig['main_structural_directories'] = ['dict']
|
||||||
|
RougailConfig['extra_namespaces']['example'] = ['extras/']
|
||||||
|
rougail = Rougail()
|
||||||
|
config = rougail.get_config()
|
||||||
|
print(config.value.dict())
|
||||||
|
|
||||||
|
Let's execute `script.py`:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ python3 script.py
|
||||||
|
{'rougail.my_variable': 'my_value', 'example.my_variable_extra': 'my_value_extra'}
|
||||||
81
docs/library/index.rst
Normal file
81
docs/library/index.rst
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
`Rougail`'s library description
|
||||||
|
=================================
|
||||||
|
|
||||||
|
Rougail is a configuration management library that allows you to load variables in a simple and convenient way.
|
||||||
|
|
||||||
|
In the following examples, we will use a specific configuration of Rougail.
|
||||||
|
You will find all the configuraiton options in :doc:`configuration`.
|
||||||
|
|
||||||
|
To load the configuration you must import the `RougailConfig` class and set the `main_structural_directories` values:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from rougail import RougailConfig
|
||||||
|
|
||||||
|
RougailConfig['main_structural_directories'] = ['dict']
|
||||||
|
|
||||||
|
Let's convert a our first structural file
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
As a reminder, a :term:`structure file` is a set of instructions that will allow us to create :term:`families` and :term:`variables`.
|
||||||
|
|
||||||
|
Let's start by creating a simple structure file.
|
||||||
|
|
||||||
|
Here is a first :file:`dict/00-base.yml` structure file:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
version: 1.1
|
||||||
|
|
||||||
|
my_variable: my_value # my variable
|
||||||
|
...
|
||||||
|
|
||||||
|
Then, let's create the :term:`Tiramisu` objects via the following script:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:caption: the `script.py` file content
|
||||||
|
|
||||||
|
from rougail import Rougail, RougailConfig
|
||||||
|
|
||||||
|
RougailConfig['main_structural_directories'] = ['dict']
|
||||||
|
rougail = Rougail()
|
||||||
|
config = rougail.run()
|
||||||
|
print(config.value.get())
|
||||||
|
|
||||||
|
.. demo:: Let's execute `script.py`:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ python3 script.py
|
||||||
|
{'rougail.my_variable': 'my_value'}
|
||||||
|
|
||||||
|
The operator role
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
The :term:`operator` role corresponds to the :term:`tiramisu` settings:
|
||||||
|
|
||||||
|
.. image:: images/tiramisu_get_set.png
|
||||||
|
|
||||||
|
.. index:: questionary
|
||||||
|
|
||||||
|
But instead of coding in the end user developer way, the opterator will prefer using the Rougail CLI interface:
|
||||||
|
|
||||||
|
.. image:: images/QuestionaryChoice.png
|
||||||
|
|
||||||
|
|
||||||
|
The Rougail CLI can output a rather complete view of the dataset:
|
||||||
|
|
||||||
|
.. image:: images/UserDataOutput.png
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:titlesonly:
|
||||||
|
:caption: Use library
|
||||||
|
|
||||||
|
parse
|
||||||
|
rougailconfig_load_from_cli
|
||||||
|
extra
|
||||||
|
custom_function
|
||||||
|
own_type
|
||||||
|
upgrade
|
||||||
52
docs/library/own_type.rst
Normal file
52
docs/library/own_type.rst
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
Create your own type
|
||||||
|
====================
|
||||||
|
|
||||||
|
A variable has a type. This type enables the variable to define the values that are accepted by this variable.
|
||||||
|
|
||||||
|
There is a series of default types, but obviously not all cases are taken.
|
||||||
|
|
||||||
|
It's possible to create your own type.
|
||||||
|
|
||||||
|
Here an example to a lipogram option (in a string, we cannot use "e" character):
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:caption: the `lipogram.py` file content
|
||||||
|
|
||||||
|
from tiramisu import StrOption
|
||||||
|
class LipogramOption(StrOption):
|
||||||
|
__slots__ = tuple()
|
||||||
|
_type = 'lipogram'
|
||||||
|
|
||||||
|
def validate(self,
|
||||||
|
value):
|
||||||
|
super().validate(value)
|
||||||
|
# verify that there is any 'e' in the sentense
|
||||||
|
if 'e' in value:
|
||||||
|
raise ValueError('Perec wrote a book without any "e", you could not do it in a simple sentence?')
|
||||||
|
|
||||||
|
To add the new lipogram type in Rougail:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
>>> from rougail import Rougail, RougailConfig
|
||||||
|
>>> RougailConfig['main_structural_directories'] = ['dict']
|
||||||
|
>>> RougailConfig['custom_types']['lipogram'] = LipogramOption
|
||||||
|
|
||||||
|
Now, we can use lipogram type.
|
||||||
|
Here is a :file:`dict/00-base.yml` structure file:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
---
|
||||||
|
version: '1.1'
|
||||||
|
var:
|
||||||
|
type: lipogram
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
>>> rougail = Rougail()
|
||||||
|
>>> config = rougail.get_config()
|
||||||
|
>>> config.option('rougail.var').value.set('blah')
|
||||||
|
>>> config.option('rougail.var').value.set('I just want to add a quality string that has no bad characters')
|
||||||
|
[...]
|
||||||
|
tiramisu.error.ValueOptionError: "I just want to add a quality string that has no bad characters" is an invalid lipogram for "var", Perec wrote a book without any "e", you could not do it in a simple sentence?
|
||||||
259
docs/library/parse.rst
Normal file
259
docs/library/parse.rst
Normal file
|
|
@ -0,0 +1,259 @@
|
||||||
|
Retrieve all variables and families
|
||||||
|
===================================
|
||||||
|
|
||||||
|
Rougail returns a :term:`Tiramisu` config.
|
||||||
|
|
||||||
|
Let's retrieve our variables and families to manager this.
|
||||||
|
|
||||||
|
First of all, create our structural file:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
:caption: the :file:`dist/00-base.yml` file content
|
||||||
|
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
version: 1.1
|
||||||
|
|
||||||
|
my_variable: # a simple variable
|
||||||
|
- value1
|
||||||
|
- value2
|
||||||
|
|
||||||
|
a_family: # a simple family
|
||||||
|
|
||||||
|
my_variable: my_value # a simple variable inside the family
|
||||||
|
|
||||||
|
a_dyn_family_{{ identifier }}:
|
||||||
|
description: a dynamic family for "{{ identifier }}"
|
||||||
|
dynamic:
|
||||||
|
variable: _.my_variable
|
||||||
|
|
||||||
|
a_leadership:
|
||||||
|
description: a leader family
|
||||||
|
|
||||||
|
a_leader: # a leader variable
|
||||||
|
a_follower: # a follower variable
|
||||||
|
...
|
||||||
|
|
||||||
|
Walk through our config
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Create our first script to walk through our config:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:caption: the :file:`script.py` file content
|
||||||
|
|
||||||
|
from rougail import Rougail, RougailConfig
|
||||||
|
|
||||||
|
RougailConfig['main_structural_directories'] = ['dist']
|
||||||
|
rougail = Rougail()
|
||||||
|
config = rougail.run()
|
||||||
|
|
||||||
|
def walk(config):
|
||||||
|
for option in config:
|
||||||
|
print(option.description())
|
||||||
|
if option.isoptiondescription():
|
||||||
|
walk(option)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
walk(config)
|
||||||
|
|
||||||
|
Let's execute `script.py`:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ python3 script.py
|
||||||
|
rougail
|
||||||
|
rougail.my_variable (a simple variable)
|
||||||
|
rougail.a_family (a simple family)
|
||||||
|
rougail.a_family.my_variable (a simple variable inside the family)
|
||||||
|
rougail.a_dyn_family_value1 (a dynamic family for "value1")
|
||||||
|
rougail.a_dyn_family_value1.a_leadership (a leader family)
|
||||||
|
rougail.a_dyn_family_value1.a_leadership.a_leader (a leader variable)
|
||||||
|
rougail.a_dyn_family_value1.a_leadership.a_follower (a follower variable)
|
||||||
|
rougail.a_dyn_family_value2 (a dynamic family for "value2")
|
||||||
|
rougail.a_dyn_family_value2.a_leadership (a leader family)
|
||||||
|
rougail.a_dyn_family_value2.a_leadership.a_leader (a leader variable)
|
||||||
|
rougail.a_dyn_family_value2.a_leadership.a_follower (a follower variable)
|
||||||
|
|
||||||
|
We retrieve alls description of variables and families.
|
||||||
|
|
||||||
|
Let us distinguish the variables of the families
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:caption: the :file:`script.py` file content
|
||||||
|
|
||||||
|
from rougail import Rougail, RougailConfig
|
||||||
|
|
||||||
|
RougailConfig['main_structural_directories'] = ['dist']
|
||||||
|
rougail = Rougail()
|
||||||
|
config = rougail.run()
|
||||||
|
|
||||||
|
def walk(config, level=0):
|
||||||
|
for option in config:
|
||||||
|
if option.isoptiondescription():
|
||||||
|
typ = "family"
|
||||||
|
else:
|
||||||
|
typ = "variable"
|
||||||
|
prefix = " " * level
|
||||||
|
print(f"{prefix}{typ}: {option.description()}")
|
||||||
|
if option.isoptiondescription():
|
||||||
|
walk(option, level + 1)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
walk(config)
|
||||||
|
|
||||||
|
Let's execute `script.py`:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
family: rougail
|
||||||
|
variable: rougail.my_variable (a simple variable)
|
||||||
|
family: rougail.a_family (a simple family)
|
||||||
|
variable: rougail.a_family.my_variable (a simple variable inside the family)
|
||||||
|
family: rougail.a_dyn_family_value1 (a dynamic family for "value1")
|
||||||
|
family: rougail.a_dyn_family_value1.a_leadership (a leader family)
|
||||||
|
variable: rougail.a_dyn_family_value1.a_leadership.a_leader (a leader variable)
|
||||||
|
variable: rougail.a_dyn_family_value1.a_leadership.a_follower (a follower variable)
|
||||||
|
family: rougail.a_dyn_family_value2 (a dynamic family for "value2")
|
||||||
|
family: rougail.a_dyn_family_value2.a_leadership (a leader family)
|
||||||
|
variable: rougail.a_dyn_family_value2.a_leadership.a_leader (a leader variable)
|
||||||
|
variable: rougail.a_dyn_family_value2.a_leadership.a_follower (a follower variable)
|
||||||
|
|
||||||
|
Or if we want more precision:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:caption: the :file:`script.py` file content
|
||||||
|
|
||||||
|
from rougail import Rougail, RougailConfig
|
||||||
|
|
||||||
|
RougailConfig['main_structural_directories'] = ['dist']
|
||||||
|
rougail = Rougail()
|
||||||
|
config = rougail.run()
|
||||||
|
|
||||||
|
def walk(config, level=0):
|
||||||
|
for option in config:
|
||||||
|
if option.isoptiondescription():
|
||||||
|
if option.isleadership():
|
||||||
|
typ = "leadership"
|
||||||
|
elif option.isdynamic():
|
||||||
|
typ = "dynamic family"
|
||||||
|
else:
|
||||||
|
typ = "family"
|
||||||
|
else:
|
||||||
|
if option.isleader():
|
||||||
|
typ = "leader"
|
||||||
|
elif option.isfollower():
|
||||||
|
typ = "follower"
|
||||||
|
else:
|
||||||
|
typ = "option"
|
||||||
|
if option.isdynamic():
|
||||||
|
typ = f"dynamic {typ}"
|
||||||
|
prefix = " " * level
|
||||||
|
print(f"{prefix}{typ}: {option.description()}")
|
||||||
|
if option.isoptiondescription():
|
||||||
|
walk(option, level + 1)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
walk(config)
|
||||||
|
|
||||||
|
Let's execute `script.py`:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
family: rougail
|
||||||
|
option: rougail.my_variable (a simple variable)
|
||||||
|
family: rougail.a_family (a simple family)
|
||||||
|
option: rougail.a_family.my_variable (a simple variable inside the family)
|
||||||
|
dynamic family: rougail.a_dyn_family_value1 (a dynamic family for "value1")
|
||||||
|
dynamic family: rougail.a_dyn_family_value1.a_leadership (a leader family)
|
||||||
|
dynamic option: rougail.a_dyn_family_value1.a_leadership.a_leader (a leader variable)
|
||||||
|
dynamic option: rougail.a_dyn_family_value1.a_leadership.a_follower (a follower variable)
|
||||||
|
dynamic family: rougail.a_dyn_family_value2 (a dynamic family for "value2")
|
||||||
|
dynamic family: rougail.a_dyn_family_value2.a_leadership (a leader family)
|
||||||
|
dynamic option: rougail.a_dyn_family_value2.a_leadership.a_leader (a leader variable)
|
||||||
|
dynamic option: rougail.a_dyn_family_value2.a_leadership.a_follower (a follower variable)
|
||||||
|
|
||||||
|
Get variable values
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
If we want to walk to get variables and their values:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:caption: the :file:`script.py` file content
|
||||||
|
|
||||||
|
from rougail import Rougail, RougailConfig
|
||||||
|
|
||||||
|
RougailConfig['main_structural_directories'] = ['dist']
|
||||||
|
rougail = Rougail()
|
||||||
|
config = rougail.run()
|
||||||
|
|
||||||
|
def walk(config):
|
||||||
|
for option in config:
|
||||||
|
if option.isoptiondescription():
|
||||||
|
walk(option)
|
||||||
|
else:
|
||||||
|
print(f"{option.description()}: {option.value.get()}")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
walk(config)
|
||||||
|
|
||||||
|
Let's execute `script.py`:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
rougail.my_variable (a simple variable): ['value1', 'value2']
|
||||||
|
rougail.a_family.my_variable (a simple variable inside the family): my_value
|
||||||
|
rougail.a_dyn_family_value1.a_leadership.a_leader (a leader variable): None
|
||||||
|
rougail.a_dyn_family_value1.a_leadership.a_follower (a follower variable): None
|
||||||
|
rougail.a_dyn_family_value2.a_leadership.a_leader (a leader variable): None
|
||||||
|
rougail.a_dyn_family_value2.a_leadership.a_follower (a follower variable): None
|
||||||
|
|
||||||
|
Modify variable values
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Some variables are mandatories but hasn't value. Here we set alls values:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:caption: the :file:`script.py` file content
|
||||||
|
|
||||||
|
from rougail import Rougail, RougailConfig
|
||||||
|
RougailConfig['main_structural_directories'] = ['dist']
|
||||||
|
rougail = Rougail()
|
||||||
|
config = rougail.run()
|
||||||
|
|
||||||
|
|
||||||
|
def walk(config):
|
||||||
|
for option in config:
|
||||||
|
if option.isoptiondescription():
|
||||||
|
walk(option)
|
||||||
|
else:
|
||||||
|
print(f"{option.description()}: {option.value.get()}")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print("Mandatories variables without value:")
|
||||||
|
print(config.value.mandatory())
|
||||||
|
config.value.set("rougail.my_variable", ["value 5", "value 6"])
|
||||||
|
config.value.set("rougail.a_dyn_family_value_5.a_leadership.a_leader", "value 1")
|
||||||
|
config.value.set("rougail.a_dyn_family_value_5.a_leadership.a_follower", "value 2")
|
||||||
|
config.value.set("rougail.a_dyn_family_value_6.a_leadership.a_leader", "value 3")
|
||||||
|
config.value.set("rougail.a_dyn_family_value_6.a_leadership.a_follower", "value 4")
|
||||||
|
print("Mandatories variables without value:")
|
||||||
|
print(config.value.mandatory())
|
||||||
|
walk(config)
|
||||||
|
|
||||||
|
|
||||||
|
Let's execute `script.py`:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
Mandatories variables without value:
|
||||||
|
[<TiramisuOption path="rougail.a_dyn_family_value1.a_leadership.a_leader">, <TiramisuOption path="rougail.a_dyn_family_value1.a_leadership.a_follower">, <TiramisuOption path="rougail.a_dyn_family_value2.a_leadership.a_leader">, <TiramisuOption path="rougail.a_dyn_family_value2.a_leadership.a_follower">]
|
||||||
|
Mandatories variables without value:
|
||||||
|
[]
|
||||||
|
rougail.my_variable (a simple variable): ['value 5', 'value 6']
|
||||||
|
rougail.a_family.my_variable (a simple variable inside the family): my_value
|
||||||
|
rougail.a_dyn_family_value_5.a_leadership.a_leader (a leader variable): value 1
|
||||||
|
rougail.a_dyn_family_value_5.a_leadership.a_follower (a follower variable): value 2
|
||||||
|
rougail.a_dyn_family_value_6.a_leadership.a_leader (a leader variable): value 3
|
||||||
|
rougail.a_dyn_family_value_6.a_leadership.a_follower (a follower variable): value 4
|
||||||
165
docs/library/rougailconfig_load_from_cli.rst
Normal file
165
docs/library/rougailconfig_load_from_cli.rst
Normal file
|
|
@ -0,0 +1,165 @@
|
||||||
|
Load Rougail configuration from Rougail command line informations
|
||||||
|
==================================================================
|
||||||
|
|
||||||
|
There is a lot you can do with the Rougail command line (rougail-cli), but sometimes you need to do a more advanced script.
|
||||||
|
|
||||||
|
Rather than duplicating the configuration, why not load the information from the configuration file, environment variables, or command line options?
|
||||||
|
|
||||||
|
We can loading a combination of source information but always in this order:
|
||||||
|
|
||||||
|
- configuration file
|
||||||
|
- environment variables
|
||||||
|
- commandline options
|
||||||
|
|
||||||
|
.. warning:: specific options reserve for command line (in namespace "cli") are not available in script
|
||||||
|
|
||||||
|
Then let's create an structual file:term:`structure file` :file:`dist/00-base.yml`:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
:caption: the :file:`dist/00-base.yml` file content
|
||||||
|
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
version: 1.1
|
||||||
|
|
||||||
|
my_variable: my_value_extra # a simple variable
|
||||||
|
...
|
||||||
|
|
||||||
|
Command line configuration file
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
Create a command line configuration file :file:`.rougailcli.yml`:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
:caption: the :file:`.rougailcli.yml` file content
|
||||||
|
|
||||||
|
---
|
||||||
|
main_structural_directories: # directories where are place structural file
|
||||||
|
- dist
|
||||||
|
step.output: json # output is not console but json
|
||||||
|
|
||||||
|
Let's execute Rougail command line:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ rougail
|
||||||
|
{
|
||||||
|
"my_variable": "my_value_extra"
|
||||||
|
}
|
||||||
|
|
||||||
|
Then, let's create the :term:`Tiramisu` objects via the following :file:`script.py` script:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:caption: the :file:`script.py` file content
|
||||||
|
|
||||||
|
from rougail import Rougail
|
||||||
|
rougail = Rougail()
|
||||||
|
try:
|
||||||
|
config = rougail.run()
|
||||||
|
print(config.value.get())
|
||||||
|
except Exception as err:
|
||||||
|
print(f"ERROR: {err}")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
Let's execute `script.py`:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ python3 script.py
|
||||||
|
ERROR: option "Directories where structural files are placed" is mandatory but hasn't value
|
||||||
|
|
||||||
|
As expected, the .rougailcli.yml file is not loaded because it is specific to the command line.
|
||||||
|
|
||||||
|
Let's modifying the script to do this:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:caption: the :file:`script.py` file content
|
||||||
|
|
||||||
|
from rougail import Rougail, RougailConfig
|
||||||
|
from rougail.cli.rougailconfig import load
|
||||||
|
load(RougailConfig, yaml_file=".rougailcli.yml")
|
||||||
|
rougail = Rougail()
|
||||||
|
try:
|
||||||
|
config = rougail.run()
|
||||||
|
print(config.value.get())
|
||||||
|
except Exception as err:
|
||||||
|
print(f"ERROR: {err}")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
Let's execute `script.py`:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ python3 script.py
|
||||||
|
{<TiramisuOption path="rougail">: {<TiramisuOption path="rougail.my_variable">: 'my_value_extra'}}
|
||||||
|
|
||||||
|
Environment variables
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
If we don't have .rougailcli.yml, it's possible to set option with environment variables, like this:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ env ROUGAILCLI_MAIN_STRUCTURAL_DIRECTORIES=dist/ ROUGAILCLI_STEP.OUTPUT=json ROUGAILCLI_MAIN_NAMESPACE=test bin/rougail
|
||||||
|
{
|
||||||
|
"test": {
|
||||||
|
"my_variable": "my_value_extra"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Do the same with a script:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:caption: the :file:`script.py` file content
|
||||||
|
|
||||||
|
from rougail import Rougail, RougailConfig
|
||||||
|
from rougail.cli.rougailconfig import load
|
||||||
|
load(RougailConfig, env_prefix="ROUGAILCLI")
|
||||||
|
rougail = Rougail()
|
||||||
|
try:
|
||||||
|
config = rougail.run()
|
||||||
|
print(config.value.get())
|
||||||
|
except Exception as err:
|
||||||
|
print(f"ERROR: {err}")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
Let's execute `script.py`:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ env ROUGAILCLI_MAIN_STRUCTURAL_DIRECTORIES=dist/ ROUGAILCLI_STEP.OUTPUT=json ROUGAILCLI_MAIN_NAMESPACE=test python3 script.py
|
||||||
|
{<TiramisuOption path="test">: {<TiramisuOption path="test.my_variable">: 'my_value_extra'}}
|
||||||
|
|
||||||
|
Command line option
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
To reproduce this:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
./bin/rougail --main_structural_directories dist/ --step.output json --main_namespace=new_test
|
||||||
|
{
|
||||||
|
"new_test": {
|
||||||
|
"my_variable": "my_value_extra"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Do this script:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
:caption: the :file:`script.py` file content
|
||||||
|
|
||||||
|
from rougail import Rougail, RougailConfig
|
||||||
|
from rougail.cli.rougailconfig import load
|
||||||
|
load(RougailConfig, commandline=True)
|
||||||
|
rougail = Rougail()
|
||||||
|
try:
|
||||||
|
config = rougail.run()
|
||||||
|
print(config.value.get())
|
||||||
|
except Exception as err:
|
||||||
|
print(f"ERROR: {err}")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
$ python3 script.py --main_structural_directories dist/ --step.output json --main_namespace=new_test
|
||||||
|
{<TiramisuOption path="new_test">: {<TiramisuOption path="new_test.my_variable">: 'my_value_extra'}
|
||||||
42
docs/library/upgrade.rst
Normal file
42
docs/library/upgrade.rst
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
Upgrade dictionnaries to upper version
|
||||||
|
======================================
|
||||||
|
|
||||||
|
All dictionnaries has a format version number.
|
||||||
|
When a new format version is proposed, it is possible to automatically convert the files to the new version.
|
||||||
|
|
||||||
|
We create a term:`structure file` named :file:`dict/01-upgrade.yml` with version 1.0:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
---
|
||||||
|
version: '1.0'
|
||||||
|
my_variable:
|
||||||
|
multi: true
|
||||||
|
my_dyn_family:
|
||||||
|
type: "dynamic"
|
||||||
|
variable: my_variable
|
||||||
|
a_variable:
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
>>> from rougail import RougailUpgrade, RougailConfig
|
||||||
|
>>> RougailConfig['main_structural_directories'] = ['dict']
|
||||||
|
>>> upgrade = RougailUpgrade()
|
||||||
|
>>> upgrade.load_dictionaries('dict_converted')
|
||||||
|
|
||||||
|
The term:`structure file` named :file:`dict_converted/01-upgrade.yml` is in version 1.1:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
version: '1.1'
|
||||||
|
my_variable:
|
||||||
|
multi: true
|
||||||
|
my_dyn_family:
|
||||||
|
type: dynamic
|
||||||
|
a_variable: null
|
||||||
|
dynamic:
|
||||||
|
type: variable
|
||||||
|
variable: my_variable
|
||||||
|
propertyerror: false
|
||||||
|
|
||||||
Loading…
Reference in a new issue