feat: better conflict with dynamic name

This commit is contained in:
egarette@silique.fr 2025-09-18 22:18:19 +02:00
parent 47c413e60c
commit e351da2069
12 changed files with 505 additions and 371 deletions

View file

@ -2,7 +2,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Tiramisu\n" "Project-Id-Version: Tiramisu\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-05-12 09:04+0200\n" "POT-Creation-Date: 2025-09-19 22:03+0200\n"
"PO-Revision-Date: \n" "PO-Revision-Date: \n"
"Last-Translator: Emmanuel Garette <egarette@cadoles.com>\n" "Last-Translator: Emmanuel Garette <egarette@cadoles.com>\n"
"Language-Team: Tiramisu's team <egarette@cadoles.com>\n" "Language-Team: Tiramisu's team <egarette@cadoles.com>\n"
@ -11,46 +11,46 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Generator: Poedit 3.5\n" "X-Generator: Poedit 3.7\n"
"X-Poedit-SourceCharset: UTF-8\n" "X-Poedit-SourceCharset: UTF-8\n"
#: tiramisu/api.py:79 #: tiramisu/api.py:86
msgid "Settings:" msgid "Settings:"
msgstr "Paramètres :" msgstr "Paramètres :"
#: tiramisu/api.py:83 #: tiramisu/api.py:90
msgid "Access to option without verifying permissive properties" msgid "Access to option without verifying permissive properties"
msgstr "Accès à une option sans vérifié les propriétés permises" msgstr "Accès à une option sans vérifié les propriétés permises"
#: tiramisu/api.py:88 #: tiramisu/api.py:95
msgid "Access to option without property restriction" msgid "Access to option without property restriction"
msgstr "Accès à une option sans restriction de propriété" msgstr "Accès à une option sans restriction de propriété"
#: tiramisu/api.py:93 #: tiramisu/api.py:100
msgid "Do not warnings during validation" msgid "Do not warnings during validation"
msgstr "Ne peut avoir de warnings durant une validation" msgstr "Ne peut avoir de warnings durant une validation"
#: tiramisu/api.py:97 #: tiramisu/api.py:104
msgid "Commands:" msgid "Commands:"
msgstr "Commandes :" msgstr "Commandes :"
#: tiramisu/api.py:111 tiramisu/api.py:1857 #: tiramisu/api.py:118 tiramisu/api.py:1955
msgid "please specify a valid sub function ({0}.{1})" msgid "please specify a valid sub function ({0}.{1})"
msgstr "veuillez spécifier une sous fonction valide ({0}.{1})" msgstr "veuillez spécifier une sous fonction valide ({0}.{1})"
#: tiramisu/api.py:196 #: tiramisu/api.py:206
msgid "please do not specify index ({0}.{1})" msgid "please do not specify index ({0}.{1})"
msgstr "veuillez ne pas spécifier d'index ({0}.{1})" msgstr "veuillez ne pas spécifier d'index ({0}.{1})"
#: tiramisu/api.py:201 tiramisu/api.py:856 #: tiramisu/api.py:211 tiramisu/api.py:940
msgid "please specify index with a follower option ({0}.{1})" msgid "please specify index with a follower option ({0}.{1})"
msgstr "veuillez spécifier un index avec une option suiveuse ({0}.{1})" msgstr "veuillez spécifier un index avec une option suiveuse ({0}.{1})"
#: tiramisu/api.py:222 #: tiramisu/api.py:234
msgid "please specify a valid sub function ({0}.{1}): {2}" msgid "please specify a valid sub function ({0}.{1}): {2}"
msgstr "veuillez spécifier une sous fonction valide ({0}.{1}): {2}" msgstr "veuillez spécifier une sous fonction valide ({0}.{1}): {2}"
#: tiramisu/api.py:446 #: tiramisu/api.py:525
msgid "" msgid ""
"the option {0} is not a dynamic option, cannot get identifiers with " "the option {0} is not a dynamic option, cannot get identifiers with "
"only_self parameter to True" "only_self parameter to True"
@ -58,15 +58,15 @@ msgstr ""
"l'option {0} n'est pas une option dynamique, ne peut retrouver l'identifiant " "l'option {0} n'est pas une option dynamique, ne peut retrouver l'identifiant "
"avec le paramètre only_self à True" "avec le paramètre only_self à True"
#: tiramisu/api.py:532 #: tiramisu/api.py:613
msgid "cannot get option from a follower symlink without index" msgid "cannot get option from a follower symlink without index"
msgstr "ne peut avoir d'option pour une symlink suiveuse sans index" msgstr "ne peut avoir d'option pour une symlink suiveuse sans index"
#: tiramisu/api.py:607 #: tiramisu/api.py:691
msgid "cannot add this property: \"{0}\"" msgid "cannot add this property: \"{0}\""
msgstr "ne peut pas ajouter cette propriété : \"{0}\"" msgstr "ne peut pas ajouter cette propriété : \"{0}\""
#: tiramisu/api.py:634 #: tiramisu/api.py:718
msgid "" msgid ""
"cannot remove option's property \"{0}\", use permissive instead in option " "cannot remove option's property \"{0}\", use permissive instead in option "
"\"{1}\"" "\"{1}\""
@ -74,11 +74,11 @@ msgstr ""
"ne supprimer la propriété \"{0}\" de l'option, utiliser plutôt permissive " "ne supprimer la propriété \"{0}\" de l'option, utiliser plutôt permissive "
"dans l'option \"{1}\"" "dans l'option \"{1}\""
#: tiramisu/api.py:638 #: tiramisu/api.py:722
msgid "cannot find \"{0}\" in option \"{1}\"" msgid "cannot find \"{0}\" in option \"{1}\""
msgstr "ne peut trouver \"{0}\" dans l'option \"{1}\"" msgstr "ne peut trouver \"{0}\" dans l'option \"{1}\""
#: tiramisu/api.py:643 #: tiramisu/api.py:727
msgid "" msgid ""
"cannot remove option's property \"{0}\", use permissive instead in option " "cannot remove option's property \"{0}\", use permissive instead in option "
"\"{1}\" at index \"{2}\"" "\"{1}\" at index \"{2}\""
@ -86,35 +86,35 @@ msgstr ""
"ne peut supprimer la propriété \"{0}\" de l'option, utilisez plutôt " "ne peut supprimer la propriété \"{0}\" de l'option, utilisez plutôt "
"permissive dans l'option \"{1}\" a l'index \"{2}\"" "permissive dans l'option \"{1}\" a l'index \"{2}\""
#: tiramisu/api.py:647 #: tiramisu/api.py:731
msgid "cannot find \"{0}\" in option \"{1}\" at index \"{2}\"" msgid "cannot find \"{0}\" in option \"{1}\" at index \"{2}\""
msgstr "ne peut trouver \"{0}\" dans l'option \"{1}\" à l'index \"{2}\"" msgstr "ne peut trouver \"{0}\" dans l'option \"{1}\" à l'index \"{2}\""
#: tiramisu/api.py:691 #: tiramisu/api.py:775
msgid "cannot find \"{0}\"" msgid "cannot find \"{0}\""
msgstr "ne peut trouver \"{0}\"" msgstr "ne peut trouver \"{0}\""
#: tiramisu/api.py:873 #: tiramisu/api.py:957
msgid "only multi value has defaultmulti" msgid "only multi value has defaultmulti"
msgstr "seule les valeurs multiple a l'attribut defaultmulti" msgstr "seule les valeurs multiple a l'attribut defaultmulti"
#: tiramisu/api.py:1037 #: tiramisu/api.py:1121
msgid "please specify a valid sub function ({0}.{1}) for {2}" msgid "please specify a valid sub function ({0}.{1}) for {2}"
msgstr "veuillez spécifier une sous fonction valide ({0}.{1}) pour {2}" msgstr "veuillez spécifier une sous fonction valide ({0}.{1}) pour {2}"
#: tiramisu/api.py:1424 #: tiramisu/api.py:1520
msgid "properties must be a frozenset" msgid "properties must be a frozenset"
msgstr "une propriété doit être de type frozenset" msgstr "une propriété doit être de type frozenset"
#: tiramisu/api.py:1428 tiramisu/api.py:1455 #: tiramisu/api.py:1524 tiramisu/api.py:1551
msgid "unknown when {} (must be in append or remove)" msgid "unknown when {} (must be in append or remove)"
msgstr "value {} inconsistent (doit être append ou remove)" msgstr "value {} inconsistent (doit être append ou remove)"
#: tiramisu/api.py:1441 tiramisu/api.py:1465 tiramisu/config.py:1676 #: tiramisu/api.py:1537 tiramisu/api.py:1561 tiramisu/config.py:1691
msgid "unknown type {}" msgid "unknown type {}"
msgstr "type inconnu {}" msgstr "type inconnu {}"
#: tiramisu/api.py:1829 #: tiramisu/api.py:1927
msgid "do not use unrestraint, nowarnings or forcepermissive together" msgid "do not use unrestraint, nowarnings or forcepermissive together"
msgstr "" msgstr ""
"il ne faut pas utiliser unrestraint, nowarnings ou forcepermissive ensemble" "il ne faut pas utiliser unrestraint, nowarnings ou forcepermissive ensemble"
@ -183,29 +183,29 @@ msgstr "le premier argument ({0}) doit être une fonction"
msgid "help_function ({0}) must be a function" msgid "help_function ({0}) must be a function"
msgstr "help_function ({0}) doit être une fonction" msgstr "help_function ({0}) doit être une fonction"
#: tiramisu/autolib.py:469 tiramisu/autolib.py:524 #: tiramisu/autolib.py:469 tiramisu/autolib.py:525
msgid "the option {0} is used in a calculation but is invalid ({1})" 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})" msgstr "l'option {0} est utilisé dans un calcul mais est invalide ({1})"
#: tiramisu/autolib.py:482 tiramisu/autolib.py:538 tiramisu/autolib.py:588 #: tiramisu/autolib.py:482 tiramisu/autolib.py:539 tiramisu/autolib.py:589
msgid "unable to get value for calculating {0}, {1}" msgid "unable to get value for calculating {0}, {1}"
msgstr "impossible de trouver la valeur pour calculer {0}, {1}" msgstr "impossible de trouver la valeur pour calculer {0}, {1}"
#: tiramisu/autolib.py:517 #: tiramisu/autolib.py:518
msgid "unable to carry out a calculation for {0}, {1}" msgid "unable to carry out a calculation for {0}, {1}"
msgstr "impossible d'effectuer le calcul pour {0}, {1}" msgstr "impossible d'effectuer le calcul pour {0}, {1}"
#: tiramisu/autolib.py:563 #: tiramisu/autolib.py:564
msgid "cannot find information for {0}, {1} is a dynamic option" msgid "cannot find information for {0}, {1} is a dynamic option"
msgstr "ne peut trouver l'information pour {0}, {1} est une option dynamique" msgstr "ne peut trouver l'information pour {0}, {1} est une option dynamique"
#: tiramisu/autolib.py:603 #: tiramisu/autolib.py:604
msgid "option {0} is not a dynoptiondescription or in a dynoptiondescription" msgid "option {0} is not a dynoptiondescription or in a dynoptiondescription"
msgstr "" msgstr ""
"l'option {0} n'est pas une dynoptiondescription ou n'est pas dans une " "l'option {0} n'est pas une dynoptiondescription ou n'est pas dans une "
"dynoptiondescription" "dynoptiondescription"
#: tiramisu/autolib.py:696 #: tiramisu/autolib.py:697
msgid "" msgid ""
"cannot calculate arguments for {0}, {1} with identifier \"{2}\", there is no " "cannot calculate arguments for {0}, {1} with identifier \"{2}\", there is no "
"identifiers" "identifiers"
@ -213,7 +213,7 @@ msgstr ""
"impossible de calculer les arguments de {0}, {1} avec l'identifiant \"{2}\", " "impossible de calculer les arguments de {0}, {1} avec l'identifiant \"{2}\", "
"il n'y a pas d'identifiants" "il n'y a pas d'identifiants"
#: tiramisu/autolib.py:708 #: tiramisu/autolib.py:709
msgid "" msgid ""
"cannot calculate arguments for {0}, {1} with identifier \"{2}\", list of " "cannot calculate arguments for {0}, {1} with identifier \"{2}\", list of "
"valid identifiers: {3}" "valid identifiers: {3}"
@ -221,12 +221,12 @@ msgstr ""
"impossible de calculer les arguments de {0}, {1} avec l'identifiant \"{2}\", " "impossible de calculer les arguments de {0}, {1} avec l'identifiant \"{2}\", "
"voici la liste des identifiants valables : {3}" "voici la liste des identifiants valables : {3}"
#: tiramisu/autolib.py:819 #: tiramisu/autolib.py:820
msgid "the follower {0} must have index in carry_out_calculation!" msgid "the follower {0} must have index in carry_out_calculation!"
msgstr "" msgstr ""
"la variable suiveuse {0} doit avoir un index dans carry_out_calculation!" "la variable suiveuse {0} doit avoir un index dans carry_out_calculation!"
#: tiramisu/autolib.py:931 #: tiramisu/autolib.py:932
msgid "" msgid ""
"unexpected error \"{1}\" in function \"{2}\" with arguments \"{3}\" and " "unexpected error \"{1}\" in function \"{2}\" with arguments \"{3}\" and "
"\"{4}\" for option {0}" "\"{4}\" for option {0}"
@ -234,50 +234,54 @@ msgstr ""
"erreur inattendue \"{1}\" dans la fonction \"{2}\" avec les arguments " "erreur inattendue \"{1}\" dans la fonction \"{2}\" avec les arguments "
"\"{3}\" et \"{4}\" pour l'option {0}" "\"{3}\" et \"{4}\" pour l'option {0}"
#: tiramisu/autolib.py:941 #: tiramisu/autolib.py:942
msgid "unexpected error \"{1}\" in function \"{2}\" for option {0}" msgid "unexpected error \"{1}\" in function \"{2}\" for option {0}"
msgstr "erreur inattendue \"{1}\" dans la fonction \"{2}\" pour l'option {0}" msgstr "erreur inattendue \"{1}\" dans la fonction \"{2}\" pour l'option {0}"
#: tiramisu/config.py:574 #: tiramisu/config.py:391 tiramisu/config.py:413
msgid "option name {0} is not unique in {1}"
msgstr "le nom de l'option {0} n'est pas unique dans {1}"
#: tiramisu/config.py:638
msgid "there is no option description for this config (may be GroupConfig)" msgid "there is no option description for this config (may be GroupConfig)"
msgstr "" msgstr ""
"il n'y a pas d'option description trouvé pour cette config (peut être un " "il n'y a pas d'option description trouvé pour cette config (peut être un "
"GroupConfig)" "GroupConfig)"
#: tiramisu/config.py:663 #: tiramisu/config.py:989 tiramisu/option/optiondescription.py:74
msgid "no option found in config with these criteria"
msgstr "aucune option trouvée dans la config avec ces critères"
#: tiramisu/config.py:978 tiramisu/option/optiondescription.py:74
msgid "option description seems to be part of an other config" msgid "option description seems to be part of an other config"
msgstr "l'option description semble faire parti d'une autre config" msgstr "l'option description semble faire parti d'une autre config"
#: tiramisu/config.py:1140 #: tiramisu/config.py:1151
msgid "parent of {0} not already exists" msgid "parent of {0} not already exists"
msgstr "le parent de {0} n'existe plus" msgstr "le parent de {0} n'existe plus"
#: tiramisu/config.py:1187 #: tiramisu/config.py:1198
msgid "cannot set leadership object has root optiondescription" msgid "cannot set leadership object has root optiondescription"
msgstr "ne peut assigner un objet leadership comme optiondescription racine" msgstr "ne peut assigner un objet leadership comme optiondescription racine"
#: tiramisu/config.py:1190 #: tiramisu/config.py:1201
msgid "cannot set dynoptiondescription object has root optiondescription" msgid "cannot set dynoptiondescription object has root optiondescription"
msgstr "" msgstr ""
"ne peut assigner un objet dynoptiondescription comme optiondescription racine" "ne peut assigner un objet dynoptiondescription comme optiondescription racine"
#: tiramisu/config.py:1242 #: tiramisu/config.py:1248
msgid "child must be a Config, GroupConfig, MixConfig or MetaConfig"
msgstr "l'enfant doit être une Config, GroupConfig, MixConfig ou MetaConfig"
#: tiramisu/config.py:1257
msgid "config name must be uniq in groupconfig for \"{0}\"" msgid "config name must be uniq in groupconfig for \"{0}\""
msgstr "le nom d'un config doit être unique dans un groupconfig pour \"{0}\"" msgstr "le nom d'un config doit être unique dans un groupconfig pour \"{0}\""
#: tiramisu/config.py:1453 #: tiramisu/config.py:1466
msgid "unknown config \"{}\"" msgid "unknown config \"{}\""
msgstr "config \"{}\" inconnue" msgstr "config \"{}\" inconnue"
#: tiramisu/config.py:1478 #: tiramisu/config.py:1491
msgid "child must be a Config, MixConfig or MetaConfig" msgid "child must be a Config, MixConfig or MetaConfig"
msgstr "l'enfant doit être une Config, MixConfig ou MetaConfig" msgstr "l'enfant doit être une Config, MixConfig ou MetaConfig"
#: tiramisu/config.py:1513 #: tiramisu/config.py:1526
msgid "" msgid ""
"force_default, force_default_if_same or force_dont_change_value cannot be " "force_default, force_default_if_same or force_dont_change_value cannot be "
"set with only_config" "set with only_config"
@ -285,43 +289,43 @@ msgstr ""
"force_default, force_default_if_same ou force_dont_change_value ne peuvent " "force_default, force_default_if_same ou force_dont_change_value ne peuvent "
"pas être spécifié avec only_config" "pas être spécifié avec only_config"
#: tiramisu/config.py:1523 #: tiramisu/config.py:1536
msgid "force_default and force_dont_change_value cannot be set together" msgid "force_default and force_dont_change_value cannot be set together"
msgstr "" msgstr ""
"force_default et force_dont_change_value ne peuvent pas être mis ensemble" "force_default et force_dont_change_value ne peuvent pas être mis ensemble"
#: tiramisu/config.py:1672 #: tiramisu/config.py:1687
msgid "config name must be uniq in groupconfig for {0}" msgid "config name must be uniq in groupconfig for {0}"
msgstr "le nom de la config doit être unique dans un groupconfig pour {0}" msgstr "le nom de la config doit être unique dans un groupconfig pour {0}"
#: tiramisu/config.py:1717 #: tiramisu/config.py:1732
msgid "config added has no name, the name is mandatory" msgid "config added has no name, the name is mandatory"
msgstr "la config ajoutée n'a pas de nom, le nom est obligatoire" msgstr "la config ajoutée n'a pas de nom, le nom est obligatoire"
#: tiramisu/config.py:1722 #: tiramisu/config.py:1737
msgid "config name \"{0}\" is not uniq in groupconfig \"{1}\"" msgid "config name \"{0}\" is not uniq in groupconfig \"{1}\""
msgstr "" msgstr ""
"le nom d'un config \"{0}\" n'est pas unique dans le groupconfig \"{1}\"" "le nom d'un config \"{0}\" n'est pas unique dans le groupconfig \"{1}\""
#: tiramisu/config.py:1740 tiramisu/config.py:1746 #: tiramisu/config.py:1755 tiramisu/config.py:1761
msgid "cannot find the config {0}" msgid "cannot find the config {0}"
msgstr "ne peut pas trouver la config {0}" msgstr "ne peut pas trouver la config {0}"
#: tiramisu/config.py:1772 #: tiramisu/config.py:1787
msgid "MetaConfig with optiondescription must have string has child, not {}" msgid "MetaConfig with optiondescription must have string has child, not {}"
msgstr "" msgstr ""
"MetaConfig avec une optiondescription doit avoir un nom comme enfant, pas {}" "MetaConfig avec une optiondescription doit avoir un nom comme enfant, pas {}"
#: tiramisu/config.py:1784 #: tiramisu/config.py:1799
msgid "child must be a Config or MetaConfig" msgid "child must be a Config or MetaConfig"
msgstr "enfant doit être une une Config ou une MetaConfig" msgstr "enfant doit être une une Config ou une MetaConfig"
#: tiramisu/config.py:1789 #: tiramisu/config.py:1804
msgid "all config in metaconfig must have the same optiondescription" msgid "all config in metaconfig must have the same optiondescription"
msgstr "" msgstr ""
"toutes les configs d'une metaconfig doivent avoir la même optiondescription" "toutes les configs d'une metaconfig doivent avoir la même optiondescription"
#: tiramisu/config.py:1806 #: tiramisu/config.py:1821
msgid "metaconfig must have the same optiondescription" msgid "metaconfig must have the same optiondescription"
msgstr "metaconfig doivent avoir la même optiondescription" msgstr "metaconfig doivent avoir la même optiondescription"
@ -354,8 +358,6 @@ msgid "cannot modify the {0} {1} because is frozen"
msgstr "ne peut modifier {0} {1} parce qu'est frozen" msgstr "ne peut modifier {0} {1} parce qu'est frozen"
#: tiramisu/error.py:160 #: tiramisu/error.py:160
#, fuzzy
#| msgid "cannot access to {0} {1} at index \"{2}\" because {2} hasn't value"
msgid "cannot access to {0} {1} at index \"{2}\" because {3} hasn't value" msgid "cannot access to {0} {1} at index \"{2}\" because {3} hasn't value"
msgstr "" msgstr ""
"ne peut accéder à {0} {1} à l'index \"{2}\" parce que {3} n'a pas de valeur" "ne peut accéder à {0} {1} à l'index \"{2}\" parce que {3} n'a pas de valeur"
@ -455,24 +457,24 @@ msgstr ""
"la fonction \"{0}\" ne doit pas retourner une liste (\"{1}\") pour l'option " "la fonction \"{0}\" ne doit pas retourner une liste (\"{1}\") pour l'option "
"suiveuse {2}" "suiveuse {2}"
#: tiramisu/error.py:331 #: tiramisu/error.py:333
msgid "invalid value" msgid "invalid value"
msgstr "valeur invalide" msgstr "valeur invalide"
#: tiramisu/error.py:341 #: tiramisu/error.py:343
msgid "attention, \"{0}\" could be an invalid {1} for {2}" msgid "attention, \"{0}\" could be an invalid {1} for {2}"
msgstr "attention, \"{0}\" peut être un {1} invalide pour {2}" msgstr "attention, \"{0}\" peut être un {1} invalide pour {2}"
#: tiramisu/error.py:345 #: tiramisu/error.py:347
msgid "attention, \"{0}\" could be an invalid {1} for {2} at index \"{3}\"" msgid "attention, \"{0}\" could be an invalid {1} for {2} at index \"{3}\""
msgstr "" msgstr ""
"attention, \"{0}\" peut être un {1} invalide pour {2} à l'index \"{3}\"" "attention, \"{0}\" peut être un {1} invalide pour {2} à l'index \"{3}\""
#: tiramisu/error.py:366 tiramisu/error.py:377 #: tiramisu/error.py:368 tiramisu/error.py:379
msgid "\"{0}\" is an invalid {1} for {2}" msgid "\"{0}\" is an invalid {1} for {2}"
msgstr "\"{0}\" est une valeur invalide pour l'option {2} de type {1}" msgstr "\"{0}\" est une valeur invalide pour l'option {2} de type {1}"
#: tiramisu/error.py:368 #: tiramisu/error.py:370
msgid "\"{0}\" is an invalid {1} for {2} at index \"{3}\"" msgid "\"{0}\" is an invalid {1} for {2} at index \"{3}\""
msgstr "\"{0}\" est un {1} invalide pour {2} à l'index \"{3}\"" msgstr "\"{0}\" est un {1} invalide pour {2} à l'index \"{3}\""
@ -547,33 +549,33 @@ msgstr "la valeur de \"{0}\" est {1}"
msgid "the value of \"{0}\" is not {1}" msgid "the value of \"{0}\" is not {1}"
msgstr "la valeur de \"{0}\" n'est pas {1}" msgstr "la valeur de \"{0}\" n'est pas {1}"
#: tiramisu/option/baseoption.py:75 tiramisu/option/symlinkoption.py:44 #: tiramisu/option/baseoption.py:76 tiramisu/option/symlinkoption.py:44
msgid "\"{0}\" is an invalid name for an option" msgid "\"{0}\" is an invalid name for an option"
msgstr "\"{0}\" est un nom invalide pour une option" msgstr "\"{0}\" est un nom invalide pour une option"
#: tiramisu/option/baseoption.py:88 #: tiramisu/option/baseoption.py:89
msgid "invalid properties type {0} for {1}, must be a frozenset" 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" msgstr "type {0} invalide pour des propriétés pour {1}, doit être un frozenset"
#: tiramisu/option/baseoption.py:100 #: tiramisu/option/baseoption.py:102
msgid "invalid property type {0} for {1}, must be a string or a Calculation" msgid "invalid property type {0} for {1}, must be a string or a Calculation"
msgstr "" msgstr ""
"type {0} invalide pour des propriétés pour {1}, doit être des caractères ou " "type {0} invalide pour des propriétés pour {1}, doit être des caractères ou "
"un objet Calculation" "un objet Calculation"
#: tiramisu/option/baseoption.py:251 #: tiramisu/option/baseoption.py:253
msgid "information's item for {0} not found: \"{1}\"" msgid "information's item for {0} not found: \"{1}\""
msgstr "item pour {0} dans les informations non trouvée: \"{1}\"" msgstr "item pour {0} dans les informations non trouvée: \"{1}\""
#: tiramisu/option/baseoption.py:269 #: tiramisu/option/baseoption.py:271
msgid "'{0}' ({1}) object attribute '{2}' is read-only" msgid "'{0}' ({1}) object attribute '{2}' is read-only"
msgstr "l'attribut {2} de l'objet '{0}' ({1}) est en lecture seule" msgstr "l'attribut {2} de l'objet '{0}' ({1}) est en lecture seule"
#: tiramisu/option/baseoption.py:310 #: tiramisu/option/baseoption.py:312
msgid "\"{}\" ({}) object attribute \"{}\" is read-only" msgid "\"{}\" ({}) object attribute \"{}\" is read-only"
msgstr "\"{}\" ({}) l'attribut de l'objet \"{}\" est en lecture seule" msgstr "\"{}\" ({}) l'attribut de l'objet \"{}\" est en lecture seule"
#: tiramisu/option/baseoption.py:322 #: tiramisu/option/baseoption.py:324
msgid "{0} not part of any Config" msgid "{0} not part of any Config"
msgstr "{0} ne fait pas parti d'une Config" msgstr "{0} ne fait pas parti d'une Config"
@ -581,19 +583,19 @@ msgstr "{0} ne fait pas parti d'une Config"
msgid "invalid string" msgid "invalid string"
msgstr "invalide caractère" msgstr "invalide caractère"
#: tiramisu/option/choiceoption.py:47 #: tiramisu/option/choiceoption.py:52
msgid "values must be a tuple or a calculation for {0}" msgid "values must be a tuple or a calculation for {0}"
msgstr "les valeurs doivent être un tuple ou une fonction pour {0}" msgstr "les valeurs doivent être un tuple ou une fonction pour {0}"
#: tiramisu/option/choiceoption.py:70 #: tiramisu/option/choiceoption.py:75
msgid "the calculated values \"{0}\" for \"{1}\" is not a list" msgid "the calculated values \"{0}\" for \"{1}\" is not a list"
msgstr "les valeurs calculées \"{0}\" pour \"{1}\" n'est pas une liste" msgstr "les valeurs calculées \"{0}\" pour \"{1}\" n'est pas une liste"
#: tiramisu/option/choiceoption.py:101 #: tiramisu/option/choiceoption.py:106
msgid "only \"{0}\" is allowed" msgid "only \"{0}\" is allowed"
msgstr "seul \"{0}\" est autorisé" msgstr "seul \"{0}\" est autorisé"
#: tiramisu/option/choiceoption.py:103 #: tiramisu/option/choiceoption.py:108
msgid "only {0} are allowed" msgid "only {0} are allowed"
msgstr "seul {0} sont autorisées" msgstr "seul {0} sont autorisées"
@ -696,7 +698,7 @@ msgstr ""
msgid "invalid identifier \"{}\" for option {}" msgid "invalid identifier \"{}\" for option {}"
msgstr "identifiant \"{}\" invalide pour l'option \"{}\"" msgstr "identifiant \"{}\" invalide pour l'option \"{}\""
#: tiramisu/option/dynoptiondescription.py:150 #: tiramisu/option/dynoptiondescription.py:154
msgid "" msgid ""
"DynOptionDescription \"{0}\" identifiers return a list with same values " "DynOptionDescription \"{0}\" identifiers return a list with same values "
"\"{1}\"" "\"{1}\""
@ -849,42 +851,45 @@ msgstr ""
msgid "the value \"{}\" is not unique" msgid "the value \"{}\" is not unique"
msgstr "la valeur \"{}\" n'est pas unique" msgstr "la valeur \"{}\" n'est pas unique"
#: tiramisu/option/option.py:356 #: tiramisu/option/option.py:357
msgid "which must not be a list" msgid "which must not be a list"
msgstr "qui ne doit pas être une liste" msgstr "qui ne doit pas être une liste"
#: tiramisu/option/option.py:408 tiramisu/option/option.py:434 #: tiramisu/option/option.py:412 tiramisu/option/option.py:450
msgid "which must be a list" msgid "which must be a list"
msgstr "qui doit être une liste" msgstr "qui doit être une liste"
#: tiramisu/option/option.py:428 #: tiramisu/option/option.py:440
msgid "which \"{}\" must be a list of list" msgid "which \"{}\" must be a list of list"
msgstr "lequel \"{}\" doit être une liste de liste" msgstr "lequel \"{}\" doit être une liste de liste"
#: tiramisu/option/optiondescription.py:109 #: tiramisu/option/optiondescription.py:111
msgid "duplicate option: {0}" #: tiramisu/option/optiondescription.py:117
msgstr "option dupliquée : {0}" msgid "\"{0}\" option description"
msgstr "l'option description \"{0}\""
#: tiramisu/option/optiondescription.py:336 #: tiramisu/option/optiondescription.py:115
#: tiramisu/option/optiondescription.py:121
msgid "root option description"
msgstr "l'option description racine"
#: tiramisu/option/optiondescription.py:123
msgid "option \"{0}\" is include in {1} but is also in {2}"
msgstr "l'option \"{0}\" est incluse dans {1} mais est aussi dans {2}"
#: tiramisu/option/optiondescription.py:328
msgid "children in optiondescription \"{}\" must be a list" msgid "children in optiondescription \"{}\" must be a list"
msgstr "les enfants d'une optiondescription \"{}\" doivent être une liste" msgstr "les enfants d'une optiondescription \"{}\" doivent être une liste"
#: tiramisu/option/optiondescription.py:364 #: tiramisu/option/optiondescription.py:357
msgid "duplicate option name: \"{0}\"" msgid "the option name \"{0}\" is duplicate in \"{1}\""
msgstr "nom de l'option dupliqué : \"{0}\"" msgstr "le nom de l'option \"{0}\" est dupliqué dans \"{1}\""
#: tiramisu/option/optiondescription.py:370 #: tiramisu/option/optiondescription.py:411
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:413
msgid "cannot change group_type if already set (old {0}, new {1})" 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})" msgstr "ne peut changer group_type si déjà spécifié (ancien {0}, nouveau {1})"
#: tiramisu/option/optiondescription.py:418 #: tiramisu/option/optiondescription.py:416
msgid "group_type: {0} not allowed" msgid "group_type: {0} not allowed"
msgstr "group_type : {0} non autorisé" msgstr "group_type : {0} non autorisé"
@ -925,27 +930,27 @@ msgstr "{0} a plus de droit que {1}"
msgid "too weak" msgid "too weak"
msgstr "trop simple" msgstr "trop simple"
#: tiramisu/option/portoption.py:80 #: tiramisu/option/portoption.py:77
msgid "inconsistency in allowed range" msgid "inconsistency in allowed range"
msgstr "inconsistence dans la plage autorisée" msgstr "inconsistence dans la plage autorisée"
#: tiramisu/option/portoption.py:85 #: tiramisu/option/portoption.py:82
msgid "max value is empty" msgid "max value is empty"
msgstr "la valeur maximum est vide" msgstr "la valeur maximum est vide"
#: tiramisu/option/portoption.py:98 #: tiramisu/option/portoption.py:95
msgid "range must have two values only" msgid "range must have two values only"
msgstr "un rang doit avoir deux valeurs seulement" msgstr "un rang doit avoir deux valeurs seulement"
#: tiramisu/option/portoption.py:101 #: tiramisu/option/portoption.py:98
msgid "first port in range must be smaller than the second one" 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" msgstr "le premier port d'un rang doit être plus petit que le second"
#: tiramisu/option/portoption.py:127 #: tiramisu/option/portoption.py:124
msgid "should be between {0} and {1}" msgid "should be between {0} and {1}"
msgstr "devrait être une nombre entre {0} et {1}" msgstr "devrait être une nombre entre {0} et {1}"
#: tiramisu/option/portoption.py:129 #: tiramisu/option/portoption.py:126
msgid "must be between {0} and {1}" msgid "must be between {0} and {1}"
msgstr "doit être une nombre entre {0} et {1}" msgstr "doit être une nombre entre {0} et {1}"
@ -989,8 +994,8 @@ msgid ""
"invalid property type {type(new_prop)} for {subconfig.option.impl_getname()} " "invalid property type {type(new_prop)} for {subconfig.option.impl_getname()} "
"with {prop.function.__name__} function" "with {prop.function.__name__} function"
msgstr "" msgstr ""
"type {type(new_prop)} de la propriété invalide pour la fonction {subconfig." "type {type(new_prop)} de la propriété invalide pour la fonction "
"option.impl_getname()} with {prop.function.__name__}" "{subconfig.option.impl_getname()} with {prop.function.__name__}"
#: tiramisu/setting.py:606 #: tiramisu/setting.py:606
msgid "permissive must be a frozenset" msgid "permissive must be a frozenset"
@ -1034,28 +1039,42 @@ msgstr ""
msgid "unknown action {}" msgid "unknown action {}"
msgstr "action inconnue {}" msgstr "action inconnue {}"
#: tiramisu/value.py:570 tiramisu/value.py:872 #: tiramisu/value.py:557 tiramisu/value.py:859
msgid "set owner \"{0}\" is forbidden" msgid "set owner \"{0}\" is forbidden"
msgstr "assigner l'utilisateur \"{0}\" est interdit" msgstr "assigner l'utilisateur \"{0}\" est interdit"
#: tiramisu/value.py:577 #: tiramisu/value.py:564
msgid "\"{0}\" is a default value, so we cannot change owner to \"{1}\"" msgid "\"{0}\" is a default value, so we cannot change owner to \"{1}\""
msgstr "" msgstr ""
"\"{0}\" est une valeur par défaut, donc ne peut changer d'utilisateur à " "\"{0}\" est une valeur par défaut, donc ne peut changer d'utilisateur à "
"\"{1}\"" "\"{1}\""
#: tiramisu/value.py:751 #: tiramisu/value.py:845
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:858
msgid "information's item not found \"{}\"" msgid "information's item not found \"{}\""
msgstr "l'information de l'objet ne sont pas trouvé \"{}\"" msgstr "l'information de l'objet ne sont pas trouvé \"{}\""
#~ msgid "no option found in config with these criteria"
#~ msgstr "aucune option trouvée dans la config avec ces critères"
#~ 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}\""
#~ msgid "duplicate option name: \"{0}\""
#~ msgstr "nom de l'option dupliqué : \"{0}\""
#~ msgid "duplicate option: {0}"
#~ msgstr "option dupliquée : {0}"
#~ 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)}\""
#~ msgid "cannot find \"{0}\" in \"{1}\"" #~ msgid "cannot find \"{0}\" in \"{1}\""
#~ msgstr "ne peut pas trouver \"{0}\" dans \"{1}\"" #~ msgstr "ne peut pas trouver \"{0}\" dans \"{1}\""
@ -1077,9 +1096,6 @@ msgstr "l'information de l'objet ne sont pas trouvé \"{}\""
#~ msgid "unknown option \"{0}\" in root optiondescription" #~ msgid "unknown option \"{0}\" in root optiondescription"
#~ msgstr "option \"{0}\" inconnue dans l'optiondescription racine" #~ msgstr "option \"{0}\" inconnue dans l'optiondescription racine"
#~ msgid "unknown option \"{0}\" in optiondescription {1}"
#~ msgstr "option \"{0}\" inconnue dans l'optiondescription {1}"
#~ msgid "" #~ msgid ""
#~ "IP \"{ip[\"value\"]}\" ({ip[\"name\"]}) with this netmask is in fact a " #~ "IP \"{ip[\"value\"]}\" ({ip[\"name\"]}) with this netmask is in fact a "
#~ "broacast address" #~ "broacast address"
@ -1090,9 +1106,6 @@ msgstr "l'information de l'objet ne sont pas trouvé \"{}\""
#~ msgid "Call: {}" #~ msgid "Call: {}"
#~ msgstr "Appel : {}" #~ 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 \"{}\"" #~ msgid "index must be set with the follower option \"{}\""
#~ msgstr "l'index est obligatoire pour l'option suiveuse \"{}\"" #~ msgstr "l'index est obligatoire pour l'option suiveuse \"{}\""
@ -1114,9 +1127,6 @@ msgstr "l'information de l'objet ne sont pas trouvé \"{}\""
#~ msgid "cannot set session_id and config together" #~ msgid "cannot set session_id and config together"
#~ msgstr "session_id et config ne peut être mis ensemble" #~ 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 {}" #~ msgid "unknown option {}"
#~ msgstr "option {} inconnue" #~ msgstr "option {} inconnue"

