Merge lp:~abentley/launchpad/daily-builds-api into lp:launchpad

Proposed by Aaron Bentley
Status: Merged
Approved by: Jelmer Vernooij
Approved revision: no longer in the source branch.
Merge reported by: Aaron Bentley
Merged at revision: not available
Proposed branch: lp:~abentley/launchpad/daily-builds-api
Merge into: lp:launchpad
Prerequisite: lp:~abentley/launchpad/daily-builds-ui
Diff against target: 118 lines (+22/-8)
5 files modified
lib/canonical/launchpad/interfaces/_schema_circular_imports.py (+2/-0)
lib/lp/code/interfaces/sourcepackagerecipe.py (+4/-4)
lib/lp/code/model/tests/test_sourcepackagerecipe.py (+6/-1)
lib/lp/registry/interfaces/person.py (+7/-1)
lib/lp/registry/model/person.py (+3/-2)
To merge this branch: bzr merge lp:~abentley/launchpad/daily-builds-api
Reviewer Review Type Date Requested Status
Jelmer Vernooij (community) code Approve
Review via email: mp+26335@code.launchpad.net

Commit message

Implement API for daily builds.

Description of the change

= Summary =
Fix bug #586954: Launchpad should provide daily builds over API

== Proposed fix ==
Expose build_daily and daily_build_archive when creating recipes and as member
variables.

== Pre-implementation notes ==
None

== Implementation details ==
None

== Tests ==
bin/test -v test_sourcepackagerecipe

== Demo and Q/A ==
Write a script using the LP API. Have it create a recipe, specifying
build_daily and daily_build_archive.

Access the build_daily and daily_build_archive member variables.

= Launchpad lint =

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

Linting changed files:
  cronscripts/request_daily_builds.py
  lib/lp/code/model/tests/test_sourcepackagerecipebuild.py
  lib/lp/code/interfaces/sourcepackagerecipebuild.py
  lib/lp/code/configure.zcml
  lib/canonical/config/schema-lazr.conf
  lib/lp/soyuz/model/publishing.py
  lib/lp/code/scripts/tests/test_request_daily_builds.py
  database/schema/security.cfg
  lib/lp/soyuz/doc/buildd-slavescanner.txt
  lib/lp/soyuz/stories/soyuz/xx-build-record.txt
  lib/lp/code/model/tests/test_sourcepackagerecipe.py
  lib/lp/testing/factory.py
  lib/lp/code/model/sourcepackagerecipebuild.py
  lib/lp/code/templates/sourcepackagerecipe-index.pt
  lib/lp/buildmaster/model/buildqueue.py
  lib/lp/soyuz/doc/buildd-dispatching.txt
  lib/lp/registry/interfaces/person.py
  lib/lp/code/browser/sourcepackagerecipe.py
  lib/lp/code/model/sourcepackagerecipe.py
  lib/lp/code/browser/tests/test_sourcepackagerecipe.py
  configs/testrunner/launchpad-lazr.conf
  lib/lp/code/interfaces/sourcepackagerecipe.py
  lib/lp/registry/model/person.py
  lib/lp/soyuz/doc/build.txt
  lib/canonical/launchpad/interfaces/_schema_circular_imports.py

== Pyflakes Doctest notices ==

lib/lp/soyuz/doc/buildd-slavescanner.txt
    689: local variable 'pub_binaries' is assigned to but never used

== Pyflakes notices ==

cronscripts/request_daily_builds.py
    19: 'canonical' imported but unused

== Pylint notices ==

cronscripts/request_daily_builds.py
    19: [W0611] Unused import canonical

lib/lp/code/model/sourcepackagerecipebuild.py
    207: [W0702, SourcePackageRecipeBuild.makeDailyBuilds] No exception type(s) specified

