Merge pull request #1319 from YunoHost/ci-format-dev

[CI] Format code
This commit is contained in:
Alexandre Aubin 2021-09-13 02:40:23 +02:00 committed by GitHub
commit 092d6f9df7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 417 additions and 254 deletions

View file

@ -511,7 +511,12 @@ def app_upgrade(app=[], url=None, file=None, force=False, no_safety_backup=False
"""
from packaging import version
from yunohost.hook import hook_add, hook_remove, hook_callback, hook_exec_with_script_debug_if_failure
from yunohost.hook import (
hook_add,
hook_remove,
hook_callback,
hook_exec_with_script_debug_if_failure,
)
from yunohost.permission import permission_sync_to_user
from yunohost.regenconf import manually_modified_files
@ -633,12 +638,17 @@ def app_upgrade(app=[], url=None, file=None, force=False, no_safety_backup=False
# Execute the app upgrade script
upgrade_failed = True
try:
upgrade_failed, failure_message_with_debug_instructions = hook_exec_with_script_debug_if_failure(
(
upgrade_failed,
failure_message_with_debug_instructions,
) = hook_exec_with_script_debug_if_failure(
extracted_app_folder + "/scripts/upgrade",
env=env_dict,
operation_logger=operation_logger,
error_message_if_script_failed=m18n.n("app_upgrade_script_failed"),
error_message_if_failed=lambda e: m18n.n("app_upgrade_failed", app=app_instance_name, error=e)
error_message_if_failed=lambda e: m18n.n(
"app_upgrade_failed", app=app_instance_name, error=e
),
)
finally:
# Whatever happened (install success or failure) we check if it broke the system
@ -669,7 +679,7 @@ def app_upgrade(app=[], url=None, file=None, force=False, no_safety_backup=False
if upgrade_failed or broke_the_system:
# display this if there are remaining apps
if apps[number + 1:]:
if apps[number + 1 :]:
not_upgraded_apps = apps[number:]
logger.error(
m18n.n(
@ -785,7 +795,13 @@ def app_install(
force -- Do not ask for confirmation when installing experimental / low-quality apps
"""
from yunohost.hook import hook_add, hook_remove, hook_callback, hook_exec, hook_exec_with_script_debug_if_failure
from yunohost.hook import (
hook_add,
hook_remove,
hook_callback,
hook_exec,
hook_exec_with_script_debug_if_failure,
)
from yunohost.log import OperationLogger
from yunohost.permission import (
user_permission_list,
@ -976,12 +992,17 @@ def app_install(
# Execute the app install script
install_failed = True
try:
install_failed, failure_message_with_debug_instructions = hook_exec_with_script_debug_if_failure(
(
install_failed,
failure_message_with_debug_instructions,
) = hook_exec_with_script_debug_if_failure(
os.path.join(extracted_app_folder, "scripts/install"),
env=env_dict,
operation_logger=operation_logger,
error_message_if_script_failed=m18n.n("app_install_script_failed"),
error_message_if_failed=lambda e: m18n.n("app_install_failed", app=app_id, error=e)
error_message_if_failed=lambda e: m18n.n(
"app_install_failed", app=app_id, error=e
),
)
finally:
# If success so far, validate that app didn't break important stuff
@ -1670,7 +1691,9 @@ def app_config_get(app, key="", full=False, export=False):
Display an app configuration in classic, full or export mode
"""
if full and export:
raise YunohostValidationError("You can't use --full and --export together.", raw_msg=True)
raise YunohostValidationError(
"You can't use --full and --export together.", raw_msg=True
)
if full:
mode = "full"

View file

@ -1496,13 +1496,18 @@ class RestoreManager:
# Execute the app install script
restore_failed = True
try:
restore_failed, failure_message_with_debug_instructions = hook_exec_with_script_debug_if_failure(
(
restore_failed,
failure_message_with_debug_instructions,
) = hook_exec_with_script_debug_if_failure(
restore_script,
chdir=app_backup_in_archive,
env=env_dict,
operation_logger=operation_logger,
error_message_if_script_failed=m18n.n("app_restore_script_failed"),
error_message_if_failed=lambda e: m18n.n("app_restore_failed", app=app_instance_name, error=e)
error_message_if_failed=lambda e: m18n.n(
"app_restore_failed", app=app_instance_name, error=e
),
)
finally:
# Cleaning temporary scripts directory

View file

@ -288,7 +288,11 @@ def service_reload_or_restart(names, test_conf=True):
if p.returncode != 0:
errors = out.decode().strip().split("\n")
logger.error(
m18n.n("service_not_reloading_because_conf_broken", name=name, errors=errors)
m18n.n(
"service_not_reloading_because_conf_broken",
name=name,
errors=errors,
)
)
continue

View file

@ -80,7 +80,6 @@ def legacy_app(request):
return "legacy_app"
@pytest.fixture()
def config_app(request):
@ -168,7 +167,10 @@ def test_app_config_bind_on_file(config_app):
def test_app_config_custom_get(config_app):
assert app_setting(config_app, "arg9") is None
assert "Files in /var/www" in app_config_get(config_app, "bind.function.arg9")["ask"]["en"]
assert (
"Files in /var/www"
in app_config_get(config_app, "bind.function.arg9")["ask"]["en"]
)
assert app_setting(config_app, "arg9") is None

View file

@ -12,7 +12,7 @@ from yunohost import domain, user
from yunohost.utils.config import (
parse_args_in_yunohost_format,
PasswordQuestion,
Question
Question,
)
from yunohost.utils.error import YunohostError
@ -75,8 +75,7 @@ def test_question_string_no_input():
]
answers = {}
with pytest.raises(YunohostError), \
patch.object(os, "isatty", return_value=False):
with pytest.raises(YunohostError), patch.object(os, "isatty", return_value=False):
parse_args_in_yunohost_format(answers, questions)
@ -90,8 +89,9 @@ def test_question_string_input():
answers = {}
expected_result = OrderedDict({"some_string": ("some_value", "string")})
with patch.object(Moulinette, "prompt", return_value="some_value"), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value="some_value"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -104,8 +104,9 @@ def test_question_string_input_no_ask():
answers = {}
expected_result = OrderedDict({"some_string": ("some_value", "string")})
with patch.object(Moulinette, "prompt", return_value="some_value"), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value="some_value"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -133,8 +134,9 @@ def test_question_string_optional_with_input():
answers = {}
expected_result = OrderedDict({"some_string": ("some_value", "string")})
with patch.object(Moulinette, "prompt", return_value="some_value"), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value="some_value"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -149,8 +151,9 @@ def test_question_string_optional_with_empty_input():
answers = {}
expected_result = OrderedDict({"some_string": ("", "string")})
with patch.object(Moulinette, "prompt", return_value=""), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value=""), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -164,8 +167,9 @@ def test_question_string_optional_with_input_without_ask():
answers = {}
expected_result = OrderedDict({"some_string": ("some_value", "string")})
with patch.object(Moulinette, "prompt", return_value="some_value"), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value="some_value"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -198,8 +202,11 @@ def test_question_string_input_test_ask():
) as prompt, patch.object(os, "isatty", return_value=True):
parse_args_in_yunohost_format(answers, questions)
prompt.assert_called_with(
message=ask_text, is_password=False, confirm=False,
prefill='', is_multiline=False
message=ask_text,
is_password=False,
confirm=False,
prefill="",
is_multiline=False,
)
@ -221,8 +228,10 @@ def test_question_string_input_test_ask_with_default():
parse_args_in_yunohost_format(answers, questions)
prompt.assert_called_with(
message=ask_text,
is_password=False, confirm=False,
prefill=default_text, is_multiline=False
is_password=False,
confirm=False,
prefill=default_text,
is_multiline=False,
)
@ -243,8 +252,8 @@ def test_question_string_input_test_ask_with_example():
Moulinette, "prompt", return_value="some_value"
) as prompt, patch.object(os, "isatty", return_value=True):
parse_args_in_yunohost_format(answers, questions)
assert ask_text in prompt.call_args[1]['message']
assert example_text in prompt.call_args[1]['message']
assert ask_text in prompt.call_args[1]["message"]
assert example_text in prompt.call_args[1]["message"]
@pytest.mark.skip # we should do something with this help
@ -264,8 +273,8 @@ def test_question_string_input_test_ask_with_help():
Moulinette, "prompt", return_value="some_value"
) as prompt, patch.object(os, "isatty", return_value=True):
parse_args_in_yunohost_format(answers, questions)
assert ask_text in prompt.call_args[1]['message']
assert help_text in prompt.call_args[1]['message']
assert ask_text in prompt.call_args[1]["message"]
assert help_text in prompt.call_args[1]["message"]
def test_question_string_with_choice():
@ -279,8 +288,9 @@ def test_question_string_with_choice_prompt():
questions = [{"name": "some_string", "type": "string", "choices": ["fr", "en"]}]
answers = {"some_string": "fr"}
expected_result = OrderedDict({"some_string": ("fr", "string")})
with patch.object(Moulinette, "prompt", return_value="fr"), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value="fr"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -288,8 +298,7 @@ def test_question_string_with_choice_bad():
questions = [{"name": "some_string", "type": "string", "choices": ["fr", "en"]}]
answers = {"some_string": "bad"}
with pytest.raises(YunohostError), \
patch.object(os, "isatty", return_value=False):
with pytest.raises(YunohostError), patch.object(os, "isatty", return_value=False):
assert parse_args_in_yunohost_format(answers, questions)
@ -305,13 +314,14 @@ def test_question_string_with_choice_ask():
]
answers = {}
with patch.object(Moulinette, "prompt", return_value="ru") as prompt, \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value="ru") as prompt, patch.object(
os, "isatty", return_value=True
):
parse_args_in_yunohost_format(answers, questions)
assert ask_text in prompt.call_args[1]['message']
assert ask_text in prompt.call_args[1]["message"]
for choice in choices:
assert choice in prompt.call_args[1]['message']
assert choice in prompt.call_args[1]["message"]
def test_question_string_with_choice_default():
@ -352,8 +362,7 @@ def test_question_password_no_input():
]
answers = {}
with pytest.raises(YunohostError), \
patch.object(os, "isatty", return_value=False):
with pytest.raises(YunohostError), patch.object(os, "isatty", return_value=False):
parse_args_in_yunohost_format(answers, questions)
@ -366,13 +375,15 @@ def test_question_password_input():
}
]
answers = {}
Question.operation_logger = { 'data_to_redact': [] }
Question.operation_logger = {"data_to_redact": []}
expected_result = OrderedDict({"some_password": ("some_value", "password")})
Question.operation_logger = MagicMock()
with patch.object(Question.operation_logger, "data_to_redact", create=True), \
patch.object(Moulinette, "prompt", return_value="some_value"), \
patch.object(os, "isatty", return_value=True):
with patch.object(
Question.operation_logger, "data_to_redact", create=True
), patch.object(Moulinette, "prompt", return_value="some_value"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -387,9 +398,11 @@ def test_question_password_input_no_ask():
expected_result = OrderedDict({"some_password": ("some_value", "password")})
Question.operation_logger = MagicMock()
with patch.object(Question.operation_logger, "data_to_redact", create=True), \
patch.object(Moulinette, "prompt", return_value="some_value"), \
patch.object(os, "isatty", return_value=True):
with patch.object(
Question.operation_logger, "data_to_redact", create=True
), patch.object(Moulinette, "prompt", return_value="some_value"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -405,8 +418,9 @@ def test_question_password_no_input_optional():
expected_result = OrderedDict({"some_password": ("", "password")})
Question.operation_logger = MagicMock()
with patch.object(Question.operation_logger, "data_to_redact", create=True), \
patch.object(os, "isatty", return_value=False):
with patch.object(
Question.operation_logger, "data_to_redact", create=True
), patch.object(os, "isatty", return_value=False):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
questions = [
@ -414,8 +428,9 @@ def test_question_password_no_input_optional():
]
Question.operation_logger = MagicMock()
with patch.object(Question.operation_logger, "data_to_redact", create=True), \
patch.object(os, "isatty", return_value=False):
with patch.object(
Question.operation_logger, "data_to_redact", create=True
), patch.object(os, "isatty", return_value=False):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -432,9 +447,11 @@ def test_question_password_optional_with_input():
expected_result = OrderedDict({"some_password": ("some_value", "password")})
Question.operation_logger = MagicMock()
with patch.object(Question.operation_logger, "data_to_redact", create=True), \
patch.object(Moulinette, "prompt", return_value="some_value"), \
patch.object(os, "isatty", return_value=True):
with patch.object(
Question.operation_logger, "data_to_redact", create=True
), patch.object(Moulinette, "prompt", return_value="some_value"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -451,9 +468,11 @@ def test_question_password_optional_with_empty_input():
expected_result = OrderedDict({"some_password": ("", "password")})
Question.operation_logger = MagicMock()
with patch.object(Question.operation_logger, "data_to_redact", create=True), \
patch.object(Moulinette, "prompt", return_value=""), \
patch.object(os, "isatty", return_value=True):
with patch.object(
Question.operation_logger, "data_to_redact", create=True
), patch.object(Moulinette, "prompt", return_value=""), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -469,9 +488,11 @@ def test_question_password_optional_with_input_without_ask():
expected_result = OrderedDict({"some_password": ("some_value", "password")})
Question.operation_logger = MagicMock()
with patch.object(Question.operation_logger, "data_to_redact", create=True), \
patch.object(Moulinette, "prompt", return_value="some_value"), \
patch.object(os, "isatty", return_value=True):
with patch.object(
Question.operation_logger, "data_to_redact", create=True
), patch.object(Moulinette, "prompt", return_value="some_value"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -487,8 +508,7 @@ def test_question_password_no_input_default():
answers = {}
# no default for password!
with pytest.raises(YunohostError), \
patch.object(os, "isatty", return_value=False):
with pytest.raises(YunohostError), patch.object(os, "isatty", return_value=False):
parse_args_in_yunohost_format(answers, questions)
@ -505,8 +525,7 @@ def test_question_password_no_input_example():
answers = {"some_password": "some_value"}
# no example for password!
with pytest.raises(YunohostError), \
patch.object(os, "isatty", return_value=False):
with pytest.raises(YunohostError), patch.object(os, "isatty", return_value=False):
parse_args_in_yunohost_format(answers, questions)
@ -522,14 +541,20 @@ def test_question_password_input_test_ask():
answers = {}
Question.operation_logger = MagicMock()
with patch.object(Question.operation_logger, "data_to_redact", create=True), \
patch.object(Moulinette, "prompt", return_value="some_value") as prompt, \
patch.object(os, "isatty", return_value=True):
with patch.object(
Question.operation_logger, "data_to_redact", create=True
), patch.object(
Moulinette, "prompt", return_value="some_value"
) as prompt, patch.object(
os, "isatty", return_value=True
):
parse_args_in_yunohost_format(answers, questions)
prompt.assert_called_with(
message=ask_text,
is_password=True, confirm=True,
prefill='', is_multiline=False
is_password=True,
confirm=True,
prefill="",
is_multiline=False,
)
@ -548,12 +573,16 @@ def test_question_password_input_test_ask_with_example():
answers = {}
Question.operation_logger = MagicMock()
with patch.object(Question.operation_logger, "data_to_redact", create=True), \
patch.object(Moulinette, "prompt", return_value="some_value") as prompt, \
patch.object(os, "isatty", return_value=True):
with patch.object(
Question.operation_logger, "data_to_redact", create=True
), patch.object(
Moulinette, "prompt", return_value="some_value"
) as prompt, patch.object(
os, "isatty", return_value=True
):
parse_args_in_yunohost_format(answers, questions)
assert ask_text in prompt.call_args[1]['message']
assert example_text in prompt.call_args[1]['message']
assert ask_text in prompt.call_args[1]["message"]
assert example_text in prompt.call_args[1]["message"]
@pytest.mark.skip # we should do something with this help
@ -571,12 +600,16 @@ def test_question_password_input_test_ask_with_help():
answers = {}
Question.operation_logger = MagicMock()
with patch.object(Question.operation_logger, "data_to_redact", create=True), \
patch.object(Moulinette, "prompt", return_value="some_value") as prompt, \
patch.object(os, "isatty", return_value=True):
with patch.object(
Question.operation_logger, "data_to_redact", create=True
), patch.object(
Moulinette, "prompt", return_value="some_value"
) as prompt, patch.object(
os, "isatty", return_value=True
):
parse_args_in_yunohost_format(answers, questions)
assert ask_text in prompt.call_args[1]['message']
assert help_text in prompt.call_args[1]['message']
assert ask_text in prompt.call_args[1]["message"]
assert help_text in prompt.call_args[1]["message"]
def test_question_password_bad_chars():
@ -590,8 +623,9 @@ def test_question_password_bad_chars():
]
for i in PasswordQuestion.forbidden_chars:
with pytest.raises(YunohostError), \
patch.object(os, "isatty", return_value=False):
with pytest.raises(YunohostError), patch.object(
os, "isatty", return_value=False
):
parse_args_in_yunohost_format({"some_password": i * 8}, questions)
@ -605,13 +639,11 @@ def test_question_password_strong_enough():
}
]
with pytest.raises(YunohostError), \
patch.object(os, "isatty", return_value=False):
with pytest.raises(YunohostError), patch.object(os, "isatty", return_value=False):
# too short
parse_args_in_yunohost_format({"some_password": "a"}, questions)
with pytest.raises(YunohostError), \
patch.object(os, "isatty", return_value=False):
with pytest.raises(YunohostError), patch.object(os, "isatty", return_value=False):
parse_args_in_yunohost_format({"some_password": "password"}, questions)
@ -625,13 +657,11 @@ def test_question_password_optional_strong_enough():
}
]
with pytest.raises(YunohostError), \
patch.object(os, "isatty", return_value=False):
with pytest.raises(YunohostError), patch.object(os, "isatty", return_value=False):
# too short
parse_args_in_yunohost_format({"some_password": "a"}, questions)
with pytest.raises(YunohostError), \
patch.object(os, "isatty", return_value=False):
with pytest.raises(YunohostError), patch.object(os, "isatty", return_value=False):
parse_args_in_yunohost_format({"some_password": "password"}, questions)
@ -656,8 +686,7 @@ def test_question_path_no_input():
]
answers = {}
with pytest.raises(YunohostError), \
patch.object(os, "isatty", return_value=False):
with pytest.raises(YunohostError), patch.object(os, "isatty", return_value=False):
parse_args_in_yunohost_format(answers, questions)
@ -672,8 +701,9 @@ def test_question_path_input():
answers = {}
expected_result = OrderedDict({"some_path": ("some_value", "path")})
with patch.object(Moulinette, "prompt", return_value="some_value"), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value="some_value"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -687,8 +717,9 @@ def test_question_path_input_no_ask():
answers = {}
expected_result = OrderedDict({"some_path": ("some_value", "path")})
with patch.object(Moulinette, "prompt", return_value="some_value"), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value="some_value"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -718,8 +749,9 @@ def test_question_path_optional_with_input():
answers = {}
expected_result = OrderedDict({"some_path": ("some_value", "path")})
with patch.object(Moulinette, "prompt", return_value="some_value"), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value="some_value"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -735,8 +767,9 @@ def test_question_path_optional_with_empty_input():
answers = {}
expected_result = OrderedDict({"some_path": ("", "path")})
with patch.object(Moulinette, "prompt", return_value=""), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value=""), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -751,8 +784,9 @@ def test_question_path_optional_with_input_without_ask():
answers = {}
expected_result = OrderedDict({"some_path": ("some_value", "path")})
with patch.object(Moulinette, "prompt", return_value="some_value"), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value="some_value"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -788,8 +822,10 @@ def test_question_path_input_test_ask():
parse_args_in_yunohost_format(answers, questions)
prompt.assert_called_with(
message=ask_text,
is_password=False, confirm=False,
prefill='', is_multiline=False
is_password=False,
confirm=False,
prefill="",
is_multiline=False,
)
@ -812,8 +848,10 @@ def test_question_path_input_test_ask_with_default():
parse_args_in_yunohost_format(answers, questions)
prompt.assert_called_with(
message=ask_text,
is_password=False, confirm=False,
prefill=default_text, is_multiline=False
is_password=False,
confirm=False,
prefill=default_text,
is_multiline=False,
)
@ -835,8 +873,8 @@ def test_question_path_input_test_ask_with_example():
Moulinette, "prompt", return_value="some_value"
) as prompt, patch.object(os, "isatty", return_value=True):
parse_args_in_yunohost_format(answers, questions)
assert ask_text in prompt.call_args[1]['message']
assert example_text in prompt.call_args[1]['message']
assert ask_text in prompt.call_args[1]["message"]
assert example_text in prompt.call_args[1]["message"]
@pytest.mark.skip # we should do something with this help
@ -857,8 +895,8 @@ def test_question_path_input_test_ask_with_help():
Moulinette, "prompt", return_value="some_value"
) as prompt, patch.object(os, "isatty", return_value=True):
parse_args_in_yunohost_format(answers, questions)
assert ask_text in prompt.call_args[1]['message']
assert help_text in prompt.call_args[1]['message']
assert ask_text in prompt.call_args[1]["message"]
assert help_text in prompt.call_args[1]["message"]
def test_question_boolean():
@ -906,8 +944,7 @@ def test_question_boolean_all_yes():
== expected_result
)
assert (
parse_args_in_yunohost_format({"some_boolean": 1}, questions)
== expected_result
parse_args_in_yunohost_format({"some_boolean": 1}, questions) == expected_result
)
assert (
parse_args_in_yunohost_format({"some_boolean": True}, questions)
@ -960,8 +997,7 @@ def test_question_boolean_all_no():
== expected_result
)
assert (
parse_args_in_yunohost_format({"some_boolean": 0}, questions)
== expected_result
parse_args_in_yunohost_format({"some_boolean": 0}, questions) == expected_result
)
assert (
parse_args_in_yunohost_format({"some_boolean": False}, questions)
@ -1005,8 +1041,7 @@ def test_question_boolean_bad_input():
]
answers = {"some_boolean": "stuff"}
with pytest.raises(YunohostError), \
patch.object(os, "isatty", return_value=False):
with pytest.raises(YunohostError), patch.object(os, "isatty", return_value=False):
parse_args_in_yunohost_format(answers, questions)
@ -1021,13 +1056,15 @@ def test_question_boolean_input():
answers = {}
expected_result = OrderedDict({"some_boolean": (1, "boolean")})
with patch.object(Moulinette, "prompt", return_value="y"), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value="y"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
expected_result = OrderedDict({"some_boolean": (0, "boolean")})
with patch.object(Moulinette, "prompt", return_value="n"), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value="n"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -1041,8 +1078,9 @@ def test_question_boolean_input_no_ask():
answers = {}
expected_result = OrderedDict({"some_boolean": (1, "boolean")})
with patch.object(Moulinette, "prompt", return_value="y"), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value="y"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -1072,8 +1110,9 @@ def test_question_boolean_optional_with_input():
answers = {}
expected_result = OrderedDict({"some_boolean": (1, "boolean")})
with patch.object(Moulinette, "prompt", return_value="y"), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value="y"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -1089,8 +1128,9 @@ def test_question_boolean_optional_with_empty_input():
answers = {}
expected_result = OrderedDict({"some_boolean": (0, "boolean")}) # default to false
with patch.object(Moulinette, "prompt", return_value=""), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value=""), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -1105,8 +1145,9 @@ def test_question_boolean_optional_with_input_without_ask():
answers = {}
expected_result = OrderedDict({"some_boolean": (0, "boolean")})
with patch.object(Moulinette, "prompt", return_value="n"), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value="n"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -1150,13 +1191,16 @@ def test_question_boolean_input_test_ask():
]
answers = {}
with patch.object(Moulinette, "prompt", return_value=0) as prompt, \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value=0) as prompt, patch.object(
os, "isatty", return_value=True
):
parse_args_in_yunohost_format(answers, questions)
prompt.assert_called_with(
message=ask_text + " [yes | no]",
is_password=False, confirm=False,
prefill='no', is_multiline=False
is_password=False,
confirm=False,
prefill="no",
is_multiline=False,
)
@ -1173,13 +1217,16 @@ def test_question_boolean_input_test_ask_with_default():
]
answers = {}
with patch.object(Moulinette, "prompt", return_value=1) as prompt, \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value=1) as prompt, patch.object(
os, "isatty", return_value=True
):
parse_args_in_yunohost_format(answers, questions)
prompt.assert_called_with(
message=ask_text + " [yes | no]",
is_password=False, confirm=False,
prefill='yes', is_multiline=False
is_password=False,
confirm=False,
prefill="yes",
is_multiline=False,
)
@ -1194,9 +1241,13 @@ def test_question_domain_empty():
expected_result = OrderedDict({"some_domain": (main_domain, "domain")})
answers = {}
with patch.object(domain, "_get_maindomain", return_value="my_main_domain.com"),\
patch.object(domain, "domain_list", return_value={"domains": [main_domain]}), \
patch.object(os, "isatty", return_value=False):
with patch.object(
domain, "_get_maindomain", return_value="my_main_domain.com"
), patch.object(
domain, "domain_list", return_value={"domains": [main_domain]}
), patch.object(
os, "isatty", return_value=False
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -1263,8 +1314,9 @@ def test_question_domain_two_domains_wrong_answer():
with patch.object(
domain, "_get_maindomain", return_value=main_domain
), patch.object(domain, "domain_list", return_value={"domains": domains}):
with pytest.raises(YunohostError), \
patch.object(os, "isatty", return_value=False):
with pytest.raises(YunohostError), patch.object(
os, "isatty", return_value=False
):
parse_args_in_yunohost_format(answers, questions)
@ -1284,8 +1336,11 @@ def test_question_domain_two_domains_default_no_ask():
with patch.object(
domain, "_get_maindomain", return_value=main_domain
), patch.object(domain, "domain_list", return_value={"domains": domains}), \
patch.object(os, "isatty", return_value=False):
), patch.object(
domain, "domain_list", return_value={"domains": domains}
), patch.object(
os, "isatty", return_value=False
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -1300,8 +1355,11 @@ def test_question_domain_two_domains_default():
with patch.object(
domain, "_get_maindomain", return_value=main_domain
), patch.object(domain, "domain_list", return_value={"domains": domains}), \
patch.object(os, "isatty", return_value=False):
), patch.object(
domain, "domain_list", return_value={"domains": domains}
), patch.object(
os, "isatty", return_value=False
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -1315,8 +1373,11 @@ def test_question_domain_two_domains_default_input():
with patch.object(
domain, "_get_maindomain", return_value=main_domain
), patch.object(domain, "domain_list", return_value={"domains": domains}), \
patch.object(os, "isatty", return_value=True):
), patch.object(
domain, "domain_list", return_value={"domains": domains}
), patch.object(
os, "isatty", return_value=True
):
expected_result = OrderedDict({"some_domain": (main_domain, "domain")})
with patch.object(Moulinette, "prompt", return_value=main_domain):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -1346,8 +1407,9 @@ def test_question_user_empty():
answers = {}
with patch.object(user, "user_list", return_value={"users": users}):
with pytest.raises(YunohostError), \
patch.object(os, "isatty", return_value=False):
with pytest.raises(YunohostError), patch.object(
os, "isatty", return_value=False
):
parse_args_in_yunohost_format(answers, questions)
@ -1373,8 +1435,9 @@ def test_question_user():
expected_result = OrderedDict({"some_user": (username, "user")})
with patch.object(user, "user_list", return_value={"users": users}), \
patch.object(user, "user_info", return_value={}):
with patch.object(user, "user_list", return_value={"users": users}), patch.object(
user, "user_info", return_value={}
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -1407,15 +1470,17 @@ def test_question_user_two_users():
answers = {"some_user": other_user}
expected_result = OrderedDict({"some_user": (other_user, "user")})
with patch.object(user, "user_list", return_value={"users": users}), \
patch.object(user, "user_info", return_value={}):
with patch.object(user, "user_list", return_value={"users": users}), patch.object(
user, "user_info", return_value={}
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
answers = {"some_user": username}
expected_result = OrderedDict({"some_user": (username, "user")})
with patch.object(user, "user_list", return_value={"users": users}), \
patch.object(user, "user_info", return_value={}):
with patch.object(user, "user_list", return_value={"users": users}), patch.object(
user, "user_info", return_value={}
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -1448,8 +1513,9 @@ def test_question_user_two_users_wrong_answer():
answers = {"some_user": "doesnt_exist.pouet"}
with patch.object(user, "user_list", return_value={"users": users}):
with pytest.raises(YunohostError), \
patch.object(os, "isatty", return_value=False):
with pytest.raises(YunohostError), patch.object(
os, "isatty", return_value=False
):
parse_args_in_yunohost_format(answers, questions)
@ -1477,8 +1543,9 @@ def test_question_user_two_users_no_default():
answers = {}
with patch.object(user, "user_list", return_value={"users": users}):
with pytest.raises(YunohostError), \
patch.object(os, "isatty", return_value=False):
with pytest.raises(YunohostError), patch.object(
os, "isatty", return_value=False
):
parse_args_in_yunohost_format(answers, questions)
@ -1505,21 +1572,20 @@ def test_question_user_two_users_default_input():
questions = [{"name": "some_user", "type": "user", "ask": "choose a user"}]
answers = {}
with patch.object(user, "user_list", return_value={"users": users}), \
patch.object(os, "isatty", return_value=True):
with patch.object(user, "user_list", return_value={"users": users}), patch.object(
os, "isatty", return_value=True
):
with patch.object(user, "user_info", return_value={}):
expected_result = OrderedDict({"some_user": (username, "user")})
with patch.object(Moulinette, "prompt", return_value=username):
assert (
parse_args_in_yunohost_format(answers, questions)
== expected_result
parse_args_in_yunohost_format(answers, questions) == expected_result
)
expected_result = OrderedDict({"some_user": (other_user, "user")})
with patch.object(Moulinette, "prompt", return_value=other_user):
assert (
parse_args_in_yunohost_format(answers, questions)
== expected_result
parse_args_in_yunohost_format(answers, questions) == expected_result
)
@ -1544,8 +1610,7 @@ def test_question_number_no_input():
]
answers = {}
with pytest.raises(YunohostError), \
patch.object(os, "isatty", return_value=False):
with pytest.raises(YunohostError), patch.object(os, "isatty", return_value=False):
parse_args_in_yunohost_format(answers, questions)
@ -1558,13 +1623,11 @@ def test_question_number_bad_input():
]
answers = {"some_number": "stuff"}
with pytest.raises(YunohostError), \
patch.object(os, "isatty", return_value=False):
with pytest.raises(YunohostError), patch.object(os, "isatty", return_value=False):
parse_args_in_yunohost_format(answers, questions)
answers = {"some_number": 1.5}
with pytest.raises(YunohostError), \
patch.object(os, "isatty", return_value=False):
with pytest.raises(YunohostError), patch.object(os, "isatty", return_value=False):
parse_args_in_yunohost_format(answers, questions)
@ -1579,17 +1642,20 @@ def test_question_number_input():
answers = {}
expected_result = OrderedDict({"some_number": (1337, "number")})
with patch.object(Moulinette, "prompt", return_value="1337"), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value="1337"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
with patch.object(Moulinette, "prompt", return_value=1337), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value=1337), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
expected_result = OrderedDict({"some_number": (0, "number")})
with patch.object(Moulinette, "prompt", return_value="0"), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value="0"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -1603,8 +1669,9 @@ def test_question_number_input_no_ask():
answers = {}
expected_result = OrderedDict({"some_number": (1337, "number")})
with patch.object(Moulinette, "prompt", return_value="1337"), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value="1337"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -1634,8 +1701,9 @@ def test_question_number_optional_with_input():
answers = {}
expected_result = OrderedDict({"some_number": (1337, "number")})
with patch.object(Moulinette, "prompt", return_value="1337"), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value="1337"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -1650,8 +1718,9 @@ def test_question_number_optional_with_input_without_ask():
answers = {}
expected_result = OrderedDict({"some_number": (0, "number")})
with patch.object(Moulinette, "prompt", return_value="0"), \
patch.object(os, "isatty", return_value=True):
with patch.object(Moulinette, "prompt", return_value="0"), patch.object(
os, "isatty", return_value=True
):
assert parse_args_in_yunohost_format(answers, questions) == expected_result
@ -1680,8 +1749,7 @@ def test_question_number_bad_default():
}
]
answers = {}
with pytest.raises(YunohostError), \
patch.object(os, "isatty", return_value=False):
with pytest.raises(YunohostError), patch.object(os, "isatty", return_value=False):
parse_args_in_yunohost_format(answers, questions)
@ -1696,13 +1764,16 @@ def test_question_number_input_test_ask():
]
answers = {}
with patch.object(Moulinette, "prompt", return_value="1111") as prompt, \
patch.object(os, "isatty", return_value=True):
with patch.object(
Moulinette, "prompt", return_value="1111"
) as prompt, patch.object(os, "isatty", return_value=True):
parse_args_in_yunohost_format(answers, questions)
prompt.assert_called_with(
message=ask_text,
is_password=False, confirm=False,
prefill='', is_multiline=False
is_password=False,
confirm=False,
prefill="",
is_multiline=False,
)
@ -1719,13 +1790,16 @@ def test_question_number_input_test_ask_with_default():
]
answers = {}
with patch.object(Moulinette, "prompt", return_value="1111") as prompt, \
patch.object(os, "isatty", return_value=True):
with patch.object(
Moulinette, "prompt", return_value="1111"
) as prompt, patch.object(os, "isatty", return_value=True):
parse_args_in_yunohost_format(answers, questions)
prompt.assert_called_with(
message=ask_text,
is_password=False, confirm=False,
prefill=str(default_value), is_multiline=False
is_password=False,
confirm=False,
prefill=str(default_value),
is_multiline=False,
)
@ -1743,11 +1817,12 @@ def test_question_number_input_test_ask_with_example():
]
answers = {}
with patch.object(Moulinette, "prompt", return_value="1111") as prompt, \
patch.object(os, "isatty", return_value=True):
with patch.object(
Moulinette, "prompt", return_value="1111"
) as prompt, patch.object(os, "isatty", return_value=True):
parse_args_in_yunohost_format(answers, questions)
assert ask_text in prompt.call_args[1]['message']
assert example_value in prompt.call_args[1]['message']
assert ask_text in prompt.call_args[1]["message"]
assert example_value in prompt.call_args[1]["message"]
@pytest.mark.skip # we should do something with this help
@ -1764,18 +1839,20 @@ def test_question_number_input_test_ask_with_help():
]
answers = {}
with patch.object(Moulinette, "prompt", return_value="1111") as prompt, \
patch.object(os, "isatty", return_value=True):
with patch.object(
Moulinette, "prompt", return_value="1111"
) as prompt, patch.object(os, "isatty", return_value=True):
parse_args_in_yunohost_format(answers, questions)
assert ask_text in prompt.call_args[1]['message']
assert help_value in prompt.call_args[1]['message']
assert ask_text in prompt.call_args[1]["message"]
assert help_value in prompt.call_args[1]["message"]
def test_question_display_text():
questions = [{"name": "some_app", "type": "display_text", "ask": "foobar"}]
answers = {}
with patch.object(sys, "stdout", new_callable=StringIO) as stdout, \
patch.object(os, "isatty", return_value=True):
with patch.object(sys, "stdout", new_callable=StringIO) as stdout, patch.object(
os, "isatty", return_value=True
):
parse_args_in_yunohost_format(answers, questions)
assert "foobar" in stdout.getvalue()

View file

@ -98,7 +98,9 @@ class ConfigPanel:
return result
def set(self, key=None, value=None, args=None, args_file=None, operation_logger=None):
def set(
self, key=None, value=None, args=None, args_file=None, operation_logger=None
):
self.filter_key = key or ""
# Read config panel toml
@ -108,7 +110,10 @@ class ConfigPanel:
raise YunohostValidationError("config_no_panel")
if (args is not None or args_file is not None) and value is not None:
raise YunohostValidationError("You should either provide a value, or a serie of args/args_file, but not both at the same time", raw_msg=True)
raise YunohostValidationError(
"You should either provide a value, or a serie of args/args_file, but not both at the same time",
raw_msg=True,
)
if self.filter_key.count(".") != 2 and value is not None:
raise YunohostValidationError("config_cant_set_value_on_section")
@ -167,7 +172,10 @@ class ConfigPanel:
# Split filter_key
filter_key = self.filter_key.split(".") if self.filter_key != "" else []
if len(filter_key) > 3:
raise YunohostError(f"The filter key {filter_key} has too many sub-levels, the max is 3.", raw_msg=True)
raise YunohostError(
f"The filter key {filter_key} has too many sub-levels, the max is 3.",
raw_msg=True,
)
if not os.path.exists(self.config_path):
return None
@ -190,7 +198,7 @@ class ConfigPanel:
"default": {
"name": "",
"services": [],
"actions": {"apply": {"en": "Apply"}}
"actions": {"apply": {"en": "Apply"}},
},
},
"sections": {
@ -199,15 +207,34 @@ class ConfigPanel:
"name": "",
"services": [],
"optional": True,
}
},
},
"options": {
"properties": ["ask", "type", "bind", "help", "example", "default",
"style", "icon", "placeholder", "visible",
"optional", "choices", "yes", "no", "pattern",
"limit", "min", "max", "step", "accept", "redact"],
"default": {}
}
"properties": [
"ask",
"type",
"bind",
"help",
"example",
"default",
"style",
"icon",
"placeholder",
"visible",
"optional",
"choices",
"yes",
"no",
"pattern",
"limit",
"min",
"max",
"step",
"accept",
"redact",
],
"default": {},
},
}
def convert(toml_node, node_type):
@ -219,14 +246,16 @@ class ConfigPanel:
This function detects all children nodes and put them in a list
"""
# Prefill the node default keys if needed
default = format_description[node_type]['default']
default = format_description[node_type]["default"]
node = {key: toml_node.get(key, value) for key, value in default.items()}
properties = format_description[node_type]['properties']
properties = format_description[node_type]["properties"]
# Define the filter_key part to use and the children type
i = list(format_description).index(node_type)
subnode_type = list(format_description)[i + 1] if node_type != "options" else None
subnode_type = (
list(format_description)[i + 1] if node_type != "options" else None
)
search_key = filter_key[i] if len(filter_key) > i else False
for key, value in toml_node.items():
@ -265,10 +294,24 @@ class ConfigPanel:
)
# List forbidden keywords from helpers and sections toml (to avoid conflict)
forbidden_keywords = ["old", "app", "changed", "file_hash", "binds", "types",
"formats", "getter", "setter", "short_setting", "type",
"bind", "nothing_changed", "changes_validated", "result",
"max_progression"]
forbidden_keywords = [
"old",
"app",
"changed",
"file_hash",
"binds",
"types",
"formats",
"getter",
"setter",
"short_setting",
"type",
"bind",
"nothing_changed",
"changes_validated",
"result",
"max_progression",
]
forbidden_keywords += format_description["sections"]
for _, _, option in self._iterate():
@ -282,10 +325,15 @@ class ConfigPanel:
for _, _, option in self._iterate():
if option["id"] not in self.values:
allowed_empty_types = ["alert", "display_text", "markdown", "file"]
if option["type"] in allowed_empty_types or option.get("bind") == "null":
if (
option["type"] in allowed_empty_types
or option.get("bind") == "null"
):
continue
else:
raise YunohostError(f"Config panel question '{option['id']}' should be initialized with a value during install or upgrade.")
raise YunohostError(
f"Config panel question '{option['id']}' should be initialized with a value during install or upgrade."
)
value = self.values[option["name"]]
# In general, the value is just a simple value.
# Sometimes it could be a dict used to overwrite the option itself
@ -440,14 +488,11 @@ class Question(object):
)
# Apply default value
class_default= getattr(self, "default_value", None)
if self.value in [None, ""] and \
(self.default is not None or class_default is not None):
self.value = (
class_default
if self.default is None
else self.default
)
class_default = getattr(self, "default_value", None)
if self.value in [None, ""] and (
self.default is not None or class_default is not None
):
self.value = class_default if self.default is None else self.default
# Normalization
# This is done to enforce a certain formating like for boolean
@ -543,30 +588,31 @@ class StringQuestion(Question):
class EmailQuestion(StringQuestion):
pattern = {
"regexp": r"^.+@.+",
"error": "config_validate_email" # i18n: config_validate_email
"error": "config_validate_email", # i18n: config_validate_email
}
class URLQuestion(StringQuestion):
pattern = {
"regexp": r"^https?://.*$",
"error": "config_validate_url" # i18n: config_validate_url
"error": "config_validate_url", # i18n: config_validate_url
}
class DateQuestion(StringQuestion):
pattern = {
"regexp": r"^\d{4}-\d\d-\d\d$",
"error": "config_validate_date" # i18n: config_validate_date
"error": "config_validate_date", # i18n: config_validate_date
}
def _prevalidate(self):
from datetime import datetime
super()._prevalidate()
if self.value not in [None, ""]:
try:
datetime.strptime(self.value, '%Y-%m-%d')
datetime.strptime(self.value, "%Y-%m-%d")
except ValueError:
raise YunohostValidationError("config_validate_date")
@ -574,14 +620,14 @@ class DateQuestion(StringQuestion):
class TimeQuestion(StringQuestion):
pattern = {
"regexp": r"^(1[12]|0?\d):[0-5]\d$",
"error": "config_validate_time" # i18n: config_validate_time
"error": "config_validate_time", # i18n: config_validate_time
}
class ColorQuestion(StringQuestion):
pattern = {
"regexp": r"^#[ABCDEFabcdef\d]{3,6}$",
"error": "config_validate_color" # i18n: config_validate_color
"error": "config_validate_color", # i18n: config_validate_color
}
@ -732,7 +778,9 @@ class DomainQuestion(Question):
def _raise_invalid_answer(self):
raise YunohostValidationError(
"app_argument_invalid", name=self.name, error=m18n.n("domain_name_unknown", domain=self.value)
"app_argument_invalid",
name=self.name,
error=m18n.n("domain_name_unknown", domain=self.value),
)
@ -813,7 +861,9 @@ class DisplayTextQuestion(Question):
super().__init__(question, user_answers)
self.optional = True
self.style = question.get("style", "info" if question['type'] == 'alert' else '')
self.style = question.get(
"style", "info" if question["type"] == "alert" else ""
)
def _format_text_for_user_input_in_cli(self):
text = _value_for_locale(self.ask)
@ -875,7 +925,9 @@ class FileQuestion(Question):
return
filename = self.value if isinstance(self.value, str) else self.value["filename"]
if "." not in filename or "." + filename.split(".")[-1] not in self.accept.replace(" ", "").split(","):
if "." not in filename or "." + filename.split(".")[
-1
] not in self.accept.replace(" ", "").split(","):
raise YunohostValidationError(
"app_argument_invalid",
name=self.name,