Mercurial > piecrust2
comparison piecrust/sources/pageref.py @ 363:dd25bd3ce1f9
serve: Refactoring and fixes to be able to serve taxonomy pages.
* Page sources' `findPagePath` is renamed to `findPageFactory`, so that it
also returns source metadata.
* Page refs now store possible hits more properly, and use the previous point
to also store metadata. As a result, they can also return a proper factory.
* Implement `findPageFactory` correctly in all built-in sources.
* When the Chef server matches a taxonomy page, get the source metadata from
the page ref in order to make a more proper page.
* Make the `getRoute(s)` functions explicitely say if they want taxonomy routes
or not.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sun, 26 Apr 2015 15:07:40 -0700 |
parents | f130365568ff |
children | 4b1019bb2533 |
comparison
equal
deleted
inserted
replaced
362:ff595828a364 | 363:dd25bd3ce1f9 |
---|---|
1 import re | 1 import re |
2 import os.path | 2 import os.path |
3 from piecrust.sources.base import PageFactory | |
3 | 4 |
4 | 5 |
5 page_ref_pattern = re.compile(r'(?P<src>[\w]+)\:(?P<path>.*?)(;|$)') | 6 page_ref_pattern = re.compile(r'(?P<src>[\w]+)\:(?P<path>.*?)(;|$)') |
6 | 7 |
7 | 8 |
11 | 12 |
12 class PageRef(object): | 13 class PageRef(object): |
13 """ A reference to a page, with support for looking a page in different | 14 """ A reference to a page, with support for looking a page in different |
14 realms. | 15 realms. |
15 """ | 16 """ |
17 _INDEX_NEEDS_LOADING = -2 | |
18 _INDEX_NOT_FOUND = -1 | |
19 | |
20 class _HitInfo(object): | |
21 def __init__(self, source_name, rel_path, path, metadata): | |
22 self.source_name = source_name | |
23 self.rel_path = rel_path | |
24 self.path = path | |
25 self.metadata = metadata | |
26 | |
16 def __init__(self, app, page_ref): | 27 def __init__(self, app, page_ref): |
17 self.app = app | 28 self.app = app |
18 self._page_ref = page_ref | 29 self._page_ref = page_ref |
19 self._paths = None | 30 self._hits = None |
20 self._first_valid_path_index = -2 | 31 self._first_valid_hit_index = self._INDEX_NEEDS_LOADING |
21 self._exts = list(app.config.get('site/auto_formats').keys()) | 32 self._exts = list(app.config.get('site/auto_formats').keys()) |
22 | 33 |
23 @property | 34 @property |
24 def exists(self): | 35 def exists(self): |
25 try: | 36 try: |
26 self._checkPaths() | 37 self._checkHits() |
27 return True | 38 return True |
28 except PageNotFoundError: | 39 except PageNotFoundError: |
29 return False | 40 return False |
30 | 41 |
31 @property | 42 @property |
32 def source_name(self): | 43 def source_name(self): |
33 self._checkPaths() | 44 self._checkHits() |
34 return self._paths[self._first_valid_path_index][0] | 45 return self._first_valid_hit.source_name |
35 | 46 |
36 @property | 47 @property |
37 def source(self): | 48 def source(self): |
38 return self.app.getSource(self.source_name) | 49 return self.app.getSource(self.source_name) |
39 | 50 |
40 @property | 51 @property |
41 def rel_path(self): | 52 def rel_path(self): |
42 self._checkPaths() | 53 self._checkHits() |
43 return self._paths[self._first_valid_path_index][1] | 54 return self._first_valid_hit.rel_path |
44 | 55 |
45 @property | 56 @property |
46 def path(self): | 57 def path(self): |
47 self._checkPaths() | 58 self._checkHits() |
48 return self._paths[self._first_valid_path_index][2] | 59 return self._first_valid_hit.path |
60 | |
61 @property | |
62 def metadata(self): | |
63 self._checkHits() | |
64 return self._first_valid_hit.metadata | |
49 | 65 |
50 @property | 66 @property |
51 def possible_rel_paths(self): | 67 def possible_rel_paths(self): |
52 self._load() | 68 self._load() |
53 return [p[1] for p in self._paths] | 69 return [h.rel_path for h in self._hits] |
54 | 70 |
55 @property | 71 @property |
56 def possible_paths(self): | 72 def possible_paths(self): |
57 self._load() | 73 self._load() |
58 return [p[2] for p in self._paths] | 74 return [h.path for h in self._hits] |
75 | |
76 def getFactory(self): | |
77 return PageFactory(self.source, self.rel_path, self.metadata) | |
78 | |
79 @property | |
80 def _first_valid_hit(self): | |
81 return self._hits[self._first_valid_hit_index] | |
59 | 82 |
60 def _load(self): | 83 def _load(self): |
61 if self._paths is not None: | 84 if self._hits is not None: |
62 return | 85 return |
63 | 86 |
64 it = list(page_ref_pattern.finditer(self._page_ref)) | 87 it = list(page_ref_pattern.finditer(self._page_ref)) |
65 if len(it) == 0: | 88 if len(it) == 0: |
66 raise Exception("Invalid page ref: %s" % self._page_ref) | 89 raise Exception("Invalid page ref: %s" % self._page_ref) |
67 | 90 |
68 self._paths = [] | 91 self._hits = [] |
69 for m in it: | 92 for m in it: |
70 source_name = m.group('src') | 93 source_name = m.group('src') |
71 source = self.app.getSource(source_name) | 94 source = self.app.getSource(source_name) |
72 if source is None: | 95 if source is None: |
73 raise Exception("No such source: %s" % source_name) | 96 raise Exception("No such source: %s" % source_name) |
74 rel_path = m.group('path') | 97 rel_path = m.group('path') |
75 path = source.resolveRef(rel_path) | 98 path, metadata = source.resolveRef(rel_path) |
76 if '%ext%' in rel_path: | 99 if '%ext%' in rel_path: |
77 for e in self._exts: | 100 for e in self._exts: |
78 self._paths.append( | 101 self._hits.append(self._HitInfo( |
79 (source_name, | 102 source_name, |
80 rel_path.replace('%ext%', e), | 103 rel_path.replace('%ext%', e), |
81 path.replace('%ext%', e))) | 104 path.replace('%ext%', e), |
105 metadata)) | |
82 else: | 106 else: |
83 self._paths.append((source_name, rel_path, path)) | 107 self._hits.append( |
108 self._HitInfo(source_name, rel_path, path, metadata)) | |
84 | 109 |
85 def _checkPaths(self): | 110 def _checkHits(self): |
86 if self._first_valid_path_index >= 0: | 111 if self._first_valid_hit_index >= 0: |
87 return | 112 return |
88 if self._first_valid_path_index == -1: | 113 if self._first_valid_hit_index == self._INDEX_NOT_FOUND: |
89 raise PageNotFoundError( | 114 raise PageNotFoundError( |
90 "No valid paths were found for page reference: %s" % | 115 "No valid paths were found for page reference: %s" % |
91 self._page_ref) | 116 self._page_ref) |
92 | 117 |
93 self._load() | 118 self._load() |
94 self._first_valid_path_index = -1 | 119 self._first_valid_hit_index = self._INDEX_NOT_FOUND |
95 for i, path_info in enumerate(self._paths): | 120 for i, hit in enumerate(self._hits): |
96 if os.path.isfile(path_info[2]): | 121 if os.path.isfile(hit.path): |
97 self._first_valid_path_index = i | 122 self._first_valid_hit_index = i |
98 break | 123 break |
99 | 124 |