launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #05111
[Merge] lp:~benji/launchpad/bug-839831 into lp:launchpad
Benji York has proposed merging lp:~benji/launchpad/bug-839831 into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #839831 in Launchpad itself: "Can't link blueprints and bugs through the API"
https://bugs.launchpad.net/launchpad/+bug/839831
For more details, see:
https://code.launchpad.net/~benji/launchpad/bug-839831/+merge/77232
This branch exposes linking a blueprint (specification) to a bug via the
web service.
Tests: tests were added to lib/lp/blueprints/tests/test_webservice.py, run with
bin/test -c -m lp.blueprints.tests.test_webservice -t TestSpecificationBugLinks
Lint: some pre-existing lint was fixed in
lib/lp/blueprints/tests/test_webservice.py
QA: use launchpadlib to link a blueprint to a bug
--
https://code.launchpad.net/~benji/launchpad/bug-839831/+merge/77232
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~benji/launchpad/bug-839831 into lp:launchpad.
=== modified file 'lib/canonical/launchpad/interfaces/_schema_circular_imports.py'
--- lib/canonical/launchpad/interfaces/_schema_circular_imports.py 2011-07-15 14:28:21 +0000
+++ lib/canonical/launchpad/interfaces/_schema_circular_imports.py 2011-09-27 20:38:30 +0000
@@ -678,6 +678,10 @@
patch_reference_property(IProductSeries, 'product', IProduct)
# ISpecification
+ISpecification['linkBug'].queryTaggedValue(
+ LAZR_WEBSERVICE_EXPORTED)['params']['bug'].schema = IBug
+ISpecification['unlinkBug'].queryTaggedValue(
+ LAZR_WEBSERVICE_EXPORTED)['params']['bug'].schema = IBug
patch_collection_property(ISpecification, 'dependencies', ISpecification)
patch_collection_property(
ISpecification, 'linked_branches', ISpecificationBranch)
=== modified file 'lib/lp/blueprints/configure.zcml'
--- lib/lp/blueprints/configure.zcml 2010-12-02 16:13:51 +0000
+++ lib/lp/blueprints/configure.zcml 2011-09-27 20:38:30 +0000
@@ -181,6 +181,7 @@
<class class="lp.blueprints.model.specificationbug.SpecificationBug">
<allow interface="lp.blueprints.interfaces.specificationbug.ISpecificationBug"/>
+ <allow interface="lazr.restful.interfaces.IJSONPublishable"/>
</class>
<subscriber
=== modified file 'lib/lp/blueprints/interfaces/specification.py'
--- lib/lp/blueprints/interfaces/specification.py 2011-09-01 13:00:35 +0000
+++ lib/lp/blueprints/interfaces/specification.py 2011-09-27 20:38:30 +0000
@@ -588,6 +588,26 @@
export_as_webservice_entry(as_of="beta")
+ @operation_parameters(
+ bug=Reference(schema=Interface)) # Really IBug
+ @export_write_operation()
+ @operation_for_version('devel')
+ def linkBug(bug):
+ """Link a bug to this branch.
+
+ :param bug: IBug to link.
+ """
+
+ @operation_parameters(
+ bug=Reference(schema=Interface)) # Really IBug
+ @export_write_operation()
+ @operation_for_version('devel')
+ def unlinkBug(bug):
+ """Unlink a bug to this branch.
+
+ :param bug: IBug to unlink.
+ """
+
class ISpecificationSet(IHasSpecifications):
"""A container for specifications."""
=== modified file 'lib/lp/blueprints/interfaces/specificationbug.py'
--- lib/lp/blueprints/interfaces/specificationbug.py 2010-08-20 20:31:18 +0000
+++ lib/lp/blueprints/interfaces/specificationbug.py 2011-09-27 20:38:30 +0000
@@ -23,5 +23,3 @@
specification = Object(title=_('The specification linked to the bug.'),
required=True, readonly=True, schema=ISpecification)
-
-
=== modified file 'lib/lp/blueprints/model/specificationbug.py'
--- lib/lp/blueprints/model/specificationbug.py 2010-08-20 20:31:18 +0000
+++ lib/lp/blueprints/model/specificationbug.py 2011-09-27 20:38:30 +0000
@@ -7,6 +7,7 @@
__all__ = ['SpecificationBug']
+from lazr.restful.interfaces import IJSONPublishable
from sqlobject import ForeignKey
from zope.interface import implements
@@ -17,7 +18,7 @@
class SpecificationBug(SQLBase):
"""A link between a spec and a bug."""
- implements(ISpecificationBug)
+ implements(ISpecificationBug, IJSONPublishable)
_table = 'SpecificationBug'
specification = ForeignKey(dbName='specification',
@@ -30,3 +31,9 @@
"""See IBugLink."""
return self.specification
+ def toDataForJSON(self, media_type):
+ """See IJSONPublishable.
+
+ These objects have no JSON representation.
+ """
+ return None
=== modified file 'lib/lp/blueprints/tests/test_webservice.py'
--- lib/lp/blueprints/tests/test_webservice.py 2011-06-21 11:44:21 +0000
+++ lib/lp/blueprints/tests/test_webservice.py 2011-09-27 20:38:30 +0000
@@ -187,7 +187,7 @@
def test_get_specification_on_product(self):
product = self.factory.makeProduct(name="fooix")
- spec_object = self.factory.makeSpecification(
+ self.factory.makeSpecification(
product=product, name="some-spec")
product_on_webservice = self.getPillarOnWebservice(product)
spec = product_on_webservice.getSpecification(name="some-spec")
@@ -196,7 +196,7 @@
def test_get_specification_on_distribution(self):
distribution = self.factory.makeDistribution(name="foobuntu")
- spec_object = self.factory.makeSpecification(
+ self.factory.makeSpecification(
distribution=distribution, name="some-spec")
distro_on_webservice = self.getPillarOnWebservice(distribution)
spec = distro_on_webservice.getSpecification(name="some-spec")
@@ -207,7 +207,7 @@
product = self.factory.makeProduct(name="fooix")
productseries = self.factory.makeProductSeries(
product=product, name="fooix-dev")
- spec_object = self.factory.makeSpecification(
+ self.factory.makeSpecification(
product=product, name="some-spec", goal=productseries)
product_on_webservice = self.getPillarOnWebservice(product)
productseries_on_webservice = product_on_webservice.getSeries(
@@ -220,7 +220,7 @@
distribution = self.factory.makeDistribution(name="foobuntu")
distroseries = self.factory.makeDistroSeries(
distribution=distribution, name="maudlin")
- spec_object = self.factory.makeSpecification(
+ self.factory.makeSpecification(
distribution=distribution, name="some-spec",
goal=distroseries)
distro_on_webservice = self.getPillarOnWebservice(distribution)
@@ -333,3 +333,51 @@
result = webservice.named_get(
subscription['self_link'], 'canBeUnsubscribedByUser').jsonBody()
self.assertFalse(result)
+
+
+class TestSpecificationBugLinks(SpecificationWebserviceTestCase):
+
+ layer = AppServerLayer
+
+ def test_bug_linking(self):
+ # Set up a spec, person, and bug.
+ with person_logged_in(ANONYMOUS):
+ db_spec = self.factory.makeSpecification()
+ db_person = self.factory.makePerson()
+ db_bug = self.factory.makeBug()
+ launchpad = self.factory.makeLaunchpadService()
+
+ # Link the bug to the spec via the web service.
+ with person_logged_in(db_person):
+ spec = ws_object(launchpad, db_spec)
+ bug = ws_object(launchpad, db_bug)
+ # There are no bugs associated with the spec/blueprint yet.
+ self.assertEqual(0, spec.bugs.total_size)
+ spec.linkBug(bug=bug)
+ transaction.commit()
+
+ # The spec now has one bug associated with it and that bug is the one
+ # we linked.
+ self.assertEqual(1, spec.bugs.total_size)
+ self.assertEqual(bug.id, spec.bugs[0].id)
+
+ def test_bug_unlinking(self):
+ # Set up a spec, person, and bug, then link the bug to the spec.
+ with person_logged_in(ANONYMOUS):
+ db_spec = self.factory.makeBlueprint()
+ db_person = self.factory.makePerson()
+ db_bug = self.factory.makeBug()
+ launchpad = self.factory.makeLaunchpadService(person=db_person)
+
+ spec = ws_object(launchpad, db_spec)
+ bug = ws_object(launchpad, db_bug)
+ spec.linkBug(bug=bug)
+
+ # There is only one bug linked at the moment.
+ self.assertEqual(1, spec.bugs.total_size)
+
+ spec.unlinkBug(bug=bug)
+ transaction.commit()
+
+ # Now that we've unlinked the bug, there are no linked bugs at all.
+ self.assertEqual(0, spec.bugs.total_size)