Skip to content

Commit 4d4790a

Browse files
committed
[GR-63680] Refactor LookupAndCallUnaryNode missing-method handling.
PullRequest: graalpython/4286
2 parents 5061b3c + 801b124 commit 4d4790a

File tree

22 files changed

+226
-130
lines changed

22 files changed

+226
-130
lines changed

ci/graal/common.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"Jsonnet files should not include this file directly but use ci/common.jsonnet instead."
55
],
66

7-
"mx_version": "7.68.13",
7+
"mx_version": "7.69.0",
88

99
"COMMENT.jdks": "When adding or removing JDKs keep in sync with JDKs in ci/common.jsonnet",
1010
"jdks": {

graalpython/com.oracle.graal.python.test/src/tests/test_complex.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0
@@ -187,7 +187,7 @@ def __index__(self):
187187
c = complex(CP1(5+5j), 7+7j)
188188
assert c == complex(-2, 12)
189189
assert type(c) == complex
190-
190+
191191
c = complex(CP1(5+5j), CP1(7+7j))
192192
assert c == complex(-2, 12)
193193
assert type(c) == complex
@@ -203,7 +203,7 @@ def __index__(self):
203203
c = CP1(CP1(5+5j), 7+7j)
204204
assert c == complex(-2, 12)
205205
assert type(c) == CP1
206-
206+
207207
c = CP1(CP1(5+5j), CP1(7+7j))
208208
assert c == complex(-2, 12)
209209
assert type(c) == CP1
@@ -215,7 +215,7 @@ def __index__(self):
215215
c = CP1(CP2(5+5j), 7+7j)
216216
assert c == complex(-7, 49)
217217
assert type(c) == CP1
218-
218+
219219
c = CP1(CP2(5+5j), CP2(7+7j))
220220
assert c == complex(-7, 49)
221221
assert type(c) == CP1
@@ -227,7 +227,7 @@ def __index__(self):
227227
c = complex(CP2(5+5j), 7+7j)
228228
assert c == complex(-7, 49)
229229
assert type(c) == complex
230-
230+
231231
c = complex(CP2(5+5j), CP2(7+7j))
232232
assert c == complex(-7, 49)
233233
assert type(c) == complex
@@ -243,7 +243,7 @@ def __index__(self):
243243
c = CP2(CP2(5+5j), 7+7j)
244244
assert c == complex(-7, 49)
245245
assert type(c) == CP2
246-
246+
247247
c = CP2(CP2(5+5j), CP2(7+7j))
248248
assert c == complex(-7, 49)
249249
assert type(c) == CP2
@@ -252,6 +252,17 @@ def __index__(self):
252252
if sys.version_info >= (3, 8, 0):
253253
assert complex(CP4()) == complex(123)
254254

255+
256+
def test_complex_subclass_without_dunder_complex_uses_fallback():
257+
class SubComplex(complex):
258+
pass
259+
260+
value = SubComplex(2 + 3j)
261+
result = complex(value)
262+
263+
assert result == 2 + 3j
264+
assert type(result) is complex
265+
255266
class ComplexTest(unittest.TestCase):
256267

257268
def assertAlmostEqual(self, a, b):
@@ -442,7 +453,7 @@ def __complex__(self):
442453
return None
443454

444455
self.assertEqual(complex(complex0(1j)), 42j)
445-
# TODO we are not able to throw warning now.
456+
# TODO we are not able to throw warning now.
446457
# with self.assertWarns(DeprecationWarning):
447458
self.assertEqual(complex(complex1(1j)), 2j)
448459
self.assertRaises(TypeError, complex, complex2(1j))

graalpython/com.oracle.graal.python.test/src/tests/test_float.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0
@@ -148,6 +148,23 @@ def __round__(x, n):
148148
a = object()
149149
assert round(C(), a) == a
150150

151+
def test_round_missing_special_method(self):
152+
class MissingRound:
153+
def __getattr__(self, name):
154+
if name == "__round__":
155+
return lambda *args: 42
156+
raise AttributeError(name)
157+
158+
with self.assertRaisesRegex(TypeError, "__round__"):
159+
round(MissingRound())
160+
161+
def test_round_returns_notimplemented(self):
162+
class NotImplementedRound:
163+
def __round__(self, *args):
164+
return NotImplemented
165+
166+
assert round(NotImplementedRound()) is NotImplemented
167+
151168
def test_create(self):
152169
class Obj:
153170
def __float__(self):

graalpython/com.oracle.graal.python.test/src/tests/test_int.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0
@@ -703,6 +703,13 @@ def __bytes__(self):
703703

704704
self.assertEqual(int.from_bytes(mybyteslike(), 'big'), 2580)
705705

706+
def test_from_object_without_bytes_uses_iterable_fallback(self):
707+
class IterableOnly:
708+
def __iter__(self):
709+
return iter([1, 2, 3])
710+
711+
self.assertEqual(int.from_bytes(IterableOnly(), 'big'), 0x010203)
712+
706713
def test_from_wrong_byteslike_object(self):
707714
class mybyteslike1():
708715
def __bytes__(self):

graalpython/com.oracle.graal.python.test/src/tests/test_json.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,26 @@
5959

6060

6161
class JsonTest(unittest.TestCase):
62+
def test_callable_object_hook(self):
63+
called = []
64+
class Hook:
65+
def __call__(self, obj):
66+
called.append(True)
67+
return obj
68+
69+
hook_instance = Hook()
70+
result = json.loads('{"a": 1, "b": 2}', object_hook=hook_instance)
71+
assert len(called) == 1
72+
assert result == {"a": 1, "b": 2}
73+
74+
def test_invalid_object_hook(self):
75+
with self.assertRaises(TypeError):
76+
json.loads('{"a": 1}', object_hook="not_a_function")
77+
78+
def test_invalid_object_pairs_hook(self):
79+
with self.assertRaises(TypeError):
80+
json.loads('{"a": 1}', object_pairs_hook=12345)
81+
6282
def test_dump(self):
6383
cwd = os.getcwd()
6484
new_file_path = os.path.join(cwd, 'myFile.json')

graalpython/com.oracle.graal.python.test/src/tests/test_math.py

Lines changed: 51 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, 2023, Oracle and/or its affiliates.
1+
# Copyright (c) 2018, 2026, Oracle and/or its affiliates.
22
# Copyright (C) 1996-2017 Python Software Foundation
33
#
44
# Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
@@ -214,7 +214,7 @@ def testAcos(self):
214214
class MyFloat2:
215215
def __float__(self):
216216
return 1.6
217-
self.assertRaises(ValueError, math.acos, MyFloat2())
217+
self.assertRaises(ValueError, math.acos, MyFloat2())
218218

219219
class MyFloat3:
220220
def __float__(self):
@@ -265,7 +265,7 @@ def testSqrt(self):
265265
self.assertRaises(ValueError, math.sqrt, -1)
266266
self.assertRaises(ValueError, math.sqrt, NINF)
267267
self.assertTrue(math.isnan(math.sqrt(NAN)))
268-
268+
269269
math.sqrt(MyFloat())
270270
math.sqrt(BIG_INT)
271271
self.assertRaises(TypeError, math.asin, 'ahoj')
@@ -307,7 +307,7 @@ def testLog1p(self):
307307
self.assertAlmostEqual(math.log1p(n), math.log1p(float(n)))
308308
self.assertRaises(ValueError, math.log1p, -1)
309309
self.assertEqual(math.log1p(INF), INF)
310-
310+
311311
# test of specializations
312312
self.ftest('log1p(MyFloat())', math.log1p(MyFloat()), 0.4700036292457356)
313313
self.assertRaises(TypeError, math.log1p, 'ahoj')
@@ -382,7 +382,7 @@ def testIsinf(self):
382382
self.assertFalse(math.isinf(float("nan")))
383383
self.assertFalse(math.isinf(0.))
384384
self.assertFalse(math.isinf(1.))
385-
385+
386386
self.assertFalse(math.isinf(True))
387387
self.assertFalse(math.isinf(LONG_INT))
388388
self.assertFalse(math.isinf(BIG_INT))
@@ -484,7 +484,7 @@ def test_basic_copysign(self):
484484
self.assertEqual(math.copysign(999999999999999999999.1, 1), 999999999999999999999.1)
485485
self.assertRaises(TypeError, math.copysign, 'hello', 1)
486486
self.assertRaises(TypeError, math.copysign, 1, 'hello')
487-
487+
488488
self.assertEqual(math.copysign(MyFloat(), 1), 0.6)
489489
self.assertEqual(math.copysign(MyFloat(), -1), -0.6)
490490
self.assertEqual(math.copysign(1.2, MyFloat()), 1.2)
@@ -679,12 +679,12 @@ def testPow(self):
679679
self.assertEqual(math.pow(999999999999999999999999999, 0), 1)
680680
self.assertEqual(math.pow(0.0, 999999999999999999999999999), 0)
681681
self.assertEqual(math.pow(999999999999999999999999999, 0.0), 1)
682-
682+
683683
class MyNumber():
684684
def __float__(self):
685685
return -2.;
686686
self.ftest('MyFloat()**-3.', math.pow(MyNumber(), -3.0), -0.125)
687-
687+
688688
def testAtan2(self):
689689
self.assertRaises(TypeError, math.atan2)
690690
self.ftest('atan2(-1, 0)', math.atan2(-1, 0), -math.pi/2)
@@ -768,7 +768,7 @@ def testCos(self):
768768
self.assertRaises(ValueError, math.cos, INF)
769769
self.assertRaises(ValueError, math.cos, NINF)
770770
self.assertTrue(math.isnan(math.cos(NAN)))
771-
771+
772772
#test of specializations
773773
self.ftest('cos(BIG_INT)', math.cos(BIG_INT), 0.4145587418469303)
774774
self.ftest('cos(MyFloat())', math.cos(MyFloat()), 0.8253356149096783)
@@ -786,7 +786,7 @@ def testCosh(self):
786786
self.ftest('cosh(MyFloat())', math.cosh(MyFloat()), 1.1854652182422676)
787787
self.assertRaises(TypeError, math.cosh, 'ahoj')
788788
self.assertRaises(OverflowError, math.cosh, BIG_INT)
789-
789+
790790
def testSin(self):
791791
self.assertRaises(TypeError, math.sin)
792792
self.ftest('sin(0)', math.sin(0), 0)
@@ -813,7 +813,7 @@ def testSinh(self):
813813
self.assertEqual(math.sinh(INF), INF)
814814
self.assertEqual(math.sinh(NINF), NINF)
815815
self.assertTrue(math.isnan(math.sinh(NAN)))
816-
816+
817817
# test of specializations
818818
self.ftest('sinh(MyFloat())', math.sinh(MyFloat()), 0.6366535821482412)
819819
self.assertRaises(TypeError, math.sinh, 'ahoj')
@@ -1128,7 +1128,7 @@ def testExp(self):
11281128
self.assertEqual(math.exp(NINF), 0.)
11291129
self.assertTrue(math.isnan(math.exp(NAN)))
11301130
self.assertRaises(OverflowError, math.exp, 1000000)
1131-
1131+
11321132
# test of specializations
11331133
self.ftest('exp(MyFloat())', math.exp(MyFloat()), 1.8221188003905089)
11341134
self.assertRaises(TypeError, math.exp, 'ahoj')
@@ -1239,7 +1239,7 @@ class II(int):
12391239
self.assertRaises(TypeError, math.ldexp, 'Hello', 1000000)
12401240
self.assertRaises(TypeError, math.ldexp, 1, 'Hello')
12411241
self.assertEqual(math.ldexp(7589167167882033, -48), 26.962138008038156)
1242-
1242+
12431243
self.assertRaises(TypeError, math.ldexp, 1, MyIndexable(2))
12441244
self.assertRaises(TypeError, math.ldexp, 1, MyInt(2))
12451245
self.assertRaises(TypeError, math.ldexp, 1, MyFloat())
@@ -1272,6 +1272,20 @@ class TestNoTrunc(object):
12721272
self.assertRaises(TypeError, math.trunc, 1, 2)
12731273
self.assertRaises(TypeError, math.trunc, TestNoTrunc())
12741274

1275+
class MissingTrunc:
1276+
def __getattr__(self, name):
1277+
if name == "__trunc__":
1278+
return lambda: 99
1279+
raise AttributeError(name)
1280+
1281+
self.assertRaises(TypeError, math.trunc, MissingTrunc())
1282+
1283+
class NotImplementedTrunc:
1284+
def __trunc__(self):
1285+
return NotImplemented
1286+
1287+
self.assertIs(math.trunc(NotImplementedTrunc()), NotImplemented)
1288+
12751289
def testDegrees(self):
12761290
self.assertRaises(TypeError, math.degrees)
12771291
self.ftest('degrees(pi)', math.degrees(math.pi), 180.0)
@@ -1325,7 +1339,7 @@ def executeFnTest(self, values, fn, fnName):
13251339
result = fn(value[0])
13261340
expected = value[1]
13271341
if math.isnan(expected):
1328-
self.assertTrue(math.isnan(result), "Test2 fail: {}({}) = {}, but was {}".format(fnName, value[0], expected, result))
1342+
self.assertTrue(math.isnan(result), "Test2 fail: {}({}) = {}, but was {}".format(fnName, value[0], expected, result))
13291343
else :
13301344
if result != expected:
13311345
if (sys.version_info.major >= 3 and sys.version_info.minor >= 5):
@@ -1334,7 +1348,7 @@ def executeFnTest(self, values, fn, fnName):
13341348
def test_erf(self):
13351349
erfValues = [(0.0, 0.0), (-0.0, -0.0), (INF, 1.0), (NINF, -1.0), (NAN, NAN),
13361350
# tiny values
1337-
(1e-308, 1.1283791670955125e-308), (5e-324, 4.9406564584124654e-324),
1351+
(1e-308, 1.1283791670955125e-308), (5e-324, 4.9406564584124654e-324),
13381352
(1e-10, 1.1283791670955126e-10),
13391353
# small integers
13401354
(1, 0.842700792949715), (2, 0.99532226501895271), (3, 0.99997790950300136),
@@ -1356,7 +1370,7 @@ def test_erfc(self):
13561370
(1e-308, 1.0), (5e-324, 1.0), (1e-10, 0.99999999988716204),
13571371
# small integers
13581372
(1, 0.157299207050285), (2, 0.004677734981047268), (3, 2.2090496998585482e-05),
1359-
(4, 1.541725790028002e-08), (5, 1.5374597944280341e-12),
1373+
(4, 1.541725790028002e-08), (5, 1.5374597944280341e-12),
13601374
# this number needs to be rounded
13611375
(6, 2.1519736712498925e-17),
13621376
(-1, 1.842700792949715), (-2, 1.9953222650189528), (-3, 1.9999779095030015),
@@ -1372,7 +1386,7 @@ def test_erfc(self):
13721386
(-26.8, 2.0), (-27.0, 2.0), (-27.2, 2.0), (-27.4, 2.0), (-27.6, 2.0)
13731387
]
13741388
self.executeFnTest(values, math.erfc, 'math.erfc')
1375-
1389+
13761390
def test_gamma(self):
13771391
self.assertRaises(ValueError, math.gamma, 0.)
13781392
self.assertRaises(ValueError, math.gamma, -0.0)
@@ -1400,34 +1414,34 @@ def test_gamma(self):
14001414
(3.5, 3.323350970447842), (-0.5, -3.5449077018110322), (-1.5, 2.3632718012073544),
14011415
(-2.5, -0.94530872048294170), (-3.5, 0.27008820585226917),
14021416
# values near 0
1403-
(0.1, 9.5135076986687306),
1404-
(0.01, 99.432585119150602),
1417+
(0.1, 9.5135076986687306),
1418+
(0.01, 99.432585119150602),
14051419
(1e-8, 99999999.422784343),
1406-
#(1e-16, 10000000000000000),
1420+
#(1e-16, 10000000000000000),
14071421
(1e-30, 9.9999999999999988e+29), (1e-160, 1.0000000000000000e+160),
1408-
(1e-308, 1.0000000000000000e+308),
1422+
(1e-308, 1.0000000000000000e+308),
14091423
(5.6e-309, 1.7857142857142848e+308),
1410-
(-0.1, -10.686287021193193),
1411-
(-0.01, -100.58719796441078),
1424+
(-0.1, -10.686287021193193),
1425+
(-0.01, -100.58719796441078),
14121426
(-1e-8, -100000000.57721567),
1413-
(-1e-16, -10000000000000000),
1427+
(-1e-16, -10000000000000000),
14141428
(-1e-30, -9.9999999999999988e+29), (-1e-160, -1.0000000000000000e+160),
1415-
(-1e-308, -1.0000000000000000e+308),
1429+
(-1e-308, -1.0000000000000000e+308),
14161430
(-5.6e-309, -1.7857142857142848e+308),
14171431
# values near negative integers
1418-
(-0.99999999999999989, -9007199254740992.0),
1432+
(-0.99999999999999989, -9007199254740992.0),
14191433
(-1.0000000000000002, 4503599627370495.5),
1420-
(-1.9999999999999998, 2251799813685248.5),
1434+
(-1.9999999999999998, 2251799813685248.5),
14211435
(-2.0000000000000004, -1125899906842623.5),
1422-
(-100.00000000000001, -7.5400833348831090e-145),
1436+
(-100.00000000000001, -7.5400833348831090e-145),
14231437
(-99.999999999999986, 7.5400833348840962e-145),
14241438
# large inputs
1425-
(170, 4.2690680090047051e+304),
1426-
(171, 7.2574156153079990e+306),
1439+
(170, 4.2690680090047051e+304),
1440+
(171, 7.2574156153079990e+306),
14271441
(171.624, 1.7942117599248104e+308),
14281442
# inputs for which gamma(x) is tiny
1429-
(-100.5, -3.3536908198076787e-159),
1430-
(-160.5, -5.2555464470078293e-286),
1443+
(-100.5, -3.3536908198076787e-159),
1444+
(-160.5, -5.2555464470078293e-286),
14311445
(-170.5, -3.3127395215386074e-308),
14321446
(-171.5, 1.9316265431711902e-310), (-176.5, -1.1956388629358166e-321), (-177.5, 4.9406564584124654e-324),
14331447
(-178.5, -0.0), (-179.5, 0.0), (-201.0001, 0.0), (-202.9999, -0.0), (-1000.5, -0.0),
@@ -1452,11 +1466,11 @@ def test_lgamma(self):
14521466

14531467
values = [(INF, INF), (-INF, INF), (NAN, NAN),
14541468
# small positive integers give factorials
1455-
(1, 0.0), (2, 0.0),
1456-
(3, 0.69314718055994529),
1457-
(4, 1.791759469228055),
1458-
(5, 3.1780538303479458),
1459-
(6, 4.7874917427820458),
1469+
(1, 0.0), (2, 0.0),
1470+
(3, 0.69314718055994529),
1471+
(4, 1.791759469228055),
1472+
(5, 3.1780538303479458),
1473+
(6, 4.7874917427820458),
14601474
# half integers
14611475
(0.5, 0.57236494292470008),
14621476
(1.5, -0.12078223763524522),

0 commit comments

Comments
 (0)