Merge lp:~julian-edwards/launchpad/pcj-requester-bug-810957 into lp:launchpad

Proposed by Julian Edwards
Status: Merged
Approved by: Julian Edwards
Approved revision: no longer in the source branch.
Merged at revision: 13458
Proposed branch: lp:~julian-edwards/launchpad/pcj-requester-bug-810957
Merge into: lp:launchpad
Diff against target: 587 lines (+119/-37)
10 files modified
lib/lp/registry/browser/distroseries.py (+1/-1)
lib/lp/services/job/interfaces/job.py (+7/-0)
lib/lp/services/job/model/job.py (+13/-3)
lib/lp/services/job/tests/test_job.py (+24/-4)
lib/lp/soyuz/browser/archive.py (+2/-1)
lib/lp/soyuz/browser/tests/test_package_copying_mixin.py (+3/-3)
lib/lp/soyuz/interfaces/packagecopyjob.py (+4/-2)
lib/lp/soyuz/model/packagecopyjob.py (+10/-6)
lib/lp/soyuz/tests/test_packagecopyjob.py (+50/-15)
lib/lp/testing/factory.py (+5/-2)
To merge this branch: bzr merge lp:~julian-edwards/launchpad/pcj-requester-bug-810957
Reviewer Review Type Date Requested Status
Abel Deuring (community) code Approve
Review via email: mp+68081@code.launchpad.net

Commit message

[r=adeuring][no-qa] Enable PackageCopyJob to store the Person who requested it.

Description of the change

= Summary =
Enable PackageCopyJob to store the Person who requested it.

== Pre-implementation notes ==
Chatted to Gavin who first wrote PCJ. IJob has a database column for requester
which is not declared in the model code, so we can just use that with some
changes to IJob.

== Implementation details ==
Fix IJob's model implementation, its createMultiple() and PackageCopyJob's
create() and createMutliple().

Note that I've had to add requestor=None to create() even though it's requred,
since I can't be sure of all the places it's called from and they would all need fixing to match the new positional parameters. The assertion matches the one
done for package_version for the same reason.

== Tests ==
bin/test -cvv test_packagecopyjob

== Demo and Q/A ==
n/a until something uses it.

= Launchpad lint =

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/services/job/interfaces/job.py
  lib/lp/soyuz/model/packagecopyjob.py
  lib/lp/soyuz/interfaces/packagecopyjob.py
  lib/lp/testing/factory.py
  lib/lp/soyuz/tests/test_packagecopyjob.py
  lib/lp/services/job/tests/test_job.py
  lib/lp/services/job/model/job.py
  lib/lp/registry/browser/distroseries.py

