launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #01832
[Merge] lp:~jelmer/launchpad/syncpackagejob-1 into lp:launchpad/devel
Jelmer Vernooij has proposed merging lp:~jelmer/launchpad/syncpackagejob-1 into lp:launchpad/devel.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
This branch adds the SyncPackageJob class for jobs that can copy packages between distributions.
Pre-Implementation Call: with Julian
Tests: ./bin/test lp.soyuz.tests.test_syncpackagejob
--
https://code.launchpad.net/~jelmer/launchpad/syncpackagejob-1/+merge/40169
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~jelmer/launchpad/syncpackagejob-1 into lp:launchpad/devel.
=== modified file 'lib/lp/soyuz/configure.zcml'
--- lib/lp/soyuz/configure.zcml 2010-10-12 08:14:07 +0000
+++ lib/lp/soyuz/configure.zcml 2010-11-05 10:46:49 +0000
@@ -899,18 +899,30 @@
<allow interface="canonical.launchpad.webapp.vocabulary.IHugeVocabulary"/>
</class>
+ <!-- DistributionJob -->
+ <class class="lp.soyuz.model.distributionjob.DistributionJob">
+ <allow interface="lp.soyuz.interfaces.distributionjob.IDistributionJob" />
+ </class>
+
<!-- InitialiseDistroSeriesJobSource -->
<securedutility
component="lp.soyuz.model.initialisedistroseriesjob.InitialiseDistroSeriesJob"
provides="lp.soyuz.interfaces.distributionjob.IInitialiseDistroSeriesJobSource">
<allow interface="lp.soyuz.interfaces.distributionjob.IInitialiseDistroSeriesJobSource"/>
</securedutility>
- <class class="lp.soyuz.model.distributionjob.DistributionJob">
- <allow interface="lp.soyuz.interfaces.distributionjob.IDistributionJob" />
- </class>
<class class="lp.soyuz.model.initialisedistroseriesjob.InitialiseDistroSeriesJob">
<allow interface="lp.soyuz.interfaces.distributionjob.IInitialiseDistroSeriesJob" />
<allow interface="lp.soyuz.interfaces.distributionjob.IDistributionJob" />
</class>
+ <!-- SyncPackageJobSource -->
+ <securedutility
+ component="lp.soyuz.model.syncpackagejob.SyncPackageJob"
+ provides="lp.soyuz.interfaces.distributionjob.ISyncPackageJobSource">
+ <allow interface="lp.soyuz.interfaces.distributionjob.ISyncPackageJobSource"/>
+ </securedutility>
+ <class class="lp.soyuz.model.syncpackagejob.SyncPackageJob">
+ <allow interface="lp.soyuz.interfaces.distributionjob.ISyncPackageJob" />
+ <allow interface="lp.soyuz.interfaces.distributionjob.IDistributionJob" />
+ </class>
</configure>
=== modified file 'lib/lp/soyuz/interfaces/distributionjob.py'
--- lib/lp/soyuz/interfaces/distributionjob.py 2010-10-12 07:46:56 +0000
+++ lib/lp/soyuz/interfaces/distributionjob.py 2010-11-05 10:46:49 +0000
@@ -8,15 +8,32 @@
"IDistributionJob",
"IInitialiseDistroSeriesJob",
"IInitialiseDistroSeriesJobSource",
+ "ISyncPackageJob",
+ "ISyncPackageJobSource",
]
-from lazr.enum import DBEnumeratedType, DBItem
-from zope.interface import Attribute, Interface
-from zope.schema import Int, Object
+from lazr.enum import (
+ DBEnumeratedType,
+ DBItem,
+ )
+from zope.interface import (
+ Attribute,
+ Interface,
+ )
+from zope.schema import (
+ Bool,
+ Int,
+ Object,
+ TextLine,
+ )
from canonical.launchpad import _
-from lp.services.job.interfaces.job import IJob, IJobSource, IRunnableJob
+from lp.services.job.interfaces.job import (
+ IJob,
+ IJobSource,
+ IRunnableJob,
+ )
from lp.registry.interfaces.distribution import IDistribution
from lp.registry.interfaces.distroseries import IDistroSeries
@@ -54,13 +71,59 @@
populating the archive from the parent distroseries.
""")
+ SYNC_PACKAGE = DBItem(2, """
+ Synchronize a single package from another distribution.
+
+ This job copies a single package, optionally including binaries.
+ """)
+
class IInitialiseDistroSeriesJobSource(IJobSource):
- """An interface for acquiring IDistributionJobs."""
+ """An interface for acquiring IInitialiseDistroSeriesJobs."""
def create(distroseries, arches, packagesets, rebuild):
"""Create a new initialisation job for a distroseries."""
+class ISyncPackageJobSource(IJobSource):
+ """An interface for acquiring IISyncPackageJobs."""
+
+ def create(source_archive, target_archive, distroseries, pocket,
+ source_package_name, version, include_binaries):
+ """Create a new sync package job."""
+
+ def getActiveJobs(archive):
+ """Retrieve all active sync jobs for an archive."""
+
+
class IInitialiseDistroSeriesJob(IRunnableJob):
"""A Job that performs actions on a distribution."""
+
+
+class ISyncPackageJob(IRunnableJob):
+ """A Job that synchronizes packages."""
+
+ pocket = Int(
+ title=_('Target package publishing pocket'), required=True,
+ readonly=True,
+ )
+
+ source_archive = Int(
+ title=_('Source Archive ID'), required=True, readonly=True,
+ )
+
+ target_archive = Int(
+ title=_('Target Archive ID'), required=True, readonly=True,
+ )
+
+ source_package_name = TextLine(
+ title=_("Source Package Name"),
+ required=True, readonly=True)
+
+ source_package_version = TextLine(
+ title=_("Source Package Version"),
+ required=True, readonly=True)
+
+ include_binaries = Bool(
+ title=_("Copy binaries"),
+ required=False, readonly=True)
=== added file 'lib/lp/soyuz/model/syncpackagejob.py'
--- lib/lp/soyuz/model/syncpackagejob.py 1970-01-01 00:00:00 +0000
+++ lib/lp/soyuz/model/syncpackagejob.py 2010-11-05 10:46:49 +0000
@@ -0,0 +1,101 @@
+# Copyright 2010 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+__metaclass__ = type
+
+__all__ = [
+ "SyncPackageJob",
+]
+
+from zope.component import getUtility
+from zope.interface import (
+ classProvides,
+ implements,
+ )
+
+from canonical.launchpad.interfaces.lpstorm import (
+ IMasterStore,
+ IStore,
+ )
+
+from lp.registry.interfaces.pocket import PackagePublishingPocket
+from lp.soyuz.interfaces.archive import IArchiveSet
+from lp.soyuz.interfaces.distributionjob import (
+ DistributionJobType,
+ ISyncPackageJob,
+ ISyncPackageJobSource,
+ )
+from lp.soyuz.model.distributionjob import (
+ DistributionJob,
+ DistributionJobDerived,
+ )
+
+
+class SyncPackageJob(DistributionJobDerived):
+ """Job that copies a package between archives."""
+
+ implements(ISyncPackageJob)
+
+ class_job_type = DistributionJobType.SYNC_PACKAGE
+ classProvides(ISyncPackageJobSource)
+
+ @classmethod
+ def create(cls, source_archive, target_archive, distroseries,
+ pocket, source_package_name, source_package_version,
+ include_binaries):
+ """See `ISyncPackageJobSource`."""
+ metadata = {
+ 'source_archive_id': source_archive.id,
+ 'target_archive_id': target_archive.id,
+ 'pocket': pocket.value,
+ 'source_package_name': source_package_name,
+ 'source_package_version': source_package_version,
+ 'include_binaries': include_binaries,
+ }
+ job = DistributionJob(
+ distroseries.distribution, distroseries, cls.class_job_type,
+ metadata)
+ IMasterStore(DistributionJob).add(job)
+ return cls(job)
+
+ @classmethod
+ def getActiveJobs(cls, archive):
+ """See `ISyncPackageJobSource`."""
+ # TODO: JRV 20101104. This iterates manually over all active
+ # SyncPackageJobs. This should usually be a short enough list,
+ # but if it really becomes and issue target_archive should
+ # be moved into a separate database field.
+ jobs = IStore(DistributionJob).find(
+ DistributionJob,
+ DistributionJob.job_type == cls.class_job_type,
+ DistributionJob.distribution == archive.distribution)
+ jobs = [cls(job) for job in jobs]
+ return (job for job in jobs if job.target_archive == archive)
+
+ @property
+ def source_archive(self):
+ return getUtility(IArchiveSet).get(self.metadata['source_archive_id'])
+
+ @property
+ def target_archive(self):
+ return getUtility(IArchiveSet).get(self.metadata['target_archive_id'])
+
+ @property
+ def pocket(self):
+ return PackagePublishingPocket.items[self.metadata['pocket']]
+
+ @property
+ def include_binaries(self):
+ return self.metadata['include_binaries']
+
+ @property
+ def source_package_name(self):
+ return self.metadata['source_package_name']
+
+ @property
+ def source_package_version(self):
+ return self.metadata['source_package_version']
+
+ def run(self):
+ """See `IRunnableJob`."""
+ raise NotImplementedError(self.run)
=== modified file 'lib/lp/soyuz/tests/test_initialisedistroseriesjob.py'
--- lib/lp/soyuz/tests/test_initialisedistroseriesjob.py 2010-10-25 23:13:55 +0000
+++ lib/lp/soyuz/tests/test_initialisedistroseriesjob.py 2010-11-05 10:46:49 +0000
@@ -6,15 +6,12 @@
import sys
from storm.exceptions import IntegrityError
-from storm.store import Store
import transaction
from zope.component import getUtility
from zope.security.proxy import removeSecurityProxy
from canonical.config import config
from canonical.testing import LaunchpadZopelessLayer
-from lp.buildmaster.enums import BuildStatus
-from lp.registry.interfaces.pocket import PackagePublishingPocket
from lp.soyuz.interfaces.distributionjob import (
IInitialiseDistroSeriesJobSource,
)
@@ -26,7 +23,6 @@
from lp.soyuz.scripts.initialise_distroseries import InitialisationError
from lp.soyuz.tests.test_publishing import SoyuzTestPublisher
from lp.testing import TestCaseWithFactory
-from lp.testing.matchers import Contains
class InitialiseDistroSeriesJobTests(TestCaseWithFactory):
=== added file 'lib/lp/soyuz/tests/test_syncpackagejob.py'
--- lib/lp/soyuz/tests/test_syncpackagejob.py 1970-01-01 00:00:00 +0000
+++ lib/lp/soyuz/tests/test_syncpackagejob.py 2010-11-05 10:46:49 +0000
@@ -0,0 +1,47 @@
+# Copyright 2010 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+from zope.component import getUtility
+
+from canonical.testing import LaunchpadZopelessLayer
+from lp.soyuz.interfaces.distributionjob import (
+ ISyncPackageJob,
+ ISyncPackageJobSource,
+ )
+from lp.registry.interfaces.pocket import PackagePublishingPocket
+from lp.testing import TestCaseWithFactory
+
+
+class SyncPackageJobTests(TestCaseWithFactory):
+ """Test case for SyncPackageJob."""
+
+ layer = LaunchpadZopelessLayer
+
+ def test_create(self):
+ # A SyncPackageJob can be created and stores its arguments.
+ distroseries = self.factory.makeDistroSeries()
+ archive1 = self.factory.makeArchive(distroseries.distribution)
+ archive2 = self.factory.makeArchive(distroseries.distribution)
+ source = getUtility(ISyncPackageJobSource)
+ job = source.create(archive1, archive2, distroseries,
+ PackagePublishingPocket.RELEASE,
+ "foo", "1.0-1", include_binaries=False)
+ self.assertProvides(job, ISyncPackageJob)
+ self.assertEquals(distroseries, job.distroseries)
+ self.assertEquals(archive1, job.source_archive)
+ self.assertEquals(archive2, job.target_archive)
+ self.assertEquals(PackagePublishingPocket.RELEASE, job.pocket)
+ self.assertEquals("foo", job.source_package_name)
+ self.assertEquals("1.0-1", job.source_package_version)
+ self.assertEquals(False, job.include_binaries)
+
+ def test_getActiveJobs(self):
+ # getActiveJobs() can retrieve all active jobs for an archive.
+ distroseries = self.factory.makeDistroSeries()
+ archive1 = self.factory.makeArchive(distroseries.distribution)
+ archive2 = self.factory.makeArchive(distroseries.distribution)
+ source = getUtility(ISyncPackageJobSource)
+ job = source.create(archive1, archive2, distroseries,
+ PackagePublishingPocket.RELEASE,
+ "foo", "1.0-1", include_binaries=False)
+ self.assertContentEqual([job], source.getActiveJobs(archive2))
Follow ups