launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #01143
[Merge] lp:~jcsackett/launchpad/series-need-usage-attributes-643902 into lp:launchpad/devel
j.c.sackett has proposed merging lp:~jcsackett/launchpad/series-need-usage-attributes-643902 into lp:launchpad/devel.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
#643902 Series need usage attributes
https://bugs.launchpad.net/bugs/643902
Summary
=======
Adds the usage attributes to productseries and distroseries, largely as a mirror of the attributes on the series related pillar.
Proposed Fix
============
Add the usage attributes as properties to the series.
Pre-implementation notes
========================
Spoke with Curtis Hovey (sinzui) and jtv about what was needed in usage attributes on the series, especially for translations.
Implementation details
======================
As in proposed fix.
Translations use the current status of templates to determine usage; however, that is overridden by requirements in the translations application (see bug 605924). That requirement will be resolve by lp:~jcsackett/launchpad/unknown-translations-service-643545, which is dependent on this branch.
Tests
=====
bin/test -t test_service_usage
Demo and Q/A
============
Currently usage of the various series should see no change from this branch.
Lint
====
Output:
= Launchpad lint =
Checking for conflicts and issues in changed files.
Linting changed files:
lib/lp/registry/adapters.py
lib/lp/registry/configure.zcml
lib/lp/registry/interfaces/distroseries.py
lib/lp/registry/interfaces/productseries.py
lib/lp/registry/model/distroseries.py
lib/lp/registry/model/productseries.py
lib/lp/registry/tests/test_service_usage.py
./lib/lp/registry/interfaces/distroseries.py
417: E301 expected 1 blank line, found 2
458: E301 expected 1 blank line, found 0
./lib/lp/registry/model/distroseries.py
364: E301 expected 1 blank line, found 2
708: E301 expected 1 blank line, found 2
Both errors related to lint's issue with comments and blank lines
--
https://code.launchpad.net/~jcsackett/launchpad/series-need-usage-attributes-643902/+merge/36145
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~jcsackett/launchpad/series-need-usage-attributes-643902 into lp:launchpad/devel.
=== modified file 'lib/lp/registry/adapters.py'
--- lib/lp/registry/adapters.py 2010-09-13 12:09:30 +0000
+++ lib/lp/registry/adapters.py 2010-09-21 13:57:44 +0000
@@ -13,19 +13,11 @@
]
-from zope.component import (
- adapter,
- getUtility,
- )
+from zope.component import getUtility
from zope.component.interfaces import ComponentLookupError
-from zope.interface import (
- implementer,
- implements,
- )
+from zope.interface import implements
from canonical.launchpad.webapp.interfaces import ILaunchpadPrincipal
-from lp.app.interfaces.launchpad import IServiceUsage
-from lp.registry.interfaces.distroseries import IDistroSeries
from lp.registry.interfaces.poll import (
IPollSet,
IPollSubset,
@@ -34,15 +26,11 @@
)
-@implementer(IServiceUsage)
-@adapter(IDistroSeries)
-def distroseries_to_serviceusage(distroseries):
- """Adapts `IDistroSeries` object to `IServiceUsage`."""
- return distroseries.distribution
-
-
-def distroseries_to_launchpadusage(distroseries):
- """Adapts `IDistroSeries` object to `ILaunchpadUsage`."""
+def distroseries_to_distribution(distroseries):
+ """Adapts `IDistroSeries` object to `IDistribution`.
+
+ This is useful for adapting to `IServiceUsage`
+ or `ILaunchpadUsage`."""
return distroseries.distribution
=== modified file 'lib/lp/registry/configure.zcml'
--- lib/lp/registry/configure.zcml 2010-09-18 00:17:07 +0000
+++ lib/lp/registry/configure.zcml 2010-09-21 13:57:44 +0000
@@ -142,6 +142,9 @@
interface="canonical.launchpad.interfaces.ICanPublishPackages"/>
<require
permission="launchpad.Edit"
+ set_schema="lp.app.interfaces.launchpad.IServiceUsage"/>
+ <require
+ permission="launchpad.Edit"
interface="lp.registry.interfaces.distroseries.IDistroSeriesEditRestricted"/>
<require
permission="launchpad.TranslationsAdmin"
@@ -194,11 +197,9 @@
<adapter
provides="lp.app.interfaces.launchpad.ILaunchpadUsage"
for="lp.registry.interfaces.distroseries.IDistroSeries"
- factory="lp.registry.adapters.distroseries_to_launchpadusage"
+ factory="lp.registry.adapters.distroseries_to_distribution"
permission="zope.Public"/>
<adapter
- factory="lp.registry.adapters.distroseries_to_serviceusage" />
- <adapter
provides="canonical.launchpad.webapp.interfaces.IBreadcrumb"
for="lp.registry.interfaces.distroseries.IDistroSeries"
factory="lp.registry.browser.distroseries.DistroSeriesBreadcrumb"
@@ -1374,6 +1375,9 @@
interface="lp.translations.interfaces.translationimportqueue.IHasTranslationImports"/>
<require
permission="launchpad.Edit"
+ set_schema="lp.app.interfaces.launchpad.IServiceUsage"/>
+ <require
+ permission="launchpad.Edit"
set_attributes="product name owner driver summary branch
translations_branch status releasefileglob
translations_autoimport_mode"/>
@@ -1407,11 +1411,6 @@
factory="lp.registry.adapters.productseries_to_product"
permission="zope.Public"/>
<adapter
- provides="lp.app.interfaces.launchpad.IServiceUsage"
- for="lp.registry.interfaces.productseries.IProductSeries"
- factory="lp.registry.adapters.productseries_to_product"
- permission="zope.Public"/>
- <adapter
provides="lp.app.interfaces.launchpad.ILaunchpadUsage"
for="lp.registry.interfaces.productseries.IProductSeries"
factory="lp.registry.adapters.productseries_to_product"
=== modified file 'lib/lp/registry/interfaces/distroseries.py'
--- lib/lp/registry/interfaces/distroseries.py 2010-08-30 19:06:34 +0000
+++ lib/lp/registry/interfaces/distroseries.py 2010-09-21 13:57:44 +0000
@@ -52,6 +52,7 @@
from canonical.launchpad.validators.name import name_validator
from canonical.launchpad.validators.version import sane_version
from lp.app.errors import NameLookupFailed
+from lp.app.interfaces.launchpad import IServiceUsage
from lp.blueprints.interfaces.specificationtarget import ISpecificationGoal
from lp.bugs.interfaces.bugtarget import (
IBugTarget,
@@ -173,7 +174,7 @@
class IDistroSeriesPublic(
ISeriesMixin, IHasAppointedDriver, IHasOwner, IBugTarget,
ISpecificationGoal, IHasMilestones, IHasOfficialBugTags,
- IHasBuildRecords, IHasTranslationTemplates):
+ IHasBuildRecords, IHasTranslationTemplates, IServiceUsage):
"""Public IDistroSeries properties."""
id = Attribute("The distroseries's unique number.")
=== modified file 'lib/lp/registry/interfaces/productseries.py'
--- lib/lp/registry/interfaces/productseries.py 2010-08-31 00:02:42 +0000
+++ lib/lp/registry/interfaces/productseries.py 2010-09-21 13:57:44 +0000
@@ -48,6 +48,7 @@
from canonical.launchpad.validators.name import name_validator
from canonical.launchpad.webapp.url import urlparse
from lp.app.errors import NameLookupFailed
+from lp.app.interfaces.launchpad import IServiceUsage
from lp.blueprints.interfaces.specificationtarget import ISpecificationGoal
from lp.bugs.interfaces.bugtarget import (
IBugTarget,
@@ -120,7 +121,7 @@
class IProductSeriesPublic(
ISeriesMixin, IHasAppointedDriver, IHasOwner, IBugTarget,
ISpecificationGoal, IHasMilestones, IHasOfficialBugTags,
- IHasTranslationTemplates):
+ IHasTranslationTemplates, IServiceUsage):
"""Public IProductSeries properties."""
# XXX Mark Shuttleworth 2004-10-14: Would like to get rid of id in
# interfaces, as soon as SQLobject allows using the object directly
=== modified file 'lib/lp/registry/model/distroseries.py'
--- lib/lp/registry/model/distroseries.py 2010-09-03 15:02:39 +0000
+++ lib/lp/registry/model/distroseries.py 2010-09-21 13:57:44 +0000
@@ -63,6 +63,8 @@
SLAVE_FLAVOR,
)
from lp.app.errors import NotFoundError
+from lp.app.enums import ServiceUsage
+from lp.app.interfaces.launchpad import IServiceUsage
from lp.blueprints.interfaces.specification import (
SpecificationFilter,
SpecificationGoalStatus,
@@ -186,7 +188,7 @@
"""A particular series of a distribution."""
implements(
ICanPublishPackages, IDistroSeries, IHasBugHeat, IHasBuildRecords,
- IHasQueueItems)
+ IHasQueueItems, IServiceUsage)
_table = 'DistroSeries'
_defaultOrder = ['distribution', 'version']
@@ -263,6 +265,41 @@
""" % self.id,
clauseTables=["ComponentSelection"])
+ @property
+ def answers_usage(self):
+ """See `IServiceUsage.`"""
+ return self.distribution.answers_usage
+
+ @property
+ def blueprints_usage(self):
+ """See `IServiceUsage.`"""
+ return self.distribution.blueprints_usage
+
+ @property
+ def translations_usage(self):
+ """See `IServiceUsage.`"""
+ # If translations_usage is set for the Product, respect it.
+ usage = self.distribution.translations_usage
+ if usage != ServiceUsage.UNKNOWN:
+ return usage
+
+ # If not, usage is based on the presence of current translation
+ # templates for the series.
+ if self.getCurrentTranslationTemplates().count() > 0:
+ return ServiceUsage.LAUNCHPAD
+ else:
+ return ServiceUsage.UNKNOWN
+
+ @property
+ def codehosting_usage(self):
+ """See `IServiceUsage.`"""
+ return self.distribution.codehosting_usage
+
+ @property
+ def bug_tracking_usage(self):
+ """See `IServiceUsage.`"""
+ return self.distribution.bug_tracking_usage
+
# DistroArchSeries lookup properties/methods.
architectures = SQLMultipleJoin(
'DistroArchSeries', joinColumn='distroseries',
=== modified file 'lib/lp/registry/model/productseries.py'
--- lib/lp/registry/model/productseries.py 2010-08-31 00:02:42 +0000
+++ lib/lp/registry/model/productseries.py 2010-09-21 13:57:44 +0000
@@ -43,6 +43,8 @@
from canonical.launchpad.webapp.publisher import canonical_url
from canonical.launchpad.webapp.sorting import sorted_dotted_numbers
from lp.app.errors import NotFoundError
+from lp.app.enums import ServiceUsage
+from lp.app.interfaces.launchpad import IServiceUsage
from lp.blueprints.interfaces.specification import (
SpecificationDefinitionStatus,
SpecificationFilter,
@@ -115,7 +117,7 @@
HasTranslationImportsMixin, HasTranslationTemplatesMixin,
StructuralSubscriptionTargetMixin, SeriesMixin):
"""A series of product releases."""
- implements(IHasBugHeat, IProductSeries)
+ implements(IHasBugHeat, IProductSeries, IServiceUsage)
_table = 'ProductSeries'
@@ -151,6 +153,41 @@
packagings = SQLMultipleJoin('Packaging', joinColumn='productseries',
orderBy=['-id'])
+ @property
+ def answers_usage(self):
+ """See `IServiceUsage.`"""
+ return self.product.answers_usage
+
+ @property
+ def blueprints_usage(self):
+ """See `IServiceUsage.`"""
+ return self.product.blueprints_usage
+
+ @property
+ def translations_usage(self):
+ """See `IServiceUsage.`"""
+ # If translations_usage is set for the Product, respect it.
+ usage = self.product.translations_usage
+ if usage != ServiceUsage.UNKNOWN:
+ return usage
+
+ # If not, usage is based on the presence of current translation
+ # templates for the series.
+ if self.potemplate_count > 0:
+ return ServiceUsage.LAUNCHPAD
+ else:
+ return ServiceUsage.UNKNOWN
+
+ @property
+ def codehosting_usage(self):
+ """See `IServiceUsage.`"""
+ return self.product.codehosting_usage
+
+ @property
+ def bug_tracking_usage(self):
+ """See `IServiceUsage.`"""
+ return self.product.bug_tracking_usage
+
def _getMilestoneCondition(self):
"""See `HasMilestonesMixin`."""
return (Milestone.productseries == self)
=== modified file 'lib/lp/registry/tests/test_service_usage.py'
--- lib/lp/registry/tests/test_service_usage.py 2010-08-22 17:21:46 +0000
+++ lib/lp/registry/tests/test_service_usage.py 2010-09-21 13:57:44 +0000
@@ -143,6 +143,29 @@
self.target.official_blueprints)
+class SeriesUsageEnumsMixin(object):
+
+ def setUp(self):
+ self.series = None
+ self.series_pillar = None
+
+ def _addCurrentPOTemplate(self):
+ raise NotImplementedError("Child class must provide _addPOTTemplate.")
+
+ def test_translations_usage_pillar(self):
+ self.assertEqual(
+ ServiceUsage.UNKNOWN,
+ self.series_pillar.translations_usage)
+ self.assertEqual(
+ ServiceUsage.UNKNOWN,
+ self.series.translations_usage)
+
+ self._addCurrentPOTemplate()
+ self.assertEqual(
+ ServiceUsage.LAUNCHPAD,
+ self.series.translations_usage)
+
+
class TestDistributionUsageEnums(TestCaseWithFactory, UsageEnumsMixin):
"""Tests the usage enums for the distribution."""
@@ -170,5 +193,54 @@
self.target = self.factory.makeProduct()
+class TestProductSeriesUsageEnums(
+ TestCaseWithFactory,
+ SeriesUsageEnumsMixin):
+
+ layer = DatabaseFunctionalLayer
+
+ def setUp(self):
+ super(TestProductSeriesUsageEnums, self).setUp()
+ self.series_pillar = self.factory.makeProduct()
+ self.series = self.factory.makeProductSeries(
+ product=self.series_pillar)
+ login_person(self.series_pillar.owner)
+
+ def _addCurrentPOTemplate(self):
+ self.factory.makePOTemplate(productseries=self.series)
+ # XXX j.c.sackett 2010-09-21 bug=605924: Right now for it to
+ # be current, the series pillar must be marked as using
+ # using translations.
+ self.series_pillar.translations_usage = ServiceUsage.LAUNCHPAD
+
+
+class TestDistroSeriesUsageEnums(
+ TestCaseWithFactory,
+ SeriesUsageEnumsMixin):
+
+ layer = DatabaseFunctionalLayer
+
+ def setUp(self):
+ super(TestDistroSeriesUsageEnums, self).setUp()
+ self.series_pillar = self.factory.makeDistribution()
+ self.series = self.factory.makeDistroSeries(
+ distribution=self.series_pillar)
+ login_person(self.series_pillar.owner)
+
+ def _addCurrentPOTemplate(self):
+ sp_name = self.factory.makeSourcePackageName()
+ self.factory.makeSourcePackage(
+ sourcepackagename=sp_name,
+ distroseries=self.series)
+ self.factory.makePOTemplate(
+ distroseries=self.series,
+ sourcepackagename=sp_name)
+
+ # XXX j.c.sackett 2010-09-21 bug=605924: Right now for it to
+ # be current, the series pillar must be marked as using
+ # using translations.
+ self.series_pillar.translations_usage = ServiceUsage.LAUNCHPAD
+
+
def test_suite():
return unittest.TestLoader().loadTestsFromName(__name__)