1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
|
# From https://github.com/python/cpython/blob/main/Lib/test/test_shutil.py
# Copyright (C) 2003 Python Software Foundation
# stdlib
import os
import pathlib
import unittest.mock
from shutil import (
ReadError,
RegistryError,
get_archive_formats,
get_unpack_formats,
make_archive,
register_archive_format,
register_unpack_format,
unregister_archive_format,
unregister_unpack_format
)
from typing import no_type_check
# 3rd party
import pytest
from domdf_python_tools.paths import TemporaryPathPlus
# this package
from handy_archives import unpack_archive
from tests.utils import TESTFN, requires_bz2, requires_lzma, requires_zlib
try:
# stdlib
from test.support import FakePath # type: ignore[import]
except ImportError:
# stdlib
from test.support.os_helper import FakePath # type: ignore[import]
def rlistdir(path):
res = []
for name in sorted(os.listdir(path)):
p = os.path.join(path, name)
if os.path.isdir(p) and not os.path.islink(p):
res.append(name + '/')
for n in rlistdir(p):
res.append(name + '/' + n)
else:
res.append(name)
return res
def write_file(path, content, binary=False):
"""Write *content* to a file located at *path*.
If *path* is a tuple instead of a string, os.path.join will be used to
make a path. If *binary* is true, the file will be opened in binary
mode.
"""
if isinstance(path, tuple):
path = os.path.join(*path)
mode = "wb" if binary else 'w'
encoding = None if binary else "utf-8"
with open(path, mode, encoding=encoding) as fp:
fp.write(content)
class TestArchives(unittest.TestCase):
@no_type_check
def test_register_archive_format(self):
with pytest.raises(TypeError, match="The 1 object is not callable"):
register_archive_format("xxx", 1)
with pytest.raises(TypeError, match="extra_args needs to be a sequence"):
register_archive_format("xxx", lambda: os, 1)
with pytest.raises(TypeError, match=r"extra_args elements are : \(arg_name, value\)"):
register_archive_format("xxx", lambda: os, [(1, 2), (1, 2, 3)])
register_archive_format("xxx", lambda: os, [(1, 2)], "xxx file")
formats = [name for name, params in get_archive_formats()]
assert "xxx" in formats
unregister_archive_format("xxx")
formats = [name for name, params in get_archive_formats()]
assert "xxx" not in formats
### shutil.unpack_archive
def check_unpack_archive(self, format): # noqa: A002 # pylint: disable=redefined-builtin
self.check_unpack_archive_with_converter(format, lambda path: path)
self.check_unpack_archive_with_converter(format, pathlib.Path)
self.check_unpack_archive_with_converter(format, FakePath)
def check_unpack_archive_with_converter(
self,
format, # noqa: A002 # pylint: disable=redefined-builtin
converter,
):
base_dir = "dist"
with TemporaryPathPlus() as root_dir:
dist = os.path.join(root_dir, base_dir)
os.makedirs(dist, exist_ok=True)
write_file((dist, "file1"), "xxx")
write_file((dist, "file2"), "xxx")
os.mkdir(os.path.join(dist, "sub"))
write_file((dist, "sub", "file3"), "xxx")
os.mkdir(os.path.join(dist, "sub2"))
write_file((root_dir, "outer"), "xxx")
expected = rlistdir(root_dir)
expected.remove("outer")
with TemporaryPathPlus() as tmpdir:
base_name = os.path.join(tmpdir, "archive")
filename = make_archive(base_name, format, root_dir, base_dir)
# let's try to unpack it now
with TemporaryPathPlus() as tmpdir2:
unpack_archive(converter(filename), converter(str(tmpdir2)))
assert rlistdir(tmpdir2) == expected
# and again, this time with the format specified
with TemporaryPathPlus() as tmpdir3:
unpack_archive(converter(filename), converter(str(tmpdir3)), format=format)
assert rlistdir(tmpdir3) == expected
with pytest.raises(ReadError, match="Unknown archive format "):
unpack_archive(converter(TESTFN))
with pytest.raises(ValueError, match="Unknown unpack format 'xxx'"):
unpack_archive(converter(TESTFN), format="xxx")
def test_unpack_archive_tar(self):
self.check_unpack_archive("tar")
@requires_zlib()
def test_unpack_archive_gztar(self):
self.check_unpack_archive("gztar")
@requires_bz2()
def test_unpack_archive_bztar(self):
self.check_unpack_archive("bztar")
@requires_lzma()
def test_unpack_archive_xztar(self):
self.check_unpack_archive("xztar")
@requires_zlib()
def test_unpack_archive_zip(self):
self.check_unpack_archive("zip")
def test_unpack_registry(self):
formats = get_unpack_formats()
def _boo(filename, extract_dir, extra):
assert extra == 1
assert filename == "stuff.boo"
assert extract_dir == "xx"
register_unpack_format("Boo", [".boo", ".b2"], _boo, [("extra", 1)])
unpack_archive("stuff.boo", "xx")
# trying to register a .boo unpacker again
with pytest.raises(RegistryError):
register_unpack_format("Boo2", [".boo"], _boo) # type: ignore[arg-type]
# should work now
unregister_unpack_format("Boo")
register_unpack_format("Boo2", [".boo"], _boo) # type: ignore[arg-type]
assert ("Boo2", [".boo"], '') in get_unpack_formats()
assert ("Boo", [".boo"], '') not in get_unpack_formats()
# let's leave a clean state
unregister_unpack_format("Boo2")
assert get_unpack_formats() == formats
# def teardown_module(module):
# for tmpdir in
if __name__ == "__main__":
unittest.main()
|