← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~sinzui/launchpad/sp-new-release-1 into lp:launchpad/devel

 

Curtis Hovey has proposed merging lp:~sinzui/launchpad/sp-new-release-1 into lp:launchpad/devel.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)


This is my branch to call attention to newer upstream releases on the source
package page.

    lp:~sinzui/launchpad/sp-new-release-1
    Diff size: 240
    Launchpad bug: https://bugs.launchpad.net/bugs/636060
    Test command: ./bin/test -vv \
          -t TestSourcePackageUpstreamConnectionsView
    Pre-implementation: jcsackett, bigjool, james_w
    Target release: 10.11


Call attention to newer upstream releases on the source package page
--------------------------------------------------------------------

Pages like https://launchpad.net/ubuntu/maverick/+source/pyjunitxml
show the upstream info. It would be most excellent to show new releases from
that series there.

The latest release information was added to the source package page a few
weeks ago, but newer releases are not prominent. During QA, it 4 minutes
to realise that the upstream version was newer than the packaged version.
Launchpad could make it easy to see upstream is newer.


Rules
-----

Revise the UI to call attention to newer releases. This may only be needed
on series in development. Stable do not package major changes.

    * Link the to the upstream release.
    * Use a bold sentence to tell the packager that he can get the latest
      release
    * Link the current version in the information portlet


QA
--

At the moment I write this:

    * Visit https://qastaging.launchpad.net/ubuntu/natty/+source/bzr
    * Verify the page tells you that upstream has a newer version
      and that it can be packaged.

Lint
----

Linting changed files:
  lib/lp/registry/browser/sourcepackage.py
  lib/lp/registry/browser/tests/test_sourcepackage_views.py
  lib/lp/registry/templates/sourcepackage-upstream-connections.pt


Test
----

Added a test to verify the PackageUpstreamTracking enum and paragraph id
are correct for the state.
    lib/lp/registry/browser/tests/test_sourcepackage_views.py


Implementation
--------------

Added an enum to describe the version difference between upstream and the
packaged version. Added a method to select the enum. Added paragraphs that
describe the condition.
    lib/lp/registry/browser/sourcepackage.py
    lib/lp/registry/templates/sourcepackage-upstream-connections.pt

There are screencaps to show the text and presentation of the four states:
    http://people.canonical.com/~curtis/upstream-version/no-version.png
    http://people.canonical.com/~curtis/upstream-version/newer-version.png
    http://people.canonical.com/~curtis/upstream-version/current-version.png
    http://people.canonical.com/~curtis/upstream-version/older-version.png
