|
@@ -1,52 +1,56 @@
|
|
|
+from collections.abc import Mapping
|
|
|
+from typing import Any, Optional
|
|
|
+
|
|
|
from core.app.app_config.entities import AppConfig, VariableEntity
|
|
|
|
|
|
|
|
|
class BaseAppGenerator:
|
|
|
- def _get_cleaned_inputs(self, user_inputs: dict, app_config: AppConfig):
|
|
|
- if user_inputs is None:
|
|
|
- user_inputs = {}
|
|
|
-
|
|
|
- filtered_inputs = {}
|
|
|
-
|
|
|
+ def _get_cleaned_inputs(self, user_inputs: Optional[Mapping[str, Any]], app_config: AppConfig) -> Mapping[str, Any]:
|
|
|
+ user_inputs = user_inputs or {}
|
|
|
# Filter input variables from form configuration, handle required fields, default values, and option values
|
|
|
variables = app_config.variables
|
|
|
- for variable_config in variables:
|
|
|
- variable = variable_config.variable
|
|
|
-
|
|
|
- if (variable not in user_inputs
|
|
|
- or user_inputs[variable] is None
|
|
|
- or (isinstance(user_inputs[variable], str) and user_inputs[variable] == '')):
|
|
|
- if variable_config.required:
|
|
|
- raise ValueError(f"{variable} is required in input form")
|
|
|
- else:
|
|
|
- filtered_inputs[variable] = variable_config.default if variable_config.default is not None else ""
|
|
|
- continue
|
|
|
-
|
|
|
- value = user_inputs[variable]
|
|
|
-
|
|
|
- if value is not None:
|
|
|
- if variable_config.type != VariableEntity.Type.NUMBER and not isinstance(value, str):
|
|
|
- raise ValueError(f"{variable} in input form must be a string")
|
|
|
- elif variable_config.type == VariableEntity.Type.NUMBER and isinstance(value, str):
|
|
|
- if '.' in value:
|
|
|
- value = float(value)
|
|
|
- else:
|
|
|
- value = int(value)
|
|
|
-
|
|
|
- if variable_config.type == VariableEntity.Type.SELECT:
|
|
|
- options = variable_config.options if variable_config.options is not None else []
|
|
|
- if value not in options:
|
|
|
- raise ValueError(f"{variable} in input form must be one of the following: {options}")
|
|
|
- elif variable_config.type in [VariableEntity.Type.TEXT_INPUT, VariableEntity.Type.PARAGRAPH]:
|
|
|
- if variable_config.max_length is not None:
|
|
|
- max_length = variable_config.max_length
|
|
|
- if len(value) > max_length:
|
|
|
- raise ValueError(f'{variable} in input form must be less than {max_length} characters')
|
|
|
-
|
|
|
- if value and isinstance(value, str):
|
|
|
- filtered_inputs[variable] = value.replace('\x00', '')
|
|
|
- else:
|
|
|
- filtered_inputs[variable] = value if value is not None else None
|
|
|
-
|
|
|
+ filtered_inputs = {var.name: self._validate_input(inputs=user_inputs, var=var) for var in variables}
|
|
|
+ filtered_inputs = {k: self._sanitize_value(v) for k, v in filtered_inputs.items()}
|
|
|
return filtered_inputs
|
|
|
|
|
|
+ def _validate_input(self, *, inputs: Mapping[str, Any], var: VariableEntity):
|
|
|
+ user_input_value = inputs.get(var.name)
|
|
|
+ if var.required and not user_input_value:
|
|
|
+ raise ValueError(f'{var.name} is required in input form')
|
|
|
+ if not var.required and not user_input_value:
|
|
|
+ # TODO: should we return None here if the default value is None?
|
|
|
+ return var.default or ''
|
|
|
+ if (
|
|
|
+ var.type
|
|
|
+ in (
|
|
|
+ VariableEntity.Type.TEXT_INPUT,
|
|
|
+ VariableEntity.Type.SELECT,
|
|
|
+ VariableEntity.Type.PARAGRAPH,
|
|
|
+ )
|
|
|
+ and user_input_value
|
|
|
+ and not isinstance(user_input_value, str)
|
|
|
+ ):
|
|
|
+ raise ValueError(f"(type '{var.type}') {var.name} in input form must be a string")
|
|
|
+ if var.type == VariableEntity.Type.NUMBER and isinstance(user_input_value, str):
|
|
|
+ # may raise ValueError if user_input_value is not a valid number
|
|
|
+ try:
|
|
|
+ if '.' in user_input_value:
|
|
|
+ return float(user_input_value)
|
|
|
+ else:
|
|
|
+ return int(user_input_value)
|
|
|
+ except ValueError:
|
|
|
+ raise ValueError(f"{var.name} in input form must be a valid number")
|
|
|
+ if var.type == VariableEntity.Type.SELECT:
|
|
|
+ options = var.options or []
|
|
|
+ if user_input_value not in options:
|
|
|
+ raise ValueError(f'{var.name} in input form must be one of the following: {options}')
|
|
|
+ elif var.type in (VariableEntity.Type.TEXT_INPUT, VariableEntity.Type.PARAGRAPH):
|
|
|
+ if var.max_length and user_input_value and len(user_input_value) > var.max_length:
|
|
|
+ raise ValueError(f'{var.name} in input form must be less than {var.max_length} characters')
|
|
|
+
|
|
|
+ return user_input_value
|
|
|
+
|
|
|
+ def _sanitize_value(self, value: Any) -> Any:
|
|
|
+ if isinstance(value, str):
|
|
|
+ return value.replace('\x00', '')
|
|
|
+ return value
|