View file

@ -5,7 +5,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2025-06-28 10:15+0300\n" "POT-Creation-Date: 2025-09-19 22:05+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -35,7 +35,7 @@ msgstr ""
msgid "Commands:" msgid "Commands:"
msgstr "" msgstr ""
#: tiramisu/api.py:118 tiramisu/api.py:1920 #: tiramisu/api.py:118 tiramisu/api.py:1955
msgid "please specify a valid sub function ({0}.{1})" msgid "please specify a valid sub function ({0}.{1})"
msgstr "" msgstr ""
@ -43,67 +43,67 @@ msgstr ""
msgid "please do not specify index ({0}.{1})" msgid "please do not specify index ({0}.{1})"
msgstr "" msgstr ""
#: tiramisu/api.py:211 tiramisu/api.py:906 #: tiramisu/api.py:211 tiramisu/api.py:940
msgid "please specify index with a follower option ({0}.{1})" msgid "please specify index with a follower option ({0}.{1})"
msgstr "" msgstr ""
#: tiramisu/api.py:232 #: tiramisu/api.py:234
msgid "please specify a valid sub function ({0}.{1}): {2}" msgid "please specify a valid sub function ({0}.{1}): {2}"
msgstr "" msgstr ""
#: tiramisu/api.py:493 #: tiramisu/api.py:525
msgid "the option {0} is not a dynamic option, cannot get identifiers with only_self parameter to True" msgid "the option {0} is not a dynamic option, cannot get identifiers with only_self parameter to True"
msgstr "" msgstr ""
#: tiramisu/api.py:581 #: tiramisu/api.py:613
msgid "cannot get option from a follower symlink without index" msgid "cannot get option from a follower symlink without index"
msgstr "" msgstr ""
#: tiramisu/api.py:657 #: tiramisu/api.py:691
msgid "cannot add this property: \"{0}\"" msgid "cannot add this property: \"{0}\""
msgstr "" msgstr ""
#: tiramisu/api.py:684 #: tiramisu/api.py:718
msgid "cannot remove option's property \"{0}\", use permissive instead in option \"{1}\"" msgid "cannot remove option's property \"{0}\", use permissive instead in option \"{1}\""
msgstr "" msgstr ""
#: tiramisu/api.py:688 #: tiramisu/api.py:722
msgid "cannot find \"{0}\" in option \"{1}\"" msgid "cannot find \"{0}\" in option \"{1}\""
msgstr "" msgstr ""
#: tiramisu/api.py:693 #: tiramisu/api.py:727
msgid "cannot remove option's property \"{0}\", use permissive instead in option \"{1}\" at index \"{2}\"" msgid "cannot remove option's property \"{0}\", use permissive instead in option \"{1}\" at index \"{2}\""
msgstr "" msgstr ""
#: tiramisu/api.py:697 #: tiramisu/api.py:731
msgid "cannot find \"{0}\" in option \"{1}\" at index \"{2}\"" msgid "cannot find \"{0}\" in option \"{1}\" at index \"{2}\""
msgstr "" msgstr ""
#: tiramisu/api.py:741 #: tiramisu/api.py:775
msgid "cannot find \"{0}\"" msgid "cannot find \"{0}\""
msgstr "" msgstr ""
#: tiramisu/api.py:923 #: tiramisu/api.py:957
msgid "only multi value has defaultmulti" msgid "only multi value has defaultmulti"
msgstr "" msgstr ""
#: tiramisu/api.py:1087 #: tiramisu/api.py:1121
msgid "please specify a valid sub function ({0}.{1}) for {2}" msgid "please specify a valid sub function ({0}.{1}) for {2}"
msgstr "" msgstr ""
#: tiramisu/api.py:1485 #: tiramisu/api.py:1520
msgid "properties must be a frozenset" msgid "properties must be a frozenset"
msgstr "" msgstr ""
#: tiramisu/api.py:1489 tiramisu/api.py:1516 #: tiramisu/api.py:1524 tiramisu/api.py:1551
msgid "unknown when {} (must be in append or remove)" msgid "unknown when {} (must be in append or remove)"
msgstr "" msgstr ""
#: tiramisu/api.py:1502 tiramisu/api.py:1526 tiramisu/config.py:1722 #: tiramisu/api.py:1537 tiramisu/api.py:1561 tiramisu/config.py:1691
msgid "unknown type {}" msgid "unknown type {}"
msgstr "" msgstr ""
#: tiramisu/api.py:1892 #: tiramisu/api.py:1927
msgid "do not use unrestraint, nowarnings or forcepermissive together" msgid "do not use unrestraint, nowarnings or forcepermissive together"
msgstr "" msgstr ""
@ -167,123 +167,123 @@ msgstr ""
msgid "help_function ({0}) must be a function" msgid "help_function ({0}) must be a function"
msgstr "" msgstr ""
#: tiramisu/autolib.py:469 tiramisu/autolib.py:524 #: tiramisu/autolib.py:469 tiramisu/autolib.py:525
msgid "the option {0} is used in a calculation but is invalid ({1})" msgid "the option {0} is used in a calculation but is invalid ({1})"
msgstr "" msgstr ""
#: tiramisu/autolib.py:482 tiramisu/autolib.py:538 tiramisu/autolib.py:588 #: tiramisu/autolib.py:482 tiramisu/autolib.py:539 tiramisu/autolib.py:589
msgid "unable to get value for calculating {0}, {1}" msgid "unable to get value for calculating {0}, {1}"
msgstr "" msgstr ""
#: tiramisu/autolib.py:517 #: tiramisu/autolib.py:518
msgid "unable to carry out a calculation for {0}, {1}" msgid "unable to carry out a calculation for {0}, {1}"
msgstr "" msgstr ""
#: tiramisu/autolib.py:563 #: tiramisu/autolib.py:564
msgid "cannot find information for {0}, {1} is a dynamic option" msgid "cannot find information for {0}, {1} is a dynamic option"
msgstr "" msgstr ""
#: tiramisu/autolib.py:603 #: tiramisu/autolib.py:604
msgid "option {0} is not a dynoptiondescription or in a dynoptiondescription" msgid "option {0} is not a dynoptiondescription or in a dynoptiondescription"
msgstr "" msgstr ""
#: tiramisu/autolib.py:696 #: tiramisu/autolib.py:697
msgid "cannot calculate arguments for {0}, {1} with identifier \"{2}\", there is no identifiers" msgid "cannot calculate arguments for {0}, {1} with identifier \"{2}\", there is no identifiers"
msgstr "" msgstr ""
#: tiramisu/autolib.py:708 #: tiramisu/autolib.py:709
msgid "cannot calculate arguments for {0}, {1} with identifier \"{2}\", list of valid identifiers: {3}" msgid "cannot calculate arguments for {0}, {1} with identifier \"{2}\", list of valid identifiers: {3}"
msgstr "" msgstr ""
#: tiramisu/autolib.py:819 #: tiramisu/autolib.py:820
msgid "the follower {0} must have index in carry_out_calculation!" msgid "the follower {0} must have index in carry_out_calculation!"
msgstr "" msgstr ""
#: tiramisu/autolib.py:931 #: tiramisu/autolib.py:932
msgid "unexpected error \"{1}\" in function \"{2}\" with arguments \"{3}\" and \"{4}\" for option {0}" msgid "unexpected error \"{1}\" in function \"{2}\" with arguments \"{3}\" and \"{4}\" for option {0}"
msgstr "" msgstr ""
#: tiramisu/autolib.py:941 #: tiramisu/autolib.py:942
msgid "unexpected error \"{1}\" in function \"{2}\" for option {0}" msgid "unexpected error \"{1}\" in function \"{2}\" for option {0}"
msgstr "" msgstr ""
#: tiramisu/config.py:609 #: tiramisu/config.py:391 tiramisu/config.py:413
msgid "option name {0} is not unique in {1}"
msgstr ""
#: tiramisu/config.py:638
msgid "there is no option description for this config (may be GroupConfig)" msgid "there is no option description for this config (may be GroupConfig)"
msgstr "" msgstr ""
#: tiramisu/config.py:698 #: tiramisu/config.py:989 tiramisu/option/optiondescription.py:74
msgid "no option found in config with these criteria"
msgstr ""
#: tiramisu/config.py:1024 tiramisu/option/optiondescription.py:74
msgid "option description seems to be part of an other config" msgid "option description seems to be part of an other config"
msgstr "" msgstr ""
#: tiramisu/config.py:1186 #: tiramisu/config.py:1151
msgid "parent of {0} not already exists" msgid "parent of {0} not already exists"
msgstr "" msgstr ""
#: tiramisu/config.py:1233 #: tiramisu/config.py:1198
msgid "cannot set leadership object has root optiondescription" msgid "cannot set leadership object has root optiondescription"
msgstr "" msgstr ""
#: tiramisu/config.py:1236 #: tiramisu/config.py:1201
msgid "cannot set dynoptiondescription object has root optiondescription" msgid "cannot set dynoptiondescription object has root optiondescription"
msgstr "" msgstr ""
#: tiramisu/config.py:1282 #: tiramisu/config.py:1248
msgid "child must be a Config, GroupConfig, MixConfig or MetaConfig" msgid "child must be a Config, GroupConfig, MixConfig or MetaConfig"
msgstr "" msgstr ""
#: tiramisu/config.py:1290 #: tiramisu/config.py:1257
msgid "config name must be uniq in groupconfig for \"{0}\"" msgid "config name must be uniq in groupconfig for \"{0}\""
msgstr "" msgstr ""
#: tiramisu/config.py:1499 #: tiramisu/config.py:1466
msgid "unknown config \"{}\"" msgid "unknown config \"{}\""
msgstr "" msgstr ""
#: tiramisu/config.py:1524 #: tiramisu/config.py:1491
msgid "child must be a Config, MixConfig or MetaConfig" msgid "child must be a Config, MixConfig or MetaConfig"
msgstr "" msgstr ""
#: tiramisu/config.py:1559 #: tiramisu/config.py:1526
msgid "force_default, force_default_if_same or force_dont_change_value cannot be set with only_config" msgid "force_default, force_default_if_same or force_dont_change_value cannot be set with only_config"
msgstr "" msgstr ""
#: tiramisu/config.py:1569 #: tiramisu/config.py:1536
msgid "force_default and force_dont_change_value cannot be set together" msgid "force_default and force_dont_change_value cannot be set together"
msgstr "" msgstr ""
#: tiramisu/config.py:1718 #: tiramisu/config.py:1687
msgid "config name must be uniq in groupconfig for {0}" msgid "config name must be uniq in groupconfig for {0}"
msgstr "" msgstr ""
#: tiramisu/config.py:1763 #: tiramisu/config.py:1732
msgid "config added has no name, the name is mandatory" msgid "config added has no name, the name is mandatory"
msgstr "" msgstr ""
#: tiramisu/config.py:1768 #: tiramisu/config.py:1737
msgid "config name \"{0}\" is not uniq in groupconfig \"{1}\"" msgid "config name \"{0}\" is not uniq in groupconfig \"{1}\""
msgstr "" msgstr ""
#: tiramisu/config.py:1786 tiramisu/config.py:1792 #: tiramisu/config.py:1755 tiramisu/config.py:1761
msgid "cannot find the config {0}" msgid "cannot find the config {0}"
msgstr "" msgstr ""
#: tiramisu/config.py:1818 #: tiramisu/config.py:1787
msgid "MetaConfig with optiondescription must have string has child, not {}" msgid "MetaConfig with optiondescription must have string has child, not {}"
msgstr "" msgstr ""
#: tiramisu/config.py:1830 #: tiramisu/config.py:1799
msgid "child must be a Config or MetaConfig" msgid "child must be a Config or MetaConfig"
msgstr "" msgstr ""
#: tiramisu/config.py:1835 #: tiramisu/config.py:1804
msgid "all config in metaconfig must have the same optiondescription" msgid "all config in metaconfig must have the same optiondescription"
msgstr "" msgstr ""
#: tiramisu/config.py:1852 #: tiramisu/config.py:1821
msgid "metaconfig must have the same optiondescription" msgid "metaconfig must have the same optiondescription"
msgstr "" msgstr ""
@ -471,31 +471,31 @@ msgstr ""
msgid "the value of \"{0}\" is not {1}" msgid "the value of \"{0}\" is not {1}"
msgstr "" msgstr ""
#: tiramisu/option/baseoption.py:75 tiramisu/option/symlinkoption.py:44 #: tiramisu/option/baseoption.py:76 tiramisu/option/symlinkoption.py:44
msgid "\"{0}\" is an invalid name for an option" msgid "\"{0}\" is an invalid name for an option"
msgstr "" msgstr ""
#: tiramisu/option/baseoption.py:88 #: tiramisu/option/baseoption.py:89
msgid "invalid properties type {0} for {1}, must be a frozenset" msgid "invalid properties type {0} for {1}, must be a frozenset"
msgstr "" msgstr ""
#: tiramisu/option/baseoption.py:100 #: tiramisu/option/baseoption.py:102
msgid "invalid property type {0} for {1}, must be a string or a Calculation" msgid "invalid property type {0} for {1}, must be a string or a Calculation"
msgstr "" msgstr ""
#: tiramisu/option/baseoption.py:251 #: tiramisu/option/baseoption.py:253
msgid "information's item for {0} not found: \"{1}\"" msgid "information's item for {0} not found: \"{1}\""
msgstr "" msgstr ""
#: tiramisu/option/baseoption.py:269 #: tiramisu/option/baseoption.py:271
msgid "'{0}' ({1}) object attribute '{2}' is read-only" msgid "'{0}' ({1}) object attribute '{2}' is read-only"
msgstr "" msgstr ""
#: tiramisu/option/baseoption.py:310 #: tiramisu/option/baseoption.py:312
msgid "\"{}\" ({}) object attribute \"{}\" is read-only" msgid "\"{}\" ({}) object attribute \"{}\" is read-only"
msgstr "" msgstr ""
#: tiramisu/option/baseoption.py:322 #: tiramisu/option/baseoption.py:324
msgid "{0} not part of any Config" msgid "{0} not part of any Config"
msgstr "" msgstr ""
@ -600,7 +600,7 @@ msgstr ""
msgid "invalid identifier \"{}\" for option {}" msgid "invalid identifier \"{}\" for option {}"
msgstr "" msgstr ""
#: tiramisu/option/dynoptiondescription.py:150 #: tiramisu/option/dynoptiondescription.py:154
msgid "DynOptionDescription \"{0}\" identifiers return a list with same values \"{1}\"" msgid "DynOptionDescription \"{0}\" identifiers return a list with same values \"{1}\""
msgstr "" msgstr ""
@ -732,43 +732,49 @@ msgstr ""
msgid "invalid default_multi value \"{0}\" for option {1}, must be a list for a submulti" msgid "invalid default_multi value \"{0}\" for option {1}, must be a list for a submulti"
msgstr "" msgstr ""
#: tiramisu/option/option.py:291 #: tiramisu/option/option.py:294
msgid "the value \"{}\" is not unique" msgid "the value \"{}\" is not unique"
msgstr "" msgstr ""
#: tiramisu/option/option.py:353 #: tiramisu/option/option.py:357
msgid "which must not be a list" msgid "which must not be a list"
msgstr "" msgstr ""
#: tiramisu/option/option.py:408 tiramisu/option/option.py:446 #: tiramisu/option/option.py:412 tiramisu/option/option.py:450
msgid "which must be a list" msgid "which must be a list"
msgstr "" msgstr ""
#: tiramisu/option/option.py:436 #: tiramisu/option/option.py:440
msgid "which \"{}\" must be a list of list" msgid "which \"{}\" must be a list of list"
msgstr "" msgstr ""
#: tiramisu/option/optiondescription.py:109 #: tiramisu/option/optiondescription.py:111
msgid "duplicate option: {0}" #: tiramisu/option/optiondescription.py:117
msgid "\"{0}\" option description"
msgstr "" msgstr ""
#: tiramisu/option/optiondescription.py:336 #: tiramisu/option/optiondescription.py:115
#: tiramisu/option/optiondescription.py:121
msgid "root option description"
msgstr ""
#: tiramisu/option/optiondescription.py:123
msgid "option \"{0}\" is include in {1} but is also in {2}"
msgstr ""
#: tiramisu/option/optiondescription.py:328
msgid "children in optiondescription \"{}\" must be a list" msgid "children in optiondescription \"{}\" must be a list"
msgstr "" msgstr ""
#: tiramisu/option/optiondescription.py:364 #: tiramisu/option/optiondescription.py:357
msgid "duplicate option name: \"{0}\"" msgid "the option name \"{0}\" is duplicate in \"{1}\""
msgstr "" msgstr ""
#: tiramisu/option/optiondescription.py:370 #: tiramisu/option/optiondescription.py:411
msgid "the option's name \"{0}\" start as the dynoptiondescription's name \"{1}\""
msgstr ""
#: tiramisu/option/optiondescription.py:413
msgid "cannot change group_type if already set (old {0}, new {1})" msgid "cannot change group_type if already set (old {0}, new {1})"
msgstr "" msgstr ""
#: tiramisu/option/optiondescription.py:418 #: tiramisu/option/optiondescription.py:416
msgid "group_type: {0} not allowed" msgid "group_type: {0} not allowed"
msgstr "" msgstr ""

