Allow adapters to use the format_exception function, and use it in the Pecan adapter. /\!\ the response status is not properly changed by the decorator yet.

This commit is contained in:
Christophe de Vienne 2012-12-06 16:51:51 +01:00
parent bd95dafa7b
commit 4edbd4bb8f
3 changed files with 54 additions and 32 deletions

View File

@ -1,5 +1,11 @@
import traceback
import functools
import inspect
import logging
import wsme.exc
log = logging.getLogger(__name__)
def iswsmefunction(f):
@ -130,3 +136,27 @@ class signature(object):
return func
sig = signature
def format_exception(excinfo, debug=False):
"""Extract informations that can be sent to the client."""
error = excinfo[1]
if isinstance(error, wsme.exc.ClientSideError):
r = dict(faultcode="Client",
faultstring=error.faultstring)
log.warning("Client-side error: %s" % r['faultstring'])
r['debuginfo'] = None
return r
else:
faultstring = str(error)
debuginfo = "\n".join(traceback.format_exception(*excinfo))
log.error('Server-side error: "%s". Detail: \n%s' % (
faultstring, debuginfo))
r = dict(faultcode="Server", faultstring=faultstring)
if debug:
r['debuginfo'] = debuginfo
else:
r['debuginfo'] = None
return r

View File

@ -1,3 +1,5 @@
from __future__ import absolute_import
import inspect
import sys
@ -6,7 +8,7 @@ import wsme.rest.args
import wsme.rest.json
import wsme.rest.xml
pecan = sys.modules['pecan']
import pecan
class JSonRenderer(object):
@ -14,6 +16,8 @@ class JSonRenderer(object):
pass
def render(self, 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']
@ -25,6 +29,8 @@ class XMLRenderer(object):
pass
def render(self, 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']
@ -52,11 +58,20 @@ def wsexpose(*args, **kwargs):
funcdef.resolve_types(wsme.types.registry)
def callfunction(self, *args, **kwargs):
args, kwargs = wsme.rest.args.get_args(
funcdef, args, kwargs,
pecan.request.body, pecan.request.content_type
)
result = f(self, *args, **kwargs)
try:
args, kwargs = wsme.rest.args.get_args(
funcdef, args, kwargs,
pecan.request.body, pecan.request.content_type
)
result = f(self, *args, **kwargs)
except:
data = wsme.api.format_exception(sys.exc_info())
if data['faultcode'] == 'Client':
pecan.response.status = 400
else:
pecan.response.status = 500
return data
return dict(
datatype=funcdef.return_type,
result=result

View File

@ -1,6 +1,5 @@
import logging
import sys
import traceback
import weakref
from six import u, b
@ -12,6 +11,7 @@ from wsme.exc import ClientSideError, MissingArgument, UnknownFunction
from wsme.protocol import getprotocol
from wsme.rest import scan_api
from wsme import spore
import wsme.api
import wsme.types
log = logging.getLogger(__name__)
@ -200,7 +200,7 @@ class WSRoot(object):
except Exception:
e = sys.exc_info()[1]
infos = self._format_exception(sys.exc_info())
infos = wsme.api.format_exception(sys.exc_info(), self._debug)
if isinstance(e, ClientSideError):
request.client_errorcount += 1
else:
@ -292,7 +292,7 @@ class WSRoot(object):
res.status = protocol.get_response_status(request)
res_content_type = protocol.get_response_contenttype(request)
except Exception:
infos = self._format_exception(sys.exc_info())
infos = wsme.api.format_exception(sys.exc_info(), self._debug)
request.server_errorcount += 1
res.text = protocol.encode_error(context, infos)
res.status = 500
@ -325,29 +325,6 @@ class WSRoot(object):
return f, fdef, args
raise UnknownFunction('/'.join(path))
def _format_exception(self, excinfo):
"""Extract informations that can be sent to the client."""
error = excinfo[1]
if isinstance(error, ClientSideError):
r = dict(faultcode="Client",
faultstring=error.faultstring)
log.warning("Client-side error: %s" % r['faultstring'])
r['debuginfo'] = None
return r
else:
faultstring = str(error)
debuginfo = "\n".join(traceback.format_exception(*excinfo))
log.error('Server-side error: "%s". Detail: \n%s' % (
faultstring, debuginfo))
r = dict(faultcode="Server", faultstring=faultstring)
if self._debug:
r['debuginfo'] = debuginfo
else:
r['debuginfo'] = None
return r
def _html_format(self, content, content_types):
try:
from pygments import highlight