diff options
Diffstat (limited to 'Lib/test')
25 files changed, 702 insertions, 222 deletions
diff --git a/Lib/test/test_asyncio/test_base_events.py b/Lib/test/test_asyncio/test_base_events.py index db15244..9f36896 100644 --- a/Lib/test/test_asyncio/test_base_events.py +++ b/Lib/test/test_asyncio/test_base_events.py @@ -5,6 +5,7 @@ import socket import time import unittest import unittest.mock +from test.support import find_unused_port, IPV6_ENABLED from asyncio import base_events from asyncio import events @@ -533,6 +534,7 @@ class BaseEventLoopWithSelectorTests(unittest.TestCase): self.assertRaises( OSError, self.loop.run_until_complete, coro) + @unittest.skipUnless(IPV6_ENABLED, 'IPv6 not supported or enabled') def test_create_datagram_endpoint_no_matching_family(self): coro = self.loop.create_datagram_endpoint( protocols.DatagramProtocol, @@ -588,3 +590,7 @@ class BaseEventLoopWithSelectorTests(unittest.TestCase): self.loop._accept_connection(MyProto, sock) self.assertTrue(sock.close.called) self.assertTrue(m_log.exception.called) + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py index f0f4810..98896e8 100644 --- a/Lib/test/test_asyncio/test_events.py +++ b/Lib/test/test_asyncio/test_events.py @@ -896,8 +896,8 @@ class EventLoopTestsMixin: proto = MyWritePipeProto(loop=self.loop) return proto - rpipe, wpipe = os.pipe() - pipeobj = io.open(wpipe, 'wb', 1024) + rsock, wsock = self.loop._socketpair() + pipeobj = io.open(wsock.detach(), 'wb', 1024) @tasks.coroutine def connect(): @@ -913,11 +913,10 @@ class EventLoopTestsMixin: self.assertEqual('CONNECTED', proto.state) transport.write(b'1') - test_utils.run_briefly(self.loop) - data = os.read(rpipe, 1024) + data = self.loop.run_until_complete(self.loop.sock_recv(rsock, 1024)) self.assertEqual(b'1', data) - os.close(rpipe) + rsock.close() self.loop.run_until_complete(proto.done) self.assertEqual('CLOSED', proto.state) @@ -986,9 +985,6 @@ class EventLoopTestsMixin: @unittest.skipIf(sys.platform == 'win32', "Don't support subprocess for Windows yet") - # Issue #19293 - @unittest.skipIf(sys.platform.startswith("aix"), - 'cannot be interrupted with signal on AIX') def test_subprocess_interactive(self): proto = None transp = None @@ -1087,9 +1083,6 @@ class EventLoopTestsMixin: @unittest.skipIf(sys.platform == 'win32', "Don't support subprocess for Windows yet") - # Issue #19293 - @unittest.skipIf(sys.platform.startswith("aix"), - 'cannot be interrupted with signal on AIX') def test_subprocess_kill(self): proto = None transp = None @@ -1113,9 +1106,6 @@ class EventLoopTestsMixin: @unittest.skipIf(sys.platform == 'win32', "Don't support subprocess for Windows yet") - # Issue #19293 - @unittest.skipIf(sys.platform.startswith("aix"), - 'cannot be interrupted with signal on AIX') def test_subprocess_send_signal(self): proto = None transp = None @@ -1233,6 +1223,26 @@ class EventLoopTestsMixin: self.loop.run_until_complete(proto.completed) self.assertEqual(-signal.SIGTERM, proto.returncode) + @unittest.skipIf(sys.platform == 'win32', + "Don't support subprocess for Windows yet") + def test_subprocess_wait_no_same_group(self): + proto = None + transp = None + + @tasks.coroutine + def connect(): + nonlocal proto + # start the new process in a new session + transp, proto = yield from self.loop.subprocess_shell( + functools.partial(MySubprocessProtocol, self.loop), + 'exit 7', stdin=None, stdout=None, stderr=None, + start_new_session=True) + self.assertIsInstance(proto, MySubprocessProtocol) + + self.loop.run_until_complete(connect()) + self.loop.run_until_complete(proto.completed) + self.assertEqual(7, proto.returncode) + if sys.platform == 'win32': from asyncio import windows_events diff --git a/Lib/test/test_asyncio/test_proactor_events.py b/Lib/test/test_asyncio/test_proactor_events.py index 05d1606..5a2a51c 100644 --- a/Lib/test/test_asyncio/test_proactor_events.py +++ b/Lib/test/test_asyncio/test_proactor_events.py @@ -478,3 +478,7 @@ class BaseProactorEventLoopTests(unittest.TestCase): self.loop._stop_serving(sock) self.assertTrue(sock.close.called) self.proactor._stop_serving.assert_called_with(sock) + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_asyncio/test_selector_events.py b/Lib/test/test_asyncio/test_selector_events.py index 53728b8..fbd5d72 100644 --- a/Lib/test/test_asyncio/test_selector_events.py +++ b/Lib/test/test_asyncio/test_selector_events.py @@ -1483,3 +1483,7 @@ class SelectorDatagramTransportTests(unittest.TestCase): transport._fatal_error(err) self.protocol.connection_refused.assert_called_with(err) m_exc.assert_called_with('Fatal error for %s', transport) + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_asyncio/test_selectors.py b/Lib/test/test_asyncio/test_selectors.py index 2f7dc69..db5b3ec 100644 --- a/Lib/test/test_asyncio/test_selectors.py +++ b/Lib/test/test_asyncio/test_selectors.py @@ -143,3 +143,7 @@ class BaseSelectorTests(unittest.TestCase): if hasattr(selectors.DefaultSelector, 'fileno'): def test_fileno(self): self.assertIsInstance(selectors.DefaultSelector().fileno(), int) + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_asyncio/test_transports.py b/Lib/test/test_asyncio/test_transports.py index 53071af..f96445c 100644 --- a/Lib/test/test_asyncio/test_transports.py +++ b/Lib/test/test_asyncio/test_transports.py @@ -53,3 +53,7 @@ class TransportTests(unittest.TestCase): self.assertRaises(NotImplementedError, transport.send_signal, 1) self.assertRaises(NotImplementedError, transport.terminate) self.assertRaises(NotImplementedError, transport.kill) + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index ccabeea..f29e7af 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -266,7 +266,7 @@ class SelectorEventLoopTests(unittest.TestCase): self.loop._subprocesses[7] = transp self.loop._sig_chld() - self.assertFalse(transp._process_exited.called) + self.assertTrue(transp._process_exited.called) self.assertFalse(m_WEXITSTATUS.called) self.assertFalse(m_WTERMSIG.called) @@ -312,6 +312,13 @@ class UnixReadPipeTransportTests(unittest.TestCase): fcntl_patcher.start() self.addCleanup(fcntl_patcher.stop) + fstat_patcher = unittest.mock.patch('os.fstat') + m_fstat = fstat_patcher.start() + st = unittest.mock.Mock() + st.st_mode = stat.S_IFIFO + m_fstat.return_value = st + self.addCleanup(fstat_patcher.stop) + def test_ctor(self): tr = unix_events._UnixReadPipeTransport( self.loop, self.pipe, self.protocol) @@ -768,3 +775,7 @@ class UnixWritePipeTransportTests(unittest.TestCase): tr.write_eof() self.assertTrue(tr._closing) self.assertFalse(self.protocol.connection_lost.called) + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_asyncio/test_windows_events.py b/Lib/test/test_asyncio/test_windows_events.py index 4b04073..969360c 100644 --- a/Lib/test/test_asyncio/test_windows_events.py +++ b/Lib/test/test_asyncio/test_windows_events.py @@ -93,3 +93,7 @@ class ProactorTests(unittest.TestCase): protocols.Protocol, ADDRESS) return 'done' + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_asyncio/test_windows_utils.py b/Lib/test/test_asyncio/test_windows_utils.py index 3b6b036..f721d31 100644 --- a/Lib/test/test_asyncio/test_windows_utils.py +++ b/Lib/test/test_asyncio/test_windows_utils.py @@ -138,3 +138,7 @@ class PopenTests(unittest.TestCase): # allow for partial reads... self.assertTrue(msg.upper().rstrip().startswith(out)) self.assertTrue(b"stderr".startswith(err)) + + +if __name__ == '__main__': + unittest.main() diff --git a/Lib/test/test_audioop.py b/Lib/test/test_audioop.py index b6b53ba..cf0ef7b 100644 --- a/Lib/test/test_audioop.py +++ b/Lib/test/test_audioop.py @@ -1,7 +1,6 @@ import audioop import sys import unittest -from test.support import run_unittest def pack(width, data): return b''.join(v.to_bytes(width, sys.byteorder, signed=True) for v in data) @@ -87,6 +86,7 @@ class TestAudioop(unittest.TestCase): self.assertEqual(audioop.avgpp(packs[w](9, 10, 5, 5, 0, 1), w), 10) self.assertEqual(audioop.avgpp(datas[1], 1), 196) self.assertEqual(audioop.avgpp(datas[2], 2), 50534) + self.assertEqual(audioop.avgpp(datas[3], 3), 12937096) self.assertEqual(audioop.avgpp(datas[4], 4), 3311897002) def test_rms(self): @@ -100,6 +100,7 @@ class TestAudioop(unittest.TestCase): -minvalues[w], delta=1) self.assertEqual(audioop.rms(datas[1], 1), 77) self.assertEqual(audioop.rms(datas[2], 2), 20001) + self.assertEqual(audioop.rms(datas[3], 3), 5120523) self.assertEqual(audioop.rms(datas[4], 4), 1310854152) def test_cross(self): @@ -227,10 +228,9 @@ class TestAudioop(unittest.TestCase): def test_lin2adpcm(self): self.assertEqual(audioop.lin2adpcm(datas[1], 1, None), (b'\x07\x7f\x7f', (-221, 39))) - self.assertEqual(audioop.lin2adpcm(datas[2], 2, None), - (b'\x07\x7f\x7f', (31, 39))) - self.assertEqual(audioop.lin2adpcm(datas[4], 4, None), - (b'\x07\x7f\x7f', (31, 39))) + for w in 2, 3, 4: + self.assertEqual(audioop.lin2adpcm(datas[w], w, None), + (b'\x07\x7f\x7f', (31, 39))) # Very cursory test for w in 1, 2, 3, 4: @@ -240,10 +240,9 @@ class TestAudioop(unittest.TestCase): def test_lin2alaw(self): self.assertEqual(audioop.lin2alaw(datas[1], 1), b'\xd5\x87\xa4\x24\xaa\x2a\x5a') - self.assertEqual(audioop.lin2alaw(datas[2], 2), - b'\xd5\x87\xa4\x24\xaa\x2a\x55') - self.assertEqual(audioop.lin2alaw(datas[4], 4), - b'\xd5\x87\xa4\x24\xaa\x2a\x55') + for w in 2, 3, 4: + self.assertEqual(audioop.lin2alaw(datas[w], w), + b'\xd5\x87\xa4\x24\xaa\x2a\x55') def test_alaw2lin(self): encoded = b'\x00\x03\x24\x2a\x51\x54\x55\x58\x6b\x71\x7f'\ @@ -262,10 +261,9 @@ class TestAudioop(unittest.TestCase): def test_lin2ulaw(self): self.assertEqual(audioop.lin2ulaw(datas[1], 1), b'\xff\xad\x8e\x0e\x80\x00\x67') - self.assertEqual(audioop.lin2ulaw(datas[2], 2), - b'\xff\xad\x8e\x0e\x80\x00\x7e') - self.assertEqual(audioop.lin2ulaw(datas[4], 4), - b'\xff\xad\x8e\x0e\x80\x00\x7e') + for w in 2, 3, 4: + self.assertEqual(audioop.lin2ulaw(datas[w], w), + b'\xff\xad\x8e\x0e\x80\x00\x7e') def test_ulaw2lin(self): encoded = b'\x00\x0e\x28\x3f\x57\x6a\x76\x7c\x7e\x7f'\ @@ -416,8 +414,5 @@ class TestAudioop(unittest.TestCase): self.assertRaises(audioop.error, audioop.alaw2lin, data, size) self.assertRaises(audioop.error, audioop.adpcm2lin, data, size, state) -def test_main(): - run_unittest(TestAudioop) - if __name__ == '__main__': - test_main() + unittest.main() diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index 90efb27..595d540 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -4519,8 +4519,10 @@ order (MRO) for bases """ global Y class Y: - pass + class Inside: + pass self.assertEqual(Y.__qualname__, 'Y') + self.assertEqual(Y.Inside.__qualname__, 'Y.Inside') def test_qualname_dict(self): ns = {'__qualname__': 'some.name'} diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py index 77477df..d5a31b8 100644 --- a/Lib/test/test_enum.py +++ b/Lib/test/test_enum.py @@ -1,8 +1,11 @@ import enum +import inspect +import pydoc import unittest from collections import OrderedDict +from enum import Enum, IntEnum, EnumMeta, unique +from io import StringIO from pickle import dumps, loads, PicklingError -from enum import Enum, IntEnum, unique # for pickle tests try: @@ -1195,5 +1198,117 @@ class TestUnique(unittest.TestCase): turkey = 3 +expected_help_output = """ +Help on class Color in module %s: + +class Color(enum.Enum) + | Method resolution order: + | Color + | enum.Enum + | builtins.object + |\x20\x20 + | Data and other attributes defined here: + |\x20\x20 + | blue = <Color.blue: 3> + |\x20\x20 + | green = <Color.green: 2> + |\x20\x20 + | red = <Color.red: 1> + |\x20\x20 + | ---------------------------------------------------------------------- + | Data descriptors inherited from enum.Enum: + |\x20\x20 + | name + | The name of the Enum member. + |\x20\x20 + | value + | The value of the Enum member. + |\x20\x20 + | ---------------------------------------------------------------------- + | Data descriptors inherited from enum.EnumMeta: + |\x20\x20 + | __members__ + | Returns a mapping of member name->value. + |\x20\x20\x20\x20\x20\x20 + | This mapping lists all enum members, including aliases. Note that this + | is a read-only view of the internal mapping. +""".strip() + +class TestStdLib(unittest.TestCase): + + class Color(Enum): + red = 1 + green = 2 + blue = 3 + + def test_pydoc(self): + # indirectly test __objclass__ + expected_text = expected_help_output % __name__ + output = StringIO() + helper = pydoc.Helper(output=output) + helper(self.Color) + result = output.getvalue().strip() + if result != expected_text: + print_diffs(expected_text, result) + self.fail("outputs are not equal, see diff above") + + def test_inspect_getmembers(self): + values = dict(( + ('__class__', EnumMeta), + ('__doc__', None), + ('__members__', self.Color.__members__), + ('__module__', __name__), + ('blue', self.Color.blue), + ('green', self.Color.green), + ('name', Enum.__dict__['name']), + ('red', self.Color.red), + ('value', Enum.__dict__['value']), + )) + result = dict(inspect.getmembers(self.Color)) + self.assertEqual(values.keys(), result.keys()) + failed = False + for k in values.keys(): + if result[k] != values[k]: + print() + print('\n%s\n key: %s\n result: %s\nexpected: %s\n%s\n' % + ('=' * 75, k, result[k], values[k], '=' * 75), sep='') + failed = True + if failed: + self.fail("result does not equal expected, see print above") + + def test_inspect_classify_class_attrs(self): + # indirectly test __objclass__ + from inspect import Attribute + values = [ + Attribute(name='__class__', kind='data', + defining_class=object, object=EnumMeta), + Attribute(name='__doc__', kind='data', + defining_class=self.Color, object=None), + Attribute(name='__members__', kind='property', + defining_class=EnumMeta, object=EnumMeta.__members__), + Attribute(name='__module__', kind='data', + defining_class=self.Color, object=__name__), + Attribute(name='blue', kind='data', + defining_class=self.Color, object=self.Color.blue), + Attribute(name='green', kind='data', + defining_class=self.Color, object=self.Color.green), + Attribute(name='red', kind='data', + defining_class=self.Color, object=self.Color.red), + Attribute(name='name', kind='data', + defining_class=Enum, object=Enum.__dict__['name']), + Attribute(name='value', kind='data', + defining_class=Enum, object=Enum.__dict__['value']), + ] + values.sort(key=lambda item: item.name) + result = list(inspect.classify_class_attrs(self.Color)) + result.sort(key=lambda item: item.name) + failed = False + for v, r in zip(values, result): + if r != v: + print('\n%s\n%s\n%s\n%s\n' % ('=' * 75, r, v, '=' * 75), sep='') + failed = True + if failed: + self.fail("result does not equal expected, see print above") + if __name__ == '__main__': unittest.main() diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py index 2d374b9..ebd99ed 100644 --- a/Lib/test/test_faulthandler.py +++ b/Lib/test/test_faulthandler.py @@ -72,9 +72,9 @@ class FaultHandlerTests(unittest.TestCase): Raise an error if the output doesn't match the expected format. """ if all_threads: - header = 'Current thread XXX' + header = 'Current thread XXX (most recent call first)' else: - header = 'Traceback (most recent call first)' + header = 'Stack (most recent call first)' regex = """ ^Fatal Python error: {name} @@ -306,7 +306,7 @@ funcA() else: lineno = 8 expected = [ - 'Traceback (most recent call first):', + 'Stack (most recent call first):', ' File "<string>", line %s in funcB' % lineno, ' File "<string>", line 11 in funcA', ' File "<string>", line 13 in <module>' @@ -338,7 +338,7 @@ def {func_name}(): func_name=func_name, ) expected = [ - 'Traceback (most recent call first):', + 'Stack (most recent call first):', ' File "<string>", line 4 in %s' % truncated, ' File "<string>", line 6 in <module>' ] @@ -392,13 +392,13 @@ waiter.join() else: lineno = 10 regex = """ -^Thread 0x[0-9a-f]+: +^Thread 0x[0-9a-f]+ \(most recent call first\): (?: File ".*threading.py", line [0-9]+ in [_a-z]+ ){{1,3}} File "<string>", line 23 in run File ".*threading.py", line [0-9]+ in _bootstrap_inner File ".*threading.py", line [0-9]+ in _bootstrap -Current thread XXX: +Current thread XXX \(most recent call first\): File "<string>", line {lineno} in dump File "<string>", line 28 in <module>$ """.strip() @@ -461,7 +461,7 @@ if file is not None: count = loops if repeat: count *= 2 - header = r'Timeout \(%s\)!\nThread 0x[0-9a-f]+:\n' % timeout_str + header = r'Timeout \(%s\)!\nThread 0x[0-9a-f]+ \(most recent call first\):\n' % timeout_str regex = expected_traceback(9, 20, header, min_count=count) self.assertRegex(trace, regex) else: @@ -563,9 +563,9 @@ sys.exit(exitcode) trace = '\n'.join(trace) if not unregister: if all_threads: - regex = 'Current thread XXX:\n' + regex = 'Current thread XXX \(most recent call first\):\n' else: - regex = 'Traceback \(most recent call first\):\n' + regex = 'Stack \(most recent call first\):\n' regex = expected_traceback(7, 28, regex) self.assertRegex(trace, regex) else: diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py index 47563c8..c0b537a 100644 --- a/Lib/test/test_ftplib.py +++ b/Lib/test/test_ftplib.py @@ -92,6 +92,7 @@ class DummyFTPHandler(asynchat.async_chat): self.next_response = '' self.next_data = None self.rest = None + self.next_retr_data = RETR_DATA self.push('220 welcome') def collect_incoming_data(self, data): @@ -221,7 +222,7 @@ class DummyFTPHandler(asynchat.async_chat): offset = int(self.rest) else: offset = 0 - self.dtp.push(RETR_DATA[offset:]) + self.dtp.push(self.next_retr_data[offset:]) self.dtp.close_when_done() self.rest = None @@ -243,6 +244,11 @@ class DummyFTPHandler(asynchat.async_chat): self.dtp.push(MLSD_DATA) self.dtp.close_when_done() + def cmd_setlongretr(self, arg): + # For testing. Next RETR will return long line. + self.next_retr_data = 'x' * int(arg) + self.push('125 setlongretr ok') + class DummyFTPServer(asyncore.dispatcher, threading.Thread): @@ -759,6 +765,20 @@ class TestFTPClass(TestCase): self.assertEqual(ftplib.parse257('257 "/foo/b""ar"'), '/foo/b"ar') self.assertEqual(ftplib.parse257('257 "/foo/b""ar" created'), '/foo/b"ar') + def test_line_too_long(self): + self.assertRaises(ftplib.Error, self.client.sendcmd, + 'x' * self.client.maxline * 2) + + def test_retrlines_too_long(self): + self.client.sendcmd('SETLONGRETR %d' % (self.client.maxline * 2)) + received = [] + self.assertRaises(ftplib.Error, + self.client.retrlines, 'retr', received.append) + + def test_storlines_too_long(self): + f = io.BytesIO(b'x' * self.client.maxline * 2) + self.assertRaises(ftplib.Error, self.client.storlines, 'stor', f) + class TestIPv6Environment(TestCase): diff --git a/Lib/test/test_funcattrs.py b/Lib/test/test_funcattrs.py index 1d8fa13..5094f7b 100644 --- a/Lib/test/test_funcattrs.py +++ b/Lib/test/test_funcattrs.py @@ -9,7 +9,9 @@ def global_function(): pass global inner_global_function def inner_global_function(): - pass + def inner_function2(): + pass + return inner_function2 return LocalClass return lambda: inner_function @@ -120,6 +122,7 @@ class FunctionPropertiesTest(FuncAttrsTest): self.assertEqual(global_function()()().__qualname__, 'global_function.<locals>.inner_function.<locals>.LocalClass') self.assertEqual(inner_global_function.__qualname__, 'inner_global_function') + self.assertEqual(inner_global_function().__qualname__, 'inner_global_function.<locals>.inner_function2') self.b.__qualname__ = 'c' self.assertEqual(self.b.__qualname__, 'c') self.b.__qualname__ = 'd' diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py index 653f01c..4a5ea7f 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -84,26 +84,30 @@ class HashLibTestCase(unittest.TestCase): if constructor: constructors.add(constructor) + def add_builtin_constructor(name): + constructor = getattr(hashlib, "__get_builtin_constructor")(name) + self.constructors_to_test[name].add(constructor) + _md5 = self._conditional_import_module('_md5') if _md5: - self.constructors_to_test['md5'].add(_md5.md5) + add_builtin_constructor('md5') _sha1 = self._conditional_import_module('_sha1') if _sha1: - self.constructors_to_test['sha1'].add(_sha1.sha1) + add_builtin_constructor('sha1') _sha256 = self._conditional_import_module('_sha256') if _sha256: - self.constructors_to_test['sha224'].add(_sha256.sha224) - self.constructors_to_test['sha256'].add(_sha256.sha256) + add_builtin_constructor('sha224') + add_builtin_constructor('sha256') _sha512 = self._conditional_import_module('_sha512') if _sha512: - self.constructors_to_test['sha384'].add(_sha512.sha384) - self.constructors_to_test['sha512'].add(_sha512.sha512) + add_builtin_constructor('sha384') + add_builtin_constructor('sha512') _sha3 = self._conditional_import_module('_sha3') if _sha3: - self.constructors_to_test['sha3_224'].add(_sha3.sha3_224) - self.constructors_to_test['sha3_256'].add(_sha3.sha3_256) - self.constructors_to_test['sha3_384'].add(_sha3.sha3_384) - self.constructors_to_test['sha3_512'].add(_sha3.sha3_512) + add_builtin_constructor('sha3_224') + add_builtin_constructor('sha3_256') + add_builtin_constructor('sha3_384') + add_builtin_constructor('sha3_512') super(HashLibTestCase, self).__init__(*args, **kwargs) @@ -132,8 +136,10 @@ class HashLibTestCase(unittest.TestCase): self.assertRaises(TypeError, hashlib.new, 1) def test_get_builtin_constructor(self): - get_builtin_constructor = hashlib.__dict__[ - '__get_builtin_constructor'] + get_builtin_constructor = getattr(hashlib, + '__get_builtin_constructor') + builtin_constructor_cache = getattr(hashlib, + '__builtin_constructor_cache') self.assertRaises(ValueError, get_builtin_constructor, 'test') try: import _md5 @@ -141,6 +147,8 @@ class HashLibTestCase(unittest.TestCase): pass # This forces an ImportError for "import _md5" statements sys.modules['_md5'] = None + # clear the cache + builtin_constructor_cache.clear() try: self.assertRaises(ValueError, get_builtin_constructor, 'md5') finally: @@ -149,6 +157,9 @@ class HashLibTestCase(unittest.TestCase): else: del sys.modules['_md5'] self.assertRaises(TypeError, get_builtin_constructor, 3) + constructor = get_builtin_constructor('md5') + self.assertIs(constructor, _md5.md5) + self.assertEqual(sorted(builtin_constructor_cache), ['MD5', 'md5']) def test_hexdigest(self): for cons in self.hash_constructors: diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py index fb6aa6a..9d34904 100644 --- a/Lib/test/test_inspect.py +++ b/Lib/test/test_inspect.py @@ -667,9 +667,19 @@ class TestClassesAndFunctions(unittest.TestCase): return 'eggs' should_find_dca = inspect.Attribute('ham', 'data', VA, VA.__dict__['ham']) self.assertIn(should_find_dca, inspect.classify_class_attrs(VA)) - should_find_ga = inspect.Attribute('ham', 'data', VA, 'spam') + should_find_ga = inspect.Attribute('ham', 'data', Meta, 'spam') self.assertIn(should_find_ga, inspect.classify_class_attrs(VA)) + def test_classify_metaclass_class_attribute(self): + class Meta(type): + fish = 'slap' + def __dir__(self): + return ['__class__', '__modules__', '__name__', 'fish'] + class Class(metaclass=Meta): + pass + should_find = inspect.Attribute('fish', 'data', Meta, 'slap') + self.assertIn(should_find, inspect.classify_class_attrs(Class)) + def test_classify_VirtualAttribute(self): class Meta(type): def __dir__(cls): @@ -680,7 +690,7 @@ class TestClassesAndFunctions(unittest.TestCase): return super().__getattr(name) class Class(metaclass=Meta): pass - should_find = inspect.Attribute('BOOM', 'data', Class, 42) + should_find = inspect.Attribute('BOOM', 'data', Meta, 42) self.assertIn(should_find, inspect.classify_class_attrs(Class)) def test_classify_VirtualAttribute_multi_classes(self): @@ -711,9 +721,9 @@ class TestClassesAndFunctions(unittest.TestCase): class Class2(Class1, metaclass=Meta3): pass - should_find1 = inspect.Attribute('one', 'data', Class1, 1) - should_find2 = inspect.Attribute('two', 'data', Class2, 2) - should_find3 = inspect.Attribute('three', 'data', Class2, 3) + should_find1 = inspect.Attribute('one', 'data', Meta1, 1) + should_find2 = inspect.Attribute('two', 'data', Meta2, 2) + should_find3 = inspect.Attribute('three', 'data', Meta3, 3) cca = inspect.classify_class_attrs(Class2) for sf in (should_find1, should_find2, should_find3): self.assertIn(sf, cca) diff --git a/Lib/test/test_ipaddress.py b/Lib/test/test_ipaddress.py index 99c54f1..c2a2009 100644 --- a/Lib/test/test_ipaddress.py +++ b/Lib/test/test_ipaddress.py @@ -1319,6 +1319,11 @@ class IpaddrUnitTest(unittest.TestCase): self.assertEqual(True, ipaddress.ip_network( '127.42.0.0/16').is_loopback) self.assertEqual(False, ipaddress.ip_network('128.0.0.0').is_loopback) + self.assertEqual(True, ipaddress.ip_network('100.64.0.0/10').is_private) + self.assertEqual(True, + ipaddress.ip_network('192.0.2.128/25').is_private) + self.assertEqual(True, + ipaddress.ip_network('192.0.3.0/24').is_global) # test addresses self.assertEqual(True, ipaddress.ip_address('0.0.0.0').is_unspecified) @@ -1384,6 +1389,10 @@ class IpaddrUnitTest(unittest.TestCase): self.assertEqual(False, ipaddress.ip_network('::1').is_unspecified) self.assertEqual(False, ipaddress.ip_network('::/127').is_unspecified) + self.assertEqual(True, + ipaddress.ip_network('2001::1/128').is_private) + self.assertEqual(True, + ipaddress.ip_network('200::1/128').is_global) # test addresses self.assertEqual(True, ipaddress.ip_address('ffff::').is_multicast) self.assertEqual(True, ipaddress.ip_address(2**128 - 1).is_multicast) diff --git a/Lib/test/test_json/test_decode.py b/Lib/test/test_json/test_decode.py index d23e285..35c02de 100644 --- a/Lib/test/test_json/test_decode.py +++ b/Lib/test/test_json/test_decode.py @@ -1,5 +1,5 @@ import decimal -from io import StringIO +from io import StringIO, BytesIO from collections import OrderedDict from test.test_json import PyTest, CTest @@ -70,5 +70,26 @@ class TestDecode: msg = 'escape' self.assertRaisesRegex(ValueError, msg, self.loads, s) + def test_invalid_input_type(self): + msg = 'the JSON object must be str' + for value in [1, 3.14, b'bytes', b'\xff\x00', [], {}, None]: + self.assertRaisesRegex(TypeError, msg, self.loads, value) + with self.assertRaisesRegex(TypeError, msg): + self.json.load(BytesIO(b'[1,2,3]')) + + def test_string_with_utf8_bom(self): + # see #18958 + bom_json = "[1,2,3]".encode('utf-8-sig').decode('utf-8') + with self.assertRaises(ValueError) as cm: + self.loads(bom_json) + self.assertIn('BOM', str(cm.exception)) + with self.assertRaises(ValueError) as cm: + self.json.load(StringIO(bom_json)) + self.assertIn('BOM', str(cm.exception)) + # make sure that the BOM is not detected in the middle of a string + bom_in_str = '"{}"'.format(''.encode('utf-8-sig').decode('utf-8')) + self.assertEqual(self.loads(bom_in_str), '\ufeff') + self.assertEqual(self.json.load(StringIO(bom_in_str)), '\ufeff') + class TestPyDecode(TestDecode, PyTest): pass class TestCDecode(TestDecode, CTest): pass diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py index 6abf443..0dcfe05 100644 --- a/Lib/test/test_platform.py +++ b/Lib/test/test_platform.py @@ -91,15 +91,28 @@ class PlatformTest(unittest.TestCase): ("CPython", "2.6.1", "tags/r261", "67515", ('r261:67515', 'Dec 6 2008 15:26:00'), 'GCC 4.0.1 (Apple Computer, Inc. build 5370)'), + ("IronPython 2.0 (2.0.0.0) on .NET 2.0.50727.3053", None, "cli") : ("IronPython", "2.0.0", "", "", ("", ""), ".NET 2.0.50727.3053"), + + ("2.6.1 (IronPython 2.6.1 (2.6.10920.0) on .NET 2.0.50727.1433)", None, "cli") + : + ("IronPython", "2.6.1", "", "", ("", ""), + ".NET 2.0.50727.1433"), + + ("2.7.4 (IronPython 2.7.4 (2.7.0.40) on Mono 4.0.30319.1 (32-bit))", None, "cli") + : + ("IronPython", "2.7.4", "", "", ("", ""), + "Mono 4.0.30319.1 (32-bit)"), + ("2.5 (trunk:6107, Mar 26 2009, 13:02:18) \n[Java HotSpot(TM) Client VM (\"Apple Computer, Inc.\")]", ('Jython', 'trunk', '6107'), "java1.5.0_16") : ("Jython", "2.5.0", "trunk", "6107", ('trunk:6107', 'Mar 26 2009'), "java1.5.0_16"), + ("2.5.2 (63378, Mar 26 2009, 18:03:29)\n[PyPy 1.0.0]", ('PyPy', 'trunk', '63378'), self.save_platform) : diff --git a/Lib/test/test_pydoc.py b/Lib/test/test_pydoc.py index 399f818..2d101aa 100644 --- a/Lib/test/test_pydoc.py +++ b/Lib/test/test_pydoc.py @@ -11,6 +11,7 @@ import re import string import test.support import time +import types import unittest import xml.etree import textwrap @@ -208,6 +209,75 @@ missing_pattern = "no Python documentation found for '%s'" # output pattern for module with bad imports badimport_pattern = "problem in %s - ImportError: No module named %r" +expected_dynamicattribute_pattern = """ +Help on class DA in module %s: + +class DA(builtins.object) + | Data descriptors defined here: + |\x20\x20 + | __dict__%s + |\x20\x20 + | __weakref__%s + |\x20\x20 + | ham + |\x20\x20 + | ---------------------------------------------------------------------- + | Data and other attributes inherited from Meta: + |\x20\x20 + | ham = 'spam' +""".strip() + +expected_virtualattribute_pattern1 = """ +Help on class Class in module %s: + +class Class(builtins.object) + | Data and other attributes inherited from Meta: + |\x20\x20 + | LIFE = 42 +""".strip() + +expected_virtualattribute_pattern2 = """ +Help on class Class1 in module %s: + +class Class1(builtins.object) + | Data and other attributes inherited from Meta1: + |\x20\x20 + | one = 1 +""".strip() + +expected_virtualattribute_pattern3 = """ +Help on class Class2 in module %s: + +class Class2(Class1) + | Method resolution order: + | Class2 + | Class1 + | builtins.object + |\x20\x20 + | Data and other attributes inherited from Meta1: + |\x20\x20 + | one = 1 + |\x20\x20 + | ---------------------------------------------------------------------- + | Data and other attributes inherited from Meta3: + |\x20\x20 + | three = 3 + |\x20\x20 + | ---------------------------------------------------------------------- + | Data and other attributes inherited from Meta2: + |\x20\x20 + | two = 2 +""".strip() + +expected_missingattribute_pattern = """ +Help on class C in module %s: + +class C(builtins.object) + | Data and other attributes defined here: + |\x20\x20 + | here = 'present!' +""".strip() + def run_pydoc(module_name, *args, **env): """ Runs pydoc on the specified module. Returns the stripped @@ -636,6 +706,127 @@ class TestHelper(unittest.TestCase): self.assertEqual(sorted(pydoc.Helper.keywords), sorted(keyword.kwlist)) +class PydocWithMetaClasses(unittest.TestCase): + @unittest.skipIf(sys.flags.optimize >= 2, + "Docstrings are omitted with -O2 and above") + @unittest.skipIf(hasattr(sys, 'gettrace') and sys.gettrace(), + 'trace function introduces __locals__ unexpectedly') + def test_DynamicClassAttribute(self): + class Meta(type): + def __getattr__(self, name): + if name == 'ham': + return 'spam' + return super().__getattr__(name) + class DA(metaclass=Meta): + @types.DynamicClassAttribute + def ham(self): + return 'eggs' + expected_text_data_docstrings = tuple('\n | ' + s if s else '' + for s in expected_data_docstrings) + output = StringIO() + helper = pydoc.Helper(output=output) + helper(DA) + expected_text = expected_dynamicattribute_pattern % ( + (__name__,) + expected_text_data_docstrings[:2]) + result = output.getvalue().strip() + if result != expected_text: + print_diffs(expected_text, result) + self.fail("outputs are not equal, see diff above") + + @unittest.skipIf(sys.flags.optimize >= 2, + "Docstrings are omitted with -O2 and above") + @unittest.skipIf(hasattr(sys, 'gettrace') and sys.gettrace(), + 'trace function introduces __locals__ unexpectedly') + def test_virtualClassAttributeWithOneMeta(self): + class Meta(type): + def __dir__(cls): + return ['__class__', '__module__', '__name__', 'LIFE'] + def __getattr__(self, name): + if name =='LIFE': + return 42 + return super().__getattr(name) + class Class(metaclass=Meta): + pass + output = StringIO() + helper = pydoc.Helper(output=output) + helper(Class) + expected_text = expected_virtualattribute_pattern1 % __name__ + result = output.getvalue().strip() + if result != expected_text: + print_diffs(expected_text, result) + self.fail("outputs are not equal, see diff above") + + @unittest.skipIf(sys.flags.optimize >= 2, + "Docstrings are omitted with -O2 and above") + @unittest.skipIf(hasattr(sys, 'gettrace') and sys.gettrace(), + 'trace function introduces __locals__ unexpectedly') + def test_virtualClassAttributeWithTwoMeta(self): + class Meta1(type): + def __dir__(cls): + return ['__class__', '__module__', '__name__', 'one'] + def __getattr__(self, name): + if name =='one': + return 1 + return super().__getattr__(name) + class Meta2(type): + def __dir__(cls): + return ['__class__', '__module__', '__name__', 'two'] + def __getattr__(self, name): + if name =='two': + return 2 + return super().__getattr__(name) + class Meta3(Meta1, Meta2): + def __dir__(cls): + return list(sorted(set( + ['__class__', '__module__', '__name__', 'three'] + + Meta1.__dir__(cls) + Meta2.__dir__(cls)))) + def __getattr__(self, name): + if name =='three': + return 3 + return super().__getattr__(name) + class Class1(metaclass=Meta1): + pass + class Class2(Class1, metaclass=Meta3): + pass + fail1 = fail2 = False + output = StringIO() + helper = pydoc.Helper(output=output) + helper(Class1) + expected_text1 = expected_virtualattribute_pattern2 % __name__ + result1 = output.getvalue().strip() + if result1 != expected_text1: + print_diffs(expected_text1, result1) + fail1 = True + output = StringIO() + helper = pydoc.Helper(output=output) + helper(Class2) + expected_text2 = expected_virtualattribute_pattern3 % __name__ + result2 = output.getvalue().strip() + if result2 != expected_text2: + print_diffs(expected_text2, result2) + fail2 = True + if fail1 or fail2: + self.fail("outputs are not equal, see diff above") + + @unittest.skipIf(sys.flags.optimize >= 2, + "Docstrings are omitted with -O2 and above") + @unittest.skipIf(hasattr(sys, 'gettrace') and sys.gettrace(), + 'trace function introduces __locals__ unexpectedly') + def test_buggy_dir(self): + class M(type): + def __dir__(cls): + return ['__class__', '__name__', 'missing', 'here'] + class C(metaclass=M): + here = 'present!' + output = StringIO() + helper = pydoc.Helper(output=output) + helper(C) + expected_text = expected_missingattribute_pattern % __name__ + result = output.getvalue().strip() + if result != expected_text: + print_diffs(expected_text, result) + self.fail("outputs are not equal, see diff above") + @reap_threads def test_main(): try: @@ -645,6 +836,7 @@ def test_main(): PydocServerTest, PydocUrlHandlerTest, TestHelper, + PydocWithMetaClasses, ) finally: reap_children() diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index 20b1a14..841d3a3 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -1104,6 +1104,28 @@ class ReTests(unittest.TestCase): self.assertEqual(re.compile(pattern, re.S).findall(b'xyz'), [b'xyz'], msg=pattern) + def test_match_repr(self): + for string in '[abracadabra]', S('[abracadabra]'): + m = re.search(r'(.+)(.*?)\1', string) + self.assertEqual(repr(m), "<%s.%s object; " + "span=(1, 12), match='abracadabra'>" % + (type(m).__module__, type(m).__qualname__)) + for string in (b'[abracadabra]', B(b'[abracadabra]'), + bytearray(b'[abracadabra]'), + memoryview(b'[abracadabra]')): + m = re.search(rb'(.+)(.*?)\1', string) + self.assertEqual(repr(m), "<%s.%s object; " + "span=(1, 12), match=b'abracadabra'>" % + (type(m).__module__, type(m).__qualname__)) + + first, second = list(re.finditer("(aa)|(bb)", "aa bb")) + self.assertEqual(repr(first), "<%s.%s object; " + "span=(0, 2), match='aa'>" % + (type(second).__module__, type(first).__qualname__)) + self.assertEqual(repr(second), "<%s.%s object; " + "span=(3, 5), match='bb'>" % + (type(second).__module__, type(second).__qualname__)) + def test_bug_2537(self): # issue 2537: empty submatches diff --git a/Lib/test/test_resource.py b/Lib/test/test_resource.py index 1bf2a5a..239d8d5 100644 --- a/Lib/test/test_resource.py +++ b/Lib/test/test_resource.py @@ -1,3 +1,5 @@ +import sys +import os import unittest from test import support import time @@ -129,6 +131,29 @@ class ResourceTest(unittest.TestCase): self.assertIsInstance(pagesize, int) self.assertGreaterEqual(pagesize, 0) + @unittest.skipUnless(sys.platform == 'linux', 'test requires Linux') + def test_linux_constants(self): + self.assertIsInstance(resource.RLIMIT_MSGQUEUE, int) + self.assertIsInstance(resource.RLIMIT_NICE, int) + self.assertIsInstance(resource.RLIMIT_RTPRIO, int) + self.assertIsInstance(resource.RLIMIT_RTTIME, int) + self.assertIsInstance(resource.RLIMIT_SIGPENDING, int) + + + @unittest.skipUnless(hasattr(resource, 'prlimit'), 'no prlimit') + def test_prlimit(self): + self.assertRaises(TypeError, resource.prlimit) + if os.geteuid() != 0: + self.assertRaises(PermissionError, resource.prlimit, + 1, resource.RLIMIT_AS) + self.assertRaises(ProcessLookupError, resource.prlimit, + -1, resource.RLIMIT_AS) + limit = resource.getrlimit(resource.RLIMIT_AS) + self.assertEqual(resource.prlimit(0, resource.RLIMIT_AS), limit) + self.assertEqual(resource.prlimit(0, resource.RLIMIT_AS, limit), + limit) + + def test_main(verbose=None): support.run_unittest(ResourceTest) diff --git a/Lib/test/test_telnetlib.py b/Lib/test/test_telnetlib.py index c9f2ccb..ba33064 100644 --- a/Lib/test/test_telnetlib.py +++ b/Lib/test/test_telnetlib.py @@ -1,10 +1,9 @@ import socket -import select +import selectors import telnetlib import time import contextlib -import unittest from unittest import TestCase from test import support threading = support.import_module('threading') @@ -112,40 +111,32 @@ class TelnetAlike(telnetlib.Telnet): self._messages += out.getvalue() return -def mock_select(*s_args): - block = False - for l in s_args: - for fob in l: - if isinstance(fob, TelnetAlike): - block = fob.sock.block - if block: - return [[], [], []] - else: - return s_args - -class MockPoller(object): - test_case = None # Set during TestCase setUp. +class MockSelector(selectors.BaseSelector): def __init__(self): - self._file_objs = [] + super().__init__() + self.keys = {} + + def register(self, fileobj, events, data=None): + key = selectors.SelectorKey(fileobj, 0, events, data) + self.keys[fileobj] = key + return key - def register(self, fd, eventmask): - self.test_case.assertTrue(hasattr(fd, 'fileno'), fd) - self.test_case.assertEqual(eventmask, select.POLLIN|select.POLLPRI) - self._file_objs.append(fd) + def unregister(self, fileobj): + key = self.keys.pop(fileobj) + return key - def poll(self, timeout=None): + def select(self, timeout=None): block = False - for fob in self._file_objs: - if isinstance(fob, TelnetAlike): - block = fob.sock.block + for fileobj in self.keys: + if isinstance(fileobj, TelnetAlike): + block = fileobj.sock.block + break if block: return [] else: - return zip(self._file_objs, [select.POLLIN]*len(self._file_objs)) + return [(key, key.events) for key in self.keys.values()] - def unregister(self, fd): - self._file_objs.remove(fd) @contextlib.contextmanager def test_socket(reads): @@ -159,7 +150,7 @@ def test_socket(reads): socket.create_connection = old_conn return -def test_telnet(reads=(), cls=TelnetAlike, use_poll=None): +def test_telnet(reads=(), cls=TelnetAlike): ''' return a telnetlib.Telnet object that uses a SocketStub with reads queued up to be read ''' for x in reads: @@ -167,29 +158,14 @@ def test_telnet(reads=(), cls=TelnetAlike, use_poll=None): with test_socket(reads): telnet = cls('dummy', 0) telnet._messages = '' # debuglevel output - if use_poll is not None: - if use_poll and not telnet._has_poll: - raise unittest.SkipTest('select.poll() required.') - telnet._has_poll = use_poll return telnet - class ExpectAndReadTestCase(TestCase): def setUp(self): - self.old_select = select.select - select.select = mock_select - self.old_poll = False - if hasattr(select, 'poll'): - self.old_poll = select.poll - select.poll = MockPoller - MockPoller.test_case = self - + self.old_selector = telnetlib._TelnetSelector + telnetlib._TelnetSelector = MockSelector def tearDown(self): - if self.old_poll: - MockPoller.test_case = None - select.poll = self.old_poll - select.select = self.old_select - + telnetlib._TelnetSelector = self.old_selector class ReadTests(ExpectAndReadTestCase): def test_read_until(self): @@ -208,22 +184,6 @@ class ReadTests(ExpectAndReadTestCase): data = telnet.read_until(b'match') self.assertEqual(data, expect) - def test_read_until_with_poll(self): - """Use select.poll() to implement telnet.read_until().""" - want = [b'x' * 10, b'match', b'y' * 10] - telnet = test_telnet(want, use_poll=True) - select.select = lambda *_: self.fail('unexpected select() call.') - data = telnet.read_until(b'match') - self.assertEqual(data, b''.join(want[:-1])) - - def test_read_until_with_select(self): - """Use select.select() to implement telnet.read_until().""" - want = [b'x' * 10, b'match', b'y' * 10] - telnet = test_telnet(want, use_poll=False) - if self.old_poll: - select.poll = lambda *_: self.fail('unexpected poll() call.') - data = telnet.read_until(b'match') - self.assertEqual(data, b''.join(want[:-1])) def test_read_all(self): """ @@ -427,23 +387,6 @@ class ExpectTests(ExpectAndReadTestCase): (_,_,data) = telnet.expect([b'match']) self.assertEqual(data, b''.join(want[:-1])) - def test_expect_with_poll(self): - """Use select.poll() to implement telnet.expect().""" - want = [b'x' * 10, b'match', b'y' * 10] - telnet = test_telnet(want, use_poll=True) - select.select = lambda *_: self.fail('unexpected select() call.') - (_,_,data) = telnet.expect([b'match']) - self.assertEqual(data, b''.join(want[:-1])) - - def test_expect_with_select(self): - """Use select.select() to implement telnet.expect().""" - want = [b'x' * 10, b'match', b'y' * 10] - telnet = test_telnet(want, use_poll=False) - if self.old_poll: - select.poll = lambda *_: self.fail('unexpected poll() call.') - (_,_,data) = telnet.expect([b'match']) - self.assertEqual(data, b''.join(want[:-1])) - def test_main(verbose=None): support.run_unittest(GeneralTests, ReadTests, WriteTests, OptionTests, diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py index 899a3fb..7249b13 100644 --- a/Lib/test/test_zipfile.py +++ b/Lib/test/test_zipfile.py @@ -591,6 +591,34 @@ class PyZipFileTests(unittest.TestCase): self.assertCompiledIn('email/__init__.py', names) self.assertCompiledIn('email/mime/text.py', names) + def test_write_filtered_python_package(self): + import test + packagedir = os.path.dirname(test.__file__) + + with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp: + + # first make sure that the test folder gives error messages + # (on the badsyntax_... files) + with captured_stdout() as reportSIO: + zipfp.writepy(packagedir) + reportStr = reportSIO.getvalue() + self.assertTrue('SyntaxError' in reportStr) + + # then check that the filter works on the whole package + with captured_stdout() as reportSIO: + zipfp.writepy(packagedir, filterfunc=lambda whatever: False) + reportStr = reportSIO.getvalue() + self.assertTrue('SyntaxError' not in reportStr) + + # then check that the filter works on individual files + with captured_stdout() as reportSIO: + zipfp.writepy(packagedir, filterfunc=lambda fn: + 'bad' not in fn) + reportStr = reportSIO.getvalue() + if reportStr: + print(reportStr) + self.assertTrue('SyntaxError' not in reportStr) + def test_write_with_optimization(self): import email packagedir = os.path.dirname(email.__file__) @@ -600,7 +628,7 @@ class PyZipFileTests(unittest.TestCase): ext = '.pyo' if optlevel == 1 else '.pyc' with TemporaryFile() as t, \ - zipfile.PyZipFile(t, "w", optimize=optlevel) as zipfp: + zipfile.PyZipFile(t, "w", optimize=optlevel) as zipfp: zipfp.writepy(packagedir) names = zipfp.namelist() @@ -630,6 +658,26 @@ class PyZipFileTests(unittest.TestCase): finally: shutil.rmtree(TESTFN2) + def test_write_python_directory_filtered(self): + os.mkdir(TESTFN2) + try: + with open(os.path.join(TESTFN2, "mod1.py"), "w") as fp: + fp.write("print(42)\n") + + with open(os.path.join(TESTFN2, "mod2.py"), "w") as fp: + fp.write("print(42 * 42)\n") + + with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp: + zipfp.writepy(TESTFN2, filterfunc=lambda fn: + not fn.endswith('mod2.py')) + + names = zipfp.namelist() + self.assertCompiledIn('mod1.py', names) + self.assertNotIn('mod2.py', names) + + finally: + shutil.rmtree(TESTFN2) + def test_write_non_pyfile(self): with TemporaryFile() as t, zipfile.PyZipFile(t, "w") as zipfp: with open(TESTFN, 'w') as f: @@ -733,25 +781,25 @@ class ExtractTests(unittest.TestCase): def test_extract_hackers_arcnames_windows_only(self): """Test combination of path fixing and windows name sanitization.""" windows_hacknames = [ - (r'..\foo\bar', 'foo/bar'), - (r'..\/foo\/bar', 'foo/bar'), - (r'foo/\..\/bar', 'foo/bar'), - (r'foo\/../\bar', 'foo/bar'), - (r'C:foo/bar', 'foo/bar'), - (r'C:/foo/bar', 'foo/bar'), - (r'C://foo/bar', 'foo/bar'), - (r'C:\foo\bar', 'foo/bar'), - (r'//conky/mountpoint/foo/bar', 'foo/bar'), - (r'\\conky\mountpoint\foo\bar', 'foo/bar'), - (r'///conky/mountpoint/foo/bar', 'conky/mountpoint/foo/bar'), - (r'\\\conky\mountpoint\foo\bar', 'conky/mountpoint/foo/bar'), - (r'//conky//mountpoint/foo/bar', 'conky/mountpoint/foo/bar'), - (r'\\conky\\mountpoint\foo\bar', 'conky/mountpoint/foo/bar'), - (r'//?/C:/foo/bar', 'foo/bar'), - (r'\\?\C:\foo\bar', 'foo/bar'), - (r'C:/../C:/foo/bar', 'C_/foo/bar'), - (r'a:b\c<d>e|f"g?h*i', 'b/c_d_e_f_g_h_i'), - ('../../foo../../ba..r', 'foo/ba..r'), + (r'..\foo\bar', 'foo/bar'), + (r'..\/foo\/bar', 'foo/bar'), + (r'foo/\..\/bar', 'foo/bar'), + (r'foo\/../\bar', 'foo/bar'), + (r'C:foo/bar', 'foo/bar'), + (r'C:/foo/bar', 'foo/bar'), + (r'C://foo/bar', 'foo/bar'), + (r'C:\foo\bar', 'foo/bar'), + (r'//conky/mountpoint/foo/bar', 'foo/bar'), + (r'\\conky\mountpoint\foo\bar', 'foo/bar'), + (r'///conky/mountpoint/foo/bar', 'conky/mountpoint/foo/bar'), + (r'\\\conky\mountpoint\foo\bar', 'conky/mountpoint/foo/bar'), + (r'//conky//mountpoint/foo/bar', 'conky/mountpoint/foo/bar'), + (r'\\conky\\mountpoint\foo\bar', 'conky/mountpoint/foo/bar'), + (r'//?/C:/foo/bar', 'foo/bar'), + (r'\\?\C:\foo\bar', 'foo/bar'), + (r'C:/../C:/foo/bar', 'C_/foo/bar'), + (r'a:b\c<d>e|f"g?h*i', 'b/c_d_e_f_g_h_i'), + ('../../foo../../ba..r', 'foo/ba..r'), ] self._test_extract_hackers_arcnames(windows_hacknames) @@ -877,10 +925,10 @@ class OtherTests(unittest.TestCase): def test_unsupported_version(self): # File has an extract_version of 120 data = (b'PK\x03\x04x\x00\x00\x00\x00\x00!p\xa1@\x00\x00\x00\x00\x00\x00' - b'\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00xPK\x01\x02x\x03x\x00\x00\x00\x00' - b'\x00!p\xa1@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00' - b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x00\x00xPK\x05\x06' - b'\x00\x00\x00\x00\x01\x00\x01\x00/\x00\x00\x00\x1f\x00\x00\x00\x00\x00') + b'\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00xPK\x01\x02x\x03x\x00\x00\x00\x00' + b'\x00!p\xa1@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x00\x00xPK\x05\x06' + b'\x00\x00\x00\x00\x01\x00\x01\x00/\x00\x00\x00\x1f\x00\x00\x00\x00\x00') self.assertRaises(NotImplementedError, zipfile.ZipFile, io.BytesIO(data), 'r') @@ -1066,11 +1114,11 @@ class OtherTests(unittest.TestCase): def test_unsupported_compression(self): # data is declared as shrunk, but actually deflated data = (b'PK\x03\x04.\x00\x00\x00\x01\x00\xe4C\xa1@\x00\x00\x00' - b'\x00\x02\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00x\x03\x00PK\x01' - b'\x02.\x03.\x00\x00\x00\x01\x00\xe4C\xa1@\x00\x00\x00\x00\x02\x00\x00' - b'\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' - b'\x80\x01\x00\x00\x00\x00xPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00' - b'/\x00\x00\x00!\x00\x00\x00\x00\x00') + b'\x00\x02\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00x\x03\x00PK\x01' + b'\x02.\x03.\x00\x00\x00\x01\x00\xe4C\xa1@\x00\x00\x00\x00\x02\x00\x00' + b'\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x80\x01\x00\x00\x00\x00xPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00' + b'/\x00\x00\x00!\x00\x00\x00\x00\x00') with zipfile.ZipFile(io.BytesIO(data), 'r') as zipf: self.assertRaises(NotImplementedError, zipf.open, 'x') @@ -1232,57 +1280,57 @@ class AbstractBadCrcTests: class StoredBadCrcTests(AbstractBadCrcTests, unittest.TestCase): compression = zipfile.ZIP_STORED zip_with_bad_crc = ( - b'PK\003\004\024\0\0\0\0\0 \213\212;:r' - b'\253\377\f\0\0\0\f\0\0\0\005\0\0\000af' - b'ilehello,AworldP' - b'K\001\002\024\003\024\0\0\0\0\0 \213\212;:' - b'r\253\377\f\0\0\0\f\0\0\0\005\0\0\0\0' - b'\0\0\0\0\0\0\0\200\001\0\0\0\000afi' - b'lePK\005\006\0\0\0\0\001\0\001\0003\000' - b'\0\0/\0\0\0\0\0') + b'PK\003\004\024\0\0\0\0\0 \213\212;:r' + b'\253\377\f\0\0\0\f\0\0\0\005\0\0\000af' + b'ilehello,AworldP' + b'K\001\002\024\003\024\0\0\0\0\0 \213\212;:' + b'r\253\377\f\0\0\0\f\0\0\0\005\0\0\0\0' + b'\0\0\0\0\0\0\0\200\001\0\0\0\000afi' + b'lePK\005\006\0\0\0\0\001\0\001\0003\000' + b'\0\0/\0\0\0\0\0') @requires_zlib class DeflateBadCrcTests(AbstractBadCrcTests, unittest.TestCase): compression = zipfile.ZIP_DEFLATED zip_with_bad_crc = ( - b'PK\x03\x04\x14\x00\x00\x00\x08\x00n}\x0c=FA' - b'KE\x10\x00\x00\x00n\x00\x00\x00\x05\x00\x00\x00af' - b'ile\xcbH\xcd\xc9\xc9W(\xcf/\xcaI\xc9\xa0' - b'=\x13\x00PK\x01\x02\x14\x03\x14\x00\x00\x00\x08\x00n' - b'}\x0c=FAKE\x10\x00\x00\x00n\x00\x00\x00\x05' - b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x00' - b'\x00afilePK\x05\x06\x00\x00\x00\x00\x01\x00' - b'\x01\x003\x00\x00\x003\x00\x00\x00\x00\x00') + b'PK\x03\x04\x14\x00\x00\x00\x08\x00n}\x0c=FA' + b'KE\x10\x00\x00\x00n\x00\x00\x00\x05\x00\x00\x00af' + b'ile\xcbH\xcd\xc9\xc9W(\xcf/\xcaI\xc9\xa0' + b'=\x13\x00PK\x01\x02\x14\x03\x14\x00\x00\x00\x08\x00n' + b'}\x0c=FAKE\x10\x00\x00\x00n\x00\x00\x00\x05' + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x00' + b'\x00afilePK\x05\x06\x00\x00\x00\x00\x01\x00' + b'\x01\x003\x00\x00\x003\x00\x00\x00\x00\x00') @requires_bz2 class Bzip2BadCrcTests(AbstractBadCrcTests, unittest.TestCase): compression = zipfile.ZIP_BZIP2 zip_with_bad_crc = ( - b'PK\x03\x04\x14\x03\x00\x00\x0c\x00nu\x0c=FA' - b'KE8\x00\x00\x00n\x00\x00\x00\x05\x00\x00\x00af' - b'ileBZh91AY&SY\xd4\xa8\xca' - b'\x7f\x00\x00\x0f\x11\x80@\x00\x06D\x90\x80 \x00 \xa5' - b'P\xd9!\x03\x03\x13\x13\x13\x89\xa9\xa9\xc2u5:\x9f' - b'\x8b\xb9"\x9c(HjTe?\x80PK\x01\x02\x14' - b'\x03\x14\x03\x00\x00\x0c\x00nu\x0c=FAKE8' - b'\x00\x00\x00n\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00' - b'\x00 \x80\x80\x81\x00\x00\x00\x00afilePK' - b'\x05\x06\x00\x00\x00\x00\x01\x00\x01\x003\x00\x00\x00[\x00' - b'\x00\x00\x00\x00') + b'PK\x03\x04\x14\x03\x00\x00\x0c\x00nu\x0c=FA' + b'KE8\x00\x00\x00n\x00\x00\x00\x05\x00\x00\x00af' + b'ileBZh91AY&SY\xd4\xa8\xca' + b'\x7f\x00\x00\x0f\x11\x80@\x00\x06D\x90\x80 \x00 \xa5' + b'P\xd9!\x03\x03\x13\x13\x13\x89\xa9\xa9\xc2u5:\x9f' + b'\x8b\xb9"\x9c(HjTe?\x80PK\x01\x02\x14' + b'\x03\x14\x03\x00\x00\x0c\x00nu\x0c=FAKE8' + b'\x00\x00\x00n\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00 \x80\x80\x81\x00\x00\x00\x00afilePK' + b'\x05\x06\x00\x00\x00\x00\x01\x00\x01\x003\x00\x00\x00[\x00' + b'\x00\x00\x00\x00') @requires_lzma class LzmaBadCrcTests(AbstractBadCrcTests, unittest.TestCase): compression = zipfile.ZIP_LZMA zip_with_bad_crc = ( - b'PK\x03\x04\x14\x03\x00\x00\x0e\x00nu\x0c=FA' - b'KE\x1b\x00\x00\x00n\x00\x00\x00\x05\x00\x00\x00af' - b'ile\t\x04\x05\x00]\x00\x00\x00\x04\x004\x19I' - b'\xee\x8d\xe9\x17\x89:3`\tq!.8\x00PK' - b'\x01\x02\x14\x03\x14\x03\x00\x00\x0e\x00nu\x0c=FA' - b'KE\x1b\x00\x00\x00n\x00\x00\x00\x05\x00\x00\x00\x00\x00' - b'\x00\x00\x00\x00 \x80\x80\x81\x00\x00\x00\x00afil' - b'ePK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x003\x00\x00' - b'\x00>\x00\x00\x00\x00\x00') + b'PK\x03\x04\x14\x03\x00\x00\x0e\x00nu\x0c=FA' + b'KE\x1b\x00\x00\x00n\x00\x00\x00\x05\x00\x00\x00af' + b'ile\t\x04\x05\x00]\x00\x00\x00\x04\x004\x19I' + b'\xee\x8d\xe9\x17\x89:3`\tq!.8\x00PK' + b'\x01\x02\x14\x03\x14\x03\x00\x00\x0e\x00nu\x0c=FA' + b'KE\x1b\x00\x00\x00n\x00\x00\x00\x05\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00 \x80\x80\x81\x00\x00\x00\x00afil' + b'ePK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x003\x00\x00' + b'\x00>\x00\x00\x00\x00\x00') class DecryptionTests(unittest.TestCase): @@ -1291,22 +1339,22 @@ class DecryptionTests(unittest.TestCase): ZIP file.""" data = ( - b'PK\x03\x04\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00\x1a\x00' - b'\x00\x00\x08\x00\x00\x00test.txt\xfa\x10\xa0gly|\xfa-\xc5\xc0=\xf9y' - b'\x18\xe0\xa8r\xb3Z}Lg\xbc\xae\xf9|\x9b\x19\xe4\x8b\xba\xbb)\x8c\xb0\xdbl' - b'PK\x01\x02\x14\x00\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00' - b'\x1a\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x01\x00 \x00\xb6\x81' - b'\x00\x00\x00\x00test.txtPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x006\x00' - b'\x00\x00L\x00\x00\x00\x00\x00' ) + b'PK\x03\x04\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00\x1a\x00' + b'\x00\x00\x08\x00\x00\x00test.txt\xfa\x10\xa0gly|\xfa-\xc5\xc0=\xf9y' + b'\x18\xe0\xa8r\xb3Z}Lg\xbc\xae\xf9|\x9b\x19\xe4\x8b\xba\xbb)\x8c\xb0\xdbl' + b'PK\x01\x02\x14\x00\x14\x00\x01\x00\x00\x00n\x92i.#y\xef?&\x00\x00\x00' + b'\x1a\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x01\x00 \x00\xb6\x81' + b'\x00\x00\x00\x00test.txtPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x006\x00' + b'\x00\x00L\x00\x00\x00\x00\x00' ) data2 = ( - b'PK\x03\x04\x14\x00\t\x00\x08\x00\xcf}38xu\xaa\xb2\x14\x00\x00\x00\x00\x02' - b'\x00\x00\x04\x00\x15\x00zeroUT\t\x00\x03\xd6\x8b\x92G\xda\x8b\x92GUx\x04' - b'\x00\xe8\x03\xe8\x03\xc7<M\xb5a\xceX\xa3Y&\x8b{oE\xd7\x9d\x8c\x98\x02\xc0' - b'PK\x07\x08xu\xaa\xb2\x14\x00\x00\x00\x00\x02\x00\x00PK\x01\x02\x17\x03' - b'\x14\x00\t\x00\x08\x00\xcf}38xu\xaa\xb2\x14\x00\x00\x00\x00\x02\x00\x00' - b'\x04\x00\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x00ze' - b'roUT\x05\x00\x03\xd6\x8b\x92GUx\x00\x00PK\x05\x06\x00\x00\x00\x00\x01' - b'\x00\x01\x00?\x00\x00\x00[\x00\x00\x00\x00\x00' ) + b'PK\x03\x04\x14\x00\t\x00\x08\x00\xcf}38xu\xaa\xb2\x14\x00\x00\x00\x00\x02' + b'\x00\x00\x04\x00\x15\x00zeroUT\t\x00\x03\xd6\x8b\x92G\xda\x8b\x92GUx\x04' + b'\x00\xe8\x03\xe8\x03\xc7<M\xb5a\xceX\xa3Y&\x8b{oE\xd7\x9d\x8c\x98\x02\xc0' + b'PK\x07\x08xu\xaa\xb2\x14\x00\x00\x00\x00\x02\x00\x00PK\x01\x02\x17\x03' + b'\x14\x00\t\x00\x08\x00\xcf}38xu\xaa\xb2\x14\x00\x00\x00\x00\x02\x00\x00' + b'\x04\x00\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x00ze' + b'roUT\x05\x00\x03\xd6\x8b\x92GUx\x00\x00PK\x05\x06\x00\x00\x00\x00\x01' + b'\x00\x01\x00?\x00\x00\x00[\x00\x00\x00\x00\x00' ) plain = b'zipfile.py encryption test' plain2 = b'\x00'*512 |
