From 90947b557897556a8562d9f27e93e4991a148e99 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Fri, 7 Feb 2025 08:01:59 +0100 Subject: [PATCH] feat: ability to resolve domainname --- locale/fr/LC_MESSAGES/tiramisu.po | 115 +++++++++++++++------ locale/tiramisu.pot | 100 ++++++++++++------ tests/test_config_domain.py | 6 ++ tiramisu/locale/fr/LC_MESSAGES/tiramisu.mo | Bin 25369 -> 26694 bytes tiramisu/option/domainnameoption.py | 19 +++- 5 files changed, 173 insertions(+), 67 deletions(-) diff --git a/locale/fr/LC_MESSAGES/tiramisu.po b/locale/fr/LC_MESSAGES/tiramisu.po index 18c79ad..eb8b124 100644 --- a/locale/fr/LC_MESSAGES/tiramisu.po +++ b/locale/fr/LC_MESSAGES/tiramisu.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: Tiramisu\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-12-15 11:03+0100\n" +"POT-Creation-Date: 2025-02-07 07:55+0100\n" "PO-Revision-Date: \n" "Last-Translator: Emmanuel Garette \n" "Language-Team: Tiramisu's team \n" @@ -205,14 +205,16 @@ msgstr "" "l'option {0} n'est pas une dynoptiondescription ou n'est pas dans une " "dynoptiondescription" -#: tiramisu/autolib.py:685 +#: tiramisu/autolib.py:687 msgid "" -"cannot calculate arguments for \"{0}\", cannot find dynamic variable \"{1}\"" +"cannot calculate arguments for \"{0}\", cannot find dynamic variable \"{1}\" " +"with identifier \"{2}\", list of valid identifiers: {3}" msgstr "" -"impossible de calculer les arguments de \"{0}\", la variable dynamic \"{1}\" " -"ne peut être trouvée" +"impossible de calculer les arguments de \"{0}\", ne peut trouver la variable " +"dynamique \"{1}\" avec l'identifiant \"{2}\", voici la liste des " +"identifiants valables : {3}" -#: tiramisu/autolib.py:864 +#: tiramisu/autolib.py:866 msgid "" "the \"{}\" function with positional arguments \"{}\" and keyword arguments " "\"{}\" must not return a list (\"{}\") for the follower option {}" @@ -221,7 +223,7 @@ msgstr "" "nommés \"{}\" ne doit pas retourner une liste (\"{}\") pour l'option " "suiveuse {}" -#: tiramisu/autolib.py:879 +#: tiramisu/autolib.py:881 msgid "" "the \"{}\" function must not return a list (\"{}\") for the follower option " "{}" @@ -229,7 +231,7 @@ msgstr "" "la fonction \"{}\" ne doit pas retourner une liste (\"{}\") pour l'option " "suiveuse {}" -#: tiramisu/autolib.py:920 +#: tiramisu/autolib.py:922 msgid "" "unexpected error \"{0}\" in function \"{1}\" with arguments \"{3}\" and " "\"{4}\" for option {2}" @@ -237,7 +239,7 @@ msgstr "" "erreur inattendue \"{0}\" dans la fonction \"{1}\" avec les arguments " "\"{3}\" et \"{4}\" pour l'option {2}" -#: tiramisu/autolib.py:931 +#: tiramisu/autolib.py:933 msgid "unexpected error \"{0}\" in function \"{1}\" for option {2}" msgstr "erreur inattendue \"{0}\" dans la fonction \"{1}\" pour l'option {2}" @@ -382,14 +384,23 @@ msgstr "ne peut accéder à l'{0} {1} à cause {2} {3}" msgid "invalid value" msgstr "valeur invalide" -#: tiramisu/error.py:201 +#: tiramisu/error.py:202 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 +#: tiramisu/error.py:204 +msgid "attention, \"{0}\" could be an invalid {1} for \"{2}\" at index \"{3}\"" +msgstr "" +"attention, \"{0}\" peut être un {1} invalide pour \"{2}\" à l'index \"{3}\"" + +#: tiramisu/error.py:223 tiramisu/error.py:234 msgid "\"{0}\" is an invalid {1} for \"{2}\"" msgstr "\"{0}\" est une valeur invalide pour l'option \"{2}\" de type {1}" +#: tiramisu/error.py:225 +msgid "\"{0}\" is an invalid {1} for \"{2}\" at index \"{3}\"" +msgstr "\"{0}\" est un {1} invalide pour \"{2}\" à l'index \"{3}\"" + #: 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" @@ -511,27 +522,27 @@ msgstr "seul \"{0}\" est autorisé" msgid "only {0} are allowed" msgstr "seul {0} sont autorisées" -#: tiramisu/option/domainnameoption.py:60 +#: tiramisu/option/domainnameoption.py:62 msgid "unknown type {0} for hostname" msgstr "type_ inconnu {0} pour le nom d'hôte" -#: tiramisu/option/domainnameoption.py:63 +#: tiramisu/option/domainnameoption.py:65 msgid "allow_ip must be a boolean" msgstr "allow_ip doit être un booléen" -#: tiramisu/option/domainnameoption.py:65 +#: tiramisu/option/domainnameoption.py:67 msgid "allow_cidr_network must be a boolean" msgstr "allow_cidr_network doit être un booléen" -#: tiramisu/option/domainnameoption.py:67 +#: tiramisu/option/domainnameoption.py:69 msgid "allow_without_dot must be a boolean" msgstr "allow_without_dot doit être un booléen" -#: tiramisu/option/domainnameoption.py:69 +#: tiramisu/option/domainnameoption.py:71 msgid "allow_startswith_dot must be a boolean" msgstr "allow_startswith_dot doit être un booléen" -#: tiramisu/option/domainnameoption.py:81 +#: tiramisu/option/domainnameoption.py:82 msgid "" "must start with lowercase characters followed by lowercase characters, " "number, \"-\" and \".\" characters are allowed" @@ -539,7 +550,7 @@ 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 +#: tiramisu/option/domainnameoption.py:85 msgid "" "must start with lowercase characters followed by lowercase characters, " "number, \"-\" and \".\" characters are recommanded" @@ -547,32 +558,56 @@ 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 +#: tiramisu/option/domainnameoption.py:90 +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:93 +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:97 +#: tiramisu/option/domainnameoption.py:98 msgid "could be a IP, otherwise {}" msgstr "peut être une IP, autrement {}" -#: tiramisu/option/domainnameoption.py:134 +#: tiramisu/option/domainnameoption.py:143 msgid "invalid length (min 1)" msgstr "longueur invalide (min 1)" -#: tiramisu/option/domainnameoption.py:137 +#: tiramisu/option/domainnameoption.py:146 msgid "invalid length (max {0})" msgstr "longueur invalide (max {0})" -#: tiramisu/option/domainnameoption.py:143 +#: tiramisu/option/domainnameoption.py:152 msgid "must have dot" msgstr "doit avoir un point" -#: tiramisu/option/domainnameoption.py:145 +#: tiramisu/option/domainnameoption.py:154 msgid "invalid length (max 255)" msgstr "longueur invalide (max 255)" -#: tiramisu/option/domainnameoption.py:163 +#: tiramisu/option/domainnameoption.py:175 +msgid "DNS resolution failed" +msgstr "la résolution DNS a échoué" + +#: tiramisu/option/domainnameoption.py:179 +msgid "error resolving DNS: {1}" +msgstr "erreur de résolution DNS : {1}" + +#: tiramisu/option/domainnameoption.py:186 msgid "must not be an IP" msgstr "ne doit pas être une IP" -#: tiramisu/option/domainnameoption.py:186 +#: tiramisu/option/domainnameoption.py:209 msgid "some characters are uppercase" msgstr "des caractères sont en majuscule" @@ -723,15 +758,15 @@ msgstr "validators doit être une liste de Calculation pour \"{0}\"" msgid "validators must be a Calculation for \"{0}\"" msgstr "validators doit être un Calculation pour \"{0}\"" -#: tiramisu/option/option.py:146 +#: tiramisu/option/option.py:141 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 +#: tiramisu/option/option.py:149 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 +#: tiramisu/option/option.py:162 msgid "" "invalid default_multi value \"{0}\" for option {1}, must be a list for a " "submulti" @@ -739,19 +774,19 @@ msgstr "" "valeur invalide pour default_multi \"{0}\" pour l'option {1}, doit être une " "liste pour une submulti" -#: tiramisu/option/option.py:290 +#: tiramisu/option/option.py:285 msgid "the value \"{}\" is not unique" msgstr "la valeur de \"{}\" n'est pas unique" -#: tiramisu/option/option.py:352 +#: tiramisu/option/option.py:347 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 +#: tiramisu/option/option.py:399 tiramisu/option/option.py:425 msgid "which must be a list" msgstr "qui doit être une liste" -#: tiramisu/option/option.py:424 +#: tiramisu/option/option.py:419 msgid "which \"{}\" must be a list of list" msgstr "lequel \"{}\" doit être une liste de liste" @@ -858,6 +893,10 @@ msgstr "devrait être une nombre entre {0} et {1}" msgid "must be between {0} and {1}" msgstr "doit être une nombre entre {0} et {1}" +#: tiramisu/option/stroption.py:41 +msgid "which is not a string" +msgstr "qui n'est pas une chaîne de caractères" + #: tiramisu/option/symlinkoption.py:51 msgid "" "malformed symlink second parameters must be an option for \"{0}\", not {1}" @@ -869,7 +908,15 @@ msgstr "" msgid "must start with http:// or https://" msgstr "doit débuter par http:// ou https://" -#: tiramisu/option/urloption.py:119 +#: tiramisu/option/urloption.py:116 +msgid "the port \"{0}\" is invalid: {1}" +msgstr "le port \"{0}\" est invalide : {1}" + +#: tiramisu/option/urloption.py:123 +msgid "the domain \"{0}\" is invalid: {1}" +msgstr "le domaine \"{0}\" est invalide : {1}" + +#: tiramisu/option/urloption.py:127 msgid "must ends with a valid resource name" msgstr "doit finir par un nom de ressource valide" diff --git a/locale/tiramisu.pot b/locale/tiramisu.pot index c0311fe..bb56be6 100644 --- a/locale/tiramisu.pot +++ b/locale/tiramisu.pot @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2024-12-15 11:06+0100\n" +"POT-Creation-Date: 2025-02-07 08:01+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -187,23 +187,23 @@ msgstr "" msgid "option {0} is not a dynoptiondescription or in a dynoptiondescription" msgstr "" -#: tiramisu/autolib.py:685 -msgid "cannot calculate arguments for \"{0}\", cannot find dynamic variable \"{1}\"" +#: tiramisu/autolib.py:687 +msgid "cannot calculate arguments for \"{0}\", cannot find dynamic variable \"{1}\" with identifier \"{2}\", list of valid identifiers: {3}" msgstr "" -#: tiramisu/autolib.py:864 +#: tiramisu/autolib.py:866 msgid "the \"{}\" function with positional arguments \"{}\" and keyword arguments \"{}\" must not return a list (\"{}\") for the follower option {}" msgstr "" -#: tiramisu/autolib.py:879 +#: tiramisu/autolib.py:881 msgid "the \"{}\" function must not return a list (\"{}\") for the follower option {}" msgstr "" -#: tiramisu/autolib.py:920 +#: tiramisu/autolib.py:922 msgid "unexpected error \"{0}\" in function \"{1}\" with arguments \"{3}\" and \"{4}\" for option {2}" msgstr "" -#: tiramisu/autolib.py:931 +#: tiramisu/autolib.py:933 msgid "unexpected error \"{0}\" in function \"{1}\" for option {2}" msgstr "" @@ -331,14 +331,22 @@ msgstr "" msgid "invalid value" msgstr "" -#: tiramisu/error.py:201 +#: tiramisu/error.py:202 msgid "attention, \"{0}\" could be an invalid {1} for \"{2}\"" msgstr "" -#: tiramisu/error.py:219 tiramisu/error.py:228 +#: tiramisu/error.py:204 +msgid "attention, \"{0}\" could be an invalid {1} for \"{2}\" at index \"{3}\"" +msgstr "" + +#: tiramisu/error.py:223 tiramisu/error.py:234 msgid "\"{0}\" is an invalid {1} for \"{2}\"" msgstr "" +#: tiramisu/error.py:225 +msgid "\"{0}\" is an invalid {1} for \"{2}\" at index \"{3}\"" +msgstr "" + #: tiramisu/function.py:65 msgid "network \"{0}\" ({1}) does not match with this netmask" msgstr "" @@ -443,60 +451,76 @@ msgstr "" msgid "only {0} are allowed" msgstr "" -#: tiramisu/option/domainnameoption.py:60 +#: tiramisu/option/domainnameoption.py:62 msgid "unknown type {0} for hostname" msgstr "" -#: tiramisu/option/domainnameoption.py:63 +#: tiramisu/option/domainnameoption.py:65 msgid "allow_ip must be a boolean" msgstr "" -#: tiramisu/option/domainnameoption.py:65 +#: tiramisu/option/domainnameoption.py:67 msgid "allow_cidr_network must be a boolean" msgstr "" -#: tiramisu/option/domainnameoption.py:67 +#: tiramisu/option/domainnameoption.py:69 msgid "allow_without_dot must be a boolean" msgstr "" -#: tiramisu/option/domainnameoption.py:69 +#: tiramisu/option/domainnameoption.py:71 msgid "allow_startswith_dot must be a boolean" msgstr "" -#: tiramisu/option/domainnameoption.py:81 +#: tiramisu/option/domainnameoption.py:82 msgid "must start with lowercase characters followed by lowercase characters, number, \"-\" and \".\" characters are allowed" msgstr "" -#: tiramisu/option/domainnameoption.py:84 +#: tiramisu/option/domainnameoption.py:85 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 +#: tiramisu/option/domainnameoption.py:90 +msgid "must start with lowercase characters followed by lowercase characters, number and \"-\" characters are allowed" +msgstr "" + +#: tiramisu/option/domainnameoption.py:93 +msgid "must start with lowercase characters followed by lowercase characters, number and \"-\" characters are recommanded" +msgstr "" + +#: tiramisu/option/domainnameoption.py:97 +#: tiramisu/option/domainnameoption.py:98 msgid "could be a IP, otherwise {}" msgstr "" -#: tiramisu/option/domainnameoption.py:134 +#: tiramisu/option/domainnameoption.py:143 msgid "invalid length (min 1)" msgstr "" -#: tiramisu/option/domainnameoption.py:137 +#: tiramisu/option/domainnameoption.py:146 msgid "invalid length (max {0})" msgstr "" -#: tiramisu/option/domainnameoption.py:143 +#: tiramisu/option/domainnameoption.py:152 msgid "must have dot" msgstr "" -#: tiramisu/option/domainnameoption.py:145 +#: tiramisu/option/domainnameoption.py:154 msgid "invalid length (max 255)" msgstr "" -#: tiramisu/option/domainnameoption.py:163 -msgid "must not be an IP" +#: tiramisu/option/domainnameoption.py:175 +msgid "DNS resolution failed" +msgstr "" + +#: tiramisu/option/domainnameoption.py:179 +msgid "error resolving DNS: {1}" msgstr "" #: tiramisu/option/domainnameoption.py:186 +msgid "must not be an IP" +msgstr "" + +#: tiramisu/option/domainnameoption.py:209 msgid "some characters are uppercase" msgstr "" @@ -632,31 +656,31 @@ msgstr "" msgid "validators must be a Calculation for \"{0}\"" msgstr "" -#: tiramisu/option/option.py:146 +#: tiramisu/option/option.py:141 msgid "invalid default_multi value \"{0}\" for option {1}" msgstr "" -#: tiramisu/option/option.py:154 +#: tiramisu/option/option.py:149 msgid "invalid default_multi value \"{0}\" for option {1}, {2}" msgstr "" -#: tiramisu/option/option.py:167 +#: tiramisu/option/option.py:162 msgid "invalid default_multi value \"{0}\" for option {1}, must be a list for a submulti" msgstr "" -#: tiramisu/option/option.py:290 +#: tiramisu/option/option.py:285 msgid "the value \"{}\" is not unique" msgstr "" -#: tiramisu/option/option.py:352 +#: tiramisu/option/option.py:347 msgid "which must not be a list" msgstr "" -#: tiramisu/option/option.py:404 tiramisu/option/option.py:430 +#: tiramisu/option/option.py:399 tiramisu/option/option.py:425 msgid "which must be a list" msgstr "" -#: tiramisu/option/option.py:424 +#: tiramisu/option/option.py:419 msgid "which \"{}\" must be a list of list" msgstr "" @@ -757,6 +781,10 @@ msgstr "" msgid "must be between {0} and {1}" msgstr "" +#: tiramisu/option/stroption.py:41 +msgid "which is not a string" +msgstr "" + #: tiramisu/option/symlinkoption.py:51 msgid "malformed symlink second parameters must be an option for \"{0}\", not {1}" msgstr "" @@ -765,7 +793,15 @@ msgstr "" msgid "must start with http:// or https://" msgstr "" -#: tiramisu/option/urloption.py:119 +#: tiramisu/option/urloption.py:116 +msgid "the port \"{0}\" is invalid: {1}" +msgstr "" + +#: tiramisu/option/urloption.py:123 +msgid "the domain \"{0}\" is invalid: {1}" +msgstr "" + +#: tiramisu/option/urloption.py:127 msgid "must ends with a valid resource name" msgstr "" diff --git a/tests/test_config_domain.py b/tests/test_config_domain.py index b329c75..3b2afae 100644 --- a/tests/test_config_domain.py +++ b/tests/test_config_domain.py @@ -275,3 +275,9 @@ def test_url(config_type): with pytest.raises(ValueError): cfg.option('u').value.set('https://FOO.COM:8443') # assert not list_sessions() + + +def test_domainname_existence(): + DomainnameOption('d', '', 'google.fr', test_existence=True) + with pytest.raises(ValueError): + DomainnameOption('d', '', 'ljijouuuehyfr.com', test_existence=True) diff --git a/tiramisu/locale/fr/LC_MESSAGES/tiramisu.mo b/tiramisu/locale/fr/LC_MESSAGES/tiramisu.mo index b7017b2ca54947f303abef043eeea3b10dde5690..6d44c40ac723d56f23249f4251cd38287b4a6758 100644 GIT binary patch delta 5465 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 None: # pylint: disable=too-many-branches,too-many-locals,too-many-arguments @@ -68,6 +70,7 @@ class DomainnameOption(StrOption): if not isinstance(allow_startswith_dot, bool): raise ValueError(_("allow_startswith_dot must be a boolean")) extra["_allow_without_dot"] = allow_without_dot + extra["_test_existence"] = test_existence if type == "domainname": if allow_without_dot: min_time = 0 @@ -161,6 +164,20 @@ class DomainnameOption(StrOption): _valid_length(dom) else: _valid_length(value) + self._validate_domain_resolution(value) + + def _validate_domain_resolution(self, value: str) -> None: + if not value.startswith(".") and self.impl_get_extra("_test_existence") is True: + try: + socket.gethostbyname(value) + except socket.gaierror as err: + raise ValueError( + _("DNS resolution failed").format(value) + ) from err + except Exception as err: + raise ValueError( + _("error resolving DNS: {1}").format(value, err) + ) from err def _validate_ip_network(self, value: str) -> None: allow_ip = self.impl_get_extra("_allow_ip")