Skip to content

Commit cac62dd

Browse files
bpo-40129: Add fake number classes in test.support.
1 parent 2c003ef commit cac62dd

19 files changed

+255
-577
lines changed

Lib/test/datetimetester.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from operator import lt, le, gt, ge, eq, ne, truediv, floordiv, mod
2020

2121
from test import support
22-
from test.support import is_resource_enabled, ALWAYS_EQ, LARGEST, SMALLEST
22+
from test.support import is_resource_enabled, ALWAYS_EQ, LARGEST, SMALLEST, FakeInt
2323

2424
import datetime as datetime_module
2525
from datetime import MINYEAR, MAXYEAR
@@ -5076,15 +5076,9 @@ def test_extra_attributes(self):
50765076
x.abc = 1
50775077

50785078
def test_check_arg_types(self):
5079-
class Number:
5080-
def __init__(self, value):
5081-
self.value = value
5082-
def __int__(self):
5083-
return self.value
5084-
50855079
for xx in [decimal.Decimal(10),
50865080
decimal.Decimal('10.9'),
5087-
Number(10)]:
5081+
FakeInt(10)]:
50885082
with self.assertWarns(DeprecationWarning):
50895083
self.assertEqual(datetime(10, 10, 10, 10, 10, 10, 10),
50905084
datetime(xx, xx, xx, xx, xx, xx, xx))
@@ -5093,7 +5087,7 @@ def __int__(self):
50935087
r'\(got type str\)$'):
50945088
datetime(10, 10, '10')
50955089

5096-
f10 = Number(10.9)
5090+
f10 = FakeInt(10.9)
50975091
with self.assertRaisesRegex(TypeError, '^__int__ returned non-int '
50985092
r'\(type float\)$'):
50995093
datetime(10, 10, f10)

Lib/test/support/__init__.py

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@
121121
"run_with_tz", "PGO", "missing_compiler_executable", "fd_count",
122122
"ALWAYS_EQ", "NEVER_EQ", "LARGEST", "SMALLEST",
123123
"LOOPBACK_TIMEOUT", "INTERNET_TIMEOUT", "SHORT_TIMEOUT", "LONG_TIMEOUT",
124+
"FakeIndex", "FakeInt", "FakeFloat", "FakeComplex", "FakePath",
124125
]
125126

126127

@@ -3189,22 +3190,37 @@ def with_pymalloc():
31893190
return _testcapi.WITH_PYMALLOC
31903191

31913192

3192-
class FakePath:
3193-
"""Simple implementing of the path protocol.
3194-
"""
3195-
def __init__(self, path):
3196-
self.path = path
3193+
class Fake:
3194+
def __init__(self, value):
3195+
self.value = value
31973196

31983197
def __repr__(self):
3199-
return f'<FakePath {self.path!r}>'
3198+
return f'<{self.__class__.__name__} {self.value!r}>'
32003199

3201-
def __fspath__(self):
3202-
if (isinstance(self.path, BaseException) or
3203-
isinstance(self.path, type) and
3204-
issubclass(self.path, BaseException)):
3205-
raise self.path
3200+
def _return(self):
3201+
if (isinstance(self.value, BaseException) or
3202+
isinstance(self.value, type) and
3203+
issubclass(self.value, BaseException)):
3204+
raise self.value
32063205
else:
3207-
return self.path
3206+
return self.value
3207+
3208+
class FakeIndex(Fake):
3209+
__index__ = Fake._return
3210+
3211+
class FakeInt(Fake):
3212+
__int__ = Fake._return
3213+
3214+
class FakeFloat(Fake):
3215+
__float__ = Fake._return
3216+
3217+
class FakeComplex(Fake):
3218+
__complex__ = Fake._return
3219+
3220+
class FakePath(Fake):
3221+
"""Simple implementing of the path protocol.
3222+
"""
3223+
__fspath__ = Fake._return
32083224

32093225

32103226
class _ALWAYS_EQ:

Lib/test/test_buffer.py

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import contextlib
1717
import unittest
1818
from test import support
19+
from test.support import FakeIndex, FakeInt
1920
from itertools import permutations, product
2021
from random import randrange, sample, choice
2122
import warnings
@@ -2510,22 +2511,9 @@ def test_memoryview_sizeof(self):
25102511
check(memoryview(a), vsize(base_struct + 3 * per_dim))
25112512

25122513
def test_memoryview_struct_module(self):
2513-
2514-
class INT(object):
2515-
def __init__(self, val):
2516-
self.val = val
2517-
def __int__(self):
2518-
return self.val
2519-
2520-
class IDX(object):
2521-
def __init__(self, val):
2522-
self.val = val
2523-
def __index__(self):
2524-
return self.val
2525-
25262514
def f(): return 7
25272515

