From d3a19b4817223cfc8f2b34279c01358c3b9c013f Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Sat, 31 Mar 2012 21:23:03 -0400 Subject: [PATCH] Move the sorter plugin into the meta module. --- hyde/ext/plugins/meta.py | 119 ++++++++++++++++++++++ hyde/layouts/basic/site.yaml | 2 +- hyde/layouts/starter/site.yaml | 2 +- hyde/tests/ext/test_grouper.py | 8 +- hyde/tests/ext/test_sorter.py | 25 +++-- hyde/tests/sites/test_paginator/site.yaml | 2 +- hyde/tests/sites/test_sorter/site.yaml | 2 +- hyde/tests/sites/test_tagger/site.yaml | 2 +- hyde/tests/ssp/site.yaml | 2 +- 9 files changed, 144 insertions(+), 20 deletions(-) diff --git a/hyde/ext/plugins/meta.py b/hyde/ext/plugins/meta.py index 9807b54..7b1defe 100644 --- a/hyde/ext/plugins/meta.py +++ b/hyde/ext/plugins/meta.py @@ -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) + diff --git a/hyde/layouts/basic/site.yaml b/hyde/layouts/basic/site.yaml index 147222c..a3a6f5d 100644 --- a/hyde/layouts/basic/site.yaml +++ b/hyde/layouts/basic/site.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.SyntextPlugin - hyde.ext.plugins.text.TextlinksPlugin diff --git a/hyde/layouts/starter/site.yaml b/hyde/layouts/starter/site.yaml index 987da59..901719d 100644 --- a/hyde/layouts/starter/site.yaml +++ b/hyde/layouts/starter/site.yaml @@ -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: diff --git a/hyde/tests/ext/test_grouper.py b/hyde/tests/ext/test_grouper.py index 992c501..0a17e47 100644 --- a/hyde/tests/ext/test_grouper.py +++ b/hyde/tests/ext/test_grouper.py @@ -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) \ No newline at end of file + assert_html_equals(out, expected) diff --git a/hyde/tests/ext/test_sorter.py b/hyde/tests/ext/test_sorter.py index 1bfea7e..43e476e 100644 --- a/hyde/tests/ext/test_sorter.py +++ b/hyde/tests/ext/test_sorter.py @@ -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"] diff --git a/hyde/tests/sites/test_paginator/site.yaml b/hyde/tests/sites/test_paginator/site.yaml index ac513fd..07082a3 100644 --- a/hyde/tests/sites/test_paginator/site.yaml +++ b/hyde/tests/sites/test_paginator/site.yaml @@ -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 diff --git a/hyde/tests/sites/test_sorter/site.yaml b/hyde/tests/sites/test_sorter/site.yaml index c15e6a9..2812603 100644 --- a/hyde/tests/sites/test_sorter/site.yaml +++ b/hyde/tests/sites/test_sorter/site.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 diff --git a/hyde/tests/sites/test_tagger/site.yaml b/hyde/tests/sites/test_tagger/site.yaml index 6ca3324..a6a54f2 100644 --- a/hyde/tests/sites/test_tagger/site.yaml +++ b/hyde/tests/sites/test_tagger/site.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: diff --git a/hyde/tests/ssp/site.yaml b/hyde/tests/ssp/site.yaml index ca1c436..bf7a311 100644 --- a/hyde/tests/ssp/site.yaml +++ b/hyde/tests/ssp/site.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.SyntextPlugin - hyde.ext.plugins.text.TextlinksPlugin