changeset 8018:68e802950fe4

feeds: introduce kallithea.lib.feeds to encapsulate webhelpers.feedgenerator
author Mads Kiilerich <mads@kiilerich.com>
date Thu, 19 Dec 2019 21:23:33 +0100
parents dfd528520236
children 6c9e8aa906cb
files kallithea/controllers/feed.py kallithea/controllers/journal.py kallithea/lib/feeds.py
diffstat 3 files changed, 97 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- a/kallithea/controllers/feed.py	Sat Dec 07 04:20:58 2019 +0100
+++ b/kallithea/controllers/feed.py	Thu Dec 19 21:23:33 2019 +0100
@@ -32,9 +32,9 @@
 from tg import response
 from tg import tmpl_context as c
 from tg.i18n import ugettext as _
-from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
 
 from kallithea import CONFIG
+from kallithea.lib import feeds
 from kallithea.lib import helpers as h
 from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired
 from kallithea.lib.base import BaseRepoController
@@ -45,10 +45,6 @@
 log = logging.getLogger(__name__)
 
 
-language = 'en-us'
-ttl = "5"
-
-
 class FeedController(BaseRepoController):
 
     @LoginRequired(allow_default_user=True)
@@ -102,39 +98,37 @@
         desc_msg.append('</pre>')
         return [safe_unicode(chunk) for chunk in desc_msg]
 
-    def _feed(self, repo_name, kind, feed_factory):
+    def _feed(self, repo_name, feeder):
         """Produce a simple feed"""
 
         @cache_region('long_term', '_get_feed_from_cache')
         def _get_feed_from_cache(*_cache_keys):  # parameters are not really used - only as caching key
-            feed = feed_factory(
+            header = dict(
                 title=_('%s %s feed') % (c.site_name, repo_name),
                 link=h.canonical_url('summary_home', repo_name=repo_name),
                 description=_('Changes on %s repository') % repo_name,
-                language=language,
-                ttl=ttl,  # rss only
             )
 
             rss_items_per_page = safe_int(CONFIG.get('rss_items_per_page', 20))
+            entries=[]
             for cs in reversed(list(c.db_repo_scm_instance[-rss_items_per_page:])):
-                feed.add_item(title=self._get_title(cs),
-                              link=h.canonical_url('changeset_home', repo_name=repo_name,
-                                       revision=cs.raw_id),
-                              author_email=cs.author_email,
-                              author_name=cs.author_name,
-                              description=''.join(self.__get_desc(cs)),
-                              pubdate=cs.date,
-                              )
+                entries.append(dict(
+                    title=self._get_title(cs),
+                    link=h.canonical_url('changeset_home', repo_name=repo_name, revision=cs.raw_id),
+                    author_email=cs.author_email,
+                    author_name=cs.author_name,
+                    description=''.join(self.__get_desc(cs)),
+                    pubdate=cs.date,
+                ))
+            return feeder.render(header, entries)
 
-            response.content_type = feed.mime_type
-            return feed.writeString('utf-8')
-
-        return _get_feed_from_cache(repo_name, kind, c.db_repo.changeset_cache.get('raw_id'))
+        response.content_type = feeder.content_type
+        return _get_feed_from_cache(repo_name, feeder.__name__)
 
     def atom(self, repo_name):
         """Produce a simple atom-1.0 feed"""
-        return self._feed(repo_name, 'ATOM', Atom1Feed)
+        return self._feed(repo_name, feeds.AtomFeed)
 
     def rss(self, repo_name):
-        """Produce an rss2 feed via feedgenerator module"""
-        return self._feed(repo_name, 'RSS', Rss201rev2Feed)
+        """Produce a simple rss2 feed"""
+        return self._feed(repo_name, feeds.RssFeed)
--- a/kallithea/controllers/journal.py	Sat Dec 07 04:20:58 2019 +0100
+++ b/kallithea/controllers/journal.py	Thu Dec 19 21:23:33 2019 +0100
@@ -23,7 +23,6 @@
 :author: marcink
 :copyright: (c) 2013 RhodeCode GmbH, and others.
 :license: GPLv3, see LICENSE.md for more details.
-
 """
 
 import logging
@@ -35,11 +34,11 @@
 from tg import request, response
 from tg import tmpl_context as c
 from tg.i18n import ugettext as _
-from webhelpers.feedgenerator import Atom1Feed, Rss201rev2Feed
 from webob.exc import HTTPBadRequest
 
 import kallithea.lib.helpers as h
 from kallithea.controllers.admin.admin import _journal_filter
+from kallithea.lib import feeds
 from kallithea.lib.auth import LoginRequired
 from kallithea.lib.base import BaseController, render
 from kallithea.lib.page import Page
@@ -104,17 +103,17 @@
 
         return journal
 
-    def _feed(self, repos, feed_factory, link, desc):
+    def _feed(self, repos, feeder, link, desc):
+        response.content_type = feeder.content_type
         journal = self._get_journal_data(repos)
 
-        feed = feed_factory(
+        header = dict(
             title=desc,
             link=link,
             description=desc,
-            language=language,
-            ttl=ttl,
         )
 
+        entries=[]
         for entry in journal[:feed_nr]:
             user = entry.user
             if user is None:
@@ -130,15 +129,16 @@
                 _url = h.canonical_url('changelog_home',
                            repo_name=entry.repository.repo_name)
 
-            feed.add_item(title=title,
-                          pubdate=entry.action_date,
-                          link=_url or h.canonical_url(''),
-                          author_email=user.email,
-                          author_name=user.full_name_or_username,
-                          description=action_extra())
+            entries.append(dict(
+                title=title,
+                pubdate=entry.action_date,
+                link=_url or h.canonical_url(''),
+                author_email=user.email,
+                author_name=user.full_name_or_username,
+                description=action_extra(),
+            ))
 
-        response.content_type = feed.mime_type
-        return feed.writeString('utf-8')
+        return feeder.render(header, entries)
 
     def _atom_feed(self, repos, public=True):
         if public:
@@ -149,7 +149,7 @@
             link = h.canonical_url('journal_atom')
             desc = '%s %s %s' % (c.site_name, _('Journal'), 'atom feed')
 
-        return self._feed(repos, Atom1Feed, link, desc)
+        return self._feed(repos, feeds.AtomFeed, link, desc)
 
     def _rss_feed(self, repos, public=True):
         if public:
@@ -160,7 +160,7 @@
             link = h.canonical_url('journal_atom')
             desc = '%s %s %s' % (c.site_name, _('Journal'), 'rss feed')
 
-        return self._feed(repos, Rss201rev2Feed, link, desc)
+        return self._feed(repos, feeds.RssFeed, link, desc)
 
     @LoginRequired()
     def index(self):
@@ -192,9 +192,7 @@
 
     @LoginRequired()
     def journal_atom(self):
-        """
-        Produce an atom-1.0 feed via feedgenerator module
-        """
+        """Produce a simple atom-1.0 feed"""
         following = UserFollowing.query() \
             .filter(UserFollowing.user_id == request.authuser.user_id) \
             .options(joinedload(UserFollowing.follows_repository)) \
@@ -203,9 +201,7 @@
 
     @LoginRequired()
     def journal_rss(self):
-        """
-        Produce an rss feed via feedgenerator module
-        """
+        """Produce a simple rss2 feed"""
         following = UserFollowing.query() \
             .filter(UserFollowing.user_id == request.authuser.user_id) \
             .options(joinedload(UserFollowing.follows_repository)) \
@@ -261,9 +257,7 @@
 
     @LoginRequired(allow_default_user=True)
     def public_journal_atom(self):
-        """
-        Produce an atom-1.0 feed via feedgenerator module
-        """
+        """Produce a simple atom-1.0 feed"""
         c.following = UserFollowing.query() \
             .filter(UserFollowing.user_id == request.authuser.user_id) \
             .options(joinedload(UserFollowing.follows_repository)) \
@@ -273,9 +267,7 @@
 
     @LoginRequired(allow_default_user=True)
     def public_journal_rss(self):
-        """
-        Produce an rss2 feed via feedgenerator module
-        """
+        """Produce a simple rss2 feed"""
         c.following = UserFollowing.query() \
             .filter(UserFollowing.user_id == request.authuser.user_id) \
             .options(joinedload(UserFollowing.follows_repository)) \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kallithea/lib/feeds.py	Thu Dec 19 21:23:33 2019 +0100
@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""
+kallithea.lib.feeds
+~~~~~~~~~~~~~~~~~~~
+
+Shared code for providing RSS and ATOM feeds.
+"""
+
+import datetime
+import re
+
+from webhelpers import feedgenerator
+
+
+language = 'en-us'
+ttl = "5"
+
+class _Feeder(object):
+
+    content_type = None
+    feed_factory = None  # a webhelpers.feedgenerator
+
+    @classmethod
+    def render(cls, header, entries):
+        feed = cls.feed_factory(
+            language=language,
+            ttl=ttl,  # rss only
+            **header
+        )
+        for e in entries:
+            feed.add_item(**e)
+        return feed.writeString('utf-8')
+
+
+class AtomFeed(_Feeder):
+
+    content_type = 'application/atom+xml'
+
+    feed_factory = feedgenerator.Atom1Feed
+
+
+class RssFeed(_Feeder):
+
+    content_type = 'application/rss+xml'
+
+    feed_factory = feedgenerator.Rss201rev2Feed