← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~sinzui/launchpad/commercial-project-picker into lp:launchpad

 

Curtis Hovey has proposed merging lp:~sinzui/launchpad/commercial-project-picker into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  Bug #930309 in Launchpad itself: "Commercial subscription information in the target picker looks like a Launchpad-Id"
  https://bugs.launchpad.net/launchpad/+bug/930309

For more details, see:
https://code.launchpad.net/~sinzui/launchpad/commercial-project-picker/+merge/95970

Include commercial subscription in the picker details.

    Launchpad bug: https://bugs.launchpad.net/bugs/930309
    Pre-implementation: jcsackett

The CommercialProjects vocabulary appends parenthetical subscription
information to the project displayname. This looks very in the picker,
and can be confused with the Launchpad-Id. The information often
overruns the space for the entry and is not shown.

--------------------------------------------------------------------

RULES

    * If the project has a commercial subscription, append it to the
      picker entry details.
      * This could be a performance issue.
        Checking commercial_subscriptionID should mitigate the cost of
        adding the subscription information. Only projects with a commercial
        subscription will get an additional DB check.
        Maybe the commercial subscription information can be gotten in bulk.
      * Oh, commercial_subscription isn't in the schema; it is a cached attr
        on Product.
    * There are three states to present in the picker
      A. commercial subscription: None
      B. Commercial subscription: Active
      C. Commercial subscription: Expired


QA

    * Visit a bug on qastaging.
    * Choose the retarget it.
    * Search for a commercial project.
    * Expand the some of the entries to see the details.
    * Verify the entry shows commercial subscription information.
      Verify the commercial project entry states that it has an active
      commercial subscription.


LINT

    lib/lp/app/browser/vocabulary.py
    lib/lp/app/browser/tests/test_vocabulary.py
    lib/lp/registry/vocabularies.py
    lib/lp/registry/interfaces/product.py
    lib/lp/registry/tests/test_commercialprojects_vocabularies.py


TEST

    ./bin/test -vvc lp.app.browser.tests.test_vocabulary
    ./bin/test -vvc lp.registry.tests.test_commercialprojects_vocabularies


IMPLEMENTATION

Added getCommercialSubscription() to TargetPickerEntrySourceAdapter that
returns None for all target types. Added getCommercialSubscription to
the IProduct subclass to summarise the commercial subscription info.
Removed a duplicate call to getMaintainer() in the base class. Add
has_current_commercial_subscription to IProduct because the model method
was private.
    lib/lp/app/browser/vocabulary.py
    lib/lp/app/browser/tests/test_vocabulary.py
    lib/lp/registry/interfaces/product.py

Removed the overloading the of project's displayname that looked like a
Launchpad-Id and could overrun the picker overlay..
    lib/lp/registry/tests/test_commercialprojects_vocabularies.py
    lib/lp/registry/vocabularies.py
-- 
https://code.launchpad.net/~sinzui/launchpad/commercial-project-picker/+merge/95970
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~sinzui/launchpad/commercial-project-picker into lp:launchpad.
=== modified file 'lib/lp/app/browser/tests/test_vocabulary.py'
--- lib/lp/app/browser/tests/test_vocabulary.py	2012-01-01 02:58:52 +0000
+++ lib/lp/app/browser/tests/test_vocabulary.py	2012-03-05 18:47:22 +0000
@@ -35,6 +35,7 @@
     VocabularyFilter,
     )
 from lp.testing import (
+    celebrity_logged_in,
     login_person,
     TestCaseWithFactory,
     )
@@ -318,6 +319,31 @@
             'http://launchpad.dev/fnord',
             self.getPickerEntry(product).alt_title_link)
 
+    def test_provides_commercial_subscription_none(self):
+        product = self.factory.makeProduct(name='fnord')
+        self.assertEqual(
+            'Commercial Subscription: None',
+            self.getPickerEntry(product).details[1])
+
+    def test_provides_commercial_subscription_active(self):
+        product = self.factory.makeProduct(name='fnord')
+        self.factory.makeCommercialSubscription(product)
+        self.assertEqual(
+            'Commercial Subscription: Active',
+            self.getPickerEntry(product).details[1])
+
+    def test_provides_commercial_subscription_expired(self):
+        product = self.factory.makeProduct(name='fnord')
+        self.factory.makeCommercialSubscription(product)
+        import datetime
+        import pytz
+        then = datetime.datetime(2005, 6, 15, 0, 0, 0, 0, pytz.UTC)
+        with celebrity_logged_in('admin'):
+            product.commercial_subscription.date_expires = then
+        self.assertEqual(
+            'Commercial Subscription: Expired',
+            self.getPickerEntry(product).details[1])
+
 
 class TestProjectGroupPickerEntrySourceAdapter(TestCaseWithFactory):
 

=== modified file 'lib/lp/app/browser/vocabulary.py'
--- lib/lp/app/browser/vocabulary.py	2012-02-22 05:22:13 +0000
+++ lib/lp/app/browser/vocabulary.py	2012-03-05 18:47:22 +0000
@@ -235,6 +235,10 @@
         """Gets the maintainer information for the target picker entry."""
         raise NotImplemented
 
