diff --git a/src/app.py b/src/app.py index 0514066c9..8ab683d81 100644 --- a/src/app.py +++ b/src/app.py @@ -51,7 +51,7 @@ from yunohost.utils.form import ( DomainOption, WebPathOption, ask_questions_and_parse_answers, - hydrate_questions_with_choices, + parse_raw_options, ) from yunohost.utils.i18n import _value_for_locale from yunohost.utils.error import YunohostError, YunohostValidationError @@ -963,8 +963,7 @@ def app_upgrade( def app_manifest(app, with_screenshot=False): manifest, extracted_app_folder = _extract_app(app) - raw_questions = manifest.get("install", {}).values() - manifest["install"] = hydrate_questions_with_choices(raw_questions) + manifest["install"] = parse_raw_options(manifest.get("install", {}), serialize=True) # Add a base64 image to be displayed in web-admin if with_screenshot and Moulinette.interface.type == "api": diff --git a/src/utils/form.py b/src/utils/form.py index 4d62b0a29..dce4b94c8 100644 --- a/src/utils/form.py +++ b/src/utils/form.py @@ -29,6 +29,7 @@ from logging import getLogger from typing import ( TYPE_CHECKING, cast, + overload, Annotated, Any, Callable, @@ -1609,6 +1610,33 @@ def ask_questions_and_parse_answers( context = {**current_values, **answers} + model_options = parse_raw_options(raw_options, serialize=False) + # Build the form from those questions and instantiate it without + # parsing/validation (construct) since it may contains required questions. + form = build_form(model_options).construct() + form = prompt_or_validate_form( + model_options, form, prefilled_answers=answers, context=context, hooks=hooks + ) + return (model_options, form) + + +@overload +def parse_raw_options( + raw_options: dict[str, Any], serialize: Literal[True] +) -> list[dict[str, Any]]: + ... + + +@overload +def parse_raw_options( + raw_options: dict[str, Any], serialize: Literal[False] = False +) -> list[AnyOption]: + ... + + +def parse_raw_options( + raw_options: dict[str, Any], serialize: bool = False +) -> Union[list[dict[str, Any]], list[AnyOption]]: # Validate/parse the options attributes try: model = OptionsModel(**raw_options) @@ -1618,24 +1646,8 @@ def ask_questions_and_parse_answers( raise YunohostValidationError(error, raw_msg=True) model.translate_options() - # Build the form from those questions and instantiate it without - # parsing/validation (construct) since it may contains required questions. - form = build_form(model.options).construct() - form = prompt_or_validate_form( - model.options, form, prefilled_answers=answers, context=context, hooks=hooks - ) - return (model.options, form) + if serialize: + return model.dict()["options"] -def hydrate_questions_with_choices(raw_questions: list[dict[str, Any]]) -> list[dict[str, Any]]: - out = [] - - for raw_question in raw_questions: - raw_question = hydrate_option_type(raw_question) - question = OPTIONS[raw_question["type"]](**raw_question) - if isinstance(question, BaseChoicesOption) and question.choices: - raw_question["choices"] = question.choices - raw_question["default"] = question.default - out.append(raw_question) - - return out + return model.options