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
---
version: '1.0'
version: '1.1'
my_variable:
validators:
- 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
---
version: '1.0'
version: '1.1'
my_variable:
validators:
- type: jinja
@ -161,7 +161,7 @@ Verification with parameters
.. code-block:: yaml
---
version: '1.0'
version: '1.1'
my_hidden_variable:
disabled: true
my_variable:
@ -189,7 +189,7 @@ An example with a suffix type parameter:
.. code-block:: yaml
---
version: '1.0'
version: '1.1'
varname:
multi: true
default:
@ -221,7 +221,7 @@ An example with an index type parameter:
.. code-block:: yaml
---
version: '1.0'
version: '1.1'
family:
type: leadership
leader:
@ -249,7 +249,7 @@ In a first dictionary, let's declare our variable and its verification function:
.. code-block:: yaml
---
version: '1.0'
version: '1.1'
my_variable:
validators:
- type: jinja
@ -263,7 +263,7 @@ In a second dictionary it is possible to redefine the calculation:
.. code-block:: yaml
---
version: '1.0'
version: '1.1'
my_variable:
redefine: true
validators:
@ -280,7 +280,7 @@ Here is a third dictionary in which we remove the validation:
.. code-block:: yaml
---
version: '1.0'
version: '1.1'
my_variable:
redefine: true
validators:

View file

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

View file

@ -92,20 +92,13 @@ Parameters
Dynamically created family
-----------------------------
To create a family dynamically, you must create a fictitious family linked to a variable.
The family name and description will actually be the prefix of the new name / description.
The suffix will come from the value of the bound variable.
The name of the families and variables it contains will be preserved, however, the description will be the prefix of the real description.
To create a family dynamically, you must create a fictitious family linked to a calculation.
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 calculation.
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:
- 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
Leader or follower variable
-----------------------------
A leader family has a typical attribute of “leadership”. The type is required.
@ -150,12 +143,12 @@ If a leader variable is hidden or disabled, the follower variables will be hidde
Examples
----------
Simple family
Simple family:
.. code-block:: yaml
---
version: '1.0'
version: '1.1'
my_family:
type: family
description: This is a great family
@ -168,7 +161,7 @@ Dynamically created family
.. code-block:: yaml
---
version: '1.0'
version: '1.1'
varname:
multi: true
default:
@ -176,18 +169,48 @@ Dynamically created family
- val2
my_dyn_family_:
type: dynamic
variable: rougail.varname
description: 'Describe '
dynamic:
type: variable
variable: rougail.varname
description: 'Describe'
my_dyn_var:
type: string
description: 'Variable description for '
description: 'Variable description'
This will dynamically create two families:
- "rougail.my_dyn_family_val1" with the description "Describe val1"
- "rougail.my_dyn_family_val2" with the description "Describe val2"
- "rougail.my_dyn_family_val1"
- "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".
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
-------------------------------
@ -200,7 +223,7 @@ Here is an example of defining a leading variable and two following variables:
.. code-block:: yaml
---
version: '1.0'
version: '1.1'
family:
type: leadership
leader:
@ -217,7 +240,6 @@ To add a new follower variable, in a new dictionary, simply define one or more n
.. code-block:: yaml
---
version: '1.0'
version: '1.1'
family:
follower3:

View file

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

View file

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

View file

