A fork of hyde, the static site generation. Some patches will be pushed upstream.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

118 lines
3.5 KiB

  1. # -*- coding: utf-8 -*-
  2. """
  3. Contains classes and utilities related to sorting
  4. resources and nodes in hyde.
  5. """
  6. import re
  7. from hyde.model import Expando
  8. from hyde.plugin import Plugin
  9. from hyde.site import Node, Resource
  10. from hyde.util import add_method, pairwalk
  11. from itertools import ifilter
  12. from functools import partial
  13. from operator import attrgetter
  14. def filter_method(item, settings=None):
  15. """
  16. Returns true if all the filters in the
  17. given settings evaluate to True.
  18. """
  19. all_match = True
  20. default_filters = {}
  21. filters = {}
  22. if hasattr(settings, 'filters'):
  23. filters.update(default_filters)
  24. filters.update(settings.filters.__dict__)
  25. for field, value in filters.items():
  26. try:
  27. res = attrgetter(field)(item)
  28. except:
  29. res = None
  30. if res != value:
  31. all_match = False
  32. break
  33. return all_match
  34. def sort_method(node, settings=None):
  35. """
  36. Sorts the resources in the given node based on the
  37. given settings.
  38. """
  39. attr = 'name'
  40. if settings and hasattr(settings, 'attr') and settings.attr:
  41. attr = settings.attr
  42. filter_ = partial(filter_method, settings=settings)
  43. resources = ifilter(filter_, node.walk_resources())
  44. reverse = False
  45. if settings and hasattr(settings, 'reverse'):
  46. reverse = settings.reverse
  47. if not isinstance(attr, list):
  48. attr = [attr]
  49. return sorted(resources,
  50. key=attrgetter(*attr),
  51. reverse=reverse)
  52. class SorterPlugin(Plugin):
  53. """
  54. Sorter plugin for hyde. Adds the ability to do
  55. sophisticated sorting by expanding the site objects
  56. to support prebuilt sorting methods. These methods
  57. can be used in the templates directly.
  58. Configuration example
  59. ---------------------
  60. #yaml
  61. sorter:
  62. kind:
  63. # Sorts by this attribute name
  64. # Uses `attrgetter` on the resource object
  65. attr: source_file.kind
  66. # The filters to be used before sorting
  67. # This can be used to remove all the items
  68. # that do not apply. For example,
  69. # filtering non html content
  70. filters:
  71. source_file.kind: html
  72. is_processable: True
  73. meta.is_listable: True
  74. """
  75. def __init__(self, site):
  76. super(SorterPlugin, self).__init__(site)
  77. def begin_site(self):
  78. """
  79. Initialize plugin. Add a sort and match method
  80. for every configuration mentioned in site settings
  81. """
  82. config = self.site.config
  83. if not hasattr(config, 'sorter'):
  84. return
  85. for name, settings in config.sorter.__dict__.items():
  86. sort_method_name = 'walk_resources_sorted_by_%s' % name
  87. self.logger.debug("Adding sort methods for [%s]" % name)
  88. add_method(Node, sort_method_name, sort_method, settings=settings)
  89. match_method_name = 'is_%s' % name
  90. add_method(Resource, match_method_name, filter_method, settings)
  91. prev_att = 'prev_by_%s' % name
  92. next_att = 'next_by_%s' % name
  93. setattr(Resource, prev_att, None)
  94. setattr(Resource, next_att, None)
  95. walker = getattr(self.site.content,
  96. sort_method_name,
  97. self.site.content.walk_resources)
  98. for prev, next in pairwalk(walker()):
  99. setattr(prev, next_att, next)
  100. setattr(next, prev_att, prev)