def __init__(self, root_dir, cache=True, debug=False, theme_site=False, env=None, cache_key=None): self.root_dir = root_dir self.debug = debug self.theme_site = theme_site self.plugin_loader = PluginLoader(self) self.cache_key = cache_key or 'default' if cache: self.cache = ExtensibleCache(self.cache_dir) else: self.cache = NullExtensibleCache() if env is None: env = StandardEnvironment() self.env = env env.initialize(self) stats = env.stats stats.registerTimer('SiteConfigLoad') stats.registerTimer('PageLoad') stats.registerTimer("BuildRenderData") stats.registerTimer("BuildLazyPageData") stats.registerTimer("PageRender") stats.registerTimer("PageRenderSegments") stats.registerTimer("PageRenderLayout") stats.registerTimer("PageSerialize") stats.registerCounter('PageLoads') stats.registerCounter('PageRenderSegments') stats.registerCounter('PageRenderLayout')
def __init__(self, root_dir, cache=True, debug=False, theme_site=False, env=None, cache_key=None): self.root_dir = root_dir self.debug = debug self.theme_site = theme_site self.plugin_loader = PluginLoader(self) self.cache_key = cache_key or 'default' if cache: self.cache = ExtensibleCache(self.cache_dir) else: self.cache = NullExtensibleCache() self.env = env if self.env is None: self.env = StandardEnvironment() self.env.initialize(self) self.env.registerTimer('SiteConfigLoad') self.env.registerTimer('PageLoad') self.env.registerTimer("PageDataBuild") self.env.registerTimer("BuildRenderData") self.env.registerTimer("PageRender") self.env.registerTimer("PageRenderSegments") self.env.registerTimer("PageRenderLayout") self.env.registerTimer("PageSerialize")
def __init__(self): self.root_dir = None self.debug = False self.templates_dirs = [] self.theme_dir = None self.cache_dir = None self.config = PieCrustConfiguration() self.plugin_loader = PluginLoader(self) self.env = None
def __init__(self, root_dir, cache=True, debug=False, theme_site=False, env=None): self.root_dir = root_dir self.debug = debug self.theme_site = theme_site self.plugin_loader = PluginLoader(self) if cache: cache_dir = os.path.join(self.cache_dir, 'default') self.cache = ExtensibleCache(cache_dir) else: self.cache = NullExtensibleCache() self.env = env if self.env is None: self.env = StandardEnvironment() self.env.initialize(self)
class PieCrust(object): def __init__(self, root_dir, cache=True, debug=False, theme_site=False, env=None): self.root_dir = root_dir self.debug = debug self.theme_site = theme_site self.plugin_loader = PluginLoader(self) if cache: cache_dir = os.path.join(self.cache_dir, 'default') self.cache = ExtensibleCache(cache_dir) else: self.cache = NullExtensibleCache() self.env = env if self.env is None: self.env = StandardEnvironment() self.env.initialize(self) @cached_property def config(self): logger.debug("Creating site configuration...") paths = [] if self.theme_dir: paths.append(os.path.join(self.theme_dir, THEME_CONFIG_PATH)) paths.append(os.path.join(self.root_dir, CONFIG_PATH)) config_cache = self.cache.getCache('app') config = PieCrustConfiguration(paths, config_cache) if self.theme_dir: # We'll need to patch the templates directories to be relative # to the site's root, and not the theme root. def _fixupThemeTemplatesDir(index, config): if index != 0: return sitec = config.get('site') if sitec is None: return tplc = sitec.get('templates_dirs') if tplc is None: return if isinstance(tplc, str): tplc = [tplc] sitec['templates_dirs'] = list( filter(tplc, lambda p: os.path.join(self.theme_dir, p))) config.fixups.append(_fixupThemeTemplatesDir) # We'll also need to flag all page sources as coming from # the theme. def _fixupThemeSources(index, config): if index != 0: return sitec = config.get('site') if sitec is None: sitec = {} config['site'] = sitec srcc = sitec.get('sources') if srcc is not None: for sn, sc in srcc.items(): sc['realm'] = REALM_THEME config.fixups.append(_fixupThemeSources) return config @cached_property def assets_dirs(self): assets_dirs = self._get_configurable_dirs(ASSETS_DIR, 'site/assets_dirs') # Also add the theme directory, if any. if self.theme_dir: default_theme_dir = os.path.join(self.theme_dir, ASSETS_DIR) if os.path.isdir(default_theme_dir): assets_dirs.append(default_theme_dir) return assets_dirs @cached_property def templates_dirs(self): templates_dirs = self._get_configurable_dirs(TEMPLATES_DIR, 'site/templates_dirs') # Also, add the theme directory, if any. if self.theme_dir: default_theme_dir = os.path.join(self.theme_dir, TEMPLATES_DIR) if os.path.isdir(default_theme_dir): templates_dirs.append(default_theme_dir) return templates_dirs @cached_property def theme_dir(self): td = self._get_dir(THEME_DIR) if td is not None: return td return os.path.join(RESOURCES_DIR, 'theme') @cached_property def cache_dir(self): return os.path.join(self.root_dir, CACHE_DIR) @property # Not a cached property because its result can change. def sub_cache_dir(self): if self.cache.enabled: return self.cache.base_dir return None @cached_property def sources(self): defs = {} for cls in self.plugin_loader.getSources(): defs[cls.SOURCE_NAME] = cls sources = [] for n, s in self.config.get('site/sources').items(): cls = defs.get(s['type']) if cls is None: raise ConfigurationError("No such page source type: %s" % s['type']) src = cls(self, n, s) sources.append(src) return sources @cached_property def routes(self): routes = [] for r in self.config.get('site/routes'): rte = Route(self, r) routes.append(rte) return routes @cached_property def taxonomies(self): taxonomies = [] for tn, tc in self.config.get('site/taxonomies').items(): tax = Taxonomy(self, tn, tc) taxonomies.append(tax) return taxonomies def getSource(self, source_name): for source in self.sources: if source.name == source_name: return source return None def getRoutes(self, source_name, *, skip_taxonomies=False): for route in self.routes: if route.source_name == source_name: if not skip_taxonomies or route.taxonomy_name is None: yield route def getRoute(self, source_name, route_metadata, *, skip_taxonomies=False): for route in self.getRoutes(source_name, skip_taxonomies=skip_taxonomies): if (route_metadata is None or route.matchesMetadata(route_metadata)): return route return None def getTaxonomyRoute(self, tax_name, source_name): for route in self.routes: if route.taxonomy_name == tax_name and route.source_name == source_name: return route return None def getTaxonomy(self, tax_name): for tax in self.taxonomies: if tax.name == tax_name: return tax return None def useSubCache(self, cache_name, cache_key): cache_hash = hashlib.md5(cache_key.encode('utf8')).hexdigest() cache_dir = os.path.join(self.cache_dir, '%s_%s' % (cache_name, cache_hash)) self._useSubCacheDir(cache_dir) def _useSubCacheDir(self, cache_dir): assert cache_dir logger.debug("Moving cache to: %s" % cache_dir) self.cache = ExtensibleCache(cache_dir) self.env._onSubCacheDirChanged(self) def _get_dir(self, default_rel_dir): abs_dir = os.path.join(self.root_dir, default_rel_dir) if os.path.isdir(abs_dir): return abs_dir return None def _get_configurable_dirs(self, default_rel_dir, conf_name): dirs = [] # Add custom directories from the configuration. conf_dirs = self.config.get(conf_name) if conf_dirs is not None: if isinstance(conf_dirs, str): dirs.append(os.path.join(self.root_dir, conf_dirs)) else: dirs += [os.path.join(self.root_dir, p) for p in conf_dirs] # Add the default directory if it exists. default_dir = os.path.join(self.root_dir, default_rel_dir) if os.path.isdir(default_dir): dirs.append(default_dir) return dirs
class PieCrust(object): def __init__(self, root_dir, cache=True, debug=False, theme_site=False, env=None): self.root_dir = root_dir self.debug = debug self.theme_site = theme_site self.plugin_loader = PluginLoader(self) if cache: cache_dir = os.path.join(self.cache_dir, 'default') self.cache = ExtensibleCache(cache_dir) else: self.cache = NullExtensibleCache() self.env = env if self.env is None: self.env = StandardEnvironment() self.env.initialize(self) @cached_property def config(self): logger.debug("Creating site configuration...") paths = [] if self.theme_dir: paths.append(os.path.join(self.theme_dir, THEME_CONFIG_PATH)) paths.append(os.path.join(self.root_dir, CONFIG_PATH)) config_cache = self.cache.getCache('app') config = PieCrustConfiguration(paths, config_cache) if self.theme_dir: # We'll need to patch the templates directories to be relative # to the site's root, and not the theme root. def _fixupThemeTemplatesDir(index, config): if index != 0: return sitec = config.get('site') if sitec is None: return tplc = sitec.get('templates_dirs') if tplc is None: return if isinstance(tplc, str): tplc = [tplc] sitec['templates_dirs'] = list(filter(tplc, lambda p: os.path.join(self.theme_dir, p))) config.fixups.append(_fixupThemeTemplatesDir) # We'll also need to flag all page sources as coming from # the theme. def _fixupThemeSources(index, config): if index != 0: return sitec = config.get('site') if sitec is None: sitec = {} config['site'] = sitec srcc = sitec.get('sources') if srcc is not None: for sn, sc in srcc.items(): sc['realm'] = REALM_THEME config.fixups.append(_fixupThemeSources) return config @cached_property def assets_dirs(self): assets_dirs = self._get_configurable_dirs(ASSETS_DIR, 'site/assets_dirs') # Also add the theme directory, if any. if self.theme_dir: default_theme_dir = os.path.join(self.theme_dir, ASSETS_DIR) if os.path.isdir(default_theme_dir): assets_dirs.append(default_theme_dir) return assets_dirs @cached_property def templates_dirs(self): templates_dirs = self._get_configurable_dirs(TEMPLATES_DIR, 'site/templates_dirs') # Also, add the theme directory, if any. if self.theme_dir: default_theme_dir = os.path.join(self.theme_dir, TEMPLATES_DIR) if os.path.isdir(default_theme_dir): templates_dirs.append(default_theme_dir) return templates_dirs @cached_property def theme_dir(self): td = self._get_dir(THEME_DIR) if td is not None: return td return os.path.join(RESOURCES_DIR, 'theme') @cached_property def cache_dir(self): return os.path.join(self.root_dir, CACHE_DIR) @property # Not a cached property because its result can change. def sub_cache_dir(self): if self.cache.enabled: return self.cache.base_dir return None @cached_property def sources(self): defs = {} for cls in self.plugin_loader.getSources(): defs[cls.SOURCE_NAME] = cls sources = [] for n, s in self.config.get('site/sources').items(): cls = defs.get(s['type']) if cls is None: raise ConfigurationError("No such page source type: %s" % s['type']) src = cls(self, n, s) sources.append(src) return sources @cached_property def routes(self): routes = [] for r in self.config.get('site/routes'): rte = Route(self, r) routes.append(rte) return routes @cached_property def taxonomies(self): taxonomies = [] for tn, tc in self.config.get('site/taxonomies').items(): tax = Taxonomy(self, tn, tc) taxonomies.append(tax) return taxonomies def getSource(self, source_name): for source in self.sources: if source.name == source_name: return source return None def getRoutes(self, source_name, *, skip_taxonomies=False): for route in self.routes: if route.source_name == source_name: if not skip_taxonomies or route.taxonomy_name is None: yield route def getRoute(self, source_name, route_metadata, *, skip_taxonomies=False): for route in self.getRoutes(source_name, skip_taxonomies=skip_taxonomies): if (route_metadata is None or route.matchesMetadata(route_metadata)): return route return None def getTaxonomyRoute(self, tax_name, source_name): for route in self.routes: if route.taxonomy_name == tax_name and route.source_name == source_name: return route return None def getTaxonomy(self, tax_name): for tax in self.taxonomies: if tax.name == tax_name: return tax return None def useSubCache(self, cache_name, cache_key): cache_hash = hashlib.md5(cache_key.encode('utf8')).hexdigest() cache_dir = os.path.join(self.cache_dir, '%s_%s' % (cache_name, cache_hash)) self._useSubCacheDir(cache_dir) def _useSubCacheDir(self, cache_dir): assert cache_dir logger.debug("Moving cache to: %s" % cache_dir) self.cache = ExtensibleCache(cache_dir) self.env._onSubCacheDirChanged(self) def _get_dir(self, default_rel_dir): abs_dir = os.path.join(self.root_dir, default_rel_dir) if os.path.isdir(abs_dir): return abs_dir return None def _get_configurable_dirs(self, default_rel_dir, conf_name): dirs = [] # Add custom directories from the configuration. conf_dirs = self.config.get(conf_name) if conf_dirs is not None: if isinstance(conf_dirs, str): dirs.append(os.path.join(self.root_dir, conf_dirs)) else: dirs += [os.path.join(self.root_dir, p) for p in conf_dirs] # Add the default directory if it exists. default_dir = os.path.join(self.root_dir, default_rel_dir) if os.path.isdir(default_dir): dirs.append(default_dir) return dirs
class PieCrust(object): def __init__(self, root_dir, cache=True, debug=False, theme_site=False, env=None, cache_key=None): self.root_dir = root_dir self.debug = debug self.theme_site = theme_site self.plugin_loader = PluginLoader(self) self.cache_key = cache_key or 'default' if cache: self.cache = ExtensibleCache(self.cache_dir) else: self.cache = NullExtensibleCache() self.env = env if self.env is None: self.env = StandardEnvironment() self.env.initialize(self) self.env.registerTimer('SiteConfigLoad') self.env.registerTimer('PageLoad') self.env.registerTimer("PageDataBuild") self.env.registerTimer("BuildRenderData") self.env.registerTimer("PageRender") self.env.registerTimer("PageRenderSegments") self.env.registerTimer("PageRenderLayout") self.env.registerTimer("PageSerialize") @cached_property def config(self): logger.debug("Creating site configuration...") start_time = time.perf_counter() if not self.theme_site: path = os.path.join(self.root_dir, CONFIG_PATH) else: path = os.path.join(self.root_dir, THEME_CONFIG_PATH) theme_path = None if not self.theme_site and self.theme_dir: theme_path = os.path.join(self.theme_dir, THEME_CONFIG_PATH) config_cache = self.cache.getCache('app') config = PieCrustConfiguration( path=path, theme_path=theme_path, cache=config_cache, theme_config=self.theme_site) if self.theme_site: variant_path = os.path.join( self.root_dir, 'configs', 'theme_preview.yml') config.addVariant(variant_path, raise_if_not_found=False) self.env.stepTimer('SiteConfigLoad', time.perf_counter() - start_time) return config @cached_property def assets_dirs(self): assets_dirs = self._get_configurable_dirs( ASSETS_DIR, 'site/assets_dirs') # Also add the theme directory, if any. if self.theme_dir: default_theme_dir = os.path.join(self.theme_dir, ASSETS_DIR) if os.path.isdir(default_theme_dir): assets_dirs.append(default_theme_dir) return assets_dirs @cached_property def templates_dirs(self): templates_dirs = self._get_configurable_dirs( TEMPLATES_DIR, 'site/templates_dirs') # Also, add the theme directory, if any. if self.theme_dir: default_theme_dir = os.path.join(self.theme_dir, TEMPLATES_DIR) if os.path.isdir(default_theme_dir): templates_dirs.append(default_theme_dir) return templates_dirs @cached_property def theme_dir(self): # No theme if the curent site is already a theme. if self.theme_site: return None # See if there's a theme we absolutely want. td = self._get_dir(THEME_DIR) if td is not None: return td # Try to load a theme specified in the configuration. from piecrust.themes.base import ThemeLoader loader = ThemeLoader(self.root_dir) theme_dir = loader.getThemeDir() if theme_dir is not None: return theme_dir # Nothing... use the default theme. return os.path.join(RESOURCES_DIR, 'theme') @cached_property def cache_dir(self): return os.path.join(self.root_dir, CACHE_DIR, self.cache_key) @cached_property def sources(self): defs = {} for cls in self.plugin_loader.getSources(): defs[cls.SOURCE_NAME] = cls sources = [] for n, s in self.config.get('site/sources').items(): cls = defs.get(s['type']) if cls is None: raise ConfigurationError("No such page source type: %s" % s['type']) src = cls(self, n, s) sources.append(src) return sources @cached_property def routes(self): routes = [] for r in self.config.get('site/routes'): rte = Route(self, r) routes.append(rte) return routes @cached_property def generators(self): defs = {} for cls in self.plugin_loader.getPageGenerators(): defs[cls.GENERATOR_NAME] = cls gens = [] for n, g in self.config.get('site/generators').items(): cls = defs.get(g['type']) if cls is None: raise ConfigurationError("No such page generator type: %s" % g['type']) gen = cls(self, n, g) gens.append(gen) return gens @cached_property def publishers(self): defs_by_name = {} defs_by_scheme = {} for cls in self.plugin_loader.getPublishers(): defs_by_name[cls.PUBLISHER_NAME] = cls if cls.PUBLISHER_SCHEME: defs_by_scheme[cls.PUBLISHER_SCHEME] = cls tgts = [] publish_config = self.config.get('publish') if publish_config is None: return tgts for n, t in publish_config.items(): pub_type = None is_scheme = False if isinstance(t, dict): pub_type = t.get('type') elif isinstance(t, str): comps = urllib.parse.urlparse(t) pub_type = comps.scheme is_scheme = True cls = (defs_by_scheme.get(pub_type) if is_scheme else defs_by_name.get(pub_type)) if cls is None: raise ConfigurationError("No such publisher: %s" % pub_type) tgt = cls(self, n, t) tgts.append(tgt) return tgts def getSource(self, source_name): for source in self.sources: if source.name == source_name: return source return None def getGenerator(self, generator_name): for gen in self.generators: if gen.name == generator_name: return gen return None def getSourceRoutes(self, source_name): for route in self.routes: if route.source_name == source_name: yield route def getSourceRoute(self, source_name, route_metadata): for route in self.getSourceRoutes(source_name): if (route_metadata is None or route.matchesMetadata(route_metadata)): return route return None def getGeneratorRoute(self, generator_name): for route in self.routes: if route.generator_name == generator_name: return route return None def getPublisher(self, target_name): for pub in self.publishers: if pub.target == target_name: return pub return None def _get_dir(self, default_rel_dir): abs_dir = os.path.join(self.root_dir, default_rel_dir) if os.path.isdir(abs_dir): return abs_dir return None def _get_configurable_dirs(self, default_rel_dir, conf_name): dirs = [] # Add custom directories from the configuration. conf_dirs = self.config.get(conf_name) if conf_dirs is not None: if isinstance(conf_dirs, str): dirs.append(os.path.join(self.root_dir, conf_dirs)) else: dirs += [os.path.join(self.root_dir, p) for p in conf_dirs] # Add the default directory if it exists. default_dir = os.path.join(self.root_dir, default_rel_dir) if os.path.isdir(default_dir): dirs.append(default_dir) return dirs
class PieCrust(object): def __init__(self, root_dir, cache=True, debug=False, theme_site=False, env=None, cache_key=None): self.root_dir = root_dir self.debug = debug self.theme_site = theme_site self.plugin_loader = PluginLoader(self) self.cache_key = cache_key or 'default' if cache: self.cache = ExtensibleCache(self.cache_dir) else: self.cache = NullExtensibleCache() if env is None: env = StandardEnvironment() self.env = env env.initialize(self) stats = env.stats stats.registerTimer('SiteConfigLoad') stats.registerTimer('PageLoad') stats.registerTimer("BuildRenderData") stats.registerTimer("BuildLazyPageData") stats.registerTimer("PageRender") stats.registerTimer("PageRenderSegments") stats.registerTimer("PageRenderLayout") stats.registerTimer("PageSerialize") stats.registerCounter('PageLoads') stats.registerCounter('PageRenderSegments') stats.registerCounter('PageRenderLayout') @cached_property def config(self): logger.debug("Creating site configuration...") start_time = time.perf_counter() if not self.theme_site: path = os.path.join(self.root_dir, CONFIG_PATH) else: path = os.path.join(self.root_dir, THEME_CONFIG_PATH) theme_path = None if not self.theme_site and self.theme_dir: theme_path = os.path.join(self.theme_dir, THEME_CONFIG_PATH) config_cache = self.cache.getCache('app') config = PieCrustConfiguration( path=path, theme_path=theme_path, cache=config_cache, theme_config=self.theme_site) local_path = os.path.join( self.root_dir, 'configs', 'local.yml') config.addVariant(local_path, raise_if_not_found=False) if self.theme_site: variant_path = os.path.join( self.root_dir, 'configs', 'theme_preview.yml') config.addVariant(variant_path, raise_if_not_found=False) self.env.stats.stepTimer('SiteConfigLoad', time.perf_counter() - start_time) return config @cached_property def assets_dirs(self): assets_dirs = self._get_configurable_dirs( ASSETS_DIR, 'site/assets_dirs') # Also add the theme directory, if any. if self.theme_dir: default_theme_dir = os.path.join(self.theme_dir, ASSETS_DIR) if os.path.isdir(default_theme_dir): assets_dirs.append(default_theme_dir) return assets_dirs @cached_property def templates_dirs(self): templates_dirs = self._get_configurable_dirs( TEMPLATES_DIR, 'site/templates_dirs') # Also, add the theme directory, if any. if self.theme_dir: default_theme_dir = os.path.join(self.theme_dir, TEMPLATES_DIR) if os.path.isdir(default_theme_dir): templates_dirs.append(default_theme_dir) return templates_dirs @cached_property def theme_dir(self): # No theme if the curent site is already a theme. if self.theme_site: return None # See if there's a theme we absolutely want. td = os.path.join(self.root_dir, THEME_DIR) if os.path.isdir(td): return td # Try to load a theme specified in the configuration. from piecrust.themes.base import ThemeLoader loader = ThemeLoader(self.root_dir) theme_dir = loader.getThemeDir() if theme_dir is not None: return theme_dir # Nothing... use the default theme. return os.path.join(RESOURCES_DIR, 'theme') @cached_property def plugins_dirs(self): return self._get_configurable_dirs(PLUGINS_DIR, 'site/plugins_dirs') @cached_property def cache_dir(self): return os.path.join(self.root_dir, CACHE_DIR, self.cache_key) @cached_property def sources(self): defs = {} for cls in self.plugin_loader.getSources(): defs[cls.SOURCE_NAME] = cls sources = [] for n, s in self.config.get('site/sources').items(): cls = defs.get(s['type']) if cls is None: raise ConfigurationError("No such page source type: %s" % s['type']) src = cls(self, n, s) sources.append(src) return sources @cached_property def routes(self): routes = [] for r in self.config.get('site/routes'): rte = Route(self, r) routes.append(rte) routes = sorted(routes, key=lambda r: r.pass_num) return routes @cached_property def publishers(self): defs_by_name = {} defs_by_scheme = {} for cls in self.plugin_loader.getPublishers(): defs_by_name[cls.PUBLISHER_NAME] = cls if cls.PUBLISHER_SCHEME: defs_by_scheme[cls.PUBLISHER_SCHEME] = cls tgts = [] publish_config = self.config.get('publish') if publish_config is None: return tgts for n, t in publish_config.items(): pub_class = None if isinstance(t, dict): pub_type = t.get('type') pub_class = defs_by_name[pub_type] pub_cfg = t elif isinstance(t, str): comps = urllib.parse.urlparse(t) pub_type = comps.scheme pub_class = defs_by_scheme[pub_type] pub_cfg = None if pub_class is None: raise ConfigurationError("No such publisher: %s" % pub_type) tgt = pub_class(self, n, pub_cfg) if pub_cfg is None: tgt.parseUrlTarget(comps) tgts.append(tgt) return tgts def getSource(self, source_name): for source in self.sources: if source.name == source_name: return source from piecrust.sources.base import SourceNotFoundError raise SourceNotFoundError(source_name) def getSourceRoute(self, source_name): for route in self.routes: if route.source_name == source_name: return route from piecrust.routing import RouteNotFoundError raise RouteNotFoundError(source_name) def getPublisher(self, target_name): for pub in self.publishers: if pub.target == target_name: return pub return None def getPage(self, source, content_item): cache_key = '%s@%s' % (source.name, content_item.spec) return self.env.page_repository.get( cache_key, lambda: Page(source, content_item)) def resolvePath(self, path): path = multi_replace(path, {'%theme_dir%': self.theme_dir}) return os.path.join(self.root_dir, path) def _get_configurable_dirs(self, default_rel_dir, conf_name): dirs = [] # Add custom directories from the configuration. conf_dirs = self.config.get(conf_name) if conf_dirs is not None: if isinstance(conf_dirs, str): dirs.append(self.resolvePath(conf_dirs)) else: dirs += [self.resolvePath(p) for p in conf_dirs] # Add the default directory if it exists. default_dir = os.path.join(self.root_dir, default_rel_dir) if os.path.isdir(default_dir): dirs.append(default_dir) return dirs