lib/lp/registry/interfaces/person.py
    850: [C0322, IPersonPublic.createRecipe] Operator not preceded by a space
    distroseries=List(value_type=Reference(schema=Interface)),
    ^
    name=TextLine(),
    recipe_text=Text(),
    sourcepackagename=TextLine(),
    daily_build_archive=Reference(schema=Interface),
    build_daily=Bool(),
    )
    @export_factory_operation(Interface, [])
    def createRecipe(name, description, recipe_text, distroseries,
    sourcepackagename, registrant, daily_build_archive=None,
    build_daily=False):
    1414: [C0322, IPersonEditRestricted.addMember] Operator not preceded by a space
    status=copy_field(ITeamMembership['status']),
    ^
    comment=Text(required=False))
    @export_write_operation()
    def addMember(person, reviewer, status=TeamMembershipStatus.APPROVED,
    comment=None, force_team_add=False,
    may_subscribe_to_list=True):
    1455: [C0322, IPersonEditRestricted.acceptInvitationToBeMemberOf] Operator not preceded by a space
    comment=Text())
    ^
    @export_write_operation()
    def acceptInvitationToBeMemberOf(team, comment):
    1467: [C0322, IPersonEditRestricted.declineInvitationToBeMemberOf] Operator not preceded by a space
    comment=Text())
    ^
    @export_write_operation()
    def declineInvitationToBeMemberOf(team, comment):
    1764: [C0322, IPersonSet.newTeam] Operator not preceded by a space
    defaultmembershipperiod='default_membership_period',
    ^
    defaultrenewalperiod='default_renewal_period')
    @operation_parameters(
    subscriptionpolicy=Choice(
    title=_('Subscription policy'), vocabulary=TeamSubscriptionPolicy,
    required=False, default=TeamSubscriptionPolicy.MODERATED))
    @export_factory_operation(
    ITeam, ['name', 'displayname', 'teamdescription',
    'defaultmembershipperiod', 'defaultrenewalperiod'])
    def newTeam(teamowner, name, displayname, teamdescription=None,
    subscriptionpolicy=TeamSubscriptionPolicy.MODERATED,
    defaultmembershipperiod=None, defaultrenewalperiod=None):
    1833: [C0322, IPersonSet.findPerson] Operator not preceded by a space
    created_after=Datetime(
    ^
    title=_("Created after"), required=False),
    created_before=Datetime(
    title=_("Created before"), required=False),
    )
    @operation_returns_collection_of(IPerson)
    @export_read_operation()
    def findPerson(text="", exclude_inactive_accounts=True,
    must_have_email=False,
    created_after=None, created_before=None):

lib/lp/code/interfaces/sourcepackagerecipe.py
    150: [C0322, ISourcePackageRecipe.requestBuild] Operator not preceded by a space
    distroseries=Reference(schema=IDistroSeries),
    ^
    )
    @export_write_operation()
    def requestBuild(archive, distroseries, requester, pocket):

lib/lp/registry/model/person.py
    1265: [W0104, Person.addMember] Statement seems to have no effect

To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

+ :param daily_build_archive: The archive to user for daily builds.
^^ You probably mean s/user/use/ here?

The newline on line 81 of your diff seems unnecessary.

Revision history for this message
Jelmer Vernooij (jelmer) wrote :

See my previous comment, it'd be nice if you could fix those two minor issues before landing.

review: Approve (code)
Revision history for this message
Aaron Bentley (abentley) wrote :

