33 |
33 |
34 class PathDontMatch(Exception): |
34 class PathDontMatch(Exception): |
35 """exception used by url evaluators to notify they can't evaluate |
35 """exception used by url evaluators to notify they can't evaluate |
36 a path |
36 a path |
37 """ |
37 """ |
38 |
38 |
39 class URLPublisherComponent(Component): |
39 class URLPublisherComponent(Component): |
40 """associate url's path to view identifier / rql queries, |
40 """associate url's path to view identifier / rql queries, |
41 by applying a chain of urlpathevaluator components. |
41 by applying a chain of urlpathevaluator components. |
42 |
42 |
43 An evaluator is a URLPathEvaluator subclass with a .evaluate_path |
43 An evaluator is a URLPathEvaluator subclass with a .evaluate_path |
48 attribute, with 0 as the greatest priority and greater values as |
48 attribute, with 0 as the greatest priority and greater values as |
49 lower priority. The first evaluator returning a result or raising |
49 lower priority. The first evaluator returning a result or raising |
50 something else than `PathDontMatch` will stop the handlers chain. |
50 something else than `PathDontMatch` will stop the handlers chain. |
51 """ |
51 """ |
52 id = 'urlpublisher' |
52 id = 'urlpublisher' |
53 |
53 |
54 def __init__(self, default_method='view'): |
54 def __init__(self, default_method='view'): |
55 super(URLPublisherComponent, self).__init__() |
55 super(URLPublisherComponent, self).__init__() |
56 self.default_method = default_method |
56 self.default_method = default_method |
57 evaluators = [] |
57 evaluators = [] |
58 for evaluatorcls in self.vreg.registry_objects('components', |
58 for evaluatorcls in self.vreg.registry_objects('components', |
59 'urlpathevaluator'): |
59 'urlpathevaluator'): |
60 # instantiation needed |
60 # instantiation needed |
61 evaluator = evaluatorcls(self) |
61 evaluator = evaluatorcls(self) |
62 evaluators.append(evaluator) |
62 evaluators.append(evaluator) |
63 self.evaluators = sorted(evaluators, key=lambda x: x.priority) |
63 self.evaluators = sorted(evaluators, key=lambda x: x.priority) |
64 |
64 |
65 def process(self, req, path): |
65 def process(self, req, path): |
66 """given an url (essentialy caracterized by a path on the server, |
66 """given an url (essentialy caracterized by a path on the server, |
67 but additional information may be found in the request object), return |
67 but additional information may be found in the request object), return |
68 a publishing method identifier (eg controller) and an optional result |
68 a publishing method identifier (eg controller) and an optional result |
69 set |
69 set |
70 |
70 |
71 :type req: `cubicweb.web.Request` |
71 :type req: `cubicweb.web.Request` |
72 :param req: the request object |
72 :param req: the request object |
73 |
73 |
74 :type path: str |
74 :type path: str |
75 :param path: the path of the resource to publish |
75 :param path: the path of the resource to publish |
76 |
76 |
77 :rtype: tuple(str, `cubicweb.common.utils.ResultSet` or None) |
77 :rtype: tuple(str, `cubicweb.common.utils.ResultSet` or None) |
78 :return: the publishing method identifier and an optional result set |
78 :return: the publishing method identifier and an optional result set |
79 |
79 |
80 :raise NotFound: if no handler is able to decode the given path |
80 :raise NotFound: if no handler is able to decode the given path |
81 """ |
81 """ |
82 parts = [part for part in path.split('/') |
82 parts = [part for part in path.split('/') |
83 if part != ''] or (self.default_method,) |
83 if part != ''] or (self.default_method,) |
84 if req.form.get('rql'): |
84 if req.form.get('rql'): |
147 super(RestPathEvaluator, self).__init__(urlpublisher) |
147 super(RestPathEvaluator, self).__init__(urlpublisher) |
148 self.etype_map = {} |
148 self.etype_map = {} |
149 for etype in self.schema.entities(): |
149 for etype in self.schema.entities(): |
150 etype = str(etype) |
150 etype = str(etype) |
151 self.etype_map[etype.lower()] = etype |
151 self.etype_map[etype.lower()] = etype |
152 |
152 |
153 def evaluate_path(self, req, parts): |
153 def evaluate_path(self, req, parts): |
154 if not (0 < len(parts) < 4): |
154 if not (0 < len(parts) < 4): |
155 raise PathDontMatch() |
155 raise PathDontMatch() |
156 try: |
156 try: |
157 etype = self.etype_map[parts.pop(0).lower()] |
157 etype = self.etype_map[parts.pop(0).lower()] |
175 raise NotFound() |
175 raise NotFound() |
176 return None, rset |
176 return None, rset |
177 |
177 |
178 def cls_rset(self, req, cls): |
178 def cls_rset(self, req, cls): |
179 return req.execute(cls.fetch_rql(req.user)) |
179 return req.execute(cls.fetch_rql(req.user)) |
180 |
180 |
181 def attr_rset(self, req, etype, attrname, value): |
181 def attr_rset(self, req, etype, attrname, value): |
182 rql = u'Any X WHERE X is %s, X %s %%(x)s' % (etype, attrname) |
182 rql = u'Any X WHERE X is %s, X %s %%(x)s' % (etype, attrname) |
183 if attrname == 'eid': |
183 if attrname == 'eid': |
184 try: |
184 try: |
185 rset = req.execute(rql, {'x': typed_eid(value)}, 'x') |
185 rset = req.execute(rql, {'x': typed_eid(value)}, 'x') |