diff --git a/docs/index.rst b/docs/index.rst index 928185cae..f12675523 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -70,7 +70,7 @@ Explained differently, Rougail allows you to easily implement an integration of :titlesonly: :caption: The library - library + library/index configuration .. toctree:: diff --git a/docs/library.rst b/docs/library.rst deleted file mode 100644 index 8d2e253b8..000000000 --- a/docs/library.rst +++ /dev/null @@ -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 diff --git a/docs/library/custom_function.rst b/docs/library/custom_function.rst new file mode 100644 index 000000000..de58fbd4c --- /dev/null +++ b/docs/library/custom_function.rst @@ -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. diff --git a/docs/library/extra.rst b/docs/library/extra.rst new file mode 100644 index 000000000..c48936810 --- /dev/null +++ b/docs/library/extra.rst @@ -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'} diff --git a/docs/library/index.rst b/docs/library/index.rst new file mode 100644 index 000000000..b2f37f1ce --- /dev/null +++ b/docs/library/index.rst @@ -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 diff --git a/docs/library/own_type.rst b/docs/library/own_type.rst new file mode 100644 index 000000000..4da6e7aeb --- /dev/null +++ b/docs/library/own_type.rst @@ -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? diff --git a/docs/library/parse.rst b/docs/library/parse.rst new file mode 100644 index 000000000..15da9e475 --- /dev/null +++ b/docs/library/parse.rst @@ -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: + [, , , ] + 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 diff --git a/docs/library/rougailconfig_load_from_cli.rst b/docs/library/rougailconfig_load_from_cli.rst new file mode 100644 index 000000000..b3948beaa --- /dev/null +++ b/docs/library/rougailconfig_load_from_cli.rst @@ -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 + {: {: '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 + {: {: '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 + {: {: 'my_value_extra'} diff --git a/docs/library/upgrade.rst b/docs/library/upgrade.rst new file mode 100644 index 000000000..4778905df --- /dev/null +++ b/docs/library/upgrade.rst @@ -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 +