View file

@ -332,7 +332,7 @@ def test_duplicated_option():
g1 g1
#in same OptionDescription #in same OptionDescription
with pytest.raises(ConflictError): with pytest.raises(ConflictError):
d1 = OptionDescription('od', '', [g1, g1]) OptionDescription('od', '', [g1, g1])
# assert not list_sessions() # assert not list_sessions()
@ -346,6 +346,28 @@ def test_duplicated_option_diff_od():
Config(d2) Config(d2)
def test_duplicated_option_diff_od_2():
g1 = IntOption('g1', '', 1)
d1 = OptionDescription('od1', '', [g1])
#in different OptionDescription
d2 = OptionDescription('od2', '', [d1, g1])
d2
with pytest.raises(ConflictError):
Config(d2)
def test_duplicated_option_diff_od_3():
g1 = IntOption('g1', '', 1)
d1 = OptionDescription('od1', '', [g1])
d3 = OptionDescription('od3', '', [g1])
#in different OptionDescription
d2 = OptionDescription('od2', '', [d1, d3])
d4 = OptionDescription('od4', '', [d2])
d4
with pytest.raises(ConflictError):
Config(d4)
def test_cannot_assign_value_to_option_description(): def test_cannot_assign_value_to_option_description():
od1 = make_description() od1 = make_description()
cfg = Config(od1) cfg = Config(od1)

