mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
Merge pull request #1013 from YunoHost/refactoring-yunohost-format-arguments-parsing
WIP: Refactoring yunohost format arguments parsing
This commit is contained in:
commit
d1d24cb6eb
3 changed files with 282 additions and 148 deletions
|
@ -13,6 +13,7 @@
|
|||
"app_already_up_to_date": "{app:s} is already up-to-date",
|
||||
"app_argument_choice_invalid": "Use one of these choices '{choices:s}' for the argument '{name:s}'",
|
||||
"app_argument_invalid": "Pick a valid value for the argument '{name:s}': {error:s}",
|
||||
"app_argument_password_no_default": "Error while parsing password argument '{name}': password argument can't have a default value for security reason",
|
||||
"app_argument_required": "Argument '{name:s}' is required",
|
||||
"app_change_url_failed_nginx_reload": "Could not reload NGINX. Here is the output of 'nginx -t':\n{nginx_errors:s}",
|
||||
"app_change_url_identical_domains": "The old and new domain/url_path are identical ('{domain:s}{path:s}'), nothing to do.",
|
||||
|
@ -599,7 +600,6 @@
|
|||
"user_unknown": "Unknown user: {user:s}",
|
||||
"user_update_failed": "Could not update user {user}: {error}",
|
||||
"user_updated": "User info changed",
|
||||
"users_available": "Available users:",
|
||||
"yunohost_already_installed": "YunoHost is already installed",
|
||||
"yunohost_ca_creation_failed": "Could not create certificate authority",
|
||||
"yunohost_ca_creation_success": "Local certification authority created.",
|
||||
|
|
|
@ -2508,6 +2508,225 @@ def _parse_args_for_action(action, args={}):
|
|||
return _parse_args_in_yunohost_format(args, action_args)
|
||||
|
||||
|
||||
class Question:
|
||||
"empty class to store questions information"
|
||||
|
||||
|
||||
class YunoHostArgumentFormatParser(object):
|
||||
hide_user_input_in_prompt = False
|
||||
|
||||
def parse_question(self, question, user_answers):
|
||||
parsed_question = Question()
|
||||
|
||||
parsed_question.name = question['name']
|
||||
parsed_question.default = question.get('default', None)
|
||||
parsed_question.choices = question.get('choices', [])
|
||||
parsed_question.optional = question.get('optional', False)
|
||||
parsed_question.ask = question.get('ask')
|
||||
parsed_question.value = user_answers.get(parsed_question.name)
|
||||
|
||||
if parsed_question.ask is None:
|
||||
parsed_question.ask = "Enter value for '%s':" % parsed_question.name
|
||||
|
||||
return parsed_question
|
||||
|
||||
def parse(self, question, user_answers):
|
||||
question = self.parse_question(question, user_answers)
|
||||
|
||||
if question.value is None:
|
||||
text_for_user_input_in_cli = self._format_text_for_user_input_in_cli(question)
|
||||
|
||||
try:
|
||||
question.value = msignals.prompt(text_for_user_input_in_cli, self.hide_user_input_in_prompt)
|
||||
except NotImplementedError:
|
||||
question.value = None
|
||||
|
||||
# we don't have an answer, check optional and default_value
|
||||
if question.value is None:
|
||||
if not question.optional and question.default is None:
|
||||
raise YunohostError('app_argument_required', name=question.name)
|
||||
else:
|
||||
question.value = getattr(self, "default_value", None) if question.default is None else question.default
|
||||
|
||||
# we have an answer, do some post checks
|
||||
if question.value is not None:
|
||||
if question.choices and question.value not in question.choices:
|
||||
self._raise_invalide_answer(question)
|
||||
|
||||
# this is done to enforce a certain formating like for boolean
|
||||
# by default it doesn't do anything
|
||||
question.value = self._post_parse_value(question)
|
||||
|
||||
return (question.value, self.argument_type)
|
||||
|
||||
def _raise_invalide_answer(self, question):
|
||||
raise YunohostError('app_argument_choice_invalid', name=question.name,
|
||||
choices=', '.join(question.choices))
|
||||
|
||||
def _format_text_for_user_input_in_cli(self, question):
|
||||
text_for_user_input_in_cli = _value_for_locale(question.ask)
|
||||
|
||||
if question.default is not None:
|
||||
text_for_user_input_in_cli += ' (default: {0})'.format(question.default)
|
||||
|
||||
if question.choices:
|
||||
text_for_user_input_in_cli += ' [{0}]'.format(' | '.join(question.choices))
|
||||
|
||||
return text_for_user_input_in_cli
|
||||
|
||||
def _post_parse_value(self, question):
|
||||
return question.value
|
||||
|
||||
|
||||
class StringArgumentParser(YunoHostArgumentFormatParser):
|
||||
argument_type = "string"
|
||||
default_value = ""
|
||||
|
||||
|
||||
class PasswordArgumentParser(YunoHostArgumentFormatParser):
|
||||
hide_user_input_in_prompt = True
|
||||
argument_type = "password"
|
||||
default_value = ""
|
||||
forbidden_chars = "{}"
|
||||
|
||||
def parse_question(self, question, user_answers):
|
||||
question = super(PasswordArgumentParser, self).parse_question(question, user_answers)
|
||||
|
||||
if question.default is not None:
|
||||
raise YunohostError('app_argument_password_no_default', name=question.name)
|
||||
|
||||
return question
|
||||
|
||||
def _post_parse_value(self, question):
|
||||
if any(char in question.value for char in self.forbidden_chars):
|
||||
raise YunohostError('pattern_password_app', forbidden_chars=self.forbidden_chars)
|
||||
|
||||
from yunohost.utils.password import assert_password_is_strong_enough
|
||||
assert_password_is_strong_enough('user', question.value)
|
||||
|
||||
return super(PasswordArgumentParser, self)._post_parse_value(question)
|
||||
|
||||
|
||||
class PathArgumentParser(YunoHostArgumentFormatParser):
|
||||
argument_type = "path"
|
||||
default_value = ""
|
||||
|
||||
|
||||
class BooleanArgumentParser(YunoHostArgumentFormatParser):
|
||||
argument_type = "boolean"
|
||||
default_value = False
|
||||
|
||||
def parse_question(self, question, user_answers):
|
||||
question = super(BooleanArgumentParser, self).parse_question(question, user_answers)
|
||||
|
||||
if question.default is None:
|
||||
question.default = False
|
||||
|
||||
return question
|
||||
|
||||
def _format_text_for_user_input_in_cli(self, question):
|
||||
text_for_user_input_in_cli = _value_for_locale(question.ask)
|
||||
|
||||
text_for_user_input_in_cli += " [yes | no]"
|
||||
|
||||
if question.default is not None:
|
||||
formatted_default = "yes" if question.default else "no"
|
||||
text_for_user_input_in_cli += ' (default: {0})'.format(formatted_default)
|
||||
|
||||
return text_for_user_input_in_cli
|
||||
|
||||
def _post_parse_value(self, question):
|
||||
if isinstance(question.value, bool):
|
||||
return 1 if question.value else 0
|
||||
|
||||
if str(question.value).lower() in ["1", "yes", "y"]:
|
||||
return 1
|
||||
|
||||
if str(question.value).lower() in ["0", "no", "n"]:
|
||||
return 0
|
||||
|
||||
raise YunohostError('app_argument_choice_invalid', name=question.name,
|
||||
choices='yes, no, y, n, 1, 0')
|
||||
|
||||
|
||||
class DomainArgumentParser(YunoHostArgumentFormatParser):
|
||||
argument_type = "domain"
|
||||
|
||||
def parse_question(self, question, user_answers):
|
||||
from yunohost.domain import domain_list, _get_maindomain
|
||||
|
||||
question = super(DomainArgumentParser, self).parse_question(question, user_answers)
|
||||
|
||||
if question.default is None:
|
||||
question.default = _get_maindomain()
|
||||
|
||||
question.choices = domain_list()["domains"]
|
||||
|
||||
return question
|
||||
|
||||
def _raise_invalide_answer(self, question):
|
||||
raise YunohostError('app_argument_invalid', name=question.name,
|
||||
error=m18n.n('domain_unknown'))
|
||||
|
||||
|
||||
class UserArgumentParser(YunoHostArgumentFormatParser):
|
||||
argument_type = "user"
|
||||
|
||||
def parse_question(self, question, user_answers):
|
||||
from yunohost.user import user_list, user_info
|
||||
from yunohost.domain import _get_maindomain
|
||||
|
||||
question = super(UserArgumentParser, self).parse_question(question, user_answers)
|
||||
question.choices = user_list()["users"]
|
||||
if question.default is None:
|
||||
root_mail = "root@%s" % _get_maindomain()
|
||||
for user in question.choices.keys():
|
||||
if root_mail in user_info(user).get("mail-aliases", []):
|
||||
question.default = user
|
||||
break
|
||||
|
||||
return question
|
||||
|
||||
def _raise_invalide_answer(self, question):
|
||||
raise YunohostError('app_argument_invalid', name=question.name,
|
||||
error=m18n.n('user_unknown', user=question.value))
|
||||
|
||||
|
||||
class AppArgumentParser(YunoHostArgumentFormatParser):
|
||||
argument_type = "app"
|
||||
|
||||
def parse_question(self, question, user_answers):
|
||||
from yunohost.app import app_list
|
||||
|
||||
question = super(AppArgumentParser, self).parse_question(question, user_answers)
|
||||
question.choices = [x["id"] for x in app_list()["apps"]]
|
||||
|
||||
return question
|
||||
|
||||
def _raise_invalide_answer(self, question):
|
||||
raise YunohostError('app_argument_invalid', name=question.name,
|
||||
error=m18n.n('app_unknown'))
|
||||
|
||||
|
||||
class DisplayTextArgumentParser(YunoHostArgumentFormatParser):
|
||||
argument_type = "display_text"
|
||||
|
||||
def parse(self, question, user_answers):
|
||||
print(question["ask"])
|
||||
|
||||
|
||||
ARGUMENTS_TYPE_PARSERS = {
|
||||
"string": StringArgumentParser,
|
||||
"password": PasswordArgumentParser,
|
||||
"path": PathArgumentParser,
|
||||
"boolean": BooleanArgumentParser,
|
||||
"domain": DomainArgumentParser,
|
||||
"user": UserArgumentParser,
|
||||
"app": AppArgumentParser,
|
||||
"display_text": DisplayTextArgumentParser,
|
||||
}
|
||||
|
||||
|
||||
def _parse_args_in_yunohost_format(user_answers, argument_questions):
|
||||
"""Parse arguments store in either manifest.json or actions.json or from a
|
||||
config panel against the user answers when they are present.
|
||||
|
@ -2519,128 +2738,14 @@ def _parse_args_in_yunohost_format(user_answers, argument_questions):
|
|||
format from actions.json/toml, manifest.json/toml
|
||||
or config_panel.json/toml
|
||||
"""
|
||||
from yunohost.domain import domain_list, _get_maindomain
|
||||
from yunohost.user import user_list, user_info
|
||||
|
||||
parsed_answers_dict = OrderedDict()
|
||||
|
||||
for question in argument_questions:
|
||||
question_name = question['name']
|
||||
question_type = question.get('type', 'string')
|
||||
question_default = question.get('default', None)
|
||||
question_choices = question.get('choices', [])
|
||||
question_value = None
|
||||
parser = ARGUMENTS_TYPE_PARSERS[question.get("type", "string")]()
|
||||
|
||||
# Transpose default value for boolean type and set it to
|
||||
# false if not defined.
|
||||
if question_type == 'boolean':
|
||||
question_default = 1 if question_default else 0
|
||||
|
||||
# do not print for webadmin
|
||||
if question_type == 'display_text' and msettings.get('interface') != 'api':
|
||||
print(_value_for_locale(question['ask']))
|
||||
continue
|
||||
|
||||
# Attempt to retrieve argument value
|
||||
if question_name in user_answers:
|
||||
question_value = user_answers[question_name]
|
||||
else:
|
||||
if 'ask' in question:
|
||||
|
||||
if question_type == 'domain':
|
||||
question_default = _get_maindomain()
|
||||
msignals.display(m18n.n('domains_available'))
|
||||
for domain in domain_list()['domains']:
|
||||
msignals.display("- {}".format(domain))
|
||||
|
||||
elif question_type == 'user':
|
||||
msignals.display(m18n.n('users_available'))
|
||||
users = user_list()['users']
|
||||
for user in users.keys():
|
||||
msignals.display("- {}".format(user))
|
||||
|
||||
root_mail = "root@%s" % _get_maindomain()
|
||||
for user in users.keys():
|
||||
if root_mail in user_info(user).get("mail-aliases", []):
|
||||
question_default = user
|
||||
break
|
||||
|
||||
elif question_type == 'password':
|
||||
msignals.display(m18n.n('good_practices_about_user_password'))
|
||||
|
||||
# Retrieve proper ask string
|
||||
text_for_user_input_in_cli = _value_for_locale(question['ask'])
|
||||
|
||||
# Append extra strings
|
||||
if question_type == 'boolean':
|
||||
text_for_user_input_in_cli += ' [yes | no]'
|
||||
elif question_choices:
|
||||
text_for_user_input_in_cli += ' [{0}]'.format(' | '.join(question_choices))
|
||||
|
||||
|
||||
if question_default is not None:
|
||||
if question_type == 'boolean':
|
||||
text_for_user_input_in_cli += ' (default: {0})'.format("yes" if question_default == 1 else "no")
|
||||
else:
|
||||
text_for_user_input_in_cli += ' (default: {0})'.format(question_default)
|
||||
|
||||
is_password = True if question_type == 'password' else False
|
||||
|
||||
try:
|
||||
input_string = msignals.prompt(text_for_user_input_in_cli, is_password)
|
||||
except NotImplementedError:
|
||||
input_string = None
|
||||
if (input_string == '' or input_string is None) \
|
||||
and question_default is not None:
|
||||
question_value = question_default
|
||||
else:
|
||||
question_value = input_string
|
||||
elif question_default is not None:
|
||||
question_value = question_default
|
||||
|
||||
# If the value is empty (none or '')
|
||||
# then check if question is optional or not
|
||||
if question_value is None or question_value == '':
|
||||
if question.get("optional", False):
|
||||
# Argument is optional, keep an empty value
|
||||
# and that's all for this question!
|
||||
parsed_answers_dict[question_name] = ('', question_type)
|
||||
continue
|
||||
else:
|
||||
# The argument is required !
|
||||
raise YunohostError('app_argument_required', name=question_name)
|
||||
|
||||
# Validate argument choice
|
||||
if question_choices and question_value not in question_choices:
|
||||
raise YunohostError('app_argument_choice_invalid', name=question_name, choices=', '.join(question_choices))
|
||||
|
||||
# Validate argument type
|
||||
if question_type == 'domain':
|
||||
if question_value not in domain_list()['domains']:
|
||||
raise YunohostError('app_argument_invalid', name=question_name, error=m18n.n('domain_unknown'))
|
||||
elif question_type == 'user':
|
||||
if question_value not in user_list()["users"].keys():
|
||||
raise YunohostError('app_argument_invalid', name=question_name, error=m18n.n('user_unknown', user=question_value))
|
||||
elif question_type == 'app':
|
||||
if not _is_installed(question_value):
|
||||
raise YunohostError('app_argument_invalid', name=question_name, error=m18n.n('app_unknown'))
|
||||
elif question_type == 'boolean':
|
||||
if isinstance(question_value, bool):
|
||||
question_value = 1 if question_value else 0
|
||||
else:
|
||||
if str(question_value).lower() in ["1", "yes", "y"]:
|
||||
question_value = 1
|
||||
elif str(question_value).lower() in ["0", "no", "n"]:
|
||||
question_value = 0
|
||||
else:
|
||||
raise YunohostError('app_argument_choice_invalid', name=question_name, choices='yes, no, y, n, 1, 0')
|
||||
elif question_type == 'password':
|
||||
forbidden_chars = "{}"
|
||||
if any(char in question_value for char in forbidden_chars):
|
||||
raise YunohostError('pattern_password_app', forbidden_chars=forbidden_chars)
|
||||
from yunohost.utils.password import assert_password_is_strong_enough
|
||||
assert_password_is_strong_enough('user', question_value)
|
||||
parsed_answers_dict[question_name] = (question_value, question_type)
|
||||
answer = parser.parse(question=question, user_answers=user_answers)
|
||||
if answer is not None:
|
||||
parsed_answers_dict[question["name"]] = answer
|
||||
|
||||
return parsed_answers_dict
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ from collections import OrderedDict
|
|||
from moulinette import msignals
|
||||
|
||||
from yunohost import domain, user, app
|
||||
from yunohost.app import _parse_args_in_yunohost_format
|
||||
from yunohost.app import _parse_args_in_yunohost_format, PasswordArgumentParser
|
||||
from yunohost.utils.error import YunohostError
|
||||
|
||||
|
||||
|
@ -70,7 +70,6 @@ def test_parse_args_in_yunohost_format_string_input():
|
|||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
@pytest.mark.skip # that shit should work x(
|
||||
def test_parse_args_in_yunohost_format_string_input_no_ask():
|
||||
questions = [{"name": "some_string", }]
|
||||
answers = {}
|
||||
|
@ -96,7 +95,6 @@ def test_parse_args_in_yunohost_format_string_optional_with_input():
|
|||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
@pytest.mark.skip # this should work without ask
|
||||
def test_parse_args_in_yunohost_format_string_optional_with_input_without_ask():
|
||||
questions = [{"name": "some_string", "optional": True, }]
|
||||
answers = {}
|
||||
|
@ -237,7 +235,6 @@ def test_parse_args_in_yunohost_format_password_input():
|
|||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
@pytest.mark.skip # that shit should work x(
|
||||
def test_parse_args_in_yunohost_format_password_input_no_ask():
|
||||
questions = [{"name": "some_password", "type": "password", }]
|
||||
answers = {}
|
||||
|
@ -250,8 +247,9 @@ def test_parse_args_in_yunohost_format_password_input_no_ask():
|
|||
def test_parse_args_in_yunohost_format_password_no_input_optional():
|
||||
questions = [{"name": "some_password", "type": "password", "optional": True, }]
|
||||
answers = {}
|
||||
expected_result = OrderedDict({"some_password": ("", "password")})
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
with pytest.raises(YunohostError):
|
||||
_parse_args_in_yunohost_format(answers, questions)
|
||||
|
||||
|
||||
def test_parse_args_in_yunohost_format_password_optional_with_input():
|
||||
|
@ -270,7 +268,6 @@ def test_parse_args_in_yunohost_format_password_optional_with_input():
|
|||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
@pytest.mark.skip # this should work without ask
|
||||
def test_parse_args_in_yunohost_format_password_optional_with_input_without_ask():
|
||||
questions = [{"name": "some_password", "type": "password", "optional": True, }]
|
||||
answers = {}
|
||||
|
@ -280,7 +277,6 @@ def test_parse_args_in_yunohost_format_password_optional_with_input_without_ask(
|
|||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
@pytest.mark.skip # this should raises
|
||||
def test_parse_args_in_yunohost_format_password_no_input_default():
|
||||
questions = [
|
||||
{
|
||||
|
@ -364,6 +360,39 @@ def test_parse_args_in_yunohost_format_password_input_test_ask_with_help():
|
|||
assert help_text in prompt.call_args[0][0]
|
||||
|
||||
|
||||
def test_parse_args_in_yunohost_format_password_bad_chars():
|
||||
questions = [
|
||||
{
|
||||
"name": "some_password",
|
||||
"type": "password",
|
||||
"ask": "some question",
|
||||
"example": "some_value",
|
||||
}
|
||||
]
|
||||
|
||||
for i in PasswordArgumentParser.forbidden_chars:
|
||||
with pytest.raises(YunohostError):
|
||||
_parse_args_in_yunohost_format({"some_password": i * 8}, questions)
|
||||
|
||||
|
||||
def test_parse_args_in_yunohost_format_password_strong_enough():
|
||||
questions = [
|
||||
{
|
||||
"name": "some_password",
|
||||
"type": "password",
|
||||
"ask": "some question",
|
||||
"example": "some_value",
|
||||
}
|
||||
]
|
||||
|
||||
with pytest.raises(YunohostError):
|
||||
# too short
|
||||
_parse_args_in_yunohost_format({"some_password": "a"}, questions)
|
||||
|
||||
with pytest.raises(YunohostError):
|
||||
_parse_args_in_yunohost_format({"some_password": "password"}, questions)
|
||||
|
||||
|
||||
def test_parse_args_in_yunohost_format_path():
|
||||
questions = [{"name": "some_path", "type": "path", }]
|
||||
answers = {"some_path": "some_value"}
|
||||
|
@ -388,7 +417,6 @@ def test_parse_args_in_yunohost_format_path_input():
|
|||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
@pytest.mark.skip # that shit should work x(
|
||||
def test_parse_args_in_yunohost_format_path_input_no_ask():
|
||||
questions = [{"name": "some_path", "type": "path", }]
|
||||
answers = {}
|
||||
|
@ -416,7 +444,6 @@ def test_parse_args_in_yunohost_format_path_optional_with_input():
|
|||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
@pytest.mark.skip # this should work without ask
|
||||
def test_parse_args_in_yunohost_format_path_optional_with_input_without_ask():
|
||||
questions = [{"name": "some_path", "type": "path", "optional": True, }]
|
||||
answers = {}
|
||||
|
@ -604,11 +631,10 @@ def test_parse_args_in_yunohost_format_boolean_input():
|
|||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
@pytest.mark.skip # we should work
|
||||
def test_parse_args_in_yunohost_format_boolean_input_no_ask():
|
||||
questions = [{"name": "some_boolean", "type": "boolean", }]
|
||||
answers = {}
|
||||
expected_result = OrderedDict({"some_boolean": ("some_value", "boolean")})
|
||||
expected_result = OrderedDict({"some_boolean": (1, "boolean")})
|
||||
|
||||
with patch.object(msignals, "prompt", return_value="y"):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
@ -660,7 +686,6 @@ def test_parse_args_in_yunohost_format_boolean_no_input_default():
|
|||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
@pytest.mark.skip # we should raise
|
||||
def test_parse_args_in_yunohost_format_boolean_bad_default():
|
||||
questions = [
|
||||
{
|
||||
|
@ -704,16 +729,17 @@ def test_parse_args_in_yunohost_format_boolean_input_test_ask_with_default():
|
|||
|
||||
|
||||
def test_parse_args_in_yunohost_format_domain_empty():
|
||||
questions = [{"name": "some_domain", "type": "domain", }]
|
||||
questions = [{"name": "some_domain", "type": "domain",}]
|
||||
main_domain = "my_main_domain.com"
|
||||
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": ["my_main_domain.com"]}
|
||||
domain, "domain_list", return_value={"domains": [main_domain]}
|
||||
):
|
||||
with pytest.raises(YunohostError):
|
||||
_parse_args_in_yunohost_format(answers, questions)
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
def test_parse_args_in_yunohost_format_domain():
|
||||
|
@ -768,7 +794,6 @@ def test_parse_args_in_yunohost_format_domain_two_domains_wrong_answer():
|
|||
_parse_args_in_yunohost_format(answers, questions)
|
||||
|
||||
|
||||
@pytest.mark.skip # XXX should work
|
||||
def test_parse_args_in_yunohost_format_domain_two_domains_default_no_ask():
|
||||
main_domain = "my_main_domain.com"
|
||||
other_domain = "some_other_domain.tld"
|
||||
|
@ -858,7 +883,8 @@ def test_parse_args_in_yunohost_format_user():
|
|||
expected_result = OrderedDict({"some_user": (username, "user")})
|
||||
|
||||
with patch.object(user, "user_list", return_value={"users": users}):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
with patch.object(user, "user_info", return_value={}):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
def test_parse_args_in_yunohost_format_user_two_users():
|
||||
|
@ -888,13 +914,15 @@ def test_parse_args_in_yunohost_format_user_two_users():
|
|||
expected_result = OrderedDict({"some_user": (other_user, "user")})
|
||||
|
||||
with patch.object(user, "user_list", return_value={"users": users}):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
with 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}):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
with patch.object(user, "user_info", return_value={}):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
def test_parse_args_in_yunohost_format_user_two_users_wrong_answer():
|
||||
|
@ -983,13 +1011,14 @@ def test_parse_args_in_yunohost_format_user_two_users_default_input():
|
|||
answers = {}
|
||||
|
||||
with patch.object(user, "user_list", return_value={"users": users}):
|
||||
expected_result = OrderedDict({"some_user": (username, "user")})
|
||||
with patch.object(msignals, "prompt", return_value=username):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
with patch.object(user, "user_info", return_value={}):
|
||||
expected_result = OrderedDict({"some_user": (username, "user")})
|
||||
with patch.object(msignals, "prompt", return_value=username):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
expected_result = OrderedDict({"some_user": (other_user, "user")})
|
||||
with patch.object(msignals, "prompt", return_value=other_user):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
expected_result = OrderedDict({"some_user": (other_user, "user")})
|
||||
with patch.object(msignals, "prompt", return_value=other_user):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
def test_parse_args_in_yunohost_format_app_empty():
|
||||
|
@ -1020,14 +1049,14 @@ def test_parse_args_in_yunohost_format_app_no_apps():
|
|||
_parse_args_in_yunohost_format(answers, questions)
|
||||
|
||||
|
||||
@pytest.mark.skip # XXX should work
|
||||
def test_parse_args_in_yunohost_format_app_no_apps_optional():
|
||||
apps = []
|
||||
questions = [{"name": "some_app", "type": "app", "optional": True}]
|
||||
answers = {}
|
||||
expected_result = OrderedDict({"some_app": (None, "app")})
|
||||
|
||||
with patch.object(app, "app_list", return_value={"apps": apps}):
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == []
|
||||
assert _parse_args_in_yunohost_format(answers, questions) == expected_result
|
||||
|
||||
|
||||
def test_parse_args_in_yunohost_format_app():
|
||||
|
|
Loading…
Add table
Reference in a new issue