Compare commits
177 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f189608886 | |||
| 9d7838ce31 | |||
| 80027569a5 | |||
| f3c323bd25 | |||
| 34e0654bbe | |||
| 349e30fc10 | |||
| 7027aaefd4 | |||
| f9c73783c5 | |||
| 1ee82bede9 | |||
| 9a7d4ef803 | |||
| 4c8a3c813a | |||
| 6ae9662e75 | |||
| f495642e39 | |||
| bc27a98229 | |||
| a70627db2b | |||
| a593fa3d35 | |||
| ae696e1738 | |||
| aa7bf6562e | |||
| 41a65ef2e5 | |||
| 2f179a2bf6 | |||
| 5a6e526d38 | |||
| 42bd463810 | |||
| bb79bbba17 | |||
| 018634a5e8 | |||
| 3661131f9f | |||
| 5ae05434fe | |||
| 0682613f94 | |||
| 27350dcab4 | |||
| fe66316e9c | |||
| bad47893d0 | |||
| 57894d09b1 | |||
| b087aa39f7 | |||
| 0adf0d3f73 | |||
| b582a57792 | |||
| c39e232fa9 | |||
| a757f739a7 | |||
| feff5dbd75 | |||
| 31c9efbf05 | |||
| e77b65ffd5 | |||
| 8f81df6909 | |||
| 4d730a6219 | |||
| 25dc5bfd42 | |||
| 9acb8b71c6 | |||
| 8d6cf62204 | |||
| e674217b63 | |||
| a68a52ad67 | |||
| 439cf7fe2d | |||
| 2ab5aee3cf | |||
| 21f1526891 | |||
| bf3396aa59 | |||
| 656df6068f | |||
| d3477d6241 | |||
| a3aff66523 | |||
| 8363580306 | |||
| cc790bb930 | |||
| 9a9544c7f9 | |||
| 192325e9e0 | |||
| e42347cf3d | |||
| 0dfb901fd5 | |||
| c80aca1e12 | |||
| c8aad30517 | |||
| 4df2b013df | |||
| 5d8278acf8 | |||
| 36f13dec22 | |||
| c4404a7d46 | |||
| 92b5257e66 | |||
| 5759e4f86b | |||
| fb0f1e5f2c | |||
| e8c692d39c | |||
| 8bf07735b8 | |||
| b120dd8e69 | |||
| 64e2d137c5 | |||
| fbba016007 | |||
| f5f55dd853 | |||
| 899226f7d2 | |||
| 4bf7274871 | |||
| dcb1800346 | |||
| 5e0af148d5 | |||
| bbcffffb82 | |||
| 99dddf20a9 | |||
| adff39d4d3 | |||
| bfc59e8084 | |||
| e2d5a30c21 | |||
| 9ee03b22bb | |||
| c8d5656094 | |||
| c4b90cbe42 | |||
| 62620d9b2e | |||
| bed7a1d3b5 | |||
| 06c87718d6 | |||
| a0677e7b00 | |||
| c840d57734 | |||
| a3b2699289 | |||
| c7a66a034e | |||
| 9e06f1142e | |||
| b902e15243 | |||
| cbccc8087f | |||
| fecab8aca6 | |||
| 97cc2460b2 | |||
| 5a4bb343b0 | |||
| bb1f117ed1 | |||
| 1662568c17 | |||
| 6be773de3c | |||
| 70b6f3d274 | |||
| e7a1caf113 | |||
| b229154df5 | |||
| e71d4600d7 | |||
| adc580069c | |||
| 9c940f8b28 | |||
| 6167e1ea2c | |||
| 46e2ede81d | |||
| 2488cc471e | |||
| 1dcc00429c | |||
| 2f9e584394 | |||
| 2027da0675 | |||
| efb23c350e | |||
| 52c8277238 | |||
| 3b0130420d | |||
| 00f29c37c4 | |||
| b9ea5edb07 | |||
| 136a0e71b7 | |||
| fc56827706 | |||
| 77490ca176 | |||
| 65ffaef2fe | |||
| c494a4662f | |||
| 0bc1e24d38 | |||
| e59b9e84df | |||
| 62097b552a | |||
| 19249875c3 | |||
| ae89e30e60 | |||
| e1b2d36aae | |||
| cc086f086a | |||
| 7ee65b6cab | |||
| 1858eeeb06 | |||
| dc311466a2 | |||
| 18df35acfe | |||
| 0e522db15f | |||
| 07a22d7966 | |||
| 7f9d6f17d7 | |||
| 2654141002 | |||
| 999b53889c | |||
| d35fe16cd9 | |||
| 04aa9444a3 | |||
| 9c7fb1d505 | |||
| 70003fcbc5 | |||
| 85f3b9f80f | |||
| b0687fdcc6 | |||
| cc5aaf6393 | |||
| df2fcb467f | |||
| 7b9d7ce419 | |||
| 63f76dc68f | |||
| e7e9687b8d | |||
| 0fea822c91 | |||
| ea6baa3dc2 | |||
| 7d830d5e40 | |||
| 81d86e7b6f | |||
| 7a5a1b42e8 | |||
| 3849c42cba | |||
| 6c1df5578f | |||
| dfd31c4fb4 | |||
| 45959ac18b | |||
| 9e8c6f96c5 | |||
| 00e0941f6e | |||
| 8afb787c98 | |||
| a91a4d6a55 | |||
| 688aa8d053 | |||
| 4c613f6425 | |||
| 145b7be0a5 | |||
| 829d7692ad | |||
| ea34751e08 | |||
| c25a66f0cb | |||
| fdfb7ec73b | |||
| db768f94af | |||
| 9782bcde95 | |||
| fbb1446fa3 | |||
| 56659f7ea4 | |||
| af3f77c920 | |||
| e29c0c8abc |
1923 changed files with 20148 additions and 12450 deletions
459
CHANGELOG.md
459
CHANGELOG.md
|
|
@ -1,3 +1,462 @@
|
|||
## 1.2.0a60 (2026-01-29)
|
||||
|
||||
### Feat
|
||||
|
||||
- support transitive in properties variable
|
||||
|
||||
## 1.2.0a59 (2026-01-21)
|
||||
|
||||
### Fix
|
||||
|
||||
- better support for secret manager
|
||||
- leadership and frozen
|
||||
|
||||
## 1.2.0a58 (2026-01-16)
|
||||
|
||||
### Fix
|
||||
|
||||
- secret with follower
|
||||
|
||||
## 1.2.0a57 (2026-01-16)
|
||||
|
||||
### Fix
|
||||
|
||||
- add transition
|
||||
|
||||
## 1.2.0a56 (2026-01-15)
|
||||
|
||||
### Fix
|
||||
|
||||
- types with subfamily
|
||||
|
||||
## 1.2.0a55 (2026-01-15)
|
||||
|
||||
### Fix
|
||||
|
||||
- better custom types support
|
||||
|
||||
## 1.2.0a54 (2026-01-14)
|
||||
|
||||
### Fix
|
||||
|
||||
- issymlinkoption is not available for an optiondescription
|
||||
- better error messages
|
||||
|
||||
## 1.2.0a53 (2026-01-05)
|
||||
|
||||
### Fix
|
||||
|
||||
- new tiramisu version support
|
||||
|
||||
## 1.2.0a52 (2026-01-03)
|
||||
|
||||
### Feat
|
||||
|
||||
- load tiramisu objects from cache
|
||||
|
||||
## 1.2.0a51 (2025-12-30)
|
||||
|
||||
### Feat
|
||||
|
||||
- add types support
|
||||
|
||||
### Fix
|
||||
|
||||
- better error message
|
||||
|
||||
## 1.2.0a50 (2025-12-23)
|
||||
|
||||
### Fix
|
||||
|
||||
- improvment
|
||||
|
||||
## 1.2.0a49 (2025-12-22)
|
||||
|
||||
### Fix
|
||||
|
||||
- better error message
|
||||
|
||||
## 1.2.0a48 (2025-12-22)
|
||||
|
||||
### Fix
|
||||
|
||||
- documentation
|
||||
|
||||
## 1.2.0a47 (2025-12-22)
|
||||
|
||||
### Fix
|
||||
|
||||
- description
|
||||
|
||||
## 1.2.0a46 (2025-12-22)
|
||||
|
||||
### Fix
|
||||
|
||||
- duplicate description
|
||||
|
||||
## 1.2.0a45 (2025-12-22)
|
||||
|
||||
### Feat
|
||||
|
||||
- better translation
|
||||
- add "do" extension for jinja2
|
||||
|
||||
### Fix
|
||||
|
||||
- user_datas => user_data
|
||||
|
||||
## 1.2.0a44 (2025-11-28)
|
||||
|
||||
### Fix
|
||||
|
||||
- disabled choices must not generate error when loaded from .rougailcli.yml
|
||||
|
||||
## 1.2.0a43 (2025-11-21)
|
||||
|
||||
### Feat
|
||||
|
||||
- add boolean return_type in validators
|
||||
|
||||
### Fix
|
||||
|
||||
- better rougailconfig copy
|
||||
- port is a string
|
||||
|
||||
## 1.2.0a42 (2025-11-06)
|
||||
|
||||
### Feat
|
||||
|
||||
- can add limit length for a variable
|
||||
|
||||
### Fix
|
||||
|
||||
- black
|
||||
|
||||
## 1.2.0a41 (2025-11-06)
|
||||
|
||||
### Feat
|
||||
|
||||
- choice if invalid value or unknown variable in user data is a fatal error or not
|
||||
|
||||
## 1.2.0a40 (2025-11-03)
|
||||
|
||||
### Feat
|
||||
|
||||
- can add name for a tiramisu config
|
||||
- active warnings for validators
|
||||
|
||||
## 1.2.0a39 (2025-10-29)
|
||||
|
||||
### Feat
|
||||
|
||||
- add tags support
|
||||
|
||||
### Fix
|
||||
|
||||
- load config leadership
|
||||
- do not load secrets if not allowed
|
||||
- update translation
|
||||
- add test
|
||||
|
||||
## 1.2.0a38 (2025-10-22)
|
||||
|
||||
## 1.2.0a37 (2025-10-16)
|
||||
|
||||
### Feat
|
||||
|
||||
- keep forced_descriptions information (mostly for rougail-output-doc)
|
||||
|
||||
### Fix
|
||||
|
||||
- name is uncalculated
|
||||
|
||||
## 1.2.0a36 (2025-10-10)
|
||||
|
||||
### Feat
|
||||
|
||||
- can desactivate isolated namespace feature
|
||||
- add return_type to property
|
||||
- remove return_values_not_error and only_default parameter
|
||||
- user_data can load secret manager values
|
||||
|
||||
### Fix
|
||||
|
||||
- translation for property is now in rougail
|
||||
- error in InformationCalculation errors
|
||||
- proprerty with unknown variable
|
||||
|
||||
## 1.2.0a35 (2025-10-02)
|
||||
|
||||
### Feat
|
||||
|
||||
- add warning class
|
||||
|
||||
## 1.2.0a34 (2025-09-30)
|
||||
|
||||
### Feat
|
||||
|
||||
- for formatter
|
||||
|
||||
## 1.2.0a33 (2025-09-29)
|
||||
|
||||
### Fix
|
||||
|
||||
- better doc for calculation with unknown variable
|
||||
|
||||
## 1.2.0a32 (2025-09-29)
|
||||
|
||||
### Feat
|
||||
|
||||
- **#28**: default value for a calculated variable with an unknown optional variable
|
||||
- **#26**: cidr and network_cidr type is depreciate
|
||||
- **#25**: add integer type which will replace number type
|
||||
|
||||
## 1.2.0a31 (2025-09-22)
|
||||
|
||||
### Fix
|
||||
|
||||
- dictionary => structure
|
||||
|
||||
## 1.2.0a30 (2025-09-20)
|
||||
|
||||
### Feat
|
||||
|
||||
- **40**: better conflict error message with dynamic name
|
||||
- add new get_root_option function
|
||||
|
||||
### Fix
|
||||
|
||||
- update test
|
||||
|
||||
## 1.2.0a29 (2025-06-20)
|
||||
|
||||
### Fix
|
||||
|
||||
- UserDatas, do now set modified option in second round
|
||||
|
||||
## 1.2.0a28 (2025-06-18)
|
||||
|
||||
### Fix
|
||||
|
||||
- conversion
|
||||
|
||||
## 1.2.0a27 (2025-06-18)
|
||||
|
||||
### Feat
|
||||
|
||||
- separate rougail and rougail-base
|
||||
|
||||
## 1.2.0a26 (2025-05-26)
|
||||
|
||||
### Fix
|
||||
|
||||
- user_data better support for follower variable
|
||||
|
||||
## 1.2.0a25 (2025-05-14)
|
||||
|
||||
### Feat
|
||||
|
||||
- can launch UserDatas twice
|
||||
|
||||
## 1.2.0a24 (2025-05-12)
|
||||
|
||||
### Fix
|
||||
|
||||
- upgrade translation
|
||||
- black
|
||||
|
||||
## 1.2.0a23 (2025-05-09)
|
||||
|
||||
### Fix
|
||||
|
||||
- add_quotes
|
||||
- tiramisu_display_name could display only description
|
||||
- use own undefined
|
||||
- support of default_dictionary_format_version file in tests
|
||||
- simplify version support
|
||||
|
||||
## 1.2.0a22 (2025-05-05)
|
||||
|
||||
### Fix
|
||||
|
||||
- user_datas support empty directory
|
||||
|
||||
## 1.2.0a21 (2025-05-02)
|
||||
|
||||
### Fix
|
||||
|
||||
- support {{ suffix }} name in 1.1 format version
|
||||
- do not force use_data usage
|
||||
- validators for an index
|
||||
|
||||
## 1.2.0a20 (2025-04-30)
|
||||
|
||||
### Fix
|
||||
|
||||
- remove symlink
|
||||
|
||||
## 1.2.0a19 (2025-04-30)
|
||||
|
||||
### Feat
|
||||
|
||||
- add ymlfile names in ConfigError message
|
||||
|
||||
### Fix
|
||||
|
||||
- update translation
|
||||
- remove negative_description support
|
||||
- redefine family in flatten mode
|
||||
- update tests
|
||||
- better multi check
|
||||
|
||||
## 1.2.0a18 (2025-04-09)
|
||||
|
||||
### Fix
|
||||
|
||||
- version
|
||||
|
||||
## 1.2.0a17 (2025-04-09)
|
||||
|
||||
### Fix
|
||||
|
||||
- better detection of multi variable in default attribute
|
||||
- better error message
|
||||
|
||||
## 1.2.0a16 (2025-04-03)
|
||||
|
||||
### Feat
|
||||
|
||||
- reoganise param conversion + better variable validation
|
||||
|
||||
### Fix
|
||||
|
||||
- correction in namespace calculation
|
||||
|
||||
## 1.2.0a15 (2025-04-01)
|
||||
|
||||
### Feat
|
||||
|
||||
- can link regexp variable
|
||||
- can link choice variable
|
||||
|
||||
### Fix
|
||||
|
||||
- update tests
|
||||
- do not raise variable in property with force_optional
|
||||
- update translation
|
||||
|
||||
## 1.2.0a14 (2025-03-30)
|
||||
|
||||
### Fix
|
||||
|
||||
- strutural step should not be available in commandline
|
||||
|
||||
## 1.2.0a13 (2025-03-27)
|
||||
|
||||
### Fix
|
||||
|
||||
- allow no user_datas installation (for example to generate doc)
|
||||
|
||||
## 1.2.0a12 (2025-03-19)
|
||||
|
||||
### Feat
|
||||
|
||||
- add rougail secret_manager
|
||||
|
||||
## 1.2.0a11 (2025-02-17)
|
||||
|
||||
### Fix
|
||||
|
||||
- add get remove properties
|
||||
|
||||
## 1.2.0a10 (2025-02-17)
|
||||
|
||||
### Fix
|
||||
|
||||
- we can define structural plugin when generate documentation
|
||||
- if a variable in user_data not existe, it's no a warnings
|
||||
|
||||
## 1.2.0a9 (2025-02-10)
|
||||
|
||||
### Feat
|
||||
|
||||
- can change defaut params for an option
|
||||
|
||||
### Fix
|
||||
|
||||
- if no description, generate negative_description too
|
||||
- error messages
|
||||
|
||||
## 1.2.0a8 (2025-01-04)
|
||||
|
||||
### Fix
|
||||
|
||||
- better support of not_for_commandline feature
|
||||
|
||||
## 1.2.0a7 (2025-01-02)
|
||||
|
||||
### Fix
|
||||
|
||||
- add structural_directory
|
||||
|
||||
## 1.2.0a6 (2025-01-02)
|
||||
|
||||
### Fix
|
||||
|
||||
- add path.py
|
||||
|
||||
## 1.2.0a5 (2025-01-02)
|
||||
|
||||
### Feat
|
||||
|
||||
- upgrade is not in formatter
|
||||
- remove prefix
|
||||
|
||||
## 1.2.0a4 (2024-12-11)
|
||||
|
||||
### Feat
|
||||
|
||||
- move test to a new project rougail-tests
|
||||
- output could have annotator
|
||||
|
||||
### Fix
|
||||
|
||||
- remove link
|
||||
- reorganise user_datas
|
||||
- only change prefix if path is relative
|
||||
|
||||
## 1.2.0a3 (2024-11-28)
|
||||
|
||||
### Fix
|
||||
|
||||
- add user_datas file
|
||||
|
||||
## 1.2.0a2 (2024-11-27)
|
||||
|
||||
### Feat
|
||||
|
||||
- add "exists" attribut for a family
|
||||
|
||||
### Fix
|
||||
|
||||
- separate UserDatas
|
||||
- options could be a list
|
||||
|
||||
## 1.2.0a1 (2024-11-25)
|
||||
|
||||
### Fix
|
||||
|
||||
- dynamic variable could be optional
|
||||
- dynamic variable declare in verion 1.0 has {{ suffix }}
|
||||
- user_data plugins could have annotator function
|
||||
- do not modify a dynamic variable if has default value
|
||||
|
||||
## 1.2.0a0 (2024-11-08)
|
||||
|
||||
### Feat
|
||||
|
||||
- add force_optional option to allow charging structure even if all variables are not available
|
||||
|
||||
## 1.1.1 (2024-11-06)
|
||||
|
||||
### Fix
|
||||
|
|
|
|||
211
README.fr.md
Normal file
211
README.fr.md
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
---
|
||||
gitea: none
|
||||
include_toc: true
|
||||
---
|
||||
[🇬🇧 (EN)](README.md) - [🇫🇷 (FR)](README.fr.md)
|
||||
|
||||
| Variable | Description | Valeur par défaut | Type | Contrôle des accès | Validateur |
|
||||
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|----------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **<a id="default_structural_format_version" name="default_structural_format_version">default_structural_format_version</a>**<br/>**Ligne de commande** : <br/>-v, --default_structural_format_version<br/>**Variable d'environnement** : DEFAULT_STRUCTURAL_FORMAT_VERSION | Version par défaut du format des fichiers de structure.<br/>Cette valeur n'est utilisée que si la version n'est pas définie dans le fichier de structure. | | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | **Choix** : <br/>• 1.0<br/>• 1.1<br/>• null |
|
||||
| **<a id="types" name="types">types</a>**<br/>**Ligne de commande** : <br/>--types<br/>**Variable d'environnement** : TYPES | Fichier avec types personnalisés.<br/>Ce fichier contient des types personnalisés au format Rougail pour les fichiers de structure. | | [`UNIX filename`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` | `standard` | `unique`<br/>• le nom de fichier peut être une chemin relatif<br/>• le fichier doit exister<br/>• type de fichier autorisé: "fichier" et "répertoire". |
|
||||
| **<a id="functions_files" name="functions_files">functions_files</a>**<br/>**Ligne de commande** : <br/>--functions_files<br/>**Variable d'environnement** : FUNCTIONS_FILES | Fichier avec les fonctions.<br/>Ce fichier contient des filtres et des fonctions Jinja2 supplémentaires utilisables dans les fichiers de structure. | | [`UNIX filename`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` | `standard` | `unique`<br/>• le nom de fichier peut être une chemin relatif<br/>• le fichier doit exister<br/>• type de fichier autorisé: "file". |
|
||||
| **<a id="modes_level" name="modes_level">modes_level</a>**<br/>**Ligne de commande** : <br/>--modes_level<br/>**Variable d'environnement** : MODES_LEVEL | Tous les niveaux de modes valides. | | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` | `standard` | `unique` |
|
||||
| **<a id="default_family_mode" name="default_family_mode">default_family_mode</a>**<br/>**Variable d'environnement** : DEFAULT_FAMILY_MODE | Mode par défaut pour une famille. | le premier défini dans "[Tous les niveaux de modes valides](#modes_level)" | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | Ce mode doit être disponible dans "[Tous les niveaux de modes valides](#modes_level)". |
|
||||
| **<a id="default_variable_mode" name="default_variable_mode">default_variable_mode</a>**<br/>**Variable d'environnement** : DEFAULT_VARIABLE_MODE | Mode par défaut pour une variable. | si la variable "[Tous les niveaux de modes valides](#modes_level)" est définit, la valeur par défaut est le second élément disponible, sinon, le premier | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | Ce mode doit être disponible dans "[Tous les niveaux de modes valides](#modes_level)". |
|
||||
| **<a id="base_option_name" name="base_option_name">base_option_name</a>**<br/>**Variable d'environnement** : BASE_OPTION_NAME | Nom de l'option pour l'option de base. | baseoption | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="export_with_import" name="export_with_import">export_with_import</a>**<br/>**Variable d'environnement** : EXPORT_WITH_IMPORT | Dans le fichier de cache, ne pas importer Tiramisu et autres dépendances. | true | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="tiramisu_cache" name="tiramisu_cache">tiramisu_cache</a>**<br/>**Ligne de commande** : <br/>-t, --tiramisu_cache<br/>**Variable d'environnement** : TIRAMISU_CACHE | Enregistrer le cache Tiramisu dans le fichier.<br/>Ce fichier contient les instructions Tiramisu utilisé en interne pour charger les variables.<br/>Ce fichier peut être utilisé pour le débogage. | | [`UNIX filename`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | • le nom de fichier peut être une chemin relatif<br/>• type de fichier autorisé: "file". |
|
||||
| **<a id="internal_functions" name="internal_functions">internal_functions</a>**<br/>**Variable d'environnement** : INTERNAL_FUNCTIONS | Nom des fonctions internes qu'il est possible d'utiliser comme fonction. | | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` | `standard` | |
|
||||
| **<a id="extra_annotators" name="extra_annotators">extra_annotators</a>**<br/>**Variable d'environnement** : EXTRA_ANNOTATORS | Nom des annotators supplémentaires. | | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` | `standard` | |
|
||||
| **<a id="suffix" name="suffix">suffix</a>**<br/>**Variable d'environnement** : SUFFIX | Suffix ajouté pour généré le nom des options. | | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="force_optional" name="force_optional">force_optional</a>**<br/>**Ligne de commande** : <br/>• --force_optional<br/>• --no-force_optional<br/>**Variable d'environnement** : FORCE_OPTIONAL | Toutes les variables dans un calcul sont optionnelles. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `obligatoire` | `standard` | |
|
||||
| **<a id="load_unexist_redefine" name="load_unexist_redefine">load_unexist_redefine</a>**<br/>**Variable d'environnement** : LOAD_UNEXIST_REDEFINE | Charger les variables redéfinis même si elles n'existe pas. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
|
||||
## Le gestionnaire de secret
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Chemin** : secret_manager\
|
||||
> `standard`
|
||||
|
||||
| Variable | Description | Valeur par défaut | Type | Contrôle des accès |
|
||||
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------|--------------------------------------------------------------------------------------------------|----------------------|
|
||||
| **<a id="secret_manager.pattern" name="secret_manager.pattern">secret_manager.pattern</a>**<br/>**Ligne de commande** : <br/>--secret_manager.pattern<br/>**Variable d'environnement** : SECRET_MANAGER.PATTERN | Le modèle de secret permettant de construire le nom de l'élément recherché dans le gestionnaire de secrets.<br/>Le modèle est au format Jinja2. | {{ project }} - {{ environment }} - {{ service }} - {{ user }} | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `obligatoire` | `standard` |
|
||||
|
||||
## Load and exporter steps
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Chemin** : step\
|
||||
> `standard`
|
||||
|
||||
| Variable | Description | Valeur par défaut | Type | Contrôle des accès | Validateur |
|
||||
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------|---------------------|--------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **<a id="step.structural" name="step.structural">step.structural</a>**<br/>**Variable d'environnement** : STEP.STRUCTURAL | Sélection pour structure. | • directory | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` | `standard` | **Choix** : <br/>• directory<br/>• string<br/>• commandline<br/>• risotto |
|
||||
| **<a id="step.user_data" name="step.user_data">step.user_data</a>**<br/>**Ligne de commande** : <br/>-u, --step.user_data<br/>**Variable d'environnement** : STEP.USER_DATA | Sélection pour données utilisateur. | | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` | `standard` *`désactivé`*<br/>**Désactivé** : les sorties "doc" n'autorisent pas des données utilisateur | `unique`<br/>**Choix** : <br/>• yaml<br/>• environment<br/>• commandline<br/>• ansible<br/>• questionary<br/>• risotto<br/>• bitwarden |
|
||||
| **<a id="step.output" name="step.output">step.output</a>**<br/>**Ligne de commande** : <br/>-o, --step.output<br/>**Variable d'environnement** : STEP.OUTPUT | Sélection pour sortie. | display | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `obligatoire` | `standard` | **Choix** : <br/>• display<br/>• json<br/>• doc<br/>• table<br/>• ansible |
|
||||
|
||||
| Variable | Description | Valeur par défaut | Type | Contrôle des accès |
|
||||
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------|---------------------|---------------------------------------------------------------------------------------------------|----------------------|
|
||||
| **<a id="define_default_params" name="define_default_params">define_default_params</a>**<br/>**Ligne de commande** : <br/>• --define_default_params<br/>• --no-define_default_params<br/>**Variable d'environnement** : DEFINE_DEFAULT_PARAMS | Sur charger les paramètre par défaut pour le type d'option. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `obligatoire` | `standard` |
|
||||
|
||||
## Paramètre par défaut pour le type d'option
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Chemin** : default_params\
|
||||
> `standard` *`désactivé`*\
|
||||
> **Désactivé** : lorsque la variable "[Sur charger les paramètre par défaut pour le type d'option](#define_default_params)" a la valeur "false"
|
||||
|
||||
### UNIX filename
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Chemin** : default_params.unix_filename\
|
||||
> `standard`
|
||||
|
||||
| Variable | Description | Valeur par défaut | Type | Contrôle des accès | Validateur |
|
||||
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------|----------------------------------|-----------------------------------------------------------------------------------------------|----------------------|----------------------------------------------------------------|
|
||||
| **<a id="default_params.unix_filename.allow_relative" name="default_params.unix_filename.allow_relative">default_params.unix_filename.allow_relative</a>**<br/>**Ligne de commande** : <br/>• --default_params.unix_filename.allow_relative<br/>• --default_params.unix_filename.no-allow_relative<br/>**Variable d'environnement** : DEFAULT_PARAMS.UNIX_FILENAME.ALLOW_RELATIVE | Le nom de fichier peut être une chemin relatif. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.unix_filename.test_existence" name="default_params.unix_filename.test_existence">default_params.unix_filename.test_existence</a>**<br/>**Ligne de commande** : <br/>• --default_params.unix_filename.test_existence<br/>• --default_params.unix_filename.no-test_existence<br/>**Variable d'environnement** : DEFAULT_PARAMS.UNIX_FILENAME.TEST_EXISTENCE | Le fichier doit exister. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.unix_filename.types" name="default_params.unix_filename.types">default_params.unix_filename.types</a>**<br/>**Ligne de commande** : <br/>--default_params.unix_filename.types<br/>**Variable d'environnement** : DEFAULT_PARAMS.UNIX_FILENAME.TYPES | Type de fichier autorisé. | • file<br/>• directory | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` | `standard` | `unique`<br/>**Choix** : <br/>• file<br/>• directory |
|
||||
|
||||
### IP
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Chemin** : default_params.ip\
|
||||
> `standard`
|
||||
|
||||
| Variable | Description | Valeur par défaut | Type | Contrôle des accès |
|
||||
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------|---------------------|-------------------------------------------------------------------------------------|----------------------|
|
||||
| **<a id="default_params.ip.private_only" name="default_params.ip.private_only">default_params.ip.private_only</a>**<br/>**Ligne de commande** : <br/>• --default_params.ip.private_only<br/>• --default_params.ip.no-private_only<br/>**Variable d'environnement** : DEFAULT_PARAMS.IP.PRIVATE_ONLY | Les IP privées sont autorisées. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.ip.allow_reserved" name="default_params.ip.allow_reserved">default_params.ip.allow_reserved</a>**<br/>**Ligne de commande** : <br/>• --default_params.ip.allow_reserved<br/>• --default_params.ip.no-allow_reserved<br/>**Variable d'environnement** : DEFAULT_PARAMS.IP.ALLOW_RESERVED | Les IP réservées sont autorisés. | true | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.ip.cidr" name="default_params.ip.cidr">default_params.ip.cidr</a>**<br/>**Ligne de commande** : <br/>• --default_params.ip.cidr<br/>• --default_params.ip.no-cidr<br/>**Variable d'environnement** : DEFAULT_PARAMS.IP.CIDR | L'IP doit être au format CIDR. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
|
||||
### CIDR
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Chemin** : default_params.cidr\
|
||||
> `standard`
|
||||
|
||||
| Variable | Description | Valeur par défaut | Type | Contrôle des accès |
|
||||
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------|---------------------|-------------------------------------------------------------------------------------|----------------------|
|
||||
| **<a id="default_params.cidr.private_only" name="default_params.cidr.private_only">default_params.cidr.private_only</a>**<br/>**Ligne de commande** : <br/>• --default_params.cidr.private_only<br/>• --default_params.cidr.no-private_only<br/>**Variable d'environnement** : DEFAULT_PARAMS.CIDR.PRIVATE_ONLY | Les IP privées sont autorisées. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.cidr.allow_reserved" name="default_params.cidr.allow_reserved">default_params.cidr.allow_reserved</a>**<br/>**Ligne de commande** : <br/>• --default_params.cidr.allow_reserved<br/>• --default_params.cidr.no-allow_reserved<br/>**Variable d'environnement** : DEFAULT_PARAMS.CIDR.ALLOW_RESERVED | Les IP réservées sont autorisés. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.cidr.cidr" name="default_params.cidr.cidr">default_params.cidr.cidr</a>**<br/>**Ligne de commande** : <br/>• --default_params.cidr.cidr<br/>• --default_params.cidr.no-cidr<br/>**Variable d'environnement** : DEFAULT_PARAMS.CIDR.CIDR | L'IP doit être au format CIDR. | true | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
|
||||
### Network
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Chemin** : default_params.network\
|
||||
> `standard`
|
||||
|
||||
| Variable | Description | Valeur par défaut | Type | Contrôle des accès |
|
||||
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------|---------------------|-------------------------------------------------------------------------------------|----------------------|
|
||||
| **<a id="default_params.network.private_only" name="default_params.network.private_only">default_params.network.private_only</a>**<br/>**Ligne de commande** : <br/>• --default_params.network.private_only<br/>• --default_params.network.no-private_only<br/>**Variable d'environnement** : DEFAULT_PARAMS.NETWORK.PRIVATE_ONLY | Les réseaux privés sont autorisés. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.network.allow_reserved" name="default_params.network.allow_reserved">default_params.network.allow_reserved</a>**<br/>**Ligne de commande** : <br/>• --default_params.network.allow_reserved<br/>• --default_params.network.no-allow_reserved<br/>**Variable d'environnement** : DEFAULT_PARAMS.NETWORK.ALLOW_RESERVED | Les réseaux réservés sont autorisés. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.network.cidr" name="default_params.network.cidr">default_params.network.cidr</a>**<br/>**Ligne de commande** : <br/>• --default_params.network.cidr<br/>• --default_params.network.no-cidr<br/>**Variable d'environnement** : DEFAULT_PARAMS.NETWORK.CIDR | Le réseau doit être au format CIDR. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
|
||||
### Network CIDR
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Chemin** : default_params.network_cidr\
|
||||
> `standard`
|
||||
|
||||
| Variable | Description | Valeur par défaut | Type | Contrôle des accès |
|
||||
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------|---------------------|-------------------------------------------------------------------------------------|----------------------|
|
||||
| **<a id="default_params.network_cidr.private_only" name="default_params.network_cidr.private_only">default_params.network_cidr.private_only</a>**<br/>**Ligne de commande** : <br/>• --default_params.network_cidr.private_only<br/>• --default_params.network_cidr.no-private_only<br/>**Variable d'environnement** : DEFAULT_PARAMS.NETWORK_CIDR.PRIVATE_ONLY | Les réseaux privés sont autorisés. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.network_cidr.allow_reserved" name="default_params.network_cidr.allow_reserved">default_params.network_cidr.allow_reserved</a>**<br/>**Ligne de commande** : <br/>• --default_params.network_cidr.allow_reserved<br/>• --default_params.network_cidr.no-allow_reserved<br/>**Variable d'environnement** : DEFAULT_PARAMS.NETWORK_CIDR.ALLOW_RESERVED | Les réseaux réservés sont autorisés. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.network_cidr.cidr" name="default_params.network_cidr.cidr">default_params.network_cidr.cidr</a>**<br/>**Ligne de commande** : <br/>• --default_params.network_cidr.cidr<br/>• --default_params.network_cidr.no-cidr<br/>**Variable d'environnement** : DEFAULT_PARAMS.NETWORK_CIDR.CIDR | Le réseau doit être au format CIDR. | true | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
|
||||
### Netbios
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Chemin** : default_params.netbios\
|
||||
> `standard`
|
||||
|
||||
| Variable | Description | Valeur par défaut | Type | Contrôle des accès | Validateur |
|
||||
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------|---------------------|-------------------------------------------------------------------------------------|----------------------|-------------------------------------------------------------------------------------------|
|
||||
| **<a id="default_params.netbios.type" name="default_params.netbios.type">default_params.netbios.type</a>**<br/>**Ligne de commande** : <br/>--default_params.netbios.type<br/>**Variable d'environnement** : DEFAULT_PARAMS.NETBIOS.TYPE | Type de nom de domaine. | netbios | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | **Choix** : <br/>• domainname<br/>• netbios<br/>• hostname<br/>• null |
|
||||
| **<a id="default_params.netbios.allow_without_dot" name="default_params.netbios.allow_without_dot">default_params.netbios.allow_without_dot</a>**<br/>**Ligne de commande** : <br/>• --default_params.netbios.allow_without_dot<br/>• --default_params.netbios.no-allow_without_dot<br/>**Variable d'environnement** : DEFAULT_PARAMS.NETBIOS.ALLOW_WITHOUT_DOT | Le nom de domaine peut être un nom d'hôte. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.netbios.test_existence" name="default_params.netbios.test_existence">default_params.netbios.test_existence</a>**<br/>**Ligne de commande** : <br/>• --default_params.netbios.test_existence<br/>• --default_params.netbios.no-test_existence<br/>**Variable d'environnement** : DEFAULT_PARAMS.NETBIOS.TEST_EXISTENCE | Le nom de domaine doit exister. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.netbios.allow_ip" name="default_params.netbios.allow_ip">default_params.netbios.allow_ip</a>**<br/>**Ligne de commande** : <br/>• --default_params.netbios.allow_ip<br/>• --default_params.netbios.no-allow_ip<br/>**Variable d'environnement** : DEFAULT_PARAMS.NETBIOS.ALLOW_IP | Le nom de domaine peut être une IP. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.netbios.allow_cidr_network" name="default_params.netbios.allow_cidr_network">default_params.netbios.allow_cidr_network</a>**<br/>**Ligne de commande** : <br/>• --default_params.netbios.allow_cidr_network<br/>• --default_params.netbios.no-allow_cidr_network<br/>**Variable d'environnement** : DEFAULT_PARAMS.NETBIOS.ALLOW_CIDR_NETWORK | Le nom de domaine peut être un réseau au format CIDR. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.netbios.allow_startswith_dot" name="default_params.netbios.allow_startswith_dot">default_params.netbios.allow_startswith_dot</a>**<br/>**Ligne de commande** : <br/>• --default_params.netbios.allow_startswith_dot<br/>• --default_params.netbios.no-allow_startswith_dot<br/>**Variable d'environnement** : DEFAULT_PARAMS.NETBIOS.ALLOW_STARTSWITH_DOT | Le nom de domaine peut démarré par un point. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
|
||||
### Domainname
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Chemin** : default_params.domainname\
|
||||
> `standard`
|
||||
|
||||
| Variable | Description | Valeur par défaut | Type | Contrôle des accès | Validateur |
|
||||
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------|---------------------|-------------------------------------------------------------------------------------|----------------------|-------------------------------------------------------------------------------------------|
|
||||
| **<a id="default_params.domainname.type" name="default_params.domainname.type">default_params.domainname.type</a>**<br/>**Ligne de commande** : <br/>--default_params.domainname.type<br/>**Variable d'environnement** : DEFAULT_PARAMS.DOMAINNAME.TYPE | Type de nom de domaine. | domainname | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | **Choix** : <br/>• domainname<br/>• netbios<br/>• hostname<br/>• null |
|
||||
| **<a id="default_params.domainname.allow_without_dot" name="default_params.domainname.allow_without_dot">default_params.domainname.allow_without_dot</a>**<br/>**Ligne de commande** : <br/>• --default_params.domainname.allow_without_dot<br/>• --default_params.domainname.no-allow_without_dot<br/>**Variable d'environnement** : DEFAULT_PARAMS.DOMAINNAME.ALLOW_WITHOUT_DOT | Le nom de domaine peut être un nom d'hôte. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.domainname.test_existence" name="default_params.domainname.test_existence">default_params.domainname.test_existence</a>**<br/>**Ligne de commande** : <br/>• --default_params.domainname.test_existence<br/>• --default_params.domainname.no-test_existence<br/>**Variable d'environnement** : DEFAULT_PARAMS.DOMAINNAME.TEST_EXISTENCE | Le nom de domaine doit exister. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.domainname.allow_ip" name="default_params.domainname.allow_ip">default_params.domainname.allow_ip</a>**<br/>**Ligne de commande** : <br/>• --default_params.domainname.allow_ip<br/>• --default_params.domainname.no-allow_ip<br/>**Variable d'environnement** : DEFAULT_PARAMS.DOMAINNAME.ALLOW_IP | Le nom de domaine peut être une IP. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.domainname.allow_cidr_network" name="default_params.domainname.allow_cidr_network">default_params.domainname.allow_cidr_network</a>**<br/>**Ligne de commande** : <br/>• --default_params.domainname.allow_cidr_network<br/>• --default_params.domainname.no-allow_cidr_network<br/>**Variable d'environnement** : DEFAULT_PARAMS.DOMAINNAME.ALLOW_CIDR_NETWORK | Le nom de domaine peut être un réseau au format CIDR. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.domainname.allow_startswith_dot" name="default_params.domainname.allow_startswith_dot">default_params.domainname.allow_startswith_dot</a>**<br/>**Ligne de commande** : <br/>• --default_params.domainname.allow_startswith_dot<br/>• --default_params.domainname.no-allow_startswith_dot<br/>**Variable d'environnement** : DEFAULT_PARAMS.DOMAINNAME.ALLOW_STARTSWITH_DOT | Le nom de domaine peut démarré par un point. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
|
||||
### Hostname
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Chemin** : default_params.hostname\
|
||||
> `standard`
|
||||
|
||||
| Variable | Description | Valeur par défaut | Type | Contrôle des accès | Validateur |
|
||||
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------|---------------------|-------------------------------------------------------------------------------------|----------------------|-------------------------------------------------------------------------------------------|
|
||||
| **<a id="default_params.hostname.type" name="default_params.hostname.type">default_params.hostname.type</a>**<br/>**Ligne de commande** : <br/>--default_params.hostname.type<br/>**Variable d'environnement** : DEFAULT_PARAMS.HOSTNAME.TYPE | Type de nom de domaine. | hostname | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | **Choix** : <br/>• domainname<br/>• netbios<br/>• hostname<br/>• null |
|
||||
| **<a id="default_params.hostname.allow_without_dot" name="default_params.hostname.allow_without_dot">default_params.hostname.allow_without_dot</a>**<br/>**Ligne de commande** : <br/>• --default_params.hostname.allow_without_dot<br/>• --default_params.hostname.no-allow_without_dot<br/>**Variable d'environnement** : DEFAULT_PARAMS.HOSTNAME.ALLOW_WITHOUT_DOT | Le nom de domaine peut être un nom d'hôte. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.hostname.test_existence" name="default_params.hostname.test_existence">default_params.hostname.test_existence</a>**<br/>**Ligne de commande** : <br/>• --default_params.hostname.test_existence<br/>• --default_params.hostname.no-test_existence<br/>**Variable d'environnement** : DEFAULT_PARAMS.HOSTNAME.TEST_EXISTENCE | Le nom de domaine doit exister. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.hostname.allow_ip" name="default_params.hostname.allow_ip">default_params.hostname.allow_ip</a>**<br/>**Ligne de commande** : <br/>• --default_params.hostname.allow_ip<br/>• --default_params.hostname.no-allow_ip<br/>**Variable d'environnement** : DEFAULT_PARAMS.HOSTNAME.ALLOW_IP | Le nom de domaine peut être une IP. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.hostname.allow_cidr_network" name="default_params.hostname.allow_cidr_network">default_params.hostname.allow_cidr_network</a>**<br/>**Ligne de commande** : <br/>• --default_params.hostname.allow_cidr_network<br/>• --default_params.hostname.no-allow_cidr_network<br/>**Variable d'environnement** : DEFAULT_PARAMS.HOSTNAME.ALLOW_CIDR_NETWORK | Le nom de domaine peut être un réseau au format CIDR. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.hostname.allow_startswith_dot" name="default_params.hostname.allow_startswith_dot">default_params.hostname.allow_startswith_dot</a>**<br/>**Ligne de commande** : <br/>• --default_params.hostname.allow_startswith_dot<br/>• --default_params.hostname.no-allow_startswith_dot<br/>**Variable d'environnement** : DEFAULT_PARAMS.HOSTNAME.ALLOW_STARTSWITH_DOT | Le nom de domaine peut démarré par un point. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
|
||||
### Web address
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Chemin** : default_params.web_address\
|
||||
> `standard`
|
||||
|
||||
| Variable | Description | Valeur par défaut | Type | Contrôle des accès | Validateur |
|
||||
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------|---------------------|-------------------------------------------------------------------------------------|----------------------|-------------------------------------------------------------------------------------------|
|
||||
| **<a id="default_params.web_address.type" name="default_params.web_address.type">default_params.web_address.type</a>**<br/>**Ligne de commande** : <br/>--default_params.web_address.type<br/>**Variable d'environnement** : DEFAULT_PARAMS.WEB_ADDRESS.TYPE | Type de nom de domaine. | domainname | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | **Choix** : <br/>• domainname<br/>• netbios<br/>• hostname<br/>• null |
|
||||
| **<a id="default_params.web_address.allow_without_dot" name="default_params.web_address.allow_without_dot">default_params.web_address.allow_without_dot</a>**<br/>**Ligne de commande** : <br/>• --default_params.web_address.allow_without_dot<br/>• --default_params.web_address.no-allow_without_dot<br/>**Variable d'environnement** : DEFAULT_PARAMS.WEB_ADDRESS.ALLOW_WITHOUT_DOT | Le nom de domaine peut être un nom d'hôte. | true | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.web_address.test_existence" name="default_params.web_address.test_existence">default_params.web_address.test_existence</a>**<br/>**Ligne de commande** : <br/>• --default_params.web_address.test_existence<br/>• --default_params.web_address.no-test_existence<br/>**Variable d'environnement** : DEFAULT_PARAMS.WEB_ADDRESS.TEST_EXISTENCE | Le nom de domaine doit exister. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.web_address.allow_ip" name="default_params.web_address.allow_ip">default_params.web_address.allow_ip</a>**<br/>**Ligne de commande** : <br/>• --default_params.web_address.allow_ip<br/>• --default_params.web_address.no-allow_ip<br/>**Variable d'environnement** : DEFAULT_PARAMS.WEB_ADDRESS.ALLOW_IP | Le nom de domaine peut être une IP. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.web_address.allow_cidr_network" name="default_params.web_address.allow_cidr_network">default_params.web_address.allow_cidr_network</a>**<br/>**Ligne de commande** : <br/>• --default_params.web_address.allow_cidr_network<br/>• --default_params.web_address.no-allow_cidr_network<br/>**Variable d'environnement** : DEFAULT_PARAMS.WEB_ADDRESS.ALLOW_CIDR_NETWORK | Le nom de domaine peut être un réseau au format CIDR. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.web_address.allow_startswith_dot" name="default_params.web_address.allow_startswith_dot">default_params.web_address.allow_startswith_dot</a>**<br/>**Ligne de commande** : <br/>• --default_params.web_address.allow_startswith_dot<br/>• --default_params.web_address.no-allow_startswith_dot<br/>**Variable d'environnement** : DEFAULT_PARAMS.WEB_ADDRESS.ALLOW_STARTSWITH_DOT | Le nom de domaine peut démarré par un point. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.web_address.allow_range" name="default_params.web_address.allow_range">default_params.web_address.allow_range</a>**<br/>**Ligne de commande** : <br/>• --default_params.web_address.allow_range<br/>• --default_params.web_address.no-allow_range<br/>**Variable d'environnement** : DEFAULT_PARAMS.WEB_ADDRESS.ALLOW_RANGE | Peut être une plage de port. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.web_address.allow_protocol" name="default_params.web_address.allow_protocol">default_params.web_address.allow_protocol</a>**<br/>**Ligne de commande** : <br/>• --default_params.web_address.allow_protocol<br/>• --default_params.web_address.no-allow_protocol<br/>**Variable d'environnement** : DEFAULT_PARAMS.WEB_ADDRESS.ALLOW_PROTOCOL | Peut avoir le protocole. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.web_address.allow_zero" name="default_params.web_address.allow_zero">default_params.web_address.allow_zero</a>**<br/>**Ligne de commande** : <br/>• --default_params.web_address.allow_zero<br/>• --default_params.web_address.no-allow_zero<br/>**Variable d'environnement** : DEFAULT_PARAMS.WEB_ADDRESS.ALLOW_ZERO | Port 0 est autorisé. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.web_address.allow_wellknown" name="default_params.web_address.allow_wellknown">default_params.web_address.allow_wellknown</a>**<br/>**Ligne de commande** : <br/>• --default_params.web_address.allow_wellknown<br/>• --default_params.web_address.no-allow_wellknown<br/>**Variable d'environnement** : DEFAULT_PARAMS.WEB_ADDRESS.ALLOW_WELLKNOWN | Les ports connus (1 à 1023) sont autorisés. | true | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.web_address.allow_registred" name="default_params.web_address.allow_registred">default_params.web_address.allow_registred</a>**<br/>**Ligne de commande** : <br/>• --default_params.web_address.allow_registred<br/>• --default_params.web_address.no-allow_registred<br/>**Variable d'environnement** : DEFAULT_PARAMS.WEB_ADDRESS.ALLOW_REGISTRED | Les ports enregistrés (1024 à 49151) sont autorisés. | true | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.web_address.allow_private" name="default_params.web_address.allow_private">default_params.web_address.allow_private</a>**<br/>**Ligne de commande** : <br/>• --default_params.web_address.allow_private<br/>• --default_params.web_address.no-allow_private<br/>**Variable d'environnement** : DEFAULT_PARAMS.WEB_ADDRESS.ALLOW_PRIVATE | Les ports privés (supérieur à 49152) sont autorisés. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
|
||||
### Port
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Chemin** : default_params.port\
|
||||
> `standard`
|
||||
|
||||
| Variable | Description | Valeur par défaut | Type | Contrôle des accès |
|
||||
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------|---------------------|-------------------------------------------------------------------------------------|----------------------|
|
||||
| **<a id="default_params.port.allow_range" name="default_params.port.allow_range">default_params.port.allow_range</a>**<br/>**Ligne de commande** : <br/>• --default_params.port.allow_range<br/>• --default_params.port.no-allow_range<br/>**Variable d'environnement** : DEFAULT_PARAMS.PORT.ALLOW_RANGE | Peut être une plage de port. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.port.allow_protocol" name="default_params.port.allow_protocol">default_params.port.allow_protocol</a>**<br/>**Ligne de commande** : <br/>• --default_params.port.allow_protocol<br/>• --default_params.port.no-allow_protocol<br/>**Variable d'environnement** : DEFAULT_PARAMS.PORT.ALLOW_PROTOCOL | Peut avoir le protocole. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.port.allow_zero" name="default_params.port.allow_zero">default_params.port.allow_zero</a>**<br/>**Ligne de commande** : <br/>• --default_params.port.allow_zero<br/>• --default_params.port.no-allow_zero<br/>**Variable d'environnement** : DEFAULT_PARAMS.PORT.ALLOW_ZERO | Port 0 est autorisé. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.port.allow_wellknown" name="default_params.port.allow_wellknown">default_params.port.allow_wellknown</a>**<br/>**Ligne de commande** : <br/>• --default_params.port.allow_wellknown<br/>• --default_params.port.no-allow_wellknown<br/>**Variable d'environnement** : DEFAULT_PARAMS.PORT.ALLOW_WELLKNOWN | Les ports connus (1 à 1023) sont autorisés. | true | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.port.allow_registred" name="default_params.port.allow_registred">default_params.port.allow_registred</a>**<br/>**Ligne de commande** : <br/>• --default_params.port.allow_registred<br/>• --default_params.port.no-allow_registred<br/>**Variable d'environnement** : DEFAULT_PARAMS.PORT.ALLOW_REGISTRED | Les ports enregistrés (1024 à 49151) sont autorisés. | true | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.port.allow_private" name="default_params.port.allow_private">default_params.port.allow_private</a>**<br/>**Ligne de commande** : <br/>• --default_params.port.allow_private<br/>• --default_params.port.no-allow_private<br/>**Variable d'environnement** : DEFAULT_PARAMS.PORT.ALLOW_PRIVATE | Les ports privés (supérieur à 49152) sont autorisés. | true | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
|
||||
|
||||
288
README.md
288
README.md
|
|
@ -1,105 +1,211 @@
|
|||

|
||||
|
||||
# Rougail
|
||||
|
||||
## Description
|
||||
|
||||
Rougail is a free full-featured configuration manager library written in python3.
|
||||
|
||||
The configuration is describe in YAML dictionary files.
|
||||
|
||||
Those dictionaries are converted into [Tiramisu](https://framagit.org/tiramisu/tiramisu) objects.
|
||||
|
||||
Rougail can be incorporated with other technologies and stacks regardless of whether they’re written in Python or not.
|
||||
|
||||
## Simple example
|
||||
|
||||
Create a directory:
|
||||
|
||||
```bash
|
||||
# mkdir dict
|
||||
```
|
||||
|
||||
## Dictionary
|
||||
|
||||
A dictionary is a variables description file.
|
||||
|
||||
Create the file `dict/dictionary.yml`:
|
||||
|
||||
```yml
|
||||
---
|
||||
version: 1.1
|
||||
# describe a variable my_first_variable
|
||||
# and a family with a variable my_second_variable
|
||||
my_first_variable: my_value
|
||||
my_family:
|
||||
my_second_variable: 1
|
||||
```
|
||||
gitea: none
|
||||
include_toc: true
|
||||
---
|
||||
[🇬🇧 (EN)](README.md) - [🇫🇷 (FR)](README.fr.md)
|
||||
|
||||
## Generate variable
|
||||
| Variable | Description | Default value | Type | Access control | Validator |
|
||||
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|------------------|--------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **<a id="default_structural_format_version" name="default_structural_format_version">default_structural_format_version</a>**<br/>**Command line**: <br/>-v, --default_structural_format_version<br/>**Environment variable**: DEFAULT_STRUCTURAL_FORMAT_VERSION | Default version of the structural file format.<br/>This value is only used if the version is not set in the structural file. | | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | **Choices**: <br/>• 1.0<br/>• 1.1<br/>• null |
|
||||
| **<a id="types" name="types">types</a>**<br/>**Command line**: <br/>--types<br/>**Environment variable**: TYPES | File with personalize types.<br/>This file contains personalize types in Rougail format for structure files. | | [`UNIX filename`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` | `standard` | `unique`<br/>• this filename could be a relative path<br/>• this file must exist<br/>• file type allowed: "directory" and "file". |
|
||||
| **<a id="functions_files" name="functions_files">functions_files</a>**<br/>**Command line**: <br/>--functions_files<br/>**Environment variable**: FUNCTIONS_FILES | File with functions.<br/>This file contains filters and additional Jinja2 functions usable in structure files. | | [`UNIX filename`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` | `standard` | `unique`<br/>• this filename could be a relative path<br/>• this file must exist<br/>• file type allowed: "file". |
|
||||
| **<a id="modes_level" name="modes_level">modes_level</a>**<br/>**Command line**: <br/>--modes_level<br/>**Environment variable**: MODES_LEVEL | All modes level available. | | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` | `standard` | `unique` |
|
||||
| **<a id="default_family_mode" name="default_family_mode">default_family_mode</a>**<br/>**Environment variable**: DEFAULT_FAMILY_MODE | Default mode for a family. | the first one defined in "[All modes level available](#modes_level)" | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | This mode must be available in "[All modes level available](#modes_level)". |
|
||||
| **<a id="default_variable_mode" name="default_variable_mode">default_variable_mode</a>**<br/>**Environment variable**: DEFAULT_VARIABLE_MODE | Default mode for a variable. | if the variable "[All modes level available](#modes_level)" is defined, the default value is the second available element, otherwise, the first | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | This mode must be available in "[All modes level available](#modes_level)". |
|
||||
| **<a id="base_option_name" name="base_option_name">base_option_name</a>**<br/>**Environment variable**: BASE_OPTION_NAME | Option name for the base option. | baseoption | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="export_with_import" name="export_with_import">export_with_import</a>**<br/>**Environment variable**: EXPORT_WITH_IMPORT | In cache file, do not importation of Tiramisu and other dependencies. | true | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="tiramisu_cache" name="tiramisu_cache">tiramisu_cache</a>**<br/>**Command line**: <br/>-t, --tiramisu_cache<br/>**Environment variable**: TIRAMISU_CACHE | Store Tiramisu cache filename.<br/>This file contains the Tiramisu instructions used internally to load the variables.<br/>This file can be used for debugging. | | [`UNIX filename`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | • this filename could be a relative path<br/>• file type allowed: "file". |
|
||||
| **<a id="internal_functions" name="internal_functions">internal_functions</a>**<br/>**Environment variable**: INTERNAL_FUNCTIONS | Name of internal functions that we can use as a function. | | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` | `standard` | |
|
||||
| **<a id="extra_annotators" name="extra_annotators">extra_annotators</a>**<br/>**Environment variable**: EXTRA_ANNOTATORS | Name of extra annotators. | | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` | `standard` | |
|
||||
| **<a id="suffix" name="suffix">suffix</a>**<br/>**Environment variable**: SUFFIX | Suffix add to generated options name. | | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="force_optional" name="force_optional">force_optional</a>**<br/>**Command line**: <br/>• --force_optional<br/>• --no-force_optional<br/>**Environment variable**: FORCE_OPTIONAL | Every variables in calculation are optionals. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | `standard` | |
|
||||
| **<a id="load_unexist_redefine" name="load_unexist_redefine">load_unexist_redefine</a>**<br/>**Environment variable**: LOAD_UNEXIST_REDEFINE | Loads redefine variables even if there don't already exists. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
|
||||
### With commandline:
|
||||
## The secret manager
|
||||
|
||||
```bash
|
||||
# rougail -m dict
|
||||
Variables:
|
||||
┣━━ 📓 my_first_variable: my_value
|
||||
┗━━ 📂 my_family
|
||||
┗━━ 📓 my_second_variable: 1
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Path**: secret_manager\
|
||||
> `standard`
|
||||
|
||||
```
|
||||
| Variable | Description | Default value | Type | Access control |
|
||||
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------|------------------------------------------------------------------------------------------------|------------------|
|
||||
| **<a id="secret_manager.pattern" name="secret_manager.pattern">secret_manager.pattern</a>**<br/>**Command line**: <br/>--secret_manager.pattern<br/>**Environment variable**: SECRET_MANAGER.PATTERN | The secret pattern to constructing the name of the item searched for in the secret manager.<br/>The pattern is in Jinja2 format. | {{ project }} - {{ environment }} - {{ service }} - {{ user }} | [`string`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | `standard` |
|
||||
|
||||
### With default value:
|
||||
## Load and exporter steps
|
||||
|
||||
Here is a python3 example file:
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Path**: step\
|
||||
> `standard`
|
||||
|
||||
```python
|
||||
from rougail import Rougail, RougailConfig
|
||||
from pprint import pprint
|
||||
| Variable | Description | Default value | Type | Access control | Validator |
|
||||
|------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------|------------------|------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **<a id="step.structural" name="step.structural">step.structural</a>**<br/>**Environment variable**: STEP.STRUCTURAL | Select for structural. | • directory | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` | `standard` | **Choices**: <br/>• directory<br/>• string<br/>• commandline<br/>• risotto |
|
||||
| **<a id="step.user_data" name="step.user_data">step.user_data</a>**<br/>**Command line**: <br/>-u, --step.user_data<br/>**Environment variable**: STEP.USER_DATA | Select for user datas. | | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` | `standard` *`disabled`*<br/>**Disabled**: outputs "doc" did not allow user data | `unique`<br/>**Choices**: <br/>• yaml<br/>• environment<br/>• commandline<br/>• ansible<br/>• questionary<br/>• risotto<br/>• bitwarden |
|
||||
| **<a id="step.output" name="step.output">step.output</a>**<br/>**Command line**: <br/>-o, --step.output<br/>**Environment variable**: STEP.OUTPUT | Select for output. | display | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | `standard` | **Choices**: <br/>• display<br/>• json<br/>• doc<br/>• table<br/>• ansible |
|
||||
|
||||
RougailConfig['dictionaries_dir'] = ['dict']
|
||||
rougail = Rougail()
|
||||
config = rougail.run()
|
||||
pprint(config.value.get(), sort_dicts=False)
|
||||
```
|
||||
| Variable | Description | Default value | Type | Access control |
|
||||
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------|-----------------|-------------------------------------------------------------------------------------------------|------------------|
|
||||
| **<a id="define_default_params" name="define_default_params">define_default_params</a>**<br/>**Command line**: <br/>• --define_default_params<br/>• --no-define_default_params<br/>**Environment variable**: DEFINE_DEFAULT_PARAMS | Override default parameters for option type. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `mandatory` | `standard` |
|
||||
|
||||
The result is:
|
||||
## Default parameters for option type
|
||||
|
||||
```json
|
||||
{<TiramisuOption path="rougail">: {<TiramisuOption path="rougail.my_first_variable">: 'my_value',
|
||||
<TiramisuOption path="rougail.my_family">: {<TiramisuOption path="rougail.my_family.my_second_variable">: 1}}}
|
||||
```
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Path**: default_params\
|
||||
> `standard` *`disabled`*\
|
||||
> **Disabled**: when the variable "[Override default parameters for option type](#define_default_params)" has the value "false"
|
||||
|
||||
### With modified value
|
||||
### UNIX filename
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Path**: default_params.unix_filename\
|
||||
> `standard`
|
||||
|
||||
| Variable | Description | Default value | Type | Access control | Validator |
|
||||
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------|----------------------------------|-----------------------------------------------------------------------------------------------|------------------|-----------------------------------------------------------------|
|
||||
| **<a id="default_params.unix_filename.allow_relative" name="default_params.unix_filename.allow_relative">default_params.unix_filename.allow_relative</a>**<br/>**Command line**: <br/>• --default_params.unix_filename.allow_relative<br/>• --default_params.unix_filename.no-allow_relative<br/>**Environment variable**: DEFAULT_PARAMS.UNIX_FILENAME.ALLOW_RELATIVE | This filename could be a relative path. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.unix_filename.test_existence" name="default_params.unix_filename.test_existence">default_params.unix_filename.test_existence</a>**<br/>**Command line**: <br/>• --default_params.unix_filename.test_existence<br/>• --default_params.unix_filename.no-test_existence<br/>**Environment variable**: DEFAULT_PARAMS.UNIX_FILENAME.TEST_EXISTENCE | This file must exist. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.unix_filename.types" name="default_params.unix_filename.types">default_params.unix_filename.types</a>**<br/>**Command line**: <br/>--default_params.unix_filename.types<br/>**Environment variable**: DEFAULT_PARAMS.UNIX_FILENAME.TYPES | File type allowed. | • file<br/>• directory | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) `multiple` | `standard` | `unique`<br/>**Choices**: <br/>• file<br/>• directory |
|
||||
|
||||
### IP
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Path**: default_params.ip\
|
||||
> `standard`
|
||||
|
||||
| Variable | Description | Default value | Type | Access control |
|
||||
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------|-----------------|-------------------------------------------------------------------------------------|------------------|
|
||||
| **<a id="default_params.ip.private_only" name="default_params.ip.private_only">default_params.ip.private_only</a>**<br/>**Command line**: <br/>• --default_params.ip.private_only<br/>• --default_params.ip.no-private_only<br/>**Environment variable**: DEFAULT_PARAMS.IP.PRIVATE_ONLY | Private IP are allowed. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.ip.allow_reserved" name="default_params.ip.allow_reserved">default_params.ip.allow_reserved</a>**<br/>**Command line**: <br/>• --default_params.ip.allow_reserved<br/>• --default_params.ip.no-allow_reserved<br/>**Environment variable**: DEFAULT_PARAMS.IP.ALLOW_RESERVED | Reserved IP are allowed. | true | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.ip.cidr" name="default_params.ip.cidr">default_params.ip.cidr</a>**<br/>**Command line**: <br/>• --default_params.ip.cidr<br/>• --default_params.ip.no-cidr<br/>**Environment variable**: DEFAULT_PARAMS.IP.CIDR | IP must be in CIDR format. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
|
||||
### CIDR
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Path**: default_params.cidr\
|
||||
> `standard`
|
||||
|
||||
| Variable | Description | Default value | Type | Access control |
|
||||
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------|-----------------|-------------------------------------------------------------------------------------|------------------|
|
||||
| **<a id="default_params.cidr.private_only" name="default_params.cidr.private_only">default_params.cidr.private_only</a>**<br/>**Command line**: <br/>• --default_params.cidr.private_only<br/>• --default_params.cidr.no-private_only<br/>**Environment variable**: DEFAULT_PARAMS.CIDR.PRIVATE_ONLY | Private IP are allowed. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.cidr.allow_reserved" name="default_params.cidr.allow_reserved">default_params.cidr.allow_reserved</a>**<br/>**Command line**: <br/>• --default_params.cidr.allow_reserved<br/>• --default_params.cidr.no-allow_reserved<br/>**Environment variable**: DEFAULT_PARAMS.CIDR.ALLOW_RESERVED | Reserved IP are allowed. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.cidr.cidr" name="default_params.cidr.cidr">default_params.cidr.cidr</a>**<br/>**Command line**: <br/>• --default_params.cidr.cidr<br/>• --default_params.cidr.no-cidr<br/>**Environment variable**: DEFAULT_PARAMS.CIDR.CIDR | IP must be in CIDR format. | true | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
|
||||
### Network
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Path**: default_params.network\
|
||||
> `standard`
|
||||
|
||||
| Variable | Description | Default value | Type | Access control |
|
||||
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------|-----------------|-------------------------------------------------------------------------------------|------------------|
|
||||
| **<a id="default_params.network.private_only" name="default_params.network.private_only">default_params.network.private_only</a>**<br/>**Command line**: <br/>• --default_params.network.private_only<br/>• --default_params.network.no-private_only<br/>**Environment variable**: DEFAULT_PARAMS.NETWORK.PRIVATE_ONLY | Private network are allowed. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.network.allow_reserved" name="default_params.network.allow_reserved">default_params.network.allow_reserved</a>**<br/>**Command line**: <br/>• --default_params.network.allow_reserved<br/>• --default_params.network.no-allow_reserved<br/>**Environment variable**: DEFAULT_PARAMS.NETWORK.ALLOW_RESERVED | Reserved network are allowed. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.network.cidr" name="default_params.network.cidr">default_params.network.cidr</a>**<br/>**Command line**: <br/>• --default_params.network.cidr<br/>• --default_params.network.no-cidr<br/>**Environment variable**: DEFAULT_PARAMS.NETWORK.CIDR | Network must be in CIDR format. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
|
||||
### Network CIDR
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Path**: default_params.network_cidr\
|
||||
> `standard`
|
||||
|
||||
| Variable | Description | Default value | Type | Access control |
|
||||
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------|-----------------|-------------------------------------------------------------------------------------|------------------|
|
||||
| **<a id="default_params.network_cidr.private_only" name="default_params.network_cidr.private_only">default_params.network_cidr.private_only</a>**<br/>**Command line**: <br/>• --default_params.network_cidr.private_only<br/>• --default_params.network_cidr.no-private_only<br/>**Environment variable**: DEFAULT_PARAMS.NETWORK_CIDR.PRIVATE_ONLY | Private network are allowed. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.network_cidr.allow_reserved" name="default_params.network_cidr.allow_reserved">default_params.network_cidr.allow_reserved</a>**<br/>**Command line**: <br/>• --default_params.network_cidr.allow_reserved<br/>• --default_params.network_cidr.no-allow_reserved<br/>**Environment variable**: DEFAULT_PARAMS.NETWORK_CIDR.ALLOW_RESERVED | Reserved network are allowed. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.network_cidr.cidr" name="default_params.network_cidr.cidr">default_params.network_cidr.cidr</a>**<br/>**Command line**: <br/>• --default_params.network_cidr.cidr<br/>• --default_params.network_cidr.no-cidr<br/>**Environment variable**: DEFAULT_PARAMS.NETWORK_CIDR.CIDR | Network must be in CIDR format. | true | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
|
||||
### Netbios
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Path**: default_params.netbios\
|
||||
> `standard`
|
||||
|
||||
| Variable | Description | Default value | Type | Access control | Validator |
|
||||
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------|-----------------|-------------------------------------------------------------------------------------|------------------|--------------------------------------------------------------------------------------------|
|
||||
| **<a id="default_params.netbios.type" name="default_params.netbios.type">default_params.netbios.type</a>**<br/>**Command line**: <br/>--default_params.netbios.type<br/>**Environment variable**: DEFAULT_PARAMS.NETBIOS.TYPE | Type of domainname. | netbios | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | **Choices**: <br/>• domainname<br/>• netbios<br/>• hostname<br/>• null |
|
||||
| **<a id="default_params.netbios.allow_without_dot" name="default_params.netbios.allow_without_dot">default_params.netbios.allow_without_dot</a>**<br/>**Command line**: <br/>• --default_params.netbios.allow_without_dot<br/>• --default_params.netbios.no-allow_without_dot<br/>**Environment variable**: DEFAULT_PARAMS.NETBIOS.ALLOW_WITHOUT_DOT | The domain name can be a hostname. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.netbios.test_existence" name="default_params.netbios.test_existence">default_params.netbios.test_existence</a>**<br/>**Command line**: <br/>• --default_params.netbios.test_existence<br/>• --default_params.netbios.no-test_existence<br/>**Environment variable**: DEFAULT_PARAMS.NETBIOS.TEST_EXISTENCE | The domain name must exist. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.netbios.allow_ip" name="default_params.netbios.allow_ip">default_params.netbios.allow_ip</a>**<br/>**Command line**: <br/>• --default_params.netbios.allow_ip<br/>• --default_params.netbios.no-allow_ip<br/>**Environment variable**: DEFAULT_PARAMS.NETBIOS.ALLOW_IP | The domain name can be an IP. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.netbios.allow_cidr_network" name="default_params.netbios.allow_cidr_network">default_params.netbios.allow_cidr_network</a>**<br/>**Command line**: <br/>• --default_params.netbios.allow_cidr_network<br/>• --default_params.netbios.no-allow_cidr_network<br/>**Environment variable**: DEFAULT_PARAMS.NETBIOS.ALLOW_CIDR_NETWORK | The domain name can be network in CIDR format. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.netbios.allow_startswith_dot" name="default_params.netbios.allow_startswith_dot">default_params.netbios.allow_startswith_dot</a>**<br/>**Command line**: <br/>• --default_params.netbios.allow_startswith_dot<br/>• --default_params.netbios.no-allow_startswith_dot<br/>**Environment variable**: DEFAULT_PARAMS.NETBIOS.ALLOW_STARTSWITH_DOT | The domain name can starts by a dot. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
|
||||
### Domainname
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Path**: default_params.domainname\
|
||||
> `standard`
|
||||
|
||||
| Variable | Description | Default value | Type | Access control | Validator |
|
||||
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------|-----------------|-------------------------------------------------------------------------------------|------------------|--------------------------------------------------------------------------------------------|
|
||||
| **<a id="default_params.domainname.type" name="default_params.domainname.type">default_params.domainname.type</a>**<br/>**Command line**: <br/>--default_params.domainname.type<br/>**Environment variable**: DEFAULT_PARAMS.DOMAINNAME.TYPE | Type of domainname. | domainname | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | **Choices**: <br/>• domainname<br/>• netbios<br/>• hostname<br/>• null |
|
||||
| **<a id="default_params.domainname.allow_without_dot" name="default_params.domainname.allow_without_dot">default_params.domainname.allow_without_dot</a>**<br/>**Command line**: <br/>• --default_params.domainname.allow_without_dot<br/>• --default_params.domainname.no-allow_without_dot<br/>**Environment variable**: DEFAULT_PARAMS.DOMAINNAME.ALLOW_WITHOUT_DOT | The domain name can be a hostname. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.domainname.test_existence" name="default_params.domainname.test_existence">default_params.domainname.test_existence</a>**<br/>**Command line**: <br/>• --default_params.domainname.test_existence<br/>• --default_params.domainname.no-test_existence<br/>**Environment variable**: DEFAULT_PARAMS.DOMAINNAME.TEST_EXISTENCE | The domain name must exist. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.domainname.allow_ip" name="default_params.domainname.allow_ip">default_params.domainname.allow_ip</a>**<br/>**Command line**: <br/>• --default_params.domainname.allow_ip<br/>• --default_params.domainname.no-allow_ip<br/>**Environment variable**: DEFAULT_PARAMS.DOMAINNAME.ALLOW_IP | The domain name can be an IP. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.domainname.allow_cidr_network" name="default_params.domainname.allow_cidr_network">default_params.domainname.allow_cidr_network</a>**<br/>**Command line**: <br/>• --default_params.domainname.allow_cidr_network<br/>• --default_params.domainname.no-allow_cidr_network<br/>**Environment variable**: DEFAULT_PARAMS.DOMAINNAME.ALLOW_CIDR_NETWORK | The domain name can be network in CIDR format. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.domainname.allow_startswith_dot" name="default_params.domainname.allow_startswith_dot">default_params.domainname.allow_startswith_dot</a>**<br/>**Command line**: <br/>• --default_params.domainname.allow_startswith_dot<br/>• --default_params.domainname.no-allow_startswith_dot<br/>**Environment variable**: DEFAULT_PARAMS.DOMAINNAME.ALLOW_STARTSWITH_DOT | The domain name can starts by a dot. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
|
||||
### Hostname
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Path**: default_params.hostname\
|
||||
> `standard`
|
||||
|
||||
| Variable | Description | Default value | Type | Access control | Validator |
|
||||
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------|-----------------|-------------------------------------------------------------------------------------|------------------|--------------------------------------------------------------------------------------------|
|
||||
| **<a id="default_params.hostname.type" name="default_params.hostname.type">default_params.hostname.type</a>**<br/>**Command line**: <br/>--default_params.hostname.type<br/>**Environment variable**: DEFAULT_PARAMS.HOSTNAME.TYPE | Type of domainname. | hostname | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | **Choices**: <br/>• domainname<br/>• netbios<br/>• hostname<br/>• null |
|
||||
| **<a id="default_params.hostname.allow_without_dot" name="default_params.hostname.allow_without_dot">default_params.hostname.allow_without_dot</a>**<br/>**Command line**: <br/>• --default_params.hostname.allow_without_dot<br/>• --default_params.hostname.no-allow_without_dot<br/>**Environment variable**: DEFAULT_PARAMS.HOSTNAME.ALLOW_WITHOUT_DOT | The domain name can be a hostname. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.hostname.test_existence" name="default_params.hostname.test_existence">default_params.hostname.test_existence</a>**<br/>**Command line**: <br/>• --default_params.hostname.test_existence<br/>• --default_params.hostname.no-test_existence<br/>**Environment variable**: DEFAULT_PARAMS.HOSTNAME.TEST_EXISTENCE | The domain name must exist. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.hostname.allow_ip" name="default_params.hostname.allow_ip">default_params.hostname.allow_ip</a>**<br/>**Command line**: <br/>• --default_params.hostname.allow_ip<br/>• --default_params.hostname.no-allow_ip<br/>**Environment variable**: DEFAULT_PARAMS.HOSTNAME.ALLOW_IP | The domain name can be an IP. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.hostname.allow_cidr_network" name="default_params.hostname.allow_cidr_network">default_params.hostname.allow_cidr_network</a>**<br/>**Command line**: <br/>• --default_params.hostname.allow_cidr_network<br/>• --default_params.hostname.no-allow_cidr_network<br/>**Environment variable**: DEFAULT_PARAMS.HOSTNAME.ALLOW_CIDR_NETWORK | The domain name can be network in CIDR format. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.hostname.allow_startswith_dot" name="default_params.hostname.allow_startswith_dot">default_params.hostname.allow_startswith_dot</a>**<br/>**Command line**: <br/>• --default_params.hostname.allow_startswith_dot<br/>• --default_params.hostname.no-allow_startswith_dot<br/>**Environment variable**: DEFAULT_PARAMS.HOSTNAME.ALLOW_STARTSWITH_DOT | The domain name can starts by a dot. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
|
||||
### Web address
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Path**: default_params.web_address\
|
||||
> `standard`
|
||||
|
||||
| Variable | Description | Default value | Type | Access control | Validator |
|
||||
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------|-----------------|-------------------------------------------------------------------------------------|------------------|--------------------------------------------------------------------------------------------|
|
||||
| **<a id="default_params.web_address.type" name="default_params.web_address.type">default_params.web_address.type</a>**<br/>**Command line**: <br/>--default_params.web_address.type<br/>**Environment variable**: DEFAULT_PARAMS.WEB_ADDRESS.TYPE | Type of domainname. | domainname | [`choice`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | **Choices**: <br/>• domainname<br/>• netbios<br/>• hostname<br/>• null |
|
||||
| **<a id="default_params.web_address.allow_without_dot" name="default_params.web_address.allow_without_dot">default_params.web_address.allow_without_dot</a>**<br/>**Command line**: <br/>• --default_params.web_address.allow_without_dot<br/>• --default_params.web_address.no-allow_without_dot<br/>**Environment variable**: DEFAULT_PARAMS.WEB_ADDRESS.ALLOW_WITHOUT_DOT | The domain name can be a hostname. | true | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.web_address.test_existence" name="default_params.web_address.test_existence">default_params.web_address.test_existence</a>**<br/>**Command line**: <br/>• --default_params.web_address.test_existence<br/>• --default_params.web_address.no-test_existence<br/>**Environment variable**: DEFAULT_PARAMS.WEB_ADDRESS.TEST_EXISTENCE | The domain name must exist. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.web_address.allow_ip" name="default_params.web_address.allow_ip">default_params.web_address.allow_ip</a>**<br/>**Command line**: <br/>• --default_params.web_address.allow_ip<br/>• --default_params.web_address.no-allow_ip<br/>**Environment variable**: DEFAULT_PARAMS.WEB_ADDRESS.ALLOW_IP | The domain name can be an IP. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.web_address.allow_cidr_network" name="default_params.web_address.allow_cidr_network">default_params.web_address.allow_cidr_network</a>**<br/>**Command line**: <br/>• --default_params.web_address.allow_cidr_network<br/>• --default_params.web_address.no-allow_cidr_network<br/>**Environment variable**: DEFAULT_PARAMS.WEB_ADDRESS.ALLOW_CIDR_NETWORK | The domain name can be network in CIDR format. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.web_address.allow_startswith_dot" name="default_params.web_address.allow_startswith_dot">default_params.web_address.allow_startswith_dot</a>**<br/>**Command line**: <br/>• --default_params.web_address.allow_startswith_dot<br/>• --default_params.web_address.no-allow_startswith_dot<br/>**Environment variable**: DEFAULT_PARAMS.WEB_ADDRESS.ALLOW_STARTSWITH_DOT | The domain name can starts by a dot. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.web_address.allow_range" name="default_params.web_address.allow_range">default_params.web_address.allow_range</a>**<br/>**Command line**: <br/>• --default_params.web_address.allow_range<br/>• --default_params.web_address.no-allow_range<br/>**Environment variable**: DEFAULT_PARAMS.WEB_ADDRESS.ALLOW_RANGE | Can be range of port. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.web_address.allow_protocol" name="default_params.web_address.allow_protocol">default_params.web_address.allow_protocol</a>**<br/>**Command line**: <br/>• --default_params.web_address.allow_protocol<br/>• --default_params.web_address.no-allow_protocol<br/>**Environment variable**: DEFAULT_PARAMS.WEB_ADDRESS.ALLOW_PROTOCOL | Can have the protocol. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.web_address.allow_zero" name="default_params.web_address.allow_zero">default_params.web_address.allow_zero</a>**<br/>**Command line**: <br/>• --default_params.web_address.allow_zero<br/>• --default_params.web_address.no-allow_zero<br/>**Environment variable**: DEFAULT_PARAMS.WEB_ADDRESS.ALLOW_ZERO | Port 0 is allowed. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.web_address.allow_wellknown" name="default_params.web_address.allow_wellknown">default_params.web_address.allow_wellknown</a>**<br/>**Command line**: <br/>• --default_params.web_address.allow_wellknown<br/>• --default_params.web_address.no-allow_wellknown<br/>**Environment variable**: DEFAULT_PARAMS.WEB_ADDRESS.ALLOW_WELLKNOWN | Well-known ports (1 to 1023) are allowed. | true | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.web_address.allow_registred" name="default_params.web_address.allow_registred">default_params.web_address.allow_registred</a>**<br/>**Command line**: <br/>• --default_params.web_address.allow_registred<br/>• --default_params.web_address.no-allow_registred<br/>**Environment variable**: DEFAULT_PARAMS.WEB_ADDRESS.ALLOW_REGISTRED | Registred ports (1024 to 49151) are allowed. | true | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
| **<a id="default_params.web_address.allow_private" name="default_params.web_address.allow_private">default_params.web_address.allow_private</a>**<br/>**Command line**: <br/>• --default_params.web_address.allow_private<br/>• --default_params.web_address.no-allow_private<br/>**Environment variable**: DEFAULT_PARAMS.WEB_ADDRESS.ALLOW_PRIVATE | Private ports (greater than 49152) are allowed. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` | |
|
||||
|
||||
### Port
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> **Path**: default_params.port\
|
||||
> `standard`
|
||||
|
||||
| Variable | Description | Default value | Type | Access control |
|
||||
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------|-----------------|-------------------------------------------------------------------------------------|------------------|
|
||||
| **<a id="default_params.port.allow_range" name="default_params.port.allow_range">default_params.port.allow_range</a>**<br/>**Command line**: <br/>• --default_params.port.allow_range<br/>• --default_params.port.no-allow_range<br/>**Environment variable**: DEFAULT_PARAMS.PORT.ALLOW_RANGE | Can be range of port. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.port.allow_protocol" name="default_params.port.allow_protocol">default_params.port.allow_protocol</a>**<br/>**Command line**: <br/>• --default_params.port.allow_protocol<br/>• --default_params.port.no-allow_protocol<br/>**Environment variable**: DEFAULT_PARAMS.PORT.ALLOW_PROTOCOL | Can have the protocol. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.port.allow_zero" name="default_params.port.allow_zero">default_params.port.allow_zero</a>**<br/>**Command line**: <br/>• --default_params.port.allow_zero<br/>• --default_params.port.no-allow_zero<br/>**Environment variable**: DEFAULT_PARAMS.PORT.ALLOW_ZERO | Port 0 is allowed. | false | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.port.allow_wellknown" name="default_params.port.allow_wellknown">default_params.port.allow_wellknown</a>**<br/>**Command line**: <br/>• --default_params.port.allow_wellknown<br/>• --default_params.port.no-allow_wellknown<br/>**Environment variable**: DEFAULT_PARAMS.PORT.ALLOW_WELLKNOWN | Well-known ports (1 to 1023) are allowed. | true | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.port.allow_registred" name="default_params.port.allow_registred">default_params.port.allow_registred</a>**<br/>**Command line**: <br/>• --default_params.port.allow_registred<br/>• --default_params.port.no-allow_registred<br/>**Environment variable**: DEFAULT_PARAMS.PORT.ALLOW_REGISTRED | Registred ports (1024 to 49151) are allowed. | true | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
| **<a id="default_params.port.allow_private" name="default_params.port.allow_private">default_params.port.allow_private</a>**<br/>**Command line**: <br/>• --default_params.port.allow_private<br/>• --default_params.port.no-allow_private<br/>**Environment variable**: DEFAULT_PARAMS.PORT.ALLOW_PRIVATE | Private ports (greater than 49152) are allowed. | true | [`boolean`](https://rougail.readthedocs.io/en/latest/variable.html#variables-types) | `standard` |
|
||||
|
||||
|
||||
Use [Tiramisu](https://framagit.org/tiramisu/tiramisu) API to change values:
|
||||
|
||||
```python
|
||||
from rougail import Rougail, RougailConfig
|
||||
from pprint import pprint
|
||||
|
||||
RougailConfig['dictionaries_dir'] = ['dict']
|
||||
rougail = Rougail()
|
||||
config = rougail.get_config()
|
||||
config.option('rougail.my_first_variable').value.set('modified_value')
|
||||
config.option('rougail.my_family.my_second_variable').value.set(2)
|
||||
pprint(config.value.get(), sort_dicts=False)
|
||||
```
|
||||
|
||||
The destination file is generated with new values:
|
||||
|
||||
```json
|
||||
{<TiramisuOption path="rougail">: {<TiramisuOption path="rougail.my_first_variable">: 'modified_value',
|
||||
<TiramisuOption path="rougail.my_family">: {<TiramisuOption path="rougail.my_family.my_second_variable">: 2}}}
|
||||
```
|
||||
|
||||
# Link
|
||||
|
||||
* [Documentation](https://rougail.readthedocs.io/en/latest/)
|
||||
* [Licence ](LICENSE)
|
||||
|
||||
# Related projects
|
||||
|
||||
* [Tiramisu](https://forge.cloud.silique.fr/gnunux/tiramisu)
|
||||
* [Risotto](https://cloud.silique.fr/gitea/risotto/risotto)
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -5,7 +5,7 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"POT-Creation-Date: 2024-11-04 12:04+0100\n"
|
||||
"POT-Creation-Date: 2026-01-21 08:42+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
|
@ -15,75 +15,437 @@ msgstr ""
|
|||
"Generated-By: pygettext.py 1.5\n"
|
||||
|
||||
|
||||
#: src/rougail/annotator/family.py:139
|
||||
#: src/rougail/annotator/family.py:152
|
||||
msgid "default variable mode \"{0}\" is not a valid mode, valid modes are {1}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/family.py:145
|
||||
#: src/rougail/annotator/family.py:158
|
||||
msgid "default family mode \"{0}\" is not a valid mode, valid modes are {1}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/family.py:177
|
||||
#: src/rougail/annotator/family.py:190
|
||||
msgid "mode \"{0}\" for \"{1}\" is not a valid mode, valid modes are {2}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/family.py:181
|
||||
#: src/rougail/annotator/family.py:194
|
||||
msgid "mode \"{0}\" for \"{1}\" is not a valid mode, no modes are available"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/family.py:245
|
||||
#: src/rougail/annotator/family.py:258
|
||||
msgid "the variable \"{0}\" is mandatory so in \"{1}\" mode but family has the higher family mode \"{2}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/family.py:283
|
||||
#: src/rougail/annotator/family.py:296
|
||||
msgid "the follower \"{0}\" is in \"{1}\" mode but leader have the higher mode \"{2}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/family.py:316
|
||||
#: src/rougail/annotator/family.py:329
|
||||
msgid "the family \"{0}\" is in \"{1}\" mode but variables and families inside have the higher modes \"{2}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/family.py:334
|
||||
#: src/rougail/annotator/family.py:347
|
||||
msgid "the variable \"{0}\" is in \"{1}\" mode but family has the higher family mode \"{2}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/value.py:77
|
||||
msgid "the follower \"{0}\" without multi attribute can only have one value"
|
||||
#: src/rougail/annotator/property.py:181
|
||||
msgid "invalid tag name \"{0}\" should only contains lowercase ascii character, number or _"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/value.py:93
|
||||
#: src/rougail/annotator/property.py:186
|
||||
msgid "invalid tag name \"{0}\" should not be a name of an existing mode"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/property.py:191
|
||||
msgid "invalid tag name \"{0}\" should not be the name of an available properties"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/value.py:78
|
||||
msgid "the follower \"{0}\" is not multi, so cannot have a list has default value"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/value.py:94
|
||||
msgid "the variable \"{0}\" is multi but has a non list default value"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/variable.py:189
|
||||
#: src/rougail/annotator/value.py:118
|
||||
msgid "the variable \"{0}\" is a \"choice\" variable but don't have any choice"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/value.py:137
|
||||
msgid "the variable \"{0}\" is a \"regexp\" variable but don't have any regexp"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/variable.py:93
|
||||
msgid "only \"unix_user\" or \"secret\" variable type can have \"secret_manager\" attribute, but \"{0}\" has type \"{1}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/variable.py:100
|
||||
msgid "the variable \"{0}\" has attribute \"secret_manager\" but is a multi variable"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/variable.py:105
|
||||
msgid "the variable \"{0}\" has attribute \"secret_manager\" so must not have default value"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/variable.py:159
|
||||
msgid "{0} values needed, but there are {{{{ var | length }}}}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/variable.py:160
|
||||
msgid "needs exactly {0} values"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/variable.py:162
|
||||
msgid "a maximum of {0} values are needed, but there are {{{{ var | length }}}}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/variable.py:163
|
||||
msgid "needs a maximum of {0} values"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/variable.py:167
|
||||
msgid "a minimum of {0} values are needed, but there are {{{{ var | length }}}}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/variable.py:168
|
||||
msgid "needs a minimum of {0} values"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/variable.py:246
|
||||
msgid "the \"{0}\" default value is a calculation with itself"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/variable.py:306
|
||||
msgid "the variable \"{0}\" has regexp attribut but has not the \"regexp\" type"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/variable.py:232
|
||||
#: src/rougail/annotator/variable.py:349
|
||||
msgid "the variable \"{0}\" has choices attribut but has not the \"choice\" type"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/annotator/variable.py:260
|
||||
#: src/rougail/annotator/variable.py:377
|
||||
msgid "the variable \"{0}\" has an unvalid default value \"{1}\" should be in {2}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert.py:281
|
||||
msgid "A variable or a family located in the \"{0}\" namespace shall not be used in the \"{1}\" namespace"
|
||||
#: src/rougail/config/__init__.py:272
|
||||
msgid "Default version of the structural file format"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert.py:475
|
||||
#: src/rougail/config/__init__.py:273
|
||||
msgid "This value is only used if the version is not set in the structural file"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:281
|
||||
msgid "File with personalize types"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:282
|
||||
msgid "This file contains personalize types in Rougail format for structure files"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:291
|
||||
msgid "File with functions"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:292
|
||||
msgid "This file contains filters and additional Jinja2 functions usable in structure files"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:303
|
||||
msgid "All modes level available"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:315
|
||||
msgid "Default mode for a family"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:321
|
||||
msgid "the first one defined in \"modes_level\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:327 src/rougail/config/__init__.py:354
|
||||
msgid "when no mode is defined in \"modes_level\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:334 src/rougail/config/__init__.py:361
|
||||
msgid "this mode must be available in \"modes_level\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:338
|
||||
msgid "Default mode for a variable"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:348
|
||||
msgid "if the variable \"modes_level\" is defined, the default value is the second available element, otherwise, the first"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:365
|
||||
msgid "Option name for the base option"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:370
|
||||
msgid "In cache file, do not importation of Tiramisu and other dependencies"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:375
|
||||
msgid "Store Tiramisu cache filename"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:376
|
||||
msgid ""
|
||||
"This file contains the Tiramisu instructions used internally to load the variables.\n"
|
||||
"\n"
|
||||
"This file can be used for debugging"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:386
|
||||
msgid "Name of internal functions that we can use as a function"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:392
|
||||
msgid "Name of extra annotators"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:398
|
||||
msgid "Suffix add to generated options name"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:404
|
||||
msgid "Every variables in calculation are optionals"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:408
|
||||
msgid "Loads redefine variables even if there don't already exists"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:412
|
||||
msgid "The secret manager"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:415
|
||||
msgid "The secret pattern to constructing the name of the item searched for in the secret manager"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:416
|
||||
msgid "The pattern is in Jinja2 format"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:425
|
||||
msgid "structural"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:426
|
||||
msgid "user datas"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:427
|
||||
msgid "output"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:448
|
||||
msgid "Select for {0}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:486
|
||||
msgid "outputs {0} did not allow user data"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:512
|
||||
msgid "Override default parameters for option type"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/config/__init__.py:515
|
||||
msgid "Default parameters for option type"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/convert.py:281
|
||||
msgid "unknown type {0} for {1}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert.py:1345
|
||||
msgid "duplicate dictionary file name {0}"
|
||||
#: src/rougail/convert/convert.py:444
|
||||
msgid "family \"{0}\" define multiple time"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert.py:1392
|
||||
#: src/rougail/convert/convert.py:715
|
||||
msgid "variable \"{0}\" define multiple time"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/convert.py:808 src/rougail/convert/convert.py:815
|
||||
msgid "params must be a dict for {0}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/convert.py:836
|
||||
msgid "\"{0}\" has an invalid \"params\" for {1}: {2}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/convert.py:850
|
||||
msgid "secret_manager must be a dict for {0}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/convert.py:1190
|
||||
msgid "Cannot execute annotate multiple time"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/error.py:67
|
||||
#: src/rougail/convert/convert.py:1197
|
||||
msgid "invalid \"structural\" definition ({0}), we cannot load any structural file!"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:132
|
||||
msgid "cannot find variable \"{0}\" defined in attribute \"{1}\" for \"{2}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:138
|
||||
msgid "the variable \"{0}\" is in fact a family in attribute \"{1}\" for \"{2}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:143
|
||||
#: src/rougail/convert/object_model.py:528
|
||||
msgid "unknown object \"{0}\" in attribute \"{1}\" for \"{2}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:162
|
||||
msgid "identifier parameter for \"{0}\" in \"{1}\" cannot be set none dynamic family"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:191
|
||||
msgid "cannot find variable \"{0}\" defined in \"{1}\" for \"{2}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:196
|
||||
msgid "variable \"{0}\" defined in \"{1}\" for \"{2}\" is a dynamic variable"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:213
|
||||
msgid "the variable \"{0}\" is not a follower, so cannot have index type for param in \"{1}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:263
|
||||
msgid "\"warnings\" are only available with attribute \"{self.attribute_name}\" for variable \"{self.path}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:325
|
||||
msgid "the variable \"{0}\" has a depreciated return_type \"{1}\", please use \"{2}\" instead in {3}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:413
|
||||
#: src/rougail/convert/object_model.py:447
|
||||
msgid "variable \"{0}\" has a calculating \"{1}\" with an invalid return_type, should be boolean or string, not \"{2}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:424
|
||||
msgid "the variable \"{0}\" has a return_type \"{1}\", for attribute \"{2}\" but has not description in {3}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:429
|
||||
msgid "value is invalid"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:523
|
||||
msgid "a variable \"{0}\" is needs in attribute \"{1}\" for \"{2}\" but it's a family"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:545
|
||||
msgid "variable \"{0}\" has an attribute \"{1}\" calculated with the unknown variable \"{2}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:593
|
||||
msgid "the variable \"{0}\" has an invalid \"{1}\" the variable \"{2}\" is in a sub dynamic option"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:602
|
||||
msgid "the leader \"{0}\" has an invalid \"{1}\" the follower \"{2}\" is a multi"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:644
|
||||
msgid "the variable \"{0}\" has an invalid attribute \"{1}\", the variable \"{2}\" must not be multi"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:658
|
||||
msgid "the variable \"{0}\" has an invalid attribute \"{1}\", the variable must not be a multi or the variable \"{2}\" must be multi"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:672
|
||||
msgid "the variable \"{0}\" has an invalid attribute \"{1}\", the variable must be a multi or the variable \"{2}\" must not be multi"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:686
|
||||
msgid "the variable \"{0}\" has an invalid attribute \"{1}\", the variable \"{2}\" is multi but is inside a list"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:708
|
||||
msgid "the variable \"{0}\" is waiting for a list as \"{1}\" but the attribute \"default\" is not a list (\"{2}\")"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:712
|
||||
msgid "the variable \"{0}\" is not waiting for a list as \"{1}\" but the attribute \"default\" is a list (\"{2}\")"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:737
|
||||
msgid "\"{0}\" attribut shall not have an \"optional\" attribute without the \"default\" attribute for variable \"{1}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:759
|
||||
msgid "variable \"{0}\" has a default value calculated with \"{1}\" which has incompatible type"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:805
|
||||
msgid "the variable \"{0}\" is waiting for a boolean as \"{1}\" but the attribute \"default\" is not a boolean (\"{2}\")"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:828
|
||||
msgid "\"when\" is not allowed in format version 1.0 for attribute \"{0}\" for variable \"{1}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:833
|
||||
msgid "the variable \"{0}\" has an invalid attribute \"{1}\", \"when\" and \"when_not\" cannot set together"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:841
|
||||
msgid "\"when_not\" is not allowed in format version 1.0 for attribute \"{0}\" for variable \"{1}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:852
|
||||
msgid "\"when\" or \"when_not\" is mandatory for the not boolean variable \"{0}\" in attribute \"{1}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:899
|
||||
msgid "cannot find variable \"{0}\" for the information \"{1}\" when calculating \"{2}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:904
|
||||
msgid "identifier not allowed for the information \"{0}\" when calculating \"{1}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:958
|
||||
msgid "\"when\" is not allowed in format version 1.0 for attribute \"{0}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:964
|
||||
#: src/rougail/convert/object_model.py:974
|
||||
msgid "the identifier has an invalid attribute \"{0}\", \"when\" and \"when_not\" cannot set together"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/object_model.py:1001
|
||||
msgid "the variable \"{0}\" is not a follower, so cannot have index type for \"{1}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/path.py:211
|
||||
msgid "A variable or a family located in the \"{0}\" namespace shall not be used in the \"{1}\" namespace"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/tiramisureflector.py:348
|
||||
msgid "variable param \"{0}\" has whole attribute but it's not allowed for external variable"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/tiramisureflector.py:351
|
||||
msgid "variable param \"{0}\" has dynamic attribute but it's not allowed for external variable"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/convert/tiramisureflector.py:360
|
||||
msgid "internal error, {0} is not a dynamic variable"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/error.py:61 src/rougail/tiramisu.py:237
|
||||
msgid "{0} in {1}"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -95,23 +457,368 @@ msgstr ""
|
|||
msgid "conflict alternative_name \"{0}\": \"{1}\" and \"{2}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/structural_commandline/annotator.py:95
|
||||
msgid "negative_description is mandatory for boolean variable, but \"{0}\" hasn't"
|
||||
#: src/rougail/structural_directory/__init__.py:130
|
||||
msgid "duplicate structural file name {0}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/structural_commandline/annotator.py:104
|
||||
msgid "negative_description is only available for boolean variable, but \"{0}\" is \"{1}\""
|
||||
#: src/rougail/structural_directory/config.py:32
|
||||
msgid "Main namespace name"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/update/update.py:738
|
||||
msgid "not a XML file: {0}"
|
||||
#: src/rougail/structural_directory/config.py:40
|
||||
msgid "directory or string is not in \"_.step.structural\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/utils.py:55
|
||||
#: src/rougail/structural_directory/config.py:43
|
||||
msgid "Directories where structural files are placed"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/structural_directory/config.py:60
|
||||
msgid "Sort structural from differents directories"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/structural_directory/config.py:69
|
||||
msgid "Namespaces are isolated"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/structural_directory/config.py:75
|
||||
msgid "directory or string is not in \"_.step.structural\" or \"_.main_namespace\" is not set"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/structural_directory/config.py:78
|
||||
msgid "Extra namespaces"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/structural_directory/config.py:87
|
||||
msgid "Extra namespace name"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/structural_directory/config.py:93
|
||||
msgid "Directories where extra structural files are placed"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/structural_directory/config.py:106
|
||||
msgid "directory is not in \"__.step.structural\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/structural_string/config.py:32
|
||||
msgid "Structural files contents"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/structural_string/config.py:33
|
||||
#: src/rougail/structural_string/config.py:51
|
||||
msgid "This variable is a list of string with YAML file format"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/structural_string/config.py:45
|
||||
msgid "string is not in \"_.step.structural\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/structural_string/config.py:50
|
||||
msgid "Extra structural contents"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/structural_string/config.py:58
|
||||
msgid "string is not in \"__.step.structural\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:85
|
||||
msgid "unknown boolean value \"{0}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:88
|
||||
msgid "IP must be in CIDR format"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:89
|
||||
msgid "private IP are allowed"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:90
|
||||
msgid "reserved IP are allowed"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:93
|
||||
msgid "network must be in CIDR format"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:94
|
||||
msgid "private network are allowed"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:95
|
||||
msgid "reserved network are allowed"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:98
|
||||
msgid "can be range of port"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:99
|
||||
msgid "can have the protocol"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:100
|
||||
msgid "port 0 is allowed"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:101
|
||||
msgid "well-known ports (1 to 1023) are allowed"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:102
|
||||
msgid "registred ports (1024 to 49151) are allowed"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:103
|
||||
msgid "private ports (greater than 49152) are allowed"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:106
|
||||
msgid "type of domainname"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:106
|
||||
msgid "type {0}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:107
|
||||
msgid "the domain name can starts by a dot"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:108
|
||||
msgid "the domain name can be a hostname"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:109
|
||||
msgid "the domain name can be an IP"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:110
|
||||
msgid "the domain name can be network in CIDR format"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:111
|
||||
msgid "the domain name must exist"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:121 src/rougail/tiramisu.py:127
|
||||
msgid "the minimum value"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:121 src/rougail/tiramisu.py:127
|
||||
msgid "the minimum value is {0}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:122 src/rougail/tiramisu.py:128
|
||||
msgid "the maximum value"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:122 src/rougail/tiramisu.py:128
|
||||
msgid "the maximum value is {0}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:137
|
||||
msgid "minimum characters length for the secret"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:137
|
||||
msgid "minimum length for the secret is {0} characters"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:138
|
||||
msgid "maximum characters length for the secret"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:138
|
||||
msgid "maximum length for the secret is {0} characters"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:139
|
||||
msgid "forbidden characters"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:139
|
||||
msgid "forbidden characters: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:146
|
||||
msgid "this filename could be a relative path"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:147
|
||||
msgid "this file must exist"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:148
|
||||
msgid "file type allowed"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:148
|
||||
msgid "file type allowed: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:438
|
||||
msgid "cannot calculate the variable \"{0}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:439
|
||||
msgid "the attribute \"{0}\" in {1} with the parameters \"{2}\" causes the error: {3}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:457
|
||||
msgid "cannot converting the variable \"{0}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:458
|
||||
msgid "\"{0}\" is an invalid {1}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/tiramisu.py:460
|
||||
msgid "the attribute \"{0}\" in {1} causes the error: {2}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/types.py:66
|
||||
msgid "type is not compatible with leadership family"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/types.py:68
|
||||
msgid "type is not compatible with dynamic family"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:104
|
||||
msgid "{0}, it will be ignored"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:155
|
||||
msgid "cannot load variable path \"{0}\", the identifier \"{1}\" is not valid in {2}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:239
|
||||
msgid "the variable contains secrets and should not be defined in {0}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:318
|
||||
msgid "it's a family so we cannot set the value {0}, it has been loading from {1}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:322
|
||||
msgid "it's a family so we cannot set the value {0}, it will be ignored when loading from {1}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:332
|
||||
msgid "it's a symlink option so we cannot set the value {0}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:334 src/rougail/user_data.py:364
|
||||
#: src/rougail/user_data.py:493 src/rougail/user_data.py:505
|
||||
#: src/rougail/user_data.py:518
|
||||
msgid "{0}, it has been loading from {1}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:336 src/rougail/user_data.py:368
|
||||
#: src/rougail/user_data.py:497 src/rougail/user_data.py:509
|
||||
#: src/rougail/user_data.py:520
|
||||
msgid "{0}, it will be ignored when loading from {1}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:341 src/rougail/user_data.py:346
|
||||
msgid "{0}, it has been loaded from {1}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:360
|
||||
msgid "variable or family \"{0}\" does not exist so cannot load \"{1}\""
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:377
|
||||
msgid "\"{0}\" is the name of a dynamic family, it has been loading from {1}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:381
|
||||
msgid "\"{0}\" is the name of a dynamic family, it will be ignored when loading from {1}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:387
|
||||
msgid "{0} loaded from {1}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:426
|
||||
msgid "variable {0} at index \"{1}\" is {2}, it has been loading from {3}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:430
|
||||
msgid "variable {0} at index \"{1}\" is {2}, it will be ignored when loading from {3}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:443
|
||||
msgid "family {0} is {1}, {2} at index \"{3}\", it has been loading from {4}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:447
|
||||
msgid "family {0} is {1}, {2} at index \"{3}\", it will be ignored when loading from {4}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:462
|
||||
msgid "variable has propery {0}, it has been loading from {1}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:466
|
||||
msgid "variable has property {0}, it will be ignored when loading from {1}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:476
|
||||
msgid "family {0} has property {1}, so cannot access to {2}, it has been loading from {3}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:480
|
||||
msgid "family {0} has property {1}, so cannot access to {2}, it will be ignored when loading from {3}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:525
|
||||
msgid "the value {0} is an invalid {1}, {2}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:531
|
||||
msgid ", it has been loading from {0}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:533
|
||||
msgid ", it will be ignored when loading from {0}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:566
|
||||
msgid "loaded from {0}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/user_data.py:574
|
||||
msgid "{0} (the search key is \"{1}\")"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/utils.py:56
|
||||
msgid "invalid variable or family name \"{0}\" must only contains lowercase ascii character, number or _"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/utils.py:117
|
||||
msgid "error in jinja \"{0}\" for the variable \"{1}\": {2}"
|
||||
#: src/rougail/utils.py:104
|
||||
msgid "error for the variable \"{1}\" in jinja \"{0}\": {2}"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/utils.py:212
|
||||
msgid "mandatory"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/utils.py:213
|
||||
msgid "hidden"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/utils.py:214
|
||||
msgid "disabled"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/utils.py:215
|
||||
msgid "unique"
|
||||
msgstr ""
|
||||
|
||||
#: src/rougail/utils.py:216
|
||||
msgid "auto modified"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -1,50 +1,18 @@
|
|||
[build-system]
|
||||
build-backend = "flit_core.buildapi"
|
||||
requires = ["flit_core >=3.8.0,<4"]
|
||||
|
||||
[project]
|
||||
name = "rougail"
|
||||
version = "1.1.1"
|
||||
authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
|
||||
readme = "README.md"
|
||||
description = "A consistency handling system that was initially designed in the configuration management"
|
||||
requires-python = ">=3.8"
|
||||
classifiers = [
|
||||
"License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3.8",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Operating System :: OS Independent",
|
||||
"Natural Language :: English",
|
||||
"Natural Language :: French",
|
||||
|
||||
]
|
||||
dependencies = [
|
||||
"ruamel.yaml ~= 0.18.6",
|
||||
"pydantic ~= 2.9.2",
|
||||
"jinja2 ~= 3.1.4",
|
||||
"tiramisu >=5.0,<6"
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
"pylint ~= 3.0.3",
|
||||
"pytest ~= 8.2.2",
|
||||
"lxml ~= 5.2.2"
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Home = "https://forge.cloud.silique.fr/stove/rougail"
|
||||
|
||||
version = "1.2.0a60"
|
||||
|
||||
[tool.commitizen]
|
||||
name = "cz_conventional_commits"
|
||||
tag_format = "$version"
|
||||
version_scheme = "pep440"
|
||||
version_provider = "pep621"
|
||||
version_files = [
|
||||
"src/rougail/__version__.py",
|
||||
"rougail-pyproject.toml:version",
|
||||
"rougail-pyproject.toml:rougail-base == ",
|
||||
"rougail-base-pyproject.toml:version",
|
||||
]
|
||||
update_changelog_on_bump = true
|
||||
changelog_merge_prerelease = true
|
||||
|
||||
|
|
|
|||
52
rougail-base-pyproject.toml
Normal file
52
rougail-base-pyproject.toml
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
[build-system]
|
||||
build-backend = "flit_core.buildapi"
|
||||
requires = ["flit_core >=3.8.0,<4"]
|
||||
|
||||
[project]
|
||||
name = "rougail-base"
|
||||
version = "1.2.0a60"
|
||||
authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
|
||||
readme = "README.md"
|
||||
description = "A consistency handling system that was initially designed in the configuration management"
|
||||
requires-python = ">=3.10"
|
||||
license = {file = "LICENSE"}
|
||||
classifiers = [
|
||||
"License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Programming Language :: Python :: 3.14",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Operating System :: OS Independent",
|
||||
"Natural Language :: English",
|
||||
"Natural Language :: French",
|
||||
|
||||
]
|
||||
dependencies = [
|
||||
"jinja2 ~= 3.1.4",
|
||||
"tiramisu ~= 5.0"
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
"pylint ~= 3.0.3",
|
||||
"pytest ~= 8.2.2",
|
||||
]
|
||||
|
||||
[tool.flit.module]
|
||||
name = "rougail"
|
||||
|
||||
[tool.flit.sdist]
|
||||
exclude = [
|
||||
"src/rougail/annotator",
|
||||
"src/rougail/config",
|
||||
"src/rougail/convert",
|
||||
"src/rougail/structural_commandline",
|
||||
"src/rougail/structural_directory",
|
||||
"src/rougail/update",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Home = "https://forge.cloud.silique.fr/stove/rougail"
|
||||
35
rougail-pyproject.toml
Normal file
35
rougail-pyproject.toml
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
[build-system]
|
||||
build-backend = "flit_core.buildapi"
|
||||
requires = ["flit_core >=3.8.0,<4"]
|
||||
|
||||
[project]
|
||||
name = "rougail"
|
||||
version = "1.2.0a60"
|
||||
authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
|
||||
description = "A consistency handling system that was initially designed in the configuration management"
|
||||
classifiers = [
|
||||
"License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
|
||||
"Programming Language :: Python",
|
||||
"Operating System :: OS Independent",
|
||||
"Natural Language :: English",
|
||||
"Natural Language :: French",
|
||||
|
||||
]
|
||||
dependencies = [
|
||||
"ruamel.yaml ~= 0.18.6",
|
||||
"pydantic ~= 2.9.2",
|
||||
"rougail-base == 1.2.0a60",
|
||||
]
|
||||
|
||||
[tool.flit.sdist]
|
||||
exclude = [
|
||||
"src/rougail/error.py",
|
||||
"src/rougail/i18n.py",
|
||||
"src/rougail/tiramisu.py",
|
||||
"src/rougail/user_datas.py",
|
||||
"src/rougail/utils.py",
|
||||
"src/rougail/__version__.py",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Home = "https://forge.cloud.silique.fr/stove/rougail"
|
||||
|
|
@ -9,7 +9,7 @@ Cadoles (http://www.cadoles.com)
|
|||
Copyright (C) 2019-2021
|
||||
|
||||
Silique (https://www.silique.fr)
|
||||
Copyright (C) 2022-2024
|
||||
Copyright (C) 2022-2026
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
|
|
@ -25,302 +25,12 @@ You should have received a copy of the GNU Lesser General Public License
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from tiramisu import Config, undefined
|
||||
from tiramisu.error import PropertiesOptionError, LeadershipError, ConfigError
|
||||
from warnings import warn
|
||||
from typing import List
|
||||
from re import compile, findall
|
||||
from .__version__ import __version__
|
||||
|
||||
from .convert import RougailConvert
|
||||
from .config import RougailConfig
|
||||
from .update import RougailUpgrade
|
||||
from .object_model import CONVERT_OPTION
|
||||
from .utils import normalize_family
|
||||
try:
|
||||
from .convert import Rougail
|
||||
from .config import RougailConfig
|
||||
|
||||
|
||||
def tiramisu_display_name(
|
||||
kls,
|
||||
subconfig,
|
||||
with_quote: bool = False,
|
||||
) -> str:
|
||||
"""Replace the Tiramisu display_name function to display path + description"""
|
||||
doc = kls._get_information(subconfig, "doc", None)
|
||||
comment = f" ({doc})" if doc and doc != kls.impl_getname() else ""
|
||||
if "{{ identifier }}" in comment:
|
||||
comment = comment.replace("{{ identifier }}", str(subconfig.identifiers[-1]))
|
||||
path = kls.impl_getpath()
|
||||
if "{{ identifier }}" in path and subconfig.identifiers:
|
||||
path = path.replace(
|
||||
"{{ identifier }}", normalize_family(str(subconfig.identifiers[-1]))
|
||||
)
|
||||
if with_quote:
|
||||
return f'"{path}"{comment}'
|
||||
return f"{path}{comment}"
|
||||
|
||||
|
||||
class Rougail:
|
||||
"""Main Rougail object"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
rougailconfig=None,
|
||||
) -> None:
|
||||
if rougailconfig is None:
|
||||
rougailconfig = RougailConfig
|
||||
self.rougailconfig = rougailconfig
|
||||
self.converted = RougailConvert(self.rougailconfig)
|
||||
self.config = None
|
||||
|
||||
def add_path_prefix(
|
||||
self,
|
||||
path_prefix: str,
|
||||
) -> None:
|
||||
"""Add a prefix"""
|
||||
self.converted.load_config()
|
||||
self.converted.parse_directories(path_prefix)
|
||||
|
||||
def run(self):
|
||||
"""Get Tiramisu Config"""
|
||||
if not self.config:
|
||||
tiram_obj = self.converted.save(self.rougailconfig["tiramisu_cache"])
|
||||
optiondescription = {}
|
||||
custom_types = {
|
||||
custom.__name__: custom
|
||||
for custom in self.rougailconfig["custom_types"].values()
|
||||
}
|
||||
exec(tiram_obj, custom_types, optiondescription) # pylint: disable=W0122
|
||||
self.config = Config(
|
||||
optiondescription["option_0"],
|
||||
display_name=tiramisu_display_name,
|
||||
)
|
||||
self.config.property.read_write()
|
||||
return self.config
|
||||
|
||||
def get_config(self):
|
||||
warn(
|
||||
"get_config is deprecated, use run instead",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.run()
|
||||
|
||||
def user_datas(self, user_datas: List[dict]):
|
||||
values = {}
|
||||
errors = []
|
||||
warnings = []
|
||||
for datas in user_datas:
|
||||
options = datas.get("options", {})
|
||||
for name, data in datas.get("values", {}).items():
|
||||
values[name] = {
|
||||
"values": data,
|
||||
"options": options.copy(),
|
||||
}
|
||||
errors.extend(datas.get("errors", []))
|
||||
warnings.extend(datas.get("warnings", []))
|
||||
self._auto_configure_dynamics(values)
|
||||
while values:
|
||||
value_is_set = False
|
||||
for option in self._get_variable(self.config):
|
||||
path = option.path()
|
||||
if path not in values:
|
||||
path = path.upper()
|
||||
options = values.get(path, {}).get("options", {})
|
||||
if path not in values or options.get("upper") is not True:
|
||||
continue
|
||||
else:
|
||||
options = values[path].get("options", {})
|
||||
value = values[path]["values"]
|
||||
if option.ismulti():
|
||||
if options.get("multi_separator") and not isinstance(value, list):
|
||||
value = value.split(options["multi_separator"])
|
||||
values[path]["values"] = value
|
||||
if options.get("needs_convert"):
|
||||
value = [convert_value(option, val) for val in value]
|
||||
values[path]["values"] = value
|
||||
values[path]["options"]["needs_convert"] = False
|
||||
elif options.get("needs_convert"):
|
||||
value = convert_value(option, value)
|
||||
index = option.index()
|
||||
if index is not None:
|
||||
if not isinstance(value, list) or index >= len(value):
|
||||
continue
|
||||
value = value[index]
|
||||
try:
|
||||
option.value.set(value)
|
||||
value_is_set = True
|
||||
if index is not None:
|
||||
values[path]["values"][index] = undefined
|
||||
if set(values[path]["values"]) == {undefined}:
|
||||
values.pop(path)
|
||||
else:
|
||||
values.pop(path)
|
||||
except Exception as err:
|
||||
if path != option.path():
|
||||
values[option.path()] = values.pop(path)
|
||||
if not value_is_set:
|
||||
break
|
||||
for path, data in values.items():
|
||||
try:
|
||||
option = self.config.option(path)
|
||||
value = data["values"]
|
||||
if option.isfollower():
|
||||
for index, val in enumerate(value):
|
||||
if val is undefined:
|
||||
continue
|
||||
self.config.option(path, index).value.set(val)
|
||||
else:
|
||||
option.value.set(value)
|
||||
except AttributeError as err:
|
||||
errors.append(str(err))
|
||||
except (ValueError, LeadershipError) as err:
|
||||
# errors.append(str(err).replace('"', "'"))
|
||||
errors.append(str(err))
|
||||
except PropertiesOptionError as err:
|
||||
# warnings.append(f'"{err}" but is defined in "{self.filename}"')
|
||||
warnings.append(str(err))
|
||||
return {
|
||||
"errors": errors,
|
||||
"warnings": warnings,
|
||||
}
|
||||
|
||||
def _get_variable(self, config):
|
||||
for subconfig in config:
|
||||
if subconfig.isoptiondescription():
|
||||
yield from self._get_variable(subconfig)
|
||||
else:
|
||||
yield subconfig
|
||||
|
||||
def _auto_configure_dynamics(
|
||||
self,
|
||||
values,
|
||||
):
|
||||
cache = {}
|
||||
added = []
|
||||
for path, data in list(values.items()):
|
||||
value = data["values"]
|
||||
# for value in data['values'].items():
|
||||
try:
|
||||
option = self.config.option(path)
|
||||
option.name()
|
||||
except (ConfigError, PropertiesOptionError):
|
||||
pass
|
||||
except AttributeError:
|
||||
config = self.config
|
||||
current_path = ""
|
||||
identifiers = []
|
||||
for name in path.split(".")[:-1]:
|
||||
if current_path:
|
||||
current_path += "."
|
||||
current_path += name
|
||||
if current_path in cache:
|
||||
config, identifier = cache[current_path]
|
||||
identifiers.append(identifier)
|
||||
else:
|
||||
tconfig = config.option(name)
|
||||
try:
|
||||
tconfig.group_type()
|
||||
config = tconfig
|
||||
except AttributeError:
|
||||
for tconfig in config.list(uncalculated=True):
|
||||
if tconfig.isdynamic(only_self=True):
|
||||
identifier = self._get_identifier(
|
||||
tconfig.name(), name
|
||||
)
|
||||
if identifier is None:
|
||||
continue
|
||||
dynamic_variable = tconfig.information.get(
|
||||
"dynamic_variable",
|
||||
None,
|
||||
)
|
||||
if not dynamic_variable:
|
||||
continue
|
||||
option_type = self.config.option(
|
||||
dynamic_variable
|
||||
).information.get("type")
|
||||
if identifiers:
|
||||
for s in identifiers:
|
||||
dynamic_variable = dynamic_variable.replace(
|
||||
"{{ identifier }}", str(s), 1
|
||||
)
|
||||
if dynamic_variable not in values:
|
||||
values[dynamic_variable] = {"values": []}
|
||||
added.append(dynamic_variable)
|
||||
elif dynamic_variable not in added:
|
||||
continue
|
||||
config = tconfig
|
||||
# option_type = option.information.get('type')
|
||||
typ = CONVERT_OPTION.get(option_type, {}).get(
|
||||
"func"
|
||||
)
|
||||
if typ:
|
||||
identifier = typ(identifier)
|
||||
if (
|
||||
identifier
|
||||
not in values[dynamic_variable]["values"]
|
||||
):
|
||||
values[dynamic_variable]["values"].append(
|
||||
identifier
|
||||
)
|
||||
identifiers.append(identifier)
|
||||
cache[current_path] = config, identifier
|
||||
break
|
||||
else:
|
||||
if option.isdynamic():
|
||||
parent_option = self.config.option(path.rsplit(".", 1)[0])
|
||||
identifiers = self._get_identifier(
|
||||
parent_option.name(uncalculated=True),
|
||||
parent_option.name(),
|
||||
)
|
||||
dynamic_variable = None
|
||||
while True:
|
||||
dynamic_variable = parent_option.information.get(
|
||||
"dynamic_variable",
|
||||
None,
|
||||
)
|
||||
if dynamic_variable:
|
||||
break
|
||||
parent_option = self.config.option(
|
||||
parent_option.path().rsplit(".", 1)[0]
|
||||
)
|
||||
if "." not in parent_option.path():
|
||||
parent_option = None
|
||||
break
|
||||
if not parent_option:
|
||||
continue
|
||||
identifiers = parent_option.identifiers()
|
||||
for identifier in identifiers:
|
||||
dynamic_variable = dynamic_variable.replace(
|
||||
"{{ identifier }}", str(identifier), 1
|
||||
)
|
||||
if dynamic_variable not in values:
|
||||
values[dynamic_variable] = {"values": []}
|
||||
added.append(dynamic_variable)
|
||||
elif dynamic_variable not in added:
|
||||
continue
|
||||
option_type = option.information.get("type")
|
||||
typ = CONVERT_OPTION.get(option_type, {}).get("func")
|
||||
if typ:
|
||||
identifier = typ(identifier)
|
||||
if identifier not in values[dynamic_variable]["values"]:
|
||||
values[dynamic_variable]["values"].append(identifier)
|
||||
cache[option.path()] = option, identifier
|
||||
|
||||
def _get_identifier(self, true_name, name) -> str:
|
||||
regexp = true_name.replace("{{ identifier }}", "(.*)")
|
||||
finded = findall(regexp, name)
|
||||
if len(finded) != 1 or not finded[0]:
|
||||
return
|
||||
return finded[0]
|
||||
|
||||
|
||||
def convert_value(option, value):
|
||||
if value == "":
|
||||
return None
|
||||
option_type = option.information.get("type")
|
||||
func = CONVERT_OPTION.get(option_type, {}).get("func")
|
||||
if func:
|
||||
return func(value)
|
||||
return value
|
||||
|
||||
|
||||
__all__ = ("Rougail", "RougailConfig", "RougailUpgrade")
|
||||
__all__ = ("Rougail", "RougailConfig", "__version__")
|
||||
except ModuleNotFoundError as err:
|
||||
__all__ = ("__version__",)
|
||||
|
|
|
|||
1
src/rougail/__version__.py
Normal file
1
src/rougail/__version__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
__version__ = "1.2.0a60"
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
"""Annotate dictionaries
|
||||
"""Annotate structural file
|
||||
|
||||
Created by:
|
||||
EOLE (http://eole.orion.education.fr)
|
||||
|
|
@ -9,7 +9,7 @@ Cadoles (http://www.cadoles.com)
|
|||
Copyright (C) 2019-2021
|
||||
|
||||
Silique (https://www.silique.fr)
|
||||
Copyright (C) 2022-2024
|
||||
Copyright (C) 2022-2026
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
|
|
@ -71,16 +71,38 @@ class SpaceAnnotator: # pylint: disable=R0903
|
|||
if extra_annotator in ANNOTATORS:
|
||||
continue
|
||||
get_annotators(ANNOTATORS, extra_annotator)
|
||||
for plugin in objectspace.plugins:
|
||||
for structural in objectspace.structurals:
|
||||
try:
|
||||
get_annotators(ANNOTATORS, f"rougail.{plugin}", "annotator")
|
||||
get_annotators(
|
||||
ANNOTATORS, f"rougail.structural_{structural}", "annotator"
|
||||
)
|
||||
except ModuleNotFoundError:
|
||||
pass
|
||||
for user_data in objectspace.user_data:
|
||||
try:
|
||||
get_annotators(
|
||||
ANNOTATORS, f"rougail.user_data_{user_data}", "annotator"
|
||||
)
|
||||
except ModuleNotFoundError:
|
||||
pass
|
||||
if objectspace.output:
|
||||
try:
|
||||
get_annotators(
|
||||
ANNOTATORS, f"rougail.output_{objectspace.output}", "annotator"
|
||||
)
|
||||
except ModuleNotFoundError:
|
||||
pass
|
||||
annotators = ANNOTATORS["rougail.annotator"].copy()
|
||||
for extra_annotator in objectspace.extra_annotators:
|
||||
annotators.extend(ANNOTATORS[extra_annotator])
|
||||
for plugin in objectspace.plugins:
|
||||
annotators.extend(ANNOTATORS[f"rougail.{plugin}.annotator"])
|
||||
for structural in objectspace.structurals:
|
||||
annotators.extend(ANNOTATORS[f"rougail.structural_{structural}.annotator"])
|
||||
for user_data in objectspace.user_data:
|
||||
annotators.extend(ANNOTATORS[f"rougail.user_data_{user_data}.annotator"])
|
||||
if objectspace.output:
|
||||
annotators.extend(
|
||||
ANNOTATORS[f"rougail.output_{objectspace.output}.annotator"]
|
||||
)
|
||||
annotators = sorted(annotators, key=get_level)
|
||||
functions = {}
|
||||
functions_files = objectspace.functions_files
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ Cadoles (http://www.cadoles.com)
|
|||
Copyright (C) 2019-2021
|
||||
|
||||
Silique (https://www.silique.fr)
|
||||
Copyright (C) 2022-2024
|
||||
Copyright (C) 2022-2026
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
|
|
@ -29,7 +29,7 @@ from typing import Optional
|
|||
from rougail.i18n import _
|
||||
from rougail.error import DictConsistencyError
|
||||
from rougail.annotator.variable import Walk
|
||||
from rougail.object_model import VariableCalculation
|
||||
from rougail.convert.object_model import VariableCalculation
|
||||
|
||||
|
||||
class Mode: # pylint: disable=R0903
|
||||
|
|
@ -122,14 +122,27 @@ class Annotator(Walk):
|
|||
for family in self.get_families():
|
||||
if not family.description:
|
||||
family.description = family.name
|
||||
self.objectspace.forced_descriptions.append(family.path)
|
||||
if family.type == "dynamic" and isinstance(
|
||||
family.dynamic, VariableCalculation
|
||||
):
|
||||
path = family.dynamic.variable
|
||||
if (
|
||||
family.version != "1.0"
|
||||
and self.objectspace.paths.regexp_relative.search(path)
|
||||
):
|
||||
path = self.objectspace.paths.get_full_path(
|
||||
family.dynamic.variable,
|
||||
family.path,
|
||||
)
|
||||
if family.version == "1.0" and "{{ suffix }}" in path:
|
||||
path = path.replace("{{ suffix }}", "{{ identifier }}")
|
||||
self.objectspace.dynamics_variable.setdefault(path, []).append(
|
||||
family.path
|
||||
)
|
||||
self.objectspace.informations.add(family.path, "dynamic_variable", path)
|
||||
if family.xmlfiles:
|
||||
self.objectspace.informations.add(family.path, "ymlfiles", family.xmlfiles)
|
||||
|
||||
def change_modes(self):
|
||||
"""change the mode of variables"""
|
||||
|
|
@ -333,7 +346,7 @@ class Annotator(Walk):
|
|||
if self._has_mode(variable):
|
||||
msg = _(
|
||||
'the variable "{0}" is in "{1}" mode but family has the higher family mode "{2}"'
|
||||
).format(variable.name, variable_mode, family_mode)
|
||||
).format(variable.path, variable_mode, family_mode)
|
||||
raise DictConsistencyError(msg, 61, variable.xmlfiles)
|
||||
self._set_auto_mode(variable, family_mode)
|
||||
if not variable.mode:
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ Cadoles (http://www.cadoles.com)
|
|||
Copyright (C) 2019-2021
|
||||
|
||||
Silique (https://www.silique.fr)
|
||||
Copyright (C) 2022-2024
|
||||
Copyright (C) 2022-2026
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
|
|
@ -25,11 +25,14 @@ You should have received a copy of the GNU Lesser General Public License
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from typing import Union
|
||||
from typing import Union, List
|
||||
from tiramisu.setting import PROPERTIES_MAKE_SENSE
|
||||
from rougail.i18n import _
|
||||
from rougail.error import DictConsistencyError
|
||||
from rougail.annotator.variable import Walk
|
||||
from rougail.object_model import Calculation
|
||||
from rougail.convert.object_model import Calculation
|
||||
from rougail.utils import NAME_REGEXP
|
||||
from rougail.convert.object_model import VariableCalculation
|
||||
|
||||
|
||||
PROPERTIES = (
|
||||
|
|
@ -49,33 +52,56 @@ class Annotator(Walk):
|
|||
|
||||
def __init__(self, objectspace, *args) -> None:
|
||||
self.objectspace = objectspace
|
||||
if not self.objectspace.paths:
|
||||
return
|
||||
self.frozen = {}
|
||||
if self.objectspace.paths:
|
||||
self.variables_default_transitive = []
|
||||
self.convert_leadership()
|
||||
self.convert_family()
|
||||
self.convert_variable()
|
||||
|
||||
def convert_leadership(self) -> None:
|
||||
for variable_path in self.objectspace.leaders:
|
||||
variable = self.objectspace.paths[variable_path]
|
||||
if variable.hidden:
|
||||
family = self.objectspace.paths[variable.path.rsplit(".", 1)[0]]
|
||||
hidden = variable.hidden
|
||||
if hidden is not True:
|
||||
hidden = hidden.model_copy()
|
||||
if hidden.ori_path is None:
|
||||
hidden.ori_path = variable_path
|
||||
family.hidden = hidden
|
||||
variable.hidden = None
|
||||
|
||||
def convert_family(self) -> None:
|
||||
"""convert families"""
|
||||
for family in self.get_families():
|
||||
self._convert_property(family)
|
||||
self.family_variable_property(family)
|
||||
# collect for force_default_on_freeze
|
||||
if family.hidden:
|
||||
self.set_variable_frozen(
|
||||
if family.hidden is True:
|
||||
frozen = True
|
||||
else:
|
||||
frozen = family.hidden.model_copy()
|
||||
frozen.attribute_name = "frozen"
|
||||
if frozen.ori_path is None:
|
||||
frozen.ori_path = family.path
|
||||
self.set_variable_frozen_inside_family(
|
||||
family.path,
|
||||
family.hidden,
|
||||
frozen,
|
||||
)
|
||||
|
||||
def set_variable_frozen(
|
||||
def set_variable_frozen_inside_family(
|
||||
self,
|
||||
family_path: str,
|
||||
hidden: Union[bool, Calculation],
|
||||
frozen: Union[bool, Calculation],
|
||||
) -> None:
|
||||
for variable_path in self.objectspace.parents[family_path]:
|
||||
if variable_path in self.objectspace.families:
|
||||
# it's a family
|
||||
self.set_variable_frozen(
|
||||
self.set_variable_frozen_inside_family(
|
||||
variable_path,
|
||||
hidden,
|
||||
frozen,
|
||||
)
|
||||
else:
|
||||
# it's a variable
|
||||
|
|
@ -84,51 +110,48 @@ class Annotator(Walk):
|
|||
if (
|
||||
self.frozen.get(variable.path) is True
|
||||
or variable.hidden is True
|
||||
or hidden is True
|
||||
or frozen is True
|
||||
):
|
||||
self.frozen[variable.path] = True
|
||||
elif variable.path in self.frozen:
|
||||
self.frozen[variable.path].append(hidden)
|
||||
else:
|
||||
self.frozen[variable.path] = [hidden]
|
||||
if variable.path in self.frozen:
|
||||
if not isinstance(self.frozen[variable.path], list):
|
||||
self.frozen[variable.path] = [frozen]
|
||||
self.frozen[variable.path].append(frozen)
|
||||
else:
|
||||
self.frozen[variable.path] = frozen
|
||||
|
||||
def convert_variable(self) -> None:
|
||||
"""convert variables"""
|
||||
for variable in self.get_variables():
|
||||
if variable.path.startswith("services."):
|
||||
continue
|
||||
if variable.type == "symlink":
|
||||
continue
|
||||
self._convert_variable_property(variable)
|
||||
self.convert_variable_property(variable)
|
||||
|
||||
def _convert_variable_property(
|
||||
def convert_variable_property(
|
||||
self,
|
||||
variable: dict,
|
||||
) -> None:
|
||||
"""convert properties"""
|
||||
path = variable.path
|
||||
self._convert_property(variable)
|
||||
self.family_variable_property(variable)
|
||||
if variable.hidden:
|
||||
if variable.hidden is True:
|
||||
self.frozen[path] = True
|
||||
elif self.frozen.get(path) is not True:
|
||||
self.frozen.setdefault(path, []).append(variable.hidden)
|
||||
frozen = variable.hidden.model_copy()
|
||||
frozen.attribute_name = "frozen"
|
||||
if frozen.ori_path is None:
|
||||
frozen.ori_path = path
|
||||
if path in self.frozen:
|
||||
frozen = self.frozen[path]
|
||||
if frozen is True:
|
||||
value = True
|
||||
if not isinstance(self.frozen, list):
|
||||
self.frozen[path] = [self.frozen[path]]
|
||||
self.frozen[path].append(frozen)
|
||||
else:
|
||||
value = []
|
||||
for calculation in frozen:
|
||||
calculation_copy = calculation.copy()
|
||||
calculation_copy.attribute_name = "frozen"
|
||||
calculation_copy.ori_path = calculation_copy.path
|
||||
calculation_copy.path = path
|
||||
value.append(calculation_copy)
|
||||
if len(value) == 1:
|
||||
value = value[0]
|
||||
self.objectspace.properties.add(path, "frozen", value)
|
||||
if not variable.auto_save:
|
||||
self.frozen[path] = frozen
|
||||
if path in self.frozen:
|
||||
self.objectspace.properties.add(path, "frozen", self.frozen[path])
|
||||
if not variable.auto_save and not variable.secret_manager:
|
||||
# if auto_save, save calculated value
|
||||
self.objectspace.properties.add(path, "force_default_on_freeze", True)
|
||||
if not variable.empty and self.objectspace.multis.get(variable.path, False):
|
||||
|
|
@ -141,8 +164,37 @@ class Annotator(Walk):
|
|||
self.objectspace.properties.add(path, "notunique", True)
|
||||
if variable.auto_save:
|
||||
self.objectspace.properties.add(path, "force_store_value", True)
|
||||
if variable.tags:
|
||||
for tag in variable.tags:
|
||||
self.check_tag(tag, variable.xmlfiles)
|
||||
self.objectspace.properties.add(variable.path, tag, True)
|
||||
self.objectspace.informations.add(
|
||||
variable.path, "tags", tuple(variable.tags)
|
||||
)
|
||||
|
||||
def _convert_property(
|
||||
def check_tag(
|
||||
self,
|
||||
tag: str,
|
||||
xmlfiles: List[str],
|
||||
):
|
||||
match = NAME_REGEXP.search(tag)
|
||||
if not match:
|
||||
msg = _(
|
||||
'invalid tag name "{0}" should only contains lowercase ascii character, number or _'
|
||||
).format(tag)
|
||||
raise DictConsistencyError(msg, 82, xmlfiles)
|
||||
if tag in self.objectspace.modes_level:
|
||||
msg = _(
|
||||
'invalid tag name "{0}" should not be a name of an existing mode'
|
||||
).format(tag)
|
||||
raise DictConsistencyError(msg, 82, xmlfiles)
|
||||
if tag in PROPERTIES_MAKE_SENSE:
|
||||
msg = _(
|
||||
'invalid tag name "{0}" should not be the name of an available properties'
|
||||
).format(tag)
|
||||
raise DictConsistencyError(msg, 82, xmlfiles)
|
||||
|
||||
def family_variable_property(
|
||||
self,
|
||||
obj: dict,
|
||||
) -> None:
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ Cadoles (http://www.cadoles.com)
|
|||
Copyright (C) 2019-2021
|
||||
|
||||
Silique (https://www.silique.fr)
|
||||
Copyright (C) 2022-2024
|
||||
Copyright (C) 2022-2026
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
|
|
@ -29,7 +29,7 @@ from rougail.annotator.variable import Walk
|
|||
|
||||
from rougail.i18n import _
|
||||
from rougail.error import DictConsistencyError
|
||||
from rougail.object_model import Calculation
|
||||
from rougail.convert.object_model import Calculation
|
||||
|
||||
|
||||
class Annotator(Walk): # pylint: disable=R0903
|
||||
|
|
@ -47,6 +47,7 @@ class Annotator(Walk): # pylint: disable=R0903
|
|||
self.objectspace = objectspace
|
||||
self.convert_value()
|
||||
self.valid_choices()
|
||||
self.valid_regexp()
|
||||
|
||||
def convert_value(self) -> None:
|
||||
"""convert value"""
|
||||
|
|
@ -75,8 +76,8 @@ class Annotator(Walk): # pylint: disable=R0903
|
|||
raise DictConsistencyError(msg, 68, variable.xmlfiles)
|
||||
if variable.path in self.objectspace.followers and multi != "submulti":
|
||||
msg = _(
|
||||
'the follower "{0}" without multi attribute can only have one value'
|
||||
).format(variable.name)
|
||||
'the follower "{0}" is not multi, so cannot have a list has default value'
|
||||
).format(variable.path)
|
||||
raise DictConsistencyError(msg, 87, variable.xmlfiles)
|
||||
if not variable.default:
|
||||
variable.default = None
|
||||
|
|
@ -92,7 +93,7 @@ class Annotator(Walk): # pylint: disable=R0903
|
|||
elif variable.multi:
|
||||
msg = _(
|
||||
'the variable "{0}" is multi but has a non list default value'
|
||||
).format(variable.name)
|
||||
).format(variable.path)
|
||||
raise DictConsistencyError(msg, 12, variable.xmlfiles)
|
||||
elif variable.path in self.objectspace.followers:
|
||||
self.objectspace.default_multi[variable.path] = variable.default
|
||||
|
|
@ -114,7 +115,9 @@ class Annotator(Walk): # pylint: disable=R0903
|
|||
if isinstance(variable.choices, Calculation):
|
||||
continue
|
||||
if variable.choices is None:
|
||||
msg = f'the variable "{variable.path}" is a "choice" variable but don\'t have any choice'
|
||||
msg = _(
|
||||
'the variable "{0}" is a "choice" variable but don\'t have any choice'
|
||||
).format(variable.path)
|
||||
raise DictConsistencyError(msg, 19, variable.xmlfiles)
|
||||
if not variable.mandatory and not variable.multi:
|
||||
self.add_choice_nil(variable)
|
||||
|
|
@ -125,3 +128,13 @@ class Annotator(Walk): # pylint: disable=R0903
|
|||
if choice is None:
|
||||
return
|
||||
variable.choices.append(None)
|
||||
|
||||
def valid_regexp(self) -> None:
|
||||
for variable in self.get_variables():
|
||||
if variable.type != "regexp":
|
||||
continue
|
||||
if variable.regexp is None:
|
||||
msg = _(
|
||||
'the variable "{0}" is a "regexp" variable but don\'t have any regexp'
|
||||
).format(variable.path)
|
||||
raise DictConsistencyError(msg, 66, variable.xmlfiles)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ Cadoles (http://www.cadoles.com)
|
|||
Copyright (C) 2019-2021
|
||||
|
||||
Silique (https://www.silique.fr)
|
||||
Copyright (C) 2022-2024
|
||||
Copyright (C) 2022-2026
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
|
|
@ -25,10 +25,20 @@ You should have received a copy of the GNU Lesser General Public License
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from rougail.i18n import _
|
||||
from rougail.error import DictConsistencyError
|
||||
from rougail.object_model import Calculation, VariableCalculation
|
||||
from tiramisu.error import display_list
|
||||
from rougail.i18n import _
|
||||
from rougail.utils import calc_multi_for_type_variable
|
||||
from rougail.error import DictConsistencyError
|
||||
from rougail.convert.object_model import (
|
||||
Calculation,
|
||||
VariableCalculation,
|
||||
VariableParam,
|
||||
IndexCalculation,
|
||||
JinjaCalculation,
|
||||
)
|
||||
from rougail.tiramisu import display_xmlfiles, RENAME_TYPE
|
||||
|
||||
from warnings import warn
|
||||
|
||||
|
||||
class Walk:
|
||||
|
|
@ -41,8 +51,6 @@ class Walk:
|
|||
for path in self.objectspace.variables:
|
||||
yield self.objectspace.paths[path]
|
||||
|
||||
# yield from get_variables(self.objectspace)
|
||||
|
||||
def get_families(self):
|
||||
"""Iter all families from the objectspace"""
|
||||
for path in self.objectspace.families:
|
||||
|
|
@ -62,50 +70,146 @@ class Annotator(Walk): # pylint: disable=R0903
|
|||
if not objectspace.paths:
|
||||
return
|
||||
self.objectspace = objectspace
|
||||
if self.objectspace.main_namespace:
|
||||
self.forbidden_name = [self.objectspace.main_namespace]
|
||||
for extra in self.objectspace.extra_dictionaries:
|
||||
self.forbidden_name.append(extra)
|
||||
else:
|
||||
self.forbidden_name = []
|
||||
# default type inference from a default value with :term:`basic types`
|
||||
self.basic_types = {
|
||||
str: "string",
|
||||
int: "number",
|
||||
int: "integer",
|
||||
bool: "boolean",
|
||||
float: "float",
|
||||
}
|
||||
self.verify_secret_managers()
|
||||
self.verify_choices()
|
||||
self.convert_variable()
|
||||
self.convert_test()
|
||||
self.convert_examples()
|
||||
self.convert_help()
|
||||
|
||||
def verify_secret_managers(self):
|
||||
for variable in self.get_variables():
|
||||
if not variable.secret_manager:
|
||||
continue
|
||||
path = variable.path
|
||||
if variable.type not in ["unix_user", "secret"]:
|
||||
msg = _(
|
||||
'only "unix_user" or "secret" variable type can have "secret_manager" attribute, but "{0}" has type "{1}"'
|
||||
)
|
||||
raise DictConsistencyError(
|
||||
msg.format(path, variable.type), 56, variable.xmlfiles
|
||||
)
|
||||
if variable.multi and path not in self.objectspace.leaders:
|
||||
msg = _(
|
||||
'the variable "{0}" has attribute "secret_manager" but is a multi variable'
|
||||
)
|
||||
raise DictConsistencyError(msg.format(path), 57, variable.xmlfiles)
|
||||
if variable.default is not None:
|
||||
msg = _(
|
||||
'the variable "{0}" has attribute "secret_manager" so must not have default value'
|
||||
)
|
||||
raise DictConsistencyError(msg.format(path), 59, variable.xmlfiles)
|
||||
|
||||
def convert_variable(self):
|
||||
"""convert variable"""
|
||||
for variable in self.get_variables():
|
||||
if variable.version != "1.0":
|
||||
if variable.type == "symlink":
|
||||
continue
|
||||
if variable.version != "1.0":
|
||||
self._convert_variable_inference(variable)
|
||||
self._convert_variable_multi(variable)
|
||||
for variable in self.get_variables():
|
||||
if variable.type == "symlink":
|
||||
continue
|
||||
if variable.version != "1.0":
|
||||
self._default_variable_copy_informations(variable)
|
||||
if variable.multi is None:
|
||||
variable.multi = False
|
||||
if variable.type is None:
|
||||
variable.type = "string"
|
||||
self.objectspace.informations.add(variable.path, "type", variable.type)
|
||||
if variable.type in RENAME_TYPE:
|
||||
warning = f'the variable "{ variable.path }" has a depreciated type "{variable.type}", please use "{RENAME_TYPE[variable.type]}" instead in {display_xmlfiles(variable.xmlfiles)}'
|
||||
warn(
|
||||
warning,
|
||||
DeprecationWarning,
|
||||
)
|
||||
variable.type = RENAME_TYPE[variable.type]
|
||||
if variable.type == "cidr":
|
||||
warning = f'the variable "{ variable.path }" has a depreciated type "{variable.type}", please use type "ip" with attribute cidr=True instead in {display_xmlfiles(variable.xmlfiles)}'
|
||||
warn(
|
||||
warning,
|
||||
DeprecationWarning,
|
||||
)
|
||||
if variable.type == "network_cidr":
|
||||
warning = f'the variable "{ variable.path }" has a depreciated type "{variable.type}", please use type "network" with attribute cidr=True instead in {display_xmlfiles(variable.xmlfiles)}'
|
||||
warn(
|
||||
warning,
|
||||
DeprecationWarning,
|
||||
)
|
||||
self.objectspace.informations.add(
|
||||
variable.path, "ymlfiles", variable.xmlfiles
|
||||
)
|
||||
if variable.version != "1.0" and variable.type is None:
|
||||
if isinstance(variable.default, IndexCalculation):
|
||||
variable.type = "integer"
|
||||
elif isinstance(variable.default, VariableCalculation):
|
||||
calculated_variable_path, calculated_variable, identifier = (
|
||||
variable.default.get_variable(self.objectspace, variable.path)
|
||||
)
|
||||
if calculated_variable is not None:
|
||||
self._default_variable_copy_informations(
|
||||
variable, calculated_variable
|
||||
)
|
||||
self._convert_variable(variable)
|
||||
if variable.multi and variable.params:
|
||||
indexes_to_remove = []
|
||||
for idx, param in enumerate(variable.params):
|
||||
if param.key == "multi_length":
|
||||
jinja = f'{{% if var | length != {param.value} %}}{_("{0} values needed, but there are {{{{ var | length }}}}").format(param.value)}{{% endif %}}'
|
||||
description = _("needs exactly {0} values").format(param.value)
|
||||
elif param.key == "multi_max_length":
|
||||
jinja = f'{{% if var | length > {param.value} %}}{_("a maximum of {0} values are needed, but there are {{{{ var | length }}}}").format(param.value)}{{% endif %}}'
|
||||
description = _("needs a maximum of {0} values").format(
|
||||
param.value
|
||||
)
|
||||
elif param.key == "multi_min_length":
|
||||
jinja = f'{{% if var | length < {param.value} %}}{_("a minimum of {0} values are needed, but there are {{{{ var | length }}}}").format(param.value)}{{% endif %}}'
|
||||
description = _("needs a minimum of {0} values").format(
|
||||
param.value
|
||||
)
|
||||
else:
|
||||
continue
|
||||
indexes_to_remove.append(idx)
|
||||
if variable.validators is None:
|
||||
variable.validators = []
|
||||
|
||||
variable.validators.append(
|
||||
JinjaCalculation(
|
||||
inside_list=True,
|
||||
version=variable.version,
|
||||
xmlfiles=variable.xmlfiles,
|
||||
attribute_name="validators",
|
||||
namespace=variable.namespace,
|
||||
jinja=jinja,
|
||||
description=description,
|
||||
params=[
|
||||
VariableParam(
|
||||
variable.path,
|
||||
"validators",
|
||||
False,
|
||||
variable.xmlfiles,
|
||||
key="var",
|
||||
namespace=variable.namespace,
|
||||
type="variable",
|
||||
variable=variable.path,
|
||||
whole=True,
|
||||
)
|
||||
],
|
||||
)
|
||||
)
|
||||
for idx in reversed(indexes_to_remove):
|
||||
variable.params.pop(idx)
|
||||
if variable.secret_manager:
|
||||
self.objectspace.properties.add(variable.path, "novalidator", True)
|
||||
|
||||
def _convert_variable_inference(
|
||||
self,
|
||||
variable,
|
||||
) -> None:
|
||||
# variable has no type
|
||||
if variable.type is None:
|
||||
if variable.type is not None:
|
||||
return
|
||||
# choice type inference from the `choices` attribute
|
||||
if variable.choices is not None:
|
||||
variable.type = "choice"
|
||||
|
|
@ -117,50 +221,68 @@ class Annotator(Walk): # pylint: disable=R0903
|
|||
else:
|
||||
tested_value = variable.default
|
||||
variable.type = self.basic_types.get(type(tested_value), None)
|
||||
|
||||
def _convert_variable_multi(
|
||||
self,
|
||||
variable,
|
||||
) -> None:
|
||||
# variable has no multi attribute
|
||||
if variable.multi is None and not (
|
||||
variable.type is None and isinstance(variable.default, VariableCalculation)
|
||||
):
|
||||
if variable.multi is not None:
|
||||
return
|
||||
if variable.path in self.objectspace.leaders:
|
||||
variable.multi = True
|
||||
variable.multi = self.objectspace.multis[variable.path] = True
|
||||
elif variable.version != "1.0" and isinstance(
|
||||
variable.default, VariableCalculation
|
||||
):
|
||||
calculated_variable_path, calculated_variable, identifier = (
|
||||
variable.default.get_variable(self.objectspace, variable.path)
|
||||
)
|
||||
if calculated_variable is not None:
|
||||
if calculated_variable.multi is None:
|
||||
if (
|
||||
isinstance(calculated_variable.default, VariableCalculation)
|
||||
and variable.path == calculated_variable.path
|
||||
):
|
||||
msg = _(
|
||||
'the "{0}" default value is a calculation with itself'
|
||||
).format(variable.path)
|
||||
raise DictConsistencyError(msg, 75, variable.xmlfiles)
|
||||
self._convert_variable_multi(calculated_variable)
|
||||
variable.multi = calc_multi_for_type_variable(
|
||||
variable,
|
||||
calculated_variable_path,
|
||||
calculated_variable,
|
||||
self.objectspace,
|
||||
)[1]
|
||||
if (
|
||||
calculated_variable.path in self.objectspace.followers
|
||||
and variable.mandatory is calculated_variable.mandatory is False
|
||||
and calculated_variable.path.rsplit(".", 1)[0]
|
||||
!= variable.path.rsplit(".", 1)[0]
|
||||
):
|
||||
variable.empty = False
|
||||
else:
|
||||
variable.multi = isinstance(variable.default, list)
|
||||
|
||||
def _default_variable_copy_informations(
|
||||
self,
|
||||
variable,
|
||||
calculated_variable,
|
||||
) -> None:
|
||||
# if a variable has a variable as default value, that means the type/params or multi should has same value
|
||||
if variable.type is not None or not isinstance(
|
||||
variable.default, VariableCalculation
|
||||
):
|
||||
return
|
||||
# copy type and params
|
||||
calculated_variable_path = variable.default.variable
|
||||
calculated_variable, identifier = self.objectspace.paths.get_with_dynamic(
|
||||
calculated_variable_path,
|
||||
variable.default.path_prefix,
|
||||
variable.path,
|
||||
variable.version,
|
||||
variable.namespace,
|
||||
variable.xmlfiles,
|
||||
)
|
||||
if calculated_variable is None:
|
||||
return
|
||||
variable.type = calculated_variable.type
|
||||
if variable.params is None and calculated_variable.params is not None:
|
||||
variable.params = calculated_variable.params
|
||||
# copy multi attribut
|
||||
if variable.multi is None:
|
||||
calculated_path = calculated_variable.path
|
||||
if (
|
||||
calculated_path in self.objectspace.leaders
|
||||
and variable.path in self.objectspace.followers
|
||||
and calculated_path.rsplit(".")[0] == variable.path.rsplit(".")[0]
|
||||
):
|
||||
variable.multi = False
|
||||
else:
|
||||
variable.multi = calculated_variable.multi
|
||||
if variable.type == "choice" and variable.choices is None:
|
||||
variable.choices = calculated_variable.choices
|
||||
if isinstance(variable.choices, VariableCalculation):
|
||||
variable.choices = variable.choices.model_copy()
|
||||
variable.choices.variable = self.objectspace.paths.get_full_path(
|
||||
variable.choices.variable,
|
||||
calculated_variable.path,
|
||||
)
|
||||
if variable.type == "regexp" and variable.regexp is None:
|
||||
variable.regexp = calculated_variable.regexp
|
||||
|
||||
def _convert_variable(
|
||||
self,
|
||||
|
|
@ -169,6 +291,10 @@ class Annotator(Walk): # pylint: disable=R0903
|
|||
# variable without description: description is the name
|
||||
if not variable.description:
|
||||
variable.description = variable.name
|
||||
self.objectspace.forced_descriptions.append(variable.path)
|
||||
if variable.type is None:
|
||||
variable.type = "string"
|
||||
self.objectspace.informations.add(variable.path, "type", variable.type)
|
||||
if variable.path in self.objectspace.followers:
|
||||
if not variable.multi:
|
||||
self.objectspace.multis[variable.path] = True
|
||||
|
|
@ -176,15 +302,6 @@ class Annotator(Walk): # pylint: disable=R0903
|
|||
self.objectspace.multis[variable.path] = "submulti"
|
||||
elif variable.multi:
|
||||
self.objectspace.multis[variable.path] = True
|
||||
if variable.path in self.objectspace.leaders:
|
||||
if not self.objectspace.multis.get(variable.path, False):
|
||||
variable.multi = self.objectspace.multis[variable.path] = True
|
||||
family = self.objectspace.paths[variable.path.rsplit(".", 1)[0]]
|
||||
if variable.hidden:
|
||||
family.hidden = variable.hidden
|
||||
# elif family.hidden:
|
||||
# variable.hidden = family.hidden
|
||||
variable.hidden = None
|
||||
if variable.regexp is not None and variable.type != "regexp":
|
||||
msg = _(
|
||||
'the variable "{0}" has regexp attribut but has not the "regexp" type'
|
||||
|
|
|
|||
|
|
@ -1,497 +0,0 @@
|
|||
"""
|
||||
Config file for Rougail
|
||||
|
||||
Created by:
|
||||
EOLE (http://eole.orion.education.fr)
|
||||
Copyright (C) 2005-2018
|
||||
|
||||
Forked by:
|
||||
Cadoles (http://www.cadoles.com)
|
||||
Copyright (C) 2019-2021
|
||||
|
||||
Silique (https://www.silique.fr)
|
||||
Copyright (C) 2022-2024
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
from tiramisu import Config
|
||||
from ruamel.yaml import YAML
|
||||
from .utils import _, load_modules, normalize_family
|
||||
from .convert import RougailConvert
|
||||
|
||||
|
||||
RENAMED = {
|
||||
"dictionaries_dir": "main_dictionaries",
|
||||
"variable_namespace": "main_namespace",
|
||||
"functions_file": "functions_files",
|
||||
}
|
||||
NOT_IN_TIRAMISU = {
|
||||
"custom_types": {},
|
||||
}
|
||||
SUBMODULES = None
|
||||
|
||||
|
||||
def get_sub_modules():
|
||||
global SUBMODULES
|
||||
if SUBMODULES is None:
|
||||
SUBMODULES = {}
|
||||
for submodule in Path(__file__).parent.iterdir():
|
||||
if submodule.name.startswith("_") or not submodule.is_dir():
|
||||
continue
|
||||
config_file = submodule / "config.py"
|
||||
if config_file.is_file():
|
||||
SUBMODULES[submodule.name] = load_modules(
|
||||
"rougail." + submodule.name + ".config", str(config_file)
|
||||
)
|
||||
return SUBMODULES
|
||||
|
||||
|
||||
def get_level(module):
|
||||
return module["level"]
|
||||
|
||||
|
||||
class _RougailConfig:
|
||||
def __init__(self, backward_compatibility: bool, root, extra_vars: dict):
|
||||
self.backward_compatibility = backward_compatibility
|
||||
self.root = root
|
||||
self.config = Config(
|
||||
self.root,
|
||||
)
|
||||
self.config.property.read_only()
|
||||
self.extra_vars = extra_vars
|
||||
self.not_in_tiramisu = NOT_IN_TIRAMISU | extra_vars
|
||||
for variable, default_value in self.not_in_tiramisu.items():
|
||||
if not isinstance(default_value, str):
|
||||
default_value = default_value.copy()
|
||||
setattr(self, variable, default_value)
|
||||
|
||||
def copy(self):
|
||||
rougailconfig = _RougailConfig(
|
||||
self.backward_compatibility, self.root, self.extra_vars
|
||||
)
|
||||
rougailconfig.config.value.importation(self.config.value.exportation())
|
||||
rougailconfig.config.property.importation(self.config.property.exportation())
|
||||
rougailconfig.config.property.read_only()
|
||||
for variable in self.not_in_tiramisu:
|
||||
value = getattr(self, variable)
|
||||
if not isinstance(value, str):
|
||||
value = value.copy()
|
||||
setattr(rougailconfig, variable, value)
|
||||
return rougailconfig
|
||||
|
||||
def __setitem__(
|
||||
self,
|
||||
key,
|
||||
value,
|
||||
) -> None:
|
||||
if key in self.not_in_tiramisu:
|
||||
setattr(self, key, value)
|
||||
else:
|
||||
self.config.property.read_write()
|
||||
if key == "export_with_import":
|
||||
key = "not_export_with_import"
|
||||
key = RENAMED.get(key, key)
|
||||
option = self.config.option(key)
|
||||
if option.isoptiondescription() and option.isleadership():
|
||||
leader = list(value)
|
||||
option.leader().value.reset()
|
||||
option.leader().value.set(leader)
|
||||
follower = option.followers()[0]
|
||||
for idx, val in enumerate(value.values()):
|
||||
self.config.option(follower.path(), idx).value.set(val)
|
||||
elif key == "not_export_with_import":
|
||||
option.value.set(not value)
|
||||
else:
|
||||
option.value.set(value)
|
||||
self.config.property.read_only()
|
||||
|
||||
def __getitem__(
|
||||
self,
|
||||
key,
|
||||
) -> None:
|
||||
if key in self.not_in_tiramisu:
|
||||
return getattr(self, key)
|
||||
if key == "export_with_import":
|
||||
key = "not_export_with_import"
|
||||
option = self.config.option(key)
|
||||
if option.isoptiondescription() and option.isleadership():
|
||||
return self.get_leadership(option)
|
||||
ret = self.config.option(key).value.get()
|
||||
if key == "not_export_with_import":
|
||||
return not ret
|
||||
return ret
|
||||
|
||||
def get_leadership(self, option) -> dict:
|
||||
leader = None
|
||||
followers = []
|
||||
for opt, value in option.value.get().items():
|
||||
if opt.issymlinkoption():
|
||||
continue
|
||||
if leader is None:
|
||||
leader = value
|
||||
else:
|
||||
followers.append(value)
|
||||
return dict(zip(leader, followers))
|
||||
|
||||
def parse(self, config) -> str:
|
||||
for option in config:
|
||||
if option.isoptiondescription():
|
||||
yield from self.parse(option)
|
||||
elif not option.issymlinkoption():
|
||||
yield f"{option.path()}: {option.value.get()}"
|
||||
|
||||
def __repr__(self):
|
||||
self.config.property.read_write()
|
||||
try:
|
||||
values = "\n".join(self.parse(self.config))
|
||||
except Exception as err:
|
||||
values = str(err)
|
||||
self.config.property.read_only()
|
||||
return values
|
||||
|
||||
|
||||
class FakeRougailConvert(RougailConvert):
|
||||
def __init__(
|
||||
self,
|
||||
add_extra_options: bool,
|
||||
) -> None:
|
||||
self.add_extra_options = add_extra_options
|
||||
super().__init__({})
|
||||
|
||||
def load_config(self) -> None:
|
||||
self.sort_dictionaries_all = False
|
||||
self.main_namespace = None
|
||||
self.suffix = ""
|
||||
self.custom_types = {}
|
||||
self.functions_files = []
|
||||
self.modes_level = []
|
||||
self.extra_annotators = []
|
||||
self.base_option_name = "baseoption"
|
||||
self.export_with_import = True
|
||||
self.internal_functions = []
|
||||
self.plugins = ["structural_commandline"]
|
||||
self.add_extra_options = self.add_extra_options
|
||||
|
||||
|
||||
def get_rougail_config(
|
||||
*,
|
||||
backward_compatibility: bool = True,
|
||||
add_extra_options: bool = True,
|
||||
) -> _RougailConfig:
|
||||
if backward_compatibility:
|
||||
main_namespace_default = "rougail"
|
||||
else:
|
||||
main_namespace_default = "null"
|
||||
rougail_options = f"""default_dictionary_format_version:
|
||||
description: Dictionary format version by default, if not specified in dictionary file
|
||||
alternative_name: v
|
||||
choices:
|
||||
- '1.0'
|
||||
- '1.1'
|
||||
mandatory: false
|
||||
|
||||
main_dictionaries:
|
||||
description: 'Directories where dictionary files are placed'
|
||||
type: unix_filename
|
||||
alternative_name: m
|
||||
params:
|
||||
allow_relative: True
|
||||
test_existence: True
|
||||
types:
|
||||
- directory
|
||||
multi: true
|
||||
|
||||
sort_dictionaries_all:
|
||||
description: Sort dictionaries from differents directories
|
||||
negative_description: Sort dictionaries directory by directory
|
||||
default: false
|
||||
|
||||
main_namespace:
|
||||
description: Main namespace name
|
||||
default: {main_namespace_default}
|
||||
alternative_name: s
|
||||
mandatory: false
|
||||
|
||||
extra_dictionaries:
|
||||
description: Extra namespaces
|
||||
type: leadership
|
||||
disabled:
|
||||
variable: main_namespace
|
||||
when: null
|
||||
|
||||
names:
|
||||
description: 'Extra namespace name'
|
||||
alternative_name: xn
|
||||
multi: true
|
||||
mandatory: false
|
||||
|
||||
directories:
|
||||
description: Directories where extra dictionary files are placed
|
||||
alternative_name: xd
|
||||
type: unix_filename
|
||||
params:
|
||||
allow_relative: true
|
||||
test_existence: true
|
||||
types:
|
||||
- directory
|
||||
multi: true
|
||||
|
||||
upgrade:
|
||||
description: Update dictionaries to newest Rougail format version
|
||||
negative_description: Do not update dictionaries to newest Rougail format version
|
||||
default: false
|
||||
|
||||
upgrade_options:
|
||||
description: Update informations
|
||||
disabled:
|
||||
variable: upgrade
|
||||
when: false
|
||||
|
||||
main_dictionaries:
|
||||
description: 'Directories where dictionary files will be placed'
|
||||
default:
|
||||
variable: __.main_dictionaries
|
||||
|
||||
extra_dictionary:
|
||||
description: 'Directories where extra files will be placed'
|
||||
type: unix_filename
|
||||
params:
|
||||
allow_relative: true
|
||||
test_existence: true
|
||||
types:
|
||||
- directory
|
||||
disabled:
|
||||
variable: __.main_namespace
|
||||
when: null
|
||||
|
||||
functions_files:
|
||||
description: File with functions
|
||||
alternative_name: c
|
||||
type: unix_filename
|
||||
params:
|
||||
allow_relative: true
|
||||
test_existence: true
|
||||
types:
|
||||
- file
|
||||
multi: true
|
||||
mandatory: false
|
||||
|
||||
modes_level:
|
||||
description: All modes level available
|
||||
multi: true
|
||||
mandatory: false
|
||||
"""
|
||||
if backward_compatibility:
|
||||
rougail_options += """
|
||||
default:
|
||||
- basic
|
||||
- standard
|
||||
- advanced
|
||||
"""
|
||||
rougail_options += """
|
||||
default_family_mode:
|
||||
description: Default mode for a family
|
||||
default:
|
||||
jinja: |
|
||||
{% if modes_level %}
|
||||
{{ modes_level[0] }}
|
||||
{% endif %}
|
||||
disabled:
|
||||
jinja: |
|
||||
{% if not modes_level %}
|
||||
No mode
|
||||
{% endif %}
|
||||
validators:
|
||||
- type: jinja
|
||||
jinja: |
|
||||
{% if default_family_mode not in modes_level %}
|
||||
not in modes_level ({modes_level})
|
||||
{% endif %}
|
||||
commandline: false
|
||||
|
||||
default_variable_mode:
|
||||
description: Default mode for a variable
|
||||
default:
|
||||
jinja: |
|
||||
{% if modes_level %}
|
||||
{% if modes_level | length == 1 %}
|
||||
{{ modes_level[0] }}
|
||||
{% else %}
|
||||
{{ modes_level[1] }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
disabled:
|
||||
jinja: |
|
||||
{% if not modes_level %}
|
||||
No mode
|
||||
{% endif %}
|
||||
validators:
|
||||
- type: jinja
|
||||
jinja: |
|
||||
{% if default_variable_mode not in modes_level %}
|
||||
not in modes_level ({modes_level})
|
||||
{% endif %}
|
||||
commandline: false
|
||||
|
||||
base_option_name:
|
||||
description: Option name for the base option
|
||||
default: baseoption
|
||||
commandline: false
|
||||
|
||||
not_export_with_import:
|
||||
description: In cache file, do not importation of Tiramisu and other dependencies
|
||||
default: false
|
||||
commandline: false
|
||||
|
||||
tiramisu_cache:
|
||||
description: Tiramisu cache filename
|
||||
alternative_name: t
|
||||
type: unix_filename
|
||||
mandatory: false
|
||||
params:
|
||||
allow_relative: true
|
||||
|
||||
internal_functions:
|
||||
description: Name of internal functions that we can use as a function
|
||||
multi: true
|
||||
mandatory: false
|
||||
commandline: false
|
||||
|
||||
extra_annotators:
|
||||
description: Name of extra annotators
|
||||
multi: true
|
||||
mandatory: false
|
||||
commandline: false
|
||||
|
||||
plugins:
|
||||
description: Name of Rougail plugins
|
||||
multi: true
|
||||
mandatory: false
|
||||
commandline: false
|
||||
|
||||
suffix:
|
||||
description: Suffix add to generated option name
|
||||
default: ''
|
||||
mandatory: false
|
||||
commandline: false
|
||||
"""
|
||||
processes = {
|
||||
"structural": [],
|
||||
"output": [],
|
||||
"user data": [],
|
||||
}
|
||||
for module in get_sub_modules().values():
|
||||
data = module.get_rougail_config()
|
||||
processes[data["process"]].append(data)
|
||||
# reorder
|
||||
for process in processes:
|
||||
processes[process] = list(sorted(processes[process], key=get_level))
|
||||
rougail_process = """step: # Load and exporter steps
|
||||
disabled:
|
||||
variable: upgrade"""
|
||||
for process in processes:
|
||||
if processes[process]:
|
||||
objects = processes[process]
|
||||
rougail_process += """
|
||||
{NAME}:
|
||||
description: Select for {NAME}
|
||||
alternative_name: {NAME[0]}
|
||||
choices:
|
||||
""".format(
|
||||
NAME=normalize_family(process),
|
||||
)
|
||||
for obj in objects:
|
||||
rougail_process += f" - {obj['name']}\n"
|
||||
if process == "structural":
|
||||
rougail_process += " commandline: false"
|
||||
elif process == "user data":
|
||||
rougail_process += """ multi: true
|
||||
mandatory: false
|
||||
"""
|
||||
hidden_outputs = [
|
||||
process["name"]
|
||||
for process in processes["output"]
|
||||
if not process.get("allow_user_data", True)
|
||||
]
|
||||
if hidden_outputs:
|
||||
rougail_process += """ hidden:
|
||||
type: jinja
|
||||
jinja: |
|
||||
"""
|
||||
for hidden_output in hidden_outputs:
|
||||
rougail_process += """ {% if _.output == 'NAME' %}
|
||||
Cannot load user data for NAME output
|
||||
{% endif %}
|
||||
""".replace(
|
||||
"NAME", hidden_output
|
||||
)
|
||||
elif objects:
|
||||
rougail_process += " default: {DEFAULT}".format(
|
||||
DEFAULT=objects[0]["name"]
|
||||
)
|
||||
else:
|
||||
if process == 'output':
|
||||
prop = 'hidden'
|
||||
else:
|
||||
prop = 'disabled'
|
||||
rougail_process += """
|
||||
{NAME}:
|
||||
description: Select for {NAME}
|
||||
mandatory: false
|
||||
{PROP}: true
|
||||
multi: true
|
||||
default: ["You haven't installed \\\"{NAME}\\\" package for rougail"]
|
||||
validators:
|
||||
- jinja: Please install a rougail-{NAME}-* package.
|
||||
""".format(
|
||||
NAME=normalize_family(process),
|
||||
PROP=prop,
|
||||
)
|
||||
rougail_options += rougail_process
|
||||
convert = FakeRougailConvert(add_extra_options)
|
||||
convert._init()
|
||||
convert.namespace = None
|
||||
convert.parse_root_file(
|
||||
"rougail.config",
|
||||
"",
|
||||
"1.1",
|
||||
YAML().load(rougail_options),
|
||||
)
|
||||
extra_vars = {}
|
||||
for process in processes:
|
||||
for obj in processes[process]:
|
||||
if "extra_vars" in obj:
|
||||
extra_vars |= obj["extra_vars"]
|
||||
if not "options" in obj:
|
||||
continue
|
||||
convert.parse_root_file(
|
||||
f'rougail.config.{obj["name"]}',
|
||||
"",
|
||||
"1.1",
|
||||
YAML().load(obj["options"]),
|
||||
)
|
||||
|
||||
tiram_obj = convert.save(None)
|
||||
optiondescription = {}
|
||||
exec(tiram_obj, {}, optiondescription) # pylint: disable=W0122
|
||||
return _RougailConfig(
|
||||
backward_compatibility,
|
||||
optiondescription["option_0"],
|
||||
extra_vars=extra_vars,
|
||||
)
|
||||
|
||||
|
||||
RougailConfig = get_rougail_config()
|
||||
604
src/rougail/config/__init__.py
Normal file
604
src/rougail/config/__init__.py
Normal file
|
|
@ -0,0 +1,604 @@
|
|||
"""
|
||||
Config file for Rougail
|
||||
|
||||
Created by:
|
||||
EOLE (http://eole.orion.education.fr)
|
||||
Copyright (C) 2005-2018
|
||||
|
||||
Forked by:
|
||||
Cadoles (http://www.cadoles.com)
|
||||
Copyright (C) 2019-2021
|
||||
|
||||
Silique (https://www.silique.fr)
|
||||
Copyright (C) 2022-2026
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
from tiramisu import Config
|
||||
from tiramisu.error import display_list
|
||||
from ruamel.yaml import YAML
|
||||
from ..utils import _, load_modules
|
||||
from ..tiramisu import normalize_family
|
||||
from ..convert import RougailConvert
|
||||
from ..convert.object_model import get_convert_option_types
|
||||
|
||||
|
||||
RENAMED = {
|
||||
"dictionaries_dir": "main_structural_directories",
|
||||
"main_dictionaries": "main_structural_directories",
|
||||
"variable_namespace": "main_namespace",
|
||||
"functions_file": "functions_files",
|
||||
}
|
||||
NOT_IN_TIRAMISU = {
|
||||
"custom_types": {},
|
||||
}
|
||||
SUBMODULES = None
|
||||
|
||||
|
||||
def get_sub_modules():
|
||||
global SUBMODULES
|
||||
if SUBMODULES is None:
|
||||
SUBMODULES = {}
|
||||
for submodule in Path(__file__).parent.parent.iterdir():
|
||||
if submodule.name.startswith("_") or not submodule.is_dir():
|
||||
continue
|
||||
config_file = submodule / "config.py"
|
||||
if config_file.is_file():
|
||||
SUBMODULES[submodule.name] = load_modules(
|
||||
"rougail." + submodule.name + ".config", str(config_file)
|
||||
)
|
||||
return SUBMODULES
|
||||
|
||||
|
||||
def get_level(module):
|
||||
return float(module["level"]) + {
|
||||
"structural": 0.1,
|
||||
"user data": 0.2,
|
||||
"output": 0.3,
|
||||
}.get(module["process"])
|
||||
|
||||
|
||||
class _RougailConfig:
|
||||
def __init__(self, backward_compatibility: bool, add_extra_options: bool):
|
||||
self.backward_compatibility = backward_compatibility
|
||||
self.add_extra_options = add_extra_options
|
||||
self.root = None
|
||||
|
||||
def copy(self, backward_compatibility=None):
|
||||
if not self.root:
|
||||
self.generate_config()
|
||||
config = self.config.config.copy()
|
||||
config.value.importation(self.config.value.exportation())
|
||||
config.property.importation(
|
||||
self.config.property.exportation()
|
||||
)
|
||||
config.property.read_only()
|
||||
if backward_compatibility is None:
|
||||
backward_compatibility = self.backward_compatibility
|
||||
rougailconfig = _RougailConfig(backward_compatibility, self.add_extra_options)
|
||||
rougailconfig.root = self.root
|
||||
rougailconfig.config = config
|
||||
rougailconfig.extra_vars = self.extra_vars.copy()
|
||||
rougailconfig.not_in_tiramisu = NOT_IN_TIRAMISU | rougailconfig.extra_vars
|
||||
for variable in self.not_in_tiramisu:
|
||||
value = getattr(self, variable)
|
||||
if not isinstance(value, str):
|
||||
value = value.copy()
|
||||
setattr(rougailconfig, variable, value)
|
||||
return rougailconfig
|
||||
|
||||
def generate_config(self):
|
||||
self.root, extra_vars = _rougail_config(
|
||||
self.backward_compatibility, self.add_extra_options
|
||||
)
|
||||
self.config = Config(
|
||||
self.root,
|
||||
)
|
||||
self.extra_vars = extra_vars
|
||||
self.not_in_tiramisu = NOT_IN_TIRAMISU | extra_vars
|
||||
for variable, default_value in self.not_in_tiramisu.items():
|
||||
if not isinstance(default_value, str):
|
||||
default_value = default_value.copy()
|
||||
setattr(self, variable, default_value)
|
||||
self.config.property.read_only()
|
||||
|
||||
def __setitem__(
|
||||
self,
|
||||
key,
|
||||
value,
|
||||
) -> None:
|
||||
if self.root is None:
|
||||
self.generate_config()
|
||||
if key in self.not_in_tiramisu:
|
||||
setattr(self, key, value)
|
||||
else:
|
||||
self.config.property.read_write()
|
||||
key = RENAMED.get(key, key)
|
||||
option = self.config.option(key)
|
||||
if option.isoptiondescription() and option.isleadership():
|
||||
if isinstance(value, RConfigLeadership):
|
||||
leader = value.leader
|
||||
followers = value.followers
|
||||
else:
|
||||
leader = list(value)
|
||||
followers = value.values()
|
||||
option.leader().value.reset()
|
||||
option.leader().value.set(leader)
|
||||
follower = option.followers()[0]
|
||||
for idx, val in enumerate(followers):
|
||||
self.config.option(follower.path(), idx).value.set(val)
|
||||
else:
|
||||
option.value.set(value)
|
||||
self.config.property.read_only()
|
||||
|
||||
def __getitem__(
|
||||
self,
|
||||
key,
|
||||
) -> None:
|
||||
if self.root is None:
|
||||
self.generate_config()
|
||||
if key in self.not_in_tiramisu:
|
||||
return getattr(self, key)
|
||||
option = self.config.option(key)
|
||||
if option.isoptiondescription() and option.isleadership():
|
||||
return self.get_leadership(option)
|
||||
ret = self.config.option(key).value.get()
|
||||
return ret
|
||||
|
||||
def __contains__(
|
||||
self,
|
||||
key,
|
||||
) -> None:
|
||||
try:
|
||||
self.__getitem__(key)
|
||||
except AttributeError:
|
||||
return False
|
||||
return True
|
||||
|
||||
def get_leadership(self, option) -> dict:
|
||||
leader = None
|
||||
followers = []
|
||||
for opt, value in option.value.get().items():
|
||||
if opt.issymlinkoption():
|
||||
continue
|
||||
if leader is None:
|
||||
leader = value
|
||||
else:
|
||||
followers.append(value)
|
||||
return RConfigLeadership(self.config, option, leader, followers)
|
||||
|
||||
def parse(self, config) -> str:
|
||||
for option in config:
|
||||
if option.isoptiondescription():
|
||||
yield from self.parse(option)
|
||||
elif not option.issymlinkoption():
|
||||
yield f"{option.path()}: {option.value.get()}"
|
||||
|
||||
def __repr__(self):
|
||||
if self.root is None:
|
||||
self.generate_config()
|
||||
self.config.property.read_write()
|
||||
try:
|
||||
values = "\n".join(self.parse(self.config))
|
||||
except Exception as err:
|
||||
values = str(err)
|
||||
self.config.property.read_only()
|
||||
return values
|
||||
|
||||
|
||||
class RConfigLeadership:
|
||||
def __init__(self, config, option, leader, followers):
|
||||
self.config = config
|
||||
self.option = option
|
||||
self.leader = leader
|
||||
self.followers = followers
|
||||
|
||||
def items(self):
|
||||
return dict(zip(self.leader, self.followers)).items()
|
||||
|
||||
def __setitem__(
|
||||
self,
|
||||
key,
|
||||
value,
|
||||
) -> None:
|
||||
self.config.property.read_write()
|
||||
names = self.option.option("names")
|
||||
leader = names.value.get()
|
||||
leader.append(key)
|
||||
names.value.set(leader)
|
||||
directories = self.option.option("directories", len(leader) - 1)
|
||||
directories.value.set(value)
|
||||
self.leader.append(key)
|
||||
self.followers.append(value)
|
||||
self.config.property.read_only()
|
||||
|
||||
def __getitem__(self, key):
|
||||
option = self.option.option(key)
|
||||
if option.isleader():
|
||||
return option.value.get()
|
||||
return [option.index(idx).value.get() for idx in range(option.value.len())]
|
||||
|
||||
def __repr__(self):
|
||||
return dict(zip(self.leader, self.followers))
|
||||
|
||||
|
||||
class StaticRougailConvert(RougailConvert):
|
||||
def __init__(
|
||||
self,
|
||||
add_extra_options: bool,
|
||||
rougailconfig: dict={},
|
||||
) -> None:
|
||||
self.add_extra_options = add_extra_options
|
||||
super().__init__(rougailconfig)
|
||||
|
||||
def load_config(self) -> None:
|
||||
self.sort_structural_files_all = False
|
||||
self.main_namespace = None
|
||||
self.suffix = ""
|
||||
self.custom_types = {}
|
||||
self.functions_files = []
|
||||
self.modes_level = []
|
||||
self.extra_annotators = []
|
||||
self.base_option_name = "baseoption"
|
||||
self.export_with_import = True
|
||||
self.internal_functions = []
|
||||
self.force_optional = False
|
||||
self.structurals = ["commandline"]
|
||||
self.user_data = []
|
||||
self.output = None
|
||||
self.tiramisu_cache = False
|
||||
# self.tiramisu_cache = "a.py"
|
||||
self.load_unexist_redefine = False
|
||||
|
||||
|
||||
def get_common_rougail_config(
|
||||
*,
|
||||
backward_compatibility=True,
|
||||
) -> str:
|
||||
rougail_options = f"""default_structural_format_version:
|
||||
description: {_('Default version of the structural file format')}
|
||||
help: {_('This value is only used if the version is not set in the structural file')}
|
||||
alternative_name: v
|
||||
choices:
|
||||
- '1.0'
|
||||
- '1.1'
|
||||
mandatory: false
|
||||
|
||||
types:
|
||||
description: {_("File with personalize types")}
|
||||
help: {_("This file contains personalize types in Rougail format for structure files")}
|
||||
type: unix_filename
|
||||
params:
|
||||
allow_relative: true
|
||||
test_existence: true
|
||||
multi: true
|
||||
mandatory: false
|
||||
|
||||
functions_files:
|
||||
description: {_("File with functions")}
|
||||
help: {_("This file contains filters and additional Jinja2 functions usable in structure files")}
|
||||
type: unix_filename
|
||||
params:
|
||||
allow_relative: true
|
||||
test_existence: true
|
||||
types:
|
||||
- file
|
||||
multi: true
|
||||
mandatory: false
|
||||
|
||||
modes_level:
|
||||
description: {_("All modes level available")}
|
||||
multi: true
|
||||
mandatory: false
|
||||
"""
|
||||
if backward_compatibility:
|
||||
rougail_options += """ default:
|
||||
- basic
|
||||
- standard
|
||||
- advanced
|
||||
"""
|
||||
rougail_options += f"""
|
||||
default_family_mode:
|
||||
description: {_("Default mode for a family")}
|
||||
default:
|
||||
jinja: |
|
||||
{{% if modes_level %}}
|
||||
{{{{ modes_level[0] }}}}
|
||||
{{% endif %}}
|
||||
description: {_('the first one defined in "modes_level"')}
|
||||
disabled:
|
||||
jinja: |
|
||||
{{% if not modes_level %}}
|
||||
No mode
|
||||
{{% endif %}}
|
||||
description: {_('when no mode is defined in "modes_level"')}
|
||||
validators:
|
||||
- type: jinja
|
||||
jinja: |
|
||||
{{% if default_family_mode not in modes_level %}}
|
||||
not in modes_level ({{modes_level}})
|
||||
{{% endif %}}
|
||||
description: {_('this mode must be available in "modes_level"')}
|
||||
commandline: false
|
||||
|
||||
default_variable_mode:
|
||||
description: {_("Default mode for a variable")}
|
||||
default:
|
||||
jinja: |
|
||||
{{% if modes_level %}}
|
||||
{{% if modes_level | length == 1 %}}
|
||||
{{{{ modes_level[0] }}}}
|
||||
{{% else %}}
|
||||
{{{{ modes_level[1] }}}}
|
||||
{{% endif %}}
|
||||
{{% endif %}}
|
||||
description: {_('if the variable "modes_level" is defined, the default value is the second available element, otherwise, the first')}
|
||||
disabled:
|
||||
jinja: |
|
||||
{{% if not modes_level %}}
|
||||
No mode
|
||||
{{% endif %}}
|
||||
description: {_('when no mode is defined in "modes_level"')}
|
||||
validators:
|
||||
- type: jinja
|
||||
jinja: |
|
||||
{{% if default_variable_mode not in modes_level %}}
|
||||
not in modes_level ({{modes_level}})
|
||||
{{% endif %}}
|
||||
description: {_('this mode must be available in "modes_level"')}
|
||||
commandline: false
|
||||
|
||||
base_option_name:
|
||||
description: {_("Option name for the base option")}
|
||||
default: baseoption
|
||||
commandline: false
|
||||
|
||||
export_with_import:
|
||||
description: {_("In cache file, do not importation of Tiramisu and other dependencies")}
|
||||
default: true
|
||||
commandline: false
|
||||
|
||||
tiramisu_cache:
|
||||
description: {_("Store Tiramisu cache filename")}
|
||||
help: "{_("This file contains the Tiramisu instructions used internally to load the variables.\n\nThis file can be used for debugging")}"
|
||||
alternative_name: t
|
||||
type: unix_filename
|
||||
mandatory: false
|
||||
params:
|
||||
allow_relative: true
|
||||
types:
|
||||
- file
|
||||
|
||||
internal_functions:
|
||||
description: {_("Name of internal functions that we can use as a function")}
|
||||
multi: true
|
||||
mandatory: false
|
||||
commandline: false
|
||||
|
||||
extra_annotators:
|
||||
description: {_("Name of extra annotators")}
|
||||
multi: true
|
||||
mandatory: false
|
||||
commandline: false
|
||||
|
||||
suffix:
|
||||
description: {_("Suffix add to generated options name")}
|
||||
default: ''
|
||||
mandatory: false
|
||||
commandline: false
|
||||
|
||||
force_optional:
|
||||
description: {_("Every variables in calculation are optionals")}
|
||||
default: False
|
||||
|
||||
load_unexist_redefine:
|
||||
description: {_("Loads redefine variables even if there don't already exists")}
|
||||
commandline: false
|
||||
default: False
|
||||
|
||||
secret_manager: # {_("The secret manager")}
|
||||
|
||||
pattern:
|
||||
description: {_("The secret pattern to constructing the name of the item searched for in the secret manager")}
|
||||
help: {_("The pattern is in Jinja2 format")}
|
||||
default: "{{{{ project }}}} - {{{{ environment }}}} - {{{{ service }}}} - {{{{ user }}}}"
|
||||
|
||||
"""
|
||||
processes = {
|
||||
"structural": [],
|
||||
"user data": [],
|
||||
"output": [],
|
||||
}
|
||||
processes_tr = {"structural": _("structural"),
|
||||
"user data": _("user datas"),
|
||||
"output": _("output"),
|
||||
}
|
||||
processes_empty = []
|
||||
for module in get_sub_modules().values():
|
||||
data = module.get_rougail_config(backward_compatibility=backward_compatibility)
|
||||
if data["process"]:
|
||||
processes[data["process"]].append(data)
|
||||
else:
|
||||
processes_empty.append(data["options"])
|
||||
# reorder
|
||||
for process in processes:
|
||||
processes[process] = list(sorted(processes[process], key=get_level))
|
||||
rougail_process = "step: # Load and exporter steps"
|
||||
for process in processes:
|
||||
if processes[process]:
|
||||
objects = processes[process]
|
||||
process_name = normalize_family(process)
|
||||
tr_process_name = processes_tr[process]
|
||||
rougail_process += f"""
|
||||
|
||||
{process_name}:
|
||||
description: {_('Select for {0}').format(tr_process_name)}
|
||||
"""
|
||||
if process != "structural":
|
||||
rougail_process += """ alternative_name: {NAME[0]}
|
||||
""".format(
|
||||
NAME=normalize_family(process),
|
||||
)
|
||||
rougail_process += """ choices:
|
||||
"""
|
||||
for obj in objects:
|
||||
rougail_process += f" - {obj['name']}\n"
|
||||
if process == "structural":
|
||||
rougail_process += """ commandline: false
|
||||
multi: true
|
||||
default:
|
||||
- directory
|
||||
"""
|
||||
elif process == "user data":
|
||||
rougail_process += """ multi: true
|
||||
mandatory: false"""
|
||||
hidden_outputs = [
|
||||
process["name"]
|
||||
for process in processes["output"]
|
||||
if not process.get("allow_user_data", True)
|
||||
]
|
||||
if hidden_outputs:
|
||||
rougail_process += """
|
||||
disabled:
|
||||
type: jinja
|
||||
jinja: |
|
||||
"""
|
||||
for hidden_output in hidden_outputs:
|
||||
rougail_process += """ {% if _.output is not propertyerror and _.output == 'NAME' %}
|
||||
Cannot load user data for NAME output
|
||||
{% endif %}
|
||||
""".replace(
|
||||
"NAME", hidden_output
|
||||
)
|
||||
rougail_process += f""" description: {_('outputs {0} did not allow user data')}
|
||||
""".format(display_list(hidden_outputs, add_quote=True, separator="or"))
|
||||
elif objects:
|
||||
rougail_process += " default: {DEFAULT}".format(
|
||||
DEFAULT=objects[0]["name"]
|
||||
)
|
||||
else:
|
||||
if process == "output":
|
||||
prop = "hidden"
|
||||
else:
|
||||
prop = "disabled"
|
||||
rougail_process += """
|
||||
{NAME}:
|
||||
description: Select for {NAME}
|
||||
mandatory: false
|
||||
{PROP}: true
|
||||
multi: true
|
||||
default: ["You haven't installed \\\"{NAME}\\\" package for rougail"]
|
||||
validators:
|
||||
- jinja: Please install a rougail-{NAME}-* package.
|
||||
""".format(
|
||||
NAME=normalize_family(process),
|
||||
PROP=prop,
|
||||
)
|
||||
rougail_process += f"""
|
||||
|
||||
define_default_params: false # {_('Override default parameters for option type')}
|
||||
|
||||
default_params:
|
||||
description: {_("Default parameters for option type")}
|
||||
disabled:
|
||||
variable: _.define_default_params
|
||||
when: false
|
||||
|
||||
"""
|
||||
for typ, typ_description, params in get_convert_option_types():
|
||||
rougail_process += f"""
|
||||
{typ}: # {typ_description}
|
||||
"""
|
||||
for key, key_type, description, multi, value, choices in params:
|
||||
rougail_process += f"""
|
||||
{key}:
|
||||
"""
|
||||
if description:
|
||||
rougail_process += f""" description: "{description}"
|
||||
"""
|
||||
rougail_process += f""" type: {key_type}
|
||||
multi: {multi}
|
||||
mandatory: false
|
||||
default: {value}
|
||||
"""
|
||||
if choices:
|
||||
rougail_process += " choices:\n"
|
||||
for choice in choices:
|
||||
rougail_process += f" - {choice}\n"
|
||||
rougail_options += rougail_process
|
||||
return processes, processes_empty, rougail_options
|
||||
|
||||
|
||||
def _rougail_config(
|
||||
backward_compatibility: bool = True,
|
||||
add_extra_options: bool = True,
|
||||
) -> "OptionDescription":
|
||||
processes, processes_empty, rougail_options = get_common_rougail_config(backward_compatibility=backward_compatibility)
|
||||
convert = StaticRougailConvert(add_extra_options)
|
||||
convert.init()
|
||||
convert.namespace = None
|
||||
convert.parse_root_file(
|
||||
["rougail.config"],
|
||||
"",
|
||||
"1.1",
|
||||
YAML().load(rougail_options),
|
||||
)
|
||||
for process_empty in processes_empty:
|
||||
convert.parse_root_file(
|
||||
["rougail.config"],
|
||||
"",
|
||||
"1.1",
|
||||
YAML().load(process_empty),
|
||||
)
|
||||
extra_vars = {}
|
||||
objects = []
|
||||
for obj in sorted(
|
||||
[obj for objects in processes.values() for obj in objects], key=get_level
|
||||
):
|
||||
if "extra_vars" in obj:
|
||||
extra_vars |= obj["extra_vars"]
|
||||
if not "options" in obj:
|
||||
continue
|
||||
if not isinstance(obj["options"], list):
|
||||
options = [obj["options"]]
|
||||
else:
|
||||
options = obj["options"]
|
||||
for option in options:
|
||||
convert.parse_root_file(
|
||||
[f'rougail.config.{obj["name"]}'],
|
||||
"",
|
||||
"1.1",
|
||||
YAML().load(option),
|
||||
)
|
||||
|
||||
tiram_obj = convert.save()
|
||||
optiondescription = {}
|
||||
exec(tiram_obj, {}, optiondescription) # pylint: disable=W0122
|
||||
return optiondescription["option_0"], extra_vars
|
||||
|
||||
|
||||
def get_rougail_config(
|
||||
*,
|
||||
backward_compatibility: bool = True,
|
||||
add_extra_options: bool = True,
|
||||
) -> _RougailConfig:
|
||||
return _RougailConfig(
|
||||
backward_compatibility,
|
||||
add_extra_options,
|
||||
)
|
||||
|
||||
|
||||
RougailConfig = get_rougail_config()
|
||||
79
src/rougail/convert/__init__.py
Normal file
79
src/rougail/convert/__init__.py
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
"""Silique (https://www.silique.fr)
|
||||
Copyright (C) 2022-2026
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
from tiramisu import Config
|
||||
from warnings import warn
|
||||
|
||||
from .convert import RougailConvert
|
||||
from ..types import rougail_type
|
||||
from ..config import RougailConfig
|
||||
from ..user_data import UserData
|
||||
from ..tiramisu import tiramisu_display_name
|
||||
|
||||
|
||||
class Rougail(UserData):
|
||||
"""Main Rougail object"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
rougailconfig: Optional[RougailConfig]=None,
|
||||
load_from_tiramisu_cache: bool=False,
|
||||
) -> None:
|
||||
if rougailconfig is None:
|
||||
rougailconfig = RougailConfig
|
||||
self.rougailconfig = rougailconfig
|
||||
self.load_from_tiramisu_cache = load_from_tiramisu_cache and Path(self.rougailconfig["tiramisu_cache"]).is_file()
|
||||
types = rougail_type(self.rougailconfig)
|
||||
if not self.load_from_tiramisu_cache:
|
||||
self.converted = RougailConvert(self.rougailconfig, *types)
|
||||
self.config = None
|
||||
|
||||
def get_root_option(self):
|
||||
if not self.load_from_tiramisu_cache:
|
||||
tiram_obj = self.converted.save()
|
||||
else:
|
||||
tiramisu_cache = self.rougailconfig["tiramisu_cache"]
|
||||
with open(tiramisu_cache, "r", encoding="utf-8") as tiramisu:
|
||||
tiram_obj = tiramisu.read()
|
||||
optiondescription = {}
|
||||
custom_types = {
|
||||
custom.__name__: custom
|
||||
for custom in self.rougailconfig["custom_types"].values()
|
||||
}
|
||||
exec(tiram_obj, custom_types, optiondescription) # pylint: disable=W0122
|
||||
return optiondescription["option_0"]
|
||||
|
||||
def run(self, *, name: Optional[str] = None):
|
||||
"""Get Tiramisu Config"""
|
||||
if not self.config:
|
||||
self.config = Config(
|
||||
self.get_root_option(),
|
||||
name=name,
|
||||
display_name=tiramisu_display_name,
|
||||
)
|
||||
self.config.property.read_write()
|
||||
return self.config
|
||||
|
||||
def get_config(self):
|
||||
warn(
|
||||
"get_config is deprecated, use run instead",
|
||||
DeprecationWarning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return self.run()
|
||||
File diff suppressed because it is too large
Load diff
1121
src/rougail/convert/object_model.py
Normal file
1121
src/rougail/convert/object_model.py
Normal file
File diff suppressed because it is too large
Load diff
242
src/rougail/convert/path.py
Normal file
242
src/rougail/convert/path.py
Normal file
|
|
@ -0,0 +1,242 @@
|
|||
"""
|
||||
Copyright (C) 2024-2026
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from typing import (
|
||||
Any,
|
||||
Dict,
|
||||
List,
|
||||
Union,
|
||||
)
|
||||
import logging
|
||||
from re import compile, findall
|
||||
|
||||
from .object_model import Family, Variable
|
||||
from ..error import DictConsistencyError
|
||||
from ..i18n import _
|
||||
from ..tiramisu import normalize_family
|
||||
|
||||
|
||||
class Paths:
|
||||
regexp_relative = compile(r"^_*\.(.*)$")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
default_namespace: str,
|
||||
isolated_namespace: bool,
|
||||
) -> None:
|
||||
self._data: Dict[str, Union[Variable, Family]] = {}
|
||||
self._dynamics: Dict[str:str] = {}
|
||||
if default_namespace is not None:
|
||||
default_namespace = normalize_family(default_namespace)
|
||||
self.default_namespace = default_namespace
|
||||
self.isolated_namespace = isolated_namespace
|
||||
|
||||
def has_value(self) -> bool:
|
||||
return self._data != {}
|
||||
|
||||
def add(
|
||||
self,
|
||||
path: str,
|
||||
data: Any,
|
||||
is_dynamic: bool,
|
||||
dynamic: str,
|
||||
*,
|
||||
force: bool = False,
|
||||
) -> None:
|
||||
self._data[path] = data
|
||||
if not force and is_dynamic:
|
||||
self._dynamics[path] = dynamic
|
||||
|
||||
def get_full_path(
|
||||
self,
|
||||
path: str,
|
||||
current_path: str,
|
||||
):
|
||||
if "{{ suffix }}" in path:
|
||||
# version 1.0 and 1.1
|
||||
path = path.replace("{{ suffix }}", "{{ identifier }}")
|
||||
relative, subpath = path.split(".", 1)
|
||||
relative_len = len(relative)
|
||||
path_len = current_path.count(".")
|
||||
if path_len + 1 == relative_len:
|
||||
return subpath
|
||||
parent_path = current_path.rsplit(".", relative_len)[0]
|
||||
return parent_path + "." + subpath
|
||||
|
||||
def get_with_dynamic(
|
||||
self,
|
||||
path: str,
|
||||
current_path: str,
|
||||
version: str,
|
||||
namespace: str,
|
||||
xmlfiles: List[str],
|
||||
) -> Any:
|
||||
identifier = None
|
||||
if version != "1.0" and self.regexp_relative.search(path):
|
||||
path = self.get_full_path(
|
||||
path,
|
||||
current_path,
|
||||
)
|
||||
# elif identifier_path:
|
||||
# path = f"{identifier_path}.{path}"
|
||||
dynamic = None
|
||||
# version 1.0
|
||||
if version == "1.0":
|
||||
if not path in self._data and "{{ suffix }}" not in path:
|
||||
new_path = None
|
||||
current_path = None
|
||||
identifiers = []
|
||||
for name in path.split("."):
|
||||
parent_path = current_path
|
||||
if current_path:
|
||||
current_path += "." + name
|
||||
else:
|
||||
current_path = name
|
||||
if current_path in self._data:
|
||||
if new_path:
|
||||
new_path += "." + name
|
||||
else:
|
||||
new_path = name
|
||||
continue
|
||||
for dynamic_path in self._dynamics:
|
||||
if "." in dynamic_path:
|
||||
parent_dynamic, name_dynamic = dynamic_path.rsplit(".", 1)
|
||||
else:
|
||||
parent_dynamic = None
|
||||
name_dynamic = dynamic_path
|
||||
if (
|
||||
parent_dynamic == parent_path
|
||||
and name_dynamic.endswith("{{ identifier }}")
|
||||
and name == name_dynamic.replace("{{ identifier }}", "")
|
||||
):
|
||||
new_path += "." + name_dynamic
|
||||
break
|
||||
regexp = "^" + name_dynamic.replace("{{ identifier }}", "(.*)")
|
||||
finded = findall(regexp, name)
|
||||
if len(finded) != 1 or not finded[0]:
|
||||
continue
|
||||
if finded[0] == "{{ identifier }}":
|
||||
identifiers.append(None)
|
||||
else:
|
||||
identifiers.append(finded[0])
|
||||
if new_path is None:
|
||||
new_path = name_dynamic
|
||||
else:
|
||||
new_path += "." + name_dynamic
|
||||
parent_path = dynamic_path
|
||||
break
|
||||
else:
|
||||
if new_path:
|
||||
new_path += "." + name
|
||||
else:
|
||||
new_path = name
|
||||
path = new_path
|
||||
else:
|
||||
identifiers = None
|
||||
elif not path in self._data:
|
||||
new_path = parent_path = current_path = None
|
||||
identifiers = []
|
||||
for name in path.split("."):
|
||||
if current_path:
|
||||
current_path += "." + name
|
||||
else:
|
||||
current_path = name
|
||||
# parent_path, name_path = path.rsplit('.', 1)
|
||||
if current_path in self._data:
|
||||
if new_path:
|
||||
new_path += "." + name
|
||||
else:
|
||||
new_path = name
|
||||
parent_path = current_path
|
||||
continue
|
||||
for dynamic_path in self._dynamics:
|
||||
if "." in dynamic_path:
|
||||
parent_dynamic, name_dynamic = dynamic_path.rsplit(".", 1)
|
||||
else:
|
||||
parent_dynamic = None
|
||||
name_dynamic = dynamic_path
|
||||
if (
|
||||
"{{ identifier }}" not in name_dynamic
|
||||
or parent_path != parent_dynamic
|
||||
):
|
||||
continue
|
||||
regexp = "^" + name_dynamic.replace("{{ identifier }}", "(.*)")
|
||||
finded = findall(regexp, name)
|
||||
if len(finded) != 1 or not finded[0]:
|
||||
continue
|
||||
if finded[0] == "{{ identifier }}":
|
||||
identifiers.append(None)
|
||||
else:
|
||||
identifiers.append(finded[0])
|
||||
if new_path is None:
|
||||
new_path = name_dynamic
|
||||
else:
|
||||
new_path += "." + name_dynamic
|
||||
parent_path = dynamic_path
|
||||
break
|
||||
else:
|
||||
if new_path:
|
||||
new_path += "." + name
|
||||
else:
|
||||
new_path = name
|
||||
if "{{ identifier }}" in name:
|
||||
identifiers.append(None)
|
||||
parent_path = current_path
|
||||
path = new_path
|
||||
else:
|
||||
identifiers = None
|
||||
if path not in self._data:
|
||||
return None, None
|
||||
option = self._data[path]
|
||||
option_namespace = option.namespace
|
||||
if (
|
||||
self.isolated_namespace
|
||||
and self.default_namespace not in [namespace, option_namespace]
|
||||
and namespace != option_namespace
|
||||
):
|
||||
msg = _(
|
||||
'A variable or a family located in the "{0}" namespace shall not be used in the "{1}" namespace'
|
||||
).format(option_namespace, namespace)
|
||||
raise DictConsistencyError(msg, 38, xmlfiles)
|
||||
return option, identifiers
|
||||
|
||||
def __getitem__(
|
||||
self,
|
||||
path: str,
|
||||
) -> Union[Family, Variable]:
|
||||
if not path in self._data:
|
||||
raise AttributeError(f"cannot find variable or family {path}")
|
||||
return self._data[path]
|
||||
|
||||
def __contains__(
|
||||
self,
|
||||
path: str,
|
||||
) -> bool:
|
||||
return path in self._data
|
||||
|
||||
def __delitem__(
|
||||
self,
|
||||
path: str,
|
||||
) -> None:
|
||||
logging.info("remove empty family %s", path)
|
||||
del self._data[path]
|
||||
|
||||
def is_dynamic(self, path: str) -> bool:
|
||||
return path in self._dynamics
|
||||
|
||||
def get(self):
|
||||
return self._data.values()
|
||||
|
|
@ -10,7 +10,7 @@ Cadoles (http://www.cadoles.com)
|
|||
Copyright (C) 2019-2021
|
||||
|
||||
Silique (https://www.silique.fr)
|
||||
Copyright (C) 2022-2024
|
||||
Copyright (C) 2022-2026
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
|
|
@ -30,10 +30,10 @@ from typing import Optional, Union
|
|||
from json import dumps
|
||||
from os.path import isfile, basename
|
||||
|
||||
from .i18n import _
|
||||
from .error import DictConsistencyError, VariableCalculationDependencyError
|
||||
from .utils import normalize_family
|
||||
from .object_model import Calculation, CONVERT_OPTION
|
||||
from ..i18n import _
|
||||
from ..error import DictConsistencyError, VariableCalculationDependencyError
|
||||
from ..tiramisu import normalize_family, CONVERT_OPTION
|
||||
from .object_model import Calculation
|
||||
|
||||
|
||||
class BaseElt: # pylint: disable=R0903
|
||||
|
|
@ -73,12 +73,7 @@ class TiramisuReflector:
|
|||
"from tiramisu import *",
|
||||
"from tiramisu.setting import ALLOWED_LEADER_PROPERTIES",
|
||||
"from re import compile as re_compile",
|
||||
]
|
||||
)
|
||||
if self.objectspace.export_with_import:
|
||||
self.text["header"].extend(
|
||||
[
|
||||
"from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription"
|
||||
"from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription",
|
||||
]
|
||||
)
|
||||
if funcs_paths:
|
||||
|
|
@ -87,7 +82,7 @@ class TiramisuReflector:
|
|||
continue
|
||||
self.text["header"].append(f"load_functions('{funcs_path}')")
|
||||
if self.objectspace.export_with_import:
|
||||
if objectspace.main_namespace:
|
||||
# if self.objectspace.has_namespace:
|
||||
self.text["header"].extend(
|
||||
[
|
||||
"try:",
|
||||
|
|
@ -131,33 +126,6 @@ class TiramisuReflector:
|
|||
elt,
|
||||
self,
|
||||
)
|
||||
# else:
|
||||
# path_prefixes = self.objectspace.paths.get_path_prefixes()
|
||||
# for path_prefix in path_prefixes:
|
||||
# space = self.objectspace.space.variables[path_prefix]
|
||||
# self.set_name(space)
|
||||
# baseprefix = Family(
|
||||
# space,
|
||||
# self,
|
||||
# )
|
||||
# basefamily.add(baseprefix)
|
||||
# for elt in self.reorder_family(space):
|
||||
# self.populate_family(
|
||||
# baseprefix,
|
||||
# elt,
|
||||
# )
|
||||
# if not hasattr(baseprefix.elt, "information"):
|
||||
# baseprefix.elt.information = self.objectspace.information(
|
||||
# baseprefix.elt.xmlfiles
|
||||
# )
|
||||
# for key, value in self.objectspace.paths.get_providers_path(
|
||||
# path_prefix
|
||||
# ).items():
|
||||
# setattr(baseprefix.elt.information, key, value)
|
||||
# for key, value in self.objectspace.paths.get_suppliers_path(
|
||||
# path_prefix
|
||||
# ).items():
|
||||
# setattr(baseprefix.elt.information, key, value)
|
||||
baseelt.name = normalize_family(self.objectspace.base_option_name)
|
||||
baseelt.description = self.objectspace.base_option_name
|
||||
self.reflector_objects[baseelt.path].get(
|
||||
|
|
@ -253,14 +221,31 @@ class Common:
|
|||
properties = []
|
||||
calc_properties = []
|
||||
for property_, value in values.items():
|
||||
if value is True:
|
||||
properties.append(self.convert_str(property_))
|
||||
elif isinstance(value, list):
|
||||
if not isinstance(value, list):
|
||||
value = [value]
|
||||
for val in value:
|
||||
calc_properties.append(self.calculation_value(val))
|
||||
else:
|
||||
calc_properties.append(self.calculation_value(value))
|
||||
return "frozenset({" + ", ".join(sorted(properties) + calc_properties) + "})"
|
||||
ret = self.calculation_property(val)
|
||||
if isinstance(ret, bool):
|
||||
if ret:
|
||||
properties.append(self.convert_str(property_))
|
||||
elif ret is not None:
|
||||
calc_properties.append(ret)
|
||||
if properties or calc_properties:
|
||||
return (
|
||||
"frozenset({" + ", ".join(sorted(properties) + calc_properties) + "})"
|
||||
)
|
||||
raise Exception("ca existe alors ...")
|
||||
|
||||
def calculation_property(
|
||||
self,
|
||||
value: Union[Calculation, bool],
|
||||
) -> Optional[bool]:
|
||||
if isinstance(value, Calculation):
|
||||
try:
|
||||
return self.calculation_value(value)
|
||||
except VariableCalculationDependencyError:
|
||||
return None
|
||||
return value
|
||||
|
||||
def calc_properties(
|
||||
self,
|
||||
|
|
@ -295,40 +280,14 @@ class Common:
|
|||
):
|
||||
"""Populate variable parameters"""
|
||||
if not isinstance(param, dict):
|
||||
if isinstance(param, str):
|
||||
value = self.convert_str(param)
|
||||
else:
|
||||
value = param
|
||||
return f"ParamValue({value})"
|
||||
param = {
|
||||
"type": "any",
|
||||
"value": param,
|
||||
}
|
||||
if param["type"] == "value":
|
||||
return f"ParamValue({param['value']})"
|
||||
if param["type"] == "information":
|
||||
# default? really?
|
||||
if self.elt.multi:
|
||||
default = []
|
||||
else:
|
||||
default = None
|
||||
if "variable" in param:
|
||||
if param["variable"].path == self.elt.path:
|
||||
return f'ParamSelfInformation("{param["information"]}", {default})'
|
||||
information_variable_path = param["variable"].path
|
||||
information_variable = self.tiramisu.reflector_objects[
|
||||
information_variable_path
|
||||
]
|
||||
if information_variable_path not in self.calls:
|
||||
option_name = information_variable.get(self.calls, self.elt.path)
|
||||
return f'ParamInformation("{param["information"]}", {default}, option={option_name})'
|
||||
else:
|
||||
information = (
|
||||
f'ParamInformation("{param["information"]}", {default})'
|
||||
)
|
||||
information_name = self.tiramisu.get_information_name()
|
||||
self.tiramisu.text["option"].append(
|
||||
f"{information_name} = {information}"
|
||||
)
|
||||
information_variable.informations.append(information_name)
|
||||
return information_name
|
||||
return f'ParamInformation("{param["information"]}", {default})'
|
||||
return self.build_information_param(param)
|
||||
if param["type"] == "identifier":
|
||||
if "identifier" in param and param["identifier"] != None:
|
||||
return f"ParamIdentifier(identifier_index={param['identifier']})"
|
||||
|
|
@ -336,13 +295,7 @@ class Common:
|
|||
if param["type"] == "index":
|
||||
return "ParamIndex()"
|
||||
if param["type"] == "variable":
|
||||
return self.build_option_param(
|
||||
param["variable"],
|
||||
param.get("propertyerror", True),
|
||||
param.get("identifier"),
|
||||
param.get("dynamic"),
|
||||
param.get("whole", False),
|
||||
)
|
||||
return self.build_variable_param(param)
|
||||
if param["type"] == "any":
|
||||
if isinstance(param["value"], str):
|
||||
value = self.convert_str(param["value"])
|
||||
|
|
@ -351,25 +304,63 @@ class Common:
|
|||
return "ParamValue(" + value + ")"
|
||||
raise Exception("pfff")
|
||||
|
||||
def build_option_param(
|
||||
def build_information_param(self, param: dict) -> str:
|
||||
# default? really?
|
||||
if self.elt.multi:
|
||||
default = []
|
||||
else:
|
||||
default = None
|
||||
if "variable" in param:
|
||||
information_variable_path = param["variable"].path
|
||||
if information_variable_path == self.elt.path:
|
||||
return f'ParamSelfInformation("{param["information"]}", {default})'
|
||||
information_variable = self.tiramisu.reflector_objects[
|
||||
information_variable_path
|
||||
]
|
||||
if information_variable_path not in self.calls:
|
||||
option_name = information_variable.get(self.calls, self.elt.path)
|
||||
return f'ParamInformation("{param["information"]}", {default}, option={option_name})'
|
||||
else:
|
||||
# if we want to get information from the a parent family
|
||||
information = f'ParamInformation("{param["information"]}", {default})'
|
||||
information_name = self.tiramisu.get_information_name()
|
||||
self.tiramisu.text["option"].append(
|
||||
f"{information_name} = {information}"
|
||||
)
|
||||
information_variable.informations.append(information_name)
|
||||
return information_name
|
||||
return f'ParamInformation("{param["information"]}", {default})'
|
||||
|
||||
def build_variable_param(
|
||||
self,
|
||||
variable,
|
||||
propertyerror,
|
||||
identifier: Optional[str],
|
||||
dynamic,
|
||||
whole: bool,
|
||||
param: dict,
|
||||
) -> str:
|
||||
"""build variable parameters"""
|
||||
variable = param["variable"]
|
||||
whole = param.get("whole", False)
|
||||
dynamic = param.get("dynamic", True)
|
||||
if variable.path == self.elt.path:
|
||||
return f"ParamSelfOption(whole={whole})"
|
||||
ret = f"ParamSelfOption(whole={whole}"
|
||||
if not dynamic:
|
||||
ret += ", dynamic=False"
|
||||
return ret + ')'
|
||||
if whole:
|
||||
msg = f'variable param "{variable.path}" has whole attribute but it\'s not allowed for external variable'
|
||||
raise DictConsistencyError(msg, 34, self.elt.xmlfiles)
|
||||
msg = _('variable param "{0}" has whole attribute but it\'s not allowed for external variable')
|
||||
raise DictConsistencyError(msg.format(variable.path), 34, self.elt.xmlfiles)
|
||||
if not dynamic:
|
||||
msg = _('variable param "{0}" has dynamic attribute but it\'s not allowed for external variable')
|
||||
raise DictConsistencyError(msg.format(variable.path), 34, self.elt.xmlfiles)
|
||||
option_name = self.tiramisu.reflector_objects[variable.path].get(
|
||||
self.calls, self.elt.path
|
||||
)
|
||||
params = [f"{option_name}"]
|
||||
identifier = param.get("identifier")
|
||||
if identifier is not None:
|
||||
if not self.objectspace.paths.is_dynamic(variable.path):
|
||||
msg = _("internal error, {0} is not a dynamic variable").format(
|
||||
variable.path
|
||||
)
|
||||
raise DictConsistencyError(msg, 49, self.elt.xmlfiles)
|
||||
param_type = "ParamDynOption"
|
||||
identifiers = []
|
||||
for ident in identifier:
|
||||
|
|
@ -377,10 +368,15 @@ class Common:
|
|||
ident = self.convert_str(ident)
|
||||
identifiers.append(str(ident))
|
||||
params.append("[" + ", ".join(identifiers) + "]")
|
||||
if param.get("optional", False):
|
||||
params.append("optional=True")
|
||||
else:
|
||||
param_type = "ParamOption"
|
||||
propertyerror = param.get("propertyerror", True)
|
||||
if not propertyerror:
|
||||
params.append("notraisepropertyerror=True")
|
||||
elif propertyerror == "transitive":
|
||||
params.append("raisepropertyerror=True")
|
||||
return f'{param_type}({", ".join(params)})'
|
||||
|
||||
def calculation_value(
|
||||
|
|
@ -388,12 +384,16 @@ class Common:
|
|||
function,
|
||||
) -> str:
|
||||
"""Generate calculated value"""
|
||||
child = function.to_function(self.objectspace)
|
||||
child = function.to_function(self.objectspace, self.elt.path)
|
||||
if isinstance(child, str):
|
||||
return self.convert_str(child)
|
||||
elif not isinstance(child, dict):
|
||||
return child
|
||||
new_args = []
|
||||
kwargs = []
|
||||
if "params" in child:
|
||||
for key, value in child["params"].items():
|
||||
if not key:
|
||||
if key is None:
|
||||
for val in value:
|
||||
new_args.append(self.populate_param(val))
|
||||
else:
|
||||
|
|
@ -406,8 +406,8 @@ class Common:
|
|||
if kwargs:
|
||||
ret += ", kwargs={" + ", ".join(kwargs) + "}"
|
||||
ret += ")"
|
||||
if hasattr(child, "warnings_only"):
|
||||
ret += f", warnings_only={child.warnings_only}"
|
||||
if "warnings_only" in child:
|
||||
ret += f", warnings_only={child['warnings_only']}"
|
||||
if "help" in child:
|
||||
ret += f", help_function=func['{child['help']}']"
|
||||
ret = ret + ")"
|
||||
|
|
@ -418,10 +418,10 @@ class Common:
|
|||
datas: Union[Calculation, str, list],
|
||||
return_a_tuple: bool = False,
|
||||
) -> str:
|
||||
if isinstance(datas, str):
|
||||
return self.convert_str(datas)
|
||||
if isinstance(datas, Calculation):
|
||||
return self.calculation_value(datas)
|
||||
datas = self.calculation_value(datas)
|
||||
elif isinstance(datas, str):
|
||||
datas = self.convert_str(datas)
|
||||
if not isinstance(datas, list):
|
||||
return datas
|
||||
params = []
|
||||
|
|
@ -430,9 +430,11 @@ class Common:
|
|||
try:
|
||||
params.append(self.calculation_value(data))
|
||||
except VariableCalculationDependencyError:
|
||||
pass
|
||||
continue
|
||||
elif isinstance(data, str):
|
||||
params.append(self.convert_str(data))
|
||||
elif isinstance(data, dict):
|
||||
params.append(data)
|
||||
else:
|
||||
params.append(str(data))
|
||||
if return_a_tuple:
|
||||
|
|
@ -473,9 +475,14 @@ class Variable(Common):
|
|||
)
|
||||
return
|
||||
if self.elt.type == "choice":
|
||||
try:
|
||||
keys["values"] = self.populate_calculation(
|
||||
self.elt.choices, return_a_tuple=True
|
||||
)
|
||||
if keys["values"] == "(,)":
|
||||
keys["values"] = tuple()
|
||||
except VariableCalculationDependencyError:
|
||||
keys["values"] = tuple()
|
||||
if self.elt.type == "regexp":
|
||||
self.object_type = "Regexp_" + self.option_name
|
||||
self.tiramisu.text["header"].append(
|
||||
|
|
@ -501,6 +508,8 @@ class Variable(Common):
|
|||
pass
|
||||
if self.elt.validators:
|
||||
keys["validators"] = self.populate_calculation(self.elt.validators)
|
||||
if self.elt.warnings:
|
||||
keys["warnings_only"] = True
|
||||
for key, value in (
|
||||
CONVERT_OPTION.get(self.elt.type, {}).get("initkwargs", {}).items()
|
||||
):
|
||||
|
|
@ -548,7 +557,10 @@ class Family(Common):
|
|||
if self.group_type:
|
||||
keys["group_type"] = self.group_type
|
||||
if self.elt.type == "dynamic":
|
||||
try:
|
||||
keys["identifiers"] = self.populate_calculation(self.elt.dynamic)
|
||||
except VariableCalculationDependencyError:
|
||||
keys["identifiers"] = []
|
||||
children = []
|
||||
for path in self.objectspace.parents[self.elt.path]:
|
||||
children.append(self.objectspace.paths[path])
|
||||
|
|
@ -9,7 +9,7 @@ Cadoles (http://www.cadoles.com)
|
|||
Copyright (C) 2019-2021
|
||||
|
||||
Silique (https://www.silique.fr)
|
||||
Copyright (C) 2022-2024
|
||||
Copyright (C) 2022-2026
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
|
|
@ -26,13 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
"""
|
||||
|
||||
from .i18n import _
|
||||
|
||||
|
||||
def display_xmlfiles(xmlfiles: list) -> str:
|
||||
"""The function format xmlfiles informations to generate errors"""
|
||||
if len(xmlfiles) == 1:
|
||||
return '"' + xmlfiles[0] + '"'
|
||||
return '"' + '", "'.join(xmlfiles[:-1]) + '"' + " and " + '"' + xmlfiles[-1] + '"'
|
||||
from .tiramisu import display_xmlfiles
|
||||
|
||||
|
||||
class ConfigError(Exception):
|
||||
|
|
@ -69,10 +63,6 @@ class DictConsistencyError(Exception):
|
|||
self.errno = errno
|
||||
|
||||
|
||||
class UpgradeError(Exception):
|
||||
"""Error during XML upgrade"""
|
||||
|
||||
|
||||
## ---- generic exceptions ----
|
||||
|
||||
|
||||
|
|
@ -81,6 +71,14 @@ class NotFoundError(Exception):
|
|||
pass
|
||||
|
||||
|
||||
class ExtensionError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class RougailWarning(UserWarning):
|
||||
pass
|
||||
|
||||
|
||||
## ---- specific exceptions ----
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Cadoles (http://www.cadoles.com)
|
|||
Copyright (C) 2019-2021
|
||||
|
||||
Silique (https://www.silique.fr)
|
||||
Copyright (C) 2022-2024
|
||||
Copyright (C) 2022-2026
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,765 +0,0 @@
|
|||
"""Rougail object model
|
||||
|
||||
Silique (https://www.silique.fr)
|
||||
Copyright (C) 2023-2024
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from typing import Optional, Union, get_type_hints, Any, Literal, List, Dict, Iterator
|
||||
from pydantic import (
|
||||
BaseModel,
|
||||
StrictBool,
|
||||
StrictInt,
|
||||
StrictFloat,
|
||||
StrictStr,
|
||||
ConfigDict,
|
||||
)
|
||||
from tiramisu import undefined
|
||||
from .utils import get_jinja_variable_to_param, get_realpath
|
||||
from .error import DictConsistencyError, VariableCalculationDependencyError
|
||||
|
||||
BASETYPE = Union[StrictBool, StrictInt, StrictFloat, StrictStr, None]
|
||||
PROPERTY_ATTRIBUTE = ["frozen", "hidden", "disabled", "mandatory"]
|
||||
|
||||
|
||||
def convert_boolean(value: str) -> bool:
|
||||
"""Boolean coercion. The Rougail XML may contain srings like `True` or `False`"""
|
||||
if isinstance(value, bool):
|
||||
return value
|
||||
value = value.lower()
|
||||
if value == "true":
|
||||
return True
|
||||
elif value == "false":
|
||||
return False
|
||||
elif value in ["", None]:
|
||||
return None
|
||||
raise Exception(f'unknown boolean value "{value}"')
|
||||
|
||||
|
||||
CONVERT_OPTION = {
|
||||
"string": dict(opttype="StrOption", example="example"),
|
||||
"number": dict(opttype="IntOption", func=int, example=42),
|
||||
"float": dict(opttype="FloatOption", func=float, example=1.42),
|
||||
"boolean": dict(opttype="BoolOption", func=convert_boolean),
|
||||
"secret": dict(opttype="PasswordOption", example="secrets"),
|
||||
"mail": dict(opttype="EmailOption", example="user@example.net"),
|
||||
"unix_filename": dict(opttype="FilenameOption", example="/tmp/myfile.txt"),
|
||||
"date": dict(opttype="DateOption", example="2000-01-01"),
|
||||
"unix_user": dict(opttype="UsernameOption", example="username"),
|
||||
"ip": dict(
|
||||
opttype="IPOption", initkwargs={"allow_reserved": True}, example="1.1.1.1"
|
||||
),
|
||||
"cidr": dict(opttype="IPOption", initkwargs={"cidr": True}, example="1.1.1.0/24"),
|
||||
"netmask": dict(opttype="NetmaskOption", example="255.255.255.0"),
|
||||
"network": dict(opttype="NetworkOption", example="1.1.1.0"),
|
||||
"network_cidr": dict(
|
||||
opttype="NetworkOption", initkwargs={"cidr": True}, example="1.1.1.0/24"
|
||||
),
|
||||
"broadcast": dict(opttype="BroadcastOption", example="1.1.1.255"),
|
||||
"netbios": dict(
|
||||
opttype="DomainnameOption",
|
||||
initkwargs={"type": "netbios", "warnings_only": True},
|
||||
example="example",
|
||||
),
|
||||
"domainname": dict(
|
||||
opttype="DomainnameOption",
|
||||
initkwargs={"type": "domainname", "allow_ip": False},
|
||||
example="example.net",
|
||||
),
|
||||
"hostname": dict(
|
||||
opttype="DomainnameOption",
|
||||
initkwargs={"type": "hostname", "allow_ip": False},
|
||||
example="example",
|
||||
),
|
||||
"web_address": dict(
|
||||
opttype="URLOption",
|
||||
initkwargs={"allow_ip": False, "allow_without_dot": True},
|
||||
example="https://example.net",
|
||||
),
|
||||
"port": dict(
|
||||
opttype="PortOption", initkwargs={"allow_private": True}, example="111"
|
||||
),
|
||||
"mac": dict(opttype="MACOption", example="00:00:00:00:00"),
|
||||
"unix_permissions": dict(
|
||||
opttype="PermissionsOption",
|
||||
initkwargs={"warnings_only": True},
|
||||
func=int,
|
||||
example="644",
|
||||
),
|
||||
"choice": dict(opttype="ChoiceOption", example="a_choice"),
|
||||
"regexp": dict(opttype="RegexpOption"),
|
||||
#
|
||||
"symlink": dict(opttype="SymLinkOption"),
|
||||
}
|
||||
|
||||
|
||||
class Param(BaseModel):
|
||||
key: str
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
path,
|
||||
attribute,
|
||||
family_is_dynamic,
|
||||
is_follower,
|
||||
xmlfiles,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
class AnyParam(Param):
|
||||
type: str
|
||||
value: Union[BASETYPE, List[BASETYPE]]
|
||||
|
||||
|
||||
class VariableParam(Param):
|
||||
type: str
|
||||
variable: str
|
||||
propertyerror: bool = True
|
||||
whole: bool = False
|
||||
optional: bool = False
|
||||
|
||||
|
||||
class IdentifierParam(Param):
|
||||
type: str
|
||||
identifier: Optional[int] = None
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
if not kwargs["family_is_dynamic"]:
|
||||
msg = f'identifier parameter for "{kwargs["attribute"]}" in "{kwargs["path"]}" cannot be set none dynamic family'
|
||||
raise DictConsistencyError(msg, 10, kwargs["xmlfiles"])
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
class InformationParam(Param):
|
||||
type: str
|
||||
information: str
|
||||
variable: Optional[str] = None
|
||||
|
||||
|
||||
class IndexParam(Param):
|
||||
type: str
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
|
||||
if not kwargs["is_follower"]:
|
||||
msg = f'the variable "{kwargs["path"]}" is not a follower, so cannot have index type for param in "{kwargs["attribute"]}"'
|
||||
raise DictConsistencyError(msg, 25, kwargs["xmlfiles"])
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
PARAM_TYPES = {
|
||||
"any": AnyParam,
|
||||
"variable": VariableParam,
|
||||
"identifier": IdentifierParam,
|
||||
"information": InformationParam,
|
||||
"index": IndexParam,
|
||||
}
|
||||
|
||||
|
||||
class Calculation(BaseModel):
|
||||
path_prefix: Optional[str]
|
||||
path: str
|
||||
inside_list: bool
|
||||
version: str
|
||||
ori_path: Optional[str] = None
|
||||
default_values: Any = None
|
||||
namespace: Optional[str]
|
||||
xmlfiles: List[str]
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
def get_realpath(
|
||||
self,
|
||||
path: str,
|
||||
) -> str:
|
||||
return get_realpath(path, self.path_prefix)
|
||||
|
||||
def get_params(self, objectspace):
|
||||
if not self.params:
|
||||
return {}
|
||||
params = {}
|
||||
for param_obj in self.params:
|
||||
param = param_obj.model_dump()
|
||||
if param.get("type") == "variable":
|
||||
if self.ori_path is None:
|
||||
path = self.path
|
||||
else:
|
||||
path = self.ori_path
|
||||
variable, identifier = objectspace.paths.get_with_dynamic(
|
||||
param["variable"],
|
||||
self.path_prefix,
|
||||
path,
|
||||
self.version,
|
||||
self.namespace,
|
||||
self.xmlfiles,
|
||||
)
|
||||
if not variable:
|
||||
if not param.get("optional"):
|
||||
msg = f'cannot find variable "{param["variable"]}" defined attribute in "{self.attribute_name}" for "{self.path}"'
|
||||
raise DictConsistencyError(msg, 22, self.xmlfiles)
|
||||
continue
|
||||
if not isinstance(variable, objectspace.variable):
|
||||
raise Exception("pfff it's a family")
|
||||
param["variable"] = variable
|
||||
if identifier:
|
||||
param["identifier"] = identifier
|
||||
if param.get("type") == "information":
|
||||
if param["variable"]:
|
||||
if self.ori_path is None:
|
||||
path = self.path
|
||||
else:
|
||||
path = self.ori_path
|
||||
variable, identifier = objectspace.paths.get_with_dynamic(
|
||||
param["variable"],
|
||||
self.path_prefix,
|
||||
path,
|
||||
self.version,
|
||||
self.namespace,
|
||||
self.xmlfiles,
|
||||
)
|
||||
if not variable:
|
||||
msg = f'cannot find variable "{param["variable"]}" defined in "{self.attribute_name}" for "{self.path}"'
|
||||
raise DictConsistencyError(msg, 14, self.xmlfiles)
|
||||
param["variable"] = variable
|
||||
if identifier:
|
||||
msg = f'variable "{param["variable"]}" defined in "{self.attribute_name}" for "{self.path}" is a dynamic variable'
|
||||
raise DictConsistencyError(msg, 15, self.xmlfiles)
|
||||
else:
|
||||
del param["variable"]
|
||||
params[param.pop("key")] = param
|
||||
return params
|
||||
|
||||
|
||||
class JinjaCalculation(Calculation):
|
||||
attribute_name: Literal[
|
||||
"frozen",
|
||||
"hidden",
|
||||
"mandatory",
|
||||
"empty",
|
||||
"disabled",
|
||||
"default",
|
||||
"validators",
|
||||
"choices",
|
||||
"dynamic",
|
||||
]
|
||||
jinja: StrictStr
|
||||
params: Optional[List[Param]] = None
|
||||
return_type: BASETYPE = None
|
||||
description: Optional[StrictStr] = None
|
||||
|
||||
def _jinja_to_function(
|
||||
self,
|
||||
function,
|
||||
return_type,
|
||||
multi,
|
||||
objectspace,
|
||||
*,
|
||||
add_help=False,
|
||||
params: Optional[dict] = None,
|
||||
):
|
||||
variable = objectspace.paths[self.path]
|
||||
jinja_path = f"{self.attribute_name}_{self.path}"
|
||||
idx = 0
|
||||
while jinja_path in objectspace.jinja:
|
||||
jinja_path = f"{self.attribute_name}_{self.path}_{idx}"
|
||||
idx += 1
|
||||
objectspace.jinja[jinja_path] = self.jinja
|
||||
default = {
|
||||
"function": function,
|
||||
"params": {
|
||||
"__internal_jinja": jinja_path,
|
||||
"__internal_type": return_type,
|
||||
"__internal_multi": multi,
|
||||
"__internal_files": self.xmlfiles,
|
||||
"__internal_attribute": self.attribute_name,
|
||||
"__internal_variable": self.path,
|
||||
},
|
||||
}
|
||||
if self.default_values:
|
||||
default["params"]["__default_value"] = self.default_values
|
||||
if add_help:
|
||||
default["help"] = function + "_help"
|
||||
if self.params:
|
||||
default["params"] |= self.get_params(objectspace)
|
||||
if params:
|
||||
default["params"] |= params
|
||||
if self.ori_path is None:
|
||||
path = self.path
|
||||
else:
|
||||
path = self.ori_path
|
||||
for sub_variable, identifier, true_path in get_jinja_variable_to_param(
|
||||
path,
|
||||
self.jinja,
|
||||
objectspace,
|
||||
variable.xmlfiles,
|
||||
objectspace.functions,
|
||||
self.path_prefix,
|
||||
self.version,
|
||||
self.namespace,
|
||||
):
|
||||
if true_path in default["params"]:
|
||||
continue
|
||||
if isinstance(sub_variable, dict):
|
||||
default["params"][true_path] = {
|
||||
"type": "value",
|
||||
"value": sub_variable,
|
||||
}
|
||||
else:
|
||||
default["params"][true_path] = {
|
||||
"type": "variable",
|
||||
"variable": sub_variable,
|
||||
}
|
||||
if self.version != "1.0":
|
||||
default["params"][true_path]["propertyerror"] = False
|
||||
if identifier:
|
||||
default["params"][true_path]["identifier"] = identifier
|
||||
return default
|
||||
|
||||
def to_function(
|
||||
self,
|
||||
objectspace,
|
||||
) -> dict:
|
||||
if self.attribute_name == "default":
|
||||
if self.return_type:
|
||||
raise Exception("return_type not allowed!")
|
||||
variable = objectspace.paths[self.path]
|
||||
return_type = variable.type
|
||||
if self.inside_list:
|
||||
multi = False
|
||||
elif self.path in objectspace.followers:
|
||||
multi = objectspace.multis[self.path] == "submulti"
|
||||
else:
|
||||
multi = self.path in objectspace.multis
|
||||
return self._jinja_to_function(
|
||||
"jinja_to_function",
|
||||
return_type,
|
||||
multi,
|
||||
objectspace,
|
||||
)
|
||||
elif self.attribute_name == "validators":
|
||||
if self.return_type:
|
||||
raise Exception("pfff")
|
||||
return self._jinja_to_function(
|
||||
"valid_with_jinja",
|
||||
"string",
|
||||
False,
|
||||
objectspace,
|
||||
)
|
||||
elif self.attribute_name in PROPERTY_ATTRIBUTE:
|
||||
if self.return_type:
|
||||
raise Exception("return_type not allowed!")
|
||||
return self._jinja_to_function(
|
||||
"jinja_to_property",
|
||||
"string",
|
||||
False,
|
||||
objectspace,
|
||||
add_help=True,
|
||||
params={None: [self.attribute_name], "when": True, "inverse": False},
|
||||
)
|
||||
elif self.attribute_name == "choices":
|
||||
return_type = self.return_type
|
||||
if return_type is None:
|
||||
return_type = "string"
|
||||
return self._jinja_to_function(
|
||||
"jinja_to_function",
|
||||
return_type,
|
||||
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):
|
||||
variable: StrictStr
|
||||
propertyerror: bool = True
|
||||
allow_none: bool = False
|
||||
|
||||
def get_variable(
|
||||
self,
|
||||
objectspace,
|
||||
) -> "Variable":
|
||||
if self.ori_path is None:
|
||||
path = self.path
|
||||
else:
|
||||
path = self.ori_path
|
||||
variable, identifier = objectspace.paths.get_with_dynamic(
|
||||
self.variable,
|
||||
self.path_prefix,
|
||||
path,
|
||||
self.version,
|
||||
self.namespace,
|
||||
self.xmlfiles,
|
||||
)
|
||||
if variable and not isinstance(variable, objectspace.variable):
|
||||
# FIXME remove the pfff
|
||||
raise Exception("pfff it's a family")
|
||||
return variable, identifier
|
||||
|
||||
def get_params(
|
||||
self,
|
||||
objectspace,
|
||||
variable: "Variable",
|
||||
identifier: Optional[str],
|
||||
*,
|
||||
needs_multi: Optional[bool] = None,
|
||||
):
|
||||
if not variable:
|
||||
msg = f'Variable not found "{self.variable}" for attribut "{self.attribute_name}" for variable "{self.path}"'
|
||||
raise DictConsistencyError(msg, 88, self.xmlfiles)
|
||||
param = {
|
||||
"type": "variable",
|
||||
"variable": variable,
|
||||
"propertyerror": self.propertyerror,
|
||||
}
|
||||
if identifier:
|
||||
param["identifier"] = identifier
|
||||
params = {None: [param]}
|
||||
if self.default_values:
|
||||
params["__default_value"] = self.default_values
|
||||
if self.allow_none:
|
||||
params["allow_none"] = True
|
||||
if needs_multi is None:
|
||||
if self.attribute_name != "default":
|
||||
needs_multi = True
|
||||
else:
|
||||
needs_multi = self.path in objectspace.multis
|
||||
calc_variable_is_multi = variable.path in objectspace.multis
|
||||
if not calc_variable_is_multi:
|
||||
if variable.path in objectspace.paths._dynamics and (
|
||||
identifier is None or identifier[-1] is None
|
||||
):
|
||||
self_dyn_path = objectspace.paths._dynamics.get(self.path)
|
||||
if self_dyn_path is not None:
|
||||
var_dyn_path = objectspace.paths._dynamics[variable.path]
|
||||
if self_dyn_path != var_dyn_path and not self_dyn_path.startswith(
|
||||
f"{var_dyn_path}."
|
||||
):
|
||||
calc_variable_is_multi = True
|
||||
else:
|
||||
calc_variable_is_multi = True
|
||||
elif identifier and "{{ identifier }}" in identifier:
|
||||
calc_variable_is_multi = True
|
||||
if needs_multi:
|
||||
if calc_variable_is_multi:
|
||||
if self.inside_list:
|
||||
msg = f'the variable "{self.path}" has an invalid attribute "{self.attribute_name}", the variable "{variable.path}" is multi but is inside a list'
|
||||
raise DictConsistencyError(msg, 18, self.xmlfiles)
|
||||
elif not self.inside_list:
|
||||
msg = f'the variable "{self.path}" has an invalid attribute "{self.attribute_name}", the variable "{variable.path}" is not multi but is not inside a list'
|
||||
raise DictConsistencyError(msg, 20, self.xmlfiles)
|
||||
elif self.inside_list:
|
||||
msg = f'the variable "{self.path}" has an invalid attribute "{self.attribute_name}", it\'s a list'
|
||||
raise DictConsistencyError(msg, 23, self.xmlfiles)
|
||||
elif calc_variable_is_multi:
|
||||
if (
|
||||
variable.multi
|
||||
or variable.path.rsplit(".", 1)[0] != self.path.rsplit(".", 1)[0]
|
||||
):
|
||||
# it's not a follower or not in same leadership
|
||||
msg = f'the variable "{self.path}" has an invalid attribute "{self.attribute_name}", the variable "{variable.path}" is a multi'
|
||||
raise DictConsistencyError(msg, 21, self.xmlfiles)
|
||||
else:
|
||||
params[None][0]["index"] = {"index": {"type": "index"}}
|
||||
return params
|
||||
|
||||
|
||||
class VariableCalculation(_VariableCalculation):
|
||||
attribute_name: Literal["default", "choices", "dynamic"]
|
||||
optional: bool = False
|
||||
|
||||
def to_function(
|
||||
self,
|
||||
objectspace,
|
||||
) -> dict:
|
||||
if self.attribute_name != "default" and self.optional:
|
||||
msg = f'"{self.attribute_name}" variable shall not have an "optional" attribute for variable "{self.variable}"'
|
||||
raise DictConsistencyError(msg, 33, self.xmlfiles)
|
||||
variable, identifier = self.get_variable(objectspace)
|
||||
if not variable and self.optional:
|
||||
raise VariableCalculationDependencyError()
|
||||
params = self.get_params(
|
||||
objectspace,
|
||||
variable,
|
||||
identifier,
|
||||
)
|
||||
return {
|
||||
"function": "calc_value",
|
||||
"params": params,
|
||||
}
|
||||
|
||||
|
||||
class VariablePropertyCalculation(_VariableCalculation):
|
||||
attribute_name: Literal[*PROPERTY_ATTRIBUTE]
|
||||
when: Any = undefined
|
||||
when_not: Any = undefined
|
||||
|
||||
def to_function(
|
||||
self,
|
||||
objectspace,
|
||||
) -> dict:
|
||||
variable, identifier = self.get_variable(objectspace)
|
||||
params = self.get_params(
|
||||
objectspace,
|
||||
variable,
|
||||
identifier,
|
||||
needs_multi=False,
|
||||
)
|
||||
variable = params[None][0]["variable"]
|
||||
if self.when is not undefined:
|
||||
if self.version == "1.0":
|
||||
msg = f'when is not allowed in format version 1.0 for attribute "{self.attribute_name}" for variable "{self.path}"'
|
||||
raise DictConsistencyError(msg, 103, variable.xmlfiles)
|
||||
if self.when_not is not undefined:
|
||||
msg = f'the variable "{self.path}" has an invalid attribute "{self.attribute_name}", when and when_not cannot set together'
|
||||
raise DictConsistencyError(msg, 31, variable.xmlfiles)
|
||||
when = self.when
|
||||
inverse = False
|
||||
elif self.when_not is not undefined:
|
||||
if self.version == "1.0":
|
||||
msg = f'when_not is not allowed in format version 1.0 for attribute "{self.attribute_name}" for variable "{self.path}"'
|
||||
raise DictConsistencyError(msg, 104, variable.xmlfiles)
|
||||
when = self.when_not
|
||||
inverse = True
|
||||
else:
|
||||
if variable.type != "boolean":
|
||||
raise Exception("only boolean!")
|
||||
when = True
|
||||
inverse = False
|
||||
params[None].insert(0, self.attribute_name)
|
||||
params["when"] = when
|
||||
params["inverse"] = inverse
|
||||
return {
|
||||
"function": "variable_to_property",
|
||||
"params": params,
|
||||
"help": "variable_to_property",
|
||||
}
|
||||
|
||||
|
||||
class InformationCalculation(Calculation):
|
||||
attribute_name: Literal["default", "choice", "dynamic"]
|
||||
information: StrictStr
|
||||
variable: Optional[StrictStr]
|
||||
|
||||
def to_function(
|
||||
self,
|
||||
objectspace,
|
||||
) -> dict:
|
||||
params = {
|
||||
None: [
|
||||
{
|
||||
"type": "information",
|
||||
"information": self.information,
|
||||
}
|
||||
]
|
||||
}
|
||||
if self.variable:
|
||||
if self.ori_path is None:
|
||||
path = self.path
|
||||
else:
|
||||
path = self.ori_path
|
||||
variable, identifier = objectspace.paths.get_with_dynamic(
|
||||
self.variable,
|
||||
self.path_prefix,
|
||||
path,
|
||||
self.version,
|
||||
self.namespace,
|
||||
self.xmlfiles,
|
||||
)
|
||||
if variable is None or identifier is not None:
|
||||
raise Exception("pfff")
|
||||
params[None][0]["variable"] = variable
|
||||
if self.default_values:
|
||||
params["__default_value"] = self.default_values
|
||||
return {
|
||||
"function": "calc_value",
|
||||
"params": params,
|
||||
}
|
||||
|
||||
|
||||
class _IdentifierCalculation(Calculation):
|
||||
identifier: Optional[int] = None
|
||||
|
||||
def get_identifier(self) -> dict:
|
||||
identifier = {"type": "identifier"}
|
||||
if self.identifier is not None:
|
||||
identifier["identifier"] = self.identifier
|
||||
return identifier
|
||||
|
||||
|
||||
class IdentifierCalculation(_IdentifierCalculation):
|
||||
attribute_name: Literal["default", "choice", "dynamic"]
|
||||
|
||||
def to_function(
|
||||
self,
|
||||
objectspace,
|
||||
) -> dict:
|
||||
identifier = {"type": "identifier"}
|
||||
if self.identifier is not None:
|
||||
identifier["identifier"] = self.identifier
|
||||
return {
|
||||
"function": "calc_value",
|
||||
"params": {None: [self.get_identifier()]},
|
||||
}
|
||||
|
||||
|
||||
class IdentifierPropertyCalculation(_IdentifierCalculation):
|
||||
attribute_name: Literal[*PROPERTY_ATTRIBUTE]
|
||||
when: Any = undefined
|
||||
when_not: Any = undefined
|
||||
|
||||
def to_function(
|
||||
self,
|
||||
objectspace,
|
||||
) -> dict:
|
||||
if self.version == "1.0":
|
||||
msg = f'when is not allowed in format version 1.0 for attribute "{self.attribute_name}"'
|
||||
raise DictConsistencyError(msg, 105, variable.xmlfiles)
|
||||
if self.when is not undefined:
|
||||
if self.when_not is not undefined:
|
||||
msg = f'the identifier has an invalid attribute "{self.attribute_name}", when and when_not cannot set together'
|
||||
raise DictConsistencyError(msg, 35, variable.xmlfiles)
|
||||
when = self.when
|
||||
inverse = False
|
||||
elif self.when_not is not undefined:
|
||||
when = self.when_not
|
||||
inverse = True
|
||||
else:
|
||||
msg = f'the identifier has an invalid attribute "{self.attribute_name}", when and when_not cannot set together'
|
||||
raise DictConsistencyError
|
||||
params = {
|
||||
None: [self.attribute_name, self.get_identifier()],
|
||||
"when": when,
|
||||
"inverse": inverse,
|
||||
}
|
||||
return {
|
||||
"function": "variable_to_property",
|
||||
"params": params,
|
||||
"help": "variable_to_property",
|
||||
}
|
||||
|
||||
|
||||
class IndexCalculation(Calculation):
|
||||
attribute_name: Literal["default", "choice", "dynamic"]
|
||||
|
||||
def to_function(
|
||||
self,
|
||||
objectspace,
|
||||
) -> dict:
|
||||
if self.path not in objectspace.followers:
|
||||
msg = f'the variable "{self.path}" is not a follower, so cannot have index type for "{self.attribute_name}"'
|
||||
raise DictConsistencyError(msg, 60, self.xmlfiles)
|
||||
return {
|
||||
"function": "calc_value",
|
||||
"params": {None: [{"type": "index"}]},
|
||||
}
|
||||
|
||||
|
||||
CALCULATION_TYPES = {
|
||||
"jinja": JinjaCalculation,
|
||||
"variable": VariableCalculation,
|
||||
"information": InformationCalculation,
|
||||
"identifier": IdentifierCalculation,
|
||||
"suffix": IdentifierCalculation,
|
||||
"index": IndexCalculation,
|
||||
}
|
||||
CALCULATION_PROPERTY_TYPES = {
|
||||
"jinja": JinjaCalculation,
|
||||
"variable": VariablePropertyCalculation,
|
||||
"information": InformationCalculation,
|
||||
"identifier": IdentifierPropertyCalculation,
|
||||
"index": IndexCalculation,
|
||||
}
|
||||
BASETYPE_CALC = Union[StrictBool, StrictInt, StrictFloat, StrictStr, Calculation, None]
|
||||
|
||||
|
||||
class Family(BaseModel):
|
||||
name: str
|
||||
description: Optional[str] = None
|
||||
type: Literal["family", "leadership", "dynamic"] = "family"
|
||||
path: str
|
||||
help: Optional[str] = None
|
||||
mode: Optional[str] = None
|
||||
hidden: Union[bool, Calculation] = False
|
||||
disabled: Union[bool, Calculation] = False
|
||||
namespace: Optional[str]
|
||||
version: str
|
||||
xmlfiles: List[str] = []
|
||||
|
||||
model_config = ConfigDict(extra="forbid", arbitrary_types_allowed=True)
|
||||
|
||||
|
||||
class Dynamic(Family):
|
||||
# None only for format 1.0
|
||||
variable: str = None
|
||||
dynamic: Union[List[Union[StrictStr, Calculation]], Calculation]
|
||||
|
||||
|
||||
class Variable(BaseModel):
|
||||
# type will be set dynamically in `annotator/value.py`, default is None
|
||||
type: str = None
|
||||
name: str
|
||||
description: Optional[str] = None
|
||||
default: Union[List[BASETYPE_CALC], BASETYPE_CALC] = None
|
||||
choices: Optional[Union[List[BASETYPE_CALC], Calculation]] = None
|
||||
regexp: Optional[str] = None
|
||||
params: Optional[List[Param]] = None
|
||||
validators: Optional[List[Calculation]] = None
|
||||
multi: Optional[bool] = None
|
||||
unique: Optional[bool] = None
|
||||
help: Optional[str] = None
|
||||
hidden: Union[bool, Calculation] = False
|
||||
disabled: Union[bool, Calculation] = False
|
||||
mandatory: Union[None, bool, Calculation] = None
|
||||
empty: Union[None, bool, Calculation] = True
|
||||
auto_save: bool = False
|
||||
mode: Optional[str] = None
|
||||
test: Optional[list] = None
|
||||
examples: Optional[list] = None
|
||||
path: str
|
||||
namespace: Optional[str]
|
||||
version: str
|
||||
path_prefix: Optional[str]
|
||||
xmlfiles: List[str] = []
|
||||
|
||||
model_config = ConfigDict(extra="forbid", arbitrary_types_allowed=True)
|
||||
|
||||
|
||||
class SymLink(BaseModel):
|
||||
type: Literal["symlink"] = "symlink"
|
||||
name: str
|
||||
path: str
|
||||
opt: Variable
|
||||
namespace: Optional[str]
|
||||
version: str
|
||||
path_prefix: Optional[str]
|
||||
xmlfiles: List[str] = []
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
"""
|
||||
Silique (https://www.silique.fr)
|
||||
Copyright (C) 2024
|
||||
Copyright (C) 2024-2026
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
|
|
@ -16,4 +16,7 @@ You should have received a copy of the GNU Lesser General Public License
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from .update import RougailUpgrade
|
||||
from .object_model import Variable, Family
|
||||
|
||||
|
||||
__all__ = ("Variable", "Family")
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
"""Annotate to add specify attribute for tiramisu-cmdline
|
||||
|
||||
Silique (https://www.silique.fr)
|
||||
Copyright (C) 2024
|
||||
Copyright (C) 2024-2026
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
|
|
@ -50,7 +50,6 @@ class Annotator(Walk):
|
|||
self.not_for_commandline(variable)
|
||||
else:
|
||||
self.manage_alternative_name(variable)
|
||||
self.manage_negative_description(variable)
|
||||
|
||||
def not_for_commandline(self, variable) -> None:
|
||||
self.objectspace.properties.add(variable.path, "not_for_commandline", True)
|
||||
|
|
@ -60,6 +59,7 @@ class Annotator(Walk):
|
|||
return
|
||||
alternative_name = variable.alternative_name
|
||||
variable_path = variable.path
|
||||
self.objectspace.informations.add(variable_path, "alternative_name", alternative_name)
|
||||
all_letters = ""
|
||||
for letter in alternative_name:
|
||||
all_letters += letter
|
||||
|
|
@ -79,34 +79,14 @@ class Annotator(Walk):
|
|||
path = alternative_name
|
||||
else:
|
||||
path = variable_path.rsplit(".", 1)[0] + "." + alternative_name
|
||||
self.objectspace.version = variable.version
|
||||
self.objectspace.add_variable(
|
||||
alternative_name,
|
||||
{"type": "symlink", "path": path, "opt": variable},
|
||||
path,
|
||||
{"type": "symlink", "opt": variable},
|
||||
variable.xmlfiles,
|
||||
False,
|
||||
False,
|
||||
variable.version,
|
||||
)
|
||||
|
||||
def manage_negative_description(self, variable) -> None:
|
||||
if not variable.negative_description:
|
||||
if variable.type == "boolean" and not self.objectspace.add_extra_options:
|
||||
raise DictConsistencyError(
|
||||
_(
|
||||
'negative_description is mandatory for boolean variable, but "{0}" hasn\'t'
|
||||
).format(variable.path),
|
||||
200,
|
||||
variable.xmlfiles,
|
||||
)
|
||||
return
|
||||
if variable.type != "boolean":
|
||||
raise DictConsistencyError(
|
||||
_(
|
||||
'negative_description is only available for boolean variable, but "{0}" is "{1}"'
|
||||
).format(variable.path, variable.type),
|
||||
201,
|
||||
variable.xmlfiles,
|
||||
)
|
||||
self.objectspace.informations.add(
|
||||
variable.path, "negative_description", variable.negative_description
|
||||
False,
|
||||
False,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Config file for Rougail-structural_commandline
|
||||
|
||||
Silique (https://www.silique.fr)
|
||||
Copyright (C) 2024
|
||||
Copyright (C) 2024-2026
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
|
|
@ -27,12 +27,13 @@ def get_rougail_config(
|
|||
structural_commandline:
|
||||
description: Configuration rougail-structural_commandline
|
||||
commandline: false
|
||||
|
||||
add_extra_options:
|
||||
description: Add extra options to tiramisu-cmdline-parser
|
||||
default: true
|
||||
"""
|
||||
return {
|
||||
"name": "exporter",
|
||||
"name": "commandline",
|
||||
"process": "structural",
|
||||
"options": options,
|
||||
"level": 20,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
"""Annotate to add specify attribute for tiramisu-cmdline
|
||||
|
||||
Silique (https://www.silique.fr)
|
||||
Copyright (C) 2024
|
||||
Copyright (C) 2024-2026
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
|
|
@ -24,11 +24,7 @@ from pydantic import BaseModel
|
|||
class Variable(BaseModel):
|
||||
alternative_name: Optional[str] = None
|
||||
commandline: bool = True
|
||||
negative_description: Optional[str] = None
|
||||
|
||||
|
||||
class Family(BaseModel):
|
||||
commandline: bool = True
|
||||
|
||||
|
||||
__all__ = ("Variable", "Family")
|
||||
|
|
|
|||
158
src/rougail/structural_directory/__init__.py
Normal file
158
src/rougail/structural_directory/__init__.py
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
"""
|
||||
Silique (https://www.silique.fr)
|
||||
Copyright (C) 2022-2026
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from typing import Union, List, Iterator, Optional
|
||||
from itertools import chain
|
||||
from pathlib import Path
|
||||
|
||||
from ruamel.yaml import YAML
|
||||
|
||||
from ..tiramisu import normalize_family
|
||||
from ..convert.path import Paths
|
||||
from ..error import DictConsistencyError
|
||||
from ..i18n import _
|
||||
|
||||
|
||||
class Walker:
|
||||
def __init__(
|
||||
self,
|
||||
convert,
|
||||
) -> None:
|
||||
"""Parse directories content"""
|
||||
self.convert = convert
|
||||
self.yaml = YAML()
|
||||
rougailconfig = self.convert.rougailconfig
|
||||
self.sort_structural_files_all = rougailconfig["sort_structural_files_all"]
|
||||
if rougailconfig["main_namespace"]:
|
||||
self.convert.paths = Paths(
|
||||
rougailconfig["main_namespace"],
|
||||
rougailconfig["isolated_namespace"],
|
||||
)
|
||||
self.load_with_extra(
|
||||
rougailconfig["extra_namespaces"],
|
||||
rougailconfig["main_namespace"],
|
||||
rougailconfig["main_structural_directories"],
|
||||
)
|
||||
else:
|
||||
self.convert.namespace = None
|
||||
namespace_path = ""
|
||||
if namespace_path in self.convert.parents:
|
||||
raise Exception("pfff")
|
||||
for filename in self.get_sorted_filename(
|
||||
rougailconfig["main_structural_directories"]
|
||||
):
|
||||
self.parse_variable_file(
|
||||
filename,
|
||||
namespace_path,
|
||||
)
|
||||
|
||||
def load_with_extra(
|
||||
self,
|
||||
extra_structures: dict,
|
||||
main_namespace: Optional[str] = None,
|
||||
main_structures: Optional[List[str]] = None,
|
||||
) -> None:
|
||||
self.convert.has_namespace = True
|
||||
if main_namespace:
|
||||
directory_dict = chain(
|
||||
(
|
||||
(
|
||||
main_namespace,
|
||||
main_structures,
|
||||
),
|
||||
),
|
||||
extra_structures.items(),
|
||||
)
|
||||
else:
|
||||
directory_dict = extra_structures.items()
|
||||
for namespace, extra_dirs in directory_dict:
|
||||
# if namespace is None:
|
||||
# self.convert.namespace = namespace
|
||||
# else:
|
||||
self.convert.namespace = normalize_family(namespace)
|
||||
namespace_path = self.convert.namespace
|
||||
if namespace_path in self.convert.parents:
|
||||
raise Exception("pfff")
|
||||
for idx, filename in enumerate(self.get_sorted_filename(extra_dirs)):
|
||||
if not idx:
|
||||
# create only for the first file
|
||||
self.convert.create_namespace(namespace, namespace_path)
|
||||
self.parse_variable_file(
|
||||
filename,
|
||||
namespace_path,
|
||||
)
|
||||
|
||||
def get_sorted_filename(
|
||||
self,
|
||||
directories: Union[str, List[str]],
|
||||
) -> Iterator[str]:
|
||||
"""Sort filename"""
|
||||
if not isinstance(directories, list):
|
||||
directories = [directories]
|
||||
if self.sort_structural_files_all:
|
||||
filenames = {}
|
||||
for directory_name in directories:
|
||||
directory = Path(directory_name)
|
||||
if not self.sort_structural_files_all:
|
||||
filenames = {}
|
||||
if directory.is_file():
|
||||
self.get_filename(directory, filenames)
|
||||
else:
|
||||
for file_path in directory.iterdir():
|
||||
self.get_filename(file_path, filenames)
|
||||
if not self.sort_structural_files_all:
|
||||
for filename in sorted(filenames):
|
||||
yield filenames[filename]
|
||||
if self.sort_structural_files_all:
|
||||
for filename in sorted(filenames):
|
||||
yield filenames[filename]
|
||||
|
||||
def get_filename(self, file_path, filenames: List[str]) -> None:
|
||||
if file_path.suffix not in [".yml", ".yaml"]:
|
||||
return
|
||||
if file_path.name in filenames:
|
||||
raise DictConsistencyError(
|
||||
_("duplicate structural file name {0}").format(file_path.name),
|
||||
78,
|
||||
[filenames[file_path.name], str(file_path)],
|
||||
)
|
||||
filenames[file_path.name] = str(file_path)
|
||||
|
||||
def parse_variable_file(
|
||||
self,
|
||||
filename: str,
|
||||
path: str,
|
||||
) -> None:
|
||||
"""Parse file"""
|
||||
with open(filename, encoding="utf8") as file_fh:
|
||||
objects = self.yaml.load(file_fh)
|
||||
if objects is None:
|
||||
return
|
||||
version = self.convert.validate_file_version(
|
||||
objects,
|
||||
filename,
|
||||
)
|
||||
self.convert.parse_root_file(
|
||||
[filename],
|
||||
path,
|
||||
version,
|
||||
objects,
|
||||
)
|
||||
|
||||
|
||||
__all__ = ("Walker",)
|
||||
116
src/rougail/structural_directory/config.py
Normal file
116
src/rougail/structural_directory/config.py
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
"""
|
||||
Silique (https://www.silique.fr)
|
||||
Copyright (C) 2024-2026
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from ..utils import _
|
||||
|
||||
|
||||
def get_rougail_config(
|
||||
*,
|
||||
backward_compatibility=True,
|
||||
) -> dict:
|
||||
if backward_compatibility:
|
||||
main_namespace_default = "rougail"
|
||||
else:
|
||||
main_namespace_default = "null"
|
||||
options = f"""
|
||||
main_namespace:
|
||||
description: {_("Main namespace name")}
|
||||
default: {main_namespace_default}
|
||||
alternative_name: s
|
||||
mandatory: false
|
||||
disabled:
|
||||
jinja: >-
|
||||
{{{{ 'directory' not in _.step.structural and 'string' not in _.step.structural }}}}
|
||||
return_type: boolean
|
||||
description: {_('directory or string is not in "_.step.structural"')}
|
||||
|
||||
main_structural_directories:
|
||||
description: {_("Directories where structural files are placed")}
|
||||
type: unix_filename
|
||||
alternative_name: m
|
||||
params:
|
||||
allow_relative: True
|
||||
test_existence: True
|
||||
multi: true
|
||||
disabled:
|
||||
jinja: >-
|
||||
{{% if 'directory' not in _.step.structural %}}
|
||||
directory is not in _.step.structural
|
||||
{{% endif %}}
|
||||
{{% if cli is defined and cli.versions is defined and cli.versions %}}
|
||||
cli.versions is specified
|
||||
{{% endif %}}
|
||||
|
||||
sort_structural_files_all:
|
||||
description: {_("Sort structural from differents directories")}
|
||||
default: false
|
||||
disabled:
|
||||
jinja: >-
|
||||
{{% if 'directory' not in _.step.structural %}}
|
||||
directory is not in _.step.structural
|
||||
{{% endif %}}
|
||||
|
||||
isolated_namespace:
|
||||
description: {_("Namespaces are isolated")}
|
||||
default: true
|
||||
disabled:
|
||||
jinja: >-
|
||||
{{{{ 'directory' not in _.step.structural and 'string' not in _.step.structural }}}}
|
||||
return_type: boolean
|
||||
description: {_('directory or string is not in "_.step.structural" or "_.main_namespace" is not set')}
|
||||
|
||||
extra_namespaces:
|
||||
description: {_("Extra namespaces")}
|
||||
type: leadership
|
||||
disabled:
|
||||
jinja: >-
|
||||
{{{{ ('directory' not in _.step.structural and 'string' not in _.step.structural) or not _.main_namespace }}}}
|
||||
return_type: boolean
|
||||
description: directory is not in _.step.structural or main_namespace is not set
|
||||
|
||||
names:
|
||||
description: {_("Extra namespace name")}
|
||||
alternative_name: xn
|
||||
multi: true
|
||||
mandatory: false
|
||||
|
||||
directories:
|
||||
description: {_("Directories where extra structural files are placed")}
|
||||
alternative_name: xd
|
||||
type: unix_filename
|
||||
params:
|
||||
allow_relative: true
|
||||
test_existence: true
|
||||
types:
|
||||
- directory
|
||||
multi: true
|
||||
disabled:
|
||||
jinja: >-
|
||||
{{{{ 'directory' not in __.step.structural }}}}
|
||||
return_type: boolean
|
||||
description: {_('directory is not in "__.step.structural"')}
|
||||
"""
|
||||
return {
|
||||
"name": "directory",
|
||||
"process": "structural",
|
||||
"options": options,
|
||||
"level": 5,
|
||||
}
|
||||
|
||||
|
||||
__all__ = "get_rougail_config"
|
||||
|
|
@ -9,7 +9,7 @@ Cadoles (http://www.cadoles.com)
|
|||
Copyright (C) 2019-2021
|
||||
|
||||
Silique (https://www.silique.fr)
|
||||
Copyright (C) 2022-2024
|
||||
Copyright (C) 2022-2026
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
|
|
@ -27,27 +27,223 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
from typing import Any
|
||||
|
||||
try:
|
||||
from tiramisu5 import DynOptionDescription, calc_value
|
||||
except ModuleNotFoundError:
|
||||
from tiramisu import DynOptionDescription, calc_value
|
||||
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,
|
||||
)
|
||||
from unicodedata import normalize, combining
|
||||
from jinja2 import StrictUndefined, DictLoader
|
||||
from jinja2.sandbox import SandboxedEnvironment
|
||||
from rougail.object_model import CONVERT_OPTION
|
||||
from rougail.error import display_xmlfiles
|
||||
from tiramisu import function_waiting_for_error
|
||||
from tiramisu.error import ValueWarning, ConfigError, PropertiesOptionError
|
||||
from .utils import normalize_family
|
||||
from re import findall
|
||||
from tiramisu import (
|
||||
DynOptionDescription,
|
||||
calc_value,
|
||||
function_waiting_for_error,
|
||||
undefined,
|
||||
)
|
||||
from tiramisu.error import (
|
||||
ValueWarning,
|
||||
ConfigError,
|
||||
PropertiesOptionError,
|
||||
CancelParam,
|
||||
errors,
|
||||
)
|
||||
|
||||
|
||||
ori_raise_carry_out_calculation_error = errors.raise_carry_out_calculation_error
|
||||
|
||||
|
||||
try:
|
||||
from .i18n import _
|
||||
except ModuleNotFoundError:
|
||||
# FIXME
|
||||
def _(msg):
|
||||
return msg
|
||||
|
||||
|
||||
def display_xmlfiles(xmlfiles: list) -> str:
|
||||
"""The function format xmlfiles informations to generate errors"""
|
||||
if not isinstance(xmlfiles, list):
|
||||
xmlfiles = [xmlfiles]
|
||||
if len(xmlfiles) == 1:
|
||||
return '"' + xmlfiles[0] + '"'
|
||||
return '"' + '", "'.join(xmlfiles[:-1]) + '"' + " and " + '"' + xmlfiles[-1] + '"'
|
||||
|
||||
|
||||
def convert_boolean(value: str) -> bool:
|
||||
"""Boolean coercion. The Rougail XML may contain srings like `True` or `False`"""
|
||||
if isinstance(value, bool):
|
||||
return value
|
||||
value = value.lower()
|
||||
if value == "true":
|
||||
return True
|
||||
elif value == "false":
|
||||
return False
|
||||
elif value in ["", None]:
|
||||
return None
|
||||
raise Exception(_('unknown boolean value "{0}"').format(value))
|
||||
|
||||
_ip_params = {
|
||||
"cidr": {"description": _("IP must be in CIDR format")},
|
||||
"private_only": {"description": _("private IP are allowed")},
|
||||
"allow_reserved": {"description": _("reserved IP are allowed")},
|
||||
}
|
||||
_network_params = {
|
||||
"cidr": {"description": _("network must be in CIDR format")},
|
||||
"private_only": {"description": _("private network are allowed")},
|
||||
"allow_reserved": {"description": _("reserved network are allowed")},
|
||||
}
|
||||
_port_params = {
|
||||
"allow_range": {"description": _("can be range of port")},
|
||||
"allow_protocol": {"description": _("can have the protocol")},
|
||||
"allow_zero": {"description": _("port 0 is allowed")},
|
||||
"allow_wellknown": {"description": _("well-known ports (1 to 1023) are allowed")},
|
||||
"allow_registred": {"description": _("registred ports (1024 to 49151) are allowed")},
|
||||
"allow_private": {"description": _("private ports (greater than 49152) are allowed")},
|
||||
}
|
||||
_domain_params = {
|
||||
"type": {"description": _("type of domainname"), "choices": ('domainname', 'netbios', 'hostname'), 'doc': _("type {0}")},
|
||||
"allow_startswith_dot": {"description": _("the domain name can starts by a dot")},
|
||||
"allow_without_dot": {"description": _("the domain name can be a hostname")},
|
||||
"allow_ip": {"description": _("the domain name can be an IP")},
|
||||
"allow_cidr_network": {"description": _("the domain name can be network in CIDR format")},
|
||||
"test_existence": {"description": _("the domain name must exist")},
|
||||
}
|
||||
_web_params = _port_params | _domain_params
|
||||
|
||||
|
||||
CONVERT_OPTION = {
|
||||
"string": dict(opttype="StrOption", example="example"),
|
||||
"number": dict(opttype="IntOption",
|
||||
func=int,
|
||||
params={
|
||||
"min_number": {"description": _("the minimum value"), 'doc': _("the minimum value is {0}")},
|
||||
"max_number": {"description": _("the maximum value"), 'doc': _("the maximum value is {0}")},
|
||||
},
|
||||
example=42),
|
||||
"integer": dict(opttype="IntOption",
|
||||
params={
|
||||
"min_integer": {"description": _("the minimum value"), 'doc': _("the minimum value is {0}")},
|
||||
"max_integer": {"description": _("the maximum value"), 'doc': _("the maximum value is {0}")},
|
||||
},
|
||||
func=int,
|
||||
example=42,
|
||||
),
|
||||
"float": dict(opttype="FloatOption", func=float, example=1.42),
|
||||
"boolean": dict(opttype="BoolOption", func=convert_boolean),
|
||||
"secret": dict(opttype="PasswordOption",
|
||||
params={
|
||||
"min_len": {"description": _("minimum characters length for the secret"), "doc": _("minimum length for the secret is {0} characters")},
|
||||
"max_len": {"description": _("maximum characters length for the secret"), "doc": _("maximum length for the secret is {0} characters")},
|
||||
"forbidden_char": {"description": _("forbidden characters"), "doc": _("forbidden characters: {0}")},
|
||||
},
|
||||
example="secrets"),
|
||||
"mail": dict(opttype="EmailOption", example="user@example.net"),
|
||||
"unix_filename": dict(opttype="FilenameOption",
|
||||
msg="UNIX filename",
|
||||
params={
|
||||
"allow_relative": {"description": _("this filename could be a relative path")},
|
||||
"test_existence": {"description": _("this file must exist")},
|
||||
"types": {"description": _("file type allowed"), "doc": _("file type allowed: {0}"), "choices": ("file", "directory"), "multi": True},
|
||||
},
|
||||
example="/tmp/myfile.txt"),
|
||||
"date": dict(opttype="DateOption", example="2000-01-01"),
|
||||
"unix_user": dict(opttype="UsernameOption", example="username",
|
||||
msg="UNIX user"
|
||||
),
|
||||
"ip": dict(
|
||||
opttype="IPOption", initkwargs={"allow_reserved": True},
|
||||
msg="IP",
|
||||
params=_ip_params,
|
||||
example="1.1.1.1"
|
||||
),
|
||||
"cidr": dict(opttype="IPOption", msg="CIDR", initkwargs={"cidr": True},
|
||||
params=_ip_params,
|
||||
example="1.1.1.0/24"),
|
||||
"netmask": dict(opttype="NetmaskOption", example="255.255.255.0"),
|
||||
"network": dict(opttype="NetworkOption",
|
||||
params=_network_params,
|
||||
example="1.1.1.0"),
|
||||
"network_cidr": dict(
|
||||
opttype="NetworkOption", initkwargs={"cidr": True}, example="1.1.1.0/24",
|
||||
params=_network_params,
|
||||
msg="network CIDR",
|
||||
),
|
||||
"broadcast": dict(opttype="BroadcastOption", example="1.1.1.255"),
|
||||
"netbios": dict(
|
||||
opttype="DomainnameOption",
|
||||
initkwargs={"type": "netbios", "warnings_only": True},
|
||||
params=_domain_params,
|
||||
example="example",
|
||||
),
|
||||
"domainname": dict(
|
||||
opttype="DomainnameOption",
|
||||
initkwargs={"type": "domainname", "allow_ip": False},
|
||||
params=_domain_params,
|
||||
example="example.net",
|
||||
),
|
||||
"hostname": dict(
|
||||
opttype="DomainnameOption",
|
||||
initkwargs={"type": "hostname", "allow_ip": False},
|
||||
params=_domain_params,
|
||||
example="example",
|
||||
),
|
||||
"web_address": dict(
|
||||
opttype="URLOption",
|
||||
initkwargs={"allow_ip": False, "allow_without_dot": True},
|
||||
msg="web address",
|
||||
params=_web_params,
|
||||
example="https://example.net",
|
||||
),
|
||||
"port": dict(
|
||||
opttype="PortOption", initkwargs={"allow_private": True},
|
||||
params=_port_params,
|
||||
example="111", func=str,
|
||||
),
|
||||
"mac": dict(opttype="MACOption", example="00:00:00:00:00"),
|
||||
"unix_permissions": dict(
|
||||
opttype="PermissionsOption",
|
||||
msg="UNIX permissions",
|
||||
initkwargs={"warnings_only": True},
|
||||
func=int,
|
||||
example="644",
|
||||
),
|
||||
"choice": dict(opttype="ChoiceOption", example="a_choice"),
|
||||
"regexp": dict(opttype="RegexpOption"),
|
||||
#
|
||||
"symlink": dict(opttype="SymLinkOption"),
|
||||
}
|
||||
RENAME_TYPE = {"number": "integer"}
|
||||
|
||||
|
||||
def get_identifier_from_dynamic_family(true_name, name) -> str:
|
||||
if true_name == "{{ identifier }}":
|
||||
return name
|
||||
regexp = true_name.replace("{{ identifier }}", "(.*)")
|
||||
finded = findall(regexp, name)
|
||||
if len(finded) != 1 or not finded[0]:
|
||||
return None
|
||||
return finded[0]
|
||||
|
||||
|
||||
def raise_carry_out_calculation_error(subconfig, *args, **kwargs):
|
||||
try:
|
||||
ori_raise_carry_out_calculation_error(subconfig, *args, **kwargs)
|
||||
except ConfigError as err:
|
||||
ymlfiles = subconfig.config_bag.context.get_values().get_information(
|
||||
subconfig, "ymlfiles", []
|
||||
)
|
||||
raise ConfigError(_("{0} in {1}").format(err, display_xmlfiles(ymlfiles)), subconfig=subconfig)
|
||||
|
||||
|
||||
errors.raise_carry_out_calculation_error = raise_carry_out_calculation_error
|
||||
|
||||
|
||||
global func
|
||||
dict_env = {}
|
||||
ENV = SandboxedEnvironment(loader=DictLoader(dict_env), undefined=StrictUndefined)
|
||||
ENV.add_extension('jinja2.ext.do')
|
||||
func = ENV.filters
|
||||
ENV.compile_templates("jinja_caches", zip=None)
|
||||
|
||||
|
|
@ -90,8 +286,10 @@ def test_propertyerror(value: Any) -> bool:
|
|||
ENV.tests["propertyerror"] = test_propertyerror
|
||||
|
||||
|
||||
def load_functions(path):
|
||||
def load_functions(path, dict_func=None):
|
||||
global _SourceFileLoader, _spec_from_loader, _module_from_spec, func
|
||||
if dict_func is None:
|
||||
dict_func = func
|
||||
loader = _SourceFileLoader("func", path)
|
||||
spec = _spec_from_loader(loader.name, loader)
|
||||
func_ = _module_from_spec(spec)
|
||||
|
|
@ -99,16 +297,94 @@ def load_functions(path):
|
|||
for function in dir(func_):
|
||||
if function.startswith("_"):
|
||||
continue
|
||||
func[function] = getattr(func_, function)
|
||||
dict_func[function] = getattr(func_, function)
|
||||
|
||||
|
||||
def rougail_calc_value(*args, __default_value=None, **kwargs):
|
||||
def normalize_family(family_name: str) -> str:
|
||||
"""replace space, accent, uppercase, ... by valid character"""
|
||||
if not family_name:
|
||||
return
|
||||
family_name = family_name.lower()
|
||||
family_name = family_name.replace("-", "_").replace(" ", "_").replace(".", "_")
|
||||
nfkd_form = normalize("NFKD", family_name)
|
||||
family_name = "".join([c for c in nfkd_form if not combining(c)])
|
||||
return family_name.lower()
|
||||
|
||||
|
||||
def tiramisu_display_name(
|
||||
kls,
|
||||
subconfig,
|
||||
with_quote: bool = False,
|
||||
) -> str:
|
||||
"""Replace the Tiramisu display_name function to display path + description"""
|
||||
def get_path():
|
||||
if description_type in ["description", "name", "name_and_description"]:
|
||||
path = kls.impl_getname()
|
||||
else:
|
||||
path = kls.impl_getpath()
|
||||
if "{{ identifier }}" in path and subconfig.identifiers:
|
||||
path = path.replace(
|
||||
"{{ identifier }}", normalize_family(str(subconfig.identifiers[-1]))
|
||||
)
|
||||
return path
|
||||
config_bag = subconfig.config_bag
|
||||
context = config_bag.context
|
||||
values = context.get_values()
|
||||
context_subconfig = context.get_root(config_bag)
|
||||
description_type = values.get_information(
|
||||
context_subconfig, "description_type", "name_and_description"
|
||||
)
|
||||
if description_type in ["description", "name_and_description", "path_and_description"]:
|
||||
doc = values.get_information(subconfig, "doc", None)
|
||||
description = doc if doc and doc != kls.impl_getname() else ""
|
||||
if "{{ identifier }}" in description and subconfig.identifiers:
|
||||
description = description.replace("{{ identifier }}", str(subconfig.identifiers[-1]))
|
||||
if description_type in ["name", "path", "name_and_description", "path_and_description"]:
|
||||
path = get_path()
|
||||
if description_type in ["name_and_description", "path_and_description"]:
|
||||
if description:
|
||||
if with_quote:
|
||||
description = f'"{path}" ({description})'
|
||||
else:
|
||||
description = f"{path} ({description})"
|
||||
else:
|
||||
if with_quote:
|
||||
description = f'"{path}"'
|
||||
else:
|
||||
description = path
|
||||
else:
|
||||
if description_type in ["name", "path"]:
|
||||
description = path
|
||||
elif not description:
|
||||
description = get_path()
|
||||
if with_quote:
|
||||
description = f'"{description}"'
|
||||
return description
|
||||
|
||||
|
||||
def rougail_calc_value(*args, __default_value=None, __internal_multi=False, **kwargs):
|
||||
values = calc_value(*args, **kwargs)
|
||||
if values is None and __internal_multi:
|
||||
values = []
|
||||
if __default_value is not None and values in [None, []]:
|
||||
return __default_value
|
||||
return values
|
||||
|
||||
|
||||
def kw_to_string(kw, root=None):
|
||||
for name, data in kw.items():
|
||||
if root is None:
|
||||
path = name
|
||||
else:
|
||||
path = root + "." + name
|
||||
if isinstance(data, dict):
|
||||
yield from kw_to_string(data, root=path)
|
||||
else:
|
||||
yield f"{path}={data}"
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@function_waiting_for_error
|
||||
def jinja_to_function(
|
||||
__internal_variable,
|
||||
|
|
@ -123,13 +399,31 @@ def jinja_to_function(
|
|||
global ENV, CONVERT_OPTION
|
||||
kw = {}
|
||||
for key, value in kwargs.items():
|
||||
if isinstance(value, list):
|
||||
val = []
|
||||
for v in value:
|
||||
if isinstance(v, PropertiesOptionError):
|
||||
v = JinjaError(v)
|
||||
if v is None:
|
||||
v = ''
|
||||
val.append(v)
|
||||
value = val
|
||||
else:
|
||||
if isinstance(value, PropertiesOptionError):
|
||||
value = JinjaError(value)
|
||||
if value is None:
|
||||
value = ''
|
||||
if "." in key:
|
||||
c_kw = kw
|
||||
path, var = key.rsplit(".", 1)
|
||||
if isinstance(value, CancelParam):
|
||||
count_o_path = value.origin_path.count(".") - value.current_path.count(
|
||||
"."
|
||||
)
|
||||
path = path.rsplit(".", count_o_path)[0]
|
||||
for subkey in path.split("."):
|
||||
c_kw = c_kw.setdefault(subkey, {})
|
||||
if not isinstance(value, CancelParam):
|
||||
c_kw[var] = value
|
||||
else:
|
||||
if key in kw:
|
||||
|
|
@ -140,28 +434,44 @@ def jinja_to_function(
|
|||
try:
|
||||
values = ENV.get_template(__internal_jinja).render(kw, **func).strip()
|
||||
except Exception as err:
|
||||
raise ConfigError(
|
||||
f'cannot calculating "{__internal_attribute}" attribute for variable "{__internal_variable}" in {display_xmlfiles(__internal_files)}: {err}'
|
||||
) from err
|
||||
kw_str = ", ".join(kw_to_string(kw))
|
||||
prefix = _('cannot calculate the variable "{0}"').format(__internal_variable)
|
||||
msg = _('the attribute "{0}" in {1} with the parameters "{2}" causes the error: {3}').format(
|
||||
__internal_attribute,
|
||||
display_xmlfiles(__internal_files),
|
||||
kw_str,
|
||||
err,
|
||||
)
|
||||
raise ConfigError(msg, prefix=prefix) from err
|
||||
convert = CONVERT_OPTION[__internal_type].get("func", str)
|
||||
if __internal_multi:
|
||||
values = [convert(val) for val in values.split("\n") if val != ""]
|
||||
values = [
|
||||
convert(val.strip()) for val in values.split("\n") if val.strip() != ""
|
||||
]
|
||||
if not values and __default_value is not None:
|
||||
return __default_value
|
||||
return values
|
||||
try:
|
||||
values = convert(values)
|
||||
except Exception as err:
|
||||
raise ConfigError(
|
||||
f'cannot converting "{__internal_attribute}" attribute for variable "{__internal_variable}" in {display_xmlfiles(__internal_files)}: {err}'
|
||||
) from err
|
||||
prefix = _('cannot converting the variable "{0}"').format(__internal_variable)
|
||||
msg = _('"{0}" is an invalid {1}').format(values, __internal_type)
|
||||
if __internal_attribute != "default":
|
||||
msg = _('the attribute "{0}" in {1} causes the error: {2}').format(
|
||||
__internal_attribute,
|
||||
display_xmlfiles(__internal_files),
|
||||
msg,
|
||||
)
|
||||
raise ConfigError(msg, prefix=prefix) from err
|
||||
values = values if values != "" and values != "None" else None
|
||||
if values is None and __default_value is not None:
|
||||
return __default_value
|
||||
return values
|
||||
|
||||
|
||||
def variable_to_property(prop, value, when, inverse):
|
||||
def variable_to_property(*, prop, value=undefined, when, inverse, **kwargs):
|
||||
if value is undefined:
|
||||
return None
|
||||
if isinstance(value, PropertiesOptionError):
|
||||
raise value from value
|
||||
if inverse:
|
||||
|
|
@ -171,27 +481,39 @@ def variable_to_property(prop, value, when, inverse):
|
|||
return prop if is_match else None
|
||||
|
||||
|
||||
def variable_to_property_transitive(*args, **kwargs):
|
||||
# do nothing, if associate variable is not accessible, autolib will raise directly
|
||||
pass
|
||||
|
||||
|
||||
@function_waiting_for_error
|
||||
def jinja_to_property(prop, when, inverse, **kwargs):
|
||||
def jinja_to_property(prop, description, when, inverse, **kwargs):
|
||||
value = func["jinja_to_function"](**kwargs)
|
||||
return func["variable_to_property"](prop, value is not None, when, inverse)
|
||||
if kwargs["__internal_type"] == "string":
|
||||
value = value is not None
|
||||
return func["variable_to_property"](
|
||||
prop=prop, value=value, when=when, inverse=inverse
|
||||
)
|
||||
|
||||
|
||||
@function_waiting_for_error
|
||||
def jinja_to_property_help(prop, **kwargs):
|
||||
value = func["jinja_to_function"](**kwargs)
|
||||
return (prop, f'"{prop}" ({value})')
|
||||
def jinja_to_property_help(prop, description, **kwargs):
|
||||
if kwargs["__internal_type"] == "string":
|
||||
description = func["jinja_to_function"](**kwargs)
|
||||
return (prop, f'"{prop}" ({description})')
|
||||
|
||||
|
||||
@function_waiting_for_error
|
||||
def valid_with_jinja(warnings_only=False, **kwargs):
|
||||
def valid_with_jinja(warnings_only=False, description=None, **kwargs):
|
||||
global ValueWarning
|
||||
value = func["jinja_to_function"](**kwargs)
|
||||
if value:
|
||||
if description is None:
|
||||
description = value
|
||||
if warnings_only:
|
||||
raise ValueWarning(value)
|
||||
raise ValueWarning(description)
|
||||
else:
|
||||
raise ValueError(value)
|
||||
raise ValueError(description)
|
||||
|
||||
|
||||
func["calc_value"] = rougail_calc_value
|
||||
|
|
@ -199,7 +521,9 @@ 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["variable_to_property_transitive"] = variable_to_property_transitive
|
||||
func["valid_with_jinja"] = valid_with_jinja
|
||||
func["normalize_family"] = normalize_family
|
||||
|
||||
|
||||
class ConvertDynOptionDescription(DynOptionDescription):
|
||||
|
|
@ -207,7 +531,8 @@ class ConvertDynOptionDescription(DynOptionDescription):
|
|||
Identifier could also contain invalid character, so we should "normalize" it
|
||||
"""
|
||||
|
||||
def convert_identifier_to_path(self, identifier):
|
||||
@staticmethod
|
||||
def convert_identifier_to_path(identifier):
|
||||
if identifier is None:
|
||||
return identifier
|
||||
if not isinstance(identifier, str):
|
||||
|
|
@ -236,6 +561,16 @@ class ConvertDynOptionDescription(DynOptionDescription):
|
|||
if "{{ identifier }}" in display:
|
||||
return display.replace(
|
||||
"{{ identifier }}",
|
||||
self.convert_identifier_to_path(self.get_identifiers(subconfig)[-1]),
|
||||
self.convert_identifier_to_path(
|
||||
self.get_identifiers(subconfig, from_display_name=True)[-1]
|
||||
),
|
||||
)
|
||||
return display
|
||||
|
||||
def name_could_conflict(self, dynchild, child):
|
||||
return (
|
||||
get_identifier_from_dynamic_family(
|
||||
dynchild.impl_getname(), child.impl_getname()
|
||||
)
|
||||
is not None
|
||||
)
|
||||
|
|
|
|||
74
src/rougail/types.py
Normal file
74
src/rougail/types.py
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
"""
|
||||
Silique (https://www.silique.fr)
|
||||
Copyright (C) 2025-2026
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
from .config import StaticRougailConvert
|
||||
from .i18n import _
|
||||
|
||||
|
||||
class TypeRougailConvert(StaticRougailConvert):
|
||||
def __init__(
|
||||
self,
|
||||
main_structural_directories: list[str],
|
||||
) -> None:
|
||||
super().__init__(False, {"sort_structural_files_all": True,
|
||||
"main_namespace": None,
|
||||
"main_structural_directories": main_structural_directories,
|
||||
})
|
||||
|
||||
def load_config(self) -> None:
|
||||
super().load_config()
|
||||
self.add_extra_options = self.add_extra_options
|
||||
self.sort_structural_files_all = False
|
||||
self.structurals = ["directory"]
|
||||
|
||||
|
||||
def rougail_type(rougailconfig):
|
||||
types = rougailconfig["types"]
|
||||
if not types:
|
||||
return {}, {}
|
||||
convert = TypeRougailConvert(types)
|
||||
convert.init()
|
||||
convert.parse_directories()
|
||||
return ({typ: to_dict_variable(convert.paths[typ]) for typ in convert.variables},
|
||||
{typ: to_dict_family(typ, convert.paths, convert.parents, convert.families) for typ in convert.families},
|
||||
)
|
||||
|
||||
|
||||
def to_dict_variable(obj, with_files=True):
|
||||
if with_files:
|
||||
keys = ['name', 'path']
|
||||
else:
|
||||
keys = ['name', 'path', 'xmlfiles']
|
||||
return {key: value for key, value in dict(obj).items() if key not in keys and value is not None}
|
||||
|
||||
|
||||
def to_dict_family(family_name, paths, parents, families, root=True):
|
||||
ret = to_dict_variable(paths[family_name], root)
|
||||
for variable_path in parents[family_name]:
|
||||
variable = paths[variable_path]
|
||||
variable_name = variable.name
|
||||
if variable_path in families:
|
||||
if variable.type == "leadership":
|
||||
raise DictConsistencyError(_("type is not compatible with leadership family"), variable.xmlfiles)
|
||||
if variable.type == "dynamic":
|
||||
raise DictConsistencyError(_("type is not compatible with dynamic family"), variable.xmlfiles)
|
||||
if variable_name in ret:
|
||||
ret["_" + variable_name] = ret.pop(variable_name)
|
||||
ret[variable_name] = to_dict_family(variable.path, paths, parents, families, False)
|
||||
else:
|
||||
ret[variable_name] = to_dict_variable(variable, False)
|
||||
return ret
|
||||
File diff suppressed because it is too large
Load diff
606
src/rougail/user_data.py
Normal file
606
src/rougail/user_data.py
Normal file
|
|
@ -0,0 +1,606 @@
|
|||
"""
|
||||
Silique (https://www.silique.fr)
|
||||
Copyright (C) 2022-2026
|
||||
|
||||
distribued with GPL-2 or later license
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
"""
|
||||
|
||||
from typing import List
|
||||
|
||||
from tiramisu import Calculation, Params, ParamValue, owners
|
||||
from tiramisu.error import (
|
||||
PropertiesOptionError,
|
||||
AttributeOptionError,
|
||||
LeadershipError,
|
||||
ConfigError,
|
||||
CancelParam,
|
||||
display_list,
|
||||
)
|
||||
from .utils import undefined, get_properties_to_string
|
||||
from .tiramisu import (
|
||||
normalize_family,
|
||||
CONVERT_OPTION,
|
||||
get_identifier_from_dynamic_family,
|
||||
)
|
||||
from .error import DictConsistencyError
|
||||
|
||||
from .i18n import _
|
||||
|
||||
|
||||
class UserData:
|
||||
def __init__(self, config) -> None:
|
||||
self.config = config
|
||||
|
||||
def user_data(
|
||||
self,
|
||||
user_data: List[dict],
|
||||
*,
|
||||
invalid_user_data_error: bool = False,
|
||||
unknown_user_data_error: bool = False,
|
||||
):
|
||||
self.values = {}
|
||||
self.errors = []
|
||||
self.warnings = []
|
||||
self.invalid_user_data_error = invalid_user_data_error
|
||||
self.unknown_user_data_error = unknown_user_data_error
|
||||
if self.invalid_user_data_error:
|
||||
self.invalids = self.errors
|
||||
else:
|
||||
self.invalids = self.warnings
|
||||
if self.unknown_user_data_error:
|
||||
self.unknowns = self.errors
|
||||
else:
|
||||
self.unknowns = self.warnings
|
||||
self.show_secrets = False
|
||||
self._populate_values(user_data)
|
||||
self._auto_configure_dynamics()
|
||||
self._populate_config()
|
||||
self.properties_to_string = get_properties_to_string()
|
||||
self._populate_error_warnings()
|
||||
return {
|
||||
"errors": self.errors,
|
||||
"warnings": self.warnings,
|
||||
}
|
||||
|
||||
def _populate_values(self, user_data):
|
||||
for datas in user_data:
|
||||
options = datas.get("options", {})
|
||||
source = datas["source"]
|
||||
for name, data in datas.get("values", {}).items():
|
||||
self.values[name] = {
|
||||
"source": source,
|
||||
"values": data,
|
||||
"options": options.copy(),
|
||||
}
|
||||
self.errors.extend(datas.get("errors", []))
|
||||
self.warnings.extend(datas.get("warnings", []))
|
||||
|
||||
def _get_variable(self, config):
|
||||
try:
|
||||
for subconfig in config:
|
||||
if subconfig.isoptiondescription():
|
||||
yield from self._get_variable(subconfig)
|
||||
else:
|
||||
yield subconfig
|
||||
except (ConfigError, ValueError) as err:
|
||||
err.prefix = ""
|
||||
if self.invalid_user_data_error:
|
||||
msg = str(err)
|
||||
else:
|
||||
msg = _('{0}, it will be ignored').format(err)
|
||||
self.invalids.append({msg: err.subconfig})
|
||||
|
||||
def _auto_configure_dynamics(self):
|
||||
cache = {}
|
||||
added = []
|
||||
for path, data in list(self.values.items()):
|
||||
try:
|
||||
option = self.config.option(path)
|
||||
option.name()
|
||||
except (ConfigError, PropertiesOptionError):
|
||||
pass
|
||||
except AttributeError:
|
||||
self._not_found_is_dynamic(self.config, path, cache, added, data)
|
||||
|
||||
def _not_found_is_dynamic(self, config, path, cache, added, data):
|
||||
"""if path is not found, check if parent is a dynamic family"""
|
||||
current_path = ""
|
||||
identifiers = []
|
||||
# get parent
|
||||
for name in path.split(".")[:-1]:
|
||||
if current_path:
|
||||
current_path += "."
|
||||
current_path += name
|
||||
if current_path in cache:
|
||||
config, identifier = cache[current_path]
|
||||
identifiers.append(identifier)
|
||||
continue
|
||||
tconfig = config.option(name)
|
||||
try:
|
||||
tconfig.group_type()
|
||||
# object exists, so current config is the temporary config
|
||||
config = tconfig
|
||||
if config.isdynamic(only_self=True):
|
||||
identifiers.append(config.identifiers()[-1])
|
||||
except AttributeError:
|
||||
# try to found the good dynamic family
|
||||
try:
|
||||
lists = config.list(uncalculated=True)
|
||||
except PropertiesOptionError:
|
||||
lists = []
|
||||
for tconfig in lists:
|
||||
if not tconfig.isdynamic(only_self=True):
|
||||
# it's not a dynamic variable
|
||||
continue
|
||||
identifier = get_identifier_from_dynamic_family(
|
||||
tconfig.name(uncalculated=True), name
|
||||
)
|
||||
if identifier == "{{ identifier }}":
|
||||
continue
|
||||
if identifier != normalize_family(identifier):
|
||||
msg = _(
|
||||
'cannot load variable path "{0}", the identifier "{1}" is not valid in {2}'
|
||||
).format(path, identifier, data["source"])
|
||||
self.invalids.append(msg)
|
||||
continue
|
||||
if identifier is None:
|
||||
# it's a dynamic variable but doesn't match the current name
|
||||
continue
|
||||
# get the variable associate to this dynamic family
|
||||
dynamic_variable = tconfig.information.get(
|
||||
"dynamic_variable",
|
||||
None,
|
||||
)
|
||||
if not dynamic_variable:
|
||||
# it's the good dynamic variable but it's not linked to a variable
|
||||
# so cannot change the variable
|
||||
continue
|
||||
option_type = self.config.option(dynamic_variable).information.get(
|
||||
"type"
|
||||
)
|
||||
dyn_options_values = (
|
||||
self.config.option(dynamic_variable).get().impl_getdefault()
|
||||
)
|
||||
if "{{ identifier }}" in dynamic_variable:
|
||||
for s in identifiers:
|
||||
dynamic_variable = dynamic_variable.replace(
|
||||
"{{ identifier }}", str(s), 1
|
||||
)
|
||||
# do not add values in variable if has already a value
|
||||
if dynamic_variable not in self.values and not dyn_options_values:
|
||||
self.values[dynamic_variable] = {"values": []}
|
||||
added.append(dynamic_variable)
|
||||
elif dynamic_variable not in added:
|
||||
continue
|
||||
config = tconfig
|
||||
identifiers.append(identifier)
|
||||
typ = CONVERT_OPTION.get(option_type, {}).get("func")
|
||||
if typ:
|
||||
identifier = typ(identifier)
|
||||
if identifier not in self.values[dynamic_variable]["values"]:
|
||||
self.values[dynamic_variable]["values"].append(identifier)
|
||||
cache[current_path] = config, identifier
|
||||
break
|
||||
|
||||
def convert_value(self, path, option, options, value):
|
||||
# converted value
|
||||
needs_convert = options.get("needs_convert", False)
|
||||
if option.ismulti():
|
||||
if options.get("multi_separator") and not isinstance(value, list):
|
||||
value = value.split(options["multi_separator"])
|
||||
self.values[path]["values"] = value
|
||||
if option.issubmulti():
|
||||
value = [[val] for val in value]
|
||||
if option.issubmulti():
|
||||
for idx, val in enumerate(value):
|
||||
if isinstance(val, list):
|
||||
value[idx] = [convert_value(option, v, needs_convert) for v in val]
|
||||
elif isinstance(value, list):
|
||||
value = [convert_value(option, val, needs_convert) for val in value]
|
||||
if needs_convert:
|
||||
self.values[path]["values"] = value
|
||||
self.values[path]["options"]["needs_convert"] = needs_convert
|
||||
elif not isinstance(value, list):
|
||||
value = convert_value(option, value, needs_convert)
|
||||
return value
|
||||
|
||||
def _populate_config(self):
|
||||
dynamics_variable = []
|
||||
while self.values:
|
||||
value_is_set = False
|
||||
for option in self._get_variable(self.config):
|
||||
values_path = path = option.path()
|
||||
if path not in self.values:
|
||||
if path in dynamics_variable or not option.isdynamic():
|
||||
continue
|
||||
values_path = option.path(uncalculated=True)
|
||||
if values_path not in self.values:
|
||||
continue
|
||||
options = self.values[values_path].get("options", {})
|
||||
if (
|
||||
options.get("allow_secrets_variables", True) is False
|
||||
and option.type() == "password"
|
||||
):
|
||||
self.errors.append({
|
||||
_(
|
||||
'the variable contains secrets and should not be defined in {0}'
|
||||
).format(self.values[values_path]["source"]): option._subconfig}
|
||||
)
|
||||
self.values.pop(path)
|
||||
continue
|
||||
value = self.convert_value(
|
||||
path, option, options, self.values[values_path]["values"]
|
||||
)
|
||||
index = option.index()
|
||||
if index is not None:
|
||||
if isinstance(value, tuple):
|
||||
self.values[values_path]["values"] = []
|
||||
# for i in range(len(option.parent().leader().value.get())):
|
||||
for i in range(option.value.len()):
|
||||
self.values[values_path]["values"].append(value)
|
||||
value = self.values[values_path]["values"]
|
||||
if not isinstance(value, list) or index >= len(value):
|
||||
continue
|
||||
value = value[index]
|
||||
option_without_index = option.index(None)
|
||||
else:
|
||||
option_without_index = option
|
||||
if option.isleader():
|
||||
# set value for a leader, it began to remove all values!
|
||||
len_leader = option.value.len()
|
||||
if len_leader:
|
||||
for idx in range(len_leader - 1, -1, -1):
|
||||
option.value.pop(idx)
|
||||
try:
|
||||
self.set_value(option, value, options, index)
|
||||
value_is_set = True
|
||||
except Exception as err:
|
||||
if path != option.path():
|
||||
self.values[option.path()] = self.values.pop(values_path)
|
||||
else:
|
||||
# value is correctly set, remove variable to the set
|
||||
if index is not None:
|
||||
# if it's a follower waiting for all followers are sets
|
||||
self.values[values_path]["values"][index] = undefined
|
||||
for tmp_value in self.values[values_path]["values"]:
|
||||
if tmp_value != undefined:
|
||||
break
|
||||
else:
|
||||
if path in self.values:
|
||||
self.values.pop(path)
|
||||
else:
|
||||
dynamics_variable.append(path)
|
||||
elif path in self.values:
|
||||
self.values.pop(path)
|
||||
else:
|
||||
dynamics_variable.append(path)
|
||||
if not value_is_set:
|
||||
break
|
||||
|
||||
def _display_value(self, option, value):
|
||||
if not self.show_secrets and option.type() == "password":
|
||||
if not isinstance(value, list):
|
||||
value = "*" * 10
|
||||
else:
|
||||
value = ["*" * 10 for val in value]
|
||||
if isinstance(value, list):
|
||||
value = display_list(value, add_quote=True)
|
||||
else:
|
||||
value = '"' + str(value) + '"'
|
||||
return value
|
||||
|
||||
def _populate_error_warnings(self):
|
||||
# we don't find variable, apply value just to get error or warning messages
|
||||
for path, options in self.values.items():
|
||||
value = options["values"]
|
||||
if options.get("secret_manager"):
|
||||
option = self.config.forcepermissive.option(path)
|
||||
else:
|
||||
option = self.config.option(path)
|
||||
try:
|
||||
if option.isoptiondescription():
|
||||
if value:
|
||||
if self.invalid_user_data_error:
|
||||
msg = _(
|
||||
'it\'s a family so we cannot set the value {0}, it has been loading from {1}'
|
||||
)
|
||||
else:
|
||||
msg = _(
|
||||
'it\'s a family so we cannot set the value {0}, it will be ignored when loading from {1}'
|
||||
)
|
||||
self.invalids.append({msg.format(
|
||||
self._display_value(option, value),
|
||||
options["source"],
|
||||
): option._subconfig}
|
||||
)
|
||||
continue
|
||||
if option.issymlinkoption():
|
||||
err = _('it\'s a symlink option so we cannot set the value {0}').format(self._display_value(option, value))
|
||||
if self.invalid_user_data_error:
|
||||
msg = _('{0}, it has been loading from {1}').format(err, options["source"])
|
||||
else:
|
||||
msg = _('{0}, it will be ignored when loading from {1}').format(err, options["source"])
|
||||
self.unknowns.append({msg: option._subconfig})
|
||||
continue
|
||||
except ConfigError as err:
|
||||
self.invalids.append({
|
||||
_("{0}, it has been loaded from {1}").format(err, options["source"]): option._subconfig}
|
||||
)
|
||||
continue
|
||||
except PropertiesOptionError as err:
|
||||
self.unknowns.append({
|
||||
_("{0}, it has been loaded from {1}").format(err, options["source"]): option._subconfig}
|
||||
)
|
||||
continue
|
||||
|
||||
except AttributeOptionError as err:
|
||||
if err.code == "option-not-found":
|
||||
err_path = err.path
|
||||
if "." not in err_path:
|
||||
subconfig = None
|
||||
child_name = err_path
|
||||
else:
|
||||
parent_path, child_name = err_path.rsplit('.', 1)
|
||||
subconfig = self.config.option(parent_path)
|
||||
subconfig._set_subconfig()
|
||||
err_msg = _(
|
||||
'variable or family "{0}" does not exist so cannot load "{1}"'
|
||||
).format(child_name, path)
|
||||
if self.unknown_user_data_error:
|
||||
msg = _(
|
||||
'{0}, it has been loading from {1}'
|
||||
)
|
||||
else:
|
||||
msg = _(
|
||||
'{0}, it will be ignored when loading from {1}'
|
||||
)
|
||||
msg = msg.format(err_msg, options["source"])
|
||||
if subconfig is not None:
|
||||
msg = {msg: subconfig._subconfig}
|
||||
self.unknowns.append(msg)
|
||||
elif err.code == "option-dynamic":
|
||||
if self.invalid_user_data_error:
|
||||
msg = _(
|
||||
'"{0}" is the name of a dynamic family, it has been loading from {1}'
|
||||
)
|
||||
else:
|
||||
msg = _(
|
||||
'"{0}" is the name of a dynamic family, it will be ignored when loading from {1}'
|
||||
)
|
||||
self.invalids.append({msg.format(option.description(with_quote=True), options["source"]): option._subconfig})
|
||||
else:
|
||||
self.invalids.append(
|
||||
_("{0} loaded from {1}").format(err, options["source"])
|
||||
)
|
||||
continue
|
||||
value = self.convert_value(
|
||||
path, option, self.values[path].get("options", {}), value
|
||||
)
|
||||
if option.isfollower():
|
||||
if not isinstance(value, tuple):
|
||||
indexes = range(len(value))
|
||||
else:
|
||||
try:
|
||||
indexes = range(len(option.parent().leader().value.get()))
|
||||
except:
|
||||
continue
|
||||
values = value
|
||||
else:
|
||||
indexes = [None]
|
||||
for index in indexes:
|
||||
try:
|
||||
if option.isfollower():
|
||||
if not isinstance(value, tuple):
|
||||
value = values[index]
|
||||
if value is undefined or isinstance(value, CancelParam):
|
||||
continue
|
||||
index_ = index
|
||||
else:
|
||||
index_ = None
|
||||
self.set_value(option, value, options.get("options", {}), index_)
|
||||
except PropertiesOptionError as err:
|
||||
if err.code == "property-error":
|
||||
properties = display_list(
|
||||
[_(prop) for prop in err.proptype], add_quote=False
|
||||
)
|
||||
err_path = err.subconfig.path
|
||||
err_description = err.subconfig.option.impl_get_display_name(err.subconfig, with_quote=True)
|
||||
display_name = option.description(with_quote=True)
|
||||
if index is not None:
|
||||
if path == err_path:
|
||||
if self.unknown_user_data_error:
|
||||
msg = _(
|
||||
'variable {0} at index "{1}" is {2}, it has been loading from {3}'
|
||||
)
|
||||
else:
|
||||
msg = _(
|
||||
'variable {0} at index "{1}" is {2}, it will be ignored when loading from {3}'
|
||||
)
|
||||
self.unknowns.append({
|
||||
msg.format(
|
||||
display_name,
|
||||
index,
|
||||
properties,
|
||||
options["source"],
|
||||
): option._subconfig}
|
||||
)
|
||||
else:
|
||||
if self.unknown_user_data_error:
|
||||
msg = _(
|
||||
'family {0} is {1}, {2} at index "{3}", it has been loading from {4}'
|
||||
)
|
||||
else:
|
||||
msg = _(
|
||||
'family {0} is {1}, {2} at index "{3}", it will be ignored when loading from {4}'
|
||||
)
|
||||
self.unknowns.append({
|
||||
msg.format(
|
||||
err_description,
|
||||
properties,
|
||||
display_name,
|
||||
index,
|
||||
options["source"],
|
||||
): option._subconfig}
|
||||
)
|
||||
else:
|
||||
if path == err_path:
|
||||
if self.unknown_user_data_error:
|
||||
msg = _(
|
||||
"variable has propery {0}, it has been loading from {1}"
|
||||
)
|
||||
else:
|
||||
msg = _(
|
||||
"variable has property {0}, it will be ignored when loading from {1}"
|
||||
)
|
||||
self.unknowns.append({
|
||||
msg.format(
|
||||
properties, options["source"]
|
||||
): option._subconfig}
|
||||
)
|
||||
else:
|
||||
if self.unknown_user_data_error:
|
||||
msg = _(
|
||||
"family {0} has property {1}, so cannot access to {2}, it has been loading from {3}"
|
||||
)
|
||||
else:
|
||||
msg = _(
|
||||
"family {0} has property {1}, so cannot access to {2}, it will be ignored when loading from {3}"
|
||||
)
|
||||
self.unknowns.append({
|
||||
msg.format(
|
||||
err_description,
|
||||
properties,
|
||||
display_name,
|
||||
options["source"],
|
||||
): option._subconfig}
|
||||
)
|
||||
else:
|
||||
if self.unknown_user_data_error:
|
||||
msg = _(
|
||||
"{0}, it has been loading from {1}"
|
||||
)
|
||||
else:
|
||||
msg = _(
|
||||
"{0}, it will be ignored when loading from {1}"
|
||||
)
|
||||
self.unknowns.append({
|
||||
msg.format(err, options["source"]): option._subconfig}
|
||||
)
|
||||
except LeadershipError as err:
|
||||
if self.unknown_user_data_error:
|
||||
msg = _(
|
||||
"{0}, it has been loading from {1}"
|
||||
)
|
||||
else:
|
||||
msg = _(
|
||||
"{0}, it will be ignored when loading from {1}"
|
||||
)
|
||||
self.unknowns.append({
|
||||
msg.format(err, options["source"]): option._subconfig}
|
||||
)
|
||||
except ConfigError as err:
|
||||
err.prefix = ""
|
||||
if self.invalid_user_data_error:
|
||||
msg = _('{0}, it has been loading from {1}').format(err, options["source"])
|
||||
else:
|
||||
msg = _('{0}, it will be ignored when loading from {1}').format(err, options["source"])
|
||||
self.invalids.append({msg: option._subconfig})
|
||||
except ValueError as err:
|
||||
err.prefix = ""
|
||||
type_ = option.type(translation=True)
|
||||
msg = _('the value {0} is an invalid {1}, {2}').format(
|
||||
self._display_value(option, value),
|
||||
type_,
|
||||
err,
|
||||
)
|
||||
if self.invalid_user_data_error:
|
||||
msg += _(', it has been loading from {0}').format(options["source"])
|
||||
else:
|
||||
msg += _(', it will be ignored when loading from {0}').format(options["source"])
|
||||
self.invalids.append({msg: option._subconfig})
|
||||
except AttributeOptionError as err:
|
||||
err.prefix = ""
|
||||
if err.code == "option-dynamic":
|
||||
continue
|
||||
raise err from err
|
||||
|
||||
def set_value(self, option, value, options, index):
|
||||
is_secret_manager = options.get("secret_manager", False)
|
||||
option_without_index = option
|
||||
if is_secret_manager and isinstance(value, tuple):
|
||||
# it's a function
|
||||
params = tuple([ParamValue(val) for val in value[1:]])
|
||||
option.information.set('secret_manager', True)
|
||||
if index is not None:
|
||||
option = option.forcepermissive.index(index)
|
||||
value = Calculation(value[0], Params(params, kwargs={"option": ParamValue(option)}))
|
||||
option = option.forcepermissive
|
||||
add_validation = True
|
||||
else:
|
||||
if index is not None:
|
||||
option = option.index(index)
|
||||
add_validation = False
|
||||
option.value.set(value)
|
||||
if add_validation:
|
||||
option.property.add("validator")
|
||||
path = option.path()
|
||||
if "source" in self.values[path]:
|
||||
if option.isfollower():
|
||||
key = f"loaded_from_{index}"
|
||||
else:
|
||||
key = "loaded_from"
|
||||
value = _("loaded from {0}").format(
|
||||
self.values[path]["source"]
|
||||
)
|
||||
if options.get("secret_manager"):
|
||||
# FIXME (true_config ???)
|
||||
default = option.value.default()
|
||||
if option.isleader():
|
||||
default = default[0]
|
||||
value = _('{0} (the search key is "{1}")').format(value, default)
|
||||
option_without_index.information.set(
|
||||
key,
|
||||
value,
|
||||
)
|
||||
|
||||
|
||||
def convert_value(option, value, needs_convert):
|
||||
if value == "":
|
||||
return None
|
||||
option_type = option.information.get("type")
|
||||
if option_type == "port":
|
||||
func = CONVERT_OPTION[option_type]["func"]
|
||||
try:
|
||||
return func(value)
|
||||
except:
|
||||
return value
|
||||
if option_type == "choice":
|
||||
try:
|
||||
choices = option.value.list()
|
||||
if value not in choices and isinstance(value, str):
|
||||
# FIXME add other tests (boolean, float, ...)
|
||||
if value.isnumeric() and int(value) in choices:
|
||||
value = int(value)
|
||||
except:
|
||||
pass
|
||||
func = CONVERT_OPTION.get(option_type, {}).get("func")
|
||||
if func:
|
||||
try:
|
||||
return func(value)
|
||||
except:
|
||||
pass
|
||||
return value
|
||||
|
|
@ -9,7 +9,7 @@ Cadoles (http://www.cadoles.com)
|
|||
Copyright (C) 2019-2021
|
||||
|
||||
Silique (https://www.silique.fr)
|
||||
Copyright (C) 2022-2024
|
||||
Copyright (C) 2022-2026
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by the
|
||||
|
|
@ -26,7 +26,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
"""
|
||||
|
||||
from typing import List, Union
|
||||
from unicodedata import normalize, combining
|
||||
import re
|
||||
from itertools import chain
|
||||
|
||||
|
|
@ -45,6 +44,8 @@ from .error import DictConsistencyError
|
|||
|
||||
NAME_REGEXP = re.compile(r"^[a-z0-9_]*$")
|
||||
|
||||
PROPERTY_ATTRIBUTE = ["frozen", "hidden", "disabled", "mandatory"]
|
||||
|
||||
|
||||
def valid_variable_family_name(
|
||||
name: str,
|
||||
|
|
@ -58,17 +59,6 @@ def valid_variable_family_name(
|
|||
raise DictConsistencyError(msg, 76, xmlfiles)
|
||||
|
||||
|
||||
def normalize_family(family_name: str) -> str:
|
||||
"""replace space, accent, uppercase, ... by valid character"""
|
||||
if not family_name:
|
||||
return
|
||||
family_name = family_name.lower()
|
||||
family_name = family_name.replace("-", "_").replace(" ", "_").replace(".", "_")
|
||||
nfkd_form = normalize("NFKD", family_name)
|
||||
family_name = "".join([c for c in nfkd_form if not combining(c)])
|
||||
return family_name.lower()
|
||||
|
||||
|
||||
def load_modules(name, module) -> List[str]:
|
||||
"""list all functions in a module"""
|
||||
loader = SourceFileLoader(name, module)
|
||||
|
|
@ -78,13 +68,10 @@ def load_modules(name, module) -> List[str]:
|
|||
return eosfunc
|
||||
|
||||
|
||||
def get_realpath(
|
||||
path: str,
|
||||
path_prefix: str,
|
||||
) -> str:
|
||||
if path_prefix:
|
||||
return f"{path_prefix}.{path}"
|
||||
return path
|
||||
# def get_realpath(
|
||||
# path: str,
|
||||
# ) -> str:
|
||||
# return path
|
||||
|
||||
|
||||
def get_jinja_variable_to_param(
|
||||
|
|
@ -93,12 +80,12 @@ def get_jinja_variable_to_param(
|
|||
objectspace,
|
||||
xmlfiles,
|
||||
functions,
|
||||
path_prefix,
|
||||
version,
|
||||
namespace,
|
||||
):
|
||||
try:
|
||||
env = SandboxedEnvironment(loader=DictLoader({"tmpl": jinja_text}))
|
||||
env.add_extension('jinja2.ext.do')
|
||||
env.filters = functions
|
||||
parsed_content = Parser(env, jinja_text, "", "").parse()
|
||||
|
||||
|
|
@ -114,10 +101,12 @@ def get_jinja_variable_to_param(
|
|||
for g in parsed_content.find_all(Getattr):
|
||||
variables.add(recurse_getattr(g))
|
||||
except TemplateSyntaxError as err:
|
||||
msg = _('error in jinja "{0}" for the variable "{1}": {2}').format(
|
||||
msg = _('error for the variable "{1}" in jinja "{0}": {2}').format(
|
||||
jinja_text, current_path, err
|
||||
)
|
||||
raise DictConsistencyError(msg, 39, xmlfiles) from err
|
||||
except AttributeError:
|
||||
pass
|
||||
variables = list(variables)
|
||||
variables.sort(reverse=True)
|
||||
founded_variables = {}
|
||||
|
|
@ -125,7 +114,6 @@ def get_jinja_variable_to_param(
|
|||
for variable_path in variables:
|
||||
variable, identifier = objectspace.paths.get_with_dynamic(
|
||||
variable_path,
|
||||
path_prefix,
|
||||
current_path,
|
||||
version,
|
||||
namespace,
|
||||
|
|
@ -140,7 +128,6 @@ def get_jinja_variable_to_param(
|
|||
break
|
||||
else:
|
||||
unknown_variables.append(variable_path)
|
||||
|
||||
for variable_path in unknown_variables:
|
||||
for v in founded_variables:
|
||||
if get_common_path(v, variable_path) == v:
|
||||
|
|
@ -152,7 +139,6 @@ def get_jinja_variable_to_param(
|
|||
vpath = vpath.rsplit(".", 1)[0]
|
||||
variable, identifier = objectspace.paths.get_with_dynamic(
|
||||
vpath,
|
||||
path_prefix,
|
||||
current_path,
|
||||
version,
|
||||
namespace,
|
||||
|
|
@ -165,3 +151,70 @@ def get_jinja_variable_to_param(
|
|||
yield {}, None, root_path
|
||||
for variable_path, data in founded_variables.items():
|
||||
yield data[1], data[0], variable_path
|
||||
|
||||
|
||||
def calc_multi_for_type_variable(
|
||||
local_variable: "Variable",
|
||||
variable_in_calculation_path: str,
|
||||
variable_in_calculation: "Variable",
|
||||
objectspace: "RougailConvert",
|
||||
) -> Union[bool, str]:
|
||||
variable_in_calculation_multi = variable_in_calculation.multi
|
||||
if local_variable.path in objectspace.families:
|
||||
# it's a family
|
||||
local_variable_multi = None
|
||||
else:
|
||||
local_variable_multi = local_variable.multi
|
||||
# variable is a leader
|
||||
if variable_in_calculation.path in objectspace.leaders:
|
||||
local_variable_parent = local_variable.path.rsplit(".", 1)[0]
|
||||
variable_in_calculation_parent = variable_in_calculation.path.rsplit(
|
||||
".", 1
|
||||
)[0]
|
||||
if local_variable_parent == variable_in_calculation_parent:
|
||||
variable_in_calculation_multi = False
|
||||
# variable is a follower
|
||||
elif variable_in_calculation.path in objectspace.followers:
|
||||
local_variable_parent = local_variable.path.rsplit(".", 1)[0]
|
||||
variable_in_calculation_parent = variable_in_calculation.path.rsplit(
|
||||
".", 1
|
||||
)[0]
|
||||
if local_variable_parent != variable_in_calculation_parent:
|
||||
if variable_in_calculation_multi:
|
||||
variable_in_calculation_multi = "submulti"
|
||||
else:
|
||||
variable_in_calculation_multi = True
|
||||
# variable is in a dynamic family
|
||||
if objectspace.paths.is_dynamic(variable_in_calculation.path):
|
||||
common_path = get_common_path(
|
||||
local_variable.path, variable_in_calculation_path
|
||||
)
|
||||
common_variable_path = variable_in_calculation_path
|
||||
if common_path:
|
||||
common_variable_path = common_variable_path[len(common_path) + 1 :]
|
||||
count_identifiers = common_variable_path.count("{{ identifier }}")
|
||||
if count_identifiers == 1:
|
||||
if variable_in_calculation_multi is False:
|
||||
variable_in_calculation_multi = True
|
||||
else:
|
||||
variable_in_calculation_multi = "submulti"
|
||||
elif count_identifiers > 1:
|
||||
variable_in_calculation_multi = "submulti"
|
||||
return local_variable_multi, variable_in_calculation_multi
|
||||
|
||||
|
||||
class Undefined:
|
||||
pass
|
||||
|
||||
|
||||
def get_properties_to_string():
|
||||
return [
|
||||
("mandatory", _("mandatory")),
|
||||
("hidden", _("hidden")),
|
||||
("disabled", _("disabled")),
|
||||
("unique", _("unique")),
|
||||
("force_store_value", _("auto modified")),
|
||||
]
|
||||
|
||||
|
||||
undefined = Undefined()
|
||||
|
|
|
|||
8
tests/default_option_params/structure/00-test.yml
Normal file
8
tests/default_option_params/structure/00-test.yml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
version: 1.1
|
||||
|
||||
file:
|
||||
type: unix_filename
|
||||
params:
|
||||
allow_relative: true
|
||||
default:
|
||||
test/unknown_file
|
||||
1
tests/dictionaries/00_0empty/makedict/read_write.json
Normal file
1
tests/dictionaries/00_0empty/makedict/read_write.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -2,7 +2,7 @@ from tiramisu import *
|
|||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('tests/dictionaries/../eosfunc/test.py')
|
||||
load_functions('../rougail-tests/funcs/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
|
|
|
|||
|
|
@ -2,7 +2,11 @@ from tiramisu import *
|
|||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('tests/dictionaries/../eosfunc/test.py')
|
||||
load_functions('../rougail-tests/funcs/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
groups.addgroup('namespace')
|
||||
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
|
|
|
|||
1
tests/dictionaries/00_0no_variable/makedict/after.json
Normal file
1
tests/dictionaries/00_0no_variable/makedict/after.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
1
tests/dictionaries/00_0no_variable/makedict/base.json
Normal file
1
tests/dictionaries/00_0no_variable/makedict/base.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
1
tests/dictionaries/00_0no_variable/makedict/before.json
Normal file
1
tests/dictionaries/00_0no_variable/makedict/before.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -2,7 +2,7 @@ from tiramisu import *
|
|||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('tests/dictionaries/../eosfunc/test.py')
|
||||
load_functions('../rougail-tests/funcs/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
|
|
@ -10,6 +10,5 @@ except:
|
|||
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
optiondescription_1 = OptionDescription(name="1", doc="1", children=[], properties=frozenset({"advanced"}))
|
||||
optiondescription_2 = OptionDescription(name="2", doc="2", children=[], properties=frozenset({"advanced"}))
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1, optiondescription_2])
|
||||
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[], properties=frozenset({"advanced"}))
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])
|
||||
|
|
@ -2,7 +2,7 @@ from tiramisu import *
|
|||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('tests/dictionaries/../eosfunc/test.py')
|
||||
load_functions('../rougail-tests/funcs/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
|
|
@ -10,6 +10,4 @@ except:
|
|||
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
optiondescription_1 = OptionDescription(name="1", doc="1", children=[], properties=frozenset({"advanced"}))
|
||||
optiondescription_5 = OptionDescription(name="2", doc="2", children=[], properties=frozenset({"advanced"}))
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1, optiondescription_5])
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[])
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -0,0 +1 @@
|
|||
[]
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -2,7 +2,7 @@ from tiramisu import *
|
|||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('tests/dictionaries/../eosfunc/test.py')
|
||||
load_functions('../rougail-tests/funcs/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
|
|
@ -10,6 +10,5 @@ except:
|
|||
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
optiondescription_1 = OptionDescription(name="1", doc="1", children=[], properties=frozenset({"advanced"}))
|
||||
optiondescription_4 = OptionDescription(name="2", doc="2", children=[], properties=frozenset({"advanced"}))
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1, optiondescription_4])
|
||||
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[], properties=frozenset({"advanced"}))
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])
|
||||
|
|
@ -2,7 +2,7 @@ from tiramisu import *
|
|||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('tests/dictionaries/../eosfunc/test.py')
|
||||
load_functions('../rougail-tests/funcs/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
|
|
@ -10,6 +10,4 @@ except:
|
|||
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
optiondescription_1 = OptionDescription(name="1", doc="1", children=[], properties=frozenset({"advanced"}))
|
||||
optiondescription_4 = OptionDescription(name="2", doc="2", children=[], properties=frozenset({"advanced"}))
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1, optiondescription_4])
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[])
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -0,0 +1 @@
|
|||
[]
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
from tiramisu import *
|
||||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('../rougail-tests/funcs/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
groups.addgroup('namespace')
|
||||
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[], properties=frozenset({"advanced"}))
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
from tiramisu import *
|
||||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('../rougail-tests/funcs/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
groups.addgroup('namespace')
|
||||
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[])
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
---
|
||||
_version: '1.1'
|
||||
version: # a variable
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"rougail.version": null
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ from tiramisu import *
|
|||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('tests/dictionaries/../eosfunc/test.py')
|
||||
load_functions('../rougail-tests/funcs/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
|
|
@ -10,6 +10,6 @@ except:
|
|||
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
option_2 = StrOption(name="version", doc="a variable", properties=frozenset({"basic", "mandatory"}), informations={'type': 'string'})
|
||||
option_2 = StrOption(name="version", doc="a variable", properties=frozenset({"basic", "mandatory"}), informations={'ymlfiles': ['../rougail-tests/structures/00_0version_underscore/rougail/00-base.yml'], 'type': 'string'})
|
||||
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_2], properties=frozenset({"basic"}))
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
from tiramisu import *
|
||||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('tests/dictionaries/../eosfunc/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
groups.addgroup('namespace')
|
||||
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
option_3 = StrOption(name="version", doc="a variable", properties=frozenset({"basic", "mandatory"}), informations={'type': 'string'})
|
||||
optiondescription_2 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_3], properties=frozenset({"basic"}))
|
||||
optiondescription_1 = OptionDescription(name="1", doc="1", children=[optiondescription_2], properties=frozenset({"basic"}))
|
||||
option_6 = StrOption(name="version", doc="a variable", properties=frozenset({"basic", "mandatory"}), informations={'type': 'string'})
|
||||
optiondescription_5 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_6], properties=frozenset({"basic"}))
|
||||
optiondescription_4 = OptionDescription(name="2", doc="2", children=[optiondescription_5], properties=frozenset({"basic"}))
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1, optiondescription_4])
|
||||
|
|
@ -2,9 +2,13 @@ from tiramisu import *
|
|||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('tests/dictionaries/../eosfunc/test.py')
|
||||
load_functions('../rougail-tests/funcs/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
groups.addgroup('namespace')
|
||||
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
option_1 = StrOption(name="version", doc="a variable", properties=frozenset({"basic", "mandatory"}), informations={'type': 'string'})
|
||||
option_1 = StrOption(name="version", doc="a variable", properties=frozenset({"basic", "mandatory"}), informations={'ymlfiles': ['../rougail-tests/structures/00_0version_underscore/rougail/00-base.yml'], 'type': 'string'})
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1])
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
---
|
||||
version: '1.0'
|
||||
empty:
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"rougail.empty": null
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ from tiramisu import *
|
|||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('tests/dictionaries/../eosfunc/test.py')
|
||||
load_functions('../rougail-tests/funcs/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
|
|
@ -10,6 +10,6 @@ except:
|
|||
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
option_2 = StrOption(name="empty", doc="empty", properties=frozenset({"basic", "mandatory"}), informations={'type': 'string'})
|
||||
option_2 = StrOption(name="empty", doc="empty", properties=frozenset({"basic", "mandatory"}), informations={'ymlfiles': ['../rougail-tests/structures/00_1empty_variable/rougail/00-base.yml'], 'type': 'string'})
|
||||
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_2], properties=frozenset({"basic"}))
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
from tiramisu import *
|
||||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('tests/dictionaries/../eosfunc/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
groups.addgroup('namespace')
|
||||
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
option_3 = StrOption(name="empty", doc="empty", properties=frozenset({"basic", "mandatory"}), informations={'type': 'string'})
|
||||
optiondescription_2 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_3], properties=frozenset({"basic"}))
|
||||
optiondescription_1 = OptionDescription(name="1", doc="1", children=[optiondescription_2], properties=frozenset({"basic"}))
|
||||
option_6 = StrOption(name="empty", doc="empty", properties=frozenset({"basic", "mandatory"}), informations={'type': 'string'})
|
||||
optiondescription_5 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_6], properties=frozenset({"basic"}))
|
||||
optiondescription_4 = OptionDescription(name="2", doc="2", children=[optiondescription_5], properties=frozenset({"basic"}))
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1, optiondescription_4])
|
||||
|
|
@ -2,9 +2,13 @@ from tiramisu import *
|
|||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('tests/dictionaries/../eosfunc/test.py')
|
||||
load_functions('../rougail-tests/funcs/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
groups.addgroup('namespace')
|
||||
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
option_1 = StrOption(name="empty", doc="empty", properties=frozenset({"basic", "mandatory"}), informations={'type': 'string'})
|
||||
option_1 = StrOption(name="empty", doc="empty", properties=frozenset({"basic", "mandatory"}), informations={'ymlfiles': ['../rougail-tests/structures/00_1empty_variable/rougail/00-base.yml'], 'type': 'string'})
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1])
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
version: 1.1
|
||||
var1: "no" # a first variable
|
||||
var2:
|
||||
description: a second variable
|
||||
multi: true
|
||||
default:
|
||||
jinja: |
|
||||
{{ _.var1 }}
|
||||
description: the value of var1
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"rougail.var1": "no",
|
||||
"rougail.var2": [
|
||||
"no"
|
||||
]
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ from tiramisu import *
|
|||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('tests/dictionaries/../eosfunc/test.py')
|
||||
load_functions('../rougail-tests/funcs/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
|
|
@ -11,7 +11,7 @@ ALLOWED_LEADER_PROPERTIES.add("basic")
|
|||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
dict_env['default_rougail.var2'] = "{{ _.var1 }}\n"
|
||||
option_2 = StrOption(name="var1", doc="a first variable", default="no", properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
|
||||
option_3 = StrOption(name="var2", doc="a second variable", multi=True, default=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("default_rougail.var2"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(True), '__internal_files': ParamValue(['tests/dictionaries/00_2default_calculated/dictionaries/rougail/00-base.yml']), '__internal_attribute': ParamValue("default"), '__internal_variable': ParamValue("rougail.var2"), '_.var1': ParamOption(option_2, notraisepropertyerror=True)})), properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
|
||||
option_2 = StrOption(name="var1", doc="a first variable", default="no", properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/00_2default_calculated/rougail/00-base.yml'], 'type': 'string'})
|
||||
option_3 = StrOption(name="var2", doc="a second variable", multi=True, default=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("default_rougail.var2"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(True), '__internal_files': ParamValue(['../rougail-tests/structures/00_2default_calculated/rougail/00-base.yml']), '__internal_attribute': ParamValue("default"), '__internal_variable': ParamValue("rougail.var2"), '_.var1': ParamOption(option_2, notraisepropertyerror=True)})), properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/00_2default_calculated/rougail/00-base.yml'], 'type': 'string'})
|
||||
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_2, option_3], properties=frozenset({"standard"}))
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
from tiramisu import *
|
||||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('tests/dictionaries/../eosfunc/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
groups.addgroup('namespace')
|
||||
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
dict_env['default_1.rougail.var2'] = "{{ _.var1 }}\n"
|
||||
dict_env['default_2.rougail.var2'] = "{{ _.var1 }}\n"
|
||||
option_3 = StrOption(name="var1", doc="a first variable", default="no", properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
|
||||
option_4 = StrOption(name="var2", doc="a second variable", multi=True, default=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("default_1.rougail.var2"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(True), '__internal_files': ParamValue(['tests/dictionaries/00_2default_calculated/dictionaries/rougail/00-base.yml']), '__internal_attribute': ParamValue("default"), '__internal_variable': ParamValue("1.rougail.var2"), '_.var1': ParamOption(option_3, notraisepropertyerror=True)})), properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
|
||||
optiondescription_2 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_3, option_4], properties=frozenset({"standard"}))
|
||||
optiondescription_1 = OptionDescription(name="1", doc="1", children=[optiondescription_2], properties=frozenset({"standard"}))
|
||||
option_7 = StrOption(name="var1", doc="a first variable", default="no", properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
|
||||
option_8 = StrOption(name="var2", doc="a second variable", multi=True, default=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("default_2.rougail.var2"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(True), '__internal_files': ParamValue(['tests/dictionaries/00_2default_calculated/dictionaries/rougail/00-base.yml']), '__internal_attribute': ParamValue("default"), '__internal_variable': ParamValue("2.rougail.var2"), '_.var1': ParamOption(option_7, notraisepropertyerror=True)})), properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
|
||||
optiondescription_6 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_7, option_8], properties=frozenset({"standard"}))
|
||||
optiondescription_5 = OptionDescription(name="2", doc="2", children=[optiondescription_6], properties=frozenset({"standard"}))
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1, optiondescription_5])
|
||||
|
|
@ -2,11 +2,15 @@ from tiramisu import *
|
|||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('tests/dictionaries/../eosfunc/test.py')
|
||||
load_functions('../rougail-tests/funcs/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
groups.addgroup('namespace')
|
||||
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
dict_env['default_var2'] = "{{ _.var1 }}\n"
|
||||
option_1 = StrOption(name="var1", doc="a first variable", default="no", properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
|
||||
option_2 = StrOption(name="var2", doc="a second variable", multi=True, default=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("default_var2"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(True), '__internal_files': ParamValue(['tests/dictionaries/00_2default_calculated/dictionaries/rougail/00-base.yml']), '__internal_attribute': ParamValue("default"), '__internal_variable': ParamValue("var2"), '_.var1': ParamOption(option_1, notraisepropertyerror=True)})), properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
|
||||
option_1 = StrOption(name="var1", doc="a first variable", default="no", properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/00_2default_calculated/rougail/00-base.yml'], 'type': 'string'})
|
||||
option_2 = StrOption(name="var2", doc="a second variable", multi=True, default=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("default_var2"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(True), '__internal_files': ParamValue(['../rougail-tests/structures/00_2default_calculated/rougail/00-base.yml']), '__internal_attribute': ParamValue("default"), '__internal_variable': ParamValue("var2"), '_.var1': ParamOption(option_1, notraisepropertyerror=True)})), properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/00_2default_calculated/rougail/00-base.yml'], 'type': 'string'})
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_2])
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
---
|
||||
version: 1.1
|
||||
var1: # a first variable
|
||||
- 'no'
|
||||
- 'yes'
|
||||
- maybe
|
||||
var2:
|
||||
description: a second variable
|
||||
multi: true
|
||||
default:
|
||||
jinja: |
|
||||
{% for val in _.var1 %}
|
||||
{{ val }}
|
||||
{% endfor %}
|
||||
description: the value of _.var1
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"rougail.var1": [
|
||||
"no",
|
||||
"yes",
|
||||
"maybe"
|
||||
],
|
||||
"rougail.var2": [
|
||||
"no",
|
||||
"yes",
|
||||
"maybe"
|
||||
]
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ from tiramisu import *
|
|||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('tests/dictionaries/../eosfunc/test.py')
|
||||
load_functions('../rougail-tests/funcs/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
|
|
@ -11,7 +11,7 @@ ALLOWED_LEADER_PROPERTIES.add("basic")
|
|||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
dict_env['default_rougail.var2'] = "{% for val in _.var1 %}\n{{ val }}\n{% endfor %}\n"
|
||||
option_2 = StrOption(name="var1", doc="a first variable", multi=True, default=["no", "yes", "maybe"], default_multi="no", properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
|
||||
option_3 = StrOption(name="var2", doc="a second variable", multi=True, default=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("default_rougail.var2"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(True), '__internal_files': ParamValue(['tests/dictionaries/00_2default_calculated_multi/dictionaries/rougail/00-base.yml']), '__internal_attribute': ParamValue("default"), '__internal_variable': ParamValue("rougail.var2"), '_.var1': ParamOption(option_2, notraisepropertyerror=True)})), properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
|
||||
option_2 = StrOption(name="var1", doc="a first variable", multi=True, default=["no", "yes", "maybe"], default_multi="no", properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/00_2default_calculated_multi/rougail/00-base.yml'], 'type': 'string'})
|
||||
option_3 = StrOption(name="var2", doc="a second variable", multi=True, default=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("default_rougail.var2"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(True), '__internal_files': ParamValue(['../rougail-tests/structures/00_2default_calculated_multi/rougail/00-base.yml']), '__internal_attribute': ParamValue("default"), '__internal_variable': ParamValue("rougail.var2"), '_.var1': ParamOption(option_2, notraisepropertyerror=True)})), properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/00_2default_calculated_multi/rougail/00-base.yml'], 'type': 'string'})
|
||||
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_2, option_3], properties=frozenset({"standard"}))
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
from tiramisu import *
|
||||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('tests/dictionaries/../eosfunc/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
groups.addgroup('namespace')
|
||||
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
dict_env['default_1.rougail.var2'] = "{% for val in _.var1 %}\n{{ val }}\n{% endfor %}\n"
|
||||
dict_env['default_2.rougail.var2'] = "{% for val in _.var1 %}\n{{ val }}\n{% endfor %}\n"
|
||||
option_3 = StrOption(name="var1", doc="a first variable", multi=True, default=["no", "yes", "maybe"], default_multi="no", properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
|
||||
option_4 = StrOption(name="var2", doc="a second variable", multi=True, default=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("default_1.rougail.var2"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(True), '__internal_files': ParamValue(['tests/dictionaries/00_2default_calculated_multi/dictionaries/rougail/00-base.yml']), '__internal_attribute': ParamValue("default"), '__internal_variable': ParamValue("1.rougail.var2"), '_.var1': ParamOption(option_3, notraisepropertyerror=True)})), properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
|
||||
optiondescription_2 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_3, option_4], properties=frozenset({"standard"}))
|
||||
optiondescription_1 = OptionDescription(name="1", doc="1", children=[optiondescription_2], properties=frozenset({"standard"}))
|
||||
option_7 = StrOption(name="var1", doc="a first variable", multi=True, default=["no", "yes", "maybe"], default_multi="no", properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
|
||||
option_8 = StrOption(name="var2", doc="a second variable", multi=True, default=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("default_2.rougail.var2"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(True), '__internal_files': ParamValue(['tests/dictionaries/00_2default_calculated_multi/dictionaries/rougail/00-base.yml']), '__internal_attribute': ParamValue("default"), '__internal_variable': ParamValue("2.rougail.var2"), '_.var1': ParamOption(option_7, notraisepropertyerror=True)})), properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
|
||||
optiondescription_6 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_7, option_8], properties=frozenset({"standard"}))
|
||||
optiondescription_5 = OptionDescription(name="2", doc="2", children=[optiondescription_6], properties=frozenset({"standard"}))
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1, optiondescription_5])
|
||||
|
|
@ -2,11 +2,15 @@ from tiramisu import *
|
|||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('tests/dictionaries/../eosfunc/test.py')
|
||||
load_functions('../rougail-tests/funcs/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
groups.addgroup('namespace')
|
||||
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
dict_env['default_var2'] = "{% for val in _.var1 %}\n{{ val }}\n{% endfor %}\n"
|
||||
option_1 = StrOption(name="var1", doc="a first variable", multi=True, default=["no", "yes", "maybe"], default_multi="no", properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
|
||||
option_2 = StrOption(name="var2", doc="a second variable", multi=True, default=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("default_var2"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(True), '__internal_files': ParamValue(['tests/dictionaries/00_2default_calculated_multi/dictionaries/rougail/00-base.yml']), '__internal_attribute': ParamValue("default"), '__internal_variable': ParamValue("var2"), '_.var1': ParamOption(option_1, notraisepropertyerror=True)})), properties=frozenset({"mandatory", "standard"}), informations={'type': 'string'})
|
||||
option_1 = StrOption(name="var1", doc="a first variable", multi=True, default=["no", "yes", "maybe"], default_multi="no", properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/00_2default_calculated_multi/rougail/00-base.yml'], 'type': 'string'})
|
||||
option_2 = StrOption(name="var2", doc="a second variable", multi=True, default=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("default_var2"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(True), '__internal_files': ParamValue(['../rougail-tests/structures/00_2default_calculated_multi/rougail/00-base.yml']), '__internal_attribute': ParamValue("default"), '__internal_variable': ParamValue("var2"), '_.var1': ParamOption(option_1, notraisepropertyerror=True)})), properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/00_2default_calculated_multi/rougail/00-base.yml'], 'type': 'string'})
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_2])
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"rougail.leadership.var1": {
|
||||
"owner": "default",
|
||||
"value": [
|
||||
"a_value"
|
||||
]
|
||||
},
|
||||
"rougail.leadership.var2": {
|
||||
"owner": [
|
||||
"default"
|
||||
],
|
||||
"value": [
|
||||
"a_value"
|
||||
]
|
||||
},
|
||||
"rougail.var2": {
|
||||
"owner": "default",
|
||||
"value": "a_value"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"rougail.leadership.var1": [
|
||||
{
|
||||
"rougail.leadership.var1": "a_value",
|
||||
"rougail.leadership.var2": "a_value"
|
||||
}
|
||||
],
|
||||
"rougail.var2": "a_value"
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"rougail.leadership.var1": {
|
||||
"owner": "default",
|
||||
"value": [
|
||||
"a_value"
|
||||
]
|
||||
},
|
||||
"rougail.leadership.var2": {
|
||||
"owner": [
|
||||
"default"
|
||||
],
|
||||
"value": [
|
||||
"a_value"
|
||||
]
|
||||
},
|
||||
"rougail.var2": {
|
||||
"owner": "default",
|
||||
"value": "a_value"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
[]
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"rougail.var2": "a_value"
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
from tiramisu import *
|
||||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('../rougail-tests/funcs/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
groups.addgroup('namespace')
|
||||
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
dict_env['default_rougail.var2'] = "{{ var1[0] }}"
|
||||
option_3 = StrOption(name="var1", doc="a first variable", multi=True, default=["a_value"], properties=frozenset({"force_default_on_freeze", "frozen", "mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/00_2default_calculated_params_permissive/rougail/00-base.yml'], 'type': 'string'})
|
||||
option_4 = StrOption(name="var2", doc="a first variable", multi=True, default_multi="a_value", properties=frozenset({"force_default_on_freeze", "frozen", "mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/00_2default_calculated_params_permissive/rougail/00-base.yml'], 'type': 'string'})
|
||||
optiondescription_2 = Leadership(name="leadership", doc="leadership", children=[option_3, option_4], properties=frozenset({"hidden", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/00_2default_calculated_params_permissive/rougail/00-base.yml']})
|
||||
option_5 = StrOption(name="var2", doc="a second variable", default=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("default_rougail.var2"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['../rougail-tests/structures/00_2default_calculated_params_permissive/rougail/00-base.yml']), '__internal_attribute': ParamValue("default"), '__internal_variable': ParamValue("rougail.var2"), 'var1': ParamOption(option_3)})), properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/00_2default_calculated_params_permissive/rougail/00-base.yml'], 'type': 'string'})
|
||||
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[optiondescription_2, option_5], properties=frozenset({"standard"}))
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
from tiramisu import *
|
||||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('../rougail-tests/funcs/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
groups.addgroup('namespace')
|
||||
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
dict_env['default_var2'] = "{{ var1[0] }}"
|
||||
option_2 = StrOption(name="var1", doc="a first variable", multi=True, default=["a_value"], properties=frozenset({"force_default_on_freeze", "frozen", "mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/00_2default_calculated_params_permissive/rougail/00-base.yml'], 'type': 'string'})
|
||||
option_3 = StrOption(name="var2", doc="a first variable", multi=True, default_multi="a_value", properties=frozenset({"force_default_on_freeze", "frozen", "mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/00_2default_calculated_params_permissive/rougail/00-base.yml'], 'type': 'string'})
|
||||
optiondescription_1 = Leadership(name="leadership", doc="leadership", children=[option_2, option_3], properties=frozenset({"hidden", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/00_2default_calculated_params_permissive/rougail/00-base.yml']})
|
||||
option_4 = StrOption(name="var2", doc="a second variable", default=Calculation(func['jinja_to_function'], Params((), kwargs={'__internal_jinja': ParamValue("default_var2"), '__internal_type': ParamValue("string"), '__internal_multi': ParamValue(False), '__internal_files': ParamValue(['../rougail-tests/structures/00_2default_calculated_params_permissive/rougail/00-base.yml']), '__internal_attribute': ParamValue("default"), '__internal_variable': ParamValue("var2"), 'var1': ParamOption(option_2)})), properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/00_2default_calculated_params_permissive/rougail/00-base.yml'], 'type': 'string'})
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1, option_4])
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"rougail.var1": {
|
||||
"owner": "default",
|
||||
"value": []
|
||||
},
|
||||
"rougail.var2": {
|
||||
"owner": "default",
|
||||
"value": []
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"rougail.var1": [],
|
||||
"rougail.var2": []
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"rougail.var1": {
|
||||
"owner": "default",
|
||||
"value": []
|
||||
},
|
||||
"rougail.var2": {
|
||||
"owner": "default",
|
||||
"value": []
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
["rougail.var1", "rougail.var2"]
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"rougail.var1": [],
|
||||
"rougail.var2": []
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
from tiramisu import *
|
||||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('../rougail-tests/funcs/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
groups.addgroup('namespace')
|
||||
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
option_2 = DomainnameOption(name="var1", doc="a first variable", multi=True, type="domainname", allow_ip=True, properties=frozenset({"basic", "mandatory"}), informations={'ymlfiles': ['../rougail-tests/structures/00_2default_calculated_variable/rougail/00-base.yml'], 'type': 'domainname'})
|
||||
option_3 = DomainnameOption(name="var2", doc="a second variable", multi=True, default=Calculation(func['calc_value'], Params((ParamOption(option_2)), kwargs={'__internal_multi': ParamValue(True)})), type="domainname", allow_ip=False, properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/00_2default_calculated_variable/rougail/00-base.yml'], 'type': 'domainname'})
|
||||
optiondescription_1 = OptionDescription(name="rougail", doc="Rougail", group_type=groups.namespace, children=[option_2, option_3], properties=frozenset({"basic"}))
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[optiondescription_1])
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
from tiramisu import *
|
||||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
from re import compile as re_compile
|
||||
from rougail.tiramisu import func, dict_env, load_functions, ConvertDynOptionDescription
|
||||
load_functions('../rougail-tests/funcs/test.py')
|
||||
try:
|
||||
groups.namespace
|
||||
except:
|
||||
groups.addgroup('namespace')
|
||||
ALLOWED_LEADER_PROPERTIES.add("basic")
|
||||
ALLOWED_LEADER_PROPERTIES.add("standard")
|
||||
ALLOWED_LEADER_PROPERTIES.add("advanced")
|
||||
option_1 = DomainnameOption(name="var1", doc="a first variable", multi=True, type="domainname", allow_ip=True, properties=frozenset({"basic", "mandatory"}), informations={'ymlfiles': ['../rougail-tests/structures/00_2default_calculated_variable/rougail/00-base.yml'], 'type': 'domainname'})
|
||||
option_2 = DomainnameOption(name="var2", doc="a second variable", multi=True, default=Calculation(func['calc_value'], Params((ParamOption(option_1)), kwargs={'__internal_multi': ParamValue(True)})), type="domainname", allow_ip=False, properties=frozenset({"mandatory", "standard"}), informations={'ymlfiles': ['../rougail-tests/structures/00_2default_calculated_variable/rougail/00-base.yml'], 'type': 'domainname'})
|
||||
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1, option_2])
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"rougail.var1": {
|
||||
"owner": "default",
|
||||
"value": null
|
||||
},
|
||||
"rougail.var2": {
|
||||
"owner": "default",
|
||||
"value": null
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"rougail.var1": null,
|
||||
"rougail.var2": null
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"rougail.var1": {
|
||||
"owner": "default",
|
||||
"value": null
|
||||
},
|
||||
"rougail.var2": {
|
||||
"owner": "default",
|
||||
"value": null
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
["rougail.var1", "rougail.var2"]
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue