62725bb773
Change-Id: I35efe85794e761877edd06722952292a3cac5d85
169 lines
5.3 KiB
Python
169 lines
5.3 KiB
Python
"""
|
|
WSME for cornice
|
|
|
|
|
|
Activate it::
|
|
|
|
config.include('wsme.cornice')
|
|
|
|
|
|
And use it::
|
|
|
|
@hello.get()
|
|
@wsexpose(Message, wsme.types.text)
|
|
def get_hello(who=u'World'):
|
|
return Message(text='Hello %s' % who)
|
|
"""
|
|
from __future__ import absolute_import
|
|
|
|
import inspect
|
|
import sys
|
|
|
|
import wsme
|
|
from wsme.rest import json as restjson
|
|
from wsme.rest import xml as restxml
|
|
import wsme.runtime
|
|
import wsme.api
|
|
import functools
|
|
|
|
from wsme.rest.args import (
|
|
args_from_args, args_from_params, args_from_body, combine_args
|
|
)
|
|
|
|
|
|
class WSMEJsonRenderer(object):
|
|
def __init__(self, info):
|
|
pass
|
|
|
|
def __call__(self, data, context):
|
|
response = context['request'].response
|
|
response.content_type = 'application/json'
|
|
if 'faultcode' in data:
|
|
if 'orig_code' in data:
|
|
response.status_code = data['orig_code']
|
|
elif data['faultcode'] == 'Client':
|
|
response.status_code = 400
|
|
else:
|
|
response.status_code = 500
|
|
return restjson.encode_error(None, data)
|
|
obj = data['result']
|
|
if isinstance(obj, wsme.api.Response):
|
|
response.status_code = obj.status_code
|
|
if obj.error:
|
|
return restjson.encode_error(None, obj.error)
|
|
obj = obj.obj
|
|
return restjson.encode_result(obj, data['datatype'])
|
|
|
|
|
|
class WSMEXmlRenderer(object):
|
|
def __init__(self, info):
|
|
pass
|
|
|
|
def __call__(self, data, context):
|
|
response = context['request'].response
|
|
if 'faultcode' in data:
|
|
if data['faultcode'] == 'Client':
|
|
response.status_code = 400
|
|
else:
|
|
response.status_code = 500
|
|
return restxml.encode_error(None, data)
|
|
response.content_type = 'text/xml'
|
|
return restxml.encode_result(data['result'], data['datatype'])
|
|
|
|
|
|
def get_outputformat(request):
|
|
df = None
|
|
if 'Accept' in request.headers:
|
|
if 'application/json' in request.headers['Accept']:
|
|
df = 'json'
|
|
elif 'text/xml' in request.headers['Accept']:
|
|
df = 'xml'
|
|
if df is None and 'Content-Type' in request.headers:
|
|
if 'application/json' in request.headers['Content-Type']:
|
|
df = 'json'
|
|
elif 'text/xml' in request.headers['Content-Type']:
|
|
df = 'xml'
|
|
return df if df else 'json'
|
|
|
|
|
|
def signature(*args, **kwargs):
|
|
sig = wsme.signature(*args, **kwargs)
|
|
|
|
def decorate(f):
|
|
args = inspect.getargspec(f)[0]
|
|
with_self = args[0] == 'self' if args else False
|
|
f = sig(f)
|
|
funcdef = wsme.api.FunctionDefinition.get(f)
|
|
funcdef.resolve_types(wsme.types.registry)
|
|
|
|
@functools.wraps(f)
|
|
def callfunction(*args):
|
|
if with_self:
|
|
if len(args) == 1:
|
|
self = args[0]
|
|
request = self.request
|
|
elif len(args) == 2:
|
|
self, request = args
|
|
else:
|
|
raise ValueError("Cannot do anything with these arguments")
|
|
else:
|
|
request = args[0]
|
|
request.override_renderer = 'wsme' + get_outputformat(request)
|
|
try:
|
|
args, kwargs = combine_args(funcdef, (
|
|
args_from_args(funcdef, (), request.matchdict),
|
|
args_from_params(funcdef, request.params),
|
|
args_from_body(funcdef, request.body, request.content_type)
|
|
))
|
|
wsme.runtime.check_arguments(funcdef, args, kwargs)
|
|
if funcdef.pass_request:
|
|
kwargs[funcdef.pass_request] = request
|
|
if with_self:
|
|
args.insert(0, self)
|
|
|
|
result = f(*args, **kwargs)
|
|
return {
|
|
'datatype': funcdef.return_type,
|
|
'result': result
|
|
}
|
|
except:
|
|
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)
|
|
if orig_code is not None:
|
|
data['orig_code'] = orig_code
|
|
return data
|
|
finally:
|
|
del exception_info
|
|
|
|
callfunction.wsme_func = f
|
|
return callfunction
|
|
return decorate
|
|
|
|
|
|
def scan_api(root=None):
|
|
from cornice.service import get_services
|
|
for service in get_services():
|
|
for method, func, options in service.definitions:
|
|
wsme_func = getattr(func, 'wsme_func')
|
|
basepath = service.path.split('/')
|
|
if basepath and not basepath[0]:
|
|
del basepath[0]
|
|
if wsme_func:
|
|
yield (
|
|
basepath + [method.lower()],
|
|
wsme_func._wsme_definition
|
|
)
|
|
|
|
|
|
def includeme(config):
|
|
import pyramid.wsgi
|
|
wsroot = wsme.WSRoot(scan_api=scan_api, webpath='/ws')
|
|
wsroot.addprotocol('extdirect')
|
|
config.add_renderer('wsmejson', WSMEJsonRenderer)
|
|
config.add_renderer('wsmexml', WSMEXmlRenderer)
|
|
config.add_route('wsme', '/ws/*path')
|
|
config.add_view(pyramid.wsgi.wsgiapp(wsroot.wsgiapp()), route_name='wsme')
|