Skip to content

Commit 4c87ba8

Browse files
committed
gh-138013: Remove test_io load_tests namespace manipulation
Reduce what happens in `load_tests` so that the next change, moving the `Buffered*` tests to `test_bufferdio` is purely mechanical movement and updating imports. This adds two classes, one per I/O implementation, to act as dispatch to the implementation-specific mocks as well as module members. Previously the mappings CTestCase and PyTestCase provide were injected directly during `load_tests`. CTestCase and PyTestCase inherit from `unittest.TestCase` so when the split happens default test discovery will work for the classes in `test_bufferedio`. `test_general` keeps a manual test list for this refactoring; some of the tests (ex. `ProtocolsTest`) aren't currently run and fixing that + helpers to not be picked up is out of my current scope. CTestCase and PyTestCase have an `io` class member which points to the implementation meaning that can be removed from individual test cases which now inherit from them.
1 parent a2ba0a7 commit 4c87ba8

File tree

1 file changed

+63
-48
lines changed

1 file changed

+63
-48
lines changed

Lib/test/test_io/test_general.py

Lines changed: 63 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,45 @@ class PyMockNonBlockWriterIO(MockNonBlockWriterIO, pyio.RawIOBase):
334334
BlockingIOError = pyio.BlockingIOError
335335

336336

337+
# Build classes which point to all the right mocks per io implementation
338+
class CTestCase(unittest.TestCase):
339+
io = io
340+
is_C = True
341+
342+
MockRawIO = CMockRawIO
343+
MisbehavedRawIO = CMisbehavedRawIO
344+
MockFileIO = CMockFileIO
345+
CloseFailureIO = CCloseFailureIO
346+
MockNonBlockWriterIO = CMockNonBlockWriterIO
347+
MockUnseekableIO = CMockUnseekableIO
348+
MockRawIOWithoutRead = CMockRawIOWithoutRead
349+
SlowFlushRawIO = CSlowFlushRawIO
350+
MockCharPseudoDevFileIO = CMockCharPseudoDevFileIO
351+
352+
# Use the class as a proxy to the io module members.
353+
def __getattr__(self, name):
354+
return getattr(self.io, name)
355+
356+
357+
class PyTestCase(unittest.TestCase):
358+
io = pyio
359+
is_C = False
360+
361+
MockRawIO = PyMockRawIO
362+
MisbehavedRawIO = PyMisbehavedRawIO
363+
MockFileIO = PyMockFileIO
364+
CloseFailureIO = PyCloseFailureIO
365+
MockNonBlockWriterIO = PyMockNonBlockWriterIO
366+
MockUnseekableIO = PyMockUnseekableIO
367+
MockRawIOWithoutRead = PyMockRawIOWithoutRead
368+
SlowFlushRawIO = PySlowFlushRawIO
369+
MockCharPseudoDevFileIO = PyMockCharPseudoDevFileIO
370+
371+
# Use the class as a proxy to the io module members.
372+
def __getattr__(self, name):
373+
return getattr(self.io, name)
374+
375+
337376
class IOTest(unittest.TestCase):
338377

339378
def setUp(self):
@@ -1100,7 +1139,7 @@ def reader(file, barrier):
11001139
write_count * thread_count)
11011140

11021141

1103-
class CIOTest(IOTest):
1142+
class CIOTest(IOTest, CTestCase):
11041143

11051144
def test_IOBase_finalize(self):
11061145
# Issue #12149: segmentation fault on _PyIOBase_finalize when both a
@@ -1224,7 +1263,7 @@ def test_stringio_setstate(self):
12241263
obj.__setstate__(('', '', 0, {}))
12251264
self.assertEqual(obj.getvalue(), '')
12261265

1227-
class PyIOTest(IOTest):
1266+
class PyIOTest(IOTest, PyTestCase):
12281267
pass
12291268

12301269

@@ -1455,7 +1494,7 @@ def test_buffer_freeing(self) :
14551494
bufio.close()
14561495
self.assertEqual(sys.getsizeof(bufio), size)
14571496

1458-
class BufferedReaderTest(unittest.TestCase, CommonBufferedTests):
1497+
class BufferedReaderTest(CommonBufferedTests):
14591498
read_mode = "rb"
14601499

