wsme/wsmeext/pecan.py
Chris Dent 1440eeb13b Fix (some) tests for modern flask and pep8
Somewhere along the way, WSME and flask/werkzeug have got out of sync
and tests have started failing. Since there aren't regular contributions
to WSME we don't catch these changes, so this may have happened months
or years ago.

I have adjusted tests to attempt to account for what I can, but one test
fails to work so I have marked it as an xfail. It works correctly with
werkzeug 1.13.x but not later. Since WSME is in something worse than
maintenance mode, I'm not inclined to fix this.

pep8/flake8 in python3 is more strict than python. The gate now
runs the pep8 jobs using python3 by default, so the local jobs
should as well. This changes the job and also fixes the new problems it
points out.

There are other failures, but they are present in master as well, so
leaving that for other changes.

Change-Id: I57ae0405e0d6ddba0bb1dac93020fb08a0fc7c89
2018-04-09 13:24:20 +01:00

143 lines
4.3 KiB
Python

from __future__ import absolute_import
import functools
import inspect
import sys
import wsme
import wsme.rest.args
import wsme.rest.json
import wsme.rest.xml
import pecan
from wsme.utils import is_valid_code
class JSonRenderer(object):
@staticmethod
def __init__(path, extra_vars):
pass
@staticmethod
def render(template_path, namespace):
if 'faultcode' in namespace:
return wsme.rest.json.encode_error(None, namespace)
return wsme.rest.json.encode_result(
namespace['result'],
namespace['datatype']
)
class XMLRenderer(object):
@staticmethod
def __init__(path, extra_vars):
pass
@staticmethod
def render(template_path, namespace):
if 'faultcode' in namespace:
return wsme.rest.xml.encode_error(None, namespace)
return wsme.rest.xml.encode_result(
namespace['result'],
namespace['datatype']
)
pecan.templating._builtin_renderers['wsmejson'] = JSonRenderer
pecan.templating._builtin_renderers['wsmexml'] = XMLRenderer
pecan_json_decorate = pecan.expose(
template='wsmejson:',
content_type='application/json',
generic=False)
pecan_xml_decorate = pecan.expose(
template='wsmexml:',
content_type='application/xml',
generic=False
)
pecan_text_xml_decorate = pecan.expose(
template='wsmexml:',
content_type='text/xml',
generic=False
)
def wsexpose(*args, **kwargs):
sig = wsme.signature(*args, **kwargs)
def decorate(f):
sig(f)
funcdef = wsme.api.FunctionDefinition.get(f)
funcdef.resolve_types(wsme.types.registry)
@functools.wraps(f)
def callfunction(self, *args, **kwargs):
return_type = funcdef.return_type
try:
args, kwargs = wsme.rest.args.get_args(
funcdef, args, kwargs, pecan.request.params, None,
pecan.request.body, pecan.request.content_type
)
if funcdef.pass_request:
kwargs[funcdef.pass_request] = pecan.request
result = f(self, *args, **kwargs)
# NOTE: Support setting of status_code with default 201
pecan.response.status = funcdef.status_code
if isinstance(result, wsme.api.Response):
pecan.response.status = result.status_code
# NOTE(lucasagomes): If the return code is 204
# (No Response) we have to make sure that we are not
# returning anything in the body response and the
# content-length is 0
if result.status_code == 204:
return_type = None
elif not isinstance(result.return_type,
wsme.types.UnsetType):
return_type = result.return_type
result = result.obj
except Exception:
try:
exception_info = sys.exc_info()
orig_exception = exception_info[1]
orig_code = getattr(orig_exception, 'code', None)
data = wsme.api.format_exception(
exception_info,
pecan.conf.get('wsme', {}).get('debug', False)
)
finally:
del exception_info
if orig_code and is_valid_code(orig_code):
pecan.response.status = orig_code
else:
pecan.response.status = 500
return data
if return_type is None:
pecan.request.pecan['content_type'] = None
pecan.response.content_type = None
return ''
return dict(
datatype=return_type,
result=result
)
if 'xml' in funcdef.rest_content_types:
pecan_xml_decorate(callfunction)
pecan_text_xml_decorate(callfunction)
if 'json' in funcdef.rest_content_types:
pecan_json_decorate(callfunction)
pecan.util._cfg(callfunction)['argspec'] = inspect.getargspec(f)
callfunction._wsme_definition = funcdef
return callfunction
return decorate