+    def getCommercialSubscription(self, target):
+        """Gets the commercial subscription details for the target."""
+        return None
+
     def getPickerEntries(self, term_values, context_object, **kwarg):
         """See `IPickerEntrySource`"""
         entries = (
@@ -265,7 +269,11 @@
             maintainer = self.getMaintainer(target)
             if maintainer is not None:
                 picker_entry.details.append(
-                    'Maintainer: %s' % self.getMaintainer(target))
+                    'Maintainer: %s' % maintainer)
+            commercial_subscription = self.getCommercialSubscription(target)
+            if commercial_subscription is not None:
+                picker_entry.details.append(
+                    'Commercial Subscription: %s' % commercial_subscription)
         return entries
 
 
@@ -342,6 +350,16 @@
         """See `TargetPickerEntrySource`"""
         return target.summary
 
+    def getCommercialSubscription(self, target):
+        """See `TargetPickerEntrySource`"""
+        if target.commercial_subscription:
+            if target.has_current_commercial_subscription:
+                return 'Active'
+            else:
+                return 'Expired'
+        else:
+            return 'None'
+
 
 @adapter(IDistribution)
 class DistributionPickerEntrySourceAdapter(TargetPickerEntrySourceAdapter):

=== modified file 'lib/lp/registry/interfaces/product.py'
--- lib/lp/registry/interfaces/product.py	2012-02-14 07:06:37 +0000
+++ lib/lp/registry/interfaces/product.py	2012-03-05 18:47:22 +0000
@@ -729,6 +729,9 @@
                     "Whether the project's licensing requires a new "
                     "commercial subscription to use launchpad.")))
 
+    has_current_commercial_subscription = Attribute("""
+        Whether the project has a current commercial subscription.""")
+
     license_status = Attribute("""
         Whether the license is OPENSOURCE, UNREVIEWED, or PROPRIETARY.""")
 

=== modified file 'lib/lp/registry/tests/test_commercialprojects_vocabularies.py'
--- lib/lp/registry/tests/test_commercialprojects_vocabularies.py	2012-02-28 04:24:19 +0000
+++ lib/lp/registry/tests/test_commercialprojects_vocabularies.py	2012-03-05 18:47:22 +0000
@@ -5,7 +5,6 @@
 
 __metaclass__ = type
 
-from lp.app.browser.tales import DateTimeFormatterAPI
 from lp.registry.interfaces.product import License
 from lp.registry.vocabularies import CommercialProjectsVocabulary
 from lp.services.identity.interfaces.emailaddress import EmailAddressStatus
@@ -96,23 +95,12 @@
         self.assertEqual(
             0, len(self.vocab.searchForTerms('norwegian-blue-widget')))
 
-    def test_toTerm_no_subscription(self):
-        # Commercial project terms contain subscription information.
-        term = self.vocab.toTerm(self.maintained_project)
-        self.assertEqual(self.maintained_project, term.value)
-        self.assertEqual('open-widget', term.token)
-        self.assertEqual('Open-widget (no subscription)', term.title)
-
-    def test_toTerm_with_subscription(self):
-        # Commercial project terms contain subscription information.
-        self.factory.makeCommercialSubscription(self.maintained_project)
-        cs = self.maintained_project.commercial_subscription
-        expiration_date = DateTimeFormatterAPI(cs.date_expires).displaydate()
-        term = self.vocab.toTerm(self.maintained_project)
-        self.assertEqual(self.maintained_project, term.value)
-        self.assertEqual('open-widget', term.token)
-        self.assertEqual(
-            'Open-widget (expires %s)' % expiration_date, term.title)
+    def test_toTerm(self):
+        # Commercial project terms contain subscription information.
+        term = self.vocab.toTerm(self.maintained_project)
+        self.assertEqual(self.maintained_project, term.value)
+        self.assertEqual('open-widget', term.token)
+        self.assertEqual('Open-widget', term.title)
 
     def test_getTermByToken_user(self):
         # The term for a token in the vocabulary is returned for maintained

=== modified file 'lib/lp/registry/vocabularies.py'
--- lib/lp/registry/vocabularies.py	2012-02-13 21:01:51 +0000
+++ lib/lp/registry/vocabularies.py	2012-03-05 18:47:22 +0000
@@ -98,7 +98,6 @@
     removeSecurityProxy,
     )
 
-from lp.app.browser.tales import DateTimeFormatterAPI
 from lp.app.interfaces.launchpad import ILaunchpadCelebrities
 from lp.blueprints.interfaces.specification import ISpecification
 from lp.bugs.interfaces.bugtask import IBugTask
@@ -1536,15 +1535,7 @@
 
     def toTerm(self, project):
         """Return the term for this object."""
-        if project.commercial_subscription is None:
-            sub_status = "(no subscription)"
-        else:
-            date_formatter = DateTimeFormatterAPI(
-                project.commercial_subscription.date_expires)
-            sub_status = "(expires %s)" % date_formatter.displaydate()
-        return SimpleTerm(project,
-                          project.name,
-                          '%s %s' % (project.displayname, sub_status))
+        return SimpleTerm(project, project.name, project.displayname)
 
     def getTermByToken(self, token):
         """Return the term for the given token."""