form: rename Questions to Options

This commit is contained in:
axolotle 2023-04-07 16:25:48 +02:00
parent 9a585f03c6
commit f9fd379997
6 changed files with 143 additions and 143 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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()

View file

@ -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():

View file

@ -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()

View file

@ -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.