diff --git a/hyde/engine.py b/hyde/engine.py index 1d15448..54947ca 100644 --- a/hyde/engine.py +++ b/hyde/engine.py @@ -116,12 +116,7 @@ class Engine(Application): Creates a site object from the given sitepath and the config file. """ sitepath = Folder(Folder(sitepath).fully_expanded_path) - config_file = sitepath.child(config) - logger.info("Reading site configuration from [%s]", config_file) - conf = {} - with codecs.open(config_file, 'r', 'utf-8') as stream: - conf = yaml.load(stream) - config = Config(sitepath, conf) + config = Config(sitepath, config_file=config) if deploy: config.deploy_root = deploy return Site(sitepath, config) \ No newline at end of file diff --git a/hyde/layouts/doc/content/commandline.html b/hyde/layouts/doc/content/commandline.html index 088ae9b..1ccce59 100644 --- a/hyde/layouts/doc/content/commandline.html +++ b/hyde/layouts/doc/content/commandline.html @@ -43,7 +43,7 @@ hyde [-s ] [-v] create [-l ] [-f] [-h] While basic and test are really barebones, doc is the one that generates this documentation and is completely usable. Hyde will get more layouts - as over time. + over time. Hyde tries to locate the specified layout in the following folders: diff --git a/hyde/layouts/doc/layout/root.j2 b/hyde/layouts/doc/layout/root.j2 index 8b0e85d..63ef6e9 100644 --- a/hyde/layouts/doc/layout/root.j2 +++ b/hyde/layouts/doc/layout/root.j2 @@ -62,7 +62,7 @@ diff --git a/hyde/layouts/doc/pages.yaml b/hyde/layouts/doc/pages.yaml new file mode 100644 index 0000000..03616fb --- /dev/null +++ b/hyde/layouts/doc/pages.yaml @@ -0,0 +1,3 @@ +extends: site.yaml +mode: production +deploy_root: ../../../../hydepy.github.com \ No newline at end of file diff --git a/hyde/model.py b/hyde/model.py index b97623c..a53f844 100644 --- a/hyde/model.py +++ b/hyde/model.py @@ -3,8 +3,12 @@ Contains data structures and utilities for hyde. """ from hyde.fs import File, Folder +import codecs import yaml +from hyde.util import getLoggerWithNullHandler +logger = getLoggerWithNullHandler('hyde.engine') + class Expando(object): """ A generic expando class that creates attributes from @@ -69,7 +73,7 @@ class Config(Expando): Represents the hyde configuration file """ - def __init__(self, sitepath, config_dict=None): + def __init__(self, sitepath, config_file=None, config_dict=None): default_config = dict( content_root='content', deploy_root='deploy', @@ -81,10 +85,31 @@ class Config(Expando): plugins = [] ) conf = dict(**default_config) + self.sitepath = Folder(sitepath) + conf.update(self.read_config(config_file)) if config_dict: conf.update(config_dict) super(Config, self).__init__(conf) - self.sitepath = Folder(sitepath) + + def read_config(self, config_file): + """ + Reads the configuration file and updates this + object while allowing for inherited configurations. + """ + conf_file = self.sitepath.child( + config_file if + config_file else 'site.yaml') + conf = {} + if File(conf_file).exists: + logger.info("Reading site configuration from [%s]", conf_file) + with codecs.open(conf_file, 'r', 'utf-8') as stream: + conf = yaml.load(stream) + if 'extends' in conf: + parent = self.read_config(conf['extends']) + parent.update(conf) + conf = parent + return conf + @property def deploy_root_path(self): diff --git a/hyde/tests/sites/test_jinja/site.yaml b/hyde/tests/sites/test_jinja/site.yaml index 4fc9fce..8fc9c9d 100644 --- a/hyde/tests/sites/test_jinja/site.yaml +++ b/hyde/tests/sites/test_jinja/site.yaml @@ -1,7 +1,4 @@ mode: development media_root:: media # Relative path from site root (the directory where this file exists) media_url: /media -template: hyde.ext.jinja2 -widgets: -plugins: -aggregators: \ No newline at end of file +template: hyde.ext.jinja2 \ No newline at end of file diff --git a/hyde/tests/test_generate.py b/hyde/tests/test_generate.py index a514895..09679c4 100644 --- a/hyde/tests/test_generate.py +++ b/hyde/tests/test_generate.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- + # -*- coding: utf-8 -*- """ Use nose `$ pip install nose` diff --git a/hyde/tests/test_jinja2template.py b/hyde/tests/test_jinja2template.py index 17ff0a3..2ec13f2 100644 --- a/hyde/tests/test_jinja2template.py +++ b/hyde/tests/test_jinja2template.py @@ -108,7 +108,7 @@ def test_markdown_with_extensions(): """ t = Jinja2Template(JINJA2.path) s = Site(JINJA2.path) - c = Config(JINJA2.path, dict(markdown=dict(extensions=['headerid']))) + c = Config(JINJA2.path, config_dict=dict(markdown=dict(extensions=['headerid']))) s.config = c t.configure(s) html = t.render(source, {}).strip() diff --git a/hyde/tests/test_model.py b/hyde/tests/test_model.py index 7db97f4..af45bf9 100644 --- a/hyde/tests/test_model.py +++ b/hyde/tests/test_model.py @@ -43,7 +43,8 @@ def test_expando_update(): assert x.a == 789 assert x.f == "opq" -TEST_SITE_ROOT = File(__file__).parent.child_folder('sites/test_jinja') +TEST_SITE = File(__file__).parent.child_folder('_test') + import yaml class TestConfig(object): @@ -70,27 +71,65 @@ class TestConfig(object): aggregators: """ + def setUp(self): + TEST_SITE.make() + TEST_SITE.parent.child_folder('sites/test_jinja').copy_contents_to(TEST_SITE) + + def tearDown(self): + TEST_SITE.delete() + def test_default_configuration(self): - c = Config(sitepath=TEST_SITE_ROOT) + c = Config(sitepath=TEST_SITE, config_dict={}) for root in ['content', 'layout', 'media']: name = root + '_root' path = name + '_path' assert hasattr(c, name) assert getattr(c, name) == root assert hasattr(c, path) - assert getattr(c, path) == TEST_SITE_ROOT.child_folder(root) + assert getattr(c, path) == TEST_SITE.child_folder(root) assert hasattr(c, 'plugins') assert len(c.plugins) == 0 - assert c.deploy_root_path == TEST_SITE_ROOT.child_folder('deploy') + assert c.deploy_root_path == TEST_SITE.child_folder('deploy') assert c.not_found == '404.html' def test_conf1(self): - c = Config(sitepath=TEST_SITE_ROOT, config_dict=yaml.load(self.conf1)) - assert c.content_root_path == TEST_SITE_ROOT.child_folder('stuff') + c = Config(sitepath=TEST_SITE, config_dict=yaml.load(self.conf1)) + assert c.content_root_path == TEST_SITE.child_folder('stuff') def test_conf2(self): - c = Config(sitepath=TEST_SITE_ROOT, config_dict=yaml.load(self.conf2)) - assert c.content_root_path == TEST_SITE_ROOT.child_folder('site/stuff') - assert c.media_root_path == TEST_SITE_ROOT.child_folder('mmm') - assert c.media_url == TEST_SITE_ROOT.child_folder('/media') + c = Config(sitepath=TEST_SITE, config_dict=yaml.load(self.conf2)) + assert c.content_root_path == TEST_SITE.child_folder('site/stuff') + assert c.media_root_path == TEST_SITE.child_folder('mmm') + assert c.media_url == TEST_SITE.child_folder('/media') + assert c.deploy_root_path == Folder('~/deploy_site') + + def test_read_from_file_by_default(self): + File(TEST_SITE.child('site.yaml')).write(self.conf2) + c = Config(sitepath=TEST_SITE) + assert c.content_root_path == TEST_SITE.child_folder('site/stuff') + assert c.media_root_path == TEST_SITE.child_folder('mmm') + assert c.media_url == TEST_SITE.child_folder('/media') + assert c.deploy_root_path == Folder('~/deploy_site') + + def test_read_from_specified_file(self): + File(TEST_SITE.child('another.yaml')).write(self.conf2) + c = Config(sitepath=TEST_SITE, config_file='another.yaml') + assert c.content_root_path == TEST_SITE.child_folder('site/stuff') + assert c.media_root_path == TEST_SITE.child_folder('mmm') + assert c.media_url == TEST_SITE.child_folder('/media') + assert c.deploy_root_path == Folder('~/deploy_site') + + def test_extends(self): + another = """ + extends: site.yaml + mode: production + media_root: xxx + """ + File(TEST_SITE.child('site.yaml')).write(self.conf2) + File(TEST_SITE.child('another.yaml')).write(another) + c = Config(sitepath=TEST_SITE, config_file='another.yaml') + assert c.mode == 'production' + assert c.content_root_path == TEST_SITE.child_folder('site/stuff') + assert c.media_root_path == TEST_SITE.child_folder('xxx') + assert c.media_url == TEST_SITE.child_folder('/media') assert c.deploy_root_path == Folder('~/deploy_site') \ No newline at end of file