| @@ -15,10 +15,39 @@ from itertools import ifilter, izip, tee, product | |||
| from operator import attrgetter | |||
| def get_tagger_sort_method(site): | |||
| config = site.config | |||
| content = site.content | |||
| walker = 'walk_resources' | |||
| sorter = None | |||
| try: | |||
| sorter = attrgetter('tagger.sorter')(config) | |||
| walker = walker + '_sorted_by_%s' % sorter | |||
| except AttributeError: | |||
| pass | |||
| try: | |||
| walker = getattr(content, walker) | |||
| except AttributeError: | |||
| raise self.template.exception_class( | |||
| "Cannot find the sorter: %s" % sorter) | |||
| return walker | |||
| def walk_resources_tagged_with(node, tag): | |||
| tags = set(tag.split('+')) | |||
| walker = get_tagger_sort_method(node.site) | |||
| for resource in walker(): | |||
| try: | |||
| taglist = set(attrgetter("meta.tags")(resource)) | |||
| except AttributeError: | |||
| continue | |||
| if tags <= taglist: | |||
| yield resource | |||
| class TaggerPlugin(Plugin): | |||
| """ | |||
| Tagger plugin for hyde. Adds the ability to do | |||
| tag resources and search based on the tags. | |||
| Tagger plugin for hyde. Adds the ability to do tag resources and search | |||
| based on the tags. | |||
| Configuration example | |||
| --------------------- | |||
| @@ -27,35 +56,40 @@ class TaggerPlugin(Plugin): | |||
| kind: | |||
| atts: source.kind | |||
| tagger: | |||
| blog: | |||
| sorter: kind # How to sort the resources in a tag | |||
| source: blog # The source folder to look for resources | |||
| target: blog/tags # The target folder to deploy the archives | |||
| sorter: kind # How to sort the resources in a tag | |||
| archives: | |||
| template: tagged_posts.j2 | |||
| target: tags | |||
| archive_extension: html | |||
| """ | |||
| def __init__(self, site): | |||
| super(GrouperPlugin, self).__init__(site) | |||
| super(TaggerPlugin, self).__init__(site) | |||
| def begin_site(self): | |||
| """ | |||
| Initialize plugin. Add the specified groups to the | |||
| site context variable. | |||
| Initialize plugin. Add tag to the site context variable. | |||
| """ | |||
| self.logger.debug("Adding tags from metadata") | |||
| config = self.site.config | |||
| if not hasattr(config, 'grouper'): | |||
| return | |||
| if not hasattr(self.site, 'grouper'): | |||
| self.site.grouper = {} | |||
| for name, grouping in self.site.config.grouper.__dict__.items(): | |||
| grouping.name = name | |||
| prev_att = 'prev_in_%s' % name | |||
| next_att = 'next_in_%s' % name | |||
| setattr(Resource, prev_att, None) | |||
| setattr(Resource, next_att, None) | |||
| self.site.grouper[name] = Group(grouping) | |||
| walker = Group.walk_resources( | |||
| self.site.content, self.site.grouper[name]) | |||
| for prev, next in pairwalk(walker): | |||
| setattr(next, prev_att, prev) | |||
| setattr(prev, next_att, next) | |||
| 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)) | |||
| @@ -49,7 +49,6 @@ depends: index.html | |||
| gen.template.env.filters['dateformat'] = dateformat | |||
| gen.generate_resource_at_path(inc.name) | |||
| res = s.content.resource_from_relative_path(inc.name) | |||
| print res.__dict__ | |||
| assert len(res.depends) == 1 | |||
| assert 'index.html' in res.depends | |||
| deps = list(gen.get_dependencies(res)) | |||
| @@ -140,7 +140,6 @@ class TestGrouperSingleLevel(object): | |||
| res = self.s.content.resource_from_relative_path('blog/' + page) | |||
| assert hasattr(res, 'section_group') | |||
| res_group = getattr(res, 'section_group') | |||
| print "%s, %s=%s" % (page, group.name, res_group.name) | |||
| assert res_group == group | |||
| def test_resource_belongs_to(self): | |||
| @@ -30,35 +30,41 @@ class TestTagger(object): | |||
| def test_tagger_walker(self): | |||
| gen = Generator(self.s) | |||
| gen.load_site_if_needed() | |||
| gen.generate_all() | |||
| tags = self.s.taggger['blog'].tags | |||
| assert hasattr(self.s, 'tagger') | |||
| assert hasattr(self.s.tagger, 'tags') | |||
| assert self.s.tagger.tags | |||
| tags = self.s.tagger.tags.to_dict() | |||
| assert tags.length == 5 | |||
| assert len(tags) == 5 | |||
| for tag in ['sad', 'happy', 'angry', 'thoughts', 'events']: | |||
| assert tag in tags | |||
| # sad_posts = [post.name for post in | |||
| # self.s.content.walk_resources_tagged_with('sad')] | |||
| # assert sad_posts.length == 2 | |||
| # assert "sad-post.html" in sad_posts | |||
| # assert "another-sad-post.html" in sad_posts | |||
| # | |||
| # happy_posts = [post.name for post in | |||
| # self.s.content.walk_resources_tagged_with('happy')] | |||
| # assert happy_posts.length == 1 | |||
| # assert "happy-post.html" in happy_posts | |||
| # | |||
| # angry_posts = [post.name for post in | |||
| # self.s.content.walk_resources_tagged_with('angry')] | |||
| # assert angry_posts.length == 1 | |||
| # assert "angry-post.html" in angry_posts | |||
| # sad_thought_posts = [post.name for post in | |||
| # self.s.content.walk_resources_tagged_with('sad')] | |||
| # assert sad_posts.length == 2 | |||
| # assert "sad-post.html" in sad_posts | |||
| # assert "another-sad-post.html" in sad_posts | |||
| sad_posts = [post.name for post in tags['sad']] | |||
| assert len(sad_posts) == 2 | |||
| assert "sad-post.html" in sad_posts | |||
| assert "another-sad-post.html" in sad_posts | |||
| sad_posts == [post.name for post in | |||
| self.s.content.walk_resources_tagged_with('sad')] | |||
| happy_posts = [post.name for post in | |||
| self.s.content.walk_resources_tagged_with('happy')] | |||
| assert len(happy_posts) == 1 | |||
| assert "happy-post.html" in happy_posts | |||
| angry_posts = [post.name for post in | |||
| self.s.content.walk_resources_tagged_with('angry')] | |||
| assert len(angry_posts) == 1 | |||
| assert "angry-post.html" in angry_posts | |||
| sad_thought_posts = [post.name for post in | |||
| self.s.content.walk_resources_tagged_with('sad+thoughts')] | |||
| assert len(sad_thought_posts) == 1 | |||
| assert "sad-post.html" in sad_thought_posts | |||
| @@ -20,11 +20,10 @@ sorter: | |||
| reverse: true | |||
| filters: | |||
| source.kind: html | |||
| meta.listable: true | |||
| tagger: | |||
| blog: | |||
| sorter: time | |||
| archives: | |||
| sorter: time | |||
| archives: | |||
| blog: | |||
| template: tagged_posts.j2 | |||
| source: blog | |||
| target: blog/tags | |||
| @@ -94,8 +94,8 @@ logging.ColorFormatter = ColorFormatter | |||
| def make_method(method_name, method_): | |||
| def method__(self): | |||
| return method_(self) | |||
| def method__(*args, **kwargs): | |||
| return method_(*args, **kwargs) | |||
| method__.__name__ = method_name | |||
| return method__ | |||