comparison piecrust/sources/pageref.py @ 242:f130365568ff

internal: Code reorganization to put less stuff in `sources.base`. Interfaces that sources can implement are in `sources.interfaces`. The default page source is in `sources.default`. The `SimplePageSource` is gone since most subclasses only wanted to do *some* stuff the same, but *lots* of stuff slightly different. I may have to revisit the code to extract exactly the code that's in common.
author Ludovic Chabant <ludovic@chabant.com>
date Wed, 18 Feb 2015 18:35:03 -0800
parents
children dd25bd3ce1f9
comparison
equal deleted inserted replaced
241:85a6c7ba5e3b 242:f130365568ff
1 import re
2 import os.path
3
4
5 page_ref_pattern = re.compile(r'(?P<src>[\w]+)\:(?P<path>.*?)(;|$)')
6
7
8 class PageNotFoundError(Exception):
9 pass
10
11
12 class PageRef(object):
13 """ A reference to a page, with support for looking a page in different
14 realms.
15 """
16 def __init__(self, app, page_ref):
17 self.app = app
18 self._page_ref = page_ref
19 self._paths = None
20 self._first_valid_path_index = -2
21 self._exts = list(app.config.get('site/auto_formats').keys())
22
23 @property
24 def exists(self):
25 try:
26 self._checkPaths()
27 return True
28 except PageNotFoundError:
29 return False
30
31 @property
32 def source_name(self):
33 self._checkPaths()
34 return self._paths[self._first_valid_path_index][0]
35
36 @property
37 def source(self):
38 return self.app.getSource(self.source_name)
39
40 @property
41 def rel_path(self):
42 self._checkPaths()
43 return self._paths[self._first_valid_path_index][1]
44
45 @property
46 def path(self):
47 self._checkPaths()
48 return self._paths[self._first_valid_path_index][2]
49
50 @property
51 def possible_rel_paths(self):
52 self._load()
53 return [p[1] for p in self._paths]
54
55 @property
56 def possible_paths(self):
57 self._load()
58 return [p[2] for p in self._paths]
59
60 def _load(self):
61 if self._paths is not None:
62 return
63
64 it = list(page_ref_pattern.finditer(self._page_ref))
65 if len(it) == 0:
66 raise Exception("Invalid page ref: %s" % self._page_ref)
67
68 self._paths = []
69 for m in it:
70 source_name = m.group('src')
71 source = self.app.getSource(source_name)
72 if source is None:
73 raise Exception("No such source: %s" % source_name)
74 rel_path = m.group('path')
75 path = source.resolveRef(rel_path)
76 if '%ext%' in rel_path:
77 for e in self._exts:
78 self._paths.append(
79 (source_name,
80 rel_path.replace('%ext%', e),
81 path.replace('%ext%', e)))
82 else:
83 self._paths.append((source_name, rel_path, path))
84
85 def _checkPaths(self):
86 if self._first_valid_path_index >= 0:
87 return
88 if self._first_valid_path_index == -1:
89 raise PageNotFoundError(
90 "No valid paths were found for page reference: %s" %
91 self._page_ref)
92
93 self._load()
94 self._first_valid_path_index = -1
95 for i, path_info in enumerate(self._paths):
96 if os.path.isfile(path_info[2]):
97 self._first_valid_path_index = i
98 break
99