From 65828484a47bc4fa19cb978c19180f6028281626 Mon Sep 17 00:00:00 2001 From: Lakshmi Vyasarajan Date: Mon, 20 Jun 2011 00:41:00 +0530 Subject: [PATCH] `hyde serve` now picks up changes in config data automatically. (Issue #24) --- CHANGELOG.rst | 7 +++++++ hyde/generator.py | 34 +++++++++++++++++++++++----------- hyde/model.py | 21 +++++++++++++++++++-- hyde/server.py | 3 +-- hyde/site.py | 26 ++++++++++++++++++++++---- hyde/tests/ext/test_sorter.py | 1 - hyde/tests/test_generate.py | 4 ++-- 7 files changed, 74 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 34d4c52..3574804 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,3 +1,10 @@ +Version 0.8.3c11 +================= + +* `hyde serve` now picks up changes in config data automatically. + (Issue #24) + + Version 0.8.3c10 =============== diff --git a/hyde/generator.py b/hyde/generator.py index df3d06b..040ce70 100644 --- a/hyde/generator.py +++ b/hyde/generator.py @@ -27,15 +27,19 @@ class Generator(object): self.site = site self.generated_once = False self.deps = Dependents(site.sitepath) + self.create_context() + self.template = None + Plugin.load_all(site) + + self.events = Plugin.get_proxy(self.site) + + def create_context(self): + site = self.site self.__context__ = dict(site=site) if hasattr(site.config, 'context'): site.context = Context.load(site.sitepath, site.config.context) self.__context__.update(site.context) - self.template = None - Plugin.load_all(site) - - self.events = Plugin.get_proxy(self.site) @contextmanager def context_for_resource(self, resource): @@ -43,8 +47,6 @@ class Generator(object): Context manager that intializes the context for a given resource and rolls it back after the resource is processed. """ - # TODO: update metadata and other resource - # specific properties here. self.__context__.update( resource=resource, node=resource.node, @@ -103,10 +105,7 @@ class Generator(object): Checks if the site requries a reload and loads if necessary. """ - #TODO: Perhaps this is better suited in Site - if not len(self.site.content.child_nodes): - logger.info("Reading site contents") - self.site.load() + self.site.reload_if_needed() def finalize(self): """ @@ -154,8 +153,9 @@ class Generator(object): last generation. """ logger.debug("Checking for changes in %s" % resource) - self.load_site_if_needed() self.load_template_if_needed() + self.load_site_if_needed() + target = File(self.site.config.deploy_root_path.child( resource.relative_deploy_path)) if not target.exists or target.older_than(resource.source_file): @@ -164,6 +164,11 @@ class Generator(object): if resource.source_file.is_binary: logger.debug("No Changes found in %s" % resource) return False + if self.site.config.needs_refresh() or \ + not target.has_changed_since(self.site.config.last_modified): + logger.debug("Site configuration changed") + return True + deps = self.get_dependencies(resource) if not deps or None in deps: logger.debug("No changes found in %s" % resource) @@ -282,8 +287,14 @@ class Generator(object): except HydeException: self.generate_all() + def refresh_config(self): + if self.site.config.needs_refresh(): + logger.debug("Refreshing configuration and context") + self.site.refresh_config() + self.create_context() def __generate_node__(self, node, incremental=False): + self.refresh_config() for node in node.walk(): logger.debug("Generating Node [%s]", node) self.events.begin_node(node) @@ -293,6 +304,7 @@ class Generator(object): def __generate_resource__(self, resource, incremental=False): + self.refresh_config() if not resource.is_processable: logger.debug("Skipping [%s]", resource) return diff --git a/hyde/model.py b/hyde/model.py index 4b1d2a6..ed73191 100644 --- a/hyde/model.py +++ b/hyde/model.py @@ -6,8 +6,9 @@ from hyde.fs import File, Folder import codecs import yaml - +from datetime import datetime from UserDict import IterableUserDict + from hyde.util import getLoggerWithNullHandler logger = getLoggerWithNullHandler('hyde.engine') @@ -135,13 +136,27 @@ class Config(Expando): plugins = [], ignore = [ "*~", "*.bak" ] ) - conf = dict(**default_config) + self.config_file = config_file + self.config_dict = config_dict + self.load_time = datetime.min + self.config_files = [] self.sitepath = Folder(sitepath) + conf = dict(**default_config) conf.update(self.read_config(config_file)) if config_dict: conf.update(config_dict) super(Config, self).__init__(conf) + @property + def last_modified(self): + return max((conf.last_modified for conf in self.config_files)) + + def needs_refresh(self): + if not self.config_files: + return True + return any((conf.has_changed_since(self.load_time) + for conf in self.config_files)) + def read_config(self, config_file): """ Reads the configuration file and updates this @@ -152,6 +167,7 @@ class Config(Expando): config_file else 'site.yaml') conf = {} if File(conf_file).exists: + self.config_files.append(File(conf_file)) logger.info("Reading site configuration from [%s]", conf_file) with codecs.open(conf_file, 'r', 'utf-8') as stream: conf = yaml.load(stream) @@ -159,6 +175,7 @@ class Config(Expando): parent = self.read_config(conf['extends']) parent.update(conf) conf = parent + self.load_time = datetime.now() return conf diff --git a/hyde/server.py b/hyde/server.py index 0eade0e..4157424 100644 --- a/hyde/server.py +++ b/hyde/server.py @@ -8,6 +8,7 @@ import select import threading import urlparse import urllib +from datetime import datetime from SimpleHTTPServer import SimpleHTTPRequestHandler from BaseHTTPServer import HTTPServer from hyde.fs import File, Folder @@ -18,8 +19,6 @@ from hyde.exceptions import HydeException from hyde.util import getLoggerWithNullHandler logger = getLoggerWithNullHandler('hyde.server') -from datetime import datetime - class HydeRequestHandler(SimpleHTTPRequestHandler): """ Serves files by regenerating the resource (or) diff --git a/hyde/site.py b/hyde/site.py index dc10b36..68f466b 100644 --- a/hyde/site.py +++ b/hyde/site.py @@ -5,12 +5,13 @@ Parses & holds information about the site to be generated. import os import fnmatch import urlparse +from functools import wraps + from hyde.exceptions import HydeException from hyde.fs import FS, File, Folder from hyde.model import Config - from hyde.util import getLoggerWithNullHandler -from functools import wraps + def path_normalized(f): @wraps(f) @@ -359,7 +360,6 @@ class RootNode(Node): return self.add_resource(afile) - class Site(object): """ Represents the site to be generated. @@ -373,11 +373,29 @@ class Site(object): self.plugins = [] self.context = {} + def refresh_config(self): + """ + Refreshes config data if one or more config files have + changed. Note that this does not refresh the meta data. + """ + if self.config.needs_refresh(): + logger.debug("Refreshing config data") + self.config = Config(self.sitepath, + self.config.config_file, + self.config.config_dict) + + def reload_if_needed(self): + """ + Reloads if the site has not been loaded before or if the + configuration has changed since the last load. + """ + if not len(self.content.child_nodes): + self.load() + def load(self): """ Walks the content and media folders to load up the sitemap. """ - self.content.load() def content_url(self, path): diff --git a/hyde/tests/ext/test_sorter.py b/hyde/tests/ext/test_sorter.py index fa2b46d..9b48b27 100644 --- a/hyde/tests/ext/test_sorter.py +++ b/hyde/tests/ext/test_sorter.py @@ -303,7 +303,6 @@ class TestSorterMeta(object): "another-sad-post.html", "happy-post.html"] for r in s.content.walk_resources(): - print r.meta.to_dict() expected = r.name in have_index assert attributes_checker(r, ['meta.index']) == expected diff --git a/hyde/tests/test_generate.py b/hyde/tests/test_generate.py index 09679c4..b4692fc 100644 --- a/hyde/tests/test_generate.py +++ b/hyde/tests/test_generate.py @@ -77,9 +77,9 @@ class TestGenerator(object): resource = site.content.resource_from_path(TEST_SITE.child('content/about.html')) gen = Generator(site) gen.generate_all() - assert not gen.has_resource_changed(resource) import time time.sleep(1) + assert not gen.has_resource_changed(resource) text = resource.source_file.read_all() resource.source_file.write(text) assert gen.has_resource_changed(resource) @@ -160,4 +160,4 @@ main: assert "abc = def" in out assert "home" in out assert "articles" in out - assert "projects" in out \ No newline at end of file + assert "projects" in out