def begin_site(self): """ Find all the styl files and set their relative deploy path. """ for resource in self.site.content.walk_resources(): if resource.source_file.kind == 'styl': new_name = resource.source_file.name_without_extension + ".css" target_folder = File(resource.relative_deploy_path).parent resource.relative_deploy_path = target_folder.child(new_name)
def test_copy_folder_target_missing(): DATA_ROOT.delete() assert not DATA_ROOT.exists DATA_JINJA2 = DATA_ROOT.child_folder(JINJA2.name) assert not DATA_JINJA2.exists JINJA2.copy_to(DATA_ROOT) assert DATA_JINJA2.exists for f in [HELPERS, INDEX, LAYOUT]: assert File(DATA_JINJA2.child(f.name)).exists
def test_can_execute_optipng(self): s = Site(TEST_SITE) s.config.mode = "production" s.config.plugins = ['hyde.ext.plugins.optipng.OptiPNGPlugin'] paths = ['/usr/local/bin/optipng'] optipng = [path for path in paths if File(path).exists] if not optipng: assert False, "Cannot find the optipng executable" optipng = optipng[0] s.config.optipng = Expando(dict(app=optipng, args=dict(quiet=""))) source = File(TEST_SITE.child('content/media/images/hyde-lt-b.png')) target = File( Folder( s.config.deploy_root_path).child('media/images/hyde-lt-b.png')) gen = Generator(s) gen.generate_resource_at_path(source) assert target.exists assert target.size < source.size
def __generate_resource__(self, resource, incremental=False): if not resource.is_processable: logger.debug("Skipping [%s]", resource) return if incremental and not self.has_resource_changed(resource): logger.debug("No changes found. Skipping resource [%s]", resource) return logger.debug("Processing [%s]", resource) with self.context_for_resource(resource) as context: if resource.source_file.is_text: self.update_deps(resource) if resource.uses_template: logger.debug("Rendering [%s]", resource) context = self.events.begin_render_resource( resource, context) or context try: text = self.template.render_resource(resource, context) except Exception: logger.error("Error occurred when" " processing template: [%s]" % resource) raise self.events.render_resource_complete(resource, context) else: text = resource.source_file.read_all() text = self.events.begin_text_resource(resource, text) or text text = self.events.text_resource_complete(resource, text) or text target = File( self.site.config.deploy_root_path.child( resource.relative_deploy_path)) target.parent.make() target.write(text) else: logger.debug("Copying binary file [%s]", resource) self.events.begin_binary_resource(resource) target = File( self.site.config.deploy_root_path.child( resource.relative_deploy_path)) target.parent.make() resource.source_file.copy_to(target) self.events.binary_resource_complete(resource)
def test_generate_resource_from_path(self): site = Site(TEST_SITE) site.load() gen = Generator(site) gen.generate_resource_at_path(TEST_SITE.child('content/about.html')) about = File(Folder(site.config.deploy_root_path).child('about.html')) assert about.exists text = about.read_all() q = PyQuery(text) assert about.name in q("div#main").text()
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: 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) if 'extends' in conf: parent = self.read_config(conf['extends']) parent.update(conf) conf = parent self.load_time = datetime.now() return conf
def test_generate_resource_from_path_with_is_processable_false(self): site = Site(TEST_SITE) site.load() resource = site.content.resource_from_path( TEST_SITE.child('content/about.html')) resource.is_processable = False gen = Generator(site) gen.generate_resource_at_path(TEST_SITE.child('content/about.html')) about = File(Folder(site.config.deploy_root_path).child('about.html')) assert not about.exists
def has_resource_changed(self, resource): """ Checks if the given resource has changed since the last generation. """ logger.debug("Checking for changes in %s" % resource) 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): logger.debug("Found changes in %s" % resource) return True 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) return False content = self.site.content.source_folder layout = Folder(self.site.sitepath).child_folder('layout') logger.debug("Checking for changes in dependents:%s" % deps) for dep in deps: if not dep: return True source = File(content.child(dep)) if not source.exists: source = File(layout.child(dep)) if not source.exists: return True if target.older_than(source): return True logger.debug("No changes found in %s" % resource) return False
def test_can_load_from_node_meta(self): d = {'title': 'A nice title', 'author': 'Lakshmi Vyas', 'twitter': 'lakshmivyas'} text = """ === title: Even nicer title === {%% extends "base.html" %%} {%% block main %%} Hi! I am a test template to make sure jinja2 generation works well with hyde. <span class="title">{{resource.meta.title}}</span> <span class="author">{{resource.meta.author}}</span> <span class="twitter">{{resource.meta.twitter}}</span> {%% endblock %%} """ about2 = File(TEST_SITE.child('content/about2.html')) about2.write(text % d) meta = File(TEST_SITE.child('content/nodemeta.yaml')) meta.write(yaml.dump(d)) s = Site(TEST_SITE) s.config.plugins = ['hyde.ext.plugins.meta.MetaPlugin'] gen = Generator(s) gen.generate_all() res = s.content.resource_from_path(about2.path) assert hasattr(res, 'meta') assert hasattr(res.meta, 'title') assert hasattr(res.meta, 'author') assert hasattr(res.meta, 'twitter') assert res.meta.title == "Even nicer title" assert res.meta.author == "Lakshmi Vyas" assert res.meta.twitter == "lakshmivyas" target = File(Folder(s.config.deploy_root_path).child('about2.html')) text = target.read_all() q = PyQuery(text) for k, v in d.items(): if not k == 'title': assert v in q("span." + k).text() assert q("span.title").text() == "Even nicer title"
def test_context_providers_no_data(self): site = Site( TEST_SITE, Config(TEST_SITE, config_dict={"context": { "providers": { "nav": "nav.yaml" } }})) nav = """ main: - home - articles - projects """ text = """ {% extends "base.html" %} {% block main %} {{nav}} {% for item in nav.main %} {{item}} {% endfor %} abc = {{ abc }} Hi! I am a test template to make sure jinja2 generation works well with hyde. {{resource.name}} {% endblock %} """ File(TEST_SITE.child('nav.yaml')).write(nav) site.load() resource = site.content.resource_from_path( TEST_SITE.child('content/about.html')) gen = Generator(site) resource.source_file.write(text) gen.generate_all() target = File(site.config.deploy_root_path.child(resource.name)) out = target.read_all() assert "home" in out assert "articles" in out assert "projects" in out
def test_plugin_chaining(self): self.site.config.plugins = [ 'hyde.tests.test_plugin.ConstantReturnPlugin', 'hyde.tests.test_plugin.NoReturnPlugin' ] path = self.site.content.source_folder.child('about.html') gen = Generator(self.site) gen.generate_resource_at_path(path) about = File( Folder(self.site.config.deploy_root_path).child('about.html')) assert about.read_all() == "Jam"
def test_can_execute_less(self): s = Site(TEST_SITE) s.config.plugins = ['hyde.ext.plugins.less.LessCSSPlugin'] paths = ['/usr/local/share/npm/bin/lessc', '~/local/bin/lessc'] less = [path for path in paths if File(path).exists] if not less: assert False, "Cannot find the lessc executable" less = less[0] s.config.less = Expando(dict(app=less)) source = TEST_SITE.child('content/media/css/site.less') target = File(Folder(s.config.deploy_root_path).child('media/css/site.css')) gen = Generator(s) gen.generate_resource_at_path(source) assert target.exists text = target.read_all() expected_text = File(LESS_SOURCE.child('expected-site.css')).read_all() assert text == expected_text return
def test_can_compress_with_stylus(self): s = Site(TEST_SITE) s.config.mode = "production" s.config.plugins = ['hyde.ext.plugins.stylus.StylusPlugin'] paths = ['/usr/local/share/npm/bin/stylus', '~/local/bin/stylus'] stylus = [path for path in paths if File(path).exists] if not stylus: assert False, "Cannot find the stylus executable" stylus = stylus[0] s.config.stylus = Expando(dict(app=stylus)) source = TEST_SITE.child('content/media/css/site.styl') target = File(Folder(s.config.deploy_root_path).child('media/css/site.css')) gen = Generator(s) gen.generate_resource_at_path(source) assert target.exists text = target.read_all() expected_text = File(STYLUS_SOURCE.child('expected-site-compressed.css')).read_all() assert text.strip() == expected_text.strip()
def test_pages_of_ten_content(self): expected_content = dedent('''\ Another Sad Post A Happy Post An Angry Post A Sad Post ''') page = self.deploy.child('pages_of_ten.txt') content = File(page).read_all() assert expected_content == content
def test_generator(self): self.setup_config(['**/*.html', 'media/css/*.css']) s = Site(self.SITE_PATH, self.config) g = Generator(s) g.generate_all() source = s.content.resource_from_relative_path( 'blog/2010/december/merry-christmas.html') target = File( s.config.deploy_root_path.child(source.relative_deploy_path)) left = source.source_file.read_all() right = target.read_all() assert left == right
def _get_sphinx_output(self,resource): """Get the sphinx output for a given resource. This returns a dict mapping block names to HTML text fragments. The most important fragment is "body" which contains the main text of the document. The other fragments are for things like navigation, related pages and so-on. """ relpath = File(resource.relative_path) relpath = relpath.parent.child(relpath.name_without_extension+".fjson") with open(self.sphinx_build_dir.child(relpath),"rb") as f: return json.load(f)
def test_can_parse_blockdown(self): s = Site(TEST_SITE) s.config.plugins = ['hyde.ext.plugins.blockdown.BlockdownPlugin'] txt ="This template tests to make sure blocks can be replaced with markdownish syntax." templ = """ {%% extends "base.html" %%} =====title======== %s ====/title========""" content = (templ.strip() % txt).strip() bd = File(TEST_SITE.child('content/blockdown.html')) bd.write(content) gen = Generator(s) gen.generate_resource_at_path(bd.path) res = s.content.resource_from_path(bd.path) target = File(s.config.deploy_root_path.child(res.relative_deploy_path)) assert target.exists text = target.read_all() q = PyQuery(text) assert q('title').text().strip() == txt.strip()
def _relative_url(self, source_path, number, basename, ext): """ Create a new URL for a new page. The first page keeps the same name; the subsequent pages are named according to file_pattern. """ path = File(source_path) if number != 1: filename = self.file_pattern.replace('$PAGE', str(number)) \ .replace('$FILE', basename) \ .replace('$EXT', ext) path = path.parent.child(os.path.normpath(filename)) return path
def test_can_uglify(self): s = Site(TEST_SITE) s.config.plugins = ['hyde.ext.plugins.uglify.UglifyPlugin'] s.config.mode = "production" paths = ['/usr/local/share/npm/bin/uglifyjs', '~/local/bin/uglifyjs', '/usr/bin/uglifyjs', '~/bin/uglifyjs'] uglify = [path for path in paths if File(path).exists] if not uglify: assert False, "Cannot find the uglify executable" uglify = uglify[0] s.config.uglify = Expando(dict(app=uglify)) source = TEST_SITE.child('content/media/js/jquery.js') target = File(Folder(s.config.deploy_root_path).child('media/js/jquery.js')) gen = Generator(s) gen.generate_resource_at_path(source) assert target.exists expected = File(UGLIFY_SOURCE.child('expected-jquery.js')) # TODO: Very fragile. Better comparison needed. assert target.read_all() == expected.read_all()
def test_walk_resources_sorted_using_generator(self): s = Site(TEST_SITE) cfg = """ meta: time: !!timestamp 2010-10-23 title: NahNahNah plugins: - hyde.ext.plugins.meta.MetaPlugin - hyde.ext.plugins.sorter.SorterPlugin sorter: time: attr: meta.time filters: source_file.kind: html """ s.config = Config(TEST_SITE, config_dict=yaml.load(cfg)) text = """ --- time: !!timestamp 2010-12-31 title: YayYayYay --- {% extends "base.html" %} {% block main %} {% set latest = site.content.walk_resources_sorted_by_time()|reverse|first %} <span class="latest">{{ latest.meta.title }}</span> {% endblock %} """ about2 = File(TEST_SITE.child('content/about2.html')) about2.write(text) gen = Generator(s) gen.generate_all() from pyquery import PyQuery target = File(Folder(s.config.deploy_root_path).child('about2.html')) text = target.read_all() q = PyQuery(text) assert q('span.latest').text() == 'YayYayYay'
def test_combine_remove(self): _, s = self._test_combine(""" --- combine: files: script.*.js remove: yes --- First line""") for i in range(1, 4): assert not File( Folder(s.config.deploy_root_path).child( 'media/js/script.%d.js' % i)).exists
def test_generate_resource_from_path_with_uses_template_false(self): site = Site(TEST_SITE) site.load() resource = site.content.resource_from_path( TEST_SITE.child('content/about.html')) resource.uses_template = False gen = Generator(site) gen.generate_resource_at_path(TEST_SITE.child('content/about.html')) about = File(Folder(site.config.deploy_root_path).child('about.html')) assert about.exists text = about.read_all() expected = resource.source_file.read_all() assert text == expected
def verify_site_contents(site, layout): assert site.exists assert site.child_folder('layout').exists assert File(site.child('info.yaml')).exists expected = map(lambda f: f.get_relative_path(layout), layout.walker.walk_all()) actual = map(lambda f: f.get_relative_path(site), site.walker.walk_all()) assert actual assert expected expected.sort() actual.sort() assert actual == expected
def test_cant_find_depends_with_reference_tag_var(self): site = Site(TEST_SITE) JINJA2.copy_contents_to(site.content.source) inc = File(TEST_SITE.child('content/inc.md')) inc.write("{% set ind = 'index.html' %}{% refer to ind as index %}") site.load() gen = Generator(site) gen.load_template_if_needed() t = gen.template deps = list(t.get_dependencies('inc.md')) assert len(deps) == 1 assert not deps[0]
def test_syntext(self): text = u""" ~~~~~~~~css~~~~~~~ .body{ background-color: white; } ~~~~~~~~~~~~~~~~~~ """ site = Site(TEST_SITE) site.config.plugins = [ 'hyde.ext.plugins.meta.MetaPlugin', 'hyde.ext.plugins.syntext.SyntextPlugin' ] syn = File(site.content.source_folder.child('syn.html')) syn.write(text) gen = Generator(site) gen.generate_all() f = File(site.config.deploy_root_path.child(syn.name)) assert f.exists html = f.read_all() assert html q = PyQuery(html) assert q('figure.code').length == 1
def full_url(self, path, safe=None): """ Determines if the given path is media or content based on the configuration and returns the appropriate url. The return value is url encoded. """ if urlparse.urlparse(path)[:2] != ("", ""): return path if self.is_media(path): relative_path = File(path).get_relative_path( Folder(self.config.media_root)) return self.media_url(relative_path, safe) else: return self.content_url(path, safe)
def wrapper(site, path): url = urlgetter(site, path) index_file_names = getattr(settings, 'index_file_names', ['index.html']) rep = File(url) if rep.name in index_file_names: url = rep.parent.path.rstrip('/') if hasattr(settings, 'append_slash') and \ settings.append_slash: url += '/' elif hasattr(settings, 'strip_extensions'): if rep.kind in settings.strip_extensions: url = rep.parent.child(rep.name_without_extension) return url or '/'
def test_ensure_no_exception_when_forced(): e = Engine(raise_exceptions=True) TEST_SITE.child_folder('layout').make() e.run(e.parse(['-s', unicode(TEST_SITE), 'create', '-f'])) verify_site_contents(TEST_SITE, Layout.find_layout()) TEST_SITE.delete() TEST_SITE.child_folder('content').make() e.run(e.parse(['-s', unicode(TEST_SITE), 'create', '-f'])) verify_site_contents(TEST_SITE, Layout.find_layout()) TEST_SITE.delete() TEST_SITE.make() File(TEST_SITE.child('site.yaml')).write("Hey") e.run(e.parse(['-s', unicode(TEST_SITE), 'create', '-f'])) verify_site_contents(TEST_SITE, Layout.find_layout())
def test_can_remove_file(): f = FS(__file__).parent c = f.child_folder('__test__') c.make() assert c.exists txt = "abc" abc = File(c.child('abc.txt')) abc.write(txt) assert abc.exists abc.delete() assert not abc.exists abc.delete() assert True # No Exception c.delete()
def test_walk_resources_sorted_with_multiple_attributes(self): s = Site(TEST_SITE) cfg = """ plugins: - hyde.ext.sorter.SorterPlugin sorter: multi: attr: - source_file.kind - node.name - name """ s.config = Config(TEST_SITE, config_dict=yaml.load(cfg)) s.load() SorterPlugin(s).begin_site() assert hasattr(s.content, 'walk_resources_sorted_by_multi') expected = ["content/404.html", "content/about.html", "content/apple-touch-icon.png", "content/blog/2010/december/merry-christmas.html", "content/crossdomain.xml", "content/favicon.ico", "content/robots.txt", "content/site.css" ] pages = [page.name for page in s.content.walk_resources_sorted_by_multi()] expected_sorted = [File(page).name for page in sorted(expected, key=lambda p: tuple( [File(p).kind, File(p).parent.name, p]))] assert pages == expected_sorted