@@ -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__ | |||