form: rework 'hydrate_questions...' with a new 'parse_raw_options' that parse and validate options

This commit is contained in:
axolotle 2023-04-19 19:58:14 +02:00
parent 37b4eb956d
commit 2a28e289ad
2 changed files with 33 additions and 22 deletions

View file

@ -51,7 +51,7 @@ from yunohost.utils.form import (
DomainOption, DomainOption,
WebPathOption, WebPathOption,
ask_questions_and_parse_answers, ask_questions_and_parse_answers,
hydrate_questions_with_choices, parse_raw_options,
) )
from yunohost.utils.i18n import _value_for_locale from yunohost.utils.i18n import _value_for_locale
from yunohost.utils.error import YunohostError, YunohostValidationError from yunohost.utils.error import YunohostError, YunohostValidationError
@ -963,8 +963,7 @@ def app_upgrade(
def app_manifest(app, with_screenshot=False): def app_manifest(app, with_screenshot=False):
manifest, extracted_app_folder = _extract_app(app) manifest, extracted_app_folder = _extract_app(app)
raw_questions = manifest.get("install", {}).values() manifest["install"] = parse_raw_options(manifest.get("install", {}), serialize=True)
manifest["install"] = hydrate_questions_with_choices(raw_questions)
# Add a base64 image to be displayed in web-admin # Add a base64 image to be displayed in web-admin
if with_screenshot and Moulinette.interface.type == "api": if with_screenshot and Moulinette.interface.type == "api":

View file

@ -29,6 +29,7 @@ from logging import getLogger
from typing import ( from typing import (
TYPE_CHECKING, TYPE_CHECKING,
cast, cast,
overload,
Annotated, Annotated,
Any, Any,
Callable, Callable,
@ -1609,6 +1610,33 @@ def ask_questions_and_parse_answers(
context = {**current_values, **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 # Validate/parse the options attributes
try: try:
model = OptionsModel(**raw_options) model = OptionsModel(**raw_options)
@ -1618,24 +1646,8 @@ def ask_questions_and_parse_answers(
raise YunohostValidationError(error, raw_msg=True) raise YunohostValidationError(error, raw_msg=True)
model.translate_options() 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]]: return model.options
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