mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
form: rename Questions to Options
This commit is contained in:
parent
9a585f03c6
commit
f9fd379997
6 changed files with 143 additions and 143 deletions
20
src/app.py
20
src/app.py
|
@ -50,8 +50,8 @@ from moulinette.utils.filesystem import (
|
||||||
|
|
||||||
from yunohost.utils.configpanel import ConfigPanel, ask_questions_and_parse_answers
|
from yunohost.utils.configpanel import ConfigPanel, ask_questions_and_parse_answers
|
||||||
from yunohost.utils.form import (
|
from yunohost.utils.form import (
|
||||||
DomainQuestion,
|
DomainOption,
|
||||||
PathQuestion,
|
WebPathOption,
|
||||||
hydrate_questions_with_choices,
|
hydrate_questions_with_choices,
|
||||||
)
|
)
|
||||||
from yunohost.utils.i18n import _value_for_locale
|
from yunohost.utils.i18n import _value_for_locale
|
||||||
|
@ -430,10 +430,10 @@ def app_change_url(operation_logger, app, domain, path):
|
||||||
|
|
||||||
# Normalize path and domain format
|
# Normalize path and domain format
|
||||||
|
|
||||||
domain = DomainQuestion.normalize(domain)
|
domain = DomainOption.normalize(domain)
|
||||||
old_domain = DomainQuestion.normalize(old_domain)
|
old_domain = DomainOption.normalize(old_domain)
|
||||||
path = PathQuestion.normalize(path)
|
path = WebPathOption.normalize(path)
|
||||||
old_path = PathQuestion.normalize(old_path)
|
old_path = WebPathOption.normalize(old_path)
|
||||||
|
|
||||||
if (domain, path) == (old_domain, old_path):
|
if (domain, path) == (old_domain, old_path):
|
||||||
raise YunohostValidationError(
|
raise YunohostValidationError(
|
||||||
|
@ -1660,8 +1660,8 @@ def app_register_url(app, domain, path):
|
||||||
permission_sync_to_user,
|
permission_sync_to_user,
|
||||||
)
|
)
|
||||||
|
|
||||||
domain = DomainQuestion.normalize(domain)
|
domain = DomainOption.normalize(domain)
|
||||||
path = PathQuestion.normalize(path)
|
path = WebPathOption.normalize(path)
|
||||||
|
|
||||||
# We cannot change the url of an app already installed simply by changing
|
# We cannot change the url of an app already installed simply by changing
|
||||||
# the settings...
|
# the settings...
|
||||||
|
@ -2853,8 +2853,8 @@ def _get_conflicting_apps(domain, path, ignore_app=None):
|
||||||
|
|
||||||
from yunohost.domain import _assert_domain_exists
|
from yunohost.domain import _assert_domain_exists
|
||||||
|
|
||||||
domain = DomainQuestion.normalize(domain)
|
domain = DomainOption.normalize(domain)
|
||||||
path = PathQuestion.normalize(path)
|
path = WebPathOption.normalize(path)
|
||||||
|
|
||||||
# Abort if domain is unknown
|
# Abort if domain is unknown
|
||||||
_assert_domain_exists(domain)
|
_assert_domain_exists(domain)
|
||||||
|
|
|
@ -34,7 +34,7 @@ from yunohost.app import (
|
||||||
)
|
)
|
||||||
from yunohost.regenconf import regen_conf, _force_clear_hashes, _process_regen_conf
|
from yunohost.regenconf import regen_conf, _force_clear_hashes, _process_regen_conf
|
||||||
from yunohost.utils.configpanel import ConfigPanel
|
from yunohost.utils.configpanel import ConfigPanel
|
||||||
from yunohost.utils.form import Question
|
from yunohost.utils.form import BaseOption
|
||||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||||
from yunohost.log import is_unit_operation
|
from yunohost.log import is_unit_operation
|
||||||
|
|
||||||
|
@ -528,7 +528,7 @@ def domain_config_set(
|
||||||
"""
|
"""
|
||||||
Apply a new domain configuration
|
Apply a new domain configuration
|
||||||
"""
|
"""
|
||||||
Question.operation_logger = operation_logger
|
BaseOption.operation_logger = operation_logger
|
||||||
config = DomainConfigPanel(domain)
|
config = DomainConfigPanel(domain)
|
||||||
return config.set(key, value, args, args_file, operation_logger=operation_logger)
|
return config.set(key, value, args, args_file, operation_logger=operation_logger)
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ import subprocess
|
||||||
from moulinette import m18n
|
from moulinette import m18n
|
||||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||||
from yunohost.utils.configpanel import ConfigPanel
|
from yunohost.utils.configpanel import ConfigPanel
|
||||||
from yunohost.utils.form import Question
|
from yunohost.utils.form import BaseOption
|
||||||
from moulinette.utils.log import getActionLogger
|
from moulinette.utils.log import getActionLogger
|
||||||
from yunohost.regenconf import regen_conf
|
from yunohost.regenconf import regen_conf
|
||||||
from yunohost.firewall import firewall_reload
|
from yunohost.firewall import firewall_reload
|
||||||
|
@ -82,7 +82,7 @@ def settings_set(operation_logger, key=None, value=None, args=None, args_file=No
|
||||||
value -- New value
|
value -- New value
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Question.operation_logger = operation_logger
|
BaseOption.operation_logger = operation_logger
|
||||||
settings = SettingsConfigPanel()
|
settings = SettingsConfigPanel()
|
||||||
key = translate_legacy_settings_to_configpanel_settings(key)
|
key = translate_legacy_settings_to_configpanel_settings(key)
|
||||||
return settings.set(key, value, args, args_file, operation_logger=operation_logger)
|
return settings.set(key, value, args, args_file, operation_logger=operation_logger)
|
||||||
|
@ -231,7 +231,7 @@ class SettingsConfigPanel(ConfigPanel):
|
||||||
# Replace all values with default values
|
# Replace all values with default values
|
||||||
self.values = self._get_default_values()
|
self.values = self._get_default_values()
|
||||||
|
|
||||||
Question.operation_logger = operation_logger
|
BaseOption.operation_logger = operation_logger
|
||||||
|
|
||||||
if operation_logger:
|
if operation_logger:
|
||||||
operation_logger.start()
|
operation_logger.start()
|
||||||
|
|
|
@ -17,12 +17,12 @@ from yunohost import app, domain, user
|
||||||
from yunohost.utils.form import (
|
from yunohost.utils.form import (
|
||||||
ARGUMENTS_TYPE_PARSERS,
|
ARGUMENTS_TYPE_PARSERS,
|
||||||
ask_questions_and_parse_answers,
|
ask_questions_and_parse_answers,
|
||||||
DisplayTextQuestion,
|
DisplayTextOption,
|
||||||
PasswordQuestion,
|
PasswordOption,
|
||||||
DomainQuestion,
|
DomainOption,
|
||||||
PathQuestion,
|
WebPathOption,
|
||||||
BooleanQuestion,
|
BooleanOption,
|
||||||
FileQuestion,
|
FileOption,
|
||||||
evaluate_simple_js_expression,
|
evaluate_simple_js_expression,
|
||||||
)
|
)
|
||||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||||
|
@ -438,7 +438,7 @@ class BaseTest:
|
||||||
id_ = raw_option["id"]
|
id_ = raw_option["id"]
|
||||||
option, value = _fill_or_prompt_one_option(raw_option, None)
|
option, value = _fill_or_prompt_one_option(raw_option, None)
|
||||||
|
|
||||||
is_special_readonly_option = isinstance(option, DisplayTextQuestion)
|
is_special_readonly_option = isinstance(option, DisplayTextOption)
|
||||||
|
|
||||||
assert isinstance(option, ARGUMENTS_TYPE_PARSERS[raw_option["type"]])
|
assert isinstance(option, ARGUMENTS_TYPE_PARSERS[raw_option["type"]])
|
||||||
assert option.type == raw_option["type"]
|
assert option.type == raw_option["type"]
|
||||||
|
@ -734,7 +734,7 @@ class TestPassword(BaseTest):
|
||||||
], reason="Should output exactly the same"),
|
], reason="Should output exactly the same"),
|
||||||
("s3cr3t!!", "s3cr3t!!"),
|
("s3cr3t!!", "s3cr3t!!"),
|
||||||
("secret", FAIL),
|
("secret", FAIL),
|
||||||
*[("supersecret" + char, FAIL) for char in PasswordQuestion.forbidden_chars], # FIXME maybe add ` \n` to the list?
|
*[("supersecret" + char, FAIL) for char in PasswordOption.forbidden_chars], # FIXME maybe add ` \n` to the list?
|
||||||
# readonly
|
# readonly
|
||||||
*xpass(scenarios=[
|
*xpass(scenarios=[
|
||||||
("s3cr3t!!", "s3cr3t!!", {"readonly": True}),
|
("s3cr3t!!", "s3cr3t!!", {"readonly": True}),
|
||||||
|
@ -1225,9 +1225,9 @@ class TestUrl(BaseTest):
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def file_clean():
|
def file_clean():
|
||||||
FileQuestion.clean_upload_dirs()
|
FileOption.clean_upload_dirs()
|
||||||
yield
|
yield
|
||||||
FileQuestion.clean_upload_dirs()
|
FileOption.clean_upload_dirs()
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
|
@ -1263,7 +1263,7 @@ def _test_file_intake_may_fail(raw_option, intake, expected_output):
|
||||||
with open(value) as f:
|
with open(value) as f:
|
||||||
assert f.read() == expected_output
|
assert f.read() == expected_output
|
||||||
|
|
||||||
FileQuestion.clean_upload_dirs()
|
FileOption.clean_upload_dirs()
|
||||||
|
|
||||||
assert not os.path.exists(value)
|
assert not os.path.exists(value)
|
||||||
|
|
||||||
|
@ -2138,88 +2138,88 @@ def test_question_number_input_test_ask_with_example():
|
||||||
|
|
||||||
|
|
||||||
def test_normalize_boolean_nominal():
|
def test_normalize_boolean_nominal():
|
||||||
assert BooleanQuestion.normalize("yes") == 1
|
assert BooleanOption.normalize("yes") == 1
|
||||||
assert BooleanQuestion.normalize("Yes") == 1
|
assert BooleanOption.normalize("Yes") == 1
|
||||||
assert BooleanQuestion.normalize(" yes ") == 1
|
assert BooleanOption.normalize(" yes ") == 1
|
||||||
assert BooleanQuestion.normalize("y") == 1
|
assert BooleanOption.normalize("y") == 1
|
||||||
assert BooleanQuestion.normalize("true") == 1
|
assert BooleanOption.normalize("true") == 1
|
||||||
assert BooleanQuestion.normalize("True") == 1
|
assert BooleanOption.normalize("True") == 1
|
||||||
assert BooleanQuestion.normalize("on") == 1
|
assert BooleanOption.normalize("on") == 1
|
||||||
assert BooleanQuestion.normalize("1") == 1
|
assert BooleanOption.normalize("1") == 1
|
||||||
assert BooleanQuestion.normalize(1) == 1
|
assert BooleanOption.normalize(1) == 1
|
||||||
|
|
||||||
assert BooleanQuestion.normalize("no") == 0
|
assert BooleanOption.normalize("no") == 0
|
||||||
assert BooleanQuestion.normalize("No") == 0
|
assert BooleanOption.normalize("No") == 0
|
||||||
assert BooleanQuestion.normalize(" no ") == 0
|
assert BooleanOption.normalize(" no ") == 0
|
||||||
assert BooleanQuestion.normalize("n") == 0
|
assert BooleanOption.normalize("n") == 0
|
||||||
assert BooleanQuestion.normalize("false") == 0
|
assert BooleanOption.normalize("false") == 0
|
||||||
assert BooleanQuestion.normalize("False") == 0
|
assert BooleanOption.normalize("False") == 0
|
||||||
assert BooleanQuestion.normalize("off") == 0
|
assert BooleanOption.normalize("off") == 0
|
||||||
assert BooleanQuestion.normalize("0") == 0
|
assert BooleanOption.normalize("0") == 0
|
||||||
assert BooleanQuestion.normalize(0) == 0
|
assert BooleanOption.normalize(0) == 0
|
||||||
|
|
||||||
assert BooleanQuestion.normalize("") is None
|
assert BooleanOption.normalize("") is None
|
||||||
assert BooleanQuestion.normalize(" ") is None
|
assert BooleanOption.normalize(" ") is None
|
||||||
assert BooleanQuestion.normalize(" none ") is None
|
assert BooleanOption.normalize(" none ") is None
|
||||||
assert BooleanQuestion.normalize("None") is None
|
assert BooleanOption.normalize("None") is None
|
||||||
assert BooleanQuestion.normalize("noNe") is None
|
assert BooleanOption.normalize("noNe") is None
|
||||||
assert BooleanQuestion.normalize(None) is None
|
assert BooleanOption.normalize(None) is None
|
||||||
|
|
||||||
|
|
||||||
def test_normalize_boolean_humanize():
|
def test_normalize_boolean_humanize():
|
||||||
assert BooleanQuestion.humanize("yes") == "yes"
|
assert BooleanOption.humanize("yes") == "yes"
|
||||||
assert BooleanQuestion.humanize("true") == "yes"
|
assert BooleanOption.humanize("true") == "yes"
|
||||||
assert BooleanQuestion.humanize("on") == "yes"
|
assert BooleanOption.humanize("on") == "yes"
|
||||||
|
|
||||||
assert BooleanQuestion.humanize("no") == "no"
|
assert BooleanOption.humanize("no") == "no"
|
||||||
assert BooleanQuestion.humanize("false") == "no"
|
assert BooleanOption.humanize("false") == "no"
|
||||||
assert BooleanQuestion.humanize("off") == "no"
|
assert BooleanOption.humanize("off") == "no"
|
||||||
|
|
||||||
|
|
||||||
def test_normalize_boolean_invalid():
|
def test_normalize_boolean_invalid():
|
||||||
with pytest.raises(YunohostValidationError):
|
with pytest.raises(YunohostValidationError):
|
||||||
BooleanQuestion.normalize("yesno")
|
BooleanOption.normalize("yesno")
|
||||||
with pytest.raises(YunohostValidationError):
|
with pytest.raises(YunohostValidationError):
|
||||||
BooleanQuestion.normalize("foobar")
|
BooleanOption.normalize("foobar")
|
||||||
with pytest.raises(YunohostValidationError):
|
with pytest.raises(YunohostValidationError):
|
||||||
BooleanQuestion.normalize("enabled")
|
BooleanOption.normalize("enabled")
|
||||||
|
|
||||||
|
|
||||||
def test_normalize_boolean_special_yesno():
|
def test_normalize_boolean_special_yesno():
|
||||||
customyesno = {"yes": "enabled", "no": "disabled"}
|
customyesno = {"yes": "enabled", "no": "disabled"}
|
||||||
|
|
||||||
assert BooleanQuestion.normalize("yes", customyesno) == "enabled"
|
assert BooleanOption.normalize("yes", customyesno) == "enabled"
|
||||||
assert BooleanQuestion.normalize("true", customyesno) == "enabled"
|
assert BooleanOption.normalize("true", customyesno) == "enabled"
|
||||||
assert BooleanQuestion.normalize("enabled", customyesno) == "enabled"
|
assert BooleanOption.normalize("enabled", customyesno) == "enabled"
|
||||||
assert BooleanQuestion.humanize("yes", customyesno) == "yes"
|
assert BooleanOption.humanize("yes", customyesno) == "yes"
|
||||||
assert BooleanQuestion.humanize("true", customyesno) == "yes"
|
assert BooleanOption.humanize("true", customyesno) == "yes"
|
||||||
assert BooleanQuestion.humanize("enabled", customyesno) == "yes"
|
assert BooleanOption.humanize("enabled", customyesno) == "yes"
|
||||||
|
|
||||||
assert BooleanQuestion.normalize("no", customyesno) == "disabled"
|
assert BooleanOption.normalize("no", customyesno) == "disabled"
|
||||||
assert BooleanQuestion.normalize("false", customyesno) == "disabled"
|
assert BooleanOption.normalize("false", customyesno) == "disabled"
|
||||||
assert BooleanQuestion.normalize("disabled", customyesno) == "disabled"
|
assert BooleanOption.normalize("disabled", customyesno) == "disabled"
|
||||||
assert BooleanQuestion.humanize("no", customyesno) == "no"
|
assert BooleanOption.humanize("no", customyesno) == "no"
|
||||||
assert BooleanQuestion.humanize("false", customyesno) == "no"
|
assert BooleanOption.humanize("false", customyesno) == "no"
|
||||||
assert BooleanQuestion.humanize("disabled", customyesno) == "no"
|
assert BooleanOption.humanize("disabled", customyesno) == "no"
|
||||||
|
|
||||||
|
|
||||||
def test_normalize_domain():
|
def test_normalize_domain():
|
||||||
assert DomainQuestion.normalize("https://yolo.swag/") == "yolo.swag"
|
assert DomainOption.normalize("https://yolo.swag/") == "yolo.swag"
|
||||||
assert DomainQuestion.normalize("http://yolo.swag") == "yolo.swag"
|
assert DomainOption.normalize("http://yolo.swag") == "yolo.swag"
|
||||||
assert DomainQuestion.normalize("yolo.swag/") == "yolo.swag"
|
assert DomainOption.normalize("yolo.swag/") == "yolo.swag"
|
||||||
|
|
||||||
|
|
||||||
def test_normalize_path():
|
def test_normalize_path():
|
||||||
assert PathQuestion.normalize("") == "/"
|
assert WebPathOption.normalize("") == "/"
|
||||||
assert PathQuestion.normalize("") == "/"
|
assert WebPathOption.normalize("") == "/"
|
||||||
assert PathQuestion.normalize("macnuggets") == "/macnuggets"
|
assert WebPathOption.normalize("macnuggets") == "/macnuggets"
|
||||||
assert PathQuestion.normalize("/macnuggets") == "/macnuggets"
|
assert WebPathOption.normalize("/macnuggets") == "/macnuggets"
|
||||||
assert PathQuestion.normalize(" /macnuggets ") == "/macnuggets"
|
assert WebPathOption.normalize(" /macnuggets ") == "/macnuggets"
|
||||||
assert PathQuestion.normalize("/macnuggets") == "/macnuggets"
|
assert WebPathOption.normalize("/macnuggets") == "/macnuggets"
|
||||||
assert PathQuestion.normalize("mac/nuggets") == "/mac/nuggets"
|
assert WebPathOption.normalize("mac/nuggets") == "/mac/nuggets"
|
||||||
assert PathQuestion.normalize("/macnuggets/") == "/macnuggets"
|
assert WebPathOption.normalize("/macnuggets/") == "/macnuggets"
|
||||||
assert PathQuestion.normalize("macnuggets/") == "/macnuggets"
|
assert WebPathOption.normalize("macnuggets/") == "/macnuggets"
|
||||||
assert PathQuestion.normalize("////macnuggets///") == "/macnuggets"
|
assert WebPathOption.normalize("////macnuggets///") == "/macnuggets"
|
||||||
|
|
||||||
|
|
||||||
def test_simple_evaluate():
|
def test_simple_evaluate():
|
||||||
|
|
|
@ -37,8 +37,8 @@ from yunohost.utils.i18n import _value_for_locale
|
||||||
from yunohost.utils.error import YunohostError, YunohostValidationError
|
from yunohost.utils.error import YunohostError, YunohostValidationError
|
||||||
from yunohost.utils.form import (
|
from yunohost.utils.form import (
|
||||||
ARGUMENTS_TYPE_PARSERS,
|
ARGUMENTS_TYPE_PARSERS,
|
||||||
FileQuestion,
|
FileOption,
|
||||||
Question,
|
BaseOption,
|
||||||
ask_questions_and_parse_answers,
|
ask_questions_and_parse_answers,
|
||||||
evaluate_simple_js_expression,
|
evaluate_simple_js_expression,
|
||||||
)
|
)
|
||||||
|
@ -213,7 +213,7 @@ class ConfigPanel:
|
||||||
# Read or get values and hydrate the config
|
# Read or get values and hydrate the config
|
||||||
self._load_current_values()
|
self._load_current_values()
|
||||||
self._hydrate()
|
self._hydrate()
|
||||||
Question.operation_logger = operation_logger
|
BaseOption.operation_logger = operation_logger
|
||||||
self._ask(action=action_id)
|
self._ask(action=action_id)
|
||||||
|
|
||||||
# FIXME: here, we could want to check constrains on
|
# FIXME: here, we could want to check constrains on
|
||||||
|
@ -244,7 +244,7 @@ class ConfigPanel:
|
||||||
# FIXME : this is currently done in the context of config panels,
|
# FIXME : this is currently done in the context of config panels,
|
||||||
# but could also happen in the context of app install ... (or anywhere else
|
# but could also happen in the context of app install ... (or anywhere else
|
||||||
# where we may parse args etc...)
|
# where we may parse args etc...)
|
||||||
FileQuestion.clean_upload_dirs()
|
FileOption.clean_upload_dirs()
|
||||||
|
|
||||||
# FIXME: i18n
|
# FIXME: i18n
|
||||||
logger.success(f"Action {action_id} successful")
|
logger.success(f"Action {action_id} successful")
|
||||||
|
@ -277,7 +277,7 @@ class ConfigPanel:
|
||||||
# Read or get values and hydrate the config
|
# Read or get values and hydrate the config
|
||||||
self._load_current_values()
|
self._load_current_values()
|
||||||
self._hydrate()
|
self._hydrate()
|
||||||
Question.operation_logger = operation_logger
|
BaseOption.operation_logger = operation_logger
|
||||||
self._ask()
|
self._ask()
|
||||||
|
|
||||||
if operation_logger:
|
if operation_logger:
|
||||||
|
@ -305,7 +305,7 @@ class ConfigPanel:
|
||||||
# FIXME : this is currently done in the context of config panels,
|
# FIXME : this is currently done in the context of config panels,
|
||||||
# but could also happen in the context of app install ... (or anywhere else
|
# but could also happen in the context of app install ... (or anywhere else
|
||||||
# where we may parse args etc...)
|
# where we may parse args etc...)
|
||||||
FileQuestion.clean_upload_dirs()
|
FileOption.clean_upload_dirs()
|
||||||
|
|
||||||
self._reload_services()
|
self._reload_services()
|
||||||
|
|
||||||
|
|
|
@ -183,7 +183,7 @@ def evaluate_simple_js_expression(expr, context={}):
|
||||||
return evaluate_simple_ast(node, context)
|
return evaluate_simple_ast(node, context)
|
||||||
|
|
||||||
|
|
||||||
class Question:
|
class BaseOption:
|
||||||
hide_user_input_in_prompt = False
|
hide_user_input_in_prompt = False
|
||||||
pattern: Optional[Dict] = None
|
pattern: Optional[Dict] = None
|
||||||
|
|
||||||
|
@ -377,26 +377,26 @@ class Question:
|
||||||
return self.value
|
return self.value
|
||||||
|
|
||||||
|
|
||||||
class StringQuestion(Question):
|
class StringOption(BaseOption):
|
||||||
argument_type = "string"
|
argument_type = "string"
|
||||||
default_value = ""
|
default_value = ""
|
||||||
|
|
||||||
|
|
||||||
class EmailQuestion(StringQuestion):
|
class EmailOption(StringOption):
|
||||||
pattern = {
|
pattern = {
|
||||||
"regexp": r"^.+@.+",
|
"regexp": r"^.+@.+",
|
||||||
"error": "config_validate_email", # i18n: config_validate_email
|
"error": "config_validate_email", # i18n: config_validate_email
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class URLQuestion(StringQuestion):
|
class URLOption(StringOption):
|
||||||
pattern = {
|
pattern = {
|
||||||
"regexp": r"^https?://.*$",
|
"regexp": r"^https?://.*$",
|
||||||
"error": "config_validate_url", # i18n: config_validate_url
|
"error": "config_validate_url", # i18n: config_validate_url
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class DateQuestion(StringQuestion):
|
class DateOption(StringOption):
|
||||||
pattern = {
|
pattern = {
|
||||||
"regexp": r"^\d{4}-\d\d-\d\d$",
|
"regexp": r"^\d{4}-\d\d-\d\d$",
|
||||||
"error": "config_validate_date", # i18n: config_validate_date
|
"error": "config_validate_date", # i18n: config_validate_date
|
||||||
|
@ -414,21 +414,21 @@ class DateQuestion(StringQuestion):
|
||||||
raise YunohostValidationError("config_validate_date")
|
raise YunohostValidationError("config_validate_date")
|
||||||
|
|
||||||
|
|
||||||
class TimeQuestion(StringQuestion):
|
class TimeOption(StringOption):
|
||||||
pattern = {
|
pattern = {
|
||||||
"regexp": r"^(?:\d|[01]\d|2[0-3]):[0-5]\d$",
|
"regexp": r"^(?:\d|[01]\d|2[0-3]):[0-5]\d$",
|
||||||
"error": "config_validate_time", # i18n: config_validate_time
|
"error": "config_validate_time", # i18n: config_validate_time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ColorQuestion(StringQuestion):
|
class ColorOption(StringOption):
|
||||||
pattern = {
|
pattern = {
|
||||||
"regexp": r"^#[ABCDEFabcdef\d]{3,6}$",
|
"regexp": r"^#[ABCDEFabcdef\d]{3,6}$",
|
||||||
"error": "config_validate_color", # i18n: config_validate_color
|
"error": "config_validate_color", # i18n: config_validate_color
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class TagsQuestion(Question):
|
class TagsOption(BaseOption):
|
||||||
argument_type = "tags"
|
argument_type = "tags"
|
||||||
default_value = ""
|
default_value = ""
|
||||||
|
|
||||||
|
@ -478,7 +478,7 @@ class TagsQuestion(Question):
|
||||||
return super()._post_parse_value()
|
return super()._post_parse_value()
|
||||||
|
|
||||||
|
|
||||||
class PasswordQuestion(Question):
|
class PasswordOption(BaseOption):
|
||||||
hide_user_input_in_prompt = True
|
hide_user_input_in_prompt = True
|
||||||
argument_type = "password"
|
argument_type = "password"
|
||||||
default_value = ""
|
default_value = ""
|
||||||
|
@ -509,13 +509,13 @@ class PasswordQuestion(Question):
|
||||||
assert_password_is_strong_enough("user", self.value)
|
assert_password_is_strong_enough("user", self.value)
|
||||||
|
|
||||||
|
|
||||||
class PathQuestion(Question):
|
class WebPathOption(BaseOption):
|
||||||
argument_type = "path"
|
argument_type = "path"
|
||||||
default_value = ""
|
default_value = ""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def normalize(value, option={}):
|
def normalize(value, option={}):
|
||||||
option = option.__dict__ if isinstance(option, Question) else option
|
option = option.__dict__ if isinstance(option, BaseOption) else option
|
||||||
|
|
||||||
if not isinstance(value, str):
|
if not isinstance(value, str):
|
||||||
raise YunohostValidationError(
|
raise YunohostValidationError(
|
||||||
|
@ -528,19 +528,19 @@ class PathQuestion(Question):
|
||||||
if option.get("optional"):
|
if option.get("optional"):
|
||||||
return ""
|
return ""
|
||||||
# Hmpf here we could just have a "else" case
|
# Hmpf here we could just have a "else" case
|
||||||
# but we also want PathQuestion.normalize("") to return "/"
|
# but we also want WebPathOption.normalize("") to return "/"
|
||||||
# (i.e. if no option is provided, hence .get("optional") is None
|
# (i.e. if no option is provided, hence .get("optional") is None
|
||||||
elif option.get("optional") is False:
|
elif option.get("optional") is False:
|
||||||
raise YunohostValidationError(
|
raise YunohostValidationError(
|
||||||
"app_argument_invalid",
|
"app_argument_invalid",
|
||||||
name=option.get("name"),
|
name=option.get("name"),
|
||||||
error="Question is mandatory",
|
error="Option is mandatory",
|
||||||
)
|
)
|
||||||
|
|
||||||
return "/" + value.strip().strip(" /")
|
return "/" + value.strip().strip(" /")
|
||||||
|
|
||||||
|
|
||||||
class BooleanQuestion(Question):
|
class BooleanOption(BaseOption):
|
||||||
argument_type = "boolean"
|
argument_type = "boolean"
|
||||||
default_value = 0
|
default_value = 0
|
||||||
yes_answers = ["1", "yes", "y", "true", "t", "on"]
|
yes_answers = ["1", "yes", "y", "true", "t", "on"]
|
||||||
|
@ -548,12 +548,12 @@ class BooleanQuestion(Question):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def humanize(value, option={}):
|
def humanize(value, option={}):
|
||||||
option = option.__dict__ if isinstance(option, Question) else option
|
option = option.__dict__ if isinstance(option, BaseOption) else option
|
||||||
|
|
||||||
yes = option.get("yes", 1)
|
yes = option.get("yes", 1)
|
||||||
no = option.get("no", 0)
|
no = option.get("no", 0)
|
||||||
|
|
||||||
value = BooleanQuestion.normalize(value, option)
|
value = BooleanOption.normalize(value, option)
|
||||||
|
|
||||||
if value == yes:
|
if value == yes:
|
||||||
return "yes"
|
return "yes"
|
||||||
|
@ -571,7 +571,7 @@ class BooleanQuestion(Question):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def normalize(value, option={}):
|
def normalize(value, option={}):
|
||||||
option = option.__dict__ if isinstance(option, Question) else option
|
option = option.__dict__ if isinstance(option, BaseOption) else option
|
||||||
|
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
value = value.strip()
|
value = value.strip()
|
||||||
|
@ -579,8 +579,8 @@ class BooleanQuestion(Question):
|
||||||
technical_yes = option.get("yes", 1)
|
technical_yes = option.get("yes", 1)
|
||||||
technical_no = option.get("no", 0)
|
technical_no = option.get("no", 0)
|
||||||
|
|
||||||
no_answers = BooleanQuestion.no_answers
|
no_answers = BooleanOption.no_answers
|
||||||
yes_answers = BooleanQuestion.yes_answers
|
yes_answers = BooleanOption.yes_answers
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
str(technical_yes).lower() not in no_answers
|
str(technical_yes).lower() not in no_answers
|
||||||
|
@ -630,7 +630,7 @@ class BooleanQuestion(Question):
|
||||||
return getattr(self, key, default)
|
return getattr(self, key, default)
|
||||||
|
|
||||||
|
|
||||||
class DomainQuestion(Question):
|
class DomainOption(BaseOption):
|
||||||
argument_type = "domain"
|
argument_type = "domain"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
@ -661,7 +661,7 @@ class DomainQuestion(Question):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
class AppQuestion(Question):
|
class AppOption(BaseOption):
|
||||||
argument_type = "app"
|
argument_type = "app"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
@ -688,7 +688,7 @@ class AppQuestion(Question):
|
||||||
self.choices.update({app["id"]: _app_display(app) for app in apps})
|
self.choices.update({app["id"]: _app_display(app) for app in apps})
|
||||||
|
|
||||||
|
|
||||||
class UserQuestion(Question):
|
class UserOption(BaseOption):
|
||||||
argument_type = "user"
|
argument_type = "user"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
@ -721,7 +721,7 @@ class UserQuestion(Question):
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
class GroupQuestion(Question):
|
class GroupOption(BaseOption):
|
||||||
argument_type = "group"
|
argument_type = "group"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
@ -747,7 +747,7 @@ class GroupQuestion(Question):
|
||||||
self.default = "all_users"
|
self.default = "all_users"
|
||||||
|
|
||||||
|
|
||||||
class NumberQuestion(Question):
|
class NumberOption(BaseOption):
|
||||||
argument_type = "number"
|
argument_type = "number"
|
||||||
default_value = None
|
default_value = None
|
||||||
|
|
||||||
|
@ -773,7 +773,7 @@ class NumberQuestion(Question):
|
||||||
if value in [None, ""]:
|
if value in [None, ""]:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
option = option.__dict__ if isinstance(option, Question) else option
|
option = option.__dict__ if isinstance(option, BaseOption) else option
|
||||||
raise YunohostValidationError(
|
raise YunohostValidationError(
|
||||||
"app_argument_invalid",
|
"app_argument_invalid",
|
||||||
name=option.get("name"),
|
name=option.get("name"),
|
||||||
|
@ -800,7 +800,7 @@ class NumberQuestion(Question):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class DisplayTextQuestion(Question):
|
class DisplayTextOption(BaseOption):
|
||||||
argument_type = "display_text"
|
argument_type = "display_text"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
|
@ -830,7 +830,7 @@ class DisplayTextQuestion(Question):
|
||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
class FileQuestion(Question):
|
class FileOption(BaseOption):
|
||||||
argument_type = "file"
|
argument_type = "file"
|
||||||
upload_dirs: List[str] = []
|
upload_dirs: List[str] = []
|
||||||
|
|
||||||
|
@ -876,7 +876,7 @@ class FileQuestion(Question):
|
||||||
upload_dir = tempfile.mkdtemp(prefix="ynh_filequestion_")
|
upload_dir = tempfile.mkdtemp(prefix="ynh_filequestion_")
|
||||||
_, file_path = tempfile.mkstemp(dir=upload_dir)
|
_, file_path = tempfile.mkstemp(dir=upload_dir)
|
||||||
|
|
||||||
FileQuestion.upload_dirs += [upload_dir]
|
FileOption.upload_dirs += [upload_dir]
|
||||||
|
|
||||||
logger.debug(f"Saving file {self.name} for file question into {file_path}")
|
logger.debug(f"Saving file {self.name} for file question into {file_path}")
|
||||||
|
|
||||||
|
@ -895,7 +895,7 @@ class FileQuestion(Question):
|
||||||
return self.value
|
return self.value
|
||||||
|
|
||||||
|
|
||||||
class ButtonQuestion(Question):
|
class ButtonOption(BaseOption):
|
||||||
argument_type = "button"
|
argument_type = "button"
|
||||||
enabled = None
|
enabled = None
|
||||||
|
|
||||||
|
@ -907,29 +907,29 @@ class ButtonQuestion(Question):
|
||||||
|
|
||||||
|
|
||||||
ARGUMENTS_TYPE_PARSERS = {
|
ARGUMENTS_TYPE_PARSERS = {
|
||||||
"string": StringQuestion,
|
"string": StringOption,
|
||||||
"text": StringQuestion,
|
"text": StringOption,
|
||||||
"select": StringQuestion,
|
"select": StringOption,
|
||||||
"tags": TagsQuestion,
|
"tags": TagsOption,
|
||||||
"email": EmailQuestion,
|
"email": EmailOption,
|
||||||
"url": URLQuestion,
|
"url": URLOption,
|
||||||
"date": DateQuestion,
|
"date": DateOption,
|
||||||
"time": TimeQuestion,
|
"time": TimeOption,
|
||||||
"color": ColorQuestion,
|
"color": ColorOption,
|
||||||
"password": PasswordQuestion,
|
"password": PasswordOption,
|
||||||
"path": PathQuestion,
|
"path": WebPathOption,
|
||||||
"boolean": BooleanQuestion,
|
"boolean": BooleanOption,
|
||||||
"domain": DomainQuestion,
|
"domain": DomainOption,
|
||||||
"user": UserQuestion,
|
"user": UserOption,
|
||||||
"group": GroupQuestion,
|
"group": GroupOption,
|
||||||
"number": NumberQuestion,
|
"number": NumberOption,
|
||||||
"range": NumberQuestion,
|
"range": NumberOption,
|
||||||
"display_text": DisplayTextQuestion,
|
"display_text": DisplayTextOption,
|
||||||
"alert": DisplayTextQuestion,
|
"alert": DisplayTextOption,
|
||||||
"markdown": DisplayTextQuestion,
|
"markdown": DisplayTextOption,
|
||||||
"file": FileQuestion,
|
"file": FileOption,
|
||||||
"app": AppQuestion,
|
"app": AppOption,
|
||||||
"button": ButtonQuestion,
|
"button": ButtonOption,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -938,7 +938,7 @@ def ask_questions_and_parse_answers(
|
||||||
prefilled_answers: Union[str, Mapping[str, Any]] = {},
|
prefilled_answers: Union[str, Mapping[str, Any]] = {},
|
||||||
current_values: Mapping[str, Any] = {},
|
current_values: Mapping[str, Any] = {},
|
||||||
hooks: Dict[str, Callable[[], None]] = {},
|
hooks: Dict[str, Callable[[], None]] = {},
|
||||||
) -> List[Question]:
|
) -> List[BaseOption]:
|
||||||
"""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.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue