add file handling

This commit is contained in:
axolotle 2023-01-11 14:10:27 +01:00
parent d677cf5eac
commit ec499b3438
2 changed files with 41 additions and 19 deletions

View file

@ -4,6 +4,8 @@ from __future__ import (
import inspect
import re
import codecs
import fastapi
import pydantic
import starlette
@ -132,12 +134,17 @@ class Interface(BaseInterface):
else ... # required
)
if param.name in paths:
param_default = fastapi.Path(param_default, **param_kwargs)
if param_kwargs.pop("file", False):
new_param = param.replace(
annotation=fastapi.UploadFile,
default=param_default
)
elif param.name in paths:
new_param = param.replace(default=fastapi.Path(param_default, **param_kwargs))
else:
param_default = fastapi.Query(param_default, **param_kwargs)
new_param = param.replace(default=fastapi.Query(param_default, **param_kwargs))
override_params.append(param.replace(default=param_default))
override_params.append(new_param)
def hook_results(*args, **kwargs):
new_kwargs = {}
@ -147,6 +154,10 @@ class Interface(BaseInterface):
if isinstance(value, pydantic.BaseModel):
# Turn pydantic model back to individual kwargs
new_kwargs = value.dict() | new_kwargs
elif isinstance(value, starlette.datastructures.UploadFile):
# views expects a opened file (fastapi UploadFile is a bytes SpooledTemporaryFile)
new_kwargs[name] = codecs.iterdecode(value.file, 'utf-8')
opened_files.append(name)
else:
new_kwargs[name] = value
@ -158,6 +169,10 @@ class Interface(BaseInterface):
raise fastapi.exceptions.RequestValidationError([ErrorWrapper(ValueError(e.strerror), ("query", "test"))])
except:
raise
finally:
# I guess we need to close the opened file
for kwarg_name in opened_files:
kwargs[kwarg_name].file.close()
route_func = override_function(
func,

View file

@ -17,6 +17,7 @@ from yunohost.interface.base import (
get_params_doc,
override_function,
)
from yunohost.utils.error import YunohostValidationError
def parse_cli_command(command: str) -> tuple[str, list[str]]:
@ -53,31 +54,37 @@ class Interface(BaseInterface):
command, args = parse_cli_command(command_def)
for param in params:
param_default = (
param.default
if not param.default == param.empty
else ... # required
)
param_kwargs = local_data.get(param.name, {})
param_kwargs["help"] = params_doc.get(param.name, None)
if param_kwargs.pop("deprecated", False):
param_kwargs["rich_help_panel"] = "Deprecated Options"
if param.name not in args and not param_kwargs.get("hidden", False):
param_kwargs["prompt"] = True
if param.name == "password":
param_kwargs["confirmation_prompt"] = True
param_kwargs["hide_input"] = True
if param_kwargs.get("prompt", False):
if param.name == "password":
param_kwargs["confirmation_prompt"] = True
param_kwargs["hide_input"] = True
# Populate default param value with typer.Argument|Option
param_default = (
param.default
if not param.default == param.empty
else ... # required
)
if param.name in args:
param_default = typer.Argument(param_default, **param_kwargs)
if param_kwargs.pop("file", False):
new_param = param.replace(
annotation=typer.FileText,
default=param_default
)
elif param.kind == param.VAR_POSITIONAL:
new_param = param
elif param.name in args:
new_param = param.replace(default=typer.Argument(param_default, **param_kwargs))
else:
param_default = typer.Option(param_default, **param_kwargs)
new_param = param.replace(default=typer.Option(param_default, **param_kwargs))
override_params.append(param.replace(default=param_default))
override_params.append(new_param)
def hook_results(*args, **kwargs):
try: