| @@ -1,3 +1,10 @@ | |||
| Version 0.8.3c11 | |||
| ================= | |||
| * `hyde serve` now picks up changes in config data automatically. | |||
| (Issue #24) | |||
| Version 0.8.3c10 | |||
| =============== | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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) | |||
| @@ -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): | |||
| @@ -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 | |||
| @@ -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 | |||
| assert "projects" in out | |||