-- 
https://code.launchpad.net/~sinzui/launchpad/sp-new-release-1/+merge/40485
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~sinzui/launchpad/sp-new-release-1 into lp:launchpad/devel.
=== modified file 'lib/lp/registry/browser/sourcepackage.py'
--- lib/lp/registry/browser/sourcepackage.py	2010-10-05 01:50:13 +0000
+++ lib/lp/registry/browser/sourcepackage.py	2010-11-09 22:06:14 +0000
@@ -6,6 +6,7 @@
 __metaclass__ = type
 
 __all__ = [
+    'PackageUpstreamTracking',
     'SourcePackageAssociationPortletView',
     'SourcePackageBreadcrumb',
     'SourcePackageChangeUpstreamView',
@@ -21,7 +22,14 @@
 import string
 import urllib
 
-from apt_pkg import ParseSrcDepends
+from apt_pkg import (
+    ParseSrcDepends,
+    VersionCompare,
+    )
+from lazr.enum import (
+    EnumeratedType,
+    Item,
+    )
 from lazr.restful.interface import copy_field
 from z3c.ptcompat import ViewPageTemplateFile
 from zope.app.form.browser import DropdownWidget
@@ -594,6 +602,37 @@
         self.next_url = self.request.getURL()
 
 
+class PackageUpstreamTracking(EnumeratedType):
+    """The state of the package's tracking of the upstream version."""
+
+    NONE = Item("""
+        None
+
+        There is not enough information to compare the current package version
+        to the upstream version.
+        """)
+
+    CURRENT = Item("""
+        Current version
+
+        The package version is the current upstream version.
+        """)
+
+    OLDER = Item("""
+        Older upstream version
+
+        The upstream version is older than the package version. Launchpad
+        Launchpad is missing upstream data.
+        """)
+
+    NEWER = Item("""
+        Newer upstream version
+
+        The upstream version is newer than the package version. The package
+        can be updated to the upstream version.
+        """)
+
+
 class SourcePackageUpstreamConnectionsView(LaunchpadView):
     """A shared view with upstream connection info."""
 
@@ -612,3 +651,24 @@
         if bugtracker is None:
             return False
         return True
+
+    @property
+    def current_release_tracking(self):
+        """The PackageUpstreamTracking state for the current release."""
+        upstream_release = self.context.productseries.getLatestRelease()
+        current_release = self.context.currentrelease
+        if upstream_release is None or current_release is None:
+            # Launchpad is missing data. There is not enough information to
+            # track releases.
+            return PackageUpstreamTracking.NONE
+        # Compare the versions by appending '-1' to upstrem release to
+        # account for the first packaging in a distro.
+        age = VersionCompare(
+            upstream_release.version + '-1', current_release.version)
+        if age > 0:
+            return PackageUpstreamTracking.NEWER
+        elif age < 0:
+            return PackageUpstreamTracking.OLDER
+        else:
+            # age == 0:
+            return PackageUpstreamTracking.CURRENT

=== modified file 'lib/lp/registry/browser/tests/test_sourcepackage_views.py'
--- lib/lp/registry/browser/tests/test_sourcepackage_views.py	2010-10-06 18:53:53 +0000
+++ lib/lp/registry/browser/tests/test_sourcepackage_views.py	2010-11-09 22:06:14 +0000
@@ -11,8 +11,12 @@
 from zope.component import getUtility
 from zope.interface import implements
 
+from canonical.launchpad.testing.pages import find_tag_by_id
 from canonical.testing.layers import DatabaseFunctionalLayer
-from lp.registry.browser.sourcepackage import get_register_upstream_url
+from lp.registry.browser.sourcepackage import (
+    get_register_upstream_url,
+    PackageUpstreamTracking,
+    )
 from lp.registry.interfaces.distribution import IDistribution
 from lp.registry.interfaces.distroseries import (
     IDistroSeries,
@@ -20,7 +24,11 @@
     )
 from lp.registry.interfaces.sourcepackage import ISourcePackage
 from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
-from lp.testing import TestCaseWithFactory
+from lp.testing import (
+    person_logged_in,
+    TestCaseWithFactory,
+    )
+from lp.testing.views import create_initialized_view
 
 
 class TestSourcePackageViewHelpers(TestCaseWithFactory):
@@ -144,3 +152,62 @@
         params = cgi.parse_qsl(query)
         self.assertEqual((expected_base, expected_params),
                          (base, params))
+
+
+class TestSourcePackageUpstreamConnectionsView(TestCaseWithFactory):
+
+    layer = DatabaseFunctionalLayer
+
+    def setUp(self):
+        super(TestSourcePackageUpstreamConnectionsView, self).setUp()
+        productseries = self.factory.makeProductSeries(name='1.0')
+        self.milestone = self.factory.makeMilestone(
+            product=productseries.product, productseries=productseries)
+        distroseries = self.factory.makeDistroRelease()
+        self.source_package = self.factory.makeSourcePackage(
+            distroseries=distroseries, sourcepackagename='fnord')
+        self.factory.makeSourcePackagePublishingHistory(
+            sourcepackagename=self.source_package.sourcepackagename,
+            distroseries=distroseries, version='1.5-1')
+        self.source_package.setPackaging(
+            productseries, productseries.product.owner)
+
+    def makeUpstreamRelease(self, version):
+        with person_logged_in(self.milestone.productseries.product.owner):
+            self.milestone.name = version
+            self.factory.makeProductRelease(self.milestone)
+
+    def assertId(self, view, id_):
+        element = find_tag_by_id(view.render(), id_)
+        self.assertTrue(element is not None)
+
+    def test_current_release_tracking_none(self):
+        view = create_initialized_view(
+            self.source_package, name='+upstream-connections')
+        self.assertEqual(
+            PackageUpstreamTracking.NONE, view.current_release_tracking)
+        self.assertId(view, 'no-upstream-version')
+
+    def test_current_release_tracking_current(self):
+        self.makeUpstreamRelease('1.5')
+        view = create_initialized_view(
+            self.source_package, name='+upstream-connections')
+        self.assertEqual(
+            PackageUpstreamTracking.CURRENT, view.current_release_tracking)
+        self.assertId(view, 'current-upstream-version')
+
+    def test_current_release_tracking_older(self):
+        self.makeUpstreamRelease('1.4')
+        view = create_initialized_view(
+            self.source_package, name='+upstream-connections')
+        self.assertEqual(
+            PackageUpstreamTracking.OLDER, view.current_release_tracking)
+        self.assertId(view, 'older-upstream-version')
+
+    def test_current_release_tracking_newer(self):
+        self.makeUpstreamRelease('1.6')
+        view = create_initialized_view(
+            self.source_package, name='+upstream-connections')
+        self.assertEqual(
+            PackageUpstreamTracking.NEWER, view.current_release_tracking)
+        self.assertId(view, 'newer-upstream-version')

=== modified file 'lib/lp/registry/templates/sourcepackage-upstream-connections.pt'
--- lib/lp/registry/templates/sourcepackage-upstream-connections.pt	2010-10-18 20:59:40 +0000
+++ lib/lp/registry/templates/sourcepackage-upstream-connections.pt	2010-11-09 22:06:14 +0000
@@ -24,13 +24,6 @@
           structure context/menu:overview/remove_packaging/fmt:icon " />
       </span>
     </dd>
-    <tal:upstream-version
-      define="release series/getLatestRelease">
-      <dd tal:condition="release">
-        Lastest version:
-        <tal:version replace="release/version"/>
-      </dd>
-    </tal:upstream-version>
   </dl>
 
   <style>
@@ -63,8 +56,35 @@
         <tal:yes-no replace="structure bool/image:boolean"/>
       </dd>
     </dl>
-
   </div>
+
+  <tal:upstream-version
+    define="release series/getLatestRelease;
+            tracking view/current_release_tracking">
+    <p id="no-upstream-version"
+      tal:condition="tracking/enumvalue:NONE">
+      <span class="sprite no">There are no registered releases</span>
+      for the <tal:project replace="series/product/displayname" />
+      &rArr; <tal:series replace="series/name" />.
+    </p>
+    <p id="newer-upstream-version"
+      tal:condition="tracking/enumvalue:NEWER">
+      <strong class="sprite warning-icon"><a
+        tal:replace="structure release/fmt:link" /> is available for
+      packaging.</strong>
+    </p>
+    <p id="older-upstream-version"
+      tal:condition="tracking/enumvalue:OLDER">
+      <span class="sprite warning-icon"><a
+        tal:replace="structure release/fmt:link" /></span> is older that the
+      current packaged version. Launchpad may be missing upstream information.
+    </p>
+    <p id="current-upstream-version"
+      tal:condition="tracking/enumvalue:CURRENT">
+      <span class="sprite yes">Packaging is up-to-date</span> for
+      <a tal:replace="structure release/fmt:link" />.
+    </p>
+  </tal:upstream-version>
 </div>
 
 </tal:root>