View file

@ -1720,16 +1720,6 @@ def test_leadership_callback_samegroup_dyndescription():
# assert not list_sessions() # assert not list_sessions()
def test_invalid_conflict_dyndescription():
st = StrOption('st', '')
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
dodinvalid = StrOption('dodinvalid', '')
dod, dodinvalid
with pytest.raises(ConflictError):
OptionDescription('od', '', [dod, dodinvalid])
# assert not list_sessions()
def test_leadership_default_multi_dyndescription4(): def test_leadership_default_multi_dyndescription4():
st1 = StrOption('st1', "", multi=True) st1 = StrOption('st1', "", multi=True)
st2 = StrOption('st2', "", multi=True, default_multi='no') st2 = StrOption('st2', "", multi=True, default_multi='no')
@ -2883,3 +2873,86 @@ def test_callback_list_dyndescription_information_not_list():
cfg.information.set('identifier', 'ival3') cfg.information.set('identifier', 'ival3')
assert cfg.option('od.dodival3.st').value.get() == ['ival3', 'val2'] assert cfg.option('od.dodival3.st').value.get() == ['ival3', 'val2']
# assert not list_sessions() # assert not list_sessions()
def test_dynoption_not_duplicate():
st = StrOption('st', '')
st2 = StrOption('st', '')
dod = DynOptionDescription('od_', '', [st], identifiers=["val1"])
dod2 = DynOptionDescription('od_', '', [st2], identifiers=["val2"])
od = OptionDescription('od', '', [dod, dod2])
od2 = OptionDescription('od', '', [od])
cfg = Config(od2)
assert parse_od_get(cfg.value.get()) == {
'od.od_val1.st': None,
'od.od_val2.st': None,
}
def test_dynoption_duplicate_1():
st = StrOption('st', '', "val1")
od = OptionDescription('od_val', '', [st])
st2 = StrOption('st', '', "val2")
dod = DynOptionDescription('od_', '', [st2], identifiers=["val"])
od1 = OptionDescription('od', '', [od, dod])
od2 = OptionDescription('od', '', [od1])
cfg = Config(od2)
with pytest.raises(ConflictError):
cfg.value.get()
with pytest.raises(ConflictError):
cfg.option('od.od_val').value.get()
def test_dynoption_duplicate_2():
st2 = StrOption('st', '', "val2")
dod = DynOptionDescription('od_', '', [st2], identifiers=["val"])
st = StrOption('st', '', "val1")
od = OptionDescription('od_val', '', [st])
od1 = OptionDescription('od', '', [dod, od])
od2 = OptionDescription('od', '', [od1])
cfg = Config(od2)
with pytest.raises(ConflictError):
cfg.value.get()
with pytest.raises(ConflictError):
cfg.option('od.od_val').value.get()
def test_dynoption_duplicate_3():
st = StrOption('od_val', '')
st2 = StrOption('st', '', "val2")
dod = DynOptionDescription('od_', '', [st2], identifiers=["val"])
od1 = OptionDescription('od', '', [dod, st])
od2 = OptionDescription('od', '', [od1])
cfg = Config(od2)
with pytest.raises(ConflictError):
cfg.value.get()
with pytest.raises(ConflictError):
cfg.option('od.od_val').value.get()
def test_dynoption_duplicate_4():
st = StrOption('st', '')
st2 = StrOption('st', '')
dod = DynOptionDescription('od_', '', [st], identifiers=["val"])
dod2 = DynOptionDescription('od_', '', [st2], identifiers=["val"])
od = OptionDescription('od', '', [dod, dod2])
od2 = OptionDescription('od', '', [od])
cfg = Config(od2)
with pytest.raises(ConflictError):
cfg.value.get()
with pytest.raises(ConflictError):
cfg.option('od.od_val').value.get()
def test_dynoption_duplicate_5():
st = StrOption('st', '')
st2 = StrOption('st', '')
dod = DynOptionDescription('od_', '', [st], identifiers=["val"])
dod2 = DynOptionDescription('od', '', [st2], identifiers=["_val"])
od = OptionDescription('od', '', [dod, dod2])
od2 = OptionDescription('od', '', [od])
cfg = Config(od2)
with pytest.raises(ConflictError):
cfg.value.get()
with pytest.raises(ConflictError):
cfg.option('od.od_val').value.get()