14611500
def test_constructor(self):
@@ -1790,7 +1829,7 @@ def test_seek_character_device_file(self):
17901829
self.assertEqual(buf.seek(0, io.SEEK_CUR), 0)
17911830

17921831

1793-
class CBufferedReaderTest(BufferedReaderTest, SizeofTest):
1832+
class CBufferedReaderTest(BufferedReaderTest, SizeofTest, CTestCase):
17941833
tp = io.BufferedReader
17951834

17961835
def test_initialization(self):
@@ -1849,11 +1888,11 @@ def test_bad_readinto_type(self):
18491888
self.assertIsInstance(cm.exception.__cause__, TypeError)
18501889

18511890

1852-
class PyBufferedReaderTest(BufferedReaderTest):
1891+
class PyBufferedReaderTest(BufferedReaderTest, PyTestCase):
18531892
tp = pyio.BufferedReader
18541893

18551894

1856-
class BufferedWriterTest(unittest.TestCase, CommonBufferedTests):
1895+
class BufferedWriterTest(CommonBufferedTests):
18571896
write_mode = "wb"
18581897

18591898
def test_constructor(self):
@@ -2148,8 +2187,7 @@ def test_slow_close_from_thread(self):
21482187
t.join()
21492188

21502189

2151-
2152-
class CBufferedWriterTest(BufferedWriterTest, SizeofTest):
2190+
class CBufferedWriterTest(BufferedWriterTest, SizeofTest, CTestCase):
21532191
tp = io.BufferedWriter
21542192

21552193
def test_initialization(self):
@@ -2189,10 +2227,10 @@ def test_args_error(self):
21892227
self.tp(self.BytesIO(), 1024, 1024, 1024)
21902228

21912229

2192-
class PyBufferedWriterTest(BufferedWriterTest):
2230+
class PyBufferedWriterTest(BufferedWriterTest, PyTestCase):
21932231
tp = pyio.BufferedWriter
21942232

2195-
class BufferedRWPairTest(unittest.TestCase):
2233+
class BufferedRWPairTest:
21962234

21972235
def test_constructor(self):
21982236
pair = self.tp(self.MockRawIO(), self.MockRawIO())
@@ -2400,10 +2438,10 @@ def test_weakref_clearing(self):
24002438
brw = None
24012439
ref = None # Shouldn't segfault.
24022440

2403-
class CBufferedRWPairTest(BufferedRWPairTest):
2441+
class CBufferedRWPairTest(BufferedRWPairTest, CTestCase):
24042442
tp = io.BufferedRWPair
24052443

2406-
class PyBufferedRWPairTest(BufferedRWPairTest):
2444+
class PyBufferedRWPairTest(BufferedRWPairTest, PyTestCase):
24072445
tp = pyio.BufferedRWPair
24082446

24092447

@@ -2662,7 +2700,7 @@ def test_interleaved_readline_write(self):
26622700
test_truncate_on_read_only = None
26632701

26642702

2665-
class CBufferedRandomTest(BufferedRandomTest, SizeofTest):
2703+
class CBufferedRandomTest(BufferedRandomTest, SizeofTest, CTestCase):
26662704
tp = io.BufferedRandom
26672705

26682706
def test_garbage_collection(self):
@@ -2675,7 +2713,7 @@ def test_args_error(self):
26752713
self.tp(self.BytesIO(), 1024, 1024, 1024)
26762714

26772715

2678-
class PyBufferedRandomTest(BufferedRandomTest):
2716+
class PyBufferedRandomTest(BufferedRandomTest, PyTestCase):
26792717
tp = pyio.BufferedRandom
26802718

26812719

@@ -4075,8 +4113,7 @@ def _to_memoryview(buf):
40754113
return memoryview(arr)
40764114

40774115

4078-
class CTextIOWrapperTest(TextIOWrapperTest):
4079-
io = io
4116+
class CTextIOWrapperTest(TextIOWrapperTest, CTestCase):
40804117
shutdown_error = "LookupError: unknown encoding: ascii"
40814118

40824119
def test_initialization(self):
@@ -4176,8 +4213,7 @@ def write(self, data):
41764213
buf._write_stack)
41774214

41784215

