diff --git a/src/yunohost/service.py b/src/yunohost/service.py index da3bded3c..2ef94878d 100644 --- a/src/yunohost/service.py +++ b/src/yunohost/service.py @@ -287,7 +287,9 @@ def service_reload_or_restart(names, test_conf=True): out, _ = p.communicate() if p.returncode != 0: errors = out.strip().split("\n") - logger.error(m18n.("service_not_reloading_because_conf_broken", errors=errors)) + logger.error( + m18n.n("service_not_reloading_because_conf_broken", errors=errors) + ) continue if _run_service_command("reload-or-restart", name): diff --git a/src/yunohost/utils/config.py b/src/yunohost/utils/config.py index 23a95b565..5c81f5007 100644 --- a/src/yunohost/utils/config.py +++ b/src/yunohost/utils/config.py @@ -29,7 +29,6 @@ from collections import OrderedDict from moulinette.interfaces.cli import colorize from moulinette import Moulinette, m18n from moulinette.utils.log import getActionLogger -from moulinette.utils.process import check_output from moulinette.utils.filesystem import ( write_to_file, read_toml, @@ -80,16 +79,22 @@ class ConfigPanel: result = {} for panel, section, option in self._iterate(): key = f"{panel['id']}.{section['id']}.{option['id']}" - if mode == 'export': - result[option['id']] = option.get('current_value') + if mode == "export": + result[option["id"]] = option.get("current_value") else: - if 'ask' in option: - result[key] = {'ask': _value_for_locale(option['ask'])} - elif 'i18n' in self.config: - result[key] = {'ask': m18n.n(self.config['i18n'] + '_' + option['id'])} - if 'current_value' in option: - question_class = ARGUMENTS_TYPE_PARSERS[option.get("type", "string")] - result[key]['value'] = question_class.humanize(option['current_value'], option) + if "ask" in option: + result[key] = {"ask": _value_for_locale(option["ask"])} + elif "i18n" in self.config: + result[key] = { + "ask": m18n.n(self.config["i18n"] + "_" + option["id"]) + } + if "current_value" in option: + question_class = ARGUMENTS_TYPE_PARSERS[ + option.get("type", "string") + ] + result[key]["value"] = question_class.humanize( + option["current_value"], option + ) return result @@ -294,8 +299,11 @@ class ConfigPanel: self.errors = None def _get_default_values(self): - return { option['id']: option['default'] - for _, _, option in self._iterate() if 'default' in option } + return { + option["id"]: option["default"] + for _, _, option in self._iterate() + if "default" in option + } def _load_current_values(self): """ @@ -319,9 +327,11 @@ class ConfigPanel: mkdir(dir_path, mode=0o700) values_to_save = {**self.values, **self.new_values} - if self.save_mode == 'diff': + if self.save_mode == "diff": defaults = self._get_default_values() - values_to_save = {k: v for k, v in values_to_save.items() if defaults.get(k) != v} + values_to_save = { + k: v for k, v in values_to_save.items() if defaults.get(k) != v + } # Save the settings to the .yaml file write_to_yaml(self.save_path, self.new_values) @@ -360,17 +370,17 @@ class Question(object): def __init__(self, question, user_answers): self.name = question["name"] - self.type = question.get("type", 'string') + self.type = question.get("type", "string") self.default = question.get("default", None) self.current_value = question.get("current_value") self.optional = question.get("optional", False) self.choices = question.get("choices", []) self.pattern = question.get("pattern") - self.ask = question.get("ask", {'en': self.name}) + self.ask = question.get("ask", {"en": self.name}) self.help = question.get("help") self.helpLink = question.get("helpLink") self.value = user_answers.get(self.name) - self.redact = question.get('redact', False) + self.redact = question.get("redact", False) # Empty value is parsed as empty string if self.default == "": @@ -384,11 +394,10 @@ class Question(object): def normalize(value, option={}): return value - def ask_if_needed(self): while True: # Display question if no value filled or if it's a readonly message - if Moulinette.interface.type== 'cli': + if Moulinette.interface.type == "cli": text_for_user_input_in_cli = self._format_text_for_user_input_in_cli() if getattr(self, "readonly", False): Moulinette.display(text_for_user_input_in_cli) @@ -433,7 +442,6 @@ class Question(object): return (self.value, self.argument_type) - def _prevalidate(self): if self.value in [None, ""] and not self.optional: raise YunohostValidationError("app_argument_required", name=self.name) @@ -442,9 +450,9 @@ class Question(object): if self.value is not None: if self.choices and self.value not in self.choices: self._raise_invalid_answer() - if self.pattern and not re.match(self.pattern['regexp'], str(self.value)): + if self.pattern and not re.match(self.pattern["regexp"], str(self.value)): raise YunohostValidationError( - self.pattern['error'], + self.pattern["error"], name=self.name, value=self.value, ) @@ -494,7 +502,10 @@ class Question(object): if self.operation_logger: self.operation_logger.data_to_redact.extend(data_to_redact) elif data_to_redact: - raise YunohostError(f"Can't redact {question.name} because no operation logger available in the context", raw_msg=True) + raise YunohostError( + f"Can't redact {self.name} because no operation logger available in the context", + raw_msg=True, + ) return self.value @@ -510,7 +521,7 @@ class TagsQuestion(Question): @staticmethod def humanize(value, option={}): if isinstance(value, list): - return ','.join(value) + return ",".join(value) return value def _prevalidate(self): @@ -540,7 +551,7 @@ class PasswordQuestion(Question): @staticmethod def humanize(value, option={}): if value: - return '***' # Avoid to display the password on screen + return "********" # Avoid to display the password on screen return "" def _prevalidate(self): @@ -571,32 +582,32 @@ class BooleanQuestion(Question): @staticmethod def humanize(value, option={}): - yes = option.get('yes', 1) - no = option.get('no', 0) + yes = option.get("yes", 1) + no = option.get("no", 0) value = str(value).lower() if value == str(yes).lower(): - return 'yes' + return "yes" if value == str(no).lower(): - return 'no' + return "no" if value in BooleanQuestion.yes_answers: - return 'yes' + return "yes" if value in BooleanQuestion.no_answers: - return 'no' + return "no" - if value in ['none', ""]: - return '' + if value in ["none", ""]: + return "" raise YunohostValidationError( "app_argument_choice_invalid", - name=self.name, - value=self.value, + name=self.name, # FIXME ... + value=value, choices="yes, no, y, n, 1, 0", ) @staticmethod def normalize(value, option={}): - yes = option.get('yes', 1) - no = option.get('no', 0) + yes = option.get("yes", 1) + no = option.get("no", 0) if str(value).lower() in BooleanQuestion.yes_answers: return yes @@ -608,19 +619,18 @@ class BooleanQuestion(Question): return None raise YunohostValidationError( "app_argument_choice_invalid", - name=self.name, - value=self.value, + name=self.name, # FIXME.... + value=value, choices="yes, no, y, n, 1, 0", ) def __init__(self, question, user_answers): super().__init__(question, user_answers) - self.yes = question.get('yes', 1) - self.no = question.get('no', 0) + self.yes = question.get("yes", 1) + self.no = question.get("no", 0) if self.default is None: self.default = False - def _format_text_for_user_input_in_cli(self): text_for_user_input_in_cli = _value_for_locale(self.ask) @@ -652,7 +662,6 @@ class DomainQuestion(Question): self.choices = domain_list()["domains"] - def _raise_invalid_answer(self): raise YunohostValidationError( "app_argument_invalid", field=self.name, error=m18n.n("domain_unknown") @@ -675,7 +684,6 @@ class UserQuestion(Question): self.default = user break - def _raise_invalid_answer(self): raise YunohostValidationError( "app_argument_invalid", @@ -698,7 +706,6 @@ class NumberQuestion(Question): self.max = question.get("max", None) self.step = question.get("step", None) - def _prevalidate(self): super()._prevalidate() if not isinstance(self.value, int) and not ( @@ -744,8 +751,7 @@ class DisplayTextQuestion(Question): super().__init__(question, user_answers) self.optional = True - self.style = question.get("style", "info") - + self.style = question.get("style", "info") def _format_text_for_user_input_in_cli(self): text = self.ask["en"] @@ -780,7 +786,7 @@ class FileQuestion(Question): self.accept = question.get("accept").replace(" ", "").split(",") else: self.accept = [] - if Moulinette.interface.type== "api": + if Moulinette.interface.type == "api": if user_answers.get(f"{self.name}[name]"): self.value = { "content": self.value, @@ -790,10 +796,13 @@ class FileQuestion(Question): if self.value and str(self.value) == self.current_value: self.value = None - def _prevalidate(self): super()._prevalidate() - if isinstance(self.value, str) and self.value and not os.path.exists(self.value): + if ( + isinstance(self.value, str) + and self.value + and not os.path.exists(self.value) + ): raise YunohostValidationError( "app_argument_invalid", field=self.name, @@ -807,10 +816,11 @@ class FileQuestion(Question): raise YunohostValidationError( "app_argument_invalid", field=self.name, - error=m18n.n("file_extension_not_accepted", file=filename, accept=self.accept), + error=m18n.n( + "file_extension_not_accepted", file=filename, accept=self.accept + ), ) - def _post_parse_value(self): from base64 import b64decode @@ -833,7 +843,10 @@ class FileQuestion(Question): # i.e. os.path.join("/foo", "/etc/passwd") == "/etc/passwd" file_path = os.path.normpath(upload_dir + "/" + filename) if not file_path.startswith(upload_dir + "/"): - raise YunohostError(f"Filename '{filename}' received from the API got a relative parent path, which is forbidden", raw_msg=True) + raise YunohostError( + f"Filename '{filename}' received from the API got a relative parent path, which is forbidden", + raw_msg=True, + ) i = 2 while os.path.exists(file_path): file_path = os.path.normpath(upload_dir + "/" + filename + (".%d" % i)) diff --git a/tests/autofix_locale_format.py b/tests/autofix_locale_format.py index f777f06f1..dd7812635 100644 --- a/tests/autofix_locale_format.py +++ b/tests/autofix_locale_format.py @@ -27,11 +27,17 @@ def fix_locale(locale_file): # should also be in the translated string, otherwise the .format # will trigger an exception! subkeys_in_ref = [k[0] for k in re.findall(r"{(\w+)(:\w)?}", string)] - subkeys_in_this_locale = [k[0] for k in re.findall(r"{(\w+)(:\w)?}", this_locale[key])] + subkeys_in_this_locale = [ + k[0] for k in re.findall(r"{(\w+)(:\w)?}", this_locale[key]) + ] - if set(subkeys_in_ref) != set(subkeys_in_this_locale) and (len(subkeys_in_ref) == len(subkeys_in_this_locale)): + if set(subkeys_in_ref) != set(subkeys_in_this_locale) and ( + len(subkeys_in_ref) == len(subkeys_in_this_locale) + ): for i, subkey in enumerate(subkeys_in_ref): - this_locale[key] = this_locale[key].replace('{%s}' % subkeys_in_this_locale[i], '{%s}' % subkey) + this_locale[key] = this_locale[key].replace( + "{%s}" % subkeys_in_this_locale[i], "{%s}" % subkey + ) fixed_stuff = True if fixed_stuff: diff --git a/tests/reformat_locales.py b/tests/reformat_locales.py index 90251d040..9119c7288 100644 --- a/tests/reformat_locales.py +++ b/tests/reformat_locales.py @@ -1,5 +1,6 @@ import re + def reformat(lang, transformations): locale = open(f"locales/{lang}.json").read() @@ -8,31 +9,52 @@ def reformat(lang, transformations): open(f"locales/{lang}.json", "w").write(locale) + ###################################################### -godamn_spaces_of_hell = ["\u00a0", "\u2000", "\u2001", "\u2002", "\u2003", "\u2004", "\u2005", "\u2006", "\u2007", "\u2008", "\u2009", "\u200A", "\u202f", "\u202F", "\u3000"] +godamn_spaces_of_hell = [ + "\u00a0", + "\u2000", + "\u2001", + "\u2002", + "\u2003", + "\u2004", + "\u2005", + "\u2006", + "\u2007", + "\u2008", + "\u2009", + "\u200A", + "\u202f", + "\u202F", + "\u3000", +] transformations = {s: " " for s in godamn_spaces_of_hell} -transformations.update({ - "…": "...", -}) +transformations.update( + { + "…": "...", + } +) reformat("en", transformations) ###################################################### -transformations.update({ - "courriel": "email", - "e-mail": "email", - "Courriel": "Email", - "E-mail": "Email", - "« ": "'", - "«": "'", - " »": "'", - "»": "'", - "’": "'", - #r"$(\w{1,2})'|( \w{1,2})'": r"\1\2’", -}) +transformations.update( + { + "courriel": "email", + "e-mail": "email", + "Courriel": "Email", + "E-mail": "Email", + "« ": "'", + "«": "'", + " »": "'", + "»": "'", + "’": "'", + # r"$(\w{1,2})'|( \w{1,2})'": r"\1\2’", + } +) reformat("fr", transformations)