← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] lp:~wallyworld/launchpad/recipe-webservice-api into lp:launchpad

 

Ian Booth has proposed merging lp:~wallyworld/launchpad/recipe-webservice-api into lp:launchpad.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)
Related bugs:
  #712329 web API call for listing recipes
  https://bugs.launchpad.net/bugs/712329
  #712331 web API call for listing recipe builds
  https://bugs.launchpad.net/bugs/712331

For more details, see:
https://code.launchpad.net/~wallyworld/launchpad/recipe-webservice-api/+merge/50684

Simple change to export via the webservice some recipe apis to list builds and recipes. See bugs 712329 and 712331.

== Implementation ==

Add required decorators to the exported methods:
IHasRecipe.getRecipes()
ISourcePackageRecipe.getBuilds()
ISourcePackageRecipe.getPendingBuilds()
ISourcePackageRecipe.getLastBuild()

== Tests ==

Add/modify tests in test_sourcepackagerecipe.TestWebservice
  test_getBuilds
  test_getRecipes
  test_requestBuild

bin/test -vvt test_sourcepackagerecipe.TestWebservice

== Lint ==
Linting changed files:
  lib/canonical/launchpad/interfaces/_schema_circular_imports.py
  lib/lp/code/interfaces/hasrecipes.py
  lib/lp/code/interfaces/sourcepackagerecipe.py
  lib/lp/code/model/tests/test_sourcepackagerecipe.py

./lib/canonical/launchpad/interfaces/_schema_circular_imports.py
     551: E501 line too long (82 characters)
     551: Line exceeds 78 characters.
./lib/lp/code/interfaces/hasrecipes.py
      21: E302 expected 2 blank lines, found 1
./lib/lp/code/interfaces/sourcepackagerecipe.py
     185: E501 line too long (83 characters)
     185: Line exceeds 78 characters.
-- 
https://code.launchpad.net/~wallyworld/launchpad/recipe-webservice-api/+merge/50684
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wallyworld/launchpad/recipe-webservice-api into lp:launchpad.
=== modified file 'lib/canonical/launchpad/interfaces/_schema_circular_imports.py'
--- lib/canonical/launchpad/interfaces/_schema_circular_imports.py	2011-02-02 09:50:58 +0000
+++ lib/canonical/launchpad/interfaces/_schema_circular_imports.py	2011-02-22 02:34:01 +0000
@@ -61,6 +61,7 @@
 from lp.buildmaster.enums import BuildStatus
 from lp.buildmaster.interfaces.buildfarmjob import IBuildFarmJob
 from lp.buildmaster.interfaces.buildqueue import IBuildQueue
+from lp.code.interfaces.hasrecipes import IHasRecipes
 from lp.code.interfaces.branch import IBranch
 from lp.code.interfaces.branchmergeproposal import IBranchMergeProposal
 from lp.code.interfaces.branchsubscription import IBranchSubscription
@@ -262,6 +263,10 @@
 
 patch_entry_return_type(IPerson, 'getRecipe', ISourcePackageRecipe)
 
+# IHasRecipe
+patch_collection_return_type(
+    IHasRecipes, 'getRecipes', ISourcePackageRecipe)
+
 IPerson['hardware_submissions'].value_type.schema = IHWSubmission
 
 # publishing.py
@@ -440,6 +445,16 @@
     ISourcePackageRelease, 'source_package_recipe_build',
     ISourcePackageRecipeBuild)
 
+# ISourcePackageRecipeView
+patch_entry_return_type(
+    ISourcePackageRecipe, 'requestBuild', ISourcePackageRecipeBuild)
+patch_entry_return_type(
+    ISourcePackageRecipe, 'getLastBuild', ISourcePackageRecipeBuild)
+patch_collection_return_type(
+    ISourcePackageRecipe, 'getPendingBuilds', ISourcePackageRecipeBuild)
+patch_collection_return_type(
+    ISourcePackageRecipe, 'getBuilds', ISourcePackageRecipeBuild)
+
 # IHasBugs
 patch_plain_parameter_type(
     IHasBugs, 'searchTasks', 'assignee', IPerson)

=== modified file 'lib/lp/code/interfaces/hasrecipes.py'
--- lib/lp/code/interfaces/hasrecipes.py	2010-08-20 20:31:18 +0000
+++ lib/lp/code/interfaces/hasrecipes.py	2011-02-22 02:34:01 +0000
@@ -10,13 +10,18 @@
 
 
 from zope.interface import (
-    Attribute,
     Interface,
     )
 
+from lazr.restful.declarations import (
+    export_read_operation,
+    operation_returns_collection_of,
+    )
 
 class IHasRecipes(Interface):
     """An object that has recipes."""
 
