Sorry about the bad update. Just in case of divergences between the prereq and this post update from devel, here's the diff: === modified file 'lib/lp/blueprints/browser/configure.zcml' --- lib/lp/blueprints/browser/configure.zcml 2010-07-27 17:17:59 +0000 +++ lib/lp/blueprints/browser/configure.zcml 2010-09-08 20:11:11 +0000 @@ -53,8 +53,7 @@ name="+mdz-specs.csv" attribute="mdzCsv"/> + name="+specs"/> @@ -500,8 +499,7 @@ class="lp.blueprints.browser.specificationtarget.HasSpecificationsView" permission="zope.Public"> + name="+specs"/> + name="+specs"/> @@ -583,8 +580,7 @@ facet="specifications" permission="zope.Public"> + name="+specs"/> === modified file 'lib/lp/blueprints/browser/specificationtarget.py' --- lib/lp/blueprints/browser/specificationtarget.py 2010-08-24 10:45:57 +0000 +++ lib/lp/blueprints/browser/specificationtarget.py 2010-09-09 18:06:03 +0000 @@ -15,6 +15,7 @@ from operator import itemgetter +from z3c.ptcompat import ViewPageTemplateFile from zope.component import queryMultiAdapter from canonical.config import config @@ -32,6 +33,8 @@ Link, ) from canonical.lazr.utils import smartquote +from lp.app.enums import service_uses_launchpad +from lp.app.interfaces.launchpad import IServiceUsage from lp.blueprints.interfaces.specification import ( SpecificationFilter, SpecificationSort, @@ -133,6 +136,50 @@ is_sprint = False has_drivers = False + # Templates for the various conditions of blueprints: + # * On Launchpad + # * External + # * Disabled + # * Unknown + default_template = ViewPageTemplateFile( + '../templates/hasspecifications-specs.pt') + not_launchpad_template = ViewPageTemplateFile( + '../templates/unknown-specs.pt') + + @property + def template(self): + # If the template has been defined in the zcml, use that, as this + # isn't the base service page for blueprints. + if hasattr(self, 'index'): + return super(HasSpecificationsView, self).template + + # Sprints and Persons don't have a usage enum for blueprints, so we + # have to fallback to the default. + if (ISprint.providedBy(self.context) + or IPerson.providedBy(self.context)): + return self.default_template + + # ProjectGroups are a special case, as their products may be a + # combination of usage settings. Use the default, since it handles + # fetching anything that's set for ProjectGroups, and it's not correct + # to say anything about the ProjectGroup's usage. + if IProjectGroup.providedBy(self.context): + return self.default_template + + # If specifications exist, ignore the usage enum. + if self.has_any_specifications: + return self.default_template + + # Otherwise, determine usage and provide the correct template. + service_usage = IServiceUsage(self.context) + if service_uses_launchpad(service_usage.blueprints_usage): + return self.default_template + else: + return self.not_launchpad_template + + def render(self): + return self.template() + # XXX: jsk: 2007-07-12 bug=173972: This method might be improved by # replacing the conditional execution with polymorphism. def initialize(self): @@ -199,7 +246,7 @@ 'distroseries', 'direction_approved', 'man_days', - 'delivery' + 'delivery', ] def dbschema(item): """Format a dbschema sortably for a spreadsheet.""" === modified file 'lib/lp/blueprints/browser/tests/test_specificationtarget.py' --- lib/lp/blueprints/browser/tests/test_specificationtarget.py 2010-08-20 20:31:18 +0000 +++ lib/lp/blueprints/browser/tests/test_specificationtarget.py 2010-09-09 18:10:22 +0000 @@ -1,15 +1,18 @@ -# Copyright 2009 Canonical Ltd. This software is licensed under the +# Copyright 2009-2010 Canonical Ltd. This software is licensed under the # GNU Affero General Public License version 3 (see the file LICENSE). __metaclass__ = type import unittest +from zope.security.proxy import removeSecurityProxy + from canonical.testing.layers import DatabaseFunctionalLayer from lp.blueprints.interfaces.specificationtarget import ( IHasSpecifications, ISpecificationTarget, ) +from lp.app.enums import ServiceUsage from lp.blueprints.publisher import BlueprintsLayer from lp.testing import ( login_person, @@ -50,7 +53,7 @@ self.verify_view(context, 'sprints/%s' % context.name) -class TestHasSpecificationsView(TestCaseWithFactory): +class TestHasSpecificationsViewInvolvement(TestCaseWithFactory): """Test specification menus links.""" layer = DatabaseFunctionalLayer @@ -68,6 +71,8 @@ def test_specificationtarget(self): context = self.factory.makeProduct(name='almond') + naked_product = removeSecurityProxy(context) + naked_product.blueprints_usage = ServiceUsage.LAUNCHPAD self.verify_involvment(context) def test_adaptable_to_specificationtarget(self): @@ -87,6 +92,63 @@ '
' in view()) +class TestHasSpecificationsTemplates(TestCaseWithFactory): + """Tests the selection of templates based on blueprints usage.""" + + layer = DatabaseFunctionalLayer + + def setUp(self): + super(TestHasSpecificationsTemplates, self).setUp() + self.user = self.factory.makePerson() + self.product = self.factory.makeProduct() + self.naked_product = removeSecurityProxy(self.product) + login_person(self.user) + + def test_not_configured(self): + self.naked_product.blueprints_usage = ServiceUsage.UNKNOWN + view = create_view( + self.product, + '+specs', + layer=BlueprintsLayer, + principal=self.user) + self.assertEqual( + view.not_launchpad_template.filename, + view.template.filename) + + def test_external(self): + self.naked_product.blueprints_usage = ServiceUsage.EXTERNAL + view = create_view( + self.product, + '+specs', + layer=BlueprintsLayer, + principal=self.user) + self.assertEqual( + view.not_launchpad_template.filename, + view.template.filename) + + def test_not_applicable(self): + self.naked_product.blueprints_usage = ServiceUsage.NOT_APPLICABLE + view = create_view( + self.product, + '+specs', + layer=BlueprintsLayer, + principal=self.user) + self.assertEqual( + view.not_launchpad_template.filename, + view.template.filename) + + def test_on_launchpad(self): + self.naked_product.blueprints_usage = ServiceUsage.LAUNCHPAD + view = create_view( + self.product, + '+specs', + layer=BlueprintsLayer, + principal=self.user) + self.assertEqual( + view.default_template.filename, + view.template.filename) + + def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.TestLoader().loadTestsFromName(__name__)) === added file 'lib/lp/blueprints/templates/unknown-specs.pt' --- lib/lp/blueprints/templates/unknown-specs.pt 1970-01-01 00:00:00 +0000 +++ lib/lp/blueprints/templates/unknown-specs.pt 2010-09-09 17:56:53 +0000 @@ -0,0 +1,59 @@ + + + + +
+ +
+ does not use Launchpad + for specification tracking. +
+ +
+ does not track + specifications. +
+ +
+ + Launchpad does not know how + uses specifications. + +
+ +
+

