Hi Ian, It generally looks good but as always I have some notes. And while I'm here, thanks for the little drive-by cleanups! === modified file 'lib/canonical/launchpad/browser/feeds.py' --- lib/canonical/launchpad/browser/feeds.py 2010-11-08 12:52:43 +0000 +++ lib/canonical/launchpad/browser/feeds.py 2011-05-20 09:01:26 +0000 @@ -177,6 +177,14 @@ "Context %r does not provide interface %r" % (context, self.usedfor)) + @classmethod + def feed_allowed(cls, context): + """Return True if a feed is allowed for the given context. We normally use dromedaryCase for methods, where the first word is expected to be a verb. Skimming over this change at first I thought it was a property! The "verb" part has a corollary: "feed allowed" can be misread as "feed those that are allowed." It's not hard to figure out that that's not what you mean, but it's a small distraction that can help slow down and confuse the reader. @@ -346,4 +368,5 @@ def feed_links(self): return [feed_type(self.context) for feed_type in self.feed_types - if feed_type.usedfor.providedBy(self.context)] + if feed_type.usedfor.providedBy(self.context) and + feed_type.feed_allowed(self.context)] The indentation of that last clause threw me off a bit. Is there some more legible way to write this? === modified file 'lib/canonical/launchpad/pagetests/feeds/xx-links.txt' --- lib/canonical/launchpad/pagetests/feeds/xx-links.txt 2011-05-05 05:46:41 +0000 +++ lib/canonical/launchpad/pagetests/feeds/xx-links.txt 2011-05-20 09:01:26 +0000 @@ -42,6 +42,37 @@ href="http://feeds.launchpad.dev/bugs/1/bug.atom" title="Bug 1 Feed" />] +But if the bug is private, there should be no link. + + >>> from canonical.launchpad.testing.pages import setupBrowserForUser + >>> from zope.component import getUtility + >>> from lp.registry.interfaces.person import IPersonSet + >>> login(ANONYMOUS) + >>> user = getUtility(IPersonSet).getByEmail('