launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #00742
[Merge] lp:~salgado/launchpad/vostok-upload-policy into lp:launchpad/devel
Guilherme Salgado has proposed merging lp:~salgado/launchpad/vostok-upload-policy into lp:launchpad/devel with lp:~salgado/launchpad/remove-security-upload-policy as a prerequisite.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
This branch moves the code related to validating the upload type from nascentupload to the upload policy, as a separate method. This makes it easy to unit test that code as well as adding more flexibility for subclasses that might want to validate differently.
It also replaces the three can_upload_* variables with a single enum variable.
--
https://code.launchpad.net/~salgado/launchpad/vostok-upload-policy/+merge/33584
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~salgado/launchpad/vostok-upload-policy into lp:launchpad/devel.
=== modified file 'lib/lp/archiveuploader/nascentupload.py'
--- lib/lp/archiveuploader/nascentupload.py 2010-08-24 08:43:51 +0000
+++ lib/lp/archiveuploader/nascentupload.py 2010-08-24 20:37:50 +0000
@@ -146,10 +146,11 @@
UploadError will be raised and sent up to the caller. If this happens
the caller should call the reject method and process a rejection.
"""
+ policy = self.policy
self.logger.debug("Beginning processing.")
try:
- self.policy.setDistroSeriesAndPocket(self.changes.suite_name)
+ policy.setDistroSeriesAndPocket(self.changes.suite_name)
except NotFoundError:
self.reject(
"Unable to find distroseries: %s" % self.changes.suite_name)
@@ -185,36 +186,12 @@
isinstance(self.changes.files[0], CustomUploadFile)):
self.logger.debug("Single Custom Upload detected.")
else:
- if self.sourceful and not self.policy.can_upload_source:
- self.reject("Upload is sourceful, but policy refuses "
- "sourceful uploads.")
-
- elif self.binaryful and not self.policy.can_upload_binaries:
- messages = [
- "Upload rejected because it contains binary packages.",
- "Ensure you are using `debuild -S`, or an equivalent",
- "command, to generate only the source package before",
- "re-uploading.",
- ]
- if self.is_ppa:
- messages.append(
- "See https://help.launchpad.net/Packaging/PPA for more "
- "information.")
- self.reject(" ".join(messages))
-
- elif (self.sourceful and self.binaryful and
- not self.policy.can_upload_mixed):
- self.reject("Upload is source/binary but policy refuses "
- "mixed uploads.")
-
- elif self.sourceful and not self.changes.dsc:
+ policy.validateUploadType(self)
+
+ if self.sourceful and not self.changes.dsc:
self.reject(
"Unable to find the DSC file in the source upload.")
- else:
- # Upload content are consistent with the current policy.
- pass
-
# Apply the overrides from the database. This needs to be done
# before doing component verifications because the component
# actually comes from overrides for packages that are not NEW.
@@ -227,7 +204,7 @@
self.verify_acl()
# Perform policy checks.
- self.policy.checkUpload(self)
+ policy.checkUpload(self)
# That's all folks.
self.logger.debug("Finished checking upload.")
@@ -996,8 +973,6 @@
# so late in the game is that in the
# mixed-upload case we only have a
# sourcepackagerelease to verify here!
- assert self.policy.can_upload_mixed, (
- "Current policy does not allow mixed uploads.")
assert sourcepackagerelease, (
"No sourcepackagerelease was found.")
binary_package_file.verifySourcePackageRelease(
=== modified file 'lib/lp/archiveuploader/tests/__init__.py'
--- lib/lp/archiveuploader/tests/__init__.py 2010-08-20 20:31:18 +0000
+++ lib/lp/archiveuploader/tests/__init__.py 2010-08-24 20:37:50 +0000
@@ -117,6 +117,10 @@
# We require the changes to be signed but not the dsc
self.unsigned_dsc_ok = True
+ def validateUploadType(self, upload):
+ """We accept uploads of any type."""
+ pass
+
def policySpecificChecks(self, upload):
"""Nothing, let it go."""
pass
=== modified file 'lib/lp/archiveuploader/tests/nascentupload-announcements.txt'
--- lib/lp/archiveuploader/tests/nascentupload-announcements.txt 2010-08-24 20:37:48 +0000
+++ lib/lp/archiveuploader/tests/nascentupload-announcements.txt 2010-08-24 20:37:50 +0000
@@ -297,9 +297,10 @@
NEW binary upload to RELEASE pocket via 'sync' policy (we need to
override sync policy to allow binary uploads):
+ >>> from lp.archiveuploader.uploadpolicy import ArchiveUploadType
>>> modified_sync_policy = getPolicy(
... name='sync', distro='ubuntu', distroseries='hoary')
- >>> modified_sync_policy.can_upload_binaries = True
+ >>> modified_sync_policy.accepted_type = ArchiveUploadType.BINARY_ONLY
>>> bar_src = NascentUpload.from_changesfile_path(
... datadir('suite/bar_1.0-1_binary/bar_1.0-1_i386.changes'),
=== modified file 'lib/lp/archiveuploader/tests/nascentupload.txt'
--- lib/lp/archiveuploader/tests/nascentupload.txt 2010-08-20 12:11:30 +0000
+++ lib/lp/archiveuploader/tests/nascentupload.txt 2010-08-24 20:37:50 +0000
@@ -499,9 +499,10 @@
need unsigned changes and binaries uploads (same as security, but also
accepts non-security uploads)
+ >>> from lp.archiveuploader.uploadpolicy import ArchiveUploadType
>>> modified_sync_policy = getPolicy(
... name='sync', distro='ubuntu', distroseries='hoary')
- >>> modified_sync_policy.can_upload_binaries = True
+ >>> modified_sync_policy.accepted_type = ArchiveUploadType.BINARY_ONLY
>>> ed_bin = NascentUpload.from_changesfile_path(
... datadir('split-upload-test/ed_0.2-20_i386.changes'),
=== modified file 'lib/lp/archiveuploader/tests/nascentuploadfile.txt'
--- lib/lp/archiveuploader/tests/nascentuploadfile.txt 2010-08-20 12:11:30 +0000
+++ lib/lp/archiveuploader/tests/nascentuploadfile.txt 2010-08-24 20:37:50 +0000
@@ -531,9 +531,10 @@
The timestamp of the files in the .deb are tested against the policy for being
too new:
+ >>> from lp.archiveuploader.uploadpolicy import ArchiveUploadType
>>> old_only_policy = getPolicy(
... name='insecure', distro='ubuntu', distroseries='hoary')
- >>> old_only_policy.can_upload_binaries = True
+ >>> old_only_policy.accepted_type = ArchiveUploadType.BINARY_ONLY
>>> old_only_policy.future_time_grace = -5 * 365 * 24 * 60 * 60
>>> ed_binary_deb = DebBinaryUploadFile(ed_deb_path,
@@ -549,7 +550,7 @@
>>> new_only_policy = getPolicy(
... name='insecure', distro='ubuntu', distroseries='hoary')
- >>> new_only_policy.can_upload_binaries = True
+ >>> new_only_policy.accepted_type = ArchiveUploadType.BINARY_ONLY
>>> new_only_policy.earliest_year = 2010
>>> ed_binary_deb = DebBinaryUploadFile(ed_deb_path,
... 'e31eeb0b6b3b87e1ea79378df864ffff',
=== modified file 'lib/lp/archiveuploader/tests/test_nascentupload_documentation.py'
--- lib/lp/archiveuploader/tests/test_nascentupload_documentation.py 2010-08-23 13:39:29 +0000
+++ lib/lp/archiveuploader/tests/test_nascentupload_documentation.py 2010-08-24 20:37:50 +0000
@@ -30,6 +30,7 @@
getPolicy,
mock_logger_quiet,
)
+from lp.archiveuploader.uploadpolicy import ArchiveUploadType
from lp.registry.interfaces.distribution import IDistributionSet
from lp.soyuz.interfaces.component import IComponentSet
@@ -52,7 +53,7 @@
def getUploadForBinary(upload_path):
"""Return a NascentUpload object for binaries."""
policy = getPolicy(name='sync', distro='ubuntu', distroseries='hoary')
- policy.can_upload_binaries = True
+ policy.accepted_type = ArchiveUploadType.BINARY_ONLY
return NascentUpload.from_changesfile_path(
datadir(upload_path), policy, mock_logger_quiet)
=== modified file 'lib/lp/archiveuploader/tests/test_ppauploadprocessor.py'
--- lib/lp/archiveuploader/tests/test_ppauploadprocessor.py 2010-08-20 20:31:18 +0000
+++ lib/lp/archiveuploader/tests/test_ppauploadprocessor.py 2010-08-24 20:37:50 +0000
@@ -681,12 +681,9 @@
"bar_1.0-1-mixed", "~name16/ubuntu")
self.processUpload(self.uploadprocessor, upload_dir)
- self.assertEqual(
- self.uploadprocessor.last_processed_upload.rejection_message,
- 'Upload rejected because it contains binary packages. Ensure '
- 'you are using `debuild -S`, or an equivalent command, to '
- 'generate only the source package before re-uploading. See '
- 'https://help.launchpad.net/Packaging/PPA for more information.')
+ self.assertIn(
+ 'Source/binary (i.e. mixed) uploads are not allowed.',
+ self.uploadprocessor.last_processed_upload.rejection_message)
def testPGPSignatureNotPreserved(self):
"""PGP signatures should be removed from PPA .changes files.
=== added file 'lib/lp/archiveuploader/tests/test_uploadpolicy.py'
--- lib/lp/archiveuploader/tests/test_uploadpolicy.py 1970-01-01 00:00:00 +0000
+++ lib/lp/archiveuploader/tests/test_uploadpolicy.py 2010-08-24 20:37:50 +0000
@@ -0,0 +1,110 @@
+#!/usr/bin/python
+#
+# Copyright 2010 Canonical Ltd. This software is licensed under the
+# GNU Affero General Public License version 3 (see the file LICENSE).
+
+from lp.archiveuploader.uploadpolicy import (
+ AbstractUploadPolicy, ArchiveUploadType)
+from lp.testing import TestCase
+
+
+class TestUploadPolicy_validateUploadType(TestCase):
+ """Test what kind (sourceful/binaryful/mixed) of uploads are accepted."""
+
+ def test_sourceful_accepted(self):
+ policy = make_policy(accepted_type=ArchiveUploadType.SOURCE_ONLY)
+ upload = make_fake_upload(sourceful=True)
+
+ policy.validateUploadType(upload)
+
+ self.assertEquals([], upload.rejections)
+
+ def test_binaryful_accepted(self):
+ policy = make_policy(accepted_type=ArchiveUploadType.BINARY_ONLY)
+ upload = make_fake_upload(binaryful=True)
+
+ policy.validateUploadType(upload)
+
+ self.assertEquals([], upload.rejections)
+
+ def test_mixed_accepted(self):
+ policy = make_policy(accepted_type=ArchiveUploadType.MIXED_ONLY)
+ upload = make_fake_upload(sourceful=True, binaryful=True)
+
+ policy.validateUploadType(upload)
+
+ self.assertEquals([], upload.rejections)
+
+ def test_sourceful_not_accepted(self):
+ policy = make_policy(accepted_type=ArchiveUploadType.BINARY_ONLY)
+ upload = make_fake_upload(sourceful=True)
+
+ policy.validateUploadType(upload)
+
+ self.assertIn(
+ 'Sourceful uploads are not accepted by this policy.',
+ upload.rejections)
+
+ def test_binaryful_not_accepted(self):
+ policy = make_policy(accepted_type=ArchiveUploadType.SOURCE_ONLY)
+ upload = make_fake_upload(binaryful=True)
+
+ policy.validateUploadType(upload)
+
+ self.assertTrue(len(upload.rejections) > 0)
+ self.assertIn(
+ 'Upload rejected because it contains binary packages.',
+ upload.rejections[0])
+
+ def test_mixed_not_accepted(self):
+ policy = make_policy(accepted_type=ArchiveUploadType.SOURCE_ONLY)
+ upload = make_fake_upload(sourceful=True, binaryful=True)
+
+ policy.validateUploadType(upload)
+
+ self.assertIn(
+ 'Source/binary (i.e. mixed) uploads are not allowed.',
+ upload.rejections)
+
+ def test_sourceful_when_only_mixed_accepted(self):
+ policy = make_policy(accepted_type=ArchiveUploadType.MIXED_ONLY)
+ upload = make_fake_upload(sourceful=True, binaryful=False)
+
+ policy.validateUploadType(upload)
+
+ self.assertIn(
+ 'Sourceful uploads are not accepted by this policy.',
+ upload.rejections)
+
+ def test_binaryful_when_only_mixed_accepted(self):
+ policy = make_policy(accepted_type=ArchiveUploadType.MIXED_ONLY)
+ upload = make_fake_upload(sourceful=False, binaryful=True)
+
+ policy.validateUploadType(upload)
+
+ self.assertTrue(len(upload.rejections) > 0)
+ self.assertIn(
+ 'Upload rejected because it contains binary packages.',
+ upload.rejections[0])
+
+
+class FakeNascentUpload:
+
+ def __init__(self, sourceful, binaryful):
+ self.sourceful = sourceful
+ self.binaryful = binaryful
+ self.is_ppa = False
+ self.rejections = []
+
+ def reject(self, msg):
+ self.rejections.append(msg)
+
+
+def make_fake_upload(sourceful=False, binaryful=False):
+ return FakeNascentUpload(sourceful, binaryful)
+
+
+def make_policy(accepted_type):
+ policy = AbstractUploadPolicy()
+ policy.accepted_type = accepted_type
+ return policy
=== modified file 'lib/lp/archiveuploader/uploadpolicy.py'
--- lib/lp/archiveuploader/uploadpolicy.py 2010-08-24 20:37:48 +0000
+++ lib/lp/archiveuploader/uploadpolicy.py 2010-08-24 20:37:50 +0000
@@ -7,6 +7,7 @@
__all__ = [
"AbstractUploadPolicy",
+ "ArchiveUploadType",
"BuildDaemonUploadPolicy",
"findPolicyByName",
"IArchiveUploadPolicy",
@@ -28,6 +29,9 @@
from lp.registry.interfaces.pocket import PackagePublishingPocket
from lp.registry.interfaces.series import SeriesStatus
+from lazr.enum import EnumeratedType, Item
+
+
# Defined here so that uploadpolicy.py doesn't depend on lp.code.
SOURCE_PACKAGE_RECIPE_UPLOAD_POLICY_NAME = 'recipe'
# Number of seconds in an hour (used later)
@@ -52,6 +56,13 @@
"""
+class ArchiveUploadType(EnumeratedType):
+
+ SOURCE_ONLY = Item("Source only")
+ BINARY_ONLY = Item("Binary only")
+ MIXED_ONLY = Item("Mixed only")
+
+
class AbstractUploadPolicy:
"""Encapsulate the policy of an upload to a launchpad archive.
@@ -63,8 +74,9 @@
"""
implements(IArchiveUploadPolicy)
+ name = 'abstract'
options = None
- name = 'abstract'
+ accepted_type = None # Must be defined in subclasses.
def __init__(self):
"""Prepare a policy..."""
@@ -75,14 +87,43 @@
self.unsigned_changes_ok = False
self.unsigned_dsc_ok = False
self.create_people = True
- self.can_upload_source = True
- self.can_upload_binaries = True
- self.can_upload_mixed = True
# future_time_grace is in seconds. 28800 is 8 hours
self.future_time_grace = 8 * HOURS
# The earliest year we accept in a deb's file's mtime
self.earliest_year = 1984
+ def validateUploadType(self, upload):
+ """Check that the type of the given upload is accepted by this policy.
+
+ When the type (e.g. sourceful, binaryful or mixed) is not accepted,
+ the upload is rejected.
+ """
+ if upload.sourceful and upload.binaryful:
+ if self.accepted_type != ArchiveUploadType.MIXED_ONLY:
+ upload.reject(
+ "Source/binary (i.e. mixed) uploads are not allowed.")
+
+ elif upload.sourceful:
+ if self.accepted_type != ArchiveUploadType.SOURCE_ONLY:
+ upload.reject(
+ "Sourceful uploads are not accepted by this policy.")
+
+ else:
+ assert upload.binaryful, (
+ "Upload is not sourceful, binaryful or mixed.")
+ if self.accepted_type != ArchiveUploadType.BINARY_ONLY:
+ messages = [
+ "Upload rejected because it contains binary packages.",
+ "Ensure you are using `debuild -S`, or an equivalent",
+ "command, to generate only the source package before",
+ "re-uploading.",
+ ]
+ if upload.is_ppa:
+ messages.append(
+ "See https://help.launchpad.net/Packaging/PPA for more "
+ "information.")
+ upload.reject(" ".join(messages))
+
def getUploader(self, changes):
"""Get the person who is doing the uploading."""
return changes.signer
@@ -171,11 +212,7 @@
"""The insecure upload policy is used by the poppy interface."""
name = 'insecure'
-
- def __init__(self):
- AbstractUploadPolicy.__init__(self)
- self.can_upload_binaries = False
- self.can_upload_mixed = False
+ accepted_type = ArchiveUploadType.SOURCE_ONLY
def rejectPPAUploads(self, upload):
"""Insecure policy allows PPA upload."""
@@ -283,14 +320,13 @@
"""The build daemon upload policy is invoked by the slave scanner."""
name = 'buildd'
+ accepted_type = ArchiveUploadType.BINARY_ONLY
def __init__(self):
super(BuildDaemonUploadPolicy, self).__init__()
# We permit unsigned uploads because we trust our build daemons
self.unsigned_changes_ok = True
self.unsigned_dsc_ok = True
- self.can_upload_source = False
- self.can_upload_mixed = False
def setOptions(self, options):
AbstractUploadPolicy.setOptions(self, options)
@@ -314,15 +350,13 @@
"""This policy is invoked when processing sync uploads."""
name = 'sync'
+ accepted_type = ArchiveUploadType.SOURCE_ONLY
def __init__(self):
AbstractUploadPolicy.__init__(self)
# We don't require changes or dsc to be signed for syncs
self.unsigned_changes_ok = True
self.unsigned_dsc_ok = True
- # We don't want binaries in a sync
- self.can_upload_mixed = False
- self.can_upload_binaries = False
def policySpecificChecks(self, upload):
"""Perform sync specific checks."""
=== modified file 'lib/lp/code/model/sourcepackagerecipebuild.py'
--- lib/lp/code/model/sourcepackagerecipebuild.py 2010-08-24 09:51:26 +0000
+++ lib/lp/code/model/sourcepackagerecipebuild.py 2010-08-24 20:37:50 +0000
@@ -40,6 +40,7 @@
from canonical.launchpad.webapp import errorlog
from lp.app.errors import NotFoundError
from lp.archiveuploader.uploadpolicy import (
+ ArchiveUploadType,
BuildDaemonUploadPolicy,
IArchiveUploadPolicy,
SOURCE_PACKAGE_RECIPE_UPLOAD_POLICY_NAME,
@@ -78,11 +79,7 @@
"""Policy for uploading the results of a source package recipe build."""
name = SOURCE_PACKAGE_RECIPE_UPLOAD_POLICY_NAME
-
- def __init__(self):
- super(SourcePackageRecipeUploadPolicy, self).__init__()
- self.can_upload_source = True
- self.can_upload_binaries = False
+ accepted_type = ArchiveUploadType.SOURCE_ONLY
def getUploader(self, changes):
"""Return the person doing the upload."""
=== modified file 'lib/lp/soyuz/browser/tests/distroseriesqueue-views.txt'
--- lib/lp/soyuz/browser/tests/distroseriesqueue-views.txt 2010-08-20 12:11:30 +0000
+++ lib/lp/soyuz/browser/tests/distroseriesqueue-views.txt 2010-08-24 20:37:50 +0000
@@ -253,6 +253,7 @@
... sourcename="foo", distroseries=hoary, version="1.0-2",
... status=PackagePublishingStatus.PUBLISHED)
+ >>> from lp.archiveuploader.uploadpolicy import ArchiveUploadType
>>> from canonical.launchpad.ftests import import_public_test_keys
>>> from canonical.launchpad.interfaces import IComponentSet
>>> from lp.soyuz.model.component import ComponentSelection
@@ -264,7 +265,7 @@
>>> trash = ComponentSelection(distroseries=hoary, component=universe)
>>> sync_policy = getPolicy(name='sync', distro='ubuntu',
... distroseries='hoary')
- >>> sync_policy.can_upload_binaries = True
+ >>> sync_policy.accepted_type = ArchiveUploadType.BINARY_ONLY
>>> foo_upload = NascentUpload.from_changesfile_path(
... datadir('suite/foo_1.0-2_multi_binary/foo_1.0-2_i386.changes'),
... sync_policy, mock_logger_quiet)