[PATCH jsonschema] Implement attributes of Paginable resource as properties

Denis Laxalde denis.laxalde at logilab.fr
Wed Jun 20 10:01:01 CEST 2018


# HG changeset patch
# User Denis Laxalde <denis.laxalde at logilab.fr>
# Date 1529417258 -7200
#      Tue Jun 19 16:07:38 2018 +0200
# Node ID 62934d2097acdbbe04182b6070b7e87ac6549dbe
# Parent  62523c338920edf7f5b6ccd206cff69f20113ec4
# Available At https://hg.logilab.org/review/cubicweb-jsonschema
#              hg pull https://hg.logilab.org/review/cubicweb-jsonschema -r 62934d2097ac
# EXP-Topic paginable-inheritance-mess
Implement attributes of Paginable resource as properties

I'm getting into trouble while trying to reuse this class in a multiple
inheritance context because the proper __init__ method is never called.
So, let's get rid of __init__ in Paginable and implement 'limit',
'offset' and '_has_next' attributes, previously defined in __init__ as
reified properties. Notice that, since _has_next may be changed (in
paginate() method), we also need a setter for this property.

Accordingly, drop super() calls in resource classes inheriting from
Paginable and mention that this class should be used as a mixin.

diff --git a/cubicweb_jsonschema/resources.py b/cubicweb_jsonschema/resources.py
--- a/cubicweb_jsonschema/resources.py
+++ b/cubicweb_jsonschema/resources.py
@@ -191,27 +191,42 @@ class RootResource(PluggableResource):
 
 
 class Paginable(object):
-    """ A paginable resource"""
-    def __init__(self, request):
-        self.request = request
-        cnx = request.cw_cnx
+    """A paginable resource mixin"""
+
+    @property
+    def _has_next(self):
+        return getattr(self, '__has_next', False)
+
+    @_has_next.setter
+    def _has_next(self, value):
+        setattr(self, '__has_next', value)
+
+    @reify
+    def limit(self):
+        cnx = self.request.cw_cnx
         if cnx is not None:
             default_limit = cnx.property_value('navigation.page-size')
         else:
             default_limit = 40
-        req_limit = request.params.get('limit', default_limit)
-        req_offset = request.params.get('offset', 0)
+        req_value = self.request.params.get('limit', default_limit)
         try:
-            self.limit = int(req_limit)
-            self.offset = int(req_offset)
+            limit = int(req_value)
         except ValueError:
-            detail = 'invalid limit ({}) or offset ({})'.format(
-                req_limit, req_offset)
+            detail = 'invalid limit ({})'.format(req_value)
+            raise json_problem(status=400, detail=detail)
+        if limit < 1:
+            detail = 'invalid limit: {}'.format(limit)
             raise json_problem(status=400, detail=detail)
-        if self.limit < 1:
-            detail = 'invalid limit: {}'.format(self.limit)
+        return limit
+
+    @reify
+    def offset(self):
+        req_value = self.request.params.get('offset', 0)
+        try:
+            return int(req_value)
+        except ValueError:
+            detail = 'invalid offset ({})'.format(req_value)
             raise json_problem(status=400, detail=detail)
-        self._has_next = False
 
     def prev_link(self):
         if self.offset > 0:
@@ -257,7 +272,6 @@ class ETypeResource(Paginable, Pluggable
         return factory
 
     def __init__(self, request, etype, parent=None):
-        super(ETypeResource, self).__init__(request)
         vreg = request.registry['cubicweb.registry']
         self.request = request
         self.etype = vreg.case_insensitive_etypes[etype.lower()]
@@ -395,7 +409,6 @@ class RelatedEntitiesResource(Paginable,
 
     @parent
     def __init__(self, request, rtype, role, **kwargs):
-        super(RelatedEntitiesResource, self).__init__(request)
         self.request = request
         self.rtype = rtype
         self.role = role
diff --git a/test/test_api_misc.py b/test/test_api_misc.py
--- a/test/test_api_misc.py
+++ b/test/test_api_misc.py
@@ -470,7 +470,7 @@ class EntitiesTC(BaseTC):
         errors = res.json_body
         expected = {
             'status': 400,
-            'detail': "invalid limit (foo) or offset (0)",
+            'detail': "invalid limit (foo)",
             'title': 'Bad Request',
         }
         self.assertEqual(errors, expected)


More information about the cubicweb-devel mailing list