Mercurial > piecrust2
changeset 173:0a86a7a6b284
routes: Actually match metadata when finding routes, fix problems with paths.
When we look for a route that matches a given page, we now look at the
source metadata that comes with that page, and compare it to the metadata
we need to build URIs.
Also, when matching URIs, we handle the case where a 'path'-component in
our pattern may be completely empty, and thus we may be missing some trailing
slashes in the URI.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sat, 03 Jan 2015 21:10:44 -0800 |
parents | 4fc1d306046b |
children | e9a3d405e18f |
files | piecrust/app.py piecrust/routing.py piecrust/serving.py |
diffstat | 3 files changed, 44 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/piecrust/app.py Sat Jan 03 20:52:19 2015 -0800 +++ b/piecrust/app.py Sat Jan 03 21:10:44 2015 -0800 @@ -512,7 +512,7 @@ def getRoute(self, source_name, source_metadata): for route in self.getRoutes(source_name, True): - if route.isMatch(source_metadata): + if route.matchesMetadata(source_metadata): return route return None
--- a/piecrust/routing.py Sat Jan 03 20:52:19 2015 -0800 +++ b/piecrust/routing.py Sat Jan 03 21:10:44 2015 -0800 @@ -26,13 +26,33 @@ self.uri_root = app.config.get('site/root').rstrip('/') + '/' self.uri_pattern = uri.lstrip('/') self.uri_format = route_re.sub(self._uriFormatRepl, self.uri_pattern) + + # Get the straight-forward regex for matching this URI pattern. p = route_re.sub(self._uriPatternRepl, self.uri_pattern) + '$' self.uri_re = re.compile(p) + + # If the URI pattern has a 'path'-type component, we'll need to match + # the versions for which that component is empty. So for instance if + # we have `/foo/%path:bar%`, we may need to match `/foo` (note the + # lack of a trailing slash). We have to build a special pattern (in + # this case without that trailing slash) to match those situations. + # (maybe there's a better way to do it but I can't think of any + # right now) + uri_pattern_no_path = ( + route_re.sub(self._uriNoPathRepl, self.uri_pattern) + .replace('//', '/') + .rstrip('/')) + if uri_pattern_no_path != self.uri_pattern: + p = route_re.sub(self._uriPatternRepl, uri_pattern_no_path) + '$' + self.uri_re_no_path = re.compile(p) + else: + self.uri_re_no_path = None + self.source_name = cfg['source'] self.taxonomy = cfg.get('taxonomy') - self.required_source_metadata = [] + self.required_source_metadata = set() for m in route_re.finditer(uri): - self.required_source_metadata.append(m.group('name')) + self.required_source_metadata.add(m.group('name')) self.template_func = None self.template_func_name = None self.template_func_args = [] @@ -50,8 +70,18 @@ def source_realm(self): return self.source.realm - def isMatch(self, source_metadata): - return True + def matchesMetadata(self, source_metadata): + return self.required_source_metadata.issubset(source_metadata.keys()) + + def matchUri(self, uri): + m = self.uri_re.match(uri) + if m: + return m + if self.uri_re_no_path: + m = self.uri_re_no_path.match(uri) + if m: + return m + return None def getUri(self, source_metadata, provider=None): if provider: @@ -78,7 +108,14 @@ name = m.group('name') qualifier = m.group('qual') if qualifier == 'path': - return r'(?P<%s>.*)' % name + return r'(?P<%s>[^\?]*)' % name + return r'(?P<%s>[^/\?]+)' % name + + def _uriNoPathRepl(self, m): + name = m.group('name') + qualifier = m.group('qual') + if qualifier == 'path': + return '' return r'(?P<%s>[^/\?]+)' % name def _createTemplateFunc(self, func_def):
--- a/piecrust/serving.py Sat Jan 03 20:52:19 2015 -0800 +++ b/piecrust/serving.py Sat Jan 03 21:10:44 2015 -0800 @@ -415,7 +415,7 @@ uri = uri.lstrip('/') res = [] for route in routes: - m = route.uri_re.match(uri) + m = route.matchUri(uri) if m: metadata = m.groupdict() res.append((route, metadata))