Mercurial > piecrust2
changeset 663:3ceeca7bb71c
themes: Add support for a `--theme` argument to `chef`.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Tue, 01 Mar 2016 22:27:28 -0800 |
parents | cbd5cdec0695 |
children | 8da29a497f61 |
files | piecrust/app.py piecrust/appconfig.py piecrust/baking/baker.py piecrust/baking/worker.py piecrust/commands/base.py piecrust/commands/builtin/serving.py piecrust/commands/builtin/util.py piecrust/main.py piecrust/pathutil.py piecrust/processing/pipeline.py piecrust/processing/worker.py piecrust/serving/middlewares.py piecrust/serving/procloop.py piecrust/serving/server.py piecrust/serving/util.py piecrust/serving/wrappers.py |
diffstat | 16 files changed, 150 insertions(+), 70 deletions(-) [+] |
line wrap: on
line diff
--- a/piecrust/app.py Tue Mar 01 22:27:04 2016 -0800 +++ b/piecrust/app.py Tue Mar 01 22:27:28 2016 -0800 @@ -54,12 +54,20 @@ start_time = time.perf_counter() 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)) + if not self.theme_site: + 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)) + else: + paths.append(os.path.join(self.root_dir, THEME_CONFIG_PATH)) + preview_path = os.path.join( + self.root_dir, 'configs', 'theme_preview.yml') + if os.path.isfile(preview_path): + paths.append(preview_path) config_cache = self.cache.getCache('app') - config = PieCrustConfiguration(paths, config_cache) + config = PieCrustConfiguration(paths, config_cache, + theme_config=self.theme_site) if self.theme_dir: # We'll need to flag all page sources as coming from # the theme. @@ -107,6 +115,8 @@ @cached_property def theme_dir(self): + if self.theme_site: + return None td = self._get_dir(THEME_DIR) if td is not None: return td
--- a/piecrust/appconfig.py Tue Mar 01 22:27:04 2016 -0800 +++ b/piecrust/appconfig.py Tue Mar 01 22:27:28 2016 -0800 @@ -29,11 +29,17 @@ class PieCrustConfiguration(Configuration): - def __init__(self, paths=None, cache=None, values=None, validate=True): - super(PieCrustConfiguration, self).__init__(values, validate) + def __init__(self, paths=None, cache=None, values=None, validate=True, + theme_config=False): + super(PieCrustConfiguration, self).__init__() self.paths = paths self.cache = cache or NullCache() self.fixups = [] + self.theme_config = theme_config + # Set the values after we set the rest, since our validation needs + # our attributes. + if values: + self.setAll(values, validate=validate) def applyVariant(self, variant_path, raise_if_not_found=True): variant = self.get(variant_path) @@ -112,6 +118,10 @@ # Add the loaded values to the default configuration. values = merge_dicts(copy.deepcopy(default_configuration), values) + # Set the theme site flag. + if self.theme_config: + values['site']['theme_site'] = True + # Figure out if we need to generate the configuration for the # default content model. sitec = values.setdefault('site', {}) @@ -159,7 +169,8 @@ is_only_blog = (len(blogsc) == 1) for blog_name in blogsc: blog_cfg = get_default_content_model_for_blog( - blog_name, is_only_blog, values) + blog_name, is_only_blog, values, + theme_site=self.theme_config) values = merge_dicts(blog_cfg, values) dcm = get_default_content_model(values) @@ -199,7 +210,8 @@ 'cache_time': 28800, 'enable_debug_info': True, 'show_debug_info': False, - 'use_default_content': True + 'use_default_content': True, + 'theme_site': False }), 'baker': collections.OrderedDict({ 'no_bake_setting': 'draft', @@ -256,7 +268,8 @@ }) -def get_default_content_model_for_blog(blog_name, is_only_blog, values): +def get_default_content_model_for_blog( + blog_name, is_only_blog, values, theme_site=False): posts_fs = values['site']['posts_fs'] blog_cfg = values.get(blog_name, {}) @@ -290,6 +303,12 @@ 'category_url', url_prefix + values['site']['category_url']).lstrip('/') + tags_taxonomy = 'pages:%s_tag.%%ext%%' % tax_page_prefix + category_taxonomy = 'pages:%s_category.%%ext%%' % tax_page_prefix + if not theme_site: + tags_taxonomy += ';theme_pages:_tag.%ext%' + category_taxonomy += ';theme_pages:_category.%ext%' + return collections.OrderedDict({ 'site': collections.OrderedDict({ 'sources': collections.OrderedDict({ @@ -304,12 +323,8 @@ 'date_format': date_format, 'default_layout': default_layout, 'taxonomy_pages': collections.OrderedDict({ - 'tags': ('pages:%s_tag.%%ext%%;' - 'theme_pages:_tag.%%ext%%' % - tax_page_prefix), - 'categories': ('pages:%s_category.%%ext%%;' - 'theme_pages:_category.%%ext%%' % - tax_page_prefix) + 'tags': tags_taxonomy, + 'categories': category_taxonomy }) }) }), @@ -416,24 +431,27 @@ raise ConfigurationError("The 'site/sources' setting must be a " "dictionary.") - # Add the theme page source if no sources were defined in the theme - # configuration itself. - has_any_theme_source = False - for sn, sc in v.items(): - if sc.get('realm') == REALM_THEME: - has_any_theme_source = True - break - if not has_any_theme_source: - v['theme_pages'] = { - 'theme_source': True, - 'fs_endpoint': 'pages', - 'data_endpoint': 'site/pages', - 'item_name': 'page', - 'realm': REALM_THEME} - values['site']['routes'].append({ - 'url': '/%path:slug%', - 'source': 'theme_pages', - 'func': 'pcurl(slug)'}) + theme_site = values['site']['theme_site'] + if not theme_site: + # Add the theme page source if no sources were defined in the theme + # configuration itself. + has_any_theme_source = False + for sn, sc in v.items(): + if sc.get('realm') == REALM_THEME: + has_any_theme_source = True + break + if not has_any_theme_source: + v['theme_pages'] = { + 'theme_source': True, + 'fs_endpoint': 'pages', + 'ignore_missing_dir': True, + 'data_endpoint': 'site/pages', + 'item_name': 'page', + 'realm': REALM_THEME} + values['site']['routes'].append({ + 'url': '/%path:slug%', + 'source': 'theme_pages', + 'func': 'pcurl(slug)'}) # Sources have the `default` scanner by default, duh. Also, a bunch # of other default values for other configuration stuff.
--- a/piecrust/baking/baker.py Tue Mar 01 22:27:04 2016 -0800 +++ b/piecrust/baking/baker.py Tue Mar 01 22:27:28 2016 -0800 @@ -551,7 +551,8 @@ previous_record_path=previous_record_path, config_variant=self.applied_config_variant, config_values=self.applied_config_values, - force=self.force, debug=self.app.debug) + force=self.force, debug=self.app.debug, + theme_site=self.app.theme_site) pool = WorkerPool( worker_count=worker_count, batch_size=batch_size,
--- a/piecrust/baking/worker.py Tue Mar 01 22:27:04 2016 -0800 +++ b/piecrust/baking/worker.py Tue Mar 01 22:27:28 2016 -0800 @@ -15,10 +15,10 @@ class BakeWorkerContext(object): - def __init__(self, root_dir, sub_cache_dir, out_dir, + def __init__(self, root_dir, sub_cache_dir, out_dir, *, previous_record_path=None, config_variant=None, config_values=None, - force=False, debug=False): + force=False, debug=False, theme_site=False): self.root_dir = root_dir self.sub_cache_dir = sub_cache_dir self.out_dir = out_dir @@ -27,6 +27,7 @@ self.config_values = config_values self.force = force self.debug = debug + self.theme_site = theme_site self.app = None self.previous_record = None self.previous_record_index = None @@ -39,7 +40,8 @@ def initialize(self): # Create the app local to this worker. - app = PieCrust(self.ctx.root_dir, debug=self.ctx.debug) + app = PieCrust(self.ctx.root_dir, debug=self.ctx.debug, + theme_site=self.ctx.theme_site) app._useSubCacheDir(self.ctx.sub_cache_dir) app.config.set('baker/is_baking', True) app.config.set('baker/worker_id', self.wid)
--- a/piecrust/commands/base.py Tue Mar 01 22:27:04 2016 -0800 +++ b/piecrust/commands/base.py Tue Mar 01 22:27:28 2016 -0800 @@ -32,7 +32,7 @@ def checkedRun(self, ctx): if ctx.app.root_dir is None and self.requires_website: - raise SiteNotFoundError() + raise SiteNotFoundError(theme=ctx.app.theme_site) return self.run(ctx)
--- a/piecrust/commands/builtin/serving.py Tue Mar 01 22:27:04 2016 -0800 +++ b/piecrust/commands/builtin/serving.py Tue Mar 01 22:27:28 2016 -0800 @@ -46,6 +46,7 @@ run_werkzeug_server( root_dir, host, port, debug_piecrust=debug, + theme_site=ctx.args.theme, sub_cache_dir=ctx.app.sub_cache_dir, use_debugger=debug, use_reloader=ctx.args.use_reloader) @@ -62,6 +63,7 @@ run_gunicorn_server( root_dir, debug_piecrust=debug, + theme_site=ctx.args.theme, sub_cache_dir=ctx.app.sub_cache_dir, gunicorn_options=options)
--- a/piecrust/commands/builtin/util.py Tue Mar 01 22:27:04 2016 -0800 +++ b/piecrust/commands/builtin/util.py Tue Mar 01 22:27:28 2016 -0800 @@ -4,7 +4,7 @@ import codecs import logging import yaml -from piecrust.app import CONFIG_PATH +from piecrust.app import CONFIG_PATH, THEME_CONFIG_PATH from piecrust.commands.base import ChefCommand @@ -19,7 +19,8 @@ self.requires_website = False def setupParser(self, parser, app): - parser.add_argument('destination', + parser.add_argument( + 'destination', help="The destination directory in which to create the website.") def run(self, ctx): @@ -31,6 +32,9 @@ os.makedirs(destination, 0o755) config_path = os.path.join(destination, CONFIG_PATH) + if ctx.args.theme: + config_path = os.path.join(destination, THEME_CONFIG_PATH) + if not os.path.isdir(os.path.dirname(config_path)): os.makedirs(os.path.dirname(config_path), 0o755)
--- a/piecrust/main.py Tue Mar 01 22:27:04 2016 -0800 +++ b/piecrust/main.py Tue Mar 01 22:27:28 2016 -0800 @@ -40,7 +40,8 @@ class NullPieCrust: - def __init__(self): + def __init__(self, theme_site=False): + self.theme_site = theme_site self.root_dir = None self.debug = False self.templates_dirs = [] @@ -50,6 +51,9 @@ self.plugin_loader = PluginLoader(self) self.env = None + def useSubCache(self, cache_name, cache_key): + pass + def main(): if sys.platform == 'darwin': @@ -84,6 +88,10 @@ '--root', help="The root directory of the website.") parser.add_argument( + '--theme', + action='store_true', + help="Makes the current command apply to a theme website.") + parser.add_argument( '--config', dest='config_variant', help="The configuration variant to use for this command.") @@ -196,15 +204,19 @@ root = os.path.expanduser(pre_args.root) else: try: - root = find_app_root() + root = find_app_root(theme=pre_args.theme) except SiteNotFoundError: root = None if not root: - app = NullPieCrust() + app = NullPieCrust( + theme_site=pre_args.theme) else: - app = PieCrust(root, cache=(not pre_args.no_cache), - debug=pre_args.debug) + app = PieCrust( + root, + theme_site=pre_args.theme, + cache=(not pre_args.no_cache), + debug=pre_args.debug) # Build a hash for a custom cache directory. cache_key = 'default'
--- a/piecrust/pathutil.py Tue Mar 01 22:27:04 2016 -0800 +++ b/piecrust/pathutil.py Tue Mar 01 22:27:28 2016 -0800 @@ -2,18 +2,23 @@ import os import os.path import fnmatch +from piecrust import CONFIG_PATH, THEME_CONFIG_PATH re_terminal_path = re.compile(r'^(\w\:)?[/\\]$') class SiteNotFoundError(Exception): - def __init__(self, root=None, msg=None): + def __init__(self, root=None, msg=None, theme=False): if not root: root = os.getcwd() + + cfg_name = CONFIG_PATH + if theme: + cfg_name = THEME_CONFIG_PATH + full_msg = ("No PieCrust website in '%s' " - "('config.yml' not found!)" % - root) + "('%s' not found!)" % (root, cfg_name)) if msg: full_msg += ": " + msg else: @@ -21,14 +26,18 @@ Exception.__init__(self, full_msg) -def find_app_root(cwd=None): +def find_app_root(cwd=None, theme=False): if cwd is None: cwd = os.getcwd() - while not os.path.isfile(os.path.join(cwd, 'config.yml')): + cfg_name = CONFIG_PATH + if theme: + cfg_name = THEME_CONFIG_PATH + + while not os.path.isfile(os.path.join(cwd, cfg_name)): cwd = os.path.dirname(cwd) if not cwd or re_terminal_path.match(cwd): - raise SiteNotFoundError(cwd) + raise SiteNotFoundError(cwd, theme=theme) return cwd
--- a/piecrust/processing/pipeline.py Tue Mar 01 22:27:04 2016 -0800 +++ b/piecrust/processing/pipeline.py Tue Mar 01 22:27:28 2016 -0800 @@ -252,7 +252,8 @@ ctx = ProcessingWorkerContext( self.app.root_dir, self.out_dir, self.tmp_dir, - self.force, self.app.debug) + force=self.force, debug=self.app.debug, + theme_site=self.app.theme_site) ctx.enabled_processors = self.enabled_processors if self.additional_processors_factories is not None: ctx.additional_processors = [
--- a/piecrust/processing/worker.py Tue Mar 01 22:27:04 2016 -0800 +++ b/piecrust/processing/worker.py Tue Mar 01 22:27:28 2016 -0800 @@ -23,13 +23,14 @@ class ProcessingWorkerContext(object): - def __init__(self, root_dir, out_dir, tmp_dir, - force=False, debug=False): + def __init__(self, root_dir, out_dir, tmp_dir, *, + force=False, debug=False, theme_site=False): self.root_dir = root_dir self.out_dir = out_dir self.tmp_dir = tmp_dir self.force = force self.debug = debug + self.theme_site = theme_site self.is_profiling = False self.enabled_processors = None self.additional_processors = None @@ -59,7 +60,8 @@ def initialize(self): # Create the app local to this worker. - app = PieCrust(self.ctx.root_dir, debug=self.ctx.debug) + app = PieCrust(self.ctx.root_dir, debug=self.ctx.debug, + theme_site=self.ctx.theme_site) app.env.registerTimer("PipelineWorker_%d_Total" % self.wid) app.env.registerTimer("PipelineWorkerInit") app.env.registerTimer("JobReceive")
--- a/piecrust/serving/middlewares.py Tue Mar 01 22:27:04 2016 -0800 +++ b/piecrust/serving/middlewares.py Tue Mar 01 22:27:28 2016 -0800 @@ -40,11 +40,12 @@ class PieCrustDebugMiddleware(object): """ WSGI middleware that handles debugging of PieCrust stuff. """ - def __init__(self, app, root_dir, debug=False, + def __init__(self, app, root_dir, debug=False, theme_site=False, sub_cache_dir=None, run_sse_check=None): self.app = app self.root_dir = root_dir self.debug = debug + self.theme_site = theme_site self.sub_cache_dir = sub_cache_dir self.run_sse_check = run_sse_check self._proc_loop = None @@ -63,6 +64,7 @@ # time so we let the implementation tell us if this is OK. from piecrust.serving.procloop import ProcessingLoop self._proc_loop = ProcessingLoop(root_dir, self._out_dir, + theme_site=theme_site, sub_cache_dir=sub_cache_dir, debug=debug) self._proc_loop.start()
--- a/piecrust/serving/procloop.py Tue Mar 01 22:27:04 2016 -0800 +++ b/piecrust/serving/procloop.py Tue Mar 01 22:27:28 2016 -0800 @@ -6,6 +6,7 @@ import logging import itertools import threading +from piecrust import CONFIG_PATH, THEME_CONFIG_PATH from piecrust.app import PieCrust from piecrust.processing.pipeline import ProcessorPipeline @@ -74,25 +75,30 @@ class ProcessingLoop(threading.Thread): - def __init__(self, root_dir, out_dir, sub_cache_dir=None, debug=False): + def __init__(self, root_dir, out_dir, sub_cache_dir=None, + theme_site=False, debug=False): super(ProcessingLoop, self).__init__( name='pipeline-reloader', daemon=True) self.root_dir = root_dir self.out_dir = out_dir self.sub_cache_dir = sub_cache_dir self.debug = debug + self.theme_site = theme_site self.last_status_id = 0 self.interval = 1 self.app = None self._roots = [] self._monitor_assets_root = False self._paths = set() - self._config_path = os.path.join(root_dir, 'config.yml') self._record = None self._last_bake = 0 self._last_config_mtime = 0 self._obs = [] self._obs_lock = threading.Lock() + if theme_site: + self._config_path = os.path.join(root_dir, THEME_CONFIG_PATH) + else: + self._config_path = os.path.join(root_dir, CONFIG_PATH) def addObserver(self, obs): with self._obs_lock: @@ -156,7 +162,8 @@ def _initPipeline(self): # Create the app and pipeline. - self.app = PieCrust(root_dir=self.root_dir, debug=self.debug) + self.app = PieCrust(root_dir=self.root_dir, debug=self.debug, + theme_site=self.theme_site) if self.sub_cache_dir: self.app._useSubCacheDir(self.sub_cache_dir) self.pipeline = ProcessorPipeline(self.app, self.out_dir)
--- a/piecrust/serving/server.py Tue Mar 01 22:27:04 2016 -0800 +++ b/piecrust/serving/server.py Tue Mar 01 22:27:28 2016 -0800 @@ -71,10 +71,12 @@ class Server(object): def __init__(self, root_dir, - debug=False, sub_cache_dir=None, enable_debug_info=True, + debug=False, theme_site=False, + sub_cache_dir=None, enable_debug_info=True, root_url='/', static_preview=True): self.root_dir = root_dir self.debug = debug + self.theme_site = theme_site self.sub_cache_dir = sub_cache_dir self.enable_debug_info = enable_debug_info self.root_url = root_url @@ -110,6 +112,7 @@ # Create the app for this request. app = get_app_for_server(self.root_dir, debug=self.debug, + theme_site=self.theme_site, sub_cache_dir=self.sub_cache_dir, root_url=self.root_url) if (app.config.get('site/enable_debug_info') and @@ -302,9 +305,9 @@ desc = [] while exception is not None: if isinstance(exception, MultipleNotFound): - desc += [e.description for e in exception._nfes] + desc += [str(e) for e in exception._nfes] elif isinstance(exception, HTTPException): - desc.append(exception.description) + desc.append(exception.get_description()) else: desc.append(str(exception))
--- a/piecrust/serving/util.py Tue Mar 01 22:27:04 2016 -0800 +++ b/piecrust/serving/util.py Tue Mar 01 22:27:28 2016 -0800 @@ -16,9 +16,9 @@ logger = logging.getLogger(__name__) -def get_app_for_server(root_dir, debug=False, sub_cache_dir=None, - root_url='/'): - app = PieCrust(root_dir=root_dir, debug=debug) +def get_app_for_server(root_dir, debug=False, theme_site=False, + sub_cache_dir=None, root_url='/'): + app = PieCrust(root_dir=root_dir, debug=debug, theme_site=theme_site) if sub_cache_dir: app._useSubCacheDir(sub_cache_dir) app.config.set('site/root', root_url)
--- a/piecrust/serving/wrappers.py Tue Mar 01 22:27:04 2016 -0800 +++ b/piecrust/serving/wrappers.py Tue Mar 01 22:27:28 2016 -0800 @@ -9,7 +9,8 @@ def run_werkzeug_server(root_dir, host, port, - debug_piecrust=False, sub_cache_dir=None, + debug_piecrust=False, theme_site=False, + sub_cache_dir=None, use_debugger=False, use_reloader=False): from werkzeug.serving import run_simple @@ -25,6 +26,7 @@ app = _get_piecrust_server(root_dir, debug=debug_piecrust, + theme_site=theme_site, sub_cache_dir=sub_cache_dir, run_sse_check=_run_sse_check) @@ -78,7 +80,8 @@ def run_gunicorn_server(root_dir, - debug_piecrust=False, sub_cache_dir=None, + debug_piecrust=False, theme_site=False, + sub_cache_dir=None, gunicorn_options=None): from gunicorn.app.base import BaseApplication @@ -98,6 +101,7 @@ app = _get_piecrust_server(root_dir, debug=debug_piecrust, + theme_site=theme_site, sub_cache_dir=sub_cache_dir) gunicorn_options = gunicorn_options or {} @@ -105,14 +109,17 @@ app_wrapper.run() -def _get_piecrust_server(root_dir, debug=False, sub_cache_dir=None, - run_sse_check=None): +def _get_piecrust_server( + root_dir, debug=False, theme_site=False, + sub_cache_dir=None, run_sse_check=None): from piecrust.serving.middlewares import ( StaticResourcesMiddleware, PieCrustDebugMiddleware) from piecrust.serving.server import WsgiServer - app = WsgiServer(root_dir, debug=debug, sub_cache_dir=sub_cache_dir) + app = WsgiServer(root_dir, debug=debug, theme_site=theme_site, + sub_cache_dir=sub_cache_dir) app = StaticResourcesMiddleware(app) app = PieCrustDebugMiddleware(app, root_dir, + theme_site=theme_site, sub_cache_dir=sub_cache_dir, run_sse_check=run_sse_check) return app