Merge lp:~michael.nelson/launchpad/create-source-recipe-build2 into lp:launchpad

Proposed by Michael Nelson
Status: Merged
Approved by: Muharem Hrnjadovic
Approved revision: not available
Merged at revision: not available
Proposed branch: lp:~michael.nelson/launchpad/create-source-recipe-build2
Merge into: lp:launchpad
Diff against target: 501 lines (+180/-37)
12 files modified
lib/lp/archiveuploader/permission.py (+19/-10)
lib/lp/archiveuploader/tests/test_permission.py (+8/-0)
lib/lp/buildmaster/interfaces/buildbase.py (+1/-1)
lib/lp/buildmaster/model/buildbase.py (+9/-5)
lib/lp/buildmaster/tests/test_buildbase.py (+0/-8)
lib/lp/soyuz/interfaces/sourcepackagerecipe.py (+12/-0)
lib/lp/soyuz/model/build.py (+4/-9)
lib/lp/soyuz/model/sourcepackagerecipe.py (+29/-0)
lib/lp/soyuz/model/sourcepackagerecipebuild.py (+2/-1)
lib/lp/soyuz/tests/test_build.py (+24/-1)
lib/lp/soyuz/tests/test_sourcepackagerecipe.py (+67/-0)
lib/lp/soyuz/tests/test_sourcepackagerecipebuild.py (+5/-2)
To merge this branch: bzr merge lp:~michael.nelson/launchpad/create-source-recipe-build2
Reviewer Review Type Date Requested Status
Muharem Hrnjadovic (community) Approve
Review via email: mp+18535@code.launchpad.net

Commit message

Adds ISourcePackageRecipe.requestBuild(), and ensures that classes that say they implement IBuildBase actually do (bug 510919)

To post a comment you must log in.
Revision history for this message
Michael Nelson (michael.nelson) wrote :

= Summary =
This branch builds on the work that james_w had approved at:

https://code.edge.launchpad.net/~james-w/launchpad/create-source-recipe-build/+merge/17435

I merged devel, so am not able to specify it as the pre-requisite branch (without showing tons of diff), so you can check my specific changes at:

http://pastebin.ubuntu.com/368292/

or with bzr diff -r 10188..10194

It does the following:
 1. Deals with the review feedback from the previous branch,
 2. Ensures that IBuildBase is provided by both SourcePackageRecipeBuild and (Binary)Build (bug 510919)
 3. Cleans some lint.

== Proposed fix ==

== Pre-implementation notes ==

Chatted with james_w briefly about what needed to be done.

== Implementation details ==

== Tests ==

bin/test -vv -t test_requestBuild -t TestBuildInterface

== Demo and Q/A ==

= Launchpad lint =

I'm not sure why lint is complaining about 'self' being missing from interface declarations?

Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.

Linting changed files:
  lib/lp/soyuz/tests/test_sourcepackagerecipebuild.py
  lib/lp/archiveuploader/uploadprocessor.py
  lib/lp/archiveuploader/permission.py
  lib/lp/buildmaster/model/buildbase.py
  lib/lp/soyuz/tests/test_build.py
  lib/lp/soyuz/tests/test_sourcepackagerecipe.py
  lib/lp/buildmaster/tests/test_buildbase.py
  lib/lp/soyuz/model/sourcepackagerecipebuild.py
  lib/lp/archiveuploader/tests/test_permission.py
  lib/lp/soyuz/model/sourcepackagerecipe.py
  lib/lp/buildmaster/interfaces/buildbase.py
  lib/lp/soyuz/interfaces/sourcepackagerecipe.py
  lib/lp/soyuz/model/build.py

== Pylint notices ==

lib/lp/soyuz/tests/test_sourcepackagerecipe.py
    11: [F0401] Unable to import 'bzrlib.plugins.builder.recipe' (No module named builder)

lib/lp/buildmaster/interfaces/buildbase.py
    14: [F0401] Unable to import 'lazr.enum' (No module named enum)
    15: [F0401] Unable to import 'lazr.restful.declarations' (No module named restful)
    16: [F0401] Unable to import 'lazr.restful.fields' (No module named restful)

lib/lp/soyuz/interfaces/sourcepackagerecipe.py
    14: [F0401] Unable to import 'lazr.restful.fields' (No module named restful)
    77: [E0211, ISourcePackageRecipe.getReferencedBranches] Method has no argument
    80: [E0213, ISourcePackageRecipe.requestBuild] Method should have "self" as first argument
    95: [E0213, ISourcePackageRecipeSource.new] Method should have "self" as first argument

