Mercurial > piecrust2
comparison piecrust/appconfig.py @ 585:25df894f9ab9
internal: Some fixes to the new app configuration.
* Tweak order of source registration.
* Add some missing default settings.
* Fix some validation code.
* Add better error handling to validation.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sat, 02 Jan 2016 16:39:26 -0800 |
parents | 9ccc933ac2c7 |
children | 3ceeca7bb71c |
comparison
equal
deleted
inserted
replaced
584:9ccc933ac2c7 | 585:25df894f9ab9 |
---|---|
76 logger.debug("Outdated cache key '%s' (expected '%s')." % ( | 76 logger.debug("Outdated cache key '%s' (expected '%s')." % ( |
77 actual_cache_key, cache_key)) | 77 actual_cache_key, cache_key)) |
78 | 78 |
79 logger.debug("Loading configuration from: %s" % self.paths) | 79 logger.debug("Loading configuration from: %s" % self.paths) |
80 values = {} | 80 values = {} |
81 for i, p in enumerate(self.paths): | 81 try: |
82 with open(p, 'r', encoding='utf-8') as fp: | 82 for i, p in enumerate(self.paths): |
83 loaded_values = yaml.load( | 83 with open(p, 'r', encoding='utf-8') as fp: |
84 fp.read(), | 84 loaded_values = yaml.load( |
85 Loader=ConfigurationLoader) | 85 fp.read(), |
86 if loaded_values is None: | 86 Loader=ConfigurationLoader) |
87 loaded_values = {} | 87 if loaded_values is None: |
88 loaded_values = {} | |
89 for fixup in self.fixups: | |
90 fixup(i, loaded_values) | |
91 merge_dicts(values, loaded_values) | |
92 | |
88 for fixup in self.fixups: | 93 for fixup in self.fixups: |
89 fixup(i, loaded_values) | 94 fixup(len(self.paths), values) |
90 merge_dicts(values, loaded_values) | 95 |
91 | 96 self._values = self._validateAll(values) |
92 for fixup in self.fixups: | 97 except Exception as ex: |
93 fixup(len(self.paths), values) | 98 raise Exception("Error loading configuration from: %s" % |
94 | 99 ', '.join(self.paths)) from ex |
95 self._values = self._validateAll(values) | |
96 | 100 |
97 logger.debug("Caching configuration...") | 101 logger.debug("Caching configuration...") |
98 self._values['__cache_key'] = cache_key | 102 self._values['__cache_key'] = cache_key |
99 config_text = json.dumps(self._values) | 103 config_text = json.dumps(self._values) |
100 self.cache.write('config.json', config_text) | 104 self.cache.write('config.json', config_text) |
127 | 131 |
128 def _visitor(path, val, parent_val, parent_key): | 132 def _visitor(path, val, parent_val, parent_key): |
129 callback_name = '_validate_' + path.replace('/', '_') | 133 callback_name = '_validate_' + path.replace('/', '_') |
130 callback = globs.get(callback_name) | 134 callback = globs.get(callback_name) |
131 if callback: | 135 if callback: |
132 val2 = callback(val, values, cache_writer) | 136 try: |
137 val2 = callback(val, values, cache_writer) | |
138 except Exception as ex: | |
139 raise Exception("Error raised in validator '%s'." % | |
140 callback_name) from ex | |
133 if val2 is None: | 141 if val2 is None: |
134 raise Exception("Validator '%s' isn't returning a " | 142 raise Exception("Validator '%s' isn't returning a " |
135 "coerced value." % callback_name) | 143 "coerced value." % callback_name) |
136 parent_val[parent_key] = val2 | 144 parent_val[parent_key] = val2 |
137 | 145 |
140 return values | 148 return values |
141 | 149 |
142 def _generateDefaultContentModel(self, values): | 150 def _generateDefaultContentModel(self, values): |
143 dcmcopy = copy.deepcopy(default_content_model_base) | 151 dcmcopy = copy.deepcopy(default_content_model_base) |
144 values = merge_dicts(dcmcopy, values) | 152 values = merge_dicts(dcmcopy, values) |
145 | |
146 dcm = get_default_content_model(values) | |
147 values = merge_dicts(dcm, values) | |
148 | 153 |
149 blogsc = values['site'].get('blogs') | 154 blogsc = values['site'].get('blogs') |
150 if blogsc is None: | 155 if blogsc is None: |
151 blogsc = ['posts'] | 156 blogsc = ['posts'] |
152 values['site']['blogs'] = blogsc | 157 values['site']['blogs'] = blogsc |
154 is_only_blog = (len(blogsc) == 1) | 159 is_only_blog = (len(blogsc) == 1) |
155 for blog_name in blogsc: | 160 for blog_name in blogsc: |
156 blog_cfg = get_default_content_model_for_blog( | 161 blog_cfg = get_default_content_model_for_blog( |
157 blog_name, is_only_blog, values) | 162 blog_name, is_only_blog, values) |
158 values = merge_dicts(blog_cfg, values) | 163 values = merge_dicts(blog_cfg, values) |
164 | |
165 dcm = get_default_content_model(values) | |
166 values = merge_dicts(dcm, values) | |
159 | 167 |
160 return values | 168 return values |
161 | 169 |
162 | 170 |
163 class _ConfigCacheWriter(object): | 171 class _ConfigCacheWriter(object): |
182 'auto_formats': collections.OrderedDict([ | 190 'auto_formats': collections.OrderedDict([ |
183 ('html', ''), | 191 ('html', ''), |
184 ('md', 'markdown'), | 192 ('md', 'markdown'), |
185 ('textile', 'textile')]), | 193 ('textile', 'textile')]), |
186 'default_auto_format': 'md', | 194 'default_auto_format': 'md', |
195 'default_pagination_source': None, | |
187 'pagination_suffix': '/%num%', | 196 'pagination_suffix': '/%num%', |
188 'slugify_mode': 'encode', | 197 'slugify_mode': 'encode', |
189 'themes_sources': [DEFAULT_THEME_SOURCE], | 198 'themes_sources': [DEFAULT_THEME_SOURCE], |
190 'cache_time': 28800, | 199 'cache_time': 28800, |
191 'enable_debug_info': True, | 200 'enable_debug_info': True, |
192 'show_debug_info': False, | 201 'show_debug_info': False, |
193 'use_default_content': True | 202 'use_default_content': True |
194 }), | 203 }), |
195 'baker': collections.OrderedDict({ | 204 'baker': collections.OrderedDict({ |
196 'no_bake_setting': 'draft' | 205 'no_bake_setting': 'draft', |
206 'workers': None, | |
207 'batch_size': None | |
197 }) | 208 }) |
198 }) | 209 }) |
199 | 210 |
200 | 211 |
201 default_content_model_base = collections.OrderedDict({ | 212 default_content_model_base = collections.OrderedDict({ |
424 'source': 'theme_pages', | 435 'source': 'theme_pages', |
425 'func': 'pcurl(slug)'}) | 436 'func': 'pcurl(slug)'}) |
426 | 437 |
427 # Sources have the `default` scanner by default, duh. Also, a bunch | 438 # Sources have the `default` scanner by default, duh. Also, a bunch |
428 # of other default values for other configuration stuff. | 439 # of other default values for other configuration stuff. |
440 reserved_endpoints = set(['piecrust', 'site', 'page', 'route', | |
441 'assets', 'pagination', 'siblings', | |
442 'family']) | |
429 for sn, sc in v.items(): | 443 for sn, sc in v.items(): |
430 if not isinstance(sc, dict): | 444 if not isinstance(sc, dict): |
431 raise ConfigurationError("All sources in 'site/sources' must " | 445 raise ConfigurationError("All sources in 'site/sources' must " |
432 "be dictionaries.") | 446 "be dictionaries.") |
433 sc.setdefault('type', 'default') | 447 sc.setdefault('type', 'default') |
437 sc.setdefault('data_type', 'iterator') | 451 sc.setdefault('data_type', 'iterator') |
438 sc.setdefault('item_name', sn) | 452 sc.setdefault('item_name', sn) |
439 sc.setdefault('items_per_page', 5) | 453 sc.setdefault('items_per_page', 5) |
440 sc.setdefault('date_format', DEFAULT_DATE_FORMAT) | 454 sc.setdefault('date_format', DEFAULT_DATE_FORMAT) |
441 sc.setdefault('realm', REALM_USER) | 455 sc.setdefault('realm', REALM_USER) |
456 | |
457 # Validate endpoints. | |
458 endpoint = sc['data_endpoint'] | |
459 if endpoint in reserved_endpoints: | |
460 raise ConfigurationError( | |
461 "Source '%s' is using a reserved endpoint name: %s" % | |
462 (sn, endpoint)) | |
442 | 463 |
443 return v | 464 return v |
444 | 465 |
445 | 466 |
446 def _validate_site_routes(v, values, cache): | 467 def _validate_site_routes(v, values, cache): |
477 for tn, tc in v.items(): | 498 for tn, tc in v.items(): |
478 tc.setdefault('multiple', False) | 499 tc.setdefault('multiple', False) |
479 tc.setdefault('term', tn) | 500 tc.setdefault('term', tn) |
480 tc.setdefault('page', '_%s.%%ext%%' % tc['term']) | 501 tc.setdefault('page', '_%s.%%ext%%' % tc['term']) |
481 | 502 |
482 # Validate endpoints, and make sure the theme has a default source. | |
483 reserved_endpoints = set(['piecrust', 'site', 'page', 'route', | |
484 'assets', 'pagination', 'siblings', | |
485 'family']) | |
486 for name, src in values['site']['sources'].items(): | |
487 endpoint = src['data_endpoint'] | |
488 if endpoint in reserved_endpoints: | |
489 raise ConfigurationError( | |
490 "Source '%s' is using a reserved endpoint name: %s" % | |
491 (name, endpoint)) | |
492 | |
493 return v | 503 return v |
494 | 504 |
495 | 505 |
496 def _validate_site_plugins(v, values, cache): | 506 def _validate_site_plugins(v, values, cache): |
497 if isinstance(v, str): | 507 if isinstance(v, str): |