feat: suffixes in dynamic family should be a jinja function (#5)

Co-authored-by: Emmanuel Garette <egarette@silique.fr>
Co-authored-by: gwen <gwenaelremond@free.fr>
Reviewed-on: #5
Co-authored-by: egarette@silique.fr <egarette@silique.fr>
Co-committed-by: egarette@silique.fr <egarette@silique.fr>
This commit is contained in:
egarette@silique.fr 2024-03-28 09:43:33 +01:00 committed by gremond
parent 887f8aea9d
commit 0d66bffd2f
488 changed files with 1899 additions and 910 deletions

View file

@ -117,7 +117,7 @@ Here is a simple example of validating values:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
my_variable: my_variable:
validators: validators:
- type: jinja - type: jinja
@ -142,7 +142,7 @@ In the constraint, it is possible to specify the error level and put it as a war
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
my_variable: my_variable:
validators: validators:
- type: jinja - type: jinja
@ -161,7 +161,7 @@ Verification with parameters
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
my_hidden_variable: my_hidden_variable:
disabled: true disabled: true
my_variable: my_variable:
@ -189,7 +189,7 @@ An example with a suffix type parameter:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
varname: varname:
multi: true multi: true
default: default:
@ -221,7 +221,7 @@ An example with an index type parameter:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
family: family:
type: leadership type: leadership
leader: leader:
@ -249,7 +249,7 @@ In a first dictionary, let's declare our variable and its verification function:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
my_variable: my_variable:
validators: validators:
- type: jinja - type: jinja
@ -263,7 +263,7 @@ In a second dictionary it is possible to redefine the calculation:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
my_variable: my_variable:
redefine: true redefine: true
validators: validators:
@ -280,7 +280,7 @@ Here is a third dictionary in which we remove the validation:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
my_variable: my_variable:
redefine: true redefine: true
validators: validators:

View file

@ -177,7 +177,7 @@ It is possible to write the condition in Jinja:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
condition: condition:
default: 'do not hide!' default: 'do not hide!'
my_variable: my_variable:
@ -213,7 +213,7 @@ A variable can therefore be calculated via the result of another variable. Pleas
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
condition: condition:
type: boolean type: boolean
my_variable: my_variable:
@ -233,7 +233,7 @@ To delete the calculation from a variable, simply do in a new dictionary:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
my_variable: my_variable:
redefine: true redefine: true
hidden: hidden:

View file

@ -20,30 +20,30 @@ Parameters
.. FIXME: faire une page sur la "convention on variable names" .. FIXME: faire une page sur la "convention on variable names"
.. list-table:: .. list-table::
:widths: 15 45 :widths: 15 45
:header-rows: 1 :header-rows: 1
* - Parameter * - Parameter
- Comments - Comments
* - type, _type * - type, _type
`string` `string`
- possile values: - possile values:
- `family` (**default value**) - `family` (**default value**)
- `leadership` - `leadership`
- `dynamic` - `dynamic`
.. note:: If a subfamily or a subvariable already has the name `"type"`, it is possible to use the `"_type"` attribute. .. note:: If a subfamily or a subvariable already has the name `"type"`, it is possible to use the `"_type"` attribute.
* - description, _description * - description, _description
`string` `string`
- Description of the family. - Description of the family.
User information to understand the usefulness of the family. User information to understand the usefulness of the family.
..note:: If a subfamily or subvariable already has the name "description" it is possible to use the "_description" attribute. ..note:: If a subfamily or subvariable already has the name "description" it is possible to use the "_description" attribute.
@ -53,7 +53,7 @@ Parameters
`string` `string`
- Additional help associated with the family. - Additional help associated with the family.
.. note:: If a subfamily or a subvariable already has the name "help" it is possible to use the "_help" attribute. .. note:: If a subfamily or a subvariable already has the name "help" it is possible to use the "_help" attribute.
* - mode, _mode * - mode, _mode
@ -61,30 +61,30 @@ Parameters
- Family mode. - Family mode.
The default mode of a family is the smallest mode of the parent families, child variables, or child families that are contained in that family. The default mode of a family is the smallest mode of the parent families, child variables, or child families that are contained in that family.
This mode also allows you to define the default mode for variables or families included in this family. This mode also allows you to define the default mode for variables or families included in this family.
.. note:: If a subfamily or a subvariable already has the name "mode" it is possible to add the "_mode" attribute. .. note:: If a subfamily or a subvariable already has the name "mode" it is possible to add the "_mode" attribute.
* - hidden, _hidden * - hidden, _hidden
`string` `string`
- Invisible family. - Invisible family.
Allows you to hide a family as well as the variables or families included in this family. Allows you to hide a family as well as the variables or families included in this family.
This means that the family will no longer be visible in `read-write` mode, but only for calculations or in `read-only` mode. This means that the family will no longer be visible in `read-write` mode, but only for calculations or in `read-only` mode.
.. note:: If a subfamily or a subvariable already has the name "hidden" it is possible to add the "_hidden" attribute. .. note:: If a subfamily or a subvariable already has the name "hidden" it is possible to add the "_hidden" attribute.
* - disabled, _disabled * - disabled, _disabled
`string` `string`
- Disabled family. - Disabled family.
Allows you to deactivate a family as well as the variables or families included in this family. Allows you to deactivate a family as well as the variables or families included in this family.
This means that the family will no longer be visible to the user but also to a :term:`calculation`. This means that the family will no longer be visible to the user but also to a :term:`calculation`.
.. note:: If a subfamily or a subvariable already has the name "disabled" it is possible to use the "_disabled" attribute. .. note:: If a subfamily or a subvariable already has the name "disabled" it is possible to use the "_disabled" attribute.
@ -92,25 +92,18 @@ Parameters
Dynamically created family Dynamically created family
----------------------------- -----------------------------
To create a family dynamically, you must create a fictitious family linked to a variable. To create a family dynamically, you must create a fictitious family linked to a calculation.
The family name and description will actually be the prefix of the new name / description. The family name will actually be the prefix of the new name. Alternativly you can specify the suffix in the name, ie `my_{{ suffix }}_name`.
The suffix will come from the value of the bound variable. The suffix will come from the calculation.
The name of the families and variables it contains will be preserved, however, the description will be the prefix of the real description.
Obviously if the content of the linked variable were to evolve, new dynamic families will appear or disappear. Obviously if the result of calculation were to evolve, new dynamic families will appear or disappear.
To note that: Leader or follower variable
- the variable linked to the family must be a multiple variable
- it is not possible to put a simple family into a dynamic family
- it is possible to put a leading family into a dynamic family
Leader or foller variable
----------------------------- -----------------------------
A leader family has a typical attribute of “leadership”. The type is required. A leader family has a typical attribute of “leadership”. The type is required.
A leader family A leader family
---------------- ----------------
The leader and follower variables are placed in a leader family. The leader and follower variables are placed in a leader family.
@ -150,25 +143,25 @@ If a leader variable is hidden or disabled, the follower variables will be hidde
Examples Examples
---------- ----------
Simple family Simple family:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
my_family: my_family:
type: family type: family
description: This is a great family description: This is a great family
help: This is the help of a great family help: This is the help of a great family
mode: expert mode: expert
Dynamically created family Dynamically created family
---------------------------- ----------------------------
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
varname: varname:
multi: true multi: true
default: default:
@ -176,20 +169,50 @@ Dynamically created family
- val2 - val2
my_dyn_family_: my_dyn_family_:
type: dynamic type: dynamic
variable: rougail.varname dynamic:
description: 'Describe ' type: variable
variable: rougail.varname
description: 'Describe'
my_dyn_var: my_dyn_var:
type: string type: string
description: 'Variable description for ' description: 'Variable description'
This will dynamically create two families: This will dynamically create two families:
- "rougail.my_dyn_family_val1" with the description "Describe val1" - "rougail.my_dyn_family_val1"
- "rougail.my_dyn_family_val2" with the description "Describe val2" - "rougail.my_dyn_family_val2"
In the dynamic family "rougail.my_dyn_family_val1" we will find a variable "my_dyn_var" with the description "Variable description for val1". In the dynamic family "rougail.my_dyn_family_val1" we will find a variable "my_dyn_var".
Leader or follower variable Here is a second example:
.. code-block:: yaml
---
version: '1.1'
varname:
multi: true
default:
- val1
- val2
my_dyn_{{ suffix }}_family:
type: dynamic
dynamic:
type: variable
variable: rougail.varname
description: 'Describe'
my_dyn_var:
type: string
description: 'Variable description'
This will dynamically create two families:
- "rougail.my_dyn_val1_family"
- "rougail.my_dyn_val2_family"
In the dynamic family "rougail.my_dyn_val1_family" we will find a variable "my_dyn_var".
Leader or follower variable
------------------------------- -------------------------------
Definition of leader and follower variables Definition of leader and follower variables
@ -200,7 +223,7 @@ Here is an example of defining a leading variable and two following variables:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
family: family:
type: leadership type: leadership
leader: leader:
@ -217,7 +240,6 @@ To add a new follower variable, in a new dictionary, simply define one or more n
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
family: family:
follower3: follower3:

View file

@ -167,7 +167,7 @@ Let's start with an example from a simple Jinja template:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
my_calculated_variable: my_calculated_variable:
default: default:
type: jinja type: jinja
@ -178,7 +178,7 @@ Here is a second example with a boolean variable:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
my_calculated_variable: my_calculated_variable:
type: boolean type: boolean
default: default:
@ -190,7 +190,7 @@ And a multiple value of the number type:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
my_calculated_variable: my_calculated_variable:
type: number type: number
multi: true multi: true
@ -206,7 +206,7 @@ Let's create a variable whose value is returned by a python function:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
my_calculated_variable: my_calculated_variable:
default: default:
type: jinja type: jinja
@ -224,7 +224,7 @@ An example with parameters:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
my_calculated_variable: my_calculated_variable:
description: my description description: my description
default: default:
@ -247,7 +247,7 @@ An example with a `suffix` type parameter:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
varname: varname:
multi: true multi: true
default: default:
@ -255,7 +255,9 @@ An example with a `suffix` type parameter:
- val2 - val2
my_dyn_family_: my_dyn_family_:
type: dynamic type: dynamic
variable: rougail.varname dynamic:
type: variable
variable: rougail.varname
description: 'Describe ' description: 'Describe '
my_dyn_var: my_dyn_var:
type: string type: string
@ -275,7 +277,7 @@ An example with an index type parameter:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
family: family:
type: leadership type: leadership
leader: leader:
@ -299,7 +301,7 @@ Copy a variable in another:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
my_variable: my_variable:
multi: true multi: true
default: default:
@ -316,7 +318,7 @@ Copy one variable to another if the source has no `property` problem:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
my_variable: my_variable:
default: val1 default: val1
disabled: true disabled: true
@ -332,7 +334,7 @@ Copy two non-multiple variables into a multiple variable:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
my_variable_1: my_variable_1:
default: val1 default: val1
my_variable_2: my_variable_2:
@ -352,7 +354,7 @@ For example using the variable for a particular suffix:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
varname: varname:
multi: true multi: true
default: default:
@ -360,7 +362,9 @@ For example using the variable for a particular suffix:
- val2 - val2
my_dyn_family_: my_dyn_family_:
type: dynamic type: dynamic
variable: rougail.varname dynamic:
type: variable
variable: rougail.varname
description: 'Describe ' description: 'Describe '
my_dyn_var_: my_dyn_var_:
type: string type: string
@ -378,7 +382,7 @@ Second example using the variable for all suffixes:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
varname: varname:
multi: true multi: true
default: default:
@ -386,7 +390,9 @@ Second example using the variable for all suffixes:
- val2 - val2
my_dyn_family_: my_dyn_family_:
type: dynamic type: dynamic
variable: rougail.varname dynamic:
type: variable
variable: rougail.varname
description: 'Describe ' description: 'Describe '
my_dyn_var_: my_dyn_var_:
type: string type: string
@ -406,7 +412,7 @@ Calculation via a suffix
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
varname: varname:
multi: true multi: true
default: default:
@ -414,7 +420,9 @@ Calculation via a suffix
- val2 - val2
my_dyn_family_: my_dyn_family_:
type: dynamic type: dynamic
variable: rougail.varname dynamic:
type: variable
variable: rougail.varname
description: 'Describe ' description: 'Describe '
my_dyn_var_: my_dyn_var_:
type: string type: string
@ -427,7 +435,7 @@ Calculation via an index
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
family: family:
type: leadership type: leadership
leader: leader:
@ -448,7 +456,7 @@ In a first dictionary, let's declare our variable and our calculation:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
my_calculated_variable: my_calculated_variable:
default: default:
type: jinja type: jinja
@ -459,7 +467,7 @@ In a second dictionary, it is possible to redefine the calculation:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
my_calculated_variable: my_calculated_variable:
redefine: true redefine: true
default: default:
@ -471,7 +479,7 @@ In a third dictionary, we even can delete the calculation if needed:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
my_calculated_variable: my_calculated_variable:
redefine: true redefine: true
default: null default: null

View file

@ -65,7 +65,7 @@ Here is a :term:`dictionary` example:
:linenos: :linenos:
--- ---
version: '1.0' version: '1.1'
proxy: proxy:
description: Configure Proxy Access to the Internet description: Configure Proxy Access to the Internet
type: family type: family
@ -126,7 +126,7 @@ Here is the tree structure we want to have::
:caption: The `hello.yaml` file :caption: The `hello.yaml` file
--- ---
version: '1.0' version: '1.1'
hello: hello:
default: world default: world
@ -168,7 +168,7 @@ Let's continuing on our "Hello world" theme and add a :term:`family` container.
:linenos: :linenos:
--- ---
version: '1.0' version: '1.1'
world: world:
description: Hello world family container description: Hello world family container
name: name:

View file

@ -26,7 +26,7 @@ Here is a first :file:`dict/00-base.yml` dictionary:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
my_variable: my_variable:
default: my_value default: my_value
@ -71,7 +71,7 @@ Then let's create an extra :term:`dictionary` :file:`extras/00-base.yml`:
.. code-block:: yaml .. code-block:: yaml
:caption: the :file:`extras/00-base.yml` file content :caption: the :file:`extras/00-base.yml` file content
--- ---
version: '1.0' version: '1.1'
my_variable_extra: my_variable_extra:
default: my_value_extra default: my_value_extra
@ -103,7 +103,7 @@ We create the complementary :term:`dictionary` named :file:`dict/01-function.yml
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
my_variable_jinja: my_variable_jinja:
type: "string" type: "string"
default: default:
@ -141,7 +141,6 @@ Let's execute `script.py`:
The value of the `my_variable_extra` variable is calculated, and it's value comes from the :func:`return_no` function. 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 Create your own type
---------------------- ----------------------
@ -180,7 +179,7 @@ Here is a :file:`dict/00-base.yml` dictionary:
.. code-block:: yaml .. code-block:: yaml
--- ---
version: '1.0' version: '1.1'
var: var:
type: lipogram type: lipogram
@ -191,3 +190,44 @@ Here is a :file:`dict/00-base.yml` dictionary:
>>> config.option('rougail.var').value.set('I just want to add a quality string that has no bad characters') >>> 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? 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:`dictionary` named :file:`dict/01-upgrade.yml` with version 1.0:
.. code-block:: yaml
---
version: '1.1'
my_variable:
multi: true
my_dyn_family:
type: "dynamic"
variable: my_variable
a_variable:
.. code-block:: python
>>> from rougail import RougailUpgrade, RougailConfig
>>> RougailConfig['dictionaries_dir'] = ['dict']
>>> upgrade = RougailUpgrade()
>>> upgrade.load_dictionaries('dict_converted')
The term:`dictionary` 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

View file

@ -35,7 +35,7 @@ Then let's put our first dictionary file in this folder, named :file:`00-proxy.y
:linenos: :linenos:
--- ---
version: '1.0' version: '1.1'
proxy: proxy:
description: Proxy configuration in order to have access to the internet description: Proxy configuration in order to have access to the internet
type: family type: family
@ -69,7 +69,7 @@ Let's create a second :file:`dict/01-proxy_mode.yml` file.
:linenos: :linenos:
--- ---
version: '1.0' version: '1.1'
proxy: proxy:
proxy_mode: proxy_mode:
description: Proxy mode description: Proxy mode
@ -122,7 +122,7 @@ Let's create the :file:`dict/02-proxy_manual.yml` dictionary:
:caption: the the :file:`dict/02-proxy_manual.yml` file :caption: the the :file:`dict/02-proxy_manual.yml` file
--- ---
version: '1.0' version: '1.1'
proxy: proxy:
manual: manual:
description: Manual proxy configuration description: Manual proxy configuration
@ -170,7 +170,7 @@ Let's create the :file:`dict/03-proxy_manual_http_proxy.yml` dictionary:
:linenos: :linenos:
--- ---
version: '1.0' version: '1.1'
proxy: proxy:
manual: manual:
http_proxy: http_proxy:
@ -195,7 +195,7 @@ We then want to offer the user the possibility of providing the same proxy for t
.. code-block:: yaml .. code-block:: yaml
:caption: the :file:`dict/04-proxy_manual_http_use_for_https.yml` file :caption: the :file:`dict/04-proxy_manual_http_use_for_https.yml` file
version: '1.0' version: '1.1'
proxy: proxy:
manual: manual:
use_for_https: use_for_https:
@ -216,7 +216,7 @@ Let's create the :file:`dict/05-proxy_manual_ssl_proxy.yml` file:
:linenos: :linenos:
--- ---
version: '1.0' version: '1.1'
proxy: proxy:
manual: manual:
ssl_proxy: ssl_proxy:
@ -360,7 +360,7 @@ Let's create the :file:`dict/06-proxy_manual_socks_proxy.yml` file:
:caption: the :file:`dict/06-proxy_manual_socks_proxy.yml` file :caption: the :file:`dict/06-proxy_manual_socks_proxy.yml` file
--- ---
version: '1.0' version: '1.1'
proxy: proxy:
manual: manual:
socks_proxy: socks_proxy:
@ -392,7 +392,7 @@ Let's create the :file:`dict/07-proxy_auto.yml` file:
:caption: the :file:`dict/07-proxy_auto.yml` file :caption: the :file:`dict/07-proxy_auto.yml` file
--- ---
version: '1.0' version: '1.1'
proxy: proxy:
auto: auto:
type: web_address type: web_address
@ -419,7 +419,7 @@ Let's create the :file:`dict/07-proxy_no_proxy.yml` file:
:linenos: :linenos:
--- ---
version: '1.0' version: '1.1'
proxy: proxy:
no_proxy: no_proxy:
description: Address for which proxy will be desactivated description: Address for which proxy will be desactivated
@ -510,7 +510,7 @@ Nothing special when creating the authentication request. To do this, let's crea
:linenos: :linenos:
--- ---
version: '1.0' version: '1.1'
proxy: proxy:
prompt_authentication: prompt_authentication:
description: Prompt for authentication if password is saved description: Prompt for authentication if password is saved
@ -535,7 +535,7 @@ Let's create a `dict/09-proxy_proxy_dns_socks5.yml` file:
:linenos: :linenos:
--- ---
version: '1.0' version: '1.1'
proxy: proxy:
proxy_dns_socks5: proxy_dns_socks5:
description: Use proxy DNS when using SOCKS v5 description: Use proxy DNS when using SOCKS v5
@ -578,7 +578,7 @@ Let's create a `dict/10-proxy_dns_over_https.yml` file:
:linenos: :linenos:
--- ---
version: '1.0' version: '1.1'
proxy: proxy:
dns_over_https: dns_over_https:
description: DNS over HTTPS description: DNS over HTTPS
@ -651,7 +651,7 @@ Here is the complete content of the FoxyProxy type proxy configuration
:linenos: :linenos:
--- ---
version: '1.0' version: '1.1'
proxy: proxy:
_type: leadership _type: leadership
title: title:
@ -813,7 +813,7 @@ If you prefer this option, here is a second extra dictionary :file:`foxyproxy/01
:linenos: :linenos:
--- ---
version: '1.0' version: '1.1'
proxy: proxy:
username: username:
redefine: true redefine: true

View file

@ -70,7 +70,6 @@ class Annotator(Walk):
self.remove_empty_families() self.remove_empty_families()
self.family_names() self.family_names()
self.change_modes() self.change_modes()
self.dynamic_families()
self.convert_help() self.convert_help()
def remove_empty_families(self) -> None: def remove_empty_families(self) -> None:
@ -299,33 +298,6 @@ class Annotator(Walk):
if not variable.mode: if not variable.mode:
variable.mode = variable_mode variable.mode = variable_mode
def dynamic_families(self):
"""link dynamic families to object"""
for family in self.get_families():
if family.type != "dynamic":
continue
try:
family.variable = self.objectspace.paths[family.variable]
except AttributeError as err:
raise Exception(
f'cannot load the dynamic family "{family.path}", cannot find variable "{family.variable}"'
)
if not family.variable.multi:
msg = _(
f'dynamic family "{family.name}" must be linked '
f"to multi variable"
)
raise DictConsistencyError(msg, 16, family.xmlfiles)
for variable in self.objectspace.parents[family.path]:
if (
isinstance(variable, self.objectspace.family)
and not variable.leadership
):
msg = _(
f'dynamic family "{family.name}" cannot contains another family'
)
raise DictConsistencyError(msg, 22, family.xmlfiles)
def convert_help(self): def convert_help(self):
"""Convert variable help""" """Convert variable help"""
for family in self.get_families(): for family in self.get_families():

View file

@ -232,6 +232,8 @@ class ParserVariable:
self.default_multi = {} self.default_multi = {}
self.jinja = {} self.jinja = {}
self.rougailconfig = rougailconfig self.rougailconfig = rougailconfig
self.convert_options = list(CONVERT_OPTION)
self.convert_options.extend(self.rougailconfig["custom_types"])
# #
self.family = Family self.family = Family
self.dynamic = Dynamic self.dynamic = Dynamic
@ -247,11 +249,10 @@ class ParserVariable:
super().__init__() super().__init__()
def get_variable(self): def get_variable(self):
convert_options = list(CONVERT_OPTION)
convert_options.extend(self.rougailconfig["custom_types"])
class Variable(_Variable): class Variable(_Variable):
type: Literal[*convert_options] = convert_options[0] #type: Literal[*convert_options] = convert_options[0]
type: str = self.convert_options[0]
return Variable return Variable
@ -269,7 +270,8 @@ class ParserVariable:
) )
# #
hint = get_type_hints(self.variable) hint = get_type_hints(self.variable)
self.variable_types = hint["type"].__args__ # pylint: disable=W0201
self.variable_types = self.convert_options #hint["type"].__args__ # pylint: disable=W0201
# #
hint = get_type_hints(self.choice) hint = get_type_hints(self.choice)
self.choice_attrs = frozenset( # pylint: disable=W0201 self.choice_attrs = frozenset( # pylint: disable=W0201
@ -346,6 +348,8 @@ class ParserVariable:
name: str, name: str,
subpath: str, subpath: str,
obj: dict, obj: dict,
version: str,
*,
first_variable: bool = False, first_variable: bool = False,
family_is_leadership: bool = False, family_is_leadership: bool = False,
family_is_dynamic: bool = False, family_is_dynamic: bool = False,
@ -368,9 +372,10 @@ class ParserVariable:
name, name,
path, path,
obj, obj,
first_variable, version,
family_is_leadership, first_variable=first_variable,
family_is_dynamic, family_is_leadership=family_is_leadership,
family_is_dynamic=family_is_dynamic,
) )
def parse_family( def parse_family(
@ -379,6 +384,8 @@ class ParserVariable:
name: str, name: str,
path: str, path: str,
obj: Optional[Dict[str, Any]], obj: Optional[Dict[str, Any]],
version: str,
*,
first_variable: bool = False, first_variable: bool = False,
family_is_leadership: bool = False, family_is_leadership: bool = False,
family_is_dynamic: bool = False, family_is_dynamic: bool = False,
@ -429,6 +436,7 @@ class ParserVariable:
family_obj, family_obj,
filename, filename,
family_is_dynamic, family_is_dynamic,
version,
) )
force_not_first = False force_not_first = False
if self.paths[path].type == "leadership": if self.paths[path].type == "leadership":
@ -447,9 +455,10 @@ class ParserVariable:
key, key,
path, path,
value, value,
first_variable, version,
family_is_leadership, first_variable=first_variable,
family_is_dynamic, family_is_leadership=family_is_leadership,
family_is_dynamic=family_is_dynamic,
) )
def list_attributes( def list_attributes(
@ -487,6 +496,7 @@ class ParserVariable:
family: dict, family: dict,
filenames: Union[str, List[str]], filenames: Union[str, List[str]],
family_is_dynamic: bool, family_is_dynamic: bool,
version: str,
) -> None: ) -> None:
"""Add a new family""" """Add a new family"""
family["path"] = path family["path"] = path
@ -496,11 +506,15 @@ class ParserVariable:
obj_type = self.get_family_or_variable_type(family) obj_type = self.get_family_or_variable_type(family)
if obj_type == "dynamic": if obj_type == "dynamic":
family_obj = self.dynamic family_obj = self.dynamic
if version == "1.0":
if family["variable"] is None:
raise Exception(f'dynamic family must have "variable" attribute for "{family["path"]}" in {family["xmlfiles"]}')
family["dynamic"] = {'type': 'variable',
'variable': family.pop("variable"),
'propertyerror': False,
}
if "variable" in family: if "variable" in family:
family["variable"] = get_realpath( raise Exception(f'dynamic family must not have "variable" attribute for "{family["path"]}" in {family["xmlfiles"]}')
family["variable"],
self.path_prefix,
)
else: else:
family_obj = self.family family_obj = self.family
# convert to Calculation objects # convert to Calculation objects
@ -549,6 +563,8 @@ class ParserVariable:
name: str, name: str,
path: str, path: str,
obj: Optional[Dict[str, Any]], obj: Optional[Dict[str, Any]],
version: str,
*,
first_variable: bool = False, first_variable: bool = False,
family_is_leadership: bool = False, family_is_leadership: bool = False,
family_is_dynamic: bool = False, family_is_dynamic: bool = False,
@ -795,7 +811,7 @@ class ParserVariable:
class RougailConvert(ParserVariable): class RougailConvert(ParserVariable):
"""Main Rougail conversion""" """Main Rougail conversion"""
supported_version = ["1.0"] supported_version = ["1.0", "1.1"]
def __init__(self, rougailconfig) -> None: def __init__(self, rougailconfig) -> None:
self.annotator = False self.annotator = False
@ -845,6 +861,7 @@ class RougailConvert(ParserVariable):
{}, {},
"", "",
False, False,
None,
) )
else: else:
root_parent = "." root_parent = "."
@ -882,7 +899,7 @@ class RougailConvert(ParserVariable):
"""Parse file""" """Parse file"""
with open(filename, encoding="utf8") as file_fh: with open(filename, encoding="utf8") as file_fh:
objects = safe_load(file_fh) objects = safe_load(file_fh)
self.validate_file_version( version = self.validate_file_version(
objects, objects,
filename, filename,
) )
@ -891,6 +908,7 @@ class RougailConvert(ParserVariable):
namespace, namespace,
path, path,
{}, {},
version,
) )
for name, obj in objects.items(): for name, obj in objects.items():
self.family_or_variable( self.family_or_variable(
@ -898,6 +916,7 @@ class RougailConvert(ParserVariable):
name, name,
path, path,
obj, obj,
version,
) )
def get_sorted_filename( def get_sorted_filename(
@ -933,11 +952,12 @@ class RougailConvert(ParserVariable):
"""version is mandatory in YAML file""" """version is mandatory in YAML file"""
if "version" not in obj: if "version" not in obj:
raise Exception(f'"version" attribut is mandatory in yaml file {filename}') raise Exception(f'"version" attribut is mandatory in yaml file {filename}')
version = obj.pop("version") version = str(obj.pop("version"))
if version not in self.supported_version: if version not in self.supported_version:
raise Exception( raise Exception(
f"pffff version ... {version} not in {self.supported_version}" f"pffff version ... {version} not in {self.supported_version}"
) )
return version
def annotate( def annotate(
self, self,

View file

@ -73,3 +73,15 @@ class DictConsistencyError(Exception):
class UpgradeError(Exception): class UpgradeError(Exception):
"""Error during XML upgrade""" """Error during XML upgrade"""
## ---- generic exceptions ----
class NotFoundError(Exception):
"not found error"
pass
class VariableNotFoundError(NotFoundError):
"Variable was not found"
def __init__(self, errmsg, varname):
self.varname = varname

View file

@ -30,7 +30,7 @@ from pydantic import (
ConfigDict, ConfigDict,
) )
from .utils import get_jinja_variable_to_param, get_realpath from .utils import get_jinja_variable_to_param, get_realpath
from .error import VariableNotFoundError
BASETYPE = Union[StrictBool, StrictInt, StrictFloat, StrictStr, None] BASETYPE = Union[StrictBool, StrictInt, StrictFloat, StrictStr, None]
@ -174,7 +174,7 @@ class Calculation(BaseModel):
class JinjaCalculation(Calculation): class JinjaCalculation(Calculation):
attribute_name: Literal[ attribute_name: Literal[
"frozen", "hidden", "mandatory", "disabled", "default", "validators", "choices" "frozen", "hidden", "mandatory", "disabled", "default", "validators", "choices", "dynamic"
] ]
jinja: StrictStr jinja: StrictStr
params: Optional[List[Param]] = None params: Optional[List[Param]] = None
@ -279,12 +279,19 @@ class JinjaCalculation(Calculation):
not self.inside_list, not self.inside_list,
objectspace, objectspace,
) )
elif self.attribute_name == "dynamic":
return self._jinja_to_function(
"jinja_to_function",
"string",
True,
objectspace,
)
raise Exception("hu?") raise Exception("hu?")
class VariableCalculation(Calculation): class VariableCalculation(Calculation):
attribute_name: Literal[ attribute_name: Literal[
"frozen", "hidden", "mandatory", "disabled", "default", "choices" "frozen", "hidden", "mandatory", "disabled", "default", "choices", "dynamic"
] ]
variable: StrictStr variable: StrictStr
propertyerror: bool = True propertyerror: bool = True
@ -296,8 +303,9 @@ class VariableCalculation(Calculation):
variable_path = self.get_realpath(self.variable) variable_path = self.get_realpath(self.variable)
variable, suffix, dynamic = objectspace.paths.get_with_dynamic(variable_path) variable, suffix, dynamic = objectspace.paths.get_with_dynamic(variable_path)
if not variable: if not variable:
raise Exception(f"pffff {variable_path}") raise VariableNotFoundError(f"Variable not found {variable_path}", variable_path)
if not isinstance(variable, objectspace.variable): if not isinstance(variable, objectspace.variable):
# FIXME remove the pfff
raise Exception("pfff it's a family") raise Exception("pfff it's a family")
param = { param = {
"type": "variable", "type": "variable",
@ -410,7 +418,8 @@ class Family(BaseModel):
class Dynamic(Family): class Dynamic(Family):
variable: str variable: str=None
dynamic: Optional[BASETYPE_CALC]
class _Variable(BaseModel): class _Variable(BaseModel):

View file

@ -33,7 +33,7 @@ from json import dumps
from os.path import isfile, basename from os.path import isfile, basename
from .i18n import _ from .i18n import _
from .error import DictConsistencyError from .error import DictConsistencyError, VariableNotFoundError
from .utils import normalize_family from .utils import normalize_family
from .object_model import Calculation, CONVERT_OPTION from .object_model import Calculation, CONVERT_OPTION
@ -571,24 +571,23 @@ class Family(Common):
keys: list, keys: list,
) -> None: ) -> None:
if self.elt.type == "dynamic": if self.elt.type == "dynamic":
dyn = self.tiramisu.reflector_objects[self.elt.variable.path].get( keys["suffixes"] = self.calculation_value(self.elt.dynamic)
self.calls, self.elt.path
)
keys[
"suffixes"
] = f"Calculation(func['calc_value'], Params((ParamOption({dyn}, notraisepropertyerror=True))))"
children = [] children = []
for path in self.objectspace.parents[self.elt.path]: for path in self.objectspace.parents[self.elt.path]:
children.append(self.objectspace.paths[path]) children.append(self.objectspace.paths[path])
keys["children"] = ( try:
"[" keys["children"] = (
+ ", ".join( "["
[ + ", ".join(
self.tiramisu.reflector_objects[child.path].get( [
self.calls, self.elt.path self.tiramisu.reflector_objects[child.path].get(
) self.calls, self.elt.path
for child in children )
] for child in children
]
)
+ "]"
) )
+ "]" except VariableNotFoundError as exc:
) msg = f"The variable '{exc.varname}' is mandatory for the dynamic family"
raise DictConsistencyError(msg, 88, self.elt.xmlfiles)

View file

@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from typing import List, Any, Optional, Tuple from typing import List, Any, Optional, Tuple
from os.path import join, isfile, isdir, basename from os.path import join, isfile, isdir, basename
from os import listdir, makedirs from os import listdir, makedirs
try: try:
from lxml.etree import parse, XMLParser, XMLSyntaxError # pylint: disable=E0611 from lxml.etree import parse, XMLParser, XMLSyntaxError # pylint: disable=E0611
from lxml.etree import Element, SubElement, tostring from lxml.etree import Element, SubElement, tostring
@ -45,16 +46,7 @@ from .config import RougailConfig
from .object_model import CONVERT_OPTION from .object_model import CONVERT_OPTION
VERSIONS = ["0.10", "1.0"] VERSIONS = ["0.10", "1.0", "1.1"]
FIXME_PRINT_FILENAME = True
FIXME_PRINT_FILENAME = False
FIXME_PRINT_FILE = True
FIXME_PRINT_FILE = False
FIXME_PRINT_UNKNOWN_VAR = True
FIXME_PRINT_UNKNOWN_VAR = False
FIXME_PRINT_REMOVE = True
FIXME_PRINT_REMOVE = False
def get_function_name(version): def get_function_name(version):
@ -70,17 +62,13 @@ class NoAliasDumper(SafeDumper):
return True return True
class upgrade_010_to_100: class upgrade_010_to_10:
def __init__( def __init__(
self, self,
dico: dict, dico: dict,
namespace: str, namespace: str,
xmlsrc: str, xmlsrc: str,
) -> None: ) -> None:
if FIXME_PRINT_FILE:
from pprint import pprint
pprint(dico)
self.xmlsrc = xmlsrc self.xmlsrc = xmlsrc
self.paths = {"family": {}, "variable": {}} self.paths = {"family": {}, "variable": {}}
self.lists = { self.lists = {
@ -94,10 +82,6 @@ class upgrade_010_to_100:
self.parse_variables_with_path() self.parse_variables_with_path()
self.parse_services(dico) self.parse_services(dico)
self.parse_constraints(dico) self.parse_constraints(dico)
if FIXME_PRINT_FILE:
print("==")
pprint(self.variables)
pprint(self.services)
def parse_variables( def parse_variables(
self, self,
@ -159,13 +143,14 @@ class upgrade_010_to_100:
new_families[name] = variable new_families[name] = variable
self.flatten_paths["variable"][name] = sub_path self.flatten_paths["variable"][name] = sub_path
self.paths["variable"][sub_path] = variable self.paths["variable"][sub_path] = variable
if "redefine" not in variable and "value" not in variable and "mandatory" not in variable and ("type" not in variable or variable["type"] != "boolean"): if (
"redefine" not in variable
and "value" not in variable
and "mandatory" not in variable
and ("type" not in variable or variable["type"] != "boolean")
):
variable["mandatory"] = False variable["mandatory"] = False
if "remove_condition" in variable and variable.pop("remove_condition"): if "remove_condition" in variable and variable.pop("remove_condition"):
if FIXME_PRINT_REMOVE:
print(
f"variable {name} in file {self.xmlsrc} has remove_condition, all properties (hidden, disabled and mandatory) are set to False"
)
for prop in ["hidden", "disabled", "mandatory"]: for prop in ["hidden", "disabled", "mandatory"]:
if prop not in variable: if prop not in variable:
variable[prop] = False variable[prop] = False
@ -334,27 +319,19 @@ class upgrade_010_to_100:
condition_value = True condition_value = True
else: else:
condition_value = self.params_condition_to_jinja( condition_value = self.params_condition_to_jinja(
source, condition["param"], name.endswith("if_in") prop, source, condition["param"], name.endswith("if_in")
) )
for target in condition["target"]: for target in condition["target"]:
typ = target.get("type", "variable") typ = target.get("type", "variable")
if typ == "variable": if typ == "variable":
variable_path = self.get_variable_path(target["text"]) variable_path = self.get_variable_path(target["text"])
if variable_path is None: if variable_path is None:
if FIXME_PRINT_UNKNOWN_VAR and not target.get("optional", False):
print(
f'pffff la target {target["text"]} de la condition n\'est pas trouvable'
)
continue continue
variable = self.paths["variable"][variable_path] variable = self.paths["variable"][variable_path]
variable[prop] = condition_value variable[prop] = condition_value
elif typ == "family": elif typ == "family":
family_path = self.get_family_path(target["text"]) family_path = self.get_family_path(target["text"])
if family_path is None: if family_path is None:
if FIXME_PRINT_UNKNOWN_VAR and not target.get("optional", False):
print(
f'pffff la target {target["text"]} de la condition n\'est pas trouvable'
)
continue continue
family = self.paths["family"][family_path] family = self.paths["family"][family_path]
family[prop] = condition_value family[prop] = condition_value
@ -386,10 +363,6 @@ class upgrade_010_to_100:
for target in check["target"]: for target in check["target"]:
variable_path = self.get_variable_path(target["text"]) variable_path = self.get_variable_path(target["text"])
if variable_path is None: if variable_path is None:
if FIXME_PRINT_UNKNOWN_VAR and not target.get("optional", False):
print(
f'pffff la target {target["text"]} dans le check n\'est pas trouvable'
)
continue continue
variable = self.paths["variable"][variable_path] variable = self.paths["variable"][variable_path]
if "validators" in variable and variable["validators"] is None: if "validators" in variable and variable["validators"] is None:
@ -411,10 +384,6 @@ class upgrade_010_to_100:
params = [] params = []
variable_path = self.get_variable_path(target["text"]) variable_path = self.get_variable_path(target["text"])
if variable_path is None: if variable_path is None:
if FIXME_PRINT_UNKNOWN_VAR and not target.get("optional", False):
print(
f'pffff la target {target["text"]} dans le fill n\'est pas trouvable'
)
continue continue
variable = self.paths["variable"][variable_path] variable = self.paths["variable"][variable_path]
if fill.get("type") == "jinja": if fill.get("type") == "jinja":
@ -428,6 +397,7 @@ class upgrade_010_to_100:
def params_condition_to_jinja( def params_condition_to_jinja(
self, self,
prop: str,
path: str, path: str,
params: List[dict], params: List[dict],
if_in: bool, if_in: bool,
@ -444,9 +414,9 @@ class upgrade_010_to_100:
if new_param: if new_param:
new_params |= new_param new_params |= new_param
if if_in: if if_in:
jinja += " %}true{% else %}false{% endif %}" jinja += " %}" + prop + "{% endif %}"
else: else:
jinja += " %}false{% else %}true{% endif %}" jinja += " %}{% else %}" + prop + "{% endif %}"
ret = { ret = {
"type": "jinja", "type": "jinja",
"jinja": jinja, "jinja": jinja,
@ -459,11 +429,9 @@ class upgrade_010_to_100:
self, self,
param: dict, param: dict,
) -> Any: ) -> Any:
# <!ATTLIST type (string|number|nil|space|boolean|variable|function|information|suffix|index) "string">
typ = param.get("type", "string") typ = param.get("type", "string")
if typ == "string": if typ == "string":
value = param["text"] value = param["text"]
# value = dumps(value, ensure_ascii=False)
elif typ == "number": elif typ == "number":
value = int(param["text"]) value = int(param["text"])
elif typ == "nil": elif typ == "nil":
@ -551,7 +519,6 @@ class upgrade_010_to_100:
new_param, value = self.get_jinja_param_and_value(param) new_param, value = self.get_jinja_param_and_value(param)
if new_param: if new_param:
params |= new_param params |= new_param
# if param.get('type') != 'variable' or value is not None:
if "name" in param: if "name" in param:
values.append(f'{param["name"]}={value}') values.append(f'{param["name"]}={value}')
else: else:
@ -577,8 +544,6 @@ class upgrade_010_to_100:
): ):
path = self.flatten_paths["variable"][path] path = self.flatten_paths["variable"][path]
if path not in self.paths["variable"]: if path not in self.paths["variable"]:
if FIXME_PRINT_UNKNOWN_VAR:
print("pffff impossible de trouver la variable", path)
return return
return path return path
@ -589,8 +554,6 @@ class upgrade_010_to_100:
if path not in self.paths["family"] and path in self.flatten_paths["family"]: if path not in self.paths["family"] and path in self.flatten_paths["family"]:
path = self.flatten_paths["family"][path] path = self.flatten_paths["family"][path]
if path not in self.paths["family"]: if path not in self.paths["family"]:
if FIXME_PRINT_UNKNOWN_VAR:
print("pffff impossible de trouver la famille", path)
return return
return path return path
@ -615,21 +578,22 @@ class RougailUpgrade:
def load_dictionaries( def load_dictionaries(
self, self,
# srcfolder: str,
dstfolder: str, dstfolder: str,
services_dstfolder: Optional[str], services_dstfolder: Optional[str] = None,
extra_dstfolder: Optional[str] = None, extra_dstfolder: Optional[str] = None,
# namespace: str,
# display: bool=True,
): ):
if extra_dstfolder is None: if extra_dstfolder is None:
extra_dstfolder = dstfolder extra_dstfolder = dstfolder
self._load_dictionaries( dict_dirs = self.rougailconfig["dictionaries_dir"]
self.rougailconfig["dictionaries_dir"], if not isinstance(dict_dirs, list):
dstfolder, dict_dirs = [dict_dirs]
services_dstfolder, for dict_dir in dict_dirs:
self.rougailconfig["variable_namespace"], self._load_dictionaries(
) dict_dir,
dstfolder,
services_dstfolder,
self.rougailconfig["variable_namespace"],
)
for namespace, extra_dirs in self.rougailconfig["extra_dictionaries"].items(): for namespace, extra_dirs in self.rougailconfig["extra_dictionaries"].items():
extra_dstsubfolder = join(extra_dstfolder, namespace) extra_dstsubfolder = join(extra_dstfolder, namespace)
if not isdir(extra_dstsubfolder): if not isdir(extra_dstsubfolder):
@ -671,7 +635,7 @@ class RougailUpgrade:
) )
if filename.endswith(".xml"): if filename.endswith(".xml"):
if parse is None: if parse is None:
raise Exception('XML module is not installed') raise Exception("XML module is not installed")
try: try:
parser = XMLParser(remove_blank_text=True) parser = XMLParser(remove_blank_text=True)
document = parse(xmlsrc, parser) document = parse(xmlsrc, parser)
@ -685,29 +649,22 @@ class RougailUpgrade:
else: else:
with xmlsrc.open() as xml_fh: with xmlsrc.open() as xml_fh:
root = safe_load(xml_fh) root = safe_load(xml_fh)
search_function_name = get_function_name(root["version"]) search_function_name = get_function_name(str(root["version"]))
ext = "yml" ext = "yml"
function_found = False function_found = False
if FIXME_PRINT_FILENAME: root_services = None
print(
"========================================================================"
)
print(xmlsrc)
print(
"========================================================================"
)
for version, function_version in FUNCTION_VERSIONS: for version, function_version in FUNCTION_VERSIONS:
if function_found and hasattr(self, function_version): if function_found and hasattr(self, function_version):
# if display:
# print(f' - convert {filename} to version {version}')
upgrade_help = self.upgrade_help.get(function_version, {}).get( upgrade_help = self.upgrade_help.get(function_version, {}).get(
filename, {} filename, {}
) )
if upgrade_help.get("remove") is True: if upgrade_help.get("remove") is True:
continue continue
root, root_services, new_type = getattr(self, function_version)( root, root_services_, new_type = getattr(self, function_version)(
root, upgrade_help, namespace, xmlsrc, ext root, upgrade_help, namespace, xmlsrc, ext
) )
if root_services_ is not None:
root_services = root_services_
if function_version == search_function_name: if function_version == search_function_name:
function_found = True function_found = True
if root: if root:
@ -733,12 +690,6 @@ class RougailUpgrade:
Dumper=NoAliasDumper, Dumper=NoAliasDumper,
) )
# if not self.dtd.validate(document):
# dtd_error = self.dtd.error_log.filter_from_errors()[0]
# msg = _(f'not a valid XML file: {dtd_error}')
# raise DictConsistencyError(msg, 43, [xmlfile])
# yield xmlfile, document.getroot()
def _attribut_to_bool(self, variable): def _attribut_to_bool(self, variable):
for prop in [ for prop in [
"mandatory", "mandatory",
@ -766,10 +717,11 @@ class RougailUpgrade:
def _attribut_to_int(self, variable): def _attribut_to_int(self, variable):
for prop in ["mode"]: for prop in ["mode"]:
if prop in variable: if prop in variable:
if variable[prop] in ['expert', 'normal']: if variable[prop] in ["expert", "normal"]:
variable[prop] = {'expert': 'advanced', variable[prop] = {
'normal': 'standard', "expert": "advanced",
}.get(variable[prop]) "normal": "standard",
}.get(variable[prop])
continue continue
try: try:
variable[prop] = int(variable[prop]) variable[prop] = int(variable[prop])
@ -891,6 +843,36 @@ class RougailUpgrade:
dico = {obj_name: dico} dico = {obj_name: dico}
return dico return dico
def _update_1_1(self, root):
if not isinstance(root, dict):
return
# migrate dynamic family
if (
("variable" in root and isinstance(root["variable"], str))
or ("_variable" in root and isinstance(root["_variable"], str))
) and (
("_type" in root and root["_type"] == "dynamic")
or ("type" in root and root["type"] == "dynamic")
):
root["dynamic"] = {
"type": "variable",
"variable": root.pop("variable"),
"propertyerror": False,
}
for key, value in root.items():
self._update_1_1(value)
def update_1_1(
self,
root,
upgrade_help: dict,
namespace: str,
xmlsrc: str,
ext: str,
):
self._update_1_1(root)
return root, None, "yml"
def update_1_0( def update_1_0(
self, self,
root: "Element", root: "Element",
@ -909,19 +891,9 @@ class RougailUpgrade:
new_objects = self._xml_to_yaml(objects, typ, variables, "") new_objects = self._xml_to_yaml(objects, typ, variables, "")
if new_objects[typ]: if new_objects[typ]:
new_root.update(new_objects) new_root.update(new_objects)
# services = root.find('services')
# if services is None:
# services = []
# new_services = self._xml_to_yaml_service(services)
# if new_services:
# new_root['services'] = new_services
# paths = self._get_path_variables(variables,
# namespace == 'configuration',
# namespace,
# )
else: else:
new_root = root new_root = root
variables, services = upgrade_010_to_100(new_root, namespace, xmlsrc).get() variables, services = upgrade_010_to_10(new_root, namespace, xmlsrc).get()
return variables, services, "yml" return variables, services, "yml"
def update_0_10( def update_0_10(

View file

@ -8,9 +8,12 @@ general:
- val2 - val2
dyn: dyn:
type: dynamic type: dynamic
variable: rougail.general.varname dynamic:
type: variable
variable: rougail.general.varname
propertyerror: false
vardyn: vardyn:
type: string type: string
description: No change description: No change
mandatory: false mandatory: false
version: '1.0' version: '1.1'

View file

@ -19,7 +19,54 @@ def _load_functions(path):
continue continue
func[function] = getattr(func_, function) func[function] = getattr(func_, function)
_load_functions('tests/dictionaries/../eosfunc/test.py') _load_functions('tests/dictionaries/../eosfunc/test.py')
from jinja2 import StrictUndefined, DictLoader
from jinja2.sandbox import SandboxedEnvironment
from rougail.annotator.variable import CONVERT_OPTION
from tiramisu.error import ValueWarning
def jinja_to_function(__internal_jinja, __internal_type, __internal_multi, **kwargs):
global ENV, CONVERT_OPTION
kw = {}
for key, value in kwargs.items():
if '.' in key:
c_kw = kw
path, var = key.rsplit('.', 1)
for subkey in path.split('.'):
c_kw = c_kw.setdefault(subkey, {})
c_kw[var] = value
else:
kw[key] = value
values = ENV.get_template(__internal_jinja).render(kw, **func).strip()
convert = CONVERT_OPTION[__internal_type].get('func', str)
if __internal_multi:
return [convert(val) for val in values.split()]
values = convert(values)
return values if values != '' and values != 'None' else None
def variable_to_property(prop, value):
return prop if value else None
def jinja_to_property(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return func['variable_to_property'](prop, value is not None)
def jinja_to_property_help(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return (prop, f'"{prop}" ({value})')
def valid_with_jinja(warnings_only=False, **kwargs):
global ValueWarning
value = func['jinja_to_function'](**kwargs)
if value:
if warnings_only:
raise ValueWarning(value)
else:
raise ValueError(value)
func['jinja_to_function'] = jinja_to_function
func['jinja_to_property'] = jinja_to_property
func['jinja_to_property_help'] = jinja_to_property_help
func['variable_to_property'] = variable_to_property
func['valid_with_jinja'] = valid_with_jinja
dict_env = {}
from rougail.tiramisu import ConvertDynOptionDescription from rougail.tiramisu import ConvertDynOptionDescription
ENV = SandboxedEnvironment(loader=DictLoader(dict_env), undefined=StrictUndefined)
ENV.filters = func
ENV.compile_templates('jinja_caches', zip=None)
option_3 = StrOption(name="varname", doc="No change", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "notempty", "standard"})) option_3 = StrOption(name="varname", doc="No change", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "notempty", "standard"}))
optiondescription_2 = OptionDescription(name="general", doc="general", children=[option_3], properties=frozenset({"standard"})) optiondescription_2 = OptionDescription(name="general", doc="general", children=[option_3], properties=frozenset({"standard"}))
option_5 = StrOption(name="vardyn", doc="No change", properties=frozenset({"standard"})) option_5 = StrOption(name="vardyn", doc="No change", properties=frozenset({"standard"}))

View file

@ -19,7 +19,54 @@ def _load_functions(path):
continue continue
func[function] = getattr(func_, function) func[function] = getattr(func_, function)
_load_functions('tests/dictionaries/../eosfunc/test.py') _load_functions('tests/dictionaries/../eosfunc/test.py')
from jinja2 import StrictUndefined, DictLoader
from jinja2.sandbox import SandboxedEnvironment
from rougail.annotator.variable import CONVERT_OPTION
from tiramisu.error import ValueWarning
def jinja_to_function(__internal_jinja, __internal_type, __internal_multi, **kwargs):
global ENV, CONVERT_OPTION
kw = {}
for key, value in kwargs.items():
if '.' in key:
c_kw = kw
path, var = key.rsplit('.', 1)
for subkey in path.split('.'):
c_kw = c_kw.setdefault(subkey, {})
c_kw[var] = value
else:
kw[key] = value
values = ENV.get_template(__internal_jinja).render(kw, **func).strip()
convert = CONVERT_OPTION[__internal_type].get('func', str)
if __internal_multi:
return [convert(val) for val in values.split()]
values = convert(values)
return values if values != '' and values != 'None' else None
def variable_to_property(prop, value):
return prop if value else None
def jinja_to_property(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return func['variable_to_property'](prop, value is not None)
def jinja_to_property_help(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return (prop, f'"{prop}" ({value})')
def valid_with_jinja(warnings_only=False, **kwargs):
global ValueWarning
value = func['jinja_to_function'](**kwargs)
if value:
if warnings_only:
raise ValueWarning(value)
else:
raise ValueError(value)
func['jinja_to_function'] = jinja_to_function
func['jinja_to_property'] = jinja_to_property
func['jinja_to_property_help'] = jinja_to_property_help
func['variable_to_property'] = variable_to_property
func['valid_with_jinja'] = valid_with_jinja
dict_env = {}
from rougail.tiramisu import ConvertDynOptionDescription from rougail.tiramisu import ConvertDynOptionDescription
ENV = SandboxedEnvironment(loader=DictLoader(dict_env), undefined=StrictUndefined)
ENV.filters = func
ENV.compile_templates('jinja_caches', zip=None)
option_4 = StrOption(name="varname", doc="No change", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "notempty", "standard"})) option_4 = StrOption(name="varname", doc="No change", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "notempty", "standard"}))
optiondescription_3 = OptionDescription(name="general", doc="general", children=[option_4], properties=frozenset({"standard"})) optiondescription_3 = OptionDescription(name="general", doc="general", children=[option_4], properties=frozenset({"standard"}))
option_6 = StrOption(name="vardyn", doc="No change", properties=frozenset({"standard"})) option_6 = StrOption(name="vardyn", doc="No change", properties=frozenset({"standard"}))

View file

@ -0,0 +1,16 @@
general:
varname:
type: string
description: No change
multi: true
default:
- val1
- val2
dyn:
type: dynamic
variable: rougail.general.varname
vardyn:
type: string
description: No change
mandatory: false
version: '1.0'

View file

@ -0,0 +1,17 @@
{
"rougail.general.varname": {
"owner": "default",
"value": [
"val1",
"val2"
]
},
"rougail.dynval1.vardyn": {
"owner": "default",
"value": null
},
"rougail.dynval2.vardyn": {
"owner": "default",
"value": null
}
}

View file

@ -0,0 +1,8 @@
{
"rougail.general.varname": [
"val1",
"val2"
],
"rougail.dynval1.vardyn": null,
"rougail.dynval2.vardyn": null
}

View file

@ -0,0 +1,17 @@
{
"rougail.general.varname": {
"owner": "default",
"value": [
"val1",
"val2"
]
},
"rougail.dynval1.vardyn": {
"owner": "default",
"value": null
},
"rougail.dynval2.vardyn": {
"owner": "default",
"value": null
}
}

View file

@ -0,0 +1,75 @@
from tiramisu import *
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
ALLOWED_LEADER_PROPERTIES.add("basic")
ALLOWED_LEADER_PROPERTIES.add("standard")
ALLOWED_LEADER_PROPERTIES.add("advanced")
from importlib.machinery import SourceFileLoader as _SourceFileLoader
from importlib.util import spec_from_loader as _spec_from_loader, module_from_spec as _module_from_spec
global func
func = {'calc_value': calc_value}
def _load_functions(path):
global _SourceFileLoader, _spec_from_loader, _module_from_spec, func
loader = _SourceFileLoader('func', path)
spec = _spec_from_loader(loader.name, loader)
func_ = _module_from_spec(spec)
loader.exec_module(func_)
for function in dir(func_):
if function.startswith('_'):
continue
func[function] = getattr(func_, function)
_load_functions('tests/dictionaries/../eosfunc/test.py')
from jinja2 import StrictUndefined, DictLoader
from jinja2.sandbox import SandboxedEnvironment
from rougail.annotator.variable import CONVERT_OPTION
from tiramisu.error import ValueWarning
def jinja_to_function(__internal_jinja, __internal_type, __internal_multi, **kwargs):
global ENV, CONVERT_OPTION
kw = {}
for key, value in kwargs.items():
if '.' in key:
c_kw = kw
path, var = key.rsplit('.', 1)
for subkey in path.split('.'):
c_kw = c_kw.setdefault(subkey, {})
c_kw[var] = value
else:
kw[key] = value
values = ENV.get_template(__internal_jinja).render(kw, **func).strip()
convert = CONVERT_OPTION[__internal_type].get('func', str)
if __internal_multi:
return [convert(val) for val in values.split()]
values = convert(values)
return values if values != '' and values != 'None' else None
def variable_to_property(prop, value):
return prop if value else None
def jinja_to_property(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return func['variable_to_property'](prop, value is not None)
def jinja_to_property_help(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return (prop, f'"{prop}" ({value})')
def valid_with_jinja(warnings_only=False, **kwargs):
global ValueWarning
value = func['jinja_to_function'](**kwargs)
if value:
if warnings_only:
raise ValueWarning(value)
else:
raise ValueError(value)
func['jinja_to_function'] = jinja_to_function
func['jinja_to_property'] = jinja_to_property
func['jinja_to_property_help'] = jinja_to_property_help
func['variable_to_property'] = variable_to_property
func['valid_with_jinja'] = valid_with_jinja
dict_env = {}
from rougail.tiramisu import ConvertDynOptionDescription
ENV = SandboxedEnvironment(loader=DictLoader(dict_env), undefined=StrictUndefined)
ENV.filters = func
ENV.compile_templates('jinja_caches', zip=None)
option_3 = StrOption(name="varname", doc="No change", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "notempty", "standard"}))
optiondescription_2 = OptionDescription(name="general", doc="general", children=[option_3], properties=frozenset({"standard"}))
option_5 = StrOption(name="vardyn", doc="No change", properties=frozenset({"standard"}))
optiondescription_4 = ConvertDynOptionDescription(name="dyn", doc="dyn", suffixes=Calculation(func['calc_value'], Params((ParamOption(option_3, notraisepropertyerror=True)))), children=[option_5], properties=frozenset({"standard"}))
optiondescription_1 = OptionDescription(name="rougail", doc="rougail", children=[optiondescription_2, optiondescription_4], properties=frozenset({"standard"}))
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])

View file

@ -0,0 +1,82 @@
from tiramisu import *
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
ALLOWED_LEADER_PROPERTIES.add("basic")
ALLOWED_LEADER_PROPERTIES.add("standard")
ALLOWED_LEADER_PROPERTIES.add("advanced")
from importlib.machinery import SourceFileLoader as _SourceFileLoader
from importlib.util import spec_from_loader as _spec_from_loader, module_from_spec as _module_from_spec
global func
func = {'calc_value': calc_value}
def _load_functions(path):
global _SourceFileLoader, _spec_from_loader, _module_from_spec, func
loader = _SourceFileLoader('func', path)
spec = _spec_from_loader(loader.name, loader)
func_ = _module_from_spec(spec)
loader.exec_module(func_)
for function in dir(func_):
if function.startswith('_'):
continue
func[function] = getattr(func_, function)
_load_functions('tests/dictionaries/../eosfunc/test.py')
from jinja2 import StrictUndefined, DictLoader
from jinja2.sandbox import SandboxedEnvironment
from rougail.annotator.variable import CONVERT_OPTION
from tiramisu.error import ValueWarning
def jinja_to_function(__internal_jinja, __internal_type, __internal_multi, **kwargs):
global ENV, CONVERT_OPTION
kw = {}
for key, value in kwargs.items():
if '.' in key:
c_kw = kw
path, var = key.rsplit('.', 1)
for subkey in path.split('.'):
c_kw = c_kw.setdefault(subkey, {})
c_kw[var] = value
else:
kw[key] = value
values = ENV.get_template(__internal_jinja).render(kw, **func).strip()
convert = CONVERT_OPTION[__internal_type].get('func', str)
if __internal_multi:
return [convert(val) for val in values.split()]
values = convert(values)
return values if values != '' and values != 'None' else None
def variable_to_property(prop, value):
return prop if value else None
def jinja_to_property(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return func['variable_to_property'](prop, value is not None)
def jinja_to_property_help(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return (prop, f'"{prop}" ({value})')
def valid_with_jinja(warnings_only=False, **kwargs):
global ValueWarning
value = func['jinja_to_function'](**kwargs)
if value:
if warnings_only:
raise ValueWarning(value)
else:
raise ValueError(value)
func['jinja_to_function'] = jinja_to_function
func['jinja_to_property'] = jinja_to_property
func['jinja_to_property_help'] = jinja_to_property_help
func['variable_to_property'] = variable_to_property
func['valid_with_jinja'] = valid_with_jinja
dict_env = {}
from rougail.tiramisu import ConvertDynOptionDescription
ENV = SandboxedEnvironment(loader=DictLoader(dict_env), undefined=StrictUndefined)
ENV.filters = func
ENV.compile_templates('jinja_caches', zip=None)
option_4 = StrOption(name="varname", doc="No change", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "notempty", "standard"}))
optiondescription_3 = OptionDescription(name="general", doc="general", children=[option_4], properties=frozenset({"standard"}))
option_6 = StrOption(name="vardyn", doc="No change", properties=frozenset({"standard"}))
optiondescription_5 = ConvertDynOptionDescription(name="dyn", doc="dyn", suffixes=Calculation(func['calc_value'], Params((ParamOption(option_4, notraisepropertyerror=True)))), children=[option_6], properties=frozenset({"standard"}))
optiondescription_2 = OptionDescription(name="rougail", doc="rougail", children=[optiondescription_3, optiondescription_5], properties=frozenset({"standard"}))
optiondescription_1 = OptionDescription(name="1", doc="1", children=[optiondescription_2], properties=frozenset({"standard"}))
option_10 = StrOption(name="varname", doc="No change", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "notempty", "standard"}))
optiondescription_9 = OptionDescription(name="general", doc="general", children=[option_10], properties=frozenset({"standard"}))
option_12 = StrOption(name="vardyn", doc="No change", properties=frozenset({"standard"}))
optiondescription_11 = ConvertDynOptionDescription(name="dyn", doc="dyn", suffixes=Calculation(func['calc_value'], Params((ParamOption(option_10, notraisepropertyerror=True)))), children=[option_12], properties=frozenset({"standard"}))
optiondescription_8 = OptionDescription(name="rougail", doc="rougail", children=[optiondescription_9, optiondescription_11], properties=frozenset({"standard"}))
optiondescription_7 = OptionDescription(name="2", doc="2", children=[optiondescription_8], properties=frozenset({"standard"}))
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1, optiondescription_7])

View file

@ -1,5 +1,5 @@
--- ---
version: '1.0' version: '1.1'
general: general:
varname: varname:
type: string type: string
@ -10,7 +10,10 @@ general:
- val2 - val2
dyn: dyn:
type: dynamic type: dynamic
variable: rougail.general.varname dynamic:
type: variable
variable: rougail.general.varname
propertyerror: false
vardyn: vardyn:
type: string type: string
description: No change description: No change

View file

@ -1,5 +1,5 @@
--- ---
version: '1.0' version: '1.1'
general: general:
varname: varname:
multi: true multi: true
@ -8,7 +8,10 @@ general:
- val2 - val2
dyn: dyn:
type: dynamic type: dynamic
variable: rougail.general.varname dynamic:
type: variable
variable: rougail.general.varname
propertyerror: false
vardyn: vardyn:
type: string type: string
default: val default: val

View file

@ -1,4 +1,4 @@
version: '1.0' version: '1.1'
general: general:
varname: varname:
type: string type: string
@ -9,7 +9,10 @@ general:
- val2 - val2
dyn: dyn:
type: dynamic type: dynamic
variable: rougail.general.varname dynamic:
type: variable
variable: rougail.general.varname
propertyerror: false
vardyn: vardyn:
type: string type: string
description: No change description: No change

View file

@ -8,7 +8,10 @@ general:
- val2 - val2
dyn: dyn:
type: dynamic type: dynamic
variable: rougail.general.varname dynamic:
type: variable
variable: rougail.general.varname
propertyerror: false
vardyn: vardyn:
type: string type: string
description: No change description: No change
@ -24,4 +27,4 @@ new:
type: string type: string
description: No change description: No change
mandatory: false mandatory: false
version: '1.0' version: '1.1'

View file

@ -9,9 +9,12 @@ general:
dyn: dyn:
description: 'Dyn ' description: 'Dyn '
type: dynamic type: dynamic
variable: rougail.general.varname dynamic:
type: variable
variable: rougail.general.varname
propertyerror: false
vardyn: vardyn:
type: string type: string
description: No change description: No change
mandatory: false mandatory: false
version: '1.0' version: '1.1'

View file

@ -19,7 +19,54 @@ def _load_functions(path):
continue continue
func[function] = getattr(func_, function) func[function] = getattr(func_, function)
_load_functions('tests/dictionaries/../eosfunc/test.py') _load_functions('tests/dictionaries/../eosfunc/test.py')
from jinja2 import StrictUndefined, DictLoader
from jinja2.sandbox import SandboxedEnvironment
from rougail.annotator.variable import CONVERT_OPTION
from tiramisu.error import ValueWarning
def jinja_to_function(__internal_jinja, __internal_type, __internal_multi, **kwargs):
global ENV, CONVERT_OPTION
kw = {}
for key, value in kwargs.items():
if '.' in key:
c_kw = kw
path, var = key.rsplit('.', 1)
for subkey in path.split('.'):
c_kw = c_kw.setdefault(subkey, {})
c_kw[var] = value
else:
kw[key] = value
values = ENV.get_template(__internal_jinja).render(kw, **func).strip()
convert = CONVERT_OPTION[__internal_type].get('func', str)
if __internal_multi:
return [convert(val) for val in values.split()]
values = convert(values)
return values if values != '' and values != 'None' else None
def variable_to_property(prop, value):
return prop if value else None
def jinja_to_property(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return func['variable_to_property'](prop, value is not None)
def jinja_to_property_help(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return (prop, f'"{prop}" ({value})')
def valid_with_jinja(warnings_only=False, **kwargs):
global ValueWarning
value = func['jinja_to_function'](**kwargs)
if value:
if warnings_only:
raise ValueWarning(value)
else:
raise ValueError(value)
func['jinja_to_function'] = jinja_to_function
func['jinja_to_property'] = jinja_to_property
func['jinja_to_property_help'] = jinja_to_property_help
func['variable_to_property'] = variable_to_property
func['valid_with_jinja'] = valid_with_jinja
dict_env = {}
from rougail.tiramisu import ConvertDynOptionDescription from rougail.tiramisu import ConvertDynOptionDescription
ENV = SandboxedEnvironment(loader=DictLoader(dict_env), undefined=StrictUndefined)
ENV.filters = func
ENV.compile_templates('jinja_caches', zip=None)
option_3 = StrOption(name="varname", doc="No change", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "notempty", "standard"})) option_3 = StrOption(name="varname", doc="No change", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "notempty", "standard"}))
optiondescription_2 = OptionDescription(name="general", doc="general", children=[option_3], properties=frozenset({"standard"})) optiondescription_2 = OptionDescription(name="general", doc="general", children=[option_3], properties=frozenset({"standard"}))
option_5 = StrOption(name="vardyn", doc="No change", properties=frozenset({"standard"})) option_5 = StrOption(name="vardyn", doc="No change", properties=frozenset({"standard"}))

View file

@ -19,7 +19,54 @@ def _load_functions(path):
continue continue
func[function] = getattr(func_, function) func[function] = getattr(func_, function)
_load_functions('tests/dictionaries/../eosfunc/test.py') _load_functions('tests/dictionaries/../eosfunc/test.py')
from jinja2 import StrictUndefined, DictLoader
from jinja2.sandbox import SandboxedEnvironment
from rougail.annotator.variable import CONVERT_OPTION
from tiramisu.error import ValueWarning
def jinja_to_function(__internal_jinja, __internal_type, __internal_multi, **kwargs):
global ENV, CONVERT_OPTION
kw = {}
for key, value in kwargs.items():
if '.' in key:
c_kw = kw
path, var = key.rsplit('.', 1)
for subkey in path.split('.'):
c_kw = c_kw.setdefault(subkey, {})
c_kw[var] = value
else:
kw[key] = value
values = ENV.get_template(__internal_jinja).render(kw, **func).strip()
convert = CONVERT_OPTION[__internal_type].get('func', str)
if __internal_multi:
return [convert(val) for val in values.split()]
values = convert(values)
return values if values != '' and values != 'None' else None
def variable_to_property(prop, value):
return prop if value else None
def jinja_to_property(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return func['variable_to_property'](prop, value is not None)
def jinja_to_property_help(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return (prop, f'"{prop}" ({value})')
def valid_with_jinja(warnings_only=False, **kwargs):
global ValueWarning
value = func['jinja_to_function'](**kwargs)
if value:
if warnings_only:
raise ValueWarning(value)
else:
raise ValueError(value)
func['jinja_to_function'] = jinja_to_function
func['jinja_to_property'] = jinja_to_property
func['jinja_to_property_help'] = jinja_to_property_help
func['variable_to_property'] = variable_to_property
func['valid_with_jinja'] = valid_with_jinja
dict_env = {}
from rougail.tiramisu import ConvertDynOptionDescription from rougail.tiramisu import ConvertDynOptionDescription
ENV = SandboxedEnvironment(loader=DictLoader(dict_env), undefined=StrictUndefined)
ENV.filters = func
ENV.compile_templates('jinja_caches', zip=None)
option_4 = StrOption(name="varname", doc="No change", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "notempty", "standard"})) option_4 = StrOption(name="varname", doc="No change", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "notempty", "standard"}))
optiondescription_3 = OptionDescription(name="general", doc="general", children=[option_4], properties=frozenset({"standard"})) optiondescription_3 = OptionDescription(name="general", doc="general", children=[option_4], properties=frozenset({"standard"}))
option_6 = StrOption(name="vardyn", doc="No change", properties=frozenset({"standard"})) option_6 = StrOption(name="vardyn", doc="No change", properties=frozenset({"standard"}))

View file

@ -0,0 +1,23 @@
---
version: '1.1'
general:
varname:
type: string
description: No change
multi: true
default:
- val1
- val2
dyn:
type: dynamic
dynamic:
type: jinja
jinja: |
{% for val in rougail.general.varname %}
{{ loop.index }}
{% endfor %}
propertyerror: false
vardyn:
type: string
description: No change
default: val

View file

@ -0,0 +1,17 @@
{
"rougail.general.varname": {
"owner": "default",
"value": [
"val1",
"val2"
]
},
"rougail.dyn1.vardyn": {
"owner": "default",
"value": "val"
},
"rougail.dyn2.vardyn": {
"owner": "default",
"value": "val"
}
}

View file

@ -0,0 +1,8 @@
{
"rougail.general.varname": [
"val1",
"val2"
],
"rougail.dyn1.vardyn": "val",
"rougail.dyn2.vardyn": "val"
}

View file

@ -0,0 +1,17 @@
{
"rougail.general.varname": {
"owner": "default",
"value": [
"val1",
"val2"
]
},
"rougail.dyn1.vardyn": {
"owner": "default",
"value": "val"
},
"rougail.dyn2.vardyn": {
"owner": "default",
"value": "val"
}
}

View file

@ -0,0 +1,76 @@
from tiramisu import *
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
ALLOWED_LEADER_PROPERTIES.add("basic")
ALLOWED_LEADER_PROPERTIES.add("standard")
ALLOWED_LEADER_PROPERTIES.add("advanced")
from importlib.machinery import SourceFileLoader as _SourceFileLoader
from importlib.util import spec_from_loader as _spec_from_loader, module_from_spec as _module_from_spec
global func
func = {'calc_value': calc_value}
def _load_functions(path):
global _SourceFileLoader, _spec_from_loader, _module_from_spec, func
loader = _SourceFileLoader('func', path)
spec = _spec_from_loader(loader.name, loader)
func_ = _module_from_spec(spec)
loader.exec_module(func_)
for function in dir(func_):
if function.startswith('_'):
continue
func[function] = getattr(func_, function)
_load_functions('tests/dictionaries/../eosfunc/test.py')
from jinja2 import StrictUndefined, DictLoader
from jinja2.sandbox import SandboxedEnvironment
from rougail.annotator.variable import CONVERT_OPTION
from tiramisu.error import ValueWarning
def jinja_to_function(__internal_jinja, __internal_type, __internal_multi, **kwargs):
global ENV, CONVERT_OPTION
kw = {}
for key, value in kwargs.items():
if '.' in key:
c_kw = kw
path, var = key.rsplit('.', 1)
for subkey in path.split('.'):
c_kw = c_kw.setdefault(subkey, {})
c_kw[var] = value
else:
kw[key] = value
values = ENV.get_template(__internal_jinja).render(kw, **func).strip()
convert = CONVERT_OPTION[__internal_type].get('func', str)
if __internal_multi:
return [convert(val) for val in values.split()]
values = convert(values)
return values if values != '' and values != 'None' else None
def variable_to_property(prop, value):
return prop if value else None
def jinja_to_property(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return func['variable_to_property'](prop, value is not None)
def jinja_to_property_help(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return (prop, f'"{prop}" ({value})')
def valid_with_jinja(warnings_only=False, **kwargs):
global ValueWarning
value = func['jinja_to_function'](**kwargs)
if value:
if warnings_only:
raise ValueWarning(value)
else:
raise ValueError(value)
func['jinja_to_function'] = jinja_to_function
func['jinja_to_property'] = jinja_to_property
func['jinja_to_property_help'] = jinja_to_property_help
func['variable_to_property'] = variable_to_property
func['valid_with_jinja'] = valid_with_jinja
dict_env = {}
from rougail.tiramisu import ConvertDynOptionDescription
dict_env['dynamic_rougail.dyn'] = "{% for val in rougail.general.varname %}\n{{ loop.index }}\n{% endfor %}\n"
ENV = SandboxedEnvironment(loader=DictLoader(dict_env), undefined=StrictUndefined)
ENV.filters = func
ENV.compile_templates('jinja_caches', zip=None)
option_3 = StrOption(name="varname", doc="No change", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "notempty", "standard"}))
optiondescription_2 = OptionDescription(name="general", doc="general", children=[option_3], properties=frozenset({"standard"}))
option_5 = StrOption(name="vardyn", doc="No change", default="val", properties=frozenset({"mandatory", "standard"}))
optiondescription_4 = ConvertDynOptionDescription(name="dyn", doc="dyn", suffixes=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("dynamic_rougail.dyn"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(True), 'rougail.general.varname': ParamOption(option_3)})), children=[option_5], properties=frozenset({"standard"}))
optiondescription_1 = OptionDescription(name="rougail", doc="rougail", children=[optiondescription_2, optiondescription_4], properties=frozenset({"standard"}))
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])

View file

@ -0,0 +1,84 @@
from tiramisu import *
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
ALLOWED_LEADER_PROPERTIES.add("basic")
ALLOWED_LEADER_PROPERTIES.add("standard")
ALLOWED_LEADER_PROPERTIES.add("advanced")
from importlib.machinery import SourceFileLoader as _SourceFileLoader
from importlib.util import spec_from_loader as _spec_from_loader, module_from_spec as _module_from_spec
global func
func = {'calc_value': calc_value}
def _load_functions(path):
global _SourceFileLoader, _spec_from_loader, _module_from_spec, func
loader = _SourceFileLoader('func', path)
spec = _spec_from_loader(loader.name, loader)
func_ = _module_from_spec(spec)
loader.exec_module(func_)
for function in dir(func_):
if function.startswith('_'):
continue
func[function] = getattr(func_, function)
_load_functions('tests/dictionaries/../eosfunc/test.py')
from jinja2 import StrictUndefined, DictLoader
from jinja2.sandbox import SandboxedEnvironment
from rougail.annotator.variable import CONVERT_OPTION
from tiramisu.error import ValueWarning
def jinja_to_function(__internal_jinja, __internal_type, __internal_multi, **kwargs):
global ENV, CONVERT_OPTION
kw = {}
for key, value in kwargs.items():
if '.' in key:
c_kw = kw
path, var = key.rsplit('.', 1)
for subkey in path.split('.'):
c_kw = c_kw.setdefault(subkey, {})
c_kw[var] = value
else:
kw[key] = value
values = ENV.get_template(__internal_jinja).render(kw, **func).strip()
convert = CONVERT_OPTION[__internal_type].get('func', str)
if __internal_multi:
return [convert(val) for val in values.split()]
values = convert(values)
return values if values != '' and values != 'None' else None
def variable_to_property(prop, value):
return prop if value else None
def jinja_to_property(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return func['variable_to_property'](prop, value is not None)
def jinja_to_property_help(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return (prop, f'"{prop}" ({value})')
def valid_with_jinja(warnings_only=False, **kwargs):
global ValueWarning
value = func['jinja_to_function'](**kwargs)
if value:
if warnings_only:
raise ValueWarning(value)
else:
raise ValueError(value)
func['jinja_to_function'] = jinja_to_function
func['jinja_to_property'] = jinja_to_property
func['jinja_to_property_help'] = jinja_to_property_help
func['variable_to_property'] = variable_to_property
func['valid_with_jinja'] = valid_with_jinja
dict_env = {}
from rougail.tiramisu import ConvertDynOptionDescription
dict_env['dynamic_1.rougail.dyn'] = "{% for val in rougail.general.varname %}\n{{ loop.index }}\n{% endfor %}\n"
dict_env['dynamic_2.rougail.dyn'] = "{% for val in rougail.general.varname %}\n{{ loop.index }}\n{% endfor %}\n"
ENV = SandboxedEnvironment(loader=DictLoader(dict_env), undefined=StrictUndefined)
ENV.filters = func
ENV.compile_templates('jinja_caches', zip=None)
option_4 = StrOption(name="varname", doc="No change", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "notempty", "standard"}))
optiondescription_3 = OptionDescription(name="general", doc="general", children=[option_4], properties=frozenset({"standard"}))
option_6 = StrOption(name="vardyn", doc="No change", default="val", properties=frozenset({"mandatory", "standard"}))
optiondescription_5 = ConvertDynOptionDescription(name="dyn", doc="dyn", suffixes=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("dynamic_1.rougail.dyn"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(True), 'rougail.general.varname': ParamOption(option_4)})), children=[option_6], properties=frozenset({"standard"}))
optiondescription_2 = OptionDescription(name="rougail", doc="rougail", children=[optiondescription_3, optiondescription_5], properties=frozenset({"standard"}))
optiondescription_1 = OptionDescription(name="1", doc="1", children=[optiondescription_2], properties=frozenset({"standard"}))
option_10 = StrOption(name="varname", doc="No change", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "notempty", "standard"}))
optiondescription_9 = OptionDescription(name="general", doc="general", children=[option_10], properties=frozenset({"standard"}))
option_12 = StrOption(name="vardyn", doc="No change", default="val", properties=frozenset({"mandatory", "standard"}))
optiondescription_11 = ConvertDynOptionDescription(name="dyn", doc="dyn", suffixes=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("dynamic_2.rougail.dyn"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(True), 'rougail.general.varname': ParamOption(option_10)})), children=[option_12], properties=frozenset({"standard"}))
optiondescription_8 = OptionDescription(name="rougail", doc="rougail", children=[optiondescription_9, optiondescription_11], properties=frozenset({"standard"}))
optiondescription_7 = OptionDescription(name="2", doc="2", children=[optiondescription_8], properties=frozenset({"standard"}))
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1, optiondescription_7])

View file

@ -1,5 +1,5 @@
--- ---
version: '1.0' version: '1.1'
general: general:
varname: varname:
type: string type: string
@ -9,7 +9,10 @@ general:
- val2 - val2
dyn: dyn:
type: dynamic type: dynamic
variable: rougail.general.varname dynamic:
type: variable
variable: rougail.general.varname
propertyerror: false
vardyn: vardyn:
type: string type: string
default: val default: val

View file

@ -1,4 +1,4 @@
version: '1.0' version: '1.1'
general: general:
varname: varname:
type: string type: string
@ -9,7 +9,10 @@ general:
- val2 - val2
dyn: dyn:
type: dynamic type: dynamic
variable: rougail.general.varname dynamic:
type: variable
variable: rougail.general.varname
propertyerror: false
vardyn: vardyn:
type: string type: string
description: No change description: No change

View file

@ -19,7 +19,54 @@ def _load_functions(path):
continue continue
func[function] = getattr(func_, function) func[function] = getattr(func_, function)
_load_functions('tests/dictionaries/../eosfunc/test.py') _load_functions('tests/dictionaries/../eosfunc/test.py')
from jinja2 import StrictUndefined, DictLoader
from jinja2.sandbox import SandboxedEnvironment
from rougail.annotator.variable import CONVERT_OPTION
from tiramisu.error import ValueWarning
def jinja_to_function(__internal_jinja, __internal_type, __internal_multi, **kwargs):
global ENV, CONVERT_OPTION
kw = {}
for key, value in kwargs.items():
if '.' in key:
c_kw = kw
path, var = key.rsplit('.', 1)
for subkey in path.split('.'):
c_kw = c_kw.setdefault(subkey, {})
c_kw[var] = value
else:
kw[key] = value
values = ENV.get_template(__internal_jinja).render(kw, **func).strip()
convert = CONVERT_OPTION[__internal_type].get('func', str)
if __internal_multi:
return [convert(val) for val in values.split()]
values = convert(values)
return values if values != '' and values != 'None' else None
def variable_to_property(prop, value):
return prop if value else None
def jinja_to_property(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return func['variable_to_property'](prop, value is not None)
def jinja_to_property_help(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return (prop, f'"{prop}" ({value})')
def valid_with_jinja(warnings_only=False, **kwargs):
global ValueWarning
value = func['jinja_to_function'](**kwargs)
if value:
if warnings_only:
raise ValueWarning(value)
else:
raise ValueError(value)
func['jinja_to_function'] = jinja_to_function
func['jinja_to_property'] = jinja_to_property
func['jinja_to_property_help'] = jinja_to_property_help
func['variable_to_property'] = variable_to_property
func['valid_with_jinja'] = valid_with_jinja
dict_env = {}
from rougail.tiramisu import ConvertDynOptionDescription from rougail.tiramisu import ConvertDynOptionDescription
ENV = SandboxedEnvironment(loader=DictLoader(dict_env), undefined=StrictUndefined)
ENV.filters = func
ENV.compile_templates('jinja_caches', zip=None)
option_3 = StrOption(name="varname", doc="No change", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "notempty", "standard"})) option_3 = StrOption(name="varname", doc="No change", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "notempty", "standard"}))
optiondescription_2 = OptionDescription(name="general", doc="general", children=[option_3], properties=frozenset({"standard"})) optiondescription_2 = OptionDescription(name="general", doc="general", children=[option_3], properties=frozenset({"standard"}))
option_5 = StrOption(name="vardyn", doc="No change", properties=frozenset({"standard"})) option_5 = StrOption(name="vardyn", doc="No change", properties=frozenset({"standard"}))

View file

@ -19,7 +19,54 @@ def _load_functions(path):
continue continue
func[function] = getattr(func_, function) func[function] = getattr(func_, function)
_load_functions('tests/dictionaries/../eosfunc/test.py') _load_functions('tests/dictionaries/../eosfunc/test.py')
from jinja2 import StrictUndefined, DictLoader
from jinja2.sandbox import SandboxedEnvironment
from rougail.annotator.variable import CONVERT_OPTION
from tiramisu.error import ValueWarning
def jinja_to_function(__internal_jinja, __internal_type, __internal_multi, **kwargs):
global ENV, CONVERT_OPTION
kw = {}
for key, value in kwargs.items():
if '.' in key:
c_kw = kw
path, var = key.rsplit('.', 1)
for subkey in path.split('.'):
c_kw = c_kw.setdefault(subkey, {})
c_kw[var] = value
else:
kw[key] = value
values = ENV.get_template(__internal_jinja).render(kw, **func).strip()
convert = CONVERT_OPTION[__internal_type].get('func', str)
if __internal_multi:
return [convert(val) for val in values.split()]
values = convert(values)
return values if values != '' and values != 'None' else None
def variable_to_property(prop, value):
return prop if value else None
def jinja_to_property(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return func['variable_to_property'](prop, value is not None)
def jinja_to_property_help(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return (prop, f'"{prop}" ({value})')
def valid_with_jinja(warnings_only=False, **kwargs):
global ValueWarning
value = func['jinja_to_function'](**kwargs)
if value:
if warnings_only:
raise ValueWarning(value)
else:
raise ValueError(value)
func['jinja_to_function'] = jinja_to_function
func['jinja_to_property'] = jinja_to_property
func['jinja_to_property_help'] = jinja_to_property_help
func['variable_to_property'] = variable_to_property
func['valid_with_jinja'] = valid_with_jinja
dict_env = {}
from rougail.tiramisu import ConvertDynOptionDescription from rougail.tiramisu import ConvertDynOptionDescription
ENV = SandboxedEnvironment(loader=DictLoader(dict_env), undefined=StrictUndefined)
ENV.filters = func
ENV.compile_templates('jinja_caches', zip=None)
option_4 = StrOption(name="varname", doc="No change", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "notempty", "standard"})) option_4 = StrOption(name="varname", doc="No change", multi=True, default=["val1", "val2"], default_multi="val1", properties=frozenset({"mandatory", "notempty", "standard"}))
optiondescription_3 = OptionDescription(name="general", doc="general", children=[option_4], properties=frozenset({"standard"})) optiondescription_3 = OptionDescription(name="general", doc="general", children=[option_4], properties=frozenset({"standard"}))
option_6 = StrOption(name="vardyn", doc="No change", properties=frozenset({"standard"})) option_6 = StrOption(name="vardyn", doc="No change", properties=frozenset({"standard"}))

View file

@ -1,5 +1,5 @@
--- ---
version: '1.0' version: '1.1'
general: general:
varname: varname:
type: number type: number
@ -10,7 +10,10 @@ general:
- 2 - 2
dyn: dyn:
type: dynamic type: dynamic
variable: rougail.general.varname dynamic:
type: variable
variable: rougail.general.varname
propertyerror: false
vardyn: vardyn:
type: string type: string
description: No change description: No change

View file

@ -1,4 +1,5 @@
version: '1.0' ---
version: '1.1'
varname: varname:
multi: true multi: true
default: default:
@ -6,7 +7,10 @@ varname:
- val2 - val2
my_dyn_family_: my_dyn_family_:
type: dynamic type: dynamic
variable: rougail.varname dynamic:
type: variable
variable: rougail.varname
propertyerror: false
description: 'Describe ' description: 'Describe '
my_dyn_var_: my_dyn_var_:
type: string type: string

View file

@ -1,5 +1,5 @@
--- ---
version: '1.0' version: '1.1'
varname: varname:
multi: true multi: true
default: default:
@ -7,7 +7,10 @@ varname:
- val2 - val2
my_dyn_family_: my_dyn_family_:
type: dynamic type: dynamic
variable: rougail.varname dynamic:
type: variable
variable: rougail.varname
propertyerror: false
description: 'Describe ' description: 'Describe '
my_dyn_var: my_dyn_var:
type: string type: string

View file

@ -1,7 +1,11 @@
version: '1.0' ---
version: '1.1'
ejabberd: ejabberd:
type: dynamic type: dynamic
variable: rougail.general.varname dynamic:
type: variable
variable: rougail.general.varname
propertyerror: false
mode: mode:
type: string type: string
mandatory: false mandatory: false

View file

@ -19,7 +19,54 @@ def _load_functions(path):
continue continue
func[function] = getattr(func_, function) func[function] = getattr(func_, function)
_load_functions('tests/dictionaries/../eosfunc/test.py') _load_functions('tests/dictionaries/../eosfunc/test.py')
from jinja2 import StrictUndefined, DictLoader
from jinja2.sandbox import SandboxedEnvironment
from rougail.annotator.variable import CONVERT_OPTION
from tiramisu.error import ValueWarning
def jinja_to_function(__internal_jinja, __internal_type, __internal_multi, **kwargs):
global ENV, CONVERT_OPTION
kw = {}
for key, value in kwargs.items():
if '.' in key:
c_kw = kw
path, var = key.rsplit('.', 1)
for subkey in path.split('.'):
c_kw = c_kw.setdefault(subkey, {})
c_kw[var] = value
else:
kw[key] = value
values = ENV.get_template(__internal_jinja).render(kw, **func).strip()
convert = CONVERT_OPTION[__internal_type].get('func', str)
if __internal_multi:
return [convert(val) for val in values.split()]
values = convert(values)
return values if values != '' and values != 'None' else None
def variable_to_property(prop, value):
return prop if value else None
def jinja_to_property(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return func['variable_to_property'](prop, value is not None)
def jinja_to_property_help(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return (prop, f'"{prop}" ({value})')
def valid_with_jinja(warnings_only=False, **kwargs):
global ValueWarning
value = func['jinja_to_function'](**kwargs)
if value:
if warnings_only:
raise ValueWarning(value)
else:
raise ValueError(value)
func['jinja_to_function'] = jinja_to_function
func['jinja_to_property'] = jinja_to_property
func['jinja_to_property_help'] = jinja_to_property_help
func['variable_to_property'] = variable_to_property
func['valid_with_jinja'] = valid_with_jinja
dict_env = {}
from rougail.tiramisu import ConvertDynOptionDescription from rougail.tiramisu import ConvertDynOptionDescription
ENV = SandboxedEnvironment(loader=DictLoader(dict_env), undefined=StrictUndefined)
ENV.filters = func
ENV.compile_templates('jinja_caches', zip=None)
option_3 = StrOption(name="varname", doc="No change", multi=True, default=["a"], default_multi="a", properties=frozenset({"mandatory", "notempty", "standard"})) option_3 = StrOption(name="varname", doc="No change", multi=True, default=["a"], default_multi="a", properties=frozenset({"mandatory", "notempty", "standard"}))
optiondescription_2 = OptionDescription(name="general", doc="général", children=[option_3], properties=frozenset({"standard"})) optiondescription_2 = OptionDescription(name="general", doc="général", children=[option_3], properties=frozenset({"standard"}))
optiondescription_1 = OptionDescription(name="rougail", doc="rougail", children=[optiondescription_2], properties=frozenset({"standard"})) optiondescription_1 = OptionDescription(name="rougail", doc="rougail", children=[optiondescription_2], properties=frozenset({"standard"}))

View file

@ -19,7 +19,54 @@ def _load_functions(path):
continue continue
func[function] = getattr(func_, function) func[function] = getattr(func_, function)
_load_functions('tests/dictionaries/../eosfunc/test.py') _load_functions('tests/dictionaries/../eosfunc/test.py')
from jinja2 import StrictUndefined, DictLoader
from jinja2.sandbox import SandboxedEnvironment
from rougail.annotator.variable import CONVERT_OPTION
from tiramisu.error import ValueWarning
def jinja_to_function(__internal_jinja, __internal_type, __internal_multi, **kwargs):
global ENV, CONVERT_OPTION
kw = {}
for key, value in kwargs.items():
if '.' in key:
c_kw = kw
path, var = key.rsplit('.', 1)
for subkey in path.split('.'):
c_kw = c_kw.setdefault(subkey, {})
c_kw[var] = value
else:
kw[key] = value
values = ENV.get_template(__internal_jinja).render(kw, **func).strip()
convert = CONVERT_OPTION[__internal_type].get('func', str)
if __internal_multi:
return [convert(val) for val in values.split()]
values = convert(values)
return values if values != '' and values != 'None' else None
def variable_to_property(prop, value):
return prop if value else None
def jinja_to_property(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return func['variable_to_property'](prop, value is not None)
def jinja_to_property_help(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return (prop, f'"{prop}" ({value})')
def valid_with_jinja(warnings_only=False, **kwargs):
global ValueWarning
value = func['jinja_to_function'](**kwargs)
if value:
if warnings_only:
raise ValueWarning(value)
else:
raise ValueError(value)
func['jinja_to_function'] = jinja_to_function
func['jinja_to_property'] = jinja_to_property
func['jinja_to_property_help'] = jinja_to_property_help
func['variable_to_property'] = variable_to_property
func['valid_with_jinja'] = valid_with_jinja
dict_env = {}
from rougail.tiramisu import ConvertDynOptionDescription from rougail.tiramisu import ConvertDynOptionDescription
ENV = SandboxedEnvironment(loader=DictLoader(dict_env), undefined=StrictUndefined)
ENV.filters = func
ENV.compile_templates('jinja_caches', zip=None)
option_4 = StrOption(name="varname", doc="No change", multi=True, default=["a"], default_multi="a", properties=frozenset({"mandatory", "notempty", "standard"})) option_4 = StrOption(name="varname", doc="No change", multi=True, default=["a"], default_multi="a", properties=frozenset({"mandatory", "notempty", "standard"}))
optiondescription_3 = OptionDescription(name="general", doc="général", children=[option_4], properties=frozenset({"standard"})) optiondescription_3 = OptionDescription(name="general", doc="général", children=[option_4], properties=frozenset({"standard"}))
optiondescription_2 = OptionDescription(name="rougail", doc="rougail", children=[optiondescription_3], properties=frozenset({"standard"})) optiondescription_2 = OptionDescription(name="rougail", doc="rougail", children=[optiondescription_3], properties=frozenset({"standard"}))

View file

@ -1,3 +1,5 @@
---
version: '1.1'
general: general:
description: général description: général
varname: varname:
@ -5,11 +7,13 @@ general:
description: No change description: No change
multi: true multi: true
default: default:
- a - a
ejabberd: ejabberd:
type: dynamic type: dynamic
variable: extra.general.varname dynamic:
type: variable
variable: extra.general.varname
propertyerror: false
mode: mode:
type: string type: string
mandatory: false mandatory: false
version: '1.0'

View file

@ -19,7 +19,54 @@ def _load_functions(path):
continue continue
func[function] = getattr(func_, function) func[function] = getattr(func_, function)
_load_functions('tests/dictionaries/../eosfunc/test.py') _load_functions('tests/dictionaries/../eosfunc/test.py')
from jinja2 import StrictUndefined, DictLoader
from jinja2.sandbox import SandboxedEnvironment
from rougail.annotator.variable import CONVERT_OPTION
from tiramisu.error import ValueWarning
def jinja_to_function(__internal_jinja, __internal_type, __internal_multi, **kwargs):
global ENV, CONVERT_OPTION
kw = {}
for key, value in kwargs.items():
if '.' in key:
c_kw = kw
path, var = key.rsplit('.', 1)
for subkey in path.split('.'):
c_kw = c_kw.setdefault(subkey, {})
c_kw[var] = value
else:
kw[key] = value
values = ENV.get_template(__internal_jinja).render(kw, **func).strip()
convert = CONVERT_OPTION[__internal_type].get('func', str)
if __internal_multi:
return [convert(val) for val in values.split()]
values = convert(values)
return values if values != '' and values != 'None' else None
def variable_to_property(prop, value):
return prop if value else None
def jinja_to_property(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return func['variable_to_property'](prop, value is not None)
def jinja_to_property_help(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return (prop, f'"{prop}" ({value})')
def valid_with_jinja(warnings_only=False, **kwargs):
global ValueWarning
value = func['jinja_to_function'](**kwargs)
if value:
if warnings_only:
raise ValueWarning(value)
else:
raise ValueError(value)
func['jinja_to_function'] = jinja_to_function
func['jinja_to_property'] = jinja_to_property
func['jinja_to_property_help'] = jinja_to_property_help
func['variable_to_property'] = variable_to_property
func['valid_with_jinja'] = valid_with_jinja
dict_env = {}
from rougail.tiramisu import ConvertDynOptionDescription from rougail.tiramisu import ConvertDynOptionDescription
ENV = SandboxedEnvironment(loader=DictLoader(dict_env), undefined=StrictUndefined)
ENV.filters = func
ENV.compile_templates('jinja_caches', zip=None)
option_3 = StrOption(name="varname", doc="No change", multi=True, default=["a"], default_multi="a", properties=frozenset({"mandatory", "notempty", "standard"})) option_3 = StrOption(name="varname", doc="No change", multi=True, default=["a"], default_multi="a", properties=frozenset({"mandatory", "notempty", "standard"}))
optiondescription_2 = OptionDescription(name="general", doc="général", children=[option_3], properties=frozenset({"standard"})) optiondescription_2 = OptionDescription(name="general", doc="général", children=[option_3], properties=frozenset({"standard"}))
optiondescription_1 = OptionDescription(name="rougail", doc="rougail", children=[optiondescription_2], properties=frozenset({"standard"})) optiondescription_1 = OptionDescription(name="rougail", doc="rougail", children=[optiondescription_2], properties=frozenset({"standard"}))

View file

@ -19,7 +19,54 @@ def _load_functions(path):
continue continue
func[function] = getattr(func_, function) func[function] = getattr(func_, function)
_load_functions('tests/dictionaries/../eosfunc/test.py') _load_functions('tests/dictionaries/../eosfunc/test.py')
from jinja2 import StrictUndefined, DictLoader
from jinja2.sandbox import SandboxedEnvironment
from rougail.annotator.variable import CONVERT_OPTION
from tiramisu.error import ValueWarning
def jinja_to_function(__internal_jinja, __internal_type, __internal_multi, **kwargs):
global ENV, CONVERT_OPTION
kw = {}
for key, value in kwargs.items():
if '.' in key:
c_kw = kw
path, var = key.rsplit('.', 1)
for subkey in path.split('.'):
c_kw = c_kw.setdefault(subkey, {})
c_kw[var] = value
else:
kw[key] = value
values = ENV.get_template(__internal_jinja).render(kw, **func).strip()
convert = CONVERT_OPTION[__internal_type].get('func', str)
if __internal_multi:
return [convert(val) for val in values.split()]
values = convert(values)
return values if values != '' and values != 'None' else None
def variable_to_property(prop, value):
return prop if value else None
def jinja_to_property(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return func['variable_to_property'](prop, value is not None)
def jinja_to_property_help(prop, **kwargs):
value = func['jinja_to_function'](**kwargs)
return (prop, f'"{prop}" ({value})')
def valid_with_jinja(warnings_only=False, **kwargs):
global ValueWarning
value = func['jinja_to_function'](**kwargs)
if value:
if warnings_only:
raise ValueWarning(value)
else:
raise ValueError(value)
func['jinja_to_function'] = jinja_to_function
func['jinja_to_property'] = jinja_to_property
func['jinja_to_property_help'] = jinja_to_property_help
func['variable_to_property'] = variable_to_property
func['valid_with_jinja'] = valid_with_jinja
dict_env = {}
from rougail.tiramisu import ConvertDynOptionDescription from rougail.tiramisu import ConvertDynOptionDescription
ENV = SandboxedEnvironment(loader=DictLoader(dict_env), undefined=StrictUndefined)
ENV.filters = func
ENV.compile_templates('jinja_caches', zip=None)
option_4 = StrOption(name="varname", doc="No change", multi=True, default=["a"], default_multi="a", properties=frozenset({"mandatory", "notempty", "standard"})) option_4 = StrOption(name="varname", doc="No change", multi=True, default=["a"], default_multi="a", properties=frozenset({"mandatory", "notempty", "standard"}))
optiondescription_3 = OptionDescription(name="general", doc="général", children=[option_4], properties=frozenset({"standard"})) optiondescription_3 = OptionDescription(name="general", doc="général", children=[option_4], properties=frozenset({"standard"}))
optiondescription_2 = OptionDescription(name="rougail", doc="rougail", children=[optiondescription_3], properties=frozenset({"standard"})) optiondescription_2 = OptionDescription(name="rougail", doc="rougail", children=[optiondescription_3], properties=frozenset({"standard"}))

View file

@ -1,2 +1,2 @@
tata.service: {} tata.service: {}
version: '1.0' version: '1.1'

View file

@ -7,4 +7,4 @@ general:
description: No change description: No change
auto_save: true auto_save: true
default: non default: non
version: '1.0' version: '1.1'

View file

@ -8,4 +8,4 @@ general:
auto_save: true auto_save: true
mode: advanced mode: advanced
default: non default: non
version: '1.0' version: '1.1'

View file

@ -5,4 +5,4 @@ general:
description: No change description: No change
hidden: true hidden: true
default: non default: non
version: '1.0' version: '1.1'

View file

@ -7,4 +7,4 @@ general:
default: non default: non
without_type: without_type:
default: non default: non
version: '1.0' version: '1.1'

View file

@ -5,4 +5,4 @@ general:
description: No change description: No change
hidden: true hidden: true
default: non default: non
version: '1.0' version: '1.1'

View file

@ -10,4 +10,4 @@ general:
type: string type: string
description: No change description: No change
default: non default: non
version: '1.0' version: '1.1'

View file

@ -10,4 +10,4 @@ general:
type: string type: string
description: No change description: No change
default: non default: non
version: '1.0' version: '1.1'

View file

@ -10,4 +10,4 @@ general:
type: string type: string
description: No change description: No change
default: non default: non
version: '1.0' version: '1.1'

View file

@ -19,4 +19,4 @@ general:
default: default:
type: jinja type: jinja
jinja: '{% if mode_conteneur_actif1 == "non" %}oui{% else %}non{% endif %}' jinja: '{% if mode_conteneur_actif1 == "non" %}oui{% else %}non{% endif %}'
version: '1.0' version: '1.1'

View file

@ -13,4 +13,4 @@ general:
default: default:
type: jinja type: jinja
jinja: '{% if not rougail.general.bool %}True,False{% else %}False{% endif %}' jinja: '{% if not rougail.general.bool %}True,False{% else %}False{% endif %}'
version: '1.0' version: '1.1'

View file

@ -12,4 +12,4 @@ int2:
default: default:
type: jinja type: jinja
jinja: '{% if not bool %}3{% else %}4{% endif %}' jinja: '{% if not bool %}3{% else %}4{% endif %}'
version: '1.0' version: '1.1'

View file

@ -12,4 +12,4 @@ int2:
default: default:
type: jinja type: jinja
jinja: '{%set bool1 = bool %}{% if not bool1 %}3{% else %}4{% endif %}' jinja: '{%set bool1 = bool %}{% if not bool1 %}3{% else %}4{% endif %}'
version: '1.0' version: '1.1'

View file

@ -10,4 +10,4 @@ general:
type: string type: string
description: No change description: No change
default: non default: non
version: '1.0' version: '1.1'

View file

@ -1,4 +1,4 @@
server_name: server_name:
type: domainname type: domainname
default: example.net default: example.net
version: '1.0' version: '1.1'

View file

@ -3,4 +3,4 @@ test.service:
certificate: certificate:
authority: authority authority: authority
owner: example owner: example
version: '1.0' version: '1.1'

View file

@ -4,4 +4,4 @@ owner:
server_name: server_name:
type: domainname type: domainname
default: example.net default: example.net
version: '1.0' version: '1.1'

View file

@ -5,4 +5,4 @@ test.service:
owner: owner:
name: rougail.owner name: rougail.owner
type: variable type: variable
version: '1.0' version: '1.1'

View file

@ -3,4 +3,4 @@ general:
type: domainname type: domainname
description: Description description: Description
default: my.domain.name default: my.domain.name
version: '1.0' version: '1.1'

View file

@ -3,4 +3,4 @@ general:
type: string type: string
description: Description description: Description
default: non default: non
version: '1.0' version: '1.1'

View file

@ -3,4 +3,4 @@ test.service:
/etc/file: {} /etc/file: {}
/etc/file2: /etc/file2:
engine: jinja engine: jinja
version: '1.0' version: '1.1'

View file

@ -3,4 +3,4 @@ general:
type: string type: string
description: Description description: Description
default: non default: non
version: '1.0' version: '1.1'

View file

@ -5,4 +5,4 @@ test.service:
engine: jinja engine: jinja
/etc/file3: /etc/file3:
disabled: true disabled: true
version: '1.0' version: '1.1'

View file

@ -3,4 +3,4 @@ general:
type: string type: string
description: Description description: Description
default: non default: non
version: '1.0' version: '1.1'

View file

@ -3,4 +3,4 @@ test.service:
/etc/file: {} /etc/file: {}
/etc/file2: /etc/file2:
engine: jinja engine: jinja
version: '1.0' version: '1.1'

View file

@ -3,4 +3,4 @@ general:
type: string type: string
description: Description description: Description
default: non default: non
version: '1.0' version: '1.1'

View file

@ -5,4 +5,4 @@ test.service:
engine: jinja engine: jinja
/etc/dir/incfile: /etc/dir/incfile:
included: content included: content
version: '1.0' version: '1.1'

View file

@ -3,4 +3,4 @@ general:
type: string type: string
description: Description description: Description
default: non default: non
version: '1.0' version: '1.1'

View file

@ -5,4 +5,4 @@ test.service:
engine: jinja engine: jinja
/etc/dir/incfile: /etc/dir/incfile:
included: name included: name
version: '1.0' version: '1.1'

View file

@ -2,4 +2,4 @@ test.service:
files: files:
/etc/file: /etc/file:
mode: 755 mode: 755
version: '1.0' version: '1.1'

View file

@ -2,4 +2,4 @@ test.service:
files: files:
/etc/file: /etc/file:
mode: 1755 mode: 1755
version: '1.0' version: '1.1'

View file

@ -3,4 +3,4 @@ general:
type: string type: string
description: Description description: Description
default: non default: non
version: '1.0' version: '1.1'

View file

@ -7,4 +7,4 @@ test.service:
owner: nobody owner: nobody
group: nobody group: nobody
engine: jinja engine: jinja
version: '1.0' version: '1.1'

View file

@ -9,4 +9,4 @@ general:
group: group:
type: unix_user type: unix_user
default: nobody default: nobody
version: '1.0' version: '1.1'

View file

@ -15,4 +15,4 @@ test.service:
name: rougail.general.group name: rougail.general.group
type: variable type: variable
engine: jinja engine: jinja
version: '1.0' version: '1.1'

View file

@ -3,4 +3,4 @@ general:
type: string type: string
description: Description description: Description
default: non default: non
version: '1.0' version: '1.1'

View file

@ -3,4 +3,4 @@ test.service:
/etc/file: {} /etc/file: {}
/etc/file2: /etc/file2:
engine: jinja engine: jinja
version: '1.0' version: '1.1'

View file

@ -3,4 +3,4 @@ general:
type: string type: string
description: Description description: Description
default: non default: non
version: '1.0' version: '1.1'

View file

@ -3,4 +3,4 @@ test.service:
/etc/file: {} /etc/file: {}
/etc/file2: /etc/file2:
engine: jinja engine: jinja
version: '1.0' version: '1.1'

View file

@ -3,4 +3,4 @@ general:
type: string type: string
description: Description description: Description
default: non default: non
version: '1.0' version: '1.1'

View file

@ -3,4 +3,4 @@ test.service:
/etc/file: {} /etc/file: {}
/etc/file2: /etc/file2:
engine: jinja engine: jinja
version: '1.0' version: '1.1'

View file

@ -3,4 +3,4 @@ general:
type: string type: string
description: Description description: Description
default: non default: non
version: '1.0' version: '1.1'

View file

@ -3,4 +3,4 @@ test.service:
/etc/systemd-makefs@dev-disk-by\x2dpartlabel: {} /etc/systemd-makefs@dev-disk-by\x2dpartlabel: {}
/etc/systemd-makefs@dev-disk-by\x2dpartlabel2: /etc/systemd-makefs@dev-disk-by\x2dpartlabel2:
engine: jinja engine: jinja
version: '1.0' version: '1.1'

View file

@ -7,4 +7,4 @@ general:
type: string type: string
description: Description description: Description
default: non default: non
version: '1.0' version: '1.1'

View file

@ -4,4 +4,4 @@ test.service:
source: source:
name: rougail.general.source_var name: rougail.general.source_var
type: variable type: variable
version: '1.0' version: '1.1'

View file

@ -9,4 +9,4 @@ general:
multi: true multi: true
default: default:
- 0.527 - 0.527
version: '1.0' version: '1.1'

View file

@ -9,4 +9,4 @@ general:
description: Redefine description description: Redefine description
help: message with " help: message with "
mandatory: false mandatory: false
version: '1.0' version: '1.1'

View file

@ -6,4 +6,4 @@ general:
multi: true multi: true
default: default:
- non - non
version: '1.0' version: '1.1'

View file

@ -7,4 +7,4 @@ general:
unique: false unique: false
default: default:
- non - non
version: '1.0' version: '1.1'

View file

@ -7,4 +7,4 @@ general:
unique: true unique: true
default: default:
- non - non
version: '1.0' version: '1.1'

Some files were not shown because too many files have changed in this diff Show more