Revision history for this message
Muharem Hrnjadovic (al-maisan) wrote :

Looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/archiveuploader/permission.py'
--- lib/lp/archiveuploader/permission.py 2010-01-15 01:37:51 +0000
+++ lib/lp/archiveuploader/permission.py 2010-02-05 10:56:18 +0000
@@ -21,24 +21,21 @@
21from lp.soyuz.interfaces.archive import ArchivePurpose21from lp.soyuz.interfaces.archive import ArchivePurpose
2222
2323
24class CannotUploadToArchive:24class CannotUploadToArchive(Exception):
25 """A reason for not being able to upload to an archive."""25 """A reason for not being able to upload to an archive."""
2626
27 _fmt = '%(person)s has no upload rights to %(archive)s.'27 _fmt = '%(person)s has no upload rights to %(archive)s.'
2828
29 def __init__(self, **args):29 def __init__(self, **args):
30 """Construct a `CannotUploadToArchive`."""30 """Construct a `CannotUploadToArchive`."""
31 self._message = self._fmt % args31 Exception.__init__(self, self._fmt % args)
3232
33 def __str__(self):33
34 return self._message34class CannotUploadToPocket(Exception):
35
36
37class CannotUploadToPocket:
38 """Returned when a pocket is closed for uploads."""35 """Returned when a pocket is closed for uploads."""
3936
40 def __init__(self, distroseries, pocket):37 def __init__(self, distroseries, pocket):
41 super(CannotUploadToPocket, self).__init__(38 Exception.__init__(self,
42 "Not permitted to upload to the %s pocket in a series in the "39 "Not permitted to upload to the %s pocket in a series in the "
43 "'%s' state." % (pocket.name, distroseries.status.name))40 "'%s' state." % (pocket.name, distroseries.status.name))
4441
@@ -73,7 +70,7 @@
73 "Signer is not permitted to upload to the component '%(component)s'.")70 "Signer is not permitted to upload to the component '%(component)s'.")
7471
75 def __init__(self, component):72 def __init__(self, component):
76 super(NoRightsForComponent, self).__init__(component=component.name)73 CannotUploadToArchive.__init__(self, component=component.name)
7774
7875
79class InvalidPocketForPPA(CannotUploadToArchive):76class InvalidPocketForPPA(CannotUploadToArchive):
@@ -88,6 +85,15 @@
88 _fmt = "Partner uploads must be for the RELEASE or PROPOSED pocket."85 _fmt = "Partner uploads must be for the RELEASE or PROPOSED pocket."
8986
9087
88class ArchiveDisabled(CannotUploadToArchive):
89 """Uploading to a disabled archive is not allowed."""
90
91 _fmt = ("%(archive_name)s is disabled.")
92
93 def __init__(self, archive_name):
94 CannotUploadToArchive.__init__(self, archive_name=archive_name)
95
96
91def components_valid_for(archive, person):97def components_valid_for(archive, person):
92 """Return the components that 'person' can upload to 'archive'.98 """Return the components that 'person' can upload to 'archive'.
9399
@@ -202,6 +208,9 @@
202 :return: CannotUploadToArchive if 'person' cannot upload to the archive,208 :return: CannotUploadToArchive if 'person' cannot upload to the archive,
203 None otherwise.209 None otherwise.
204 """210 """
211 if not archive.enabled:
212 return ArchiveDisabled(archive.displayname)
213
205 # For PPAs...214 # For PPAs...
206 if archive.is_ppa:215 if archive.is_ppa:
207 if not archive.canUpload(person):216 if not archive.canUpload(person):
208217
=== modified file 'lib/lp/archiveuploader/tests/test_permission.py'
--- lib/lp/archiveuploader/tests/test_permission.py 2009-12-13 11:55:40 +0000
+++ lib/lp/archiveuploader/tests/test_permission.py 2010-02-05 10:56:18 +0000
@@ -241,6 +241,14 @@
241 self.assertCanUpload(241 self.assertCanUpload(
242 person, spn, archive, component_a, strict_component=False)242 person, spn, archive, component_a, strict_component=False)
243243
244 def test_cannot_upload_to_disabled_archive(self):
245 spn = self.factory.makeSourcePackageName()
246 archive = self.factory.makeArchive()
247 removeSecurityProxy(archive).disable()
248 component = self.factory.makeComponent()
249 self.assertCannotUpload(u"%s is disabled." % (archive.displayname),
250 archive.owner, spn, archive, component)
251
244252
245def test_suite():253def test_suite():
246 return unittest.TestLoader().loadTestsFromName(__name__)254 return unittest.TestLoader().loadTestsFromName(__name__)
247255
=== modified file 'lib/lp/buildmaster/interfaces/buildbase.py'
--- lib/lp/buildmaster/interfaces/buildbase.py 2010-01-22 04:11:36 +0000
+++ lib/lp/buildmaster/interfaces/buildbase.py 2010-02-05 10:56:18 +0000
@@ -109,7 +109,7 @@
109 title=_("Distribution"), required=True,109 title=_("Distribution"), required=True,
110 description=_("Shortcut for its distribution.")))110 description=_("Shortcut for its distribution.")))
111111
112 def getUploaderCommand(upload_leaf):112 def getUploaderCommand(upload_leaf, uploader_logfilename):
113 """Get the command to run as the uploader.113 """Get the command to run as the uploader.
114114
115 :return: A list of command line arguments, beginning with the115 :return: A list of command line arguments, beginning with the
116116
=== modified file 'lib/lp/buildmaster/model/buildbase.py'
--- lib/lp/buildmaster/model/buildbase.py 2010-01-21 22:09:51 +0000
+++ lib/lp/buildmaster/model/buildbase.py 2010-02-05 10:56:18 +0000
@@ -16,7 +16,6 @@
16import subprocess16import subprocess
1717
18from storm.store import Store18from storm.store import Store
19from zope.interface import implements
20from zope.security.proxy import removeSecurityProxy19from zope.security.proxy import removeSecurityProxy
2120
22from canonical.config import config21from canonical.config import config
@@ -24,16 +23,21 @@
24from canonical.database.sqlbase import (23from canonical.database.sqlbase import (
25 clear_current_connection_cache, cursor, flush_database_updates)24 clear_current_connection_cache, cursor, flush_database_updates)
26from canonical.librarian.utils import copy_and_close25from canonical.librarian.utils import copy_and_close
27from lp.buildmaster.interfaces.buildbase import IBuildBase
28from lp.registry.interfaces.pocket import pocketsuffix26from lp.registry.interfaces.pocket import pocketsuffix
29from lp.soyuz.interfaces.build import BuildStatus27from lp.soyuz.interfaces.build import BuildStatus
30from lp.soyuz.model.buildqueue import BuildQueue28from lp.soyuz.model.buildqueue import BuildQueue
3129
3230
33class BuildBase:31class BuildBase:
3432 """A mixin class providing functionality for farm jobs that build a
35 implements(IBuildBase)33 package.
3634
35 Note: this class does not implement IBuildBase as we currently duplicate
36 the properties defined on IBuildBase on the inheriting class tables.
37 BuildBase cannot therefore implement IBuildBase itself, as storm requires
38 that the corresponding __storm_table__ be defined for the class. Instead,
39 the classes using the BuildBase mixin must ensure that they implement IBuildBase.
40 """
37 policy_name = 'buildd'41 policy_name = 'buildd'
3842
39 def getUploadLeaf(self, build_id, now=None):43 def getUploadLeaf(self, build_id, now=None):
4044
=== modified file 'lib/lp/buildmaster/tests/test_buildbase.py'
--- lib/lp/buildmaster/tests/test_buildbase.py 2010-01-21 22:35:21 +0000
+++ lib/lp/buildmaster/tests/test_buildbase.py 2010-02-05 10:56:18 +0000
@@ -11,7 +11,6 @@
1111
12from canonical.config import config12from canonical.config import config
13from canonical.testing.layers import DatabaseFunctionalLayer13from canonical.testing.layers import DatabaseFunctionalLayer
14from lp.buildmaster.interfaces.buildbase import IBuildBase
15from lp.buildmaster.model.buildbase import BuildBase14from lp.buildmaster.model.buildbase import BuildBase
16from lp.registry.interfaces.pocket import pocketsuffix15from lp.registry.interfaces.pocket import pocketsuffix
17from lp.testing import TestCase, TestCaseWithFactory16from lp.testing import TestCase, TestCaseWithFactory
@@ -20,13 +19,6 @@
20class TestBuildBase(TestCase):19class TestBuildBase(TestCase):
21 """Tests for `IBuildBase`."""20 """Tests for `IBuildBase`."""
2221
23 def disabled_test_build_base_provides_interface(self):
24 # XXX: JonathanLange 2010-01-22 bug=510919: BuildBase is supposed to
25 # implement IBuildBase, but doesn't atm. Since it's not the focus of
26 # the branch, we'll postpone the work.
27 build_base = BuildBase()
28 self.assertProvides(build_base, IBuildBase)
29
30 def test_getUploadLeaf(self):22 def test_getUploadLeaf(self):
31 # getUploadLeaf returns the current time, followed by the build id.23 # getUploadLeaf returns the current time, followed by the build id.
32 build_base = BuildBase()24 build_base = BuildBase()
3325
=== modified file 'lib/lp/soyuz/interfaces/sourcepackagerecipe.py'
--- lib/lp/soyuz/interfaces/sourcepackagerecipe.py 2010-01-14 21:31:28 +0000
+++ lib/lp/soyuz/interfaces/sourcepackagerecipe.py 2010-02-05 10:56:18 +0000
@@ -29,6 +29,7 @@
29 """A forbidden instruction was found in the recipe."""29 """A forbidden instruction was found in the recipe."""
3030
31 def __init__(self, instruction_name):31 def __init__(self, instruction_name):
32 super(ForbiddenInstruction, self).__init__()
32 self.instruction_name = instruction_name33 self.instruction_name = instruction_name
3334
3435
@@ -36,6 +37,7 @@
36 """The format of the recipe supplied was too new."""37 """The format of the recipe supplied was too new."""
3738
38 def __init__(self, supplied_format, newest_supported):39 def __init__(self, supplied_format, newest_supported):
40 super(TooNewRecipeFormat, self).__init__()
39 self.supplied_format = supplied_format41 self.supplied_format = supplied_format
40 self.newest_supported = newest_supported42 self.newest_supported = newest_supported
4143
@@ -75,6 +77,16 @@
75 def getReferencedBranches():77 def getReferencedBranches():
76 """An iterator of the branches referenced by this recipe."""78 """An iterator of the branches referenced by this recipe."""
7779
80 def requestBuild(archive, distroseries, requester, pocket):
81 """Request that the recipe be built in to the specified archive.
82
83 :param archive: The IArchive which you want the build to end up in.
84 :param requester: the person requesting the build.
85 :param pocket: the pocket that should be targeted.
86 :raises: various specific upload errors if the requestor is not
87 able to upload to the archive.
88 """
89
7890
79class ISourcePackageRecipeSource(Interface):91class ISourcePackageRecipeSource(Interface):
80 """A utility of this interface can be used to create and access recipes.92 """A utility of this interface can be used to create and access recipes.
8193
=== modified file 'lib/lp/soyuz/model/build.py'
--- lib/lp/soyuz/model/build.py 2010-01-20 22:09:26 +0000
+++ lib/lp/soyuz/model/build.py 2010-02-05 10:56:18 +0000
@@ -11,9 +11,6 @@
11import datetime11import datetime
12import logging12import logging
13import operator13import operator
14import os
15import subprocess
16import time
1714
18from zope.interface import implements15from zope.interface import implements
19from zope.component import getUtility16from zope.component import getUtility
@@ -30,8 +27,7 @@
30from canonical.database.datetimecol import UtcDateTimeCol27from canonical.database.datetimecol import UtcDateTimeCol
31from canonical.database.enumcol import EnumCol28from canonical.database.enumcol import EnumCol
32from canonical.database.sqlbase import (29from canonical.database.sqlbase import (
33 clear_current_connection_cache, flush_database_updates, cursor,30 cursor, quote_like, SQLBase, sqlvalues)
34 quote_like, SQLBase, sqlvalues)
35from canonical.launchpad.components.decoratedresultset import (31from canonical.launchpad.components.decoratedresultset import (
36 DecoratedResultSet)32 DecoratedResultSet)
37from canonical.launchpad.database.librarian import (33from canonical.launchpad.database.librarian import (
@@ -47,17 +43,16 @@
47from canonical.launchpad.webapp.interfaces import (43from canonical.launchpad.webapp.interfaces import (
48 IStoreSelector, MAIN_STORE, DEFAULT_FLAVOR)44 IStoreSelector, MAIN_STORE, DEFAULT_FLAVOR)
49from canonical.launchpad.webapp.tales import DurationFormatterAPI45from canonical.launchpad.webapp.tales import DurationFormatterAPI
50from canonical.librarian.utils import copy_and_close
51from lp.archivepublisher.utils import get_ppa_reference46from lp.archivepublisher.utils import get_ppa_reference
52from lp.buildmaster.interfaces.buildfarmjob import BuildFarmJobType47from lp.buildmaster.interfaces.buildfarmjob import BuildFarmJobType
53from lp.buildmaster.model.buildbase import BuildBase48from lp.buildmaster.model.buildbase import BuildBase
54from lp.registry.interfaces.pocket import (PackagePublishingPocket,49from lp.registry.interfaces.pocket import PackagePublishingPocket
55 pocketsuffix)
56from lp.services.job.model.job import Job50from lp.services.job.model.job import Job
57from lp.soyuz.adapters.archivedependencies import get_components_for_building51from lp.soyuz.adapters.archivedependencies import get_components_for_building
58from lp.soyuz.interfaces.archive import ArchivePurpose52from lp.soyuz.interfaces.archive import ArchivePurpose
59from lp.soyuz.interfaces.build import (53from lp.soyuz.interfaces.build import (
60 BuildStatus, BuildSetStatus, CannotBeRescored, IBuild, IBuildSet)54 BuildStatus, BuildSetStatus, CannotBeRescored, IBuild, IBuildSet)
55from lp.buildmaster.interfaces.buildbase import IBuildBase
61from lp.buildmaster.interfaces.builder import IBuilderSet56from lp.buildmaster.interfaces.builder import IBuilderSet
62from lp.soyuz.interfaces.publishing import active_publishing_status57from lp.soyuz.interfaces.publishing import active_publishing_status
63from lp.soyuz.model.binarypackagerelease import BinaryPackageRelease58from lp.soyuz.model.binarypackagerelease import BinaryPackageRelease
@@ -71,7 +66,7 @@
7166
7267
73class Build(BuildBase, SQLBase):68class Build(BuildBase, SQLBase):
74 implements(IBuild)69 implements(IBuildBase, IBuild)
75 _table = 'Build'70 _table = 'Build'
76 _defaultOrder = 'id'71 _defaultOrder = 'id'
7772
7873
=== modified file 'lib/lp/soyuz/model/sourcepackagerecipe.py'
--- lib/lp/soyuz/model/sourcepackagerecipe.py 2010-01-13 03:18:49 +0000
+++ lib/lp/soyuz/model/sourcepackagerecipe.py 2010-02-05 10:56:18 +0000
@@ -10,16 +10,27 @@
1010
11from storm.locals import Int, Reference, Store, Storm, Unicode11from storm.locals import Int, Reference, Store, Storm, Unicode
1212
13from zope.component import getUtility
13from zope.interface import classProvides, implements14from zope.interface import classProvides, implements
1415
15from canonical.database.datetimecol import UtcDateTimeCol16from canonical.database.datetimecol import UtcDateTimeCol
16from canonical.launchpad.interfaces.lpstorm import IMasterStore17from canonical.launchpad.interfaces.lpstorm import IMasterStore
1718
19from lp.soyuz.interfaces.archive import ArchivePurpose
20from lp.soyuz.interfaces.component import IComponentSet
21from lp.archiveuploader.permission import check_upload_to_archive
18from lp.soyuz.interfaces.sourcepackagerecipe import (22from lp.soyuz.interfaces.sourcepackagerecipe import (
19 ISourcePackageRecipe, ISourcePackageRecipeSource)23 ISourcePackageRecipe, ISourcePackageRecipeSource)
24from lp.soyuz.interfaces.sourcepackagerecipebuild import (
25 ISourcePackageRecipeBuildSource)
20from lp.soyuz.model.sourcepackagerecipedata import _SourcePackageRecipeData26from lp.soyuz.model.sourcepackagerecipedata import _SourcePackageRecipeData
2127
2228
29class NonPPABuildRequest(Exception):
30 """A build was requested to a non-PPA and this is currently
31 unsupported."""
32
33
23class SourcePackageRecipe(Storm):34class SourcePackageRecipe(Storm):
24 """See `ISourcePackageRecipe` and `ISourcePackageRecipeSource`."""35 """See `ISourcePackageRecipe` and `ISourcePackageRecipeSource`."""
2536
@@ -82,3 +93,21 @@
82 sprecipe.name = name93 sprecipe.name = name
83 store.add(sprecipe)94 store.add(sprecipe)
84 return sprecipe95 return sprecipe
96
97 def requestBuild(self, archive, requester, pocket):
98 """See `ISourcePackageRecipe`."""
99 if archive.purpose != ArchivePurpose.PPA:
100 raise NonPPABuildRequest
101 component = getUtility(IComponentSet)["multiverse"]
102 reject_reason = check_upload_to_archive(
103 requester, self.distroseries, self.sourcepackagename,
104 archive, component, pocket)
105 if reject_reason is not None:
106 raise reject_reason
107
108 sourcepackage = self.distroseries.getSourcePackage(
109 self.sourcepackagename)
110 build = getUtility(ISourcePackageRecipeBuildSource).new(sourcepackage,
111 self, requester, archive)
112 build.queueBuild()
113 return build
85114
=== modified file 'lib/lp/soyuz/model/sourcepackagerecipebuild.py'
--- lib/lp/soyuz/model/sourcepackagerecipebuild.py 2010-01-22 04:01:17 +0000
+++ lib/lp/soyuz/model/sourcepackagerecipebuild.py 2010-02-05 10:56:18 +0000
@@ -21,6 +21,7 @@
21from zope.component import getUtility21from zope.component import getUtility
22from zope.interface import classProvides, implements22from zope.interface import classProvides, implements
2323
24from lp.buildmaster.interfaces.buildbase import IBuildBase
24from lp.buildmaster.interfaces.buildfarmjob import BuildFarmJobType25from lp.buildmaster.interfaces.buildfarmjob import BuildFarmJobType
25from lp.buildmaster.model.buildbase import BuildBase26from lp.buildmaster.model.buildbase import BuildBase
26from lp.buildmaster.model.packagebuildfarmjob import PackageBuildFarmJob27from lp.buildmaster.model.packagebuildfarmjob import PackageBuildFarmJob
@@ -41,7 +42,7 @@
4142
42 policy_name = 'recipe'43 policy_name = 'recipe'
4344
44 implements(ISourcePackageRecipeBuild)45 implements(IBuildBase, ISourcePackageRecipeBuild)
45 classProvides(ISourcePackageRecipeBuildSource)46 classProvides(ISourcePackageRecipeBuildSource)
4647
47 build_farm_job_type = BuildFarmJobType.RECIPEBRANCHBUILD48 build_farm_job_type = BuildFarmJobType.RECIPEBRANCHBUILD
4849
=== modified file 'lib/lp/soyuz/tests/test_build.py'
--- lib/lp/soyuz/tests/test_build.py 2010-01-11 23:43:59 +0000
+++ lib/lp/soyuz/tests/test_build.py 2010-02-05 10:56:18 +0000
@@ -3,6 +3,8 @@
33
4"""Test Build features."""4"""Test Build features."""
55
6from datetime import datetime, timedelta
7import pytz
6import unittest8import unittest
79
8from storm.store import Store10from storm.store import Store
@@ -10,9 +12,10 @@
1012
11from canonical.testing import LaunchpadZopelessLayer13from canonical.testing import LaunchpadZopelessLayer
12from lp.services.job.model.job import Job14from lp.services.job.model.job import Job
15from lp.buildmaster.interfaces.buildbase import IBuildBase
13from lp.buildmaster.interfaces.builder import IBuilderSet16from lp.buildmaster.interfaces.builder import IBuilderSet
14from lp.soyuz.interfaces.component import IComponentSet17from lp.soyuz.interfaces.component import IComponentSet
15from lp.soyuz.interfaces.build import BuildStatus, IBuildSet18from lp.soyuz.interfaces.build import BuildStatus, IBuild, IBuildSet
16from lp.soyuz.interfaces.publishing import PackagePublishingStatus19from lp.soyuz.interfaces.publishing import PackagePublishingStatus
17from lp.soyuz.model.buildqueue import BuildQueue20from lp.soyuz.model.buildqueue import BuildQueue
18from lp.soyuz.model.buildpackagejob import BuildPackageJob21from lp.soyuz.model.buildpackagejob import BuildPackageJob
@@ -21,6 +24,26 @@
21from lp.testing import TestCaseWithFactory24from lp.testing import TestCaseWithFactory
2225
2326
27class TestBuildInterface(TestCaseWithFactory):
28
29 layer = LaunchpadZopelessLayer
30
31 def test_providesInterfaces(self):
32 # Build provides IBuildBase and IBuild.
33 publisher = SoyuzTestPublisher()
34 publisher.prepareBreezyAutotest()
35 gedit_src_hist = publisher.getPubSource(
36 sourcename="gedit", status=PackagePublishingStatus.PUBLISHED)
37 build = gedit_src_hist.createMissingBuilds()[0]
38
39 # The IBuild.calculated_buildstart property asserts
40 # that both datebuilt and buildduration are set.
41 build.datebuilt = datetime.now(pytz.UTC)
42 build.buildduration = timedelta(0, 1)
43
44 self.assertProvides(build, IBuildBase)
45 self.assertProvides(build, IBuild)
46
24class TestBuildUpdateDependencies(TestCaseWithFactory):47class TestBuildUpdateDependencies(TestCaseWithFactory):
2548
26 layer = LaunchpadZopelessLayer49 layer = LaunchpadZopelessLayer
2750
=== modified file 'lib/lp/soyuz/tests/test_sourcepackagerecipe.py'
--- lib/lp/soyuz/tests/test_sourcepackagerecipe.py 2010-01-13 03:18:49 +0000
+++ lib/lp/soyuz/tests/test_sourcepackagerecipe.py 2010-02-05 10:56:18 +0000
@@ -10,14 +10,33 @@
1010
11from bzrlib.plugins.builder.recipe import RecipeParser11from bzrlib.plugins.builder.recipe import RecipeParser
1212
13from storm.locals import Store
14
13from zope.component import getUtility15from zope.component import getUtility
14from zope.security.interfaces import Unauthorized16from zope.security.interfaces import Unauthorized
17from zope.security.proxy import removeSecurityProxy
1518
16from canonical.testing.layers import DatabaseFunctionalLayer19from canonical.testing.layers import DatabaseFunctionalLayer
1720
21from lp.archiveuploader.permission import (
22 ArchiveDisabled, CannotUploadToArchive, InvalidPocketForPPA)
23from lp.registry.interfaces.pocket import PackagePublishingPocket
24from lp.services.job.interfaces.job import (
25 IJob, JobStatus)
26from lp.soyuz.interfaces.archive import ArchivePurpose
27from lp.soyuz.interfaces.buildqueue import (
28 IBuildQueue)
18from lp.soyuz.interfaces.sourcepackagerecipe import (29from lp.soyuz.interfaces.sourcepackagerecipe import (
19 ForbiddenInstruction, ISourcePackageRecipe, ISourcePackageRecipeSource,30 ForbiddenInstruction, ISourcePackageRecipe, ISourcePackageRecipeSource,
20 TooNewRecipeFormat)31 TooNewRecipeFormat)
32from lp.soyuz.interfaces.sourcepackagerecipebuild import (
33 ISourcePackageRecipeBuild, ISourcePackageRecipeBuildJob)
34from lp.soyuz.model.buildqueue import (
35 BuildQueue)
36from lp.soyuz.model.sourcepackagerecipebuild import (
37 SourcePackageRecipeBuildJob)
38from lp.soyuz.model.sourcepackagerecipe import (
39 NonPPABuildRequest)
21from lp.testing import login_person, TestCaseWithFactory40from lp.testing import login_person, TestCaseWithFactory
2241
2342
@@ -154,6 +173,54 @@
154 TooNewRecipeFormat,173 TooNewRecipeFormat,
155 self.makeSourcePackageRecipeFromBuilderRecipe, builder_recipe)174 self.makeSourcePackageRecipeFromBuilderRecipe, builder_recipe)
156175
176 def test_requestBuild(self):
177 recipe = self.factory.makeSourcePackageRecipe()
178 ppa = self.factory.makeArchive()
179 build = recipe.requestBuild(ppa, ppa.owner,
180 PackagePublishingPocket.RELEASE)
181 self.assertProvides(build, ISourcePackageRecipeBuild)
182 self.assertEqual(build.archive, ppa)
183 self.assertEqual(build.distroseries, recipe.distroseries)
184 self.assertEqual(build.requester, ppa.owner)
185 store = Store.of(build)
186 store.flush()
187 build_job = store.find(SourcePackageRecipeBuildJob,
188 SourcePackageRecipeBuildJob.build_id==build.id).one()
189 self.assertProvides(build_job, ISourcePackageRecipeBuildJob)
190 self.assertTrue(build_job.virtualized)
191 job = build_job.job
192 self.assertProvides(job, IJob)
193 self.assertEquals(job.status, JobStatus.WAITING)
194 build_queue = store.find(BuildQueue, BuildQueue.job==job.id).one()
195 self.assertProvides(build_queue, IBuildQueue)
196 self.assertTrue(build_queue.virtualized)
197
198 def test_requestBuildRejectsNotPPA(self):
199 recipe = self.factory.makeSourcePackageRecipe()
200 not_ppa = self.factory.makeArchive(purpose=ArchivePurpose.PRIMARY)
201 self.assertRaises(NonPPABuildRequest, recipe.requestBuild, not_ppa,
202 not_ppa.owner, PackagePublishingPocket.RELEASE)
203
204 def test_requestBuildRejectsNoPermission(self):
205 recipe = self.factory.makeSourcePackageRecipe()
206 ppa = self.factory.makeArchive()
207 requester = self.factory.makePerson()
208 self.assertRaises(CannotUploadToArchive, recipe.requestBuild, ppa,
209 requester, PackagePublishingPocket.RELEASE)
210
211 def test_requestBuildRejectsInvalidPocket(self):
212 recipe = self.factory.makeSourcePackageRecipe()
213 ppa = self.factory.makeArchive()
214 self.assertRaises(InvalidPocketForPPA, recipe.requestBuild, ppa,
215 ppa.owner, PackagePublishingPocket.BACKPORTS)
216
217 def test_requestBuildRejectsDisabledArchive(self):
218 recipe = self.factory.makeSourcePackageRecipe()
219 ppa = self.factory.makeArchive()
220 removeSecurityProxy(ppa).disable()
221 self.assertRaises(ArchiveDisabled, recipe.requestBuild, ppa,
222 ppa.owner, PackagePublishingPocket.RELEASE)
223
157224
158class TestRecipeBranchRoundTripping(TestCaseWithFactory):225class TestRecipeBranchRoundTripping(TestCaseWithFactory):
159226
160227
=== modified file 'lib/lp/soyuz/tests/test_sourcepackagerecipebuild.py'
--- lib/lp/soyuz/tests/test_sourcepackagerecipebuild.py 2010-01-20 01:24:01 +0000
+++ lib/lp/soyuz/tests/test_sourcepackagerecipebuild.py 2010-02-05 10:56:18 +0000
@@ -13,6 +13,7 @@
1313
14from canonical.testing.layers import DatabaseFunctionalLayer14from canonical.testing.layers import DatabaseFunctionalLayer
1515
16from lp.buildmaster.interfaces.buildbase import IBuildBase
16from lp.soyuz.interfaces.buildqueue import IBuildQueue17from lp.soyuz.interfaces.buildqueue import IBuildQueue
17from lp.soyuz.interfaces.sourcepackagerecipebuild import (18from lp.soyuz.interfaces.sourcepackagerecipebuild import (
18 ISourcePackageRecipeBuildJob, ISourcePackageRecipeBuild,19 ISourcePackageRecipeBuildJob, ISourcePackageRecipeBuild,
@@ -33,9 +34,11 @@
33 archive=self.factory.makeArchive(),34 archive=self.factory.makeArchive(),
34 requester=self.factory.makePerson())35 requester=self.factory.makePerson())
3536
36 def test_providesInterface(self):37 def test_providesInterfaces(self):
37 # SourcePackageRecipeBuild provides ISourcePackageRecipeBuild.38 # SourcePackageRecipeBuild provides IBuildBase and
39 # ISourcePackageRecipeBuild.
38 spb = self.makeSourcePackageRecipeBuild()40 spb = self.makeSourcePackageRecipeBuild()
41 self.assertProvides(spb, IBuildBase)
39 self.assertProvides(spb, ISourcePackageRecipeBuild)42 self.assertProvides(spb, ISourcePackageRecipeBuild)
4043
41 def test_saves_record(self):44 def test_saves_record(self):