@ -26,7 +26,7 @@ Here is a first :file:`dict/00-base.yml` dictionary:
.. code-block:: yaml
---
version: '1.0'
version: '1.1'
my_variable:
default: my_value
@ -71,7 +71,7 @@ Then let's create an extra :term:`dictionary` :file:`extras/00-base.yml`:
.. code-block:: yaml
:caption: the :file:`extras/00-base.yml` file content
---
version: '1.0'
version: '1.1'
my_variable_extra:
default: my_value_extra
@ -103,7 +103,7 @@ We create the complementary :term:`dictionary` named :file:`dict/01-function.yml
.. code-block:: yaml
---
version: '1.0'
version: '1.1'
my_variable_jinja:
type: "string"
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.
Create your own type
----------------------
@ -180,7 +179,7 @@ Here is a :file:`dict/00-base.yml` dictionary:
.. code-block:: yaml
---
version: '1.0'
version: '1.1'
var:
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')
[...]
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:
---
version: '1.0'
version: '1.1'
proxy:
description: Proxy configuration in order to have access to the internet
type: family
@ -69,7 +69,7 @@ Let's create a second :file:`dict/01-proxy_mode.yml` file.
:linenos:
---
version: '1.0'
version: '1.1'
proxy:
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
---
version: '1.0'
version: '1.1'
proxy:
manual:
description: Manual proxy configuration
@ -170,7 +170,7 @@ Let's create the :file:`dict/03-proxy_manual_http_proxy.yml` dictionary:
:linenos:
---
version: '1.0'
version: '1.1'
proxy:
manual:
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
:caption: the :file:`dict/04-proxy_manual_http_use_for_https.yml` file
version: '1.0'
version: '1.1'
proxy:
manual:
use_for_https:
@ -216,7 +216,7 @@ Let's create the :file:`dict/05-proxy_manual_ssl_proxy.yml` file:
:linenos:
---
version: '1.0'
version: '1.1'
proxy:
manual:
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
---
version: '1.0'
version: '1.1'
proxy:
manual:
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
---
version: '1.0'
version: '1.1'
proxy:
auto:
type: web_address
@ -419,7 +419,7 @@ Let's create the :file:`dict/07-proxy_no_proxy.yml` file:
:linenos:
---
version: '1.0'
version: '1.1'
proxy:
no_proxy:
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:
---
version: '1.0'
version: '1.1'
proxy:
prompt_authentication:
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:
---
version: '1.0'
version: '1.1'
proxy:
proxy_dns_socks5:
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:
---
version: '1.0'
version: '1.1'
proxy:
dns_over_https:
description: DNS over HTTPS
@ -651,7 +651,7 @@ Here is the complete content of the FoxyProxy type proxy configuration
:linenos:
---
version: '1.0'
version: '1.1'
proxy:
_type: leadership
title:
@ -813,7 +813,7 @@ If you prefer this option, here is a second extra dictionary :file:`foxyproxy/01
:linenos:
---
version: '1.0'
version: '1.1'
proxy:
username:
redefine: true

View file

@ -70,7 +70,6 @@ class Annotator(Walk):
self.remove_empty_families()
self.family_names()
self.change_modes()
self.dynamic_families()
self.convert_help()
def remove_empty_families(self) -> None:
@ -299,33 +298,6 @@ class Annotator(Walk):
if not 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):
"""Convert variable help"""
for family in self.get_families():

View file

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

View file

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

View file