has a wiki, which + may be used for specifications.

+ +

+ + wiki + +

+ +
+ + +
+ + === modified file 'lib/lp/registry/browser/tests/pillar-views.txt' --- lib/lp/registry/browser/tests/pillar-views.txt 2010-09-10 13:29:42 +0000 +++ lib/lp/registry/browser/tests/pillar-views.txt 2010-09-10 14:21:30 +0000 @@ -36,12 +36,14 @@ True >>> print view.answers_usage.name LAUNCHPAD - >>> view.translations_usage.name - 'UNKNOWN' + >>> print view.translations_usage.name + UNKNOWN >>> print view.blueprints_usage.name UNKNOWN >>> print view.codehosting_usage.name UNKNOWN + >>> print view.codehosting_usage.name + NOT_APPLICABLE The view provides a list of enabled links that is rendered by the template. === modified file 'lib/lp/registry/doc/distribution.txt' --- lib/lp/registry/doc/distribution.txt 2010-09-10 13:29:42 +0000 +++ lib/lp/registry/doc/distribution.txt 2010-09-10 14:23:47 +0000 @@ -495,7 +495,6 @@ Traceback (most recent call last): Unauthorized: (..., 'translations_usage', 'launchpad.Edit') - Specification Listings ...................... @@ -520,7 +519,6 @@ >>> kubuntu.specifications(filter=filter).count() 1 - There are 2 completed specs for Kubuntu: >>> filter = [SpecificationFilter.COMPLETE] === modified file 'lib/lp/registry/doc/product.txt' --- lib/lp/registry/doc/product.txt 2010-09-10 13:29:42 +0000 +++ lib/lp/registry/doc/product.txt 2010-09-10 14:24:29 +0000 @@ -324,6 +324,7 @@ >>> print alsa.answers_usage.name UNKNOWN + Product Creation ----------------