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:
|
||||
:caption: The library
|
||||
|
||||
library
|
||||
library/index
|
||||
configuration
|
||||
|
||||
.. 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