Source code for clld.web.adapters.base
"""Base classes for adapters."""
from __future__ import unicode_literals
from uuid import uuid4
from zope.interface import implementer
from pyramid.response import Response
from pyramid.renderers import render as pyramid_render
from six import text_type
from clldutils.misc import to_binary, slug
from clld import interfaces
[docs]class Renderable(object):
"""Virtual base class for adapters.
Adapters can provide custom behaviour either by specifying a template to use for
rendering, or by overwriting the render method.
"""
name = None
template = None
mimetype = 'text/plain'
extension = None
send_mimetype = None
rel = 'alternate'
content_type_params = None
def __init__(self, obj):
self.obj = obj
@property
def label(self):
return getattr(self, '__label__', self.__class__.__name__)
@property
def charset(self):
return 'utf-8' \
if self.mimetype.startswith('text/') \
or 'xml' in self.mimetype \
or 'kml' in self.mimetype \
else None
def render_to_response(self, ctx, req):
res = Response(self.render(ctx, req))
res.vary = to_binary('Accept')
res.content_type = str(self.send_mimetype or self.mimetype)
if self.charset:
res.content_type += str('; charset=') + str(self.charset)
if self.content_type_params:
d = res.content_type_params
for k, v in self.content_type_params.items():
d[str(k)] = str(v)
res.content_type_params = d
return res
def template_context(self, ctx, req):
return {}
def render(self, ctx, req):
context = self.template_context(ctx, req)
context.setdefault('ctx', ctx)
return pyramid_render(self.template, context, request=req)
[docs]@implementer(interfaces.IRepresentation)
class Representation(Renderable):
"""Base class for adapters implementing IRepresentation."""
class _Json(Renderable):
"""JavaScript Object Notation."""
name = 'JSON'
mimetype = 'application/json'
extension = 'json'
def render(self, ctx, req):
return pyramid_render('json', ctx, request=req)
@implementer(interfaces.IRepresentation)
class Json(_Json):
pass
@implementer(interfaces.IIndex)
class JsonIndex(_Json):
pass
[docs]class SolrDoc(Json):
"""Document for indexing with Solr encoded in JSON."""
name = 'Solr JSON'
send_mimetype = Json.mimetype
mimetype = 'application/vnd.clld.solr+json'
extension = 'solr.json'
def render(self, ctx, req):
return pyramid_render(
'json', ctx.__solr__(req) if hasattr(ctx, '__solr__') else {}, request=req)
[docs]@implementer(interfaces.IIndex)
class Index(Renderable):
"""Base class for adapters implementing IIndex."""
def adapter_factory(*args, **kw):
# for backwards compatibility we interpret the first positional argument as template:
if args:
kw['template'] = args[0]
assert 'template' in kw
kw.setdefault('mimetype', 'text/html')
kw.setdefault('extension', 'html')
base = kw.pop('base', Representation)
return type(str('AdapterFromFactory%s' % slug(text_type(uuid4()))), (base,), kw)