| @@ -5,6 +5,8 @@ Contains classes and utilities related to meta data in hyde. | |||
| import re | |||
| from operator import attrgetter | |||
| from itertools import ifilter | |||
| from functools import partial | |||
| from hyde.model import Expando | |||
| from hyde.plugin import Plugin | |||
| from hyde.fs import File, Folder | |||
| @@ -394,3 +396,120 @@ extends: false | |||
| archive_file.write(text.strip()) | |||
| self.site.content.add_resource(archive_file) | |||
| def filter_method(item, settings=None): | |||
| """ | |||
| Returns true if all the filters in the | |||
| given settings evaluate to True. | |||
| """ | |||
| all_match = True | |||
| default_filters = {} | |||
| filters = {} | |||
| if hasattr(settings, 'filters'): | |||
| filters.update(default_filters) | |||
| filters.update(settings.filters.__dict__) | |||
| for field, value in filters.items(): | |||
| try: | |||
| res = attrgetter(field)(item) | |||
| except: | |||
| res = None | |||
| if res != value: | |||
| all_match = False | |||
| break | |||
| return all_match | |||
| def attributes_checker(item, attributes=None): | |||
| """ | |||
| Checks if the given list of attributes exist. | |||
| """ | |||
| try: | |||
| x = attrgetter(*attributes)(item) | |||
| return True | |||
| except AttributeError: | |||
| return False | |||
| def sort_method(node, settings=None): | |||
| """ | |||
| Sorts the resources in the given node based on the | |||
| given settings. | |||
| """ | |||
| attr = 'name' | |||
| if settings and hasattr(settings, 'attr') and settings.attr: | |||
| attr = settings.attr | |||
| reverse = False | |||
| if settings and hasattr(settings, 'reverse'): | |||
| reverse = settings.reverse | |||
| if not isinstance(attr, list): | |||
| attr = [attr] | |||
| filter_ = partial(filter_method, settings=settings) | |||
| excluder_ = partial(attributes_checker, attributes=attr) | |||
| resources = ifilter(lambda x: excluder_(x) and filter_(x), | |||
| node.walk_resources()) | |||
| return sorted(resources, | |||
| key=attrgetter(*attr), | |||
| reverse=reverse) | |||
| class SorterPlugin(Plugin): | |||
| """ | |||
| Sorter plugin for hyde. Adds the ability to do | |||
| sophisticated sorting by expanding the site objects | |||
| to support prebuilt sorting methods. These methods | |||
| can be used in the templates directly. | |||
| Configuration example | |||
| --------------------- | |||
| #yaml | |||
| sorter: | |||
| kind: | |||
| # Sorts by this attribute name | |||
| # Uses `attrgetter` on the resource object | |||
| attr: source_file.kind | |||
| # The filters to be used before sorting | |||
| # This can be used to remove all the items | |||
| # that do not apply. For example, | |||
| # filtering non html content | |||
| filters: | |||
| source_file.kind: html | |||
| is_processable: True | |||
| meta.is_listable: True | |||
| """ | |||
| def __init__(self, site): | |||
| super(SorterPlugin, self).__init__(site) | |||
| def begin_site(self): | |||
| """ | |||
| Initialize plugin. Add a sort and match method | |||
| for every configuration mentioned in site settings | |||
| """ | |||
| config = self.site.config | |||
| if not hasattr(config, 'sorter'): | |||
| return | |||
| for name, settings in config.sorter.__dict__.items(): | |||
| sort_method_name = 'walk_resources_sorted_by_%s' % name | |||
| self.logger.debug("Adding sort methods for [%s]" % name) | |||
| add_method(Node, sort_method_name, sort_method, settings=settings) | |||
| match_method_name = 'is_%s' % name | |||
| add_method(Resource, match_method_name, filter_method, settings) | |||
| prev_att = 'prev_by_%s' % name | |||
| next_att = 'next_by_%s' % name | |||
| setattr(Resource, prev_att, None) | |||
| setattr(Resource, next_att, None) | |||
| walker = getattr(self.site.content, | |||
| sort_method_name, | |||
| self.site.content.walk_resources) | |||
| for prev, next in pairwalk(walker()): | |||
| setattr(prev, next_att, next) | |||
| setattr(next, prev_att, prev) | |||
| @@ -5,7 +5,7 @@ base_url: / # The base url for autogenerated links. | |||
| plugins: | |||
| - hyde.ext.plugins.meta.MetaPlugin | |||
| - hyde.ext.plugins.meta.AutoExtendPlugin | |||
| - hyde.ext.plugins.sorter.SorterPlugin | |||
| - hyde.ext.plugins.meta.SorterPlugin | |||
| - hyde.ext.plugins.meta.TaggerPlugin | |||
| - hyde.ext.plugins.text.SyntextPlugin | |||
| - hyde.ext.plugins.text.TextlinksPlugin | |||
| @@ -12,7 +12,7 @@ plugins: | |||
| - hyde.ext.plugins.meta.MetaPlugin | |||
| - hyde.ext.plugins.meta.AutoExtendPlugin | |||
| # Plugins needed for the advances section. | |||
| - hyde.ext.plugins.sorter.SorterPlugin | |||
| - hyde.ext.plugins.meta.SorterPlugin | |||
| - hyde.ext.plugins.grouper.GrouperPlugin | |||
| - hyde.ext.plugins.meta.TaggerPlugin | |||
| context: | |||
| @@ -5,7 +5,7 @@ Use nose | |||
| `$ nosetests` | |||
| """ | |||
| from hyde.ext.plugins.meta import MetaPlugin | |||
| from hyde.ext.plugins.sorter import SorterPlugin | |||
| from hyde.ext.plugins.meta import SorterPlugin | |||
| from hyde.ext.plugins.grouper import GrouperPlugin | |||
| from hyde.generator import Generator | |||
| from hyde.site import Site | |||
| @@ -30,7 +30,7 @@ class TestGrouperSingleLevel(object): | |||
| nodemeta: meta.yaml | |||
| plugins: | |||
| - hyde.ext.plugins.meta.MetaPlugin | |||
| - hyde.ext.plugins.sorter.SorterPlugin | |||
| - hyde.ext.plugins.meta.SorterPlugin | |||
| - hyde.ext.plugins.grouper.GrouperPlugin | |||
| sorter: | |||
| kind: | |||
| @@ -236,7 +236,7 @@ class TestGrouperSingleLevel(object): | |||
| nodemeta: meta.yaml | |||
| plugins: | |||
| - hyde.ext.plugins.meta.MetaPlugin | |||
| - hyde.ext.plugins.sorter.SorterPlugin | |||
| - hyde.ext.plugins.meta.SorterPlugin | |||
| - hyde.ext.plugins.grouper.GrouperPlugin | |||
| sorter: | |||
| kind: | |||
| @@ -321,4 +321,4 @@ class TestGrouperSingleLevel(object): | |||
| gen.load_site_if_needed() | |||
| gen.load_template_if_needed() | |||
| out = gen.template.render(text, {'site':self.s}) | |||
| assert_html_equals(out, expected) | |||
| assert_html_equals(out, expected) | |||
| @@ -5,7 +5,12 @@ Use nose | |||
| `$ nosetests` | |||
| """ | |||
| from hyde.ext.plugins.meta import MetaPlugin | |||
| <<<<<<< HEAD | |||
| from hyde.ext.plugins.sorter import SorterPlugin | |||
| ======= | |||
| from hyde.ext.plugins.meta import SorterPlugin | |||
| from hyde.fs import File, Folder | |||
| >>>>>>> Move the sorter plugin into the meta module. | |||
| from hyde.generator import Generator | |||
| from hyde.site import Site | |||
| from hyde.model import Config, Expando | |||
| @@ -30,7 +35,7 @@ class TestSorter(object): | |||
| def test_walk_resources_sorted(self): | |||
| s = Site(TEST_SITE) | |||
| s.load() | |||
| s.config.plugins = ['hyde.ext.sorter.SorterPlugin'] | |||
| s.config.plugins = ['hyde.ext.meta.SorterPlugin'] | |||
| s.config.sorter = Expando(dict(kind=dict(attr=['source_file.kind', 'name']))) | |||
| SorterPlugin(s).begin_site() | |||
| @@ -54,7 +59,7 @@ class TestSorter(object): | |||
| def test_walk_resources_sorted_reverse(self): | |||
| s = Site(TEST_SITE) | |||
| s.load() | |||
| s.config.plugins = ['hyde.ext.sorter.SorterPlugin'] | |||
| s.config.plugins = ['hyde.ext.meta.SorterPlugin'] | |||
| s.config.sorter = Expando(dict(kind=dict(attr=['source_file.kind', 'name'], reverse=True))) | |||
| SorterPlugin(s).begin_site() | |||
| @@ -80,7 +85,7 @@ class TestSorter(object): | |||
| s = Site(TEST_SITE) | |||
| cfg = """ | |||
| plugins: | |||
| - hyde.ext.sorter.SorterPlugin | |||
| - hyde.ext.meta.SorterPlugin | |||
| sorter: | |||
| kind2: | |||
| filters: | |||
| @@ -104,7 +109,7 @@ class TestSorter(object): | |||
| s = Site(TEST_SITE) | |||
| cfg = """ | |||
| plugins: | |||
| - hyde.ext.sorter.SorterPlugin | |||
| - hyde.ext.meta.SorterPlugin | |||
| sorter: | |||
| multi: | |||
| attr: | |||
| @@ -142,7 +147,7 @@ class TestSorter(object): | |||
| s = Site(TEST_SITE) | |||
| cfg = """ | |||
| plugins: | |||
| - hyde.ext.sorter.SorterPlugin | |||
| - hyde.ext.meta.SorterPlugin | |||
| sorter: | |||
| kind2: | |||
| filters: | |||
| @@ -167,7 +172,7 @@ class TestSorter(object): | |||
| s = Site(TEST_SITE) | |||
| cfg = """ | |||
| plugins: | |||
| - hyde.ext.sorter.SorterPlugin | |||
| - hyde.ext.meta.SorterPlugin | |||
| sorter: | |||
| kind2: | |||
| filters: | |||
| @@ -203,7 +208,7 @@ class TestSorter(object): | |||
| s = Site(TEST_SITE) | |||
| cfg = """ | |||
| plugins: | |||
| - hyde.ext.sorter.SorterPlugin | |||
| - hyde.ext.meta.SorterPlugin | |||
| sorter: | |||
| folder_name: | |||
| attr: | |||
| @@ -244,7 +249,7 @@ class TestSorter(object): | |||
| title: NahNahNah | |||
| plugins: | |||
| - hyde.ext.plugins.meta.MetaPlugin | |||
| - hyde.ext.plugins.sorter.SorterPlugin | |||
| - hyde.ext.plugins.meta.SorterPlugin | |||
| sorter: | |||
| time: | |||
| attr: meta.time | |||
| @@ -290,7 +295,7 @@ class TestSorterMeta(object): | |||
| def test_attribute_checker_no_meta(self): | |||
| s = Site(TEST_SITE) | |||
| s.load() | |||
| from hyde.ext.plugins.sorter import attributes_checker | |||
| from hyde.ext.plugins.meta import attributes_checker | |||
| for r in s.content.walk_resources(): | |||
| assert not attributes_checker(r, ['meta.index']) | |||
| @@ -298,7 +303,7 @@ class TestSorterMeta(object): | |||
| s = Site(TEST_SITE) | |||
| s.load() | |||
| MetaPlugin(s).begin_site() | |||
| from hyde.ext.plugins.sorter import attributes_checker | |||
| from hyde.ext.plugins.meta import attributes_checker | |||
| have_index = ["angry-post.html", | |||
| "another-sad-post.html", | |||
| "happy-post.html"] | |||
| @@ -4,7 +4,7 @@ media_url: /media # URL where the media files are served from. | |||
| base_url: / # The base url for autogenerated links. | |||
| plugins: | |||
| - hyde.ext.plugins.meta.MetaPlugin | |||
| - hyde.ext.plugins.sorter.SorterPlugin | |||
| - hyde.ext.plugins.meta.SorterPlugin | |||
| - hyde.ext.plugins.structure.PaginatorPlugin | |||
| meta: | |||
| nodemeta: meta.yaml | |||
| @@ -5,7 +5,7 @@ base_url: / # The base url for autogenerated links. | |||
| plugins: | |||
| - hyde.ext.plugins.meta.MetaPlugin | |||
| - hyde.ext.plugins.meta.AutoExtendPlugin | |||
| - hyde.ext.plugins.sorter.SorterPlugin | |||
| - hyde.ext.plugins.meta.SorterPlugin | |||
| - hyde.ext.plugins.text.TextlinksPlugin | |||
| meta: | |||
| nodemeta: meta.yaml | |||
| @@ -5,7 +5,7 @@ base_url: / # The base url for autogenerated links. | |||
| plugins: | |||
| - hyde.ext.plugins.meta.MetaPlugin | |||
| - hyde.ext.plugins.meta.AutoExtendPlugin | |||
| - hyde.ext.plugins.sorter.SorterPlugin | |||
| - hyde.ext.plugins.meta.SorterPlugin | |||
| - hyde.ext.plugins.meta.TaggerPlugin | |||
| - hyde.ext.plugins.text.TextlinksPlugin | |||
| meta: | |||
| @@ -5,7 +5,7 @@ base_url: / # The base url for autogenerated links. | |||
| plugins: | |||
| - hyde.ext.plugins.meta.MetaPlugin | |||
| - hyde.ext.plugins.meta.AutoExtendPlugin | |||
| - hyde.ext.plugins.sorter.SorterPlugin | |||
| - hyde.ext.plugins.meta.SorterPlugin | |||
| - hyde.ext.plugins.meta.TaggerPlugin | |||
| - hyde.ext.plugins.text.SyntextPlugin | |||
| - hyde.ext.plugins.text.TextlinksPlugin | |||