4179-
class PyTextIOWrapperTest(TextIOWrapperTest):
4180-
io = pyio
4216+
class PyTextIOWrapperTest(TextIOWrapperTest, PyTestCase):
41814217
shutdown_error = "LookupError: unknown encoding: ascii"
41824218

41834219

@@ -4299,6 +4335,8 @@ def test_translate(self):
42994335
self.assertEqual(decoder.decode(b"\r\r\n"), "\r\r\n")
43004336

43014337
class CIncrementalNewlineDecoderTest(IncrementalNewlineDecoderTest):
4338+
IncrementalNewlineDecoder = io.IncrementalNewlineDecoder
4339+
43024340
@support.cpython_only
43034341
def test_uninitialized(self):
43044342
uninitialized = self.IncrementalNewlineDecoder.__new__(
@@ -4310,7 +4348,7 @@ def test_uninitialized(self):
43104348

43114349

43124350
class PyIncrementalNewlineDecoderTest(IncrementalNewlineDecoderTest):
4313-
pass
4351+
IncrementalNewlineDecoder = pyio.IncrementalNewlineDecoder
43144352

43154353

43164354
# XXX Tests for open()
@@ -4679,8 +4717,7 @@ def test_text_encoding(self):
46794717
self.assertEqual(b"utf-8", proc.out.strip())
46804718

46814719

4682-
class CMiscIOTest(MiscIOTest):
4683-
io = io
4720+
class CMiscIOTest(MiscIOTest, CTestCase):
46844721
name_of_module = "io", "_io"
46854722
extra_exported = "BlockingIOError",
46864723

@@ -4745,8 +4782,7 @@ def test_daemon_threads_shutdown_stderr_deadlock(self):
47454782
self.check_daemon_threads_shutdown_deadlock('stderr')
47464783

47474784

4748-
class PyMiscIOTest(MiscIOTest):
4749-
io = pyio
4785+
class PyMiscIOTest(MiscIOTest, PyTestCase):
47504786
name_of_module = "_pyio", "io"
47514787
extra_exported = "BlockingIOError", "open_code",
47524788
not_exported = "valid_seek_flags",
@@ -5007,11 +5043,11 @@ def test_interrupted_write_retry_text(self):
50075043
self.check_interrupted_write_retry("x", mode="w", encoding="latin1")
50085044

50095045

5010-
class CSignalsTest(SignalsTest):
5011-
io = io
5046+
class CSignalsTest(SignalsTest, CTestCase):
5047+
pass
50125048

5013-
class PySignalsTest(SignalsTest):
5014-
io = pyio
5049+
class PySignalsTest(SignalsTest, PyTestCase):
5050+
pass
50155051

50165052
# Handling reentrancy issues would slow down _pyio even more, so the
50175053
# tests are disabled.
@@ -5050,27 +5086,6 @@ def load_tests(loader, tests, pattern):
50505086
CSignalsTest, PySignalsTest, TestIOCTypes,
50515087
)
50525088

5053-
# Put the namespaces of the IO module we are testing and some useful mock
5054-
# classes in the __dict__ of each test.
5055-
mocks = (MockRawIO, MisbehavedRawIO, MockFileIO, CloseFailureIO,
5056-
MockNonBlockWriterIO, MockUnseekableIO, MockRawIOWithoutRead,
5057-
SlowFlushRawIO, MockCharPseudoDevFileIO)
5058-
all_members = io.__all__
5059-
c_io_ns = {name : getattr(io, name) for name in all_members}
5060-
py_io_ns = {name : getattr(pyio, name) for name in all_members}
5061-
globs = globals()
5062-
c_io_ns.update((x.__name__, globs["C" + x.__name__]) for x in mocks)
5063-
py_io_ns.update((x.__name__, globs["Py" + x.__name__]) for x in mocks)
5064-
for test in tests:
5065-
if test.__name__.startswith("C"):
5066-
for name, obj in c_io_ns.items():
5067-
setattr(test, name, obj)
5068-
test.is_C = True
5069-
elif test.__name__.startswith("Py"):
5070-
for name, obj in py_io_ns.items():
5071-
setattr(test, name, obj)
5072-
test.is_C = False
5073-
50745089
suite = loader.suiteClass()
50755090
for test in tests:
50765091
suite.addTest(loader.loadTestsFromTestCase(test))

0 commit comments

Comments
 (0)