import tiramisu-json in tiramisu repository
This commit is contained in:
@ -25,6 +25,7 @@ from .setting import ConfigBag, OptionBag, owners, groups, Undefined, undefined,
|
||||
FORBIDDEN_SET_PROPERTIES, SPECIAL_PROPERTIES, EXPIRATION_TIME
|
||||
from .config import KernelConfig, SubConfig, KernelGroupConfig, KernelMetaConfig, KernelMixConfig
|
||||
from .option import ChoiceOption, OptionDescription
|
||||
from .todict import TiramisuDict
|
||||
|
||||
|
||||
TIRAMISU_VERSION = 3
|
||||
@ -626,6 +627,7 @@ class _TiramisuOption(CommonTiramisu):
|
||||
self._option_bag.path = self._path
|
||||
self._option_bag.index = self._index
|
||||
self._option_bag.config_bag = self._config_bag
|
||||
self._tiramisu_dict = None
|
||||
if not self._registers:
|
||||
_registers(self._registers, 'TiramisuOption')
|
||||
|
||||
@ -728,6 +730,29 @@ class _TiramisuOptionDescription(_TiramisuOption):
|
||||
subconfig,
|
||||
self._config_bag)
|
||||
|
||||
def dict(self,
|
||||
clearable: str="all",
|
||||
remotable: str="minimum",
|
||||
form: List=[]) -> Dict:
|
||||
"""convert config and option to tiramisu format"""
|
||||
if self._tiramisu_dict is None:
|
||||
option = self._get_option()
|
||||
name = option.impl_getname()
|
||||
root = self._subconfig._get_subpath(name)
|
||||
config = self._config_bag.context
|
||||
self._tiramisu_dict = TiramisuDict(Config(self._config_bag.context),
|
||||
root=root,
|
||||
clearable=clearable,
|
||||
remotable=remotable)
|
||||
return self._tiramisu_dict.todict(form)
|
||||
|
||||
def updates(self,
|
||||
body: List) -> Dict:
|
||||
"""updates value with tiramisu format"""
|
||||
if self._tiramisu_dict is None:
|
||||
raise APIError(_('please use .dict() before .updates()'))
|
||||
return self._tiramisu_dict.set_updates(body)
|
||||
|
||||
|
||||
class TiramisuOption(CommonTiramisuOption):
|
||||
"""Manage selected option"""
|
||||
@ -1060,6 +1085,11 @@ class TiramisuContextPermissive(TiramisuContext):
|
||||
|
||||
|
||||
class TiramisuContextOption(TiramisuContext):
|
||||
def __init__(self,
|
||||
*args,
|
||||
**kwargs) -> None:
|
||||
self._tiramisu_dict = None
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def _find(self,
|
||||
name,
|
||||
@ -1159,6 +1189,25 @@ class TiramisuContextOption(TiramisuContext):
|
||||
config_bag.context):
|
||||
yield toption
|
||||
|
||||
def dict(self,
|
||||
clearable="all",
|
||||
remotable="minimum",
|
||||
form=[]):
|
||||
"""convert config and option to tiramisu format"""
|
||||
if self._tiramisu_dict is None:
|
||||
self._tiramisu_dict = TiramisuDict(Config(self._config_bag.context),
|
||||
root=None,
|
||||
clearable=clearable,
|
||||
remotable=remotable)
|
||||
return self._tiramisu_dict.todict(form)
|
||||
|
||||
def updates(self,
|
||||
body: List) -> Dict:
|
||||
"""updates value with tiramisu format"""
|
||||
if self._tiramisu_dict is None:
|
||||
raise APIError(_('please use .dict() before .updates()'))
|
||||
return self._tiramisu_dict.set_updates(body)
|
||||
|
||||
|
||||
class _TiramisuContextConfigReset():
|
||||
def reset(self):
|
||||
|
@ -2,7 +2,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Tiramisu\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-03-05 08:46+CET\n"
|
||||
"POT-Creation-Date: 2019-04-08 08:41+CEST\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: Emmanuel Garette <egarette@cadoles.com>\n"
|
||||
"Language-Team: Tiramisu's team <egarette@cadoles.com>\n"
|
||||
@ -14,74 +14,78 @@ msgstr ""
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"X-Poedit-SourceCharset: UTF-8\n"
|
||||
|
||||
#: tiramisu/api.py:58
|
||||
#: tiramisu/api.py:59
|
||||
msgid "Settings:"
|
||||
msgstr "Paramètres :"
|
||||
|
||||
#: tiramisu/api.py:59
|
||||
#: tiramisu/api.py:60
|
||||
msgid "Access to option without verifying permissive properties"
|
||||
msgstr "Accès à une option sans vérifié les propriétés permises"
|
||||
|
||||
#: tiramisu/api.py:60
|
||||
#: tiramisu/api.py:61
|
||||
msgid "Access to option without property restriction"
|
||||
msgstr "Accès à une option sans restriction de propriété"
|
||||
|
||||
#: tiramisu/api.py:64
|
||||
#: tiramisu/api.py:65
|
||||
msgid "Call: {}"
|
||||
msgstr "Appel : {}"
|
||||
|
||||
#: tiramisu/api.py:66
|
||||
#: tiramisu/api.py:67
|
||||
msgid "Commands:"
|
||||
msgstr "Commandes :"
|
||||
|
||||
#: tiramisu/api.py:103
|
||||
#: tiramisu/api.py:104
|
||||
msgid ""
|
||||
"index \"{}\" is higher than the leadership length \"{}\" for option \"{}\""
|
||||
msgstr ""
|
||||
"l'index \"{}\" est supérieur à la longueur de l'option leadership \"{}\" "
|
||||
"pour l'option \"{}\""
|
||||
|
||||
#: tiramisu/api.py:108
|
||||
#: tiramisu/api.py:109
|
||||
msgid "option must not be an optiondescription"
|
||||
msgstr "option ne doit pas être une optiondescription"
|
||||
|
||||
#: tiramisu/api.py:135
|
||||
#: tiramisu/api.py:136
|
||||
msgid "index must be set with the follower option \"{}\""
|
||||
msgstr "l'index est obligatoire pour l'option suiveuse \"{}\""
|
||||
|
||||
#: tiramisu/api.py:138
|
||||
#: tiramisu/api.py:139
|
||||
msgid "unknown method {}"
|
||||
msgstr "méthode {} inconnue"
|
||||
|
||||
#: tiramisu/api.py:360
|
||||
#: tiramisu/api.py:361
|
||||
msgid "cannot add this property: \"{0}\""
|
||||
msgstr "ne peut pas ajouter cette propriété : \"{0}\""
|
||||
|
||||
#: tiramisu/api.py:503 tiramisu/config.py:252
|
||||
#: tiramisu/api.py:505 tiramisu/config.py:252
|
||||
msgid "can't delete a SymLinkOption"
|
||||
msgstr "ne peut supprimer une valeur à une SymLinkOption"
|
||||
|
||||
#: tiramisu/api.py:636 tiramisu/api.py:1322
|
||||
#: tiramisu/api.py:639 tiramisu/api.py:1375
|
||||
msgid "please specify a valid sub function ({})"
|
||||
msgstr "veuillez spécifier une sous fonction valide ({})"
|
||||
|
||||
#: tiramisu/api.py:699 tiramisu/api.py:1145
|
||||
#: tiramisu/api.py:702 tiramisu/api.py:1176
|
||||
msgid "unknown list type {}"
|
||||
msgstr "type de liste inconnue {}"
|
||||
|
||||
#: tiramisu/api.py:701 tiramisu/api.py:1147
|
||||
#: tiramisu/api.py:704 tiramisu/api.py:1178
|
||||
msgid "unknown group_type: {0}"
|
||||
msgstr "group_type inconnu: {0}"
|
||||
|
||||
#: tiramisu/api.py:974
|
||||
#: tiramisu/api.py:753 tiramisu/api.py:1208
|
||||
msgid "please use .dict() before .updates()"
|
||||
msgstr "faire .dico() avant .updates()"
|
||||
|
||||
#: tiramisu/api.py:1000
|
||||
msgid "properties must be a set"
|
||||
msgstr "une propriété doit être de type set"
|
||||
|
||||
#: tiramisu/api.py:980 tiramisu/api.py:1002
|
||||
#: tiramisu/api.py:1006 tiramisu/api.py:1028
|
||||
msgid "unknown when {} (must be in append or remove)"
|
||||
msgstr "value {} inconsistent (doit être append ou remove)"
|
||||
|
||||
#: tiramisu/api.py:992 tiramisu/api.py:1014 tiramisu/config.py:1227
|
||||
#: tiramisu/api.py:1018 tiramisu/api.py:1040 tiramisu/config.py:1249
|
||||
msgid "unknown type {}"
|
||||
msgstr "type inconnu {}"
|
||||
|
||||
@ -191,9 +195,9 @@ msgstr "le nom d'un config doit être unique dans un groupconfig pour \"{0}\""
|
||||
msgid "unknown config \"{}\""
|
||||
msgstr "config \"{}\" inconnue"
|
||||
|
||||
#: tiramisu/config.py:987 tiramisu/config.py:1202
|
||||
#: tiramisu/config.py:987 tiramisu/config.py:1224
|
||||
msgid "{}config's children should be config, not {}"
|
||||
msgstr "enfants d'un {}config doit être une config, pas {0}"
|
||||
msgstr "enfants d'un {}config doit être une config, pas {}"
|
||||
|
||||
#: tiramisu/config.py:992
|
||||
msgid "child must be a Config, MixConfig or MetaConfig"
|
||||
@ -216,27 +220,38 @@ msgid "force_default and force_dont_change_value cannot be set together"
|
||||
msgstr ""
|
||||
"force_default et force_dont_change_value ne peuvent pas être mis ensemble"
|
||||
|
||||
#: tiramisu/config.py:1189
|
||||
#: tiramisu/config.py:1176
|
||||
msgid "config is already in a metaconfig"
|
||||
msgstr "la config est déjà dans une metaconfig"
|
||||
|
||||
#: tiramisu/config.py:1178 tiramisu/config.py:1247
|
||||
msgid "config name must be uniq in groupconfig for {0}"
|
||||
msgstr "le nom de la config doit être unique dans un groupconfig pour {0}"
|
||||
|
||||
#: tiramisu/config.py:1192
|
||||
msgid "cannot find the config {}"
|
||||
msgstr "ne peut pas trouver la config {0}"
|
||||
|
||||
#: tiramisu/config.py:1211
|
||||
msgid "MetaConfig with optiondescription must have string has child, not {}"
|
||||
msgstr ""
|
||||
"MetaConfig avec une optiondescription doit avoir un nom comme enfant, pas {}"
|
||||
|
||||
#: tiramisu/config.py:1208
|
||||
#: tiramisu/config.py:1230
|
||||
msgid "child must be a Config or MetaConfig"
|
||||
msgstr "enfant doit être une une Config ou une MetaConfig"
|
||||
|
||||
#: tiramisu/config.py:1212
|
||||
#: tiramisu/config.py:1234
|
||||
msgid "all config in metaconfig must have the same optiondescription"
|
||||
msgstr ""
|
||||
"toutes les configs d'une metaconfig doivent avoir la même optiondescription"
|
||||
|
||||
#: tiramisu/config.py:1225
|
||||
msgid "config name must be uniq in groupconfig for {0}"
|
||||
msgstr "le nom de la config doit être unique dans un groupconfig pour {0}"
|
||||
|
||||
#: tiramisu/config.py:1250
|
||||
msgid "cannot find the config {}"
|
||||
msgstr "ne peut pas trouver la config {0}"
|
||||
#: tiramisu/config.py:1272
|
||||
#, fuzzy
|
||||
#| msgid "all config in metaconfig must have the same optiondescription"
|
||||
msgid "metaconfig must have the same optiondescription"
|
||||
msgstr ""
|
||||
"toutes les configs d'une metaconfig doivent avoir la même optiondescription"
|
||||
|
||||
#: tiramisu/error.py:24
|
||||
msgid "and"
|
||||
@ -250,11 +265,11 @@ msgstr "ou"
|
||||
msgid " {} "
|
||||
msgstr " {} "
|
||||
|
||||
#: tiramisu/error.py:103 tiramisu/setting.py:563
|
||||
#: tiramisu/error.py:103 tiramisu/setting.py:579
|
||||
msgid "property"
|
||||
msgstr "de la propriété"
|
||||
|
||||
#: tiramisu/error.py:105 tiramisu/setting.py:565
|
||||
#: tiramisu/error.py:105 tiramisu/setting.py:581
|
||||
msgid "properties"
|
||||
msgstr "des propriétés"
|
||||
|
||||
@ -266,38 +281,42 @@ msgstr "ne peut accéder à {0} \"{1}\" parce que \"{2}\" a {3} {4}"
|
||||
msgid "cannot access to {0} \"{1}\" because has {2} {3}"
|
||||
msgstr "ne peut accéder à l'{0} \"{1}\" a cause {2} {3}"
|
||||
|
||||
#: tiramisu/error.py:185
|
||||
#: tiramisu/error.py:189
|
||||
msgid "invalid value"
|
||||
msgstr "valeur invalide"
|
||||
|
||||
#: tiramisu/error.py:190
|
||||
#: tiramisu/error.py:194
|
||||
msgid "attention, \"{0}\" could be an invalid {1} for \"{2}\""
|
||||
msgstr "attention, \"{0}\" peut être un {1} invalide pour \"{2}\""
|
||||
|
||||
#: tiramisu/error.py:194 tiramisu/error.py:198
|
||||
#: tiramisu/error.py:198 tiramisu/error.py:202
|
||||
msgid "\"{0}\" is an invalid {1} for \"{2}\""
|
||||
msgstr "\"{0}\" est une valeur invalide pour l'option \"{2}\" de type {1}"
|
||||
|
||||
#: tiramisu/function.py:31
|
||||
#: tiramisu/function.py:34
|
||||
msgid "args in params must be a tuple"
|
||||
msgstr "args dans params doit être un tuple"
|
||||
|
||||
#: tiramisu/function.py:34 tiramisu/function.py:39
|
||||
#: tiramisu/function.py:37 tiramisu/function.py:42
|
||||
msgid "arg in params must be a Param"
|
||||
msgstr "arg dans params doit être un Param"
|
||||
|
||||
#: tiramisu/function.py:36
|
||||
#: tiramisu/function.py:39
|
||||
msgid "kwargs in params must be a dict"
|
||||
msgstr "kwargs dans params doit être un dict"
|
||||
|
||||
#: tiramisu/function.py:52
|
||||
#: tiramisu/function.py:58
|
||||
msgid "paramoption needs an option not {}"
|
||||
msgstr "paramoption doit être une option pas {0}"
|
||||
|
||||
#: tiramisu/function.py:58
|
||||
#: tiramisu/function.py:64
|
||||
msgid "param must have a boolean not a {} for notraisepropertyerror"
|
||||
msgstr "param doit avoir un booléan pas un {} pour notraisepropertyerror"
|
||||
|
||||
#: tiramisu/function.py:271
|
||||
msgid "unexpected {} condition_operator in calc_value"
|
||||
msgstr "condition_operator {} inattendue dans la fonction calc_value"
|
||||
|
||||
#: tiramisu/option/baseoption.py:75 tiramisu/option/symlinkoption.py:33
|
||||
msgid "\"{0}\" is an invalid name for an option"
|
||||
msgstr "\"{0}\" est un nom invalide pour une option"
|
||||
@ -328,7 +347,7 @@ msgstr ""
|
||||
msgid "missing those arguments \"{}\" in function \"{}\" for \"{}\""
|
||||
msgstr "les arguments \"{}\" sont manquant dans la fonction \"{}\" pour \"{}\""
|
||||
|
||||
#: tiramisu/option/baseoption.py:257
|
||||
#: tiramisu/option/baseoption.py:258
|
||||
msgid ""
|
||||
"params defined for a callback function but no callback defined yet for "
|
||||
"option \"{0}\""
|
||||
@ -336,28 +355,28 @@ msgstr ""
|
||||
"paramètres définis pour la fonction de callback mais aucun callback défini "
|
||||
"pour l'option \"{0}\""
|
||||
|
||||
#: tiramisu/option/baseoption.py:349 tiramisu/storage/dictionary/value.py:275
|
||||
#: tiramisu/option/baseoption.py:350 tiramisu/storage/dictionary/value.py:275
|
||||
#: tiramisu/storage/sqlite3/value.py:201
|
||||
msgid "information's item not found: {0}"
|
||||
msgstr "item '{0}' dans les informations non trouvée"
|
||||
|
||||
#: tiramisu/option/baseoption.py:362
|
||||
#: tiramisu/option/baseoption.py:363
|
||||
msgid "'{0}' ({1}) object attribute '{2}' is read-only"
|
||||
msgstr "l'attribut {2} de l'objet '{0}' ({1}) est en lecture seule"
|
||||
|
||||
#: tiramisu/option/baseoption.py:393
|
||||
#: tiramisu/option/baseoption.py:394
|
||||
msgid "\"{}\" ({}) object attribute \"{}\" is read-only"
|
||||
msgstr "\"{}\" ({}) l'attribut de l'objet \"{}\" est en lecture seule"
|
||||
|
||||
#: tiramisu/option/baseoption.py:403
|
||||
#: tiramisu/option/baseoption.py:404
|
||||
msgid "\"{}\" not part of any Config"
|
||||
msgstr "\"{}\" ne fait pas parti d'une Config"
|
||||
|
||||
#: tiramisu/option/baseoption.py:450
|
||||
#: tiramisu/option/baseoption.py:453
|
||||
msgid "malformed requirements must be an option in option {0}"
|
||||
msgstr "requirements mal formés doit être une option dans l'option {0}"
|
||||
|
||||
#: tiramisu/option/baseoption.py:453
|
||||
#: tiramisu/option/baseoption.py:456
|
||||
msgid ""
|
||||
"malformed requirements multi option must not set as requires of non multi "
|
||||
"option {0}"
|
||||
@ -365,59 +384,59 @@ msgstr ""
|
||||
"requirements mal formés une option multiple ne doit pas être spécifié comme "
|
||||
"pré-requis à l'option non multiple {0}"
|
||||
|
||||
#: tiramisu/option/baseoption.py:486
|
||||
#: tiramisu/option/baseoption.py:495
|
||||
msgid ""
|
||||
"malformed requirements expected must have option and value for option {0}"
|
||||
msgstr ""
|
||||
"expected mal formés pour le requirements, doit avoir une option et une "
|
||||
"valeur pour l'option {0}"
|
||||
|
||||
#: tiramisu/option/baseoption.py:493 tiramisu/option/baseoption.py:509
|
||||
#: tiramisu/option/baseoption.py:502 tiramisu/option/baseoption.py:518
|
||||
msgid "malformed requirements expected value must be valid for option {0}: {1}"
|
||||
msgstr ""
|
||||
"valeur de \"expected\" malformé, doit être valide pour l'option {0} : {1}"
|
||||
|
||||
#: tiramisu/option/baseoption.py:523
|
||||
#: tiramisu/option/baseoption.py:532
|
||||
msgid ""
|
||||
"malformed requirements for option: {0} action cannot be force_store_value"
|
||||
msgstr ""
|
||||
"requirements mal formés pour l'option : {0} action ne peut pas être "
|
||||
"force_store_value"
|
||||
|
||||
#: tiramisu/option/baseoption.py:531
|
||||
#: tiramisu/option/baseoption.py:540
|
||||
msgid "malformed requirements for option: {0} inverse must be boolean"
|
||||
msgstr ""
|
||||
"requirements mal formés pour l'option : {0} inverse doit être un booléen"
|
||||
|
||||
#: tiramisu/option/baseoption.py:538
|
||||
#: tiramisu/option/baseoption.py:547
|
||||
msgid "malformed requirements for option: {0} transitive must be boolean"
|
||||
msgstr ""
|
||||
"requirements mal formés pour l'option : {0} transitive doit être booléen"
|
||||
|
||||
#: tiramisu/option/baseoption.py:545
|
||||
#: tiramisu/option/baseoption.py:554
|
||||
msgid "malformed requirements for option: {0} same_action must be boolean"
|
||||
msgstr ""
|
||||
"requirements mal formés pour l'option : {0} same_action doit être un booléen"
|
||||
|
||||
#: tiramisu/option/baseoption.py:552
|
||||
#: tiramisu/option/baseoption.py:561
|
||||
msgid ""
|
||||
"malformed requirements for option: \"{0}\" operator must be \"or\" or \"and\""
|
||||
msgstr ""
|
||||
"requirements mal formés pour l'option : \"{0}\" l'opérateur doit être \"or\" "
|
||||
"ou \"and\""
|
||||
|
||||
#: tiramisu/option/baseoption.py:564
|
||||
#: tiramisu/option/baseoption.py:574
|
||||
msgid "malformed requirements type for option: {0}, must be a dict"
|
||||
msgstr ""
|
||||
"type requirements malformé pour l'option : {0}, doit être un dictionnaire"
|
||||
|
||||
#: tiramisu/option/baseoption.py:570
|
||||
#: tiramisu/option/baseoption.py:580
|
||||
msgid "malformed requirements for option: {0} unknown keys {1}, must only {2}"
|
||||
msgstr ""
|
||||
"requirements mal formés pour l'option : {0} clefs inconnues {1}, doit "
|
||||
"seulement avoir {2}"
|
||||
|
||||
#: tiramisu/option/baseoption.py:579
|
||||
#: tiramisu/option/baseoption.py:592
|
||||
msgid ""
|
||||
"malformed requirements for option: {0} require must have option, expected "
|
||||
"and action keys"
|
||||
@ -425,56 +444,56 @@ msgstr ""
|
||||
"requirements malformé pour l'option : {0} l'exigence doit avoir les clefs "
|
||||
"option, expected et action"
|
||||
|
||||
#: tiramisu/option/booloption.py:30
|
||||
#: tiramisu/option/booloption.py:31
|
||||
msgid "boolean"
|
||||
msgstr "booléen"
|
||||
|
||||
#: tiramisu/option/broadcastoption.py:31
|
||||
#: tiramisu/option/broadcastoption.py:32
|
||||
msgid "broadcast address"
|
||||
msgstr "adresse broadcast"
|
||||
|
||||
#: tiramisu/option/broadcastoption.py:38 tiramisu/option/dateoption.py:37
|
||||
#: tiramisu/option/domainnameoption.py:113 tiramisu/option/ipoption.py:77
|
||||
#: tiramisu/option/netmaskoption.py:41 tiramisu/option/networkoption.py:67
|
||||
#: tiramisu/option/passwordoption.py:38 tiramisu/option/portoption.py:106
|
||||
#: tiramisu/option/urloption.py:40
|
||||
#: tiramisu/option/broadcastoption.py:39 tiramisu/option/dateoption.py:38
|
||||
#: tiramisu/option/domainnameoption.py:118 tiramisu/option/ipoption.py:83
|
||||
#: tiramisu/option/netmaskoption.py:42 tiramisu/option/networkoption.py:68
|
||||
#: tiramisu/option/passwordoption.py:39 tiramisu/option/portoption.py:107
|
||||
#: tiramisu/option/urloption.py:41
|
||||
msgid "invalid string"
|
||||
msgstr "invalide caractère"
|
||||
|
||||
#: tiramisu/option/broadcastoption.py:56
|
||||
#: tiramisu/option/broadcastoption.py:57
|
||||
msgid "invalid len for vals"
|
||||
msgstr "longueur invalide pour vals"
|
||||
|
||||
#: tiramisu/option/broadcastoption.py:61
|
||||
#: tiramisu/option/broadcastoption.py:62
|
||||
msgid "broadcast \"{4}\" invalid with network {0}/{1} (\"{2}\"/\"{3}\")"
|
||||
msgstr ""
|
||||
"le broadcast \"{4}\" est invalide pour le réseau {0}/{1} (\"{2}\"/\"{3}\")"
|
||||
|
||||
#: tiramisu/option/choiceoption.py:36
|
||||
#: tiramisu/option/choiceoption.py:37
|
||||
msgid "choice"
|
||||
msgstr "choix"
|
||||
|
||||
#: tiramisu/option/choiceoption.py:65
|
||||
#: tiramisu/option/choiceoption.py:66
|
||||
msgid "values is not a function, so values_params must be None"
|
||||
msgstr "values n'est pas une fonction, donc values_params doit être None"
|
||||
|
||||
#: tiramisu/option/choiceoption.py:67
|
||||
#: tiramisu/option/choiceoption.py:68
|
||||
msgid "values must be a tuple or a function for {0}"
|
||||
msgstr "values doit être un tuple ou une fonction pour {0}"
|
||||
|
||||
#: tiramisu/option/choiceoption.py:100
|
||||
#: tiramisu/option/choiceoption.py:101
|
||||
msgid "calculated values for {0} is not a list"
|
||||
msgstr "valeurs calculées for {0} n'est pas une liste"
|
||||
|
||||
#: tiramisu/option/choiceoption.py:113
|
||||
#: tiramisu/option/choiceoption.py:114
|
||||
msgid "only \"{0}\" is allowed"
|
||||
msgstr "seul \"{0}\" est autorisé"
|
||||
|
||||
#: tiramisu/option/choiceoption.py:116
|
||||
#: tiramisu/option/choiceoption.py:117
|
||||
msgid "only \"{0}\" are allowed"
|
||||
msgstr "seul \"{0}\" sont autorisés"
|
||||
|
||||
#: tiramisu/option/dateoption.py:30
|
||||
#: tiramisu/option/dateoption.py:31
|
||||
msgid "date"
|
||||
msgstr "date"
|
||||
|
||||
@ -482,43 +501,43 @@ msgstr "date"
|
||||
msgid "domain name"
|
||||
msgstr "nom de domaine"
|
||||
|
||||
#: tiramisu/option/domainnameoption.py:58
|
||||
#: tiramisu/option/domainnameoption.py:59
|
||||
msgid "unknown type_ {0} for hostname"
|
||||
msgstr "type_ inconnu {0} pour le nom d'hôte"
|
||||
|
||||
#: tiramisu/option/domainnameoption.py:61
|
||||
#: tiramisu/option/domainnameoption.py:62
|
||||
msgid "allow_ip must be a boolean"
|
||||
msgstr "allow_ip doit être un booléen"
|
||||
|
||||
#: tiramisu/option/domainnameoption.py:63
|
||||
#: tiramisu/option/domainnameoption.py:64
|
||||
msgid "allow_without_dot must be a boolean"
|
||||
msgstr "allow_without_dot doit être un booléen"
|
||||
|
||||
#: tiramisu/option/domainnameoption.py:107
|
||||
#: tiramisu/option/domainnameoption.py:112
|
||||
msgid "invalid length (min 1)"
|
||||
msgstr "longueur invalide (min 1)"
|
||||
|
||||
#: tiramisu/option/domainnameoption.py:109
|
||||
#: tiramisu/option/domainnameoption.py:114
|
||||
msgid "invalid length (max {0})"
|
||||
msgstr "longueur invalide (max {0})"
|
||||
|
||||
#: tiramisu/option/domainnameoption.py:121
|
||||
#: tiramisu/option/domainnameoption.py:125
|
||||
msgid "must not be an IP"
|
||||
msgstr "ne doit pas être une IP"
|
||||
|
||||
#: tiramisu/option/domainnameoption.py:125
|
||||
#: tiramisu/option/domainnameoption.py:131
|
||||
msgid "must have dot"
|
||||
msgstr "doit avec un point"
|
||||
|
||||
#: tiramisu/option/domainnameoption.py:127
|
||||
#: tiramisu/option/domainnameoption.py:133
|
||||
msgid "invalid length (max 255)"
|
||||
msgstr "longueur invalide (max 255)"
|
||||
|
||||
#: tiramisu/option/domainnameoption.py:135
|
||||
#: tiramisu/option/domainnameoption.py:141
|
||||
msgid "some characters are uppercase"
|
||||
msgstr "des caractères sont en majuscule"
|
||||
|
||||
#: tiramisu/option/domainnameoption.py:138
|
||||
#: tiramisu/option/domainnameoption.py:144
|
||||
msgid "some characters may cause problems"
|
||||
msgstr "des caractères peuvent poser problèmes"
|
||||
|
||||
@ -550,63 +569,63 @@ msgstr ""
|
||||
"le callback de DynOptionDescription retourne une list avec plusieurs valeurs "
|
||||
"\"{}\""
|
||||
|
||||
#: tiramisu/option/emailoption.py:31
|
||||
#: tiramisu/option/emailoption.py:32
|
||||
msgid "email address"
|
||||
msgstr "adresse mail"
|
||||
|
||||
#: tiramisu/option/filenameoption.py:30
|
||||
#: tiramisu/option/filenameoption.py:31
|
||||
msgid "file name"
|
||||
msgstr "nom de fichier"
|
||||
|
||||
#: tiramisu/option/floatoption.py:30
|
||||
#: tiramisu/option/floatoption.py:31
|
||||
msgid "float"
|
||||
msgstr "nombre flottant"
|
||||
|
||||
#: tiramisu/option/intoption.py:30
|
||||
#: tiramisu/option/intoption.py:31
|
||||
msgid "integer"
|
||||
msgstr "nombre"
|
||||
|
||||
#: tiramisu/option/intoption.py:54
|
||||
#: tiramisu/option/intoption.py:55
|
||||
msgid "value must be greater than \"{0}\""
|
||||
msgstr "valeur doit être supérieur à {0}"
|
||||
|
||||
#: tiramisu/option/intoption.py:57
|
||||
#: tiramisu/option/intoption.py:58
|
||||
msgid "value must be less than \"{0}\""
|
||||
msgstr "valeur doit être inférieur à \"{0}\""
|
||||
|
||||
#: tiramisu/option/ipoption.py:35
|
||||
#: tiramisu/option/ipoption.py:36
|
||||
msgid "IP"
|
||||
msgstr "IP"
|
||||
|
||||
#: tiramisu/option/ipoption.py:83 tiramisu/option/networkoption.py:73
|
||||
#: tiramisu/option/ipoption.py:89 tiramisu/option/networkoption.py:74
|
||||
msgid "must use CIDR notation"
|
||||
msgstr "doit utiliser la notation CIDR"
|
||||
|
||||
#: tiramisu/option/ipoption.py:105
|
||||
#: tiramisu/option/ipoption.py:111
|
||||
msgid "shouldn't be reserved IP"
|
||||
msgstr "ne devrait pas être une IP réservée"
|
||||
|
||||
#: tiramisu/option/ipoption.py:107
|
||||
#: tiramisu/option/ipoption.py:113
|
||||
msgid "mustn't be reserved IP"
|
||||
msgstr "ne doit pas être une IP réservée"
|
||||
|
||||
#: tiramisu/option/ipoption.py:111
|
||||
#: tiramisu/option/ipoption.py:117
|
||||
msgid "should be private IP"
|
||||
msgstr "devrait être une IP privée"
|
||||
|
||||
#: tiramisu/option/ipoption.py:113
|
||||
#: tiramisu/option/ipoption.py:119
|
||||
msgid "must be private IP"
|
||||
msgstr "doit être une IP privée"
|
||||
|
||||
#: tiramisu/option/ipoption.py:141
|
||||
#: tiramisu/option/ipoption.py:147
|
||||
msgid "\"{0}\" is not in network \"{1}\" (\"{2}\")"
|
||||
msgstr "\"{0}\" n'est pas dans le réseau \"{1}\" (\"{2}\")"
|
||||
|
||||
#: tiramisu/option/ipoption.py:157
|
||||
#: tiramisu/option/ipoption.py:163
|
||||
msgid "ip_network needs an IP, a network and a netmask"
|
||||
msgstr "ip_network nécessite une IP, un réseau et un masque de réseau"
|
||||
|
||||
#: tiramisu/option/ipoption.py:163
|
||||
#: tiramisu/option/ipoption.py:169
|
||||
msgid "\"{4}\" is not in network \"{0}\"/\"{1}\" (\"{2}\"/\"{3}\")"
|
||||
msgstr "\"{4}\" n'est pas dans le réseau \"{0}\"/\"{1}\" (\"{2}\"/\"{3}\")"
|
||||
|
||||
@ -657,51 +676,51 @@ msgstr ""
|
||||
"requirement mal formé pour l'option \"{0}\" ne doit pas être dans une "
|
||||
"suiveuse pour \"{1}\""
|
||||
|
||||
#: tiramisu/option/netmaskoption.py:34
|
||||
#: tiramisu/option/netmaskoption.py:35
|
||||
msgid "netmask address"
|
||||
msgstr "adresse netmask"
|
||||
|
||||
#: tiramisu/option/netmaskoption.py:59
|
||||
#: tiramisu/option/netmaskoption.py:60
|
||||
msgid "network_netmask needs a network and a netmask"
|
||||
msgstr "network_netmask nécessite un réseau et un masque de réseau"
|
||||
|
||||
#: tiramisu/option/netmaskoption.py:68
|
||||
#: tiramisu/option/netmaskoption.py:69
|
||||
msgid "with netmask \"{0}\" (\"{1}\")"
|
||||
msgstr "avec le masque \"{0}\" (\"{1}\")"
|
||||
|
||||
#: tiramisu/option/netmaskoption.py:71
|
||||
#: tiramisu/option/netmaskoption.py:72
|
||||
msgid "with network \"{0}\" (\"{1}\")"
|
||||
msgstr "avec le réseau \"{0}\" (\"{1}\")"
|
||||
|
||||
#: tiramisu/option/netmaskoption.py:82
|
||||
#: tiramisu/option/netmaskoption.py:83
|
||||
msgid "ip_netmask needs an IP and a netmask"
|
||||
msgstr "ip_netmask nécessite une IP et un masque de réseau"
|
||||
|
||||
#: tiramisu/option/netmaskoption.py:90
|
||||
#: tiramisu/option/netmaskoption.py:91
|
||||
msgid "this is a network with netmask \"{0}\" (\"{1}\")"
|
||||
msgstr "c'est une adresse réseau avec le masque \"{0}\" (\"{1}\")"
|
||||
|
||||
#: tiramisu/option/netmaskoption.py:94
|
||||
#: tiramisu/option/netmaskoption.py:95
|
||||
msgid "this is a broadcast with netmask \"{0}\" (\"{1}\")"
|
||||
msgstr "c'est une adresse broadcast avec le masque \"{0}\" (\"{1}\")"
|
||||
|
||||
#: tiramisu/option/netmaskoption.py:99
|
||||
#: tiramisu/option/netmaskoption.py:100
|
||||
msgid "IP \"{0}\" (\"{1}\") is the network"
|
||||
msgstr "IP \"{0}\" (\"{1}\") est le réseau"
|
||||
|
||||
#: tiramisu/option/netmaskoption.py:103
|
||||
#: tiramisu/option/netmaskoption.py:104
|
||||
msgid "IP \"{0}\" (\"{1}\") is the broadcast"
|
||||
msgstr "IP \"{0}\" (\"{1}\") est l'adresse de broadcast"
|
||||
|
||||
#: tiramisu/option/networkoption.py:31
|
||||
#: tiramisu/option/networkoption.py:32
|
||||
msgid "network address"
|
||||
msgstr "adresse réseau"
|
||||
|
||||
#: tiramisu/option/networkoption.py:90
|
||||
#: tiramisu/option/networkoption.py:91
|
||||
msgid "shouldn't be reserved network"
|
||||
msgstr "ne devrait pas être une IP réservée"
|
||||
|
||||
#: tiramisu/option/networkoption.py:92
|
||||
#: tiramisu/option/networkoption.py:93
|
||||
msgid "mustn't be reserved network"
|
||||
msgstr "ne doit pas être une IP réservée"
|
||||
|
||||
@ -734,89 +753,89 @@ msgstr ""
|
||||
"la valeur de la default_multi \"{0}\" est invalide pour l'option \"{1}\", "
|
||||
"doit être une liste pour une submulti"
|
||||
|
||||
#: tiramisu/option/option.py:255
|
||||
#: tiramisu/option/option.py:259
|
||||
msgid "invalid value \"{}\", this value is already in \"{}\""
|
||||
msgstr "valeur invalide \"{}\", cette valeur est déjà dans \"{}\""
|
||||
|
||||
#: tiramisu/option/option.py:285
|
||||
#: tiramisu/option/option.py:289
|
||||
msgid "which must not be a list"
|
||||
msgstr "qui ne doit pas être une liste"
|
||||
|
||||
#: tiramisu/option/option.py:319 tiramisu/option/option.py:328
|
||||
#: tiramisu/option/option.py:323 tiramisu/option/option.py:332
|
||||
msgid "which must be a list"
|
||||
msgstr "qui doit être une liste"
|
||||
|
||||
#: tiramisu/option/option.py:333
|
||||
#: tiramisu/option/option.py:337
|
||||
msgid "which \"{}\" must be a list of list"
|
||||
msgstr "lequel \"{}\" doit être une liste de liste"
|
||||
|
||||
#: tiramisu/option/option.py:375
|
||||
#: tiramisu/option/option.py:379
|
||||
msgid "default value not allowed if option \"{0}\" is calculated"
|
||||
msgstr ""
|
||||
"la valeur par défaut n'est pas possible si l'option \"{0}\" est calculée"
|
||||
|
||||
#: tiramisu/option/option.py:423
|
||||
#: tiramisu/option/option.py:427
|
||||
msgid "'{0}' ({1}) cannot add consistency, option is read-only"
|
||||
msgstr ""
|
||||
"'{0}' ({1}) ne peut ajouter de consistency, l'option est en lecture seul"
|
||||
|
||||
#: tiramisu/option/option.py:431
|
||||
#: tiramisu/option/option.py:435
|
||||
msgid "consistency {0} not available for this option"
|
||||
msgstr "consistency {0} non valable pour cette option"
|
||||
|
||||
#: tiramisu/option/option.py:438
|
||||
#: tiramisu/option/option.py:442
|
||||
msgid "unknown parameter {0} in consistency"
|
||||
msgstr "paramètre inconnu {0} dans un test de consistance"
|
||||
|
||||
#: tiramisu/option/option.py:550 tiramisu/option/option.py:555
|
||||
#: tiramisu/option/option.py:554 tiramisu/option/option.py:559
|
||||
msgid "cannot add consistency with submulti option"
|
||||
msgstr "ne peut ajouter de test de consistence a une option submulti"
|
||||
|
||||
#: tiramisu/option/option.py:556
|
||||
#: tiramisu/option/option.py:560
|
||||
msgid "consistency must be set with an option, not {}"
|
||||
msgstr ""
|
||||
"test de consistence doit être renseigné avec une option, et non avec {}"
|
||||
|
||||
#: tiramisu/option/option.py:559 tiramisu/option/option.py:567
|
||||
#: tiramisu/option/option.py:563 tiramisu/option/option.py:571
|
||||
msgid ""
|
||||
"almost one option in consistency is in a dynoptiondescription but not all"
|
||||
msgstr ""
|
||||
"au moins une option dans le test de consistance est dans une "
|
||||
"dynoptiondescription mais pas toutes"
|
||||
|
||||
#: tiramisu/option/option.py:563
|
||||
#: tiramisu/option/option.py:567
|
||||
msgid "option in consistency must be in same dynoptiondescription"
|
||||
msgstr ""
|
||||
"option dans une consistency doit être dans le même dynoptiondescription"
|
||||
|
||||
#: tiramisu/option/option.py:570
|
||||
#: tiramisu/option/option.py:574
|
||||
msgid "cannot add consistency with itself"
|
||||
msgstr "ne peut ajouter une consistency avec lui même"
|
||||
|
||||
#: tiramisu/option/option.py:572
|
||||
#: tiramisu/option/option.py:576
|
||||
msgid "every options in consistency must be multi or none"
|
||||
msgstr ""
|
||||
"toutes les options d'une consistency doivent être multi ou ne pas l'être"
|
||||
|
||||
#: tiramisu/option/option.py:612
|
||||
#: tiramisu/option/option.py:616
|
||||
msgid "unexpected length of \"{}\" in constency \"{}\", should be \"{}\""
|
||||
msgstr ""
|
||||
"longueur inconsistante pour \"{}\" dans le test de consistence \"{}\", "
|
||||
"devrait être \"{}\""
|
||||
|
||||
#: tiramisu/option/option.py:712
|
||||
#: tiramisu/option/option.py:716
|
||||
msgid "should be different from the value of \"{}\""
|
||||
msgstr "devrait être différent de la valeur de \"{}\""
|
||||
|
||||
#: tiramisu/option/option.py:714
|
||||
#: tiramisu/option/option.py:718
|
||||
msgid "must be different from the value of \"{}\""
|
||||
msgstr "doit être différent de la valeur de \"{}\""
|
||||
|
||||
#: tiramisu/option/option.py:717
|
||||
#: tiramisu/option/option.py:721
|
||||
msgid "value for {} should be different"
|
||||
msgstr "valeur pour {} devrait être différent"
|
||||
|
||||
#: tiramisu/option/option.py:719
|
||||
#: tiramisu/option/option.py:723
|
||||
msgid "value for {} must be different"
|
||||
msgstr "valeur pour {} doit être différent"
|
||||
|
||||
@ -835,7 +854,7 @@ msgstr ""
|
||||
msgid "the dynoption \"{0}\" cannot have \"force_store_value\" property"
|
||||
msgstr "la dynoption \"{0}\" ne peut avoir la propriété \"force_store_value\""
|
||||
|
||||
#: tiramisu/option/optiondescription.py:97 tiramisu/setting.py:643
|
||||
#: tiramisu/option/optiondescription.py:97 tiramisu/setting.py:665
|
||||
msgid ""
|
||||
"a leader ({0}) cannot have \"force_default_on_freeze\" or "
|
||||
"\"force_metaconfig_on_freeze\" property without \"frozen\""
|
||||
@ -910,35 +929,35 @@ msgstr "ne peut changer group_type si déjà spécifié (ancien {0}, nouveau {1}
|
||||
msgid "group_type: {0} not allowed"
|
||||
msgstr "group_type : {0} non autorisé"
|
||||
|
||||
#: tiramisu/option/passwordoption.py:31
|
||||
#: tiramisu/option/passwordoption.py:32
|
||||
msgid "password"
|
||||
msgstr "mot de passe"
|
||||
|
||||
#: tiramisu/option/portoption.py:43
|
||||
#: tiramisu/option/portoption.py:44
|
||||
msgid "port"
|
||||
msgstr "port"
|
||||
|
||||
#: tiramisu/option/portoption.py:80
|
||||
#: tiramisu/option/portoption.py:81
|
||||
msgid "inconsistency in allowed range"
|
||||
msgstr "inconsistence dans la plage autorisée"
|
||||
|
||||
#: tiramisu/option/portoption.py:85
|
||||
#: tiramisu/option/portoption.py:86
|
||||
msgid "max value is empty"
|
||||
msgstr "la valeur maximum est vide"
|
||||
|
||||
#: tiramisu/option/portoption.py:110
|
||||
#: tiramisu/option/portoption.py:111
|
||||
msgid "range must have two values only"
|
||||
msgstr "un rang doit avoir deux valeurs seulement"
|
||||
|
||||
#: tiramisu/option/portoption.py:112
|
||||
#: tiramisu/option/portoption.py:113
|
||||
msgid "first port in range must be smaller than the second one"
|
||||
msgstr "le premier port d'un rang doit être plus petit que le second"
|
||||
|
||||
#: tiramisu/option/portoption.py:122
|
||||
#: tiramisu/option/portoption.py:123
|
||||
msgid "must be an integer between {0} and {1}"
|
||||
msgstr "doit être une nombre entre {0} et {1}"
|
||||
|
||||
#: tiramisu/option/stroption.py:32
|
||||
#: tiramisu/option/stroption.py:33
|
||||
msgid "string"
|
||||
msgstr "texte"
|
||||
|
||||
@ -950,23 +969,23 @@ msgstr "symlinkoption mal formé, doit être une option pour symlink {0}"
|
||||
msgid "unknown option \"{0}\" in syndynoptiondescription \"{1}\""
|
||||
msgstr "l'option \"{0}\" inconnue dans la syndynoptiondescription \"{1}\""
|
||||
|
||||
#: tiramisu/option/urloption.py:33
|
||||
#: tiramisu/option/urloption.py:34
|
||||
msgid "URL"
|
||||
msgstr "URL"
|
||||
|
||||
#: tiramisu/option/urloption.py:43
|
||||
#: tiramisu/option/urloption.py:44
|
||||
msgid "must start with http:// or https://"
|
||||
msgstr "doit débuter par http:// ou https://"
|
||||
|
||||
#: tiramisu/option/urloption.py:61
|
||||
#: tiramisu/option/urloption.py:62
|
||||
msgid "port must be an between 0 and 65536"
|
||||
msgstr "port doit être entre 0 et 65536"
|
||||
|
||||
#: tiramisu/option/urloption.py:70
|
||||
#: tiramisu/option/urloption.py:71
|
||||
msgid "must ends with a valid resource name"
|
||||
msgstr "doit finir par un nom de ressource valide"
|
||||
|
||||
#: tiramisu/option/usernameoption.py:31
|
||||
#: tiramisu/option/usernameoption.py:32
|
||||
msgid "username"
|
||||
msgstr "nom d'utilisateur"
|
||||
|
||||
@ -978,7 +997,7 @@ msgstr "ne peut redéfinir ({0})"
|
||||
msgid "can't unbind {0}"
|
||||
msgstr "ne peut supprimer ({0})"
|
||||
|
||||
#: tiramisu/setting.py:518
|
||||
#: tiramisu/setting.py:519
|
||||
msgid ""
|
||||
"malformed requirements imbrication detected for option: '{0}' with "
|
||||
"requirement on: '{1}'"
|
||||
@ -986,48 +1005,56 @@ msgstr ""
|
||||
"imbrication de requirements mal formés detectée pour l'option : '{0}' avec "
|
||||
"requirement sur : '{1}'"
|
||||
|
||||
#: tiramisu/setting.py:566
|
||||
#: tiramisu/setting.py:582
|
||||
msgid ""
|
||||
"cannot access to option \"{0}\" because required option \"{1}\" has {2} {3}"
|
||||
msgstr ""
|
||||
"ne peut accéder à l'option \"{0}\" parce que l'option requise \"{1}\" a {2} "
|
||||
"{3}"
|
||||
|
||||
#: tiramisu/setting.py:590
|
||||
#: tiramisu/setting.py:608
|
||||
msgid "the calculated value is {0}"
|
||||
msgstr "valeurs calculées est {0}"
|
||||
|
||||
#: tiramisu/setting.py:610
|
||||
msgid "the calculated value is not {0}"
|
||||
msgstr "valeurs calculées n'est pas {0}"
|
||||
|
||||
#: tiramisu/setting.py:614
|
||||
msgid "the value of \"{0}\" is {1}"
|
||||
msgstr "la valeur de \"{0}\" est {1}"
|
||||
|
||||
#: tiramisu/setting.py:592
|
||||
#: tiramisu/setting.py:616
|
||||
msgid "the value of \"{0}\" is not {1}"
|
||||
msgstr "la valeur de \"{0}\" n'est pas {1}"
|
||||
|
||||
#: tiramisu/setting.py:633
|
||||
#: tiramisu/setting.py:655
|
||||
msgid "cannot set property {} for option \"{}\" this property is calculated"
|
||||
msgstr ""
|
||||
"ne peut ajouter la propriété {} pour l'option \"{}\" cette propriété est "
|
||||
"calculée"
|
||||
|
||||
#: tiramisu/setting.py:638
|
||||
#: tiramisu/setting.py:660
|
||||
msgid "can't assign property to the symlinkoption \"{}\""
|
||||
msgstr "ne peut assigner une propriété à une symlinkoption \"{}\""
|
||||
|
||||
#: tiramisu/setting.py:670
|
||||
#: tiramisu/setting.py:692
|
||||
msgid "permissive must be a frozenset"
|
||||
msgstr "une permissive doit être de type frozenset"
|
||||
|
||||
#: tiramisu/setting.py:674
|
||||
#: tiramisu/setting.py:696
|
||||
msgid "can't assign permissive to the symlinkoption \"{}\""
|
||||
msgstr "ne peut assigner une permissive à la symlinkoption \"{}\""
|
||||
|
||||
#: tiramisu/setting.py:681
|
||||
#: tiramisu/setting.py:703
|
||||
msgid "cannot add those permissives: {0}"
|
||||
msgstr "ne peut ajouter ces permissives : {0}"
|
||||
|
||||
#: tiramisu/setting.py:698
|
||||
#: tiramisu/setting.py:720
|
||||
msgid "can't reset properties to the symlinkoption \"{}\""
|
||||
msgstr "ne peut réinitialiser les propriétés de la symlinkoption \"{}\""
|
||||
|
||||
#: tiramisu/setting.py:713
|
||||
#: tiramisu/setting.py:735
|
||||
msgid "can't reset permissives to the symlinkoption \"{}\""
|
||||
msgstr "ne peut réinitialiser les permissive de la symlinkoption \"{}\""
|
||||
|
||||
@ -1061,19 +1088,45 @@ msgstr "ne peut supprimer une session non persistante"
|
||||
msgid "cannot change setting when connexion is already opened"
|
||||
msgstr "ne peut changer les paramètres quand une connexion est déjà ouverte"
|
||||
|
||||
#: tiramisu/value.py:424
|
||||
#: tiramisu/todict.py:66
|
||||
msgid "context is not supported from now for {}"
|
||||
msgstr "context n'est pas supporté maintenant pour {}"
|
||||
|
||||
#: tiramisu/todict.py:82 tiramisu/todict.py:91
|
||||
msgid "option {} only works when remotable is not \"none\""
|
||||
msgstr "l'option {} ne fonctionne que si remotable is \"none\""
|
||||
|
||||
#: tiramisu/todict.py:706 tiramisu/todict.py:839
|
||||
msgid "unknown form {}"
|
||||
msgstr "form {} inconnu"
|
||||
|
||||
#: tiramisu/todict.py:751
|
||||
msgid "not in current area"
|
||||
msgstr "n'est pas dans l'espace courant"
|
||||
|
||||
#: tiramisu/todict.py:771
|
||||
msgid "only multi option can have action \"add\", but \"{}\" is not a multi"
|
||||
msgstr ""
|
||||
"seules des options multiples peuvent avoir l'action \"add\", mais \"{}\" "
|
||||
"n'est pas une valeur multiple"
|
||||
|
||||
#: tiramisu/todict.py:773
|
||||
msgid "unknown action"
|
||||
msgstr "action inconnue"
|
||||
|
||||
#: tiramisu/value.py:427
|
||||
msgid "can't set owner for the symlinkoption \"{}\""
|
||||
msgstr "ne peut spécifier d'utilisateur à la symlinkoption \"{}\""
|
||||
|
||||
#: tiramisu/value.py:427 tiramisu/value.py:639
|
||||
#: tiramisu/value.py:430 tiramisu/value.py:642
|
||||
msgid "set owner \"{0}\" is forbidden"
|
||||
msgstr "assigner l'utilisateur \"{0}\" est interdit"
|
||||
|
||||
#: tiramisu/value.py:430
|
||||
#: tiramisu/value.py:433
|
||||
msgid "no value for {0} cannot change owner to {1}"
|
||||
msgstr "pas de valeur pour {0} ne peut changer d'utilisateur pour {1}"
|
||||
|
||||
#: tiramisu/value.py:508
|
||||
#: tiramisu/value.py:511
|
||||
msgid "index \"{}\" is higher than the length \"{}\" for option \"{}\""
|
||||
msgstr ""
|
||||
"l'index \"{}\" est supérieur à la longueur de l'option \"{}\" pour l'option "
|
||||
|
@ -5,7 +5,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"POT-Creation-Date: 2019-04-07 10:39+CEST\n"
|
||||
"POT-Creation-Date: 2019-04-08 08:41+CEST\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,71 +15,75 @@ msgstr ""
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
|
||||
|
||||
#: tiramisu/api.py:58
|
||||
#: tiramisu/api.py:59
|
||||
msgid "Settings:"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:59
|
||||
#: tiramisu/api.py:60
|
||||
msgid "Access to option without verifying permissive properties"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:60
|
||||
#: tiramisu/api.py:61
|
||||
msgid "Access to option without property restriction"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:64
|
||||
#: tiramisu/api.py:65
|
||||
msgid "Call: {}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:66
|
||||
#: tiramisu/api.py:67
|
||||
msgid "Commands:"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:103
|
||||
#: tiramisu/api.py:104
|
||||
msgid "index \"{}\" is higher than the leadership length \"{}\" for option \"{}\""
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:108
|
||||
#: tiramisu/api.py:109
|
||||
msgid "option must not be an optiondescription"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:135
|
||||
#: tiramisu/api.py:136
|
||||
msgid "index must be set with the follower option \"{}\""
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:138
|
||||
#: tiramisu/api.py:139
|
||||
msgid "unknown method {}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:360
|
||||
#: tiramisu/api.py:361
|
||||
msgid "cannot add this property: \"{0}\""
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:504 tiramisu/config.py:252
|
||||
#: tiramisu/api.py:505 tiramisu/config.py:252
|
||||
msgid "can't delete a SymLinkOption"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:637 tiramisu/api.py:1326
|
||||
#: tiramisu/api.py:639 tiramisu/api.py:1375
|
||||
msgid "please specify a valid sub function ({})"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:700 tiramisu/api.py:1146
|
||||
#: tiramisu/api.py:702 tiramisu/api.py:1176
|
||||
msgid "unknown list type {}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:702 tiramisu/api.py:1148
|
||||
#: tiramisu/api.py:704 tiramisu/api.py:1178
|
||||
msgid "unknown group_type: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:975
|
||||
#: tiramisu/api.py:753 tiramisu/api.py:1208
|
||||
msgid "please use .dict() before .updates()"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:1000
|
||||
msgid "properties must be a set"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:981 tiramisu/api.py:1003
|
||||
#: tiramisu/api.py:1006 tiramisu/api.py:1028
|
||||
msgid "unknown when {} (must be in append or remove)"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/api.py:993 tiramisu/api.py:1015 tiramisu/config.py:1249
|
||||
#: tiramisu/api.py:1018 tiramisu/api.py:1040 tiramisu/config.py:1249
|
||||
msgid "unknown type {}"
|
||||
msgstr ""
|
||||
|
||||
@ -959,6 +963,30 @@ msgstr ""
|
||||
msgid "cannot change setting when connexion is already opened"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/todict.py:66
|
||||
msgid "context is not supported from now for {}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/todict.py:82 tiramisu/todict.py:91
|
||||
msgid "option {} only works when remotable is not \"none\""
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/todict.py:706 tiramisu/todict.py:839
|
||||
msgid "unknown form {}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/todict.py:751
|
||||
msgid "not in current area"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/todict.py:771
|
||||
msgid "only multi option can have action \"add\", but \"{}\" is not a multi"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/todict.py:773
|
||||
msgid "unknown action"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:427
|
||||
msgid "can't set owner for the symlinkoption \"{}\""
|
||||
msgstr ""
|
||||
|
875
tiramisu/todict.py
Normal file
875
tiramisu/todict.py
Normal file
@ -0,0 +1,875 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import warnings
|
||||
import sys
|
||||
from copy import copy
|
||||
from collections import OrderedDict
|
||||
from .error import ValueWarning, ValueErrorWarning, PropertiesOptionError
|
||||
from . import SynDynOption, RegexpOption, ChoiceOption, ParamContext, ParamOption
|
||||
from .i18n import _
|
||||
|
||||
|
||||
TYPES = {'SymLinkOption': 'symlink',
|
||||
'IntOption': 'integer',
|
||||
'FloatOption': 'integer',
|
||||
'ChoiceOption': 'choice',
|
||||
'BoolOption': 'boolean',
|
||||
'PasswordOption': 'password',
|
||||
'PortOption': 'integer',
|
||||
'DateOption': 'date',
|
||||
'DomainnameOption': 'domainname',
|
||||
'StrOption': 'string'
|
||||
}
|
||||
INPUTS = ['string',
|
||||
'integer',
|
||||
'filename',
|
||||
'password',
|
||||
'email',
|
||||
'username',
|
||||
'ip',
|
||||
'domainname']
|
||||
|
||||
ACTION_HIDE = ['hidden', 'disabled']
|
||||
|
||||
|
||||
# return always warning (even if same warning is already returned)
|
||||
warnings.simplefilter("always", ValueWarning)
|
||||
|
||||
|
||||
class Callbacks(object):
|
||||
def __init__(self, tiramisu_web):
|
||||
self.tiramisu_web = tiramisu_web
|
||||
self.clearable = tiramisu_web.clearable
|
||||
self.remotable = tiramisu_web.remotable
|
||||
self.callbacks = []
|
||||
|
||||
def add(self,
|
||||
path,
|
||||
childapi,
|
||||
options,
|
||||
schema,
|
||||
force_store_value):
|
||||
self.callbacks.append((path, childapi, options, schema, force_store_value))
|
||||
|
||||
def manage_callbacks(self,
|
||||
path,
|
||||
childapi,
|
||||
options,
|
||||
callback,
|
||||
callback_params,
|
||||
form,
|
||||
schema):
|
||||
if callback_params is not None:
|
||||
remote = True
|
||||
for callback_param in callback_params.args:
|
||||
if isinstance(callback_param, ParamContext):
|
||||
raise ValueError(_('context is not supported from now for {}').format(path))
|
||||
if isinstance(callback_param, ParamOption):
|
||||
if callback.__name__ == 'tiramisu_copy':
|
||||
if self.clearable == 'minimum':
|
||||
form.setdefault(path, {})['clearable'] = True
|
||||
if form.get(path, {}).get('remote') is not True and form[options[callback_param.option]].get('remote', False) is not True:
|
||||
form.setdefault(options[callback_param.option], {})
|
||||
form[options[callback_param.option]].setdefault('copy', []).append(path)
|
||||
remote = False
|
||||
elif options.get(callback_param.option) is not None:
|
||||
#form.setdefault(options[callback_param.option], {})
|
||||
form.setdefault(path, {})
|
||||
form[path]['remote'] = True
|
||||
#break
|
||||
if remote:
|
||||
if self.remotable == 'none':
|
||||
raise ValueError(_('option {} only works when remotable is not "none"').format(path))
|
||||
form.setdefault(path, {})['remote'] = True
|
||||
else:
|
||||
if 'expire' not in childapi.property.get() and childapi.owner.isdefault():
|
||||
schema[path]['value'] = childapi.value.get()
|
||||
if self.clearable == 'minimum':
|
||||
form.setdefault(path, {})['clearable'] = True
|
||||
else:
|
||||
if self.remotable == 'none':
|
||||
raise ValueError(_('option {} only works when remotable is not "none"').format(path))
|
||||
# FIXME is not default, show calculate
|
||||
form.setdefault(path, {})['remote'] = True
|
||||
|
||||
|
||||
def process(self,
|
||||
form):
|
||||
for path, childapi, options, schema, force_store_value in self.callbacks:
|
||||
if not childapi.option.isoptiondescription():
|
||||
callback, callback_params = childapi.option.callbacks()
|
||||
if callback is not None:
|
||||
if force_store_value and self.clearable != 'all':
|
||||
return
|
||||
self.manage_callbacks(path,
|
||||
childapi,
|
||||
options,
|
||||
callback,
|
||||
callback_params,
|
||||
form,
|
||||
schema)
|
||||
|
||||
|
||||
class Consistencies(object):
|
||||
def __init__(self, tiramisu_web):
|
||||
self.not_equal = []
|
||||
self.options = {}
|
||||
self.tiramisu_web = tiramisu_web
|
||||
|
||||
def add(self, path, childapi):
|
||||
child = childapi.option.get()
|
||||
if isinstance(child, SynDynOption):
|
||||
child = child._impl_getopt()
|
||||
self.options[child] = path
|
||||
if not childapi.option.isoptiondescription():
|
||||
for consistency in childapi.option.consistencies():
|
||||
cons_id, func, all_cons_opts, params = consistency
|
||||
if func == '_cons_not_equal':
|
||||
options = []
|
||||
for option in all_cons_opts:
|
||||
option = option()
|
||||
options.append(option)
|
||||
# FIXME transitive
|
||||
self.not_equal.append((options, params.get('warnings_only')))
|
||||
|
||||
def process(self, form):
|
||||
for not_equal, warnings_only in self.not_equal:
|
||||
not_equal_option = []
|
||||
for option in not_equal:
|
||||
not_equal_option.append(self.options[option])
|
||||
for idx, path in enumerate(not_equal_option):
|
||||
if form.get(path, {}).get('remote') is True:
|
||||
continue
|
||||
options = copy(not_equal_option)
|
||||
options.pop(idx)
|
||||
form.setdefault(path, {}).setdefault('not_equal',
|
||||
{'options': []})
|
||||
form[path]['not_equal']['options'].extend(options)
|
||||
if warnings_only or getattr(option, '_warnings_only', False):
|
||||
form[path]['not_equal']['warnings'] = True
|
||||
|
||||
|
||||
class Requires(object):
|
||||
def __init__(self, tiramisu_web):
|
||||
self.requires = {}
|
||||
self.options = {}
|
||||
self.tiramisu_web = tiramisu_web
|
||||
self.config = tiramisu_web.config
|
||||
self.remotable = tiramisu_web.remotable
|
||||
|
||||
def manage_requires(self,
|
||||
require_obj,
|
||||
childapi,
|
||||
path,
|
||||
form,
|
||||
action_hide,
|
||||
current_action):
|
||||
for requires in childapi.option.requires():
|
||||
for require in requires:
|
||||
options, action, inverse, \
|
||||
transitive, same_action, operator = require
|
||||
if transitive is False:
|
||||
# transitive to "False" not supported yet for a requirement
|
||||
if require_obj.remotable == 'none':
|
||||
raise ValueError('require set for {} but remotable is "none"'
|
||||
''.format(path))
|
||||
form.setdefault(path, {'key': path})['remote'] = True
|
||||
return
|
||||
if same_action is False:
|
||||
# same_action to "False" not supported yet for a requirement
|
||||
if require_obj.remotable == 'none':
|
||||
raise ValueError('require set for {} but remotable is "none"'
|
||||
''.format(path))
|
||||
form.setdefault(path, {'key': path})['remote'] = True
|
||||
return
|
||||
if operator == 'and':
|
||||
# operator "and" not supported yet for a requirement
|
||||
if require_obj.remotable == 'none':
|
||||
raise ValueError('require set for {} but remotable is "none"'
|
||||
''.format(path))
|
||||
form.setdefault(path, {'key': path})['remote'] = True
|
||||
return
|
||||
for option, expected in options:
|
||||
option_path = require_obj.options.get(option)
|
||||
if option_path is not None and action in action_hide:
|
||||
if current_action is None:
|
||||
current_action = action
|
||||
elif current_action != action:
|
||||
if require_obj.remotable == 'none':
|
||||
raise ValueError('require set for {} but remotable is "none"'
|
||||
''.format(path))
|
||||
form.setdefault(option_path, {'key': option_path})['remote'] = True
|
||||
for exp in expected:
|
||||
if inverse:
|
||||
act = 'show'
|
||||
inv_act = 'hide'
|
||||
else:
|
||||
act = 'hide'
|
||||
inv_act = 'show'
|
||||
require_obj.requires.setdefault(path,
|
||||
{'expected': {}}
|
||||
)['expected'].setdefault(exp,
|
||||
{}).setdefault(act,
|
||||
[]).append(option_path)
|
||||
if isinstance(option, ChoiceOption):
|
||||
for value in require_obj.config.unrestraint.option(option_path).value.list():
|
||||
if value not in expected:
|
||||
require_obj.requires.setdefault(path,
|
||||
{'expected': {}}
|
||||
)['expected'].setdefault(value,
|
||||
{}).setdefault(inv_act,
|
||||
[]).append(option_path)
|
||||
require_obj.requires[path].setdefault('default', {}).setdefault(inv_act, []).append(option_path)
|
||||
else:
|
||||
if require_obj.remotable == 'none':
|
||||
raise ValueError('require set for {} but remotable est "none"'
|
||||
''.format(path))
|
||||
form.setdefault(option_path, {'key': option_path})['remote'] = True
|
||||
|
||||
def add(self, path, childapi, form):
|
||||
#collect id of all options
|
||||
child = childapi.option.get()
|
||||
if isinstance(child, SynDynOption):
|
||||
child = child._impl_getopt()
|
||||
self.options[child] = path
|
||||
current_action = None
|
||||
|
||||
self.manage_requires(self,
|
||||
childapi,
|
||||
path,
|
||||
form,
|
||||
ACTION_HIDE,
|
||||
current_action)
|
||||
|
||||
def is_remote(self, path, form):
|
||||
if self.remotable == 'all':
|
||||
return True
|
||||
else:
|
||||
return form.get(path) and form[path].get('remote', False)
|
||||
|
||||
def process(self, form):
|
||||
dependencies = {}
|
||||
for path, values in self.requires.items():
|
||||
if form.get(path, {}).get('remote') is True:
|
||||
continue
|
||||
if 'default' in values:
|
||||
for option in values['default'].get('show', []):
|
||||
if path == option:
|
||||
form.setdefault(path, {'key': path})['remote'] = True
|
||||
if not self.is_remote(option, form):
|
||||
dependencies.setdefault(option,
|
||||
{'default': {}, 'expected': {}}
|
||||
)['default'].setdefault('show', [])
|
||||
if path not in dependencies[option]['default']['show']:
|
||||
dependencies[option]['default']['show'].append(path)
|
||||
for option in values['default'].get('hide', []):
|
||||
if path == option:
|
||||
form.setdefault(path, {'key': path})['remote'] = True
|
||||
if not self.is_remote(option, form):
|
||||
dependencies.setdefault(option,
|
||||
{'default': {}, 'expected': {}}
|
||||
)['default'].setdefault('hide', [])
|
||||
if path not in dependencies[option]['default']['hide']:
|
||||
dependencies[option]['default']['hide'].append(path)
|
||||
for expected, actions in values['expected'].items():
|
||||
if expected is None:
|
||||
expected = ''
|
||||
for option in actions.get('show', []):
|
||||
if path == option:
|
||||
form.setdefault(path, {'key': path})['remote'] = True
|
||||
if not self.is_remote(option, form):
|
||||
dependencies.setdefault(option,
|
||||
{'expected': {}}
|
||||
)['expected'].setdefault(expected,
|
||||
{}).setdefault('show', [])
|
||||
if path not in dependencies[option]['expected'][expected]['show']:
|
||||
dependencies[option]['expected'][expected]['show'].append(path)
|
||||
for option in actions.get('hide', []):
|
||||
if path == option:
|
||||
form.setdefault(path, {'key': path})['remote'] = True
|
||||
if not self.is_remote(option, form):
|
||||
dependencies.setdefault(option,
|
||||
{'expected': {}}
|
||||
)['expected'].setdefault(expected,
|
||||
{}).setdefault('hide', [])
|
||||
if path not in dependencies[option]['expected'][expected]['hide']:
|
||||
dependencies[option]['expected'][expected]['hide'].append(path)
|
||||
for path, dependency in dependencies.items():
|
||||
form[path]['dependencies'] = dependency
|
||||
|
||||
|
||||
class TiramisuDict:
|
||||
|
||||
# propriete:
|
||||
# hidden
|
||||
# mandatory
|
||||
# editable
|
||||
|
||||
# FIXME model:
|
||||
# #optionnel mais qui bouge
|
||||
# choices/suggests
|
||||
# warning
|
||||
#
|
||||
# #bouge
|
||||
# owner
|
||||
# properties
|
||||
|
||||
def __init__(self,
|
||||
config,
|
||||
root=None,
|
||||
clearable="all",
|
||||
remotable="minimum"):
|
||||
if 'demoting_error_warning' not in config.property.get():
|
||||
raise ValueError('demoting_error_warning property is mandatory')
|
||||
self.config = config
|
||||
self.root = root
|
||||
self.requires = None
|
||||
self.callbacks = None
|
||||
self.consistencies = None
|
||||
#all, minimum, none
|
||||
self.clearable = clearable
|
||||
#all, minimum, none
|
||||
self.remotable = remotable
|
||||
self.context_properties = self.config.property.get()
|
||||
self.context_permissives = self.config.permissive.get()
|
||||
|
||||
def add_help(self,
|
||||
obj,
|
||||
childapi):
|
||||
hlp = childapi.information.get('help', None)
|
||||
if hlp is not None:
|
||||
obj['help'] = hlp
|
||||
|
||||
def get_list(self, root, subchildapi):
|
||||
for childapi in subchildapi.list('all'):
|
||||
childname = childapi.option.name()
|
||||
if root is None:
|
||||
path = childname
|
||||
else:
|
||||
path = root + '.' + childname
|
||||
yield path, childapi
|
||||
|
||||
def walk(self,
|
||||
root,
|
||||
subchildapi,
|
||||
schema,
|
||||
model,
|
||||
form,
|
||||
order,
|
||||
updates_status,
|
||||
init=False):
|
||||
if init:
|
||||
if form is not None:
|
||||
self.requires = Requires(self)
|
||||
self.consistencies = Consistencies(self)
|
||||
self.callbacks = Callbacks(self)
|
||||
else:
|
||||
init = False
|
||||
if subchildapi is None:
|
||||
if root is None:
|
||||
subchildapi = self.config.unrestraint.option
|
||||
else:
|
||||
subchildapi = self.config.unrestraint.option(root)
|
||||
isleadership = False
|
||||
else:
|
||||
isleadership = subchildapi.option.isleadership()
|
||||
leader_len = None
|
||||
for path, childapi in self.get_list(root, subchildapi):
|
||||
if isleadership and leader_len is None:
|
||||
leader_len = childapi.value.len()
|
||||
props_no_requires = set(childapi.option.properties())
|
||||
if form is not None:
|
||||
self.requires.add(path,
|
||||
childapi,
|
||||
form)
|
||||
self.consistencies.add(path,
|
||||
childapi)
|
||||
self.callbacks.add(path,
|
||||
childapi,
|
||||
self.requires.options,
|
||||
schema,
|
||||
'force_store_value' in props_no_requires)
|
||||
childapi_option = childapi.option
|
||||
if model is not None:
|
||||
self.gen_model(model,
|
||||
childapi,
|
||||
path,
|
||||
leader_len,
|
||||
props_no_requires,
|
||||
updates_status)
|
||||
if order is not None:
|
||||
order.append(path)
|
||||
if childapi.option.isoptiondescription():
|
||||
if childapi_option.isleadership():
|
||||
type_ = 'array'
|
||||
else:
|
||||
type_ = 'object'
|
||||
if schema is not None:
|
||||
schema[path] = {'name': path,
|
||||
'properties': OrderedDict(),
|
||||
'type': type_}
|
||||
subschema = schema[path]['properties']
|
||||
else:
|
||||
subschema = schema
|
||||
self.walk(path,
|
||||
childapi,
|
||||
subschema,
|
||||
model,
|
||||
form,
|
||||
order,
|
||||
updates_status)
|
||||
else:
|
||||
child = childapi_option.get()
|
||||
childtype = child.__class__.__name__
|
||||
if childtype == 'SynDynOption':
|
||||
childtype = child._impl_getopt().__class__.__name__
|
||||
if childapi_option.issymlinkoption():
|
||||
web_type = 'symlink'
|
||||
else:
|
||||
web_type = childapi_option.type()
|
||||
value = childapi.option.default()
|
||||
if value not in [[], None]:
|
||||
has_value = True
|
||||
else:
|
||||
value = None
|
||||
has_value = False
|
||||
|
||||
is_multi = childapi_option.ismulti()
|
||||
if is_multi:
|
||||
default = childapi_option.defaultmulti()
|
||||
if default not in [None, []]:
|
||||
has_value = True
|
||||
else:
|
||||
default = None
|
||||
else:
|
||||
default = None
|
||||
|
||||
if schema is not None:
|
||||
self.gen_schema(schema,
|
||||
childapi,
|
||||
childapi_option,
|
||||
path,
|
||||
props_no_requires,
|
||||
value,
|
||||
default,
|
||||
is_multi,
|
||||
web_type)
|
||||
if form is not None:
|
||||
self.gen_form(form,
|
||||
web_type,
|
||||
path,
|
||||
child,
|
||||
childapi_option,
|
||||
childtype,
|
||||
has_value)
|
||||
if schema is not None:
|
||||
schema[path]['title'] = childapi_option.doc()
|
||||
self.add_help(schema[path],
|
||||
childapi)
|
||||
if init and form is not None:
|
||||
self.callbacks.process(form)
|
||||
self.requires.process(form)
|
||||
self.consistencies.process(form)
|
||||
del self.requires
|
||||
del self.consistencies
|
||||
|
||||
|
||||
def gen_schema(self,
|
||||
schema,
|
||||
childapi,
|
||||
childapi_option,
|
||||
path,
|
||||
props_no_requires,
|
||||
value,
|
||||
default,
|
||||
is_multi,
|
||||
web_type):
|
||||
schema[path] = {'name': path,
|
||||
'type': web_type}
|
||||
if childapi_option.issymlinkoption():
|
||||
schema[path]['opt_path'] = childapi_option.get().impl_getopt().impl_getpath()
|
||||
else:
|
||||
if value is not None:
|
||||
schema[path]['value'] = value
|
||||
|
||||
if default is not None:
|
||||
schema[path]['default'] = default
|
||||
|
||||
if is_multi:
|
||||
schema[path]['isMulti'] = is_multi
|
||||
|
||||
if childapi_option.issubmulti():
|
||||
schema[path]['isSubMulti'] = True
|
||||
|
||||
if 'auto_freeze' in props_no_requires:
|
||||
schema[path]['autoFreeze'] = True
|
||||
|
||||
if web_type == 'choice':
|
||||
schema[path]['enum'] = childapi.value.list()
|
||||
empty_is_required = not childapi.option.isfollower() and is_multi
|
||||
if (empty_is_required and not 'empty' in props_no_requires) or \
|
||||
(not empty_is_required and not 'mandatory' in props_no_requires):
|
||||
schema[path]['enum'] = [''] + list(schema[path]['enum'])
|
||||
|
||||
|
||||
def gen_form(self,
|
||||
form,
|
||||
web_type,
|
||||
path,
|
||||
child,
|
||||
childapi_option,
|
||||
childtype,
|
||||
has_value):
|
||||
obj_form = {}
|
||||
if path in form:
|
||||
obj_form.update(form[path])
|
||||
if not childapi_option.issymlinkoption():
|
||||
if self.clearable == 'all':
|
||||
obj_form['clearable'] = True
|
||||
if has_value and self.clearable != 'none':
|
||||
obj_form['clearable'] = True
|
||||
if self.remotable == 'all' or childapi_option.has_dependency():
|
||||
obj_form['remote'] = True
|
||||
if web_type == 'integer':
|
||||
obj_form['allowedpattern'] = '[0-9]'
|
||||
if isinstance(child, RegexpOption):
|
||||
obj_form['pattern'] = child._regexp.pattern
|
||||
if web_type == 'domainname':
|
||||
obj_form['pattern'] = child.impl_get_extra('_domain_re').pattern
|
||||
if childtype in ['IPOption', 'NetworkOption', 'NetmaskOption']:
|
||||
#FIXME only from 0.0.0.0 to 255.255.255.255
|
||||
obj_form['pattern'] = r'^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
|
||||
if childtype == 'FloatOption':
|
||||
obj_form['step'] = 'any'
|
||||
if childtype == 'PortOption':
|
||||
obj_form['min'] = child.impl_get_extra('_min_value')
|
||||
obj_form['max'] = child.impl_get_extra('_max_value')
|
||||
if web_type == 'choice':
|
||||
obj_form['type'] = 'choice'
|
||||
elif web_type in INPUTS:
|
||||
obj_form['type'] = 'input'
|
||||
if obj_form:
|
||||
form[path] = obj_form
|
||||
|
||||
def calc_raises_properties(self, childapi):
|
||||
old_properties = childapi._option_bag.config_bag.properties
|
||||
del childapi._option_bag.config_bag.properties
|
||||
ret = childapi.option.properties(only_raises=True)
|
||||
childapi._option_bag.config_bag.properties = old_properties
|
||||
return ret
|
||||
|
||||
def _gen_model_properties(self,
|
||||
childapi,
|
||||
path,
|
||||
index,
|
||||
props_no_requires):
|
||||
obj = {}
|
||||
isfollower = childapi.option.isfollower()
|
||||
if index is None and isfollower:
|
||||
# cannot calculated requires with follower without index
|
||||
props = props_no_requires
|
||||
else:
|
||||
props = set(childapi.property.get())
|
||||
if self.calc_raises_properties(childapi):
|
||||
obj['display'] = False
|
||||
if not isfollower and childapi.option.ismulti():
|
||||
if 'empty' in props:
|
||||
obj['required'] = True
|
||||
props.remove('empty')
|
||||
if 'mandatory' in props:
|
||||
obj['needs_len'] = True
|
||||
props.remove('mandatory')
|
||||
elif 'mandatory' in props:
|
||||
obj['required'] = True
|
||||
props.remove('mandatory')
|
||||
if 'frozen' in props:
|
||||
obj['readOnly'] = True
|
||||
props.remove('frozen')
|
||||
if 'hidden' in props:
|
||||
obj['hidden'] = True
|
||||
props.remove('hidden')
|
||||
if 'disabled' in props:
|
||||
obj['hidden'] = True
|
||||
props.remove('disabled')
|
||||
if props:
|
||||
lprops = list(props)
|
||||
lprops.sort()
|
||||
obj['properties'] = lprops
|
||||
return obj
|
||||
|
||||
def gen_model(self,
|
||||
model,
|
||||
childapi,
|
||||
path,
|
||||
leader_len,
|
||||
props_no_requires,
|
||||
updates_status):
|
||||
if childapi.option.isoptiondescription():
|
||||
props = set(childapi.property.get())
|
||||
obj = {}
|
||||
if self.calc_raises_properties(childapi):
|
||||
obj['display'] = False
|
||||
if props:
|
||||
lprops = list(props)
|
||||
lprops.sort()
|
||||
obj['properties'] = lprops
|
||||
if 'hidden' in props or 'disabled' in props:
|
||||
obj['hidden'] = True
|
||||
try:
|
||||
self.config.option(path).option.get()
|
||||
except PropertiesOptionError:
|
||||
pass
|
||||
else:
|
||||
obj = self._gen_model_properties(childapi,
|
||||
path,
|
||||
None,
|
||||
props_no_requires)
|
||||
if childapi.option.isfollower():
|
||||
for index in range(leader_len):
|
||||
follower_childapi = self.config.unrestraint.option(path, index)
|
||||
sobj = self._gen_model_properties(follower_childapi,
|
||||
path,
|
||||
index,
|
||||
props_no_requires)
|
||||
self._get_model_value(follower_childapi,
|
||||
path,
|
||||
sobj,
|
||||
index,
|
||||
updates_status)
|
||||
if sobj:
|
||||
model.setdefault(path, {})[str(index)] = sobj
|
||||
else:
|
||||
self._get_model_value(childapi,
|
||||
path,
|
||||
obj,
|
||||
None,
|
||||
updates_status)
|
||||
if obj:
|
||||
if not childapi.option.isoptiondescription() and childapi.option.isfollower():
|
||||
model.setdefault(path, {})[None] = obj
|
||||
else:
|
||||
model[path] = obj
|
||||
|
||||
def _get_model_value(self,
|
||||
childapi,
|
||||
path,
|
||||
obj,
|
||||
index,
|
||||
updates_status):
|
||||
# FIXME unrestraint ...
|
||||
try:
|
||||
nchildapi = self.config.option(path, index=index)
|
||||
with warnings.catch_warnings(record=True) as warns:
|
||||
value = nchildapi.value.get()
|
||||
self._get_value_with_exception(obj,
|
||||
childapi,
|
||||
warns)
|
||||
except PropertiesOptionError:
|
||||
value = childapi.value.get()
|
||||
warns = []
|
||||
if value is not None and value != []:
|
||||
obj['value'] = value
|
||||
obj['owner'] = childapi.owner.get()
|
||||
|
||||
def _get_value_with_exception(self,
|
||||
obj,
|
||||
childapi,
|
||||
values):
|
||||
for value in values:
|
||||
if isinstance(value.message, ValueErrorWarning):
|
||||
value.message.prefix = ''
|
||||
if childapi.option.isleader():
|
||||
obj.setdefault('invalid', [])
|
||||
obj['invalid'].append({'error': str(value.message),
|
||||
'index': value.message.index})
|
||||
else:
|
||||
obj.setdefault('error', [])
|
||||
obj['error'].append(str(value.message))
|
||||
obj['invalid'] = True
|
||||
else:
|
||||
obj.setdefault('warnings', [])
|
||||
obj['warnings'].append(str(value.message))
|
||||
obj['hasWarnings'] = True
|
||||
|
||||
def get_form(self, form):
|
||||
ret = []
|
||||
buttons = []
|
||||
dict_form = OrderedDict()
|
||||
for form_ in form:
|
||||
if 'key' in form_:
|
||||
dict_form[form_['key']] = form_
|
||||
elif form_.get('type') == 'submit':
|
||||
if 'cmd' not in form_:
|
||||
form_['cmd'] = 'submit'
|
||||
buttons.append(form_)
|
||||
else:
|
||||
raise ValueError(_('unknown form {}').format(form_))
|
||||
|
||||
for key, form_ in self.form.items():
|
||||
form_['key'] = key
|
||||
if key in dict_form:
|
||||
form_.update(dict_form[key])
|
||||
ret.append(form_)
|
||||
ret.extend(buttons)
|
||||
return ret
|
||||
|
||||
def del_value(self, childapi, path, index):
|
||||
if index is not None and childapi.option.isleader():
|
||||
childapi.value.pop(index)
|
||||
elif index is None or childapi.option.isfollower():
|
||||
childapi.value.reset()
|
||||
else:
|
||||
multi = childapi.value.get()
|
||||
multi.pop(index)
|
||||
childapi.value.set(multi)
|
||||
|
||||
def add_value(self, childapi, path, value):
|
||||
multi = childapi.value.get()
|
||||
multi.append(value)
|
||||
childapi.value.set(multi)
|
||||
|
||||
def mod_value(self, childapi, path, index, value):
|
||||
if index is None or childapi.option.isfollower():
|
||||
childapi.value.set(value)
|
||||
else:
|
||||
multi = childapi.value.get()
|
||||
if not multi and index == 0:
|
||||
multi.append(value)
|
||||
else:
|
||||
multi[index] = value
|
||||
childapi.value.set(multi)
|
||||
|
||||
def apply_updates(self,
|
||||
oripath,
|
||||
updates,
|
||||
model_ori):
|
||||
updates_status = {}
|
||||
for update in updates:
|
||||
path = update['name']
|
||||
index = update.get('index')
|
||||
if oripath is not None and not path.startswith(oripath):
|
||||
raise ValueError(_('not in current area'))
|
||||
childapi = self.config.option(path)
|
||||
childapi_option = childapi.option
|
||||
if childapi_option.isfollower():
|
||||
childapi = self.config.option(path, index)
|
||||
with warnings.catch_warnings(record=True) as warns:
|
||||
#try:
|
||||
if update['action'] == 'modify':
|
||||
self.mod_value(childapi,
|
||||
path,
|
||||
index,
|
||||
update.get('value'))
|
||||
elif update['action'] == 'delete':
|
||||
self.del_value(childapi,
|
||||
path,
|
||||
index)
|
||||
elif update['action'] == 'add':
|
||||
if childapi_option.ismulti():
|
||||
self.add_value(childapi, path, update['value'])
|
||||
else:
|
||||
raise ValueError(_('only multi option can have action "add", but "{}" is not a multi').format(path))
|
||||
else:
|
||||
raise ValueError(_('unknown action'))
|
||||
#except ValueError as err:
|
||||
# updates_status.setdefault(path, {})[index] = err
|
||||
# continue
|
||||
if warns != []:
|
||||
updates_status.setdefault(path, {}).setdefault(index, []).extend(warns)
|
||||
return updates_status
|
||||
|
||||
def set_updates(self,
|
||||
body):
|
||||
root_path = self.root
|
||||
updates = body.get('updates', [])
|
||||
updates_status = self.apply_updates(root_path,
|
||||
updates,
|
||||
body.get('model'))
|
||||
if 'model' in body:
|
||||
order = []
|
||||
old_model = body['model']
|
||||
new_model = self.todict(order=order,
|
||||
build_schema=False,
|
||||
build_form=False,
|
||||
updates_status=updates_status)['model']
|
||||
values = {'updates': list_keys(old_model, new_model, order, updates_status),
|
||||
'model': new_model}
|
||||
else:
|
||||
values = None
|
||||
return values
|
||||
|
||||
def todict(self,
|
||||
custom_form=[],
|
||||
build_schema=True,
|
||||
build_model=True,
|
||||
build_form=True,
|
||||
order=None,
|
||||
updates_status={}):
|
||||
rootpath = self.root
|
||||
if build_schema:
|
||||
schema = OrderedDict()
|
||||
else:
|
||||
schema = None
|
||||
if build_model:
|
||||
model = {}
|
||||
else:
|
||||
model = None
|
||||
if build_form:
|
||||
form = {}
|
||||
buttons = []
|
||||
else:
|
||||
form = None
|
||||
self.walk(rootpath,
|
||||
None,
|
||||
schema,
|
||||
model,
|
||||
form,
|
||||
order,
|
||||
updates_status,
|
||||
init=True)
|
||||
if build_form:
|
||||
for form_ in custom_form:
|
||||
if 'key' in form_:
|
||||
key = form_.pop('key')
|
||||
form.setdefault(key, {}).update(form_)
|
||||
elif form_.get('type') == 'submit':
|
||||
# FIXME if an Option has a key "null"?
|
||||
form.setdefault(None, []).append(form_)
|
||||
else:
|
||||
raise ValueError(_('unknown form {}').format(form_))
|
||||
ret = {}
|
||||
if build_schema:
|
||||
ret['schema'] = schema
|
||||
if build_model:
|
||||
ret['model'] = model
|
||||
if build_form:
|
||||
ret['form'] = form
|
||||
ret['version'] = '1.0'
|
||||
return ret
|
||||
|
||||
|
||||
def list_keys(model_a, model_b, ordered_key, updates_status):
|
||||
model_a_dict = {}
|
||||
model_b_dict = {}
|
||||
|
||||
keys_a = set(model_a.keys())
|
||||
keys_b = set(model_b.keys())
|
||||
|
||||
keys = (keys_a ^ keys_b) | set(updates_status.keys())
|
||||
|
||||
for key in keys_a & keys_b:
|
||||
keys_mod_a = set(model_a[key].keys())
|
||||
keys_mod_b = set(model_b[key].keys())
|
||||
if keys_mod_a != keys_mod_b:
|
||||
keys.add(key)
|
||||
else:
|
||||
for skey in keys_mod_a:
|
||||
if model_a[key][skey] != model_b[key][skey]:
|
||||
keys.add(key)
|
||||
break
|
||||
def sort_key(key):
|
||||
try:
|
||||
return ordered_key.index(key)
|
||||
except ValueError:
|
||||
return -1
|
||||
return sorted(list(keys), key=sort_key)
|
Reference in New Issue
Block a user