""" 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')