def main(self, args): """ Will not be executed. A sub command is required. This function exists to provide common parameters for the subcommands and some generic stuff like version and metadata """ sitepath = Folder(args.sitepath).fully_expanded_path return Folder(sitepath)
def node_from_path(self, path): """ Gets the node that maps to the given path. If no match is found it returns None. """ if Folder(path) == self.source_folder: return self return self.node_map.get(str(Folder(path)), None)
def __init__(self, sitepath=None, config=None): super(Site, self).__init__() self.sitepath = Folder(Folder(sitepath).fully_expanded_path) # Add sitepath to the list of module search paths so that # local plugins can be included. sys.path.insert(0, self.sitepath.fully_expanded_path) self.config = config if config else Config(self.sitepath) self.content = RootNode(self.config.content_root_path, self) self.plugins = [] self.context = {}
def test_get_resource_from_relative_deploy_path(): s = Site(TEST_SITE_ROOT) s.load() path = 'blog/2010/december' node = s.content.node_from_relative_path(path) resource = node.get_resource('merry-christmas.html') assert resource == s.content.resource_from_relative_deploy_path( Folder(path).child('merry-christmas.html')) resource.relative_deploy_path = Folder(path).child('merry-christmas.php') assert resource == s.content.resource_from_relative_deploy_path( Folder(path).child('merry-christmas.php'))
def test_load(): s = Site(TEST_SITE_ROOT) s.load() path = 'blog/2010/december' node = s.content.node_from_relative_path(path) assert node assert Folder(node.relative_path) == Folder(path) path += '/merry-christmas.html' resource = s.content.resource_from_relative_path(path) assert resource assert resource.relative_path == path assert not s.content.resource_from_relative_path('/happy-festivus.html')
def test_load_with_config(self): s = Site(self.SITE_PATH, config=self.config) s.load() path = 'blog/2010/december' node = s.content.node_from_relative_path(path) assert node assert Folder(node.relative_path) == Folder(path) path += '/merry-christmas.html' resource = s.content.resource_from_relative_path(path) assert resource assert resource.relative_path == path assert not s.content.resource_from_relative_path( '/happy-festivus.html')
def add_node(self, a_folder): """ Adds a new node to this folder's hierarchy. Also adds it to the hashtable of path to node associations for quick lookup. """ folder = Folder(a_folder) node = self.node_from_path(folder) if node: logger.debug("Node exists at [%s]" % node.relative_path) return node if not folder.is_descendant_of(self.source_folder): raise HydeException("The given folder [%s] does not" " belong to this hierarchy [%s]" % (folder, self.source_folder)) p_folder = folder parent = None hierarchy = [] while not parent: hierarchy.append(p_folder) p_folder = p_folder.parent parent = self.node_from_path(p_folder) hierarchy.reverse() node = parent if parent else self for h_folder in hierarchy: node = node.add_child_node(h_folder) self.node_map[str(h_folder)] = node logger.debug("Added node [%s] to [%s]" % (node.relative_path, self.source_folder)) return node
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 == c.content_root_path.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 == c.content_root_path.child_folder('mmm') assert c.media_url == TEST_SITE.child_folder('/media') assert c.deploy_root_path == Folder('~/deploy_site')
def thumb(self, defaults={}, width=None, height=None): """ Generate a thumbnail for the given image """ if width is None and height is None: width, height = defaults['width'], defaults['height'] im = Image.open(self.path) if im.mode != 'RGBA': im = im.convert('RGBA') # Convert to a thumbnail if width is None: # height is not None width = im.size[0]*height/im.size[1] + 1 elif height is None: # width is not None height = im.size[1]*width/im.size[0] + 1 im.thumbnail((width, height), Image.ANTIALIAS) # Prepare path path = os.path.join(os.path.dirname(self.get_relative_deploy_path()), "%s%s" % (defaults['prefix'], self.name)) target = File(Folder(self.site.config.deploy_root_path).child(path)) target.parent.make() if self.name.endswith(".jpg"): im.save(target.path, "JPEG", optimize=True, quality=75) else: im.save(target.path, "PNG", optimize=True) return Thumb(path, width=im.size[0], height=im.size[1])
def test_url_cleaner(self): s = Site(TEST_SITE) cfg = """ plugins: - hyde.ext.plugins.urls.UrlCleanerPlugin urlcleaner: index_file_names: - about.html strip_extensions: - html append_slash: true """ s.config = Config(TEST_SITE, config_dict=yaml.load(cfg, Loader=yaml.FullLoader)) text = """ {% extends "base.html" %} {% block main %} <a id="index" href="{{ content_url('about.html') }}"></a> <a id="blog" href= "{{ content_url('blog/2010/december/merry-christmas.html') }}"></a> {% endblock %} """ about2 = File(TEST_SITE.child('content/test.html')) about2.write(text) gen = Generator(s) gen.generate_all() from pyquery import PyQuery target = File(Folder(s.config.deploy_root_path).child('test.html')) text = target.read_all() q = PyQuery(text) assert q('a#index').attr("href") == '/' assert q('a#blog').attr( "href") == '/blog/2010/december/merry-christmas'
def load(sitepath, ctx): """ Load context from config data and providers. """ context = {} try: context.update(ctx.data.__dict__) except AttributeError: # No context data found pass providers = {} try: providers.update(ctx.providers.__dict__) except AttributeError: # No providers found pass for provider_name, resource_name in providers.items(): res = File(Folder(sitepath).child(resource_name)) if res.exists: data = make_expando( yaml.load(res.read_all(), Loader=yaml.FullLoader)) context[provider_name] = data return context
def begin_site(self): """ Finds all the folders that need flattening and changes the relative deploy path of all resources in those folders. """ items = [] try: items = self.site.config.flattener.items except AttributeError: pass for item in items: node = None target = '' try: node = self.site.content.node_from_relative_path(item.source) target = Folder(item.target) except AttributeError: continue if node: for resource in node.walk_resources(): target_path = target.child(resource.name) self.logger.debug('Flattening resource path [%s] to [%s]' % (resource, target_path)) resource.relative_deploy_path = target_path for child in node.walk(): child.relative_deploy_path = target.path
def test_ignores_pattern_in_content(self): text = """ {% markdown %} Heading 1 === Heading 2 === {% endmarkdown %} """ about2 = File(TEST_SITE.child('content/about2.html')) about2.write(text) s = Site(TEST_SITE) s.load() res = s.content.resource_from_path(about2.path) assert res.is_processable s.config.plugins = ['hyde.ext.plugins.meta.MetaPlugin'] gen = Generator(s) gen.generate_all() target = File(Folder(s.config.deploy_root_path).child('about2.html')) text = target.read_all() q = PyQuery(text) assert q("h1").length == 2 assert q("h1:nth-child(1)").text().strip() == "Heading 1" assert q("h1:nth-child(2)").text().strip() == "Heading 2"
def _get_layout_folder(root, layout_name='basic'): """ Finds the layout folder from the given root folder. If it does not exist, return None """ layouts_folder = Folder(unicode(root)).child_folder(LAYOUTS) layout_folder = layouts_folder.child_folder(layout_name) return layout_folder if layout_folder.exists else None
def __init__(self, sitepath, depends_file_name='.hyde_deps'): self.sitepath = Folder(sitepath) self.deps_file = File(self.sitepath.child(depends_file_name)) self.data = {} if self.deps_file.exists: self.data = yaml.load(self.deps_file.read_all()) import atexit atexit.register(self.save)
def test_media_url_from_resource(self): s = Site(self.SITE_PATH, config=self.config) s.load() path = 'css/site.css' resource = s.content.resource_from_relative_path( Folder("media").child(path)) assert resource assert resource.full_url == "/media/" + path
def test_multiple_levels(self): page_d = {'title': 'An even nicer title'} blog_d = {'author': 'Laks'} content_d = {'title': 'A nice title', 'author': 'Lakshmi Vyas'} site_d = { 'author': 'Lakshmi', 'twitter': 'lakshmivyas', 'nodemeta': 'meta.yaml' } text = """ --- title: %(title)s --- {%% 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/blog/about2.html')) about2.write(text % page_d) content_meta = File(TEST_SITE.child('content/nodemeta.yaml')) content_meta.write(yaml.dump(content_d)) content_meta = File(TEST_SITE.child('content/blog/meta.yaml')) content_meta.write(yaml.dump(blog_d)) s = Site(TEST_SITE) s.config.plugins = ['hyde.ext.plugins.meta.MetaPlugin'] s.config.meta = site_d gen = Generator(s) gen.generate_all() expected = {} expected.update(site_d) expected.update(content_d) expected.update(blog_d) expected.update(page_d) res = s.content.resource_from_path(about2.path) assert hasattr(res, 'meta') for k, v in list(expected.items()): assert hasattr(res.meta, k) assert getattr(res.meta, k) == v target = File( Folder(s.config.deploy_root_path).child('blog/about2.html')) text = target.read_all() q = PyQuery(text) for k, v in list(expected.items()): if k != 'nodemeta': assert v in q("span." + k).text()
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 test_plugin_chaining(self): self.site.config.plugins = [ 'test_plugin.ConstantReturnPlugin', '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_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 test_relative_deploy_path_override(): s = Site(TEST_SITE_ROOT) s.load() res = s.content.resource_from_relative_path( 'blog/2010/december/merry-christmas.html') res.relative_deploy_path = 'blog/2010/december/happy-holidays.html' for page in s.content.walk_resources(): if res.source_file == page.source_file: assert page.relative_deploy_path == 'blog/2010/december/happy-holidays.html' else: assert page.relative_deploy_path == Folder(page.relative_path)
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 test_can_execute_optipng(self): s = Site(TEST_SITE) s.config.mode = "production" s.config.plugins = ['hyde.ext.plugins.images.OptiPNGPlugin'] s.config.optipng = Expando(dict(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 test_can_uglify(self): s = Site(TEST_SITE) s.config.plugins = ['hyde.ext.plugins.js.UglifyPlugin'] s.config.mode = "production" 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_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 media_url(self, path, safe=None): """ Returns the media url by appending the media base url from the config with the given path. The return value is url encoded. """ fpath = Folder(self.config.media_url) \ .child(path) \ .replace(os.sep, '/').encode("utf-8") if safe is not None: return quote(fpath, safe) elif self.config.encode_safe is not None: return quote(fpath, self.config.encode_safe) else: return quote(fpath)
def test_scss(self): s = Site(TEST_SITE) s.config.mode = 'prod' s.config.plugins = ['hyde.ext.plugins.css.SassyCSSPlugin'] source = TEST_SITE.child('content/media/css/site.scss') 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(SCSS_SOURCE.child('expected-site.css')).read_all() assert_no_diff(expected_text, text)
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 == c.content_root_path.child_folder('xxx') assert c.media_url == TEST_SITE.child_folder('/media') assert c.deploy_root_path == Folder('~/deploy_site')
def test_uglify_with_extra_options(self): s = Site(TEST_SITE) s.config.plugins = ['hyde.ext.plugins.js.UglifyPlugin'] s.config.mode = "production" s.config.uglify = Expando(dict(args={"nc":""})) 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-nc.js')) # TODO: Very fragile. Better comparison needed. text = target.read_all() assert text.startswith("(function(")