Merge lp:~jml/launchpad/more-recipe-model-code into lp:launchpad/db-devel

Proposed by Jonathan Lange
Status: Merged
Merged at revision: not available
Proposed branch: lp:~jml/launchpad/more-recipe-model-code
Merge into: lp:launchpad/db-devel
Prerequisite: lp:~mwhudson/launchpad/recipe-model-code
Diff against target: 594 lines (+311/-41)
13 files modified
.bzrignore (+1/-0)
database/schema/security.cfg (+1/-0)
lib/lp/soyuz/configure.zcml (+11/-0)
lib/lp/soyuz/interfaces/build.py (+1/-0)
lib/lp/soyuz/interfaces/sourcepackagebuild.py (+94/-0)
lib/lp/soyuz/interfaces/sourcepackagerecipe.py (+0/-1)
lib/lp/soyuz/model/sourcepackagebuild.py (+97/-0)
lib/lp/soyuz/model/sourcepackagerecipe.py (+3/-1)
lib/lp/soyuz/tests/test_sourcepackagebuild.py (+43/-0)
lib/lp/soyuz/tests/test_sourcepackagerecipe.py (+11/-33)
lib/lp/testing/factory.py (+47/-3)
standard_template.py (+1/-1)
standard_test_template.py (+1/-2)
To merge this branch: bzr merge lp:~jml/launchpad/more-recipe-model-code
Reviewer Review Type Date Requested Status
Canonical Launchpad Engineering Pending
Review via email: mp+17188@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Jonathan Lange (jml) wrote :