@ -33,7 +33,7 @@ from json import dumps
from os.path import isfile, basename
from .i18n import _
from .error import DictConsistencyError
from .error import DictConsistencyError, VariableNotFoundError
from .utils import normalize_family
from .object_model import Calculation, CONVERT_OPTION
@ -571,24 +571,23 @@ class Family(Common):
keys: list,
) -> None:
if self.elt.type == "dynamic":
dyn = self.tiramisu.reflector_objects[self.elt.variable.path].get(
self.calls, self.elt.path
)
keys[
"suffixes"
] = f"Calculation(func['calc_value'], Params((ParamOption({dyn}, notraisepropertyerror=True))))"
keys["suffixes"] = self.calculation_value(self.elt.dynamic)
children = []
for path in self.objectspace.parents[self.elt.path]:
children.append(self.objectspace.paths[path])
keys["children"] = (
"["
+ ", ".join(
[
self.tiramisu.reflector_objects[child.path].get(
self.calls, self.elt.path
)
for child in children
]
try:
keys["children"] = (
"["
+ ", ".join(
[
self.tiramisu.reflector_objects[child.path].get(
self.calls, self.elt.path
)
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 os.path import join, isfile, isdir, basename
from os import listdir, makedirs
try:
from lxml.etree import parse, XMLParser, XMLSyntaxError # pylint: disable=E0611
from lxml.etree import Element, SubElement, tostring
@ -45,16 +46,7 @@ from .config import RougailConfig
from .object_model import CONVERT_OPTION
VERSIONS = ["0.10", "1.0"]
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
VERSIONS = ["0.10", "1.0", "1.1"]
def get_function_name(version):
@ -70,17 +62,13 @@ class NoAliasDumper(SafeDumper):
return True
class upgrade_010_to_100:
class upgrade_010_to_10:
def __init__(
self,
dico: dict,
namespace: str,
xmlsrc: str,
) -> None:
if FIXME_PRINT_FILE:
from pprint import pprint
pprint(dico)
self.xmlsrc = xmlsrc
self.paths = {"family": {}, "variable": {}}
self.lists = {
@ -94,10 +82,6 @@ class upgrade_010_to_100:
self.parse_variables_with_path()
self.parse_services(dico)
self.parse_constraints(dico)
if FIXME_PRINT_FILE:
print("==")
pprint(self.variables)
pprint(self.services)
def parse_variables(
self,
@ -159,13 +143,14 @@ class upgrade_010_to_100:
new_families[name] = variable
self.flatten_paths["variable"][name] = sub_path
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
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"]:
if prop not in variable:
variable[prop] = False
@ -334,27 +319,19 @@ class upgrade_010_to_100:
condition_value = True
else:
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"]:
typ = target.get("type", "variable")
if typ == "variable":
variable_path = self.get_variable_path(target["text"])
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
variable = self.paths["variable"][variable_path]
variable[prop] = condition_value
elif typ == "family":
family_path = self.get_family_path(target["text"])
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
family = self.paths["family"][family_path]
family[prop] = condition_value
@ -386,10 +363,6 @@ class upgrade_010_to_100:
for target in check["target"]:
variable_path = self.get_variable_path(target["text"])
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
variable = self.paths["variable"][variable_path]
if "validators" in variable and variable["validators"] is None:
@ -411,10 +384,6 @@ class upgrade_010_to_100:
params = []
variable_path = self.get_variable_path(target["text"])
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
variable = self.paths["variable"][variable_path]
if fill.get("type") == "jinja":
@ -428,6 +397,7 @@ class upgrade_010_to_100:
def params_condition_to_jinja(
self,
prop: str,
path: str,
params: List[dict],
if_in: bool,
@ -444,9 +414,9 @@ class upgrade_010_to_100:
if new_param:
new_params |= new_param
if if_in:
jinja += " %}true{% else %}false{% endif %}"
jinja += " %}" + prop + "{% endif %}"
else:
jinja += " %}false{% else %}true{% endif %}"
jinja += " %}{% else %}" + prop + "{% endif %}"
ret = {
"type": "jinja",
"jinja": jinja,
@ -459,11 +429,9 @@ class upgrade_010_to_100:
self,
param: dict,
) -> Any:
# <!ATTLIST type (string|number|nil|space|boolean|variable|function|information|suffix|index) "string">
typ = param.get("type", "string")
if typ == "string":
value = param["text"]
# value = dumps(value, ensure_ascii=False)
elif typ == "number":
value = int(param["text"])
elif typ == "nil":
@ -551,7 +519,6 @@ class upgrade_010_to_100:
new_param, value = self.get_jinja_param_and_value(param)
if new_param:
params |= new_param
# if param.get('type') != 'variable' or value is not None:
if "name" in param:
values.append(f'{param["name"]}={value}')
else:
@ -577,8 +544,6 @@ class upgrade_010_to_100:
):
path = self.flatten_paths["variable"][path]
if path not in self.paths["variable"]:
if FIXME_PRINT_UNKNOWN_VAR:
print("pffff impossible de trouver la variable", path)
return
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"]:
path = self.flatten_paths["family"][path]
if path not in self.paths["family"]:
if FIXME_PRINT_UNKNOWN_VAR:
print("pffff impossible de trouver la famille", path)
return
return path
@ -615,21 +578,22 @@ class RougailUpgrade:
def load_dictionaries(
self,
# srcfolder: str,
dstfolder: str,
services_dstfolder: Optional[str],
services_dstfolder: Optional[str] = None,
extra_dstfolder: Optional[str] = None,
# namespace: str,
# display: bool=True,
):
if extra_dstfolder is None:
extra_dstfolder = dstfolder
self._load_dictionaries(
self.rougailconfig["dictionaries_dir"],
dstfolder,
services_dstfolder,
self.rougailconfig["variable_namespace"],
)
dict_dirs = self.rougailconfig["dictionaries_dir"]
if not isinstance(dict_dirs, list):
dict_dirs = [dict_dirs]
for dict_dir in dict_dirs:
self._load_dictionaries(
dict_dir,
dstfolder,
services_dstfolder,
self.rougailconfig["variable_namespace"],
)
for namespace, extra_dirs in self.rougailconfig["extra_dictionaries"].items():
extra_dstsubfolder = join(extra_dstfolder, namespace)
if not isdir(extra_dstsubfolder):
@ -671,7 +635,7 @@ class RougailUpgrade:
)
if filename.endswith(".xml"):
if parse is None:
raise Exception('XML module is not installed')
raise Exception("XML module is not installed")
try:
parser = XMLParser(remove_blank_text=True)
document = parse(xmlsrc, parser)
@ -685,29 +649,22 @@ class RougailUpgrade:
else:
with xmlsrc.open() as 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"
function_found = False
if FIXME_PRINT_FILENAME:
print(
"========================================================================"
)
print(xmlsrc)
print(
"========================================================================"
)
root_services = None
for version, function_version in FUNCTION_VERSIONS:
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(
filename, {}
)
if upgrade_help.get("remove") is True:
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
)
if root_services_ is not None:
root_services = root_services_
if function_version == search_function_name:
function_found = True
if root:
@ -733,12 +690,6 @@ class RougailUpgrade:
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):
for prop in [
"mandatory",
@ -766,10 +717,11 @@ class RougailUpgrade:
def _attribut_to_int(self, variable):
for prop in ["mode"]:
if prop in variable:
if variable[prop] in ['expert', 'normal']:
variable[prop] = {'expert': 'advanced',
'normal': 'standard',
}.get(variable[prop])
if variable[prop] in ["expert", "normal"]:
variable[prop] = {
"expert": "advanced",
"normal": "standard",
}.get(variable[prop])
continue
try:
variable[prop] = int(variable[prop])
@ -891,6 +843,36 @@ class RougailUpgrade:
dico = {obj_name: 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(
self,
root: "Element",
@ -909,19 +891,9 @@ class RougailUpgrade:
new_objects = self._xml_to_yaml(objects, typ, variables, "")
if new_objects[typ]:
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:
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"
def update_0_10(

View file

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

View file

@ -19,7 +19,54 @@ def _load_functions(path):
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"}))

View file

@ -19,7 +19,54 @@ def _load_functions(path):
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"}))

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:
varname:
type: string
@ -10,7 +10,10 @@ general:
- val2
dyn:
type: dynamic
variable: rougail.general.varname
dynamic:
type: variable
variable: rougail.general.varname
propertyerror: false
vardyn:
type: string
description: No change

View file

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

View file

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

View file

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

View file

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

View file

@ -19,7 +19,54 @@ def _load_functions(path):
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"}))

View file

@ -19,7 +19,54 @@ def _load_functions(path):
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"}))

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:
varname:
type: string
@ -9,7 +9,10 @@ general:
- val2
dyn:
type: dynamic
variable: rougail.general.varname
dynamic:
type: variable
variable: rougail.general.varname
propertyerror: false
vardyn:
type: string
default: val

View file

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

View file

@ -19,7 +19,54 @@ def _load_functions(path):
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"}))

View file

@ -19,7 +19,54 @@ def _load_functions(path):
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"}))

View file

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

View file

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

View file

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

View file

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

View file

@ -19,7 +19,54 @@ def _load_functions(path):
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=["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_1 = OptionDescription(name="rougail", doc="rougail", children=[optiondescription_2], properties=frozenset({"standard"}))

View file

@ -19,7 +19,54 @@ def _load_functions(path):
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=["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_2 = OptionDescription(name="rougail", doc="rougail", children=[optiondescription_3], properties=frozenset({"standard"}))

View file

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

View file

@ -19,7 +19,54 @@ def _load_functions(path):
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=["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_1 = OptionDescription(name="rougail", doc="rougail", children=[optiondescription_2], properties=frozenset({"standard"}))

View file

@ -19,7 +19,54 @@ def _load_functions(path):
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=["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_2 = OptionDescription(name="rougail", doc="rougail", children=[optiondescription_3], properties=frozenset({"standard"}))

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -13,4 +13,4 @@ general:
default:
type: jinja
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:
type: jinja
jinja: '{% if not bool %}3{% else %}4{% endif %}'
version: '1.0'
version: '1.1'

View file

@ -12,4 +12,4 @@ int2:
default:
type: jinja
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
description: No change
default: non
version: '1.0'
version: '1.1'

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -3,4 +3,4 @@ general:
type: string
description: Description
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\x2dpartlabel2:
engine: jinja
version: '1.0'
version: '1.1'

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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