File: test_unpack_archive.py

package info (click to toggle)
python-handy-archives 0.2.0-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,300 kB
  • sloc: python: 4,153; makefile: 5
file content (180 lines) | stat: -rw-r--r-- 5,357 bytes parent folder | download
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()