cubicweb/pyramid/resources.py
author Denis Laxalde <denis.laxalde@logilab.fr>
Mon, 20 Mar 2017 17:38:43 +0100
branch3.24
changeset 12077 e282711ac6b2
parent 11820 ec612abc2e2e
child 11967 83739be20fab
permissions -rw-r--r--
Added tag 3.24.7, debian/3.24.7-1, centos/3.24.7-1 for changeset 58f1e8545a77

"""Contains resources classes.
"""
from six import text_type

from rql import TypeResolverException

from pyramid.decorator import reify
from pyramid.httpexceptions import HTTPNotFound


class EntityResource(object):

    """A resource class for an entity. It provide method to retrieve an entity
    by eid.
    """

    @classmethod
    def from_eid(cls):
        def factory(request):
            return cls(request, None, None, request.matchdict['eid'])
        return factory

    def __init__(self, request, cls, attrname, value):
        self.request = request
        self.cls = cls
        self.attrname = attrname
        self.value = value

    @reify
    def rset(self):
        req = self.request.cw_request
        if self.cls is None:
            return req.execute('Any X WHERE X eid %(x)s',
                               {'x': int(self.value)})
        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 = req.execute(st.as_string(), {'x': int(self.value)})
            except (ValueError, TypeResolverException):
                # conflicting eid/type
                raise HTTPNotFound()
        else:
            rset = req.execute(st.as_string(), {'x': text_type(self.value)})
        return rset


class ETypeResource(object):

    """A resource for etype.
    """
    @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):
        # Try eid first, then rest attribute as for URL path evaluation
        # mecanism in cubicweb.web.views.urlpublishing.
        for attrname in ('eid', self.cls.cw_rest_attr_info()[0]):
            resource = EntityResource(self.request, self.cls, attrname, value)
            try:
                rset = resource.rset
            except HTTPNotFound:
                continue
            if rset.rowcount:
                return resource
        raise KeyError(value)

    @reify
    def rset(self):
        rql = self.cls.fetch_rql(self.request.cw_cnx.user)
        rset = self.request.cw_request.execute(rql)
        return rset