class TornadoTemplateProvider(ProviderBase): """Default provider for `text/html`.""" CONTENT_TYPE = ContentType(MediaType.TextHtml) def provide(self, model, handler, **kwargs): """Render a template with the given model into HTML. By default we will use the tornado built in template language.""" try: model.validate() handler.render(handler.get_template(model), **model.to_primitive()) except ModelValidationError as e: e.messages = {"result_model": e.messages} raise HTTPError(500, reason=json.dumps(e.messages)) def error(self, status_code, message, handler): """Simply return errors in html .. seealso:: :py:mod:`supercell.api.provider.ProviderBase.error` """ handler.finish("<html><title>%(code)d: %(message)s</title>" "<body>%(code)d: %(message)s</body></html>" % { "code": status_code, "message": message, })
def map_consumer(content_type, handler): """Map a given content type to the correct provider implementation. If no provider matches, raise a `NoProviderFound` exception. :param accept_header: HTTP Accept header value :type accept_header: str :param handler: supercell request handler :raises: :exc:`NoConsumerFound` """ accept = parse_accept_header(content_type) if len(accept) == 0: raise NoConsumerFound() (ctype, params, q) = accept[0] if ctype not in handler._CONS_CONTENT_TYPES: raise NoConsumerFound() c = ContentType(ctype, vendor=params.get('vendor', None), version=params.get('version', None)) if c not in handler._CONS_CONTENT_TYPES[ctype]: raise NoConsumerFound() known_types = [ t for t in ConsumerMeta.KNOWN_CONTENT_TYPES[ctype] if t[0] == c ] if len(known_types) == 1: return (handler._CONS_MODEL[c], known_types[0][1]) raise NoConsumerFound()
class JsonProvider(ProviderBase): """Default `application/json` provider.""" CONTENT_TYPE = ContentType(MediaType.ApplicationJson) def provide(self, model, handler): """Simply return the json via `json.dumps`. .. seealso:: :py:mod:`supercell.api.provider.ProviderBase.provide` """ try: model.validate() handler.write(model.to_primitive()) except ModelValidationError as e: e.messages = {"result_model": e.messages} raise HTTPError(500, reason=json.dumps(e.messages)) def error(self, status_code, message, handler): """Simply return errors in json. .. seealso:: :py:mod:`supercell.api.provider.ProviderBase.error` """ try: message = json.loads(message) except ValueError: pass res = {"message": message, "error": True} handler.set_header('Content-Type', MediaType.ApplicationJson) handler.finish(escape.json_encode(res))
class TornadoTemplateProvider(ProviderBase): """Default provider for `text/html`.""" CONTENT_TYPE = ContentType(MediaType.TextHtml) def provide(self, model, handler): """Render a template with the given model into HTML. By default we will use the tornado built in template language.""" model.validate() handler.render(handler.get_template(model), **model.to_primitive())
class JsonProvider(ProviderBase): """Default `application/json` provider.""" CONTENT_TYPE = ContentType(MediaType.ApplicationJson) def provide(self, model, handler): """Simply return the json via `json.dumps`. .. seealso:: :py:mod:`supercell.api.provider.ProviderBase.provide` """ model.validate() handler.write(model.to_primitive())
def map_provider(accept_header, handler, allow_default=False): """Map a given content type to the correct provider implementation. If no provider matches, raise a `NoProviderFound` exception. :param accept_header: HTTP Accept header value :type accept_header: str :param handler: supercell request handler :param allow_default: allow usage of default provider if no accept header is set, default is False :type allow_default: bool :raises: :exc:`NoProviderFound` :return: A tuple of the matching provider implementation class and the provide()-kwargs :rtype: (supercell.api.provider.ProviderBase, dict) """ if not hasattr(handler, '_PROD_CONTENT_TYPES'): raise NoProviderFound() accept = parse_accept_header(accept_header) if len(accept) > 0: for (ctype, params, q) in accept: if ctype not in handler._PROD_CONTENT_TYPES: continue c = ContentType(ctype, vendor=params.get('vendor', None), version=params.get('version', None)) if c not in handler._PROD_CONTENT_TYPES[ctype]: continue known_types = [t for t in ProviderMeta.KNOWN_CONTENT_TYPES[ctype] if t[0] == c] configuration = handler._PROD_CONFIGURATION[ctype] if len(known_types) == 1: return (known_types[0][1], configuration) if allow_default and 'default' in handler._PROD_CONTENT_TYPES: content_type = handler._PROD_CONTENT_TYPES['default'] configuration = handler._PROD_CONFIGURATION['default'] ctype = content_type.content_type default_type = [t for t in ProviderMeta.KNOWN_CONTENT_TYPES[ctype] if t[0] == content_type] if len(default_type) == 1: return (default_type[0][1], configuration) raise NoProviderFound()
class JsonConsumer(ConsumerBase): """Default **application/json** provider.""" CONTENT_TYPE = ContentType(MediaType.ApplicationJson) """The **application/json** :class:`ContentType`.""" def consume(self, handler, model): """Parse the body json via :func:`json.loads` and initialize the `model`. .. seealso:: :py:mod:`supercell.api.provider.ProviderBase.provide` """ # TODO error if no request body is set return model(json.loads(handler.request.body.decode('utf8')))
def wrapper(cls): """The real class decorator.""" assert isinstance(cls, type), 'This decorator may only be used as ' + \ 'class decorator' if not hasattr(cls, '_PROD_CONTENT_TYPES'): cls._PROD_CONTENT_TYPES = defaultdict(list) ctype = ContentType(content_type, vendor, version) cls._PROD_CONTENT_TYPES[content_type].append(ctype) if default: assert 'default' not in cls._PROD_CONTENT_TYPES, 'TODO: nice msg' cls._PROD_CONTENT_TYPES['default'] = ctype return cls
def wrapper(cls): """The real decorator.""" assert isinstance(cls, type), 'This decorator may only be used as ' + \ 'class decorator' assert model, 'In order to consume content a schematics model ' + \ 'class has to be given via the model parameter' if not hasattr(cls, '_CONS_CONTENT_TYPES'): cls._CONS_CONTENT_TYPES = defaultdict(list) if not hasattr(cls, '_CONS_MODEL'): cls._CONS_MODEL = dict() ct = ContentType(content_type, vendor, version) cls._CONS_CONTENT_TYPES[content_type].append(ct) cls._CONS_MODEL[ct] = model return cls
def map_provider(accept_header, handler, allow_default=False): """Map a given content type to the correct provider implementation. If no provider matches, raise a `NoProviderFound` exception. :param accept_header: HTTP Accept header value :type accept_header: str :param handler: supercell request handler :raises: :exc:`NoProviderFound` """ if not hasattr(handler, '_PROD_CONTENT_TYPES'): raise NoProviderFound() accept = parse_accept_header(accept_header) if len(accept) > 0: for (ctype, params, q) in accept: if ctype not in handler._PROD_CONTENT_TYPES: continue c = ContentType(ctype, vendor=params.get('vendor', None), version=params.get('version', None)) if c not in handler._PROD_CONTENT_TYPES[ctype]: continue known_types = [ t for t in ProviderMeta.KNOWN_CONTENT_TYPES[ctype] if t[0] == c ] if len(known_types) == 1: return known_types[0][1] if 'default' in handler._PROD_CONTENT_TYPES: content_type = handler._PROD_CONTENT_TYPES['default'] ctype = content_type.content_type default_type = [ t for t in ProviderMeta.KNOWN_CONTENT_TYPES[ctype] if t[0] == content_type ] if len(default_type) == 1: return default_type[0][1] raise NoProviderFound()
class JsonProviderWithVendorAndVersion(JsonProvider): CONTENT_TYPE = ContentType(MediaType.ApplicationJson, vendor='supercell', version=1.0)
class MoreDetailedJsonProvider(JsonProvider): CONTENT_TYPE = ContentType(MediaType.ApplicationJson, vendor='supercell')
class JsonPatchConsumer(JsonConsumer): """Default **application/json-patch+json** consumer.""" CONTENT_TYPE = ContentType(MediaType.ApplicationJsonPatch) """The **application/json-patch+json** :class:`ContentType`."""