/splinext/frontpage/__init__.py

https://github.com/veekun/spline · Python · 97 lines · 66 code · 14 blank · 17 comment · 4 complexity · e0b2a1555f9dd65977bea37beaee8371 MD5 · raw file

  1. from collections import defaultdict, namedtuple
  2. from pkg_resources import resource_filename
  3. import re
  4. import subprocess
  5. from pylons import config
  6. from spline.lib import helpers
  7. from spline.lib.plugin import PluginBase, PluginLink, Priority
  8. from spline.lib.plugin.load import run_hooks
  9. import splinext.frontpage.controllers.frontpage
  10. from splinext.frontpage.sources import FeedSource, GitSource
  11. def add_routes_hook(map, *args, **kwargs):
  12. """Hook to inject some of our behavior into the routes configuration."""
  13. map.connect('/', controller='frontpage', action='index')
  14. def load_sources_hook(config, *args, **kwargs):
  15. """Hook to load all the known sources and stuff them in config. Run once,
  16. on server startup.
  17. Frontpage hooks are also passed the `config` hash, as it's not available
  18. during setup.
  19. """
  20. # Extract source definitions from config and store as source_name => config
  21. update_config = defaultdict(dict)
  22. key_rx = re.compile(
  23. '(?x) ^ spline-frontpage [.] sources [.] (\w+) (?: [.] (\w+) )? $')
  24. for key, val in config.iteritems():
  25. # Match against spline-frontpage.source.(source).(key)
  26. match = key_rx.match(key)
  27. if not match:
  28. continue
  29. source_name, subkey = match.groups()
  30. if not subkey:
  31. # This is the type declaration; use a special key
  32. subkey = '__type__'
  33. update_config[source_name][subkey] = val
  34. # Figure out the global limit and expiration time, with reasonable
  35. # defaults. Make sure they're integers.
  36. global_limit = int(config.get('spline-frontpage.limit', 10))
  37. # max_age is optional and can be None
  38. try:
  39. global_max_age = int(config['spline-frontpage.max_age'])
  40. except KeyError:
  41. global_max_age = None
  42. config['spline-frontpage.limit'] = global_limit
  43. config['spline-frontpage.max_age'] = global_max_age
  44. # Ask plugins to turn configuration into source objects
  45. sources = []
  46. for source, source_config in update_config.iteritems():
  47. hook_name = 'frontpage_updates_' + source_config['__type__']
  48. del source_config['__type__'] # don't feed this to constructor!
  49. # Default to global limit and max age. Source takes care of making
  50. # integers and whatnot
  51. source_config.setdefault('limit', global_limit)
  52. source_config.setdefault('max_age', global_max_age)
  53. # Hooks return a list of sources; combine with running list
  54. sources += run_hooks(hook_name, config=config, **source_config)
  55. # Save the list of sources, and done
  56. config['spline-frontpage.sources'] = sources
  57. def source_cron_hook(*args, **kwargs):
  58. """Hook to pass on cron tics to all sources, should they need it for e.g.
  59. caching.
  60. """
  61. for source in config['spline-frontpage.sources']:
  62. source.do_cron(*args, **kwargs)
  63. class FrontPagePlugin(PluginBase):
  64. def controllers(self):
  65. return dict(
  66. frontpage = splinext.frontpage.controllers.frontpage.FrontPageController,
  67. )
  68. def template_dirs(self):
  69. return [
  70. (resource_filename(__name__, 'templates'), Priority.FIRST)
  71. ]
  72. def hooks(self):
  73. return [
  74. ('routes_mapping', Priority.NORMAL, add_routes_hook),
  75. ('after_setup', Priority.NORMAL, load_sources_hook),
  76. ('cron', Priority.NORMAL, source_cron_hook),
  77. ('frontpage_updates_rss', Priority.NORMAL, FeedSource),
  78. ('frontpage_updates_git', Priority.NORMAL, GitSource),
  79. ]