[routes] Add a 'cwentities' route with traversal
authorChristophe de Vienne <christophe@unlish.com>
Tue, 09 Jun 2015 11:34:17 +0200
changeset 11596 1f2570f1d72a
parent 11595 9ab8c7100fc0
child 11597 286611d1d7a4
[routes] Add a 'cwentities' route with traversal The route uses a factory that produces ETypeResource and EntityResource as a context. A 'delete' view serve as a test and demonstration. The module being experimental, it has to be explicitely included.
pyramid_cubicweb/entities.py
pyramid_cubicweb/tests/test_entities.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pyramid_cubicweb/entities.py	Tue Jun 09 11:34:17 2015 +0200
@@ -0,0 +1,85 @@
+from __future__ import absolute_import
+
+from rql import TypeResolverException
+
+from pyramid.decorator import reify
+from pyramid.httpexceptions import HTTPNotFound
+from pyramid.view import view_config
+
+
+class EntityResource(object):
+    def __init__(self, request, cls, attrname, value):
+        self.request = request
+        self.cls = cls
+        self.attrname = attrname
+        self.value = value
+
+    @reify
+    def rset(self):
+        st = self.cls.fetch_rqlst(self.request.cw_cnx.user, ordermethod=None)
+        st.add_constant_restriction(st.get_variable('X'), self.attrname,
+                                    'x', 'Substitute')
+        if self.attrname == 'eid':
+            try:
+                rset = self.request.cw_cnx.execute(
+                    st.as_string(), {'x': int(self.value)})
+            except (ValueError, TypeResolverException):
+                # conflicting eid/type
+                raise HTTPNotFound()
+        else:
+            rset = self.request.cw_cnx.execute(
+                st.as_string(), {'x': unicode(self.value)})
+        return rset
+
+
+class ETypeResource(object):
+    @classmethod
+    def from_match(cls, matchname):
+        def factory(request):
+            return cls(request, request.matchdict[matchname])
+        return factory
+
+    def __init__(self, request, etype):
+        vreg = request.registry['cubicweb.registry']
+
+        self.request = request
+        self.etype = vreg.case_insensitive_etypes[etype.lower()]
+        self.cls = vreg['etypes'].etype_class(self.etype)
+
+    def __getitem__(self, value):
+        attrname = self.cls.cw_rest_attr_info()[0]
+        return EntityResource(self.request, self.cls, attrname, value)
+
+
+class MatchIsETypePredicate(object):
+    def __init__(self, matchname, config):
+        self.matchname = matchname
+        self.etypes = frozenset(
+            k.lower() for k in config.registry['cubicweb.registry']['etypes'])
+
+    def text(self):
+        return 'match_is_etype = %s' % self.matchname
+
+    phash = text
+
+    def __call__(self, info, request):
+        return info['match'][self.matchname].lower() in \
+            request.registry['cubicweb.registry'].case_insensitive_etypes
+
+
+@view_config(
+    route_name='cwentities',
+    context=EntityResource,
+    request_method='DELETE')
+def delete_entity(context, request):
+    context.rset.one().cw_delete()
+    request.response.status_int = 204
+    return request.response
+
+
+def includeme(config):
+    config.add_route_predicate('match_is_etype', MatchIsETypePredicate)
+    config.add_route(
+        'cwentities', '/{etype}/*traverse',
+        factory=ETypeResource.from_match('etype'), match_is_etype='etype')
+    config.scan(__name__)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pyramid_cubicweb/tests/test_entities.py	Tue Jun 09 11:34:17 2015 +0200
@@ -0,0 +1,20 @@
+from __future__ import absolute_import
+
+from . import PyramidCWTest
+
+
+class EntitiesTest(PyramidCWTest):
+    def includeme(self, config):
+        config.include('pyramid_cubicweb.entities')
+
+    def test_delete(self):
+        with self.admin_access.repo_cnx() as cnx:
+            cnx.create_entity('CWGroup', name=u'tmp')
+            cnx.commit()
+
+        self.login()
+        res = self.webapp.delete('/cwgroup/tmp')
+        self.assertEqual(res.status_int, 204)
+
+        with self.admin_access.repo_cnx() as cnx:
+            self.assertEqual(cnx.find('CWGroup', name=u'tmp').rowcount, 0)