2528-
values = [INT(9), IDX(9),
2516+
values = [FakeInt(9), FakeIndex(9),
25292517
2.2+3j, Decimal("-21.1"), 12.2, Fraction(5, 2),
25302518
[1,2,3], {4,5,6}, {7:8}, (), (9,),
25312519
True, False, None, Ellipsis,

Lib/test/test_bytes.py

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import test.support
1919
import test.string_tests
2020
import test.list_tests
21-
from test.support import bigaddrspacetest, MAX_Py_ssize_t
21+
from test.support import bigaddrspacetest, MAX_Py_ssize_t, FakeIndex
2222
from test.support.script_helper import assert_python_failure
2323

2424

@@ -35,13 +35,6 @@ def check_bytes_warnings(func):
3535
return func
3636

3737

38-
class Indexable:
39-
def __init__(self, value=0):
40-
self.value = value
41-
def __index__(self):
42-
return self.value
43-
44-
4538
class BaseBytesTest:
4639

4740
def test_basics(self):
@@ -133,11 +126,11 @@ def __index__(self):
133126
self.assertEqual(bytes(a), b'*' * 1000) # should not crash
134127

135128
def test_from_index(self):
136-
b = self.type2test([Indexable(), Indexable(1), Indexable(254),
137-
Indexable(255)])
129+
b = self.type2test([FakeIndex(0), FakeIndex(1), FakeIndex(254),
130+
FakeIndex(255)])
138131
self.assertEqual(list(b), [0, 1, 254, 255])
139-
self.assertRaises(ValueError, self.type2test, [Indexable(-1)])
140-
self.assertRaises(ValueError, self.type2test, [Indexable(256)])
132+
self.assertRaises(ValueError, self.type2test, [FakeIndex(-1)])
133+
self.assertRaises(ValueError, self.type2test, [FakeIndex(256)])
141134

142135
def test_from_buffer(self):
143136
a = self.type2test(array.array('B', [1, 2, 3]))
@@ -208,11 +201,8 @@ def test_constructor_overflow(self):
208201
def test_constructor_exceptions(self):
209202
# Issue #34974: bytes and bytearray constructors replace unexpected
210203
# exceptions.
211-
class BadInt:
212-
def __index__(self):
213-
1/0
214-
self.assertRaises(ZeroDivisionError, self.type2test, BadInt())
215-
self.assertRaises(ZeroDivisionError, self.type2test, [BadInt()])
204+
self.assertRaises(ZeroDivisionError, self.type2test, FakeIndex(ZeroDivisionError))
205+
self.assertRaises(ZeroDivisionError, self.type2test, [FakeIndex(ZeroDivisionError)])
216206

217207
class BadIterable:
218208
def __iter__(self):
@@ -1267,7 +1257,7 @@ def test_setitem(self):
12671257
self.assertEqual(b, bytearray([1, 100, 3]))
12681258
b[-1] = 200
12691259
self.assertEqual(b, bytearray([1, 100, 200]))
1270-
b[0] = Indexable(10)
1260+
b[0] = FakeIndex(10)
12711261
self.assertEqual(b, bytearray([10, 100, 200]))
12721262
try:
12731263
b[3] = 0
@@ -1285,7 +1275,7 @@ def test_setitem(self):
12851275
except ValueError:
12861276
pass
12871277
try:
1288-
b[0] = Indexable(-1)
1278+
b[0] = FakeIndex(-1)
12891279
self.fail("Didn't raise ValueError")
12901280
except ValueError:
12911281
pass
@@ -1483,7 +1473,7 @@ def test_extend(self):
14831473
self.assertRaises(ValueError, a.extend, [0, 1, 2, -1])
14841474
self.assertEqual(len(a), 0)
14851475
a = bytearray(b'')
1486-
a.extend([Indexable(ord('a'))])
1476+
a.extend([FakeIndex(ord('a'))])
14871477
self.assertEqual(a, b'a')
14881478

14891479
def test_remove(self):
@@ -1500,7 +1490,7 @@ def test_remove(self):
15001490
b.remove(ord('h'))
15011491
self.assertEqual(b, b'e')
15021492
self.assertRaises(TypeError, lambda: b.remove(b'e'))
1503-
b.remove(Indexable(ord('e')))
1493+
b.remove(FakeIndex(ord('e')))
15041494
self.assertEqual(b, b'')
15051495

15061496
# test values outside of the ascii range: (0, 127)
@@ -1533,7 +1523,7 @@ def test_append(self):
15331523
self.assertEqual(len(b), 1)
15341524
self.assertRaises(TypeError, lambda: b.append(b'o'))
15351525
b = bytearray()
1536-
b.append(Indexable(ord('A')))
1526+
b.append(FakeIndex(ord('A')))
15371527
self.assertEqual(b, b'A')
15381528

15391529
def test_insert(self):
@@ -1545,7 +1535,7 @@ def test_insert(self):
15451535
self.assertEqual(b, b'mississippi')
15461536
self.assertRaises(TypeError, lambda: b.insert(0, b'1'))
15471537
b = bytearray()
1548-
b.insert(0, Indexable(ord('A')))
1538+
b.insert(0, FakeIndex(ord('A')))
15491539
self.assertEqual(b, b'A')
15501540

15511541
def test_copied(self):

Lib/test/test_cmath.py

Lines changed: 10 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from test.support import requires_IEEE_754, cpython_only
2+
from test.support import FakeIndex, FakeInt, FakeFloat, FakeComplex
23
from test.test_math import parse_testfile, test_file
34
import test.test_math as test_math
45
import unittest
@@ -191,85 +192,34 @@ def test_user_object(self):
191192
# Now we introduce a variety of classes whose instances might
192193
# end up being passed to the cmath functions
193194

194-
# usual case: new-style class implementing __complex__
195-
class MyComplex(object):
196-
def __init__(self, value):
197-
self.value = value
198-
def __complex__(self):
199-
return self.value
200-
201-
# old-style class implementing __complex__
202-
class MyComplexOS:
203-
def __init__(self, value):
204-
self.value = value
205-
def __complex__(self):
206-
return self.value
207-
208-
# classes for which __complex__ raises an exception
209195
class SomeException(Exception):
210196
pass
211-
class MyComplexException(object):
212-
def __complex__(self):
213-
raise SomeException
214-
class MyComplexExceptionOS:
215-
def __complex__(self):
216-
raise SomeException
217-
218-
# some classes not providing __float__ or __complex__
219-
class NeitherComplexNorFloat(object):
220-
pass
221-
class NeitherComplexNorFloatOS:
222-
pass
223-
class Index:
224-
def __int__(self): return 2
225-
def __index__(self): return 2
226-
class MyInt:
227-
def __int__(self): return 2
228197

229198
# other possible combinations of __float__ and __complex__
230199
# that should work
231-
class FloatAndComplex(object):
200+
class FloatAndComplex:
232201
def __float__(self):
233202
return flt_arg
234203
def __complex__(self):
235204
return cx_arg
236-
class FloatAndComplexOS:
237-
def __float__(self):
238-
return flt_arg
239-
def __complex__(self):
240-
return cx_arg
241-
class JustFloat(object):
242-
def __float__(self):
243-
return flt_arg
244-
class JustFloatOS:
245-
def __float__(self):
246-
return flt_arg
247205

248206
for f in self.test_functions:
249207
# usual usage
250-
self.assertEqual(f(MyComplex(cx_arg)), f(cx_arg))
251-
self.assertEqual(f(MyComplexOS(cx_arg)), f(cx_arg))
208+
self.assertEqual(f(FakeComplex(cx_arg)), f(cx_arg))
252209
# other combinations of __float__ and __complex__
253210
self.assertEqual(f(FloatAndComplex()), f(cx_arg))
254-
self.assertEqual(f(FloatAndComplexOS()), f(cx_arg))
255-
self.assertEqual(f(JustFloat()), f(flt_arg))
256-
self.assertEqual(f(JustFloatOS()), f(flt_arg))
257-
self.assertEqual(f(Index()), f(int(Index())))
211+
self.assertEqual(f(FakeFloat(flt_arg)), f(flt_arg))
212+
self.assertEqual(f(FakeIndex(2)), f(2))
258213
# TypeError should be raised for classes not providing
259214
# either __complex__ or __float__, even if they provide
260-
# __int__ or __index__. An old-style class
261-
# currently raises AttributeError instead of a TypeError;
262-
# this could be considered a bug.
263-
self.assertRaises(TypeError, f, NeitherComplexNorFloat())
264-
self.assertRaises(TypeError, f, MyInt())
265-
self.assertRaises(Exception, f, NeitherComplexNorFloatOS())
215+
# __int__.
216+
self.assertRaises(TypeError, f, object())
217+
self.assertRaises(TypeError, f, FakeInt(2))
266218
# non-complex return value from __complex__ -> TypeError
267219
for bad_complex in non_complexes:
268-
self.assertRaises(TypeError, f, MyComplex(bad_complex))
269-
self.assertRaises(TypeError, f, MyComplexOS(bad_complex))
220+
self.assertRaises(TypeError, f, FakeComplex(bad_complex))
270221
# exceptions in __complex__ should be propagated correctly
271-
self.assertRaises(SomeException, f, MyComplexException())
272-
self.assertRaises(SomeException, f, MyComplexExceptionOS())
222+
self.assertRaises(SomeException, f, FakeComplex(SomeException))
273223

274224
def test_input_type(self):
275225
# ints should be acceptable inputs to all cmath

0 commit comments

Comments
 (0)