From 7c2e029f6dfa3319f6b3119a267912bff4161a34 Mon Sep 17 00:00:00 2001 From: axolotle Date: Fri, 13 Jan 2023 12:27:42 +0100 Subject: [PATCH] add simple pattern validation --- src/interface/api.py | 5 +++++ src/interface/base.py | 14 ++++++++++---- src/interface/cli.py | 17 +++++++++++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/interface/api.py b/src/interface/api.py index b90b01dc0..a658f5874 100644 --- a/src/interface/api.py +++ b/src/interface/api.py @@ -134,6 +134,11 @@ class Interface(BaseInterface): else ... # required ) + pattern = param_kwargs.pop("pattern", None) + if pattern: + # FIXME for now throw generic error (need to catch and update text) + param_kwargs["regex"] = pattern + if param_kwargs.pop("file", False): new_param = param.replace( annotation=fastapi.UploadFile, diff --git a/src/interface/base.py b/src/interface/base.py index 72ecb45a6..e3bbc9c64 100644 --- a/src/interface/base.py +++ b/src/interface/base.py @@ -42,6 +42,12 @@ def get_params_doc(docstring: Optional[str]) -> dict[str, str]: } +def validate_pattern(pattern: str, value: str, name: str): + if not re.match(pattern, value, re.UNICODE): + raise ValueError(f"'{value}' does'nt match pattern '{pattern}'") + return value + + def override_function( func: Callable, func_signature: inspect.Signature, @@ -89,10 +95,10 @@ class BaseInterface: def filter_params(self, params: list[inspect.Parameter]) -> list[inspect.Parameter]: private = self.local_data.get("private", []) - if private: - return [param for param in params if param.name not in private] - - return params + return [ + param for param in params + if param.name not in private and param.name != "operation_logger" + ] def api(self, *args, **kwargs): return pass_func diff --git a/src/interface/cli.py b/src/interface/cli.py index 1bdcff541..91477840a 100644 --- a/src/interface/cli.py +++ b/src/interface/cli.py @@ -17,6 +17,7 @@ from yunohost.interface.base import ( merge_dicts, get_params_doc, override_function, + validate_pattern ) from yunohost.utils.error import YunohostValidationError @@ -31,6 +32,18 @@ def print_as_yaml(data: Any): rprint(Syntax(data, "yaml", background_color="default")) +def pattern_validator(pattern: str, name: str): + def inner_validator(ctx: typer.Context, param_: typer.CallbackParam, value: str): + if ctx.resilient_parsing: + return + try: + return validate_pattern(pattern, value, name) + except ValueError as e: + raise typer.BadParameter(str(e)) + + return inner_validator + + class Interface(BaseInterface): kind = InterfaceKind.CLI instance: typer.Typer @@ -89,6 +102,10 @@ class Interface(BaseInterface): param_kwargs["confirmation_prompt"] = True param_kwargs["hide_input"] = True + pattern = param_kwargs.pop("pattern", None) + if pattern: + param_kwargs["callback"] = pattern_validator(pattern, param.name) + # Populate default param value with typer.Argument|Option if param_kwargs.pop("file", False): new_param = param.replace(