View file

@ -212,7 +212,9 @@ def option_type(typ):
"please specify index with a follower option ({0}.{1})" "please specify index with a follower option ({0}.{1})"
).format(self.__class__.__name__, func.__name__) ).format(self.__class__.__name__, func.__name__)
raise ConfigError(msg) raise ConfigError(msg)
if 'validate_properties' in types or (self._validate_properties and "dont_validate_property" not in types): if "validate_properties" in types or (
self._validate_properties and "dont_validate_property" not in types
):
settings = self._config_bag.context.get_settings() settings = self._config_bag.context.get_settings()
parent = self._subconfig.parent parent = self._subconfig.parent
if parent and parent.transitive_properties: if parent and parent.transitive_properties:
@ -267,7 +269,9 @@ class _TiramisuOptionWalk:
): ):
options = [] options = []
for sub_subconfig in subconfig.get_children( for sub_subconfig in subconfig.get_children(
validate_properties, uncalculated=uncalculated, with_index=with_index, validate_properties,
uncalculated=uncalculated,
with_index=with_index,
): ):
options.append( options.append(
TiramisuOption( TiramisuOption(
@ -298,7 +302,15 @@ class _TiramisuOptionOptionDescription:
"""Get Tiramisu option""" """Get Tiramisu option"""
return self._subconfig.option return self._subconfig.option
@option_type(["optiondescription", "option", "with_or_without_index", "symlink", "allow_dynoption"]) @option_type(
[
"optiondescription",
"option",
"with_or_without_index",
"symlink",
"allow_dynoption",
]
)
def isoptiondescription(self): def isoptiondescription(self):
"""Test if option is an optiondescription""" """Test if option is an optiondescription"""
return self._subconfig.option.impl_is_optiondescription() return self._subconfig.option.impl_is_optiondescription()
@ -376,10 +388,14 @@ class _TiramisuOptionOptionDescription:
index = self._index index = self._index
parent = self._subconfig.parent parent = self._subconfig.parent
parent_option = parent.option parent_option = parent.option
for woption in self._subconfig.option.get_dependencies(self._config_bag.context): for woption in self._subconfig.option.get_dependencies(
self._config_bag.context
):
option = woption() option = woption()
if not uncalculated and option.issubdyn(): if not uncalculated and option.issubdyn():
for subconfig in context.get_dynamic_from_dyn_option(self._subconfig, option): for subconfig in context.get_dynamic_from_dyn_option(
self._subconfig, option
):
options.append( options.append(
TiramisuOption( TiramisuOption(
subconfig.path, subconfig.path,
@ -388,7 +404,9 @@ class _TiramisuOptionOptionDescription:
) )
) )
elif not uncalculated and option.impl_is_dynoptiondescription(): elif not uncalculated and option.impl_is_dynoptiondescription():
for subconfig in context.get_dynamic_from_dyn_option(self._subconfig, option): for subconfig in context.get_dynamic_from_dyn_option(
self._subconfig, option
):
options.append( options.append(
TiramisuOption( TiramisuOption(
subconfig.path, subconfig.path,
@ -397,7 +415,12 @@ class _TiramisuOptionOptionDescription:
) )
) )
else: else:
if not option.impl_is_optiondescription() and option.impl_is_follower() and parent_option.impl_is_leadership() and parent_option.in_same_leadership(option): if (
not option.impl_is_optiondescription()
and option.impl_is_follower()
and parent_option.impl_is_leadership()
and parent_option.in_same_leadership(option)
):
if index is not None: if index is not None:
current_indexes = [index] current_indexes = [index]
else: else:
@ -606,7 +629,9 @@ class TiramisuOptionOwner(CommonTiramisuOption):
@option_type(["symlink", "option", "with_index"]) @option_type(["symlink", "option", "with_index"])
def get(self, only_self=False): def get(self, only_self=False):
"""Get owner for a specified option""" """Get owner for a specified option"""
return self._config_bag.context.get_owner(self._subconfig, validate_meta=not only_self) return self._config_bag.context.get_owner(
self._subconfig, validate_meta=not only_self
)
@option_type(["symlink", "option", "with_index"]) @option_type(["symlink", "option", "with_index"])
def isdefault(self): def isdefault(self):
@ -1251,7 +1276,7 @@ class TiramisuContextValue(TiramisuConfig, _TiramisuODGet):
path: str, path: str,
value: Any, value: Any,
*, *,
index: Optional[int] = None, index: Optional[int] = None,
only_config=undefined, only_config=undefined,
force_default=undefined, force_default=undefined,
force_default_if_same=undefined, force_default_if_same=undefined,
@ -1269,12 +1294,13 @@ class TiramisuContextValue(TiramisuConfig, _TiramisuODGet):
kwargs["force_dont_change_value"] = force_dont_change_value kwargs["force_dont_change_value"] = force_dont_change_value
context = self._config_bag.context context = self._config_bag.context
if isinstance(context, KernelGroupConfig): if isinstance(context, KernelGroupConfig):
subconfig = Fake_SubConfig(self._config_bag, subconfig = Fake_SubConfig(
path, self._config_bag,
index, path,
) index,
)
else: else:
subconfig = context.get_sub_config( subconfig = context.get_sub_config(
self._config_bag, self._config_bag,
path, path,
index, index,

View file

@ -507,6 +507,7 @@ def manager_callback(
index_, index_,
validate_properties=not self_calc, validate_properties=not self_calc,
properties=properties, properties=properties,
valid_conflict=False,
) )
except PropertiesOptionError as err: except PropertiesOptionError as err:
# raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation # raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation

View file

@ -166,7 +166,7 @@ class CCache:
def get_dynamic_from_dyn_option(self, subconfig, option): def get_dynamic_from_dyn_option(self, subconfig, option):
config_bag = subconfig.config_bag config_bag = subconfig.config_bag
sub_paths = option.impl_getpath() sub_paths = option.impl_getpath()
current_paths = subconfig.path.split('.') current_paths = subconfig.path.split(".")
current_paths_max_index = len(current_paths) - 1 current_paths_max_index = len(current_paths) - 1
current_subconfigs = [] current_subconfigs = []
parent = subconfig parent = subconfig
@ -186,7 +186,10 @@ class CCache:
allow_dynoption=True, allow_dynoption=True,
) )
if sub_option.impl_is_dynoptiondescription(): if sub_option.impl_is_dynoptiondescription():
if idx <= current_paths_max_index and sub_option == current_subconfigs[idx].option: if (
idx <= current_paths_max_index
and sub_option == current_subconfigs[idx].option
):
new_currents.append(current_subconfigs[idx]) new_currents.append(current_subconfigs[idx])
else: else:
new_currents.extend( new_currents.extend(
@ -374,12 +377,26 @@ class SubConfig:
if self.option.impl_is_leadership() and not uncalculated and with_index: if self.option.impl_is_leadership() and not uncalculated and with_index:
yield from self.get_leadership_children(validate_properties) yield from self.get_leadership_children(validate_properties)
else: else:
children_name = []
for child in self.option.get_children(): for child in self.option.get_children():
if child.impl_is_dynoptiondescription() and not uncalculated: if child.impl_is_dynoptiondescription() and not uncalculated:
yield from self.dyn_to_subconfig( for dyn_child in self.dyn_to_subconfig(
child, child,
validate_properties, validate_properties,
) ):
yield dyn_child
if child.could_conflict:
name = dyn_child.path
if name in children_name:
raise ConflictError(
_("option name \"{0}\" is not unique in {1}").format(
name,
self.option.impl_get_display_name(
self, with_quote=True
),
)
)
children_name.append(name)
else: else:
try: try:
yield self.get_child( yield self.get_child(
@ -390,6 +407,18 @@ class SubConfig:
except PropertiesOptionError as err: except PropertiesOptionError as err:
if err.proptype in (["mandatory"], ["empty"]): if err.proptype in (["mandatory"], ["empty"]):
raise err raise err
if child.could_conflict:
name = child.impl_getpath()
if name in children_name:
raise ConflictError(
_("option name \"{0}\" is not unique in {1}").format(
name,
self.option.impl_get_display_name(
self, with_quote=True
),
)
)
children_name.append(name)
def get_child( def get_child(
self, self,
@ -561,15 +590,16 @@ class SubConfig:
def change_context(self, context) -> "SubConfig": def change_context(self, context) -> "SubConfig":
config_bag = self.config_bag.copy() config_bag = self.config_bag.copy()
config_bag.context = context config_bag.context = context
return SubConfig(self.option, return SubConfig(
self.index, self.option,
self.path, self.index,
config_bag, self.path,
self.parent, config_bag,
self.identifiers, self.parent,
true_path=self.true_path, self.identifiers,
validate_properties=False, true_path=self.true_path,
) validate_properties=False,
)
class _Config(CCache): class _Config(CCache):
@ -623,80 +653,8 @@ class _Config(CCache):
"""get cache for values""" """get cache for values"""
return self._impl_values_cache # pylint: disable=no-member return self._impl_values_cache # pylint: disable=no-member
# ============================================================================= # # =============================================================================
# WALK # # WALK
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)
if isinstance(value, list):
return byvalue in value
return value == byvalue
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,
)
for option in options:
path = option.impl_getpath()
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, ...
try:
self.get_sub_config(
option_bag.config_bag, # pylint: disable=no-member
path,
None,
validate_properties=True,
)
except PropertiesOptionError:
continue
found = True
if not with_option:
yield path
else:
yield path, option
self._find_return_results(
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"))
def walk_valid_value( def walk_valid_value(
self, self,
subconfig, subconfig,
@ -741,6 +699,7 @@ class _Config(CCache):
properties=undefined, properties=undefined,
true_path: Optional[str] = None, true_path: Optional[str] = None,
allow_dynoption: bool = False, allow_dynoption: bool = False,
valid_conflict: bool = True,
): ):
subconfig = self.get_root(config_bag) subconfig = self.get_root(config_bag)
if path is None: if path is None:
@ -773,6 +732,32 @@ class _Config(CCache):
identifier, option = option identifier, option = option
else: else:
identifier = None identifier = None
if valid_conflict and option.could_conflict:
for ref in option.could_conflict:
child = ref()
if child.impl_is_dynoptiondescription():
for dyn_child in subconfig.dyn_to_subconfig(
child,
validate_properties,
):
if path == dyn_child.path:
raise ConflictError(
_("option name \"{0}\" is not unique in {1}").format(
name,
option.impl_get_display_name(
subconfig, with_quote=True
),
)
)
elif child.impl_getname() == name:
raise ConflictError(
_("option name \"{0}\" is not unique in {1}").format(
name,
self.option.impl_get_display_name(
self, with_quote=True
),
)
)
subconfig = subconfig.get_child( subconfig = subconfig.get_child(
option, option,
index_, index_,
@ -851,16 +836,14 @@ class _Config(CCache):
# ============================================================================= # =============================================================================
# Manage value # Manage value
def set_value(self, def set_value(
subconfig, self,
value: Any, subconfig,
) -> Any: value: Any,
"""set value ) -> Any:
""" """set value"""
self.get_settings().validate_properties(subconfig) self.get_settings().validate_properties(subconfig)
return self.get_values().set_value(subconfig, return self.get_values().set_value(subconfig, value)
value
)
def get_value( def get_value(
self, self,
@ -1282,7 +1265,9 @@ class KernelGroupConfig(_CommonConfig):
names = [] names = []
for child in children: for child in children:
if not isinstance(child, (KernelConfig, KernelGroupConfig)): if not isinstance(child, (KernelConfig, KernelGroupConfig)):
raise TypeError(_("child must be a Config, GroupConfig, MixConfig or MetaConfig")) raise TypeError(
_("child must be a Config, GroupConfig, MixConfig or MetaConfig")
)
name_ = child._impl_name name_ = child._impl_name
names.append(name_) names.append(name_)
if len(names) != len(set(names)): if len(names) != len(set(names)):
@ -1597,7 +1582,9 @@ class KernelMixConfig(KernelGroupConfig):
validate_properties=validate_properties, validate_properties=validate_properties,
) )
if force_default_if_same: if force_default_if_same:
if not child.get_values().hasvalue(subconfig.path, index=subconfig.index): if not child.get_values().hasvalue(
subconfig.path, index=subconfig.index
):
child_value = undefined child_value = undefined
else: else:
child_value = child.get_value(moption_bag) child_value = child.get_value(moption_bag)

View file

@ -59,6 +59,7 @@ class Base:
"_dependencies", "_dependencies",
"_dependencies_information", "_dependencies_information",
"_identifiers_dependencies", "_identifiers_dependencies",
"could_conflict",
"__weakref__", "__weakref__",
) )
@ -93,6 +94,7 @@ class Base:
_setattr = object.__setattr__ _setattr = object.__setattr__
_setattr(self, "_name", name) _setattr(self, "_name", name)
_setattr(self, "_informations", {"doc": doc}) _setattr(self, "_informations", {"doc": doc})
_setattr(self, "could_conflict", [])
for prop in properties: for prop in properties:
if not isinstance(prop, str): if not isinstance(prop, str):
if not isinstance(prop, Calculation): if not isinstance(prop, Calculation):
@ -188,6 +190,7 @@ class Base:
else: else:
dico = tuple([keys, tuple(dico.values())]) dico = tuple([keys, tuple(dico.values())])
_setattr(self, "_informations", dico) _setattr(self, "_informations", dico)
_setattr(self, "could_conflict", tuple(self.could_conflict))
extra = getattr(self, "_extra", None) extra = getattr(self, "_extra", None)
if extra is not None: if extra is not None:
_setattr( _setattr(

View file

@ -82,6 +82,9 @@ class DynOptionDescription(OptionDescription):
identifier = identifier.replace(".", "_") identifier = identifier.replace(".", "_")
return identifier return identifier
def name_could_conflict(self, dynchild, child):
return child.impl_getname().startswith(dynchild.impl_getname())
def impl_is_dynoptiondescription(self) -> bool: def impl_is_dynoptiondescription(self) -> bool:
return True return True
@ -145,7 +148,11 @@ class DynOptionDescription(OptionDescription):
) )
else: else:
values_.append(val) values_.append(val)
if __debug__ and "demoting_error_warning" not in subconfig.config_bag.properties and len(values_) > len(set(values_)): if (
__debug__
and "demoting_error_warning" not in subconfig.config_bag.properties
and len(values_) > len(set(values_))
):
raise ValueError( raise ValueError(
_( _(
'DynOptionDescription "{0}" identifiers return a list with same values "{1}"' 'DynOptionDescription "{0}" identifiers return a list with same values "{1}"'

View file

@ -286,9 +286,13 @@ class Option(BaseOption):
return return
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 return
indexes = [index for index, value in enumerate(values) if value == current_value] indexes = [
index for index, value in enumerate(values) if value == current_value
]
if len(indexes) > 1: if len(indexes) > 1:
raise ValueError(_('the value "{}" is not unique' "").format(current_value)) raise ValueError(
_('the value "{}" is not unique' "").format(current_value)
)
def calculation_validator( def calculation_validator(
val, val,
@ -456,7 +460,7 @@ class Option(BaseOption):
except ValueError as err: except ValueError as err:
self.validate_parse_error(val, err_index, err, subconfig) self.validate_parse_error(val, err_index, err, subconfig)
ret = False ret = False
# return False # return False
return ret return ret
def validate_parse_error(self, val, index, err, subconfig): def validate_parse_error(self, val, index, err, subconfig):

View file

@ -106,7 +106,24 @@ class CacheOptionDescription(BaseOption):
if "force_store_value" in properties: if "force_store_value" in properties:
force_store_values.append(option) force_store_values.append(option)
if option.impl_is_readonly(): if option.impl_is_readonly():
raise ConflictError(_("duplicate option: {0}").format(option)) previous_path = option.impl_getpath()
if "." in previous_path:
previous_path = _('"{0}" option description').format(
previous_path.rsplit(".", 1)[0]
)
else:
previous_path = _("root option description")
if currpath:
current_path = _('"{0}" option description').format(
".".join(currpath)
)
else:
current_path = _("root option description")
raise ConflictError(
_('option "{0}" is include in {1} but is also in {2}').format(
option.impl_get_display_name(None), current_path, previous_path
)
)
if not self.impl_is_readonly() and display_name: if not self.impl_is_readonly() and display_name:
option._display_name_function = ( option._display_name_function = (
display_name # pylint: disable=protected-access display_name # pylint: disable=protected-access
@ -286,31 +303,6 @@ class OptionDescriptionWalk(CacheOptionDescription):
"""get children""" """get children"""
return self._children[1] 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"""
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,
):
yield subopt
elif (byname is None or option.impl_getname() == byname) and (
bytype is None or isinstance(option, bytype)
):
yield option
class OptionDescription(OptionDescriptionWalk): class OptionDescription(OptionDescriptionWalk):
"""Config's schema (organisation, group) and container of Options """Config's schema (organisation, group) and container of Options
@ -343,35 +335,38 @@ class OptionDescription(OptionDescriptionWalk):
properties=properties, properties=properties,
) )
child_names = [] child_names = []
if __debug__: fix_child_names = []
dynopt_names = [] dynopts = []
for child in children: for child in children:
name = child.impl_getname() name = child.impl_getname()
child_names.append(name) child_names.append(name)
if __debug__ and child.impl_is_dynoptiondescription(): if child.impl_is_dynoptiondescription():
dynopt_names.append(name) dynopts.append(child)
else:
fix_child_names.append(name)
# before sorting # before sorting
children_ = (tuple(child_names), tuple(children)) children_ = (tuple(child_names), tuple(children))
if __debug__: # better performance like this
# better performance like this fix_child_names.sort()
child_names.sort() old = None
old = None for child_name in fix_child_names:
for child in child_names: if child_name == old:
if child == old: raise ConflictError(
raise ConflictError( _('the option name "{0}" is duplicate in "{1}"').format(
_("duplicate option name: " '"{0}"').format(child) child_name, self.impl_get_display_name(None)
) )
if dynopt_names: )
for dynopt in dynopt_names: old = child_name
if child != dynopt and child.startswith(dynopt): for dynopt in dynopts:
raise ConflictError( if dynopt.could_conflict:
_( continue
'the option\'s name "{0}" start as the dynoptiondescription\'s name "{1}"' for child in children:
).format(child, dynopt) if child != dynopt and dynopt.name_could_conflict(dynopt, child):
) dynopt.could_conflict.append(weakref.ref(child))
old = child child.could_conflict.append(weakref.ref(dynopt))
break
self._children = children_ self._children = children_
# the group_type is useful for filtering OptionDescriptions in a config # the group_type is useful for filtering OptionDescriptions in a config
self._group_type = None self._group_type = None