This branch adds model code for the SourcePackageBuild table. That's pretty much it.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2010-01-10 22:23:32 +0000
3+++ .bzrignore 2010-01-12 04:22:16 +0000
4@@ -54,3 +54,4 @@
5 _trial_temp
6 lazr-js
7 lib/canonical/buildd/launchpad-files
8+.testrepository
9
10=== modified file 'database/schema/security.cfg'
11--- database/schema/security.cfg 2010-01-12 04:22:13 +0000
12+++ database/schema/security.cfg 2010-01-12 04:22:16 +0000
13@@ -275,6 +275,7 @@
14 public.sourcepackagepublishinghistory = SELECT
15 public.seriessourcepackagebranch = SELECT, INSERT, UPDATE, DELETE
16 public.sourcepackageformatselection = SELECT
17+public.sourcepackagebuild = SELECT, INSERT, UPDATE, DELETE
18 public.sourcepackagerecipe = SELECT, INSERT, UPDATE, DELETE
19 public.sourcepackagerecipedata = SELECT, INSERT, UPDATE, DELETE
20 public.sourcepackagerecipedatainstruction = SELECT, INSERT, UPDATE, DELETE
21
22=== modified file 'lib/lp/soyuz/configure.zcml'
23--- lib/lp/soyuz/configure.zcml 2010-01-12 04:22:13 +0000
24+++ lib/lp/soyuz/configure.zcml 2010-01-12 04:22:16 +0000
25@@ -945,4 +945,15 @@
26 <allow interface="lp.soyuz.interfaces.sourcepackagerecipe.ISourcePackageRecipeSource"/>
27 </securedutility>
28
29+ <class
30+ class="lp.soyuz.model.sourcepackagebuild.SourcePackageBuild">
31+ <allow interface="lp.soyuz.interfaces.sourcepackagebuild.ISourcePackageBuild"/>
32+ </class>
33+
34+ <securedutility
35+ component="lp.soyuz.model.sourcepackagebuild.SourcePackageBuild"
36+ provides="lp.soyuz.interfaces.sourcepackagebuild.ISourcePackageBuildSource">
37+ <allow interface="lp.soyuz.interfaces.sourcepackagebuild.ISourcePackageBuildSource"/>
38+ </securedutility>
39+
40 </configure>
41
42=== modified file 'lib/lp/soyuz/interfaces/build.py'
43--- lib/lp/soyuz/interfaces/build.py 2009-11-20 18:06:28 +0000
44+++ lib/lp/soyuz/interfaces/build.py 2010-01-12 04:22:16 +0000
45@@ -201,6 +201,7 @@
46 description=_("Build duration interval, calculated when the "
47 "build result gets collected."))
48
49+ # XXX: jml 2010-01-12: Rename to build_log.
50 buildlog = Object(
51 schema=ILibraryFileAlias, required=False,
52 title=_("The LibraryFileAlias containing the entire buildlog."))
53
54=== added file 'lib/lp/soyuz/interfaces/sourcepackagebuild.py'
55--- lib/lp/soyuz/interfaces/sourcepackagebuild.py 1970-01-01 00:00:00 +0000
56+++ lib/lp/soyuz/interfaces/sourcepackagebuild.py 2010-01-12 04:22:16 +0000
57@@ -0,0 +1,94 @@
58+# Copyright 2010 Canonical Ltd. This software is licensed under the
59+# GNU Affero General Public License version 3 (see the file LICENSE).
60+
61+"""Interfaces for source package builds."""
62+
63+__metaclass__ = type
64+__all__ = [
65+ 'ISourcePackageBuild',
66+ 'ISourcePackageBuildSource',
67+ ]
68+
69+from lazr.restful.fields import Reference
70+
71+from zope.interface import Attribute, Interface
72+from zope.schema import Choice, Datetime, Object, Timedelta
73+
74+from canonical.launchpad import _
75+from canonical.launchpad.interfaces.librarian import ILibraryFileAlias
76+
77+from lp.registry.interfaces.person import IPerson
78+from lp.registry.interfaces.distroseries import IDistroSeries
79+from lp.registry.interfaces.sourcepackagename import ISourcePackageName
80+from lp.soyuz.interfaces.build import BuildStatus
81+from lp.soyuz.interfaces.builder import IBuilder
82+from lp.soyuz.interfaces.sourcepackagerecipe import ISourcePackageRecipe
83+
84+
85+class ISourcePackageBuild(Interface):
86+ """A build of a source package."""
87+
88+ date_created = Datetime(required=True, readonly=True)
89+
90+ distroseries = Reference(
91+ IDistroSeries, title=_("The distroseries being built for"),
92+ readonly=True)
93+
94+ sourcepackagename = Reference(
95+ ISourcePackageName,
96+ title=_("The name of the source package being built"),
97+ readonly=True)
98+
99+ # XXX: JonathanLange 2010-01-12: Move build_state, date_built,
100+ # build_duration, build_log, builder and maybe date_first_dispatched to a
101+ # separate base interface shared by this and IBuild. Additionally, change
102+ # IBuild to IBinaryPackageBuild.
103+ build_state = Choice(
104+ title=_('State'), required=True, vocabulary=BuildStatus,
105+ description=_("The current build state."))
106+
107+ date_built = Datetime(required=False)
108+
109+ build_duration = Timedelta(
110+ title=_("Build Duration"), required=False,
111+ description=_("Build duration interval, calculated when the "
112+ "build result gets collected."))
113+
114+ build_log = Object(
115+ schema=ILibraryFileAlias, required=False,
116+ title=_("The LibraryFileAlias containing the entire build log."))
117+
118+ builder = Object(
119+ title=_("Builder"), schema=IBuilder, required=False,
120+ description=_("The builder handling this build request."))
121+
122+ date_first_dispatched = Datetime(
123+ title=_('Date first dispatched'), required=False,
124+ description=_("The actual build start time. Set when the build "
125+ "is dispatched the first time and not changed in "
126+ "subsequent build attempts."))
127+
128+ requester = Object(
129+ schema=IPerson, required=False,
130+ title=_("The person who wants this to be done."))
131+
132+ recipe = Object(
133+ schema=ISourcePackageRecipe, required=True,
134+ title=_("The recipe being built."))
135+
136+ manifest = Attribute(_("The manifest of the built package."))
137+
138+
139+class ISourcePackageBuildSource(Interface):
140+ """A utility of this interface be used to create source package builds."""
141+
142+ def new(sourcepackage, recipe, requester, date_created=None):
143+ """Create an `ISourcePackageBuild`.
144+
145+ :param sourcepackage: The `ISourcePackage` that this is building.
146+ :param recipe: The `ISourcePackageRecipe` that this is building.
147+ :param requester: The `IPerson` who wants to build it.
148+ :param date_created: The date this build record was created. If not
149+ provided, defaults to now.
150+ :return: `ISourcePackageBuild`.
151+ """
152
153=== modified file 'lib/lp/soyuz/interfaces/sourcepackagerecipe.py'
154--- lib/lp/soyuz/interfaces/sourcepackagerecipe.py 2010-01-12 04:22:13 +0000
155+++ lib/lp/soyuz/interfaces/sourcepackagerecipe.py 2010-01-12 04:22:16 +0000
156@@ -14,7 +14,6 @@
157 from lazr.restful.fields import Reference
158
159 from zope.interface import Interface
160-
161 from zope.schema import Datetime, Text, TextLine
162
163 from canonical.launchpad import _
164
165=== added file 'lib/lp/soyuz/model/sourcepackagebuild.py'
166--- lib/lp/soyuz/model/sourcepackagebuild.py 1970-01-01 00:00:00 +0000
167+++ lib/lp/soyuz/model/sourcepackagebuild.py 2010-01-12 04:22:16 +0000
168@@ -0,0 +1,97 @@
169+# Copyright 2010 Canonical Ltd. This software is licensed under the
170+# GNU Affero General Public License version 3 (see the file LICENSE).
171+
172+"""Implementation code for source package builds."""
173+
174+__metaclass__ = type
175+__all__ = [
176+ 'SourcePackageBuild',
177+ ]
178+
179+from canonical.database.constants import UTC_NOW
180+from canonical.database.datetimecol import UtcDateTimeCol
181+from canonical.database.enumcol import EnumCol
182+from canonical.launchpad.interfaces.lpstorm import IMasterStore
183+
184+from storm.locals import Int, Reference, Storm, TimeDelta
185+
186+from zope.interface import classProvides, implements
187+
188+from lp.soyuz.interfaces.build import BuildStatus
189+from lp.soyuz.interfaces.sourcepackagebuild import (
190+ ISourcePackageBuild, ISourcePackageBuildSource)
191+
192+
193+class SourcePackageBuild(Storm):
194+
195+ __storm_table__ = 'SourcePackageBuild'
196+
197+ implements(ISourcePackageBuild)
198+ classProvides(ISourcePackageBuildSource)
199+
200+ id = Int(primary=True)
201+
202+ build_duration = TimeDelta(name='build_duration', default=None)
203+
204+ builder_id = Int(name='builder', allow_none=True)
205+ builder = Reference(builder_id, 'Builder.id')
206+
207+ build_log_id = Int(name='build_log', allow_none=True)
208+ build_log = Reference(build_log_id, 'LibraryFileAlias.id')
209+
210+ build_state = EnumCol(
211+ dbName='build_state', notNull=True, schema=BuildStatus)
212+
213+ date_created = UtcDateTimeCol(notNull=True)
214+ date_built = UtcDateTimeCol(notNull=False)
215+ date_first_dispatched = UtcDateTimeCol(notNull=False)
216+
217+ distroseries_id = Int(name='distroseries', allow_none=True)
218+ distroseries = Reference(distroseries_id, 'DistroSeries.id')
219+
220+ sourcepackagename_id = Int(name='sourcepackagename', allow_none=True)
221+ sourcepackagename = Reference(sourcepackagename_id, 'SourcePackageName.id')
222+
223+ recipe_id = Int(name='recipe', allow_none=False)
224+ recipe = Reference(recipe_id, 'SourcePackageRecipe.id')
225+
226+ requester_id = Int(name='requester', allow_none=False)
227+ requester = Reference(requester_id, 'Person.id')
228+
229+ manifest_id = Int(name='manifest', allow_none=True)
230+ manifest = Reference(manifest_id, '_SourcePackageRecipeData.id')
231+
232+ def __init__(self, distroseries, sourcepackagename, recipe, requester,
233+ date_created=None, date_first_dispatched=None,
234+ date_built=None, manifest=None, builder=None,
235+ build_state=BuildStatus.NEEDSBUILD, build_log=None,
236+ build_duration=None):
237+ """Construct a SourcePackageBuild."""
238+ super(SourcePackageBuild, self).__init__()
239+ self.build_duration = build_duration
240+ self.build_log = build_log
241+ self.builder = builder
242+ self.build_state = build_state
243+ self.date_built = date_built
244+ self.date_created = date_created
245+ self.date_first_dispatched = date_first_dispatched
246+ self.distroseries = distroseries
247+ self.manifest = manifest
248+ self.recipe = recipe
249+ self.requester = requester
250+ self.sourcepackagename = sourcepackagename
251+
252+ @classmethod
253+ def new(cls, sourcepackage, recipe, requester, date_created=None):
254+ """See `ISourcePackageBuildSource`."""
255+ store = IMasterStore(SourcePackageBuild)
256+ if date_created is None:
257+ date_created = UTC_NOW
258+ spbuild = cls(
259+ sourcepackage.distroseries,
260+ sourcepackage.sourcepackagename,
261+ recipe,
262+ requester,
263+ date_created=date_created)
264+ store.add(spbuild)
265+ return spbuild
266
267=== modified file 'lib/lp/soyuz/model/sourcepackagerecipe.py'
268--- lib/lp/soyuz/model/sourcepackagerecipe.py 2010-01-12 04:22:13 +0000
269+++ lib/lp/soyuz/model/sourcepackagerecipe.py 2010-01-12 04:22:16 +0000
270@@ -4,7 +4,9 @@
271 """Implementation of the `SourcePackageRecipe` content type."""
272
273 __metaclass__ = type
274-__all__ = ['SourcePackageRecipe']
275+__all__ = [
276+ 'SourcePackageRecipe',
277+ ]
278
279 from storm.locals import Int, Reference, Storm, Unicode
280
281
282=== added file 'lib/lp/soyuz/tests/test_sourcepackagebuild.py'
283--- lib/lp/soyuz/tests/test_sourcepackagebuild.py 1970-01-01 00:00:00 +0000
284+++ lib/lp/soyuz/tests/test_sourcepackagebuild.py 2010-01-12 04:22:16 +0000
285@@ -0,0 +1,43 @@
286+# Copyright 2010 Canonical Ltd. This software is licensed under the
287+# GNU Affero General Public License version 3 (see the file LICENSE).
288+
289+"""Tests for source package builds."""
290+
291+__metaclass__ = type
292+
293+import unittest
294+
295+import transaction
296+from zope.component import getUtility
297+
298+from canonical.testing.layers import DatabaseFunctionalLayer
299+
300+from lp.soyuz.interfaces.sourcepackagebuild import (
301+ ISourcePackageBuild, ISourcePackageBuildSource)
302+from lp.testing import TestCaseWithFactory
303+
304+
305+class TestSourcePackageBuild(TestCaseWithFactory):
306+ """Test the source package build object."""
307+
308+ layer = DatabaseFunctionalLayer
309+
310+ def makeSourcePackageBuild(self):
311+ return getUtility(ISourcePackageBuildSource).new(
312+ sourcepackage=self.factory.makeSourcePackage(),
313+ recipe=self.factory.makeSourcePackageRecipe(),
314+ requester=self.factory.makePerson())
315+
316+ def test_providesInterface(self):
317+ # SourcePackageBuild provides ISourcePackageBuild.
318+ spb = self.makeSourcePackageBuild()
319+ self.assertProvides(spb, ISourcePackageBuild)
320+
321+ def test_saves_record(self):
322+ spb = self.makeSourcePackageBuild()
323+ transaction.commit()
324+ self.assertProvides(spb, ISourcePackageBuild)
325+
326+
327+def test_suite():
328+ return unittest.TestLoader().loadTestsFromName(__name__)
329
330=== modified file 'lib/lp/soyuz/tests/test_sourcepackagerecipe.py'
331--- lib/lp/soyuz/tests/test_sourcepackagerecipe.py 2010-01-12 04:22:13 +0000
332+++ lib/lp/soyuz/tests/test_sourcepackagerecipe.py 2010-01-12 04:22:16 +0000
333@@ -21,32 +21,11 @@
334 from lp.testing import login_person, TestCaseWithFactory
335
336
337-MINIMAL_RECIPE_TEXT = u'''\
338-# bzr-builder format 0.2 deb-version 1.0
339-%s
340-'''
341-
342 class TestSourcePackageRecipe(TestCaseWithFactory):
343 """Tests for `SourcePackageRecipe` objects."""
344
345 layer = DatabaseFunctionalLayer
346
347- def makeBuilderRecipe(self, *branches):
348- """Make a builder recipe that references `branches`.
349-
350- If no branches are passed, return a recipe text that references an
351- arbitrary branch.
352- """
353- if len(branches) == 0:
354- branches = (self.factory.makeAnyBranch(),)
355- base_branch = branches[0]
356- other_branches = branches[1:]
357- text = MINIMAL_RECIPE_TEXT % base_branch.bzr_identity
358- for i, branch in enumerate(other_branches):
359- text += 'merge dummy-%s %s\n' % (i, branch.bzr_identity)
360- parser = RecipeParser(text)
361- return parser.parse()
362-
363 def makeSourcePackageRecipeFromBuilderRecipe(self, builder_recipe):
364 """Make a SourcePackageRecipe from `builder_recipe` and arbitrary other fields.
365 """
366@@ -68,7 +47,7 @@
367 distroseries = self.factory.makeDistroSeries()
368 sourcepackagename = self.factory.makeSourcePackageName()
369 name = self.factory.getUniqueString(u'recipe-name')
370- builder_recipe = self.makeBuilderRecipe()
371+ builder_recipe = self.factory.makeRecipe()
372 recipe = getUtility(ISourcePackageRecipeSource).new(
373 registrant=registrant, owner=owner, distroseries=distroseries,
374 sourcepackagename=sourcepackagename, name=name,
375@@ -87,14 +66,14 @@
376 def test_recipe_implements_interface(self):
377 # SourcePackageRecipe objects implement ISourcePackageRecipe.
378 recipe = self.makeSourcePackageRecipeFromBuilderRecipe(
379- self.makeBuilderRecipe())
380+ self.factory.makeRecipe())
381 self.assertProvides(recipe, ISourcePackageRecipe)
382
383 def test_branch_links_created(self):
384 # When a recipe is created, we can query it for links to the branch
385 # it references.
386 branch = self.factory.makeAnyBranch()
387- builder_recipe = self.makeBuilderRecipe(branch)
388+ builder_recipe = self.factory.makeRecipe(branch)
389 sp_recipe = self.makeSourcePackageRecipeFromBuilderRecipe(
390 builder_recipe)
391 self.assertEquals([branch], list(sp_recipe.getReferencedBranches()))
392@@ -104,7 +83,7 @@
393 # returns all of them.
394 branch1 = self.factory.makeAnyBranch()
395 branch2 = self.factory.makeAnyBranch()
396- builder_recipe = self.makeBuilderRecipe(branch1, branch2)
397+ builder_recipe = self.factory.makeRecipe(branch1, branch2)
398 sp_recipe = self.makeSourcePackageRecipeFromBuilderRecipe(
399 builder_recipe)
400 self.assertEquals(
401@@ -114,11 +93,11 @@
402 def test_random_user_cant_edit(self):
403 # An arbitrary user can't set attributes.
404 branch1 = self.factory.makeAnyBranch()
405- builder_recipe1 = self.makeBuilderRecipe(branch1)
406+ builder_recipe1 = self.factory.makeRecipe(branch1)
407 sp_recipe = self.makeSourcePackageRecipeFromBuilderRecipe(
408 builder_recipe1)
409 branch2 = self.factory.makeAnyBranch()
410- builder_recipe2 = self.makeBuilderRecipe(branch2)
411+ builder_recipe2 = self.factory.makeRecipe(branch2)
412 login_person(self.factory.makePerson())
413 self.assertRaises(
414 Unauthorized, setattr, sp_recipe, 'builder_recipe',
415@@ -128,11 +107,11 @@
416 # When the recipe_text is replaced, getReferencedBranches returns
417 # (only) the branches referenced by the new recipe.
418 branch1 = self.factory.makeAnyBranch()
419- builder_recipe1 = self.makeBuilderRecipe(branch1)
420+ builder_recipe1 = self.factory.makeRecipe(branch1)
421 sp_recipe = self.makeSourcePackageRecipeFromBuilderRecipe(
422 builder_recipe1)
423 branch2 = self.factory.makeAnyBranch()
424- builder_recipe2 = self.makeBuilderRecipe(branch2)
425+ builder_recipe2 = self.factory.makeRecipe(branch2)
426 login_person(sp_recipe.owner.teamowner)
427 #import pdb; pdb.set_trace()
428 sp_recipe.builder_recipe = builder_recipe2
429@@ -152,7 +131,7 @@
430
431 def test_run_rejected_without_mangling_recipe(self):
432 branch1 = self.factory.makeAnyBranch()
433- builder_recipe1 = self.makeBuilderRecipe(branch1)
434+ builder_recipe1 = self.factory.makeRecipe(branch1)
435 sp_recipe = self.makeSourcePackageRecipeFromBuilderRecipe(
436 builder_recipe1)
437 recipe_text = '''\
438@@ -169,12 +148,13 @@
439 self.assertEquals([branch1], list(sp_recipe.getReferencedBranches()))
440
441 def test_reject_newer_formats(self):
442- builder_recipe = self.makeBuilderRecipe()
443+ builder_recipe = self.factory.makeRecipe()
444 builder_recipe.format = 0.3
445 self.assertRaises(
446 TooNewRecipeFormat,
447 self.makeSourcePackageRecipeFromBuilderRecipe, builder_recipe)
448
449+
450 class TestRecipeBranchRoundTripping(TestCaseWithFactory):
451
452 layer = DatabaseFunctionalLayer
453@@ -364,7 +344,5 @@
454 child_branch, "zam", self.merged_branch.bzr_identity, revspec="2")
455
456
457-
458 def test_suite():
459 return unittest.TestLoader().loadTestsFromName(__name__)
460-
461
462=== modified file 'lib/lp/testing/factory.py'
463--- lib/lp/testing/factory.py 2010-01-05 00:53:47 +0000
464+++ lib/lp/testing/factory.py 2010-01-12 04:22:16 +0000
465@@ -22,6 +22,7 @@
466 from itertools import count
467 from StringIO import StringIO
468 import os.path
469+from textwrap import dedent
470
471 import pytz
472 from storm.store import Store
473@@ -40,6 +41,7 @@
474 from lp.soyuz.adapters.packagelocation import PackageLocation
475 from lp.soyuz.interfaces.publishing import PackagePublishingStatus
476 from lp.soyuz.interfaces.section import ISectionSet
477+from lp.soyuz.interfaces.sourcepackagerecipe import ISourcePackageRecipeSource
478 from canonical.launchpad.database.account import Account
479 from canonical.launchpad.database.emailaddress import EmailAddress
480 from canonical.launchpad.database.message import Message, MessageChunk
481@@ -76,7 +78,7 @@
482 from lp.translations.interfaces.translationgroup import (
483 ITranslationGroupSet)
484 from lp.translations.interfaces.translator import ITranslatorSet
485-from lp.translations.interfaces.translationsperson import ITranslationsPerson
486+from lp.translations.interfaces.translationsperson import ITranslationsPerson
487 from canonical.launchpad.ftests._sqlobject import syncUpdate
488 from lp.services.mail.signedmessage import SignedMessage
489 from lp.services.worlddata.interfaces.country import ICountrySet
490@@ -225,6 +227,12 @@
491 for any other required objects.
492 """
493
494+ # Used for makeBuilderRecipe.
495+ MINIMAL_RECIPE_TEXT = dedent(u'''\
496+ # bzr-builder format 0.2 deb-version 1.0
497+ %s
498+ ''')
499+
500 def makeCopyArchiveLocation(self, distribution=None, owner=None,
501 name=None, enabled=True):
502 """Create and return a new arbitrary location for copy packages."""
503@@ -511,7 +519,8 @@
504 group = self.makeTranslationGroup()
505 if person is None:
506 person = self.makePerson()
507- ITranslationsPerson(person).translations_relicensing_agreement = license
508+ tx_person = ITranslationsPerson(person)
509+ tx_person.translations_relicensing_agreement = license
510 return getUtility(ITranslatorSet).new(group, language, person)
511
512 def makeMilestone(
513@@ -946,7 +955,7 @@
514 author = self.getUniqueString('author')
515 for index in range(count):
516 revision = revision_set.new(
517- revision_id = self.getUniqueString('revision-id'),
518+ revision_id=self.getUniqueString('revision-id'),
519 log_body=self.getUniqueString('log-body'),
520 revision_date=date_generator.next(),
521 revision_author=author,
522@@ -1552,6 +1561,41 @@
523 processor, url, name, title, description, owner, active,
524 virtualized, vm_host)
525
526+ def makeRecipe(self, *branches):
527+ """Make a builder recipe that references `branches`.
528+
529+ If no branches are passed, return a recipe text that references an
530+ arbitrary branch.
531+ """
532+ from bzrlib.plugins.builder.recipe import RecipeParser
533+ if len(branches) == 0:
534+ branches = (self.makeAnyBranch(),)
535+ base_branch = branches[0]
536+ other_branches = branches[1:]
537+ text = self.MINIMAL_RECIPE_TEXT % base_branch.bzr_identity
538+ for i, branch in enumerate(other_branches):
539+ text += 'merge dummy-%s %s\n' % (i, branch.bzr_identity)
540+ parser = RecipeParser(text)
541+ return parser.parse()
542+
543+ def makeSourcePackageRecipe(self, registrant=None, owner=None,
544+ distroseries=None, sourcepackagename=None,
545+ name=None, *branches):
546+ """Make a `SourcePackageRecipe`."""
547+ if registrant is None:
548+ registrant = self.makePerson()
549+ if owner is None:
550+ owner = self.makePerson()
551+ if distroseries is None:
552+ distroseries = self.makeDistroSeries()
553+ if sourcepackagename is None:
554+ sourcepackagename = self.makeSourcePackageName()
555+ if name is None:
556+ name = self.getUniqueString().decode('utf8')
557+ recipe = self.makeRecipe(*branches)
558+ return getUtility(ISourcePackageRecipeSource).new(
559+ registrant, owner, distroseries, sourcepackagename, name, recipe)
560+
561 def makePOTemplate(self, productseries=None, distroseries=None,
562 sourcepackagename=None, owner=None, name=None,
563 translation_domain=None, path=None):
564
565=== modified file 'standard_template.py'
566--- standard_template.py 2010-01-01 04:02:51 +0000
567+++ standard_template.py 2010-01-12 04:22:16 +0000
568@@ -1,7 +1,7 @@
569 # Copyright 2010 Canonical Ltd. This software is licensed under the
570 # GNU Affero General Public License version 3 (see the file LICENSE).
571
572-"""Module docstring goes here."""
573+"""XXX: Module docstring goes here."""
574
575 __metaclass__ = type
576 __all__ = []
577
578=== modified file 'standard_test_template.py'
579--- standard_test_template.py 2010-01-01 04:02:51 +0000
580+++ standard_test_template.py 2010-01-12 04:22:16 +0000
581@@ -1,7 +1,7 @@
582 # Copyright 2010 Canonical Ltd. This software is licensed under the
583 # GNU Affero General Public License version 3 (see the file LICENSE).
584
585-"""Module docstring goes here."""
586+"""XXX: Module docstring goes here."""
587
588 __metaclass__ = type
589
590@@ -12,4 +12,3 @@
591
592 def test_suite():
593 return unittest.TestLoader().loadTestsFromName(__name__)
594-

Subscribers

People subscribed via source and target branches

to status/vote changes: