Commit 2c50a09a authored by Antoine Pitrou's avatar Antoine Pitrou

On behalf of Tarek: Issue #11501: disutils.archive_utils.make_zipfile no

longer fails if zlib is not installed. Instead, the zipfile.ZIP_STORED
compression is used to create the ZipFile. Patch by Natalia B. Bidart.
parent 7dedcb46
...@@ -9,6 +9,12 @@ import os ...@@ -9,6 +9,12 @@ import os
from warnings import warn from warnings import warn
import sys import sys
try:
import zipfile
except ImportError:
zipfile = None
from distutils.errors import DistutilsExecError from distutils.errors import DistutilsExecError
from distutils.spawn import spawn from distutils.spawn import spawn
from distutils.dir_util import mkpath from distutils.dir_util import mkpath
...@@ -74,11 +80,6 @@ def make_zipfile(base_name, base_dir, verbose=0, dry_run=0): ...@@ -74,11 +80,6 @@ def make_zipfile(base_name, base_dir, verbose=0, dry_run=0):
available, raises DistutilsExecError. Returns the name of the output zip available, raises DistutilsExecError. Returns the name of the output zip
file. file.
""" """
try:
import zipfile
except ImportError:
zipfile = None
zip_filename = base_name + ".zip" zip_filename = base_name + ".zip"
mkpath(os.path.dirname(zip_filename), dry_run=dry_run) mkpath(os.path.dirname(zip_filename), dry_run=dry_run)
...@@ -105,8 +106,12 @@ def make_zipfile(base_name, base_dir, verbose=0, dry_run=0): ...@@ -105,8 +106,12 @@ def make_zipfile(base_name, base_dir, verbose=0, dry_run=0):
zip_filename, base_dir) zip_filename, base_dir)
if not dry_run: if not dry_run:
zip = zipfile.ZipFile(zip_filename, "w", try:
compression=zipfile.ZIP_DEFLATED) zip = zipfile.ZipFile(zip_filename, "w",
compression=zipfile.ZIP_DEFLATED)
except RuntimeError:
zip = zipfile.ZipFile(zip_filename, "w",
compression=zipfile.ZIP_STORED)
for dirpath, dirnames, filenames in os.walk(base_dir): for dirpath, dirnames, filenames in os.walk(base_dir):
for name in filenames: for name in filenames:
......
...@@ -7,12 +7,13 @@ import tarfile ...@@ -7,12 +7,13 @@ import tarfile
from os.path import splitdrive from os.path import splitdrive
import warnings import warnings
from distutils import archive_util
from distutils.archive_util import (check_archive_formats, make_tarball, from distutils.archive_util import (check_archive_formats, make_tarball,
make_zipfile, make_archive, make_zipfile, make_archive,
ARCHIVE_FORMATS) ARCHIVE_FORMATS)
from distutils.spawn import find_executable, spawn from distutils.spawn import find_executable, spawn
from distutils.tests import support from distutils.tests import support
from test.support import check_warnings, run_unittest from test.support import check_warnings, run_unittest, patch
try: try:
import zipfile import zipfile
...@@ -20,10 +21,18 @@ try: ...@@ -20,10 +21,18 @@ try:
except ImportError: except ImportError:
ZIP_SUPPORT = find_executable('zip') ZIP_SUPPORT = find_executable('zip')
try:
import zlib
ZLIB_SUPPORT = True
except ImportError:
ZLIB_SUPPORT = False
class ArchiveUtilTestCase(support.TempdirManager, class ArchiveUtilTestCase(support.TempdirManager,
support.LoggingSilencer, support.LoggingSilencer,
unittest.TestCase): unittest.TestCase):
@unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
def test_make_tarball(self): def test_make_tarball(self):
# creating something to tar # creating something to tar
tmpdir = self.mkdtemp() tmpdir = self.mkdtemp()
...@@ -84,8 +93,9 @@ class ArchiveUtilTestCase(support.TempdirManager, ...@@ -84,8 +93,9 @@ class ArchiveUtilTestCase(support.TempdirManager,
base_name = os.path.join(tmpdir2, 'archive') base_name = os.path.join(tmpdir2, 'archive')
return tmpdir, tmpdir2, base_name return tmpdir, tmpdir2, base_name
@unittest.skipUnless(find_executable('tar') and find_executable('gzip'), @unittest.skipUnless(find_executable('tar') and find_executable('gzip')
'Need the tar command to run') and ZLIB_SUPPORT,
'Need the tar, gzip and zlib command to run')
def test_tarfile_vs_tar(self): def test_tarfile_vs_tar(self):
tmpdir, tmpdir2, base_name = self._create_files() tmpdir, tmpdir2, base_name = self._create_files()
old_dir = os.getcwd() old_dir = os.getcwd()
...@@ -169,7 +179,8 @@ class ArchiveUtilTestCase(support.TempdirManager, ...@@ -169,7 +179,8 @@ class ArchiveUtilTestCase(support.TempdirManager,
self.assertTrue(not os.path.exists(tarball)) self.assertTrue(not os.path.exists(tarball))
self.assertEqual(len(w.warnings), 1) self.assertEqual(len(w.warnings), 1)
@unittest.skipUnless(ZIP_SUPPORT, 'Need zip support to run') @unittest.skipUnless(ZIP_SUPPORT and ZLIB_SUPPORT,
'Need zip and zlib support to run')
def test_make_zipfile(self): def test_make_zipfile(self):
# creating something to tar # creating something to tar
tmpdir = self.mkdtemp() tmpdir = self.mkdtemp()
...@@ -182,6 +193,29 @@ class ArchiveUtilTestCase(support.TempdirManager, ...@@ -182,6 +193,29 @@ class ArchiveUtilTestCase(support.TempdirManager,
# check if the compressed tarball was created # check if the compressed tarball was created
tarball = base_name + '.zip' tarball = base_name + '.zip'
self.assertTrue(os.path.exists(tarball))
@unittest.skipUnless(ZIP_SUPPORT, 'Need zip support to run')
def test_make_zipfile_no_zlib(self):
patch(self, archive_util.zipfile, 'zlib', None) # force zlib ImportError
called = []
zipfile_class = zipfile.ZipFile
def fake_zipfile(*a, **kw):
if kw.get('compression', None) == zipfile.ZIP_STORED:
called.append((a, kw))
return zipfile_class(*a, **kw)
patch(self, archive_util.zipfile, 'ZipFile', fake_zipfile)
# create something to tar and compress
tmpdir, tmpdir2, base_name = self._create_files()
make_zipfile(base_name, tmpdir)
tarball = base_name + '.zip'
self.assertEqual(called,
[((tarball, "w"), {'compression': zipfile.ZIP_STORED})])
self.assertTrue(os.path.exists(tarball))
def test_check_archive_formats(self): def test_check_archive_formats(self):
self.assertEqual(check_archive_formats(['gztar', 'xxx', 'zip']), self.assertEqual(check_archive_formats(['gztar', 'xxx', 'zip']),
......
...@@ -18,6 +18,13 @@ setup(name='foo', version='0.1', py_modules=['foo'], ...@@ -18,6 +18,13 @@ setup(name='foo', version='0.1', py_modules=['foo'],
""" """
try:
import zlib
ZLIB_SUPPORT = True
except ImportError:
ZLIB_SUPPORT = False
class BuildDumbTestCase(support.TempdirManager, class BuildDumbTestCase(support.TempdirManager,
support.LoggingSilencer, support.LoggingSilencer,
support.EnvironGuard, support.EnvironGuard,
...@@ -34,6 +41,7 @@ class BuildDumbTestCase(support.TempdirManager, ...@@ -34,6 +41,7 @@ class BuildDumbTestCase(support.TempdirManager,
sys.argv[:] = self.old_sys_argv[1] sys.argv[:] = self.old_sys_argv[1]
super(BuildDumbTestCase, self).tearDown() super(BuildDumbTestCase, self).tearDown()
@unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
def test_simple_built(self): def test_simple_built(self):
# let's create a simple package # let's create a simple package
......
...@@ -40,6 +40,13 @@ somecode%(sep)sdoc.dat ...@@ -40,6 +40,13 @@ somecode%(sep)sdoc.dat
somecode%(sep)sdoc.txt somecode%(sep)sdoc.txt
""" """
try:
import zlib
ZLIB_SUPPORT = True
except ImportError:
ZLIB_SUPPORT = False
class SDistTestCase(PyPIRCCommandTestCase): class SDistTestCase(PyPIRCCommandTestCase):
def setUp(self): def setUp(self):
...@@ -78,6 +85,7 @@ class SDistTestCase(PyPIRCCommandTestCase): ...@@ -78,6 +85,7 @@ class SDistTestCase(PyPIRCCommandTestCase):
cmd.warn = _warn cmd.warn = _warn
return dist, cmd return dist, cmd
@unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
def test_prune_file_list(self): def test_prune_file_list(self):
# this test creates a package with some vcs dirs in it # this test creates a package with some vcs dirs in it
# and launch sdist to make sure they get pruned # and launch sdist to make sure they get pruned
...@@ -119,6 +127,7 @@ class SDistTestCase(PyPIRCCommandTestCase): ...@@ -119,6 +127,7 @@ class SDistTestCase(PyPIRCCommandTestCase):
# making sure everything has been pruned correctly # making sure everything has been pruned correctly
self.assertEqual(len(content), 4) self.assertEqual(len(content), 4)
@unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
def test_make_distribution(self): def test_make_distribution(self):
# check if tar and gzip are installed # check if tar and gzip are installed
...@@ -153,6 +162,7 @@ class SDistTestCase(PyPIRCCommandTestCase): ...@@ -153,6 +162,7 @@ class SDistTestCase(PyPIRCCommandTestCase):
result.sort() result.sort()
self.assertEqual(result, ['fake-1.0.tar', 'fake-1.0.tar.gz']) self.assertEqual(result, ['fake-1.0.tar', 'fake-1.0.tar.gz'])
@unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
def test_add_defaults(self): def test_add_defaults(self):
# http://bugs.python.org/issue2279 # http://bugs.python.org/issue2279
...@@ -218,6 +228,7 @@ class SDistTestCase(PyPIRCCommandTestCase): ...@@ -218,6 +228,7 @@ class SDistTestCase(PyPIRCCommandTestCase):
finally: finally:
f.close() f.close()
@unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
def test_metadata_check_option(self): def test_metadata_check_option(self):
# testing the `medata-check` option # testing the `medata-check` option
dist, cmd = self.get_cmd(metadata={}) dist, cmd = self.get_cmd(metadata={})
...@@ -277,7 +288,7 @@ class SDistTestCase(PyPIRCCommandTestCase): ...@@ -277,7 +288,7 @@ class SDistTestCase(PyPIRCCommandTestCase):
cmd.formats = 'supazipa' cmd.formats = 'supazipa'
self.assertRaises(DistutilsOptionError, cmd.finalize_options) self.assertRaises(DistutilsOptionError, cmd.finalize_options)
@unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
def test_get_file_list(self): def test_get_file_list(self):
# make sure MANIFEST is recalculated # make sure MANIFEST is recalculated
dist, cmd = self.get_cmd() dist, cmd = self.get_cmd()
...@@ -318,6 +329,7 @@ class SDistTestCase(PyPIRCCommandTestCase): ...@@ -318,6 +329,7 @@ class SDistTestCase(PyPIRCCommandTestCase):
self.assertEqual(len(manifest2), 6) self.assertEqual(len(manifest2), 6)
self.assertIn('doc2.txt', manifest2[-1]) self.assertIn('doc2.txt', manifest2[-1])
@unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
def test_manifest_marker(self): def test_manifest_marker(self):
# check that autogenerated MANIFESTs have a marker # check that autogenerated MANIFESTs have a marker
dist, cmd = self.get_cmd() dist, cmd = self.get_cmd()
...@@ -334,6 +346,7 @@ class SDistTestCase(PyPIRCCommandTestCase): ...@@ -334,6 +346,7 @@ class SDistTestCase(PyPIRCCommandTestCase):
self.assertEqual(manifest[0], self.assertEqual(manifest[0],
'# file GENERATED by distutils, do NOT edit') '# file GENERATED by distutils, do NOT edit')
@unittest.skipUnless(ZLIB_SUPPORT, 'Need zlib support to run')
def test_manual_manifest(self): def test_manual_manifest(self):
# check that a MANIFEST without a marker is left alone # check that a MANIFEST without a marker is left alone
dist, cmd = self.get_cmd() dist, cmd = self.get_cmd()
......
...@@ -1096,3 +1096,36 @@ def strip_python_stderr(stderr): ...@@ -1096,3 +1096,36 @@ def strip_python_stderr(stderr):
""" """
stderr = re.sub(br"\[\d+ refs\]\r?\n?$", b"", stderr).strip() stderr = re.sub(br"\[\d+ refs\]\r?\n?$", b"", stderr).strip()
return stderr return stderr
def patch(test_instance, object_to_patch, attr_name, new_value):
"""Override 'object_to_patch'.'attr_name' with 'new_value'.
Also, add a cleanup procedure to 'test_instance' to restore
'object_to_patch' value for 'attr_name'.
The 'attr_name' should be a valid attribute for 'object_to_patch'.
"""
# check that 'attr_name' is a real attribute for 'object_to_patch'
# will raise AttributeError if it does not exist
getattr(object_to_patch, attr_name)
# keep a copy of the old value
attr_is_local = False
try:
old_value = object_to_patch.__dict__[attr_name]
except (AttributeError, KeyError):
old_value = getattr(object_to_patch, attr_name, None)
else:
attr_is_local = True
# restore the value when the test is done
def cleanup():
if attr_is_local:
setattr(object_to_patch, attr_name, old_value)
else:
delattr(object_to_patch, attr_name)
test_instance.addCleanup(cleanup)
# actually override the attribute
setattr(object_to_patch, attr_name, new_value)
...@@ -72,6 +72,7 @@ Eric Beser ...@@ -72,6 +72,7 @@ Eric Beser
Steven Bethard Steven Bethard
Stephen Bevan Stephen Bevan
Ron Bickers Ron Bickers
Natalia B. Bidart
David Binger David Binger
Dominic Binks Dominic Binks
Philippe Biondi Philippe Biondi
......
...@@ -40,6 +40,10 @@ Core and Builtins ...@@ -40,6 +40,10 @@ Core and Builtins
Library Library
------- -------
- Issue #11501: disutils.archive_utils.make_zipfile no longer fails if zlib is
not installed. Instead, the zipfile.ZIP_STORED compression is used to create
the ZipFile. Patch by Natalia B. Bidart.
- Issue #11491: dbm.error is no longer raised when dbm.open is called with - Issue #11491: dbm.error is no longer raised when dbm.open is called with
the "n" as the flag argument and the file exists. The behavior matches the "n" as the flag argument and the file exists. The behavior matches
the documentation and general logic. the documentation and general logic.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment