diff --git a/.gitignore b/.gitignore index a5c71d3..5f764ac 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ *~ *# *.pyc -*.mo *.swp build/ diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 2835134..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,8 +0,0 @@ -# Include the README -include *.rst - -# Include the license file -include LICENSE.txt - -# Include the data files -recursive-include tiramisu *.py *.mo diff --git a/README.md b/README.md index 597532c..6a79f1b 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,25 @@ ![Logo Tiramisu](logo.png "logo Tiramisu") +An options controller tool +------------------------------------- + +Due to more and more available options required to set up an operating system, +compiler options or whatever, it became quite annoying to hand the necessary +options to where they are actually used and even more annoying to add new +options. To circumvent these problems the configuration control was +introduced... + +Tiramisu is an options handler and an options controller, wich aims at +producing flexible and fast options access. + + [Documentations](doc/README.md) - # LICENSES -See COPYING for the licences of the code and the documentation. +See [COPYING](COPYING) for the licences of the code and the documentation. -See AUTHORS for the details about the tiramisu's team. +See [AUTHORS](AUTHORS) for the details about the tiramisu's team. diff --git a/locale/fr/LC_MESSAGES/tiramisu.po b/locale/fr/LC_MESSAGES/tiramisu.po new file mode 100644 index 0000000..16f4bad --- /dev/null +++ b/locale/fr/LC_MESSAGES/tiramisu.po @@ -0,0 +1,1367 @@ +msgid "" +msgstr "" +"Project-Id-Version: Tiramisu\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-10-30 13:15+0100\n" +"PO-Revision-Date: \n" +"Last-Translator: Emmanuel Garette \n" +"Language-Team: Tiramisu's team \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Poedit 3.5\n" +"X-Poedit-SourceCharset: UTF-8\n" + +#: tiramisu/api.py:79 +msgid "Settings:" +msgstr "Paramètres :" + +#: tiramisu/api.py:83 +msgid "Access to option without verifying permissive properties" +msgstr "Accès à une option sans vérifié les propriétés permises" + +#: tiramisu/api.py:88 +msgid "Access to option without property restriction" +msgstr "Accès à une option sans restriction de propriété" + +#: tiramisu/api.py:93 +msgid "Do not warnings during validation" +msgstr "Ne peut avoir de warnings durant une validation" + +#: tiramisu/api.py:97 +msgid "Commands:" +msgstr "Commandes :" + +#: tiramisu/api.py:111 tiramisu/api.py:1840 +msgid "please specify a valid sub function ({0}.{1})" +msgstr "veuillez spécifier une sous fonction valide ({0}.{1})" + +#: tiramisu/api.py:194 +msgid "please do not specify index ({0}.{1})" +msgstr "veuillez ne pas spécifier d'index ({0}.{1})" + +#: tiramisu/api.py:199 tiramisu/api.py:844 +msgid "please specify index with a follower option ({0}.{1})" +msgstr "veuillez spécifier un index avec une option suiveuse ({0}.{1})" + +#: tiramisu/api.py:220 +msgid "please specify a valid sub function ({0}.{1}): {2}" +msgstr "veuillez spécifier une sous fonction valide ({0}.{1}): {2}" + +#: tiramisu/api.py:431 +msgid "" +"the option {0} is not a dynamic option, cannot get identifiers with " +"only_self parameter to True" +msgstr "" +"l'option {0} n'est pas une option dynamique, ne peut retrouver l'identifiant " +"avec le paramètre only_self à True" + +#: tiramisu/api.py:517 +msgid "cannot get option from a follower symlink without index" +msgstr "ne peut avoir d'option pour une symlink suiveuse sans index" + +#: tiramisu/api.py:592 +msgid "cannot add this property: \"{0}\"" +msgstr "ne peut pas ajouter cette propriété : \"{0}\"" + +#: tiramisu/api.py:619 +msgid "" +"cannot remove option's property \"{0}\", use permissive instead in option " +"\"{1}\"" +msgstr "" +"ne supprimer la propriété \"{0}\" de l'option, utiliser plutôt permissive " +"dans l'option \"{1}\"" + +#: tiramisu/api.py:623 +msgid "cannot find \"{0}\" in option \"{1}\"" +msgstr "ne peut trouver \"{0}\" dans l'option \"{1}\"" + +#: tiramisu/api.py:628 +msgid "" +"cannot remove option's property \"{0}\", use permissive instead in option " +"\"{1}\" at index \"{2}\"" +msgstr "" +"ne peut supprimer la propriété \"{0}\" de l'option, utilisez plutôt " +"permissive dans l'option \"{1}\" a l'index \"{2}\"" + +#: tiramisu/api.py:632 +msgid "cannot find \"{0}\" in option \"{1}\" at index \"{2}\"" +msgstr "ne peut trouver \"{0}\" dans l'option \"{1}\" à l'index \"{2}\"" + +#: tiramisu/api.py:676 +msgid "cannot find \"{0}\"" +msgstr "ne peut trouver \"{0}\"" + +#: tiramisu/api.py:808 +msgid "cannot reduce length of the leader {}" +msgstr "il est impossible de réduire la longueur du leader \"{}\"" + +#: tiramisu/api.py:861 +msgid "only multi value has defaultmulti" +msgstr "seule les valeurs multiple a l'attribut defaultmulti" + +#: tiramisu/api.py:1020 +msgid "please specify a valid sub function ({0}.{1}) for {2}" +msgstr "veuillez spécifier une sous fonction valide ({0}.{1}) pour {2}" + +#: tiramisu/api.py:1407 +msgid "properties must be a frozenset" +msgstr "une propriété doit être de type frozenset" + +#: tiramisu/api.py:1411 tiramisu/api.py:1438 +msgid "unknown when {} (must be in append or remove)" +msgstr "value {} inconsistent (doit être append ou remove)" + +#: tiramisu/api.py:1424 tiramisu/api.py:1448 tiramisu/config.py:1680 +msgid "unknown type {}" +msgstr "type inconnu {}" + +#: tiramisu/api.py:1812 +msgid "do not use unrestraint, nowarnings or forcepermissive together" +msgstr "" +"il ne faut pas utiliser unrestraint, nowarnings ou forcepermissive ensemble" + +#: tiramisu/autolib.py:80 +msgid "args in params must be a tuple" +msgstr "args dans params doit être un tuple" + +#: tiramisu/autolib.py:83 tiramisu/autolib.py:88 +msgid "arg in params must be a Param" +msgstr "arg dans params doit être un Param" + +#: tiramisu/autolib.py:85 +msgid "kwargs in params must be a dict" +msgstr "kwargs dans params doit être un dict" + +#: tiramisu/autolib.py:113 +msgid "paramoption needs an option not {}" +msgstr "paramoption doit être une option pas {0}" + +#: tiramisu/autolib.py:119 +msgid "param must have a boolean not a {} for notraisepropertyerror" +msgstr "param doit avoir un booléan pas un {} pour notraisepropertyerror" + +#: tiramisu/autolib.py:122 +msgid "param must have a boolean not a {} for raisepropertyerror" +msgstr "param doit avoir un booléan pas un {} pour raisepropertyerror" + +#: tiramisu/autolib.py:212 +msgid "option in ParamInformation cannot be a symlinkoption" +msgstr "l'option dans ParamInformation ne peut pas être un symlinkoption" + +#: tiramisu/autolib.py:215 +msgid "option in ParamInformation cannot be a follower" +msgstr "l'option dans ParamInformation ne peut pas être suiveuse" + +#: tiramisu/autolib.py:218 +msgid "option in ParamInformation cannot be a dynamic option" +msgstr "l'option dans ParamInformation ne peut pas être une option dynamique" + +#: tiramisu/autolib.py:279 +msgid "first argument ({0}) must be a function" +msgstr "le premier argument ({0}à doit être une fonction" + +#: tiramisu/autolib.py:283 +msgid "help_function ({0}) must be a function" +msgstr "help_function ({0}) doit être une fonction" + +#: tiramisu/autolib.py:452 tiramisu/autolib.py:514 +msgid "unable to carry out a calculation for {}, {}" +msgstr "impossible d'effectuer le calcul pour {}, {}" + +#: tiramisu/autolib.py:461 tiramisu/autolib.py:521 +msgid "the option {0} is used in a calculation but is invalid ({1})" +msgstr "l'option {0} est utilisé dans un calcul mais est invalide ({1})" + +#: tiramisu/autolib.py:477 tiramisu/autolib.py:535 tiramisu/autolib.py:584 +msgid "unable to get value for calculating {0}, {1}" +msgstr "impossible de trouver la valeur pour calculer {0}, {1}" + +#: tiramisu/autolib.py:601 +msgid "option {0} is not a dynoptiondescription or in a dynoptiondescription" +msgstr "" +"l'option {0} n'est pas une dynoptiondescription ou n'est pas dans une " +"dynoptiondescription" + +#: tiramisu/autolib.py:848 +msgid "" +"the \"{}\" function with positional arguments \"{}\" and keyword arguments " +"\"{}\" must not return a list (\"{}\") for the follower option {}" +msgstr "" +"la fonction \"{}\" avec les arguments positionnels \"{}\" et les arguments " +"nommés \"{}\" ne doit pas retourner une liste (\"{}\") pour l'option " +"suiveuse {}" + +#: tiramisu/autolib.py:863 +msgid "" +"the \"{}\" function must not return a list (\"{}\") for the follower option " +"{}" +msgstr "" +"la fonction \"{}\" ne doit pas retourner une liste (\"{}\") pour l'option " +"suiveuse {}" + +#: tiramisu/autolib.py:904 +msgid "" +"unexpected error \"{0}\" in function \"{1}\" with arguments \"{3}\" and " +"\"{4}\" for option {2}" +msgstr "" +"erreur inattendue \"{0}\" dans la fonction \"{1}\" avec les arguments " +"\"{3}\" et \"{4}\" pour l'option {2}" + +#: tiramisu/autolib.py:915 +msgid "unexpected error \"{0}\" in function \"{1}\" for option {2}" +msgstr "erreur inattendue \"{0}\" dans la fonction \"{1}\" pour l'option {2}" + +#: tiramisu/config.py:419 +msgid "" +"index \"{0}\" is greater than the leadership length \"{1}\" for option {2}" +msgstr "" +"l'index \"{0}\" est supérieur à la longueur de la leadership \"{1}\" pour " +"l'option {2}" + +#: tiramisu/config.py:579 +msgid "there is no option description for this config (may be GroupConfig)" +msgstr "" +"il n'y a pas d'option description trouvé pour cette config (peut être un " +"GroupConfig)" + +#: tiramisu/config.py:668 +msgid "no option found in config with these criteria" +msgstr "aucune option trouvée dans la config avec ces critères" + +#: tiramisu/config.py:871 +msgid "" +"the follower option {0} has greater length ({1}) than the leader length ({2})" +msgstr "" +"l'option suiveuse {0} a une longueur supérieur ({1}) à la longueur de " +"l'option leader ({2})" + +#: tiramisu/config.py:982 tiramisu/option/optiondescription.py:74 +msgid "option description seems to be part of an other config" +msgstr "l'option description semble faire parti d'une autre config" + +#: tiramisu/config.py:1144 +msgid "parent of {0} not already exists" +msgstr "le parent de {0} n'existe plus" + +#: tiramisu/config.py:1191 +msgid "cannot set leadership object has root optiondescription" +msgstr "ne peut assigner un objet leadership comme optiondescription racine" + +#: tiramisu/config.py:1194 +msgid "cannot set dynoptiondescription object has root optiondescription" +msgstr "" +"ne peut assigner un objet dynoptiondescription comme optiondescription racine" + +#: tiramisu/config.py:1246 +msgid "config name must be uniq in groupconfig for \"{0}\"" +msgstr "le nom d'un config doit être unique dans un groupconfig pour \"{0}\"" + +#: tiramisu/config.py:1457 +msgid "unknown config \"{}\"" +msgstr "config \"{}\" inconnue" + +#: tiramisu/config.py:1482 +msgid "child must be a Config, MixConfig or MetaConfig" +msgstr "l'enfant doit être une Config, MixConfig ou MetaConfig" + +#: tiramisu/config.py:1517 +msgid "" +"force_default, force_default_if_same or force_dont_change_value cannot be " +"set with only_config" +msgstr "" +"force_default, force_default_if_same ou force_dont_change_value ne peuvent " +"pas être spécifié avec only_config" + +#: tiramisu/config.py:1527 +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:1676 +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:1721 +msgid "config added has no name, the name is mandatory" +msgstr "la config ajoutée n'a pas de nom, le nom est obligatoire" + +#: tiramisu/config.py:1726 +msgid "config name \"{0}\" is not uniq in groupconfig \"{1}\"" +msgstr "" +"le nom d'un config \"{0}\" n'est pas unique dans le groupconfig \"{1}\"" + +#: tiramisu/config.py:1744 tiramisu/config.py:1750 +msgid "cannot find the config {0}" +msgstr "ne peut pas trouver la config {0}" + +#: tiramisu/config.py:1776 +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:1788 +msgid "child must be a Config or MetaConfig" +msgstr "enfant doit être une une Config ou une MetaConfig" + +#: tiramisu/config.py:1793 +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:1810 +msgid "metaconfig must have the same optiondescription" +msgstr "metaconfig doivent avoir la même optiondescription" + +#: tiramisu/error.py:31 +msgid "and" +msgstr "et" + +#: tiramisu/error.py:33 +msgid "or" +msgstr "ou" + +#: tiramisu/error.py:55 +msgid " {} " +msgstr " {} " + +#: tiramisu/error.py:108 +msgid "property" +msgstr "de la propriété" + +#: tiramisu/error.py:110 +msgid "properties" +msgstr "des propriétés" + +#: tiramisu/error.py:113 +msgid "cannot modify the {0} {1} because \"{2}\" has {3} {4}" +msgstr "ne peut modifier {0} \"{1}\" parce que \"{2}\" a {3} {4}" + +#: tiramisu/error.py:115 +msgid "cannot modify the {0} {1} because has {2} {3}" +msgstr "ne peut modifier {0} \"{1}\" à cause {2} {3}" + +#: tiramisu/error.py:118 +msgid "cannot access to {0} {1} because \"{2}\" has {3} {4}" +msgstr "ne peut accéder à {0} {1} parce que \"{2}\" a {3} {4}" + +#: tiramisu/error.py:120 +msgid "cannot access to {0} {1} because has {2} {3}" +msgstr "ne peut accéder à l'{0} {1} à cause {2} {3}" + +#: tiramisu/error.py:192 +msgid "invalid value" +msgstr "valeur invalide" + +#: tiramisu/error.py:201 +msgid "attention, \"{0}\" could be an invalid {1} for \"{2}\"" +msgstr "attention, \"{0}\" peut être un {1} invalide pour \"{2}\"" + +#: tiramisu/error.py:219 tiramisu/error.py:228 +msgid "\"{0}\" is an invalid {1} for \"{2}\"" +msgstr "\"{0}\" est une valeur invalide pour l'option \"{2}\" de type {1}" + +#: tiramisu/function.py:65 +msgid "network \"{0}\" ({1}) does not match with this netmask" +msgstr "le réseau \"{0}\" (\"{1}\") ne correspond pas avec le masque de réseau" + +#: tiramisu/function.py:83 +msgid "IP \"{0}\" ({1}) with this netmask is in fact a network address" +msgstr "" +"l'IP \"{0}\" ({1}) avec ce masque réseau est en faite une adresse réseau" + +#: tiramisu/function.py:88 +msgid "IP \"{0}\" ({1}) with this netmask is in fact a broadcast address" +msgstr "" +"l'IP \"{0}\" ({1}) avec ce masque réseau est en faite une adresse de " +"broadcast" + +#: tiramisu/function.py:106 +msgid "broadcast invalid with network {0} ({1}) and netmask {2} ({3})" +msgstr "" +"le broadcast est invalide pour le réseau {0} ({1}) et le masque réseau {2} " +"({3})" + +#: tiramisu/function.py:134 +msgid "this IP is not in network {network[\"value\"]} ({network[\"name\"]})" +msgstr "" +"cette IP n'est pas dans le réseau {network[\"value\"]} ({network[\"name\"]})" + +#: tiramisu/function.py:136 +msgid "" +"this IP is not in network {network[\"value\"]} ({network[\"name\"]}) with " +"netmask {netmask[\"value\"]} ({netmask[\"name\"]})" +msgstr "" +"cette IP n'est pas dans le réseau {network[\"value\"]} ({network[\"name\"]}) " +"avec le netmask {netmask[\"value\"]} ({netmask[\"name\"]})" + +#: tiramisu/function.py:143 +msgid "this IP with the network {0} ({1}) is in fact a network address" +msgstr "cette IP avec le réseau {0} ({1}) est un faite une adresse réseau" + +#: tiramisu/function.py:148 +msgid "this IP with the network {0} ({1}) is in fact a broadcast address" +msgstr "" +"cette IP avec le réseau {0} ({1}) est en faite une adresse de broadcast" + +#: tiramisu/function.py:165 +msgid "value is identical to {0}" +msgstr "la valeur est identique à {0}" + +#: tiramisu/function.py:400 +msgid "" +"unexpected value in calc_value with join attribute \"{0}\" with invalid " +"length \"{1}\"" +msgstr "" +"valeur inattendue dans calc_value avec l'attribute join \"{0}\" avec la " +"longueur invalide \"{1}\"" + +#: tiramisu/function.py:527 +msgid "unexpected {0} condition_operator in calc_value" +msgstr "condition_operator {0} inattendue dans la fonction calc_value" + +#: tiramisu/function.py:591 +msgid "unexpected condition_{0} must have \"todict\" argument" +msgstr "condition_{0} inattendu, doit avoir l'argument \"todict\"" + +#: tiramisu/function.py:602 +msgid "the value of \"{0}\" is {1}" +msgstr "la valeur de \"{0}\" est {1}" + +#: tiramisu/function.py:604 +msgid "the value of \"{0}\" is not {1}" +msgstr "la valeur de \"{0}\" n'est pas {1}" + +#: tiramisu/option/baseoption.py:75 tiramisu/option/symlinkoption.py:44 +msgid "\"{0}\" is an invalid name for an option" +msgstr "\"{0}\" est un nom invalide pour une option" + +#: tiramisu/option/baseoption.py:88 +msgid "invalid properties type {0} for {1}, must be a frozenset" +msgstr "type {0} invalide pour des propriétés pour {1}, doit être un frozenset" + +#: tiramisu/option/baseoption.py:98 +msgid "invalid property type {0} for {1}, must be a string or a Calculation" +msgstr "" +"type {0} invalide pour des propriétés pour {1}, doit être des caractères ou " +"un objet Calculation" + +#: tiramisu/option/baseoption.py:249 +msgid "information's item for {0} not found: \"{1}\"" +msgstr "item pour {0} dans les informations non trouvée: \"{1}\"" + +#: tiramisu/option/baseoption.py:267 +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:308 +msgid "\"{}\" ({}) object attribute \"{}\" is read-only" +msgstr "\"{}\" ({}) l'attribut de l'objet \"{}\" est en lecture seule" + +#: tiramisu/option/baseoption.py:320 +msgid "{0} not part of any Config" +msgstr "{0} ne fait pas parti d'une Config" + +#: tiramisu/option/broadcastoption.py:41 +msgid "invalid string" +msgstr "invalide caractère" + +#: tiramisu/option/choiceoption.py:47 +msgid "values must be a tuple or a calculation for {0}" +msgstr "les valeurs doivent être un tuple ou une fonction pour {0}" + +#: tiramisu/option/choiceoption.py:70 +msgid "the calculated values \"{0}\" for \"{1}\" is not a list" +msgstr "les valeurs calculées \"{0}\" pour \"{1}\" n'est pas une liste" + +#: tiramisu/option/choiceoption.py:101 +msgid "only \"{0}\" is allowed" +msgstr "seul \"{0}\" est autorisé" + +#: tiramisu/option/choiceoption.py:103 +msgid "only {0} are allowed" +msgstr "seul {0} sont autorisées" + +#: tiramisu/option/domainnameoption.py:60 +msgid "unknown type {0} for hostname" +msgstr "type_ inconnu {0} pour le nom d'hôte" + +#: tiramisu/option/domainnameoption.py:63 +msgid "allow_ip must be a boolean" +msgstr "allow_ip doit être un booléen" + +#: tiramisu/option/domainnameoption.py:65 +msgid "allow_cidr_network must be a boolean" +msgstr "allow_cidr_network doit être un booléen" + +#: tiramisu/option/domainnameoption.py:67 +msgid "allow_without_dot must be a boolean" +msgstr "allow_without_dot doit être un booléen" + +#: tiramisu/option/domainnameoption.py:69 +msgid "allow_startswith_dot must be a boolean" +msgstr "allow_startswith_dot doit être un booléen" + +#: tiramisu/option/domainnameoption.py:81 +msgid "" +"must start with lowercase characters followed by lowercase characters, " +"number, \"-\" and \".\" characters are allowed" +msgstr "" +"doit démarrer par un caractère en minuscule suivi par des caractères en " +"minuscule, des nombres, \"-\" et \".\" sont autorisés" + +#: tiramisu/option/domainnameoption.py:84 +msgid "" +"must start with lowercase characters followed by lowercase characters, " +"number, \"-\" and \".\" characters are recommanded" +msgstr "" +"doit démarrer par un caractère en minuscule suivi par des caractères en " +"minuscule, des nombres, \"-\" et \".\" sont recommandés" + +#: tiramisu/option/domainnameoption.py:88 +#: tiramisu/option/domainnameoption.py:89 +msgid "could be a IP, otherwise {}" +msgstr "peut être une IP, autrement {}" + +#: tiramisu/option/domainnameoption.py:134 +msgid "invalid length (min 1)" +msgstr "longueur invalide (min 1)" + +#: tiramisu/option/domainnameoption.py:137 +msgid "invalid length (max {0})" +msgstr "longueur invalide (max {0})" + +#: tiramisu/option/domainnameoption.py:143 +msgid "must have dot" +msgstr "doit avoir un point" + +#: tiramisu/option/domainnameoption.py:145 +msgid "invalid length (max 255)" +msgstr "longueur invalide (max 255)" + +#: tiramisu/option/domainnameoption.py:163 +msgid "must not be an IP" +msgstr "ne doit pas être une IP" + +#: tiramisu/option/domainnameoption.py:186 +msgid "some characters are uppercase" +msgstr "des caractères sont en majuscule" + +#: tiramisu/option/dynoptiondescription.py:131 +msgid "DynOptionDescription identifiers for option {0}, is not a list ({1})" +msgstr "" +"les identifiants de la DynOptionDescription pour l'option {0}, n'est pas une " +"liste ({1})" + +#: tiramisu/option/dynoptiondescription.py:142 +msgid "invalid identifier \"{}\" for option {}" +msgstr "identifiant \"{}\" invalide pour l'option \"{}\"" + +#: tiramisu/option/dynoptiondescription.py:150 +msgid "" +"DynOptionDescription \"{0}\" identifiers return a list with same values " +"\"{1}\"" +msgstr "" +"Les identifiants de la DynOptionDescription \"{0}\" retourne une liste avec " +"des valeurs identiques \"{1}\"" + +#: tiramisu/option/filenameoption.py:47 +msgid "types parameter must be a list, not \"{0}\" for \"{1}\"" +msgstr "" +"le paramètre types doit être une liste, au lieu de \"{0}\" pour \"{1}\"" + +#: tiramisu/option/filenameoption.py:67 +msgid "must starts with \"/\"" +msgstr "doit débuter par \"/\"" + +#: tiramisu/option/filenameoption.py:78 +msgid "cannot find {0} \"{1}\"" +msgstr "ne peut pas trouver {0} \"{1}\"" + +#: tiramisu/option/intoption.py:52 +msgid "value should be equal or greater than \"{0}\"" +msgstr "la valeur devrait être supérieur ou égal à {0}" + +#: tiramisu/option/intoption.py:54 +msgid "value must be equal or greater than \"{0}\"" +msgstr "valeur doit être supérieur ou égal à {0}" + +#: tiramisu/option/intoption.py:59 +msgid "value should be less than \"{0}\"" +msgstr "valeur devrait être inférieur à \"{0}\"" + +#: tiramisu/option/intoption.py:61 +msgid "value must be less than \"{0}\"" +msgstr "valeur doit être inférieur à \"{0}\"" + +#: tiramisu/option/ipoption.py:57 +msgid "it's in fact a network address" +msgstr "c'est un faite une adresse réseau" + +#: tiramisu/option/ipoption.py:59 +msgid "it's in fact a broacast address" +msgstr "c'est en faite une adresse de broadcast" + +#: tiramisu/option/ipoption.py:71 +msgid "CIDR address must have a \"/\"" +msgstr "une adresse CIDR doit avoir un \"/\"" + +#: tiramisu/option/ipoption.py:80 +msgid "shouldn't be reserved IP" +msgstr "ne devrait pas être une IP réservée" + +#: tiramisu/option/ipoption.py:82 +msgid "mustn't be reserved IP" +msgstr "ne doit pas être une IP réservée" + +#: tiramisu/option/ipoption.py:86 +msgid "should be private IP" +msgstr "devrait être une IP privée" + +#: tiramisu/option/ipoption.py:88 +msgid "must be private IP" +msgstr "doit être une IP privée" + +#: tiramisu/option/leadership.py:55 +msgid "cannot set \"group_type\" attribute for a Leadership" +msgstr "ne peut mettre l'attribut \"group_type\" pour une Leadership" + +#: tiramisu/option/leadership.py:67 +msgid "a leader and a follower are mandatories in leadership \"{}\"" +msgstr "" +"une option leader et une option suiveuse sont obligatoires dans une option " +"leadership \"{}\"" + +#: tiramisu/option/leadership.py:89 +msgid "leader cannot have \"{}\" property" +msgstr "leader ne peut avoir la propriété \"{}\"" + +#: tiramisu/option/leadership.py:101 +msgid "leadership {0} shall not have a symlinkoption" +msgstr "une option leadership \"{0}\" ne devrait pas avoir de symlinkoption" + +#: tiramisu/option/leadership.py:108 +msgid "leadership {0} shall not have a subgroup" +msgstr "une option leadership \"{0}\" ne devrait pas avoir de sous-groupe" + +#: tiramisu/option/leadership.py:114 +msgid "" +"only multi option allowed in leadership {0} but option {1} is not a multi" +msgstr "" +"seules des options multiples sont autorisées dans l'option leadership " +"\"{0}\" alors que l'option \"{1}\" n'est pas une option multiple" + +#: tiramisu/option/leadership.py:141 +msgid "not allowed default value for follower option {0} in leadership {1}" +msgstr "" +"valeur par défaut non autorisée pour l'option suiveuse {0} dans l'option " +"leadership {1}" + +#: tiramisu/option/networkoption.py:45 +msgid "must use CIDR notation" +msgstr "doit utiliser la notation CIDR" + +#: tiramisu/option/networkoption.py:60 +msgid "shouldn't be reserved network" +msgstr "ne devrait pas être une IP réservée" + +#: tiramisu/option/networkoption.py:62 +msgid "mustn't be reserved network" +msgstr "ne doit pas être une IP réservée" + +#: tiramisu/option/option.py:73 +msgid "default_multi is set whereas multi is False in option: {0}" +msgstr "" +"default_multi est spécifié alors que multi est à False pour l'option : {0}" + +#: tiramisu/option/option.py:93 +msgid "invalid multi type \"{}\" for \"{}\"" +msgstr "type multiple \"{}\" invalide pour \"{}\"" + +#: tiramisu/option/option.py:112 +msgid "validators must be a list of Calculation for \"{0}\"" +msgstr "validators doit être une liste de Calculation pour \"{0}\"" + +#: tiramisu/option/option.py:117 +msgid "validators must be a Calculation for \"{0}\"" +msgstr "validators doit être un Calculation pour \"{0}\"" + +#: tiramisu/option/option.py:146 +msgid "invalid default_multi value \"{0}\" for option {1}" +msgstr "la valeur default_multi est invalide {0} pour l'option {1}" + +#: tiramisu/option/option.py:154 +msgid "invalid default_multi value \"{0}\" for option {1}, {2}" +msgstr "la valeur default_multi est invalide \"{0}\" pour l'option {1}, {2}" + +#: tiramisu/option/option.py:167 +msgid "" +"invalid default_multi value \"{0}\" for option {1}, must be a list for a " +"submulti" +msgstr "" +"valeur invalide pour default_multi \"{0}\" pour l'option {1}, doit être une " +"liste pour une submulti" + +#: tiramisu/option/option.py:290 +msgid "the value \"{}\" is not unique" +msgstr "la valeur de \"{}\" n'est pas unique" + +#: tiramisu/option/option.py:352 +msgid "which must not be a list" +msgstr "qui ne doit pas être une liste" + +#: tiramisu/option/option.py:404 tiramisu/option/option.py:430 +msgid "which must be a list" +msgstr "qui doit être une liste" + +#: tiramisu/option/option.py:424 +msgid "which \"{}\" must be a list of list" +msgstr "lequel \"{}\" doit être une liste de liste" + +#: tiramisu/option/optiondescription.py:109 +msgid "duplicate option: {0}" +msgstr "option dupliquée : {0}" + +#: tiramisu/option/optiondescription.py:244 +msgid "" +"unknown option \"{0}\" in root optiondescription (it's a dynamic option)" +msgstr "" +"option \"{0}\" inconnue dans l'optiondescription racine (c'est une option " +"dynamique)" + +#: tiramisu/option/optiondescription.py:279 +msgid "unknown option \"{0}\" in root optiondescription" +msgstr "option \"{0}\" inconnue dans l'optiondescription racine" + +#: tiramisu/option/optiondescription.py:282 +msgid "unknown option \"{0}\" in optiondescription {1}" +msgstr "option \"{0}\" inconnue dans l'optiondescription {1}" + +#: tiramisu/option/optiondescription.py:338 +msgid "children in optiondescription \"{}\" must be a list" +msgstr "les enfants d'une optiondescription \"{}\" doivent être une liste" + +#: tiramisu/option/optiondescription.py:366 +msgid "duplicate option name: \"{0}\"" +msgstr "nom de l'option dupliqué : \"{0}\"" + +#: tiramisu/option/optiondescription.py:372 +msgid "" +"the option's name \"{0}\" start as the dynoptiondescription's name \"{1}\"" +msgstr "" +"le nom de l'option \"{0}\" commence comme le nom du dynoptiondescription " +"\"{1}\"" + +#: tiramisu/option/optiondescription.py:415 +msgid "cannot change group_type if already set (old {0}, new {1})" +msgstr "ne peut changer group_type si déjà spécifié (ancien {0}, nouveau {1})" + +#: tiramisu/option/optiondescription.py:420 +msgid "group_type: {0} not allowed" +msgstr "group_type : {0} non autorisé" + +#: tiramisu/option/permissionsoption.py:52 +msgid "only 3 or 4 octal digits are allowed" +msgstr "seulement 3 ou 4 chiffres octal sont autorisées" + +#: tiramisu/option/permissionsoption.py:63 +msgid "user" +msgstr "nom d'utilisateur" + +#: tiramisu/option/permissionsoption.py:64 +#: tiramisu/option/permissionsoption.py:66 +msgid "group" +msgstr "groupe" + +#: tiramisu/option/permissionsoption.py:67 +msgid "other" +msgstr "autre" + +#: tiramisu/option/permissionsoption.py:68 +msgid "{0} has more right than {1}" +msgstr "{0} a plus de droit que {1}" + +#: tiramisu/option/permissionsoption.py:71 +msgid "too weak" +msgstr "trop simple" + +#: tiramisu/option/portoption.py:74 +msgid "inconsistency in allowed range" +msgstr "inconsistence dans la plage autorisée" + +#: tiramisu/option/portoption.py:79 +msgid "max value is empty" +msgstr "la valeur maximum est vide" + +#: tiramisu/option/portoption.py:92 +msgid "range must have two values only" +msgstr "un rang doit avoir deux valeurs seulement" + +#: tiramisu/option/portoption.py:95 +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:121 +msgid "should be between {0} and {1}" +msgstr "devrait être une nombre entre {0} et {1}" + +#: tiramisu/option/portoption.py:123 +msgid "must be between {0} and {1}" +msgstr "doit être une nombre entre {0} et {1}" + +#: tiramisu/option/symlinkoption.py:51 +msgid "" +"malformed symlink second parameters must be an option for \"{0}\", not {1}" +msgstr "" +"symlink mal formé, le second paramètre doit être une option pour \"{0}\", " +"not {1}" + +#: tiramisu/option/urloption.py:91 +msgid "must start with http:// or https://" +msgstr "doit débuter par http:// ou https://" + +#: tiramisu/option/urloption.py:119 +msgid "must ends with a valid resource name" +msgstr "doit finir par un nom de ressource valide" + +#: tiramisu/setting.py:255 +msgid "can't rebind {0}" +msgstr "ne peut redéfinir ({0})" + +#: tiramisu/setting.py:262 +msgid "can't unbind {0}" +msgstr "ne peut supprimer ({0})" + +#: tiramisu/setting.py:464 +msgid "" +"invalid property type {type(new_prop)} for {subconfig.option.impl_getname()} " +"with {prop.function.__name__} function" +msgstr "" +"type {type(new_prop)} de la propriété invalide pour la fonction {subconfig." +"option.impl_getname()} with {prop.function.__name__}" + +#: tiramisu/setting.py:476 +msgid "leader cannot have \"{new_prop}\" property" +msgstr "une option leader ne peu avoir la propriété \"{new_prop}\"" + +#: tiramisu/setting.py:564 +msgid "leader cannot have \"{0}\" property" +msgstr "leader ne peut avoir la propriété \"{0}\"" + +#: tiramisu/setting.py:573 +msgid "" +"a leader ({0}) cannot have \"force_default_on_freeze\" or " +"\"force_metaconfig_on_freeze\" property without \"frozen\"" +msgstr "" +"une option leader ({0}) ne peut avoir de propriété " +"\"force_default_on_freeze\" or \"force_metaconfig_on_freeze\" sans \"frozen\"" + +#: tiramisu/setting.py:607 +msgid "permissive must be a frozenset" +msgstr "une permissive doit être de type frozenset" + +#: tiramisu/setting.py:617 +msgid "cannot add those permissives: {0}" +msgstr "ne peut ajouter ces permissives : {0}" + +#: tiramisu/setting.py:654 +msgid "can't reset properties to the symlinkoption \"{}\"" +msgstr "ne peut réinitialiser les propriétés de la symlinkoption \"{}\"" + +#: tiramisu/setting.py:667 +msgid "can't reset permissives to the symlinkoption \"{}\"" +msgstr "ne peut réinitialiser les permissive de la symlinkoption \"{}\"" + +#: tiramisu/todict.py:395 +msgid "option {} only works when remotable is not \"none\"" +msgstr "l'option {} ne fonctionne que si remotable n'est pas \"none\"" + +#: tiramisu/todict.py:561 +msgid "unable to transform tiramisu object to dict: {}" +msgstr "impossible de transformer l'objet tiramisu en dict : {}" + +#: tiramisu/todict.py:876 tiramisu/todict.py:1033 +msgid "unknown form {}" +msgstr "form {} inconnu" + +#: tiramisu/todict.py:923 +msgid "not in current area" +msgstr "n'est pas dans l'espace courant" + +#: tiramisu/todict.py:947 +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:953 +msgid "unknown action {}" +msgstr "action inconnue {}" + +#: tiramisu/value.py:564 tiramisu/value.py:861 +msgid "set owner \"{0}\" is forbidden" +msgstr "assigner l'utilisateur \"{0}\" est interdit" + +#: tiramisu/value.py:571 +msgid "\"{0}\" is a default value, so we cannot change owner to \"{1}\"" +msgstr "" +"\"{0}\" est une valeur par défaut, donc ne peut changer d'utilisateur à " +"\"{1}\"" + +#: tiramisu/value.py:740 +msgid "" +"index {index} is greater than the length {length} for option {subconfig." +"option.impl_get_display_name(with_quote=True)}" +msgstr "" +"l'index {index} est supérieur à la longueur \"{length}\" pour l'option " +"\"{subconfig.option.impl_get_display_name(with_quote=True)}\"" + +#: tiramisu/value.py:847 +msgid "information's item not found \"{}\"" +msgstr "l'information de l'objet ne sont pas trouvé \"{}\"" + +#~ msgid "" +#~ "IP \"{ip[\"value\"]}\" ({ip[\"name\"]}) with this netmask is in fact a " +#~ "broacast address" +#~ msgstr "" +#~ "l'IP \"{0}\" ({1]}) avec le masque réseau est en faire une adresse " +#~ "broadcast" + +#~ msgid "Call: {}" +#~ msgstr "Appel : {}" + +#~ msgid "option must not be an optiondescription" +#~ msgstr "option ne doit pas être une optiondescription" + +#~ msgid "index must be set with the follower option \"{}\"" +#~ msgstr "l'index est obligatoire pour l'option suiveuse \"{}\"" + +#~ msgid "unknown method {} in {}" +#~ msgstr "méthode {} inconnue dans {}" + +#~ msgid "can't delete a SymLinkOption" +#~ msgstr "ne peut supprimer une valeur à une SymLinkOption" + +#~ msgid "unknown config type {}" +#~ msgstr "type de config {} inconnue" + +#~ msgid "unknown list type {}" +#~ msgstr "type de liste inconnue {}" + +#~ msgid "unknown group_type: {0}" +#~ msgstr "group_type inconnu: {0}" + +#~ msgid "cannot set session_id and config together" +#~ msgstr "session_id et config ne peut être mis ensemble" + +#~ msgid "\"{0}\" must be an optiondescription, not an {1}" +#~ msgstr "\"{0}\" doit être une optiondescription, et non {1}" + +#~ msgid "unknown option {}" +#~ msgstr "option {} inconnue" + +#~ msgid "can't assign to a SymLinkOption" +#~ msgstr "ne peut assigner une valeur à une SymLinkOption" + +#~ msgid "make_dict can't filtering with value without option" +#~ msgstr "make_dict ne peut filtrer sur une valeur mais sans option" + +#~ msgid "unexpected path \"{0}\", should start with \"{1}\"" +#~ msgstr "chemin inconsistant \"{0}\", devrait commencé par \"{1}\"" + +#~ msgid "cannot duplicate {}" +#~ msgstr "ne peut dupliquer : {0}" + +#~ msgid "invalid session ID: {0} for config" +#~ msgstr "ID de session invalide : {0} pour une config" + +#~ msgid "groupconfig's children must be a list" +#~ msgstr "enfants d'une groupconfig doit être une liste" + +#~ msgid "groupconfig's children must be Config, MetaConfig or GroupConfig" +#~ msgstr "" +#~ "les enfants d'un groupconfig doivent être des Config, MetaConfig ou " +#~ "GroupConfig" + +#~ msgid "conflict: properties already set in requirement {0} for {1}" +#~ msgstr "" +#~ "conflit : les propriétés sont déjà mis dans les requirements {0} pour {1}" + +#~ msgid "{0}_params must be a params" +#~ msgstr "{0}_params doit être un params" + +#~ msgid "missing those arguments \"{}\" in function \"{}\" for \"{}\"" +#~ msgstr "" +#~ "les arguments \"{}\" sont manquant dans la fonction \"{}\" pour \"{}\"" + +#~ msgid "" +#~ "params defined for a callback function but no callback defined yet for " +#~ "option \"{0}\"" +#~ msgstr "" +#~ "paramètres définis pour la fonction de callback mais aucun callback " +#~ "défini pour l'option \"{0}\"" + +#~ msgid "malformed requirements must be an option in option {0}" +#~ msgstr "requirements mal formés doit être une option dans l'option {0}" + +#~ msgid "" +#~ "malformed requirements multi option must not set as requires of non multi " +#~ "option {0}" +#~ msgstr "" +#~ "requirements mal formés une option multiple ne doit pas être spécifié " +#~ "comme pré-requis à l'option non multiple {0}" + +#~ 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}" + +#~ 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}" + +#~ 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" + +#~ 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" + +#~ msgid "malformed requirements for option: {0} transitive must be boolean" +#~ msgstr "" +#~ "requirements mal formés pour l'option : {0} transitive doit être booléen" + +#~ 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" + +#~ 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\"" + +#~ msgid "malformed requirements type for option: {0}, must be a dict" +#~ msgstr "" +#~ "type requirements malformé pour l'option : {0}, doit être un dictionnaire" + +#~ 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}" + +#~ msgid "" +#~ "malformed requirements for option: {0} require must have option, expected " +#~ "and action keys" +#~ msgstr "" +#~ "requirements malformé pour l'option : {0} l'exigence doit avoir les clefs " +#~ "option, expected et action" + +#~ msgid "boolean" +#~ msgstr "booléen" + +#~ msgid "invalid broadcast consistency, a network and a netmask are needed" +#~ msgstr "" +#~ "adresse de broadcast inconsistante, un réseau et un masque sont " +#~ "nécessaires." + +#~ msgid "choice" +#~ msgstr "choix" + +#~ 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" + +#~ msgid "date" +#~ msgstr "date" + +#~ msgid "domain name" +#~ msgstr "nom de domaine" + +#~ msgid "only lowercase, number and - are characters are allowed" +#~ msgstr "" +#~ "seuls les caractères en minuscule, les nombres et \"-\" sont autorisés" + +#~ msgid "only lowercase, number and \"-\" are characters are recommanded" +#~ msgstr "" +#~ "seuls les caractères en minuscule, les nombres et \"-\" sont recommandés" + +#~ msgid "cannot set symlinkoption in a dynoptiondescription" +#~ msgstr "ne peut mettre une symlinkoption dans une dynoptiondescription" + +#~ msgid "callback is mandatory for the dynoptiondescription \"{}\"" +#~ msgstr "un callback est obligatoire pour le dynoptiondescription \"{}\"" + +#~ msgid "email address" +#~ msgstr "adresse mail" + +#~ msgid "file name" +#~ msgstr "nom de fichier" + +#~ msgid "float" +#~ msgstr "nombre flottant" + +#~ msgid "integer" +#~ msgstr "nombre" + +#~ msgid "IP" +#~ msgstr "IP" + +#~ msgid "IP not in network \"{0}\" (\"{1}\")" +#~ msgstr "l'IP n'est pas dans le réseau \"{0}\" (\"{1}\")" + +#~ 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" + +#~ msgid "IP not in network \"{2}\"/\"{4}\" (\"{3}\"/\"{5}\")" +#~ msgstr "l'IP n'est pas dans le réseau \"{2}\"/\"{4}\" (\"{3}\"/\"{5}\")" + +#~ msgid "" +#~ "the network doest not match with IP \"{0}\" (\"{1}\") and network \"{4}\" " +#~ "(\"{5}\")" +#~ msgstr "" +#~ "le réseau ne correspond pas à l'IP \"{0}\" (\"{1}\") et au réseau \"{4}\" " +#~ "(\"{5}\")" + +#~ msgid "" +#~ "the netmask does not match with IP \"{0}\" (\"{1}\") and broadcast " +#~ "\"{2}\" (\"{3}\")" +#~ msgstr "" +#~ "le masque de réseau ne correspond pas à l'IP \"{0}\" (\"{1}\") et au " +#~ "broadcast \"{2}\" (\"{3}\")" + +#~ msgid "callback of leader's option shall not refered to a follower's ones" +#~ msgstr "" +#~ "callback d'une variable leader ne devrait pas référencer une variable " +#~ "suiveuse" + +#~ msgid "leader {} have requirement, but Leadership {} too" +#~ msgstr "" +#~ "l'option leader {} a des requirements mais l'option leadership {} " +#~ "également" + +#~ msgid "" +#~ "malformed requirements option \"{0}\" must not be in follower for \"{1}\"" +#~ msgstr "" +#~ "requirement mal formé pour l'option \"{0}\" ne doit pas être dans une " +#~ "suiveuse pour \"{1}\"" + +#~ msgid "netmask address" +#~ msgstr "adresse netmask" + +#~ msgid "network_netmask needs a network and a netmask" +#~ msgstr "network_netmask nécessite un réseau et un masque de réseau" + +#~ msgid "the netmask \"{0}\" (\"{1}\") does not match" +#~ msgstr "le masque \"{0}\" (\"{1}\") ne correspond pas" + +#~ msgid "ip_netmask needs an IP and a netmask" +#~ msgstr "ip_netmask nécessite une IP et un masque de réseau" + +#~ msgid "this is a network with netmask \"{0}\" (\"{1}\")" +#~ msgstr "c'est une adresse réseau avec le masque \"{0}\" (\"{1}\")" + +#~ msgid "this is a broadcast with netmask \"{0}\" (\"{1}\")" +#~ msgstr "c'est une adresse broadcast avec le masque \"{0}\" (\"{1}\")" + +#~ msgid "IP \"{0}\" (\"{1}\") is the network" +#~ msgstr "IP \"{0}\" (\"{1}\") est le réseau" + +#~ msgid "IP \"{0}\" (\"{1}\") is the broadcast" +#~ msgstr "IP \"{0}\" (\"{1}\") est l'adresse de broadcast" + +#~ msgid "unique must be a boolean, not \"{}\"" +#~ msgstr "unique doit être un booléan, pas \"{}\"" + +#~ msgid "unique must be set only with multi value" +#~ msgstr "unique doit être activé uniquement avec une valeur multiple" + +#~ msgid "invalid value \"{}\", this value is already in \"{}\"" +#~ msgstr "valeur invalide \"{}\", cette valeur est déjà dans \"{}\"" + +#~ 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" + +#~ msgid "'{0}' ({1}) cannot add consistency, option is read-only" +#~ msgstr "" +#~ "'{0}' ({1}) ne peut ajouter de consistency, l'option est en lecture seul" + +#~ msgid "consistency {0} not available for this option" +#~ msgstr "consistency {0} non valable pour cette option" + +#~ msgid "unknown parameter {0} in consistency" +#~ msgstr "paramètre inconnu {0} dans un test de consistance" + +#~ msgid "cannot add consistency with submulti option" +#~ msgstr "ne peut ajouter de test de consistence a une option submulti" + +#~ msgid "consistency must be set with an option, not {}" +#~ msgstr "" +#~ "test de consistence doit être renseigné avec une option, et non avec {}" + +#~ 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" + +#~ msgid "option in consistency must be in same dynoptiondescription" +#~ msgstr "" +#~ "option dans une consistency doit être dans le même dynoptiondescription" + +#~ msgid "cannot add consistency with itself" +#~ msgstr "ne peut ajouter une consistency avec lui même" + +#~ 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" + +#~ msgid "unexpected length of \"{}\" in constency \"{}\", should be \"{}\"" +#~ msgstr "" +#~ "longueur inconsistante pour \"{}\" dans le test de consistence \"{}\", " +#~ "devrait être \"{}\"" + +#~ msgid "should be different from the value of {}" +#~ msgstr "devrait être différent de la valeur de {}" + +#~ msgid "must be different from the value of {}" +#~ msgstr "doit être différent de la valeur de {}" + +#~ msgid "value for {} should be different" +#~ msgstr "valeur pour {} devrait être différent" + +#~ msgid "value for {} must be different" +#~ msgstr "valeur pour {} doit être différent" + +#~ msgid "the dynoption \"{0}\" cannot have \"force_store_value\" property" +#~ msgstr "" +#~ "la dynoption \"{0}\" ne peut avoir la propriété \"force_store_value\"" + +#~ msgid "malformed consistency option \"{0}\" must be in same leadership" +#~ msgstr "" +#~ "test de consistance mal formé pour l'option \"{0}\" doit être dans la " +#~ "même option leadership" + +#~ msgid "malformed consistency option \"{0}\" must not be a multi for \"{1}\"" +#~ msgstr "" +#~ "test de consistence mal formé pour l'option \"{0}\" ne doit doit pas être " +#~ "une liste pour \"{1}\"" + +#~ msgid "" +#~ "malformed consistency option \"{0}\" must be in same leadership as \"{1}\"" +#~ msgstr "" +#~ "test de consistance mal formé pour l'option \"{0}\" doit être dans la " +#~ "même option leadership que \"{1}\"" + +#~ msgid "" +#~ "malformed requirements option \"{0}\" must be in same leadership for " +#~ "\"{1}\"" +#~ msgstr "" +#~ "requirements mal formé pour l'option \"{0}\" doit être dans la même " +#~ "option leadership que \"{1}\"" + +#~ msgid "" +#~ "malformed requirements option \"{0}\" must not be a multi for \"{1}\"" +#~ msgstr "" +#~ "requirement mal formés pour l'option \"{0}\" ne doit pas être une valeur " +#~ "multiple pour \"{1}\"" + +#~ msgid "consistency with option {0} which is not in Config" +#~ msgstr "consistency avec l'option {0} qui n'est pas dans une Config" + +#~ msgid "password" +#~ msgstr "mot de passe" + +#~ msgid "port" +#~ msgstr "port" + +#~ msgid "string" +#~ msgstr "texte" + +#~ msgid "unknown option \"{0}\" in syndynoptiondescription \"{1}\"" +#~ msgstr "l'option \"{0}\" inconnue dans la syndynoptiondescription \"{1}\"" + +#~ msgid "URL" +#~ msgstr "URL" + +#~ msgid "port must be an between 0 and 65536" +#~ msgstr "port doit être entre 0 et 65536" + +#~ msgid "" +#~ "malformed requirements imbrication detected for option: '{0}' with " +#~ "requirement on: '{1}'" +#~ msgstr "" +#~ "imbrication de requirements mal formés detectée pour l'option : '{0}' " +#~ "avec requirement sur : '{1}'" + +#~ msgid "the calculated value is {0}" +#~ msgstr "valeurs calculées est {0}" + +#~ msgid "the calculated value is not {0}" +#~ msgstr "valeurs calculées n'est pas {0}" + +#~ 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" + +#~ msgid "can't assign property to the symlinkoption \"{}\"" +#~ msgstr "ne peut assigner une propriété à une symlinkoption \"{}\"" + +#~ msgid "can't assign permissive to the symlinkoption \"{}\"" +#~ msgstr "ne peut assigner une permissive à la symlinkoption \"{}\"" + +#~ msgid "cannot import the storage {0}" +#~ msgstr "ne peut pas importer le stockage {0}" + +#~ msgid "storage_type is already set, cannot rebind it" +#~ msgstr "storage_type est déjà défini, impossible de le redéfinir" + +#~ msgid "session \"{}\" already exists" +#~ msgstr "la session \"{}\" existe déjà" + +#~ msgid "a dictionary cannot be persistent" +#~ msgstr "un espace de stockage dictionary ne peut être persistant" + +#~ msgid "cannot delete none persistent session" +#~ 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" + +#~ msgid "context is not supported from now for {}" +#~ msgstr "context n'est pas supporté maintenant pour {}" + +#~ msgid "can't set owner for the symlinkoption \"{}\"" +#~ msgstr "ne peut spécifier d'utilisateur à la symlinkoption \"{}\"" + +#~ msgid "please use .dict() before .updates()" +#~ msgstr "faire .dict() avant .updates()" + +#~ msgid "{}config's children should be config, not {}" +#~ msgstr "enfants d'un {}config doit être une config, pas {}" + +#~ msgid "child has already a {}config's" +#~ msgstr "enfant a déjà un {}config" + +#~ msgid "config is already in a metaconfig" +#~ msgstr "la config est déjà dans une metaconfig" + +#~ msgid "some characters may cause problems" +#~ msgstr "des caractères peuvent poser problèmes" + +#~ msgid "\"{0}\" is not in network \"{1}\" (\"{2}\")" +#~ msgstr "\"{0}\" n'est pas dans le réseau \"{1}\" (\"{2}\")" + +#~ msgid "invalid len for vals" +#~ msgstr "longueur invalide pour vals" diff --git a/locale/tiramisu.pot b/locale/tiramisu.pot new file mode 100644 index 0000000..4a37617 --- /dev/null +++ b/locale/tiramisu.pot @@ -0,0 +1,811 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR ORGANIZATION +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2024-10-30 13:15+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: pygettext.py 1.5\n" + + +#: tiramisu/api.py:79 +msgid "Settings:" +msgstr "" + +#: tiramisu/api.py:83 +msgid "Access to option without verifying permissive properties" +msgstr "" + +#: tiramisu/api.py:88 +msgid "Access to option without property restriction" +msgstr "" + +#: tiramisu/api.py:93 +msgid "Do not warnings during validation" +msgstr "" + +#: tiramisu/api.py:97 +msgid "Commands:" +msgstr "" + +#: tiramisu/api.py:111 tiramisu/api.py:1840 +msgid "please specify a valid sub function ({0}.{1})" +msgstr "" + +#: tiramisu/api.py:194 +msgid "please do not specify index ({0}.{1})" +msgstr "" + +#: tiramisu/api.py:199 tiramisu/api.py:844 +msgid "please specify index with a follower option ({0}.{1})" +msgstr "" + +#: tiramisu/api.py:220 +msgid "please specify a valid sub function ({0}.{1}): {2}" +msgstr "" + +#: tiramisu/api.py:431 +msgid "the option {0} is not a dynamic option, cannot get identifiers with only_self parameter to True" +msgstr "" + +#: tiramisu/api.py:517 +msgid "cannot get option from a follower symlink without index" +msgstr "" + +#: tiramisu/api.py:592 +msgid "cannot add this property: \"{0}\"" +msgstr "" + +#: tiramisu/api.py:619 +msgid "cannot remove option's property \"{0}\", use permissive instead in option \"{1}\"" +msgstr "" + +#: tiramisu/api.py:623 +msgid "cannot find \"{0}\" in option \"{1}\"" +msgstr "" + +#: tiramisu/api.py:628 +msgid "cannot remove option's property \"{0}\", use permissive instead in option \"{1}\" at index \"{2}\"" +msgstr "" + +#: tiramisu/api.py:632 +msgid "cannot find \"{0}\" in option \"{1}\" at index \"{2}\"" +msgstr "" + +#: tiramisu/api.py:676 +msgid "cannot find \"{0}\"" +msgstr "" + +#: tiramisu/api.py:808 +msgid "cannot reduce length of the leader {}" +msgstr "" + +#: tiramisu/api.py:861 +msgid "only multi value has defaultmulti" +msgstr "" + +#: tiramisu/api.py:1020 +msgid "please specify a valid sub function ({0}.{1}) for {2}" +msgstr "" + +#: tiramisu/api.py:1407 +msgid "properties must be a frozenset" +msgstr "" + +#: tiramisu/api.py:1411 tiramisu/api.py:1438 +msgid "unknown when {} (must be in append or remove)" +msgstr "" + +#: tiramisu/api.py:1424 tiramisu/api.py:1448 tiramisu/config.py:1680 +msgid "unknown type {}" +msgstr "" + +#: tiramisu/api.py:1812 +msgid "do not use unrestraint, nowarnings or forcepermissive together" +msgstr "" + +#: tiramisu/autolib.py:80 +msgid "args in params must be a tuple" +msgstr "" + +#: tiramisu/autolib.py:83 tiramisu/autolib.py:88 +msgid "arg in params must be a Param" +msgstr "" + +#: tiramisu/autolib.py:85 +msgid "kwargs in params must be a dict" +msgstr "" + +#: tiramisu/autolib.py:113 +msgid "paramoption needs an option not {}" +msgstr "" + +#: tiramisu/autolib.py:119 +msgid "param must have a boolean not a {} for notraisepropertyerror" +msgstr "" + +#: tiramisu/autolib.py:122 +msgid "param must have a boolean not a {} for raisepropertyerror" +msgstr "" + +#: tiramisu/autolib.py:212 +msgid "option in ParamInformation cannot be a symlinkoption" +msgstr "" + +#: tiramisu/autolib.py:215 +msgid "option in ParamInformation cannot be a follower" +msgstr "" + +#: tiramisu/autolib.py:218 +msgid "option in ParamInformation cannot be a dynamic option" +msgstr "" + +#: tiramisu/autolib.py:279 +msgid "first argument ({0}) must be a function" +msgstr "" + +#: tiramisu/autolib.py:283 +msgid "help_function ({0}) must be a function" +msgstr "" + +#: tiramisu/autolib.py:452 tiramisu/autolib.py:514 +msgid "unable to carry out a calculation for {}, {}" +msgstr "" + +#: tiramisu/autolib.py:461 tiramisu/autolib.py:521 +msgid "the option {0} is used in a calculation but is invalid ({1})" +msgstr "" + +#: tiramisu/autolib.py:477 tiramisu/autolib.py:535 tiramisu/autolib.py:584 +msgid "unable to get value for calculating {0}, {1}" +msgstr "" + +#: tiramisu/autolib.py:601 +msgid "option {0} is not a dynoptiondescription or in a dynoptiondescription" +msgstr "" + +#: tiramisu/autolib.py:848 +msgid "the \"{}\" function with positional arguments \"{}\" and keyword arguments \"{}\" must not return a list (\"{}\") for the follower option {}" +msgstr "" + +#: tiramisu/autolib.py:863 +msgid "the \"{}\" function must not return a list (\"{}\") for the follower option {}" +msgstr "" + +#: tiramisu/autolib.py:904 +msgid "unexpected error \"{0}\" in function \"{1}\" with arguments \"{3}\" and \"{4}\" for option {2}" +msgstr "" + +#: tiramisu/autolib.py:915 +msgid "unexpected error \"{0}\" in function \"{1}\" for option {2}" +msgstr "" + +#: tiramisu/config.py:419 +msgid "index \"{0}\" is greater than the leadership length \"{1}\" for option {2}" +msgstr "" + +#: tiramisu/config.py:579 +msgid "there is no option description for this config (may be GroupConfig)" +msgstr "" + +#: tiramisu/config.py:668 +msgid "no option found in config with these criteria" +msgstr "" + +#: tiramisu/config.py:871 +msgid "the follower option {0} has greater length ({1}) than the leader length ({2})" +msgstr "" + +#: tiramisu/config.py:982 tiramisu/option/optiondescription.py:74 +msgid "option description seems to be part of an other config" +msgstr "" + +#: tiramisu/config.py:1144 +msgid "parent of {0} not already exists" +msgstr "" + +#: tiramisu/config.py:1191 +msgid "cannot set leadership object has root optiondescription" +msgstr "" + +#: tiramisu/config.py:1194 +msgid "cannot set dynoptiondescription object has root optiondescription" +msgstr "" + +#: tiramisu/config.py:1246 +msgid "config name must be uniq in groupconfig for \"{0}\"" +msgstr "" + +#: tiramisu/config.py:1457 +msgid "unknown config \"{}\"" +msgstr "" + +#: tiramisu/config.py:1482 +msgid "child must be a Config, MixConfig or MetaConfig" +msgstr "" + +#: tiramisu/config.py:1517 +msgid "force_default, force_default_if_same or force_dont_change_value cannot be set with only_config" +msgstr "" + +#: tiramisu/config.py:1527 +msgid "force_default and force_dont_change_value cannot be set together" +msgstr "" + +#: tiramisu/config.py:1676 +msgid "config name must be uniq in groupconfig for {0}" +msgstr "" + +#: tiramisu/config.py:1721 +msgid "config added has no name, the name is mandatory" +msgstr "" + +#: tiramisu/config.py:1726 +msgid "config name \"{0}\" is not uniq in groupconfig \"{1}\"" +msgstr "" + +#: tiramisu/config.py:1744 tiramisu/config.py:1750 +msgid "cannot find the config {0}" +msgstr "" + +#: tiramisu/config.py:1776 +msgid "MetaConfig with optiondescription must have string has child, not {}" +msgstr "" + +#: tiramisu/config.py:1788 +msgid "child must be a Config or MetaConfig" +msgstr "" + +#: tiramisu/config.py:1793 +msgid "all config in metaconfig must have the same optiondescription" +msgstr "" + +#: tiramisu/config.py:1810 +msgid "metaconfig must have the same optiondescription" +msgstr "" + +#: tiramisu/error.py:31 +msgid "and" +msgstr "" + +#: tiramisu/error.py:33 +msgid "or" +msgstr "" + +#: tiramisu/error.py:55 +msgid " {} " +msgstr "" + +#: tiramisu/error.py:108 +msgid "property" +msgstr "" + +#: tiramisu/error.py:110 +msgid "properties" +msgstr "" + +#: tiramisu/error.py:113 +msgid "cannot modify the {0} {1} because \"{2}\" has {3} {4}" +msgstr "" + +#: tiramisu/error.py:115 +msgid "cannot modify the {0} {1} because has {2} {3}" +msgstr "" + +#: tiramisu/error.py:118 +msgid "cannot access to {0} {1} because \"{2}\" has {3} {4}" +msgstr "" + +#: tiramisu/error.py:120 +msgid "cannot access to {0} {1} because has {2} {3}" +msgstr "" + +#: tiramisu/error.py:192 +msgid "invalid value" +msgstr "" + +#: tiramisu/error.py:201 +msgid "attention, \"{0}\" could be an invalid {1} for \"{2}\"" +msgstr "" + +#: tiramisu/error.py:219 tiramisu/error.py:228 +msgid "\"{0}\" is an invalid {1} for \"{2}\"" +msgstr "" + +#: tiramisu/function.py:65 +msgid "network \"{0}\" ({1}) does not match with this netmask" +msgstr "" + +#: tiramisu/function.py:83 +msgid "IP \"{0}\" ({1}) with this netmask is in fact a network address" +msgstr "" + +#: tiramisu/function.py:88 +msgid "IP \"{0}\" ({1}) with this netmask is in fact a broadcast address" +msgstr "" + +#: tiramisu/function.py:106 +msgid "broadcast invalid with network {0} ({1}) and netmask {2} ({3})" +msgstr "" + +#: tiramisu/function.py:134 +msgid "this IP is not in network {network[\"value\"]} ({network[\"name\"]})" +msgstr "" + +#: tiramisu/function.py:136 +msgid "this IP is not in network {network[\"value\"]} ({network[\"name\"]}) with netmask {netmask[\"value\"]} ({netmask[\"name\"]})" +msgstr "" + +#: tiramisu/function.py:143 +msgid "this IP with the network {0} ({1}) is in fact a network address" +msgstr "" + +#: tiramisu/function.py:148 +msgid "this IP with the network {0} ({1}) is in fact a broadcast address" +msgstr "" + +#: tiramisu/function.py:165 +msgid "value is identical to {0}" +msgstr "" + +#: tiramisu/function.py:400 +msgid "unexpected value in calc_value with join attribute \"{0}\" with invalid length \"{1}\"" +msgstr "" + +#: tiramisu/function.py:527 +msgid "unexpected {0} condition_operator in calc_value" +msgstr "" + +#: tiramisu/function.py:591 +msgid "unexpected condition_{0} must have \"todict\" argument" +msgstr "" + +#: tiramisu/function.py:602 +msgid "the value of \"{0}\" is {1}" +msgstr "" + +#: tiramisu/function.py:604 +msgid "the value of \"{0}\" is not {1}" +msgstr "" + +#: tiramisu/option/baseoption.py:75 tiramisu/option/symlinkoption.py:44 +msgid "\"{0}\" is an invalid name for an option" +msgstr "" + +#: tiramisu/option/baseoption.py:88 +msgid "invalid properties type {0} for {1}, must be a frozenset" +msgstr "" + +#: tiramisu/option/baseoption.py:98 +msgid "invalid property type {0} for {1}, must be a string or a Calculation" +msgstr "" + +#: tiramisu/option/baseoption.py:249 +msgid "information's item for {0} not found: \"{1}\"" +msgstr "" + +#: tiramisu/option/baseoption.py:267 +msgid "'{0}' ({1}) object attribute '{2}' is read-only" +msgstr "" + +#: tiramisu/option/baseoption.py:308 +msgid "\"{}\" ({}) object attribute \"{}\" is read-only" +msgstr "" + +#: tiramisu/option/baseoption.py:320 +msgid "{0} not part of any Config" +msgstr "" + +#: tiramisu/option/broadcastoption.py:41 +msgid "invalid string" +msgstr "" + +#: tiramisu/option/choiceoption.py:47 +msgid "values must be a tuple or a calculation for {0}" +msgstr "" + +#: tiramisu/option/choiceoption.py:70 +msgid "the calculated values \"{0}\" for \"{1}\" is not a list" +msgstr "" + +#: tiramisu/option/choiceoption.py:101 +msgid "only \"{0}\" is allowed" +msgstr "" + +#: tiramisu/option/choiceoption.py:103 +msgid "only {0} are allowed" +msgstr "" + +#: tiramisu/option/domainnameoption.py:60 +msgid "unknown type {0} for hostname" +msgstr "" + +#: tiramisu/option/domainnameoption.py:63 +msgid "allow_ip must be a boolean" +msgstr "" + +#: tiramisu/option/domainnameoption.py:65 +msgid "allow_cidr_network must be a boolean" +msgstr "" + +#: tiramisu/option/domainnameoption.py:67 +msgid "allow_without_dot must be a boolean" +msgstr "" + +#: tiramisu/option/domainnameoption.py:69 +msgid "allow_startswith_dot must be a boolean" +msgstr "" + +#: tiramisu/option/domainnameoption.py:81 +msgid "must start with lowercase characters followed by lowercase characters, number, \"-\" and \".\" characters are allowed" +msgstr "" + +#: tiramisu/option/domainnameoption.py:84 +msgid "must start with lowercase characters followed by lowercase characters, number, \"-\" and \".\" characters are recommanded" +msgstr "" + +#: tiramisu/option/domainnameoption.py:88 +#: tiramisu/option/domainnameoption.py:89 +msgid "could be a IP, otherwise {}" +msgstr "" + +#: tiramisu/option/domainnameoption.py:134 +msgid "invalid length (min 1)" +msgstr "" + +#: tiramisu/option/domainnameoption.py:137 +msgid "invalid length (max {0})" +msgstr "" + +#: tiramisu/option/domainnameoption.py:143 +msgid "must have dot" +msgstr "" + +#: tiramisu/option/domainnameoption.py:145 +msgid "invalid length (max 255)" +msgstr "" + +#: tiramisu/option/domainnameoption.py:163 +msgid "must not be an IP" +msgstr "" + +#: tiramisu/option/domainnameoption.py:186 +msgid "some characters are uppercase" +msgstr "" + +#: tiramisu/option/dynoptiondescription.py:131 +msgid "DynOptionDescription identifiers for option {0}, is not a list ({1})" +msgstr "" + +#: tiramisu/option/dynoptiondescription.py:142 +msgid "invalid identifier \"{}\" for option {}" +msgstr "" + +#: tiramisu/option/dynoptiondescription.py:150 +msgid "DynOptionDescription \"{0}\" identifiers return a list with same values \"{1}\"" +msgstr "" + +#: tiramisu/option/filenameoption.py:47 +msgid "types parameter must be a list, not \"{0}\" for \"{1}\"" +msgstr "" + +#: tiramisu/option/filenameoption.py:67 +msgid "must starts with \"/\"" +msgstr "" + +#: tiramisu/option/filenameoption.py:78 +msgid "cannot find {0} \"{1}\"" +msgstr "" + +#: tiramisu/option/intoption.py:52 +msgid "value should be equal or greater than \"{0}\"" +msgstr "" + +#: tiramisu/option/intoption.py:54 +msgid "value must be equal or greater than \"{0}\"" +msgstr "" + +#: tiramisu/option/intoption.py:59 +msgid "value should be less than \"{0}\"" +msgstr "" + +#: tiramisu/option/intoption.py:61 +msgid "value must be less than \"{0}\"" +msgstr "" + +#: tiramisu/option/ipoption.py:57 +msgid "it's in fact a network address" +msgstr "" + +#: tiramisu/option/ipoption.py:59 +msgid "it's in fact a broacast address" +msgstr "" + +#: tiramisu/option/ipoption.py:71 +msgid "CIDR address must have a \"/\"" +msgstr "" + +#: tiramisu/option/ipoption.py:80 +msgid "shouldn't be reserved IP" +msgstr "" + +#: tiramisu/option/ipoption.py:82 +msgid "mustn't be reserved IP" +msgstr "" + +#: tiramisu/option/ipoption.py:86 +msgid "should be private IP" +msgstr "" + +#: tiramisu/option/ipoption.py:88 +msgid "must be private IP" +msgstr "" + +#: tiramisu/option/leadership.py:55 +msgid "cannot set \"group_type\" attribute for a Leadership" +msgstr "" + +#: tiramisu/option/leadership.py:67 +msgid "a leader and a follower are mandatories in leadership \"{}\"" +msgstr "" + +#: tiramisu/option/leadership.py:89 +msgid "leader cannot have \"{}\" property" +msgstr "" + +#: tiramisu/option/leadership.py:101 +msgid "leadership {0} shall not have a symlinkoption" +msgstr "" + +#: tiramisu/option/leadership.py:108 +msgid "leadership {0} shall not have a subgroup" +msgstr "" + +#: tiramisu/option/leadership.py:114 +msgid "only multi option allowed in leadership {0} but option {1} is not a multi" +msgstr "" + +#: tiramisu/option/leadership.py:141 +msgid "not allowed default value for follower option {0} in leadership {1}" +msgstr "" + +#: tiramisu/option/networkoption.py:45 +msgid "must use CIDR notation" +msgstr "" + +#: tiramisu/option/networkoption.py:60 +msgid "shouldn't be reserved network" +msgstr "" + +#: tiramisu/option/networkoption.py:62 +msgid "mustn't be reserved network" +msgstr "" + +#: tiramisu/option/option.py:73 +msgid "default_multi is set whereas multi is False in option: {0}" +msgstr "" + +#: tiramisu/option/option.py:93 +msgid "invalid multi type \"{}\" for \"{}\"" +msgstr "" + +#: tiramisu/option/option.py:112 +msgid "validators must be a list of Calculation for \"{0}\"" +msgstr "" + +#: tiramisu/option/option.py:117 +msgid "validators must be a Calculation for \"{0}\"" +msgstr "" + +#: tiramisu/option/option.py:146 +msgid "invalid default_multi value \"{0}\" for option {1}" +msgstr "" + +#: tiramisu/option/option.py:154 +msgid "invalid default_multi value \"{0}\" for option {1}, {2}" +msgstr "" + +#: tiramisu/option/option.py:167 +msgid "invalid default_multi value \"{0}\" for option {1}, must be a list for a submulti" +msgstr "" + +#: tiramisu/option/option.py:290 +msgid "the value \"{}\" is not unique" +msgstr "" + +#: tiramisu/option/option.py:352 +msgid "which must not be a list" +msgstr "" + +#: tiramisu/option/option.py:404 tiramisu/option/option.py:430 +msgid "which must be a list" +msgstr "" + +#: tiramisu/option/option.py:424 +msgid "which \"{}\" must be a list of list" +msgstr "" + +#: tiramisu/option/optiondescription.py:109 +msgid "duplicate option: {0}" +msgstr "" + +#: tiramisu/option/optiondescription.py:244 +msgid "unknown option \"{0}\" in root optiondescription (it's a dynamic option)" +msgstr "" + +#: tiramisu/option/optiondescription.py:279 +msgid "unknown option \"{0}\" in root optiondescription" +msgstr "" + +#: tiramisu/option/optiondescription.py:282 +msgid "unknown option \"{0}\" in optiondescription {1}" +msgstr "" + +#: tiramisu/option/optiondescription.py:338 +msgid "children in optiondescription \"{}\" must be a list" +msgstr "" + +#: tiramisu/option/optiondescription.py:366 +msgid "duplicate option name: \"{0}\"" +msgstr "" + +#: tiramisu/option/optiondescription.py:372 +msgid "the option's name \"{0}\" start as the dynoptiondescription's name \"{1}\"" +msgstr "" + +#: tiramisu/option/optiondescription.py:415 +msgid "cannot change group_type if already set (old {0}, new {1})" +msgstr "" + +#: tiramisu/option/optiondescription.py:420 +msgid "group_type: {0} not allowed" +msgstr "" + +#: tiramisu/option/permissionsoption.py:52 +msgid "only 3 or 4 octal digits are allowed" +msgstr "" + +#: tiramisu/option/permissionsoption.py:63 +msgid "user" +msgstr "" + +#: tiramisu/option/permissionsoption.py:64 +#: tiramisu/option/permissionsoption.py:66 +msgid "group" +msgstr "" + +#: tiramisu/option/permissionsoption.py:67 +msgid "other" +msgstr "" + +#: tiramisu/option/permissionsoption.py:68 +msgid "{0} has more right than {1}" +msgstr "" + +#: tiramisu/option/permissionsoption.py:71 +msgid "too weak" +msgstr "" + +#: tiramisu/option/portoption.py:74 +msgid "inconsistency in allowed range" +msgstr "" + +#: tiramisu/option/portoption.py:79 +msgid "max value is empty" +msgstr "" + +#: tiramisu/option/portoption.py:92 +msgid "range must have two values only" +msgstr "" + +#: tiramisu/option/portoption.py:95 +msgid "first port in range must be smaller than the second one" +msgstr "" + +#: tiramisu/option/portoption.py:121 +msgid "should be between {0} and {1}" +msgstr "" + +#: tiramisu/option/portoption.py:123 +msgid "must be between {0} and {1}" +msgstr "" + +#: tiramisu/option/symlinkoption.py:51 +msgid "malformed symlink second parameters must be an option for \"{0}\", not {1}" +msgstr "" + +#: tiramisu/option/urloption.py:91 +msgid "must start with http:// or https://" +msgstr "" + +#: tiramisu/option/urloption.py:119 +msgid "must ends with a valid resource name" +msgstr "" + +#: tiramisu/setting.py:255 +msgid "can't rebind {0}" +msgstr "" + +#: tiramisu/setting.py:262 +msgid "can't unbind {0}" +msgstr "" + +#: tiramisu/setting.py:464 +msgid "invalid property type {type(new_prop)} for {subconfig.option.impl_getname()} with {prop.function.__name__} function" +msgstr "" + +#: tiramisu/setting.py:476 +msgid "leader cannot have \"{new_prop}\" property" +msgstr "" + +#: tiramisu/setting.py:564 +msgid "leader cannot have \"{0}\" property" +msgstr "" + +#: tiramisu/setting.py:573 +msgid "a leader ({0}) cannot have \"force_default_on_freeze\" or \"force_metaconfig_on_freeze\" property without \"frozen\"" +msgstr "" + +#: tiramisu/setting.py:607 +msgid "permissive must be a frozenset" +msgstr "" + +#: tiramisu/setting.py:617 +msgid "cannot add those permissives: {0}" +msgstr "" + +#: tiramisu/setting.py:654 +msgid "can't reset properties to the symlinkoption \"{}\"" +msgstr "" + +#: tiramisu/setting.py:667 +msgid "can't reset permissives to the symlinkoption \"{}\"" +msgstr "" + +#: tiramisu/todict.py:395 +msgid "option {} only works when remotable is not \"none\"" +msgstr "" + +#: tiramisu/todict.py:561 +msgid "unable to transform tiramisu object to dict: {}" +msgstr "" + +#: tiramisu/todict.py:876 tiramisu/todict.py:1033 +msgid "unknown form {}" +msgstr "" + +#: tiramisu/todict.py:923 +msgid "not in current area" +msgstr "" + +#: tiramisu/todict.py:947 +msgid "only multi option can have action \"add\", but \"{}\" is not a multi" +msgstr "" + +#: tiramisu/todict.py:953 +msgid "unknown action {}" +msgstr "" + +#: tiramisu/value.py:564 tiramisu/value.py:861 +msgid "set owner \"{0}\" is forbidden" +msgstr "" + +#: tiramisu/value.py:571 +msgid "\"{0}\" is a default value, so we cannot change owner to \"{1}\"" +msgstr "" + +#: tiramisu/value.py:740 +msgid "index {index} is greater than the length {length} for option {subconfig.option.impl_get_display_name(with_quote=True)}" +msgstr "" + +#: tiramisu/value.py:847 +msgid "information's item not found \"{}\"" +msgstr "" + diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..40e1d87 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,35 @@ +[build-system] +build-backend = "flit_core.buildapi" +requires = ["flit_core >=3.8.0,<4"] + +[project] +name = "tiramisu" +version = "4.1.0" +authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}] +readme = "README.md" +description = "an options controller tool" +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", + +] + +[project.urls] +Home = "https://forge.cloud.silique.fr/stove/tiramisu" + +[tool.commitizen] +name = "cz_conventional_commits" +tag_format = "$version" +version_scheme = "pep440" +version_provider = "pep621" +update_changelog_on_bump = true diff --git a/setup.py b/setup.py deleted file mode 100644 index c523627..0000000 --- a/setup.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -from setuptools import setup -import os -from tiramisu import __version__ - - -ORI_PACKAGE_NAME = 'tiramisu' -PACKAGE_NAME = os.environ.get('PACKAGE_DST', ORI_PACKAGE_NAME) - -if PACKAGE_NAME != ORI_PACKAGE_NAME: - package_dir = {PACKAGE_NAME: ORI_PACKAGE_NAME} -else: - package_dir = None - -setup( - version=__version__, - author="Tiramisu's team", - author_email='gnunux@gnunux.info', - name=PACKAGE_NAME, - description='an options controller tool', - url='https://forge.cloud.silique.fr/stove/tiramisu/', - license='GNU Library or Lesser General Public License (LGPL)', - provides=['tiramisu_api'], - install_requires=['setuptools'], - classifiers=[ - "Programming Language :: Python :: 3", - "License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)", - "Operating System :: OS Independent", - "Natural Language :: English", - "Natural Language :: French", - ], - long_description="""\ -An options controller tool -------------------------------------- - -Due to more and more available options required to set up an operating system, -compiler options or whatever, it became quite annoying to hand the necessary -options to where they are actually used and even more annoying to add new -options. To circumvent these problems the configuration control was -introduced... - -Tiramisu is an options handler and an options controller, wich aims at -producing flexible and fast options access. - - -This version requires Python 3.5 or later. -""", - include_package_data=True, - package_dir=package_dir, - packages=[PACKAGE_NAME], -) diff --git a/tests/auto/test_auto.py b/tests/auto/test_auto.py index 585becf..58d23bb 100644 --- a/tests/auto/test_auto.py +++ b/tests/auto/test_auto.py @@ -86,8 +86,6 @@ def build_variables(*, if hidden: base_name += 'hidden_' #str_mandatory_multi_hidden_information_deps - if base_name + 'information_deps' == 'str_mandatory_multi_hidden_information_deps': - print('blah', multi, properties, str1_5_informations) str1 = StrOption(base_name + 'information_deps', '', multi=multi, @@ -465,7 +463,6 @@ def _test_option(option, without_index=False): assert isinstance(option.path(), str) and (option.path() == name or option.path().endswith(f'.{name}')) if '_deps' in name: assert option.has_dependency(False) - print(option.path()) assert option.dependencies() else: assert not option.has_dependency(False) diff --git a/tests/test_option_validator.py b/tests/test_option_validator.py index 211f240..76901a9 100644 --- a/tests/test_option_validator.py +++ b/tests/test_option_validator.py @@ -1046,12 +1046,12 @@ def test_validator_error_prefix(): try: cfg.option('b').value.set(1) except Exception as err: - assert str(err) == _('"{0}" is an invalid {1} for "{2}"').format('1', _('integer'), 'b') + ', ' + _('value is identical to {}').format('"a"') + assert str(err) == _('"{0}" is an invalid {1} for "{2}"').format('1', _('integer'), 'b') + ', ' + _('value is identical to {0}').format('"a"') try: cfg.option('b').value.set(1) except Exception as err: err.prefix = '' - assert str(err) == _('value is identical to {}').format('"a"') + assert str(err) == _('value is identical to {0}').format('"a"') # assert not list_sessions() diff --git a/tiramisu/__init__.py b/tiramisu/__init__.py index 0034f2a..11c2b69 100644 --- a/tiramisu/__init__.py +++ b/tiramisu/__init__.py @@ -14,11 +14,29 @@ # along with this program. If not, see . """Configuration management library written in python """ -from .function import calc_value, calc_value_property_help, valid_ip_netmask, \ - valid_network_netmask, valid_in_network, valid_broadcast, \ - valid_not_equal, function_waiting_for_dict, function_waiting_for_error -from .autolib import Calculation, Params, ParamOption, ParamDynOption, ParamSelfOption, \ - ParamValue, ParamIndex, ParamIdentifier, ParamInformation, ParamSelfInformation +from .function import ( + calc_value, + calc_value_property_help, + valid_ip_netmask, + valid_network_netmask, + valid_in_network, + valid_broadcast, + valid_not_equal, + function_waiting_for_dict, + function_waiting_for_error, +) +from .autolib import ( + Calculation, + Params, + ParamOption, + ParamDynOption, + ParamSelfOption, + ParamValue, + ParamIndex, + ParamIdentifier, + ParamInformation, + ParamSelfInformation, +) from .option import * from .error import ConfigError from .api import Config, MetaConfig, GroupConfig, MixConfig @@ -26,35 +44,36 @@ from .option import __all__ as all_options from .setting import owners, groups, undefined -allfuncs = ['Calculation', - 'Params', - 'ParamOption', - 'ParamDynOption', - 'ParamSelfOption', - 'ParamValue', - 'ParamIndex', - 'ParamIdentifier', - 'ParamInformation', - 'ParamSelfInformation', - 'MetaConfig', - 'MixConfig', - 'GroupConfig', - 'Config', - 'ConfigError', - 'undefined', - 'owners', - 'groups', - 'calc_value', - 'calc_value_property_help', - 'valid_ip_netmask', - 'valid_network_netmask', - 'valid_in_network', - 'valid_broadcast', - 'function_waiting_for_dict', - 'function_waiting_for_error', - ] +allfuncs = [ + "Calculation", + "Params", + "ParamOption", + "ParamDynOption", + "ParamSelfOption", + "ParamValue", + "ParamIndex", + "ParamIdentifier", + "ParamInformation", + "ParamSelfInformation", + "MetaConfig", + "MixConfig", + "GroupConfig", + "Config", + "ConfigError", + "undefined", + "owners", + "groups", + "calc_value", + "calc_value_property_help", + "valid_ip_netmask", + "valid_network_netmask", + "valid_in_network", + "valid_broadcast", + "function_waiting_for_dict", + "function_waiting_for_error", +] allfuncs.extend(all_options) -del(all_options) +del all_options __all__ = tuple(allfuncs) -del(allfuncs) +del allfuncs __version__ = "4.1.0" diff --git a/tiramisu/api.py b/tiramisu/api.py index 2f2908a..7a4f11b 100644 --- a/tiramisu/api.py +++ b/tiramisu/api.py @@ -21,12 +21,29 @@ from functools import wraps from copy import deepcopy -from .error import ConfigError, LeadershipError, ValueErrorWarning, PropertiesOptionError +from .error import ( + ConfigError, + LeadershipError, + ValueErrorWarning, + PropertiesOptionError, +) from .i18n import _ -from .setting import ConfigBag, owners, groups, undefined, \ - FORBIDDEN_SET_PROPERTIES, SPECIAL_PROPERTIES, \ - DEFAULT_PROPERTIES -from .config import KernelConfig, KernelGroupConfig, KernelMetaConfig, KernelMixConfig, SubConfig +from .setting import ( + ConfigBag, + owners, + groups, + undefined, + FORBIDDEN_SET_PROPERTIES, + SPECIAL_PROPERTIES, + DEFAULT_PROPERTIES, +) +from .config import ( + KernelConfig, + KernelGroupConfig, + KernelMetaConfig, + KernelMixConfig, + SubConfig, +) from .option import RegexpOption, OptionDescription, ChoiceOption, Leadership from .todict import TiramisuDict from .autolib import Calculation @@ -36,22 +53,22 @@ TIRAMISU_VERSION = 5 class TiramisuHelp: - _tmpl_help = ' {0}\t{1}' + _tmpl_help = " {0}\t{1}" - def help(self, - _display: bool=True) -> List[str]: - def display(doc=''): - if _display: # pragma: no cover + def help(self, _display: bool = True) -> List[str]: + def display(doc=""): + if _display: # pragma: no cover print(doc) + all_modules = dir(self.__class__) modules = [] max_len = 0 force = False for module_name in all_modules: - if module_name in ['forcepermissive', 'unrestraint', 'nowarnings']: + if module_name in ["forcepermissive", "unrestraint", "nowarnings"]: force = True - max_len = max(max_len, len('forcepermissive')) - elif module_name != 'help' and not module_name.startswith('_'): + max_len = max(max_len, len("forcepermissive")) + elif module_name != "help" and not module_name.startswith("_"): modules.append(module_name) max_len = max(max_len, len(module_name)) modules.sort() @@ -59,19 +76,25 @@ class TiramisuHelp: display(_(getdoc(self))) display() if force: - display(_('Settings:')) - display(self._tmpl_help.format('forcepermissive', - _('Access to option without verifying permissive ' - 'properties'), - ).expandtabs(max_len + 10)) - display(self._tmpl_help.format('unrestraint', - _('Access to option without property restriction') - ).expandtabs(max_len + 10)) - display(self._tmpl_help.format('nowarnings', - _('Do not warnings during validation') - ).expandtabs(max_len + 10)) + display(_("Settings:")) + display( + self._tmpl_help.format( + "forcepermissive", + _("Access to option without verifying permissive " "properties"), + ).expandtabs(max_len + 10) + ) + display( + self._tmpl_help.format( + "unrestraint", _("Access to option without property restriction") + ).expandtabs(max_len + 10) + ) + display( + self._tmpl_help.format( + "nowarnings", _("Do not warnings during validation") + ).expandtabs(max_len + 10) + ) display() - display(_('Commands:')) + display(_("Commands:")) for module_name in modules: module = getattr(self, module_name) doc = _(getdoc(module)) @@ -79,12 +102,16 @@ class TiramisuHelp: display() def __dir__(self): - if '_registers' in super().__dir__(): + if "_registers" in super().__dir__(): return list(self._registers.keys()) return super().__dir__() def __getattr__(self, subfunc): - raise ConfigError(_(f'please specify a valid sub function ({self.__class__.__name__}.{subfunc})')) + raise ConfigError( + _("please specify a valid sub function ({0}.{1})").format( + self.__class__.__name__, subfunc + ) + ) class CommonTiramisu(TiramisuHelp): @@ -93,12 +120,13 @@ class CommonTiramisu(TiramisuHelp): def _set_subconfig(self) -> None: if not self._subconfig: - self._subconfig = self._config_bag.context.get_sub_config(self._config_bag, - self._path, - self._index, - validate_properties=False, - allow_dynoption=self._allow_dynoption, - ) + self._subconfig = self._config_bag.context.get_sub_config( + self._config_bag, + self._path, + self._index, + validate_properties=False, + allow_dynoption=self._allow_dynoption, + ) def option_type(typ): @@ -112,87 +140,103 @@ def option_type(typ): def wrapped(*args, **kwargs): self = args[0] config_bag = self._config_bag - if self._config_bag.context.impl_type == 'group' and 'group' in types: - options_bag = [OptionBag(None, - None, - self._config_bag, - path=self._path, - )] - kwargs['is_group'] = True + if self._config_bag.context.impl_type == "group" and "group" in types: + options_bag = [ + OptionBag( + None, + None, + self._config_bag, + path=self._path, + ) + ] + kwargs["is_group"] = True return func(self, options_bag, *args[1:], **kwargs) self._set_subconfig() option = self._subconfig.option error_type = None - if 'dynamic' in types: + if "dynamic" in types: if not self._subconfig.is_dynamic: - error_type = 'only available for dynamic option' + error_type = "only available for dynamic option" elif option.impl_is_optiondescription(): - if 'optiondescription' not in types: + if "optiondescription" not in types: if option.impl_is_leadership(): - if 'leadership' not in types: - error_type = 'not available for a Leadership' + if "leadership" not in types: + error_type = "not available for a Leadership" else: - error_type = 'not available for an OptionDescription' + error_type = "not available for an OptionDescription" elif option.impl_is_symlinkoption(): - if 'symlink' not in types: - error_type = 'this function is not available for a SymLinkOption' - elif 'option' not in types: - if 'choice' in types: + if "symlink" not in types: + error_type = "this function is not available for a SymLinkOption" + elif "option" not in types: + if "choice" in types: if not isinstance(option, ChoiceOption): - error_type = 'only available for ChoiceOption' + error_type = "only available for ChoiceOption" elif option.impl_is_leader(): - if 'leader' not in types: - error_type = 'not available for a Leader' + if "leader" not in types: + error_type = "not available for a Leader" elif option.impl_is_follower(): - if 'follower' not in types: - error_type = 'not available for a Follower' + if "follower" not in types: + error_type = "not available for a Follower" else: - error_type = 'not available for an Option' + error_type = "not available for an Option" if not error_type: - if not option.impl_is_optiondescription() and \ - not option.impl_is_symlinkoption() and \ - option.impl_is_follower(): + if ( + not option.impl_is_optiondescription() + and not option.impl_is_symlinkoption() + and option.impl_is_follower() + ): # default is "without_index" - if 'with_index' not in types and 'with_or_without_index' not in types and \ - self._index is not None: - msg = _('please do not specify index ' - f'({self.__class__.__name__}.{func.__name__})') - raise ConfigError(_(msg)) - if self._index is None and 'with_index' in types: - msg = _('please specify index with a follower option ' - f'({self.__class__.__name__}.{func.__name__})') + if ( + "with_index" not in types + and "with_or_without_index" not in types + and self._index is not None + ): + msg = _("please do not specify index ({0}.{1})").format( + self.__class__.__name__, func.__name__ + ) raise ConfigError(msg) - if self._validate_properties and 'dont_validate_property' not in types: + if self._index is None and "with_index" in types: + msg = _( + "please specify index with a follower option ({0}.{1})" + ).format(self.__class__.__name__, func.__name__) + raise ConfigError(msg) + if self._validate_properties and "dont_validate_property" not in types: settings = self._config_bag.context.get_settings() parent = self._subconfig.parent if parent and parent.transitive_properties: while parent: if not parent.parent.transitive_properties: - settings.validate_properties(parent, - need_help=True, - ) + settings.validate_properties( + parent, + need_help=True, + ) break parent = parent.parent - settings.validate_properties(self._subconfig, - need_help=True, - ) + settings.validate_properties( + self._subconfig, + need_help=True, + ) return func(self, *args[1:], **kwargs) - msg = _('please specify a valid sub function ' - f'({self.__class__.__name__}.{func.__name__}): {error_type}') + msg = _("please specify a valid sub function ({0}.{1}): {2}").format( + self.__class__.__name__, func.__name__, error_type + ) raise ConfigError(msg) + wrapped.func = func return wrapped + return wrapper class CommonTiramisuOption(CommonTiramisu): _validate_properties = False - def __init__(self, - path: str, - index: Optional[int], - config_bag: ConfigBag, - ) -> None: + def __init__( + self, + path: str, + index: Optional[int], + config_bag: ConfigBag, + ) -> None: self._path = path self._index = index self._config_bag = config_bag @@ -201,116 +245,131 @@ class CommonTiramisuOption(CommonTiramisu): class _TiramisuOptionWalk: - def _list(self, - subconfig: SubConfig, - validate_properties: bool, - *, - uncalculated: bool=False, - ): + def _list( + self, + subconfig: SubConfig, + validate_properties: bool, + *, + uncalculated: bool = False, + ): options = [] - for sub_subconfig in subconfig.get_children(validate_properties, uncalculated=uncalculated): - options.append(TiramisuOption(sub_subconfig.path, - sub_subconfig.index, - self._config_bag, - subconfig=sub_subconfig, - )) + for sub_subconfig in subconfig.get_children( + validate_properties, uncalculated=uncalculated + ): + options.append( + TiramisuOption( + sub_subconfig.path, + sub_subconfig.index, + self._config_bag, + subconfig=sub_subconfig, + ) + ) return options class _TiramisuOptionOptionDescription: """Manage option""" + _validate_properties = False - @option_type(['optiondescription', 'option', 'with_or_without_index', 'symlink']) + @option_type(["optiondescription", "option", "with_or_without_index", "symlink"]) def get(self): """Get Tiramisu option""" return self._subconfig.option - @option_type(['optiondescription', 'option', 'with_or_without_index', 'symlink']) + @option_type(["optiondescription", "option", "with_or_without_index", "symlink"]) def isoptiondescription(self): """Test if option is an optiondescription""" return self._subconfig.option.impl_is_optiondescription() - @option_type(['optiondescription']) + @option_type(["optiondescription"]) def isleadership(self): """Test if option is a leader or a follower""" return self._subconfig.option.impl_is_leadership() - @option_type(['optiondescription', 'option', 'with_or_without_index', 'symlink']) - def description(self, - uncalculated: bool=False, - ): + @option_type(["optiondescription", "option", "with_or_without_index", "symlink"]) + def description( + self, + uncalculated: bool = False, + ): """Get option description""" if not uncalculated: return self._subconfig.option.impl_get_display_name(self._subconfig) - return self._subconfig.option._get_information(self._subconfig, - 'doc', - None, - ) + return self._subconfig.option._get_information( + self._subconfig, + "doc", + None, + ) - @option_type(['optiondescription', 'option', 'symlink', 'with_or_without_index']) - def name(self, - *, - uncalculated: bool=False, - ) -> str: + @option_type(["optiondescription", "option", "symlink", "with_or_without_index"]) + def name( + self, + *, + uncalculated: bool = False, + ) -> str: """Get option name""" if uncalculated: return self._subconfig.option.impl_getname() - return self._subconfig.true_path.rsplit('.', 1)[-1] + return self._subconfig.true_path.rsplit(".", 1)[-1] - @option_type(['optiondescription', 'option', 'with_or_without_index', 'symlink']) - def path(self, - *, - uncalculated: bool=False, - ) -> str: + @option_type(["optiondescription", "option", "with_or_without_index", "symlink"]) + def path( + self, + *, + uncalculated: bool = False, + ) -> str: """Get option path""" if uncalculated: return self._subconfig.option.impl_getpath() return self._subconfig.true_path - @option_type(['optiondescription', 'option', 'symlink', 'with_or_without_index']) - def has_dependency(self, - self_is_dep=True, - ) -> bool: + @option_type(["optiondescription", "option", "symlink", "with_or_without_index"]) + def has_dependency( + self, + self_is_dep=True, + ) -> bool: """Test if option has dependency""" return self._subconfig.option.impl_has_dependency(self_is_dep) - @option_type(['optiondescription', 'option', 'symlink', 'with_or_without_index']) + @option_type(["optiondescription", "option", "symlink", "with_or_without_index"]) def dependencies(self): """Get dependencies from this option""" options = [] for option in self._subconfig.option.get_dependencies(self._config_bag.context): - options.append(TiramisuOption(option().impl_getpath(), - None, - self._config_bag, - allow_dynoption=True, - )) + options.append( + TiramisuOption( + option().impl_getpath(), + None, + self._config_bag, + allow_dynoption=True, + ) + ) return options - @option_type(['option', 'optiondescription', 'symlink', 'with_or_without_index']) + @option_type(["option", "optiondescription", "symlink", "with_or_without_index"]) def type(self): """Get de option type""" option = self._subconfig.option if option.impl_is_optiondescription(): - return 'optiondescription' + return "optiondescription" return option.get_type() - @option_type(['option', 'symlink', 'with_or_without_index']) + @option_type(["option", "symlink", "with_or_without_index"]) def extra(self, extra): """Get de option extra""" return self._subconfig.option.impl_get_extra(extra) - @option_type(['option', 'optiondescription', 'symlink', 'with_or_without_index']) - def isdynamic(self, - *, - only_self: bool=False): + @option_type(["option", "optiondescription", "symlink", "with_or_without_index"]) + def isdynamic(self, *, only_self: bool = False): """Test if option is a dynamic optiondescription""" if not only_self: return self._subconfig.is_dynamic - return self._subconfig.option.impl_is_optiondescription() and \ - self._subconfig.option.impl_is_dynoptiondescription() + return ( + self._subconfig.option.impl_is_optiondescription() + and self._subconfig.option.impl_is_dynoptiondescription() + ) - @option_type(['option', 'leadership']) + @option_type(["option", "leadership"]) def leader(self): """Get the leader option for a leadership or a follower option""" option = self._subconfig.option @@ -318,17 +377,19 @@ class _TiramisuOptionOptionDescription: leadership = self._subconfig else: leadership = self._subconfig.parent - leader_subconfig = leadership.get_child(leadership.option.get_leader(), - None, - False, - ) - return TiramisuOption(leader_subconfig.path, - None, - self._config_bag, - subconfig=leader_subconfig, - ) + leader_subconfig = leadership.get_child( + leadership.option.get_leader(), + None, + False, + ) + return TiramisuOption( + leader_subconfig.path, + None, + self._config_bag, + subconfig=leader_subconfig, + ) - @option_type(['leadership']) + @option_type(["leadership"]) def followers(self): """Get the followers option for a leadership""" option = self._subconfig.option @@ -338,203 +399,246 @@ class _TiramisuOptionOptionDescription: leadership = self._subconfig.parent ret = [] for follower in leadership.option.get_followers(): - follower_subconfig = leadership.get_child(follower, - None, - False, - ) - ret.append(TiramisuOption(follower_subconfig.path, - None, - self._config_bag, - subconfig=follower_subconfig, - )) + follower_subconfig = leadership.get_child( + follower, + None, + False, + ) + ret.append( + TiramisuOption( + follower_subconfig.path, + None, + self._config_bag, + subconfig=follower_subconfig, + ) + ) return ret - @option_type(['dynamic', 'with_or_without_index']) - def identifiers(self, - only_self: bool=False, - uncalculated: bool=False, - ): + @option_type(["dynamic", "with_or_without_index"]) + def identifiers( + self, + only_self: bool = False, + uncalculated: bool = False, + ): """Get identifiers for dynamic option""" if not only_self: return self._subconfig.identifiers - if not self._subconfig.option.impl_is_optiondescription() or \ - not self._subconfig.option.impl_is_dynoptiondescription(): - raise ConfigError(_(f'the option {self._subconfig.path} is not a dynamic option, cannot get identifiers with only_self parameter to True')) - return self._subconfig.option.get_identifiers(self._subconfig.parent, - uncalculated=uncalculated, - ) + if ( + not self._subconfig.option.impl_is_optiondescription() + or not self._subconfig.option.impl_is_dynoptiondescription() + ): + raise ConfigError( + _( + "the option {0} is not a dynamic option, cannot get identifiers with only_self parameter to True" + ).format(self._subconfig.path) + ) + return self._subconfig.option.get_identifiers( + self._subconfig.parent, + uncalculated=uncalculated, + ) class _TiramisuOptionOption(_TiramisuOptionOptionDescription): """Manage option""" - @option_type(['option', 'symlink', 'with_or_without_index']) + + @option_type(["option", "symlink", "with_or_without_index"]) def ismulti(self): """Test if option could have multi value""" return self._subconfig.option.impl_is_multi() - @option_type(['option', 'symlink', 'with_or_without_index']) + @option_type(["option", "symlink", "with_or_without_index"]) def issubmulti(self): """Test if option could have submulti value""" return self._subconfig.option.impl_is_submulti() - @option_type(['option', 'with_or_without_index', 'symlink']) + @option_type(["option", "with_or_without_index", "symlink"]) def isleader(self): """Test if option is a leader""" return self._subconfig.option.impl_is_leader() - @option_type(['option', 'with_or_without_index', 'symlink']) + @option_type(["option", "with_or_without_index", "symlink"]) def isfollower(self): """Test if option is a follower""" return self._subconfig.option.impl_is_follower() - @option_type(['option', 'symlink', 'with_or_without_index']) + @option_type(["option", "symlink", "with_or_without_index"]) def issymlinkoption(self) -> bool: """Test if option is a symlink option""" return self._subconfig.option.impl_is_symlinkoption() - @option_type(['option', 'with_or_without_index']) + @option_type(["option", "with_or_without_index"]) def pattern(self) -> str: """Get the option pattern""" option = self._subconfig.option type = option.get_type() if isinstance(option, RegexpOption): return option._regexp.pattern - if type == 'integer': + if type == "integer": # FIXME negative too! - return r'^[0-9]+$' - if type == 'domain name': - return option.impl_get_extra('_domain_re').pattern - if type in ['ip', 'network', 'netmask']: - #FIXME only from 0.0.0.0 to 255.255.255.255 - return 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]?)$' + return r"^[0-9]+$" + if type == "domain name": + return option.impl_get_extra("_domain_re").pattern + if type in ["ip", "network", "netmask"]: + # FIXME only from 0.0.0.0 to 255.255.255.255 + return 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]?)$" - @option_type(['option', 'with_or_without_index', 'symlink']) + @option_type(["option", "with_or_without_index", "symlink"]) def index(self): """Get index of option""" return self._subconfig.index - @option_type(['symlink', 'optiondescription']) + @option_type(["symlink", "optiondescription"]) def option(self, *args, **kwargs): """For OptionDescription get sub option, for symlinkoption get the linked option""" if self._subconfig.option.impl_is_optiondescription(): return self._option_description(*args, **kwargs) return self._option_symlink(*args, **kwargs) - def _option_description(self, - path, - index=None, - ): - sub_path = self._path + '.' + path - return TiramisuOption(sub_path, - index, - self._config_bag, - ) + def _option_description( + self, + path, + index=None, + ): + sub_path = self._path + "." + path + return TiramisuOption( + sub_path, + index, + self._config_bag, + ) def _option_symlink(self): - subconfig = self._subconfig.config_bag.context._get(self._subconfig, - need_help=True, - validate_properties=self._validate_properties, - ) + subconfig = self._subconfig.config_bag.context._get( + self._subconfig, + need_help=True, + validate_properties=self._validate_properties, + ) if isinstance(subconfig, list): - raise ConfigError(_('cannot get option from a follower symlink without index')) + raise ConfigError( + _("cannot get option from a follower symlink without index") + ) subconfig.true_path = subconfig.path - return TiramisuOption(subconfig.path, - subconfig.index, - self._config_bag, - subconfig=subconfig, - ) + return TiramisuOption( + subconfig.path, + subconfig.index, + self._config_bag, + subconfig=subconfig, + ) class TiramisuOptionOwner(CommonTiramisuOption): """Manage option's owner""" - _validate_properties=True - @option_type(['symlink', 'option', 'with_index']) + _validate_properties = True + + @option_type(["symlink", "option", "with_index"]) def get(self): """Get owner for a specified option""" return self._config_bag.context.get_owner(self._subconfig) - @option_type(['symlink', 'option', 'with_index']) + @option_type(["symlink", "option", "with_index"]) def isdefault(self): """Is option has defaut value""" return self._config_bag.context.get_owner(self._subconfig) == owners.default - @option_type(['option', 'with_index']) - def set(self, - owner: str, - ) -> None: + @option_type(["option", "with_index"]) + def set( + self, + owner: str, + ) -> None: """Get owner for a specified option""" try: obj_owner = getattr(owners, owner) except AttributeError: owners.addowner(owner) obj_owner = getattr(owners, owner) - self._config_bag.context.get_values().set_owner(self._subconfig, - obj_owner, - ) + self._config_bag.context.get_values().set_owner( + self._subconfig, + obj_owner, + ) class TiramisuOptionProperty(CommonTiramisuOption): """Manage option's property""" + _validate_properties = False - @option_type(['option', 'optiondescription', 'with_index', 'symlink']) - def get(self, - *, - only_raises: bool=False, - apply_requires: bool=True, - uncalculated: bool=False, - ): + @option_type(["option", "optiondescription", "with_index", "symlink"]) + def get( + self, + *, + only_raises: bool = False, + apply_requires: bool = True, + uncalculated: bool = False, + ): """Get properties for an option""" settings = self._config_bag.context.get_settings() if not only_raises: - return settings.getproperties(self._subconfig, - uncalculated=uncalculated, - apply_requires=apply_requires, - ) - return settings.calc_raises_properties(self._subconfig, - uncalculated=uncalculated, - apply_requires=apply_requires, - ) + return settings.getproperties( + self._subconfig, + uncalculated=uncalculated, + apply_requires=apply_requires, + ) + return settings.calc_raises_properties( + self._subconfig, + uncalculated=uncalculated, + apply_requires=apply_requires, + ) - @option_type(['option', 'optiondescription', 'with_or_without_index']) + @option_type(["option", "optiondescription", "with_or_without_index"]) def add(self, prop): """Add new property for an option""" if prop in FORBIDDEN_SET_PROPERTIES: - raise ConfigError(_('cannot add this property: "{0}"').format( - ' '.join(prop))) + raise ConfigError( + _('cannot add this property: "{0}"').format(" ".join(prop)) + ) settings = self._config_bag.context.get_settings() - props = settings.get_personalize_properties(self._path, - self._index, - ) - settings.setproperties(self._subconfig, - props | {prop}, - ) + props = settings.get_personalize_properties( + self._path, + self._index, + ) + settings.setproperties( + self._subconfig, + props | {prop}, + ) - @option_type(['option', 'optiondescription', 'with_or_without_index']) - def remove(self, - prop, - ): + @option_type(["option", "optiondescription", "with_or_without_index"]) + def remove( + self, + prop, + ): """Remove new property for an option""" settings = self._config_bag.context.get_settings() - props = settings.get_personalize_properties(self._path, - self._index, - ) + props = settings.get_personalize_properties( + self._path, + self._index, + ) if prop not in props: - if prop in settings.getproperties(self._subconfig): - msg = f'cannot remove option\'s property "{prop}", use permissive instead' + if self._index is None: + if prop in settings.getproperties(self._subconfig): + msg = _( + 'cannot remove option\'s property "{0}", use permissive instead in option "{1}"' + ).format(prop, self._path) + else: + msg = _('cannot find "{0}" in option "{1}"').format( + prop, self._path + ) else: - msg = f'cannot find "{prop}"' - msg += f' in option "{self._path}"' - if self._index is not None: - msg += f' at index "{self._index}"' + if prop in settings.getproperties(self._subconfig): + msg = _( + 'cannot remove option\'s property "{0}", use permissive instead in option "{1}" at index "{2}"' + ).format(prop, self._path, self._index) + else: + msg = _('cannot find "{0}" in option "{1}" at index "{2}"').format( + prop, self._path, self._index + ) raise ConfigError(msg) - settings.setproperties(self._subconfig, - props - {prop}, - ) + settings.setproperties( + self._subconfig, + props - {prop}, + ) - @option_type(['option', 'optiondescription', 'with_or_without_index']) + @option_type(["option", "optiondescription", "with_or_without_index"]) def reset(self): """Reset all personalised properties""" self._config_bag.context.get_settings().reset(self._subconfig) @@ -542,35 +646,41 @@ class TiramisuOptionProperty(CommonTiramisuOption): class TiramisuOptionPermissive(CommonTiramisuOption): """Manage option's permissive""" + _validate_properties = False - @option_type(['option', 'optiondescription', 'symlink', 'with_or_without_index']) + @option_type(["option", "optiondescription", "symlink", "with_or_without_index"]) def get(self): """Get permissives value""" return self._config_bag.context.get_settings().getpermissives(self._subconfig) - @option_type(['option', 'optiondescription', 'with_or_without_index']) - def add(self, - permissive, - ): + @option_type(["option", "optiondescription", "with_or_without_index"]) + def add( + self, + permissive, + ): """Set permissives value""" - permissives = self._config_bag.context.get_settings().getpermissives(self._subconfig) - self._config_bag.context.get_settings().setpermissives(self._subconfig, - frozenset(permissives | {permissive}), - ) + permissives = self._config_bag.context.get_settings().getpermissives( + self._subconfig + ) + self._config_bag.context.get_settings().setpermissives( + self._subconfig, + frozenset(permissives | {permissive}), + ) - @option_type(['option', 'optiondescription', 'with_or_without_index']) + @option_type(["option", "optiondescription", "with_or_without_index"]) def remove(self, permissive): """Remove a config property""" permissives = set(self.get()) if permissive not in permissives: - msg = f'cannot find "{permissive}"' + msg = _('cannot find "{0}"').format(permissive) raise ConfigError(msg) - self._config_bag.context.get_settings().setpermissives(self._subconfig, - frozenset(permissives - {permissive}), - ) + self._config_bag.context.get_settings().setpermissives( + self._subconfig, + frozenset(permissives - {permissive}), + ) - @option_type(['option', 'optiondescription', 'with_or_without_index']) + @option_type(["option", "optiondescription", "with_or_without_index"]) def reset(self): """Reset all personalised permissive""" self._config_bag.context.get_settings().reset_permissives(self._subconfig) @@ -578,40 +688,44 @@ class TiramisuOptionPermissive(CommonTiramisuOption): class TiramisuOptionInformation(CommonTiramisuOption): """Manage option's informations""" + _validate_properties = False _allow_dynoption = True - @option_type(['option', 'optiondescription', 'with_or_without_index', 'symlink']) - def get(self, - name: str, - default=undefined, - ) -> Any: + @option_type(["option", "optiondescription", "with_or_without_index", "symlink"]) + def get( + self, + name: str, + default=undefined, + ) -> Any: """Get information""" - return self._config_bag.context.get_values().get_information(self._subconfig, - name, - default, - ) + return self._config_bag.context.get_values().get_information( + self._subconfig, + name, + default, + ) - @option_type(['option', 'optiondescription']) - def set(self, - key: str, - value: Any) -> None: + @option_type(["option", "optiondescription"]) + def set(self, key: str, value: Any) -> None: """Set information""" - self._config_bag.context.get_values().set_information(self._subconfig, - key, - value, - ) + self._config_bag.context.get_values().set_information( + self._subconfig, + key, + value, + ) - @option_type(['option', 'optiondescription']) - def remove(self, - key: str, - ) -> None: + @option_type(["option", "optiondescription"]) + def remove( + self, + key: str, + ) -> None: """Remove information""" - self._config_bag.context.get_values().del_information(key, - path=self._path, - ) + self._config_bag.context.get_values().del_information( + key, + path=self._path, + ) - @option_type(['option', 'optiondescription', 'with_or_without_index', 'symlink']) + @option_type(["option", "optiondescription", "with_or_without_index", "symlink"]) def list(self) -> list: """List information's keys""" lst1 = set(self._subconfig.option._list_information()) @@ -619,41 +733,47 @@ class TiramisuOptionInformation(CommonTiramisuOption): return lst1 | lst2 -class _TiramisuODGet(): - def _od_get(self, - root_subconfig: SubConfig, - ) -> dict: +class _TiramisuODGet: + def _od_get( + self, + root_subconfig: SubConfig, + ) -> dict: """exports the whole config into a `dict` :returns: dict of Option's name (or path) and values """ + def parse_od_get(values): ret_ = {} for subconfig, value in values.items(): - option = TiramisuOption(subconfig.path, - subconfig.index, - self._config_bag, - subconfig=subconfig, - ) + option = TiramisuOption( + subconfig.path, + subconfig.index, + self._config_bag, + subconfig=subconfig, + ) if option.isoptiondescription(): value = parse_od_get(value) ret_[option] = value return ret_ + return parse_od_get(self._config_bag.context.walk(root_subconfig)) class TiramisuOptionValue(CommonTiramisuOption, _TiramisuODGet): """Manage option's value""" + _validate_properties = True - @option_type(['option', 'symlink', 'with_index', 'optiondescription']) - def get(self, - *, - uncalculated: bool=False, - ): + @option_type(["option", "symlink", "with_index", "optiondescription"]) + def get( + self, + *, + uncalculated: bool = False, + ): """Get value for an option or option and sub option with values with optiondescription""" if self._subconfig.option.impl_is_optiondescription(): if uncalculated: - raise ConfigError('uncalculated is not allowed for optiondescription') + raise ConfigError("uncalculated is not allowed for optiondescription") return self._od_get(self._subconfig) if uncalculated: value = self._subconfig.option.impl_getdefault() @@ -665,36 +785,44 @@ class TiramisuOptionValue(CommonTiramisuOption, _TiramisuODGet): return value[index] return self._get(uncalculated) - def _get(self, - need_help: bool=True, - ): + def _get( + self, + need_help: bool = True, + ): """Get option's value""" return self._config_bag.context.get_value(self._subconfig, need_help) - @option_type(['option', 'with_index']) - def set(self, - value, - ): + @option_type(["option", "with_index"]) + def set( + self, + value, + ): """Change option's value""" option = self._subconfig.option - if not isinstance(value, Calculation) and option.impl_is_leader() and \ - len(value) < self._subconfig.parent.get_length_leadership(): - raise LeadershipError(_('cannot reduce length of the leader {}' - '').format(option.impl_get_display_name(self._subconfig, with_quote=True))) + if ( + not isinstance(value, Calculation) + and option.impl_is_leader() + and len(value) < self._subconfig.parent.get_length_leadership() + ): + raise LeadershipError( + _("cannot reduce length of the leader {}" "").format( + option.impl_get_display_name(self._subconfig, with_quote=True) + ) + ) values = self._config_bag.context.get_values() - return values.set_value(self._subconfig, - value - ) + return values.set_value(self._subconfig, value) - @option_type(['group', 'option', 'with_index']) - def reset(self, - is_group: bool=False, - ) -> None: + @option_type(["group", "option", "with_index"]) + def reset( + self, + is_group: bool = False, + ) -> None: """Reset value for an option""" if is_group: - self._config_bag.context.reset(self._subconfig.path, - self._config_bag, - ) + self._config_bag.context.reset( + self._subconfig.path, + self._config_bag, + ) else: values = self._config_bag.context.get_values() if self._subconfig.index is not None: @@ -702,29 +830,38 @@ class TiramisuOptionValue(CommonTiramisuOption, _TiramisuODGet): else: values.reset(self._subconfig) - @option_type(['option', 'with_or_without_index', 'symlink', "dont_validate_property"]) - def default(self, - uncalculated: bool=False, - ) -> Any: + @option_type( + ["option", "with_or_without_index", "symlink", "dont_validate_property"] + ) + def default( + self, + uncalculated: bool = False, + ) -> Any: """Get default value (default of option or calculated value)""" if uncalculated: return self._subconfig.option.impl_getdefault() if self._subconfig.option.impl_is_follower() and self._subconfig.index is None: - msg = _('please specify index with a follower option ' - f'({self.__class__.__name__}.{func.__name__})') + msg = _("please specify index with a follower option ({0}.{1})").format( + self.__class__.__name__, func.__name__ + ) raise ConfigError(msg) - if 'force_store_value' in self._subconfig.properties and 'force_store_value' in self._config_bag.properties: + if ( + "force_store_value" in self._subconfig.properties + and "force_store_value" in self._config_bag.properties + ): return self._get(self._subconfig) return self._config_bag.context.get_values().get_default_value(self._subconfig) - @option_type(['option', 'with_or_without_index', 'symlink', "dont_validate_property"]) + @option_type( + ["option", "with_or_without_index", "symlink", "dont_validate_property"] + ) def defaultmulti(self): """Get default value when added a value for a multi option (not for optiondescription)""" if not self._subconfig.option.impl_is_multi(): - raise ConfigError(_('only multi value has defaultmulti')) + raise ConfigError(_("only multi value has defaultmulti")) return self._subconfig.option.impl_getdefault_multi() - @option_type(['option', 'with_index']) + @option_type(["option", "with_index"]) def valid(self): """The if the option's value is valid""" try: @@ -738,26 +875,30 @@ class TiramisuOptionValue(CommonTiramisuOption, _TiramisuODGet): return False return True - @option_type(['choice', 'with_index']) - def list(self, - *, - uncalculated: bool=False, - ): + @option_type(["choice", "with_index"]) + def list( + self, + *, + uncalculated: bool = False, + ): """All values available for a ChoiceOption""" - return self._subconfig.option.impl_get_values(self._subconfig, - uncalculated, - ) + return self._subconfig.option.impl_get_values( + self._subconfig, + uncalculated, + ) - @option_type('leader') - def pop(self, - index: int, - ): + @option_type("leader") + def pop( + self, + index: int, + ): """Pop a value""" - self._config_bag.context.get_values().reset_leadership(self._subconfig, - index, - ) + self._config_bag.context.get_values().reset_leadership( + self._subconfig, + index, + ) - @option_type(['leader', 'follower', 'with_or_without_index']) + @option_type(["leader", "follower", "with_or_without_index"]) def len(self): """Length for a leadership""" return self._subconfig.parent.get_length_leadership() @@ -768,44 +909,54 @@ class TiramisuOptionValue(CommonTiramisuOption, _TiramisuODGet): if subconfig.option.impl_is_optiondescription(): ori_config_bag = self._subconfig.config_bag config_bag = ori_config_bag.copy() - config_bag.properties -= {'mandatory', 'empty', 'warnings'} + config_bag.properties -= {"mandatory", "empty", "warnings"} config_bag.set_permissive() self._subconfig.config_bag = config_bag options = [] - for subconfig in self._config_bag.context.walk(self._subconfig, - only_mandatory=True, - ): - options.append(TiramisuOption(subconfig.path, - subconfig.index, - ori_config_bag, - subconfig=subconfig, - )) + for subconfig in self._config_bag.context.walk( + self._subconfig, + only_mandatory=True, + ): + options.append( + TiramisuOption( + subconfig.path, + subconfig.index, + ori_config_bag, + subconfig=subconfig, + ) + ) self._subconfig.config_bag = ori_config_bag return options try: - self._config_bag.context.walk_valid_value(self._subconfig, only_mandatory=True) + self._config_bag.context.walk_valid_value( + self._subconfig, only_mandatory=True + ) except PropertiesOptionError as err: - return err.proptype == ['mandatory'] or err.proptype == ['empty'] + return err.proptype == ["mandatory"] or err.proptype == ["empty"] return False -def _registers(_registers: Dict[str, type], - prefix: str, - ): +def _registers( + _registers: Dict[str, type], + prefix: str, +): for module_name in globals().keys(): if module_name != prefix and module_name.startswith(prefix): module = globals()[module_name] - func_name = module_name[len(prefix):].lower() + func_name = module_name[len(prefix) :].lower() _registers[func_name] = module -#__________________________________________________________________________________________________ + + +# __________________________________________________________________________________________________ # class TiramisuConfig(TiramisuHelp, _TiramisuOptionWalk): - def __init__(self, - config_bag: ConfigBag, - orig_config_bags: Optional[List["OptionBag"]], - ) -> None: + def __init__( + self, + config_bag: ConfigBag, + orig_config_bags: Optional[List["OptionBag"]], + ) -> None: self._config_bag = config_bag self._orig_config_bags = orig_config_bags @@ -824,98 +975,116 @@ class TiramisuConfig(TiramisuHelp, _TiramisuOptionWalk): return self._config_bag.context.impl_getname() -class TiramisuOption(CommonTiramisu, - _TiramisuOptionOption, - TiramisuConfig, - ): +class TiramisuOption( + CommonTiramisu, + _TiramisuOptionOption, + TiramisuConfig, +): """Manage selected option""" + _validate_properties = False _registers = {} - def __init__(self, - path: Optional[str]=None, - index: Optional[int]=None, - config_bag: Optional[ConfigBag]=None, - *, - subconfig: Optional[SubConfig]=None, - allow_dynoption: bool=False, - ) -> None: + + def __init__( + self, + path: Optional[str] = None, + index: Optional[int] = None, + config_bag: Optional[ConfigBag] = None, + *, + subconfig: Optional[SubConfig] = None, + allow_dynoption: bool = False, + ) -> None: self._path = path self._index = index self._config_bag = config_bag self._allow_dynoption = allow_dynoption self._subconfig = subconfig if not self._registers: - _registers(self._registers, 'TiramisuOption') + _registers(self._registers, "TiramisuOption") def __repr__(self): msg = f' Any: if subfunc in self._registers: - return self._registers[subfunc](self._path, - self._index, - self._config_bag, - ) - raise ConfigError(_(f'please specify a valid sub function ({self.__class__.__name__}.{subfunc}) for {self._path}')) -# + return self._registers[subfunc]( + self._path, + self._index, + self._config_bag, + ) + raise ConfigError( + _("please specify a valid sub function ({0}.{1}) for {2}").format( + self.__class__.__name__, subfunc, self._path + ) + ) + + # def __iter__(self): self._set_subconfig() for sub_subconfig in self._subconfig.get_children(True): - yield TiramisuOption(sub_subconfig.path, - sub_subconfig.index, - self._config_bag, - subconfig=sub_subconfig, - ) + yield TiramisuOption( + sub_subconfig.path, + sub_subconfig.index, + self._config_bag, + subconfig=sub_subconfig, + ) - @option_type('optiondescription') + @option_type("optiondescription") def group_type(self): """Get type for an optiondescription (only for optiondescription)""" self._set_subconfig() return self._subconfig.option.impl_get_group_type() - @option_type('optiondescription') - def list(self, - *, - validate_properties: bool=True, - uncalculated: bool=False, - ): + @option_type("optiondescription") + def list( + self, + *, + validate_properties: bool = True, + uncalculated: bool = False, + ): """List options inside an option description (by default list only option)""" self._set_subconfig() - return self._list(self._subconfig, - validate_properties, - uncalculated=uncalculated, - ) + return self._list( + self._subconfig, + validate_properties, + uncalculated=uncalculated, + ) - def _load_dict(self, - clearable: str="all", - remotable: str="minimum", - ): + def _load_dict( + self, + clearable: str = "all", + remotable: str = "minimum", + ): config = self._config_bag.context - self._tiramisu_dict = TiramisuDict(self._return_config(config), - root=self._path, - clearable=clearable, - remotable=remotable) + self._tiramisu_dict = TiramisuDict( + self._return_config(config), + root=self._path, + clearable=clearable, + remotable=remotable, + ) - @option_type('optiondescription') - def dict(self, - clearable: str="all", - remotable: str="minimum", - form: List=[], - force: bool=False, - ) -> Dict: + @option_type("optiondescription") + def dict( + self, + clearable: str = "all", + remotable: str = "minimum", + form: List = [], + force: bool = False, + ) -> Dict: """Convert config and option to tiramisu format""" if force or self._tiramisu_dict is None: self._load_dict(clearable, remotable) return self._tiramisu_dict.todict(form) - @option_type('optiondescription') - def updates(self, - body: List, - ) -> Dict: + @option_type("optiondescription") + def updates( + self, + body: List, + ) -> Dict: """Updates value with tiramisu format""" if self._tiramisu_dict is None: # pragma: no cover self._load_dict() @@ -924,32 +1093,38 @@ class TiramisuOption(CommonTiramisu, class TiramisuContextInformation(TiramisuConfig): """Manage config informations""" - def get(self, - name, - default=undefined, - ): + + def get( + self, + name, + default=undefined, + ): """Get an information""" context = self._config_bag.context values = context.get_values() subconfig = context.get_root(self._config_bag) - return values.get_information(subconfig, - name, - default, - ) + return values.get_information( + subconfig, + name, + default, + ) - def set(self, + def set( + self, + name, + value, + ): + """Set an information""" + self._config_bag.context.impl_set_information( + self._config_bag, name, value, - ): - """Set an information""" - self._config_bag.context.impl_set_information(self._config_bag, - name, - value, - ) + ) - def remove(self, - name, - ): + def remove( + self, + name, + ): """Remove an information""" self._config_bag.context.impl_del_information(name) @@ -970,70 +1145,78 @@ class TiramisuContextInformation(TiramisuConfig): class TiramisuContextValue(TiramisuConfig, _TiramisuODGet): """Manage config value""" + def mandatory(self): """Return path of options with mandatory property without any value""" config_bag = self._config_bag.copy() - config_bag.properties -= {'mandatory', 'empty', 'warnings'} + config_bag.properties -= {"mandatory", "empty", "warnings"} config_bag.set_permissive() root = self._config_bag.context.get_root(config_bag) options = [] - for subconfig in self._config_bag.context.walk(root, - only_mandatory=True, - ): - options.append(TiramisuOption(subconfig.path, - subconfig.index, - self._config_bag, - subconfig=subconfig, - )) + for subconfig in self._config_bag.context.walk( + root, + only_mandatory=True, + ): + options.append( + TiramisuOption( + subconfig.path, + subconfig.index, + self._config_bag, + subconfig=subconfig, + ) + ) return options # FIXME should be only for group/meta - def set(self, - path: str, - value: Any, - only_config=undefined, - force_default=undefined, - force_default_if_same=undefined, - force_dont_change_value=undefined, - ): + def set( + self, + path: str, + value: Any, + only_config=undefined, + force_default=undefined, + force_default_if_same=undefined, + force_dont_change_value=undefined, + ): """Set a value in config or children for a path""" kwargs = {} if only_config is not undefined: - kwargs['only_config'] = only_config + kwargs["only_config"] = only_config if force_default is not undefined: - kwargs['force_default'] = force_default + kwargs["force_default"] = force_default if force_default_if_same is not undefined: - kwargs['force_default_if_same'] = force_default_if_same + kwargs["force_default_if_same"] = force_default_if_same if force_dont_change_value is not undefined: - kwargs['force_dont_change_value'] = force_dont_change_value - option_bag = OptionBag(None, - None, - self._config_bag, - path=path, - ) - return self._config_bag.context.set_value(option_bag, - value, - **kwargs, - ) + kwargs["force_dont_change_value"] = force_dont_change_value + option_bag = OptionBag( + None, + None, + self._config_bag, + path=path, + ) + return self._config_bag.context.set_value( + option_bag, + value, + **kwargs, + ) # FIXME should be only for group/meta - def reset(self, - path: str, - only_children: bool=False): + def reset(self, path: str, only_children: bool = False): """Reset value""" - self._config_bag.context.reset(path, - only_children, - self._config_bag, - ) + self._config_bag.context.reset( + path, + only_children, + self._config_bag, + ) def get(self): """Get option and sub option with values""" root = self._config_bag.context.get_root(self._config_bag) return self._od_get(root) - def exportation(self, - with_default_owner: bool=False, - ): + def exportation( + self, + with_default_owner: bool = False, + ): """Export all values""" exportation = deepcopy(self._config_bag.context.get_values()._values) if not with_default_owner: @@ -1053,6 +1236,7 @@ class TiramisuContextValue(TiramisuConfig, _TiramisuODGet): class TiramisuContextOwner(TiramisuConfig): """Global owner""" + def get(self): """Get owner""" return self._config_bag.context.get_values().get_context_owner() @@ -1069,16 +1253,18 @@ class TiramisuContextOwner(TiramisuConfig): class PropertyPermissive: - def _set_default_permissive(self, - settings, - ): + def _set_default_permissive( + self, + settings, + ): or_properties = settings.rw_append - settings.ro_append - SPECIAL_PROPERTIES permissives = frozenset(settings.get_context_permissives() | or_properties) settings.set_context_permissives(permissives) - def _reset_config_properties(self, - settings, - ): + def _reset_config_properties( + self, + settings, + ): properties = settings.get_context_properties() permissives = settings.get_context_permissives() self._config_bag.properties = properties @@ -1091,30 +1277,35 @@ class PropertyPermissive: class TiramisuContextProperty(TiramisuConfig, PropertyPermissive): """Manage config properties""" + def read_only(self): """Set config to read only mode""" if self._config_bag.is_unrestraint: - raise ConfigError('cannot change context property in unrestraint mode') + raise ConfigError("cannot change context property in unrestraint mode") old_props = self._config_bag.properties settings = self._config_bag.context.get_settings() settings.read_only(self._config_bag) self._set_default_permissive(settings) self._reset_config_properties(settings) - if 'force_store_value' not in old_props and \ - 'force_store_value' in self._config_bag.properties: + if ( + "force_store_value" not in old_props + and "force_store_value" in self._config_bag.properties + ): self._force_store_value() def read_write(self): """Set config to read and write mode""" if self._config_bag.is_unrestraint: - raise ConfigError('cannot change context property in unrestraint mode') + raise ConfigError("cannot change context property in unrestraint mode") old_props = self._config_bag.properties settings = self._config_bag.context.get_settings() settings.read_write(self._config_bag) self._set_default_permissive(settings) self._reset_config_properties(settings) - if 'force_store_value' not in old_props and \ - 'force_store_value' in self._config_bag.properties: + if ( + "force_store_value" not in old_props + and "force_store_value" in self._config_bag.properties + ): self._force_store_value() def add(self, prop): @@ -1133,31 +1324,34 @@ class TiramisuContextProperty(TiramisuConfig, PropertyPermissive): props.remove(prop) self._set(frozenset(props)) - def get(self, - *, - only_raises: bool=False, - apply_requires: bool=True, - uncalculated: bool=False, - ) -> Set: + def get( + self, + *, + only_raises: bool = False, + apply_requires: bool = True, + uncalculated: bool = False, + ) -> Set: """Get all config properties""" if only_raises: return set() return self._config_bag.properties - def _set(self, - props, - ): + def _set( + self, + props, + ): """Personalise config properties""" if self._config_bag.is_unrestraint: - raise ConfigError('cannot change context property in unrestraint mode') - if 'force_store_value' in props: - force_store_value = 'force_store_value' not in self._config_bag.properties + raise ConfigError("cannot change context property in unrestraint mode") + if "force_store_value" in props: + force_store_value = "force_store_value" not in self._config_bag.properties else: force_store_value = False settings = self._config_bag.context.get_settings() - settings.set_context_properties(props, - self._config_bag.context, - ) + settings.set_context_properties( + props, + self._config_bag.context, + ) self._reset_config_properties(settings) if force_store_value: self._force_store_value() @@ -1165,7 +1359,7 @@ class TiramisuContextProperty(TiramisuConfig, PropertyPermissive): def reset(self): """Remove config properties""" if self._config_bag.is_unrestraint: - raise ConfigError('cannot change context property in unrestraint mode') + raise ConfigError("cannot change context property in unrestraint mode") settings = self._config_bag.context.get_settings() settings.reset(self._config_bag) self._reset_config_properties(settings) @@ -1173,30 +1367,30 @@ class TiramisuContextProperty(TiramisuConfig, PropertyPermissive): def exportation(self): """Export config properties""" settings = self._config_bag.context.get_settings() - return {'properties': deepcopy(settings._properties), - 'ro_append': settings.ro_append.copy(), - 'ro_remove': settings.ro_remove.copy(), - 'rw_append': settings.rw_append.copy(), - 'rw_remove': settings.rw_remove.copy(), - } - + return { + "properties": deepcopy(settings._properties), + "ro_append": settings.ro_append.copy(), + "ro_remove": settings.ro_remove.copy(), + "rw_append": settings.rw_append.copy(), + "rw_remove": settings.rw_remove.copy(), + } def importation(self, data): """Import config properties""" if self._config_bag.is_unrestraint: - raise ConfigError('cannot change context property in unrestraint mode') - properties = data['properties'] - if 'force_store_value' in properties.get(None, {}).get(None, []): - force_store_value = 'force_store_value' not in self._config_bag.properties + raise ConfigError("cannot change context property in unrestraint mode") + properties = data["properties"] + if "force_store_value" in properties.get(None, {}).get(None, []): + force_store_value = "force_store_value" not in self._config_bag.properties else: force_store_value = False context = self._config_bag.context settings = context.get_settings() settings._properties = deepcopy(properties) - settings.ro_append = data['ro_append'].copy() - settings.ro_remove = data['ro_remove'].copy() - settings.rw_append = data['rw_append'].copy() - settings.rw_remove = data['rw_remove'].copy() + settings.ro_append = data["ro_append"].copy() + settings.ro_remove = data["ro_remove"].copy() + settings.rw_append = data["rw_append"].copy() + settings.rw_remove = data["rw_remove"].copy() context.reset_cache(None, None) self._reset_config_properties(settings) if force_store_value: @@ -1206,52 +1400,57 @@ class TiramisuContextProperty(TiramisuConfig, PropertyPermissive): descr = self._config_bag.context.get_description() descr.impl_build_force_store_values(self._config_bag) - def setdefault(self, - properties: Set[str], - type: Optional[str], - when: Optional[str]=None) -> None: + def setdefault( + self, properties: Set[str], type: Optional[str], when: Optional[str] = None + ) -> None: if not isinstance(properties, frozenset): - raise TypeError(_('properties must be a frozenset')) + raise TypeError(_("properties must be a frozenset")) setting = self._config_bag.context.get_settings() - if when not in ['append', 'remove']: - raise ValueError(_('unknown when {} (must be in append or remove)').format(when)) - if type == 'read_only': - if when == 'append': + if when not in ["append", "remove"]: + raise ValueError( + _("unknown when {} (must be in append or remove)").format(when) + ) + if type == "read_only": + if when == "append": setting.ro_append = properties else: setting.ro_remove = properties - elif type == 'read_write': - if when == 'append': + elif type == "read_write": + if when == "append": setting.rw_append = properties else: setting.rw_remove = properties else: - raise ValueError(_('unknown type {}').format(type)) + raise ValueError(_("unknown type {}").format(type)) - def default(self, - type: Optional[str]=None, - when: Optional[str]=None, - ) -> Set[str]: + def default( + self, + type: Optional[str] = None, + when: Optional[str] = None, + ) -> Set[str]: setting = self._config_bag.context.get_settings() if type is None and when is None: return DEFAULT_PROPERTIES - if type == 'current': + if type == "current": return setting.get_context_properties() - if when not in ['append', 'remove']: - raise ValueError(_('unknown when {} (must be in append or remove)').format(when)) - if type == 'read_only': - if when == 'append': + if when not in ["append", "remove"]: + raise ValueError( + _("unknown when {} (must be in append or remove)").format(when) + ) + if type == "read_only": + if when == "append": return setting.ro_append return setting.ro_remove - if type == 'read_write': - if when == 'append': + if type == "read_write": + if when == "append": return setting.rw_append return setting.rw_remove - raise ValueError(_('unknown type {}').format(type)) + raise ValueError(_("unknown type {}").format(type)) class TiramisuContextPermissive(TiramisuConfig, PropertyPermissive): """Manage config permissives""" + def get(self): """Get config permissives""" return self._get() @@ -1259,12 +1458,13 @@ class TiramisuContextPermissive(TiramisuConfig, PropertyPermissive): def _get(self): return self._config_bag.context.get_settings().get_context_permissives() - def _set(self, - permissives, - ): + def _set( + self, + permissives, + ): """Set config permissives""" if self._config_bag.is_unrestraint: - raise ConfigError('cannot change context permissive in unrestraint mode') + raise ConfigError("cannot change context permissive in unrestraint mode") settings = self._config_bag.context.get_settings() settings.set_context_permissives(permissives) self._reset_config_properties(settings) @@ -1276,19 +1476,20 @@ class TiramisuContextPermissive(TiramisuConfig, PropertyPermissive): def importation(self, permissives): """Import config permissives""" if self._config_bag.is_unrestraint: - raise ConfigError('cannot change context permissive in unrestraint mode') + raise ConfigError("cannot change context permissive in unrestraint mode") context = self._config_bag.context settings = context.get_settings() settings._permissives = deepcopy(permissives) - context.reset_cache(None, - None, - ) + context.reset_cache( + None, + None, + ) self._reset_config_properties(settings) def reset(self): """Remove config permissives""" if self._config_bag.is_unrestraint: - raise ConfigError('cannot change context permissive in unrestraint mode') + raise ConfigError("cannot change context permissive in unrestraint mode") settings = self._config_bag.context.get_settings() settings.reset_permissives(self._config_bag) self._set_default_permissive(settings) @@ -1317,11 +1518,12 @@ class TiramisuContextOption(TiramisuConfig, _TiramisuOptionWalk): def __iter__(self): root = self._config_bag.context.get_root(self._config_bag) for sub_subconfig in root.get_children(True): - yield TiramisuOption(sub_subconfig.path, - sub_subconfig.index, - self._config_bag, - subconfig=sub_subconfig, - ) + yield TiramisuOption( + sub_subconfig.path, + sub_subconfig.index, + self._config_bag, + subconfig=sub_subconfig, + ) def get(self): """Get Tiramisu option""" @@ -1331,29 +1533,35 @@ class TiramisuContextOption(TiramisuConfig, _TiramisuOptionWalk): """Test if option is a leader or a follower""" return False - def description(self, - uncalculated: bool=False, - ) -> str: + def description( + self, + uncalculated: bool = False, + ) -> str: """Get option description""" if not uncalculated: - return self._config_bag.context.get_description().impl_get_display_name(None) - return self._config_bag.context.get_description()._get_information(None, - 'doc', - None, - ) + return self._config_bag.context.get_description().impl_get_display_name( + None + ) + return self._config_bag.context.get_description()._get_information( + None, + "doc", + None, + ) def name(self): """Get option name""" return None - def path(self, - ): + def path( + self, + ): """Get option path""" return None - def has_dependency(self, - self_is_dep=True, - ) -> bool: + def has_dependency( + self, + self_is_dep=True, + ) -> bool: """Test if option has dependency""" return False @@ -1367,35 +1575,37 @@ class TiramisuContextOption(TiramisuConfig, _TiramisuOptionWalk): def type(self): """Get de option type""" - return 'optiondescription' + return "optiondescription" - def list(self, - *, - validate_properties: bool=True, - uncalculated: bool=False, - ): + def list( + self, + *, + validate_properties: bool = True, + uncalculated: bool = False, + ): """List options (by default list only option)""" root = self._config_bag.context.get_root(self._config_bag) - return self._list(root, - validate_properties, - uncalculated=uncalculated, - ) + return self._list( + root, + validate_properties, + uncalculated=uncalculated, + ) - def _load_dict(self, - clearable="all", - remotable="minimum"): - self._tiramisu_dict = TiramisuDict(self._return_config(self._config_bag.context), - root=None, - clearable=clearable, - remotable=remotable, - ) + def _load_dict(self, clearable="all", remotable="minimum"): + self._tiramisu_dict = TiramisuDict( + self._return_config(self._config_bag.context), + root=None, + clearable=clearable, + remotable=remotable, + ) - def dict(self, - clearable="all", - remotable="minimum", - form=None, - force=False, - ): + def dict( + self, + clearable="all", + remotable="minimum", + form=None, + force=False, + ): """Convert config and option to tiramisu format""" if form is None: form = [] @@ -1403,20 +1613,21 @@ class TiramisuContextOption(TiramisuConfig, _TiramisuOptionWalk): self._load_dict(clearable, remotable) return self._tiramisu_dict.todict(form) - def updates(self, - body: List) -> Dict: + def updates(self, body: List) -> Dict: """Updates value with tiramisu format""" if self._tiramisu_dict is None: # pragma: no cover self._load_dict() return self._tiramisu_dict.set_updates(body) -class _TiramisuContextConfigReset(): +class _TiramisuContextConfigReset: def reset(self): """Remove all datas to current config (informations, values, properties, ...)""" # Option's values context_owner = self._config_bag.context.get_values().get_context_owner() - self._config_bag.context.get_values()._values = {None: {None: [None, context_owner]}} + self._config_bag.context.get_values()._values = { + None: {None: [None, context_owner]} + } # Option's informations self._config_bag.context.get_values()._informations = {} # Option's properties @@ -1429,9 +1640,10 @@ class _TiramisuContextConfigReset(): class _TiramisuContextConfig(TiramisuConfig, _TiramisuContextConfigReset): """Actions to Config""" + def type(self): """Type a Config""" - return 'config' + return "config" def copy(self, name=None): """Copy current config""" @@ -1440,10 +1652,11 @@ class _TiramisuContextConfig(TiramisuConfig, _TiramisuContextConfigReset): def deepcopy(self, metaconfig_prefix=None, name=None): """Copy current config with all parents""" - config = self._config_bag.context.duplicate(metaconfig_prefix=metaconfig_prefix, - deep=[], - name=name, - ) + config = self._config_bag.context.duplicate( + metaconfig_prefix=metaconfig_prefix, + deep=[], + name=name, + ) return self._return_config(config) def parents(self): @@ -1460,28 +1673,32 @@ class _TiramisuContextConfig(TiramisuConfig, _TiramisuContextConfigReset): class _TiramisuContextGroupConfig(TiramisuConfig): """Actions to GroupConfig""" + def type(self): """Type a Config""" - return 'groupconfig' + return "groupconfig" def list(self): """List children's config""" - return [self._return_config(child) for child in self._config_bag.context.get_children()] -# -# def find(self, -# name: str, -# value=undefined, -# ): -# """Find an or a list of config with finding option""" -# return GroupConfig(self._config_bag.context.find_group(byname=name, -# byvalue=value, -# config_bag=self._config_bag, -# )) + return [ + self._return_config(child) + for child in self._config_bag.context.get_children() + ] - def __call__(self, - path: Optional[str]): + # + # def find(self, + # name: str, + # value=undefined, + # ): + # """Find an or a list of config with finding option""" + # return GroupConfig(self._config_bag.context.find_group(byname=name, + # byvalue=value, + # config_bag=self._config_bag, + # )) + + def __call__(self, path: Optional[str]): """Select a child Tiramisu config""" - spaths = path.split('.') + spaths = path.split(".") config = self._config_bag.context for spath in spaths: config = config.getconfig(spath) @@ -1489,29 +1706,32 @@ class _TiramisuContextGroupConfig(TiramisuConfig): return self._return_config(config) return self._return_config(config) - def copy(self, name=None): config = self._config_bag.context.duplicate(name=name) return self._return_config(config) def deepcopy(self, name=None, metaconfig_prefix=None): - config = self._config_bag.context.duplicate(metaconfig_prefix=metaconfig_prefix, - deep=[], - name=name, - ) + config = self._config_bag.context.duplicate( + metaconfig_prefix=metaconfig_prefix, + deep=[], + name=name, + ) return self._return_config(config) def path(self): return self._config_bag.context.get_config_path() -class _TiramisuContextMixConfig(_TiramisuContextGroupConfig, _TiramisuContextConfigReset): +class _TiramisuContextMixConfig( + _TiramisuContextGroupConfig, _TiramisuContextConfigReset +): """Actions to MixConfig""" + def type(self): """Type a Config""" - return 'mixconfig' + return "mixconfig" - def new(self, name=None, type='config'): + def new(self, name=None, type="config"): """Create and add a new config""" config = self._config_bag.context new_config = config.new_config(type_=type, name=name) @@ -1522,8 +1742,7 @@ class _TiramisuContextMixConfig(_TiramisuContextGroupConfig, _TiramisuContextCon config = self._config_bag.context.remove_config(name) return self._return_config(config) - def add(self, - config): + def add(self, config): """Add config from MetaConfig""" # pylint: disable=protected-access self._config_bag.context.add_config(config._config_bag.context) @@ -1538,9 +1757,10 @@ class _TiramisuContextMixConfig(_TiramisuContextGroupConfig, _TiramisuContextCon class _TiramisuContextMetaConfig(_TiramisuContextMixConfig): """Actions to MetaConfig""" + def type(self): """Type a Config""" - return 'metaconfig' + return "metaconfig" class TiramisuContextCache(TiramisuConfig): @@ -1550,9 +1770,10 @@ class TiramisuContextCache(TiramisuConfig): """Reset cache""" self._config_bag.context.reset_cache(None, None) - def set_expiration_time(self, - time: int, - ) -> None: + def set_expiration_time( + self, + time: int, + ) -> None: """Change expiration time value""" self._config_bag.expiration_time = time @@ -1562,92 +1783,104 @@ class TiramisuContextCache(TiramisuConfig): class TiramisuAPI(TiramisuHelp): - """TiramisuAPI common class - """ + """TiramisuAPI common class""" + _registers = {} - def __init__(self, - config_bag, - orig_config_bags=None) -> None: + def __init__(self, config_bag, orig_config_bags=None) -> None: self._config_bag = config_bag self._orig_config_bags = orig_config_bags if not self._registers: - _registers(self._registers, 'TiramisuContext') + _registers(self._registers, "TiramisuContext") super().__init__() - def option(self, - path: str, - index: Optional[int]=None, - ) -> TiramisuOption: + def option( + self, + path: str, + index: Optional[int] = None, + ) -> TiramisuOption: """Select an option by path""" - return TiramisuOption(path, - index, - self._config_bag, - ) + return TiramisuOption( + path, + index, + self._config_bag, + ) def __getattr__(self, subfunc: str) -> Any: - if subfunc in ['forcepermissive', 'unrestraint', 'nowarnings']: + if subfunc in ["forcepermissive", "unrestraint", "nowarnings"]: if self._orig_config_bags: - msg = _('do not use unrestraint, nowarnings or forcepermissive together') + msg = _( + "do not use unrestraint, nowarnings or forcepermissive together" + ) raise ConfigError(msg) config_bag = self._config_bag.copy() - if subfunc == 'unrestraint': + if subfunc == "unrestraint": config_bag.unrestraint() - elif subfunc == 'nowarnings': + elif subfunc == "nowarnings": config_bag.nowarnings() else: config_bag.set_permissive() return ConfigProp(config_bag, [self._config_bag]) - if subfunc == 'config': + if subfunc == "config": config_type = self._config_bag.context.impl_type - if config_type == 'group': + if config_type == "group": config = _TiramisuContextGroupConfig - elif config_type == 'meta': + elif config_type == "meta": config = _TiramisuContextMetaConfig - elif config_type == 'mix': + elif config_type == "mix": config = _TiramisuContextMixConfig else: config = _TiramisuContextConfig - return config(self._config_bag, - self._orig_config_bags) + return config(self._config_bag, self._orig_config_bags) if subfunc in self._registers: config_bag = self._config_bag # del config_bag.permissives - return self._registers[subfunc](config_bag, - self._orig_config_bags) - raise ConfigError(_(f'please specify a valid sub function ({self.__class__.__name__}.{subfunc})')) + return self._registers[subfunc](config_bag, self._orig_config_bags) + raise ConfigError( + _("please specify a valid sub function ({0}.{1})").format( + self.__class__.__name__, subfunc + ) + ) def __dir__(self): - return list(self._registers.keys()) + \ - ['unrestraint', 'forcepermissive', 'nowarnings', 'config'] + return list(self._registers.keys()) + [ + "unrestraint", + "forcepermissive", + "nowarnings", + "config", + ] class ConfigProp(TiramisuAPI, TiramisuContextOption): def __repr__(self): - return f'' + return f"" class Config(TiramisuAPI, TiramisuContextOption): """Root config object that enables us to handle the configuration options""" - def __init__(self, - descr: OptionDescription, - name=None, - display_name=None, - ) -> None: + + def __init__( + self, + descr: OptionDescription, + name=None, + display_name=None, + ) -> None: if isinstance(descr, KernelConfig): config = descr else: - config = KernelConfig(descr, - name=name, - display_name=display_name, - ) + config = KernelConfig( + descr, + name=name, + display_name=display_name, + ) settings = config.get_settings() properties = settings.get_context_properties() permissives = settings.get_context_permissives() - config_bag = ConfigBag(config, - properties=properties, - permissives=permissives, - ) + config_bag = ConfigBag( + config, + properties=properties, + permissives=permissives, + ) super().__init__(config_bag) def __del__(self): @@ -1659,20 +1892,22 @@ class Config(TiramisuAPI, TiramisuContextOption): pass def __repr__(self): - return f'' + return f"" class MetaConfig(TiramisuAPI): """MetaConfig object that enables us to handle the sub configuration's options with common root optiondescription """ + # pylint: disable=too-few-public-methods - def __init__(self, - children: 'Config'=None, - name=None, - optiondescription: Optional[OptionDescription]=None, - display_name=None - ) -> None: + def __init__( + self, + children: "Config" = None, + name=None, + optiondescription: Optional[OptionDescription] = None, + display_name=None, + ) -> None: if children is None: children = [] if isinstance(children, KernelMetaConfig): @@ -1685,17 +1920,16 @@ class MetaConfig(TiramisuAPI): else: _children.append(child) - config = KernelMetaConfig(_children, - optiondescription=optiondescription, - name=name, - display_name=display_name, - ) + config = KernelMetaConfig( + _children, + optiondescription=optiondescription, + name=name, + display_name=display_name, + ) settings = config.get_settings() properties = settings.get_context_properties() permissives = settings.get_context_permissives() - config_bag = ConfigBag(config, - properties=properties, - permissives=permissives) + config_bag = ConfigBag(config, properties=properties, permissives=permissives) super().__init__(config_bag) @@ -1703,13 +1937,15 @@ class MixConfig(TiramisuAPI): """MixConfig object that enables us to handle the sub configuration's options with differents root optiondescription """ + # pylint: disable=too-few-public-methods - def __init__(self, - optiondescription: OptionDescription, - children: List[Config], - name: Callable=None, - display_name=None - ) -> None: + def __init__( + self, + optiondescription: OptionDescription, + children: List[Config], + name: Callable = None, + display_name=None, + ) -> None: if isinstance(children, KernelMixConfig): config = children else: @@ -1720,28 +1956,32 @@ class MixConfig(TiramisuAPI): else: _children.append(child) - config = KernelMixConfig(optiondescription, - _children, - name=name, - display_name=display_name, - ) + config = KernelMixConfig( + optiondescription, + _children, + name=name, + display_name=display_name, + ) settings = config.get_settings() properties = settings.get_context_properties(config.properties_cache) permissives = settings.get_context_permissives() - config_bag = ConfigBag(config, - properties=properties, - permissives=permissives, - ) + config_bag = ConfigBag( + config, + properties=properties, + permissives=permissives, + ) super().__init__(config_bag) class GroupConfig(TiramisuAPI): """GroupConfig that enables us to access the sub configuration's options""" + # pylint: disable=too-few-public-methods - def __init__(self, - children, - name=None, - ) -> None: + def __init__( + self, + children, + name=None, + ) -> None: if isinstance(children, KernelGroupConfig): config = children else: @@ -1753,7 +1993,5 @@ class GroupConfig(TiramisuAPI): _children.append(child) config = KernelGroupConfig(_children, name=name) - config_bag = ConfigBag(config, - properties=None, - permissives=None) + config_bag = ConfigBag(config, properties=None, permissives=None) super().__init__(config_bag) diff --git a/tiramisu/autolib.py b/tiramisu/autolib.py index 3f1cf6e..fa714b4 100644 --- a/tiramisu/autolib.py +++ b/tiramisu/autolib.py @@ -26,33 +26,36 @@ from .error import PropertiesOptionError, ConfigError, LeadershipError, ValueWar from .i18n import _ from .setting import undefined, ConfigBag from .function import FUNCTION_WAITING_FOR_DICT, FUNCTION_WAITING_FOR_ERROR + # ____________________________________________________________ -def get_calculated_value(subconfig: "SubConfig", - value: Any, - *, - reset_cache: bool=True, - validate_properties: bool=True, - ) -> Any: - """value could be a calculation, in this case do calculation - """ +def get_calculated_value( + subconfig: "SubConfig", + value: Any, + *, + reset_cache: bool = True, + validate_properties: bool = True, +) -> Any: + """value could be a calculation, in this case do calculation""" has_calculation = False if isinstance(value, Calculation): if subconfig is None: return undefined, False - value = value.execute(subconfig, - validate_properties=validate_properties, - ) + value = value.execute( + subconfig, + validate_properties=validate_properties, + ) has_calculation = True elif isinstance(value, list): # if value is a list, do subcalculation for idx, val in enumerate(value): - value[idx], _has_calculation = get_calculated_value(subconfig, - val, - reset_cache=False, - validate_properties=validate_properties, - ) + value[idx], _has_calculation = get_calculated_value( + subconfig, + val, + reset_cache=False, + validate_properties=validate_properties, + ) if value[idx] is undefined: return undefined, False if _has_calculation: @@ -61,7 +64,8 @@ def get_calculated_value(subconfig: "SubConfig", class Params: - __slots__ = ('args', 'kwargs') + __slots__ = ("args", "kwargs") + def __init__(self, args=None, kwargs=None, **kwgs): if args is None: args = tuple() @@ -73,15 +77,15 @@ class Params: args = (args,) else: if not isinstance(args, tuple): - raise ValueError(_('args in params must be a tuple')) + raise ValueError(_("args in params must be a tuple")) for arg in args: if not isinstance(arg, Param): - raise ValueError(_('arg in params must be a Param')) + raise ValueError(_("arg in params must be a Param")) if not isinstance(kwargs, dict): - raise ValueError(_('kwargs in params must be a dict')) + raise ValueError(_("kwargs in params must be a dict")) for arg in kwargs.values(): if not isinstance(arg, Param): - raise ValueError(_('arg in params must be a Param')) + raise ValueError(_("arg in params must be a Param")) self.args = args self.kwargs = kwargs @@ -92,78 +96,101 @@ class Param: class ParamOption(Param): - __slots__ = ('option', - 'notraisepropertyerror', - 'raisepropertyerror', - ) - def __init__(self, - option: 'Option', - notraisepropertyerror: bool=False, - raisepropertyerror: bool=False, - ) -> None: - if __debug__ and not hasattr(option, 'impl_is_symlinkoption'): - raise ValueError(_('paramoption needs an option not {}').format(type(option))) + __slots__ = ( + "option", + "notraisepropertyerror", + "raisepropertyerror", + ) + + def __init__( + self, + option: "Option", + notraisepropertyerror: bool = False, + raisepropertyerror: bool = False, + ) -> None: + if __debug__ and not hasattr(option, "impl_is_symlinkoption"): + raise ValueError( + _("paramoption needs an option not {}").format(type(option)) + ) if option.impl_is_symlinkoption(): cur_opt = option.impl_getopt() else: cur_opt = option - assert isinstance(notraisepropertyerror, bool), _('param must have a boolean not a {} for notraisepropertyerror').format(type(notraisepropertyerror)) - assert isinstance(raisepropertyerror, bool), _('param must have a boolean not a {} for raisepropertyerror').format(type(raisepropertyerror)) + assert isinstance(notraisepropertyerror, bool), _( + "param must have a boolean not a {} for notraisepropertyerror" + ).format(type(notraisepropertyerror)) + assert isinstance(raisepropertyerror, bool), _( + "param must have a boolean not a {} for raisepropertyerror" + ).format(type(raisepropertyerror)) self.option = cur_opt self.notraisepropertyerror = notraisepropertyerror self.raisepropertyerror = raisepropertyerror class ParamDynOption(ParamOption): - __slots__ = ('identifiers', - 'optional', - ) - def __init__(self, - option: 'Option', - identifiers: list[str], - notraisepropertyerror: bool=False, - raisepropertyerror: bool=False, - optional: bool=False, - ) -> None: - super().__init__(option, - notraisepropertyerror, - raisepropertyerror, - ) + __slots__ = ( + "identifiers", + "optional", + ) + + def __init__( + self, + option: "Option", + identifiers: list[str], + notraisepropertyerror: bool = False, + raisepropertyerror: bool = False, + optional: bool = False, + ) -> None: + super().__init__( + option, + notraisepropertyerror, + raisepropertyerror, + ) if not isinstance(identifiers, list): - raise Exception(f'identifiers in ParamDynOption must be a list, not {identifiers}') + raise Exception( + f"identifiers in ParamDynOption must be a list, not {identifiers}" + ) if not isinstance(optional, bool): - raise Exception(f'optional in ParamDynOption must be a boolean, not {optional}') + raise Exception( + f"optional in ParamDynOption must be a boolean, not {optional}" + ) self.identifiers = identifiers self.optional = optional class ParamSelfOption(Param): - __slots__ = ('whole') - def __init__(self, - whole: bool=undefined, - ) -> None: + __slots__ = "whole" + + def __init__( + self, + whole: bool = undefined, + ) -> None: """whole: send all value for a multi, not only indexed value""" if whole is not undefined: self.whole = whole class ParamValue(Param): - __slots__ = ('value',) + __slots__ = ("value",) + def __init__(self, value): self.value = value class ParamInformation(Param): - __slots__ = ('information_name', - 'default_value', - 'option', - 'self_option', - ) - def __init__(self, - information_name: str, - default_value: Any=undefined, - option: 'Option'=None - ) -> None: + __slots__ = ( + "information_name", + "default_value", + "option", + "self_option", + ) + + def __init__( + self, + information_name: str, + default_value: Any = undefined, + option: "Option" = None, + ) -> None: self.information_name = information_name self.default_value = default_value self.self_option = None @@ -174,20 +201,22 @@ class ParamInformation(Param): def set_self_option(self, option): self.self_option = option - def set_option(self, - option: 'Option'=None - ) -> None: - if not hasattr(self, 'self_option'): - raise ConfigError('cannot add option in information after creating config') + def set_option(self, option: "Option" = None) -> None: + if not hasattr(self, "self_option"): + raise ConfigError("cannot add option in information after creating config") if self.option: - raise ConfigError('cannot redefine option in information') + raise ConfigError("cannot redefine option in information") if not option.impl_is_optiondescription(): if option.impl_is_symlinkoption(): - raise ValueError(_('option in ParamInformation cannot be a symlinkoption')) + raise ValueError( + _("option in ParamInformation cannot be a symlinkoption") + ) if option.impl_is_follower(): - raise ValueError(_('option in ParamInformation cannot be a follower')) + raise ValueError(_("option in ParamInformation cannot be a follower")) if option.impl_is_dynsymlinkoption(): - raise ValueError(_('option in ParamInformation cannot be a dynamic option')) + raise ValueError( + _("option in ParamInformation cannot be a dynamic option") + ) self.option = option if self.self_option: informations = self.self_option._dependencies_information @@ -195,21 +224,26 @@ class ParamInformation(Param): del self.self_option._dependencies_information else: informations.remove(None) - if not getattr(option, '_dependencies_information', {}): + if not getattr(option, "_dependencies_information", {}): option._dependencies_information = {None: []} option._dependencies_information[None].append(self) - option._dependencies_information.setdefault(self.information_name, []).append(weakref.ref(self.self_option)) + option._dependencies_information.setdefault( + self.information_name, [] + ).append(weakref.ref(self.self_option)) class ParamSelfInformation(ParamInformation): __slots__ = tuple() - def __init__(self, - information_name: str, - default_value: Any=undefined, - ) -> None: - return super().__init__(information_name, - default_value, - ) + + def __init__( + self, + information_name: str, + default_value: Any = undefined, + ) -> None: + return super().__init__( + information_name, + default_value, + ) class ParamIndex(Param): @@ -217,29 +251,38 @@ class ParamIndex(Param): class ParamIdentifier(Param): - __slots__ = ('identifier_index',) - def __init__(self, - identifier_index: int=-1, - ) -> None: + __slots__ = ("identifier_index",) + + def __init__( + self, + identifier_index: int = -1, + ) -> None: self.identifier_index = identifier_index class Calculation: - __slots__ = ('function', - 'params', - 'help_function', - '_has_index', - 'warnings_only', - ) - def __init__(self, - function: Callable, - params: Params=Params(), - help_function: Optional[Callable]=None, - warnings_only: bool=False, - ): - assert isinstance(function, Callable), _('first argument ({0}) must be a function').format(function) + __slots__ = ( + "function", + "params", + "help_function", + "_has_index", + "warnings_only", + ) + + def __init__( + self, + function: Callable, + params: Params = Params(), + help_function: Optional[Callable] = None, + warnings_only: bool = False, + ): + assert isinstance(function, Callable), _( + "first argument ({0}) must be a function" + ).format(function) if help_function: - assert isinstance(help_function, Callable), _('help_function ({0}) must be a function').format(help_function) + assert isinstance(help_function, Callable), _( + "help_function ({0}) must be a function" + ).format(help_function) self.help_function = help_function else: self.help_function = None @@ -252,87 +295,98 @@ class Calculation: if warnings_only is True: self.warnings_only = warnings_only - def execute(self, - subconfig: "SubConfig", - *, - orig_value: Any=undefined, - allow_value_error: bool=False, - force_value_warning: bool=False, - for_settings: bool=False, - validate_properties: bool=True, - ) -> Any: - return carry_out_calculation(subconfig, - callback=self.function, - callback_params=self.params, - index=subconfig.index, - config_bag=subconfig.config_bag, - orig_value=orig_value, - allow_value_error=allow_value_error, - force_value_warning=force_value_warning, - for_settings=for_settings, - validate_properties=validate_properties, - ) + def execute( + self, + subconfig: "SubConfig", + *, + orig_value: Any = undefined, + allow_value_error: bool = False, + force_value_warning: bool = False, + for_settings: bool = False, + validate_properties: bool = True, + ) -> Any: + return carry_out_calculation( + subconfig, + callback=self.function, + callback_params=self.params, + index=subconfig.index, + config_bag=subconfig.config_bag, + orig_value=orig_value, + allow_value_error=allow_value_error, + force_value_warning=force_value_warning, + for_settings=for_settings, + validate_properties=validate_properties, + ) - def help(self, - subconfig: "SubConfig", - for_settings: bool=False, - ) -> str: + def help( + self, + subconfig: "SubConfig", + for_settings: bool = False, + ) -> str: if not self.help_function: - return self.execute(subconfig, - for_settings=for_settings, - ) - return carry_out_calculation(subconfig, - callback=self.help_function, - callback_params=self.params, - index=subconfig.index, - config_bag=subconfig.config_bag, - for_settings=for_settings, - ) + return self.execute( + subconfig, + for_settings=for_settings, + ) + return carry_out_calculation( + subconfig, + callback=self.help_function, + callback_params=self.params, + index=subconfig.index, + config_bag=subconfig.config_bag, + for_settings=for_settings, + ) def __deepcopy__(x, memo): return x -def manager_callback(callback: Callable, - param: Param, - subconfig: 'SubConfig', - index: Optional[int], - orig_value, - config_bag: ConfigBag, - for_settings: bool, - validate_properties: bool, - ) -> Any: +def manager_callback( + callback: Callable, + param: Param, + subconfig: "SubConfig", + index: Optional[int], + orig_value, + config_bag: ConfigBag, + for_settings: bool, + validate_properties: bool, +) -> Any: """replace Param by true value""" option = subconfig.option - def calc_apply_index(param, - same_leadership, - ): - return index is not None and \ - not getattr(param, 'whole', not same_leadership) - def calc_self(param, - index, - value, - config_bag, - ): + def calc_apply_index( + param, + same_leadership, + ): + return index is not None and not getattr(param, "whole", not same_leadership) + + def calc_self( + param, + index, + value, + config_bag, + ): # index must be apply only if follower is_follower = subconfig.option.impl_is_follower() # FIXME "same_leadership" or "is_follower"? - apply_index = calc_apply_index(param, - is_follower, - ) + apply_index = calc_apply_index( + param, + is_follower, + ) if value is undefined or (apply_index is False and is_follower): path = subconfig.path - properties = config_bag.context.get_settings().getproperties(subconfig, - uncalculated=True, - ) - new_value = get_value(config_bag, - subconfig, - param, - True, - apply_index=apply_index, - properties=properties, - ) + properties = config_bag.context.get_settings().getproperties( + subconfig, + uncalculated=True, + ) + new_value = get_value( + config_bag, + subconfig, + param, + True, + apply_index=apply_index, + properties=properties, + ) if apply_index is False and is_follower: new_value[index] = value value = new_value @@ -340,101 +394,148 @@ def manager_callback(callback: Callable, value = value[index] return value - def get_value(config_bag, - subconfig, - param, - self_calc, - *, - apply_index=True, - properties=undefined, - ): + def get_value( + config_bag, + subconfig, + param, + self_calc, + *, + apply_index=True, + properties=undefined, + ): option = subconfig.option - if option.impl_is_follower() and (subconfig.index is None or apply_index is False): + if option.impl_is_follower() and ( + subconfig.index is None or apply_index is False + ): value = [] for idx in range(subconfig.parent.get_length_leadership()): - subconfig = get_option_bag(config_bag, - option, - param, - idx, - self_calc, - properties=properties, - ) - value.append(_get_value(param, - subconfig, - )) + subconfig = get_option_bag( + config_bag, + option, + param, + idx, + self_calc, + properties=properties, + ) + value.append( + _get_value( + param, + subconfig, + ) + ) else: - value = _get_value(param, - subconfig, - ) + value = _get_value( + param, + subconfig, + ) return value - def _get_value(param: Params, - subconfig: 'SubConfig', - ) -> Any: + def _get_value( + param: Params, + subconfig: "SubConfig", + ) -> Any: try: # get value value = config_bag.context.get_value(subconfig) except PropertiesOptionError as err: # raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation - if isinstance(param, ParamSelfOption) or param.notraisepropertyerror or param.raisepropertyerror: + if ( + isinstance(param, ParamSelfOption) + or param.notraisepropertyerror + or param.raisepropertyerror + ): raise err from err - display_name = subconfig.option.impl_get_display_name(subconfig, with_quote=True) - raise ConfigError(_('unable to carry out a calculation for {}, {}').format(display_name, err)) from err + display_name = subconfig.option.impl_get_display_name( + subconfig, with_quote=True + ) + raise ConfigError( + _("unable to carry out a calculation for {}, {}").format( + display_name, err + ) + ) from err except ValueError as err: - display_name = subconfig.option.impl_get_display_name(subconfig, with_quote=True) - raise ValueError(_('the option {0} is used in a calculation but is invalid ({1})').format(display_name, err)) from err + display_name = subconfig.option.impl_get_display_name( + subconfig, with_quote=True + ) + raise ValueError( + _( + "the option {0} is used in a calculation but is invalid ({1})" + ).format(display_name, err) + ) from err except AttributeError as err: if isinstance(param, ParamDynOption) and param.optional: # cannot acces, simulate a propertyerror - raise PropertiesOptionError(subconfig, - ['configerror'], - config_bag.context.get_settings(), - ) - display_name = subconfig.option.impl_get_display_name(subconfig, with_quote=True) - raise ConfigError(_(f'unable to get value for calculating {display_name}, {err}')) from err + raise PropertiesOptionError( + subconfig, + ["configerror"], + config_bag.context.get_settings(), + ) + display_name = subconfig.option.impl_get_display_name( + subconfig, with_quote=True + ) + raise ConfigError( + _("unable to get value for calculating {0}, {1}").format( + display_name, err + ) + ) from err return value - def get_option_bag(config_bag, - opt, - param, - index_, - self_calc, - *, - properties=undefined, - ): + def get_option_bag( + config_bag, + opt, + param, + index_, + self_calc, + *, + properties=undefined, + ): # don't validate if option is option that we tried to validate if for_settings: - config_bag.properties = config_bag.properties - {'warnings'} + config_bag.properties = config_bag.properties - {"warnings"} if not for_settings: - config_bag.properties -= {'warnings'} + config_bag.properties -= {"warnings"} if self_calc: config_bag.unrestraint() config_bag.remove_validation() try: - subsubconfig = config_bag.context.get_sub_config(config_bag, - opt.impl_getpath(), - index_, - validate_properties=not self_calc, - properties=properties, - ) + subsubconfig = config_bag.context.get_sub_config( + config_bag, + opt.impl_getpath(), + index_, + validate_properties=not self_calc, + properties=properties, + ) except PropertiesOptionError as err: # raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation if param.notraisepropertyerror or param.raisepropertyerror: raise err from err display_name = option.impl_get_display_name(subconfig, with_quote=True) - raise ConfigError(_('unable to carry out a calculation for {}, {}').format(display_name, err)) from err + raise ConfigError( + _("unable to carry out a calculation for {}, {}").format( + display_name, err + ) + ) from err except ValueError as err: display_name = option.impl_get_display_name(subconfig, with_quote=True) - raise ValueError(_('the option {0} is used in a calculation but is invalid ({1})').format(display_name, err)) from err + raise ValueError( + _( + "the option {0} is used in a calculation but is invalid ({1})" + ).format(display_name, err) + ) from err except AttributeError as err: if isinstance(param, ParamDynOption) and param.optional: # cannot acces, simulate a propertyerror - raise PropertiesOptionError(param, - ['configerror'], - config_bag.context.get_settings(), - ) + raise PropertiesOptionError( + param, + ["configerror"], + config_bag.context.get_settings(), + ) display_name = option.impl_get_display_name(subconfig, with_quote=True) - raise ConfigError(_(f'unable to get value for calculating {display_name}, {err}')) from err + raise ConfigError( + _("unable to get value for calculating {0}, {1}").format( + display_name, err + ) + ) from err return subsubconfig if isinstance(param, ParamValue): @@ -446,57 +547,84 @@ def manager_callback(callback: Callable, elif param.option: if param.option.issubdyn(): search_option = param.option - isubconfig = subconfig.get_common_child(search_option, - true_path=subconfig.path, - ) + isubconfig = subconfig.get_common_child( + search_option, + true_path=subconfig.path, + ) if isinstance(isubconfig, list): - display_name = option.impl_get_display_name(subconfig, with_quote=True) - search_name = search_option.impl_get_display_name(None, with_quote=True) - raise ConfigError(f'cannot find information for {display_name}, {search_name} is a dynamic option') + display_name = option.impl_get_display_name( + subconfig, with_quote=True + ) + search_name = search_option.impl_get_display_name( + None, with_quote=True + ) + raise ConfigError( + f"cannot find information for {display_name}, {search_name} is a dynamic option" + ) else: - isubconfig = get_option_bag(config_bag, - param.option, - param, - None, - False, - #properties=properties, - ) + isubconfig = get_option_bag( + config_bag, + param.option, + param, + None, + False, + # properties=properties, + ) else: isubconfig = config_bag.context.get_root(config_bag) try: - return config_bag.context.get_values().get_information(isubconfig, - param.information_name, - param.default_value, - ) + return config_bag.context.get_values().get_information( + isubconfig, + param.information_name, + param.default_value, + ) except ValueError as err: display_name = option.impl_get_display_name(subconfig, with_quote=True) - raise ConfigError(_(f'unable to get value for calculating {display_name}, {err}')) from err + raise ConfigError( + _("unable to get value for calculating {0}, {1}").format( + display_name, err + ) + ) from err if isinstance(param, ParamIndex): return index if isinstance(param, ParamIdentifier): - if not option.issubdyn() and (not option.impl_is_optiondescription() or not option.impl_is_dynoptiondescription()): - display_name = subconfig.option.impl_get_display_name(subconfig, with_quote=True) - raise ConfigError(_(f'option {display_name} is not a dynoptiondescription or in a dynoptiondescription')) + if not option.issubdyn() and ( + not option.impl_is_optiondescription() + or not option.impl_is_dynoptiondescription() + ): + display_name = subconfig.option.impl_get_display_name( + subconfig, with_quote=True + ) + raise ConfigError( + _( + "option {0} is not a dynoptiondescription or in a dynoptiondescription" + ).format(display_name) + ) return subconfig.identifiers[param.identifier_index] if isinstance(param, ParamSelfOption): - value = calc_self(param, - index, - orig_value, - config_bag, - ) + value = calc_self( + param, + index, + orig_value, + config_bag, + ) if callback.__name__ not in FUNCTION_WAITING_FOR_DICT: return value - return {'name': option.impl_get_display_name(subconfig), - 'value': value, - } + return { + "name": option.impl_get_display_name(subconfig), + "value": value, + } if isinstance(param, ParamOption): callbk_option = param.option - if index is not None and callbk_option.impl_get_leadership() and \ - callbk_option.impl_get_leadership().in_same_leadership(option): + if ( + index is not None + and callbk_option.impl_get_leadership() + and callbk_option.impl_get_leadership().in_same_leadership(option) + ): if not callbk_option.impl_is_follower(): # leader index_ = None @@ -511,17 +639,18 @@ def manager_callback(callback: Callable, if callbk_option.issubdyn(): if isinstance(param, ParamDynOption): identifiers = param.identifiers.copy() - paths = callbk_option.impl_getpath().split('.') + paths = callbk_option.impl_getpath().split(".") parents = [config_bag.context.get_root(config_bag)] subconfigs_is_a_list = False for name in paths: new_parents = [] for parent in parents: - doption = parent.option.get_child(name, - config_bag, - parent, - allow_dynoption=True, - ) + doption = parent.option.get_child( + name, + config_bag, + parent, + allow_dynoption=True, + ) if doption.impl_is_dynoptiondescription(): if not identifiers: identifier = None @@ -529,31 +658,40 @@ def manager_callback(callback: Callable, identifier = identifiers.pop(0) if not identifier: subconfigs_is_a_list = True - new_parents.extend(parent.dyn_to_subconfig(doption, - True, - ) - ) + new_parents.extend( + parent.dyn_to_subconfig( + doption, + True, + ) + ) else: name = doption.impl_getname(identifier) try: - doption = parent.option.get_child(name, - config_bag, - parent, - ) + doption = parent.option.get_child( + name, + config_bag, + parent, + ) except AttributeError as err: raise ConfigError(err) from err - new_parents.append(parent.get_child(doption, - None, - True, - name=name, - identifier=identifier, - )) + new_parents.append( + parent.get_child( + doption, + None, + True, + name=name, + identifier=identifier, + ) + ) else: - new_parents.append(parent.get_child(doption, - None, - True, - name=name, - )) + new_parents.append( + parent.get_child( + doption, + None, + True, + name=name, + ) + ) parents = new_parents if subconfigs_is_a_list: @@ -563,32 +701,36 @@ def manager_callback(callback: Callable, else: search_option = param.option - subconfigs = subconfig.get_common_child(search_option, - true_path=subconfig.path, - validate_properties=validate_properties, - ) + subconfigs = subconfig.get_common_child( + search_option, + true_path=subconfig.path, + validate_properties=validate_properties, + ) if isinstance(subconfigs, list): values = [] else: values = None subconfigs = [subconfigs] else: - subconfigs = [get_option_bag(config_bag, - callbk_option, - param, - index_, - False, - #properties=properties, - ) - ] + subconfigs = [ + get_option_bag( + config_bag, + callbk_option, + param, + index_, + False, + # properties=properties, + ) + ] values = None for subconfig in subconfigs: callbk_option = subconfig.option - value = get_value(config_bag, - subconfig, - param, - False, - ) + value = get_value( + config_bag, + subconfig, + param, + False, + ) if with_index: value = value[index] if values is not None: @@ -597,22 +739,22 @@ def manager_callback(callback: Callable, value = values if callback.__name__ not in FUNCTION_WAITING_FOR_DICT: return value - return {'name': callbk_option.impl_get_display_name(subconfig), - 'value': value} + return {"name": callbk_option.impl_get_display_name(subconfig), "value": value} -def carry_out_calculation(subconfig: 'SubConfig', - callback: Callable, - callback_params: Optional[Params], - index: Optional[int], - config_bag: Optional[ConfigBag], - orig_value=undefined, - allow_value_error: bool=False, - force_value_warning: bool=False, - for_settings: bool=False, - *, - validate_properties: bool=True, - ): +def carry_out_calculation( + subconfig: "SubConfig", + callback: Callable, + callback_params: Optional[Params], + index: Optional[int], + config_bag: Optional[ConfigBag], + orig_value=undefined, + allow_value_error: bool = False, + force_value_warning: bool = False, + for_settings: bool = False, + *, + validate_properties: bool = True, +): """a function that carries out a calculation for an option's value :param option: the option @@ -630,26 +772,37 @@ def carry_out_calculation(subconfig: 'SubConfig', if PropertiesOptionError) Values could have multiple values only when key is ''.""" option = subconfig.option - if not option.impl_is_optiondescription() and option.impl_is_follower() and index is None: - raise ConfigError(f'the follower {option.impl_get_display_name(subconfig, with_quote=True)} must have index in carry_out_calculation!') + if ( + not option.impl_is_optiondescription() + and option.impl_is_follower() + and index is None + ): + raise ConfigError( + f"the follower {option.impl_get_display_name(subconfig, with_quote=True)} must have index in carry_out_calculation!" + ) + def fake_items(iterator): return ((None, i) for i in iterator) + args = [] kwargs = {} config_bag = config_bag.copy() config_bag.set_permissive() if callback_params: - for key, param in chain(fake_items(callback_params.args), callback_params.kwargs.items()): + for key, param in chain( + fake_items(callback_params.args), callback_params.kwargs.items() + ): try: - value = manager_callback(callback, - param, - subconfig, - index, - orig_value, - config_bag, - for_settings, - validate_properties, - ) + value = manager_callback( + callback, + param, + subconfig, + index, + orig_value, + config_bag, + for_settings, + validate_properties, + ) if key is None: args.append(value) else: @@ -659,49 +812,75 @@ def carry_out_calculation(subconfig: 'SubConfig', raise err if callback.__name__ in FUNCTION_WAITING_FOR_DICT: if key is None: - args.append({'propertyerror': str(err), 'name': option.impl_get_display_name(subconfig)}) + args.append( + { + "propertyerror": str(err), + "name": option.impl_get_display_name(subconfig), + } + ) else: - kwargs[key] = {'propertyerror': str(err), 'name': option.impl_get_display_name(subconfig)} + kwargs[key] = { + "propertyerror": str(err), + "name": option.impl_get_display_name(subconfig), + } if callback.__name__ in FUNCTION_WAITING_FOR_ERROR: if key is None: args.append(err) else: kwargs[key] = err - ret = calculate(subconfig, - callback, - allow_value_error, - force_value_warning, + ret = calculate( + subconfig, + callback, + allow_value_error, + force_value_warning, + args, + kwargs, + ) + if ( + isinstance(ret, list) + and not option.impl_is_dynoptiondescription() + and not option.impl_is_optiondescription() + and option.impl_is_follower() + and not option.impl_is_submulti() + ): + if args or kwargs: + raise LeadershipError( + _( + 'the "{}" function with positional arguments "{}" ' + 'and keyword arguments "{}" must not return ' + 'a list ("{}") for the follower option {}' + "" + ).format( + callback.__name__, args, kwargs, - ) - if isinstance(ret, list) and not option.impl_is_dynoptiondescription() and \ - not option.impl_is_optiondescription() and \ - option.impl_is_follower() and not option.impl_is_submulti(): - if args or kwargs: - raise LeadershipError(_('the "{}" function with positional arguments "{}" ' - 'and keyword arguments "{}" must not return ' - 'a list ("{}") for the follower option {}' - '').format(callback.__name__, - args, - kwargs, - ret, - option.impl_get_display_name(subconfig, with_quote=True))) + ret, + option.impl_get_display_name(subconfig, with_quote=True), + ) + ) else: - raise LeadershipError(_('the "{}" function must not return a list ("{}") ' - 'for the follower option {}' - '').format(callback.__name__, - ret, - option.impl_get_display_name(subconfig, with_quote=True))) + raise LeadershipError( + _( + 'the "{}" function must not return a list ("{}") ' + "for the follower option {}" + "" + ).format( + callback.__name__, + ret, + option.impl_get_display_name(subconfig, with_quote=True), + ) + ) return ret -def calculate(subconfig, - callback: Callable, - allow_value_error: bool, - force_value_warning: bool, - args, - kwargs, - ): +def calculate( + subconfig, + callback: Callable, + allow_value_error: bool, + force_value_warning: bool, + args, + kwargs, +): """wrapper that launches the 'callback' :param callback: callback function @@ -722,15 +901,20 @@ def calculate(subconfig, except Exception as err: error = err if args or kwargs: - msg = _('unexpected error "{0}" in function "{1}" with arguments "{3}" and "{4}" ' - 'for option {2}').format(str(error), - callback.__name__, - subconfig.option.impl_get_display_name(subconfig, with_quote=True), - args, - kwargs) + msg = _( + 'unexpected error "{0}" in function "{1}" with arguments "{3}" and "{4}" ' + "for option {2}" + ).format( + str(error), + callback.__name__, + subconfig.option.impl_get_display_name(subconfig, with_quote=True), + args, + kwargs, + ) else: - msg = _('unexpected error "{0}" in function "{1}" for option {2}' - '').format(str(error), - callback.__name__, - subconfig.option.impl_get_display_name(subconfig, with_quote=True)) + msg = _('unexpected error "{0}" in function "{1}" for option {2}' "").format( + str(error), + callback.__name__, + subconfig.option.impl_get_display_name(subconfig, with_quote=True), + ) raise ConfigError(msg) from error diff --git a/tiramisu/cacheobj.py b/tiramisu/cacheobj.py index 171f058..508fb2f 100644 --- a/tiramisu/cacheobj.py +++ b/tiramisu/cacheobj.py @@ -19,9 +19,9 @@ from time import time class Cache: - """cache object - """ - __slots__ = ('_cache',) + """cache object""" + + __slots__ = ("_cache",) def __init__(self): self._cache = {} @@ -35,29 +35,30 @@ class Cache: index = subconfig.index return path, index - def getcache(self, - subconfig, - type_, - expiration=True, - ): - """get the cache value fot a specified path - """ + def getcache( + self, + subconfig, + type_, + expiration=True, + ): + """get the cache value fot a specified path""" no_cache = False, None, False path, index = self._get_path_index(subconfig) if path not in self._cache or index not in self._cache[path]: return no_cache value, timestamp, validated = self._cache[path][index] props = subconfig.config_bag.properties - if type_ == 'self_props': + if type_ == "self_props": # cached value is self_props self_props = value else: self_props = subconfig.properties - if 'cache' in props or \ - 'cache' in self_props: - if expiration and timestamp and \ - ('expire' in props or \ - 'expire' in self_props): + if "cache" in props or "cache" in self_props: + if ( + expiration + and timestamp + and ("expire" in props or "expire" in self_props) + ): ntime = int(time()) if timestamp + subconfig.config_bag.expiration_time >= ntime: return True, value, validated @@ -65,37 +66,38 @@ class Cache: return True, value, validated return no_cache - def setcache(self, - subconfig, - val, - type_='values', - validated=True, - ): + def setcache( + self, + subconfig, + val, + type_="values", + validated=True, + ): """add val in cache for a specified path if follower, add index """ - if type_ == 'values': - if 'cache' not in subconfig.config_bag.properties and \ - 'cache' not in subconfig.properties: + if type_ == "values": + if ( + "cache" not in subconfig.config_bag.properties + and "cache" not in subconfig.properties + ): return - elif (subconfig is None or 'cache' not in subconfig.config_bag.properties) and \ - 'cache' not in val: + elif ( + subconfig is None or "cache" not in subconfig.config_bag.properties + ) and "cache" not in val: return path, index = self._get_path_index(subconfig) self._cache.setdefault(path, {})[index] = (val, int(time()), validated) def delcache(self, path): - """reset cache a a specified path - """ - if path in self._cache: + """reset cache a a specified path""" + if path in self._cache: del self._cache[path] def get_cached(self): - """get cache values - """ + """get cache values""" return self._cache def reset_all_cache(self): - """reset all cache values - """ + """reset all cache values""" self._cache.clear() diff --git a/tiramisu/config.py b/tiramisu/config.py index 6c2e645..444157b 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -25,8 +25,7 @@ from copy import copy, deepcopy from typing import Optional, List, Any, Union from os.path import commonprefix -from .error import PropertiesOptionError, ConfigError, ConflictError, \ - LeadershipError +from .error import PropertiesOptionError, ConfigError, ConflictError, LeadershipError from .option import DynOptionDescription, Leadership, Option from .setting import ConfigBag, Settings, undefined, groups from .value import Values, owners @@ -40,43 +39,49 @@ def get_common_path(path1, path2): common_path = commonprefix([path1, path2]) if common_path in [path1, path2]: return common_path - if common_path.endswith('.'): + if common_path.endswith("."): return common_path[:-1] - if '.' in common_path: - return common_path.rsplit('.', 1)[0] + if "." in common_path: + return common_path.rsplit(".", 1)[0] return None class CCache: __slots__ = tuple() + # ============================================================================= # CACHE - def reset_cache(self, - subconfig, - resetted_opts=None, - ): - """reset all settings in cache - """ + def reset_cache( + self, + subconfig, + resetted_opts=None, + ): + """reset all settings in cache""" if resetted_opts is None: resetted_opts = [] if subconfig is not None: - if 'cache' not in subconfig.config_bag.properties: + if "cache" not in subconfig.config_bag.properties: return - subconfig.config_bag.properties = subconfig.config_bag.properties - {'cache'} - self.reset_one_option_cache(subconfig, - resetted_opts, - ) - subconfig.config_bag.properties = subconfig.config_bag.properties | {'cache'} + subconfig.config_bag.properties = subconfig.config_bag.properties - { + "cache" + } + self.reset_one_option_cache( + subconfig, + resetted_opts, + ) + subconfig.config_bag.properties = subconfig.config_bag.properties | { + "cache" + } else: self._impl_values_cache.reset_all_cache() # pylint: disable=no-member self.properties_cache.reset_all_cache() # pylint: disable=no-member - def reset_one_option_cache(self, - subconfig, - resetted_opts, - ): - """reset cache for one option - """ + def reset_one_option_cache( + self, + subconfig, + resetted_opts, + ): + """reset cache for one option""" if subconfig.path in resetted_opts: return resetted_opts.append(subconfig.path) @@ -85,122 +90,146 @@ class CCache: option = woption() if option.issubdyn(): # it's an option in dynoptiondescription, remove cache for all generated option - self.reset_cache_dyn_option(config_bag, - option, - resetted_opts, - ) + self.reset_cache_dyn_option( + config_bag, + option, + resetted_opts, + ) elif option.impl_is_dynoptiondescription(): - self._reset_cache_dyn_optiondescription(option, - config_bag, - resetted_opts, - ) + self._reset_cache_dyn_optiondescription( + option, + config_bag, + resetted_opts, + ) else: - option_subconfig = self.get_sub_config(config_bag, - option.impl_getpath(), - None, - properties=None, - validate_properties=False, - ) - self.reset_one_option_cache(option_subconfig, - resetted_opts, - ) + option_subconfig = self.get_sub_config( + config_bag, + option.impl_getpath(), + None, + properties=None, + validate_properties=False, + ) + self.reset_one_option_cache( + option_subconfig, + resetted_opts, + ) del option - subconfig.option.reset_cache(subconfig.path, - config_bag, - resetted_opts, - ) + subconfig.option.reset_cache( + subconfig.path, + config_bag, + resetted_opts, + ) - def _reset_cache_dyn_optiondescription(self, - option, - config_bag, - resetted_opts, - ): + def _reset_cache_dyn_optiondescription( + self, + option, + config_bag, + resetted_opts, + ): # reset cache for all chidren path = option.impl_getpath() - if '.' in path: - parent_path = path.rsplit('.', 1)[0] - parent_subconfig = self.get_sub_config(config_bag, - parent_path, - None, - properties=None, - validate_properties=False, - ) + if "." in path: + parent_path = path.rsplit(".", 1)[0] + parent_subconfig = self.get_sub_config( + config_bag, + parent_path, + None, + properties=None, + validate_properties=False, + ) else: parent_subconfig = self.get_root(config_bag) - for subconfig in parent_subconfig.dyn_to_subconfig(option, - False, - ): - self.reset_one_option_cache(subconfig, - resetted_opts, - ) - for walk_subconfig in self.walk(subconfig, - no_value=True, - validate_properties=False, - ): - self.reset_one_option_cache(walk_subconfig, - resetted_opts, - ) + for subconfig in parent_subconfig.dyn_to_subconfig( + option, + False, + ): + self.reset_one_option_cache( + subconfig, + resetted_opts, + ) + for walk_subconfig in self.walk( + subconfig, + no_value=True, + validate_properties=False, + ): + self.reset_one_option_cache( + walk_subconfig, + resetted_opts, + ) - - def reset_cache_dyn_option(self, - config_bag, - option, - resetted_opts, - ): + def reset_cache_dyn_option( + self, + config_bag, + option, + resetted_opts, + ): currents = [self.get_root(config_bag)] sub_paths = option.impl_getpath() - for sub_path in sub_paths.split('.'): + for sub_path in sub_paths.split("."): new_currents = [] for current in currents: - sub_option = current.option.get_child(sub_path, - config_bag, - current, - allow_dynoption=True, - ) + sub_option = current.option.get_child( + sub_path, + config_bag, + current, + allow_dynoption=True, + ) if sub_option.impl_is_dynoptiondescription(): - new_currents.extend(list(current.dyn_to_subconfig(sub_option, - False, - ))) + new_currents.extend( + list( + current.dyn_to_subconfig( + sub_option, + False, + ) + ) + ) else: - new_currents.append(current.get_child(sub_option, - None, - False, - properties=None, - ), - ) + new_currents.append( + current.get_child( + sub_option, + None, + False, + properties=None, + ), + ) currents = new_currents for dyn_option_subconfig in currents: - self.reset_one_option_cache(dyn_option_subconfig, - resetted_opts, - ) + self.reset_one_option_cache( + dyn_option_subconfig, + resetted_opts, + ) + class SubConfig: - __slots__ = ('config_bag', - 'option', - 'parent', - 'index', - 'path', - 'true_path', - '_properties', - 'apply_requires', - 'transitive_properties', - 'is_dynamic', - 'identifiers', - '_length', - ) - def __init__(self, - option: Option, - index: Optional[int], - path: str, - config_bag: ConfigBag, - parent: Optional['SubConfig'], - identifiers: Optional[list[str]], - *, - true_path: Optional[str]=None, - properties: Union[list[str], undefined]=undefined, - validate_properties: bool=True, - ) -> None: + __slots__ = ( + "config_bag", + "option", + "parent", + "index", + "path", + "true_path", + "_properties", + "apply_requires", + "transitive_properties", + "is_dynamic", + "identifiers", + "_length", + ) + + def __init__( + self, + option: Option, + index: Optional[int], + path: str, + config_bag: ConfigBag, + parent: Optional["SubConfig"], + identifiers: Optional[list[str]], + *, + true_path: Optional[str] = None, + properties: Union[list[str], undefined] = undefined, + validate_properties: bool = True, + ) -> None: self.index = index self.identifiers = identifiers self.option = option @@ -210,7 +239,9 @@ class SubConfig: self.path = path if true_path is None: true_path = path - is_follower = not option.impl_is_optiondescription() and option.impl_is_follower() + is_follower = ( + not option.impl_is_optiondescription() and option.impl_is_follower() + ) self.apply_requires = not is_follower or index is not None self.true_path = true_path if parent and parent.is_dynamic or self.option.impl_is_dynoptiondescription(): @@ -221,18 +252,20 @@ class SubConfig: if validate_properties: if self.path and self._properties is undefined: settings = config_bag.context.get_settings() - self._properties = settings.getproperties(self, - apply_requires=False, - ) + self._properties = settings.getproperties( + self, + apply_requires=False, + ) self.config_bag.context.get_settings().validate_properties(self) self._properties = undefined self.config_bag.context.get_settings().validate_properties(self) if self.apply_requires and self.option.impl_is_optiondescription(): if self.path and self.properties is not None: settings = config_bag.context.get_settings() - self.transitive_properties = settings.calc_transitive_properties(self, - self.properties, - ) + self.transitive_properties = settings.calc_transitive_properties( + self, + self.properties, + ) else: self.transitive_properties = frozenset() @@ -244,9 +277,10 @@ class SubConfig: else: settings = self.config_bag.context.get_settings() self._properties = frozenset() - self._properties = settings.getproperties(self, - apply_requires=self.apply_requires, - ) + self._properties = settings.getproperties( + self, + apply_requires=self.apply_requires, + ) return self._properties @properties.setter @@ -254,14 +288,15 @@ class SubConfig: self._properties = properties def __repr__(self): - return f'' + return f"" - def dyn_to_subconfig(self, - child: Option, - validate_properties: bool, - *, - true_path: Optional[str]=None, - ) -> List['SubConfig']: + def dyn_to_subconfig( + self, + child: Option, + validate_properties: bool, + *, + true_path: Optional[str] = None, + ) -> List["SubConfig"]: config_bag = self.config_bag for identifier in child.get_identifiers(self): try: @@ -270,84 +305,93 @@ class SubConfig: properties = None else: properties = undefined - yield self.get_child(child, - None, - validate_properties, - identifier=identifier, - name=name, - properties=properties, - true_path=true_path, - ) + yield self.get_child( + child, + None, + validate_properties, + identifier=identifier, + name=name, + properties=properties, + true_path=true_path, + ) except PropertiesOptionError as err: - if err.proptype in (['mandatory'], ['empty']): + if err.proptype in (["mandatory"], ["empty"]): raise err - def get_leadership_children(self, - validate_properties, - ): + def get_leadership_children( + self, + validate_properties, + ): # it's a leadership so walk to leader and follower # followers has specific length leader, *followers = self.option.get_children() - yield self.get_child(leader, - None, - validate_properties, - ) + yield self.get_child( + leader, + None, + validate_properties, + ) for idx in range(self.get_length_leadership()): for follower in followers: try: - yield self.get_child(follower, - idx, - validate_properties, - ) + yield self.get_child( + follower, + idx, + validate_properties, + ) except PropertiesOptionError as err: - if err.proptype in (['mandatory'], ['empty']): + if err.proptype in (["mandatory"], ["empty"]): raise err from err - def get_children(self, - validate_properties, - *, - uncalculated: bool=False, - ): + def get_children( + self, + validate_properties, + *, + uncalculated: bool = False, + ): if self.option.impl_is_leadership() and not uncalculated: yield from self.get_leadership_children(validate_properties) else: for child in self.option.get_children(): if child.impl_is_dynoptiondescription() and not uncalculated: - yield from self.dyn_to_subconfig(child, - validate_properties, - ) + yield from self.dyn_to_subconfig( + child, + validate_properties, + ) else: try: - yield self.get_child(child, - None, - validate_properties, - ) + yield self.get_child( + child, + None, + validate_properties, + ) except PropertiesOptionError as err: - if err.proptype in (['mandatory'], ['empty']): + if err.proptype in (["mandatory"], ["empty"]): raise err - def get_child(self, - option: Option, - index: Optional[int], - validate_properties: bool, - *, - properties=undefined, - allow_dynoption: bool=False, - identifier: Optional[str]=None, - name: Optional[str]=None, - check_index: bool=True, - config_bag: ConfigBag=None, - true_path: Optional[str]=None, - ) -> 'SubConfig': + def get_child( + self, + option: Option, + index: Optional[int], + validate_properties: bool, + *, + properties=undefined, + allow_dynoption: bool = False, + identifier: Optional[str] = None, + name: Optional[str] = None, + check_index: bool = True, + config_bag: ConfigBag = None, + true_path: Optional[str] = None, + ) -> "SubConfig": # pylint: disable=too-many-branches,too-many-locals,too-many-arguments if config_bag is None: config_bag = self.config_bag if not self.option.impl_is_optiondescription(): raise TypeError(f'"{self.path}" is not an optiondescription') - path = self.get_path(name, - option, - ) + path = self.get_path( + name, + option, + ) if identifier is None: identifiers = self.identifiers else: @@ -355,123 +399,144 @@ class SubConfig: identifiers = self.identifiers + [identifier] else: identifiers = [identifier] - subsubconfig = SubConfig(option, - index, - path, - self.config_bag, - self, - identifiers, - properties=properties, - validate_properties=validate_properties, - true_path=true_path, - ) + subsubconfig = SubConfig( + option, + index, + path, + self.config_bag, + self, + identifiers, + properties=properties, + validate_properties=validate_properties, + true_path=true_path, + ) if check_index and index is not None: - if option.impl_is_optiondescription() or \ - not option.impl_is_follower(): - raise ConfigError('index must be set only with a follower option') + if option.impl_is_optiondescription() or not option.impl_is_follower(): + raise ConfigError("index must be set only with a follower option") length = self.get_length_leadership() if index >= length: - raise LeadershipError(_(f'index "{index}" is greater than the leadership ' - f'length "{length}" for option ' - f'{option.impl_get_display_name(subsubconfig, with_quote=True)}')) + raise LeadershipError( + _( + 'index "{0}" is greater than the leadership length "{1}" for option {2}' + ).format( + index, + length, + option.impl_get_display_name(subsubconfig, with_quote=True), + ) + ) return subsubconfig - def get_path(self, - name: str, - option: Option, - ) -> str: + def get_path( + self, + name: str, + option: Option, + ) -> str: if name is None: name = option.impl_getname() if self.path is None: path = name else: - path = self.path + '.' + name + path = self.path + "." + name return path def get_length_leadership(self): - """Get the length of leader option (useful to know follower's length) - """ + """Get the length of leader option (useful to know follower's length)""" if self._length is None: cconfig_bag = self.config_bag.copy() cconfig_bag.remove_validation() leader = self.option.get_leader() - path = self.get_path(None, - leader, - ) - subconfig = SubConfig(leader, - None, - path, - cconfig_bag, - self, - self.identifiers, - validate_properties=False, - ) + path = self.get_path( + None, + leader, + ) + subconfig = SubConfig( + leader, + None, + path, + cconfig_bag, + self, + self.identifiers, + validate_properties=False, + ) self._length = len(cconfig_bag.context.get_value(subconfig)) return self._length - def get_common_child(self, - search_option: 'BaseOption', - true_path: Optional[str]=None, - validate_properties: bool=True, - ): + def get_common_child( + self, + search_option: "BaseOption", + true_path: Optional[str] = None, + validate_properties: bool = True, + ): current_option_path = self.option.impl_getpath() search_option_path = search_option.impl_getpath() common_path = get_common_path(current_option_path, search_option_path) config_bag = self.config_bag index = None - if not self.option.impl_is_optiondescription() and \ - self.option.impl_is_follower() and search_option.impl_is_follower() and \ - self.parent.option == search_option.impl_get_leadership(): + if ( + not self.option.impl_is_optiondescription() + and self.option.impl_is_follower() + and search_option.impl_is_follower() + and self.parent.option == search_option.impl_get_leadership() + ): index = self.index search_child_number = 0 parents = [self.parent] else: if common_path: parent = self.parent - common_parent_number = common_path.count('.') + 1 - for idx in range(current_option_path.count('.') - common_parent_number): + common_parent_number = common_path.count(".") + 1 + for idx in range(current_option_path.count(".") - common_parent_number): parent = parent.parent parents = [parent] else: common_parent_number = 0 parents = [config_bag.context.get_root(config_bag)] - search_child_number = search_option_path.count('.') - common_parent_number + search_child_number = search_option_path.count(".") - common_parent_number subconfigs_is_a_list = False if search_child_number: if common_parent_number: - parent_paths = search_option_path.rsplit('.', search_child_number + 1)[1:-1] + parent_paths = search_option_path.rsplit(".", search_child_number + 1)[ + 1:-1 + ] else: - parent_paths = search_option_path.split('.')[:-1] + parent_paths = search_option_path.split(".")[:-1] for parent_path in parent_paths: new_parents = [] for parent in parents: - sub_option = parent.option.get_child(parent_path, - config_bag, - parent, - allow_dynoption=True, - ) + sub_option = parent.option.get_child( + parent_path, + config_bag, + parent, + allow_dynoption=True, + ) if sub_option.impl_is_dynoptiondescription(): - new_parents.extend(parent.dyn_to_subconfig(sub_option, - True, - true_path=true_path, - ) - ) + new_parents.extend( + parent.dyn_to_subconfig( + sub_option, + True, + true_path=true_path, + ) + ) subconfigs_is_a_list = True else: - new_parents.append(parent.get_child(sub_option, - None, - validate_properties, - true_path=true_path, - ) - ) + new_parents.append( + parent.get_child( + sub_option, + None, + validate_properties, + true_path=true_path, + ) + ) parents = new_parents subconfigs = [] for parent in parents: - subconfigs.append(parent.get_child(search_option, - index, - validate_properties, - ) - ) + subconfigs.append( + parent.get_child( + search_option, + index, + validate_properties, + ) + ) if subconfigs_is_a_list: return subconfigs return subconfigs[0] @@ -483,17 +548,20 @@ class _Config(CCache): on-demand. A Config is also a SubConfig. Root Config is call context below """ - __slots__ = ('_impl_context', - '_impl_descr', - '_impl_path', - ) - def __init__(self, - descr, - context, - subpath=None, - ): - """ Configuration option management class + __slots__ = ( + "_impl_context", + "_impl_descr", + "_impl_path", + ) + + def __init__( + self, + descr, + context, + subpath=None, + ): + """Configuration option management class :param descr: describes the configuration schema :type descr: an instance of ``option.OptionDescription`` @@ -507,45 +575,44 @@ class _Config(CCache): self._impl_path = subpath def get_description(self): - """get root description - """ - assert self._impl_descr is not None, _('there is no option description for this config' - ' (may be GroupConfig)') + """get root description""" + assert self._impl_descr is not None, _( + "there is no option description for this config" " (may be GroupConfig)" + ) return self._impl_descr def get_settings(self): - """get settings object - """ + """get settings object""" return self._impl_settings # pylint: disable=no-member def get_values(self): - """get values object - """ + """get values object""" return self._impl_values # pylint: disable=no-member def get_values_cache(self): - """get cache for values - """ + """get cache for values""" return self._impl_values_cache # pylint: disable=no-member # ============================================================================= # WALK - def find(self, - option_bag, - bytype, - byname, - byvalue, - raise_if_not_found=True, - only_path=undefined, - only_option=undefined, - with_option=False, - ): + def find( + self, + option_bag, + bytype, + byname, + byvalue, + raise_if_not_found=True, + only_path=undefined, + only_option=undefined, + with_option=False, + ): """ convenience method for finding an option that lives only in the subtree :param first: return only one option if True, a list otherwise :return: find list or an exception if nothing has been found """ + # pylint: disable=too-many-arguments,too-many-locals def _filter_by_value(soption_bag): value = self.get_value(soption_bag) @@ -555,30 +622,35 @@ class _Config(CCache): found = False if only_path is not undefined: + def _fake_iter(): yield only_option + options = _fake_iter() else: - options = option_bag.option.get_children_recursively(bytype, - byname, - option_bag.config_bag, - ) + options = option_bag.option.get_children_recursively( + bytype, + byname, + option_bag.config_bag, + ) for option in options: path = option.impl_getpath() - soption_bag = OptionBag(option, - None, - option_bag.config_bag, - ) + soption_bag = OptionBag( + option, + None, + option_bag.config_bag, + ) if byvalue is not undefined and not _filter_by_value(soption_bag): continue if option_bag.config_bag.properties: - #remove option with propertyerror, ... + # remove option with propertyerror, ... try: - self.get_sub_config(option_bag.config_bag, # pylint: disable=no-member - path, - None, - validate_properties=True, - ) + self.get_sub_config( + option_bag.config_bag, # pylint: disable=no-member + path, + None, + validate_properties=True, + ) except PropertiesOptionError: continue found = True @@ -586,63 +658,67 @@ class _Config(CCache): yield path else: yield path, option - self._find_return_results(found, - raise_if_not_found, - ) + self._find_return_results( + found, + raise_if_not_found, + ) - def _find_return_results(self, - found, - raise_if_not_found): + def _find_return_results(self, found, raise_if_not_found): if not found and raise_if_not_found: - raise AttributeError(_("no option found in config" - " with these criteria")) + raise AttributeError(_("no option found in config" " with these criteria")) - def walk_valid_value(self, - subconfig, - only_mandatory, - ): - value = self.get_value(subconfig, - need_help=False, - ) + def walk_valid_value( + self, + subconfig, + only_mandatory, + ): + value = self.get_value( + subconfig, + need_help=False, + ) ori_config_bag = subconfig.config_bag config_bag = ori_config_bag.copy() if only_mandatory: - config_bag.properties |= {'mandatory', 'empty'} + config_bag.properties |= {"mandatory", "empty"} subconfig.config_bag = config_bag - self.get_settings().validate_mandatory(subconfig, - value, - ) + self.get_settings().validate_mandatory( + subconfig, + value, + ) subconfig.config_bag = ori_config_bag return value - def get_root(self, - config_bag: ConfigBag, - ) -> SubConfig: - return SubConfig(config_bag.context.get_description(), - None, - None, - config_bag, - None, - None, - ) + def get_root( + self, + config_bag: ConfigBag, + ) -> SubConfig: + return SubConfig( + config_bag.context.get_description(), + None, + None, + config_bag, + None, + None, + ) - def get_sub_config(self, - config_bag, - path, - index, - *, - validate_properties: bool=True, - properties=undefined, - true_path: Optional[str]=None, - allow_dynoption: bool=False, - ): + def get_sub_config( + self, + config_bag, + path, + index, + *, + validate_properties: bool = True, + properties=undefined, + true_path: Optional[str] = None, + allow_dynoption: bool = False, + ): subconfig = self.get_root(config_bag) if path is None: paths = [] len_path = 0 else: - if '.' in path: - paths = path.split('.') + if "." in path: + paths = path.split(".") else: paths = [path] len_path = len(paths) - 1 @@ -656,33 +732,36 @@ class _Config(CCache): if not subconfig.option.impl_is_optiondescription(): raise TypeError(f'"{subconfig.true_path}" is not an optiondescription') - option = subconfig.option.get_child(name, - config_bag, - subconfig, - with_identifier=True, - allow_dynoption=allow_dynoption, - ) + option = subconfig.option.get_child( + name, + config_bag, + subconfig, + with_identifier=True, + allow_dynoption=allow_dynoption, + ) if isinstance(option, tuple): identifier, option = option else: identifier = None - subconfig = subconfig.get_child(option, - index_, - validate_properties, - properties=properties, - name=name, - identifier=identifier, - true_path=true_path_, - ) + subconfig = subconfig.get_child( + option, + index_, + validate_properties, + properties=properties, + name=name, + identifier=identifier, + true_path=true_path_, + ) return subconfig - def walk(self, - root_subconfig: SubConfig, - *, - no_value: bool=False, - only_mandatory: bool=False, - validate_properties: bool=True, - ): + def walk( + self, + root_subconfig: SubConfig, + *, + no_value: bool = False, + only_mandatory: bool = False, + validate_properties: bool = True, + ): if only_mandatory or no_value: ret = [] else: @@ -692,11 +771,12 @@ class _Config(CCache): if only_mandatory and subconfig.option.impl_is_symlinkoption(): continue if subconfig.option.impl_is_optiondescription(): - values = self.walk(subconfig, - no_value=no_value, - only_mandatory=only_mandatory, - validate_properties=validate_properties, - ) + values = self.walk( + subconfig, + no_value=no_value, + only_mandatory=only_mandatory, + validate_properties=validate_properties, + ) if only_mandatory or no_value: ret.extend(values) else: @@ -705,9 +785,10 @@ class _Config(CCache): if no_value: ret.append(subconfig) else: - option = self.walk_option(subconfig, - only_mandatory, - ) + option = self.walk_option( + subconfig, + only_mandatory, + ) if only_mandatory: if option: ret.append(subconfig) @@ -715,16 +796,18 @@ class _Config(CCache): ret[subconfig] = option[1] return ret - def walk_option(self, - subconfig: SubConfig, - only_mandatory: bool, - ): + def walk_option( + self, + subconfig: SubConfig, + only_mandatory: bool, + ): try: - value = self.walk_valid_value(subconfig, - only_mandatory, - ) + value = self.walk_valid_value( + subconfig, + only_mandatory, + ) except PropertiesOptionError as err: - if err.proptype in (['mandatory'], ['empty']): + if err.proptype in (["mandatory"], ["empty"]): if only_mandatory: return True else: @@ -738,58 +821,71 @@ class _Config(CCache): # ============================================================================= # Manage value - def get_value(self, - subconfig, - need_help=True, - ): + def get_value( + self, + subconfig, + need_help=True, + ): """ :return: option's value if name is an option name, OptionDescription otherwise """ original_index = subconfig.index - subconfig = self._get(subconfig, - need_help, - ) + subconfig = self._get( + subconfig, + need_help, + ) if isinstance(subconfig, list): value = [] follower_subconfig = None is_follower = not subconfig or subconfig[0].option.impl_is_follower() for sconfig in subconfig: if not is_follower or follower_subconfig is None: - follower_subconfig = self.get_sub_config(sconfig.config_bag, - sconfig.path, - sconfig.index, - ) + follower_subconfig = self.get_sub_config( + sconfig.config_bag, + sconfig.path, + sconfig.index, + ) else: - follower_subconfig = follower_subconfig.parent.get_child(sconfig.option, - sconfig.index, - False, - ) - value.append(self.get_value(follower_subconfig, - need_help=need_help, - )) + follower_subconfig = follower_subconfig.parent.get_child( + sconfig.option, + sconfig.index, + False, + ) + value.append( + self.get_value( + follower_subconfig, + need_help=need_help, + ) + ) else: value = self.get_values().get_cached_value(subconfig) if subconfig.option.impl_is_follower(): length = subconfig.parent.get_length_leadership() follower_len = self.get_values().get_max_length(subconfig.path) if follower_len > length: - option_name = subconfig.option.impl_get_display_name(subconfig, with_quote=True) - raise LeadershipError(_(f'the follower option {option_name} ' - f'has greater length ({follower_len}) than the leader ' - f'length ({length})')) - self.get_settings().validate_mandatory(subconfig, - value, - ) + option_name = subconfig.option.impl_get_display_name( + subconfig, with_quote=True + ) + raise LeadershipError( + _( + "the follower option {0} has greater length ({1}) than the leader length ({2})" + ).format(option_name, follower_len, length) + ) + self.get_settings().validate_mandatory( + subconfig, + value, + ) if original_index != subconfig.index: value = value[original_index] return value - def _get(self, - subconfig: "SubConfig", - need_help: bool, - validate_properties: bool=True, - ) -> "OptionBag": + def _get( + self, + subconfig: "SubConfig", + need_help: bool, + validate_properties: bool = True, + ) -> "OptionBag": # pylint: disable=too-many-locals option = subconfig.option if not option.impl_is_symlinkoption(): @@ -797,54 +893,63 @@ class _Config(CCache): suboption = option.impl_getopt() if suboption.issubdyn(): dynopt = suboption.getsubdyn() - return subconfig.get_common_child(suboption, - true_path=subconfig.path, - validate_properties=validate_properties, - ) + return subconfig.get_common_child( + suboption, + true_path=subconfig.path, + validate_properties=validate_properties, + ) if suboption.impl_is_follower() and subconfig.index is None: - subconfig = self.get_sub_config(subconfig.config_bag, # pylint: disable=no-member - suboption.impl_getpath(), - None, - validate_properties=validate_properties, - true_path=subconfig.path, - ) + subconfig = self.get_sub_config( + subconfig.config_bag, # pylint: disable=no-member + suboption.impl_getpath(), + None, + validate_properties=validate_properties, + true_path=subconfig.path, + ) leadership_length = subconfig.parent.get_length_leadership() ret = [] follower = subconfig.option parent = subconfig.parent for idx in range(leadership_length): - ret.append(parent.get_child(follower, - idx, - True, - )) + ret.append( + parent.get_child( + follower, + idx, + True, + ) + ) return ret if suboption.impl_is_leader(): index = None else: index = subconfig.index - s_subconfig = self.get_sub_config(subconfig.config_bag, # pylint: disable=no-member - suboption.impl_getpath(), - index, - validate_properties=validate_properties, - true_path=subconfig.path, - ) - return self._get(s_subconfig, - need_help, - ) + s_subconfig = self.get_sub_config( + subconfig.config_bag, # pylint: disable=no-member + suboption.impl_getpath(), + index, + validate_properties=validate_properties, + true_path=subconfig.path, + ) + return self._get( + s_subconfig, + need_help, + ) - def get_owner(self, - subconfig: "SubConfig", - ): - """get owner - """ - subconfigs = self._get(subconfig, - need_help=True, - ) + def get_owner( + self, + subconfig: "SubConfig", + ): + """get owner""" + subconfigs = self._get( + subconfig, + need_help=True, + ) if isinstance(subconfigs, list): for sc in subconfigs: - owner = self.get_owner(sc, - ) + owner = self.get_owner( + sc, + ) if owner != owners.default: break else: @@ -856,46 +961,53 @@ class _Config(CCache): class _CommonConfig(_Config): "abstract base class for the Config, KernelGroupConfig and the KernelMetaConfig" - __slots__ = ('_impl_values', - '_impl_values_cache', - '_impl_settings', - 'properties_cache', - '_impl_permissives_cache', - 'parents', - 'impl_type', - ) + __slots__ = ( + "_impl_values", + "_impl_values_cache", + "_impl_settings", + "properties_cache", + "_impl_permissives_cache", + "parents", + "impl_type", + ) def _impl_build_all_caches(self, descr): if not descr.impl_already_build_caches(): descr._group_type = groups.root # pylint: disable=protected-access - descr._build_cache(self._display_name) # pylint: disable=no-member,protected-access - if not hasattr(descr, '_cache_force_store_values'): - raise ConfigError(_('option description seems to be part of an other ' - 'config')) + descr._build_cache( + self._display_name + ) # pylint: disable=no-member,protected-access + if not hasattr(descr, "_cache_force_store_values"): + raise ConfigError( + _("option description seems to be part of an other " "config") + ) def get_parents(self): - """get parents - """ + """get parents""" for parent in self.parents: # pylint: disable=no-member yield parent() # information - def impl_set_information(self, - config_bag, - key, - value, - ): + def impl_set_information( + self, + config_bag, + key, + value, + ): """updates the information's attribute :param key: information's key (ex: "help", "doc" :param value: information's value (ex: "the help string") """ - self._impl_values.set_information(None, # pylint: disable=no-member - key, - value, - ) - for option in self.get_description()._cache_dependencies_information.get(key, []): # pylint: disable=protected-access - #option_bag = OptionBag(option, + self._impl_values.set_information( + None, # pylint: disable=no-member + key, + value, + ) + for option in self.get_description()._cache_dependencies_information.get( + key, [] + ): # pylint: disable=protected-access + # option_bag = OptionBag(option, # None, # config_bag, # properties=None, @@ -903,87 +1015,101 @@ class _CommonConfig(_Config): option_bag = None self.reset_cache(option_bag) - def impl_get_information(self, - subconfig, - key, - default, - ): + def impl_get_information( + self, + subconfig, + key, + default, + ): """retrieves one information's item :param key: the item string (ex: "help") """ - return self._impl_values.get_information(None, # pylint: disable=no-member - key, - default, - ) + return self._impl_values.get_information( + None, # pylint: disable=no-member + key, + default, + ) - def impl_del_information(self, - key, - raises=True, - ): - """delete an information - """ - self._impl_values.del_information(key, # pylint: disable=no-member - raises, - ) + def impl_del_information( + self, + key, + raises=True, + ): + """delete an information""" + self._impl_values.del_information( + key, # pylint: disable=no-member + raises, + ) def impl_list_information(self): - """list information keys for context - """ + """list information keys for context""" return self._impl_values.list_information() # pylint: disable=no-member - def gen_fake_context(self) -> 'KernelConfig': - """generate a fake values to improve validation when assign a new value - """ + def gen_fake_context(self) -> "KernelConfig": + """generate a fake values to improve validation when assign a new value""" export = deepcopy(self.get_values()._values) # pylint: disable=protected-access - fake_context = KernelConfig(self._impl_descr, - force_values=export, - force_settings=self.get_settings(), - name=self._impl_name, # pylint: disable=no-member - ) + fake_context = KernelConfig( + self._impl_descr, + force_values=export, + force_settings=self.get_settings(), + name=self._impl_name, # pylint: disable=no-member + ) fake_context.parents = self.parents # pylint: disable=no-member return fake_context - def duplicate(self, - force_values=None, - force_settings=None, - metaconfig_prefix=None, - child=None, - deep=None, - name=None, - ): - """duplication config - """ + def duplicate( + self, + force_values=None, + force_settings=None, + metaconfig_prefix=None, + child=None, + deep=None, + name=None, + ): + """duplication config""" # pylint: disable=too-many-arguments if name is None: name = self._impl_name # pylint: disable=no-member if isinstance(self, KernelConfig): - duplicated_config = KernelConfig(self._impl_descr, - _duplicate=True, - force_values=force_values, - force_settings=force_settings, - name=name, - ) + duplicated_config = KernelConfig( + self._impl_descr, + _duplicate=True, + force_values=force_values, + force_settings=force_settings, + name=name, + ) else: - duplicated_config = KernelMetaConfig([], - _duplicate=True, - optiondescription=self._impl_descr, - name=name, - ) + duplicated_config = KernelMetaConfig( + [], + _duplicate=True, + optiondescription=self._impl_descr, + name=name, + ) duplicated_values = duplicated_config.get_values() duplicated_settings = duplicated_config.get_settings() - duplicated_values._values = deepcopy(self.get_values()._values) # pylint: disable=protected-access - duplicated_values._informations = deepcopy(self.get_values()._informations) # pylint: disable=protected-access - duplicated_settings._properties = deepcopy(self.get_settings()._properties) # pylint: disable=protected-access - duplicated_settings._permissives = deepcopy(self.get_settings()._permissives) # pylint: disable=protected-access + duplicated_values._values = deepcopy( + self.get_values()._values + ) # pylint: disable=protected-access + duplicated_values._informations = deepcopy( + self.get_values()._informations + ) # pylint: disable=protected-access + duplicated_settings._properties = deepcopy( + self.get_settings()._properties + ) # pylint: disable=protected-access + duplicated_settings._permissives = deepcopy( + self.get_settings()._permissives + ) # pylint: disable=protected-access duplicated_settings.ro_append = self.get_settings().ro_append duplicated_settings.rw_append = self.get_settings().rw_append duplicated_settings.ro_remove = self.get_settings().ro_remove duplicated_settings.rw_remove = self.get_settings().rw_remove -# duplicated_settings.default_properties = self.get_settings().default_properties + # duplicated_settings.default_properties = self.get_settings().default_properties duplicated_config.reset_cache(None, None) if child is not None: - duplicated_config._impl_children.append(child) # pylint: disable=protected-access + duplicated_config._impl_children.append( + child + ) # pylint: disable=protected-access child.parents.append(weakref.ref(duplicated_config)) if self.parents: # pylint: disable=no-member if deep is not None: @@ -994,56 +1120,61 @@ class _CommonConfig(_Config): subname = wparent.impl_getname() if metaconfig_prefix: subname = metaconfig_prefix + subname - duplicated_config = wparent.duplicate(deep=deep, - metaconfig_prefix=metaconfig_prefix, - child=duplicated_config, - name=subname, - ) + duplicated_config = wparent.duplicate( + deep=deep, + metaconfig_prefix=metaconfig_prefix, + child=duplicated_config, + name=subname, + ) else: duplicated_config.parents = self.parents # pylint: disable=no-member for parent in self.parents: # pylint: disable=no-member - parent()._impl_children.append(duplicated_config) # pylint: disable=protected-access + parent()._impl_children.append( + duplicated_config + ) # pylint: disable=protected-access return duplicated_config def get_config_path(self): - """get config path - """ + """get config path""" path = self.impl_getname() for parent in self.parents: # pylint: disable=no-member wparent = parent() if wparent is None: # pragma: no cover - raise ConfigError(_(f'parent of {self._impl_name} not already exists')) # pylint: disable=no-member - path = parent().get_config_path() + '.' + path + raise ConfigError( + _("parent of {0} not already exists").format(self._impl_name) + ) # pylint: disable=no-member + path = parent().get_config_path() + "." + path return path def impl_getname(self): - """get config name - """ + """get config name""" return self._impl_name # pylint: disable=no-member # ____________________________________________________________ class KernelConfig(_CommonConfig): - """main configuration management entry - """ - # pylint: disable=too-many-instance-attributes - __slots__ = ('__weakref__', - '_impl_name', - '_display_name', - '_impl_symlink', - '_storage', - ) - impl_type = 'config' + """main configuration management entry""" - def __init__(self, - descr, - force_values=None, - force_settings=None, - name=None, - display_name=None, - _duplicate=False, - ): - """ Configuration option management class + # pylint: disable=too-many-instance-attributes + __slots__ = ( + "__weakref__", + "_impl_name", + "_display_name", + "_impl_symlink", + "_storage", + ) + impl_type = "config" + + def __init__( + self, + descr, + force_values=None, + force_settings=None, + name=None, + display_name=None, + _duplicate=False, + ): + """Configuration option management class :param descr: describes the configuration schema :type descr: an instance of ``option.OptionDescription`` @@ -1056,9 +1187,11 @@ class KernelConfig(_CommonConfig): self._impl_symlink = [] self._impl_name = name if isinstance(descr, Leadership): - raise ConfigError(_('cannot set leadership object has root optiondescription')) + raise ConfigError( + _("cannot set leadership object has root optiondescription") + ) if isinstance(descr, DynOptionDescription): - msg = _('cannot set dynoptiondescription object has root optiondescription') + msg = _("cannot set dynoptiondescription object has root optiondescription") raise ConfigError(msg) if force_settings is not None and force_values is not None: self._impl_settings = force_settings @@ -1075,28 +1208,31 @@ class KernelConfig(_CommonConfig): self._impl_context = weakref.ref(self) if None in [force_settings, force_values]: self._impl_build_all_caches(descr) - super().__init__(descr, - self._impl_context, - None, - ) + super().__init__( + descr, + self._impl_context, + None, + ) class KernelGroupConfig(_CommonConfig): - """Group a config with same optiondescription tree - """ - __slots__ = ('__weakref__', - '_impl_children', - '_impl_name', - '_display_name', - ) - impl_type = 'group' + """Group a config with same optiondescription tree""" - def __init__(self, - children, - display_name=None, - name=None, - _descr=None, - ): + __slots__ = ( + "__weakref__", + "_impl_children", + "_impl_name", + "_display_name", + ) + impl_type = "group" + + def __init__( + self, + children, + display_name=None, + name=None, + _descr=None, + ): # pylint: disable=super-init-not-called names = [] for child in children: @@ -1106,8 +1242,11 @@ class KernelGroupConfig(_CommonConfig): while range(1, len(names) + 1): name = names.pop(0) if name in names: - raise ConflictError(_('config name must be uniq in ' - 'groupconfig for "{0}"').format(name)) + raise ConflictError( + _( + "config name must be uniq in " 'groupconfig for "{0}"' + ).format(name) + ) self._impl_children = children self.parents = [] @@ -1119,20 +1258,21 @@ class KernelGroupConfig(_CommonConfig): self._impl_path = None def get_children(self): - """get all children - """ + """get all children""" return self._impl_children - def reset_cache(self, - option_bag, - resetted_opts=None, - ): + def reset_cache( + self, + option_bag, + resetted_opts=None, + ): if resetted_opts is None: resetted_opts = [] if isinstance(self, KernelMixConfig): - super().reset_cache(option_bag, - resetted_opts=copy(resetted_opts), - ) + super().reset_cache( + option_bag, + resetted_opts=copy(resetted_opts), + ) for child in self._impl_children: if option_bag is not None: coption_bag = option_bag.copy() @@ -1141,26 +1281,30 @@ class KernelGroupConfig(_CommonConfig): coption_bag.config_bag = cconfig_bag else: coption_bag = None - child.reset_cache(coption_bag, - resetted_opts=copy(resetted_opts), - ) + child.reset_cache( + coption_bag, + resetted_opts=copy(resetted_opts), + ) - def set_value(self, - option_bag, - value, - only_config=False, - ): - """Setattr not in current KernelGroupConfig, but in each children - """ + def set_value( + self, + option_bag, + value, + only_config=False, + ): + """Setattr not in current KernelGroupConfig, but in each children""" ret = [] for child in self._impl_children: cconfig_bag = option_bag.config_bag.copy() cconfig_bag.context = child if isinstance(child, KernelGroupConfig): - ret.extend(child.set_value(option_bag, - value, - only_config=only_config, - )) + ret.extend( + child.set_value( + option_bag, + value, + only_config=only_config, + ) + ) else: settings = child.get_settings() properties = settings.get_context_properties(child.properties_cache) @@ -1169,66 +1313,78 @@ class KernelGroupConfig(_CommonConfig): cconfig_bag.permissives = permissives try: # GROUP - coption_bag = child.get_sub_option_bag(cconfig_bag, - option_bag.path, - option_bag.index, - False, - ) - child.set_value(coption_bag, - value, - ) + coption_bag = child.get_sub_option_bag( + cconfig_bag, + option_bag.path, + option_bag.index, + False, + ) + child.set_value( + coption_bag, + value, + ) except PropertiesOptionError as err: # pylint: disable=protected-access - ret.append(PropertiesOptionError(err._option_bag, - err.proptype, - err._settings, - err._opt_type, - err._name, - err._orig_opt)) + ret.append( + PropertiesOptionError( + err._option_bag, + err.proptype, + err._settings, + err._opt_type, + err._name, + err._orig_opt, + ) + ) except (ValueError, LeadershipError, AttributeError) as err: ret.append(err) return ret - - def find_group(self, - config_bag, - byname=None, - bypath=undefined, - byoption=undefined, - byvalue=undefined, - raise_if_not_found=True, - _sub=False, - ): - """Find first not in current KernelGroupConfig, but in each children - """ + def find_group( + self, + config_bag, + byname=None, + bypath=undefined, + byoption=undefined, + byvalue=undefined, + raise_if_not_found=True, + _sub=False, + ): + """Find first not in current KernelGroupConfig, but in each children""" # pylint: disable=too-many-arguments # if KernelMetaConfig, all children have same OptionDescription in # context so search only one time the option for all children - if bypath is undefined and byname is not None and \ - self.impl_type == 'meta': - root_option_bag = OptionBag(self.get_description(), - None, - config_bag, - ) - next(self.find(root_option_bag, - bytype=None, - byname=byname, - byvalue=undefined, - raise_if_not_found=raise_if_not_found, - with_option=True, - )) + if bypath is undefined and byname is not None and self.impl_type == "meta": + root_option_bag = OptionBag( + self.get_description(), + None, + config_bag, + ) + next( + self.find( + root_option_bag, + bytype=None, + byname=byname, + byvalue=undefined, + raise_if_not_found=raise_if_not_found, + with_option=True, + ) + ) byname = None ret = [] for child in self._impl_children: if isinstance(child, KernelGroupConfig): - ret.extend(child.find_group(byname=byname, - bypath=bypath, - byoption=byoption, - byvalue=byvalue, - config_bag=config_bag, - raise_if_not_found=False, - _sub=True)) + ret.extend( + child.find_group( + byname=byname, + bypath=bypath, + byoption=byoption, + byvalue=byvalue, + config_bag=config_bag, + raise_if_not_found=False, + _sub=True, + ) + ) else: cconfig_bag = config_bag.copy() cconfig_bag.context = child @@ -1238,34 +1394,39 @@ class KernelGroupConfig(_CommonConfig): permissives = settings.get_context_permissives() cconfig_bag.properties = properties cconfig_bag.permissives = permissives - root_option_bag = OptionBag(child.get_description(), - None, - cconfig_bag, - ) + root_option_bag = OptionBag( + child.get_description(), + None, + cconfig_bag, + ) try: - next(child.find(root_option_bag, - None, - byname, - byvalue, - raise_if_not_found=False, - only_path=bypath, - only_option=byoption, - )) + next( + child.find( + root_option_bag, + None, + byname, + byvalue, + raise_if_not_found=False, + only_path=bypath, + only_option=byoption, + ) + ) ret.append(child) except StopIteration: pass if not _sub: - self._find_return_results(ret != [], # pylint: disable=use-implicit-booleaness-not-comparison - raise_if_not_found, - ) + self._find_return_results( + ret != [], # pylint: disable=use-implicit-booleaness-not-comparison + raise_if_not_found, + ) return ret - def reset(self, - path: str, - config_bag: ConfigBag, - ) -> None: - """reset value for specified path - """ + def reset( + self, + path: str, + config_bag: ConfigBag, + ) -> None: + """reset value for specified path""" for child in self._impl_children: settings = child.get_settings() cconfig_bag = config_bag.copy() @@ -1277,18 +1438,19 @@ class KernelGroupConfig(_CommonConfig): cconfig_bag.permissives = permissives cconfig_bag.remove_validation() # GROUP - option_bag = child.get_sub_option_bag(cconfig_bag, - path, - None, - False, - )[-1] + option_bag = child.get_sub_option_bag( + cconfig_bag, + path, + None, + False, + )[-1] child.get_values().reset(option_bag) - def getconfig(self, - name: str, - ) -> KernelConfig: - """get a child from a config name - """ + def getconfig( + self, + name: str, + ) -> KernelConfig: + """get a child from a config name""" for child in self._impl_children: if name == child.impl_getname(): return child @@ -1296,21 +1458,23 @@ class KernelGroupConfig(_CommonConfig): class KernelMixConfig(KernelGroupConfig): - """Kernel mixconfig: this config can have differents optiondescription tree - """ - # pylint: disable=too-many-instance-attributes - __slots__ = ('_impl_symlink', - '_storage', - ) - impl_type = 'mix' + """Kernel mixconfig: this config can have differents optiondescription tree""" - def __init__(self, - optiondescription, - children, - name=None, - display_name=None, - _duplicate=False, - ): + # pylint: disable=too-many-instance-attributes + __slots__ = ( + "_impl_symlink", + "_storage", + ) + impl_type = "mix" + + def __init__( + self, + optiondescription, + children, + name=None, + display_name=None, + _duplicate=False, + ): self._impl_name = name self._impl_symlink = [] for child in children: @@ -1327,34 +1491,44 @@ class KernelMixConfig(KernelGroupConfig): self._impl_values_cache = Cache() self._display_name = display_name self._impl_build_all_caches(optiondescription) - super().__init__(children, - _descr=optiondescription, - display_name=display_name, - ) + super().__init__( + children, + _descr=optiondescription, + display_name=display_name, + ) - def set_value(self, - option_bag, - value, - only_config=False, - force_default=False, - force_dont_change_value=False, - force_default_if_same=False, - ): + def set_value( + self, + option_bag, + value, + only_config=False, + force_default=False, + force_dont_change_value=False, + force_default_if_same=False, + ): """only_config: could be set if you want modify value in all Config included in - this KernelMetaConfig + this KernelMetaConfig """ # pylint: disable=too-many-branches,too-many-nested-blocks,too-many-locals,too-many-arguments ret = [] if only_config: if force_default or force_default_if_same or force_dont_change_value: - raise ValueError(_('force_default, force_default_if_same or ' - 'force_dont_change_value cannot be set with' - ' only_config')) + raise ValueError( + _( + "force_default, force_default_if_same or " + "force_dont_change_value cannot be set with" + " only_config" + ) + ) else: if force_default or force_default_if_same or force_dont_change_value: if force_default and force_dont_change_value: - raise ValueError(_('force_default and force_dont_change_value' - ' cannot be set together')) + raise ValueError( + _( + "force_default and force_dont_change_value" + " cannot be set together" + ) + ) for child in self._impl_children: cconfig_bag = option_bag.config_bag.copy() cconfig_bag.context = child @@ -1363,235 +1537,275 @@ class KernelMixConfig(KernelGroupConfig): cconfig_bag.properties = properties cconfig_bag.permissives = settings.get_context_permissives() try: - if self.impl_type == 'meta': + if self.impl_type == "meta": obj = self else: obj = child - validate_properties = not force_default and not force_default_if_same + validate_properties = ( + not force_default and not force_default_if_same + ) # MIX - moption_bag = obj.get_sub_option_bag(cconfig_bag, - option_bag.path, - option_bag.index, - validate_properties, - )[-1] + moption_bag = obj.get_sub_option_bag( + cconfig_bag, + option_bag.path, + option_bag.index, + validate_properties, + )[-1] if force_default_if_same: if not child.get_values().hasvalue(option_bag.path): child_value = undefined else: child_value = child.get_value(moption_bag) - if force_default or (force_default_if_same and value == child_value): + if force_default or ( + force_default_if_same and value == child_value + ): child.get_values().reset(moption_bag) continue if force_dont_change_value: child_value = child.get_value(moption_bag) if value != child_value: - child.set_value(moption_bag, - child_value, - ) + child.set_value( + moption_bag, + child_value, + ) except PropertiesOptionError as err: # pylint: disable=protected-access - ret.append(PropertiesOptionError(err._option_bag, - err.proptype, - err._settings, - err._opt_type, - err._name, - err._orig_opt, - )) + ret.append( + PropertiesOptionError( + err._option_bag, + err.proptype, + err._settings, + err._opt_type, + err._name, + err._orig_opt, + ) + ) except (ValueError, LeadershipError, AttributeError) as err: ret.append(err) try: # MIX - moption_bag = self.get_sub_option_bag(option_bag.config_bag, - option_bag.path, - option_bag.index, - not only_config, - )[-1] + moption_bag = self.get_sub_option_bag( + option_bag.config_bag, + option_bag.path, + option_bag.index, + not only_config, + )[-1] if only_config: - ret = super().set_value(moption_bag, - value, - only_config=only_config, - ) + ret = super().set_value( + moption_bag, + value, + only_config=only_config, + ) else: - _CommonConfig.set_value(self, - moption_bag, - value, - ) + _CommonConfig.set_value( + self, + moption_bag, + value, + ) except (PropertiesOptionError, ValueError, LeadershipError) as err: ret.append(err) return ret - def reset(self, - path: str, - only_children: bool, - config_bag: ConfigBag, - ) -> None: - """reset value for a specified path - """ + def reset( + self, + path: str, + only_children: bool, + config_bag: ConfigBag, + ) -> None: + """reset value for a specified path""" # pylint: disable=arguments-differ rconfig_bag = config_bag.copy() rconfig_bag.remove_validation() - if self.impl_type == 'meta': + if self.impl_type == "meta": # MIX - option_bag = self.get_sub_option_bag(config_bag, - path, - None, - True, - )[-1] + option_bag = self.get_sub_option_bag( + config_bag, + path, + None, + True, + )[-1] elif not only_children: try: # MIX - option_bag = self.get_sub_option_bag(rconfig_bag, - path, - None, - True, - )[-1] + option_bag = self.get_sub_option_bag( + rconfig_bag, + path, + None, + True, + )[-1] except AttributeError: only_children = True for child in self._impl_children: rconfig_bag.context = child try: - if self.impl_type == 'meta': + if self.impl_type == "meta": moption_bag = option_bag moption_bag.config_bag = rconfig_bag else: # MIX - moption_bag = child.get_sub_option_bag(rconfig_bag, - path, - None, - True, - )[-1] + moption_bag = child.get_sub_option_bag( + rconfig_bag, + path, + None, + True, + )[-1] child.get_values().reset(moption_bag) except AttributeError: pass if isinstance(child, KernelMixConfig): - child.reset(path, - False, - rconfig_bag, - ) + child.reset( + path, + False, + rconfig_bag, + ) if not only_children: option_bag.config_bag = config_bag self.get_values().reset(option_bag) - def new_config(self, - name=None, - type_='config', - ): + def new_config( + self, + name=None, + type_="config", + ): """Create a new config/metaconfig/mixconfig and add it to this MixConfig""" if name: for child in self._impl_children: if child.impl_getname() == name: - raise ConflictError(_('config name must be uniq in ' - 'groupconfig for {0}').format(child)) - assert type_ in ('config', 'metaconfig', 'mixconfig'), _('unknown type {}').format(type_) - if type_ == 'config': - config = KernelConfig(self._impl_descr, - name=name) - elif type_ == 'metaconfig': - config = KernelMetaConfig([], - optiondescription=self._impl_descr, - name=name, - ) - elif type_ == 'mixconfig': - config = KernelMixConfig(children=[], - optiondescription=self._impl_descr, - name=name, - ) + raise ConflictError( + _("config name must be uniq in " "groupconfig for {0}").format( + child + ) + ) + assert type_ in ("config", "metaconfig", "mixconfig"), _( + "unknown type {}" + ).format(type_) + if type_ == "config": + config = KernelConfig(self._impl_descr, name=name) + elif type_ == "metaconfig": + config = KernelMetaConfig( + [], + optiondescription=self._impl_descr, + name=name, + ) + elif type_ == "mixconfig": + config = KernelMixConfig( + children=[], + optiondescription=self._impl_descr, + name=name, + ) # Copy context properties/permissives settings = config.get_settings() properties = settings.get_context_properties() - settings.set_context_properties(properties, - config, - ) + settings.set_context_properties( + properties, + config, + ) settings.set_context_permissives(settings.get_context_permissives()) settings.ro_append = settings.ro_append settings.rw_append = settings.rw_append settings.ro_remove = settings.ro_remove settings.rw_remove = settings.rw_remove -# settings.default_properties = settings.default_properties + # settings.default_properties = settings.default_properties config.parents.append(weakref.ref(self)) self._impl_children.append(config) return config - def add_config(self, - config, - ): + def add_config( + self, + config, + ): """Add a child config to a mix config""" if not config.impl_getname(): - raise ConfigError(_('config added has no name, the name is mandatory')) - if config.impl_getname() in [child.impl_getname() for child in self._impl_children]: - raise ConflictError(_('config name "{0}" is not uniq in ' - 'groupconfig "{1}"').format(config.impl_getname(), - self.impl_getname()), - ) + raise ConfigError(_("config added has no name, the name is mandatory")) + if config.impl_getname() in [ + child.impl_getname() for child in self._impl_children + ]: + raise ConflictError( + _('config name "{0}" is not uniq in ' 'groupconfig "{1}"').format( + config.impl_getname(), self.impl_getname() + ), + ) config.parents.append(weakref.ref(self)) self._impl_children.append(config) config.reset_cache(None, None) - def remove_config(self, - name, - ): + def remove_config( + self, + name, + ): """Remove a child config to a mix config by it's name""" for current_index, child in enumerate(self._impl_children): if name == child.impl_getname(): child.reset_cache(None, None) break else: - raise ConfigError(_(f'cannot find the config {name}')) + raise ConfigError(_("cannot find the config {0}").format(name)) for child_index, parent in enumerate(child.parents): if parent() == self: break else: # pragma: no cover - raise ConfigError(_('cannot find the config {}').format(self.impl_getname())) + raise ConfigError( + _("cannot find the config {0}").format(self.impl_getname()) + ) self._impl_children.pop(current_index) child.parents.pop(child_index) return child class KernelMetaConfig(KernelMixConfig): - """Meta config - """ - __slots__ = tuple() - impl_type = 'meta' + """Meta config""" - def __init__(self, - children, - optiondescription=None, - name=None, - display_name=None, - _duplicate=False, - ): + __slots__ = tuple() + impl_type = "meta" + + def __init__( + self, + children, + optiondescription=None, + name=None, + display_name=None, + _duplicate=False, + ): descr = None if optiondescription is not None: if not _duplicate: new_children = [] for child_name in children: - assert isinstance(child_name, str), _('MetaConfig with optiondescription' - ' must have string has child, ' - 'not {}').format(child_name) - new_children.append(KernelConfig(optiondescription, name=child_name)) + assert isinstance(child_name, str), _( + "MetaConfig with optiondescription" + " must have string has child, " + "not {}" + ).format(child_name) + new_children.append( + KernelConfig(optiondescription, name=child_name) + ) children = new_children descr = optiondescription for child in children: - if __debug__ and not isinstance(child, (KernelConfig, - KernelMetaConfig)): + if __debug__ and not isinstance(child, (KernelConfig, KernelMetaConfig)): raise TypeError(_("child must be a Config or MetaConfig")) if descr is None: descr = child.get_description() elif descr is not child.get_description(): - raise ValueError(_('all config in metaconfig must ' - 'have the same optiondescription')) - super().__init__(descr, - children, - name=name, - display_name=display_name, - ) + raise ValueError( + _( + "all config in metaconfig must " + "have the same optiondescription" + ) + ) + super().__init__( + descr, + children, + name=name, + display_name=display_name, + ) - def add_config(self, - config, - ): + def add_config( + self, + config, + ): if self._impl_descr is not config.get_description(): - raise ValueError(_('metaconfig must ' - 'have the same optiondescription')) + raise ValueError(_("metaconfig must " "have the same optiondescription")) super().add_config(config) diff --git a/tiramisu/error.py b/tiramisu/error.py index 4fe6e2e..4d27ffb 100644 --- a/tiramisu/error.py +++ b/tiramisu/error.py @@ -19,17 +19,18 @@ import weakref from .i18n import _ -def display_list(lst, - *, - separator='and', - add_quote=False, - ) -> str(): +def display_list( + lst, + *, + separator="and", + add_quote=False, +) -> str(): if not lst: return '""' - if separator == 'and': - separator = _('and') - elif separator == 'or': - separator = _('or') + if separator == "and": + separator = _("and") + elif separator == "or": + separator = _("or") if isinstance(lst, tuple) or isinstance(lst, frozenset): lst = list(lst) if len(lst) == 1: @@ -51,30 +52,35 @@ def display_list(lst, lst__.append(l) lst__.sort() last = lst__[-1] - return ', '.join(lst__[:-1]) + _(' {} ').format(separator) + '{}'.format(last) + return ", ".join(lst__[:-1]) + _(" {} ").format(separator) + "{}".format(last) # Exceptions for an Option class PropertiesOptionError(AttributeError): "attempt to access to an option with a property that is not allowed" - def __init__(self, - subconfig, - proptype, - settings, - opt_type=None, - name=None, - orig_opt=None, - help_properties=None): + + def __init__( + self, + subconfig, + proptype, + settings, + opt_type=None, + name=None, + orig_opt=None, + help_properties=None, + ): if opt_type: self._opt_type = opt_type self._name = name self._orig_opt = orig_opt else: if subconfig.option.impl_is_optiondescription(): - self._opt_type = 'optiondescription' + self._opt_type = "optiondescription" else: - self._opt_type = 'option' - self._name = subconfig.option.impl_get_display_name(subconfig, with_quote=True) + self._opt_type = "option" + self._name = subconfig.option.impl_get_display_name( + subconfig, with_quote=True + ) self._orig_opt = None self._subconfig = subconfig self.proptype = proptype @@ -91,7 +97,7 @@ class PropertiesOptionError(AttributeError): if self.msg is not None: return self.msg if self._settings is None: - return 'error' + return "error" if self.help_properties: properties = list(self.help_properties) else: @@ -99,46 +105,47 @@ class PropertiesOptionError(AttributeError): only_one = len(properties) == 1 properties_msg = display_list(properties, add_quote=True) if only_one: - prop_msg = _('property') + prop_msg = _("property") else: - prop_msg = _('properties') - if properties == ['frozen']: + prop_msg = _("properties") + if properties == ["frozen"]: if self._orig_opt: - msg = 'cannot modify the {0} {1} because "{2}" has {3} {4}' + msg = _('cannot modify the {0} {1} because "{2}" has {3} {4}') else: - msg = 'cannot modify the {0} {1} because has {2} {3}' + msg = _("cannot modify the {0} {1} because has {2} {3}") else: if self._orig_opt: - msg = 'cannot access to {0} {1} because "{2}" has {3} {4}' + msg = _('cannot access to {0} {1} because "{2}" has {3} {4}') else: - msg = 'cannot access to {0} {1} because has {2} {3}' + msg = _("cannot access to {0} {1} because has {2} {3}") if self._orig_opt: # FIXME _orig_opt ? - self.msg = _(msg).format(self._opt_type, - self._orig_opt.impl_get_display_name(subconfig, with_quote=True), - self._name, - prop_msg, - properties_msg) + self.msg = msg.format( + self._opt_type, + self._orig_opt.impl_get_display_name(subconfig, with_quote=True), + self._name, + prop_msg, + properties_msg, + ) else: - self.msg = _(msg).format(self._opt_type, - self._name, - prop_msg, - properties_msg) + self.msg = msg.format(self._opt_type, self._name, prop_msg, properties_msg) del self._opt_type, self._name del self._settings, self._orig_opt return self.msg -#____________________________________________________________ +# ____________________________________________________________ # Exceptions for a Config class ConfigError(Exception): """attempt to change an option's owner without a value or in case of `_descr` is None or if a calculation cannot be carried out""" - def __init__(self, - exp, - ori_err=None, - ): + + def __init__( + self, + exp, + ori_err=None, + ): super().__init__(exp) self.ori_err = ori_err @@ -148,8 +155,8 @@ class ConflictError(Exception): pass -#____________________________________________________________ -# miscellaneous exceptions +# ____________________________________________________________ +# miscellaneous exceptions class LeadershipError(Exception): "problem with a leadership's value length" pass @@ -161,13 +168,7 @@ class ConstError(TypeError): class _CommonError: - def __init__(self, - subconfig, - val, - display_type, - opt, - err_msg, - index): + def __init__(self, subconfig, val, display_type, opt, err_msg, index): self.val = val self.display_type = display_type self.opt = weakref.ref(opt) @@ -180,24 +181,24 @@ class _CommonError: try: msg = self.prefix except AttributeError: - self.prefix = self.tmpl.format(self.val, - _(self.display_type), - self.name) + self.prefix = self.tmpl.format(self.val, _(self.display_type), self.name) msg = self.prefix if self.err_msg: if msg: - msg += ', {}'.format(self.err_msg) + msg += ", {}".format(self.err_msg) else: msg = self.err_msg if not msg: - msg = _('invalid value') + msg = _("invalid value") return msg class ValueWarning(_CommonError, UserWarning): - tmpl = _('attention, "{0}" could be an invalid {1} for "{2}"') + tmpl = None def __init__(self, *args, **kwargs): + if ValueWarning.tmpl is None: + ValueWarning.tmpl = _('attention, "{0}" could be an invalid {1} for "{2}"') if len(args) == 1 and not kwargs: self.msg = args[0] else: @@ -211,8 +212,18 @@ class ValueWarning(_CommonError, UserWarning): class ValueOptionError(_CommonError, ValueError): - tmpl = _('"{0}" is an invalid {1} for "{2}"') + tmpl = None + + def __init__(self, *args, **kwargs): + if ValueOptionError.tmpl is None: + ValueOptionError.tmpl = _('"{0}" is an invalid {1} for "{2}"') + super().__init__(*args, **kwargs) class ValueErrorWarning(ValueWarning): - tmpl = _('"{0}" is an invalid {1} for "{2}"') + tmpl = None + + def __init__(self, *args, **kwargs): + if ValueErrorWarning.tmpl is None: + ValueErrorWarning.tmpl = _('"{0}" is an invalid {1} for "{2}"') + super().__init__(*args, **kwargs) diff --git a/tiramisu/function.py b/tiramisu/function.py index 3741b55..b31013e 100644 --- a/tiramisu/function.py +++ b/tiramisu/function.py @@ -48,73 +48,83 @@ def function_waiting_for_error(function): @function_waiting_for_dict -def valid_network_netmask(network: dict, - netmask: dict, - ): +def valid_network_netmask( + network: dict, + netmask: dict, +): """ validates if network and netmask are coherent this validator must be set to netmask option """ - if None in [network['value'], netmask['value']]: + if None in [network["value"], netmask["value"]]: return try: ip_network(f'{network["value"]}/{netmask["value"]}') except ValueError as err: - raise ValueError(_(f'network "{network["value"]}" ({network["name"]}) does not match ' - 'with this netmask')) from err + raise ValueError( + _('network "{0}" ({1}) does not match with this netmask').format( + network["value"], network["name"] + ) + ) from err @function_waiting_for_dict -def valid_ip_netmask(ip: dict, # pylint: disable=invalid-name - netmask: dict, - ): +def valid_ip_netmask( + ip: dict, # pylint: disable=invalid-name + netmask: dict, +): """validates if ip and netmask are coherent this validator must be set to netmask option """ - if None in [ip['value'], netmask['value']]: + if None in [ip["value"], netmask["value"]]: return ip_netmask = ip_interface(f'{ip["value"]}/{netmask["value"]}') if ip_netmask.ip == ip_netmask.network.network_address: - msg = _(f'IP "{ip["value"]}" ({ip["name"]}) with this netmask is ' - 'in fact a network address') + msg = _('IP "{0}" ({1}) with this netmask is in fact a network address').format( + ip["value"], ip["name"] + ) raise ValueError(msg) if ip_netmask.ip == ip_netmask.network.broadcast_address: - msg = _(f'IP "{ip["value"]}" ({ip["name"]}) with this netmask is ' - 'in fact a broacast address') + msg = _( + 'IP "{0}" ({1}) with this netmask is in fact a broadcast address' + ).format(ip["value"], ip["name"]) raise ValueError(msg) @function_waiting_for_dict -def valid_broadcast(network: dict, - netmask: dict, - broadcast: dict, - ): - """validates if the broadcast is coherent with network and netmask - """ - if None in [network['value'], netmask['value'], broadcast['value']]: +def valid_broadcast( + network: dict, + netmask: dict, + broadcast: dict, +): + """validates if the broadcast is coherent with network and netmask""" + if None in [network["value"], netmask["value"], broadcast["value"]]: return - if ip_network(f'{network["value"]}/{netmask["value"]}').broadcast_address != \ - ip_address(broadcast['value']): - msg = _(f'broadcast invalid with network {network["value"]} ({network["name"]}) ' - f'and netmask {netmask["value"]} ({netmask["name"]})') + if ip_network( + f'{network["value"]}/{netmask["value"]}' + ).broadcast_address != ip_address(broadcast["value"]): + msg = _( + "broadcast invalid with network {0} ({1}) and netmask {2} ({3})" + ).format(network["value"], network["name"], netmask["value"], netmask["name"]) raise ValueError(msg) @function_waiting_for_dict -def valid_in_network(ip: dict, # pylint: disable=invalid-name - network: dict, - netmask=Optional[dict], - ): +def valid_in_network( + ip: dict, # pylint: disable=invalid-name + network: dict, + netmask=Optional[dict], +): """validates if an IP is in a network this validator must be set to ip option """ - if None in [ip['value'], network['value']]: + if None in [ip["value"], network["value"]]: return - if '/' in network['value']: + if "/" in network["value"]: # it's a CIDR network - network_value = network['value'] + network_value = network["value"] else: - if netmask is None or netmask['value'] is None: + if netmask is None or netmask["value"] is None: return network_value = f'{network["value"]}/{netmask["value"]}' network_obj = ip_network(network_value) @@ -123,56 +133,63 @@ def valid_in_network(ip: dict, # pylint: disable=invalid-name if netmask is None: msg = _('this IP is not in network {network["value"]} ({network["name"]})') else: - msg = _('this IP is not in network {network["value"]} ({network["name"]}) ' - 'with netmask {netmask["value"]} ({netmask["name"]})') + msg = _( + 'this IP is not in network {network["value"]} ({network["name"]}) ' + 'with netmask {netmask["value"]} ({netmask["name"]})' + ) raise ValueError(msg) # test if ip is not network/broadcast IP if ip_netmask.ip == ip_netmask.network.network_address: - msg = _(f'this IP with the network {network["value"]} ({network["value"]} ' - 'is in fact a network address') + msg = _( + "this IP with the network {0} ({1}) is in fact a network address" + ).format(network["value"], network["name"]) raise ValueError(msg) if ip_netmask.ip == ip_netmask.network.broadcast_address: - msg = _(f'this IP with the network {network["value"]} ({network["value"]} ' - 'is in fact a broadcast address') + msg = _( + "this IP with the network {0} ({1}) is in fact a broadcast address" + ).format(network["value"], network["value"]) raise ValueError(msg) @function_waiting_for_dict def valid_not_equal(*values): - """valid that two options have not same value - """ + """valid that two options have not same value""" equal = set() for val in values[1:]: - if 'propertyerror' in val: + if "propertyerror" in val: continue - if values[0]['value'] == val['value'] is not None: - equal.add(val['name']) + if values[0]["value"] == val["value"] is not None: + equal.add(val["name"]) if not equal: return - msg = _(f'value is identical to {display_list(list(equal), add_quote=True)}') + msg = _("value is identical to {0}").format( + display_list(list(equal), add_quote=True) + ) raise ValueError(msg) class CalcValue: - """class to calc_value with different functions - """ + """class to calc_value with different functions""" + # pylint: disable=too-many-instance-attributes - def __call__(self, - *args: List[Any], - multi: bool=False, - default: Any=undefined, - condition: Any=undefined, - no_condition_is_invalid: bool=False, - expected: Any=undefined, - condition_operator: str='AND', - reverse_condition: bool=False, - allow_none: bool=False, - remove_duplicate_value: bool=False, - join: Optional[str]=None, - min_args_len: Optional[int]=None, - operator: Optional[str]=None, - index: Optional[int]=None, - **kwargs) -> Any: + def __call__( + self, + *args: List[Any], + multi: bool = False, + default: Any = undefined, + condition: Any = undefined, + no_condition_is_invalid: bool = False, + expected: Any = undefined, + condition_operator: str = "AND", + reverse_condition: bool = False, + allow_none: bool = False, + remove_duplicate_value: bool = False, + join: Optional[str] = None, + min_args_len: Optional[int] = None, + operator: Optional[str] = None, + index: Optional[int] = None, + **kwargs, + ) -> Any: # pylint: disable=too-many-statements,too-many-branches,too-many-nested-blocks,too-many-locals """calculate value :param args: list of value @@ -336,10 +353,13 @@ class CalcValue: self.condition_operator = condition_operator self.reverse_condition = reverse_condition self.kwargs = kwargs - self.no_condition_is_invalid = no_condition_is_invalid # pylint: disable=attribute-defined-outside-init - value = self.get_value(default, - min_args_len, - ) + self.no_condition_is_invalid = ( + no_condition_is_invalid # pylint: disable=attribute-defined-outside-init + ) + value = self.get_value( + default, + min_args_len, + ) if not multi: if join is not None: if None not in value: @@ -348,11 +368,12 @@ class CalcValue: value = None elif value and operator: new_value = value[0] - oper = {'mul': mul, - 'add': add, - 'div': truediv, - 'sub': sub, - }[operator] + oper = { + "mul": mul, + "add": add, + "div": truediv, + "sub": sub, + }[operator] for val in value[1:]: new_value = oper(new_value, val) value = new_value @@ -376,8 +397,9 @@ class CalcValue: break lval = len(val) if length_val is not None and length_val != lval: - msg = _('unexpected value in calc_value with join attribute ' - f'"{val}" with invalid length "{length_val}"') + msg = _( + 'unexpected value in calc_value with join attribute "{0}" with invalid length "{1}"' + ).format(val, length_val) raise ValueError(msg) length_val = lval new_value = [] @@ -403,19 +425,16 @@ class CalcValue: value = new_value return value - def value_from_kwargs(self, - value: Any, - pattern: str, - to_dict: bool=False, - empty_test=undefined) -> Any: - """get value from kwargs - """ + def value_from_kwargs( + self, value: Any, pattern: str, to_dict: bool = False, empty_test=undefined + ) -> Any: + """get value from kwargs""" # pylint: disable=too-many-branches # if value attribute exist return it's value # otherwise pattern_0, pattern_1, ... # otherwise undefined if value is not empty_test: - if to_dict == 'all': + if to_dict == "all": returns = {None: value} else: returns = value @@ -426,7 +445,7 @@ class CalcValue: if key.startswith(pattern): index = int(key[len_pattern:]) if isinstance(pattern_value, dict): - pattern_value = pattern_value['value'] + pattern_value = pattern_value["value"] kwargs_matches[index] = pattern_value if not kwargs_matches: returns = undefined @@ -443,38 +462,47 @@ class CalcValue: returns.append(kwargs_matches[key]) return returns - def is_condition_matches(self, - condition_value, - ): - """verify the condition - """ + def is_condition_matches( + self, + condition_value, + ): + """verify the condition""" # pylint: disable=too-many-branches - calculated_conditions = self.value_from_kwargs(condition_value, - 'condition_', - to_dict='all', - ) + calculated_conditions = self.value_from_kwargs( + condition_value, + "condition_", + to_dict="all", + ) if calculated_conditions is undefined: is_matches = not self.no_condition_is_invalid else: is_matches = None - calculated_expected = self.value_from_kwargs(self.expected, - 'expected_', - to_dict=True, - ) - calculated_reverse = self.value_from_kwargs(self.reverse_condition, - 'reverse_condition_', - to_dict=True, - empty_test=False, - ) + calculated_expected = self.value_from_kwargs( + self.expected, + "expected_", + to_dict=True, + ) + calculated_reverse = self.value_from_kwargs( + self.reverse_condition, + "reverse_condition_", + to_dict=True, + empty_test=False, + ) for idx, calculated_condition in calculated_conditions.items(): if isinstance(calculated_expected, dict): if idx is not None: if isinstance(calculated_expected[idx], list): - current_matches = calculated_condition in calculated_expected[idx] + current_matches = ( + calculated_condition in calculated_expected[idx] + ) else: - current_matches = calculated_condition == calculated_expected[idx] + current_matches = ( + calculated_condition == calculated_expected[idx] + ) else: - current_matches = calculated_condition in calculated_expected.values() + current_matches = ( + calculated_condition in calculated_expected.values() + ) else: current_matches = calculated_condition == calculated_expected if isinstance(calculated_reverse, dict) and idx in calculated_reverse: @@ -483,36 +511,41 @@ class CalcValue: reverse_condition = False if is_matches is None: is_matches = current_matches - if self.condition_operator == 'AND': + if self.condition_operator == "AND": is_matches = is_matches and current_matches if reverse_condition: is_matches = not is_matches if not is_matches: break - elif self.condition_operator == 'OR': + elif self.condition_operator == "OR": is_matches = is_matches or current_matches if reverse_condition: is_matches = not is_matches if is_matches: break else: - msg = _(f'unexpected {self.condition_operator} condition_operator ' - 'in calc_value') + msg = _( + "unexpected {0} condition_operator " "in calc_value" + ).format(self.condition_operator) raise ValueError(msg) - is_matches = is_matches and not self.reverse_condition \ - or not is_matches and self.reverse_condition + is_matches = ( + is_matches + and not self.reverse_condition + or not is_matches + and self.reverse_condition + ) return is_matches - def get_value(self, - default, - min_args_len, - ): - """get the value from arguments - """ + def get_value( + self, + default, + min_args_len, + ): + """get the value from arguments""" # retrieve the condition if isinstance(self.condition, dict): - if 'value' in self.condition: - condition_value = self.condition['value'] + if "value" in self.condition: + condition_value = self.condition["value"] else: condition_value = undefined else: @@ -527,9 +560,10 @@ class CalcValue: value = [] if not value: # default value - new_default = self.value_from_kwargs(default, - 'default_', - ) + new_default = self.value_from_kwargs( + default, + "default_", + ) if new_default is not undefined: if not isinstance(new_default, list): value = [new_default] @@ -538,34 +572,32 @@ class CalcValue: return value def get_args(self): - """get all arguments - """ + """get all arguments""" return list(self.args) class CalcValuePropertyHelp(CalcValue): - """special class to display property error - """ + """special class to display property error""" + def get_name(self): - """get the condition name - """ - return self.condition['name'] + """get the condition name""" + return self.condition["name"] def get_indexed_name(self, index: int) -> str: - """get name for a specified index - """ - condition_index = self.kwargs.get(f'condition_{index}') + """get name for a specified index""" + condition_index = self.kwargs.get(f"condition_{index}") if condition_index is not None and not isinstance(condition_index, dict): - raise ValueError(_(f'unexpected condition_{index} must have "todict" argument')) - return condition_index['name'] + raise ValueError( + _('unexpected condition_{0} must have "todict" argument').format(index) + ) + return condition_index["name"] - - def build_property_message(self, - name: str, - value: Any, - ) -> str: - """prepare message to display error message if needed - """ + def build_property_message( + self, + name: str, + value: Any, + ) -> str: + """prepare message to display error message if needed""" if not self.reverse_condition: msg = _('the value of "{0}" is {1}').format(name, value) else: @@ -575,21 +607,21 @@ class CalcValuePropertyHelp(CalcValue): def get_args(self): args = super().get_args() action = args[0] - calculated_expected = self.value_from_kwargs(self.expected, - 'expected_', - to_dict=True) + calculated_expected = self.value_from_kwargs( + self.expected, "expected_", to_dict=True + ) if self.condition is not undefined: - if 'propertyerror' in self.condition: - msg = self.condition['propertyerror'] + if "propertyerror" in self.condition: + msg = self.condition["propertyerror"] else: name = self.get_name() if isinstance(calculated_expected, dict): calc_values = calculated_expected.values() else: calc_values = [calculated_expected] - display_value = display_list([str(val) for val in calc_values], - separator='or', - add_quote=True) + display_value = display_list( + [str(val) for val in calc_values], separator="or", add_quote=True + ) msg = self.build_property_message(name, display_value) else: msgs = [] @@ -601,8 +633,10 @@ class CalcValuePropertyHelp(CalcValue): calc_value = CalcValue() -calc_value.__name__ = 'calc_value' # pylint: disable=attribute-defined-outside-init +calc_value.__name__ = "calc_value" # pylint: disable=attribute-defined-outside-init # function_waiting_for_dict(calc_value) calc_value_property_help = CalcValuePropertyHelp() -calc_value_property_help.__name__ = 'calc_value_property_help' # pylint: disable=attribute-defined-outside-init +calc_value_property_help.__name__ = ( + "calc_value_property_help" # pylint: disable=attribute-defined-outside-init +) function_waiting_for_dict(calc_value_property_help) diff --git a/tiramisu/i18n.py b/tiramisu/i18n.py index 958fff5..ddc766e 100644 --- a/tiramisu/i18n.py +++ b/tiramisu/i18n.py @@ -18,55 +18,9 @@ # the rough gus of pypy: pypy: http://codespeak.net/svn/pypy/dist/pypy/config/ # the whole pypy projet is under MIT licence "internationalisation utilities" -from .log import log +from gettext import translation +from pathlib import Path -from gettext import translation, NullTranslations -from platform import system -from pkg_resources import resource_filename -from os import environ +t = translation('tiramisu', str(Path(__file__).parent / 'locale'), fallback=True) - -DEFAULT = 'en' - - -def get_translation() -> str: - """Sets the user locale as langage - The default is set to english - """ - # Application name (without .i18n) - app_name = __name__[:-5] - translations_path = resource_filename(app_name, 'locale') - - if 'TIRAMISU_LOCALE' in environ: # pragma: no cover - user_locale = environ['TIRAMISU_LOCALE'] - else: - if 'Windows' in system(): # pragma: no cover - import ctypes - from locale import windows_locale - default_locale = windows_locale[ctypes.windll.kernel32.GetUserDefaultUILanguage()] - else: - from locale import getlocale - default_locale = getlocale() - if default_locale and isinstance(default_locale, tuple): - if default_locale[0] is not None: - user_locale = default_locale[0][:2] - else: - user_locale = DEFAULT - elif default_locale: # pragma: no cover - user_locale = default_locale[:2] - else: # pragma: no cover - user_locale = DEFAULT - try: - trans = translation(domain=app_name, - localedir=translations_path, - languages=[user_locale], - ) -# codeset='UTF-8') - except FileNotFoundError: # pragma: no cover - log.debug('cannot found translation file for langage {} in localedir {}'.format(user_locale, - translations_path)) - trans = NullTranslations() - return trans.gettext - - -_ = get_translation() +_ = t.gettext diff --git a/tiramisu/locale/fr/LC_MESSAGES/tiramisu.mo b/tiramisu/locale/fr/LC_MESSAGES/tiramisu.mo new file mode 100644 index 0000000..64c604e Binary files /dev/null and b/tiramisu/locale/fr/LC_MESSAGES/tiramisu.mo differ diff --git a/tiramisu/locale/fr/LC_MESSAGES/tiramisu.po b/tiramisu/locale/fr/LC_MESSAGES/tiramisu.po deleted file mode 100644 index 9a8ccda..0000000 --- a/tiramisu/locale/fr/LC_MESSAGES/tiramisu.po +++ /dev/null @@ -1,1192 +0,0 @@ -msgid "" -msgstr "" -"Project-Id-Version: Tiramisu\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-08-28 15:53+CEST\n" -"PO-Revision-Date: \n" -"Last-Translator: Emmanuel Garette \n" -"Language-Team: Tiramisu's team \n" -"Language: fr\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 2.2.3\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Poedit-SourceCharset: UTF-8\n" - -#: tiramisu/api.py:59 -msgid "Settings:" -msgstr "Paramètres :" - -#: 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:61 -msgid "Access to option without property restriction" -msgstr "Accès à une option sans restriction de propriété" - -#: tiramisu/api.py:65 -msgid "Call: {}" -msgstr "Appel : {}" - -#: tiramisu/api.py:67 -msgid "Commands:" -msgstr "Commandes :" - -#: tiramisu/api.py:104 -msgid "" -"index \"{}\" is greater than the leadership length \"{}\" for option \"{}\"" -msgstr "" -"l'index \"{}\" est supérieur à la longueur de la leadership \"{}\" pour " -"l'option \"{}\"" - -#: tiramisu/api.py:109 -msgid "option must not be an optiondescription" -msgstr "option ne doit pas être une optiondescription" - -#: tiramisu/api.py:137 -msgid "index must be set with the follower option \"{}\"" -msgstr "l'index est obligatoire pour l'option suiveuse \"{}\"" - -#: tiramisu/api.py:140 -msgid "unknown method {} in {}" -msgstr "méthode {} inconnue dans {}" - -#: tiramisu/api.py:398 -msgid "cannot add this property: \"{0}\"" -msgstr "ne peut pas ajouter cette propriété : \"{0}\"" - -#: tiramisu/api.py:554 tiramisu/config.py:239 -msgid "can't delete a SymLinkOption" -msgstr "ne peut supprimer une valeur à une SymLinkOption" - -#: tiramisu/api.py:714 tiramisu/api.py:1515 -msgid "please specify a valid sub function ({})" -msgstr "veuillez spécifier une sous fonction valide ({})" - -#: tiramisu/api.py:734 -msgid "unknown config type {}" -msgstr "type de config {} inconnue" - -#: tiramisu/api.py:795 tiramisu/api.py:1271 -msgid "unknown list type {}" -msgstr "type de liste inconnue {}" - -#: tiramisu/api.py:797 tiramisu/api.py:1273 -msgid "unknown group_type: {0}" -msgstr "group_type inconnu: {0}" - -#: tiramisu/api.py:1096 -msgid "properties must be a frozenset" -msgstr "une propriété doit être de type frozenset" - -#: tiramisu/api.py:1102 tiramisu/api.py:1124 -msgid "unknown when {} (must be in append or remove)" -msgstr "value {} inconsistent (doit être append ou remove)" - -#: tiramisu/api.py:1114 tiramisu/api.py:1136 tiramisu/config.py:1269 -msgid "unknown type {}" -msgstr "type inconnu {}" - -#: tiramisu/api.py:1440 -msgid "cannot set session_id and config together" -msgstr "session_id et config ne peut être mis ensemble" - -#: tiramisu/autolib.py:96 -msgid "unable to carry out a calculation for \"{}\", {}" -msgstr "impossible d'effectuer le calcul pour \"{}\", {}" - -#: tiramisu/autolib.py:257 -msgid "" -"the \"{}\" function with positional arguments \"{}\" and keyword arguments " -"\"{}\" must not return a list (\"{}\") for the follower option \"{}\"" -msgstr "" -"la fonction \"{}\" avec les arguments positionnels \"{}\" et les arguments " -"nommés \"{}\" ne doit pas retourner une liste (\"{}\") pour l'option " -"suiveuse \"{}\"" - -#: tiramisu/autolib.py:266 -msgid "" -"the \"{}\" function must not return a list (\"{}\") for the follower option " -"\"{}\"" -msgstr "" -"la fonction \"{}\" ne doit pas retourner une liste (\"{}\") pour l'option " -"suiveuse \"{}\"" - -#: tiramisu/autolib.py:295 -msgid "" -"unexpected error \"{0}\" in function \"{1}\" with arguments \"{3}\" and " -"\"{4}\" for option \"{2}\"" -msgstr "" -"erreur inattendue \"{0}\" dans la fonction \"{1}\" avec les arguments " -"\"{3}\" et \"{4}\" pour l'option \"{2}\"" - -#: tiramisu/autolib.py:302 -msgid "unexpected error \"{0}\" in function \"{1}\" for option \"{2}\"" -msgstr "" -"erreur inattendue \"{0}\" dans la fonction \"{1}\" pour l'option \"{2}\"" - -#: tiramisu/config.py:69 -msgid "\"{0}\" must be an optiondescription, not an {1}" -msgstr "\"{0}\" doit être une optiondescription, et non {1}" - -#: tiramisu/config.py:200 -msgid "unknown option {}" -msgstr "option {} inconnue" - -#: tiramisu/config.py:208 -msgid "there is no option description for this config (may be GroupConfig)" -msgstr "" -"il n'y a pas d'option description trouvé pour cette config (peut être un " -"GroupConfig)" - -#: tiramisu/config.py:224 -msgid "can't assign to a SymLinkOption" -msgstr "ne peut assigner une valeur à une SymLinkOption" - -#: tiramisu/config.py:228 -msgid "cannot reduce length of the leader \"{}\"" -msgstr "il est impossible de réduire la longueur du leader \"{}\"" - -#: tiramisu/config.py:308 -msgid "" -"the follower option \"{}\" has greater length ({}) than the leader length " -"({})" -msgstr "" -"l'option suiveuse \"{}\" a une longueur supérieur ({}) à la longueur de " -"l'option leader ({})" - -#: tiramisu/config.py:405 -msgid "no option found in config with these criteria" -msgstr "aucune option trouvée dans la config avec ces critères" - -#: tiramisu/config.py:455 -msgid "make_dict can't filtering with value without option" -msgstr "make_dict ne peut filtrer sur une valeur mais sans option" - -#: tiramisu/config.py:508 -msgid "unexpected path \"{0}\", should start with \"{1}\"" -msgstr "chemin inconsistant \"{0}\", devrait commencé par \"{1}\"" - -#: tiramisu/config.py:660 -msgid "cannot duplicate {}" -msgstr "ne peut dupliquer : {0}" - -#: tiramisu/config.py:716 -msgid "parent of {} not already exists" -msgstr "le parent de {} n'existe plus" - -#: tiramisu/config.py:755 -msgid "cannot set leadership object has root optiondescription" -msgstr "ne peut assigner un objet leadership comme optiondescription racine" - -#: tiramisu/config.py:757 -msgid "cannot set dynoptiondescription object has root optiondescription" -msgstr "" -"ne peut assigner un objet dynoptiondescription comme optiondescription racine" - -#: tiramisu/config.py:774 tiramisu/config.py:819 -msgid "invalid session ID: {0} for config" -msgstr "ID de session invalide : {0} pour une config" - -#: tiramisu/config.py:803 -msgid "groupconfig's children must be a list" -msgstr "enfants d'une groupconfig doit être une liste" - -#: tiramisu/config.py:807 -msgid "groupconfig's children must be Config, MetaConfig or GroupConfig" -msgstr "" -"les enfants d'un groupconfig doivent être des Config, MetaConfig ou " -"GroupConfig" - -#: tiramisu/config.py:814 -msgid "config name must be uniq in groupconfig for \"{0}\"" -msgstr "le nom d'un config doit être unique dans un groupconfig pour \"{0}\"" - -#: tiramisu/config.py:984 -msgid "unknown config \"{}\"" -msgstr "config \"{}\" inconnue" - -#: tiramisu/config.py:1005 -msgid "child must be a Config, MixConfig or MetaConfig" -msgstr "l'enfant doit être une Config, MixConfig ou MetaConfig" - -#: tiramisu/config.py:1037 -msgid "" -"force_default, force_default_if_same or force_dont_change_value cannot be " -"set with only_config" -msgstr "" -"force_default, force_default_if_same ou force_dont_change_value ne peuvent " -"pas être spécifié avec only_config" - -#: tiramisu/config.py:1059 -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:1190 tiramisu/config.py:1267 -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:1207 tiramisu/config.py:1216 -msgid "cannot find the config {}" -msgstr "ne peut pas trouver la config {0}" - -#: tiramisu/config.py:1238 -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:1250 -msgid "child must be a Config or MetaConfig" -msgstr "enfant doit être une une Config ou une MetaConfig" - -#: tiramisu/config.py:1254 -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:1305 -msgid "metaconfig must have the same optiondescription" -msgstr "metaconfig doivent avoir la même optiondescription" - -#: tiramisu/error.py:24 -msgid "and" -msgstr "et" - -#: tiramisu/error.py:26 -msgid "or" -msgstr "ou" - -#: tiramisu/error.py:50 -msgid " {} " -msgstr " {} " - -#: tiramisu/error.py:105 tiramisu/setting.py:601 -msgid "property" -msgstr "de la propriété" - -#: tiramisu/error.py:107 tiramisu/setting.py:603 -msgid "properties" -msgstr "des propriétés" - -#: tiramisu/error.py:109 -msgid "cannot access to {0} \"{1}\" because \"{2}\" has {3} {4}" -msgstr "ne peut accéder à {0} \"{1}\" parce que \"{2}\" a {3} {4}" - -#: tiramisu/error.py:116 -msgid "cannot access to {0} \"{1}\" because has {2} {3}" -msgstr "ne peut accéder à l'{0} \"{1}\" à cause {2} {3}" - -#: tiramisu/error.py:192 -msgid "invalid value" -msgstr "valeur invalide" - -#: tiramisu/error.py:197 -msgid "attention, \"{0}\" could be an invalid {1} for \"{2}\"" -msgstr "attention, \"{0}\" peut être un {1} invalide pour \"{2}\"" - -#: tiramisu/error.py:201 tiramisu/error.py:205 -msgid "\"{0}\" is an invalid {1} for \"{2}\"" -msgstr "\"{0}\" est une valeur invalide pour l'option \"{2}\" de type {1}" - -#: tiramisu/function.py:34 -msgid "args in params must be a tuple" -msgstr "args dans params doit être un tuple" - -#: 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:39 -msgid "kwargs in params must be a dict" -msgstr "kwargs dans params doit être un dict" - -#: tiramisu/function.py:58 -msgid "paramoption needs an option not {}" -msgstr "paramoption doit être une option pas {0}" - -#: 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" - -#: tiramisu/option/baseoption.py:93 -msgid "invalid properties type {0} for {1}, must be a frozenset" -msgstr "type {0} invalide pour des propriétés pour {1}, doit être un frozenset" - -#: tiramisu/option/baseoption.py:115 -msgid "conflict: properties already set in requirement {0} for {1}" -msgstr "" -"conflit : les propriétés sont déjà mis dans les requirements {0} pour {1}" - -#: tiramisu/option/baseoption.py:162 -msgid "{0} must be a function" -msgstr "{0} doit être une fonction" - -#: tiramisu/option/baseoption.py:164 -msgid "{0}_params must be a params" -msgstr "{0}_params doit être un params" - -#: tiramisu/option/baseoption.py:205 -msgid "cannot find those arguments \"{}\" in function \"{}\" for \"{}\"" -msgstr "" -"ne peut trouver les arguments \"{}\" dans la fonction \"{}\" pour \"{}\"" - -#: tiramisu/option/baseoption.py:224 -msgid "missing those arguments \"{}\" in function \"{}\" for \"{}\"" -msgstr "les arguments \"{}\" sont manquant dans la fonction \"{}\" pour \"{}\"" - -#: tiramisu/option/baseoption.py:258 -msgid "" -"params defined for a callback function but no callback defined yet for " -"option \"{0}\"" -msgstr "" -"paramètres définis pour la fonction de callback mais aucun callback défini " -"pour l'option \"{0}\"" - -#: tiramisu/option/baseoption.py:350 tiramisu/storage/dictionary/value.py:256 -#: 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: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:394 -msgid "\"{}\" ({}) object attribute \"{}\" is read-only" -msgstr "\"{}\" ({}) l'attribut de l'objet \"{}\" est en lecture seule" - -#: tiramisu/option/baseoption.py:404 -msgid "\"{}\" not part of any Config" -msgstr "\"{}\" ne fait pas parti d'une Config" - -#: tiramisu/option/baseoption.py:459 -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:462 -msgid "" -"malformed requirements multi option must not set as requires of non multi " -"option {0}" -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:501 -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:508 tiramisu/option/baseoption.py:524 -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:538 -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:546 -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:553 -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:560 -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:567 -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:580 -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:586 -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:598 -msgid "" -"malformed requirements for option: {0} require must have option, expected " -"and action keys" -msgstr "" -"requirements malformé pour l'option : {0} l'exigence doit avoir les clefs " -"option, expected et action" - -#: tiramisu/option/booloption.py:31 -msgid "boolean" -msgstr "booléen" - -#: tiramisu/option/broadcastoption.py:32 -msgid "broadcast address" -msgstr "adresse de broadcast" - -#: tiramisu/option/broadcastoption.py:39 tiramisu/option/dateoption.py:38 -#: tiramisu/option/domainnameoption.py:126 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:57 -msgid "invalid broadcast consistency, a network and a netmask are needed" -msgstr "" -"adresse de broadcast inconsistente, un réseau et un masque sont nécessaires." - -#: 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:37 -msgid "choice" -msgstr "choix" - -#: 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: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:108 -msgid "calculated values for {0} is not a list" -msgstr "valeurs calculées for {0} n'est pas une liste" - -#: tiramisu/option/choiceoption.py:123 -msgid "only \"{0}\" is allowed" -msgstr "seul \"{0}\" est autorisé" - -#: tiramisu/option/choiceoption.py:126 -msgid "only {0} are allowed" -msgstr "seul {0} sont autorisées" - -#: tiramisu/option/dateoption.py:31 -msgid "date" -msgstr "date" - -#: tiramisu/option/domainnameoption.py:38 -msgid "domain name" -msgstr "nom de domaine" - -#: 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:62 -msgid "allow_ip must be a boolean" -msgstr "allow_ip doit être un booléen" - -#: 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:73 -msgid "only lowercase, number, \"-\" and \".\" are characters are allowed" -msgstr "" -"seuls les caractères en minuscule, les nombres, \"-\" et \".\" sont autorisés" - -#: tiramisu/option/domainnameoption.py:74 -msgid "only lowercase, number, \"-\" and \".\" are characters are recommanded" -msgstr "" -"seuls les caractères en minuscule, les nombres, \"-\" et \".\" sont " -"recommandés" - -#: tiramisu/option/domainnameoption.py:77 -msgid "only lowercase, number and - are characters are allowed" -msgstr "seuls les caractères en minuscule, les nombres et \"-\" sont autorisés" - -#: tiramisu/option/domainnameoption.py:78 -msgid "only lowercase, number and \"-\" are characters are recommanded" -msgstr "" -"seuls les caractères en minuscule, les nombres et \"-\" sont recommandés" - -#: tiramisu/option/domainnameoption.py:80 -#: tiramisu/option/domainnameoption.py:81 -msgid "could be a IP, otherwise {}" -msgstr "peut être une IP, autrement {}" - -#: tiramisu/option/domainnameoption.py:120 -msgid "invalid length (min 1)" -msgstr "longueur invalide (min 1)" - -#: tiramisu/option/domainnameoption.py:122 -msgid "invalid length (max {0})" -msgstr "longueur invalide (max {0})" - -#: tiramisu/option/domainnameoption.py:133 -msgid "must not be an IP" -msgstr "ne doit pas être une IP" - -#: tiramisu/option/domainnameoption.py:139 -msgid "must have dot" -msgstr "doit avoir un point" - -#: tiramisu/option/domainnameoption.py:141 -msgid "invalid length (max 255)" -msgstr "longueur invalide (max 255)" - -#: tiramisu/option/domainnameoption.py:149 -msgid "some characters are uppercase" -msgstr "des caractères sont en majuscule" - -#: tiramisu/option/dynoptiondescription.py:56 -msgid "cannot set optiondescription in a dynoptiondescription" -msgstr "ne peut mettre une optiondescription dans une dynoptiondescription" - -#: tiramisu/option/dynoptiondescription.py:61 -msgid "cannot set symlinkoption in a dynoptiondescription" -msgstr "ne peut mettre une symlinkoption dans une dynoptiondescription" - -#: tiramisu/option/dynoptiondescription.py:72 -msgid "callback is mandatory for the dynoptiondescription \"{}\"" -msgstr "un callback est obligatoire pour le dynoptiondescription \"{}\"" - -#: tiramisu/option/dynoptiondescription.py:86 -msgid "DynOptionDescription callback for option \"{}\", is not a list ({})" -msgstr "" -"le résultat du callback du DynOptionDescription de l'option \"{}\" n'est pas " -"une liste ({})" - -#: tiramisu/option/dynoptiondescription.py:92 -msgid "invalid identifier \"{}\" for option \"{}\"" -msgstr "identifiant \"{}\" invalide pour l'option \"{}\"" - -#: tiramisu/option/dynoptiondescription.py:101 -msgid "DynOptionDescription callback return a list with multiple value \"{}\"" -msgstr "" -"le callback de DynOptionDescription retourne une list avec plusieurs valeurs " -"\"{}\"" - -#: tiramisu/option/emailoption.py:32 -msgid "email address" -msgstr "adresse mail" - -#: tiramisu/option/filenameoption.py:31 -msgid "file name" -msgstr "nom de fichier" - -#: tiramisu/option/floatoption.py:31 -msgid "float" -msgstr "nombre flottant" - -#: tiramisu/option/intoption.py:31 -msgid "integer" -msgstr "nombre" - -#: tiramisu/option/intoption.py:55 -msgid "value must be equal or greater than \"{0}\"" -msgstr "valeur doit être supérieur ou égal à {0}" - -#: tiramisu/option/intoption.py:58 -msgid "value must be less than \"{0}\"" -msgstr "valeur doit être inférieur à \"{0}\"" - -#: tiramisu/option/ipoption.py:36 -msgid "IP" -msgstr "IP" - -#: 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:111 -msgid "shouldn't be reserved IP" -msgstr "ne devrait pas être une IP réservée" - -#: 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:117 -msgid "should be private IP" -msgstr "devrait être une IP privée" - -#: tiramisu/option/ipoption.py:119 -msgid "must be private IP" -msgstr "doit être une IP privée" - -#: tiramisu/option/ipoption.py:147 -msgid "IP not in network \"{0}\" (\"{1}\")" -msgstr "l'IP n'est pas dans le réseau \"{0}\" (\"{1}\")" - -#: tiramisu/option/ipoption.py:162 -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:169 -msgid "IP not in network \"{2}\"/\"{4}\" (\"{3}\"/\"{5}\")" -msgstr "l'IP n'est pas dans le réseau \"{2}\"/\"{4}\" (\"{3}\"/\"{5}\")" - -#: tiramisu/option/ipoption.py:171 -msgid "" -"the network doest not match with IP \"{0}\" (\"{1}\") and network " -"\"{4}\" (\"{5}\")" -msgstr "" -"le réseau ne correspond pas à l'IP \"{0}\" (\"{1}\") et au réseau " -"\"{4}\" (\"{5}\")" - -#: tiramisu/option/ipoption.py:173 -msgid "" -"the netmask does not match with IP \"{0}\" (\"{1}\") and broadcast " -"\"{2}\" (\"{3}\")" -msgstr "" -"le masque de réseau ne correspond pas à l'IP \"{0}\" (\"{1}\") et au " -"broadcast \"{2}\" (\"{3}\")" - -#: tiramisu/option/leadership.py:56 -msgid "a leader and a follower are mandatories in leadership \"{}\"" -msgstr "" -"une option leader et une option suiveuse sont obligatoires dans une option " -"leadership \"{}\"" - -#: tiramisu/option/leadership.py:62 -msgid "leadership \"{0}\" shall not have a symlinkoption" -msgstr "une option leadership \"{0}\" ne devrait pas avoir de symlinkoption" - -#: tiramisu/option/leadership.py:65 -msgid "leadership \"{0}\" shall not have a subgroup" -msgstr "une option leadership \"{0}\" ne devrait pas avoir de sous-groupe" - -#: tiramisu/option/leadership.py:68 -msgid "" -"only multi option allowed in leadership \"{0}\" but option \"{1}\" is not a " -"multi" -msgstr "" -"seules des options multiples sont autorisées dans l'option leadership \"{0}\" " -"alors que l'option \"{1}\" n'est pas une option multiple" - -#: tiramisu/option/leadership.py:73 -msgid "" -"not allowed default value for follower option \"{0}\" in leadership \"{1}\"" -msgstr "" -"valeur par défaut non autorisée pour l'option suiveuse \"{0}\" dans l'option " -"leadership \"{1}\"" - -#: tiramisu/option/leadership.py:89 -msgid "callback of leader's option shall not refered to a follower's ones" -msgstr "" -"callback d'une variable leader ne devrait pas référencer une variable " -"suiveuse" - -#: tiramisu/option/leadership.py:97 -msgid "leader {} have requirement, but Leadership {} too" -msgstr "" -"l'option leader {} a des requirements mais l'option leadership {} également" - -#: tiramisu/option/leadership.py:112 -msgid "" -"malformed requirements option \"{0}\" must not be in follower for \"{1}\"" -msgstr "" -"requirement mal formé pour l'option \"{0}\" ne doit pas être dans une " -"suiveuse pour \"{1}\"" - -#: tiramisu/option/netmaskoption.py:35 -msgid "netmask address" -msgstr "adresse netmask" - -#: 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:69 -msgid "the netmask \"{0}\" (\"{1}\") does not match" -msgstr "le masque \"{0}\" (\"{1}\") ne correspond pas" - -#: tiramisu/option/netmaskoption.py:72 -msgid "the network \"{0}\" (\"{1}\") does not match" -msgstr "le réseau \"{0}\" (\"{1}\") ne correspond pas" - -#: 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: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: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:100 -msgid "IP \"{0}\" (\"{1}\") is the network" -msgstr "IP \"{0}\" (\"{1}\") est le réseau" - -#: 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:32 -msgid "network address" -msgstr "adresse réseau" - -#: 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:93 -msgid "mustn't be reserved network" -msgstr "ne doit pas être une IP réservée" - -#: tiramisu/option/option.py:78 -msgid "default_multi is set whereas multi is False in option: {0}" -msgstr "" -"default_multi est spécifié alors que multi est à False pour l'option : {0}" - -#: tiramisu/option/option.py:95 -msgid "invalid multi type \"{}\"" -msgstr "valeur multiple invalide \"{}\"" - -#: tiramisu/option/option.py:118 -msgid "unique must be a boolean, not \"{}\"" -msgstr "unique doit être un booléan, pas \"{}\"" - -#: tiramisu/option/option.py:120 -msgid "unique must be set only with multi value" -msgstr "unique doit être activé uniquement avec une valeur multiple" - -#: tiramisu/option/option.py:131 -msgid "invalid default_multi value {0} for option {1}: {2}" -msgstr "la valeur default_multi est invalide {0} pour l'option {1} : {2}" - -#: tiramisu/option/option.py:137 -msgid "" -"invalid default_multi value \"{0}\" for option \"{1}\", must be a list for a " -"submulti" -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:259 -msgid "invalid value \"{}\", this value is already in \"{}\"" -msgstr "valeur invalide \"{}\", cette valeur est déjà dans \"{}\"" - -#: tiramisu/option/option.py:289 -msgid "which must not be a list" -msgstr "qui ne doit pas être une liste" - -#: 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:337 -msgid "which \"{}\" must be a list of list" -msgstr "lequel \"{}\" doit être une liste de liste" - -#: 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: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:435 -msgid "consistency {0} not available for this option" -msgstr "consistency {0} non valable pour cette option" - -#: 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: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: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: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: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:574 -msgid "cannot add consistency with itself" -msgstr "ne peut ajouter une consistency avec lui même" - -#: 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:616 -msgid "unexpected length of \"{}\" in constency \"{}\", should be \"{}\"" -msgstr "" -"longueur inconsistante pour \"{}\" dans le test de consistence \"{}\", " -"devrait être \"{}\"" - -#: tiramisu/option/option.py:715 -msgid "should be different from the value of {}" -msgstr "devrait être différent de la valeur de {}" - -#: tiramisu/option/option.py:717 -msgid "must be different from the value of {}" -msgstr "doit être différent de la valeur de {}" - -#: tiramisu/option/option.py:720 -msgid "value for {} should be different" -msgstr "valeur pour {} devrait être différent" - -#: tiramisu/option/option.py:722 -msgid "value for {} must be different" -msgstr "valeur pour {} doit être différent" - -#: tiramisu/option/optiondescription.py:63 -#: tiramisu/option/optiondescription.py:181 -msgid "option description seems to be part of an other config" -msgstr "l'option description semble faire parti d'une autre config" - -#: tiramisu/option/optiondescription.py:87 -msgid "the follower \"{0}\" cannot have \"force_store_value\" property" -msgstr "" -"l'option suiveuse \"{0}\" ne doit pas avoir la propriété \"force_store_value" -"\"" - -#: tiramisu/option/optiondescription.py:91 -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:99 tiramisu/setting.py:689 -msgid "" -"a leader ({0}) cannot have \"force_default_on_freeze\" or " -"\"force_metaconfig_on_freeze\" property without \"frozen\"" -msgstr "" -"une option leader ({0}) ne peut avoir de propriété \"force_default_on_freeze" -"\" sans \"frozen\"" - -#: tiramisu/option/optiondescription.py:108 -msgid "malformed consistency option \"{0}\" must be in same leadership" -msgstr "" -"test de consistance mal formé pour l'option \"{0}\" doit être dans la même " -"option leadership" - -#: tiramisu/option/optiondescription.py:116 -msgid "malformed consistency option \"{0}\" must not be a multi for \"{1}\"" -msgstr "" -"test de consistence mal formé pour l'option \"{0}\" ne doit doit pas être " -"une liste pour \"{1}\"" - -#: tiramisu/option/optiondescription.py:120 -msgid "" -"malformed consistency option \"{0}\" must be in same leadership as \"{1}\"" -msgstr "" -"test de consistance mal formé pour l'option \"{0}\" doit être dans la même " -"option leadership que \"{1}\"" - -#: tiramisu/option/optiondescription.py:151 -msgid "" -"malformed requirements option \"{0}\" must be in same leadership for \"{1}\"" -msgstr "" -"requirements mal formé pour l'option \"{0}\" doit être dans la même option " -"leadership que \"{1}\"" - -#: tiramisu/option/optiondescription.py:155 -msgid "malformed requirements option \"{0}\" must not be a multi for \"{1}\"" -msgstr "" -"requirement mal formés pour l'option \"{0}\" ne doit pas être une valeur " -"multiple pour \"{1}\"" - -#: tiramisu/option/optiondescription.py:159 -msgid "duplicate option: {0}" -msgstr "option dupliquée : {0}" - -#: tiramisu/option/optiondescription.py:170 -msgid "consistency with option {0} which is not in Config" -msgstr "consistency avec l'option {0} qui n'est pas dans une Config" - -#: tiramisu/option/optiondescription.py:225 -msgid "unknown option \"{0}\" in optiondescription \"{1}\"" -msgstr "option \"{0}\" inconnue dans l'optiondescription \"{1}\"" - -#: tiramisu/option/optiondescription.py:279 -msgid "children in optiondescription \"{}\" must be a list" -msgstr "les enfants d'une optiondescription \"{}\" doivent être une liste" - -#: tiramisu/option/optiondescription.py:303 -msgid "duplicate option name: \"{0}\"" -msgstr "nom de l'option dupliqué : \"{0}\"" - -#: tiramisu/option/optiondescription.py:308 -msgid "" -"the option's name \"{}\" start as the dynoptiondescription's name \"{}\"" -msgstr "" -"le nom de l'option \"{}\" commence comme le nom du dynoptiondescription " -"\"{}\"" - -#: tiramisu/option/optiondescription.py:333 -msgid "cannot change group_type if already set (old {0}, new {1})" -msgstr "ne peut changer group_type si déjà spécifié (ancien {0}, nouveau {1})" - -#: tiramisu/option/optiondescription.py:337 -msgid "group_type: {0} not allowed" -msgstr "group_type : {0} non autorisé" - -#: tiramisu/option/passwordoption.py:32 -msgid "password" -msgstr "mot de passe" - -#: tiramisu/option/portoption.py:44 -msgid "port" -msgstr "port" - -#: tiramisu/option/portoption.py:81 -msgid "inconsistency in allowed range" -msgstr "inconsistence dans la plage autorisée" - -#: tiramisu/option/portoption.py:86 -msgid "max value is empty" -msgstr "la valeur maximum est vide" - -#: tiramisu/option/portoption.py:111 -msgid "range must have two values only" -msgstr "un rang doit avoir deux valeurs seulement" - -#: 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:123 -msgid "must be an integer between {0} and {1}" -msgstr "doit être une nombre entre {0} et {1}" - -#: tiramisu/option/stroption.py:33 -msgid "string" -msgstr "texte" - -#: tiramisu/option/symlinkoption.py:37 -msgid "malformed symlinkoption must be an option for symlink {0}" -msgstr "symlinkoption mal formé, doit être une option pour symlink {0}" - -#: tiramisu/option/syndynoptiondescription.py:68 -msgid "unknown option \"{0}\" in syndynoptiondescription \"{1}\"" -msgstr "l'option \"{0}\" inconnue dans la syndynoptiondescription \"{1}\"" - -#: tiramisu/option/urloption.py:34 -msgid "URL" -msgstr "URL" - -#: tiramisu/option/urloption.py:44 -msgid "must start with http:// or https://" -msgstr "doit débuter par http:// ou https://" - -#: 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:71 -msgid "must ends with a valid resource name" -msgstr "doit finir par un nom de ressource valide" - -#: tiramisu/option/usernameoption.py:32 -msgid "username" -msgstr "nom d'utilisateur" - -#: tiramisu/setting.py:262 -msgid "can't rebind {0}" -msgstr "ne peut redéfinir ({0})" - -#: tiramisu/setting.py:267 -msgid "can't unbind {0}" -msgstr "ne peut supprimer ({0})" - -#: tiramisu/setting.py:541 -msgid "" -"malformed requirements imbrication detected for option: '{0}' with " -"requirement on: '{1}'" -msgstr "" -"imbrication de requirements mal formés detectée pour l'option : '{0}' avec " -"requirement sur : '{1}'" - -#: tiramisu/setting.py:604 -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:632 -msgid "the calculated value is {0}" -msgstr "valeurs calculées est {0}" - -#: tiramisu/setting.py:634 -msgid "the calculated value is not {0}" -msgstr "valeurs calculées n'est pas {0}" - -#: tiramisu/setting.py:638 -msgid "the value of \"{0}\" is {1}" -msgstr "la valeur de \"{0}\" est {1}" - -#: tiramisu/setting.py:640 -msgid "the value of \"{0}\" is not {1}" -msgstr "la valeur de \"{0}\" n'est pas {1}" - -#: tiramisu/setting.py:679 -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:684 -msgid "can't assign property to the symlinkoption \"{}\"" -msgstr "ne peut assigner une propriété à une symlinkoption \"{}\"" - -#: tiramisu/setting.py:716 -msgid "permissive must be a frozenset" -msgstr "une permissive doit être de type frozenset" - -#: tiramisu/setting.py:720 -msgid "can't assign permissive to the symlinkoption \"{}\"" -msgstr "ne peut assigner une permissive à la symlinkoption \"{}\"" - -#: tiramisu/setting.py:727 -msgid "cannot add those permissives: {0}" -msgstr "ne peut ajouter ces permissives : {0}" - -#: tiramisu/setting.py:744 -msgid "can't reset properties to the symlinkoption \"{}\"" -msgstr "ne peut réinitialiser les propriétés de la symlinkoption \"{}\"" - -#: tiramisu/setting.py:759 -msgid "can't reset permissives to the symlinkoption \"{}\"" -msgstr "ne peut réinitialiser les permissive de la symlinkoption \"{}\"" - -#: tiramisu/storage/__init__.py:61 -msgid "cannot import the storage {0}" -msgstr "ne peut pas importer le stockage {0}" - -#: tiramisu/storage/__init__.py:73 -msgid "storage_type is already set, cannot rebind it" -msgstr "storage_type est déjà défini, impossible de le redéfinir" - -#: tiramisu/storage/dictionary/storage.py:44 -#: tiramisu/storage/sqlite3/storage.py:129 -msgid "session \"{}\" already exists" -msgstr "la session \"{}\" existe déjà" - -#: tiramisu/storage/dictionary/storage.py:46 -msgid "a dictionary cannot be persistent" -msgstr "un espace de stockage dictionary ne peut être persistant" - -#: tiramisu/storage/dictionary/value.py:265 -#: tiramisu/storage/sqlite3/value.py:213 -msgid "information's item not found {0}" -msgstr "l'information de l'objet ne sont pas trouvé {0}" - -#: tiramisu/storage/dictionary/value.py:284 -msgid "cannot delete none persistent session" -msgstr "ne peut supprimer une session non persistante" - -#: tiramisu/storage/sqlite3/storage.py:44 -msgid "cannot change setting when connexion is already opened" -msgstr "ne peut changer les paramètres quand une connexion est déjà ouverte" - -#: tiramisu/todict.py:67 tiramisu/todict.py:563 -msgid "context is not supported from now for {}" -msgstr "context n'est pas supporté maintenant pour {}" - -#: tiramisu/todict.py:345 -msgid "option {} only works when remotable is not \"none\"" -msgstr "l'option {} ne fonctionne que si remotable n'est pas \"none\"" - -#: tiramisu/todict.py:489 -msgid "unable to transform tiramisu object to dict: {}" -msgstr "impossible de transformer l'objet tiramisu en dict : {}" - -#: tiramisu/todict.py:795 tiramisu/todict.py:927 -msgid "unknown form {}" -msgstr "form {} inconnu" - -#: tiramisu/todict.py:840 -msgid "not in current area" -msgstr "n'est pas dans l'espace courant" - -#: tiramisu/todict.py:860 -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:862 -msgid "unknown action" -msgstr "action inconnue" - -#: tiramisu/value.py:425 -msgid "can't set owner for the symlinkoption \"{}\"" -msgstr "ne peut spécifier d'utilisateur à la symlinkoption \"{}\"" - -#: tiramisu/value.py:428 tiramisu/value.py:638 -msgid "set owner \"{0}\" is forbidden" -msgstr "assigner l'utilisateur \"{0}\" est interdit" - -#: tiramisu/value.py:431 -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:509 -msgid "index {} is greater than the length {} for option \"{}\"" -msgstr "l'index {} est supérieur à la longueur \"{}\" pour l'option \"{}\"" - -#~ msgid "please use .dict() before .updates()" -#~ msgstr "faire .dict() avant .updates()" - -#~ msgid "{}config's children should be config, not {}" -#~ msgstr "enfants d'un {}config doit être une config, pas {}" - -#~ msgid "child has already a {}config's" -#~ msgstr "enfant a déjà un {}config" - -#~ msgid "config is already in a metaconfig" -#~ msgstr "la config est déjà dans une metaconfig" - -#~ msgid "some characters may cause problems" -#~ msgstr "des caractères peuvent poser problèmes" - -#~ msgid "\"{0}\" is not in network \"{1}\" (\"{2}\")" -#~ msgstr "\"{0}\" n'est pas dans le réseau \"{1}\" (\"{2}\")" - -#~ msgid "invalid len for vals" -#~ msgstr "longueur invalide pour vals" diff --git a/tiramisu/locale/tiramisu.pot b/tiramisu/locale/tiramisu.pot deleted file mode 100644 index 104398a..0000000 --- a/tiramisu/locale/tiramisu.pot +++ /dev/null @@ -1,711 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR ORGANIZATION -# FIRST AUTHOR , YEAR. -# -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2023-11-19 21:26+0100\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Generated-By: pygettext.py 1.5\n" - - -#: tiramisu/api.py:61 -msgid "Settings:" -msgstr "" - -#: tiramisu/api.py:63 -msgid "Access to option without verifying permissive properties" -msgstr "" - -#: tiramisu/api.py:67 -msgid "Access to option without property restriction" -msgstr "" - -#: tiramisu/api.py:70 -msgid "Do not warnings during validation" -msgstr "" - -#: tiramisu/api.py:75 -msgid "Call: {}" -msgstr "" - -#: tiramisu/api.py:77 -msgid "Commands:" -msgstr "" - -#: tiramisu/api.py:185 -msgid "unknown list type {}" -msgstr "" - -#: tiramisu/api.py:187 -msgid "unknown group_type: {0}" -msgstr "" - -#: tiramisu/api.py:352 -msgid "only multi value has defaultmulti" -msgstr "" - -#: tiramisu/api.py:371 tiramisu/option/intoption.py:31 -msgid "integer" -msgstr "" - -#: tiramisu/api.py:374 tiramisu/option/domainnameoption.py:43 -msgid "domain name" -msgstr "" - -#: tiramisu/api.py:376 -msgid "ip" -msgstr "" - -#: tiramisu/api.py:376 -msgid "netmask" -msgstr "" - -#: tiramisu/api.py:376 -msgid "network" -msgstr "" - -#: tiramisu/api.py:471 -msgid "cannot add this property: \"{0}\"" -msgstr "" - -#: tiramisu/api.py:621 -msgid "cannot reduce length of the leader \"{}\"" -msgstr "" - -#: tiramisu/api.py:1088 -msgid "properties must be a frozenset" -msgstr "" - -#: tiramisu/api.py:1094 tiramisu/api.py:1118 -msgid "unknown when {} (must be in append or remove)" -msgstr "" - -#: tiramisu/api.py:1106 tiramisu/api.py:1127 tiramisu/config.py:1210 -msgid "unknown type {}" -msgstr "" - -#: tiramisu/api.py:1432 -msgid "do not use unrestraint, nowarnings or forcepermissive together" -msgstr "" - -#: tiramisu/autolib.py:44 -msgid "args in params must be a tuple" -msgstr "" - -#: tiramisu/autolib.py:47 tiramisu/autolib.py:52 -msgid "arg in params must be a Param" -msgstr "" - -#: tiramisu/autolib.py:49 -msgid "kwargs in params must be a dict" -msgstr "" - -#: tiramisu/autolib.py:72 -msgid "paramoption needs an option not {}" -msgstr "" - -#: tiramisu/autolib.py:77 -msgid "param must have a boolean not a {} for notraisepropertyerror" -msgstr "" - -#: tiramisu/autolib.py:78 -msgid "param must have a boolean not a {} for raisepropertyerror" -msgstr "" - -#: tiramisu/autolib.py:133 -msgid "option in ParamInformation cannot be a symlinkoption" -msgstr "" - -#: tiramisu/autolib.py:135 -msgid "option in ParamInformation cannot be a follower" -msgstr "" - -#: tiramisu/autolib.py:137 -msgid "option in ParamInformation cannot be a dynamic option" -msgstr "" - -#: tiramisu/autolib.py:166 -msgid "first argument ({0}) must be a function" -msgstr "" - -#: tiramisu/autolib.py:168 -msgid "help_function ({0}) must be a function" -msgstr "" - -#: tiramisu/autolib.py:316 tiramisu/autolib.py:362 -msgid "unable to carry out a calculation for \"{}\", {}" -msgstr "" - -#: tiramisu/autolib.py:319 tiramisu/autolib.py:365 -msgid "the option \"{0}\" is used in a calculation but is invalid ({1})" -msgstr "" - -#: tiramisu/autolib.py:402 -msgid "option \"{}\" cannot be calculated: {}" -msgstr "" - -#: tiramisu/autolib.py:411 -msgid "option \"{}\" is not in a dynoptiondescription" -msgstr "" - -#: tiramisu/autolib.py:562 -msgid "the \"{}\" function with positional arguments \"{}\" and keyword arguments \"{}\" must not return a list (\"{}\") for the follower option \"{}\"" -msgstr "" - -#: tiramisu/autolib.py:571 -msgid "the \"{}\" function must not return a list (\"{}\") for the follower option \"{}\"" -msgstr "" - -#: tiramisu/autolib.py:604 -msgid "unexpected error \"{0}\" in function \"{1}\" with arguments \"{3}\" and \"{4}\" for option \"{2}\"" -msgstr "" - -#: tiramisu/autolib.py:611 -msgid "unexpected error \"{0}\" in function \"{1}\" for option \"{2}\"" -msgstr "" - -#: tiramisu/config.py:82 -msgid "there is no option description for this config (may be GroupConfig)" -msgstr "" - -#: tiramisu/config.py:269 -msgid "no option found in config with these criteria" -msgstr "" - -#: tiramisu/config.py:532 tiramisu/option/optiondescription.py:72 -msgid "option description seems to be part of an other config" -msgstr "" - -#: tiramisu/config.py:790 -msgid "cannot set leadership object has root optiondescription" -msgstr "" - -#: tiramisu/config.py:792 -msgid "cannot set dynoptiondescription object has root optiondescription" -msgstr "" - -#: tiramisu/config.py:840 -msgid "config name must be uniq in groupconfig for \"{0}\"" -msgstr "" - -#: tiramisu/config.py:1024 -msgid "unknown config \"{}\"" -msgstr "" - -#: tiramisu/config.py:1047 -msgid "child must be a Config, MixConfig or MetaConfig" -msgstr "" - -#: tiramisu/config.py:1079 -msgid "force_default, force_default_if_same or force_dont_change_value cannot be set with only_config" -msgstr "" - -#: tiramisu/config.py:1085 -msgid "force_default and force_dont_change_value cannot be set together" -msgstr "" - -#: tiramisu/config.py:1208 -msgid "config name must be uniq in groupconfig for {0}" -msgstr "" - -#: tiramisu/config.py:1246 -msgid "config added has no name, the name is mandatory" -msgstr "" - -#: tiramisu/config.py:1248 -msgid "config name \"{0}\" is not uniq in groupconfig \"{1}\"" -msgstr "" - -#: tiramisu/config.py:1270 -msgid "cannot find the config {}" -msgstr "" - -#: tiramisu/config.py:1294 -msgid "MetaConfig with optiondescription must have string has child, not {}" -msgstr "" - -#: tiramisu/config.py:1303 -msgid "child must be a Config or MetaConfig" -msgstr "" - -#: tiramisu/config.py:1307 -msgid "all config in metaconfig must have the same optiondescription" -msgstr "" - -#: tiramisu/config.py:1319 -msgid "metaconfig must have the same optiondescription" -msgstr "" - -#: tiramisu/error.py:26 -msgid "and" -msgstr "" - -#: tiramisu/error.py:28 -msgid "or" -msgstr "" - -#: tiramisu/error.py:50 -msgid " {} " -msgstr "" - -#: tiramisu/error.py:98 -msgid "property" -msgstr "" - -#: tiramisu/error.py:100 -msgid "properties" -msgstr "" - -#: tiramisu/error.py:187 -msgid "invalid value" -msgstr "" - -#: tiramisu/error.py:192 -msgid "attention, \"{0}\" could be an invalid {1} for \"{2}\"" -msgstr "" - -#: tiramisu/error.py:208 tiramisu/error.py:212 -msgid "\"{0}\" is an invalid {1} for \"{2}\"" -msgstr "" - -#: tiramisu/function.py:113 -msgid "this IP is not in network {network[\"value\"]} ({network[\"name\"]})" -msgstr "" - -#: tiramisu/function.py:115 -msgid "this IP is not in network {network[\"value\"]} ({network[\"name\"]}) with netmask {netmask[\"value\"]} ({netmask[\"name\"]})" -msgstr "" - -#: tiramisu/function.py:559 -msgid "the value of \"{0}\" is {1}" -msgstr "" - -#: tiramisu/function.py:561 -msgid "the value of \"{0}\" is not {1}" -msgstr "" - -#: tiramisu/option/baseoption.py:70 tiramisu/option/symlinkoption.py:40 -msgid "\"{0}\" is an invalid name for an option" -msgstr "" - -#: tiramisu/option/baseoption.py:83 -msgid "invalid properties type {0} for {1}, must be a frozenset" -msgstr "" - -#: tiramisu/option/baseoption.py:89 -msgid "invalid property type {0} for {1}, must be a string or a Calculation" -msgstr "" - -#: tiramisu/option/baseoption.py:227 -msgid "'{0}' ({1}) object attribute '{2}' is read-only" -msgstr "" - -#: tiramisu/option/baseoption.py:265 -msgid "\"{}\" ({}) object attribute \"{}\" is read-only" -msgstr "" - -#: tiramisu/option/booloption.py:32 -msgid "boolean" -msgstr "" - -#: tiramisu/option/broadcastoption.py:33 -msgid "broadcast address" -msgstr "" - -#: tiramisu/option/broadcastoption.py:41 -msgid "invalid string" -msgstr "" - -#: tiramisu/option/choiceoption.py:38 -msgid "choice" -msgstr "" - -#: tiramisu/option/choiceoption.py:51 -msgid "values must be a tuple or a calculation for {0}" -msgstr "" - -#: tiramisu/option/choiceoption.py:67 -msgid "the calculated values \"{0}\" for \"{1}\" is not a list" -msgstr "" - -#: tiramisu/option/choiceoption.py:97 -msgid "only \"{0}\" is allowed" -msgstr "" - -#: tiramisu/option/choiceoption.py:99 -msgid "only {0} are allowed" -msgstr "" - -#: tiramisu/option/dateoption.py:33 -msgid "date" -msgstr "" - -#: tiramisu/option/domainnameoption.py:62 -msgid "unknown type {0} for hostname" -msgstr "" - -#: tiramisu/option/domainnameoption.py:65 -msgid "allow_ip must be a boolean" -msgstr "" - -#: tiramisu/option/domainnameoption.py:67 -msgid "allow_cidr_network must be a boolean" -msgstr "" - -#: tiramisu/option/domainnameoption.py:69 -msgid "allow_without_dot must be a boolean" -msgstr "" - -#: tiramisu/option/domainnameoption.py:71 -msgid "allow_startswith_dot must be a boolean" -msgstr "" - -#: tiramisu/option/domainnameoption.py:81 -msgid "must start with lowercase characters followed by lowercase characters, number, \"-\" and \".\" characters are allowed" -msgstr "" - -#: tiramisu/option/domainnameoption.py:82 -msgid "must start with lowercase characters followed by lowercase characters, number, \"-\" and \".\" characters are recommanded" -msgstr "" - -#: tiramisu/option/domainnameoption.py:84 -#: tiramisu/option/domainnameoption.py:85 -msgid "could be a IP, otherwise {}" -msgstr "" - -#: tiramisu/option/domainnameoption.py:125 -msgid "invalid length (min 1)" -msgstr "" - -#: tiramisu/option/domainnameoption.py:127 -msgid "invalid length (max {0})" -msgstr "" - -#: tiramisu/option/domainnameoption.py:133 -msgid "must have dot" -msgstr "" - -#: tiramisu/option/domainnameoption.py:135 -msgid "invalid length (max 255)" -msgstr "" - -#: tiramisu/option/domainnameoption.py:154 -msgid "must not be an IP" -msgstr "" - -#: tiramisu/option/domainnameoption.py:180 -msgid "some characters are uppercase" -msgstr "" - -#: tiramisu/option/dynoptiondescription.py:65 -msgid "identifiers in dynoptiondescription has to be a calculation" -msgstr "" - -#: tiramisu/option/dynoptiondescription.py:109 -msgid "invalid identifier \"{}\" for option \"{}\"" -msgstr "" - -#: tiramisu/option/emailoption.py:34 -msgid "email address" -msgstr "" - -#: tiramisu/option/filenameoption.py:31 -msgid "file name" -msgstr "" - -#: tiramisu/option/filenameoption.py:38 -msgid "must starts with \"/\"" -msgstr "" - -#: tiramisu/option/floatoption.py:32 -msgid "float" -msgstr "" - -#: tiramisu/option/ipoption.py:33 -msgid "IP" -msgstr "" - -#: tiramisu/option/ipoption.py:57 -msgid "it's in fact a network address" -msgstr "" - -#: tiramisu/option/ipoption.py:59 -msgid "it's in fact a broacast address" -msgstr "" - -#: tiramisu/option/ipoption.py:72 -msgid "CIDR address must have a \"/\"" -msgstr "" - -#: tiramisu/option/ipoption.py:83 -msgid "shouldn't be reserved IP" -msgstr "" - -#: tiramisu/option/ipoption.py:85 -msgid "mustn't be reserved IP" -msgstr "" - -#: tiramisu/option/ipoption.py:89 -msgid "should be private IP" -msgstr "" - -#: tiramisu/option/ipoption.py:91 -msgid "must be private IP" -msgstr "" - -#: tiramisu/option/leadership.py:56 -msgid "a leader and a follower are mandatories in leadership \"{}\"" -msgstr "" - -#: tiramisu/option/leadership.py:73 -msgid "leader cannot have \"{}\" property" -msgstr "" - -#: tiramisu/option/leadership.py:77 -msgid "leadership \"{0}\" shall not have a symlinkoption" -msgstr "" - -#: tiramisu/option/leadership.py:80 -msgid "leadership \"{0}\" shall not have a subgroup" -msgstr "" - -#: tiramisu/option/leadership.py:83 -msgid "only multi option allowed in leadership \"{0}\" but option \"{1}\" is not a multi" -msgstr "" - -#: tiramisu/option/macoption.py:34 -msgid "mac address" -msgstr "" - -#: tiramisu/option/netmaskoption.py:32 -msgid "netmask address" -msgstr "" - -#: tiramisu/option/networkoption.py:32 -msgid "network address" -msgstr "" - -#: tiramisu/option/networkoption.py:51 -msgid "must use CIDR notation" -msgstr "" - -#: tiramisu/option/networkoption.py:68 -msgid "shouldn't be reserved network" -msgstr "" - -#: tiramisu/option/networkoption.py:70 -msgid "mustn't be reserved network" -msgstr "" - -#: tiramisu/option/option.py:69 -msgid "default_multi is set whereas multi is False in option: {0}" -msgstr "" - -#: tiramisu/option/option.py:86 -msgid "invalid multi type \"{}\" for \"{}\"" -msgstr "" - -#: tiramisu/option/option.py:102 -msgid "validators must be a Calculation for \"{}\"" -msgstr "" - -#: tiramisu/option/option.py:127 -msgid "invalid default_multi value \"{0}\" for option \"{1}\"" -msgstr "" - -#: tiramisu/option/option.py:137 -msgid "invalid default_multi value \"{0}\" for option \"{1}\", must be a list for a submulti" -msgstr "" - -#: tiramisu/option/option.py:291 -msgid "the value \"{}\" is not unique" -msgstr "" - -#: tiramisu/option/option.py:331 -msgid "which must not be a list" -msgstr "" - -#: tiramisu/option/option.py:373 tiramisu/option/option.py:399 -msgid "which must be a list" -msgstr "" - -#: tiramisu/option/option.py:392 -msgid "which \"{}\" must be a list of list" -msgstr "" - -#: tiramisu/option/optiondescription.py:109 -msgid "duplicate option: {0}" -msgstr "" - -#: tiramisu/option/optiondescription.py:306 -msgid "children in optiondescription \"{}\" must be a list" -msgstr "" - -#: tiramisu/option/optiondescription.py:329 -msgid "duplicate option name: \"{0}\"" -msgstr "" - -#: tiramisu/option/optiondescription.py:374 -msgid "cannot change group_type if already set (old {0}, new {1})" -msgstr "" - -#: tiramisu/option/optiondescription.py:378 -msgid "group_type: {0} not allowed" -msgstr "" - -#: tiramisu/option/passwordoption.py:32 -msgid "password" -msgstr "" - -#: tiramisu/option/permissionsoption.py:38 -msgid "unix file permissions" -msgstr "" - -#: tiramisu/option/permissionsoption.py:52 -msgid "only 3 or 4 octal digits are allowed" -msgstr "" - -#: tiramisu/option/permissionsoption.py:65 -msgid "user" -msgstr "" - -#: tiramisu/option/permissionsoption.py:66 -#: tiramisu/option/permissionsoption.py:68 -msgid "group" -msgstr "" - -#: tiramisu/option/permissionsoption.py:69 -msgid "other" -msgstr "" - -#: tiramisu/option/permissionsoption.py:73 -msgid "too weak" -msgstr "" - -#: tiramisu/option/portoption.py:41 -msgid "port" -msgstr "" - -#: tiramisu/option/portoption.py:71 -msgid "inconsistency in allowed range" -msgstr "" - -#: tiramisu/option/portoption.py:76 -msgid "max value is empty" -msgstr "" - -#: tiramisu/option/portoption.py:91 -msgid "range must have two values only" -msgstr "" - -#: tiramisu/option/portoption.py:93 -msgid "first port in range must be smaller than the second one" -msgstr "" - -#: tiramisu/option/stroption.py:33 -msgid "string" -msgstr "" - -#: tiramisu/option/symlinkoption.py:44 -msgid "malformed symlinkoption must be an option for symlink {0}" -msgstr "" - -#: tiramisu/option/symlinkoption.py:60 -msgid "cannot set symlinkoption in a dynoptiondescription" -msgstr "" - -#: tiramisu/option/urloption.py:39 -msgid "URL" -msgstr "" - -#: tiramisu/option/urloption.py:91 -msgid "must start with http:// or https://" -msgstr "" - -#: tiramisu/option/urloption.py:122 -msgid "must ends with a valid resource name" -msgstr "" - -#: tiramisu/option/usernameoption.py:35 -msgid "unix username" -msgstr "" - -#: tiramisu/option/usernameoption.py:42 -msgid "unix groupname" -msgstr "" - -#: tiramisu/setting.py:302 -msgid "can't rebind {0}" -msgstr "" - -#: tiramisu/setting.py:308 -msgid "can't unbind {0}" -msgstr "" - -#: tiramisu/setting.py:515 -msgid "invalid property type {type(new_prop)} for {option_bag.option.impl_getname()} with {prop.function.__name__} function" -msgstr "" - -#: tiramisu/setting.py:521 -msgid "leader cannot have \"{new_prop}\" property" -msgstr "" - -#: tiramisu/setting.py:591 -msgid "leader cannot have \"{list(not_allowed_properties)}\" property" -msgstr "" - -#: tiramisu/setting.py:595 -msgid "a leader ({opt.impl_get_display_name()}) cannot have \"force_default_on_freeze\" or \"force_metaconfig_on_freeze\" property without \"frozen\"" -msgstr "" - -#: tiramisu/setting.py:626 -msgid "permissive must be a frozenset" -msgstr "" - -#: tiramisu/setting.py:635 -msgid "cannot add those permissives: {0}" -msgstr "" - -#: tiramisu/todict.py:352 -msgid "option {} only works when remotable is not \"none\"" -msgstr "" - -#: tiramisu/todict.py:505 -msgid "unable to transform tiramisu object to dict: {}" -msgstr "" - -#: tiramisu/todict.py:816 tiramisu/todict.py:955 -msgid "unknown form {}" -msgstr "" - -#: tiramisu/todict.py:862 -msgid "not in current area" -msgstr "" - -#: tiramisu/todict.py:883 -msgid "only multi option can have action \"add\", but \"{}\" is not a multi" -msgstr "" - -#: tiramisu/todict.py:885 -msgid "unknown action {}" -msgstr "" - -#: tiramisu/value.py:506 tiramisu/value.py:722 -msgid "set owner \"{0}\" is forbidden" -msgstr "" - -#: tiramisu/value.py:636 -msgid "index {index} is greater than the length {length} for option {option_bag.option.impl_get_display_name(with_quote=True)}" -msgstr "" - -#: tiramisu/value.py:695 -msgid "information's item not found: {0}" -msgstr "" - diff --git a/tiramisu/log.py b/tiramisu/log.py index eea35d3..504da72 100644 --- a/tiramisu/log.py +++ b/tiramisu/log.py @@ -19,12 +19,12 @@ from logging import getLogger, DEBUG, StreamHandler, Formatter import os -log = getLogger('tiramisu') -if os.environ.get('TIRAMISU_DEBUG') == 'True': # pragma: no cover +log = getLogger("tiramisu") +if os.environ.get("TIRAMISU_DEBUG") == "True": # pragma: no cover log.setLevel(DEBUG) handler = StreamHandler() handler.setLevel(DEBUG) - formatter = Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') + formatter = Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") handler.setFormatter(formatter) log.addHandler(handler) diff --git a/tiramisu/option/__init__.py b/tiramisu/option/__init__.py index 8e742d6..355cf54 100644 --- a/tiramisu/option/__init__.py +++ b/tiramisu/option/__init__.py @@ -25,7 +25,8 @@ from .dynoptiondescription import DynOptionDescription from .leadership import Leadership from .baseoption import submulti from .symlinkoption import SymLinkOption -#from .syndynoption import SynDynOption, SynDynOptionDescription, SynDynLeadership + +# from .syndynoption import SynDynOption, SynDynOptionDescription, SynDynLeadership from .option import Option from .choiceoption import ChoiceOption from .booloption import BoolOption @@ -48,12 +49,33 @@ from .macoption import MACOption from .permissionsoption import PermissionsOption -__all__ = ('Leadership', 'OptionDescription', 'DynOptionDescription', -# 'SynDynOptionDescription', 'SynDynLeadership','SynDynOption', - 'Option', 'SymLinkOption', - 'ChoiceOption', 'BoolOption', 'DateOption', - 'IntOption', 'FloatOption', 'StrOption', - 'IPOption', 'PortOption', 'NetworkOption', 'NetmaskOption', - 'BroadcastOption', 'DomainnameOption', 'EmailOption', 'URLOption', - 'UsernameOption', 'GroupnameOption', 'FilenameOption', 'PasswordOption', 'submulti', - 'RegexpOption', 'MACOption', 'PermissionsOption') +__all__ = ( + "Leadership", + "OptionDescription", + "DynOptionDescription", + # 'SynDynOptionDescription', 'SynDynLeadership','SynDynOption', + "Option", + "SymLinkOption", + "ChoiceOption", + "BoolOption", + "DateOption", + "IntOption", + "FloatOption", + "StrOption", + "IPOption", + "PortOption", + "NetworkOption", + "NetmaskOption", + "BroadcastOption", + "DomainnameOption", + "EmailOption", + "URLOption", + "UsernameOption", + "GroupnameOption", + "FilenameOption", + "PasswordOption", + "submulti", + "RegexpOption", + "MACOption", + "PermissionsOption", +) diff --git a/tiramisu/option/baseoption.py b/tiramisu/option/baseoption.py index 7396ec1..6f10ad3 100644 --- a/tiramisu/option/baseoption.py +++ b/tiramisu/option/baseoption.py @@ -36,40 +36,41 @@ submulti = 2 def valid_name(name): - """valid option name - """ + """valid option name""" if not isinstance(name, str): return False - if '.' in name: + if "." in name: return False return True -#____________________________________________________________ +# ____________________________________________________________ # class Base: - """Base use by all *Option* classes (Option, OptionDescription, SymLinkOption, ...) - """ - __slots__ = ('_name', - '_path', - '_informations', - '_subdyns', - '_properties', - '_has_dependency', - '_dependencies', - '_dependencies_information', - '_identifiers_dependencies', - '__weakref__' - ) + """Base use by all *Option* classes (Option, OptionDescription, SymLinkOption, ...)""" - def __init__(self, - name: str, - doc: str, - informations: Optional[Dict], - *, - properties=None, - is_multi: bool=False, - ) -> None: + __slots__ = ( + "_name", + "_path", + "_informations", + "_subdyns", + "_properties", + "_has_dependency", + "_dependencies", + "_dependencies_information", + "_identifiers_dependencies", + "__weakref__", + ) + + def __init__( + self, + name: str, + doc: str, + informations: Optional[Dict], + *, + properties=None, + is_multi: bool = False, + ) -> None: if not valid_name(name): raise ValueError(_('"{0}" is an invalid name for an option').format(name)) if properties is None: @@ -80,88 +81,99 @@ class Base: # if option is a multi, it cannot be 'empty' (None not allowed in the list) # and cannot have multiple time the same value # 'empty' and 'unique' are removed for follower's option - if 'notunique' not in properties: - properties = properties | {'unique'} - if 'notempty' not in properties: - properties = properties | {'empty'} - assert isinstance(properties, frozenset), _('invalid properties type {0} for {1},' - ' must be a frozenset').format(type(properties), - name) + if "notunique" not in properties: + properties = properties | {"unique"} + if "notempty" not in properties: + properties = properties | {"empty"} + assert isinstance(properties, frozenset), _( + "invalid properties type {0} for {1}," " must be a frozenset" + ).format(type(properties), name) _setattr = object.__setattr__ - _setattr(self, '_name', name) - _setattr(self, '_informations', {'doc': doc}) + _setattr(self, "_name", name) + _setattr(self, "_informations", {"doc": doc}) for prop in properties: if not isinstance(prop, str): if not isinstance(prop, Calculation): - raise ValueError(_('invalid property type {0} for {1}, must be a string or a ' - 'Calculation').format(type(prop), name)) + raise ValueError( + _( + "invalid property type {0} for {1}, must be a string or a " + "Calculation" + ).format(type(prop), name) + ) for param in chain(prop.params.args, prop.params.kwargs.values()): if isinstance(param, ParamOption): param.option._add_dependency(self) if properties: - _setattr(self, '_properties', properties) + _setattr(self, "_properties", properties) self.set_informations(informations) - def set_informations(self, - informations: Optional[Dict], - ) -> None: + def set_informations( + self, + informations: Optional[Dict], + ) -> None: if not informations: return for key, value in informations.items(): - self._set_information(key, - value, - ) + self._set_information( + key, + value, + ) - def impl_has_dependency(self, - self_is_dep: bool=True, - ) -> bool: - """this has dependency - """ + def impl_has_dependency( + self, + self_is_dep: bool = True, + ) -> bool: + """this has dependency""" if self_is_dep is True: - return getattr(self, '_has_dependency', False) - return hasattr(self, '_dependencies') + return getattr(self, "_has_dependency", False) + return hasattr(self, "_dependencies") - def get_dependencies(self, - context_od, - ) -> Set[str]: - ret = set(getattr(self, '_dependencies', STATIC_TUPLE)) - if context_od and hasattr(context_od, '_dependencies'): + def get_dependencies( + self, + context_od, + ) -> Set[str]: + ret = set(getattr(self, "_dependencies", STATIC_TUPLE)) + if context_od and hasattr(context_od, "_dependencies"): # add options that have context is set in calculation - return set(context_od._dependencies) | ret # pylint: disable=protected-access + return ( + set(context_od._dependencies) | ret + ) # pylint: disable=protected-access return ret def _get_identifiers_dependencies(self) -> Set[str]: - return getattr(self, '_identifiers_dependencies', STATIC_TUPLE) + return getattr(self, "_identifiers_dependencies", STATIC_TUPLE) - def _add_dependency(self, - option, - is_identifier: bool=False, - ) -> None: + def _add_dependency( + self, + option, + is_identifier: bool = False, + ) -> None: woption = weakref.ref(option) options = self.get_dependencies(None) options.add(woption) - self._dependencies = tuple(options) # pylint: disable=attribute-defined-outside-init + self._dependencies = tuple( + options + ) # pylint: disable=attribute-defined-outside-init if is_identifier: options = list(self._get_identifiers_dependencies()) options.append(woption) - self._identifiers_dependencies = tuple(options) # pylint: disable=attribute-defined-outside-init + self._identifiers_dependencies = tuple( + options + ) # pylint: disable=attribute-defined-outside-init def impl_is_optiondescription(self) -> bool: - """option is an option description - """ + """option is an option description""" return False def impl_is_dynoptiondescription(self) -> bool: - """option is not a dyn option description - """ + """option is not a dyn option description""" return False def impl_is_sub_dyn_optiondescription(self): return False def impl_getname(self) -> str: - """get name - """ + """get name""" return self._name # pylint: disable=no-member def _set_readonly(self) -> None: @@ -170,40 +182,39 @@ class Base: dico = self._informations # pylint: disable=no-member keys = tuple(dico.keys()) if len(keys) == 1: - dico = dico['doc'] + dico = dico["doc"] else: dico = tuple([keys, tuple(dico.values())]) - _setattr(self, '_informations', dico) - extra = getattr(self, '_extra', None) + _setattr(self, "_informations", dico) + extra = getattr(self, "_extra", None) if extra is not None: - _setattr(self, '_extra', tuple([tuple(extra.keys()), tuple(extra.values())])) + _setattr( + self, "_extra", tuple([tuple(extra.keys()), tuple(extra.values())]) + ) def impl_is_readonly(self) -> str: - """the option is readonly - """ - return hasattr(self, '_path') + """the option is readonly""" + return hasattr(self, "_path") def impl_getproperties(self) -> FrozenSet[str]: - """get properties - """ - return getattr(self, '_properties', frozenset()) + """get properties""" + return getattr(self, "_properties", frozenset()) - def _setsubdyn(self, - subdyn, - ) -> None: + def _setsubdyn( + self, + subdyn, + ) -> None: # pylint: disable=attribute-defined-outside-init - if getattr(self, '_subdyns', None) is None: + if getattr(self, "_subdyns", None) is None: self._subdyns = [] self._subdyns.append(subdyn) def issubdyn(self) -> bool: - """is sub dynoption - """ - return getattr(self, '_subdyns', None) is not None + """is sub dynoption""" + return getattr(self, "_subdyns", None) is not None def getsubdyn(self): - """get sub dynoption - """ + """get sub dynoption""" return self._subdyns[0]() def get_sub_dyns(self): @@ -211,11 +222,12 @@ class Base: # ____________________________________________________________ # information - def _get_information(self, - subconfig: "SubConfig", - key: str, - default: Any=undefined, - ) -> Any: + def _get_information( + self, + subconfig: "SubConfig", + key: str, + default: Any = undefined, + ) -> Any: """retrieves one information's item :param key: the item string (ex: "help") @@ -225,7 +237,7 @@ class Base: if key in dico[0]: return dico[1][dico[0].index(key)] elif isinstance(dico, str): - if key == 'doc': + if key == "doc": return dico elif isinstance(dico, dict): if key in dico: @@ -233,13 +245,17 @@ class Base: if default is not undefined: return default # pylint: disable=no-member - raise ValueError(_(f'information\'s item for {self.impl_get_display_name(subconfig, with_quote=True)} ' - f'not found: "{key}"')) + raise ValueError( + _('information\'s item for {0} not found: "{1}"').format( + self.impl_get_display_name(subconfig, with_quote=True), key + ) + ) - def _set_information(self, - key: str, - value: Any, - ) -> None: + def _set_information( + self, + key: str, + value: Any, + ) -> None: """updates the information's attribute (which is a dictionary) @@ -247,20 +263,20 @@ class Base: :param value: information's value (ex: "the help string") """ if self.impl_is_readonly(): - raise AttributeError(_("'{0}' ({1}) object attribute '{2}' is" - " read-only").format(self.__class__.__name__, - self, - key)) + raise AttributeError( + _("'{0}' ({1}) object attribute '{2}' is" " read-only").format( + self.__class__.__name__, self, key + ) + ) self._informations[key] = value # pylint: disable=no-member def _list_information(self) -> Any: - """get the list of information keys - """ + """get the list of information keys""" dico = self._informations # pylint: disable=no-member if isinstance(dico, tuple): return list(dico[0]) if not isinstance(dico, dict): - return ['doc'] + return ["doc"] # it's a dict return list(dico.keys()) @@ -270,12 +286,14 @@ class BaseOption(Base): in options that have to be set only once, it is of course done in the __setattr__ method """ - __slots__ = ('_display_name_function',) - def __setattr__(self, - name: str, - value: Any, - ) -> Any: + __slots__ = ("_display_name_function",) + + def __setattr__( + self, + name: str, + value: Any, + ) -> Any: """set once and only once some attributes in the option, like `_name`. `_name` cannot be changed once the option is pushed in the :class:`tiramisu.option.OptionDescription`. @@ -286,72 +304,78 @@ class BaseOption(Base): """ # never change _name in an option or attribute when object is readonly if self.impl_is_readonly(): - raise AttributeError(_('"{}" ({}) object attribute "{}" is' - ' read-only').format(self.__class__.__name__, - self.impl_get_display_name(None), - name)) + raise AttributeError( + _('"{}" ({}) object attribute "{}" is' " read-only").format( + self.__class__.__name__, self.impl_get_display_name(None), name + ) + ) super().__setattr__(name, value) def impl_getpath(self) -> str: - """get the path of the option - """ + """get the path of the option""" try: return self._path except AttributeError as err: - raise AttributeError(_(f'{self.impl_get_display_name(None, with_quote=True)} not part of any Config')) \ - from err + raise AttributeError( + _("{0} not part of any Config").format( + self.impl_get_display_name(None, with_quote=True) + ) + ) from err - def impl_get_display_name(self, - subconfig: "SubConfig", - *, - with_quote: bool=False, - ) -> str: - """get display name - """ - if hasattr(self, '_display_name_function'): - return self._display_name_function(self, - subconfig, - with_quote=with_quote, - ) - name = self._get_information(subconfig, 'doc', None) - if name is None or name == '': + def impl_get_display_name( + self, + subconfig: "SubConfig", + *, + with_quote: bool = False, + ) -> str: + """get display name""" + if hasattr(self, "_display_name_function"): + return self._display_name_function( + self, + subconfig, + with_quote=with_quote, + ) + name = self._get_information(subconfig, "doc", None) + if name is None or name == "": if subconfig and subconfig.path: - name = subconfig.path.rsplit('.', 1)[-1] + name = subconfig.path.rsplit(".", 1)[-1] else: name = self._name if with_quote: return f'"{name}"' return name - def reset_cache(self, - path: str, - config_bag: 'OptionBag', - resetted_opts: List[Base], # pylint: disable=unused-argument - ) -> None: - """reset cache - """ + def reset_cache( + self, + path: str, + config_bag: "OptionBag", + resetted_opts: List[Base], # pylint: disable=unused-argument + ) -> None: + """reset cache""" context = config_bag.context context.properties_cache.delcache(path) - context._impl_permissives_cache.delcache(path) # pylint: disable=protected-access + context._impl_permissives_cache.delcache( + path + ) # pylint: disable=protected-access if not self.impl_is_optiondescription(): - context.get_values_cache().delcache(path) # pylint: disable=protected-access + context.get_values_cache().delcache( + path + ) # pylint: disable=protected-access def impl_is_symlinkoption(self) -> bool: - """the option is not a symlinkoption - """ + """the option is not a symlinkoption""" return False def get_dependencies_information(self) -> List[str]: - """get dependencies information - """ - return getattr(self, '_dependencies_information', {}) + """get dependencies information""" + return getattr(self, "_dependencies_information", {}) - def value_dependencies(self, - value: Any, - is_identifier: bool=False, - ) -> Any: - """parse dependancies to add dependencies - """ + def value_dependencies( + self, + value: Any, + is_identifier: bool = False, + ) -> Any: + """parse dependancies to add dependencies""" if isinstance(value, list): for val in value: if isinstance(value, list): @@ -361,12 +385,12 @@ class BaseOption(Base): elif isinstance(value, Calculation): self.value_dependency(value, is_identifier) - def value_dependency(self, - value: Any, - is_identifier: bool=False, - ) -> Any: - """parse dependancy to add dependencies - """ + def value_dependency( + self, + value: Any, + is_identifier: bool = False, + ) -> Any: + """parse dependancy to add dependencies""" for param in chain(value.params.args, value.params.kwargs.values()): if isinstance(param, ParamOption): # pylint: disable=protected-access @@ -382,7 +406,9 @@ class BaseOption(Base): else: param.set_self_option(self) opt = None - if not getattr(dest, '_dependencies_information', {}): + if not getattr(dest, "_dependencies_information", {}): dest._dependencies_information = {None: []} dest._dependencies_information[None].append(param) - dest._dependencies_information.setdefault(param.information_name, []).append(opt) + dest._dependencies_information.setdefault( + param.information_name, [] + ).append(opt) diff --git a/tiramisu/option/booloption.py b/tiramisu/option/booloption.py index 9b53082..9b48705 100644 --- a/tiramisu/option/booloption.py +++ b/tiramisu/option/booloption.py @@ -26,15 +26,15 @@ from .option import Option class BoolOption(Option): - """represents a choice between ``True`` and ``False`` - """ - __slots__ = tuple() - _type = 'boolean' + """represents a choice between ``True`` and ``False``""" - def validate(self, - value: bool, - ) -> None: - """validate value - """ + __slots__ = tuple() + _type = "boolean" + + def validate( + self, + value: bool, + ) -> None: + """validate value""" if not isinstance(value, bool): raise ValueError() diff --git a/tiramisu/option/broadcastoption.py b/tiramisu/option/broadcastoption.py index 79a69e7..e294a7b 100644 --- a/tiramisu/option/broadcastoption.py +++ b/tiramisu/option/broadcastoption.py @@ -27,21 +27,21 @@ from .option import Option class BroadcastOption(Option): - """represents the choice of a broadcast - """ - __slots__ = tuple() - _type = 'broadcast address' + """represents the choice of a broadcast""" - def validate(self, - value: str, - ) -> None: - """validate - """ + __slots__ = tuple() + _type = "broadcast address" + + def validate( + self, + value: str, + ) -> None: + """validate""" if not isinstance(value, str): - raise ValueError(_('invalid string')) - if value.count('.') != 3: + raise ValueError(_("invalid string")) + if value.count(".") != 3: raise ValueError() - for val in value.split('.'): + for val in value.split("."): if val.startswith("0") and len(val) > 1: raise ValueError() try: diff --git a/tiramisu/option/choiceoption.py b/tiramisu/option/choiceoption.py index ae78c8e..797dd2e 100644 --- a/tiramisu/option/choiceoption.py +++ b/tiramisu/option/choiceoption.py @@ -34,73 +34,73 @@ class ChoiceOption(Option): The option can also have the value ``None`` """ + __slots__ = tuple() - _type = 'choice' - - def __init__(self, - name, - doc, - values, - *args, - **kwargs): + _type = "choice" + def __init__(self, name, doc, values, *args, **kwargs): """ :param values: is a list of values the option can possibly take """ if not isinstance(values, (Calculation, tuple)): - raise TypeError(_('values must be a tuple or a calculation for {0}' - ).format(name)) + raise TypeError( + _("values must be a tuple or a calculation for {0}").format(name) + ) self._choice_values = values - super().__init__(name, - doc, - *args, - **kwargs) + super().__init__(name, doc, *args, **kwargs) - def impl_get_values(self, - subconfig: "SubConfig", - uncalculated: bool=False, - ): - """get values allowed by option - """ + def impl_get_values( + self, + subconfig: "SubConfig", + uncalculated: bool = False, + ): + """get values allowed by option""" choices = self._choice_values if isinstance(choices, tuple): choices = list(choices) if uncalculated: return choices - values = get_calculated_value(subconfig, - choices, - )[0] - + values = get_calculated_value( + subconfig, + choices, + )[0] + if values != undefined and not isinstance(values, (list, tuple)): - raise ConfigError(_('the calculated values "{0}" for "{1}" is not a list' - '').format(values, self.impl_getname())) + raise ConfigError( + _('the calculated values "{0}" for "{1}" is not a list' "").format( + values, self.impl_getname() + ) + ) return values - def validate(self, - value: Any, - ) -> None: - """nothing to valide - """ + def validate( + self, + value: Any, + ) -> None: + """nothing to valide""" - def validate_with_option(self, - value: Any, - subconfig: "SubConfig", - loaded: bool, - ) -> None: + def validate_with_option( + self, + value: Any, + subconfig: "SubConfig", + loaded: bool, + ) -> None: if loaded and isinstance(self._choice_values, Calculation): return values = self.impl_get_values(subconfig) self.validate_values(value, values) - def validate_values(self, - value, - values, - ) -> None: - """validate values - """ + def validate_values( + self, + value, + values, + ) -> None: + """validate values""" if values is not undefined and value not in values: if len(values) == 1: - raise ValueError(_('only "{0}" is allowed' - '').format(values[0])) - raise ValueError(_('only {0} are allowed' - '').format(display_list(values, add_quote=True))) + raise ValueError(_('only "{0}" is allowed' "").format(values[0])) + raise ValueError( + _("only {0} are allowed" "").format( + display_list(values, add_quote=True) + ) + ) diff --git a/tiramisu/option/dateoption.py b/tiramisu/option/dateoption.py index 3cf64d3..59343e1 100644 --- a/tiramisu/option/dateoption.py +++ b/tiramisu/option/dateoption.py @@ -27,13 +27,12 @@ from .stroption import StrOption class DateOption(StrOption): - """represents the choice of a date - """ - __slots__ = tuple() - _type = 'date' + """represents the choice of a date""" - def validate(self, - value: str) -> None: + __slots__ = tuple() + _type = "date" + + def validate(self, value: str) -> None: super().validate(value) try: datetime.strptime(value, "%Y-%m-%d") diff --git a/tiramisu/option/domainnameoption.py b/tiramisu/option/domainnameoption.py index b7cfb2b..756c515 100644 --- a/tiramisu/option/domainnameoption.py +++ b/tiramisu/option/domainnameoption.py @@ -39,126 +39,139 @@ class DomainnameOption(StrOption): domainname: fqdn: with tld, not supported yet """ - __slots__ = tuple() - _type = 'domain name' - def __init__(self, - name: str, - doc: str, - *args, - allow_ip: bool=False, - allow_cidr_network: bool=False, - type: str='domainname', - allow_without_dot: bool=False, - allow_startswith_dot: bool=False, - **kwargs, - ) -> None: + __slots__ = tuple() + _type = "domain name" + + def __init__( + self, + name: str, + doc: str, + *args, + allow_ip: bool = False, + allow_cidr_network: bool = False, + type: str = "domainname", + allow_without_dot: bool = False, + allow_startswith_dot: bool = False, + **kwargs, + ) -> None: # pylint: disable=too-many-branches,too-many-locals,too-many-arguments - if type not in ['netbios', 'hostname', 'domainname']: - raise ValueError(_('unknown type {0} for hostname').format(type)) - extra = {'_dom_type': type} + if type not in ["netbios", "hostname", "domainname"]: + raise ValueError(_("unknown type {0} for hostname").format(type)) + extra = {"_dom_type": type} if not isinstance(allow_ip, bool): - raise ValueError(_('allow_ip must be a boolean')) + raise ValueError(_("allow_ip must be a boolean")) if not isinstance(allow_cidr_network, bool): - raise ValueError(_('allow_cidr_network must be a boolean')) + raise ValueError(_("allow_cidr_network must be a boolean")) if not isinstance(allow_without_dot, bool): - raise ValueError(_('allow_without_dot must be a boolean')) + raise ValueError(_("allow_without_dot must be a boolean")) if not isinstance(allow_startswith_dot, bool): - raise ValueError(_('allow_startswith_dot must be a boolean')) - extra['_allow_without_dot'] = allow_without_dot - if type == 'domainname': + raise ValueError(_("allow_startswith_dot must be a boolean")) + extra["_allow_without_dot"] = allow_without_dot + if type == "domainname": if allow_without_dot: min_time = 0 else: min_time = 1 - regexp = r'((?!-)[a-z0-9-]{{{1},{0}}}\.){{{1},}}[a-z0-9-]{{1,{0}}}'.format(self._get_len(type), min_time) + regexp = r"((?!-)[a-z0-9-]{{{1},{0}}}\.){{{1},}}[a-z0-9-]{{1,{0}}}".format( + self._get_len(type), min_time + ) else: - regexp = r'((?!-)[a-z0-9-]{{1,{0}}})'.format(self._get_len(type)) - msg = _('must start with lowercase characters followed by lowercase characters, number, "-" and "." characters are allowed') - msg_warning = _('must start with lowercase characters followed by lowercase characters, number, "-" and "." characters are recommanded') + regexp = r"((?!-)[a-z0-9-]{{1,{0}}})".format(self._get_len(type)) + msg = _( + 'must start with lowercase characters followed by lowercase characters, number, "-" and "." characters are allowed' + ) + msg_warning = _( + 'must start with lowercase characters followed by lowercase characters, number, "-" and "." characters are recommanded' + ) if allow_ip: - msg = _('could be a IP, otherwise {}').format(msg) - msg_warning = _('could be a IP, otherwise {}').format(msg_warning) + msg = _("could be a IP, otherwise {}").format(msg) + msg_warning = _("could be a IP, otherwise {}").format(msg_warning) if not allow_cidr_network: - regexp = r'(?:{0}|(?:(?:(?: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]?)))'.format(regexp) + regexp = r"(?:{0}|(?:(?:(?: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]?)))".format( + regexp + ) else: - regexp = r'(?:{0}|(?:(?:(?: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]?)/[0-9][0-9]))'.format(regexp) - regexp = r'^{0}$'.format(regexp) - extra['_domain_re'] = re.compile(regexp) - extra['_domain_re_message'] = msg - extra['_domain_re_message_warning'] = msg_warning - extra['_has_upper'] = re.compile('[A-Z]') + regexp = r"(?:{0}|(?:(?:(?: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]?)/[0-9][0-9]))".format( + regexp + ) + regexp = r"^{0}$".format(regexp) + extra["_domain_re"] = re.compile(regexp) + extra["_domain_re_message"] = msg + extra["_domain_re_message_warning"] = msg_warning + extra["_has_upper"] = re.compile("[A-Z]") if allow_ip: - extra['_ip'] = IPOption(name, - doc, - ) - extra['_allow_ip'] = allow_ip + extra["_ip"] = IPOption( + name, + doc, + ) + extra["_allow_ip"] = allow_ip if allow_cidr_network: - extra['_network'] = NetworkOption(name, - doc, - cidr=True, - ) - extra['_allow_cidr_network'] = allow_cidr_network - extra['_allow_startswith_dot'] = allow_startswith_dot + extra["_network"] = NetworkOption( + name, + doc, + cidr=True, + ) + extra["_allow_cidr_network"] = allow_cidr_network + extra["_allow_startswith_dot"] = allow_startswith_dot - super().__init__(name, - doc, - *args, - extra=extra, - **kwargs, - ) + super().__init__( + name, + doc, + *args, + extra=extra, + **kwargs, + ) def _get_len(self, type_): - if type_ == 'netbios': + if type_ == "netbios": return 15 return 63 - def _validate_domain(self, - value: str) -> None: + def _validate_domain(self, value: str) -> None: def _valid_length(val): if len(val) < 1: raise ValueError(_("invalid length (min 1)")) if len(val) > part_name_length: - raise ValueError(_("invalid length (max {0})" - "").format(part_name_length)) + raise ValueError( + _("invalid length (max {0})" "").format(part_name_length) + ) - part_name_length = self._get_len(self.impl_get_extra('_dom_type')) - if self.impl_get_extra('_dom_type') == 'domainname': - if not self.impl_get_extra('_allow_without_dot') and not "." in value: + part_name_length = self._get_len(self.impl_get_extra("_dom_type")) + if self.impl_get_extra("_dom_type") == "domainname": + if not self.impl_get_extra("_allow_without_dot") and not "." in value: raise ValueError(_("must have dot")) if len(value) > 255: raise ValueError(_("invalid length (max 255)")) - if self.impl_get_extra('_allow_startswith_dot') and value.startswith('.'): + if self.impl_get_extra("_allow_startswith_dot") and value.startswith("."): val = value[1:] else: val = value - if val.endswith('.'): + if val.endswith("."): nval = val[:-1] else: nval = val - for dom in nval.split('.'): + for dom in nval.split("."): _valid_length(dom) else: _valid_length(value) - def _validate_ip_network(self, - value: str) -> None: - allow_ip = self.impl_get_extra('_allow_ip') - allow_cidr_network = self.impl_get_extra('_allow_cidr_network') + def _validate_ip_network(self, value: str) -> None: + allow_ip = self.impl_get_extra("_allow_ip") + allow_cidr_network = self.impl_get_extra("_allow_cidr_network") if allow_ip is False and allow_cidr_network is False: - raise ValueError(_('must not be an IP')) + raise ValueError(_("must not be an IP")) if allow_ip is True: try: - self.impl_get_extra('_ip').validate(value) + self.impl_get_extra("_ip").validate(value) return except ValueError as err: if allow_cidr_network is False: raise err if allow_cidr_network is True: - self.impl_get_extra('_network').validate(value) + self.impl_get_extra("_network").validate(value) - def validate(self, - value: str) -> None: + def validate(self, value: str) -> None: super().validate(value) try: # check if it's an IP or network @@ -168,42 +181,40 @@ class DomainnameOption(StrOption): else: self._validate_ip_network(value) - def _second_level_validation_domain(self, - value: str, - warnings_only: bool) -> None: - if self.impl_get_extra('_has_upper').search(value): - raise ValueError(_('some characters are uppercase')) - if self.impl_get_extra('_allow_startswith_dot') and value.startswith('.'): + def _second_level_validation_domain(self, value: str, warnings_only: bool) -> None: + if self.impl_get_extra("_has_upper").search(value): + raise ValueError(_("some characters are uppercase")) + if self.impl_get_extra("_allow_startswith_dot") and value.startswith("."): val = value[1:] else: val = value - if val.endswith('.'): + if val.endswith("."): nval = val[:-1] else: nval = val - if not self.impl_get_extra('_domain_re').search(nval): + if not self.impl_get_extra("_domain_re").search(nval): if warnings_only: - raise ValueError(self.impl_get_extra('_domain_re_message_warning')) - raise ValueError(self.impl_get_extra('_domain_re_message')) + raise ValueError(self.impl_get_extra("_domain_re_message_warning")) + raise ValueError(self.impl_get_extra("_domain_re_message")) - def _second_level_validation_ip_network(self, - value: str, - warnings_only: bool) -> None: - allow_ip = self.impl_get_extra('_allow_ip') - allow_cidr_network = self.impl_get_extra('_allow_cidr_network') + def _second_level_validation_ip_network( + self, value: str, warnings_only: bool + ) -> None: + allow_ip = self.impl_get_extra("_allow_ip") + allow_cidr_network = self.impl_get_extra("_allow_cidr_network") # it's an IP so validate with IPOption if allow_ip is True and allow_cidr_network is False: try: - self.impl_get_extra('_ip').second_level_validation(value, warnings_only) + self.impl_get_extra("_ip").second_level_validation(value, warnings_only) return except ValueError as err: raise err if allow_cidr_network is True: - self.impl_get_extra('_network').second_level_validation(value, warnings_only) + self.impl_get_extra("_network").second_level_validation( + value, warnings_only + ) - def second_level_validation(self, - value: str, - warnings_only: bool) -> None: + def second_level_validation(self, value: str, warnings_only: bool) -> None: try: # check if it's an IP or network ip_interface(value) diff --git a/tiramisu/option/dynoptiondescription.py b/tiramisu/option/dynoptiondescription.py index 724f2f4..47f8dba 100644 --- a/tiramisu/option/dynoptiondescription.py +++ b/tiramisu/option/dynoptiondescription.py @@ -35,27 +35,32 @@ from ..error import ConfigError from ..autolib import Calculation, get_calculated_value -NAME_REGEXP = re.compile(r'^[a-zA-Z\d\-_]*$') -class DynOptionDescription(OptionDescription): - """dyn option description - """ - __slots__ = ('_identifiers', - '_subdyns', - ) +NAME_REGEXP = re.compile(r"^[a-zA-Z\d\-_]*$") - def __init__(self, - name: str, - doc: str, - children: List[BaseOption], - identifiers: Calculation, - **kwargs, - ) -> None: + +class DynOptionDescription(OptionDescription): + """dyn option description""" + + __slots__ = ( + "_identifiers", + "_subdyns", + ) + + def __init__( + self, + name: str, + doc: str, + children: List[BaseOption], + identifiers: Calculation, + **kwargs, + ) -> None: # pylint: disable=too-many-arguments - super().__init__(name, - doc, - children, - **kwargs, - ) + super().__init__( + name, + doc, + children, + **kwargs, + ) # check children + set relation to this dynoptiondescription wself = weakref.ref(self) for child in children: @@ -64,75 +69,86 @@ class DynOptionDescription(OptionDescription): self.value_dependencies(identifiers, is_identifier=True) self._identifiers = identifiers - def convert_identifier_to_path(self, - identifier: Any, - ) -> str: - """convert identifier to use it to a path - """ + def convert_identifier_to_path( + self, + identifier: Any, + ) -> str: + """convert identifier to use it to a path""" if identifier is None: return None if not isinstance(identifier, str): identifier = str(identifier) - if '.' in identifier: - identifier = identifier.replace('.', '_') + if "." in identifier: + identifier = identifier.replace(".", "_") return identifier def impl_is_dynoptiondescription(self) -> bool: return True - def option_is_self(self, - option, - ) -> bool: + def option_is_self( + self, + option, + ) -> bool: return option == self def impl_getname(self, identifier=None) -> str: - """get name - """ + """get name""" name = super().impl_getname() if identifier is None: return name path_identifier = self.convert_identifier_to_path(identifier) return name + path_identifier - def get_identifiers(self, - parent: 'SubConfig', - *, - uncalculated: bool=False, - ) -> List[str]: - """get dynamic identifiers - """ - subconfig = parent.get_child(self, - None, - False, - properties=None, - ) + def get_identifiers( + self, + parent: "SubConfig", + *, + uncalculated: bool = False, + ) -> List[str]: + """get dynamic identifiers""" + subconfig = parent.get_child( + self, + None, + False, + properties=None, + ) identifiers = self._identifiers if isinstance(identifiers, list): identifiers = identifiers.copy() if uncalculated: return identifiers - values = get_calculated_value(subconfig, - identifiers, - validate_properties=False, - )[0] + values = get_calculated_value( + subconfig, + identifiers, + validate_properties=False, + )[0] if values is None: values = [] values_ = [] if __debug__: if not isinstance(values, list): - raise ValueError(_('DynOptionDescription identifiers for ' - f'option {self.impl_get_display_name(subconfig, with_quote=True)}, is not ' - f'a list ({values})')) + raise ValueError( + _( + "DynOptionDescription identifiers for option {0}, is not a list ({1})" + ).format( + self.impl_get_display_name(subconfig, with_quote=True), values + ) + ) for val in values: cval = self.convert_identifier_to_path(val) if not isinstance(cval, str) or re.match(NAME_REGEXP, cval) is None: if __debug__ and cval is not None: - raise ValueError(_('invalid identifier "{}" for option {}' - '').format(cval, - self.impl_get_display_name(subconfig, with_quote=True))) + raise ValueError( + _('invalid identifier "{}" for option {}' "").format( + cval, self.impl_get_display_name(subconfig, with_quote=True) + ) + ) else: values_.append(val) if __debug__ and len(values_) > len(set(values_)): - raise ValueError(_(f'DynOptionDescription "{self._name}" identifiers return a list with ' - f'same values "{values_}"''')) + raise ValueError( + _( + 'DynOptionDescription "{0}" identifiers return a list with same values "{1}"' + ).format(self._name, values_) + ) return values_ diff --git a/tiramisu/option/emailoption.py b/tiramisu/option/emailoption.py index b5c3ab9..48dc0cf 100644 --- a/tiramisu/option/emailoption.py +++ b/tiramisu/option/emailoption.py @@ -27,8 +27,10 @@ from .stroption import RegexpOption class EmailOption(RegexpOption): - """represents a choice of an email - """ + """represents a choice of an email""" + __slots__ = tuple() - _regexp = re.compile(r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$") - _type = 'email address' + _regexp = re.compile( + r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$" + ) + _type = "email address" diff --git a/tiramisu/option/filenameoption.py b/tiramisu/option/filenameoption.py index dfe69d9..bfcf0e8 100644 --- a/tiramisu/option/filenameoption.py +++ b/tiramisu/option/filenameoption.py @@ -28,45 +28,54 @@ from .stroption import StrOption class FilenameOption(StrOption): - """validate file or directory name - """ + """validate file or directory name""" + __slots__ = tuple() - _type = 'file name' + _type = "file name" - def __init__(self, - name: str, - *args, - allow_relative=False, - test_existence=False, - types=['file', 'directory'], - **kwargs): + def __init__( + self, + name: str, + *args, + allow_relative=False, + test_existence=False, + types=["file", "directory"], + **kwargs, + ): if not isinstance(types, list): - raise ValueError(_(f'types parameter must be a list, not "{types}" for "{name}"')) + raise ValueError( + _('types parameter must be a list, not "{0}" for "{1}"').format( + types, name + ) + ) for typ in types: - if typ not in ['file', 'directory']: + if typ not in ["file", "directory"]: raise ValueError(f'unknown type "{typ}" for "{name}"') - extra = {'_allow_relative': allow_relative, - '_test_existence': test_existence, - '_types': types, - } - super().__init__(name, - *args, - extra=extra, - **kwargs) + extra = { + "_allow_relative": allow_relative, + "_test_existence": test_existence, + "_types": types, + } + super().__init__(name, *args, extra=extra, **kwargs) - def validate(self, - value: str, - ) -> None: + def validate( + self, + value: str, + ) -> None: super().validate(value) - if not self.impl_get_extra('_allow_relative') and not value.startswith('/'): + if not self.impl_get_extra("_allow_relative") and not value.startswith("/"): raise ValueError(_('must starts with "/"')) - if value is not None and self.impl_get_extra('_test_existence'): - types = self.impl_get_extra('_types') + if value is not None and self.impl_get_extra("_test_existence"): + types = self.impl_get_extra("_types") file = Path(value) found = False - if 'file' in types and file.is_file(): + if "file" in types and file.is_file(): found = True - if not found and 'directory' in types and file.is_dir(): + if not found and "directory" in types and file.is_dir(): found = True if not found: - raise ValueError(_(f'cannot find {display_list(types, separator="or")} "{value}"')) + raise ValueError( + _('cannot find {0} "{1}"').format( + display_list(types, separator="or"), value + ) + ) diff --git a/tiramisu/option/floatoption.py b/tiramisu/option/floatoption.py index 6b2c09d..9507baa 100644 --- a/tiramisu/option/floatoption.py +++ b/tiramisu/option/floatoption.py @@ -26,12 +26,11 @@ from .option import Option class FloatOption(Option): - """represents a choice of a floating point number - """ - __slots__ = tuple() - _type = 'float' + """represents a choice of a floating point number""" - def validate(self, - value: float) -> None: + __slots__ = tuple() + _type = "float" + + def validate(self, value: float) -> None: if not isinstance(value, float): raise ValueError() diff --git a/tiramisu/option/intoption.py b/tiramisu/option/intoption.py index 2e95fc0..18d3952 100644 --- a/tiramisu/option/intoption.py +++ b/tiramisu/option/intoption.py @@ -28,40 +28,35 @@ from .option import Option class IntOption(Option): "represents a choice of an integer" __slots__ = tuple() - _type = 'integer' + _type = "integer" - def __init__(self, - *args, - min_number=None, - max_number=None, - **kwargs): + def __init__(self, *args, min_number=None, max_number=None, **kwargs): extra = {} if min_number is not None: - extra['min_number'] = min_number + extra["min_number"] = min_number if max_number is not None: - extra['max_number'] = max_number + extra["max_number"] = max_number super().__init__(*args, extra=extra, **kwargs) - def validate(self, - value: int, - ) -> None: + def validate( + self, + value: int, + ) -> None: if not isinstance(value, int): raise ValueError() - def second_level_validation(self, - value, - warnings_only): - min_number = self.impl_get_extra('min_number') + def second_level_validation(self, value, warnings_only): + min_number = self.impl_get_extra("min_number") if min_number is not None and value < min_number: if warnings_only: - msg = 'value should be equal or greater than "{0}"' + msg = _('value should be equal or greater than "{0}"') else: - msg = 'value must be equal or greater than "{0}"' - raise ValueError(_(msg).format(min_number)) - max_number = self.impl_get_extra('max_number') + msg = _('value must be equal or greater than "{0}"') + raise ValueError(msg.format(min_number)) + max_number = self.impl_get_extra("max_number") if max_number is not None and value > max_number: if warnings_only: - msg = 'value should be less than "{0}"' + msg = _('value should be less than "{0}"') else: - msg = 'value must be less than "{0}"' - raise ValueError(_(msg).format(max_number)) + msg = _('value must be less than "{0}"') + raise ValueError(msg.format(max_number)) diff --git a/tiramisu/option/ipoption.py b/tiramisu/option/ipoption.py index 88f2946..d2599c2 100644 --- a/tiramisu/option/ipoption.py +++ b/tiramisu/option/ipoption.py @@ -27,26 +27,26 @@ from .stroption import StrOption class IPOption(StrOption): - """represents the choice of an ip - """ - __slots__ = tuple() - _type = 'IP' + """represents the choice of an ip""" - def __init__(self, - *args, - private_only=False, - allow_reserved=False, - cidr=False, - extra=None, - **kwargs): + __slots__ = tuple() + _type = "IP" + + def __init__( + self, + *args, + private_only=False, + allow_reserved=False, + cidr=False, + extra=None, + **kwargs, + ): if extra is None: extra = {} - extra['_private_only'] = private_only - extra['_allow_reserved'] = allow_reserved - extra['_cidr'] = cidr - super().__init__(*args, - extra=extra, - **kwargs) + extra["_private_only"] = private_only + extra["_allow_reserved"] = allow_reserved + extra["_cidr"] = cidr + super().__init__(*args, extra=extra, **kwargs) def _validate_cidr(self, value): try: @@ -64,27 +64,24 @@ class IPOption(StrOption): except ValueError as err: raise ValueError() from err - def validate(self, - value: str) -> None: + def validate(self, value: str) -> None: super().validate(value) - if self.impl_get_extra('_cidr'): - if '/' not in value: + if self.impl_get_extra("_cidr"): + if "/" not in value: raise ValueError(_('CIDR address must have a "/"')) self._validate_cidr(value) else: self._validate_ip(value) - def second_level_validation(self, - value: str, - warnings_only: bool) -> None: + def second_level_validation(self, value: str, warnings_only: bool) -> None: ip_obj = ip_interface(value) - if not self.impl_get_extra('_allow_reserved') and ip_obj.is_reserved: + if not self.impl_get_extra("_allow_reserved") and ip_obj.is_reserved: if warnings_only: msg = _("shouldn't be reserved IP") else: msg = _("mustn't be reserved IP") raise ValueError(msg) - if self.impl_get_extra('_private_only') and not ip_obj.is_private: + if self.impl_get_extra("_private_only") and not ip_obj.is_private: if warnings_only: msg = _("should be private IP") else: diff --git a/tiramisu/option/leadership.py b/tiramisu/option/leadership.py index 8ac73a3..7c351e0 100644 --- a/tiramisu/option/leadership.py +++ b/tiramisu/option/leadership.py @@ -26,6 +26,7 @@ from typing import List, Iterator, Optional from ..i18n import _ from ..setting import groups, undefined, ALLOWED_LEADER_PROPERTIES from .optiondescription import OptionDescription + # from .syndynoption import SynDynLeadership from .baseoption import BaseOption from .option import Option @@ -34,31 +35,39 @@ from ..autolib import Calculation class Leadership(OptionDescription): - """Leadership - """ - # pylint: disable=too-many-arguments - __slots__ = ('leader', - 'followers', - ) + """Leadership""" - def __init__(self, - name: str, - doc, - children: List[BaseOption], - **kwargs, - ) -> None: - if 'group_type' in kwargs: - raise LeadershipError(_('cannot set "group_type" attribute for a Leadership')) - super().__init__(name, - doc, - children, - **kwargs, - ) + # pylint: disable=too-many-arguments + __slots__ = ( + "leader", + "followers", + ) + + def __init__( + self, + name: str, + doc, + children: List[BaseOption], + **kwargs, + ) -> None: + if "group_type" in kwargs: + raise LeadershipError( + _('cannot set "group_type" attribute for a Leadership') + ) + super().__init__( + name, + doc, + children, + **kwargs, + ) self._group_type = groups.leadership followers = [] if len(children) < 2: - raise ValueError(_('a leader and a follower are mandatories in leadership "{}"' - '').format(name)) + raise ValueError( + _( + 'a leader and a follower are mandatories in leadership "{}"' "" + ).format(name) + ) for idx, child in enumerate(children): if __debug__: self._check_child_is_valid(child, idx, children) @@ -66,34 +75,51 @@ class Leadership(OptionDescription): if __debug__: self._check_default_value(child) # remove empty property for follower - child._properties = frozenset(child._properties - {'empty', 'unique'}) + child._properties = frozenset(child._properties - {"empty", "unique"}) followers.append(child) child._add_dependency(self) child._leadership = weakref.ref(self) if __debug__: leader = children[0] for prop in leader.impl_getproperties(): - if prop not in ALLOWED_LEADER_PROPERTIES and not isinstance(prop, Calculation): - raise LeadershipError(_('leader cannot have "{}" property').format(prop)) + if prop not in ALLOWED_LEADER_PROPERTIES and not isinstance( + prop, Calculation + ): + raise LeadershipError( + _('leader cannot have "{}" property').format(prop) + ) - def _check_child_is_valid(self, - child: BaseOption, - index: int, - children: [BaseOption], - ) -> None: + def _check_child_is_valid( + self, + child: BaseOption, + index: int, + children: [BaseOption], + ) -> None: if child.impl_is_symlinkoption(): if not index: - raise ValueError(_('leadership {0} shall not have ' - "a symlinkoption").format(self.impl_get_display_name(None, with_quote=True))) + raise ValueError( + _("leadership {0} shall not have " "a symlinkoption").format( + self.impl_get_display_name(None, with_quote=True) + ) + ) return if not isinstance(child, Option): - raise ValueError(_('leadership {0} shall not have ' - 'a subgroup').format(self.impl_get_display_name(None, with_quote=True))) + raise ValueError( + _("leadership {0} shall not have " "a subgroup").format( + self.impl_get_display_name(None, with_quote=True) + ) + ) if not child.impl_is_multi(): - raise ValueError(_('only multi option allowed in leadership {0} but option ' - '{1} is not a multi' - '').format(self.impl_get_display_name(None, with_quote=True), - child.impl_get_display_name(None, with_quote=True))) + raise ValueError( + _( + "only multi option allowed in leadership {0} but option " + "{1} is not a multi" + "" + ).format( + self.impl_get_display_name(None, with_quote=True), + child.impl_get_display_name(None, with_quote=True), + ) + ) def _check_default_value(self, child: BaseOption): if child.impl_is_symlinkoption(): @@ -111,78 +137,84 @@ class Leadership(OptionDescription): else: calculation = isinstance(default, Calculation) if not calculation: - raise ValueError(_('not allowed default value for follower option ' - f'{child.impl_get_display_name(None, with_quote=True)} in leadership ' - f'{self.impl_get_display_name(None, with_quote=True)}')) + raise ValueError( + _( + "not allowed default value for follower option {0} in leadership {1}" + ).format( + child.impl_get_display_name(None, with_quote=True), + self.impl_get_display_name(None, with_quote=True), + ) + ) - def _setsubdyn(self, - subdyn, - ) -> None: + def _setsubdyn( + self, + subdyn, + ) -> None: for chld in self._children[1]: chld._setsubdyn(subdyn) super()._setsubdyn(subdyn) - def is_leader(self, - opt: Option, - ) -> bool: - """the option is the leader - """ + def is_leader( + self, + opt: Option, + ) -> bool: + """the option is the leader""" leader = self.get_leader() if opt.impl_is_dynsymlinkoption(): opt = opt.opt return opt == leader def get_leader(self) -> Option: - """get leader - """ + """get leader""" return self._children[1][0] def get_followers(self) -> Iterator[Option]: - """get all followers - """ + """get all followers""" for follower in self._children[1][1:]: yield follower - def in_same_leadership(self, - opt: Option, - ) -> bool: - """check if followers are in same leadership - """ + def in_same_leadership( + self, + opt: Option, + ) -> bool: + """check if followers are in same leadership""" if opt.impl_is_dynsymlinkoption(): opt = opt.opt return opt in self._children[1] def reset(self, parent: "SubConfig") -> None: - """reset follower value - """ + """reset follower value""" values = parent.config_bag.context.get_values() for follower in self.get_followers(): - subconfig_follower = parent.get_child(follower, - None, - False, - ) - values.reset(subconfig_follower, - validate=False, - ) + subconfig_follower = parent.get_child( + follower, + None, + False, + ) + values.reset( + subconfig_follower, + validate=False, + ) - def follower_force_store_value(self, - value, - subconfig: 'SubConfig', - owner, - ) -> None: - """apply force_store_value to follower - """ + def follower_force_store_value( + self, + value, + subconfig: "SubConfig", + owner, + ) -> None: + """apply force_store_value to follower""" if not value: return config_bag = subconfig.config_bag values = config_bag.context.get_values() for idx, follower in enumerate(self.get_children()): - sub_subconfig = subconfig.get_child(follower, - None, - False, - config_bag=config_bag, - ) - if 'force_store_value' not in sub_subconfig.properties: + sub_subconfig = subconfig.get_child( + follower, + None, + False, + config_bag=config_bag, + ) + if "force_store_value" not in sub_subconfig.properties: continue self_path = sub_subconfig.path if not idx: @@ -193,25 +225,27 @@ class Leadership(OptionDescription): apply_requires = False indexes = range(len(value)) for index in indexes: - i_sub_subconfig = subconfig.get_child(follower, - index, - False, - config_bag=config_bag, - ) - values.set_storage_value(self_path, - index, - values.get_value(i_sub_subconfig)[0], - owner, - ) + i_sub_subconfig = subconfig.get_child( + follower, + index, + False, + config_bag=config_bag, + ) + values.set_storage_value( + self_path, + index, + values.get_value(i_sub_subconfig)[0], + owner, + ) - def pop(self, - subconfig: 'SubConfig', - index: int, - *, - followers: Optional[List[Option]]=undefined, - ) -> None: - """pop leader value and follower's one - """ + def pop( + self, + subconfig: "SubConfig", + index: int, + *, + followers: Optional[List[Option]] = undefined, + ) -> None: + """pop leader value and follower's one""" if followers is undefined: # followers are not undefined only in SynDynLeadership followers = self.get_followers() @@ -219,51 +253,58 @@ class Leadership(OptionDescription): config_bag.remove_validation() values = config_bag.context.get_values() for follower in followers: - sub_subconfig = subconfig.parent.get_child(follower, - index, - True, - properties=set(), # do not check force_default_on_freeze - # or force_metaconfig_on_freeze - config_bag=config_bag, - ) + sub_subconfig = subconfig.parent.get_child( + follower, + index, + True, + properties=set(), # do not check force_default_on_freeze + # or force_metaconfig_on_freeze + config_bag=config_bag, + ) values.reduce_index(sub_subconfig) - def reset_cache(self, - path: str, - config_bag: 'ConfigBag', - resetted_opts: List[Option], - ) -> None: - self._reset_cache(path, - self.get_leader(), - self.get_followers(), - config_bag, - resetted_opts, - ) + def reset_cache( + self, + path: str, + config_bag: "ConfigBag", + resetted_opts: List[Option], + ) -> None: + self._reset_cache( + path, + self.get_leader(), + self.get_followers(), + config_bag, + resetted_opts, + ) - def _reset_cache(self, - path: str, - leader: Option, - followers: List[Option], - config_bag: 'ConfigBag', - resetted_opts: List[Option], - ) -> None: - super().reset_cache(path, - config_bag, - resetted_opts, - ) + def _reset_cache( + self, + path: str, + leader: Option, + followers: List[Option], + config_bag: "ConfigBag", + resetted_opts: List[Option], + ) -> None: + super().reset_cache( + path, + config_bag, + resetted_opts, + ) leader_path = leader.impl_getpath() if leader_path not in resetted_opts: - leader.reset_cache(leader_path, - config_bag, - resetted_opts, - ) + leader.reset_cache( + leader_path, + config_bag, + resetted_opts, + ) for follower in followers: follower_path = follower.impl_getpath() if follower_path not in resetted_opts: - follower.reset_cache(follower_path, - config_bag, - resetted_opts, - ) + follower.reset_cache( + follower_path, + config_bag, + resetted_opts, + ) def impl_is_leadership(self) -> None: return True diff --git a/tiramisu/option/macoption.py b/tiramisu/option/macoption.py index a2943dd..8b993f2 100644 --- a/tiramisu/option/macoption.py +++ b/tiramisu/option/macoption.py @@ -27,8 +27,8 @@ from .stroption import RegexpOption class MACOption(RegexpOption): - """represents the choice of a mac address - """ + """represents the choice of a mac address""" + __slots__ = tuple() _regexp = re.compile(r"^([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2})$") - _type = 'mac address' + _type = "mac address" diff --git a/tiramisu/option/netmaskoption.py b/tiramisu/option/netmaskoption.py index 976c1b5..9fa1933 100644 --- a/tiramisu/option/netmaskoption.py +++ b/tiramisu/option/netmaskoption.py @@ -26,18 +26,17 @@ from .stroption import StrOption class NetmaskOption(StrOption): - """represents the choice of a netmask - """ - __slots__ = tuple() - _type = 'netmask address' + """represents the choice of a netmask""" - def validate(self, - value: str) -> None: + __slots__ = tuple() + _type = "netmask address" + + def validate(self, value: str) -> None: super().validate(value) - for val in value.split('.'): + for val in value.split("."): if val.startswith("0") and len(val) > 1: raise ValueError() try: - ip_network(f'0.0.0.0/{value}') + ip_network(f"0.0.0.0/{value}") except ValueError as err: raise ValueError() from err diff --git a/tiramisu/option/networkoption.py b/tiramisu/option/networkoption.py index 763ec72..e06d90d 100644 --- a/tiramisu/option/networkoption.py +++ b/tiramisu/option/networkoption.py @@ -29,30 +29,24 @@ from .stroption import StrOption class NetworkOption(StrOption): "represents the choice of a network" __slots__ = tuple() - _type = 'network address' + _type = "network address" - def __init__(self, - *args, - cidr=False, - **kwargs): - extra = {'_cidr': cidr} - super().__init__(*args, - extra=extra, - **kwargs) + def __init__(self, *args, cidr=False, **kwargs): + extra = {"_cidr": cidr} + super().__init__(*args, extra=extra, **kwargs) - def validate(self, - value: str) -> None: + def validate(self, value: str) -> None: super().validate(value) - if value.count('.') != 3: + if value.count(".") != 3: raise ValueError() - cidr = self.impl_get_extra('_cidr') + cidr = self.impl_get_extra("_cidr") if cidr: - if '/' not in value: - raise ValueError(_('must use CIDR notation')) - value_ = value.split('/')[0] + if "/" not in value: + raise ValueError(_("must use CIDR notation")) + value_ = value.split("/")[0] else: value_ = value - for val in value_.split('.'): + for val in value_.split("."): if val.startswith("0") and len(val) > 1: raise ValueError() try: @@ -60,9 +54,7 @@ class NetworkOption(StrOption): except ValueError as err: raise ValueError() from err - def second_level_validation(self, - value: str, - warnings_only: bool) -> None: + def second_level_validation(self, value: str, warnings_only: bool) -> None: if ip_network(value).network_address.is_reserved: if warnings_only: msg = _("shouldn't be reserved network") diff --git a/tiramisu/option/option.py b/tiramisu/option/option.py index 290c92f..39dc11a 100644 --- a/tiramisu/option/option.py +++ b/tiramisu/option/option.py @@ -37,37 +37,43 @@ class Option(BaseOption): Reminder: an Option object is **not** a container for the value. """ - __slots__ = ('_extra', - '_warnings_only', - # multi - '_multi', - # value - '_default', - '_default_multi', - # - '_validators', - # - '_leadership', - '_choice_values', - '_choice_values_params', - ) + __slots__ = ( + "_extra", + "_warnings_only", + # multi + "_multi", + # value + "_default", + "_default_multi", + # + "_validators", + # + "_leadership", + "_choice_values", + "_choice_values_params", + ) _type = None - def __init__(self, - name: str, - doc: str, - default: Any=undefined, - default_multi: Any=None, - multi: bool=False, - validators: Optional[List[Calculation]]=None, - properties: Optional[List[str]]=None, - warnings_only: bool=False, - extra: Optional[Dict]=None, - informations: Optional[Dict]=None, - ): + + def __init__( + self, + name: str, + doc: str, + default: Any = undefined, + default_multi: Any = None, + multi: bool = False, + validators: Optional[List[Calculation]] = None, + properties: Optional[List[str]] = None, + warnings_only: bool = False, + extra: Optional[Dict] = None, + informations: Optional[Dict] = None, + ): _setattr = object.__setattr__ if not multi and default_multi is not None: - raise ValueError(_("default_multi is set whereas multi is False" - " in option: {0}").format(name)) + raise ValueError( + _( + "default_multi is set whereas multi is False" " in option: {0}" + ).format(name) + ) if default is undefined: if multi is False: default = None @@ -83,117 +89,140 @@ class Option(BaseOption): is_multi = True _multi = submulti else: - raise ValueError(_('invalid multi type "{}" for "{}"').format(multi, - name, - )) + raise ValueError( + _('invalid multi type "{}" for "{}"').format( + multi, + name, + ) + ) if _multi != 1: - _setattr(self, '_multi', _multi) + _setattr(self, "_multi", _multi) if multi is not False and default is None: default = [] - super().__init__(name, - doc, - informations, - properties=properties, - is_multi=is_multi, - ) + super().__init__( + name, + doc, + informations, + properties=properties, + is_multi=is_multi, + ) if validators is not None: if __debug__ and not isinstance(validators, list): - raise ValueError(_(f'validators must be a list of Calculation for "{name}"')) + raise ValueError( + _('validators must be a list of Calculation for "{0}"').format(name) + ) for validator in validators: if __debug__ and not isinstance(validator, Calculation): - raise ValueError(_('validators must be a Calculation for "{}"').format(name)) + raise ValueError( + _('validators must be a Calculation for "{0}"').format(name) + ) self.value_dependency(validator) self._validators = tuple(validators) if extra is not None and extra != {}: - _setattr(self, '_extra', extra) + _setattr(self, "_extra", extra) if warnings_only is True: - _setattr(self, '_warnings_only', warnings_only) + _setattr(self, "_warnings_only", warnings_only) if is_multi and default_multi is not None: + def test_multi_value(value): if isinstance(value, Calculation): return -# option_bag = OptionBag(self, -# None, -# undefined, -# properties=None, -# ) + # option_bag = OptionBag(self, + # None, + # undefined, + # properties=None, + # ) try: self.validate(value) - self.validate_with_option(value, - None, - loaded=True, - ) + self.validate_with_option( + value, + None, + loaded=True, + ) except ValueError as err: str_err = str(err) if not str_err: - raise ValueError(_('invalid default_multi value "{0}" ' - 'for option {1}').format(str(value), - self.impl_get_display_name(None, with_quote=True)) - ) from err - raise ValueError(_(f'invalid default_multi value "{value}" for option ' - f'{self.impl_get_display_name(None, with_quote=True)}, {str_err}') - ) from err + raise ValueError( + _( + 'invalid default_multi value "{0}" ' "for option {1}" + ).format( + str(value), + self.impl_get_display_name(None, with_quote=True), + ) + ) from err + raise ValueError( + _( + 'invalid default_multi value "{0}" for option {1}, {2}' + ).format( + value, + self.impl_get_display_name(None, with_quote=True), + str_err, + ) + ) from err + if _multi is submulti: if not isinstance(default_multi, Calculation): if not isinstance(default_multi, list): - raise ValueError(_('invalid default_multi value "{0}" ' - 'for option {1}, must be a list for a submulti' - '').format(str(default_multi), - self.impl_get_display_name(None, with_quote=True))) + raise ValueError( + _( + 'invalid default_multi value "{0}" ' + "for option {1}, must be a list for a submulti" + "" + ).format( + str(default_multi), + self.impl_get_display_name(None, with_quote=True), + ) + ) for value in default_multi: test_multi_value(value) else: test_multi_value(default_multi) - _setattr(self, '_default_multi', default_multi) -# option_bag = OptionBag(self, -# None, -# undefined, -# properties=None, -# ) - self.impl_validate(None, - default, - loaded=True, - ) - self.impl_validate(None, - default, - check_error=False, - loaded=True, - ) + _setattr(self, "_default_multi", default_multi) + # option_bag = OptionBag(self, + # None, + # undefined, + # properties=None, + # ) + self.impl_validate( + None, + default, + loaded=True, + ) + self.impl_validate( + None, + default, + check_error=False, + loaded=True, + ) self.value_dependencies(default) - if (is_multi and default != []) or \ - (not is_multi and default is not None): + if (is_multi and default != []) or (not is_multi and default is not None): if is_multi and isinstance(default, list): default = tuple(default) - _setattr(self, '_default', default) + _setattr(self, "_default", default) - #__________________________________________________________________________ + # __________________________________________________________________________ # option's information def impl_is_multi(self) -> bool: - """is it a multi option - """ - return getattr(self, '_multi', 1) != 1 + """is it a multi option""" + return getattr(self, "_multi", 1) != 1 def impl_is_submulti(self) -> bool: - """is it a submulti option - """ - return getattr(self, '_multi', 1) == 2 + """is it a submulti option""" + return getattr(self, "_multi", 1) == 2 def impl_is_dynsymlinkoption(self) -> bool: - """is a dynsymlinkoption? - """ + """is a dynsymlinkoption?""" return False def get_type(self) -> str: - """get the type of option - """ + """get the type of option""" return self._type def impl_getdefault(self) -> Any: - """accessing the default value - """ + """accessing the default value""" is_multi = self.impl_is_multi() - default = getattr(self, '_default', undefined) + default = getattr(self, "_default", undefined) if default is undefined: if is_multi: default = [] @@ -204,162 +233,186 @@ class Option(BaseOption): return default def impl_getdefault_multi(self) -> Any: - """accessing the default value for a multi - """ + """accessing the default value for a multi""" if self.impl_is_submulti(): default_value = [] else: default_value = None - return getattr(self, '_default_multi', default_value) + return getattr(self, "_default_multi", default_value) - def impl_get_extra(self, - key: str, - ) -> Any: - """if extra parameters are store get it - """ - extra = getattr(self, '_extra', {}) + def impl_get_extra( + self, + key: str, + ) -> Any: + """if extra parameters are store get it""" + extra = getattr(self, "_extra", {}) if isinstance(extra, tuple): if key in extra[0]: return extra[1][extra[0].index(key)] return None return extra.get(key) - #__________________________________________________________________________ + # __________________________________________________________________________ # validator - def impl_validate(self, - subconfig: Optional["SubConfig"], - value: Any, - *, - check_error: bool=True, - loaded: bool=False, - ) -> bool: + def impl_validate( + self, + subconfig: Optional["SubConfig"], + value: Any, + *, + check_error: bool = True, + loaded: bool = False, + ) -> bool: """Return True if value is really valid If not validate or invalid return it returns False """ - if check_error and subconfig and \ - not 'validator' in subconfig.config_bag.properties: + if ( + check_error + and subconfig + and not "validator" in subconfig.config_bag.properties + ): return False if subconfig: force_index = subconfig.index else: force_index = None - is_warnings_only = getattr(self, '_warnings_only', False) + is_warnings_only = getattr(self, "_warnings_only", False) def _is_not_unique(value): # if set(value) has not same length than value - if not subconfig or not check_error or \ - 'unique' not in subconfig.properties: + if not subconfig or not check_error or "unique" not in subconfig.properties: return lvalue = [val for val in value if val is not None] if len(set(lvalue)) == len(lvalue): return for idx, val in enumerate(value): - if val not in value[idx+1:]: + if val not in value[idx + 1 :]: continue - raise ValueError(_('the value "{}" is not unique' - '').format(val)) + raise ValueError(_('the value "{}" is not unique' "").format(val)) - def calculation_validator(val, - _index, - ): - for validator in getattr(self, '_validators', []): - calc_is_warnings_only = hasattr(validator, 'warnings_only') and \ - validator.warnings_only - if ((check_error and not calc_is_warnings_only) or - (not check_error and calc_is_warnings_only)): + def calculation_validator( + val, + _index, + ): + for validator in getattr(self, "_validators", []): + calc_is_warnings_only = ( + hasattr(validator, "warnings_only") and validator.warnings_only + ) + if (check_error and not calc_is_warnings_only) or ( + not check_error and calc_is_warnings_only + ): try: - kwargs = {'allow_value_error': True, - 'force_value_warning': calc_is_warnings_only, - } + kwargs = { + "allow_value_error": True, + "force_value_warning": calc_is_warnings_only, + } if _index is not None and subconfig.index == _index: lsubconfig = subconfig else: identifier = subconfig.identifiers if identifier is not None: identifier = identifier[-1] - lsubconfig = subconfig.parent.get_child(subconfig.option, - _index, - False, - properties=subconfig.properties, - identifier=identifier, - name=subconfig.path.rsplit('.', 1)[-1], - check_index=False, - ) - kwargs['orig_value'] = value + lsubconfig = subconfig.parent.get_child( + subconfig.option, + _index, + False, + properties=subconfig.properties, + identifier=identifier, + name=subconfig.path.rsplit(".", 1)[-1], + check_index=False, + ) + kwargs["orig_value"] = value - validator.execute(lsubconfig, - **kwargs, - ) + validator.execute( + lsubconfig, + **kwargs, + ) except ValueWarning as warn: - warnings.warn_explicit(ValueWarning(subconfig, - val, - _(self.get_type()), - self, - str(warn), - _index, - ), - ValueWarning, - self.__class__.__name__, 319) + warnings.warn_explicit( + ValueWarning( + subconfig, + val, + _(self.get_type()), + self, + str(warn), + _index, + ), + ValueWarning, + self.__class__.__name__, + 319, + ) - def do_validation(_value, - _index, - ): + def do_validation( + _value, + _index, + ): # if _value is None: return if isinstance(_value, list): - raise ValueError(_('which must not be a list')) + raise ValueError(_("which must not be a list")) if isinstance(_value, Calculation) and not subconfig: return # option validation if check_error: self.validate(_value) - self.validate_with_option(_value, - subconfig, - loaded=loaded, - ) + self.validate_with_option( + _value, + subconfig, + loaded=loaded, + ) # second level validation - if (check_error and not is_warnings_only) or (not check_error and is_warnings_only): + if (check_error and not is_warnings_only) or ( + not check_error and is_warnings_only + ): try: - self.second_level_validation(_value, - is_warnings_only) + self.second_level_validation(_value, is_warnings_only) except ValueError as err: if is_warnings_only: - warnings.warn_explicit(ValueWarning(subconfig, - _value, - _(self.get_type()), - self, - str(err), - _index), - ValueWarning, - self.__class__.__name__, 0) + warnings.warn_explicit( + ValueWarning( + subconfig, + _value, + _(self.get_type()), + self, + str(err), + _index, + ), + ValueWarning, + self.__class__.__name__, + 0, + ) else: raise err from err # ? if not loaded: - calculation_validator(_value, - _index, - ) + calculation_validator( + _value, + _index, + ) + val = value err_index = force_index try: if not self.impl_is_multi(): - do_validation(val, - None, - ) + do_validation( + val, + None, + ) elif force_index is not None: if self.impl_is_submulti(): if not isinstance(value, list): - raise ValueError(_('which must be a list')) + raise ValueError(_("which must be a list")) for val in value: - do_validation(val, - force_index, - ) + do_validation( + val, + force_index, + ) _is_not_unique(value) else: - do_validation(val, - force_index, - ) + do_validation( + val, + force_index, + ) elif isinstance(value, Calculation) and not subconfig: pass elif self.impl_is_submulti(): @@ -367,83 +420,79 @@ class Option(BaseOption): if isinstance(lval, Calculation): continue if not isinstance(lval, list): - raise ValueError(_('which "{}" must be a list of list' - '').format(lval)) + raise ValueError( + _('which "{}" must be a list of list' "").format(lval) + ) for val in lval: - do_validation(val, - err_index) + do_validation(val, err_index) _is_not_unique(lval) elif not isinstance(value, list): - raise ValueError(_('which must be a list')) + raise ValueError(_("which must be a list")) else: # FIXME suboptimal, not several time for whole=True! for err_index, val in enumerate(value): - do_validation(val, - err_index, - ) + do_validation( + val, + err_index, + ) _is_not_unique(value) except ValueError as err: - if not subconfig or \ - 'demoting_error_warning' not in subconfig.config_bag.properties: - raise ValueOptionError(subconfig, - val, - _(self.get_type()), - self, - str(err), - err_index) from err - warnings.warn_explicit(ValueErrorWarning(subconfig, - val, - _(self.get_type()), - self, - str(err), - err_index), - ValueErrorWarning, - self.__class__.__name__, 0) + if ( + not subconfig + or "demoting_error_warning" not in subconfig.config_bag.properties + ): + raise ValueOptionError( + subconfig, val, _(self.get_type()), self, str(err), err_index + ) from err + warnings.warn_explicit( + ValueErrorWarning( + subconfig, val, _(self.get_type()), self, str(err), err_index + ), + ValueErrorWarning, + self.__class__.__name__, + 0, + ) return False return True - def validate_with_option(self, - value: Any, - subconfig: "SubConfig", - *, - loaded: bool, - ) -> None: - """validation function with option - """ + def validate_with_option( + self, + value: Any, + subconfig: "SubConfig", + *, + loaded: bool, + ) -> None: + """validation function with option""" - def second_level_validation(self, - value: Any, - warnings_only: bool, - ) -> None: - """less import validation function - """ + def second_level_validation( + self, + value: Any, + warnings_only: bool, + ) -> None: + """less import validation function""" def impl_is_leader(self): - """check if option is a leader in a leadership - """ + """check if option is a leader in a leadership""" leadership = self.impl_get_leadership() if leadership is None: return False return leadership.is_leader(self) def impl_is_follower(self): - """check if option is a leader in a follower - """ + """check if option is a leader in a follower""" leadership = self.impl_get_leadership() if leadership is None: return False return not leadership.is_leader(self) def impl_get_leadership(self): - """get leadership - """ - leadership = getattr(self, '_leadership', None) + """get leadership""" + leadership = getattr(self, "_leadership", None) if leadership is None: return leadership - #pylint: disable=not-callable + # pylint: disable=not-callable return leadership() def validate(self, value: Any): - """option needs a validate function - """ + """option needs a validate function""" raise NotImplementedError() diff --git a/tiramisu/option/optiondescription.py b/tiramisu/option/optiondescription.py index 9045da8..b1ba72e 100644 --- a/tiramisu/option/optiondescription.py +++ b/tiramisu/option/optiondescription.py @@ -27,33 +27,34 @@ from typing import Optional, Iterator, Union, List, Dict from ..i18n import _ from ..setting import ConfigBag, groups, undefined, owners, Undefined from .baseoption import BaseOption + # from .syndynoption import SubDynOptionDescription, SynDynOptionDescription from ..error import ConfigError, ConflictError class CacheOptionDescription(BaseOption): - """manage cache for option description - """ - __slots__ = ('_cache_force_store_values', - '_cache_dependencies_information', - ) + """manage cache for option description""" + + __slots__ = ( + "_cache_force_store_values", + "_cache_dependencies_information", + ) def impl_already_build_caches(self) -> bool: - """is a readonly option? - """ + """is a readonly option?""" return self.impl_is_readonly() - def _build_cache(self, - display_name, - _consistencies=None, - _consistencies_id=0, - currpath: List[str]=None, - cache_option=None, - force_store_values=None, - dependencies_information=None, - ) -> None: - """validate options and set option has readonly option - """ + def _build_cache( + self, + display_name, + _consistencies=None, + _consistencies_id=0, + currpath: List[str] = None, + cache_option=None, + force_store_values=None, + dependencies_information=None, + ) -> None: + """validate options and set option has readonly option""" # pylint: disable=too-many-branches,too-many-arguments # _consistencies is None only when we start to build cache if _consistencies is None: @@ -69,112 +70,137 @@ class CacheOptionDescription(BaseOption): if self.impl_is_readonly(): # cache already set - raise ConfigError(_('option description seems to be part of an other ' - 'config')) + raise ConfigError( + _("option description seems to be part of an other " "config") + ) for option in self.get_children(): if __debug__: cache_option.append(option) sub_currpath = currpath + [option.impl_getname()] - subpath = '.'.join(sub_currpath) + subpath = ".".join(sub_currpath) if isinstance(option, OptionDescription): # pylint: disable=protected-access - option._build_cache(display_name, - _consistencies, - _consistencies_id, - sub_currpath, - cache_option, - force_store_values, - dependencies_information, - ) + option._build_cache( + display_name, + _consistencies, + _consistencies_id, + sub_currpath, + cache_option, + force_store_values, + dependencies_information, + ) elif not option.impl_is_symlinkoption(): informations = option.get_dependencies_information() if informations: for param in informations.pop(None): del param.self_option - for information, options in option.get_dependencies_information().items(): + for ( + information, + options, + ) in option.get_dependencies_information().items(): if None in options: - dependencies_information.setdefault(information, []).append(option) + dependencies_information.setdefault(information, []).append( + option + ) properties = option.impl_getproperties() - if 'force_store_value' in properties: + if "force_store_value" in properties: force_store_values.append(option) if option.impl_is_readonly(): - raise ConflictError(_('duplicate option: {0}').format(option)) + raise ConflictError(_("duplicate option: {0}").format(option)) if not self.impl_is_readonly() and display_name: - option._display_name_function = display_name # pylint: disable=protected-access + option._display_name_function = ( + display_name # pylint: disable=protected-access + ) option._path = subpath # pylint: disable=protected-access option._set_readonly() # pylint: disable=protected-access if init: - self._cache_force_store_values = force_store_values # pylint: disable=attribute-defined-outside-init + self._cache_force_store_values = ( + force_store_values # pylint: disable=attribute-defined-outside-init + ) self._cache_dependencies_information = dependencies_information # pylint: disable=attribute-defined-outside-init - self._path = None # pylint: disable=attribute-defined-outside-init,no-member + self._path = ( + None # pylint: disable=attribute-defined-outside-init,no-member + ) self._set_readonly() - def impl_build_force_store_values(self, - config_bag: ConfigBag, - ) -> None: - """set value to force_store_values option - """ + def impl_build_force_store_values( + self, + config_bag: ConfigBag, + ) -> None: + """set value to force_store_values option""" # pylint: disable=too-many-branches context = config_bag.context - if 'force_store_value' not in config_bag.properties: + if "force_store_value" not in config_bag.properties: return values = config_bag.context.get_values() for option in self._cache_force_store_values: if option.issubdyn(): - paths = option.impl_getpath().split('.') + paths = option.impl_getpath().split(".") parents = [config_bag.context.get_root(config_bag)] for name in paths: new_parents = [] for parent in parents: - doption = parent.option.get_child(name, - config_bag, - parent, - allow_dynoption=True, - ) + doption = parent.option.get_child( + name, + config_bag, + parent, + allow_dynoption=True, + ) if doption.impl_is_dynoptiondescription(): - new_parents.extend(parent.dyn_to_subconfig(doption, - True, - ) - ) + new_parents.extend( + parent.dyn_to_subconfig( + doption, + True, + ) + ) else: - new_parents.append(parent.get_child(doption, - None, - True, - name=name, - )) + new_parents.append( + parent.get_child( + doption, + None, + True, + name=name, + ) + ) parents = new_parents subconfigs = new_parents else: - subconfigs = [context.get_sub_config(config_bag, - option.impl_getpath(), - None, - properties=None, - validate_properties=False, - )] + subconfigs = [ + context.get_sub_config( + config_bag, + option.impl_getpath(), + None, + properties=None, + validate_properties=False, + ) + ] if option.impl_is_follower(): for follower_subconfig in subconfigs: parent = follower_subconfig.parent follower_len = parent.get_length_leadership() for index in range(follower_len): - if values.hasvalue(follower_subconfig.path, - index=index, - ): + if values.hasvalue( + follower_subconfig.path, + index=index, + ): continue - idx_follower_subconfig = parent.get_child(follower_subconfig.option, - index, - validate_properties=False, - ) + idx_follower_subconfig = parent.get_child( + follower_subconfig.option, + index, + validate_properties=False, + ) value = values.get_value(idx_follower_subconfig)[0] if value is None: continue - values.set_storage_value(follower_subconfig.path, - index, - value, - owners.forced, - ) + values.set_storage_value( + follower_subconfig.path, + index, + value, + owners.forced, + ) else: for subconfig in subconfigs: subconfig.properties = frozenset() @@ -183,52 +209,59 @@ class CacheOptionDescription(BaseOption): continue if values.hasvalue(subconfig.path): continue - values.set_storage_value(subconfig.path, - None, - value, - owners.forced, - ) + values.set_storage_value( + subconfig.path, + None, + value, + owners.forced, + ) class OptionDescriptionWalk(CacheOptionDescription): - """get child of option description - """ - __slots__ = ('_children',) + """get child of option description""" - def get_path(self, - config_bag, - ): - if config_bag is undefined or \ - config_bag.context.get_description() == self: - return '' + __slots__ = ("_children",) + + def get_path( + self, + config_bag, + ): + if config_bag is undefined or config_bag.context.get_description() == self: + return "" return self.impl_getpath() - def get_child_not_dynamic(self, - name, - allow_dynoption, - ): + def get_child_not_dynamic( + self, + name, + allow_dynoption, + ): if name in self._children[0]: # pylint: disable=no-member - option = self._children[1][self._children[0].index(name)] # pylint: disable=no-member + option = self._children[1][ + self._children[0].index(name) + ] # pylint: disable=no-member if option.impl_is_dynoptiondescription() and not allow_dynoption: - raise AttributeError(_(f'unknown option "{name}" ' - "in root optiondescription (it's a dynamic option)" - )) + raise AttributeError( + _( + 'unknown option "{0}" in root optiondescription (it\'s a dynamic option)' + ).format(name) + ) return option - def get_child(self, - name: str, - config_bag: ConfigBag, - parent: 'SubConfig', - *, - with_identifier: bool=False, - allow_dynoption: bool=False, - ) -> Union[BaseOption]: - """get a child - """ + def get_child( + self, + name: str, + config_bag: ConfigBag, + parent: "SubConfig", + *, + with_identifier: bool = False, + allow_dynoption: bool = False, + ) -> Union[BaseOption]: + """get a child""" # if not dyn - option = self.get_child_not_dynamic(name, - allow_dynoption, - ) + option = self.get_child_not_dynamic( + name, + allow_dynoption, + ) if option: return option # if dyn @@ -242,39 +275,42 @@ class OptionDescriptionWalk(CacheOptionDescription): return child return identifier, child if self.impl_get_group_type() == groups.root: # pylint: disable=no-member - raise AttributeError(_(f'unknown option "{name}" ' - 'in root optiondescription' - )) - raise AttributeError(_(f'unknown option "{name}" ' - f'in optiondescription {self.impl_get_display_name(parent, with_quote=True)}' - )) + raise AttributeError( + _('unknown option "{0}" in root optiondescription').format(name) + ) + raise AttributeError( + _('unknown option "{0}" in optiondescription {1}').format( + name, self.impl_get_display_name(parent, with_quote=True) + ) + ) def get_children(self) -> List[BaseOption]: - """get children - """ + """get children""" return self._children[1] - def get_children_recursively(self, - bytype: Optional[BaseOption], - byname: Optional[str], - config_bag: ConfigBag, - self_opt: BaseOption=None, - *, - option_identifiers: Optional[list]=None - ) -> Iterator[Union[BaseOption]]: - """get children recursively - """ + def get_children_recursively( + self, + bytype: Optional[BaseOption], + byname: Optional[str], + config_bag: ConfigBag, + self_opt: BaseOption = None, + *, + option_identifiers: Optional[list] = None, + ) -> Iterator[Union[BaseOption]]: + """get children recursively""" if self_opt is None: self_opt = self for option in self_opt.get_children(): if option.impl_is_optiondescription(): - for subopt in option.get_children_recursively(bytype, - byname, - config_bag, - ): + for subopt in option.get_children_recursively( + bytype, + byname, + config_bag, + ): yield subopt - elif (byname is None or option.impl_getname() == byname) and \ - (bytype is None or isinstance(option, bytype)): + elif (byname is None or option.impl_getname() == byname) and ( + bytype is None or isinstance(option, bytype) + ): yield option @@ -282,28 +318,32 @@ class OptionDescription(OptionDescriptionWalk): """Config's schema (organisation, group) and container of Options The `OptionsDescription` objects lives in the `tiramisu.config.Config`. """ - __slots__ = ('_group_type',) - def __init__(self, - name: str, - doc: str, - children: List[BaseOption], - *, - properties=None, - informations: Optional[Dict]=None, - group_type: Optional[groups.GroupType]=groups.default, - ) -> None: + __slots__ = ("_group_type",) + + def __init__( + self, + name: str, + doc: str, + children: List[BaseOption], + *, + properties=None, + informations: Optional[Dict] = None, + group_type: Optional[groups.GroupType] = groups.default, + ) -> None: """ :param children: a list of options (including optiondescriptions) """ - assert isinstance(children, list), _('children in optiondescription "{}" ' - 'must be a list').format(name) - super().__init__(name, - doc, - informations, - properties=properties, - ) + assert isinstance(children, list), _( + 'children in optiondescription "{}" ' "must be a list" + ).format(name) + super().__init__( + name, + doc, + informations, + properties=properties, + ) child_names = [] if __debug__: dynopt_names = [] @@ -322,45 +362,48 @@ class OptionDescription(OptionDescriptionWalk): old = None for child in child_names: if child == old: - raise ConflictError(_('duplicate option name: ' - '"{0}"').format(child)) + raise ConflictError( + _("duplicate option name: " '"{0}"').format(child) + ) if dynopt_names: for dynopt in dynopt_names: if child != dynopt and child.startswith(dynopt): - raise ConflictError(_(f'the option\'s name "{child}" start as ' - f'the dynoptiondescription\'s name "{dynopt}"')) + raise ConflictError( + _( + 'the option\'s name "{0}" start as the dynoptiondescription\'s name "{1}"' + ).format(child, dynopt) + ) old = child self._children = children_ # the group_type is useful for filtering OptionDescriptions in a config self._group_type = None self.impl_set_group_type(group_type) - def _setsubdyn(self, - subdyn, - ) -> None: + def _setsubdyn( + self, + subdyn, + ) -> None: for child in self._children[1]: child._setsubdyn(subdyn) super()._setsubdyn(subdyn) def impl_is_optiondescription(self) -> bool: - """the option is an option description - """ + """the option is an option description""" return True def impl_is_dynoptiondescription(self) -> bool: - """the option is not dynamic - """ + """the option is not dynamic""" return False def impl_is_leadership(self) -> bool: - """the option is not a leadership - """ + """the option is not a leadership""" return False # ____________________________________________________________ - def impl_set_group_type(self, - group_type: groups.GroupType, - ) -> None: + def impl_set_group_type( + self, + group_type: groups.GroupType, + ) -> None: """sets a given group object to an OptionDescription :param group_type: an instance of `GroupType` or `LeadershipGroupType` @@ -368,22 +411,23 @@ class OptionDescription(OptionDescriptionWalk): """ if __debug__: if self._group_type is not None and self._group_type != groups.default: - raise ValueError(_('cannot change group_type if already set ' - '(old {0}, new {1})').format(self._group_type, - group_type)) + raise ValueError( + _( + "cannot change group_type if already set " "(old {0}, new {1})" + ).format(self._group_type, group_type) + ) if not isinstance(group_type, groups.GroupType): - raise ValueError(_('group_type: {0}' - ' not allowed').format(group_type)) + raise ValueError(_("group_type: {0}" " not allowed").format(group_type)) if isinstance(group_type, groups.LeadershipGroupType): - raise ConfigError('please use Leadership object instead of OptionDescription') + raise ConfigError( + "please use Leadership object instead of OptionDescription" + ) self._group_type = group_type def impl_get_group_type(self) -> groups.GroupType: - """get the group type of option description - """ + """get the group type of option description""" return self._group_type def impl_is_dynsymlinkoption(self) -> bool: - """option is not a dyn symlink option - """ + """option is not a dyn symlink option""" return False diff --git a/tiramisu/option/passwordoption.py b/tiramisu/option/passwordoption.py index c814aa5..44582f8 100644 --- a/tiramisu/option/passwordoption.py +++ b/tiramisu/option/passwordoption.py @@ -26,7 +26,7 @@ from .stroption import StrOption class PasswordOption(StrOption): - """represents the choice of a password - """ + """represents the choice of a password""" + __slots__ = tuple() - _type = 'password' + _type = "password" diff --git a/tiramisu/option/permissionsoption.py b/tiramisu/option/permissionsoption.py index 8835984..5ecff99 100644 --- a/tiramisu/option/permissionsoption.py +++ b/tiramisu/option/permissionsoption.py @@ -33,27 +33,25 @@ class PermissionsOption(IntOption): If a fourth digit is present to the setuid bit, the setgid bit and the sticky bit attributes. This option is an integer value. """ + __slots__ = tuple() perm_re = re.compile(r"^[0-7]{3,4}$") - _type = 'unix file permissions' + _type = "unix file permissions" - def __init__(self, - *args, - **kwargs, - ) -> None: - #do not display intoption attributs - super().__init__(*args, - **kwargs) + def __init__( + self, + *args, + **kwargs, + ) -> None: + # do not display intoption attributs + super().__init__(*args, **kwargs) - def validate(self, - value: str) -> None: + def validate(self, value: str) -> None: super().validate(value) if not self.perm_re.search(str(value)): - raise ValueError(_('only 3 or 4 octal digits are allowed')) + raise ValueError(_("only 3 or 4 octal digits are allowed")) - def second_level_validation(self, - value: str, - warnings_only: bool) -> None: + def second_level_validation(self, value: str, warnings_only: bool) -> None: old_digit = 7 str_value = str(value) if len(str_value) == 4: @@ -62,12 +60,12 @@ class PermissionsOption(IntOption): new_digit = int(digit) if old_digit < new_digit: if idx == 1: - old = _('user') - new = _('group') + old = _("user") + new = _("group") else: - old = _('group') - new = _('other') - raise ValueError(_(f'{new} has more right than {old}')) + old = _("group") + new = _("other") + raise ValueError(_("{0} has more right than {1}").format(new, old)) old_digit = new_digit - if str_value == '777': - raise ValueError(_('too weak')) + if str_value == "777": + raise ValueError(_("too weak")) diff --git a/tiramisu/option/portoption.py b/tiramisu/option/portoption.py index 90b14ee..a1010a0 100644 --- a/tiramisu/option/portoption.py +++ b/tiramisu/option/portoption.py @@ -36,62 +36,64 @@ class PortOption(StrOption): Port number 0 is reserved and can't be used. see: http://en.wikipedia.org/wiki/Port_numbers """ + __slots__ = tuple() port_re = re.compile(r"^[0-9]*$") - _type = 'port' + _type = "port" - def __init__(self, - *args, - allow_range: bool=False, - allow_zero: bool=False, - allow_wellknown: bool=True, - allow_registred: bool=True, - allow_protocol: bool=False, - allow_private: bool=False, - **kwargs) -> None: + def __init__( + self, + *args, + allow_range: bool = False, + allow_zero: bool = False, + allow_wellknown: bool = True, + allow_registred: bool = True, + allow_protocol: bool = False, + allow_private: bool = False, + **kwargs, + ) -> None: - extra = {'_allow_range': allow_range, - '_allow_protocol': allow_protocol, - '_min_value': None, - '_max_value': None, - } + extra = { + "_allow_range": allow_range, + "_allow_protocol": allow_protocol, + "_min_value": None, + "_max_value": None, + } ports_min = [0, 1, 1024, 49152] ports_max = [0, 1023, 49151, 65535] is_finally = False - for index, allowed in enumerate([allow_zero, - allow_wellknown, - allow_registred, - allow_private]): - if extra['_min_value'] is None: + for index, allowed in enumerate( + [allow_zero, allow_wellknown, allow_registred, allow_private] + ): + if extra["_min_value"] is None: if allowed: - extra['_min_value'] = ports_min[index] + extra["_min_value"] = ports_min[index] elif not allowed: is_finally = True elif allowed and is_finally: - raise ValueError(_('inconsistency in allowed range')) + raise ValueError(_("inconsistency in allowed range")) if allowed: - extra['_max_value'] = ports_max[index] + extra["_max_value"] = ports_max[index] - if extra['_max_value'] is None: - raise ValueError(_('max value is empty')) + if extra["_max_value"] is None: + raise ValueError(_("max value is empty")) - super().__init__(*args, - extra=extra, - **kwargs) + super().__init__(*args, extra=extra, **kwargs) - def validate(self, - value: str) -> None: + def validate(self, value: str) -> None: super().validate(value) - if self.impl_get_extra('_allow_protocol') and (value.startswith('tcp:') or - value.startswith('udp:')): + if self.impl_get_extra("_allow_protocol") and ( + value.startswith("tcp:") or value.startswith("udp:") + ): value = [value[4:]] - elif self.impl_get_extra('_allow_range') and ":" in str(value): - value = value.split(':') + elif self.impl_get_extra("_allow_range") and ":" in str(value): + value = value.split(":") if len(value) != 2: - raise ValueError(_('range must have two values only')) + raise ValueError(_("range must have two values only")) if not value[0] < value[1]: - raise ValueError(_('first port in range must be' - ' smaller than the second one')) + raise ValueError( + _("first port in range must be" " smaller than the second one") + ) else: value = [value] @@ -99,22 +101,29 @@ class PortOption(StrOption): if not self.port_re.search(val): raise ValueError() - def second_level_validation(self, - value: str, - warnings_only: bool) -> None: - if self.impl_get_extra('_allow_protocol') and (value.startswith('tcp:') or - value.startswith('udp:')): + def second_level_validation(self, value: str, warnings_only: bool) -> None: + if self.impl_get_extra("_allow_protocol") and ( + value.startswith("tcp:") or value.startswith("udp:") + ): value = [value[4:]] - elif ':' in value: - value = value.split(':') + elif ":" in value: + value = value.split(":") else: value = [value] for val in value: val = int(val) - if not self.impl_get_extra('_min_value') <= val <= self.impl_get_extra('_max_value'): + if ( + not self.impl_get_extra("_min_value") + <= val + <= self.impl_get_extra("_max_value") + ): if warnings_only: - msg = 'should be between {0} and {1}' + msg = _("should be between {0} and {1}") else: - msg = 'must be between {0} and {1}' - raise ValueError(_(msg).format(self.impl_get_extra('_min_value'), - self.impl_get_extra('_max_value'))) + msg = _("must be between {0} and {1}") + raise ValueError( + msg.format( + self.impl_get_extra("_min_value"), + self.impl_get_extra("_max_value"), + ) + ) diff --git a/tiramisu/option/stroption.py b/tiramisu/option/stroption.py index 30e3e4c..a4b7faa 100644 --- a/tiramisu/option/stroption.py +++ b/tiramisu/option/stroption.py @@ -27,31 +27,31 @@ from .option import Option class StrOption(Option): - """represents a string - """ - __slots__ = tuple() - _type = 'string' + """represents a string""" - def validate(self, - value: str, - ) -> None: - """validation - """ + __slots__ = tuple() + _type = "string" + + def validate( + self, + value: str, + ) -> None: + """validation""" if not isinstance(value, str): raise ValueError() class RegexpOption(StrOption): - """regexp validation, this is base option use to do a custom's one - """ + """regexp validation, this is base option use to do a custom's one""" + __slots__ = tuple() - def validate(self, - value: Any, - ) -> None: + def validate( + self, + value: Any, + ) -> None: # pylint: disable=no-member - """validation - """ + """validation""" super().validate(value) match = self._regexp.search(value) if not match: diff --git a/tiramisu/option/symlinkoption.py b/tiramisu/option/symlinkoption.py index 8d29bbc..7042bc5 100644 --- a/tiramisu/option/symlinkoption.py +++ b/tiramisu/option/symlinkoption.py @@ -27,61 +27,66 @@ from ..i18n import _ class SymLinkOption(BaseOption): - """SymLinkOption link to an other option - """ - __slots__ = ('_opt', - '_leadership', - ) + """SymLinkOption link to an other option""" - def __init__(self, - name: str, - opt: BaseOption, - ) -> None: + __slots__ = ( + "_opt", + "_leadership", + ) + + def __init__( + self, + name: str, + opt: BaseOption, + ) -> None: # pylint: disable=super-init-not-called if not valid_name(name): raise ValueError(_('"{0}" is an invalid name for an option').format(name)) - if not isinstance(opt, BaseOption) or \ - opt.impl_is_optiondescription() or \ - opt.impl_is_symlinkoption(): - raise ValueError(_(f'malformed symlink second parameters must be an option for "{name}", not {opt}')) + if ( + not isinstance(opt, BaseOption) + or opt.impl_is_optiondescription() + or opt.impl_is_symlinkoption() + ): + raise ValueError( + _( + 'malformed symlink second parameters must be an option for "{0}", not {1}' + ).format(name, opt) + ) self._name = name self._opt = opt self._leadership = None opt._add_dependency(self) - def __getattr__(self, - name: str, - ) -> Any: - if name == '_subdyns': + def __getattr__( + self, + name: str, + ) -> Any: + if name == "_subdyns": return None - if name == '_path': + if name == "_path": raise AttributeError() return getattr(self._opt, name) def impl_is_symlinkoption(self) -> bool: - """it's a symlinkoption - """ + """it's a symlinkoption""" return True def impl_is_leader(self) -> bool: return False def impl_is_follower(self): - """check if option is a leader in a follower - """ + """check if option is a leader in a follower""" leadership = self._leadership if leadership is None: return False return not leadership().is_leader(self) def impl_getopt(self) -> BaseOption: - """get to linked option - """ + """get to linked option""" return self._opt def impl_is_multi(self) -> bool: - """is it a multi? - """ + """is it a multi?""" if self._opt.impl_is_multi(): return True if self._opt.issubdyn() or self.issubdyn(): @@ -91,6 +96,5 @@ class SymLinkOption(BaseOption): return False def impl_is_submulti(self) -> bool: - """is it a submulti? - """ + """is it a submulti?""" return self._opt.impl_is_submulti() diff --git a/tiramisu/option/urloption.py b/tiramisu/option/urloption.py index b56342b..1677dbd 100644 --- a/tiramisu/option/urloption.py +++ b/tiramisu/option/urloption.py @@ -32,93 +32,97 @@ from .portoption import PortOption class URLOption(StrOption): - """URLOption to check url value - """ + """URLOption to check url value""" + __slots__ = tuple() path_re = re.compile(r"^[A-Za-z0-9\-\._~:/\?#\[\]@!%\$&\'\(\)\*\+,;=]+$") - _type = 'URL' + _type = "URL" - def __init__(self, - name: str, - doc: str, - *args, - allow_ip: bool=False, - type: str='domainname', - allow_without_dot=False, - allow_range: bool=False, - allow_zero: bool=False, - allow_wellknown: bool=True, - allow_registred: bool=True, - allow_private: bool=False, - **kwargs, - ) -> None: + def __init__( + self, + name: str, + doc: str, + *args, + allow_ip: bool = False, + type: str = "domainname", + allow_without_dot=False, + allow_range: bool = False, + allow_zero: bool = False, + allow_wellknown: bool = True, + allow_registred: bool = True, + allow_private: bool = False, + **kwargs, + ) -> None: # pylint: disable=too-many-arguments,too-many-locals,redefined-builtin - extra = {'_domainname': DomainnameOption(name, - doc, - allow_ip=allow_ip, - type=type, - allow_without_dot=allow_without_dot), - '_port': PortOption(name, - doc, - allow_range=allow_range, - allow_zero=allow_zero, - allow_wellknown=allow_wellknown, - allow_registred=allow_registred, - allow_private=allow_private)} - super().__init__(name, - doc, - extra=extra, - *args, - **kwargs, - ) + extra = { + "_domainname": DomainnameOption( + name, + doc, + allow_ip=allow_ip, + type=type, + allow_without_dot=allow_without_dot, + ), + "_port": PortOption( + name, + doc, + allow_range=allow_range, + allow_zero=allow_zero, + allow_wellknown=allow_wellknown, + allow_registred=allow_registred, + allow_private=allow_private, + ), + } + super().__init__( + name, + doc, + extra=extra, + *args, + **kwargs, + ) - def _get_domain_port_files(self, - value: str) -> (str, str): - if value.startswith('http://'): - type_ = 'http' + def _get_domain_port_files(self, value: str) -> (str, str): + if value.startswith("http://"): + type_ = "http" value = value[7:] - elif value.startswith('https://'): - type_ = 'https' + elif value.startswith("https://"): + type_ = "https" value = value[8:] else: - raise ValueError(_('must start with http:// or ' - 'https://')) + raise ValueError(_("must start with http:// or " "https://")) # get domain/files - splitted = value.split('/', 1) + splitted = value.split("/", 1) if len(splitted) == 1: domain = value files = None else: domain, files = splitted # if port in domain - splitted = domain.split(':', 1) + splitted = domain.split(":", 1) if len(splitted) == 1: domain = splitted[0] - port = {'http': '80', - 'https': '443'}[type_] + port = {"http": "80", "https": "443"}[type_] else: domain, port = splitted return domain, port, files - def validate(self, - value: str) -> None: + def validate(self, value: str) -> None: super().validate(value) domain, port, files = self._get_domain_port_files(value) # validate port - portoption = self.impl_get_extra('_port') + portoption = self.impl_get_extra("_port") portoption.validate(port) # validate domainname - domainnameoption = self.impl_get_extra('_domainname') + domainnameoption = self.impl_get_extra("_domainname") domainnameoption.validate(domain) # validate files - if files is not None and files != '' and not self.path_re.search(files): - raise ValueError(_('must ends with a valid resource name')) + if files is not None and files != "" and not self.path_re.search(files): + raise ValueError(_("must ends with a valid resource name")) def second_level_validation(self, value, warnings_only): domain, port, _ = self._get_domain_port_files(value) # validate port - portoption = self.impl_get_extra('_port') + portoption = self.impl_get_extra("_port") portoption.second_level_validation(port, warnings_only) # validate domainname - domainnameoption = self.impl_get_extra('_domainname') + domainnameoption = self.impl_get_extra("_domainname") domainnameoption.second_level_validation(domain, warnings_only) diff --git a/tiramisu/option/usernameoption.py b/tiramisu/option/usernameoption.py index 4b698bd..8451df7 100644 --- a/tiramisu/option/usernameoption.py +++ b/tiramisu/option/usernameoption.py @@ -27,16 +27,16 @@ from .stroption import RegexpOption class UsernameOption(RegexpOption): - """UsernameOption to check unix username value - """ + """UsernameOption to check unix username value""" + __slots__ = tuple() - #regexp build with 'man 8 adduser' informations + # regexp build with 'man 8 adduser' informations _regexp = re.compile(r"^[a-z_][a-z0-9_-]{0,30}[$a-z0-9_-]{0,1}$") - _type = 'unix username' + _type = "unix username" class GroupnameOption(UsernameOption): - """GroupnameOption to check unix group value - """ + """GroupnameOption to check unix group value""" + __slots__ = tuple() - _type = 'unix groupname' + _type = "unix groupname" diff --git a/tiramisu/setting.py b/tiramisu/setting.py index 5dcbf0a..d278cd1 100644 --- a/tiramisu/setting.py +++ b/tiramisu/setting.py @@ -17,7 +17,13 @@ # ____________________________________________________________ from typing import Union, Set from itertools import chain -from .error import PropertiesOptionError, ConstError, ConfigError, LeadershipError, display_list +from .error import ( + PropertiesOptionError, + ConstError, + ConfigError, + LeadershipError, + display_list, +) from .i18n import _ @@ -26,131 +32,147 @@ from .i18n import _ # user access several time to value/setting EXPIRATION_TIME = 5 -#List of default properties (you can add new one if needed). +# List of default properties (you can add new one if needed). # -#For common properties and personalise properties, if a propery is set for -#an Option and for the Config together, Setting raise a PropertiesOptionError +# For common properties and personalise properties, if a propery is set for +# an Option and for the Config together, Setting raise a PropertiesOptionError # -#* Common properties: +# * Common properties: # -#hidden +# hidden # option with this property can only get value in read only mode. This # option is not available in read write mode. # -#disabled +# disabled # option with this property cannot be set/get # -#frozen +# frozen # cannot set value for option with this properties if 'frozen' is set in # config # -#* Special property: +# * Special property: # -#permissive +# permissive # option with 'permissive' cannot raise PropertiesOptionError for properties # set in permissive # config with 'permissive', whole option in this config cannot raise # PropertiesOptionError for properties set in permissive # -#mandatory +# mandatory # should set value for option with this properties if 'mandatory' is set in # config # example: 'a', ['a'], [None] are valid # None, [] are not valid # -#empty +# empty # raise mandatory PropertiesOptionError if multi or leader have empty value # example: ['a'] is valid # [None] is not valid # -#unique +# unique # raise ValueError if a value is set twice or more in a multi Option # -#* Special Config properties: +# * Special Config properties: # -#cache +# cache # if set, enable cache settings and values # -#expire +# expire # if set, settings and values in cache expire after ``expiration_time`` # -#everything_frozen +# everything_frozen # whole option in config are frozen (even if option have not frozen # property) # -#validator +# validator # launch validator set by user in option (this property has no effect # for internal validator) # -#warnings +# warnings # display warnings during validation # -#demoting_error_warning +# demoting_error_warning # all value errors are convert to warning (ValueErrorWarning) -DEFAULT_PROPERTIES = frozenset(['cache', 'validator', 'warnings']) -SPECIAL_PROPERTIES = {'frozen', 'mandatory', 'empty', 'force_store_value'} +DEFAULT_PROPERTIES = frozenset(["cache", "validator", "warnings"]) +SPECIAL_PROPERTIES = {"frozen", "mandatory", "empty", "force_store_value"} -#Config can be in two defaut mode: +# Config can be in two defaut mode: # -#read_only +# read_only # you can get all variables not disabled but you cannot set any variables # if a value has a callback without any value, callback is launch and value # of this variable can change # you cannot access to mandatory variable without values # -#read_write +# read_write # you can get all variables not disabled and not hidden # you can set all variables not frozen -RO_APPEND = frozenset(['frozen', - 'disabled', - 'validator', - 'everything_frozen', - 'mandatory', - 'empty', - 'force_store_value', - ]) -RO_REMOVE = frozenset(['permissive', - 'hidden', - ]) -RW_APPEND = frozenset(['frozen', - 'disabled', - 'validator', - 'hidden', - 'force_store_value', - ]) -RW_REMOVE = frozenset(['permissive', - 'everything_frozen', - 'mandatory', - 'empty', - ]) +RO_APPEND = frozenset( + [ + "frozen", + "disabled", + "validator", + "everything_frozen", + "mandatory", + "empty", + "force_store_value", + ] +) +RO_REMOVE = frozenset( + [ + "permissive", + "hidden", + ] +) +RW_APPEND = frozenset( + [ + "frozen", + "disabled", + "validator", + "hidden", + "force_store_value", + ] +) +RW_REMOVE = frozenset( + [ + "permissive", + "everything_frozen", + "mandatory", + "empty", + ] +) -FORBIDDEN_SET_PROPERTIES = frozenset(['force_store_value']) -FORBIDDEN_SET_PERMISSIVES = frozenset(['force_default_on_freeze', - 'force_metaconfig_on_freeze', - 'force_store_value', - ]) -ALLOWED_LEADER_PROPERTIES = {'empty', - 'notempty', - 'notunique', - 'unique', - 'force_store_value', - 'mandatory', - 'force_default_on_freeze', - 'force_metaconfig_on_freeze', - 'frozen', - } +FORBIDDEN_SET_PROPERTIES = frozenset(["force_store_value"]) +FORBIDDEN_SET_PERMISSIVES = frozenset( + [ + "force_default_on_freeze", + "force_metaconfig_on_freeze", + "force_store_value", + ] +) +ALLOWED_LEADER_PROPERTIES = { + "empty", + "notempty", + "notunique", + "unique", + "force_store_value", + "mandatory", + "force_default_on_freeze", + "force_metaconfig_on_freeze", + "frozen", +} static_set = frozenset() # ____________________________________________________________ class Undefined: - """Object undefined, means that there is not value - """ + """Object undefined, means that there is not value""" + # pylint: disable=too-few-public-methods def __str__(self): # pragma: no cover - return 'Undefined' + return "Undefined" __repr__ = __str__ @@ -159,21 +181,18 @@ undefined = Undefined() class ConfigBag: - """Object to store information for context - """ - __slots__ = ('context', # link to the current context - 'properties', # properties for current context - 'true_properties', # properties for current context - 'is_unrestraint', - 'permissives', # permissives for current context - 'expiration_time', # EXPIRATION_TIME - ) + """Object to store information for context""" - def __init__(self, - context, - properties: set, - permissives: frozenset, - **kwargs): + __slots__ = ( + "context", # link to the current context + "properties", # properties for current context + "true_properties", # properties for current context + "is_unrestraint", + "permissives", # permissives for current context + "expiration_time", # EXPIRATION_TIME + ) + + def __init__(self, context, properties: set, permissives: frozenset, **kwargs): self.context = context self.properties = properties self.permissives = permissives @@ -181,40 +200,39 @@ class ConfigBag: setattr(self, key, value) def __getattr__(self, key): - if key == 'true_properties': + if key == "true_properties": return self.properties - if key == 'expiration_time': - self.expiration_time = EXPIRATION_TIME # pylint: disable=attribute-defined-outside-init + if key == "expiration_time": + self.expiration_time = ( + EXPIRATION_TIME # pylint: disable=attribute-defined-outside-init + ) return self.expiration_time - if key == 'is_unrestraint': + if key == "is_unrestraint": return False raise KeyError(f'unknown key "{key}" for ConfigBag') # pragma: no cover def nowarnings(self): - """do not warnings - """ - self.properties = frozenset(self.properties - {'warnings'}) + """do not warnings""" + self.properties = frozenset(self.properties - {"warnings"}) def remove_validation(self): - """do not validate option - """ - self.properties = frozenset(self.properties - {'validator'}) + """do not validate option""" + self.properties = frozenset(self.properties - {"validator"}) def unrestraint(self): - """do not restraint access to option - """ + """do not restraint access to option""" self.is_unrestraint = True # pylint: disable=attribute-defined-outside-init - self.true_properties = self.properties # pylint: disable=attribute-defined-outside-init - self.properties = frozenset(['cache']) + self.true_properties = ( + self.properties + ) # pylint: disable=attribute-defined-outside-init + self.properties = frozenset(["cache"]) def set_permissive(self): - """set permissive - """ - self.properties = frozenset(self.properties | {'permissive'}) + """set permissive""" + self.properties = frozenset(self.properties | {"permissive"}) def copy(self): - """copy the config - """ + """copy the config""" kwargs = {} for key in self.__slots__: kwargs[key] = getattr(self, key) @@ -228,22 +246,25 @@ class _NameSpace: when attribute is added, we cannot delete it """ - def __setattr__(self, - name, - value, - ): + def __setattr__( + self, + name, + value, + ): if name in self.__dict__: raise ConstError(_("can't rebind {0}").format(name)) self.__dict__[name] = value - def __delattr__(self, - name, - ): + def __delattr__( + self, + name, + ): raise ConstError(_("can't unbind {0}").format(name)) class GroupModule(_NameSpace): "emulates a module to manage unique group (OptionDescription) names" + # pylint: disable=too-few-public-methods class GroupType(str): """allowed normal group (OptionDescription) names @@ -259,12 +280,10 @@ class GroupModule(_NameSpace): """ class RootGroupType(GroupType): - """root means this is the root optiondescription of whole config - """ + """root means this is the root optiondescription of whole config""" def addgroup(self, name): - """add a new group type - """ + """add a new group type""" setattr(groups, name, groups.GroupType(name)) @@ -273,10 +292,10 @@ class OwnerModule(_NameSpace): owners are living in `Config._value_owners` """ + # pylint: disable=too-few-public-methods class Owner(str): - """allowed owner names - """ + """allowed owner names""" class DefaultOwner(Owner): """groups that are default (typically 'default')""" @@ -293,16 +312,22 @@ class OwnerModule(_NameSpace): groups = GroupModule() # groups.default: default group set when creating a new optiondescription -groups.default = groups.DefaultGroupType('default') # pylint: disable=attribute-defined-outside-init +groups.default = groups.DefaultGroupType( + "default" +) # pylint: disable=attribute-defined-outside-init # groups.leadership: leadership group is a special optiondescription, all suboptions should # be multi option and all values should have same length, to find # leader's option, the optiondescription's name should be same than de # leader's option""" -groups.leadership = groups.LeadershipGroupType('leadership') # pylint: disable=attribute-defined-outside-init +groups.leadership = groups.LeadershipGroupType( + "leadership" +) # pylint: disable=attribute-defined-outside-init # groups.root: this group is the root optiondescription of whole config -groups.root = groups.RootGroupType('root') # pylint: disable=attribute-defined-outside-init +groups.root = groups.RootGroupType( + "root" +) # pylint: disable=attribute-defined-outside-init # ____________________________________________________________ @@ -310,13 +335,15 @@ groups.root = groups.RootGroupType('root') # pylint: disable=attribute-defined- owners = OwnerModule() # default: is the config owner after init time -owners.default = owners.DefaultOwner('default') # pylint: disable=attribute-defined-outside-init +owners.default = owners.DefaultOwner( + "default" +) # pylint: disable=attribute-defined-outside-init # user: is the generic is the generic owner -owners.addowner('user') +owners.addowner("user") -#forced: special owner when value is forced -owners.addowner('forced') +# forced: special owner when value is forced +owners.addowner("forced") forbidden_owners = (owners.default, owners.forced) # pylint: disable=no-member @@ -325,15 +352,16 @@ forbidden_owners = (owners.default, owners.forced) # pylint: disable=no-member # ____________________________________________________________ class Settings: "``config.Config()``'s configuration options settings" - __slots__ = ('_properties', - '_permissives', - '_permissives', - '__weakref__', - 'ro_append', - 'ro_remove', - 'rw_append', - 'rw_remove', - ) + __slots__ = ( + "_properties", + "_permissives", + "_permissives", + "__weakref__", + "ro_append", + "ro_remove", + "rw_append", + "rw_remove", + ) def __init__(self): """ @@ -354,39 +382,39 @@ class Settings: # get properties and permissive methods def get_context_properties(self): - """get context properties - """ + """get context properties""" return self.get_personalize_properties() - def get_personalize_properties(self, - path: Union[None, str]=None, - index: Union[None, int]=None, - ) -> Set[str]: - """Get the properties modified by user for a path or index - """ + def get_personalize_properties( + self, + path: Union[None, str] = None, + index: Union[None, int] = None, + ) -> Set[str]: + """Get the properties modified by user for a path or index""" if path not in self._properties or index not in self._properties[path]: return frozenset() return self._properties[path][index] - def getproperties(self, - subconfig: 'SubConfig', - *, - apply_requires=True, - uncalculated=False, - help_property=False, - transitive_raise=True, - ): - """get properties - """ + def getproperties( + self, + subconfig: "SubConfig", + *, + apply_requires=True, + uncalculated=False, + help_property=False, + transitive_raise=True, + ): + """get properties""" # pylint: disable=too-many-branches option = subconfig.option if option.impl_is_symlinkoption(): option = option.impl_getopt() if apply_requires and not uncalculated and not help_property: cache = subconfig.config_bag.context.properties_cache - is_cached, props, validated = cache.getcache(subconfig, # pylint: disable=unused-variable - 'self_props', - ) + is_cached, props, validated = cache.getcache( + subconfig, # pylint: disable=unused-variable + "self_props", + ) else: is_cached = False if not is_cached: @@ -397,9 +425,10 @@ class Settings: if props_config: p_props.append(props_config) if subconfig.index is not None: - props_config = self.get_personalize_properties(subconfig.path, - subconfig.index, - ) + props_config = self.get_personalize_properties( + subconfig.path, + subconfig.index, + ) if props_config: p_props.append(props_config) for prop in chain(*p_props): @@ -411,13 +440,15 @@ class Settings: elif apply_requires: try: if not help_property: - new_prop = prop.execute(subconfig, - for_settings=True, - ) + new_prop = prop.execute( + subconfig, + for_settings=True, + ) else: - new_prop = prop.help(subconfig, - for_settings=True, - ) + new_prop = prop.help( + subconfig, + for_settings=True, + ) if isinstance(new_prop, str): new_prop = (new_prop, new_prop) if new_prop is None: @@ -426,25 +457,43 @@ class Settings: if transitive_raise: raise err from err continue - if (not help_property and not isinstance(new_prop, str)) or \ - (help_property and not isinstance(new_prop, tuple)): - raise ValueError(_('invalid property type {type(new_prop)} for ' - '{subconfig.option.impl_getname()} with ' - '{prop.function.__name__} function')) - if not option.impl_is_optiondescription() and \ - option.impl_is_leader() and \ - new_prop not in ALLOWED_LEADER_PROPERTIES: - raise LeadershipError(_('leader cannot have "{new_prop}" property')) + if (not help_property and not isinstance(new_prop, str)) or ( + help_property and not isinstance(new_prop, tuple) + ): + raise ValueError( + _( + "invalid property type {type(new_prop)} for " + "{subconfig.option.impl_getname()} with " + "{prop.function.__name__} function" + ) + ) + if ( + not option.impl_is_optiondescription() + and option.impl_is_leader() + and new_prop not in ALLOWED_LEADER_PROPERTIES + ): + raise LeadershipError( + _('leader cannot have "{new_prop}" property') + ) props.add(new_prop) props -= self.getpermissives(subconfig) - if not uncalculated and apply_requires and \ - not subconfig.config_bag.is_unrestraint and \ - not help_property and transitive_raise: - cache.setcache(subconfig, - props, - type_='properties', - ) - if not uncalculated and subconfig.parent and subconfig.parent.transitive_properties: + if ( + not uncalculated + and apply_requires + and not subconfig.config_bag.is_unrestraint + and not help_property + and transitive_raise + ): + cache.setcache( + subconfig, + props, + type_="properties", + ) + if ( + not uncalculated + and subconfig.parent + and subconfig.parent.transitive_properties + ): parent_properties = subconfig.parent.transitive_properties parent_properties -= self.getpermissives(subconfig) if help_property: @@ -453,25 +502,25 @@ class Settings: return props def get_context_permissives(self): - """get context permissives - """ + """get context permissives""" return self.getpermissives(None) - def _getpermissives(self, - path, - index, - ): + def _getpermissives( + self, + path, + index, + ): if not path in self._permissives: ret = frozenset() else: ret = self._permissives[path].get(index, frozenset()) return ret - def getpermissives(self, - subconfig: "SubConfig", - ): - """get permissive - """ + def getpermissives( + self, + subconfig: "SubConfig", + ): + """get permissive""" if subconfig is None: path = None index = None @@ -483,26 +532,27 @@ class Settings: else: path = subconfig.path index = subconfig.index - permissives = self._getpermissives(path, - None, - ) + permissives = self._getpermissives( + path, + None, + ) if index is not None: option_permissives = self._permissives.get(path, {}).get(index, set()) permissives = frozenset(option_permissives | permissives) return permissives - #____________________________________________________________ + # ____________________________________________________________ # set methods def set_context_properties(self, properties, context): - """set context properties - """ + """set context properties""" self._properties[None][None] = properties context.reset_cache(None) - def setproperties(self, - subconfig, - properties, - ): + def setproperties( + self, + subconfig, + properties, + ): """save properties for specified path (never save properties if same has option properties) """ @@ -510,31 +560,40 @@ class Settings: if not opt.impl_is_optiondescription() and opt.impl_is_leader(): not_allowed_properties = properties - ALLOWED_LEADER_PROPERTIES if not_allowed_properties: - raise LeadershipError(_(f'leader cannot have "{display_list(not_allowed_properties)}" ' - 'property')) - if ('force_default_on_freeze' in properties or \ - 'force_metaconfig_on_freeze' in properties) and 'frozen' not in properties: - raise LeadershipError(_('a leader ({opt.impl_get_display_name()}) cannot have ' - '"force_default_on_freeze" or ' - '"force_metaconfig_on_freeze" property without "frozen"')) + raise LeadershipError( + _('leader cannot have "{0}" property').format( + display_list(not_allowed_properties) + ) + ) + if ( + "force_default_on_freeze" in properties + or "force_metaconfig_on_freeze" in properties + ) and "frozen" not in properties: + raise LeadershipError( + _( + 'a leader ({0}) cannot have "force_default_on_freeze" or "force_metaconfig_on_freeze" property without "frozen"' + ).format(opt.impl_get_display_name()) + ) self._properties.setdefault(subconfig.path, {})[subconfig.index] = properties # values too because of follower values could have a PropertiesOptionError has value subconfig.config_bag.context.reset_cache(subconfig) subconfig.properties = properties - def set_context_permissives(self, - permissives, - ): - """set context permissive - """ - self.setpermissives(None, - permissives, - ) + def set_context_permissives( + self, + permissives, + ): + """set context permissive""" + self.setpermissives( + None, + permissives, + ) - def setpermissives(self, - subconfig, - permissives, - ): + def setpermissives( + self, + subconfig, + permissives, + ): """ enables us to put the permissives in the storage @@ -545,7 +604,7 @@ class Settings: instead of passing a :class:`tiramisu.option.Option()` object. """ if not isinstance(permissives, frozenset): - raise TypeError(_('permissive must be a frozenset')) + raise TypeError(_("permissive must be a frozenset")) if subconfig is not None: path = subconfig.path index = subconfig.index @@ -554,107 +613,115 @@ class Settings: index = None forbidden_permissives = FORBIDDEN_SET_PERMISSIVES & permissives if forbidden_permissives: - raise ConfigError(_('cannot add those permissives: {0}').format( - ' '.join(forbidden_permissives))) + raise ConfigError( + _("cannot add those permissives: {0}").format( + " ".join(forbidden_permissives) + ) + ) self._permissives.setdefault(path, {})[index] = permissives if subconfig is not None: subconfig.config_bag.context.reset_cache(subconfig) - #____________________________________________________________ + # ____________________________________________________________ # reset methods - def _get_path_index_config_option(self, - bag: Union['SubConfig', ConfigBag], - msg: str, - ): + def _get_path_index_config_option( + self, + bag: Union["SubConfig", ConfigBag], + msg: str, + ): if isinstance(bag, ConfigBag): path = None index = None config_bag = bag - subconfig= None + subconfig = None else: - assert not bag.option.impl_is_symlinkoption(), \ - _(msg).format(bag.option.impl_get_display_name()) + assert not bag.option.impl_is_symlinkoption(), msg.format( + bag.option.impl_get_display_name() + ) path = bag.path index = bag.index config_bag = bag.config_bag subconfig = bag return path, index, config_bag, subconfig - def reset(self, - bag: Union['SubConfig', ConfigBag], - ): - """reset property - """ - path, index, config_bag, subconfig = \ - self._get_path_index_config_option(bag, - "can't reset properties to " - "the symlinkoption \"{}\"", - ) + def reset( + self, + bag: Union["SubConfig", ConfigBag], + ): + """reset property""" + path, index, config_bag, subconfig = self._get_path_index_config_option( + bag, + _("can't reset properties to " 'the symlinkoption "{}"'), + ) if path in self._properties and index in self._properties[path]: del self._properties[path][index] config_bag.context.reset_cache(subconfig) - def reset_permissives(self, - bag: Union['SubConfig', ConfigBag], - ): - """reset permission - """ - path, index, config_bag, subconfig = \ - self._get_path_index_config_option(bag, - "can't reset permissives to " - "the symlinkoption \"{}\"", - ) + def reset_permissives( + self, + bag: Union["SubConfig", ConfigBag], + ): + """reset permission""" + path, index, config_bag, subconfig = self._get_path_index_config_option( + bag, + _("can't reset permissives to " 'the symlinkoption "{}"'), + ) if path in self._permissives and index in self._permissives[path]: del self._permissives[path][index] config_bag.context.reset_cache(subconfig) - #____________________________________________________________ + # ____________________________________________________________ # validate properties - def calc_raises_properties(self, - subconfig, - *, - apply_requires=True, - uncalculated=False, - transitive_raise=True, - not_unrestraint: bool=False, - ): - """raise if needed - """ + def calc_raises_properties( + self, + subconfig, + *, + apply_requires=True, + uncalculated=False, + transitive_raise=True, + not_unrestraint: bool = False, + ): + """raise if needed""" if not uncalculated and apply_requires and subconfig.properties is not None: option_properties = subconfig.properties else: - option_properties = self.getproperties(subconfig, - apply_requires=apply_requires, - uncalculated=uncalculated, - transitive_raise=transitive_raise, - ) - return self._calc_raises_properties(subconfig, - option_properties, - not_unrestraint, - ) + option_properties = self.getproperties( + subconfig, + apply_requires=apply_requires, + uncalculated=uncalculated, + transitive_raise=transitive_raise, + ) + return self._calc_raises_properties( + subconfig, + option_properties, + not_unrestraint, + ) - def calc_transitive_properties(self, - subconfig, - option_properties, - ): + def calc_transitive_properties( + self, + subconfig, + option_properties, + ): config_bag = subconfig.config_bag - modified, context_properties = self.calc_read(self.rw_remove, - self.rw_append, - config_bag, - ) + modified, context_properties = self.calc_read( + self.rw_remove, + self.rw_append, + config_bag, + ) raises_properties = context_properties - SPECIAL_PROPERTIES # remove global permissive properties - if raises_properties and 'permissive' in raises_properties: + if raises_properties and "permissive" in raises_properties: raises_properties -= config_bag.permissives properties = option_properties & raises_properties # at this point it should not remain any property for the option return properties - def _calc_raises_properties(self, - subconfig, - option_properties, - not_unrestraint: bool, - ): + def _calc_raises_properties( + self, + subconfig, + option_properties, + not_unrestraint: bool, + ): config_bag = subconfig.config_bag if not_unrestraint and config_bag.is_unrestraint: context_properties = config_bag.true_properties @@ -662,100 +729,126 @@ class Settings: context_properties = config_bag.properties raises_properties = context_properties - SPECIAL_PROPERTIES # remove global permissive properties - if raises_properties and 'permissive' in raises_properties: + if raises_properties and "permissive" in raises_properties: raises_properties -= config_bag.permissives properties = option_properties & raises_properties # at this point it should not remain any property for the option return properties - def validate_properties(self, - subconfig, - *, - need_help=True, - ): - """check properties - """ + def validate_properties( + self, + subconfig, + *, + need_help=True, + ): + """check properties""" config_properties = subconfig.config_bag.properties - if not config_properties or config_properties == frozenset(['cache']): + if not config_properties or config_properties == frozenset(["cache"]): # if no global property return for transitive_raise in [False, True]: - properties = self.calc_raises_properties(subconfig, - transitive_raise=transitive_raise, - ) + properties = self.calc_raises_properties( + subconfig, + transitive_raise=transitive_raise, + ) if properties != frozenset(): if need_help: - help_properties = dict(self.getproperties(subconfig, - help_property=True, - transitive_raise=transitive_raise, - )) + help_properties = dict( + self.getproperties( + subconfig, + help_property=True, + transitive_raise=transitive_raise, + ) + ) calc_properties = [] - for property_ in self._calc_raises_properties(subconfig, - set(help_properties.keys()), - False, - ): + for property_ in self._calc_raises_properties( + subconfig, + set(help_properties.keys()), + False, + ): calc_properties.append(help_properties[property_]) calc_properties = frozenset(calc_properties) else: calc_properties = properties - raise PropertiesOptionError(subconfig, - properties, - self, - help_properties=calc_properties, - ) + raise PropertiesOptionError( + subconfig, + properties, + self, + help_properties=calc_properties, + ) - def validate_mandatory(self, - subconfig, - value, - ): - """verify if option is mandatory without value - """ - if 'mandatory' not in subconfig.config_bag.properties: + def validate_mandatory( + self, + subconfig, + value, + ): + """verify if option is mandatory without value""" + if "mandatory" not in subconfig.config_bag.properties: return values = subconfig.config_bag.context.get_values() - if not ('permissive' in subconfig.config_bag.properties and - 'mandatory' in subconfig.config_bag.permissives) and \ - 'mandatory' in subconfig.properties and values.isempty(subconfig, - value, - False, - ): - raise PropertiesOptionError(subconfig, - ['mandatory'], - self, - ) - if 'empty' in subconfig.properties and values.isempty(subconfig, - value, - True, - ): - raise PropertiesOptionError(subconfig, - ['empty'], - self, - ) + if ( + not ( + "permissive" in subconfig.config_bag.properties + and "mandatory" in subconfig.config_bag.permissives + ) + and "mandatory" in subconfig.properties + and values.isempty( + subconfig, + value, + False, + ) + ): + raise PropertiesOptionError( + subconfig, + ["mandatory"], + self, + ) + if "empty" in subconfig.properties and values.isempty( + subconfig, + value, + True, + ): + raise PropertiesOptionError( + subconfig, + ["empty"], + self, + ) - def validate_frozen(self, - subconfig, - ): - """verify if option is frozen - """ - if subconfig.config_bag.properties and \ - ('everything_frozen' in subconfig.config_bag.properties or - ('frozen' in subconfig.config_bag.properties and \ - 'frozen' in subconfig.properties)) and \ - not (('permissive' in subconfig.config_bag.properties) and - 'frozen' in subconfig.config_bag.permissives): - raise PropertiesOptionError(subconfig, - ['frozen'], - self, - ) + def validate_frozen( + self, + subconfig, + ): + """verify if option is frozen""" + if ( + subconfig.config_bag.properties + and ( + "everything_frozen" in subconfig.config_bag.properties + or ( + "frozen" in subconfig.config_bag.properties + and "frozen" in subconfig.properties + ) + ) + and not ( + ("permissive" in subconfig.config_bag.properties) + and "frozen" in subconfig.config_bag.permissives + ) + ): + raise PropertiesOptionError( + subconfig, + ["frozen"], + self, + ) return False - #____________________________________________________________ + + # ____________________________________________________________ # read only/read write - def calc_read(self, - remove, - append, - config_bag, - ): + def calc_read( + self, + remove, + append, + config_bag, + ): props = self.get_personalize_properties() modified = False if remove & props: @@ -766,34 +859,41 @@ class Settings: modified = True return modified, frozenset(props) - def _read(self, - remove, - append, - config_bag, - ): - modified, props = self.calc_read(remove, - append, - config_bag, - ) + def _read( + self, + remove, + append, + config_bag, + ): + modified, props = self.calc_read( + remove, + append, + config_bag, + ) if modified: - self.set_context_properties(props, - config_bag.context, - ) + self.set_context_properties( + props, + config_bag.context, + ) - def read_only(self, - config_bag, - ): + def read_only( + self, + config_bag, + ): "convenience method to freeze, hide and disable" - self._read(self.ro_remove, - self.ro_append, - config_bag, - ) + self._read( + self.ro_remove, + self.ro_append, + config_bag, + ) - def read_write(self, - config_bag, - ): + def read_write( + self, + config_bag, + ): "convenience method to freeze, hide and disable" - self._read(self.rw_remove, - self.rw_append, - config_bag, - ) + self._read( + self.rw_remove, + self.rw_append, + config_bag, + ) diff --git a/tiramisu/todict.py b/tiramisu/todict.py index dd9d2fe..47a0eb5 100644 --- a/tiramisu/todict.py +++ b/tiramisu/todict.py @@ -6,23 +6,27 @@ from copy import copy from itertools import chain from .error import ValueWarning, ValueErrorWarning, PropertiesOptionError, ConfigError from .setting import undefined -#from .option.syndynoption import SynDynOption + +# from .option.syndynoption import SynDynOption from . import RegexpOption, ChoiceOption, ParamOption from .i18n import _ -CONVERT_WEB_TYPE = {'bool': 'boolean', - 'str': 'string', - 'int': 'integer', - } -INPUTS = ['string', - 'integer', - 'filename', - 'password', - 'email', - 'username', - 'ip', - 'domainname'] +CONVERT_WEB_TYPE = { + "bool": "boolean", + "str": "string", + "int": "integer", +} +INPUTS = [ + "string", + "integer", + "filename", + "password", + "email", + "username", + "ip", + "domainname", +] # return always warning (even if same warning is already returned) @@ -37,42 +41,50 @@ class Callbacks(object): self.remotable = tiramisu_web.remotable self.callbacks = [] - def add(self, + def add(self, path, childapi, schema, force_store_value): + if self.remotable == "all" or childapi.isoptiondescription(): + return + + # callback, callback_params = childapi.callbacks() + # if callback is None: # FIXME ? and force_store_value and self.clearable != 'all': + # return + # self.callbacks.append((callback, callback_params, path, childapi, schema, force_store_value)) + + def process_properties(self, form): + for ( + callback, + callback_params, path, childapi, schema, - force_store_value): - if self.remotable == 'all' or childapi.isoptiondescription(): - return -# callback, callback_params = childapi.callbacks() -# if callback is None: # FIXME ? and force_store_value and self.clearable != 'all': -# return -# self.callbacks.append((callback, callback_params, path, childapi, schema, force_store_value)) - - def process_properties(self, form): - for callback, callback_params, path, childapi, schema, force_store_value in self.callbacks: + force_store_value, + ) in self.callbacks: if childapi.isfollower(): self.tiramisu_web.set_remotable(path, form, childapi) continue has_option = False if callback_params is not None: - for callback_param in chain(callback_params.args, callback_params.kwargs.values()): + for callback_param in chain( + callback_params.args, callback_params.kwargs.values() + ): if isinstance(callback_param, ParamOption): has_option = True - if 'expire' in childapi.properties(): - self.tiramisu_web.set_remotable(callback_param.impl_getpath(), form) - if not has_option and form.get(path, {}).get('remote', False) == False: - if 'expire' in childapi.properties(): + if "expire" in childapi.properties(): + self.tiramisu_web.set_remotable( + callback_param.impl_getpath(), form + ) + if not has_option and form.get(path, {}).get("remote", False) == False: + if "expire" in childapi.properties(): self.tiramisu_web.set_remotable(path, form, childapi) elif childapi.owner.isdefault(): # get calculated value and set clearable - schema[path]['value'] = childapi.value.get() - if self.clearable == 'minimum': - form.setdefault(path, {})['clearable'] = True + schema[path]["value"] = childapi.value.get() + if self.clearable == "minimum": + form.setdefault(path, {})["clearable"] = True def manage_callbacks(self, form): pass - #for callback, callback_params, path, childapi, schema, force_store_value in self.callbacks: + # for callback, callback_params, path, childapi, schema, force_store_value in self.callbacks: # if callback_params is not None: # for callback_param in chain(callback_params.args, callback_params.kwargs.values()): # if isinstance(callback_param, ParamOption) and callback.__name__ == 'tiramisu_copy': @@ -81,8 +93,7 @@ class Callbacks(object): # form.setdefault(opt_path, {}) # form[opt_path].setdefault('copy', []).append(path) - def process(self, - form): + def process(self, form): self.process_properties(form) self.manage_callbacks(form) @@ -97,7 +108,7 @@ class Consistencies(object): if not childapi.isoptiondescription(): for consistency in childapi.consistencies(): cons_id, func, all_cons_opts, params = consistency - if func == '_cons_not_equal' and params.get('transitive', True) is True: + if func == "_cons_not_equal" and params.get("transitive", True) is True: options_path = [] for option in all_cons_opts: options_path.append(option()._path) @@ -105,8 +116,12 @@ class Consistencies(object): option = option() paths = options_path.copy() paths.pop(idx) - warnings_only = params.get('warnings_only') or getattr(option, '_warnings_only', False) - self.not_equal.setdefault(option._path, {}).setdefault(warnings_only, []).extend(paths) + warnings_only = params.get("warnings_only") or getattr( + option, "_warnings_only", False + ) + self.not_equal.setdefault(option._path, {}).setdefault( + warnings_only, [] + ).extend(paths) else: for option in all_cons_opts: self.tiramisu_web.set_remotable(option()._path, form) @@ -119,12 +134,12 @@ class Consistencies(object): form[path] = {} for warnings_only in self.not_equal[path]: options = self.not_equal[path][warnings_only] - if 'not_equal' not in form[path]: - form[path]['not_equal'] = [] - obj = {'options': options} + if "not_equal" not in form[path]: + form[path]["not_equal"] = [] + obj = {"options": options} if warnings_only: - obj['warnings'] = True - form[path]['not_equal'].append(obj) + obj["warnings"] = True + form[path]["not_equal"].append(obj) class Requires(object): @@ -140,157 +155,189 @@ class Requires(object): else: isfollower = childapi.isfollower() if isfollower: - parent_path = path.rsplit('.', 1)[0] + parent_path = path.rsplit(".", 1)[0] parent = self.tiramisu_web.config.unrestraint.option(parent_path) leader = parent.list()[0] self.tiramisu_web.set_remotable(leader.path(), form, leader) - def manage_requires(self, - childapi, - path, - form, - current_action, - ): + def manage_requires( + self, + childapi, + path, + form, + current_action, + ): for requires in childapi.property.get(uncalculated=True): if not isinstance(requires, str): - option = requires.params.kwargs['condition'].option - expected = [requires.params.kwargs['expected'].value] + option = requires.params.kwargs["condition"].option + expected = [requires.params.kwargs["expected"].value] action = requires.params.args[0].value - if 'reverse_condition' in requires.params.kwargs: - inverse = requires.params.kwargs['reverse_condition'].value + if "reverse_condition" in requires.params.kwargs: + inverse = requires.params.kwargs["reverse_condition"].value else: inverse = False transitive = True same_action = True - operator = 'or' + operator = "or" if 1 == 1: -# len_to_long = len(requires) > 1 -# for require in requires: -# options, action, inverse, transitive, same_action, operator = require -# if not len_to_long: -# len_to_long = len(options) > 1 -# for option, expected in options: + # len_to_long = len(requires) > 1 + # for require in requires: + # options, action, inverse, transitive, same_action, operator = require + # if not len_to_long: + # len_to_long = len(options) > 1 + # for option, expected in options: if isinstance(option, tuple): - for option_param in chain(option[1].args, option[1].kwargs.values()): + for option_param in chain( + option[1].args, option[1].kwargs.values() + ): if isinstance(option_param, ParamOption): - self.tiramisu_web.set_remotable(option_param.option.impl_getpath(), form) + self.tiramisu_web.set_remotable( + option_param.option.impl_getpath(), form + ) self.set_master_remote(childapi, path, form) -# elif len_to_long: -# self.tiramisu_web.set_remotable(option.impl_getpath(), form) -# self.set_master_remote(childapi, path, form) + # elif len_to_long: + # self.tiramisu_web.set_remotable(option.impl_getpath(), form) + # self.set_master_remote(childapi, path, form) else: option_path = option.impl_getpath() if action in self.action_hide: - require_option = self.tiramisu_web.config.unrestraint.option(option_path) - if transitive is False or same_action is False or operator == 'and': + require_option = ( + self.tiramisu_web.config.unrestraint.option(option_path) + ) + if ( + transitive is False + or same_action is False + or operator == "and" + ): # transitive to "False" not supported yet for a requirement # same_action to "False" not supported yet for a requirement # operator "and" not supported yet for a requirement - self.tiramisu_web.set_remotable(option_path, form, require_option) + self.tiramisu_web.set_remotable( + option_path, form, require_option + ) self.set_master_remote(childapi, path, form) -# if require_option.option.requires(): -# for reqs in require_option.option.requires(): -# for req in reqs: -# for subopt, subexp in req[0]: -# if not isinstance(subopt, tuple): -# self.tiramisu_web.set_remotable(subopt.impl_getpath(), form) -# self.set_master_remote(childapi, path, form) + # if require_option.option.requires(): + # for reqs in require_option.option.requires(): + # for req in reqs: + # for subopt, subexp in req[0]: + # if not isinstance(subopt, tuple): + # self.tiramisu_web.set_remotable(subopt.impl_getpath(), form) + # self.set_master_remote(childapi, path, form) if inverse: - act = 'show' - inv_act = 'hide' + act = "show" + inv_act = "hide" else: - act = 'hide' - inv_act = 'show' + act = "hide" + inv_act = "show" if isinstance(option, ChoiceOption): - require_option = self.tiramisu_web.config.unrestraint.option(option_path) - values = self.tiramisu_web.get_enum(require_option, - require_option.ismulti(), - option_path, - require_option.property.get()) + require_option = ( + self.tiramisu_web.config.unrestraint.option( + option_path + ) + ) + values = self.tiramisu_web.get_enum( + require_option, + require_option.ismulti(), + option_path, + require_option.property.get(), + ) for value in values: if value not in expected: - self.requires.setdefault(path, - {'expected': {}} - )['expected'].setdefault(value, - {}).setdefault(inv_act, - []).append(option_path) + self.requires.setdefault( + path, {"expected": {}} + )["expected"].setdefault(value, {}).setdefault( + inv_act, [] + ).append( + option_path + ) if current_action is None: current_action = action elif current_action != action: self.tiramisu_web.set_remotable(option_path, form) self.set_master_remote(childapi, path, form) for exp in expected: - self.requires.setdefault(path, - {'expected': {}} - )['expected'].setdefault(exp, - {}).setdefault(act, - []).append(option_path) - self.requires[path].setdefault('default', {}).setdefault(inv_act, []).append(option_path) + self.requires.setdefault(path, {"expected": {}})[ + "expected" + ].setdefault(exp, {}).setdefault(act, []).append( + option_path + ) + self.requires[path].setdefault("default", {}).setdefault( + inv_act, [] + ).append(option_path) else: self.tiramisu_web.set_remotable(option_path, form) self.set_master_remote(childapi, path, form) def add(self, path, childapi, form): - #collect id of all options + # collect id of all options child = childapi.get() -# if isinstance(child, SynDynOption): -# child = child.opt + # if isinstance(child, SynDynOption): + # child = child.opt self.options[child] = path current_action = None - self.manage_requires(childapi, - path, - form, - current_action, - ) + self.manage_requires( + childapi, + path, + form, + current_action, + ) def process(self, form): dependencies = {} for path, values in self.requires.items(): - if 'default' in values: - for option in values['default'].get('show', []): + if "default" in values: + for option in values["default"].get("show", []): if path == option: self.tiramisu_web.set_remotable(path, form) if not self.tiramisu_web.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', []): + 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: self.tiramisu_web.set_remotable(path, form) if not self.tiramisu_web.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(): + 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', []): + expected = "" + for option in actions.get("show", []): if path == option: self.tiramisu_web.set_remotable(path, form) if not self.tiramisu_web.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', []): + 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: self.tiramisu_web.set_remotable(path, form) if not self.tiramisu_web.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) + 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.setdefault(path, {})['dependencies'] = dependency + form.setdefault(path, {})["dependencies"] = dependency class TiramisuDict: @@ -309,67 +356,64 @@ class TiramisuDict: # owner # properties - def __init__(self, - config, - root=None, - clearable="all", - remotable="minimum"): + def __init__(self, config, root=None, clearable="all", remotable="minimum"): self.config = config self.root = root self.requires = None self.callbacks = None self.consistencies = None - #all, minimum, none + # all, minimum, none self.clearable = clearable - #all, minimum, none + # all, minimum, none self.remotable = remotable - def add_help(self, - obj, - childapi): - hlp = childapi.information.get('help', None) + def add_help(self, obj, childapi): + hlp = childapi.information.get("help", None) if hlp is not None: - obj['help'] = hlp + obj["help"] = hlp def get_list(self, root, subchildapi): - #ret = [] + # ret = [] for childapi in subchildapi.list(): childname = childapi.name() if root is None: path = childname else: - path = root + '.' + childname + path = root + "." + childname yield (path, childapi) - #return ret + # return ret def is_remote(self, path, form): - if self.remotable == 'all': + if self.remotable == "all": return True else: - return path in form and form[path].get('remote', False) == True + return path in form and form[path].get("remote", False) == True def set_remotable(self, path, form, childapi=None): - if self.remotable == 'none': - raise ValueError(_('option {} only works when remotable is not "none"').format(path)) - form.setdefault(path, {})['remote'] = True + if self.remotable == "none": + raise ValueError( + _('option {} only works when remotable is not "none"').format(path) + ) + form.setdefault(path, {})["remote"] = True if childapi is None: childapi = self.config.unrestraint.option(path) if childapi.isfollower(): - parent_path = path.rsplit('.', 1)[0] + parent_path = path.rsplit(".", 1)[0] parent = self.config.unrestraint.option(parent_path) leader = parent.list()[0] - form.setdefault(leader.path(), {})['remote'] = True + form.setdefault(leader.path(), {})["remote"] = True - def walk(self, - root, - subchildapi, - schema, - model, - form, - order, - updates_status, - init=False, - ): + def walk( + self, + root, + subchildapi, + schema, + model, + form, + order, + updates_status, + init=False, + ): error = None if init: if form is not None: @@ -397,55 +441,63 @@ class TiramisuDict: else: props_no_requires = set(childapi.property.get()) if form is not None: - self.requires.add(path, - childapi, - form, - ) - self.consistencies.add(path, - childapi, - form, - ) - self.callbacks.add(path, - childapi, - schema, - 'force_store_value' in props_no_requires, - ) - if model is not None and childapi.isoptiondescription() or not childapi.issymlinkoption(): - self.gen_model(model, - childapi, - path, - leader_len, - updates_status, - ) + self.requires.add( + path, + childapi, + form, + ) + self.consistencies.add( + path, + childapi, + form, + ) + self.callbacks.add( + path, + childapi, + schema, + "force_store_value" in props_no_requires, + ) + if ( + model is not None + and childapi.isoptiondescription() + or not childapi.issymlinkoption() + ): + self.gen_model( + model, + childapi, + path, + leader_len, + updates_status, + ) if order is not None: order.append(path) if childapi.isoptiondescription(): - web_type = 'optiondescription' + web_type = "optiondescription" if childapi.isleadership(): - type_ = 'array' + type_ = "array" else: - type_ = 'object' + type_ = "object" if schema is not None: - schema[path] = {'properties': {}, - 'type': type_} - subschema = schema[path]['properties'] + schema[path] = {"properties": {}, "type": type_} + subschema = schema[path]["properties"] else: subschema = schema - self.walk(path, - childapi, - subschema, - model, - form, - order, - updates_status, - ) + self.walk( + path, + childapi, + subschema, + model, + form, + order, + updates_status, + ) else: child = childapi.get() childtype = child.__class__.__name__ - if childtype == 'SynDynOption': + if childtype == "SynDynOption": childtype = child.opt.__class__.__name__ if childapi.issymlinkoption(): - web_type = 'symlink' + web_type = "symlink" value = None defaultmulti = None is_multi = False @@ -464,31 +516,33 @@ class TiramisuDict: else: defaultmulti = None if schema is not None: - self.gen_schema(schema, - childapi, - path, - props_no_requires, - value, - defaultmulti, - is_multi, - web_type, - form, - ) + self.gen_schema( + schema, + childapi, + path, + props_no_requires, + value, + defaultmulti, + is_multi, + web_type, + form, + ) if form is not None: - self.gen_form(form, - web_type, - path, - child, - childapi, - childtype, - ) + self.gen_form( + form, + web_type, + path, + child, + childapi, + childtype, + ) if schema is not None: - if web_type != 'symlink': - schema[path]['title'] = childapi.description() - self.add_help(schema[path], - childapi) + if web_type != "symlink": + schema[path]["title"] = childapi.description() + self.add_help(schema[path], childapi) except Exception as err: import traceback + traceback.print_exc() if not init: raise err @@ -503,186 +557,193 @@ class TiramisuDict: if error: msg = str(error) del error - raise ConfigError(_('unable to transform tiramisu object to dict: {}').format(msg)) + raise ConfigError( + _("unable to transform tiramisu object to dict: {}").format(msg) + ) - - def gen_schema(self, - schema, - childapi, - path, - props_no_requires, - value, - defaultmulti, - is_multi, - web_type, - form, - ): - schema[path] = {'type': web_type} + def gen_schema( + self, + schema, + childapi, + path, + props_no_requires, + value, + defaultmulti, + is_multi, + web_type, + form, + ): + schema[path] = {"type": web_type} if childapi.issymlinkoption(): sym_option = childapi.get() - schema[path]['opt_path'] = sym_option.impl_getopt().impl_getpath() + schema[path]["opt_path"] = sym_option.impl_getopt().impl_getpath() else: if defaultmulti is not None: - schema[path]['defaultmulti'] = defaultmulti + schema[path]["defaultmulti"] = defaultmulti if is_multi: - schema[path]['isMulti'] = is_multi + schema[path]["isMulti"] = is_multi if childapi.issubmulti(): - schema[path]['isSubMulti'] = True + schema[path]["isSubMulti"] = True - if 'auto_freeze' in props_no_requires: - schema[path]['autoFreeze'] = True + if "auto_freeze" in props_no_requires: + schema[path]["autoFreeze"] = True - if web_type == 'choice': - #values, values_params = childapi.value.callbacks() - #if values_params: + if web_type == "choice": + # values, values_params = childapi.value.callbacks() + # if values_params: # for values_param in chain(values_params.args, values_params.kwargs.values()): # if isinstance(values_param, ParamOption): # self.set_remotable(path, form, childapi) # return - schema[path]['enum'] = self.get_enum(childapi, - is_multi, - path, - props_no_requires) + schema[path]["enum"] = self.get_enum( + childapi, is_multi, path, props_no_requires + ) if value is not None and not self.is_remote(path, form): - schema[path]['value'] = value + schema[path]["value"] = value - - def get_enum(self, - childapi, - is_multi, - path, - props_no_requires, - ): + def get_enum( + self, + childapi, + is_multi, + path, + props_no_requires, + ): values = childapi.value.list() empty_is_required = not childapi.isfollower() and is_multi - if '' not in values and ((empty_is_required and not 'empty' in props_no_requires) or \ - (not empty_is_required and not 'mandatory' in props_no_requires)): - values = [''] + list(values) + if "" not in values and ( + (empty_is_required and not "empty" in props_no_requires) + or (not empty_is_required and not "mandatory" in props_no_requires) + ): + values = [""] + list(values) return values - def gen_form(self, - form, - web_type, - path, - child, - childapi, - childtype, - ): + def gen_form( + self, + form, + web_type, + path, + child, + childapi, + childtype, + ): obj_form = {} if path in form: obj_form.update(form[path]) if not childapi.issymlinkoption(): - #if childapi_option.validator() != (None, None): + # if childapi_option.validator() != (None, None): # obj_form['remote'] = True # params = childapi_option.validator()[1] # if params is not None: # for param in chain(params.args, params.kwargs.values()): # if isinstance(param, ParamOption): # self.set_remotable(param.option.impl_getpath(), form) - if self.clearable == 'all': - obj_form['clearable'] = True - if self.clearable != 'none': - obj_form['clearable'] = True - if self.remotable == 'all' or childapi.has_dependency(): - obj_form['remote'] = True - if childtype == 'IPOption' and (child.impl_get_extra('_private_only') or not child.impl_get_extra('_allow_reserved') or child.impl_get_extra('_cidr')): - obj_form['remote'] = True - if childtype == 'DateOption': - obj_form['remote'] = True - if not obj_form.get('remote', False): + if self.clearable == "all": + obj_form["clearable"] = True + if self.clearable != "none": + obj_form["clearable"] = True + if self.remotable == "all" or childapi.has_dependency(): + obj_form["remote"] = True + if childtype == "IPOption" and ( + child.impl_get_extra("_private_only") + or not child.impl_get_extra("_allow_reserved") + or child.impl_get_extra("_cidr") + ): + obj_form["remote"] = True + if childtype == "DateOption": + obj_form["remote"] = True + if not obj_form.get("remote", False): pattern = childapi.pattern() if pattern is not None: - obj_form['pattern'] = pattern - if childtype == 'PortOption': - obj_form['min'] = child.impl_get_extra('_min_value') - obj_form['max'] = child.impl_get_extra('_max_value') - if childtype == 'FloatOption': - obj_form['step'] = 'any' - if web_type == 'choice': - obj_form['type'] = 'choice' + obj_form["pattern"] = pattern + if childtype == "PortOption": + obj_form["min"] = child.impl_get_extra("_min_value") + obj_form["max"] = child.impl_get_extra("_max_value") + if childtype == "FloatOption": + obj_form["step"] = "any" + if web_type == "choice": + obj_form["type"] = "choice" elif web_type in INPUTS: - obj_form['type'] = 'input' + obj_form["type"] = "input" if obj_form: form[path] = obj_form - def calc_raises_properties(self, - obj, - childapi, - ): + def calc_raises_properties( + self, + obj, + childapi, + ): old_properties = childapi._config_bag.properties config = childapi._config_bag.context settings = config.get_settings() - childapi._config_bag.properties = self.config.property.default('current') # settings.get_context_properties(config._impl_properties_cache) - childapi._config_bag.properties -= {'permissive'} - properties = childapi.property.get(only_raises=True, - uncalculated=True, - ) + childapi._config_bag.properties = self.config.property.default( + "current" + ) # settings.get_context_properties(config._impl_properties_cache) + childapi._config_bag.properties -= {"permissive"} + properties = childapi.property.get( + only_raises=True, + uncalculated=True, + ) properties -= childapi.permissive.get() # 'hidden=True' means cannot access with or without permissive option # 'display=False' means cannot access only without permissive option if properties: - obj['display'] = False + obj["display"] = False properties -= self.config.permissive.get() if properties: - obj['hidden'] = True + obj["hidden"] = True childapi._config_bag.properties = old_properties - def _gen_model_properties(self, - childapi, - path, - index, - ): + def _gen_model_properties( + self, + childapi, + path, + index, + ): isfollower = childapi.isfollower() props = set(childapi.property.get()) - obj = self.gen_properties(props, - isfollower, - childapi.ismulti(), - index) + obj = self.gen_properties(props, isfollower, childapi.ismulti(), index) self.calc_raises_properties(obj, childapi) return obj - def gen_properties(self, - properties, - isfollower, - ismulti, - index): + def gen_properties(self, properties, isfollower, ismulti, index): obj = {} if not isfollower and ismulti: - if 'empty' in properties: + if "empty" in properties: if index is None: - obj['required'] = True - properties.remove('empty') - if 'mandatory' in properties: + obj["required"] = True + properties.remove("empty") + if "mandatory" in properties: if index is None: - obj['needs_len'] = True - properties.remove('mandatory') - elif 'mandatory' in properties: + obj["needs_len"] = True + properties.remove("mandatory") + elif "mandatory" in properties: if index is None: - obj['required'] = True - properties.remove('mandatory') - if 'frozen' in properties: + obj["required"] = True + properties.remove("mandatory") + if "frozen" in properties: if index is None: - obj['readOnly'] = True - properties.remove('frozen') - if 'hidden' in properties: - properties.remove('hidden') - if 'disabled' in properties: - properties.remove('disabled') + obj["readOnly"] = True + properties.remove("frozen") + if "hidden" in properties: + properties.remove("hidden") + if "disabled" in properties: + properties.remove("disabled") if properties: lprops = list(properties) lprops.sort() - obj['properties'] = lprops + obj["properties"] = lprops return obj - def gen_model(self, - model, - childapi, - path, - leader_len, - updates_status, - ): + def gen_model( + self, + model, + childapi, + path, + leader_len, + updates_status, + ): if childapi.isoptiondescription(): props = set(childapi.property.get()) obj = {} @@ -690,117 +751,114 @@ class TiramisuDict: if props: lprops = list(props) lprops.sort() - obj['properties'] = lprops + obj["properties"] = lprops try: self.config.option(path).get() except PropertiesOptionError: pass else: - obj = self._gen_model_properties(childapi, - path, - None, - ) + obj = self._gen_model_properties( + childapi, + path, + None, + ) if childapi.isfollower(): for index in range(leader_len): follower_childapi = self.config.unrestraint.option(path, index) - sobj = self._gen_model_properties(follower_childapi, - path, - index, - ) - self._get_model_value(follower_childapi, - path, - sobj, - index, - updates_status, - ) + sobj = self._gen_model_properties( + follower_childapi, + path, + index, + ) + 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, - ) + self._get_model_value( + childapi, + path, + obj, + None, + updates_status, + ) if obj: if not childapi.isoptiondescription() and childapi.isfollower(): - model.setdefault(path, {})['null'] = obj + model.setdefault(path, {})["null"] = obj else: model[path] = obj - def _get_model_value(self, - childapi, - path, - obj, - index, - updates_status, - ): + def _get_model_value( + self, + childapi, + path, + obj, + index, + updates_status, + ): if path in updates_status and index in updates_status[path]: value = childapi.value.get() - self._get_value_with_exception(obj, - childapi, - updates_status[path][index]) + self._get_value_with_exception(obj, childapi, updates_status[path][index]) del updates_status[path][index] else: try: with warnings.catch_warnings(record=True) as warns: value = self.config.option(path, index=index).value.get() - self._get_value_with_exception(obj, - childapi, - warns) + self._get_value_with_exception(obj, childapi, warns) except ValueError as err: - self._get_value_with_exception(obj, - childapi, - [err]) + self._get_value_with_exception(obj, childapi, [err]) value = self.config.unrestraint.option(path, index=index).value.get() except PropertiesOptionError as err: config_bag = self.config._config_bag settings = config_bag.context.get_settings() - if settings._calc_raises_properties(childapi._subconfig, - set(err.proptype), - not_unrestraint=True, - ): - obj['hidden'] = True - obj['display'] = False + if settings._calc_raises_properties( + childapi._subconfig, + set(err.proptype), + not_unrestraint=True, + ): + obj["hidden"] = True + obj["display"] = False value = childapi.value.get() if value is not None and value != []: - obj['value'] = value + obj["value"] = value if not childapi.owner.isdefault(): - obj['owner'] = childapi.owner.get() + obj["owner"] = childapi.owner.get() - def _get_value_with_exception(self, - obj, - childapi, - values): + def _get_value_with_exception(self, obj, childapi, values): for value in values: if isinstance(value, ValueError): - obj.setdefault('error', []) + obj.setdefault("error", []) msg = str(value) - if msg not in obj.get('error', []): - obj['error'].append(msg) - obj['invalid'] = True + if msg not in obj.get("error", []): + obj["error"].append(msg) + obj["invalid"] = True elif isinstance(value.message, ValueErrorWarning): - value.message.prefix = '' - obj.setdefault('error', []) + value.message.prefix = "" + obj.setdefault("error", []) msg = str(value.message) - if msg not in obj.get('error', []): - obj['error'].append(msg) - obj['invalid'] = True + if msg not in obj.get("error", []): + obj["error"].append(msg) + obj["invalid"] = True else: - value.message.prefix = '' - obj.setdefault('warnings', []) + value.message.prefix = "" + obj.setdefault("warnings", []) msg = str(value.message) - if msg not in obj.get('error', []): - obj['warnings'].append(msg) - obj['hasWarnings'] = True + if msg not in obj.get("error", []): + obj["warnings"].append(msg) + obj["hasWarnings"] = True def gen_global(self): ret = {} - ret['owner'] = self.config.owner.get() - ret['properties'] = list(self.config.property.get()) - ret['properties'].sort() - ret['permissives'] = list(self.config.permissive.get()) - ret['permissives'].sort() + ret["owner"] = self.config.owner.get() + ret["properties"] = list(self.config.property.get()) + ret["properties"].sort() + ret["permissives"] = list(self.config.permissive.get()) + ret["permissives"].sort() return ret def get_form(self, form): @@ -808,17 +866,17 @@ class TiramisuDict: buttons = [] dict_form = {} 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' + 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_)) + raise ValueError(_("unknown form {}").format(form_)) for key, form_ in self.form.items(): - form_['key'] = key + form_["key"] = key if key in dict_form: form_.update(dict_form[key]) ret.append(form_) @@ -851,77 +909,94 @@ class TiramisuDict: multi[index] = value childapi.value.set(multi) - def apply_updates(self, - oripath, - updates, - model_ori, - ): + def apply_updates( + self, + oripath, + updates, + model_ori, + ): updates_status = {} for update in updates: - path = update['name'] - index = update.get('index') + path = update["name"] + index = update.get("index") if oripath is not None and not path.startswith(oripath): - raise ValueError(_('not in current area')) + raise ValueError(_("not in current area")) childapi = self.config.option(path) if childapi.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', undefined), - ) - elif update['action'] == 'delete': - self.del_value(childapi, - path, - index, - ) - elif update['action'] == 'add': + if update["action"] == "modify": + self.mod_value( + childapi, + path, + index, + update.get("value", undefined), + ) + elif update["action"] == "delete": + self.del_value( + childapi, + path, + index, + ) + elif update["action"] == "add": if childapi.ismulti(): - self.add_value(childapi, path, update['value']) + self.add_value(childapi, path, update["value"]) else: - raise ValueError(_('only multi option can have action "add", but "{}" is not a multi').format(path)) + raise ValueError( + _( + 'only multi option can have action "add", but "{}" is not a multi' + ).format(path) + ) else: - raise ValueError(_('unknown action {}').format(update['action'])) + raise ValueError( + _("unknown action {}").format(update["action"]) + ) except ValueError as err: updates_status.setdefault(path, {})[index] = [err] if warns != []: updates_status.setdefault(path, {}).setdefault(index, []).extend(warns) return updates_status - def set_updates(self, - body, - ): + 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: + 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, - ) - values = {'updates': list_keys(old_model, new_model['model'], order, updates_status), - 'model': new_model['model']} + old_model = body["model"] + new_model = self.todict( + order=order, + build_schema=False, + build_form=False, + updates_status=updates_status, + ) + values = { + "updates": list_keys( + old_model, new_model["model"], order, updates_status + ), + "model": new_model["model"], + } else: values = updates_status return values - def todict(self, - custom_form=[], - build_schema=True, - build_model=True, - build_form=True, - order=None, - updates_status={}, - ): + 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 = {} @@ -936,34 +1011,35 @@ class TiramisuDict: buttons = [] else: form = None - self.walk(rootpath, - None, - schema, - model, - form, - order, - updates_status, - init=True, - ) + 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') + if "key" in form_: + key = form_.pop("key") form.setdefault(key, {}).update(form_) - elif form_.get('type') == 'submit': + 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_)) + raise ValueError(_("unknown form {}").format(form_)) ret = {} if build_schema: - ret['schema'] = schema + ret["schema"] = schema if build_model: - ret['model'] = model - ret['global'] = self.gen_global() + ret["model"] = model + ret["global"] = self.gen_global() if build_form: - ret['form'] = form - ret['version'] = '1.0' + ret["form"] = form + ret["version"] = "1.0" return ret @@ -986,9 +1062,11 @@ def list_keys(model_a, model_b, ordered_key, updates_status): 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) diff --git a/tiramisu/value.py b/tiramisu/value.py index 6a956f5..214ff10 100644 --- a/tiramisu/value.py +++ b/tiramisu/value.py @@ -26,15 +26,18 @@ class Values: """This class manage value (default value, stored value or calculated value It's also responsible of a caching utility. """ - # pylint: disable=too-many-public-methods - __slots__ = ('_values', - '_informations', - '__weakref__', - ) - def __init__(self, - default_values: Union[None, dict]=None, - ) -> None: + # pylint: disable=too-many-public-methods + __slots__ = ( + "_values", + "_informations", + "__weakref__", + ) + + def __init__( + self, + default_values: Union[None, dict] = None, + ) -> None: """ Initializes the values's dict. @@ -47,11 +50,12 @@ class Values: default_values = {None: {None: [None, owners.user]}} self._values = default_values - #______________________________________________________________________ + # ______________________________________________________________________ # get value - def get_cached_value(self, - subconfig: "SubConfig", - ) -> Any: + def get_cached_value( + self, + subconfig: "SubConfig", + ) -> Any: """get value directly in cache if set otherwise calculated value and set it in cache @@ -60,60 +64,72 @@ class Values: # try to retrive value in cache setting_properties = subconfig.config_bag.properties cache = subconfig.config_bag.context.get_values_cache() - is_cached, value, validated = cache.getcache(subconfig, - 'values', - ) + is_cached, value, validated = cache.getcache( + subconfig, + "values", + ) # no cached value so get value if not is_cached: value, has_calculation = self.get_value(subconfig) # validates and warns value if not validated: - validate = subconfig.option.impl_validate(subconfig, - value, - check_error=True, - ) - if 'warnings' in setting_properties: - subconfig.option.impl_validate(subconfig, - value, - check_error=False, - ) + validate = subconfig.option.impl_validate( + subconfig, + value, + check_error=True, + ) + if "warnings" in setting_properties: + subconfig.option.impl_validate( + subconfig, + value, + check_error=False, + ) # set value to cache if not is_cached and not has_calculation: - cache.setcache(subconfig, - value, - validated=validate, - ) + cache.setcache( + subconfig, + value, + validated=validate, + ) if isinstance(value, list): # return a copy, so value cannot be modified value = value.copy() # and return it return value - def get_value(self, - subconfig: "SubConfig", - ) -> Any: + def get_value( + self, + subconfig: "SubConfig", + ) -> Any: """actually retrieves the stored value or the default value (value modified by user) :returns: value """ # get owner and value from store default_value = [undefined, owners.default] - value, owner = self._values.get(subconfig.path, {}).get(subconfig.index, default_value) - if owner == owners.default or \ - ('frozen' in subconfig.properties and \ - ('force_default_on_freeze' in subconfig.properties or \ - self.check_force_to_metaconfig(subconfig))): + value, owner = self._values.get(subconfig.path, {}).get( + subconfig.index, default_value + ) + if owner == owners.default or ( + "frozen" in subconfig.properties + and ( + "force_default_on_freeze" in subconfig.properties + or self.check_force_to_metaconfig(subconfig) + ) + ): # the value is a default value # get it value = self.get_default_value(subconfig) - value, has_calculation = get_calculated_value(subconfig, - value, - ) + value, has_calculation = get_calculated_value( + subconfig, + value, + ) return value, has_calculation - def get_default_value(self, - subconfig: "SubConfig", - ) -> Any: + def get_default_value( + self, + subconfig: "SubConfig", + ) -> Any: """get default value: - get parents config value or - get calculated value or @@ -122,15 +138,24 @@ class Values: msubconfig = self._get_modified_parent(subconfig) if msubconfig is not None: # retrieved value from parent config - return msubconfig.config_bag.context.get_values().get_cached_value(msubconfig) + return msubconfig.config_bag.context.get_values().get_cached_value( + msubconfig + ) # now try to get calculated value: - value, _has_calculation = get_calculated_value(subconfig, - subconfig.option.impl_getdefault(), - ) - if subconfig.index is not None and isinstance(value, (list, tuple)) \ - and (not subconfig.option.impl_is_submulti() or \ - not value or isinstance(value[0], list)): + value, _has_calculation = get_calculated_value( + subconfig, + subconfig.option.impl_getdefault(), + ) + if ( + subconfig.index is not None + and isinstance(value, (list, tuple)) + and ( + not subconfig.option.impl_is_submulti() + or not value + or isinstance(value[0], list) + ) + ): # if index (so slave), must return good value for this index # for submulti, first index is a list, assume other data are list too index = subconfig.index @@ -139,46 +164,50 @@ class Values: else: # no value for this index, retrieve default multi value # default_multi is already a list for submulti - value, _has_calculation = get_calculated_value(subconfig, - subconfig.option.impl_getdefault_multi(), - ) - self.reset_cache_after_calculation(subconfig, - value, - ) + value, _has_calculation = get_calculated_value( + subconfig, + subconfig.option.impl_getdefault_multi(), + ) + self.reset_cache_after_calculation( + subconfig, + value, + ) return value - #______________________________________________________________________ - def check_force_to_metaconfig(self, - subconfig: "OptionBag", - ) -> bool: - """Check if the value must be retrieve from parent metaconfig or not - """ + # ______________________________________________________________________ + def check_force_to_metaconfig( + self, + subconfig: "OptionBag", + ) -> bool: + """Check if the value must be retrieve from parent metaconfig or not""" # force_metaconfig_on_freeze is set to an option and context is a kernelconfig # => to metaconfig # force_metaconfig_on_freeze is set *explicitly* to an option and context is a # kernelmetaconfig => to sub metaconfig - if 'force_metaconfig_on_freeze' in subconfig.properties: + if "force_metaconfig_on_freeze" in subconfig.properties: settings = subconfig.config_bag.context.get_settings() - if subconfig.config_bag.context.impl_type == 'config': + if subconfig.config_bag.context.impl_type == "config": return True # it's a not a config, force to metaconfig only in *explicitly* set - return 'force_metaconfig_on_freeze' in settings.get_stored_properties(subconfig.path, - subconfig.index, - frozenset(), - ) + return "force_metaconfig_on_freeze" in settings.get_stored_properties( + subconfig.path, + subconfig.index, + frozenset(), + ) return False - def reset_cache_after_calculation(self, - subconfig, - value, - ): - """if value is modification after calculation, invalid cache - """ + def reset_cache_after_calculation( + self, + subconfig, + value, + ): + """if value is modification after calculation, invalid cache""" cache = subconfig.config_bag.context.get_values_cache() - is_cache, cache_value, _ = cache.getcache(subconfig, - 'values', - expiration=False, - ) + is_cache, cache_value, _ = cache.getcache( + subconfig, + "values", + expiration=False, + ) if not is_cache or cache_value == value: # calculation return same value as previous value, # so do not invalidate cache @@ -186,17 +215,18 @@ class Values: # calculated value is a new value, so reset cache subconfig.config_bag.context.reset_cache(subconfig) # and manage force_store_value - self._set_force_value_identifier(subconfig, - value, - ) + self._set_force_value_identifier( + subconfig, + value, + ) - def isempty(self, - subconfig: "SubConfig", - value: Any, - force_allow_empty_list: bool, - ) -> bool: - """convenience method to know if an option is empty - """ + def isempty( + self, + subconfig: "SubConfig", + value: Any, + force_allow_empty_list: bool, + ) -> bool: + """convenience method to know if an option is empty""" index = subconfig.index option = subconfig.option if index is None and option.impl_is_submulti(): @@ -206,166 +236,199 @@ class Values: isempty = self._isempty_multi(val, force_allow_empty_list) if isempty: break - elif (index is None or \ - (index is not None and option.impl_is_submulti())) and \ - option.impl_is_multi(): + elif ( + index is None or (index is not None and option.impl_is_submulti()) + ) and option.impl_is_multi(): # it's a single list isempty = self._isempty_multi(value, force_allow_empty_list) else: - isempty = value is None or value == '' + isempty = value is None or value == "" return isempty - def _isempty_multi(self, - value: Any, - force_allow_empty_list: bool, - ) -> bool: + def _isempty_multi( + self, + value: Any, + force_allow_empty_list: bool, + ) -> bool: if not isinstance(value, list): return False - return (not force_allow_empty_list and value == []) or None in value or '' in value + return ( + (not force_allow_empty_list and value == []) or None in value or "" in value + ) - #______________________________________________________________________ + # ______________________________________________________________________ # set value - def set_value(self, - subconfig: "SubConfig", - value: Any, - ) -> None: - """set value to option - """ + def set_value( + self, + subconfig: "SubConfig", + value: Any, + ) -> None: + """set value to option""" owner = self.get_context_owner() setting_properties = subconfig.config_bag.properties ori_value = value - if 'validator' in setting_properties: - value, has_calculation = self.setvalue_validation(subconfig, - value, - ) + if "validator" in setting_properties: + value, has_calculation = self.setvalue_validation( + subconfig, + value, + ) elif isinstance(value, list): # copy value = value.copy() - self._setvalue(subconfig, - ori_value, - owner, - ) - if 'force_store_value' in setting_properties and subconfig.option.impl_is_leader(): + self._setvalue( + subconfig, + ori_value, + owner, + ) + if ( + "force_store_value" in setting_properties + and subconfig.option.impl_is_leader() + ): leader = subconfig.option.impl_get_leadership() parent = subconfig.parent parent._length = len(value) - leader.follower_force_store_value(value, - parent, - owners.forced, - ) - validator = 'validator' in setting_properties and \ - 'demoting_error_warning' not in setting_properties + leader.follower_force_store_value( + value, + parent, + owners.forced, + ) + validator = ( + "validator" in setting_properties + and "demoting_error_warning" not in setting_properties + ) if validator and not has_calculation: cache = subconfig.config_bag.context.get_values_cache() - cache.setcache(subconfig, - value, - validated=validator, - ) - elif 'validator' in setting_properties and has_calculation: + cache.setcache( + subconfig, + value, + validated=validator, + ) + elif "validator" in setting_properties and has_calculation: cache = subconfig.config_bag.context.get_values_cache() cache.delcache(subconfig.path) - def setvalue_validation(self, - subconfig: "SubConfig", - value: Any, - ): - """validate value before set value - """ + def setvalue_validation( + self, + subconfig: "SubConfig", + value: Any, + ): + """validate value before set value""" settings = subconfig.config_bag.context.get_settings() # First validate properties with this value opt = subconfig.option settings.validate_frozen(subconfig) - val, has_calculation = get_calculated_value(subconfig, - value, - ) - settings.validate_mandatory(subconfig, - val, - ) + val, has_calculation = get_calculated_value( + subconfig, + value, + ) + settings.validate_mandatory( + subconfig, + val, + ) # Value must be valid for option - opt.impl_validate(subconfig, - val, - check_error=True, - ) - if 'warnings' in subconfig.config_bag.properties: + opt.impl_validate( + subconfig, + val, + check_error=True, + ) + if "warnings" in subconfig.config_bag.properties: # No error found so emit warnings - opt.impl_validate(subconfig, - val, - check_error=False, - ) + opt.impl_validate( + subconfig, + val, + check_error=False, + ) return val, has_calculation - def _setvalue(self, - subconfig: "SubConfig", - value: Any, - owner: str, - ) -> None: + def _setvalue( + self, + subconfig: "SubConfig", + value: Any, + owner: str, + ) -> None: subconfig.config_bag.context.reset_cache(subconfig) - self.set_storage_value(subconfig.path, - subconfig.index, - value, - owner, - ) - self._set_force_value_identifier(subconfig, - value, - ) + self.set_storage_value( + subconfig.path, + subconfig.index, + value, + owner, + ) + self._set_force_value_identifier( + subconfig, + value, + ) - def set_storage_value(self, - path, - index, - value, - owner, - ): - """set a value - """ + def set_storage_value( + self, + path, + index, + value, + owner, + ): + """set a value""" self._values.setdefault(path, {})[index] = [value, owner] - def _set_force_value_identifier(self, - subconfig: 'SubConfig', - identifier_values, - ) -> None: - """ force store value for an option for identifiers - """ + def _set_force_value_identifier( + self, + subconfig: "SubConfig", + identifier_values, + ) -> None: + """force store value for an option for identifiers""" # pylint: disable=too-many-locals - if 'force_store_value' not in subconfig.config_bag.properties: + if "force_store_value" not in subconfig.config_bag.properties: return config_bag = subconfig.config_bag context = config_bag.context - for woption in subconfig.option._get_identifiers_dependencies(): # pylint: disable=protected-access - options = subconfig.get_common_child(woption(), - true_path=subconfig.path, - validate_properties=False, - ) + for ( + woption + ) in ( + subconfig.option._get_identifiers_dependencies() + ): # pylint: disable=protected-access + options = subconfig.get_common_child( + woption(), + true_path=subconfig.path, + validate_properties=False, + ) if not isinstance(options, list): options = [options] for option in options: parent = option.parent for identifier in identifier_values: name = option.option.impl_getname(identifier) - opt_subconfig = parent.get_child(option.option, - None, - False, - identifier=identifier, - name=name, - ) - - for walk_subconfig in context.walk(opt_subconfig, - no_value=True, - validate_properties=False, - ): - if 'force_store_value' not in walk_subconfig.properties: - continue - default_value = [self.get_value(walk_subconfig)[0], owners.forced] - self._values.setdefault(walk_subconfig.path, {})[walk_subconfig.index] = default_value + opt_subconfig = parent.get_child( + option.option, + None, + False, + identifier=identifier, + name=name, + ) - def _get_modified_parent(self, - subconfig: "SubConfig", - ) -> Optional["SubConfig"]: - """ Search in differents parents a Config with a modified value + for walk_subconfig in context.walk( + opt_subconfig, + no_value=True, + validate_properties=False, + ): + if "force_store_value" not in walk_subconfig.properties: + continue + default_value = [ + self.get_value(walk_subconfig)[0], + owners.forced, + ] + self._values.setdefault(walk_subconfig.path, {})[ + walk_subconfig.index + ] = default_value + + def _get_modified_parent( + self, + subconfig: "SubConfig", + ) -> Optional["SubConfig"]: + """Search in differents parents a Config with a modified value If not found, return None For follower option, return the Config where leader is modified """ + def build_option_bag(subconfig, parent): doption_bag = subconfig.copy() config_bag = subconfig.config_bag.copy() @@ -376,46 +439,53 @@ class Values: for parent in subconfig.config_bag.context.get_parents(): doption_bag = build_option_bag(subconfig, parent) - if 'force_metaconfig_on_freeze' in subconfig.properties: + if "force_metaconfig_on_freeze" in subconfig.properties: # remove force_metaconfig_on_freeze only if option in metaconfig # hasn't force_metaconfig_on_freeze properties ori_properties = doption_bag.properties settings = doption_bag.config_bag.context.get_settings() doption_bag.properties = settings.getproperties(doption_bag) if not self.check_force_to_metaconfig(doption_bag): - doption_bag.properties = ori_properties - {'force_metaconfig_on_freeze'} + doption_bag.properties = ori_properties - { + "force_metaconfig_on_freeze" + } else: doption_bag.properties = ori_properties - parent_owner = parent.get_values().getowner(doption_bag, - parent, - only_default=True, - ) + parent_owner = parent.get_values().getowner( + doption_bag, + parent, + only_default=True, + ) if parent_owner != owners.default: return doption_bag return None - - #______________________________________________________________________ + # ______________________________________________________________________ # owner - def is_default_owner(self, - subconfig: "SubConfig", - *, - validate_meta: bool=True, - ) -> bool: - """is default owner for an option - """ - return self.getowner(subconfig, - validate_meta=validate_meta, - only_default=True, - ) == owners.default + def is_default_owner( + self, + subconfig: "SubConfig", + *, + validate_meta: bool = True, + ) -> bool: + """is default owner for an option""" + return ( + self.getowner( + subconfig, + validate_meta=validate_meta, + only_default=True, + ) + == owners.default + ) - def hasvalue(self, - path, - *, - index=None, - ): + def hasvalue( + self, + path, + *, + index=None, + ): """if path has a value return: boolean """ @@ -426,12 +496,13 @@ class Values: return index in self._values[path] return False - def getowner(self, - subconfig: "SubConfig", - *, - validate_meta=True, - only_default=False, - ): + def getowner( + self, + subconfig: "SubConfig", + *, + validate_meta=True, + only_default=False, + ): """ retrieves the option's owner @@ -440,41 +511,49 @@ class Values: was present :returns: a `setting.owners.Owner` object """ -# context = subconfig.config_bag.context -# settings = context.get_settings() -# settings.validate_properties(subconfig) - if 'frozen' in subconfig.properties and \ - 'force_default_on_freeze' in subconfig.properties: + # context = subconfig.config_bag.context + # settings = context.get_settings() + # settings.validate_properties(subconfig) + if ( + "frozen" in subconfig.properties + and "force_default_on_freeze" in subconfig.properties + ): return owners.default if only_default: - if self.hasvalue(subconfig.path, - index=subconfig.index, - ): - owner = 'not_default' + if self.hasvalue( + subconfig.path, + index=subconfig.index, + ): + owner = "not_default" else: owner = owners.default else: - owner = self._values.get(subconfig.path, {}).get(subconfig.index, - [undefined, owners.default], - )[1] - if validate_meta is not False and (owner is owners.default or - 'frozen' in subconfig.properties and - 'force_metaconfig_on_freeze' in subconfig.properties): + owner = self._values.get(subconfig.path, {}).get( + subconfig.index, + [undefined, owners.default], + )[1] + if validate_meta is not False and ( + owner is owners.default + or "frozen" in subconfig.properties + and "force_metaconfig_on_freeze" in subconfig.properties + ): msubconfig = self._get_modified_parent(subconfig) if msubconfig is not None: values = msubconfig.config_bag.context.get_values() - owner = values.getowner(msubconfig, - parent, - only_default=only_default, - ) - elif 'force_metaconfig_on_freeze' in subconfig.properties: + owner = values.getowner( + msubconfig, + parent, + only_default=only_default, + ) + elif "force_metaconfig_on_freeze" in subconfig.properties: return owners.default return owner - def set_owner(self, - subconfig, - owner, - ): + def set_owner( + self, + subconfig, + owner, + ): """ sets a owner to an option @@ -484,170 +563,205 @@ class Values: if owner in forbidden_owners: raise ValueError(_('set owner "{0}" is forbidden').format(str(owner))) - if not self.hasvalue(subconfig.path, - index=subconfig.index, - ): - raise ConfigError(_(f'"{subconfig.path}" is a default value, so we cannot change owner to "{owner}"')) + if not self.hasvalue( + subconfig.path, + index=subconfig.index, + ): + raise ConfigError( + _( + '"{0}" is a default value, so we cannot change owner to "{1}"' + ).format(subconfig.path, owner) + ) subconfig.config_bag.context.get_settings().validate_frozen(subconfig) self._values[subconfig.path][subconfig.index][1] = owner - #______________________________________________________________________ + + # ______________________________________________________________________ # reset - def reset(self, - subconfig: "SubConfig", - *, - validate: bool=True, - ) -> None: - """reset value for an option - """ + def reset( + self, + subconfig: "SubConfig", + *, + validate: bool = True, + ) -> None: + """reset value for an option""" config_bag = subconfig.config_bag hasvalue = self.hasvalue(subconfig.path) context = config_bag.context setting_properties = config_bag.properties if validate: - if hasvalue and 'validator' in setting_properties: + if hasvalue and "validator" in setting_properties: fake_context = context.gen_fake_context() fake_config_bag = config_bag.copy() fake_config_bag.remove_validation() fake_config_bag.context = fake_context - fake_subconfig = fake_context.get_sub_config(fake_config_bag, - subconfig.path, - subconfig.index, - validate_properties=False, - ) + fake_subconfig = fake_context.get_sub_config( + fake_config_bag, + subconfig.path, + subconfig.index, + validate_properties=False, + ) fake_values = fake_context.get_values() fake_values.reset(fake_subconfig) fake_subconfig.config_bag.properties = setting_properties value = fake_values.get_default_value(fake_subconfig) - fake_values.setvalue_validation(fake_subconfig, - value, - ) -# if hasvalue: + fake_values.setvalue_validation( + fake_subconfig, + value, + ) + # if hasvalue: opt = subconfig.option if opt.impl_is_leader(): opt.impl_get_leadership().reset(subconfig.parent) - if 'force_store_value' in setting_properties and \ - 'force_store_value' in subconfig.properties: + if ( + "force_store_value" in setting_properties + and "force_store_value" in subconfig.properties + ): value = self.get_default_value(subconfig) - self._setvalue(subconfig, - value, - owners.forced, - ) + self._setvalue( + subconfig, + value, + owners.forced, + ) else: value = None if subconfig.path in self._values: del self._values[subconfig.path] - if 'force_store_value' in setting_properties and subconfig.option.impl_is_leader(): + if ( + "force_store_value" in setting_properties + and subconfig.option.impl_is_leader() + ): if value is None: value = self.get_default_value(subconfig) leader = subconfig.option.impl_get_leadership() - leader.follower_force_store_value(value, - subconfig.parent, - owners.forced, - ) + leader.follower_force_store_value( + value, + subconfig.parent, + owners.forced, + ) context.reset_cache(subconfig) - #______________________________________________________________________ + + # ______________________________________________________________________ # Follower def get_max_length(self, path: str) -> int: - """get max index for a follower and determine the length of the follower - """ + """get max index for a follower and determine the length of the follower""" values = self._values.get(path, {}) if values: return max(values) + 1 return 0 - def reset_follower(self, - subconfig: "SubConfig", - ) -> None: - """reset value for a follower - """ - if not self.hasvalue(subconfig.path, - index=subconfig.index, - ): + def reset_follower( + self, + subconfig: "SubConfig", + ) -> None: + """reset value for a follower""" + if not self.hasvalue( + subconfig.path, + index=subconfig.index, + ): return config_bag = subconfig.config_bag context = config_bag.context setting_properties = config_bag.properties - if 'validator' in setting_properties: + if "validator" in setting_properties: fake_context = context.gen_fake_context() fake_config_bag = config_bag.copy() fake_config_bag.remove_validation() fake_config_bag.context = fake_context - fake_subconfig = fake_context.get_sub_config(fake_config_bag, - subconfig.path, - subconfig.index, - validate_properties=False, - ) + fake_subconfig = fake_context.get_sub_config( + fake_config_bag, + subconfig.path, + subconfig.index, + validate_properties=False, + ) fake_values = fake_context.get_values() fake_values.reset_follower(fake_subconfig) fake_subconfig.config_bag.properties = setting_properties value = fake_values.get_default_value(fake_subconfig) - fake_values.setvalue_validation(fake_subconfig, - value, - ) - if 'force_store_value' in setting_properties and \ - 'force_store_value' in subconfig.properties: - value = self.get_default_value(subconfig, - ) + fake_values.setvalue_validation( + fake_subconfig, + value, + ) + if ( + "force_store_value" in setting_properties + and "force_store_value" in subconfig.properties + ): + value = self.get_default_value( + subconfig, + ) - self._setvalue(subconfig, - value, - owners.forced, - ) + self._setvalue( + subconfig, + value, + owners.forced, + ) else: self.resetvalue_index(subconfig) context.reset_cache(subconfig) - def resetvalue_index(self, - subconfig: "SubConfig", - ) -> None: - """reset a value for a follower at an index - """ - if subconfig.path in self._values and subconfig.index in self._values[subconfig.path]: + def resetvalue_index( + self, + subconfig: "SubConfig", + ) -> None: + """reset a value for a follower at an index""" + if ( + subconfig.path in self._values + and subconfig.index in self._values[subconfig.path] + ): del self._values[subconfig.path][subconfig.index] - def reduce_index(self, - subconfig: "SubConfig", - ) -> None: - """reduce follower's value from a specified index - """ + def reduce_index( + self, + subconfig: "SubConfig", + ) -> None: + """reduce follower's value from a specified index""" self.resetvalue_index(subconfig) for index in range(subconfig.index + 1, self.get_max_length(subconfig.path)): - if self.hasvalue(subconfig.path, - index=index, - ): - self._values[subconfig.path][index - 1] = self._values[subconfig.path].pop(index) + if self.hasvalue( + subconfig.path, + index=index, + ): + self._values[subconfig.path][index - 1] = self._values[ + subconfig.path + ].pop(index) - def reset_leadership(self, - subconfig: "SubConfig", - index: int, - ) -> None: - """reset leadership from an index - """ + def reset_leadership( + self, + subconfig: "SubConfig", + index: int, + ) -> None: + """reset leadership from an index""" current_value = self.get_cached_value(subconfig) length = len(current_value) if index >= length: - raise IndexError(_('index {index} is greater than the length {length} ' - 'for option {subconfig.option.impl_get_display_name(with_quote=True)}')) + raise IndexError( + _( + "index {index} is greater than the length {length} " + "for option {subconfig.option.impl_get_display_name(with_quote=True)}" + ) + ) current_value.pop(index) leadership_subconfig = subconfig.parent - leadership_subconfig.option.pop(subconfig, - index, - ) - self.set_value(subconfig, - current_value, - ) + leadership_subconfig.option.pop( + subconfig, + index, + ) + self.set_value( + subconfig, + current_value, + ) - #______________________________________________________________________ + # ______________________________________________________________________ # information - def set_information(self, - subconfig, - key, - value, - ): + def set_information( + self, + subconfig, + key, + value, + ): """updates the information's attribute :param key: information's key (ex: "help", "doc" @@ -670,25 +784,30 @@ class Values: continue option = woption() if option.issubdyn(): - option_subconfigs = subconfig.get_common_child(option, - validate_properties=False, - ) + option_subconfigs = subconfig.get_common_child( + option, + validate_properties=False, + ) if not isinstance(option_subconfigs, list): option_subconfigs = [option_subconfigs] else: - option_subconfigs = [context.get_sub_config(config_bag, - option.impl_getpath(), - None, - validate_properties=False, - )] + option_subconfigs = [ + context.get_sub_config( + config_bag, + option.impl_getpath(), + None, + validate_properties=False, + ) + ] for option_subconfig in option_subconfigs: context.reset_cache(option_subconfig) - def get_information(self, - subconfig, - name, - default, - ): + def get_information( + self, + subconfig, + name, + default, + ): """retrieves one information's item :param name: the item string (ex: "help") @@ -704,44 +823,44 @@ class Values: except KeyError as err: pass if option is not None: - return option._get_information(subconfig, - name, - default, - ) - return subconfig.config_bag.context.get_description()._get_information(subconfig, - name, - default, - ) + return option._get_information( + subconfig, + name, + default, + ) + return subconfig.config_bag.context.get_description()._get_information( + subconfig, + name, + default, + ) - def del_information(self, - key: Any, - raises: bool=True, - path: str=None, - ): - """delete information for a specified key - """ + def del_information( + self, + key: Any, + raises: bool = True, + path: str = None, + ): + """delete information for a specified key""" if path in self._informations and key in self._informations[path]: del self._informations[path][key] elif raises: - raise ValueError(_(f"information's item not found \"{key}\"")) + raise ValueError(_('information\'s item not found "{}"').format(key)) - def list_information(self, - path: str=None, - ) -> List[str]: - """list all informations keys for a specified path - """ + def list_information( + self, + path: str = None, + ) -> List[str]: + """list all informations keys for a specified path""" return list(self._informations.get(path, {}).keys()) - #____________________________________________________________ + # ____________________________________________________________ # default owner methods def set_context_owner(self, owner: str) -> None: - """set the context owner - """ + """set the context owner""" if owner in forbidden_owners: raise ValueError(_('set owner "{0}" is forbidden').format(str(owner))) self._values[None][None][1] = owner def get_context_owner(self) -> str: - """get the context owner - """ + """get the context owner""" return self._values[None][None][1]