I have already fixed those issues. See diff.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/launchpad/interfaces/_schema_circular_imports.py'
2--- lib/canonical/launchpad/interfaces/_schema_circular_imports.py 2010-06-07 21:03:18 +0000
3+++ lib/canonical/launchpad/interfaces/_schema_circular_imports.py 2010-06-14 20:18:47 +0000
4@@ -198,6 +198,8 @@
5 patch_entry_return_type(IPerson, 'createRecipe', ISourcePackageRecipe)
6 patch_list_parameter_type(IPerson, 'createRecipe', 'distroseries',
7 Reference(schema=IDistroSeries))
8+patch_plain_parameter_type(IPerson, 'createRecipe', 'daily_build_archive',
9+ IArchive)
10
11 patch_entry_return_type(IPerson, 'getRecipe', ISourcePackageRecipe)
12
13
14=== modified file 'lib/lp/code/interfaces/sourcepackagerecipe.py'
15--- lib/lp/code/interfaces/sourcepackagerecipe.py 2010-06-14 20:18:45 +0000
16+++ lib/lp/code/interfaces/sourcepackagerecipe.py 2010-06-14 20:18:47 +0000
17@@ -71,8 +71,8 @@
18
19 id = Int()
20
21- daily_build_archive = Reference(
22- IArchive, title=_("The archive to use for daily builds."))
23+ daily_build_archive = exported(Reference(
24+ IArchive, title=_("The archive to use for daily builds.")))
25
26 date_created = Datetime(required=True, readonly=True)
27 date_last_modified = Datetime(required=True, readonly=True)
28@@ -94,8 +94,8 @@
29 Reference(IDistroSeries), title=_("The distroseries this recipe will"
30 " build a source package for"),
31 readonly=False)
32- build_daily = Bool(
33- title=_("Build daily"))
34+ build_daily = exported(Bool(
35+ title=_("Build daily")))
36
37 name = exported(TextLine(
38 title=_("Name"), required=True,
39
40=== modified file 'lib/lp/code/model/tests/test_sourcepackagerecipe.py'
41--- lib/lp/code/model/tests/test_sourcepackagerecipe.py 2010-06-12 13:34:11 +0000
42+++ lib/lp/code/model/tests/test_sourcepackagerecipe.py 2010-06-14 20:18:47 +0000
43@@ -629,14 +629,17 @@
44 db_distroseries = self.factory.makeDistroSeries()
45 if recipe_text is None:
46 recipe_text = self.makeRecipeText()
47+ db_archive = self.factory.makeArchive(owner=owner, name="recipe-ppa")
48 launchpad = launchpadlib_for('test', user,
49 service_root="http://api.launchpad.dev:8085")
50 login(ANONYMOUS)
51 distroseries = ws_object(launchpad, db_distroseries)
52 ws_owner = ws_object(launchpad, owner)
53+ ws_archive = ws_object(launchpad, db_archive)
54 recipe = ws_owner.createRecipe(
55 name='toaster-1', description='a recipe', recipe_text=recipe_text,
56- distroseries=[distroseries.self_link])
57+ distroseries=[distroseries.self_link], build_daily=True,
58+ daily_build_archive=ws_archive)
59 # at the moment, distroseries is not exposed in the API.
60 transaction.commit()
61 db_recipe = owner.getRecipe(name=u'toaster-1')
62@@ -653,6 +656,8 @@
63 self.assertEqual(team.teamowner.name, recipe.registrant.name)
64 self.assertEqual('toaster-1', recipe.name)
65 self.assertEqual(recipe_text, recipe.recipe_text)
66+ self.assertTrue(recipe.build_daily)
67+ self.assertEqual('recipe-ppa', recipe.daily_build_archive.name)
68
69 def test_recipe_text(self):
70 recipe_text2 = self.makeRecipeText()
71
72=== modified file 'lib/lp/registry/interfaces/person.py'
73--- lib/lp/registry/interfaces/person.py 2010-05-22 01:42:59 +0000
74+++ lib/lp/registry/interfaces/person.py 2010-06-14 20:18:47 +0000
75@@ -850,15 +850,21 @@
76 distroseries=List(value_type=Reference(schema=Interface)),
77 name=TextLine(),
78 recipe_text=Text(),
79+ daily_build_archive=Reference(schema=Interface),
80+ build_daily=Bool(),
81 )
82 @export_factory_operation(Interface, [])
83- def createRecipe(name, description, recipe_text, distroseries, registrant):
84+ def createRecipe(name, description, recipe_text, distroseries,
85+ registrant, daily_build_archive=None, build_daily=False):
86 """Create a SourcePackageRecipe owned by this person.
87
88 :param name: the name to use for referring to the recipe.
89 :param description: A description of the recipe.
90 :param recipe_text: The text of the recipe.
91 :param distroseries: The distroseries to use.
92+ :param registrant: The person who created this recipe.
93+ :param daily_build_archive: The archive to use for daily builds.
94+ :param build_daily: If True, build this recipe daily (if changed).
95 :return: a SourcePackageRecipe.
96 """
97
98
99=== modified file 'lib/lp/registry/model/person.py'
100--- lib/lp/registry/model/person.py 2010-06-02 15:59:47 +0000
101+++ lib/lp/registry/model/person.py 2010-06-14 20:18:47 +0000
102@@ -2263,13 +2263,14 @@
103 return rset
104
105 def createRecipe(self, name, description, recipe_text, distroseries,
106- registrant):
107+ registrant, daily_build_archive=None, build_daily=False):
108 """See `IPerson`."""
109 from lp.code.model.sourcepackagerecipe import SourcePackageRecipe
110 builder_recipe = RecipeParser(recipe_text).parse()
111 spnset = getUtility(ISourcePackageNameSet)
112 return SourcePackageRecipe.new(
113- registrant, self, name, builder_recipe, description, distroseries)
114+ registrant, self, name, builder_recipe, description, distroseries,
115+ daily_build_archive, build_daily)
116
117 def getRecipe(self, name):
118 from lp.code.model.sourcepackagerecipe import SourcePackageRecipe