Mercurial > piecrust2
comparison piecrust/routing.py @ 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 | a42469dbdc47 |
children | d47d9493bb0a |
comparison
equal
deleted
inserted
replaced
172:4fc1d306046b | 173:0a86a7a6b284 |
---|---|
24 self.app = app | 24 self.app = app |
25 uri = cfg['url'] | 25 uri = cfg['url'] |
26 self.uri_root = app.config.get('site/root').rstrip('/') + '/' | 26 self.uri_root = app.config.get('site/root').rstrip('/') + '/' |
27 self.uri_pattern = uri.lstrip('/') | 27 self.uri_pattern = uri.lstrip('/') |
28 self.uri_format = route_re.sub(self._uriFormatRepl, self.uri_pattern) | 28 self.uri_format = route_re.sub(self._uriFormatRepl, self.uri_pattern) |
29 | |
30 # Get the straight-forward regex for matching this URI pattern. | |
29 p = route_re.sub(self._uriPatternRepl, self.uri_pattern) + '$' | 31 p = route_re.sub(self._uriPatternRepl, self.uri_pattern) + '$' |
30 self.uri_re = re.compile(p) | 32 self.uri_re = re.compile(p) |
33 | |
34 # If the URI pattern has a 'path'-type component, we'll need to match | |
35 # the versions for which that component is empty. So for instance if | |
36 # we have `/foo/%path:bar%`, we may need to match `/foo` (note the | |
37 # lack of a trailing slash). We have to build a special pattern (in | |
38 # this case without that trailing slash) to match those situations. | |
39 # (maybe there's a better way to do it but I can't think of any | |
40 # right now) | |
41 uri_pattern_no_path = ( | |
42 route_re.sub(self._uriNoPathRepl, self.uri_pattern) | |
43 .replace('//', '/') | |
44 .rstrip('/')) | |
45 if uri_pattern_no_path != self.uri_pattern: | |
46 p = route_re.sub(self._uriPatternRepl, uri_pattern_no_path) + '$' | |
47 self.uri_re_no_path = re.compile(p) | |
48 else: | |
49 self.uri_re_no_path = None | |
50 | |
31 self.source_name = cfg['source'] | 51 self.source_name = cfg['source'] |
32 self.taxonomy = cfg.get('taxonomy') | 52 self.taxonomy = cfg.get('taxonomy') |
33 self.required_source_metadata = [] | 53 self.required_source_metadata = set() |
34 for m in route_re.finditer(uri): | 54 for m in route_re.finditer(uri): |
35 self.required_source_metadata.append(m.group('name')) | 55 self.required_source_metadata.add(m.group('name')) |
36 self.template_func = None | 56 self.template_func = None |
37 self.template_func_name = None | 57 self.template_func_name = None |
38 self.template_func_args = [] | 58 self.template_func_args = [] |
39 self._createTemplateFunc(cfg.get('func')) | 59 self._createTemplateFunc(cfg.get('func')) |
40 | 60 |
48 | 68 |
49 @property | 69 @property |
50 def source_realm(self): | 70 def source_realm(self): |
51 return self.source.realm | 71 return self.source.realm |
52 | 72 |
53 def isMatch(self, source_metadata): | 73 def matchesMetadata(self, source_metadata): |
54 return True | 74 return self.required_source_metadata.issubset(source_metadata.keys()) |
75 | |
76 def matchUri(self, uri): | |
77 m = self.uri_re.match(uri) | |
78 if m: | |
79 return m | |
80 if self.uri_re_no_path: | |
81 m = self.uri_re_no_path.match(uri) | |
82 if m: | |
83 return m | |
84 return None | |
55 | 85 |
56 def getUri(self, source_metadata, provider=None): | 86 def getUri(self, source_metadata, provider=None): |
57 if provider: | 87 if provider: |
58 source_metadata = dict(source_metadata) | 88 source_metadata = dict(source_metadata) |
59 source_metadata.update(provider.getRouteMetadata()) | 89 source_metadata.update(provider.getRouteMetadata()) |
76 | 106 |
77 def _uriPatternRepl(self, m): | 107 def _uriPatternRepl(self, m): |
78 name = m.group('name') | 108 name = m.group('name') |
79 qualifier = m.group('qual') | 109 qualifier = m.group('qual') |
80 if qualifier == 'path': | 110 if qualifier == 'path': |
81 return r'(?P<%s>.*)' % name | 111 return r'(?P<%s>[^\?]*)' % name |
112 return r'(?P<%s>[^/\?]+)' % name | |
113 | |
114 def _uriNoPathRepl(self, m): | |
115 name = m.group('name') | |
116 qualifier = m.group('qual') | |
117 if qualifier == 'path': | |
118 return '' | |
82 return r'(?P<%s>[^/\?]+)' % name | 119 return r'(?P<%s>[^/\?]+)' % name |
83 | 120 |
84 def _createTemplateFunc(self, func_def): | 121 def _createTemplateFunc(self, func_def): |
85 if func_def is None: | 122 if func_def is None: |
86 return | 123 return |