def __init__(self, raw_text, element, meta=None): self.raw_text = raw_text self.element = element if meta: self.meta = Expando(meta) else: self.meta = Expando({})
def test_plugin_node_filters_begin_text_resource(self): def empty_return(*args, **kwargs): return None with patch.object(ConstantReturnPlugin, 'begin_text_resource', new=Mock(wraps=empty_return)) as mock1: with patch.object(NoReturnPlugin, 'begin_text_resource', new=Mock(wraps=empty_return)) as mock2: self.site.config.plugins = [ 'hyde.tests.test_plugin.ConstantReturnPlugin', 'hyde.tests.test_plugin.NoReturnPlugin' ] self.site.config.constantreturn = Expando( dict(include_paths="media")) self.site.config.noreturn = Expando( dict(include_file_pattern="*.html", include_paths=["blog"])) gen = Generator(self.site) gen.generate_all() mock1_args = sorted( set([arg[0][0].name for arg in mock1.call_args_list])) mock2_args = sorted( set([arg[0][0].name for arg in mock2.call_args_list])) assert len(mock1_args) == 1 assert len(mock2_args) == 1 assert mock1_args == ["site.css"] assert mock2_args == ["merry-christmas.html"]
def test_plugin_filters_begin_text_resource(self): def empty_return(self, resource, text=''): return text with patch.object(ConstantReturnPlugin, 'begin_text_resource', new=Mock(wraps=empty_return)) as mock1: with patch.object(NoReturnPlugin, 'begin_text_resource', new=Mock(wraps=empty_return)) as mock2: self.site.config.plugins = [ 'hyde.tests.test_plugin.ConstantReturnPlugin', 'hyde.tests.test_plugin.NoReturnPlugin' ] self.site.config.constantreturn = Expando( dict(include_file_pattern="*.css")) self.site.config.noreturn = Expando( dict(include_file_pattern=["*.html", "*.txt"])) gen = Generator(self.site) gen.generate_all() mock1_args = sorted( set([arg[0][0].name for arg in mock1.call_args_list])) mock2_args = sorted( set([arg[0][0].name for arg in mock2.call_args_list])) assert len(mock1_args) == 1 assert len(mock2_args) == 4 assert mock1_args == ["site.css"] assert mock2_args == [ "404.html", "about.html", "merry-christmas.html", "robots.txt" ]
def _parse_raw_text(self): ''' find the meta data and text ''' # first, find yaml matter, # assuming only the bottom '---' to save space idx_ym = self.raw_text.find(YAML_FINDER, len(YAML_FINDER)) if idx_ym > 0: ym = self.raw_text[:idx_ym - 1] else: ym = '' # make the meta dict meta = Expando(yaml.load(ym)) if not meta: # if meta is None, make is a dict meta = Expando({}) elif isinstance(self.meta, str): # if meta ends up as a string, assume it's empty meta = Expando({}) idx_ym = -1 # if a meta collision occurs, the yaml-matter is prefered # except in the case of 'class', which appends it to the existing version try: old_class = getattr(self.meta, "class") new_class = old_class + " " + getattr(meta, "class") setattr(self.meta, "class", new_class) delattr(meta, "class") except AttributeError: pass self.meta.update(meta) # attempt to enumerate class and id, if possible try: setattr(self.meta, "id", self.meta.id % self.idx) except (AttributeError, TypeError): pass try: setattr(self.meta, "class", getattr(self.meta, "class") % self.idx) except (AttributeError, TypeError): pass # now find the standard text if idx_ym > 0: self.slide_text = self.raw_text[idx_ym + len(YAML_FINDER):] else: self.slide_text = self.raw_text
def test_expando_update(): d1 = {"a": 123, "b": "abc"} x = Expando(d1) assert x.a == d1['a'] assert x.b == d1['b'] d = {"b": {"c": 456, "d": {"e": "abc"}}, "f": "lmn"} x.update(d) assert x.a == d1['a'] assert x.b.c == d['b']['c'] assert x.b.d.e == d['b']['d']['e'] assert x.f == d["f"] d2 = {"a": 789, "f": "opq"} y = Expando(d2) x.update(y) assert x.a == 789 assert x.f == "opq"
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', '~/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 syntax(env, value, lexer=None, filename=None): """ Processes the contained block using `pygments` """ try: import pygments from pygments import lexers from pygments import formatters except ImportError: logger.error(u"pygments library is required to" " use syntax highlighting tags.") raise TemplateError("Cannot load pygments") pyg = (lexers.get_lexer_by_name(lexer) if lexer else lexers.guess_lexer(value)) settings = {} if hasattr(env.config, 'syntax'): settings = getattr(env.config.syntax, 'options', Expando({})).to_dict() formatter = formatters.HtmlFormatter(**settings) code = pygments.highlight(value, pyg, formatter) code = code.replace('\n\n', '\n \n').replace('\n', '<br />') caption = filename if filename else pyg.name if hasattr(env.config, 'syntax'): if not getattr(env.config.syntax, 'use_figure', True): return Markup(code) return Markup( '<div class="codebox"><figure class="code">%s<figcaption>%s</figcaption></figure></div>\n\n' % (code, caption))
def begin_site(self): """ Initialize plugin. Add tag to the site context variable and methods for walking tagged resources. """ self.logger.debug("Adding tags from metadata") config = self.site.config content = self.site.content tags = {} add_method(Node, 'walk_resources_tagged_with', walk_resources_tagged_with) walker = get_tagger_sort_method(self.site) for resource in walker(): try: taglist = attrgetter("meta.tags")(resource) except AttributeError: continue for tag in taglist: if not tag in tags: tags[tag] = [resource] add_method(Node, 'walk_resources_tagged_with_%s' % tag, walk_resources_tagged_with, tag=tag) else: tags[tag].append(resource) self.site.tagger = Expando(dict(tags=tags))
def test_expando_to_dict_with_update(): d1 = {"a": 123, "b": "abc"} x = Expando(d1) d = {"b": {"c": 456, "d": {"e": "abc"}}, "f": "lmn"} x.update(d) expected = {} expected.update(d1) expected.update(d) assert expected == x.to_dict() d2 = {"a": 789, "f": "opq"} y = Expando(d2) x.update(y) expected.update(d2) assert expected == x.to_dict()
def settings(self): """Settings for this plugin. This property combines default settings with those specified in the site config to produce the final settings for this plugin. """ settings = Expando({}) settings.sanity_check = True settings.conf_path = "." settings.block_map = {} try: user_settings = getattr(self.site.config, self.plugin_name) except AttributeError: pass else: for name in dir(user_settings): if not name.startswith("_"): setattr(settings, name, getattr(user_settings, name)) return settings
def settings(self): """Settings for this plugin. This property combines default settings with those specified in the site config to produce the final settings for this plugin. """ settings = Expando({}) settings.sanity_check = True settings.conf_path = "." settings.block_map = {} try: user_settings = getattr(self.site.config, self.plugin_name) except AttributeError: pass else: for name in dir(user_settings): if not name.startswith("_"): setattr(settings,name,getattr(user_settings,name)) return settings
def settings(self): """ The settings for this plugin the site config. """ opts = Expando({}) try: opts = getattr(self.site.config, self.plugin_name) except AttributeError: pass return opts
def test_can_execute_optipng(self): s = Site(TEST_SITE) s.config.mode = "production" s.config.plugins = ['hyde.ext.plugins.optipng.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_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(")
def test_can_execute_stylus(self): s = Site(TEST_SITE) s.config.plugins = ['hyde.ext.plugins.stylus.StylusPlugin'] paths = ['/usr/local/share/npm/bin/stylus'] for path in paths: if File(path).exists: s.config.stylus = Expando(dict(app=path)) 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.css')).read_all() assert text.strip() == expected_text.strip()
def begin_site(self): """ Initialize plugin. Add tag to the site context variable and methods for walking tagged resources. """ self.logger.debug("Adding tags from metadata") config = self.site.config content = self.site.content tags = {} add_method(Node, 'walk_resources_tagged_with', walk_resources_tagged_with) walker = get_tagger_sort_method(self.site) for resource in walker(): self._process_tags_in_resource(resource, tags) self._process_tag_metadata(tags) self.site.tagger = Expando(dict(tags=tags)) self._generate_archives()
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', '/usr/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 test_walk_resources_sorted_by_index(self): s = Site(TEST_SITE) s.load() config = {"index": {"attr": ['meta.index', 'name']}} s.config.sorter = Expando(config) MetaPlugin(s).begin_site() SorterPlugin(s).begin_site() assert hasattr(s.content, 'walk_resources_sorted_by_index') expected = [ "angry-post.html", "another-sad-post.html", "happy-post.html" ] pages = [ page.name for page in s.content.walk_resources_sorted_by_index() ] assert pages == sorted(expected, key=lambda f: (File(f).kind, f))
def markdown(env, value): """ Markdown filter with support for extensions. """ try: import markdown as md except ImportError: logger.error(u"Cannot load the markdown library.") raise TemplateError("Cannot load the markdown library") output = value d = {} if hasattr(env.config, 'markdown'): d['extensions'] = getattr(env.config.markdown, 'extensions', []) d['extension_configs'] = getattr(env.config.markdown, 'extension_configs', Expando({})).to_dict() marked = md.Markdown(**d) return marked.convert(output)
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_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(self): s = Site(TEST_SITE) s.load() s.config.plugins = ['hyde.ext.meta.SorterPlugin'] s.config.sorter = Expando( dict(kind=dict(attr=['source_file.kind', 'name']))) SorterPlugin(s).begin_site() assert hasattr(s.content, 'walk_resources_sorted_by_kind') expected = [ "404.html", "about.html", "apple-touch-icon.png", "merry-christmas.html", "crossdomain.xml", "favicon.ico", "robots.txt", "site.css" ] pages = [ page.name for page in s.content.walk_resources_sorted_by_kind() ] assert pages == sorted(expected, key=lambda f: (File(f).kind, f))
def test_expando_to_dict(): d = {"a": 123, "b": {"c": 456, "d": {"e": "abc"}}} x = Expando(d) assert d == x.to_dict()
def presenter(env, raw_text, id=None, resource=None): ''' A filter that builds a presentation ''' # get the config data relevant to this presentation's settings try: res_meta = getattr(resource.meta, "presenter") except AttributeError: res_meta = None try: res_meta_id = getattr(res_meta, id) except AttributeError: res_meta_id = None try: conf_id = getattr(config_cache, id) except AttributeError: conf_id = None # gather relevant settings for the presentation and slides settings = {"raw_text": raw_text, "slide_items": {"env": env}} # look for the proper settings for the presentation for k, v in default.items(): try: # try resource.meta.presenter.KEY settings[k] = getattr(res_meta, k) except AttributeError: try: # try resource.meta.presenter.ID.KEY settings[k] = getattr(res_meta_id, k) except AttributeError: try: # try config.presenter.ID.KEY settings[k] = getattr(conf_id, k) except AttributeError: # take the default value settings[k] = v # set the id meta data if id: if settings["meta"]: settings["meta"].update({"id": id}) else: settings["meta"] = Expando({"id": id}) # look for the proper settings for the slides for k, v in slide_default.items(): try: # try resource.meta.presenter.slides.KEY settings["slide_items"][k] = getattr(getattr(res_meta, "slides"), k) except AttributeError: try: # try resource.meta.presenter.slides.ID.KEY settings["slide_items"][k] = getattr( getattr(res_meta_id, "slides"), k) except AttributeError: try: # try config.presenter.slides.ID.KEY settings["slide_items"][k] = getattr( getattr(conf_id, "slides"), k) except AttributeError: # take the default value settings["slide_items"][k] = v # get the resource's presentation list try: pres = resource.pres except AttributeError: resource.pres = [] pres = resource.pres # create a presentation for this resource P = Presentation(**settings) pres.append(P) return P.html
def test_expando_two_levels(): d = {"a": 123, "b": {"c": 456}} x = Expando(d) assert x.a == d['a'] assert x.b.c == d['b']['c']
def test_expando_three_levels(): d = {"a": 123, "b": {"c": 456, "d": {"e": "abc"}}} x = Expando(d) assert x.a == d['a'] assert x.b.c == d['b']['c'] assert x.b.d.e == d['b']['d']['e']
def test_nav_with_grouper_sorted(self): cfg = """ nodemeta: meta.yaml plugins: - hyde.ext.plugins.meta.MetaPlugin - hyde.ext.plugins.sorter.SorterPlugin - hyde.ext.plugins.grouper.GrouperPlugin sorter: kind: attr: - source_file.kind filters: is_processable: True grouper: section: description: Sections in the site sorter: kind groups: - name: start description: Getting Started - name: awesome description: Awesome - name: plugins description: Plugins """ self.s.config = Config(TEST_SITE, config_dict=yaml.load(cfg)) self.s.load() MetaPlugin(self.s).begin_site() SorterPlugin(self.s).begin_site() GrouperPlugin(self.s).begin_site() text =""" {% set sorted = site.grouper['section'].groups|sort(attribute='name') %} {% for group in sorted %} <ul> <li> <h2>{{ group.name|title }}</h2> <h3>{{ group.description }}</h3> <ul class="links"> {% for resource in group.walk_resources_in_node(site.content) %} <li>{{resource.name}}</li> {% endfor %} </ul> </li> </ul> {% endfor %} """ expected = """ <ul> <li> <h2>Awesome</h2> <h3>Awesome</h3> <ul class="links"> </ul> </li> </ul> <ul> <li> <h2>Plugins</h2> <h3>Plugins</h3> <ul class="links"> <li>plugins.html</li> <li>tags.html</li> </ul> </li> </ul> <ul> <li> <h2>Start</h2> <h3>Getting Started</h3> <ul class="links"> <li>installation.html</li> <li>overview.html</li> <li>templating.html</li> </ul> </li> </ul> """ self.s.config.grouper.section.groups.append(Expando({"name": "awesome", "description": "Aweesoome"})); gen = Generator(self.s) gen.load_site_if_needed() gen.load_template_if_needed() out = gen.template.render(text, {'site':self.s}) assert_html_equals(out, expected)
def test_expando_one_level(): d = {"a": 123, "b": "abc"} x = Expando(d) assert x.a == d['a'] assert x.b == d['b']