Merge lp:~jtv/launchpad/bug-884649-branch-1 into lp:launchpad

Proposed by Jeroen T. Vermeulen
Status: Merged
Approved by: Julian Edwards
Approved revision: no longer in the source branch.
Merged at revision: 14232
Proposed branch: lp:~jtv/launchpad/bug-884649-branch-1
Merge into: lp:launchpad
Diff against target: 502 lines (+276/-89)
3 files modified
lib/lp/archivepublisher/domination.py (+104/-75)
lib/lp/archivepublisher/tests/test_dominator.py (+170/-2)
lib/lp/soyuz/model/publishing.py (+2/-12)
To merge this branch: bzr merge lp:~jtv/launchpad/bug-884649-branch-1
Reviewer Review Type Date Requested Status
Julian Edwards (community) Approve
Review via email: mp+80988@code.launchpad.net

Commit message

[r=julian-edwards][bug=884649] Part 1 of Dominator optimization.

Description of the change

= Summary =

The Dominator is having performance problems, now that we've introduced binary double-domination. (It's probably not as exciting as it sounds, but it'll fix a lot of uninstallable packages.)

Getting dominator performance under control needs some careful but radical internal reorganizations.

== Proposed fix ==

Prepare for some of the coming changes (yes, there's a bug-884649-branch-2 in the works) and, while we're at it, cut some dead wood out of the main query involved in the added functionality.

That main query is executed for almost any binary package publication at some point in its lifetime. The dead wood is two tables being joined through SourcePackageRelease, when all that's needed is an equijoin on the foreign keys to SourcePackageRelease. The table itself isn't needed in the join; this was easy to miss given the complexity of the search.

== Pre-implementation notes ==

Discussed extensively with Julian. see bug 884649 for notes.

== Implementation details ==

You'll see two complex queries extracted into new methods, so as to keep the higher-level logic clearer and more isolated. This serves another purpose: the same logic was constructed once and then invoked twice, from a little locally-defined function that I need to break up. Had to find other ways to minimize repetition.

I'm also adding some code duplication: two poorly-related conditions in an if/elif chain that have the same, very simple body. It was clearer as an intermediate step to separate those into separate elifs. But rest assured: my next branch hoists that logic out of there and into a dedicated policy function (which is used only where needed, thus saving time). So the duplication is only there so that the complexity can be more easily removed.

== Tests ==

I ran them all, actually. But anything with “dominator” or “domination” or “dominate” in the name is particularly likely to be relevant:
{{{
./bin/test -vvc -t dominat
}}}

== Demo and Q/A ==

The dominator should still work, and probably be just slightly faster. It's hard to benchmark accurately though, since every run will face different sets of active publications. We could just run it twice on a second server and time the second run; the second run won't be as representative because it has no changes to make, but at least it will run in predictable time.

= Launchpad lint =

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/archivepublisher/domination.py
  lib/lp/soyuz/model/publishing.py

To post a comment you must log in.
Revision history for this message
Julian Edwards (julian-edwards) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/archivepublisher/domination.py'
--- lib/lp/archivepublisher/domination.py 2011-10-18 11:56:09 +0000
+++ lib/lp/archivepublisher/domination.py 2011-11-02 10:31:27 +0000
@@ -53,6 +53,7 @@
53__all__ = ['Dominator']53__all__ = ['Dominator']
5454
55from datetime import timedelta55from datetime import timedelta
56from operator import itemgetter
5657
57import apt_pkg58import apt_pkg
58from storm.expr import (59from storm.expr import (
@@ -67,6 +68,9 @@
67 flush_database_updates,68 flush_database_updates,
68 sqlvalues,69 sqlvalues,
69 )70 )
71from canonical.launchpad.components.decoratedresultset import (
72 DecoratedResultSet,
73 )
70from canonical.launchpad.interfaces.lpstorm import IStore74from canonical.launchpad.interfaces.lpstorm import IStore
71from lp.registry.model.sourcepackagename import SourcePackageName75from lp.registry.model.sourcepackagename import SourcePackageName
72from lp.services.database.bulk import load_related76from lp.services.database.bulk import load_related
@@ -258,7 +262,8 @@
258 # Go through publications from latest version to oldest. This262 # Go through publications from latest version to oldest. This
259 # makes it easy to figure out which release superseded which:263 # makes it easy to figure out which release superseded which:
260 # the dominant is always the oldest live release that is newer264 # the dominant is always the oldest live release that is newer
261 # than the one being superseded.265 # than the one being superseded. In this loop, that means the
266 # dominant is always the last live publication we saw.
262 publications = sorted(267 publications = sorted(
263 publications, cmp=generalization.compare, reverse=True)268 publications, cmp=generalization.compare, reverse=True)
264269
@@ -272,25 +277,29 @@
272 for pub in publications:277 for pub in publications:
273 version = generalization.getPackageVersion(pub)278 version = generalization.getPackageVersion(pub)
274 # There should never be two published releases with the same279 # There should never be two published releases with the same
275 # version. So this comparison is really a string280 # version. So it doesn't matter whether this comparison is
276 # comparison, not a version comparison: if the versions are281 # really a string comparison or a version comparison: if the
277 # equal by either measure, they're from the same release.282 # versions are equal by either measure, they're from the same
278 if dominant_version is not None and version == dominant_version:283 # release.
284 if version == dominant_version:
279 # This publication is for a live version, but has been285 # This publication is for a live version, but has been
280 # superseded by a newer publication of the same version.286 # superseded by a newer publication of the same version.
281 # Supersede it.287 # Supersede it.
282 pub.supersede(current_dominant, logger=self.logger)288 pub.supersede(current_dominant, logger=self.logger)
283 self.logger.debug2(289 self.logger.debug2(
284 "Superseding older publication for version %s.", version)290 "Superseding older publication for version %s.", version)
285 elif (version in live_versions or291 elif version in live_versions:
286 (not generalization.is_source and
287 not self._checkArchIndep(pub))):
288 # This publication stays active; if any publications292 # This publication stays active; if any publications
289 # that follow right after this are to be superseded,293 # that follow right after this are to be superseded,
290 # this is the release that they are superseded by.294 # this is the release that they are superseded by.
291 current_dominant = pub295 current_dominant = pub
292 dominant_version = version296 dominant_version = version
293 self.logger.debug2("Keeping version %s.", version)297 self.logger.debug2("Keeping version %s.", version)
298 elif not (generalization.is_source or self._checkArchIndep(pub)):
299 # As a special case, we keep this version live as well.
300 current_dominant = pub
301 dominant_version = version
302 self.logger.debug2("Keeping version %s.", version)
294 elif current_dominant is None:303 elif current_dominant is None:
295 # This publication is no longer live, but there is no304 # This publication is no longer live, but there is no
296 # newer version to supersede it either. Therefore it305 # newer version to supersede it either. Therefore it
@@ -442,72 +451,81 @@
442 # always equals to "scheduleddeletiondate - quarantine".451 # always equals to "scheduleddeletiondate - quarantine".
443 pub_record.datemadepending = UTC_NOW452 pub_record.datemadepending = UTC_NOW
444453
454 def findBinariesForDomination(self, distroarchseries, pocket):
455 """Find binary publications that need dominating.
456
457 This is only for traditional domination, where the latest published
458 publication is always kept published. It will ignore publications
459 that have no other publications competing for the same binary package.
460 """
461 # Avoid circular imports.
462 from lp.soyuz.model.publishing import BinaryPackagePublishingHistory
463
464 bpph_location_clauses = [
465 BinaryPackagePublishingHistory.status ==
466 PackagePublishingStatus.PUBLISHED,
467 BinaryPackagePublishingHistory.distroarchseries ==
468 distroarchseries,
469 BinaryPackagePublishingHistory.archive == self.archive,
470 BinaryPackagePublishingHistory.pocket == pocket,
471 ]
472 candidate_binary_names = Select(
473 BinaryPackageName.id,
474 And(
475 BinaryPackageRelease.binarypackagenameID ==
476 BinaryPackageName.id,
477 BinaryPackagePublishingHistory.binarypackagereleaseID ==
478 BinaryPackageRelease.id,
479 bpph_location_clauses,
480 ),
481 group_by=BinaryPackageName.id,
482 having=Count(BinaryPackagePublishingHistory.id) > 1)
483 main_clauses = [
484 BinaryPackageRelease.id ==
485 BinaryPackagePublishingHistory.binarypackagereleaseID,
486 BinaryPackageRelease.binarypackagenameID.is_in(
487 candidate_binary_names),
488 BinaryPackageRelease.binpackageformat !=
489 BinaryPackageFormat.DDEB,
490 ]
491 main_clauses.extend(bpph_location_clauses)
492
493 store = IStore(BinaryPackagePublishingHistory)
494 return store.find(BinaryPackagePublishingHistory, *main_clauses)
495
445 def dominateBinaries(self, distroseries, pocket):496 def dominateBinaries(self, distroseries, pocket):
446 """Perform domination on binary package publications.497 """Perform domination on binary package publications.
447498
448 Dominates binaries, restricted to `distroseries`, `pocket`, and499 Dominates binaries, restricted to `distroseries`, `pocket`, and
449 `self.archive`.500 `self.archive`.
450 """501 """
451 # Avoid circular imports.
452 from lp.soyuz.model.publishing import BinaryPackagePublishingHistory
453
454 generalization = GeneralizedPublication(is_source=False)502 generalization = GeneralizedPublication(is_source=False)
455503
456 for distroarchseries in distroseries.architectures:504 for distroarchseries in distroseries.architectures:
457 self.logger.info(505 self.logger.info(
458 "Performing domination across %s/%s (%s)",506 "Performing domination across %s/%s (%s)",
459 distroseries.name, pocket.title,507 distroarchseries.distroseries.name, pocket.title,
460 distroarchseries.architecturetag)508 distroarchseries.architecturetag)
461509
462 bpph_location_clauses = [510 self.logger.info("Finding binaries...")
463 BinaryPackagePublishingHistory.status ==511 bins = self.findBinariesForDomination(distroarchseries, pocket)
464 PackagePublishingStatus.PUBLISHED,512 sorted_packages = self._sortPackages(bins, generalization)
465 BinaryPackagePublishingHistory.distroarchseries ==513 self.logger.info("Dominating binaries...")
466 distroarchseries,514 self._dominatePublications(sorted_packages, generalization)
467 BinaryPackagePublishingHistory.archive == self.archive,515
468 BinaryPackagePublishingHistory.pocket == pocket,516 # We need to make a second pass to cover the cases where:
469 ]517 # * arch-specific binaries were not all dominated before arch-all
470 candidate_binary_names = Select(518 # ones that depend on them
471 BinaryPackageName.id,519 # * An arch-all turned into an arch-specific, or vice-versa
472 And(520 # * A package is completely schizophrenic and changes all of
473 BinaryPackageRelease.binarypackagenameID ==521 # its binaries between arch-all and arch-any (apparently
474 BinaryPackageName.id,522 # occurs sometimes!)
475 BinaryPackagePublishingHistory.binarypackagereleaseID ==523 for distroarchseries in distroseries.architectures:
476 BinaryPackageRelease.id,524 self.logger.info("Finding binaries...(2nd pass)")
477 bpph_location_clauses,525 bins = self.findBinariesForDomination(distroarchseries, pocket)
478 ),526 sorted_packages = self._sortPackages(bins, generalization)
479 group_by=BinaryPackageName.id,527 self.logger.info("Dominating binaries...(2nd pass)")
480 having=Count(BinaryPackagePublishingHistory.id) > 1)528 self._dominatePublications(sorted_packages, generalization)
481 main_clauses = [
482 BinaryPackagePublishingHistory,
483 BinaryPackageRelease.id ==
484 BinaryPackagePublishingHistory.binarypackagereleaseID,
485 BinaryPackageRelease.binarypackagenameID.is_in(
486 candidate_binary_names),
487 BinaryPackageRelease.binpackageformat !=
488 BinaryPackageFormat.DDEB,
489 ]
490 main_clauses.extend(bpph_location_clauses)
491
492 def do_domination(pass2_msg=""):
493 msg = "binaries..." + pass2_msg
494 self.logger.info("Finding %s" % msg)
495 bins = IStore(
496 BinaryPackagePublishingHistory).find(*main_clauses)
497 self.logger.info("Dominating %s" % msg)
498 sorted_packages = self._sortPackages(bins, generalization)
499 self._dominatePublications(sorted_packages, generalization)
500
501 do_domination()
502
503 # We need to make a second pass to cover the cases where:
504 # * arch-specific binaries were not all dominated before arch-all
505 # ones that depend on them
506 # * An arch-all turned into an arch-specific, or vice-versa
507 # * A package is completely schizophrenic and changes all of
508 # its binaries between arch-all and arch-any (apparently
509 # occurs sometimes!)
510 do_domination("(2nd pass)")
511529
512 def _composeActiveSourcePubsCondition(self, distroseries, pocket):530 def _composeActiveSourcePubsCondition(self, distroseries, pocket):
513 """Compose ORM condition for restricting relevant source pubs."""531 """Compose ORM condition for restricting relevant source pubs."""
@@ -522,21 +540,11 @@
522 SourcePackagePublishingHistory.pocket == pocket,540 SourcePackagePublishingHistory.pocket == pocket,
523 )541 )
524542
525 def dominateSources(self, distroseries, pocket):543 def findSourcesForDomination(self, distroseries, pocket):
526 """Perform domination on source package publications.544 """Find binary publications that need dominating."""
527
528 Dominates sources, restricted to `distroseries`, `pocket`, and
529 `self.archive`.
530 """
531 # Avoid circular imports.545 # Avoid circular imports.
532 from lp.soyuz.model.publishing import SourcePackagePublishingHistory546 from lp.soyuz.model.publishing import SourcePackagePublishingHistory
533547
534 generalization = GeneralizedPublication(is_source=True)
535
536 self.logger.debug(
537 "Performing domination across %s/%s (Source)",
538 distroseries.name, pocket.title)
539
540 spph_location_clauses = self._composeActiveSourcePubsCondition(548 spph_location_clauses = self._composeActiveSourcePubsCondition(
541 distroseries, pocket)549 distroseries, pocket)
542 having_multiple_active_publications = (550 having_multiple_active_publications = (
@@ -546,12 +554,33 @@
546 And(join_spph_spr(), join_spr_spn(), spph_location_clauses),554 And(join_spph_spr(), join_spr_spn(), spph_location_clauses),
547 group_by=SourcePackageName.id,555 group_by=SourcePackageName.id,
548 having=having_multiple_active_publications)556 having=having_multiple_active_publications)
549 sources = IStore(SourcePackagePublishingHistory).find(557
550 SourcePackagePublishingHistory,558 # We'll also access the SourcePackageReleases associated with
559 # the publications we find. Since they're in the join anyway,
560 # load them alongside the publications.
561 # Actually we'll also want the SourcePackageNames, but adding
562 # those to the (outer) query would complicate it, and
563 # potentially slow it down.
564 query = IStore(SourcePackagePublishingHistory).find(
565 (SourcePackagePublishingHistory, SourcePackageRelease),
551 join_spph_spr(),566 join_spph_spr(),
552 SourcePackageRelease.sourcepackagenameID.is_in(567 SourcePackageRelease.sourcepackagenameID.is_in(
553 candidate_source_names),568 candidate_source_names),
554 spph_location_clauses)569 spph_location_clauses)
570 return DecoratedResultSet(query, itemgetter(0))
571
572 def dominateSources(self, distroseries, pocket):
573 """Perform domination on source package publications.
574
575 Dominates sources, restricted to `distroseries`, `pocket`, and
576 `self.archive`.
577 """
578 self.logger.debug(
579 "Performing domination across %s/%s (Source)",
580 distroseries.name, pocket.title)
581
582 generalization = GeneralizedPublication(is_source=True)
583 sources = self.findSourcesForDomination(distroseries, pocket)
555584
556 self.logger.debug("Dominating sources...")585 self.logger.debug("Dominating sources...")
557 self._dominatePublications(586 self._dominatePublications(
558587
=== modified file 'lib/lp/archivepublisher/tests/test_dominator.py'
--- lib/lp/archivepublisher/tests/test_dominator.py 2011-10-27 11:36:13 +0000
+++ lib/lp/archivepublisher/tests/test_dominator.py 2011-11-02 10:31:27 +0000
@@ -361,7 +361,10 @@
361def make_spphs_for_versions(factory, versions):361def make_spphs_for_versions(factory, versions):
362 """Create publication records for each of `versions`.362 """Create publication records for each of `versions`.
363363
364 They records are created in the same order in which they are specified.364 All these publications will be in the same source package, archive,
365 distroseries, and pocket. They will all be in Published status.
366
367 The records are created in the same order in which they are specified.
365 Make the order irregular to prove that version ordering is not a368 Make the order irregular to prove that version ordering is not a
366 coincidence of object creation order etc.369 coincidence of object creation order etc.
367370
@@ -371,6 +374,7 @@
371 spn = factory.makeSourcePackageName()374 spn = factory.makeSourcePackageName()
372 distroseries = factory.makeDistroSeries()375 distroseries = factory.makeDistroSeries()
373 pocket = factory.getAnyPocket()376 pocket = factory.getAnyPocket()
377 archive = distroseries.main_archive
374 sprs = [378 sprs = [
375 factory.makeSourcePackageRelease(379 factory.makeSourcePackageRelease(
376 sourcepackagename=spn, version=version)380 sourcepackagename=spn, version=version)
@@ -378,11 +382,34 @@
378 return [382 return [
379 factory.makeSourcePackagePublishingHistory(383 factory.makeSourcePackagePublishingHistory(
380 distroseries=distroseries, pocket=pocket,384 distroseries=distroseries, pocket=pocket,
381 sourcepackagerelease=spr,385 sourcepackagerelease=spr, archive=archive,
382 status=PackagePublishingStatus.PUBLISHED)386 status=PackagePublishingStatus.PUBLISHED)
383 for spr in sprs]387 for spr in sprs]
384388
385389
390def make_bpphs_for_versions(factory, versions):
391 """Create publication records for each of `versions`.
392
393 All these publications will be in the same binary package, source
394 package, archive, distroarchseries, and pocket. They will all be in
395 Published status.
396 """
397 bpn = factory.makeBinaryPackageName()
398 spn = factory.makeSourcePackageName()
399 das = factory.makeDistroArchSeries()
400 archive = das.distroseries.main_archive
401 pocket = factory.getAnyPocket()
402 bprs = [
403 factory.makeBinaryPackageRelease(binarypackagename=bpn)
404 for version in versions]
405 return [
406 factory.makeBinaryPackagePublishingHistory(
407 binarypackagerelease=bpr, binarypackagename=bpn,
408 distroarchseries=das, pocket=pocket, archive=archive,
409 sourcepackagename=spn, status=PackagePublishingStatus.PUBLISHED)
410 for bpr in bprs]
411
412
386def list_source_versions(spphs):413def list_source_versions(spphs):
387 """Extract the versions from `spphs` as a list, in the same order."""414 """Extract the versions from `spphs` as a list, in the same order."""
388 return [spph.sourcepackagerelease.version for spph in spphs]415 return [spph.sourcepackagerelease.version for spph in spphs]
@@ -921,3 +948,144 @@
921 [],948 [],
922 dominator.findPublishedSPPHs(949 dominator.findPublishedSPPHs(
923 spph.distroseries, spph.pocket, other_package.name))950 spph.distroseries, spph.pocket, other_package.name))
951
952 def test_findBinariesForDomination_finds_published_publications(self):
953 bpphs = make_bpphs_for_versions(self.factory, ['1.0', '1.1'])
954 dominator = self.makeDominator(bpphs)
955 self.assertContentEqual(
956 bpphs, dominator.findBinariesForDomination(
957 bpphs[0].distroarchseries, bpphs[0].pocket))
958
959 def test_findBinariesForDomination_skips_single_pub_packages(self):
960 # The domination algorithm that uses findBinariesForDomination
961 # always keeps the latest version live. Thus, a single
962 # publication isn't worth dominating. findBinariesForDomination
963 # won't return it.
964 bpphs = make_bpphs_for_versions(self.factory, ['1.0'])
965 dominator = self.makeDominator(bpphs)
966 self.assertContentEqual(
967 [], dominator.findBinariesForDomination(
968 bpphs[0].distroarchseries, bpphs[0].pocket))
969
970 def test_findBinariesForDomination_ignores_other_distroseries(self):
971 bpphs = make_bpphs_for_versions(self.factory, ['1.0', '1.1'])
972 dominator = self.makeDominator(bpphs)
973 das = bpphs[0].distroarchseries
974 other_series = self.factory.makeDistroSeries(
975 distribution=das.distroseries.distribution)
976 other_das = self.factory.makeDistroArchSeries(
977 distroseries=other_series, architecturetag=das.architecturetag,
978 processorfamily=das.processorfamily)
979 self.assertContentEqual(
980 [], dominator.findBinariesForDomination(
981 other_das, bpphs[0].pocket))
982
983 def test_findBinariesForDomination_ignores_other_architectures(self):
984 bpphs = make_bpphs_for_versions(self.factory, ['1.0', '1.1'])
985 dominator = self.makeDominator(bpphs)
986 other_das = self.factory.makeDistroArchSeries(
987 distroseries=bpphs[0].distroseries)
988 self.assertContentEqual(
989 [], dominator.findBinariesForDomination(
990 other_das, bpphs[0].pocket))
991
992 def test_findBinariesForDomination_ignores_other_archive(self):
993 bpphs = make_bpphs_for_versions(self.factory, ['1.0', '1.1'])
994 dominator = self.makeDominator(bpphs)
995 dominator.archive = self.factory.makeArchive()
996 self.assertContentEqual(
997 [], dominator.findBinariesForDomination(
998 bpphs[0].distroarchseries, bpphs[0].pocket))
999
1000 def test_findBinariesForDomination_ignores_other_pocket(self):
1001 bpphs = make_bpphs_for_versions(self.factory, ['1.0', '1.1'])
1002 dominator = self.makeDominator(bpphs)
1003 for bpph in bpphs:
1004 removeSecurityProxy(bpph).pocket = PackagePublishingPocket.UPDATES
1005 self.assertContentEqual(
1006 [], dominator.findBinariesForDomination(
1007 bpphs[0].distroarchseries, PackagePublishingPocket.SECURITY))
1008
1009 def test_findBinariesForDomination_ignores_other_status(self):
1010 # If we have one BPPH for each possible status, plus one
1011 # Published one to stop findBinariesForDomination from skipping
1012 # the package, findBinariesForDomination returns only the
1013 # Published ones.
1014 versions = [
1015 '1.%d' % self.factory.getUniqueInteger()
1016 for status in PackagePublishingStatus.items] + ['0.9']
1017 bpphs = make_bpphs_for_versions(self.factory, versions)
1018 dominator = self.makeDominator(bpphs)
1019
1020 for bpph, status in zip(bpphs, PackagePublishingStatus.items):
1021 bpph.status = status
1022
1023 # These are the Published publications. The other ones will all
1024 # be ignored.
1025 published_bpphs = [
1026 bpph
1027 for bpph in bpphs
1028 if bpph.status == PackagePublishingStatus.PUBLISHED]
1029
1030 self.assertContentEqual(
1031 published_bpphs,
1032 dominator.findBinariesForDomination(
1033 bpphs[0].distroarchseries, bpphs[0].pocket))
1034
1035 def test_findSourcesForDomination_finds_published_publications(self):
1036 spphs = make_spphs_for_versions(self.factory, ['2.0', '2.1'])
1037 dominator = self.makeDominator(spphs)
1038 self.assertContentEqual(
1039 spphs, dominator.findSourcesForDomination(
1040 spphs[0].distroseries, spphs[0].pocket))
1041
1042 def test_findSourcesForDomination_skips_single_pub_packages(self):
1043 # The domination algorithm that uses findSourcesForDomination
1044 # always keeps the latest version live. Thus, a single
1045 # publication isn't worth dominating. findSourcesForDomination
1046 # won't return it.
1047 spphs = make_spphs_for_versions(self.factory, ['2.0'])
1048 dominator = self.makeDominator(spphs)
1049 self.assertContentEqual(
1050 [], dominator.findSourcesForDomination(
1051 spphs[0].distroseries, spphs[0].pocket))
1052
1053 def test_findSourcesForDomination_ignores_other_distroseries(self):
1054 spphs = make_spphs_for_versions(self.factory, ['2.0', '2.1'])
1055 dominator = self.makeDominator(spphs)
1056 other_series = self.factory.makeDistroSeries(
1057 distribution=spphs[0].distroseries.distribution)
1058 self.assertContentEqual(
1059 [], dominator.findSourcesForDomination(
1060 other_series, spphs[0].pocket))
1061
1062 def test_findSourcesForDomination_ignores_other_pocket(self):
1063 spphs = make_spphs_for_versions(self.factory, ['2.0', '2.1'])
1064 dominator = self.makeDominator(spphs)
1065 for spph in spphs:
1066 removeSecurityProxy(spph).pocket = PackagePublishingPocket.UPDATES
1067 self.assertContentEqual(
1068 [], dominator.findSourcesForDomination(
1069 spphs[0].distroseries, PackagePublishingPocket.SECURITY))
1070
1071 def test_findSourcesForDomination_ignores_other_status(self):
1072 versions = [
1073 '1.%d' % self.factory.getUniqueInteger()
1074 for status in PackagePublishingStatus.items] + ['0.9']
1075 spphs = make_spphs_for_versions(self.factory, versions)
1076 dominator = self.makeDominator(spphs)
1077
1078 for spph, status in zip(spphs, PackagePublishingStatus.items):
1079 spph.status = status
1080
1081 # These are the Published publications. The other ones will all
1082 # be ignored.
1083 published_spphs = [
1084 spph
1085 for spph in spphs
1086 if spph.status == PackagePublishingStatus.PUBLISHED]
1087
1088 self.assertContentEqual(
1089 published_spphs,
1090 dominator.findSourcesForDomination(
1091 spphs[0].distroseries, spphs[0].pocket))
9241092
=== modified file 'lib/lp/soyuz/model/publishing.py'
--- lib/lp/soyuz/model/publishing.py 2011-10-23 02:58:56 +0000
+++ lib/lp/soyuz/model/publishing.py 2011-11-02 10:31:27 +0000
@@ -33,7 +33,6 @@
33 Desc,33 Desc,
34 LeftJoin,34 LeftJoin,
35 Or,35 Or,
36 Select,
37 Sum,36 Sum,
38 )37 )
39from storm.store import Store38from storm.store import Store
@@ -1154,19 +1153,10 @@
1154 # Avoid circular wotsits.1153 # Avoid circular wotsits.
1155 from lp.soyuz.model.binarypackagebuild import BinaryPackageBuild1154 from lp.soyuz.model.binarypackagebuild import BinaryPackageBuild
1156 from lp.soyuz.model.distroarchseries import DistroArchSeries1155 from lp.soyuz.model.distroarchseries import DistroArchSeries
1157 from lp.soyuz.model.sourcepackagerelease import SourcePackageRelease1156
1158 source_select = Select(
1159 SourcePackageRelease.id,
1160 And(
1161 BinaryPackageBuild.source_package_release_id ==
1162 SourcePackageRelease.id,
1163 BinaryPackageRelease.build == BinaryPackageBuild.id,
1164 self.binarypackagereleaseID == BinaryPackageRelease.id,
1165 ))
1166 pubs = [1157 pubs = [
1167 BinaryPackageBuild.source_package_release_id ==1158 BinaryPackageBuild.source_package_release_id ==
1168 SourcePackageRelease.id,1159 self.binarypackagerelease.build.source_package_release_id,
1169 SourcePackageRelease.id.is_in(source_select),
1170 BinaryPackageRelease.build == BinaryPackageBuild.id,1160 BinaryPackageRelease.build == BinaryPackageBuild.id,
1171 BinaryPackagePublishingHistory.binarypackagereleaseID ==1161 BinaryPackagePublishingHistory.binarypackagereleaseID ==
1172 BinaryPackageRelease.id,1162 BinaryPackageRelease.id,