Return-Path: X-Original-To: apmail-incubator-allura-commits-archive@minotaur.apache.org Delivered-To: apmail-incubator-allura-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id B65CEF477 for ; Tue, 7 May 2013 22:29:31 +0000 (UTC) Received: (qmail 58509 invoked by uid 500); 7 May 2013 22:29:31 -0000 Delivered-To: apmail-incubator-allura-commits-archive@incubator.apache.org Received: (qmail 58486 invoked by uid 500); 7 May 2013 22:29:31 -0000 Mailing-List: contact allura-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: allura-dev@incubator.apache.org Delivered-To: mailing list allura-commits@incubator.apache.org Received: (qmail 58417 invoked by uid 99); 7 May 2013 22:29:31 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 07 May 2013 22:29:31 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 59417889128; Tue, 7 May 2013 22:29:31 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: tvansteenburgh@apache.org To: allura-commits@incubator.apache.org Date: Tue, 07 May 2013 22:29:35 -0000 Message-Id: In-Reply-To: <2c3f31fc313f4f6cb54827abcb408fb0@git.apache.org> References: <2c3f31fc313f4f6cb54827abcb408fb0@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [05/50] [abbrv] git commit: [#6172] Refactor feed functionality into mixin controller [#6172] Refactor feed functionality into mixin controller Signed-off-by: Tim Van Steenburgh Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/391aa922 Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/391aa922 Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/391aa922 Branch: refs/heads/tv/2053 Commit: 391aa92294b69a228cee4b857c65e0d780ee0a36 Parents: 7244932 Author: Tim Van Steenburgh Authored: Tue Apr 30 17:44:37 2013 +0000 Committer: Dave Brondsema Committed: Tue Apr 30 19:45:59 2013 +0000 ---------------------------------------------------------------------- Allura/allura/controllers/basetest_project_root.py | 2 - Allura/allura/controllers/discuss.py | 75 ++++------- Allura/allura/controllers/feed.py | 108 +++++++++++++++ Allura/allura/controllers/project.py | 39 ++---- Allura/allura/controllers/repository.py | 31 +---- Allura/allura/ext/user_profile/user_main.py | 55 ++------ ForgeBlog/forgeblog/main.py | 62 ++------- .../forgediscussion/controllers/root.py | 44 ++---- ForgeSVN/forgesvn/controllers.py | 3 +- ForgeSVN/forgesvn/svn_main.py | 3 - ForgeTracker/forgetracker/tracker_main.py | 64 ++------- ForgeWiki/forgewiki/wiki_main.py | 67 ++------- 12 files changed, 219 insertions(+), 334 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/391aa922/Allura/allura/controllers/basetest_project_root.py ---------------------------------------------------------------------- diff --git a/Allura/allura/controllers/basetest_project_root.py b/Allura/allura/controllers/basetest_project_root.py index f9ec3d5..8c48ed6 100644 --- a/Allura/allura/controllers/basetest_project_root.py +++ b/Allura/allura/controllers/basetest_project_root.py @@ -66,8 +66,6 @@ class BasetestProjectRootController(WsgiDispatchController, ProjectController): ''' def __init__(self): - setattr(self, 'feed.rss', self.feed) - setattr(self, 'feed.atom', self.feed) for n in M.Neighborhood.query.find(): if n.url_prefix.startswith('//'): continue n.bind_controller(self) http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/391aa922/Allura/allura/controllers/discuss.py ---------------------------------------------------------------------- diff --git a/Allura/allura/controllers/discuss.py b/Allura/allura/controllers/discuss.py index 5abb3a2..b37d880 100644 --- a/Allura/allura/controllers/discuss.py +++ b/Allura/allura/controllers/discuss.py @@ -38,6 +38,7 @@ from allura.lib.helpers import DateTimeConverter from allura.lib.widgets import discuss as DW from .attachments import AttachmentsController, AttachmentController +from .feed import Feed, FeedController log = logging.getLogger(__name__) @@ -68,13 +69,11 @@ class WidgetConfig(object): thread_header = DW.ThreadHeader() # Controllers -class DiscussionController(BaseController): +class DiscussionController(BaseController, FeedController): M=ModelConfig W=WidgetConfig def __init__(self): - setattr(self, 'feed.rss', self.feed) - setattr(self, 'feed.atom', self.feed) if not hasattr(self, 'ThreadController'): self.ThreadController = ThreadController if not hasattr(self, 'PostController'): @@ -106,29 +105,18 @@ class DiscussionController(BaseController): M.session.artifact_orm_session._get().skip_mod_date = True redirect(request.referer) - @without_trailing_slash - @expose() - @validate(dict( - since=DateTimeConverter(if_empty=None), - until=DateTimeConverter(if_empty=None), - page=validators.Int(if_empty=None), - limit=validators.Int(if_empty=None))) - def feed(self, since=None, until=None, page=None, limit=None, **kw): - if request.environ['PATH_INFO'].endswith('.atom'): - feed_type = 'atom' - else: - feed_type = 'rss' - title = 'Recent posts to %s' % self.discussion.name - feed = M.Feed.feed( + def get_feed(self, project, app, user): + """Return a :class:`allura.controllers.feed.Feed` object describing + the xml feed for this controller. + + Overrides :meth:`allura.controllers.feed.FeedController.get_feed`. + + """ + return Feed( dict(ref_id={'$in': [t.index_id() for t in self.discussion.threads]}), - feed_type, - title, - self.discussion.url(), - title, - since, until, page, limit) - response.headers['Content-Type'] = '' - response.content_type = 'application/xml' - return feed.writeString('utf-8') + 'Recent posts to %s' % self.discussion.name, + self.discussion.url()) + class AppDiscussionController(DiscussionController): @@ -156,7 +144,7 @@ class ThreadsController(BaseController): else: raise exc.HTTPNotFound() -class ThreadController(BaseController): +class ThreadController(BaseController, FeedController): __metaclass__=h.ProxiedAttrMeta M=h.attrproxy('_discussion_controller', 'M') W=h.attrproxy('_discussion_controller', 'W') @@ -170,8 +158,6 @@ class ThreadController(BaseController): require_access(self.thread.ref.artifact, 'read') def __init__(self, discussion_controller, thread_id): - setattr(self, 'feed.rss', self.feed) - setattr(self, 'feed.atom', self.feed) self._discussion_controller = discussion_controller self.discussion = discussion_controller.discussion self.thread = self.M.Thread.query.get(_id=thread_id) @@ -237,29 +223,18 @@ class ThreadController(BaseController): flash('Thread flagged as spam.') redirect(self.discussion.url()) - @without_trailing_slash - @expose() - @validate(dict( - since=DateTimeConverter(if_empty=None), - until=DateTimeConverter(if_empty=None), - page=validators.Int(if_empty=None), - limit=validators.Int(if_empty=None))) - def feed(self, since=None, until=None, page=None, limit=None, **kw): - if request.environ['PATH_INFO'].endswith('.atom'): - feed_type = 'atom' - else: - feed_type = 'rss' - title = 'Recent posts to %s' % (self.thread.subject or '(no subject)') - feed = M.Feed.feed( + def get_feed(self, project, app, user): + """Return a :class:`allura.controllers.feed.Feed` object describing + the xml feed for this controller. + + Overrides :meth:`allura.controllers.feed.FeedController.get_feed`. + + """ + return Feed( dict(ref_id=self.thread.index_id()), - feed_type, - title, - self.thread.url(), - title, - since, until, page, limit) - response.headers['Content-Type'] = '' - response.content_type = 'application/xml' - return feed.writeString('utf-8') + 'Recent posts to %s' % (self.thread.subject or '(no subject)'), + self.thread.url()) + class PostController(BaseController): __metaclass__=h.ProxiedAttrMeta http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/391aa922/Allura/allura/controllers/feed.py ---------------------------------------------------------------------- diff --git a/Allura/allura/controllers/feed.py b/Allura/allura/controllers/feed.py new file mode 100644 index 0000000..f014b21 --- /dev/null +++ b/Allura/allura/controllers/feed.py @@ -0,0 +1,108 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +from tg import expose, validate, request, response +from tg.decorators import without_trailing_slash +from formencode import validators as V +from pylons import tmpl_context as c +from webob import exc + +from allura import model as M +from allura.lib import helpers as h + + +class Feed(object): + """A facade for the arguments required by + :meth:`allura.model.artifact.Feed.feed`. + + Used by :meth:`FeedController.feed` to create a real feed. + + """ + def __init__(self, query, title, url, description=None): + self.query = query + self.title = title + self.url = url + self.description = description or title + + +class FeedController(object): + """Mixin class which adds RSS and Atom feed endpoints to an existing + controller. + + Feeds will be accessible at the following URLs: + + http://host/path/to/controller/feed -> RSS + http://host/path/to/controller/feed.rss -> RSS + http://host/path/to/controller/feed.atom -> Atom + + A default feed is provided by :meth:`get_feed`. Subclasses that need + a customized feed should override :meth:`get_feed`. + + """ + FEED_TYPES = ['.atom', '.rss'] + FEED_NAMES = ['feed{0}'.format(typ) for typ in FEED_TYPES] + + def __getattr__(self, name): + if name in self.FEED_NAMES: + return self.feed + raise AttributeError(name) + + def _get_feed_type(self, request): + for typ in self.FEED_TYPES: + if request.environ['PATH_INFO'].endswith(typ): + return typ.lstrip('.') + return 'rss' + + @without_trailing_slash + @expose() + @validate(dict( + since=h.DateTimeConverter(if_empty=None, if_invalid=None), + until=h.DateTimeConverter(if_empty=None, if_invalid=None), + page=V.Int(if_empty=None), + limit=V.Int(if_empty=None))) + def feed(self, since=None, until=None, page=None, limit=None, **kw): + """Return a utf8-encoded XML feed (RSS or Atom) to the browser. + """ + feed_def = self.get_feed(c.project, c.app, c.user) + if not feed_def: + raise exc.HTTPNotFound + feed = M.Feed.feed( + feed_def.query, + self._get_feed_type(request), + feed_def.title, + feed_def.url, + feed_def.description, + since, until, page, limit) + response.headers['Content-Type'] = '' + response.content_type = 'application/xml' + return feed.writeString('utf-8') + + def get_feed(self, project, app, user): + """Return a default :class:`Feed` for this controller. + + Subclasses should override to customize the feed. + + :param project: :class:`allura.model.project.Project` + :param app: :class:`allura.app.Application` + :param user: :class:`allura.model.auth.User` + :rtype: :class:`Feed` + + """ + return Feed( + dict(project_id=project._id, app_config_id=app.config._id), + 'Recent changes to %s' % app.config.options.mount_point, + app.url) http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/391aa922/Allura/allura/controllers/project.py ---------------------------------------------------------------------- diff --git a/Allura/allura/controllers/project.py b/Allura/allura/controllers/project.py index 4f02632..3bfe0ca 100644 --- a/Allura/allura/controllers/project.py +++ b/Allura/allura/controllers/project.py @@ -40,6 +40,7 @@ from allura.lib import helpers as h from allura.lib import utils from allura.lib.decorators import require_post from allura.controllers.error import ErrorController +from allura.controllers.feed import Feed, FeedController from allura.lib.security import require_access, has_access from allura.lib.security import RoleCache from allura.lib.widgets import forms as ff @@ -299,11 +300,9 @@ class ToolListController(object): if e.tool_name and e.tool_name.lower() == tool_name] return dict(entries=entries, type=entries[0].tool_name.capitalize() if entries else None) -class ProjectController(object): +class ProjectController(FeedController): def __init__(self): - setattr(self, 'feed.rss', self.feed) - setattr(self, 'feed.atom', self.feed) setattr(self, '_nav.json', self._nav) self.screenshot = ScreenshotsController() self._list = ToolListController() @@ -367,29 +366,17 @@ class ProjectController(object): else: redirect(c.project.app_configs[0].options.mount_point + '/') - @without_trailing_slash - @expose() - @validate(dict( - since=h.DateTimeConverter(if_empty=None, if_invalid=None), - until=h.DateTimeConverter(if_empty=None, if_invalid=None), - page=validators.Int(if_empty=None), - limit=validators.Int(if_empty=None))) - def feed(self, since=None, until=None, page=None, limit=None, **kw): - if request.environ['PATH_INFO'].endswith('.atom'): - feed_type = 'atom' - else: - feed_type = 'rss' - title = 'Recent changes to Project %s' % c.project.name - feed = M.Feed.feed( - dict(project_id=c.project._id), - feed_type, - title, - c.project.url(), - title, - since, until, page, limit) - response.headers['Content-Type'] = '' - response.content_type = 'application/xml' - return feed.writeString('utf-8') + def get_feed(self, project, app, user): + """Return a :class:`allura.controllers.feed.Feed` object describing + the xml feed for this controller. + + Overrides :meth:`allura.controllers.feed.FeedController.get_feed`. + + """ + return Feed( + dict(project_id=project._id), + 'Recent changes to Project %s' % project.name, + project.url()) @expose() def icon(self, **kw): http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/391aa922/Allura/allura/controllers/repository.py ---------------------------------------------------------------------- diff --git a/Allura/allura/controllers/repository.py b/Allura/allura/controllers/repository.py index 5e006ba..59b154e 100644 --- a/Allura/allura/controllers/repository.py +++ b/Allura/allura/controllers/repository.py @@ -49,6 +49,7 @@ from allura.lib.widgets.subscriptions import SubscribeForm from allura import model as M from allura.lib.widgets import form_fields as ffw from allura.controllers.base import DispatchIndex +from allura.controllers.feed import FeedController from allura.lib.diff import HtmlSideBySideDiff from paste.deploy.converters import asbool from allura.app import SitemapEntry @@ -61,14 +62,10 @@ def on_import(): CommitBrowser.TreeBrowserClass = TreeBrowser TreeBrowser.FileBrowserClass = FileBrowser -class RepoRootController(BaseController): +class RepoRootController(BaseController, FeedController): _discuss = AppDiscussionController() commit_browser_widget=SCMCommitBrowserWidget() - def __init__(self): - setattr(self, 'feed.atom', self.feed) - setattr(self, 'feed.rss', self.feed) - def _check_security(self): security.require(security.has_access(c.app, 'read')) @@ -187,30 +184,6 @@ class RepoRootController(BaseController): redirect(mr.url()) @without_trailing_slash - @expose() - @validate(dict( - since=h.DateTimeConverter(if_empty=None, if_invalid=None), - until=h.DateTimeConverter(if_empty=None, if_invalid=None), - offset=validators.Int(if_empty=None), - limit=validators.Int(if_empty=None))) - def feed(self, since=None, until=None, offset=None, limit=None, **kw): - if request.environ['PATH_INFO'].endswith('.atom'): - feed_type = 'atom' - else: - feed_type = 'rss' - title = 'Recent changes to %s' % c.app.config.options.mount_point - feed = M.Feed.feed( - dict(project_id=c.project._id,app_config_id=c.app.config._id), - feed_type, - title, - c.app.url, - title, - since, until, offset, limit) - response.headers['Content-Type'] = '' - response.content_type = 'application/xml' - return feed.writeString('utf-8') - - @without_trailing_slash @expose('jinja:allura:templates/repo/commit_browser.html') def commit_browser(self): if not c.app.repo or c.app.repo.status != 'ready': http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/391aa922/Allura/allura/ext/user_profile/user_main.py ---------------------------------------------------------------------- diff --git a/Allura/allura/ext/user_profile/user_main.py b/Allura/allura/ext/user_profile/user_main.py index 0491199..c6e2402 100644 --- a/Allura/allura/ext/user_profile/user_main.py +++ b/Allura/allura/ext/user_profile/user_main.py @@ -32,6 +32,7 @@ from allura.lib.helpers import DateTimeConverter from allura.lib.security import require_access from allura.model import User, Feed, ACE from allura.controllers import BaseController +from allura.controllers.feed import Feed, FeedController from allura.lib.decorators import require_post log = logging.getLogger(__name__) @@ -79,11 +80,7 @@ class UserProfileApp(Application): pass -class UserProfileController(BaseController): - - def __init__(self): - setattr(self, 'feed.rss', self.feed) - setattr(self, 'feed.atom', self.feed) +class UserProfileController(BaseController, FeedController): def _check_security(self): require_access(c.project, 'read') @@ -94,38 +91,16 @@ class UserProfileController(BaseController): if not user: raise exc.HTTPNotFound() return dict(user=user) - # This will be fully implemented in a future iteration - # @expose('jinja:allura.ext.user_profile:templates/user_subscriptions.html') - # def subscriptions(self): - # username = c.project.shortname.split('/')[1] - # user = User.by_username(username) - # subs = Subscriptions.query.find({'user_id':user._id}).all() - # for sub in subs: - # for s in sub.subscriptions: - # r = g.solr_short_timeout.search(s.artifact_index_id) - # print r.docs - # return dict(user=user) - - @expose() - @validate(dict( - since=DateTimeConverter(if_empty=None), - until=DateTimeConverter(if_empty=None), - page=validators.Int(if_empty=None), - limit=validators.Int(if_empty=None))) - def feed(self, since=None, until=None, page=None, limit=None, **kw): - user = c.project.user_project_of - if request.environ['PATH_INFO'].endswith('.atom'): - feed_type = 'atom' - else: - feed_type = 'rss' - title = 'Recent posts by %s' % user.display_name - feed = Feed.feed( - {'author_link':user.url()}, - feed_type, - title, - c.project.url(), - title, - since, until, page, limit) - response.headers['Content-Type'] = '' - response.content_type = 'application/xml' - return feed.writeString('utf-8') + + def get_feed(self, project, app, user): + """Return a :class:`allura.controllers.feed.Feed` object describing + the xml feed for this controller. + + Overrides :meth:`allura.controllers.feed.FeedController.get_feed`. + + """ + user = project.user_project_of + return Feed( + {'author_link': user.url()}, + 'Recent posts by %s' % user.display_name, + project.url()) http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/391aa922/ForgeBlog/forgeblog/main.py ---------------------------------------------------------------------- diff --git a/ForgeBlog/forgeblog/main.py b/ForgeBlog/forgeblog/main.py index f745af9..0c7af13 100644 --- a/ForgeBlog/forgeblog/main.py +++ b/ForgeBlog/forgeblog/main.py @@ -46,6 +46,7 @@ from allura.lib.widgets import form_fields as ffw from allura.lib.widgets.search import SearchResults, SearchHelp from allura import model as M from allura.controllers import BaseController, AppDiscussionController +from allura.controllers.feed import Feed, FeedController # Local imports from forgeblog import model as BM @@ -180,11 +181,9 @@ class ForgeBlogApp(Application): BM.BlogPostSnapshot.query.remove(dict(app_config_id=c.app.config._id)) super(ForgeBlogApp, self).uninstall(project) -class RootController(BaseController): +class RootController(BaseController, FeedController): def __init__(self): - setattr(self, 'feed.atom', self.feed) - setattr(self, 'feed.rss', self.feed) self._discuss = AppDiscussionController() def _check_security(self): @@ -255,30 +254,6 @@ class RootController(BaseController): redirect(h.really_unicode(post.url()).encode('utf-8')) - @without_trailing_slash - @expose() - @validate(dict( - since=h.DateTimeConverter(if_empty=None, if_invalid=None), - until=h.DateTimeConverter(if_empty=None, if_invalid=None), - offset=validators.Int(if_empty=None), - limit=validators.Int(if_empty=None))) - def feed(self, since=None, until=None, offset=None, limit=None, **kw): - if request.environ['PATH_INFO'].endswith('.atom'): - feed_type = 'atom' - else: - feed_type = 'rss' - title = '%s - %s' % (c.project.name, c.app.config.options.mount_label) - feed = M.Feed.feed( - dict(project_id=c.project._id, app_config_id=c.app.config._id), - feed_type, - title, - c.app.url, - title, - since, until, offset, limit) - response.headers['Content-Type'] = '' - response.content_type = 'application/xml' - return feed.writeString('utf-8') - @with_trailing_slash @expose('jinja:allura:templates/markdown_syntax_dialog.html') def markdown_syntax_dialog(self, **kw): @@ -293,12 +268,10 @@ class RootController(BaseController): raise exc.HTTPNotFound() return PostController(post), rest -class PostController(BaseController): +class PostController(BaseController, FeedController): def __init__(self, post): self.post = post - setattr(self, 'feed.atom', self.feed) - setattr(self, 'feed.rss', self.feed) def _check_security(self): require_access(self.post, 'read') @@ -380,28 +353,17 @@ class PostController(BaseController): self.post.unsubscribe() redirect(h.really_unicode(request.referer).encode('utf-8')) - @without_trailing_slash - @expose() - @validate(dict( - since=h.DateTimeConverter(if_empty=None, if_invalid=None), - until=h.DateTimeConverter(if_empty=None, if_invalid=None), - offset=validators.Int(if_empty=None), - limit=validators.Int(if_empty=None))) - def feed(self, since=None, until=None, offset=None, limit=None, **kw): - if request.environ['PATH_INFO'].endswith('.atom'): - feed_type = 'atom' - else: - feed_type = 'rss' - feed = M.Feed.feed( + def get_feed(self, project, app, user): + """Return a :class:`allura.controllers.feed.Feed` object describing + the xml feed for this controller. + + Overrides :meth:`allura.controllers.feed.FeedController.get_feed`. + + """ + return Feed( dict(ref_id=self.post.index_id()), - feed_type, - 'Recent changes to %s' % self.post.title, - self.post.url(), 'Recent changes to %s' % self.post.title, - since, until, offset, limit) - response.headers['Content-Type'] = '' - response.content_type = 'application/xml' - return feed.writeString('utf-8') + self.post.url()) def _get_version(self, version): if not version: return self.post http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/391aa922/ForgeDiscussion/forgediscussion/controllers/root.py ---------------------------------------------------------------------- diff --git a/ForgeDiscussion/forgediscussion/controllers/root.py b/ForgeDiscussion/forgediscussion/controllers/root.py index 02c3cde..f731da3 100644 --- a/ForgeDiscussion/forgediscussion/controllers/root.py +++ b/ForgeDiscussion/forgediscussion/controllers/root.py @@ -27,14 +27,13 @@ from pylons import request from formencode import validators from webob import exc - from allura.lib.security import require_access, has_access, require_authenticated -from allura.model import Feed from allura.lib.search import search_app from allura.lib import helpers as h from allura.lib.utils import AntiSpam from allura.lib.decorators import require_post from allura.controllers import BaseController, DispatchIndex +from allura.controllers.feed import Feed, FeedController from .forum import ForumController from forgediscussion import import_support @@ -48,7 +47,7 @@ from forgediscussion.widgets.admin import AddForumShort log = logging.getLogger(__name__) -class RootController(BaseController, DispatchIndex): +class RootController(BaseController, DispatchIndex, FeedController): class W(object): forum_subscription_form=FW.ForumSubscriptionForm() @@ -58,10 +57,6 @@ class RootController(BaseController, DispatchIndex): search_results = SearchResults() search_help = SearchHelp(comments=False, history=False) - def __init__(self): - setattr(self, 'feed.rss', self.feed) - setattr(self, 'feed.atom', self.feed) - def _check_security(self): require_access(c.app, 'read') @@ -191,29 +186,18 @@ class RootController(BaseController, DispatchIndex): obj['obj'].subscriptions.pop(str(c.user._id), None) redirect(request.referer) - @expose() - @validate(dict( - since=h.DateTimeConverter(if_empty=None), - until=h.DateTimeConverter(if_empty=None), - page=validators.Int(if_empty=None), - limit=validators.Int(if_empty=None))) - def feed(self, since=None, until=None, page=None, limit=None, **kw): - if request.environ['PATH_INFO'].endswith('.atom'): - feed_type = 'atom' - else: - feed_type = 'rss' - title = 'Recent posts to %s' % c.app.config.options.mount_label - - feed = Feed.feed( - dict(project_id=c.project._id, app_config_id=c.app.config._id), - feed_type, - title, - c.app.url, - title, - since, until, page, limit) - response.headers['Content-Type'] = '' - response.content_type = 'application/xml' - return feed.writeString('utf-8') + def get_feed(self, project, app, user): + """Return a :class:`allura.controllers.feed.Feed` object describing + the xml feed for this controller. + + Overrides :meth:`allura.controllers.feed.FeedController.get_feed`. + + """ + return Feed( + dict(project_id=project._id, app_config_id=app.config._id), + 'Recent posts to %s' % app.config.options.mount_label, + app.url) + class RootRestController(BaseController): http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/391aa922/ForgeSVN/forgesvn/controllers.py ---------------------------------------------------------------------- diff --git a/ForgeSVN/forgesvn/controllers.py b/ForgeSVN/forgesvn/controllers.py index 2e39fc7..66709f0 100644 --- a/ForgeSVN/forgesvn/controllers.py +++ b/ForgeSVN/forgesvn/controllers.py @@ -20,9 +20,10 @@ from tg.decorators import with_trailing_slash from pylons import tmpl_context as c from allura.controllers import repository +from allura.controllers.feed import FeedController -class BranchBrowser(repository.BranchBrowser): +class BranchBrowser(repository.BranchBrowser, FeedController): def __init__(self): super(BranchBrowser, self).__init__(None) http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/391aa922/ForgeSVN/forgesvn/svn_main.py ---------------------------------------------------------------------- diff --git a/ForgeSVN/forgesvn/svn_main.py b/ForgeSVN/forgesvn/svn_main.py index ef7d008..dcb4fd6 100644 --- a/ForgeSVN/forgesvn/svn_main.py +++ b/ForgeSVN/forgesvn/svn_main.py @@ -64,9 +64,6 @@ class ForgeSVNApp(RepositoryApp): self.root = BranchBrowser() default_root = RepoRootController() self.root.refresh = default_root.refresh - self.root.feed = default_root.feed - setattr(self.root, 'feed.rss', self.root.feed) - setattr(self.root, 'feed.atom', self.root.feed) self.root.commit_browser = default_root.commit_browser self.root.commit_browser_data = default_root.commit_browser_data self.root.status = default_root.status http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/391aa922/ForgeTracker/forgetracker/tracker_main.py ---------------------------------------------------------------------- diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py index 349ef1e..6270e96 100644 --- a/ForgeTracker/forgetracker/tracker_main.py +++ b/ForgeTracker/forgetracker/tracker_main.py @@ -61,6 +61,7 @@ from allura.lib.zarkov_helpers import zero_fill_zarkov_result from allura.controllers import AppDiscussionController, AppDiscussionRestController from allura.controllers import attachments as ac from allura.controllers import BaseController +from allura.controllers.feed import Feed, FeedController from allura.tasks import mail_tasks # Local imports @@ -467,11 +468,9 @@ def solr_columns(): columns.append(dict(name='votes', sort_name='votes_total_i', label='Votes', active=True)) return columns -class RootController(BaseController): +class RootController(BaseController, FeedController): def __init__(self): - setattr(self, 'feed.atom', self.feed) - setattr(self, 'feed.rss', self.feed) setattr(self, 'search_feed.atom', self.search_feed) setattr(self, 'search_feed.rss', self.search_feed) self._discuss = AppDiscussionController() @@ -711,30 +710,6 @@ class RootController(BaseController): 'Static page explaining markdown.' return dict() - @without_trailing_slash - @expose() - @validate(dict( - since=h.DateTimeConverter(if_empty=None, if_invalid=None), - until=h.DateTimeConverter(if_empty=None, if_invalid=None), - offset=validators.Int(if_empty=None), - limit=validators.Int(if_empty=None))) - def feed(self, since=None, until=None, offset=None, limit=None, **kw): - if request.environ['PATH_INFO'].endswith('.atom'): - feed_type = 'atom' - else: - feed_type = 'rss' - title = 'Recent changes to %s' % c.app.config.options.mount_point - feed = M.Feed.feed( - dict(project_id=c.project._id,app_config_id=c.app.config._id), - feed_type, - title, - c.app.url, - title, - since, until, offset, limit) - response.headers['Content-Type'] = '' - response.content_type = 'application/xml' - return feed.writeString('utf-8') - @expose() @h.vardec @require_post() @@ -1233,7 +1208,7 @@ def filtered_by_subscription(tickets, project_id=None, app_config_id=None): return filtered -class TicketController(BaseController): +class TicketController(BaseController, FeedController): def __init__(self, ticket_num=None): if ticket_num is not None: @@ -1248,8 +1223,6 @@ class TicketController(BaseController): utils.permanent_redirect(self.ticket.url()) self.attachment = AttachmentsController(self.ticket) # self.comments = CommentController(self.ticket) - setattr(self, 'feed.atom', self.feed) - setattr(self, 'feed.rss', self.feed) def _check_security(self): if self.ticket is not None: @@ -1285,30 +1258,19 @@ class TicketController(BaseController): else: raise exc.HTTPNotFound, 'Ticket #%s does not exist.' % self.ticket_num - @without_trailing_slash - @expose() - @validate(dict( - since=h.DateTimeConverter(if_empty=None, if_invalid=None), - until=h.DateTimeConverter(if_empty=None, if_invalid=None), - offset=validators.Int(if_empty=None), - limit=validators.Int(if_empty=None))) - def feed(self, since=None, until=None, offset=None, limit=None, **kw): - if request.environ['PATH_INFO'].endswith('.atom'): - feed_type = 'atom' - else: - feed_type = 'rss' + def get_feed(self, project, app, user): + """Return a :class:`allura.controllers.feed.Feed` object describing + the xml feed for this controller. + + Overrides :meth:`allura.controllers.feed.FeedController.get_feed`. + + """ title = 'Recent changes to %d: %s' % ( self.ticket.ticket_num, self.ticket.summary) - feed = M.Feed.feed( - {'ref_id':self.ticket.index_id()}, - feed_type, - title, - self.ticket.url(), + return Feed( + {'ref_id': self.ticket.index_id()}, title, - since, until, offset, limit) - response.headers['Content-Type'] = '' - response.content_type = 'application/xml' - return feed.writeString('utf-8') + self.ticket.url()) @expose() @require_post() http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/391aa922/ForgeWiki/forgewiki/wiki_main.py ---------------------------------------------------------------------- diff --git a/ForgeWiki/forgewiki/wiki_main.py b/ForgeWiki/forgewiki/wiki_main.py index b923350..dfb982b 100644 --- a/ForgeWiki/forgewiki/wiki_main.py +++ b/ForgeWiki/forgewiki/wiki_main.py @@ -41,6 +41,7 @@ from allura.lib.security import require_access, has_access from allura.controllers import AppDiscussionController, BaseController from allura.controllers import DispatchIndex from allura.controllers import attachments as ac +from allura.controllers.feed import Feed, FeedController from allura.lib import widgets as w from allura.lib.widgets import form_fields as ffw from allura.lib.widgets.subscriptions import SubscribeForm @@ -277,11 +278,9 @@ The wiki uses [Markdown](%s) syntax. WM.Globals.query.remove(dict(app_config_id=self.config._id)) super(ForgeWikiApp, self).uninstall(project) -class RootController(BaseController, DispatchIndex): +class RootController(BaseController, DispatchIndex, FeedController): def __init__(self): - setattr(self, 'feed.atom', self.feed) - setattr(self, 'feed.rss', self.feed) c.create_page_lightbox = W.create_page_lightbox self._discuss = AppDiscussionController() @@ -409,31 +408,8 @@ class RootController(BaseController, DispatchIndex): 'Display a page about how to use markdown.' return dict(example=MARKDOWN_EXAMPLE) - @without_trailing_slash - @expose() - @validate(dict( - since=h.DateTimeConverter(if_empty=None, if_invalid=None), - until=h.DateTimeConverter(if_empty=None, if_invalid=None), - offset=validators.Int(if_empty=None), - limit=validators.Int(if_empty=None))) - def feed(self, since=None, until=None, offset=None, limit=None, **kw): - if request.environ['PATH_INFO'].endswith('.atom'): - feed_type = 'atom' - else: - feed_type = 'rss' - title = 'Recent changes to %s' % c.app.config.options.mount_point - feed = M.Feed.feed( - dict(project_id=c.project._id,app_config_id=c.app.config._id), - feed_type, - title, - c.app.url, - title, - since, until, offset, limit) - response.headers['Content-Type'] = '' - response.content_type = 'application/xml' - return feed.writeString('utf-8') - -class PageController(BaseController): + +class PageController(BaseController, FeedController): def __init__(self, title): self.title = h.really_unicode(unquote(title)) @@ -442,8 +418,6 @@ class PageController(BaseController): if self.page is not None: self.attachment = WikiAttachmentsController(self.page) c.create_page_lightbox = W.create_page_lightbox - setattr(self, 'feed.atom', self.feed) - setattr(self, 'feed.rss', self.feed) def _check_security(self): if self.page: @@ -583,30 +557,19 @@ class PageController(BaseController): raise exc.HTTPNotFound return pformat(self.page) - @without_trailing_slash - @expose() - @validate(dict( - since=h.DateTimeConverter(if_empty=None, if_invalid=None), - until=h.DateTimeConverter(if_empty=None, if_invalid=None), - offset=validators.Int(if_empty=None), - limit=validators.Int(if_empty=None))) - def feed(self, since=None, until=None, offset=None, limit=None, **kw): + def get_feed(self, project, app, user): + """Return a :class:`allura.controllers.feed.Feed` object describing + the xml feed for this controller. + + Overrides :meth:`allura.controllers.feed.FeedController.get_feed`. + + """ if not self.page: - raise exc.HTTPNotFound - if request.environ['PATH_INFO'].endswith('.atom'): - feed_type = 'atom' - else: - feed_type = 'rss' - feed = M.Feed.feed( - {'ref_id':self.page.index_id()}, - feed_type, - 'Recent changes to %s' % self.page.title, - self.page.url(), + return None + return Feed( + {'ref_id': self.page.index_id()}, 'Recent changes to %s' % self.page.title, - since, until, offset, limit) - response.headers['Content-Type'] = '' - response.content_type = 'application/xml' - return feed.writeString('utf-8') + self.page.url()) @without_trailing_slash @expose('json')