comparison piecrust/app.py @ 666:81d9c3a3a0b5

internal: Get rid of the whole "sub cache" business. * Compute cache keys up front, so the cache directory is only chosen once. * Buffer up config variants to apply before loading the config. Makes it possible to cache variant-resulting configs, too. * Make a factory class to reuse the logic that creates the `PieCrust` object correctly for multi-process workers and such. * Add a test.
author Ludovic Chabant <ludovic@chabant.com>
date Thu, 03 Mar 2016 08:22:41 -0800
parents 3ceeca7bb71c
children 3df808b133f8
comparison
equal deleted inserted replaced
665:5dc13c816045 666:81d9c3a3a0b5
21 logger = logging.getLogger(__name__) 21 logger = logging.getLogger(__name__)
22 22
23 23
24 class PieCrust(object): 24 class PieCrust(object):
25 def __init__(self, root_dir, cache=True, debug=False, theme_site=False, 25 def __init__(self, root_dir, cache=True, debug=False, theme_site=False,
26 env=None): 26 env=None, cache_key=None):
27 self.root_dir = root_dir 27 self.root_dir = root_dir
28 self.debug = debug 28 self.debug = debug
29 self.theme_site = theme_site 29 self.theme_site = theme_site
30 self.plugin_loader = PluginLoader(self) 30 self.plugin_loader = PluginLoader(self)
31 self.cache_key = cache_key or 'default'
31 32
32 if cache: 33 if cache:
33 cache_dir = os.path.join(self.cache_dir, 'default') 34 self.cache = ExtensibleCache(self.cache_dir)
34 self.cache = ExtensibleCache(cache_dir)
35 else: 35 else:
36 self.cache = NullExtensibleCache() 36 self.cache = NullExtensibleCache()
37 37
38 self.env = env 38 self.env = env
39 if self.env is None: 39 if self.env is None:
80 config['site'] = sitec 80 config['site'] = sitec
81 srcc = sitec.get('sources') 81 srcc = sitec.get('sources')
82 if srcc is not None: 82 if srcc is not None:
83 for sn, sc in srcc.items(): 83 for sn, sc in srcc.items():
84 sc['realm'] = REALM_THEME 84 sc['realm'] = REALM_THEME
85 config.fixups.append(_fixupThemeSources) 85 config.addFixup(_fixupThemeSources)
86 86
87 self.env.stepTimer('SiteConfigLoad', time.perf_counter() - start_time) 87 self.env.stepTimer('SiteConfigLoad', time.perf_counter() - start_time)
88 return config 88 return config
89 89
90 @cached_property 90 @cached_property
122 return td 122 return td
123 return os.path.join(RESOURCES_DIR, 'theme') 123 return os.path.join(RESOURCES_DIR, 'theme')
124 124
125 @cached_property 125 @cached_property
126 def cache_dir(self): 126 def cache_dir(self):
127 return os.path.join(self.root_dir, CACHE_DIR) 127 return os.path.join(self.root_dir, CACHE_DIR, self.cache_key)
128
129 @property # Not a cached property because its result can change.
130 def sub_cache_dir(self):
131 if self.cache.enabled:
132 return self.cache.base_dir
133 return None
134 128
135 @cached_property 129 @cached_property
136 def sources(self): 130 def sources(self):
137 defs = {} 131 defs = {}
138 for cls in self.plugin_loader.getSources(): 132 for cls in self.plugin_loader.getSources():
195 for tax in self.taxonomies: 189 for tax in self.taxonomies:
196 if tax.name == tax_name: 190 if tax.name == tax_name:
197 return tax 191 return tax
198 return None 192 return None
199 193
200 def useSubCache(self, cache_name, cache_key):
201 cache_hash = hashlib.md5(cache_key.encode('utf8')).hexdigest()
202 cache_dir = os.path.join(self.cache_dir,
203 '%s_%s' % (cache_name, cache_hash))
204 self._useSubCacheDir(cache_dir)
205
206 def _useSubCacheDir(self, cache_dir):
207 assert cache_dir
208 logger.debug("Moving cache to: %s" % cache_dir)
209 self.cache = ExtensibleCache(cache_dir)
210 self.env._onSubCacheDirChanged(self)
211
212 def _get_dir(self, default_rel_dir): 194 def _get_dir(self, default_rel_dir):
213 abs_dir = os.path.join(self.root_dir, default_rel_dir) 195 abs_dir = os.path.join(self.root_dir, default_rel_dir)
214 if os.path.isdir(abs_dir): 196 if os.path.isdir(abs_dir):
215 return abs_dir 197 return abs_dir
216 return None 198 return None
232 dirs.append(default_dir) 214 dirs.append(default_dir)
233 215
234 return dirs 216 return dirs
235 217
236 218
219
237 def apply_variant_and_values(app, config_variant=None, config_values=None): 220 def apply_variant_and_values(app, config_variant=None, config_values=None):
238 if config_variant is not None: 221 if config_variant is not None:
239 logger.debug("Applying configuration variant '%s'." % config_variant) 222 logger.debug("Adding configuration variant '%s'." % config_variant)
240 app.config.applyVariant('variants/' + config_variant) 223 variant_path = os.path.join(
224 app.root_dir, 'configs', '%s.yml' % config_variant)
225 app.config.addVariant(variant_path)
241 226
242 if config_values is not None: 227 if config_values is not None:
243 for name, value in config_values: 228 for name, value in config_values:
244 logger.debug("Setting configuration '%s' to: %s" % (name, value)) 229 logger.debug("Adding configuration override '%s': %s" % (name, value))
245 app.config.set(name, value) 230 app.config.addVariantValue(name, value)
246 231
232
233 class PieCrustFactory(object):
234 def __init__(
235 self, root_dir, *,
236 cache=True, cache_key=None,
237 config_variant=None, config_values=None,
238 debug=False, theme_site=False):
239 self.root_dir = root_dir
240 self.cache = cache
241 self.cache_key = cache_key
242 self.config_variant = config_variant
243 self.config_values = config_values
244 self.debug = debug
245 self.theme_site = theme_site
246
247 def create(self):
248 app = PieCrust(
249 self.root_dir,
250 cache=self.cache,
251 cache_key=self.cache_key,
252 debug=self.debug,
253 theme_site=self.theme_site)
254 apply_variant_and_values(
255 app, self.config_variant, self.config_values)
256 return app
257