Added support for max_age.
authorEevee <git@veekun.com>
Sun, 18 Jul 2010 22:59:42 +0000 (15:59 -0700)
committerEevee <git@veekun.com>
Sun, 18 Jul 2010 22:59:42 +0000 (15:59 -0700)
splinext/frontpage/__init__.py
splinext/frontpage/controllers/frontpage.py

index 2154f6e..e4caec2 100644 (file)
@@ -25,7 +25,7 @@ RSS_SUMMARY_LENGTH = 1000
 FrontPageRSS = namedtuple('FrontPageRSS',
     ['time', 'entry', 'template', 'category', 'content', 'icon'])
 
-def rss_hook(limit, url, title=None, icon=None):
+def rss_hook(limit, max_age, url, title=None, icon=None):
     """Front page handler for news feeds."""
     feed = feedparser.parse(url)
 
@@ -42,6 +42,11 @@ def rss_hook(limit, url, title=None, icon=None):
             timestamp_tuple = entry.updated_parsed
         timestamp = datetime.datetime(*timestamp_tuple[:6])
 
+        if max_age and timestamp < max_age:
+            # Entries should be oldest-first, so we can bail after the first
+            # expired entry
+            break
+
         # Try to find something to show!  Default to the summary, if there is
         # one, or try to generate one otherwise
         content = u''
@@ -97,7 +102,7 @@ FrontPageGit = namedtuple('FrontPageGit',
 FrontPageGitCommit = namedtuple('FrontPageGitCommit',
     ['hash', 'author', 'time', 'subject', 'repo'])
 
-def git_hook(limit, title, gitweb, repo_paths, repo_names,
+def git_hook(limit, max_age, title, gitweb, repo_paths, repo_names,
     tag_pattern=None, icon=None):
 
     """Front page handler for repository history."""
@@ -127,6 +132,22 @@ def git_hook(limit, title, gitweb, repo_paths, repo_names,
 
     updates = []
     for tag, since_tag in zip(interesting_tags, tags[1:]):
+        # Get the date when this tag was actually created
+        args = [
+            'git',
+            '--git-dir=' + repo_paths[0],
+            'for-each-ref',
+            '--format=%(taggerdate:raw)',
+            'refs/tags/' + tag,
+        ]
+        tag_timestamp, _ = subprocess.Popen(args, stdout=subprocess.PIPE) \
+            .communicate()
+        tag_unixtime, tag_timezone = tag_timestamp.split(None, 1)
+        tagged_timestamp = datetime.datetime.fromtimestamp(int(tag_unixtime))
+
+        if max_age and tagged_timestamp < max_age:
+            break
+
         commits = []
 
         for repo_path, repo_name in zip(repo_paths, repo_names):
@@ -152,19 +173,8 @@ def git_hook(limit, title, gitweb, repo_paths, repo_names,
                     )
                 )
 
-        # LASTLY, get the date when this tag was actually created
-        args = [
-            'git',
-            'for-each-ref',
-            '--format=%(taggerdate:raw)',
-            'refs/tags/' + tag,
-        ]
-        tag_timestamp, _ = subprocess.Popen(args, stdout=subprocess.PIPE) \
-            .communicate()
-        tag_unixtime, tag_timezone = tag_timestamp.split(None, 1)
-
         update = FrontPageGit(
-            time = datetime.datetime.fromtimestamp(int(tag_unixtime)),
+            time = tagged_timestamp,
             gitweb = gitweb,
             log = commits,
             template = '/front_page/git.mako',
index 478c367..5aba8c5 100644 (file)
@@ -1,4 +1,5 @@
 from collections import defaultdict
+import datetime
 import logging
 import re
 
@@ -26,8 +27,13 @@ class FrontPageController(BaseController):
 
         Hook handlers should return a list of FrontPageUpdate objects.
 
-        Standard hook parameters are `limit`, the maximum number of items that
-        should ever be returned.
+        Standard hook parameters are:
+        `limit`, the maximum number of items that should ever be returned.
+        `max_age`, the number of seconds after which items expire.
+        `title`, a name for the source.
+        `icon`, an icon to show next to its name.
+
+        `limit` and `max_age` are also global options.
 
         Updates are configured in the .ini like so:
 
@@ -40,9 +46,6 @@ class FrontPageController(BaseController):
 
             run_hooks('frontpage_updates_updatetype', opt1=val1, opt2=val2)
 
-        Standard options are not shown and take precedence over whatever's in
-        the config file.
-
         Local plugins can override the fairly simple index.mako template to
         customize the front page layout.
         """
@@ -60,29 +63,58 @@ class FrontPageController(BaseController):
                 # This is the type declaration; use a special key
                 subkey = '__type__'
 
+            if subkey in ('limit', 'max_age'):
+                val = int(val)
             update_config[source_name][subkey] = val
 
-
-        global_config = dict(
-            limit = 10,
-        )
+        global_limit = int(config.get('spline-frontpage.limit', 10))
+        now = datetime.datetime.now()
+        try:
+            global_max_age = now - datetime.timedelta(
+                seconds=int(config['spline-frontpage.max_age']))
+        except KeyError:
+            global_max_age = None
 
         # Ask plugins to deal with this stuff for us!
         updates = []
         for source, source_config in update_config.iteritems():
-            source_config2 = source_config.copy()
-            hook_name = 'frontpage_updates_' + source_config2.pop('__type__')
-            source_config2.update(global_config)
-
-            # Hooks should return a list of FrontPageUpdate objects, making this
-            # return value a list of lists
-            updates_lol = run_hooks(hook_name, **source_config2)
+            hook_name = 'frontpage_updates_' + source_config['__type__']
+
+            # Merge with the global config
+            merged_config = source_config.copy()
+            del merged_config['__type__']
+
+            merged_config['limit'] = min(
+                merged_config.get('limit', global_limit),
+                global_limit,
+            )
+
+            try:
+                local_max_age = now - datetime.timedelta(
+                    seconds=merged_config['max_age'])
+            except KeyError:
+                local_max_age = None
+
+            if global_max_age and local_max_age:
+                merged_config['max_age'] = max(global_max_age, local_max_age)
+            else:
+                merged_config['max_age'] = global_max_age or local_max_age
+
+            # Hooks should return a list of FrontPageUpdate-like objects,
+            # making this return value a list of lists
+            updates_lol = run_hooks(hook_name, **merged_config)
             updates += sum(updates_lol, [])
 
-        # Sort everything by descending time, then crop to the right number of
-        # items
-        updates.sort(key=lambda obj: obj.time)
-        updates.reverse()
-        c.updates = updates[:global_config['limit']]
+            # Little optimization: maximum age effectively becomes the age of
+            # the oldest thing that would still appear on the page, as anything
+            # older would drop off the end no matter what.
+            # So sort by descending time and crop each iteration...
+            updates.sort(key=lambda obj: obj.time, reverse=True)
+            updates = updates[:global_limit]
+
+            if updates:
+                global_max_age = updates[-1].time
+
+        c.updates = updates
 
         return render('/index.mako')