Skip to content

Commit 527ef07

Browse files
Fix, refactor and extend tests for shutil.make_archive().
1 parent 2a23adf commit 527ef07

1 file changed

Lines changed: 83 additions & 89 deletions

File tree

Lib/test/test_shutil.py

Lines changed: 83 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from contextlib import ExitStack
1515
from os.path import splitdrive
1616
from distutils.spawn import find_executable, spawn
17-
from shutil import (_make_tarball, _make_zipfile, make_archive,
17+
from shutil import (make_archive,
1818
register_archive_format, unregister_archive_format,
1919
get_archive_formats, Error, unpack_archive,
2020
register_unpack_format, RegistryError,
@@ -86,6 +86,18 @@ def read_file(path, binary=False):
8686
with open(path, 'rb' if binary else 'r') as fp:
8787
return fp.read()
8888

89+
def rlistdir(path):
90+
res = []
91+
for name in sorted(os.listdir(path)):
92+
p = os.path.join(path, name)
93+
if os.path.isdir(p) and not os.path.islink(p):
94+
res.append(name + '/')
95+
for n in rlistdir(p):
96+
res.append(name + '/' + n)
97+
else:
98+
res.append(name)
99+
return res
100+
89101

90102
class TestShutil(unittest.TestCase):
91103

@@ -951,114 +963,105 @@ def test_copy2(self):
951963
@requires_zlib
952964
def test_make_tarball(self):
953965
# creating something to tar
954-
tmpdir = self.mkdtemp()
955-
write_file((tmpdir, 'file1'), 'xxx')
956-
write_file((tmpdir, 'file2'), 'xxx')
957-
os.mkdir(os.path.join(tmpdir, 'sub'))
958-
write_file((tmpdir, 'sub', 'file3'), 'xxx')
966+
root_dir, base_dir = self._create_files('')
959967

960968
tmpdir2 = self.mkdtemp()
961969
# force shutil to create the directory
962970
os.rmdir(tmpdir2)
963-
unittest.skipUnless(splitdrive(tmpdir)[0] == splitdrive(tmpdir2)[0],
971+
unittest.skipUnless(splitdrive(root_dir)[0] == splitdrive(tmpdir2)[0],
964972
"source and target should be on same drive")
965973

966974
base_name = os.path.join(tmpdir2, 'archive')
967975

968976
# working with relative paths to avoid tar warnings
969-
with support.change_cwd(tmpdir):
970-
_make_tarball(splitdrive(base_name)[1], '.')
977+
make_archive(splitdrive(base_name)[1], 'gztar', root_dir, '.')
971978

972979
# check if the compressed tarball was created
973980
tarball = base_name + '.tar.gz'
974-
self.assertTrue(os.path.exists(tarball))
981+
self.assertTrue(os.path.isfile(tarball))
982+
self.assertTrue(tarfile.is_tarfile(tarball))
983+
with tarfile.open(tarball, 'r:gz') as tf:
984+
self.assertCountEqual(tf.getnames(),
985+
['.', './sub', './sub2',
986+
'./file1', './file2', './sub/file3'])
975987

976988
# trying an uncompressed one
977989
base_name = os.path.join(tmpdir2, 'archive')
978-
with support.change_cwd(tmpdir):
979-
_make_tarball(splitdrive(base_name)[1], '.', compress=None)
990+
make_archive(splitdrive(base_name)[1], 'tar', root_dir, '.')
980991
tarball = base_name + '.tar'
981-
self.assertTrue(os.path.exists(tarball))
992+
self.assertTrue(os.path.isfile(tarball))
993+
self.assertTrue(tarfile.is_tarfile(tarball))
994+
with tarfile.open(tarball, 'r') as tf:
995+
self.assertCountEqual(tf.getnames(),
996+
['.', './sub', './sub2',
997+
'./file1', './file2', './sub/file3'])
982998

983999
def _tarinfo(self, path):
984-
tar = tarfile.open(path)
985-
try:
1000+
with tarfile.open(path) as tar:
9861001
names = tar.getnames()
9871002
names.sort()
9881003
return tuple(names)
989-
finally:
990-
tar.close()
9911004

992-
def _create_files(self):
1005+
def _create_files(self, base_dir='dist'):
9931006
# creating something to tar
994-
tmpdir = self.mkdtemp()
995-
dist = os.path.join(tmpdir, 'dist')
996-
os.mkdir(dist)
1007+
root_dir = self.mkdtemp()
1008+
dist = os.path.join(root_dir, base_dir)
1009+
os.makedirs(dist, exist_ok=True)
9971010
write_file((dist, 'file1'), 'xxx')
9981011
write_file((dist, 'file2'), 'xxx')
9991012
os.mkdir(os.path.join(dist, 'sub'))
10001013
write_file((dist, 'sub', 'file3'), 'xxx')
10011014
os.mkdir(os.path.join(dist, 'sub2'))
1002-
tmpdir2 = self.mkdtemp()
1003-
base_name = os.path.join(tmpdir2, 'archive')
1004-
return tmpdir, tmpdir2, base_name
1015+
if base_dir:
1016+
write_file((root_dir, 'outer'), 'xxx')
1017+
return root_dir, base_dir
10051018

10061019
@requires_zlib
1007-
@unittest.skipUnless(find_executable('tar') and find_executable('gzip'),
1020+
@unittest.skipUnless(find_executable('tar'),
10081021
'Need the tar command to run')
10091022
def test_tarfile_vs_tar(self):
1010-
tmpdir, tmpdir2, base_name = self._create_files()
1011-
with support.change_cwd(tmpdir):
1012-
_make_tarball(base_name, 'dist')
1023+
root_dir, base_dir = self._create_files()
1024+
base_name = os.path.join(self.mkdtemp(), 'archive')
1025+
make_archive(base_name, 'gztar', root_dir, base_dir)
10131026

10141027
# check if the compressed tarball was created
10151028
tarball = base_name + '.tar.gz'
1016-
self.assertTrue(os.path.exists(tarball))
1029+
self.assertTrue(os.path.isfile(tarball))
10171030

10181031
# now create another tarball using `tar`
1019-
tarball2 = os.path.join(tmpdir, 'archive2.tar.gz')
1020-
tar_cmd = ['tar', '-cf', 'archive2.tar', 'dist']
1021-
gzip_cmd = ['gzip', '-f9', 'archive2.tar']
1022-
with support.change_cwd(tmpdir):
1023-
with captured_stdout() as s:
1024-
spawn(tar_cmd)
1025-
spawn(gzip_cmd)
1026-
1027-
self.assertTrue(os.path.exists(tarball2))
1032+
tarball2 = os.path.join(root_dir, 'archive2.tar')
1033+
tar_cmd = ['tar', '-cf', 'archive2.tar', base_dir]
1034+
with support.change_cwd(root_dir), captured_stdout():
1035+
spawn(tar_cmd)
1036+
1037+
self.assertTrue(os.path.isfile(tarball2))
10281038
# let's compare both tarballs
10291039
self.assertEqual(self._tarinfo(tarball), self._tarinfo(tarball2))
10301040

10311041
# trying an uncompressed one
1032-
base_name = os.path.join(tmpdir2, 'archive')
1033-
with support.change_cwd(tmpdir):
1034-
_make_tarball(base_name, 'dist', compress=None)
1042+
make_archive(base_name, 'tar', root_dir, base_dir)
10351043
tarball = base_name + '.tar'
1036-
self.assertTrue(os.path.exists(tarball))
1044+
self.assertTrue(os.path.isfile(tarball))
10371045

10381046
# now for a dry_run
1039-
base_name = os.path.join(tmpdir2, 'archive')
1040-
with support.change_cwd(tmpdir):
1041-
_make_tarball(base_name, 'dist', compress=None, dry_run=True)
1047+
make_archive(base_name, 'tar', root_dir, base_dir, dry_run=True)
10421048
tarball = base_name + '.tar'
1043-
self.assertTrue(os.path.exists(tarball))
1049+
self.assertTrue(os.path.isfile(tarball))
10441050

10451051
@requires_zlib
10461052
@unittest.skipUnless(ZIP_SUPPORT, 'Need zip support to run')
10471053
def test_make_zipfile(self):
1048-
# creating something to tar
1049-
tmpdir = self.mkdtemp()
1050-
write_file((tmpdir, 'file1'), 'xxx')
1051-
write_file((tmpdir, 'file2'), 'xxx')
1052-
1053-
tmpdir2 = self.mkdtemp()
1054-
# force shutil to create the directory
1055-
os.rmdir(tmpdir2)
1056-
base_name = os.path.join(tmpdir2, 'archive')
1057-
_make_zipfile(base_name, tmpdir)
1054+
# creating something to zip
1055+
root_dir, base_dir = self._create_files()
1056+
base_name = os.path.join(self.mkdtemp(), 'archive')
1057+
res = make_archive(base_name, 'zip', root_dir, 'dist')
10581058

1059-
# check if the compressed tarball was created
1060-
tarball = base_name + '.zip'
1061-
self.assertTrue(os.path.exists(tarball))
1059+
self.assertEqual(res, base_name + '.zip')
1060+
self.assertTrue(os.path.isfile(res))
1061+
self.assertTrue(zipfile.is_zipfile(res))
1062+
with zipfile.ZipFile(res) as zf:
1063+
self.assertCountEqual(zf.namelist(),
1064+
['dist/file1', 'dist/file2', 'dist/sub/file3'])
10621065

10631066

10641067
def test_make_archive(self):
@@ -1076,36 +1079,37 @@ def test_make_archive_owner_group(self):
10761079
else:
10771080
group = owner = 'root'
10781081

1079-
base_dir, root_dir, base_name = self._create_files()
1080-
base_name = os.path.join(self.mkdtemp() , 'archive')
1082+
root_dir, base_dir = self._create_files()
1083+
base_name = os.path.join(self.mkdtemp(), 'archive')
10811084
res = make_archive(base_name, 'zip', root_dir, base_dir, owner=owner,
10821085
group=group)
1083-
self.assertTrue(os.path.exists(res))
1086+
self.assertTrue(os.path.isfile(res))
10841087

10851088
res = make_archive(base_name, 'zip', root_dir, base_dir)
1086-
self.assertTrue(os.path.exists(res))
1089+
self.assertTrue(os.path.isfile(res))
10871090

10881091
res = make_archive(base_name, 'tar', root_dir, base_dir,
10891092
owner=owner, group=group)
1090-
self.assertTrue(os.path.exists(res))
1093+
self.assertTrue(os.path.isfile(res))
10911094

10921095
res = make_archive(base_name, 'tar', root_dir, base_dir,
10931096
owner='kjhkjhkjg', group='oihohoh')
1094-
self.assertTrue(os.path.exists(res))
1097+
self.assertTrue(os.path.isfile(res))
10951098

10961099

10971100
@requires_zlib
10981101
@unittest.skipUnless(UID_GID_SUPPORT, "Requires grp and pwd support")
10991102
def test_tarfile_root_owner(self):
1100-
tmpdir, tmpdir2, base_name = self._create_files()
1103+
root_dir, base_dir = self._create_files()
1104+
base_name = os.path.join(self.mkdtemp(), 'archive')
11011105
group = grp.getgrgid(0)[0]
11021106
owner = pwd.getpwuid(0)[0]
1103-
with support.change_cwd(tmpdir):
1104-
archive_name = _make_tarball(base_name, 'dist', compress=None,
1105-
owner=owner, group=group)
1107+
with support.change_cwd(root_dir):
1108+
archive_name = make_archive(base_name, 'gztar', root_dir, 'dist',
1109+
owner=owner, group=group)
11061110

11071111
# check if the compressed tarball was created
1108-
self.assertTrue(os.path.exists(archive_name))
1112+
self.assertTrue(os.path.isfile(archive_name))
11091113

11101114
# now checks the rights
11111115
archive = tarfile.open(archive_name)
@@ -1162,40 +1166,30 @@ def test_register_archive_format(self):
11621166
formats = [name for name, params in get_archive_formats()]
11631167
self.assertNotIn('xxx', formats)
11641168

1165-
def _compare_dirs(self, dir1, dir2):
1166-
# check that dir1 and dir2 are equivalent,
1167-
# return the diff
1168-
diff = []
1169-
for root, dirs, files in os.walk(dir1):
1170-
for file_ in files:
1171-
path = os.path.join(root, file_)
1172-
target_path = os.path.join(dir2, os.path.split(path)[-1])
1173-
if not os.path.exists(target_path):
1174-
diff.append(file_)
1175-
return diff
1176-
11771169
@requires_zlib
11781170
def test_unpack_archive(self):
11791171
formats = ['tar', 'gztar', 'zip']
11801172
if BZ2_SUPPORTED:
11811173
formats.append('bztar')
11821174

1175+
root_dir, base_dir = self._create_files()
11831176
for format in formats:
1184-
tmpdir = self.mkdtemp()
1185-
base_dir, root_dir, base_name = self._create_files()
1186-
tmpdir2 = self.mkdtemp()
1177+
expected = rlistdir(root_dir)
1178+
expected.remove('outer')
1179+
if format == 'zip':
1180+
expected.remove('dist/sub2/')
1181+
base_name = os.path.join(self.mkdtemp(), 'archive')
11871182
filename = make_archive(base_name, format, root_dir, base_dir)
11881183

11891184
# let's try to unpack it now
1185+
tmpdir2 = self.mkdtemp()
11901186
unpack_archive(filename, tmpdir2)
1191-
diff = self._compare_dirs(tmpdir, tmpdir2)
1192-
self.assertEqual(diff, [])
1187+
self.assertEqual(rlistdir(tmpdir2), expected)
11931188

11941189
# and again, this time with the format specified
11951190
tmpdir3 = self.mkdtemp()
11961191
unpack_archive(filename, tmpdir3, format=format)
1197-
diff = self._compare_dirs(tmpdir, tmpdir3)
1198-
self.assertEqual(diff, [])
1192+
self.assertEqual(rlistdir(tmpdir3), expected)
11991193
self.assertRaises(shutil.ReadError, unpack_archive, TESTFN)
12001194
self.assertRaises(ValueError, unpack_archive, TESTFN, format='xxx')
12011195

0 commit comments

Comments
 (0)