Source code for papyrus.renderers

from six import BytesIO

import geojson

from six import string_types
from papyrus.geojsonencoder import dumps
from papyrus.xsd import XSDGenerator


[docs]class GeoJSON(object): """ GeoJSON renderer. This class is actually a renderer factory helper, implemented in the same way as Pyramid's JSONP renderer. Configure a GeoJSON renderer using the ``add_renderer`` method on the Configurator object: .. code-block:: python from papyrus.renderers import GeoJSON config.add_renderer('geojson', GeoJSON()) Once this renderer has been registered as above , you can use ``geojson`` as the ``renderer`` parameter to ``@view_config`` or to the ``add_view`` method on the Configurator object: .. code-block:: python @view_config(renderer='geojson') def myview(request): return Feature(id=1, geometry=Point(1, 2), properties=dict(foo='bar')) The GeoJSON renderer supports `JSONP <http://en.wikipedia.org/wiki/JSONP>`_: - If there is a parameter in the request's HTTP query string that matches the ``jsonp_param_name`` of the registered JSONP renderer (by default, ``callback``), the renderer will return a JSONP response. - If there is no callback parameter in the request's query string, the renderer will return a 'plain' JSON response. By default the renderer treats lists and tuples as feature collections. If you want lists and tuples to be treated as geometry collections, set ``collection_type`` to ``'GeometryCollection'``: .. code-block:: python config.add_renderer( 'geojson', GeoJSON(collection_type='GeometryCollection') """ def __init__(self, jsonp_param_name='callback', collection_type=geojson.factory.FeatureCollection): self.jsonp_param_name = jsonp_param_name if isinstance(collection_type, string_types): collection_type = getattr(geojson.factory, collection_type) self.collection_type = collection_type def __call__(self, info): def _render(value, system): if isinstance(value, (list, tuple)): value = self.collection_type(value) ret = dumps(value) request = system.get('request') if request is not None: response = request.response ct = response.content_type if ct == response.default_content_type: callback = request.params.get(self.jsonp_param_name) if callback is None: response.content_type = 'application/json' else: response.content_type = 'text/javascript' ret = ('%(callback)s(%(json)s);' % {'callback': callback, 'json': ret}) return ret return _render
[docs]class XSD(object): """ XSD renderer. An XSD renderer generate an XML schema document from an SQLAlchemy Table object. Configure a XSD renderer using the ``add_renderer`` method on the Configurator object: .. code-block:: python from papyrus.renderers import XSD config.add_renderer('xsd', XSD()) Once this renderer has been registered as above , you can use ``xsd`` as the ``renderer`` parameter to ``@view_config`` or to the ``add_view`` method on the Configurator object: .. code-block:: python from myapp.models import Spot @view_config(renderer='xsd') def myview(request): return Spot By default, the XSD renderer will skip columns which are primary keys or foreign keys. If you wish to include primary keys then pass ``include_primary_keys=True`` when creating the XSD object, for example: .. code-block:: python from papyrus.renderers import XSD config.add_renderer('xsd', XSD(include_primary_keys=True)) If you wish to include foreign keys then pass ``include_foreign_keys=True`` when creating the XSD object, for example: .. code-block:: python from papyrus.renderers import XSD config.add_renderer('xsd', XSD(include_foreign_keys=True)) The XSD renderer adds ``xsd:element`` nodes for the column properties it finds in the class. The XSD renderer will ignore other property types. For example it will ignore relationship properties and association proxies. If you want to add ``xsd:element`` nodes for other elements in the class then use a ``sequence_callback``. For example: .. code-block: python from papyrus.renderers import XSD from papyrus.xsd import tag def callback(tb, cls): attrs = {} attrs['minOccurs'] = str(0) attrs['nillable'] = 'true' attrs['name'] = 'property_name' with tag(tb, 'xsd:element', attrs) as tb: with tag(tb, 'xsd:simpleType') as tb: with tag(tb, 'xsd:restriction', {'base': 'xsd:string'}) as tb: for enum in ('male', 'female'): with tag(tb, 'xsd:enumeration', {'value': enum}): pass config.add_renderer('xsd', XSD(sequence_callback=callback)) The callback receives an ``xml.etree.ElementTree.TreeBuilder`` object and the mapped class being serialized. """ def __init__(self, include_primary_keys=False, include_foreign_keys=False, sequence_callback=None): self.generator = XSDGenerator( include_primary_keys=include_primary_keys, include_foreign_keys=include_foreign_keys, sequence_callback=sequence_callback ) def __call__(self, table): def _render(cls, system): request = system.get('request') if request is not None: response = request.response response.content_type = 'application/xml' io = self.generator.get_class_xsd(BytesIO(), cls) return io.getvalue() return _render