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 |
|