Skip to content

Commit 2b751f7

Browse files
committed
Restore guarded C API argument and object test sources
Restore ten CPython 3.15 test modules through the actual update_lib migrator. Eight are canonical copies; codecs/getargs use declared exact optional-module and required-attribute bindings while all class/function/decorator/assertion ASTs remain unchanged. Extend the landed generic updater with an explicit import-binding rewrite option, preserving default validation and hash/path/block/protected-AST guards. Reproduced on main 88f3733 after both prerequisite PRs landed. The recovered reviewed tooling delta is applied before migration; no synthetic dependency commit is included. Current host tooling suite passes 241 tests with Python 3.13, selected AST/source proof and normal hooks pass, and all output bytes match preserved historical Python 3.15 migration hashes. This is not a fresh Python 3.15 runtime or dependency-graph validation. No C API test modules or native fixtures were executed; unsupported fixture skips are not complete C API compatibility. Assisted-by: OpenAI Codex:model version unavailable
1 parent 88f3733 commit 2b751f7

13 files changed

Lines changed: 5471 additions & 9 deletions

‎Lib/test/test_capi/test_codecs.py‎

Lines changed: 880 additions & 0 deletions
Large diffs are not rendered by default.

‎Lib/test/test_capi/test_complex.py‎

Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
from math import isnan
2+
import errno
3+
import unittest
4+
import warnings
5+
6+
from test.test_capi.test_getargs import (BadComplex, BadComplex2, Complex,
7+
FloatSubclass, Float, BadFloat,
8+
BadFloat2, ComplexSubclass)
9+
from test.support import import_helper
10+
from test.support.testcase import ComplexesAreIdenticalMixin
11+
12+
13+
_testcapi = import_helper.import_module('_testcapi')
14+
_testlimitedcapi = import_helper.import_module('_testlimitedcapi')
15+
_testinternalcapi = import_helper.import_module('_testinternalcapi')
16+
17+
NULL = None
18+
INF = float("inf")
19+
NAN = float("nan")
20+
DBL_MAX = _testcapi.DBL_MAX
21+
22+
23+
class BadComplex3:
24+
def __complex__(self):
25+
raise RuntimeError
26+
27+
28+
class CAPIComplexTest(ComplexesAreIdenticalMixin, unittest.TestCase):
29+
def test_check(self):
30+
# Test PyComplex_Check()
31+
check = _testlimitedcapi.complex_check
32+
33+
self.assertTrue(check(1+2j))
34+
self.assertTrue(check(ComplexSubclass(1+2j)))
35+
self.assertFalse(check(Complex()))
36+
self.assertFalse(check(3))
37+
self.assertFalse(check(3.0))
38+
self.assertFalse(check(object()))
39+
40+
# CRASHES check(NULL)
41+
42+
def test_checkexact(self):
43+
# PyComplex_CheckExact()
44+
checkexact = _testlimitedcapi.complex_checkexact
45+
46+
self.assertTrue(checkexact(1+2j))
47+
self.assertFalse(checkexact(ComplexSubclass(1+2j)))
48+
self.assertFalse(checkexact(Complex()))
49+
self.assertFalse(checkexact(3))
50+
self.assertFalse(checkexact(3.0))
51+
self.assertFalse(checkexact(object()))
52+
53+
# CRASHES checkexact(NULL)
54+
55+
def test_fromccomplex(self):
56+
# Test PyComplex_FromCComplex()
57+
fromccomplex = _testcapi.complex_fromccomplex
58+
59+
self.assertEqual(fromccomplex(1+2j), 1.0+2.0j)
60+
61+
def test_fromdoubles(self):
62+
# Test PyComplex_FromDoubles()
63+
fromdoubles = _testlimitedcapi.complex_fromdoubles
64+
65+
self.assertEqual(fromdoubles(1.0, 2.0), 1.0+2.0j)
66+
67+
def test_realasdouble(self):
68+
# Test PyComplex_RealAsDouble()
69+
realasdouble = _testlimitedcapi.complex_realasdouble
70+
71+
self.assertEqual(realasdouble(1+2j), 1.0)
72+
self.assertEqual(realasdouble(-1+0j), -1.0)
73+
self.assertEqual(realasdouble(4.25), 4.25)
74+
self.assertEqual(realasdouble(-1.0), -1.0)
75+
self.assertEqual(realasdouble(42), 42.)
76+
self.assertEqual(realasdouble(-1), -1.0)
77+
78+
# Test subclasses of complex/float
79+
self.assertEqual(realasdouble(ComplexSubclass(1+2j)), 1.0)
80+
self.assertEqual(realasdouble(FloatSubclass(4.25)), 4.25)
81+
82+
# Test types with __complex__ dunder method
83+
self.assertEqual(realasdouble(Complex()), 4.25)
84+
self.assertRaises(TypeError, realasdouble, BadComplex())
85+
with self.assertWarns(DeprecationWarning):
86+
self.assertEqual(realasdouble(BadComplex2()), 4.25)
87+
with warnings.catch_warnings():
88+
warnings.simplefilter("error", DeprecationWarning)
89+
self.assertRaises(DeprecationWarning, realasdouble, BadComplex2())
90+
self.assertRaises(RuntimeError, realasdouble, BadComplex3())
91+
92+
# Test types with __float__ dunder method
93+
self.assertEqual(realasdouble(Float()), 4.25)
94+
self.assertRaises(TypeError, realasdouble, BadFloat())
95+
with self.assertWarns(DeprecationWarning):
96+
self.assertEqual(realasdouble(BadFloat2()), 4.25)
97+
98+
self.assertRaises(TypeError, realasdouble, object())
99+
100+
# CRASHES realasdouble(NULL)
101+
102+
def test_imagasdouble(self):
103+
# Test PyComplex_ImagAsDouble()
104+
imagasdouble = _testlimitedcapi.complex_imagasdouble
105+
106+
self.assertEqual(imagasdouble(1+2j), 2.0)
107+
self.assertEqual(imagasdouble(1-1j), -1.0)
108+
self.assertEqual(imagasdouble(4.25), 0.0)
109+
self.assertEqual(imagasdouble(42), 0.0)
110+
111+
# Test subclasses of complex/float
112+
self.assertEqual(imagasdouble(ComplexSubclass(1+2j)), 2.0)
113+
self.assertEqual(imagasdouble(FloatSubclass(4.25)), 0.0)
114+
115+
# Test types with __complex__ dunder method
116+
self.assertEqual(imagasdouble(Complex()), 0.5)
117+
self.assertRaises(TypeError, imagasdouble, BadComplex())
118+
with self.assertWarns(DeprecationWarning):
119+
self.assertEqual(imagasdouble(BadComplex2()), 0.5)
120+
with warnings.catch_warnings():
121+
warnings.simplefilter("error", DeprecationWarning)
122+
self.assertRaises(DeprecationWarning, imagasdouble, BadComplex2())
123+
self.assertRaises(RuntimeError, imagasdouble, BadComplex3())
124+
125+
# Test types with __float__ dunder method
126+
self.assertEqual(imagasdouble(Float()), 0.0)
127+
self.assertRaises(TypeError, imagasdouble, BadFloat())
128+
with self.assertWarns(DeprecationWarning):
129+
self.assertEqual(imagasdouble(BadFloat2()), 0.0)
130+
131+
self.assertRaises(TypeError, imagasdouble, object())
132+
133+
# CRASHES imagasdouble(NULL)
134+
135+
def test_asccomplex(self):
136+
# Test PyComplex_AsCComplex()
137+
asccomplex = _testcapi.complex_asccomplex
138+
139+
self.assertEqual(asccomplex(1+2j), 1.0+2.0j)
140+
self.assertEqual(asccomplex(-1+2j), -1.0+2.0j)
141+
self.assertEqual(asccomplex(4.25), 4.25+0.0j)
142+
self.assertEqual(asccomplex(-1.0), -1.0+0.0j)
143+
self.assertEqual(asccomplex(42), 42+0j)
144+
self.assertEqual(asccomplex(-1), -1.0+0.0j)
145+
146+
# Test subclasses of complex/float
147+
self.assertEqual(asccomplex(ComplexSubclass(1+2j)), 1.0+2.0j)
148+
self.assertEqual(asccomplex(FloatSubclass(4.25)), 4.25+0.0j)
149+
150+
# Test types with __complex__ dunder method
151+
self.assertEqual(asccomplex(Complex()), 4.25+0.5j)
152+
self.assertRaises(TypeError, asccomplex, BadComplex())
153+
with self.assertWarns(DeprecationWarning):
154+
self.assertEqual(asccomplex(BadComplex2()), 4.25+0.5j)
155+
with warnings.catch_warnings():
156+
warnings.simplefilter("error", DeprecationWarning)
157+
self.assertRaises(DeprecationWarning, asccomplex, BadComplex2())
158+
self.assertRaises(RuntimeError, asccomplex, BadComplex3())
159+
160+
# Test types with __float__ dunder method
161+
self.assertEqual(asccomplex(Float()), 4.25+0.0j)
162+
self.assertRaises(TypeError, asccomplex, BadFloat())
163+
with self.assertWarns(DeprecationWarning):
164+
self.assertEqual(asccomplex(BadFloat2()), 4.25+0.0j)
165+
166+
self.assertRaises(TypeError, asccomplex, object())
167+
168+
# CRASHES asccomplex(NULL)
169+
170+
def test_py_c_sum(self):
171+
# Test _Py_c_sum()
172+
_py_c_sum = _testcapi._py_c_sum
173+
174+
self.assertEqual(_py_c_sum(1, 1j), (1+1j, 0))
175+
176+
def test_py_cr_sum(self):
177+
# Test _Py_cr_sum()
178+
_py_cr_sum = _testinternalcapi._py_cr_sum
179+
180+
self.assertComplexesAreIdentical(_py_cr_sum(-0j, -0.0)[0],
181+
complex(-0.0, -0.0))
182+
183+
def test_py_c_diff(self):
184+
# Test _Py_c_diff()
185+
_py_c_diff = _testcapi._py_c_diff
186+
187+
self.assertEqual(_py_c_diff(1, 1j), (1-1j, 0))
188+
189+
def test_py_cr_diff(self):
190+
# Test _Py_cr_diff()
191+
_py_cr_diff = _testinternalcapi._py_cr_diff
192+
193+
self.assertComplexesAreIdentical(_py_cr_diff(-0j, 0.0)[0],
194+
complex(-0.0, -0.0))
195+
196+
def test_py_rc_diff(self):
197+
# Test _Py_rc_diff()
198+
_py_rc_diff = _testinternalcapi._py_rc_diff
199+
200+
self.assertComplexesAreIdentical(_py_rc_diff(-0.0, 0j)[0],
201+
complex(-0.0, -0.0))
202+
203+
def test_py_c_neg(self):
204+
# Test _Py_c_neg()
205+
_py_c_neg = _testcapi._py_c_neg
206+
207+
self.assertEqual(_py_c_neg(1+1j), -1-1j)
208+
209+
def test_py_c_prod(self):
210+
# Test _Py_c_prod()
211+
_py_c_prod = _testcapi._py_c_prod
212+
213+
self.assertEqual(_py_c_prod(2, 1j), (2j, 0))
214+
215+
def test_py_cr_prod(self):
216+
# Test _Py_cr_prod()
217+
_py_cr_prod = _testinternalcapi._py_cr_prod
218+
219+
self.assertComplexesAreIdentical(_py_cr_prod(complex('inf+1j'), INF)[0],
220+
complex('inf+infj'))
221+
222+
def test_py_c_quot(self):
223+
# Test _Py_c_quot()
224+
_py_c_quot = _testcapi._py_c_quot
225+
226+
self.assertEqual(_py_c_quot(1, 1j), (-1j, 0))
227+
self.assertEqual(_py_c_quot(1, -1j), (1j, 0))
228+
self.assertEqual(_py_c_quot(1j, 2), (0.5j, 0))
229+
self.assertEqual(_py_c_quot(1j, -2), (-0.5j, 0))
230+
self.assertEqual(_py_c_quot(1, 2j), (-0.5j, 0))
231+
232+
z, e = _py_c_quot(NAN, 1j)
233+
self.assertTrue(isnan(z.real))
234+
self.assertTrue(isnan(z.imag))
235+
self.assertEqual(e, 0)
236+
237+
z, e = _py_c_quot(1j, NAN)
238+
self.assertTrue(isnan(z.real))
239+
self.assertTrue(isnan(z.imag))
240+
self.assertEqual(e, 0)
241+
242+
self.assertEqual(_py_c_quot(1, 0j)[1], errno.EDOM)
243+
244+
def test_py_cr_quot(self):
245+
# Test _Py_cr_quot()
246+
_py_cr_quot = _testinternalcapi._py_cr_quot
247+
248+
self.assertComplexesAreIdentical(_py_cr_quot(complex('inf+1j'), 2**1000)[0],
249+
INF + 2**-1000*1j)
250+
251+
def test_py_rc_quot(self):
252+
# Test _Py_rc_quot()
253+
_py_rc_quot = _testinternalcapi._py_rc_quot
254+
255+
self.assertComplexesAreIdentical(_py_rc_quot(1.0, complex('nan-infj'))[0],
256+
0j)
257+
258+
def test_py_c_pow(self):
259+
# Test _Py_c_pow()
260+
_py_c_pow = _testcapi._py_c_pow
261+
262+
self.assertEqual(_py_c_pow(1j, 0j), (1+0j, 0))
263+
self.assertEqual(_py_c_pow(1, 1j), (1+0j, 0))
264+
self.assertEqual(_py_c_pow(0j, 1), (0j, 0))
265+
self.assertAlmostEqual(_py_c_pow(1j, 2)[0], -1.0+0j)
266+
267+
r, e = _py_c_pow(1+1j, -1)
268+
self.assertAlmostEqual(r, 0.5-0.5j)
269+
self.assertEqual(e, 0)
270+
271+
self.assertEqual(_py_c_pow(0j, -1)[1], errno.EDOM)
272+
self.assertEqual(_py_c_pow(0j, 1j)[1], errno.EDOM)
273+
max_num = DBL_MAX+1j
274+
self.assertEqual(_py_c_pow(max_num, max_num),
275+
(complex(INF, INF), errno.ERANGE))
276+
self.assertEqual(_py_c_pow(max_num, 2),
277+
(complex(INF, INF), errno.ERANGE))
278+
279+
280+
def test_py_c_abs(self):
281+
# Test _Py_c_abs()
282+
_py_c_abs = _testcapi._py_c_abs
283+
284+
self.assertEqual(_py_c_abs(-1), (1.0, 0))
285+
self.assertEqual(_py_c_abs(1j), (1.0, 0))
286+
287+
self.assertEqual(_py_c_abs(complex('+inf+1j')), (INF, 0))
288+
self.assertEqual(_py_c_abs(complex('-inf+1j')), (INF, 0))
289+
self.assertEqual(_py_c_abs(complex('1.25+infj')), (INF, 0))
290+
self.assertEqual(_py_c_abs(complex('1.25-infj')), (INF, 0))
291+
292+
self.assertTrue(isnan(_py_c_abs(complex('1.25+nanj'))[0]))
293+
self.assertTrue(isnan(_py_c_abs(complex('nan-1j'))[0]))
294+
295+
self.assertEqual(_py_c_abs(complex(*[DBL_MAX]*2))[1], errno.ERANGE)
296+
297+
298+
if __name__ == "__main__":
299+
unittest.main()

0 commit comments

Comments
 (0)