+    @operation_returns_collection_of(Interface)
+    @export_read_operation()
     def getRecipes():
         """Returns all recipes associated with the object."""

=== modified file 'lib/lp/code/interfaces/sourcepackagerecipe.py'
--- lib/lp/code/interfaces/sourcepackagerecipe.py	2011-02-18 02:39:47 +0000
+++ lib/lp/code/interfaces/sourcepackagerecipe.py	2011-02-22 02:34:01 +0000
@@ -24,12 +24,18 @@
 from lazr.restful.declarations import (
     call_with,
     export_as_webservice_entry,
+    export_read_operation,
     export_write_operation,
     exported,
     mutator_for,
     operation_for_version,
     operation_parameters,
+<<<<<<< TREE
     operation_removed_in_version,
+=======
+    operation_returns_collection_of,
+    operation_returns_entry,
+>>>>>>> MERGE-SOURCE
     REQUEST_USER,
     )
 from lazr.restful.fields import (
@@ -113,12 +119,18 @@
         :param distroseries: The distroseries to build for.
         """
 
+    @operation_returns_collection_of(Interface)
+    @export_read_operation()
     def getBuilds():
         """Return a ResultSet of all the non-pending builds."""
 
+    @operation_returns_collection_of(Interface)
+    @export_read_operation()
     def getPendingBuilds():
         """Return a ResultSet of all the pending builds."""
 
+    @operation_returns_entry(Interface)
+    @export_read_operation()
     def getLastBuild():
         """Return the the most recent build of this recipe."""
 
@@ -127,6 +139,7 @@
         archive=Reference(schema=IArchive),
         distroseries=Reference(schema=IDistroSeries),
         pocket=Choice(vocabulary=PackagePublishingPocket,))
+    @operation_returns_entry(Interface)
     @export_write_operation()
     def requestBuild(archive, distroseries, requester, pocket):
         """Request that the recipe be built in to the specified archive.

=== modified file 'lib/lp/code/model/tests/test_sourcepackagerecipe.py'
--- lib/lp/code/model/tests/test_sourcepackagerecipe.py	2011-02-18 04:25:00 +0000
+++ lib/lp/code/model/tests/test_sourcepackagerecipe.py	2011-02-22 02:34:01 +0000
@@ -10,7 +10,6 @@
     timedelta,
     )
 import textwrap
-import unittest
 
 from bzrlib.plugins.builder.recipe import ForbiddenInstructionError
 from pytz import UTC
@@ -901,8 +900,14 @@
         recipe, user = self.makeRecipe()[:-1]
         self.assertEqual(recipe, user.getRecipe(name=recipe.name))
 
+    def test_getRecipes(self):
+        """Person.getRecipes works as expected."""
+        recipe, user = self.makeRecipe()[:-1]
+        [ws_recipe] = user.getRecipes()
+        self.assertEqual(recipe, ws_recipe)
+
     def test_requestBuild(self):
-        """Build requests can be performed."""
+        """Build requests can be performed and getLastBuild() works."""
         person = self.factory.makePerson()
         archive = self.factory.makeArchive(owner=person)
         distroseries = self.factory.makeSourcePackageRecipeDistroseries()
@@ -910,9 +915,10 @@
         recipe, user, launchpad = self.makeRecipe(person)
         distroseries = ws_object(launchpad, distroseries)
         archive = ws_object(launchpad, archive)
-        recipe.requestBuild(
+        build = recipe.requestBuild(
             archive=archive, distroseries=distroseries,
             pocket=PackagePublishingPocket.RELEASE.title)
+        self.assertEqual(build, recipe.getLastBuild())
 
     def test_requestBuildRejectRepeat(self):
         """Build requests are rejected if already pending."""
@@ -967,6 +973,21 @@
             pocket=PackagePublishingPocket.RELEASE.title)
         self.assertIn('BuildNotAllowedForDistro', str(e))
 
-
-def test_suite():
-    return unittest.TestLoader().loadTestsFromName(__name__)
+    def test_getBuilds(self):
+        """SourcePackageRecipe.get[Pending]Builds works as expected."""
+        person = self.factory.makePerson()
+        archives = [self.factory.makeArchive(owner=person) for x in range(4)]
+        distroseries= self.factory.makeSourcePackageRecipeDistroseries()
+
+        recipe, user, launchpad = self.makeRecipe(person)
+        distroseries = ws_object(launchpad, distroseries)
+
+        builds = []
+        for archive in archives:
+            archive = ws_object(launchpad, archive)
+            build = recipe.requestBuild(
+                archive=archive, distroseries=distroseries,
+                pocket=PackagePublishingPocket.RELEASE.title)
+            builds.insert(0, build)
+        self.assertEqual(builds, list(recipe.getPendingBuilds()))
+        self.assertEqual([], list(recipe.getBuilds()))


Follow ups