launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #20444
[Merge] lp:~cjwatson/launchpad/refactor-queue-custom-2 into lp:launchpad
Colin Watson has proposed merging lp:~cjwatson/launchpad/refactor-queue-custom-2 into lp:launchpad with lp:~cjwatson/launchpad/refactor-queue-custom as a prerequisite.
Commit message:
Eliminate circular archivepublisher imports from lp.soyuz.model.queue.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad/refactor-queue-custom-2/+merge/295456
Eliminate circular archivepublisher imports from lp.soyuz.model.queue.
--
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~cjwatson/launchpad/refactor-queue-custom-2 into lp:launchpad.
=== modified file 'lib/lp/archivepublisher/configure.zcml'
--- lib/lp/archivepublisher/configure.zcml 2016-05-23 11:22:25 +0000
+++ lib/lp/archivepublisher/configure.zcml 2016-05-23 11:22:25 +0000
@@ -74,6 +74,20 @@
interface="lp.soyuz.interfaces.queue.ICustomUploadHandler"/>
</securedutility>
<securedutility
+ class="lp.archivepublisher.static_translations.StaticTranslationsUpload"
+ provides="lp.soyuz.interfaces.queue.ICustomUploadHandler"
+ name="STATIC_TRANSLATIONS">
+ <allow
+ interface="lp.soyuz.interfaces.queue.ICustomUploadHandler"/>
+ </securedutility>
+ <securedutility
+ class="lp.archivepublisher.meta_data.MetaDataUpload"
+ provides="lp.soyuz.interfaces.queue.ICustomUploadHandler"
+ name="META_DATA">
+ <allow
+ interface="lp.soyuz.interfaces.queue.ICustomUploadHandler"/>
+ </securedutility>
+ <securedutility
class="lp.archivepublisher.signing.SigningUpload"
provides="lp.soyuz.interfaces.queue.ICustomUploadHandler"
name="SIGNING">
=== added file 'lib/lp/archivepublisher/meta_data.py'
--- lib/lp/archivepublisher/meta_data.py 1970-01-01 00:00:00 +0000
+++ lib/lp/archivepublisher/meta_data.py 2016-05-23 11:22:25 +0000
@@ -0,0 +1,54 @@
+# Copyright 2016 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Processing of archive meta-data uploads."""
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+ "MetaDataUpload",
+ ]
+
+import os
+
+from lp.archivepublisher.config import getPubConfig
+from lp.archivepublisher.customupload import CustomUpload
+from lp.services.librarian.utils import copy_and_close
+
+
+class MetaDataUpload(CustomUpload):
+ """Meta-data custom upload.
+
+ Meta-data custom files are published, unmodified, to a special area
+ outside the actual archive directory. This is so that the files can be
+ seen even when the archive is private, and allows commercial customers
+ to browse contents for potential later purchase.
+ """
+ custom_type = "meta-data"
+
+ @classmethod
+ def publish(cls, packageupload, libraryfilealias, logger=None):
+ """See `ICustomUploadHandler`."""
+ upload = cls(logger=logger)
+ upload.process(packageupload, libraryfilealias)
+
+ def process(self, packageupload, libraryfilealias):
+ pubconf = getPubConfig(packageupload.archive)
+ if pubconf.metaroot is None:
+ if self.logger is not None:
+ self.logger.debug(
+ "Skipping meta-data for archive without metaroot.")
+ return
+
+ dest_file = os.path.join(pubconf.metaroot, libraryfilealias.filename)
+ if not os.path.isdir(pubconf.metaroot):
+ os.makedirs(pubconf.metaroot, 0o755)
+
+ # At this point we now have a directory of the format:
+ # <person_name>/meta/<ppa_name>
+ # We're ready to copy the file out of the librarian into it.
+
+ file_obj = open(dest_file, "wb")
+ libraryfilealias.open()
+ copy_and_close(libraryfilealias, file_obj)
=== added file 'lib/lp/archivepublisher/static_translations.py'
--- lib/lp/archivepublisher/static_translations.py 1970-01-01 00:00:00 +0000
+++ lib/lp/archivepublisher/static_translations.py 2016-05-23 11:22:25 +0000
@@ -0,0 +1,32 @@
+# Copyright 2016 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Processing of static translations uploads."""
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+__metaclass__ = type
+__all__ = [
+ "StaticTranslationsUpload",
+ ]
+
+from lp.archivepublisher.customupload import CustomUpload
+
+
+class StaticTranslationsUpload(CustomUpload):
+ """Static translations upload.
+
+ Static translations are not published. Currently, they're only exposed
+ via webservice methods so that third parties can retrieve them from the
+ librarian.
+ """
+ custom_type = "static-translations"
+
+ @classmethod
+ def publish(cls, packageupload, libraryfilealias, logger=None):
+ """See `ICustomUploadHandler`."""
+ if logger is not None:
+ logger.debug("Skipping publishing of static translations.")
+
+ def process(self, packageupload, libraryfilealias):
+ pass
=== removed file 'lib/lp/archivepublisher/tests/publishing-meta-data-files.txt'
--- lib/lp/archivepublisher/tests/publishing-meta-data-files.txt 2014-07-07 07:36:54 +0000
+++ lib/lp/archivepublisher/tests/publishing-meta-data-files.txt 1970-01-01 00:00:00 +0000
@@ -1,88 +0,0 @@
-Publishing Meta-Data Custom Files
-=================================
-
-Meta-data custom files are published, unmodified, to a special area
-outside the actual archive directory. This is so that the files can be
-seen even when the archive is private, and allows commercial customers
-to browse contents for potential later purchase.
-
-We can demonstrate this publishing behaviour by creating a
-PackageUploadCustom object for a meta-data upload:
-
- >>> from lp.services.librarian.interfaces import (
- ... ILibraryFileAliasSet)
- >>> from cStringIO import StringIO
- >>> from lp.services.log.logger import FakeLogger
- >>> from lp.registry.interfaces.distribution import IDistributionSet
- >>> from lp.soyuz.enums import PackageUploadCustomFormat
- >>> from lp.soyuz.interfaces.publishing import PackagePublishingPocket
- >>> from lp.soyuz.model.queue import PackageUploadCustom
-
- >>> hoary = getUtility(IDistributionSet)['ubuntu']['hoary']
- >>> ppa = factory.makeArchive(distribution=hoary.distribution)
- >>> package_upload = hoary.createQueueEntry(
- ... pocket=PackagePublishingPocket.RELEASE, changesfilename="test",
- ... changesfilecontent="test",
- ... archive=ppa)
- >>> content = "test"
- >>> test_file = getUtility(
- ... ILibraryFileAliasSet).create(
- ... "testmeta", len(content), StringIO(content), "text/plain")
- >>> custom_upload = PackageUploadCustom()
- >>> custom_upload.customformat = PackageUploadCustomFormat.META_DATA
- >>> custom_upload.packageupload = package_upload
- >>> custom_upload.libraryfilealias = test_file
- >>> # commit so that the file is put in the librarian.
- >>> import transaction
- >>> transaction.commit()
-
-Now we can publish the custom upload:
-
- >>> custom_upload.publish(logger=FakeLogger())
- DEBUG Publishing custom testmeta to ubuntu/hoary
-
-The custom file is just called "testmeta" with the contents "test". It will
-be published in a location of the scheme:
-
-/<person_name>/meta/<ppa_name>/<filename>
-
- >>> import os
- >>> from lp.archivepublisher.config import getPubConfig
- >>> pub_config = getPubConfig(ppa)
- >>> ppa_root = pub_config.distroroot
- >>> final_destination = os.path.join(
- ... ppa_root, ppa.owner.name, "meta", ppa.name)
- >>> published_file = os.path.join(
- ... final_destination, "testmeta")
-
- >>> os.path.exists(published_file)
- True
-
- >>> with open(published_file, 'rb') as fp:
- ... content = fp.read()
-
- >>> print content
- test
-
-The meta-data directory is currently only defined for Ubuntu PPAs, so
-publishing a meta-data upload in a non-Ubuntu PPA is a no-op.
-
- >>> bat = getUtility(IDistributionSet)['ubuntutest']['breezy-autotest']
- >>> ppa = factory.makeArchive(distribution=bat.distribution)
- >>> package_upload = bat.createQueueEntry(
- ... pocket=PackagePublishingPocket.RELEASE, changesfilename="test",
- ... changesfilecontent="test",
- ... archive=ppa)
- >>> custom_upload = PackageUploadCustom()
- >>> custom_upload.customformat = PackageUploadCustomFormat.META_DATA
- >>> custom_upload.packageupload = package_upload
- >>> custom_upload.libraryfilealias = test_file
-
- >>> custom_upload.publish(logger=FakeLogger())
- DEBUG Publishing custom testmeta to ubuntutest/breezy-autotest
- DEBUG Skipping meta-data for archive without metaroot.
-
- >>> final_destination = os.path.join(
- ... ppa_root, ppa.owner.name, "meta", ppa.name)
- >>> os.path.exists(final_destination)
- False
=== added file 'lib/lp/archivepublisher/tests/test_meta_data.py'
--- lib/lp/archivepublisher/tests/test_meta_data.py 1970-01-01 00:00:00 +0000
+++ lib/lp/archivepublisher/tests/test_meta_data.py 2016-05-23 11:22:25 +0000
@@ -0,0 +1,69 @@
+# Copyright 2016 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+"""Test meta-data custom uploads."""
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+__metaclass__ = type
+
+import os
+
+from testtools.matchers import (
+ FileContains,
+ Not,
+ PathExists,
+ )
+import transaction
+from zope.component import getUtility
+
+from lp.archivepublisher.config import getPubConfig
+from lp.archivepublisher.meta_data import MetaDataUpload
+from lp.registry.interfaces.distribution import IDistributionSet
+from lp.services.log.logger import BufferLogger
+from lp.testing import TestCaseWithFactory
+from lp.testing.layers import LaunchpadZopelessLayer
+
+
+class TestMetaData(TestCaseWithFactory):
+
+ layer = LaunchpadZopelessLayer
+
+ def test_ubuntu_ppa(self):
+ """A meta-data upload to an Ubuntu PPA is published.
+
+ The custom file is published to
+ /<person_name>/meta/<ppa_name>/<filename>.
+ """
+ ubuntu = getUtility(IDistributionSet)["ubuntu"]
+ archive = self.factory.makeArchive(distribution=ubuntu)
+ packageupload = self.factory.makePackageUpload(archive=archive)
+ content = self.factory.getUniqueString()
+ libraryfilealias = self.factory.makeLibraryFileAlias(content=content)
+ transaction.commit()
+ logger = BufferLogger()
+ MetaDataUpload(logger=logger).process(packageupload, libraryfilealias)
+ self.assertEqual("", logger.getLogBuffer())
+ published_file = os.path.join(
+ getPubConfig(archive).distroroot, archive.owner.name, "meta",
+ archive.name, libraryfilealias.filename)
+ self.assertThat(published_file, FileContains(content))
+
+ def test_non_ubuntu_ppa(self):
+ """A meta-data upload to a non-Ubuntu PPA is not published.
+
+ The meta-data directory is currently only defined for Ubuntu PPAs.
+ """
+ archive = self.factory.makeArchive(
+ distribution=self.factory.makeDistribution())
+ packageupload = self.factory.makePackageUpload(archive=archive)
+ libraryfilealias = self.factory.makeLibraryFileAlias(db_only=True)
+ logger = BufferLogger()
+ MetaDataUpload(logger=logger).process(packageupload, libraryfilealias)
+ self.assertEqual(
+ "DEBUG Skipping meta-data for archive without metaroot.\n",
+ logger.getLogBuffer())
+ published_file = os.path.join(
+ getPubConfig(archive).distroroot, archive.owner.name, "meta",
+ archive.name, libraryfilealias.filename)
+ self.assertThat(published_file, Not(PathExists()))
=== modified file 'lib/lp/soyuz/model/queue.py'
--- lib/lp/soyuz/model/queue.py 2016-05-23 11:22:25 +0000
+++ lib/lp/soyuz/model/queue.py 2016-05-23 11:22:25 +0000
@@ -12,7 +12,6 @@
]
from itertools import chain
-import os
from sqlobject import (
ForeignKey,
@@ -38,10 +37,6 @@
from zope.interface import implementer
from lp.app.errors import NotFoundError
-# XXX 2009-05-10 julian
-# This should not import from archivepublisher, but to avoid
-# that it needs a bit of redesigning here around the publication stuff.
-from lp.archivepublisher.config import getPubConfig
from lp.archiveuploader.tagfiles import parse_tagfile_content
from lp.registry.interfaces.gpg import IGPGKeySet
from lp.registry.interfaces.pocket import PackagePublishingPocket
@@ -73,7 +68,6 @@
LibraryFileAlias,
LibraryFileContent,
)
-from lp.services.librarian.utils import copy_and_close
from lp.services.mail.signedmessage import strip_pgp_signature
from lp.services.propertycache import (
cachedproperty,
@@ -121,10 +115,6 @@
from lp.soyuz.model.distroarchseries import DistroArchSeries
from lp.soyuz.model.section import Section
-# There are imports below in PackageUploadCustom for various bits
-# of the archivepublisher which cause circular import errors if they
-# are placed here.
-
def debug(logger, msg):
"""Shorthand debug notation for publish() methods."""
@@ -1357,98 +1347,13 @@
def publish(self, logger=None):
"""See `IPackageUploadCustom`."""
- # This is a marker as per the comment in lib/lp/soyuz/enums.py:
- ##CUSTOMFORMAT##
- # Essentially, if you alter anything to do with what custom formats
- # are, what their tags are, or anything along those lines, you should
- # grep for the marker in the source tree and fix it up in every place
- # so marked.
debug(logger, "Publishing custom %s to %s/%s" % (
self.packageupload.displayname,
self.packageupload.distroseries.distribution.name,
self.packageupload.distroseries.name))
-
- self.publisher_dispatch[self.customformat](self, logger)
-
- def publishDebianInstaller(self, logger=None):
- """See `IPackageUploadCustom`."""
- handler = getUtility(ICustomUploadHandler, "DEBIAN_INSTALLER")
- handler.publish(
- self.packageupload, self.libraryfilealias, logger=logger)
-
- def publishDistUpgrader(self, logger=None):
- """See `IPackageUploadCustom`."""
- handler = getUtility(ICustomUploadHandler, "DIST_UPGRADER")
- handler.publish(
- self.packageupload, self.libraryfilealias, logger=logger)
-
- def publishDdtpTarball(self, logger=None):
- """See `IPackageUploadCustom`."""
- handler = getUtility(ICustomUploadHandler, "DDTP_TARBALL")
- handler.publish(
- self.packageupload, self.libraryfilealias, logger=logger)
-
- def publishRosettaTranslations(self, logger=None):
- """See `IPackageUploadCustom`."""
- handler = getUtility(ICustomUploadHandler, "ROSETTA_TRANSLATIONS")
- handler.publish(
- self.packageupload, self.libraryfilealias, logger=logger)
-
- def publishStaticTranslations(self, logger=None):
- """See `IPackageUploadCustom`."""
- # Static translations are not published. Currently, they're
- # only exposed via webservice methods so that third parties can
- # retrieve them from the librarian.
- debug(logger, "Skipping publishing of static translations.")
- return
-
- def publishMetaData(self, logger=None):
- """See `IPackageUploadCustom`."""
- # In the future this could use the existing custom upload file
- # processing which deals with versioning, etc., but that's too
- # complicated for our needs right now. Also, the existing code
- # assumes that everything is a tarball and tries to unpack it.
-
- # See the XXX near the import for getPubConfig.
- archive_config = getPubConfig(self.packageupload.archive)
- if archive_config.metaroot is None:
- debug(logger, "Skipping meta-data for archive without metaroot.")
- return
-
- dest_file = os.path.join(
- archive_config.metaroot, self.libraryfilealias.filename)
- if not os.path.isdir(archive_config.metaroot):
- os.makedirs(archive_config.metaroot, 0o755)
-
- # At this point we now have a directory of the format:
- # <person_name>/meta/<ppa_name>
- # We're ready to copy the file out of the librarian into it.
-
- file_obj = file(dest_file, "wb")
- self.libraryfilealias.open()
- copy_and_close(self.libraryfilealias, file_obj)
-
- def publishSigning(self, logger=None):
- """See `IPackageUploadCustom`."""
- handler = getUtility(ICustomUploadHandler, "SIGNING")
- handler.publish(
- self.packageupload, self.libraryfilealias, logger=logger)
-
- publisher_dispatch = {
- PackageUploadCustomFormat.DEBIAN_INSTALLER: publishDebianInstaller,
- PackageUploadCustomFormat.ROSETTA_TRANSLATIONS:
- publishRosettaTranslations,
- PackageUploadCustomFormat.DIST_UPGRADER: publishDistUpgrader,
- PackageUploadCustomFormat.DDTP_TARBALL: publishDdtpTarball,
- PackageUploadCustomFormat.STATIC_TRANSLATIONS:
- publishStaticTranslations,
- PackageUploadCustomFormat.META_DATA: publishMetaData,
- PackageUploadCustomFormat.SIGNING: publishSigning,
- }
-
- # publisher_dispatch must have an entry for each value of
- # PackageUploadCustomFormat.
- assert len(publisher_dispatch) == len(PackageUploadCustomFormat)
+ handler = getUtility(ICustomUploadHandler, self.customformat.name)
+ handler.publish(
+ self.packageupload, self.libraryfilealias, logger=logger)
@implementer(IPackageUploadSet)
=== modified file 'lib/lp/soyuz/tests/test_packageupload.py'
--- lib/lp/soyuz/tests/test_packageupload.py 2015-11-26 13:31:45 +0000
+++ lib/lp/soyuz/tests/test_packageupload.py 2016-05-23 11:22:25 +0000
@@ -16,7 +16,10 @@
)
from testtools.matchers import Equals
import transaction
-from zope.component import getUtility
+from zope.component import (
+ getUtility,
+ queryUtility,
+ )
from zope.schema import getFields
from zope.security.interfaces import Unauthorized as ZopeUnauthorized
from zope.security.proxy import removeSecurityProxy
@@ -39,6 +42,7 @@
from lp.soyuz.interfaces.archivepermission import IArchivePermissionSet
from lp.soyuz.interfaces.component import IComponentSet
from lp.soyuz.interfaces.queue import (
+ ICustomUploadHandler,
IPackageUpload,
IPackageUploadSet,
QueueAdminUnauthorizedError,
@@ -54,12 +58,14 @@
person_logged_in,
record_two_runs,
StormStatementRecorder,
+ TestCase,
TestCaseWithFactory,
)
from lp.testing.dbuser import dbuser
from lp.testing.layers import (
LaunchpadFunctionalLayer,
LaunchpadZopelessLayer,
+ ZopelessLayer,
)
from lp.testing.matchers import (
HasQueryCount,
@@ -573,6 +579,18 @@
self.assertIs(None, pu.sourcepackagerelease)
+class TestPackageUploadCustom(TestCase):
+ """Unit tests for `PackageUploadCustom`."""
+
+ layer = ZopelessLayer
+
+ def test_handlers(self):
+ # Each element of `PackageUploadCustomFormat` has a handler.
+ for customformat in PackageUploadCustomFormat.items:
+ self.assertIsNotNone(
+ queryUtility(ICustomUploadHandler, customformat.name))
+
+
class TestPackageUploadSet(TestCaseWithFactory):
"""Unit tests for `PackageUploadSet`."""
Follow ups