mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
[CI] Format code
This commit is contained in:
parent
c2fc2c4e51
commit
ec5e5d6b73
5 changed files with 62 additions and 49 deletions
|
@ -58,7 +58,7 @@ from yunohost.utils.config import (
|
||||||
ask_questions_and_parse_answers,
|
ask_questions_and_parse_answers,
|
||||||
Question,
|
Question,
|
||||||
DomainQuestion,
|
DomainQuestion,
|
||||||
PathQuestion
|
PathQuestion,
|
||||||
)
|
)
|
||||||
from yunohost.utils.i18n import _value_for_locale
|
from yunohost.utils.i18n import _value_for_locale
|
||||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||||
|
@ -903,7 +903,11 @@ def app_install(
|
||||||
# Retrieve arguments list for install script
|
# Retrieve arguments list for install script
|
||||||
raw_questions = manifest.get("arguments", {}).get("install", {})
|
raw_questions = manifest.get("arguments", {}).get("install", {})
|
||||||
questions = ask_questions_and_parse_answers(raw_questions, prefilled_answers=args)
|
questions = ask_questions_and_parse_answers(raw_questions, prefilled_answers=args)
|
||||||
args = {question.name: question.value for question in questions if question.value is not None}
|
args = {
|
||||||
|
question.name: question.value
|
||||||
|
for question in questions
|
||||||
|
if question.value is not None
|
||||||
|
}
|
||||||
|
|
||||||
# Validate domain / path availability for webapps
|
# Validate domain / path availability for webapps
|
||||||
path_requirement = _guess_webapp_path_requirement(questions, extracted_app_folder)
|
path_requirement = _guess_webapp_path_requirement(questions, extracted_app_folder)
|
||||||
|
@ -1642,13 +1646,15 @@ def app_action_run(operation_logger, app, action, args=None):
|
||||||
# Retrieve arguments list for install script
|
# Retrieve arguments list for install script
|
||||||
raw_questions = actions[action].get("arguments", {})
|
raw_questions = actions[action].get("arguments", {})
|
||||||
questions = ask_questions_and_parse_answers(raw_questions, prefilled_answers=args)
|
questions = ask_questions_and_parse_answers(raw_questions, prefilled_answers=args)
|
||||||
args = {question.name: question.value for question in questions if question.value is not None}
|
args = {
|
||||||
|
question.name: question.value
|
||||||
|
for question in questions
|
||||||
|
if question.value is not None
|
||||||
|
}
|
||||||
|
|
||||||
tmp_workdir_for_app = _make_tmp_workdir_for_app(app=app)
|
tmp_workdir_for_app = _make_tmp_workdir_for_app(app=app)
|
||||||
|
|
||||||
env_dict = _make_environment_for_app_script(
|
env_dict = _make_environment_for_app_script(app, args=args, args_prefix="ACTION_")
|
||||||
app, args=args, args_prefix="ACTION_"
|
|
||||||
)
|
|
||||||
env_dict["YNH_ACTION"] = action
|
env_dict["YNH_ACTION"] = action
|
||||||
env_dict["YNH_APP_BASEDIR"] = tmp_workdir_for_app
|
env_dict["YNH_APP_BASEDIR"] = tmp_workdir_for_app
|
||||||
|
|
||||||
|
@ -2404,15 +2410,15 @@ def _guess_webapp_path_requirement(questions: List[Question], app_folder: str) -
|
||||||
|
|
||||||
if re.search(
|
if re.search(
|
||||||
r"\npath(_url)?=[\"']?/[\"']?", install_script_content
|
r"\npath(_url)?=[\"']?/[\"']?", install_script_content
|
||||||
) and re.search(
|
) and re.search(r"ynh_webpath_register", install_script_content):
|
||||||
r"ynh_webpath_register", install_script_content
|
|
||||||
):
|
|
||||||
return "full_domain"
|
return "full_domain"
|
||||||
|
|
||||||
return "?"
|
return "?"
|
||||||
|
|
||||||
|
|
||||||
def _validate_webpath_requirement(questions: List[Question], path_requirement: str) -> None:
|
def _validate_webpath_requirement(
|
||||||
|
questions: List[Question], path_requirement: str
|
||||||
|
) -> None:
|
||||||
|
|
||||||
domain_questions = [question for question in questions if question.type == "domain"]
|
domain_questions = [question for question in questions if question.type == "domain"]
|
||||||
path_questions = [question for question in questions if question.type == "path"]
|
path_questions = [question for question in questions if question.type == "path"]
|
||||||
|
|
|
@ -148,9 +148,9 @@ def test_app_config_regular_setting(config_app):
|
||||||
assert app_config_get(config_app, "main.components.boolean") == "1"
|
assert app_config_get(config_app, "main.components.boolean") == "1"
|
||||||
assert app_setting(config_app, "boolean") == "1"
|
assert app_setting(config_app, "boolean") == "1"
|
||||||
|
|
||||||
with pytest.raises(YunohostValidationError), \
|
with pytest.raises(YunohostValidationError), patch.object(
|
||||||
patch.object(os, "isatty", return_value=False), \
|
os, "isatty", return_value=False
|
||||||
patch.object(Moulinette, "prompt", return_value="pwet"):
|
), patch.object(Moulinette, "prompt", return_value="pwet"):
|
||||||
app_config_set(config_app, "main.components.boolean", "pwet")
|
app_config_set(config_app, "main.components.boolean", "pwet")
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ from yunohost.utils.config import (
|
||||||
DomainQuestion,
|
DomainQuestion,
|
||||||
PathQuestion,
|
PathQuestion,
|
||||||
BooleanQuestion,
|
BooleanQuestion,
|
||||||
FileQuestion
|
FileQuestion,
|
||||||
)
|
)
|
||||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||||
|
|
||||||
|
@ -94,7 +94,6 @@ def test_question_string_default_type():
|
||||||
assert out.value == "some_value"
|
assert out.value == "some_value"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_question_string_no_input():
|
def test_question_string_no_input():
|
||||||
questions = [
|
questions = [
|
||||||
{
|
{
|
||||||
|
@ -486,12 +485,7 @@ def test_question_password_no_input_optional():
|
||||||
assert out.value == ""
|
assert out.value == ""
|
||||||
|
|
||||||
questions = [
|
questions = [
|
||||||
{
|
{"name": "some_password", "type": "password", "optional": True, "default": ""}
|
||||||
"name": "some_password",
|
|
||||||
"type": "password",
|
|
||||||
"optional": True,
|
|
||||||
"default": ""
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
|
|
||||||
with patch.object(os, "isatty", return_value=False):
|
with patch.object(os, "isatty", return_value=False):
|
||||||
|
@ -1725,6 +1719,7 @@ def test_question_number_input():
|
||||||
assert out.type == "number"
|
assert out.type == "number"
|
||||||
assert out.value == 0
|
assert out.value == 0
|
||||||
|
|
||||||
|
|
||||||
def test_question_number_input_no_ask():
|
def test_question_number_input_no_ask():
|
||||||
questions = [
|
questions = [
|
||||||
{
|
{
|
||||||
|
@ -1933,13 +1928,7 @@ def test_question_number_input_test_ask_with_help():
|
||||||
|
|
||||||
|
|
||||||
def test_question_display_text():
|
def test_question_display_text():
|
||||||
questions = [
|
questions = [{"name": "some_app", "type": "display_text", "ask": "foobar"}]
|
||||||
{
|
|
||||||
"name": "some_app",
|
|
||||||
"type": "display_text",
|
|
||||||
"ask": "foobar"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
answers = {}
|
answers = {}
|
||||||
|
|
||||||
with patch.object(sys, "stdout", new_callable=StringIO) as stdout, patch.object(
|
with patch.object(sys, "stdout", new_callable=StringIO) as stdout, patch.object(
|
||||||
|
|
|
@ -420,7 +420,9 @@ def user_update(
|
||||||
# without a specified value, change_password will be set to the const 0.
|
# without a specified value, change_password will be set to the const 0.
|
||||||
# In this case we prompt for the new password.
|
# In this case we prompt for the new password.
|
||||||
if Moulinette.interface.type == "cli" and not change_password:
|
if Moulinette.interface.type == "cli" and not change_password:
|
||||||
change_password = Moulinette.prompt(m18n.n("ask_password"), is_password=True, confirm=True)
|
change_password = Moulinette.prompt(
|
||||||
|
m18n.n("ask_password"), is_password=True, confirm=True
|
||||||
|
)
|
||||||
# Ensure sufficiently complex password
|
# Ensure sufficiently complex password
|
||||||
assert_password_is_strong_enough("user", change_password)
|
assert_password_is_strong_enough("user", change_password)
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,9 @@ class ConfigPanel:
|
||||||
)
|
)
|
||||||
# FIXME: semantics, technically here this is not about a prompt...
|
# FIXME: semantics, technically here this is not about a prompt...
|
||||||
if question_class.hide_user_input_in_prompt:
|
if question_class.hide_user_input_in_prompt:
|
||||||
result[key]["value"] = "**************" # Prevent displaying password in `config get`
|
result[key][
|
||||||
|
"value"
|
||||||
|
] = "**************" # Prevent displaying password in `config get`
|
||||||
|
|
||||||
if mode == "full":
|
if mode == "full":
|
||||||
return self.config
|
return self.config
|
||||||
|
@ -269,9 +271,7 @@ class ConfigPanel:
|
||||||
|
|
||||||
# Now fill the sublevels (+ apply filter_key)
|
# Now fill the sublevels (+ apply filter_key)
|
||||||
i = list(format_description).index(level)
|
i = list(format_description).index(level)
|
||||||
sublevel = (
|
sublevel = list(format_description)[i + 1] if level != "options" else None
|
||||||
list(format_description)[i + 1] if level != "options" else None
|
|
||||||
)
|
|
||||||
search_key = filter_key[i] if len(filter_key) > i else False
|
search_key = filter_key[i] if len(filter_key) > i else False
|
||||||
|
|
||||||
for key, value in raw_infos.items():
|
for key, value in raw_infos.items():
|
||||||
|
@ -385,11 +385,13 @@ class ConfigPanel:
|
||||||
|
|
||||||
# Check and ask unanswered questions
|
# Check and ask unanswered questions
|
||||||
questions = ask_questions_and_parse_answers(section["options"], self.args)
|
questions = ask_questions_and_parse_answers(section["options"], self.args)
|
||||||
self.new_values.update({
|
self.new_values.update(
|
||||||
|
{
|
||||||
question.name: question.value
|
question.name: question.value
|
||||||
for question in questions
|
for question in questions
|
||||||
if question.value is not None
|
if question.value is not None
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
self.errors = None
|
self.errors = None
|
||||||
|
|
||||||
|
@ -506,7 +508,7 @@ class Question(object):
|
||||||
prefill=prefill,
|
prefill=prefill,
|
||||||
is_multiline=(self.type == "text"),
|
is_multiline=(self.type == "text"),
|
||||||
autocomplete=self.choices,
|
autocomplete=self.choices,
|
||||||
help=_value_for_locale(self.help)
|
help=_value_for_locale(self.help),
|
||||||
)
|
)
|
||||||
|
|
||||||
def ask_if_needed(self):
|
def ask_if_needed(self):
|
||||||
|
@ -574,12 +576,18 @@ class Question(object):
|
||||||
|
|
||||||
# Prevent displaying a shitload of choices
|
# Prevent displaying a shitload of choices
|
||||||
# (e.g. 100+ available users when choosing an app admin...)
|
# (e.g. 100+ available users when choosing an app admin...)
|
||||||
choices = list(self.choices.values()) if isinstance(self.choices, dict) else self.choices
|
choices = (
|
||||||
|
list(self.choices.values())
|
||||||
|
if isinstance(self.choices, dict)
|
||||||
|
else self.choices
|
||||||
|
)
|
||||||
choices_to_display = choices[:20]
|
choices_to_display = choices[:20]
|
||||||
remaining_choices = len(choices[20:])
|
remaining_choices = len(choices[20:])
|
||||||
|
|
||||||
if remaining_choices > 0:
|
if remaining_choices > 0:
|
||||||
choices_to_display += [m18n.n("other_available_options", n=remaining_choices)]
|
choices_to_display += [
|
||||||
|
m18n.n("other_available_options", n=remaining_choices)
|
||||||
|
]
|
||||||
|
|
||||||
choices_to_display = " | ".join(choices_to_display)
|
choices_to_display = " | ".join(choices_to_display)
|
||||||
|
|
||||||
|
@ -744,7 +752,7 @@ class PathQuestion(Question):
|
||||||
raise YunohostValidationError(
|
raise YunohostValidationError(
|
||||||
"app_argument_invalid",
|
"app_argument_invalid",
|
||||||
name=option.get("name"),
|
name=option.get("name"),
|
||||||
error="Question is mandatory"
|
error="Question is mandatory",
|
||||||
)
|
)
|
||||||
|
|
||||||
return "/" + value.strip().strip(" /")
|
return "/" + value.strip().strip(" /")
|
||||||
|
@ -794,8 +802,12 @@ class BooleanQuestion(Question):
|
||||||
no_answers = BooleanQuestion.no_answers
|
no_answers = BooleanQuestion.no_answers
|
||||||
yes_answers = BooleanQuestion.yes_answers
|
yes_answers = BooleanQuestion.yes_answers
|
||||||
|
|
||||||
assert str(technical_yes).lower() not in no_answers, f"'yes' value can't be in {no_answers}"
|
assert (
|
||||||
assert str(technical_no).lower() not in yes_answers, f"'no' value can't be in {yes_answers}"
|
str(technical_yes).lower() not in no_answers
|
||||||
|
), f"'yes' value can't be in {no_answers}"
|
||||||
|
assert (
|
||||||
|
str(technical_no).lower() not in yes_answers
|
||||||
|
), f"'no' value can't be in {yes_answers}"
|
||||||
|
|
||||||
no_answers += [str(technical_no).lower()]
|
no_answers += [str(technical_no).lower()]
|
||||||
yes_answers += [str(technical_yes).lower()]
|
yes_answers += [str(technical_yes).lower()]
|
||||||
|
@ -915,7 +927,7 @@ class NumberQuestion(Question):
|
||||||
raise YunohostValidationError(
|
raise YunohostValidationError(
|
||||||
"app_argument_invalid",
|
"app_argument_invalid",
|
||||||
name=option.get("name"),
|
name=option.get("name"),
|
||||||
error=m18n.n("invalid_number")
|
error=m18n.n("invalid_number"),
|
||||||
)
|
)
|
||||||
|
|
||||||
def _prevalidate(self):
|
def _prevalidate(self):
|
||||||
|
@ -1044,7 +1056,9 @@ ARGUMENTS_TYPE_PARSERS = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def ask_questions_and_parse_answers(questions: Dict, prefilled_answers: Union[str, Mapping[str, Any]] = {}) -> List[Question]:
|
def ask_questions_and_parse_answers(
|
||||||
|
questions: Dict, prefilled_answers: Union[str, Mapping[str, Any]] = {}
|
||||||
|
) -> List[Question]:
|
||||||
"""Parse arguments store in either manifest.json or actions.json or from a
|
"""Parse arguments store in either manifest.json or actions.json or from a
|
||||||
config panel against the user answers when they are present.
|
config panel against the user answers when they are present.
|
||||||
|
|
||||||
|
@ -1062,7 +1076,9 @@ def ask_questions_and_parse_answers(questions: Dict, prefilled_answers: Union[st
|
||||||
# whereas parse.qs return list of values (which is useful for tags, etc)
|
# whereas parse.qs return list of values (which is useful for tags, etc)
|
||||||
# For now, let's not migrate this piece of code to parse_qs
|
# For now, let's not migrate this piece of code to parse_qs
|
||||||
# Because Aleks believes some bits of the app CI rely on overriding values (e.g. foo=foo&...&foo=bar)
|
# Because Aleks believes some bits of the app CI rely on overriding values (e.g. foo=foo&...&foo=bar)
|
||||||
prefilled_answers = dict(urllib.parse.parse_qsl(prefilled_answers or "", keep_blank_values=True))
|
prefilled_answers = dict(
|
||||||
|
urllib.parse.parse_qsl(prefilled_answers or "", keep_blank_values=True)
|
||||||
|
)
|
||||||
|
|
||||||
if not prefilled_answers:
|
if not prefilled_answers:
|
||||||
prefilled_answers = {}
|
prefilled_answers = {}
|
||||||
|
|
Loading…
Add table
Reference in a new issue