To post a comment you must log in.
Revision history for this message
Abel Deuring (adeuring) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/registry/browser/distroseries.py'
2--- lib/lp/registry/browser/distroseries.py 2011-07-08 09:06:24 +0000
3+++ lib/lp/registry/browser/distroseries.py 2011-07-18 08:23:36 +0000
4@@ -1161,7 +1161,7 @@
5 )
6 for dsd in self.getUpgrades()]
7 getUtility(IPlainPackageCopyJobSource).createMultiple(
8- target_distroseries, copies,
9+ target_distroseries, copies, self.user,
10 copy_policy=PackageCopyPolicy.MASS_SYNC)
11
12 self.request.response.addInfoNotification(
13
14=== modified file 'lib/lp/services/job/interfaces/job.py'
15--- lib/lp/services/job/interfaces/job.py 2011-07-06 14:02:54 +0000
16+++ lib/lp/services/job/interfaces/job.py 2011-07-18 08:23:36 +0000
17@@ -22,6 +22,7 @@
18 DBEnumeratedType,
19 DBItem,
20 )
21+from lazr.restful.fields import Reference
22 from zope.interface import (
23 Attribute,
24 Interface,
25@@ -35,6 +36,7 @@
26 )
27
28 from canonical.launchpad import _
29+from lp.registry.interfaces.person import IPerson
30
31
32 class SuspendJobException(Exception):
33@@ -109,6 +111,11 @@
34 max_retries = Int(title=_(
35 'The number of retries permitted before this job permanently fails.'))
36
37+ requester = Reference(
38+ IPerson, title=_("The person who requested the job"),
39+ required=False, readonly=True
40+ )
41+
42 is_pending = Bool(
43 title=_("Whether or not this job's status is such that it "
44 "could eventually complete."))
45
46=== modified file 'lib/lp/services/job/model/job.py'
47--- lib/lp/services/job/model/job.py 2011-07-06 14:02:54 +0000
48+++ lib/lp/services/job/model/job.py 2011-07-18 08:23:36 +0000
49@@ -21,6 +21,10 @@
50 Or,
51 Select,
52 )
53+from storm.locals import (
54+ Int,
55+ Reference,
56+ )
57 from zope.interface import implements
58
59 from canonical.database.constants import UTC_NOW
60@@ -73,6 +77,9 @@
61
62 max_retries = IntCol(default=0)
63
64+ requester_id = Int(name='requester', allow_none=True)
65+ requester = Reference(requester_id, 'Person.id')
66+
67 # Mapping of valid target states from a given state.
68 _valid_transitions = {
69 JobStatus.WAITING:
70@@ -108,16 +115,19 @@
71 return self.status in self.PENDING_STATUSES
72
73 @classmethod
74- def createMultiple(self, store, num_jobs):
75+ def createMultiple(self, store, num_jobs, requester=None):
76 """Create multiple `Job`s at once.
77
78 :param store: `Store` to ceate the jobs in.
79 :param num_jobs: Number of `Job`s to create.
80+ :param request: The `IPerson` requesting the jobs.
81 :return: An iterable of `Job.id` values for the new jobs.
82 """
83- job_contents = ["(%s)" % quote(JobStatus.WAITING)] * num_jobs
84+ job_contents = [
85+ "(%s, %s)" % (
86+ quote(JobStatus.WAITING), quote(requester))] * num_jobs
87 result = store.execute("""
88- INSERT INTO Job (status)
89+ INSERT INTO Job (status, requester)
90 VALUES %s
91 RETURNING id
92 """ % ", ".join(job_contents))
93
94=== modified file 'lib/lp/services/job/tests/test_job.py'
95--- lib/lp/services/job/tests/test_job.py 2011-07-06 14:02:54 +0000
96+++ lib/lp/services/job/tests/test_job.py 2011-07-18 08:23:36 +0000
97@@ -22,10 +22,13 @@
98 Job,
99 LeaseHeld,
100 )
101-from lp.testing import TestCase
102-
103-
104-class TestJob(TestCase):
105+from lp.testing import (
106+ TestCase,
107+ TestCaseWithFactory,
108+ )
109+
110+
111+class TestJob(TestCaseWithFactory):
112 """Ensure Job behaves as intended."""
113
114 layer = ZopelessDatabaseLayer
115@@ -39,6 +42,12 @@
116 job = Job()
117 self.assertEqual(job.status, JobStatus.WAITING)
118
119+ def test_stores_requester(self):
120+ job = Job()
121+ random_joe = self.factory.makePerson()
122+ job.requester = random_joe
123+ self.assertEqual(random_joe, job.requester)
124+
125 def test_createMultiple_creates_requested_number_of_jobs(self):
126 job_ids = list(Job.createMultiple(IStore(Job), 3))
127 self.assertEqual(3, len(job_ids))
128@@ -55,6 +64,17 @@
129 job = store.get(Job, Job.createMultiple(store, 1)[0])
130 self.assertEqual(JobStatus.WAITING, job.status)
131
132+ def test_createMultiple_sets_requester(self):
133+ store = IStore(Job)
134+ requester = self.factory.makePerson()
135+ job = store.get(Job, Job.createMultiple(store, 1, requester)[0])
136+ self.assertEqual(requester, job.requester)
137+
138+ def test_createMultiple_defaults_requester_to_None(self):
139+ store = IStore(Job)
140+ job = store.get(Job, Job.createMultiple(store, 1)[0])
141+ self.assertEqual(None, job.requester)
142+
143 def test_start(self):
144 """Job.start should update the object appropriately.
145
146
147=== modified file 'lib/lp/soyuz/browser/archive.py'
148--- lib/lp/soyuz/browser/archive.py 2011-06-29 21:49:36 +0000
149+++ lib/lp/soyuz/browser/archive.py 2011-07-18 08:23:36 +0000
150@@ -1284,7 +1284,8 @@
151 spph.source_package_name, spph.archive, dest_archive, dest_series,
152 dest_pocket, include_binaries=include_binaries,
153 package_version=spph.sourcepackagerelease.version,
154- copy_policy=PackageCopyPolicy.INSECURE)
155+ copy_policy=PackageCopyPolicy.INSECURE,
156+ requester=person)
157
158 return structured("""
159 <p>Requested sync of %s packages.</p>
160
161=== modified file 'lib/lp/soyuz/browser/tests/test_package_copying_mixin.py'
162--- lib/lp/soyuz/browser/tests/test_package_copying_mixin.py 2011-06-02 08:16:03 +0000
163+++ lib/lp/soyuz/browser/tests/test_package_copying_mixin.py 2011-07-18 08:23:36 +0000
164@@ -219,7 +219,7 @@
165 pocket = self.factory.getAnyPocket()
166 copy_asynchronously(
167 [spph], archive, dest_series, pocket, include_binaries=False,
168- check_permissions=False)
169+ check_permissions=False, person=self.factory.makePerson())
170 self.assertEqual(None, find_spph_copy(archive, spph))
171
172 def test_copy_synchronously_lists_packages(self):
173@@ -243,7 +243,7 @@
174 archive = dest_series.distribution.main_archive
175 copy_asynchronously(
176 [spph], archive, dest_series, pocket, include_binaries=False,
177- check_permissions=False)
178+ check_permissions=False, person=self.factory.makePerson())
179 jobs = list(getUtility(IPlainPackageCopyJobSource).getActiveJobs(
180 archive))
181 self.assertEqual(1, len(jobs))
182@@ -263,7 +263,7 @@
183 view.canCopySynchronously = FakeMethod(result=False)
184 view.do_copy(
185 'selected_differences', [spph], archive, dest_series, pocket,
186- False, check_permissions=False)
187+ False, check_permissions=False, person=self.factory.makePerson())
188 jobs = list(getUtility(IPlainPackageCopyJobSource).getActiveJobs(
189 archive))
190 self.assertNotEqual([], jobs)
191
192=== modified file 'lib/lp/soyuz/interfaces/packagecopyjob.py'
193--- lib/lp/soyuz/interfaces/packagecopyjob.py 2011-07-12 14:23:40 +0000
194+++ lib/lp/soyuz/interfaces/packagecopyjob.py 2011-07-18 08:23:36 +0000
195@@ -126,7 +126,7 @@
196 def create(package_name, source_archive,
197 target_archive, target_distroseries, target_pocket,
198 include_binaries=False, package_version=None,
199- copy_policy=PackageCopyPolicy.INSECURE):
200+ copy_policy=PackageCopyPolicy.INSECURE, requester=None):
201 """Create a new `IPlainPackageCopyJob`.
202
203 :param package_name: The name of the source package to copy.
204@@ -141,9 +141,10 @@
205 :param package_version: The version string for the package version
206 that is to be copied.
207 :param copy_policy: Applicable `PackageCopyPolicy`.
208+ :param requester: The user requesting the copy.
209 """
210
211- def createMultiple(target_distroseries, copy_tasks,
212+ def createMultiple(target_distroseries, copy_tasks, requester,
213 copy_policy=PackageCopyPolicy.INSECURE,
214 include_binaries=False):
215 """Create multiple new `IPlainPackageCopyJob`s at once.
216@@ -153,6 +154,7 @@
217 :param copy_tasks: A list of tuples describing the copies to be
218 performed: (package name, package version, source archive,
219 target archive, target pocket).
220+ :param requester: The user requesting the copy.
221 :param copy_policy: Applicable `PackageCopyPolicy`.
222 :param include_binaries: As in `do_copy`.
223 :return: An iterable of `PackageCopyJob` ids.
224
225=== modified file 'lib/lp/soyuz/model/packagecopyjob.py'
226--- lib/lp/soyuz/model/packagecopyjob.py 2011-07-08 09:06:24 +0000
227+++ lib/lp/soyuz/model/packagecopyjob.py 2011-07-18 08:23:36 +0000
228@@ -131,9 +131,11 @@
229 return cls.wrap(IStore(PackageCopyJob).get(PackageCopyJob, pcj_id))
230
231 def __init__(self, source_archive, target_archive, target_distroseries,
232- job_type, metadata, package_name=None, copy_policy=None):
233+ job_type, metadata, requester, package_name=None,
234+ copy_policy=None):
235 super(PackageCopyJob, self).__init__()
236 self.job = Job()
237+ self.job.requester = requester
238 self.job_type = job_type
239 self.source_archive = source_archive
240 self.target_archive = target_archive
241@@ -250,9 +252,10 @@
242 def create(cls, package_name, source_archive,
243 target_archive, target_distroseries, target_pocket,
244 include_binaries=False, package_version=None,
245- copy_policy=PackageCopyPolicy.INSECURE):
246+ copy_policy=PackageCopyPolicy.INSECURE, requester=None):
247 """See `IPlainPackageCopyJobSource`."""
248 assert package_version is not None, "No package version specified."
249+ assert requester is not None, "No requester specified."
250 metadata = cls._makeMetadata(
251 target_pocket, package_version, include_binaries)
252 job = PackageCopyJob(
253@@ -262,7 +265,8 @@
254 target_distroseries=target_distroseries,
255 package_name=package_name,
256 copy_policy=copy_policy,
257- metadata=metadata)
258+ metadata=metadata,
259+ requester=requester)
260 IMasterStore(PackageCopyJob).add(job)
261 return cls(job)
262
263@@ -292,12 +296,12 @@
264 return format_string % sqlvalues(*data)
265
266 @classmethod
267- def createMultiple(cls, target_distroseries, copy_tasks,
268+ def createMultiple(cls, target_distroseries, copy_tasks, requester,
269 copy_policy=PackageCopyPolicy.INSECURE,
270 include_binaries=False):
271 """See `IPlainPackageCopyJobSource`."""
272 store = IMasterStore(Job)
273- job_ids = Job.createMultiple(store, len(copy_tasks))
274+ job_ids = Job.createMultiple(store, len(copy_tasks), requester)
275 job_contents = [
276 cls._composeJobInsertionTuple(
277 target_distroseries, copy_policy, include_binaries, job_id,
278@@ -484,7 +488,7 @@
279 if pu is not None:
280 # A PackageUpload will only exist if the copy job had to be
281 # held in the queue because of policy/ancestry checks. If one
282- # does exist we need to make sure
283+ # does exist we need to make sure.
284 pu.setDone()
285
286 def abort(self):
287
288=== modified file 'lib/lp/soyuz/tests/test_packagecopyjob.py'
289--- lib/lp/soyuz/tests/test_packagecopyjob.py 2011-07-12 14:52:52 +0000
290+++ lib/lp/soyuz/tests/test_packagecopyjob.py 2011-07-18 08:23:36 +0000
291@@ -92,9 +92,10 @@
292 target_archive = dsd.derived_series.main_archive
293 target_distroseries = dsd.derived_series
294 target_pocket = self.factory.getAnyPocket()
295+ requester = self.factory.makePerson()
296 return getUtility(IPlainPackageCopyJobSource).create(
297 dsd.source_package_name.name, source_archive, target_archive,
298- target_distroseries, target_pocket,
299+ target_distroseries, target_pocket, requester=requester,
300 package_version=dsd.parent_source_version, **kwargs)
301
302 def runJob(self, job):
303@@ -122,13 +123,15 @@
304 distroseries = self.factory.makeDistroSeries()
305 archive1 = self.factory.makeArchive(distroseries.distribution)
306 archive2 = self.factory.makeArchive(distroseries.distribution)
307+ requester = self.factory.makePerson()
308 source = getUtility(IPlainPackageCopyJobSource)
309 job = source.create(
310 package_name="foo", source_archive=archive1,
311 target_archive=archive2, target_distroseries=distroseries,
312 target_pocket=PackagePublishingPocket.RELEASE,
313 package_version="1.0-1", include_binaries=False,
314- copy_policy=PackageCopyPolicy.MASS_SYNC)
315+ copy_policy=PackageCopyPolicy.MASS_SYNC,
316+ requester=requester)
317 self.assertProvides(job, IPackageCopyJob)
318 self.assertEquals(archive1.id, job.source_archive_id)
319 self.assertEquals(archive1, job.source_archive)
320@@ -140,6 +143,7 @@
321 self.assertEqual("1.0-1", job.package_version)
322 self.assertEquals(False, job.include_binaries)
323 self.assertEquals(PackageCopyPolicy.MASS_SYNC, job.copy_policy)
324+ self.assertEqual(requester, job.requester)
325
326 def test_createMultiple_creates_one_job_per_copy(self):
327 mother = self.factory.makeDistroSeriesParent()
328@@ -148,6 +152,7 @@
329 derived_series=derived_series)
330 mother_package = self.factory.makeSourcePackageName()
331 father_package = self.factory.makeSourcePackageName()
332+ requester = self.factory.makePerson()
333 job_source = getUtility(IPlainPackageCopyJobSource)
334 copy_tasks = [
335 (
336@@ -166,7 +171,8 @@
337 ),
338 ]
339 job_ids = list(
340- job_source.createMultiple(mother.derived_series, copy_tasks))
341+ job_source.createMultiple(mother.derived_series, copy_tasks,
342+ requester))
343 jobs = list(job_source.getActiveJobs(derived_series.main_archive))
344 self.assertContentEqual(job_ids, [job.id for job in jobs])
345 self.assertEqual(len(copy_tasks), len(set([job.job for job in jobs])))
346@@ -185,17 +191,24 @@
347 for job in jobs]
348 self.assertEqual(copy_tasks, requested_copies)
349
350+ # The passed requester should be the same on all jobs.
351+ actual_requester = set(job.requester for job in jobs)
352+ self.assertEqual(1, len(actual_requester))
353+ self.assertEqual(requester, jobs[0].requester)
354+
355 def test_getActiveJobs(self):
356 # getActiveJobs() can retrieve all active jobs for an archive.
357 distroseries = self.factory.makeDistroSeries()
358 archive1 = self.factory.makeArchive(distroseries.distribution)
359 archive2 = self.factory.makeArchive(distroseries.distribution)
360 source = getUtility(IPlainPackageCopyJobSource)
361+ requester = self.factory.makePerson()
362 job = source.create(
363 package_name="foo", source_archive=archive1,
364 target_archive=archive2, target_distroseries=distroseries,
365 target_pocket=PackagePublishingPocket.RELEASE,
366- package_version="1.0-1", include_binaries=False)
367+ package_version="1.0-1", include_binaries=False,
368+ requester=requester)
369 self.assertContentEqual([job], source.getActiveJobs(archive2))
370
371 def test_getActiveJobs_gets_oldest_first(self):
372@@ -249,12 +262,14 @@
373 distroseries = self.factory.makeDistroSeries()
374 archive1 = self.factory.makeArchive(distroseries.distribution)
375 archive2 = self.factory.makeArchive(distroseries.distribution)
376+ requester = self.factory.makePerson()
377 job_source = getUtility(IPlainPackageCopyJobSource)
378 job = job_source.create(
379 package_name="foo", source_archive=archive1,
380 target_archive=archive2, target_distroseries=distroseries,
381 target_pocket=PackagePublishingPocket.RELEASE,
382- package_version="1.0-1", include_binaries=False)
383+ package_version="1.0-1", include_binaries=False,
384+ requester=requester)
385 naked_job = removeSecurityProxy(job)
386 naked_job.reportFailure = FakeMethod()
387
388@@ -268,12 +283,14 @@
389 package = self.factory.makeSourcePackageName()
390 archive1 = self.factory.makeArchive(distroseries.distribution)
391 archive2 = self.factory.makeArchive(distroseries.distribution)
392+ requester = self.factory.makePerson()
393 source = getUtility(IPlainPackageCopyJobSource)
394 job = source.create(
395 package_name=package.name, source_archive=archive1,
396 target_archive=archive2, target_distroseries=distroseries,
397 target_pocket=PackagePublishingPocket.UPDATES,
398- include_binaries=False, package_version='1.0')
399+ include_binaries=False, package_version='1.0',
400+ requester=requester)
401
402 naked_job = removeSecurityProxy(job)
403 naked_job.reportFailure = FakeMethod()
404@@ -315,12 +332,14 @@
405 archive=target_archive)
406
407 source = getUtility(IPlainPackageCopyJobSource)
408+ requester = self.factory.makePerson()
409 job = source.create(
410 package_name="libc",
411 source_archive=breezy_archive, target_archive=target_archive,
412 target_distroseries=target_series,
413 target_pocket=PackagePublishingPocket.RELEASE,
414- package_version="2.8-1", include_binaries=False)
415+ package_version="2.8-1", include_binaries=False,
416+ requester=requester)
417 self.assertEqual("libc", job.package_name)
418 self.assertEqual("2.8-1", job.package_version)
419
420@@ -348,12 +367,14 @@
421 distroseries = self.factory.makeDistroSeries()
422 archive1 = self.factory.makeArchive(distroseries.distribution)
423 archive2 = self.factory.makeArchive(distroseries.distribution)
424+ requester = self.factory.makePerson()
425 source = getUtility(IPlainPackageCopyJobSource)
426 job = source.create(
427 package_name="foo", source_archive=archive1,
428 target_archive=archive2, target_distroseries=distroseries,
429 target_pocket=PackagePublishingPocket.RELEASE,
430- package_version="1.0-1", include_binaries=False)
431+ package_version="1.0-1", include_binaries=False,
432+ requester=requester)
433 oops_vars = job.getOopsVars()
434 naked_job = removeSecurityProxy(job)
435 self.assertIn(
436@@ -374,6 +395,7 @@
437 distroseries = publisher.breezy_autotest
438 archive1 = self.factory.makeArchive(distroseries.distribution)
439 archive2 = self.factory.makeArchive(distroseries.distribution)
440+ requester = self.factory.makePerson()
441 publisher.getPubSource(
442 distroseries=distroseries, sourcename="libc",
443 version="2.8-1", status=PackagePublishingStatus.PUBLISHED,
444@@ -382,7 +404,8 @@
445 package_name="libc", source_archive=archive1,
446 target_archive=archive2, target_distroseries=distroseries,
447 target_pocket=PackagePublishingPocket.RELEASE,
448- package_version="2.8-1", include_binaries=False)
449+ package_version="2.8-1", include_binaries=False,
450+ requester=requester)
451 transaction.commit()
452
453 out, err, exit_code = run_script(
454@@ -401,12 +424,14 @@
455 distroseries = self.factory.makeDistroSeries()
456 archive1 = self.factory.makeArchive(distroseries.distribution)
457 archive2 = self.factory.makeArchive(distroseries.distribution)
458+ requester = self.factory.makePerson()
459 source = getUtility(IPlainPackageCopyJobSource)
460 job = source.create(
461 package_name="foo", source_archive=archive1,
462 target_archive=archive2, target_distroseries=distroseries,
463 target_pocket=PackagePublishingPocket.RELEASE,
464- package_version="1.0-1", include_binaries=True)
465+ package_version="1.0-1", include_binaries=True,
466+ requester=requester)
467 self.assertEqual(
468 ("<PlainPackageCopyJob to copy package foo from "
469 "{distroseries.distribution.name}/{archive1.name} to "
470@@ -519,6 +544,7 @@
471 # target_archive.
472
473 source = getUtility(IPlainPackageCopyJobSource)
474+ requester = self.factory.makePerson()
475 job = source.create(
476 package_name="libc",
477 package_version="2.8-1",
478@@ -526,7 +552,8 @@
479 target_archive=target_archive,
480 target_distroseries=distroseries,
481 target_pocket=PackagePublishingPocket.RELEASE,
482- include_binaries=False)
483+ include_binaries=False,
484+ requester=requester)
485
486 self.runJob(job)
487
488@@ -556,6 +583,7 @@
489 # Now, run the copy job, which should raise an error because
490 # there's no ancestry.
491 source = getUtility(IPlainPackageCopyJobSource)
492+ requester = self.factory.makePerson()
493 job = source.create(
494 package_name="copyme",
495 package_version="2.8-1",
496@@ -563,7 +591,8 @@
497 target_archive=target_archive,
498 target_distroseries=distroseries,
499 target_pocket=PackagePublishingPocket.RELEASE,
500- include_binaries=False)
501+ include_binaries=False,
502+ requester=requester)
503
504 self.assertRaises(SuspendJobException, self.runJob, job)
505 # Simulate the job runner suspending after getting a
506@@ -619,6 +648,7 @@
507 # Now, run the copy job.
508
509 source = getUtility(IPlainPackageCopyJobSource)
510+ requester = self.factory.makePerson()
511 job = source.create(
512 package_name="copyme",
513 package_version="2.8-1",
514@@ -626,7 +656,8 @@
515 target_archive=target_archive,
516 target_distroseries=distroseries,
517 target_pocket=PackagePublishingPocket.RELEASE,
518- include_binaries=False)
519+ include_binaries=False,
520+ requester=requester)
521
522 # The job should be suspended and there's a PackageUpload with
523 # its package_copy_job set.
524@@ -672,6 +703,7 @@
525
526 # Now, run the copy job.
527 source = getUtility(IPlainPackageCopyJobSource)
528+ requester = self.factory.makePerson()
529 job = source.create(
530 package_name="copyme",
531 package_version="2.8-1",
532@@ -679,7 +711,8 @@
533 target_archive=target_archive,
534 target_distroseries=distroseries,
535 target_pocket=PackagePublishingPocket.RELEASE,
536- include_binaries=False)
537+ include_binaries=False,
538+ requester=requester)
539
540 # The job should be suspended and there's a PackageUpload with
541 # its package_copy_job set in the UNAPPROVED queue.
542@@ -715,6 +748,7 @@
543 archive=source_archive)
544
545 source = getUtility(IPlainPackageCopyJobSource)
546+ requester = self.factory.makePerson()
547 job = source.create(
548 package_name="copyme",
549 package_version="2.8-1",
550@@ -722,7 +756,8 @@
551 target_archive=target_archive,
552 target_distroseries=distroseries,
553 target_pocket=PackagePublishingPocket.RELEASE,
554- include_binaries=False)
555+ include_binaries=False,
556+ requester=requester)
557
558 # Run the job so it gains a PackageUpload.
559 self.assertRaises(SuspendJobException, self.runJob, job)
560
561=== modified file 'lib/lp/testing/factory.py'
562--- lib/lp/testing/factory.py 2011-07-13 20:55:34 +0000
563+++ lib/lp/testing/factory.py 2011-07-18 08:23:36 +0000
564@@ -4165,7 +4165,8 @@
565
566 def makePlainPackageCopyJob(
567 self, package_name=None, package_version=None, source_archive=None,
568- target_archive=None, target_distroseries=None, target_pocket=None):
569+ target_archive=None, target_distroseries=None, target_pocket=None,
570+ requester=None):
571 """Create a new `PlainPackageCopyJob`."""
572 if package_name is None and package_version is None:
573 package_name = self.makeSourcePackageName().name
574@@ -4178,10 +4179,12 @@
575 target_distroseries = self.makeDistroSeries()
576 if target_pocket is None:
577 target_pocket = self.getAnyPocket()
578+ if requester is None:
579+ requester = self.makePerson()
580 return getUtility(IPlainPackageCopyJobSource).create(
581 package_name, source_archive, target_archive,
582 target_distroseries, target_pocket,
583- package_version=package_version)
584+ package_version=package_version, requester=requester)
585
586
587 # Some factory methods return simple Python types. We don't add