Merge lp:~michael.nelson/launchpad/distro-series-difference-basic-model into lp:launchpad/db-devel

Proposed by Michael Nelson
Status: Merged
Approved by: Michael Nelson
Approved revision: no longer in the source branch.
Merged at revision: 9724
Proposed branch: lp:~michael.nelson/launchpad/distro-series-difference-basic-model
Merge into: lp:launchpad/db-devel
Prerequisite: lp:~michael.nelson/launchpad/distro-series-difference-schema
Diff against target: 531 lines (+462/-0)
7 files modified
lib/lp/registry/configure.zcml (+11/-0)
lib/lp/registry/enum.py (+57/-0)
lib/lp/registry/exceptions.py (+17/-0)
lib/lp/registry/interfaces/distroseriesdifference.py (+108/-0)
lib/lp/registry/model/distroseriesdifference.py (+117/-0)
lib/lp/registry/tests/test_distroseriesdifference.py (+110/-0)
lib/lp/testing/factory.py (+42/-0)
To merge this branch: bzr merge lp:~michael.nelson/launchpad/distro-series-difference-basic-model
Reviewer Review Type Date Requested Status
Abel Deuring (community) code Approve
Review via email: mp+33885@code.launchpad.net

Commit message

Adds basic model functionality for the DistroSeriesDifference model (for https://dev.launchpad.net/LEP/DerivativeDistributions)

Description of the change

Overview
========

This branch continues on from:

https://code.edge.launchpad.net/~michael.nelson/launchpad/distro-series-difference-schema/+merge/33515

and implements the basic model, enums and tests for representing the distroseriesdifference pages such as:

https://dev.launchpad.net/LEP/DerivativeDistributions?action=AttachFile&do=get&target=derived-series-diffs_5.png

Details
=======

I've set the status and activity_log fields as readonly as a following branch will adds more functionality to the model including security for the status and activity_log fields.

Test with:
bin/test -vvm lp.registry.tests.test_distroseriesdifference

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

Hi Michael,

nice work! I have just two nitpicks:

> === added file 'lib/lp/registry/interfaces/distroseriesdifference.py'
> --- lib/lp/registry/interfaces/distroseriesdifference.py 1970-01-01 00:00:00 +0000
> +++ lib/lp/registry/interfaces/distroseriesdifference.py 2010-08-27 09:31:04 +0000

[...]

> + activity_log = Text(
> + title=_('A log of activity and comments for this difference'),
> + required=False, readonly=True)

s/difference/difference./

> === added file 'lib/lp/registry/tests/test_distroseriesdifference.py'
> --- lib/lp/registry/tests/test_distroseriesdifference.py 1970-01-01 00:00:00 +0000
> +++ lib/lp/registry/tests/test_distroseriesdifference.py 2010-08-27 09:31:04 +0000

[...]

> + def test_new_non_derived_series(self):
> + # A DistroSeriesDifference cannot be created with a non-derived
> + # series.
> + distro_series = self.factory.makeDistroSeries()
> + self.assertRaises(
> + NotADerivedSeriesError,
> + self.factory.makeDistroSeriesDifference,
> + derived_series=distro_series)

I would prefer something like

    distroseriesdifferencesource_factory = getUtility(IDistroSeriesDifferenceSource)
    self.assertRaises(
        NotADerivedSeriesError, distroseriesdifferencesource_factory.new, ...)

This makes it a bit more explicit which method is tested.

review: Approve (code)
Revision history for this message
Michael Nelson (michael.nelson) wrote :

On Fri, Aug 27, 2010 at 1:39 PM, Abel Deuring
<email address hidden> wrote:
> Review: Approve code
> Hi Michael,
>
> nice work! I have just two nitpicks:

Thanks Abel, incremental attached. In addition to the changes you
mentioned, I've switched the activity_log to be a property rather than
a db field due to a schema change.

Cheers,
Michael

1=== modified file 'lib/lp/registry/interfaces/distroseriesdifference.py'
2--- lib/lp/registry/interfaces/distroseriesdifference.py 2010-08-27 09:28:03 +0000
3+++ lib/lp/registry/interfaces/distroseriesdifference.py 2010-08-27 12:29:55 +0000
4@@ -54,7 +54,7 @@
5 "The most recently generated package diff for this difference."))
6
7 activity_log = Text(
8- title=_('A log of activity and comments for this difference'),
9+ title=_('A log of activity and comments for this difference.'),
10 required=False, readonly=True)
11
12 status = Choice(
13
14=== modified file 'lib/lp/registry/model/distroseriesdifference.py'
15--- lib/lp/registry/model/distroseriesdifference.py 2010-08-27 09:02:40 +0000
16+++ lib/lp/registry/model/distroseriesdifference.py 2010-08-27 12:38:58 +0000
17@@ -56,7 +56,6 @@
18 last_package_diff = Reference(
19 last_package_diff_id, 'PackageDiff.id')
20
21- activity_log = Unicode(name='activity_log', allow_none=True)
22 status = DBEnum(name='status', allow_none=False,
23 enum=DistroSeriesDifferenceStatus)
24 difference_type = DBEnum(name='difference_type', allow_none=False,
25@@ -88,6 +87,11 @@
26 """See `IDistroSeriesDifference`."""
27 return self._getLatestSourcePub(for_parent=True)
28
29+ @property
30+ def activity_log(self):
31+ """See `IDistroSeriesDifference`."""
32+ return u""
33+
34 def _getLatestSourcePub(self, for_parent=False):
35 """Helper to keep source_pub/parent_source_pub DRY."""
36 distro_series = self.derived_series
37
38=== modified file 'lib/lp/registry/tests/test_distroseriesdifference.py'
39--- lib/lp/registry/tests/test_distroseriesdifference.py 2010-08-27 09:02:40 +0000
40+++ lib/lp/registry/tests/test_distroseriesdifference.py 2010-08-27 12:37:35 +0000
41@@ -44,10 +44,15 @@
42 # A DistroSeriesDifference cannot be created with a non-derived
43 # series.
44 distro_series = self.factory.makeDistroSeries()
45+ source_package_name = self.factory.makeSourcePackageName('myfoo')
46+ distroseriesdifference_factory = getUtility(
47+ IDistroSeriesDifferenceSource)
48+
49 self.assertRaises(
50- NotADerivedSeriesError,
51- self.factory.makeDistroSeriesDifference,
52- derived_series=distro_series)
53+ NotADerivedSeriesError, distroseriesdifference_factory.new,
54+ distro_series, source_package_name,
55+ DistroSeriesDifferenceType.UNIQUE_TO_DERIVED_SERIES
56+ )
57
58 def test_source_pub(self):
59 # The related source pub is returned for the derived series.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/registry/configure.zcml'
2--- lib/lp/registry/configure.zcml 2010-08-23 03:25:20 +0000
3+++ lib/lp/registry/configure.zcml 2010-08-31 07:47:46 +0000
4@@ -102,6 +102,17 @@
5 date_last_modified
6 person"/>
7 </class>
8+
9+ <!-- DistroSeriesDifference -->
10+ <securedutility
11+ component="lp.registry.model.distroseriesdifference.DistroSeriesDifference"
12+ provides="lp.registry.interfaces.distroseriesdifference.IDistroSeriesDifferenceSource">
13+ <allow interface="lp.registry.interfaces.distroseriesdifference.IDistroSeriesDifferenceSource"/>
14+ </securedutility>
15+ <class
16+ class="lp.registry.model.distroseriesdifference.DistroSeriesDifference">
17+ <allow interface="lp.registry.interfaces.distroseriesdifference.IDistroSeriesDifference"/>
18+ </class>
19 <class
20 class="lp.registry.model.distroseries.DistroSeries">
21 <allow
22
23=== modified file 'lib/lp/registry/enum.py'
24--- lib/lp/registry/enum.py 2010-08-20 20:31:18 +0000
25+++ lib/lp/registry/enum.py 2010-08-31 07:47:46 +0000
26@@ -6,6 +6,8 @@
27 __metaclass__ = type
28 __all__ = [
29 'BugNotificationLevel',
30+ 'DistroSeriesDifferenceStatus',
31+ 'DistroSeriesDifferenceType',
32 ]
33
34 from lazr.enum import (
35@@ -47,3 +49,58 @@
36 notifications about new events in the bugs's discussion, like new
37 comments.
38 """)
39+
40+
41+class DistroSeriesDifferenceStatus(DBEnumeratedType):
42+ """Distribution series difference status.
43+
44+ The status of a package difference between two DistroSeries.
45+ """
46+
47+ NEEDS_ATTENTION = DBItem(1, """
48+ Needs attention
49+
50+ This difference is current and needs attention.
51+ """)
52+
53+ IGNORED = DBItem(2, """
54+ Ignored
55+
56+ This difference is being ignored until a new package is uploaded
57+ or the status is manually updated.
58+ """)
59+
60+ IGNORED_ALWAYS = DBItem(3, """
61+ Ignored always
62+
63+ This difference should always be ignored.
64+ """)
65+
66+ RESOLVED = DBItem(4, """
67+ Resolved
68+
69+ This difference has been resolved and versions are now equal.
70+ """)
71+
72+class DistroSeriesDifferenceType(DBEnumeratedType):
73+ """Distribution series difference type."""
74+
75+ UNIQUE_TO_DERIVED_SERIES = DBItem(1, """
76+ Unique to derived series
77+
78+ This package is present in the derived series but not the parent
79+ series.
80+ """)
81+
82+ MISSING_FROM_DERIVED_SERIES = DBItem(2, """
83+ Missing from derived series
84+
85+ This package is present in the parent series but missing from the
86+ derived series.
87+ """)
88+
89+ DIFFERENT_VERSIONS = DBItem(3, """
90+ Different versions
91+
92+ This package is present in both series with different versions.
93+ """)
94
95=== added file 'lib/lp/registry/exceptions.py'
96--- lib/lp/registry/exceptions.py 1970-01-01 00:00:00 +0000
97+++ lib/lp/registry/exceptions.py 2010-08-31 07:47:46 +0000
98@@ -0,0 +1,17 @@
99+# Copyright 2010 Canonical Ltd. This software is licensed under the
100+# GNU Affero General Public License version 3 (see the file LICENSE).
101+
102+"""Exceptions for the Registry app."""
103+
104+__metaclass__ = type
105+__all__ = [
106+ 'NotADerivedSeriesError',
107+ ]
108+
109+
110+class NotADerivedSeriesError(Exception):
111+ """A distro series difference must be created with a derived series.
112+
113+ This is raised when a DistroSeriesDifference is created with a
114+ non-derived series - that is, a distroseries with a null Parent."""
115+
116
117=== added file 'lib/lp/registry/interfaces/distroseriesdifference.py'
118--- lib/lp/registry/interfaces/distroseriesdifference.py 1970-01-01 00:00:00 +0000
119+++ lib/lp/registry/interfaces/distroseriesdifference.py 2010-08-31 07:47:46 +0000
120@@ -0,0 +1,108 @@
121+# Copyright 2010 Canonical Ltd. This software is licensed under the
122+# GNU Affero General Public License version 3 (see the file LICENSE).
123+
124+"""Interface classes for a difference between two distribution series."""
125+
126+__metaclass__ = type
127+
128+
129+__all__ = [
130+ 'IDistroSeriesDifference',
131+ 'IDistroSeriesDifferenceSource',
132+ ]
133+
134+from lazr.restful.fields import Reference
135+from zope.interface import Interface
136+from zope.schema import (
137+ Choice,
138+ Int,
139+ Text,
140+ )
141+
142+from canonical.launchpad import _
143+from lp.registry.enum import (
144+ DistroSeriesDifferenceStatus,
145+ DistroSeriesDifferenceType,
146+ )
147+from lp.registry.interfaces.distroseries import IDistroSeries
148+from lp.registry.interfaces.sourcepackagename import ISourcePackageName
149+from lp.soyuz.interfaces.packagediff import IPackageDiff
150+from lp.soyuz.interfaces.publishing import ISourcePackagePublishingHistory
151+
152+
153+class IDistroSeriesDifference(Interface):
154+ """An interface for a package difference between two distroseries."""
155+
156+ id = Int(title=_('ID'), required=True, readonly=True)
157+
158+ derived_series = Reference(
159+ IDistroSeries, title=_("Derived series"), required=True,
160+ readonly=True, description=_(
161+ "The distribution series which, together with its parent, "
162+ "identifies the two series with the difference."))
163+
164+ source_package_name = Reference(
165+ ISourcePackageName,
166+ title=_("Source package name"), required=True, readonly=True,
167+ description=_(
168+ "The package with a difference between the derived series "
169+ "and its parent."))
170+
171+ package_diff = Reference(
172+ IPackageDiff, title=_("Package diff"), required=False,
173+ readonly=True, description=_(
174+ "The most recently generated package diff for this difference."))
175+
176+ activity_log = Text(
177+ title=_('A log of activity and comments for this difference.'),
178+ required=False, readonly=True)
179+
180+ status = Choice(
181+ title=_('Distro series difference status.'),
182+ description=_('The current status of this difference.'),
183+ vocabulary=DistroSeriesDifferenceStatus,
184+ required=True, readonly=True)
185+
186+ difference_type = Choice(
187+ title=_('Difference type'),
188+ description=_('The type of difference for this package.'),
189+ vocabulary=DistroSeriesDifferenceType,
190+ required=True, readonly=True)
191+
192+ source_pub = Reference(
193+ ISourcePackagePublishingHistory,
194+ title=_("Derived source pub"), readonly=True,
195+ description=_(
196+ "The most recent published version in the derived series."))
197+
198+ parent_source_pub = Reference(
199+ ISourcePackagePublishingHistory,
200+ title=_("Parent source pub"), readonly=True,
201+ description=_(
202+ "The most recent published version in the parent series."))
203+
204+
205+class IDistroSeriesDifferenceSource(Interface):
206+ """A utility of this interface can be used to create differences."""
207+
208+ def new(derived_series, source_package_name, difference_type,
209+ status=DistroSeriesDifferenceStatus.NEEDS_ATTENTION):
210+ """Create an `IDistroSeriesDifference`.
211+
212+ :param derived_series: The distribution series which was derived
213+ from a parent. If a series without a parent is passed an
214+ exception is raised.
215+ :type derived_series: `IDistroSeries`.
216+ :param source_package_name: A source package name identifying the
217+ package with a difference.
218+ :type source_package_name: `ISourcePackageName`.
219+ :param difference_type: Indicates the type of difference represented
220+ by this record.
221+ :type difference_type: `DistroSeriesDifferenceType`.
222+ :param status: The current status of this difference.
223+ :type status: `DistorSeriesDifferenceStatus`.
224+ :raises NotADerivedSeriesError: When the passed distro series
225+ is not a derived series.
226+ :return: A new `DistroSeriesDifference` object.
227+ """
228+
229
230=== added file 'lib/lp/registry/model/distroseriesdifference.py'
231--- lib/lp/registry/model/distroseriesdifference.py 1970-01-01 00:00:00 +0000
232+++ lib/lp/registry/model/distroseriesdifference.py 2010-08-31 07:47:46 +0000
233@@ -0,0 +1,117 @@
234+# Copyright 2010 Canonical Ltd. This software is licensed under the
235+# GNU Affero General Public License version 3 (see the file LICENSE).
236+
237+"""Database classes for a difference between two distribution series."""
238+
239+__metaclass__ = type
240+
241+__all__ = [
242+ 'DistroSeriesDifference',
243+ ]
244+
245+
246+from storm.locals import (
247+ Int,
248+ Reference,
249+ Storm,
250+ Unicode,
251+ )
252+from zope.interface import (
253+ classProvides,
254+ implements,
255+ )
256+
257+from canonical.database.enumcol import DBEnum
258+from canonical.launchpad.interfaces.lpstorm import IMasterStore
259+from lp.registry.enum import (
260+ DistroSeriesDifferenceStatus,
261+ DistroSeriesDifferenceType,
262+ )
263+from lp.registry.exceptions import NotADerivedSeriesError
264+from lp.registry.interfaces.distroseriesdifference import (
265+ IDistroSeriesDifference,
266+ IDistroSeriesDifferenceSource,
267+ )
268+
269+
270+class DistroSeriesDifference(Storm):
271+ """See `DistroSeriesDifference`."""
272+ implements(IDistroSeriesDifference)
273+ classProvides(IDistroSeriesDifferenceSource)
274+ __storm_table__ = 'DistroSeriesDifference'
275+
276+ id = Int(primary=True)
277+
278+ derived_series_id = Int(name='derived_series', allow_none=False)
279+ derived_series = Reference(
280+ derived_series_id, 'DistroSeries.id')
281+
282+ source_package_name_id = Int(
283+ name='source_package_name', allow_none=False)
284+ source_package_name = Reference(
285+ source_package_name_id, 'SourcePackageName.id')
286+
287+ package_diff_id = Int(
288+ name='package_diff', allow_none=True)
289+ package_diff = Reference(
290+ package_diff_id, 'PackageDiff.id')
291+
292+ status = DBEnum(name='status', allow_none=False,
293+ enum=DistroSeriesDifferenceStatus)
294+ difference_type = DBEnum(name='difference_type', allow_none=False,
295+ enum=DistroSeriesDifferenceType)
296+
297+ @staticmethod
298+ def new(derived_series, source_package_name, difference_type,
299+ status=DistroSeriesDifferenceStatus.NEEDS_ATTENTION):
300+ """See `IDistroSeriesDifferenceSource`."""
301+ if derived_series.parent_series is None:
302+ raise NotADerivedSeriesError()
303+
304+ store = IMasterStore(DistroSeriesDifference)
305+ diff = DistroSeriesDifference()
306+ diff.derived_series = derived_series
307+ diff.source_package_name = source_package_name
308+ diff.status = status
309+ diff.difference_type = difference_type
310+
311+ return store.add(diff)
312+
313+ @property
314+ def source_pub(self):
315+ """See `IDistroSeriesDifference`."""
316+ return self._getLatestSourcePub()
317+
318+ @property
319+ def parent_source_pub(self):
320+ """See `IDistroSeriesDifference`."""
321+ return self._getLatestSourcePub(for_parent=True)
322+
323+ @property
324+ def activity_log(self):
325+ """See `IDistroSeriesDifference`."""
326+ return u""
327+
328+ def _getLatestSourcePub(self, for_parent=False):
329+ """Helper to keep source_pub/parent_source_pub DRY."""
330+ distro_series = self.derived_series
331+ if for_parent:
332+ distro_series = self.derived_series.parent_series
333+
334+ pubs = distro_series.getPublishedSources(
335+ self.source_package_name, include_pending=True)
336+
337+ # The most recent published source is the first one.
338+ if pubs:
339+ return pubs[0]
340+ else:
341+ return None
342+
343+ def _getVersions(self):
344+ """Helper method returning versions string."""
345+ src_pub_ver = parent_src_pub_ver = "-"
346+ if self.source_pub:
347+ src_pub_ver = self.source_pub.source_package_version
348+ if self.parent_source_pub is not None:
349+ parent_src_pub_ver = self.parent_source_pub.source_package_version
350+ return parent_src_pub_ver + "/" + src_pub_ver
351
352=== added file 'lib/lp/registry/tests/test_distroseriesdifference.py'
353--- lib/lp/registry/tests/test_distroseriesdifference.py 1970-01-01 00:00:00 +0000
354+++ lib/lp/registry/tests/test_distroseriesdifference.py 2010-08-31 07:47:46 +0000
355@@ -0,0 +1,110 @@
356+# Copyright 2010 Canonical Ltd. This software is licensed under the
357+# GNU Affero General Public License version 3 (see the file LICENSE).
358+
359+"""Model tests for the DistroSeriesDifference class."""
360+
361+__metaclass__ = type
362+
363+import unittest
364+
365+from storm.store import Store
366+from zope.component import getUtility
367+
368+from canonical.launchpad.webapp.testing import verifyObject
369+from canonical.testing import DatabaseFunctionalLayer
370+from lp.testing import TestCaseWithFactory
371+from lp.registry.enum import DistroSeriesDifferenceType
372+from lp.registry.exceptions import NotADerivedSeriesError
373+from lp.registry.interfaces.distroseriesdifference import (
374+ IDistroSeriesDifference,
375+ IDistroSeriesDifferenceSource,
376+ )
377+from lp.soyuz.interfaces.publishing import PackagePublishingStatus
378+
379+
380+class DistroSeriesDifferenceTestCase(TestCaseWithFactory):
381+
382+ layer = DatabaseFunctionalLayer
383+
384+ def test_implements_interface(self):
385+ # The implementation implements the interface correctly.
386+ ds_diff = self.factory.makeDistroSeriesDifference()
387+ # Flush the store to ensure db constraints are triggered.
388+ Store.of(ds_diff).flush()
389+
390+ verifyObject(IDistroSeriesDifference, ds_diff)
391+
392+ def test_source_implements_interface(self):
393+ # The utility for creating differences implements its interface.
394+ utility = getUtility(IDistroSeriesDifferenceSource)
395+
396+ verifyObject(IDistroSeriesDifferenceSource, utility)
397+
398+ def test_new_non_derived_series(self):
399+ # A DistroSeriesDifference cannot be created with a non-derived
400+ # series.
401+ distro_series = self.factory.makeDistroSeries()
402+ source_package_name = self.factory.makeSourcePackageName('myfoo')
403+ distroseriesdifference_factory = getUtility(
404+ IDistroSeriesDifferenceSource)
405+
406+ self.assertRaises(
407+ NotADerivedSeriesError, distroseriesdifference_factory.new,
408+ distro_series, source_package_name,
409+ DistroSeriesDifferenceType.UNIQUE_TO_DERIVED_SERIES
410+ )
411+
412+ def test_source_pub(self):
413+ # The related source pub is returned for the derived series.
414+ ds_diff = self.factory.makeDistroSeriesDifference(
415+ source_package_name_str="foonew")
416+
417+ self.assertEqual(
418+ 'foonew', ds_diff.source_pub.source_package_name)
419+ self.assertEqual(
420+ ds_diff.derived_series, ds_diff.source_pub.distroseries)
421+
422+ def test_source_pub_gets_latest_pending(self):
423+ # The most recent publication is always returned, even if its pending.
424+ ds_diff = self.factory.makeDistroSeriesDifference(
425+ source_package_name_str="foonew")
426+ pending_pub = self.factory.makeSourcePackagePublishingHistory(
427+ sourcepackagename=ds_diff.source_package_name,
428+ distroseries=ds_diff.derived_series,
429+ status=PackagePublishingStatus.PENDING)
430+
431+ self.assertEqual(pending_pub, ds_diff.source_pub)
432+
433+ def test_source_pub_returns_none(self):
434+ # None is returned when there is no source pub.
435+ ds_diff = self.factory.makeDistroSeriesDifference(
436+ difference_type=(
437+ DistroSeriesDifferenceType.MISSING_FROM_DERIVED_SERIES))
438+
439+ self.assertIs(None, ds_diff.source_pub)
440+
441+ def test_parent_source_pub(self):
442+ # The related source pub for the parent distro series is returned.
443+ ds_diff = self.factory.makeDistroSeriesDifference(
444+ source_package_name_str="foonew")
445+
446+ self.assertEqual(
447+ 'foonew', ds_diff.parent_source_pub.source_package_name)
448+ self.assertEqual(
449+ ds_diff.derived_series.parent_series,
450+ ds_diff.parent_source_pub.distroseries)
451+
452+ def test_paren_source_pub_gets_latest_pending(self):
453+ # The most recent publication is always returned, even if its pending.
454+ ds_diff = self.factory.makeDistroSeriesDifference(
455+ source_package_name_str="foonew")
456+ pending_pub = self.factory.makeSourcePackagePublishingHistory(
457+ sourcepackagename=ds_diff.source_package_name,
458+ distroseries=ds_diff.derived_series.parent_series,
459+ status=PackagePublishingStatus.PENDING)
460+
461+ self.assertEqual(pending_pub, ds_diff.parent_source_pub)
462+
463+
464+def test_suite():
465+ return unittest.TestLoader().loadTestsFromName(__name__)
466
467=== modified file 'lib/lp/testing/factory.py'
468--- lib/lp/testing/factory.py 2010-08-30 16:32:53 +0000
469+++ lib/lp/testing/factory.py 2010-08-31 07:47:46 +0000
470@@ -154,12 +154,16 @@
471 IHWSubmissionDeviceSet,
472 IHWSubmissionSet,
473 )
474+from lp.registry.enum import DistroSeriesDifferenceType
475 from lp.registry.interfaces.distribution import IDistributionSet
476 from lp.registry.interfaces.distributionmirror import (
477 MirrorContent,
478 MirrorSpeed,
479 )
480 from lp.registry.interfaces.distroseries import IDistroSeries
481+from lp.registry.interfaces.distroseriesdifference import (
482+ IDistroSeriesDifferenceSource,
483+ )
484 from lp.registry.interfaces.gpg import (
485 GPGKeyAlgorithm,
486 IGPGKeySet,
487@@ -1817,6 +1821,44 @@
488 # Most people think of distro releases as distro series.
489 makeDistroSeries = makeDistroRelease
490
491+ def makeDistroSeriesDifference(
492+ self, derived_series=None, source_package_name_str=None,
493+ versions=None,
494+ difference_type=DistroSeriesDifferenceType.DIFFERENT_VERSIONS):
495+ """Create a new distro series source package difference."""
496+ if derived_series is None:
497+ parent_series = self.makeDistroSeries()
498+ derived_series = self.makeDistroSeries(
499+ parent_series=parent_series)
500+
501+ if source_package_name_str is None:
502+ source_package_name_str = self.getUniqueString('src-name')
503+
504+ source_package_name = self.getOrMakeSourcePackageName(
505+ source_package_name_str)
506+
507+ if versions is None:
508+ versions = {}
509+
510+ if difference_type is not (
511+ DistroSeriesDifferenceType.MISSING_FROM_DERIVED_SERIES):
512+
513+ source_pub = self.makeSourcePackagePublishingHistory(
514+ distroseries=derived_series,
515+ version=versions.get('derived'),
516+ sourcepackagename=source_package_name)
517+
518+ if difference_type is not (
519+ DistroSeriesDifferenceType.UNIQUE_TO_DERIVED_SERIES):
520+
521+ source_pub = self.makeSourcePackagePublishingHistory(
522+ distroseries=derived_series.parent_series,
523+ version=versions.get('parent'),
524+ sourcepackagename=source_package_name)
525+
526+ return getUtility(IDistroSeriesDifferenceSource).new(
527+ derived_series, source_package_name, difference_type)
528+
529 def makeDistroArchSeries(self, distroseries=None,
530 architecturetag=None, processorfamily=None,
531 official=True, owner=None,

Subscribers

People subscribed via source and target branches

to status/vote changes: