web/views/urlpublishing.py
branchtls-sprint
changeset 1802 d628defebc17
parent 661 4f61eb8a96b7
child 1977 606923dff11b
equal deleted inserted replaced
1801:672acc730ce5 1802:d628defebc17
    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'):
    95             raise NotFound(path)
    95             raise NotFound(path)
    96         if pmid is None:
    96         if pmid is None:
    97             pmid = self.default_method
    97             pmid = self.default_method
    98         return pmid, rset
    98         return pmid, rset
    99 
    99 
   100         
   100 
   101 class URLPathEvaluator(Component):
   101 class URLPathEvaluator(Component):
   102     __abstract__ = True
   102     __abstract__ = True
   103     id = 'urlpathevaluator'
   103     id = 'urlpathevaluator'
   104 
   104 
   105     def __init__(self, urlpublisher):
   105     def __init__(self, urlpublisher):
   134             raise PathDontMatch()
   134             raise PathDontMatch()
   135         if rset.rowcount == 0:
   135         if rset.rowcount == 0:
   136             raise NotFound()
   136             raise NotFound()
   137         return None, rset
   137         return None, rset
   138 
   138 
   139         
   139 
   140 class RestPathEvaluator(URLPathEvaluator):
   140 class RestPathEvaluator(URLPathEvaluator):
   141     """handle path with the form::
   141     """handle path with the form::
   142 
   142 
   143         <etype>[[/<attribute name>]/<attribute value>]*
   143         <etype>[[/<attribute name>]/<attribute value>]*
   144     """
   144     """
   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')
   209                 # XXX we might want to chain url rewrites
   209                 # XXX we might want to chain url rewrites
   210                 return rewriter.rewrite(req, uri)
   210                 return rewriter.rewrite(req, uri)
   211             except KeyError:
   211             except KeyError:
   212                 continue
   212                 continue
   213         raise PathDontMatch()
   213         raise PathDontMatch()
   214         
   214 
   215 
   215 
   216 class ActionPathEvaluator(URLPathEvaluator):
   216 class ActionPathEvaluator(URLPathEvaluator):
   217     """handle path with the form::
   217     """handle path with the form::
   218 
   218 
   219     <any evaluator path>/<action>
   219     <any evaluator path>/<action>