cubicweb/pyramid/resources.py
changeset 12911 a17cbf539a69
parent 12567 26744ad37953
equal deleted inserted replaced
12910:c87c3943d6ab 12911:a17cbf539a69
    16 # details.
    16 # details.
    17 #
    17 #
    18 # You should have received a copy of the GNU Lesser General Public License along
    18 # You should have received a copy of the GNU Lesser General Public License along
    19 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
    19 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
    20 
    20 
    21 """Pyramid resource definitions for CubicWeb."""
       
    22 
       
    23 from rql import TypeResolverException
       
    24 
       
    25 from pyramid.decorator import reify
       
    26 from pyramid.httpexceptions import HTTPNotFound
    21 from pyramid.httpexceptions import HTTPNotFound
    27 
    22 
    28 
    23 from cubicweb import rdf
    29 class EntityResource(object):
       
    30 
       
    31     """A resource class for an entity. It provide method to retrieve an entity
       
    32     by eid.
       
    33     """
       
    34 
       
    35     @classmethod
       
    36     def from_eid(cls):
       
    37         def factory(request):
       
    38             return cls(request, None, None, request.matchdict['eid'])
       
    39         return factory
       
    40 
       
    41     def __init__(self, request, cls, attrname, value):
       
    42         self.request = request
       
    43         self.cls = cls
       
    44         self.attrname = attrname
       
    45         self.value = value
       
    46 
       
    47     @reify
       
    48     def rset(self):
       
    49         req = self.request.cw_request
       
    50         if self.cls is None:
       
    51             return req.execute('Any X WHERE X eid %(x)s',
       
    52                                {'x': int(self.value)})
       
    53         st = self.cls.fetch_rqlst(self.request.cw_cnx.user, ordermethod=None)
       
    54         st.add_constant_restriction(st.get_variable('X'), self.attrname,
       
    55                                     'x', 'Substitute')
       
    56         if self.attrname == 'eid':
       
    57             try:
       
    58                 rset = req.execute(st.as_string(), {'x': int(self.value)})
       
    59             except (ValueError, TypeResolverException):
       
    60                 # conflicting eid/type
       
    61                 raise HTTPNotFound()
       
    62         else:
       
    63             rset = req.execute(st.as_string(), {'x': self.value})
       
    64         return rset
       
    65 
    24 
    66 
    25 
    67 class ETypeResource(object):
    26 def negociate_mime_type(request, possible_mimetypes):
       
    27     accepted_headers_by_weight = sorted(
       
    28         request.accept.parsed or [], key=lambda h: h[1], reverse=True
       
    29     )
       
    30     mime_type_negociated = None
       
    31     for parsed_header in accepted_headers_by_weight:
       
    32         accepted_mime_type = parsed_header[0]
       
    33         if accepted_mime_type in possible_mimetypes:
       
    34             mime_type_negociated = accepted_mime_type
       
    35             break
       
    36     return mime_type_negociated
    68 
    37 
    69     """A resource for etype.
       
    70     """
       
    71     @classmethod
       
    72     def from_match(cls, matchname):
       
    73         def factory(request):
       
    74             return cls(request, request.matchdict[matchname])
       
    75         return factory
       
    76 
    38 
    77     def __init__(self, request, etype):
    39 def rdf_context_from_eid(request):
    78         vreg = request.registry['cubicweb.registry']
    40     mime_type = negociate_mime_type(request, rdf.RDF_MIMETYPE_TO_FORMAT)
       
    41     if mime_type is None:
       
    42         raise HTTPNotFound()
       
    43     entity = request.cw_request.entity_from_eid(request.matchdict['eid'])
       
    44     return RDFResource(entity, mime_type)
    79 
    45 
    80         self.request = request
       
    81         self.etype = vreg.case_insensitive_etypes[etype.lower()]
       
    82         self.cls = vreg['etypes'].etype_class(self.etype)
       
    83 
    46 
    84     def __getitem__(self, value):
    47 class RDFResource:
    85         # Try eid first, then rest attribute as for URL path evaluation
    48     def __init__(self, entity, mime_type):
    86         # mecanism in cubicweb.web.views.urlpublishing.
    49         self.entity = entity
    87         for attrname in ('eid', self.cls.cw_rest_attr_info()[0]):
    50         self.mime_type = mime_type
    88             resource = EntityResource(self.request, self.cls, attrname, value)
       
    89             try:
       
    90                 rset = resource.rset
       
    91             except HTTPNotFound:
       
    92                 continue
       
    93             if rset.rowcount:
       
    94                 return resource
       
    95         raise KeyError(value)
       
    96 
       
    97     @reify
       
    98     def rset(self):
       
    99         rql = self.cls.fetch_rql(self.request.cw_cnx.user)
       
   100         rset = self.request.cw_request.execute(rql)
       
   101         return rset