[responses] html and plaintext return types as ret_type argument

This commit is contained in:
Maxime Alves LIRMM 2022-08-18 20:19:36 +02:00
parent 5d1b88daca
commit 53a691d985
8 changed files with 58 additions and 6 deletions

View File

@ -1,5 +1,11 @@
# HalfAPI
## 0.7.0-rc0
- Add *html* return type as default argument ret_type
- Add *txt* return type
## 0.6.21
- Store only domain's config in halfapi['config']

View File

@ -1,5 +1,5 @@
#!/usr/bin/env python3
__version__ = '0.6.21'
__version__ = '0.6.22-rc0'
def version():
return f'HalfAPI version:{__version__}'

View File

@ -16,7 +16,7 @@ import yaml
from starlette.exceptions import HTTPException
from halfapi.lib import acl
from halfapi.lib.responses import ORJSONResponse, ODSResponse, XLSXResponse
from halfapi.lib.responses import ORJSONResponse, ODSResponse, XLSXResponse, PlainTextResponse, HTMLResponse
# from halfapi.lib.router import read_router
from halfapi.lib.constants import VERBS
@ -59,6 +59,11 @@ def route_decorator(fct: FunctionType, ret_type: str = 'json') -> Coroutine:
@acl.args_check
async def wrapped(request, *args, **kwargs):
fct_args_spec = inspect.getfullargspec(fct).args
fct_args_defaults = inspect.getfullargspec(fct).defaults or []
fct_args_defaults_dict = {}
for i in range(len(fct_args_defaults)):
fct_args_defaults_dict[fct_args_spec[-i]] = fct_args_defaults[-i]
fct_args = request.path_params.copy()
if 'halfapi' in fct_args_spec:
@ -76,9 +81,11 @@ def route_decorator(fct: FunctionType, ret_type: str = 'json') -> Coroutine:
if 'out' in fct_args_spec:
fct_args['out'] = kwargs.get('out')
""" If format argument is specified (either by get or by post param)
""" If format argument is specified (either by get, post param or function argument)
"""
if 'ret_type' in fct_args_defaults_dict:
ret_type = fct_args_defaults_dict['ret_type']
else:
ret_type = fct_args.get('data', {}).get('format', 'json')
try:
@ -101,6 +108,19 @@ def route_decorator(fct: FunctionType, ret_type: str = 'json') -> Coroutine:
return XLSXResponse(res)
if ret_type in ['html', 'xhtml']:
res = fct(**fct_args)
assert isinstance(res, str)
return HTMLResponse(res)
if ret_type in 'txt':
res = fct(**fct_args)
assert isinstance(res, str)
return PlainTextResponse(res)
raise NotImplementedError
except NotImplementedError as exc:

View File

@ -23,7 +23,7 @@ from io import BytesIO
import orjson
# asgi framework
from starlette.responses import PlainTextResponse, Response, JSONResponse
from starlette.responses import PlainTextResponse, Response, JSONResponse, HTMLResponse
from .user import JWTUser, Nobody
from ..logging import logger

View File

@ -1,9 +1,11 @@
import pytest
from click.testing import CliRunner
from halfapi.cli.cli import cli
import os
from unittest.mock import patch
@pytest.mark.skip
def test_run_noproject(cli_runner):
with cli_runner.isolated_filesystem():
result = cli_runner.invoke(cli, ['config'])

View File

@ -0,0 +1,13 @@
from halfapi.lib import acl
ACLS = {
'GET': [{'acl':acl.public}]
}
def get(ret_type='html'):
"""
responses:
200:
description: dummy abc.alphabet route
"""
return '\n'.join(('trololo', '', 'ololotr'))

View File

@ -0,0 +1,4 @@
from . import get
def test_get():
assert isinstance(get(), str)

View File

@ -1,3 +1,4 @@
import pytest
from halfapi.testing.test_domain import TestDomain
from pprint import pprint
@ -13,3 +14,9 @@ class TestDummyDomain(TestDomain):
def test_routes(self):
self.check_routes()
def test_html_route(self):
res = self.client.get('/ret_type')
assert res.status_code == 200
assert isinstance(res.content.decode(), str)
assert res.headers['content-type'].split(';')[0] == 'text/html'