← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~mwhudson/launchpad/vostok-traverse-distro into lp:launchpad/devel

 

Michael Hudson has proposed merging lp:~mwhudson/launchpad/vostok-traverse-distro into lp:launchpad/devel with lp:~mwhudson/launchpad/vostok-main-template as a prerequisite.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)


Hi,

This branch adds a navigation for the vostok root that allows you to traverse
to distributions.

Cheers,
mwh
-- 
https://code.launchpad.net/~mwhudson/launchpad/vostok-traverse-distro/+merge/31241
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~mwhudson/launchpad/vostok-traverse-distro into lp:launchpad/devel.
=== modified file 'lib/lp/testing/factory.py'
--- lib/lp/testing/factory.py	2010-07-28 22:46:12 +0000
+++ lib/lp/testing/factory.py	2010-07-29 05:18:50 +0000
@@ -846,7 +846,7 @@
                 url = self.getUniqueURL()
         else:
             raise UnknownBranchTypeError(
-                'Unrecognized branch type: %r' % (branch_type,))
+                'Unrecognized branch type: %r' % branch_type)
 
         namespace = get_branch_namespace(
             owner, product=product, distroseries=distroseries,
@@ -1656,7 +1656,7 @@
         return library_file_alias
 
     def makeDistribution(self, name=None, displayname=None, owner=None,
-                         members=None, title=None):
+                         members=None, title=None, aliases=None):
         """Make a new distribution."""
         if name is None:
             name = self.getUniqueString()
@@ -1671,9 +1671,12 @@
             owner = self.makePerson()
         if members is None:
             members = self.makeTeam(owner)
-        return getUtility(IDistributionSet).new(
+        distro = getUtility(IDistributionSet).new(
             name, displayname, title, description, summary, domainname,
             members, owner)
+        if aliases is not None:
+            removeSecurityProxy(distro).setAliases(aliases)
+        return distro
 
     def makeDistroRelease(self, distribution=None, version=None,
                           status=SeriesStatus.DEVELOPMENT,
@@ -1808,7 +1811,7 @@
 
     def makeRecipeText(self, *branches):
         if len(branches) == 0:
-            branches = (self.makeAnyBranch(), )
+            branches = (self.makeAnyBranch(),)
         base_branch = branches[0]
         other_branches = branches[1:]
         text = MINIMAL_RECIPE_TEXT % base_branch.bzr_identity

=== modified file 'lib/lp/vostok/browser/configure.zcml'
--- lib/lp/vostok/browser/configure.zcml	2010-07-29 05:18:48 +0000
+++ lib/lp/vostok/browser/configure.zcml	2010-07-29 05:18:50 +0000
@@ -27,4 +27,9 @@
      layer="lp.vostok.publisher.VostokLayer"
      />
 
+  <browser:navigation
+      module="lp.vostok.publisher"
+      classes="VostokRootNavigation"
+      />
+
 </configure>

=== modified file 'lib/lp/vostok/publisher.py'
--- lib/lp/vostok/publisher.py	2010-07-29 05:18:48 +0000
+++ lib/lp/vostok/publisher.py	2010-07-29 05:18:50 +0000
@@ -7,19 +7,24 @@
 __all__ = [
     'VostokBrowserRequest',
     'VostokLayer',
+    'VostokRootNavigation',
     'vostok_request_publication_factory',
     ]
 
 
+from zope.component import getUtility
 from zope.interface import implements, Interface
 from zope.publisher.interfaces.browser import (
     IBrowserRequest, IDefaultBrowserLayer)
 
+from canonical.launchpad.webapp import canonical_url, Navigation
 from canonical.launchpad.webapp.publication import LaunchpadBrowserPublication
 from canonical.launchpad.webapp.servers import (
     LaunchpadBrowserRequest, VirtualHostRequestPublicationFactory)
 from canonical.launchpad.webapp.vhosts import allvhosts
 
+from lp.registry.interfaces.distribution import IDistributionSet
+
 
 class VostokLayer(IBrowserRequest, IDefaultBrowserLayer):
     """The Vostok layer."""
@@ -46,6 +51,19 @@
     implements(IVostokRoot)
 
 
+class VostokRootNavigation(Navigation):
+
+    usedfor = IVostokRoot
+
+    def traverse(self, name):
+        distro = getUtility(IDistributionSet)[name]
+        if distro is not None and distro.name != name:
+            # This distro was accessed through one of its aliases, so we
+            # must redirect to its canonical URL.
+            return self.redirectSubTree(canonical_url(distro), status=301)
+        return distro
+
+
 class VostokBrowserPublication(LaunchpadBrowserPublication):
     root_object_interface = IVostokRoot
 

=== added file 'lib/lp/vostok/tests/test_navigation.py'
--- lib/lp/vostok/tests/test_navigation.py	1970-01-01 00:00:00 +0000
+++ lib/lp/vostok/tests/test_navigation.py	2010-07-29 05:18:50 +0000
@@ -0,0 +1,47 @@
+# Copyright 2010 Canonical Ltd.  This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Tests for vostok's root navigation."""
+
+__metaclass__ = type
+
+from zope.component import getMultiAdapter
+from zope.publisher.interfaces.browser import IBrowserPublisher
+
+from canonical.launchpad.webapp import canonical_url
+from canonical.launchpad.webapp.interfaces import NotFoundError
+from canonical.launchpad.webapp.servers import LaunchpadTestRequest
+from canonical.testing.layers import DatabaseFunctionalLayer
+
+from lp.testing import TestCaseWithFactory
+from lp.vostok.publisher import VostokRootNavigation, VostokRoot
+
+
+class TestRootNavigation(TestCaseWithFactory):
+
+    layer = DatabaseFunctionalLayer
+
+    @property
+    def _navigation(self):
+        return getMultiAdapter(
+            (VostokRoot(), LaunchpadTestRequest()), IBrowserPublisher,
+            name='')
+
+    def test_use_VostokRootNavigation(self):
+        self.assertIsInstance(self._navigation, VostokRootNavigation)
+
+    def test_traverse_to_distributions(self):
+        distro = self.factory.makeDistribution()
+        traversed = self._navigation.traverse(distro.name)
+        self.assertEqual(distro, traversed)
+
+    def test_traverse_to_distribution_aliases(self):
+        # When we traverse to a distribution using one of its aliases, we're
+        # redirected to the distribution's page.
+        distro = self.factory.makeDistribution(aliases=['f00'])
+        redirection_view = self._navigation.traverse('f00')
+        self.assertEqual(canonical_url(distro), redirection_view.target)
+
+    def test_can_not_traverse_to_projects(self):
+        path = self.factory.makeProject().name
+        self.assertRaises(NotFoundError, self._navigation.traverse, path)