Skip to content

Commit 65f8ff6

Browse files
committed
[GR-60120] Support scipy 1.13.1
PullRequest: graalpython/3596
2 parents 3852160 + 42062e2 commit 65f8ff6

File tree

10 files changed

+164
-45
lines changed

10 files changed

+164
-45
lines changed

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_descr.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,3 +329,18 @@ class TestDescr(CPyExtTestCase):
329329
callfunction="wrap_PyDescr_NewClassMethod",
330330
cmpfunc=unhandled_error_compare
331331
)
332+
333+
334+
def test_class_assignment_managed_subclass():
335+
class IntermediateType(CPyExtType("BaseForAssignment")):
336+
def __repr__(self):
337+
return "intermediate"
338+
339+
class ChildType(IntermediateType):
340+
def __repr__(self):
341+
return "child"
342+
343+
o = ChildType()
344+
assert repr(o) == "child"
345+
o.__class__ = IntermediateType
346+
assert repr(o) == "intermediate"

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2018, 2024, 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
@@ -281,6 +281,9 @@ def test_compare_infinite(self):
281281
self.assertFalse(num < ninf)
282282
self.assertFalse(num <= ninf)
283283

284+
def test_too_large_exponent(self):
285+
self.assertEqual(float(9.6652344473471409e+13020482957104346813665225475455405808065502685256002111130525326263065544707062128277904331411231482727389186536355106830667631510992459549990606158658919), float('inf'))
286+
284287

285288
fromHex = float.fromhex
286289

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/FloatUtils.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,11 @@ public static StringToDoubleResult stringToDouble(String str, int start, int len
239239
public static double parseValidString(String substr) {
240240
double d = Double.parseDouble(substr);
241241
if (!Double.isFinite(d)) {
242-
d = new BigDecimal(substr).doubleValue();
242+
try {
243+
d = new BigDecimal(substr).doubleValue();
244+
} catch (NumberFormatException e) {
245+
// Can happen when the number is too large, just let it return +-infinity then
246+
}
243247
}
244248
return d;
245249
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/object/ObjectBuiltins.java

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@
7575
import com.oracle.graal.python.builtins.modules.BuiltinConstructorsFactory;
7676
import com.oracle.graal.python.builtins.objects.PNone;
7777
import com.oracle.graal.python.builtins.objects.PNotImplemented;
78+
import com.oracle.graal.python.builtins.objects.cext.PythonAbstractNativeObject;
79+
import com.oracle.graal.python.builtins.objects.cext.structs.CFields;
80+
import com.oracle.graal.python.builtins.objects.cext.structs.CStructAccess;
7881
import com.oracle.graal.python.builtins.objects.dict.PDict;
7982
import com.oracle.graal.python.builtins.objects.function.PKeyword;
8083
import com.oracle.graal.python.builtins.objects.getsetdescriptor.DescriptorBuiltins.DescrDeleteNode;
@@ -84,13 +87,14 @@
8487
import com.oracle.graal.python.builtins.objects.method.PBuiltinMethod;
8588
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltinsClinicProviders.FormatNodeClinicProviderGen;
8689
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltinsClinicProviders.ReduceExNodeClinicProviderGen;
87-
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltinsFactory.GetAttributeNodeFactory;
8890
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltinsFactory.DictNodeFactory;
91+
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltinsFactory.GetAttributeNodeFactory;
8992
import com.oracle.graal.python.builtins.objects.set.PSet;
9093
import com.oracle.graal.python.builtins.objects.type.PythonBuiltinClass;
9194
import com.oracle.graal.python.builtins.objects.type.SpecialMethodSlot;
9295
import com.oracle.graal.python.builtins.objects.type.TpSlots;
9396
import com.oracle.graal.python.builtins.objects.type.TpSlots.GetObjectSlotsNode;
97+
import com.oracle.graal.python.builtins.objects.type.TypeFlags;
9498
import com.oracle.graal.python.builtins.objects.type.TypeNodes;
9599
import com.oracle.graal.python.builtins.objects.type.TypeNodes.CheckCompatibleForAssigmentNode;
96100
import com.oracle.graal.python.builtins.objects.type.TypeNodes.GetBaseClassNode;
@@ -127,6 +131,7 @@
127131
import com.oracle.graal.python.nodes.function.builtins.PythonVarargsBuiltinNode;
128132
import com.oracle.graal.python.nodes.function.builtins.clinic.ArgumentClinicProvider;
129133
import com.oracle.graal.python.nodes.object.BuiltinClassProfiles.IsBuiltinClassExactProfile;
134+
import com.oracle.graal.python.nodes.object.BuiltinClassProfiles.IsBuiltinClassProfile;
130135
import com.oracle.graal.python.nodes.object.BuiltinClassProfiles.IsOtherBuiltinClassProfile;
131136
import com.oracle.graal.python.nodes.object.DeleteDictNode;
132137
import com.oracle.graal.python.nodes.object.GetClassNode;
@@ -146,7 +151,8 @@
146151
import com.oracle.truffle.api.dsl.Cached;
147152
import com.oracle.truffle.api.dsl.Cached.Exclusive;
148153
import com.oracle.truffle.api.dsl.Cached.Shared;
149-
import com.oracle.truffle.api.dsl.Fallback;
154+
import com.oracle.truffle.api.dsl.GenerateCached;
155+
import com.oracle.truffle.api.dsl.GenerateInline;
150156
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
151157
import com.oracle.truffle.api.dsl.Idempotent;
152158
import com.oracle.truffle.api.dsl.ImportStatic;
@@ -180,46 +186,49 @@ static Object getClass(Object self, @SuppressWarnings("unused") PNone value,
180186
return getClassNode.execute(inliningTarget, self);
181187
}
182188

183-
@Specialization(guards = "isNativeClass(klass)")
184-
static Object setClass(@SuppressWarnings("unused") Object self, @SuppressWarnings("unused") Object klass,
185-
@Shared @Cached PRaiseNode raiseNode) {
186-
throw raiseNode.raise(TypeError, ErrorMessages.CLASS_ASSIGNMENT_ONLY_SUPPORTED_FOR_HEAP_TYPES_OR_MODTYPE_SUBCLASSES);
187-
}
188-
189-
@Specialization(guards = "isPythonClass(value) || isPythonBuiltinClassType(value)")
190-
static PNone setClass(VirtualFrame frame, PythonObject self, Object value,
189+
@Specialization(guards = "!isNoValue(value)")
190+
static PNone setClass(VirtualFrame frame, Object self, Object value,
191191
@Bind("this") Node inliningTarget,
192-
@Cached HiddenAttr.WriteNode writeHiddenAttrNode,
193-
@Cached IsOtherBuiltinClassProfile classProfile1,
194-
@Cached IsOtherBuiltinClassProfile classProfile2,
192+
@Cached TypeNodes.IsTypeNode isTypeNode,
193+
@Cached IsBuiltinClassProfile isModuleProfile,
194+
@Cached TypeNodes.GetTypeFlagsNode getTypeFlagsNode,
195195
@Cached CheckCompatibleForAssigmentNode checkCompatibleForAssigmentNode,
196196
@Exclusive @Cached GetClassNode getClassNode,
197-
@Exclusive @Cached PRaiseNode.Lazy raiseNode) {
197+
@Cached SetClassNode setClassNode,
198+
@Cached PRaiseNode.Lazy raiseNode) {
199+
if (!isTypeNode.execute(inliningTarget, value)) {
200+
throw raiseNode.get(inliningTarget).raise(TypeError, ErrorMessages.CLASS_MUST_BE_SET_TO_CLASS, value);
201+
}
198202
Object type = getClassNode.execute(inliningTarget, self);
199-
if (isBuiltinClassNotModule(inliningTarget, value, classProfile1) || PGuards.isNativeClass(value) || isBuiltinClassNotModule(inliningTarget, type, classProfile2) ||
200-
PGuards.isNativeClass(type)) {
203+
boolean bothModuleSubtypes = isModuleProfile.profileClass(inliningTarget, type, PythonBuiltinClassType.PythonModule) &&
204+
isModuleProfile.profileClass(inliningTarget, value, PythonBuiltinClassType.PythonModule);
205+
boolean bothMutable = (getTypeFlagsNode.execute(type) & TypeFlags.IMMUTABLETYPE) == 0 && (getTypeFlagsNode.execute(value) & TypeFlags.IMMUTABLETYPE) == 0;
206+
if (!bothModuleSubtypes && !bothMutable) {
201207
throw raiseNode.get(inliningTarget).raise(TypeError, ErrorMessages.CLASS_ASSIGNMENT_ONLY_SUPPORTED_FOR_HEAP_TYPES_OR_MODTYPE_SUBCLASSES);
202208
}
203209

204210
checkCompatibleForAssigmentNode.execute(frame, type, value);
205-
writeHiddenAttrNode.execute(inliningTarget, self, HiddenAttr.CLASS, value);
211+
setClassNode.execute(inliningTarget, self, value);
212+
206213
return PNone.NONE;
207214
}
208215

209-
private static boolean isBuiltinClassNotModule(Node inliningTarget, Object type, IsOtherBuiltinClassProfile classProfile) {
210-
return classProfile.profileIsOtherBuiltinClass(inliningTarget, type, PythonBuiltinClassType.PythonModule);
211-
}
216+
@GenerateInline
217+
@GenerateCached(false)
218+
abstract static class SetClassNode extends Node {
219+
public abstract void execute(Node inliningTarget, Object self, Object newClass);
212220

213-
@Specialization(guards = {"isPythonClass(value) || isPythonBuiltinClassType(value)", "!isPythonObject(self)"})
214-
static Object getClass(@SuppressWarnings("unused") Object self, @SuppressWarnings("unused") Object value,
215-
@Shared @Cached PRaiseNode raiseNode) {
216-
throw raiseNode.raise(TypeError, ErrorMessages.CLASS_ASSIGNMENT_ONLY_SUPPORTED_FOR_HEAP_TYPES_OR_MODTYPE_SUBCLASSES);
217-
}
221+
@Specialization
222+
static void doPythonObject(Node inliningTarget, PythonObject self, Object newClass,
223+
@Cached HiddenAttr.WriteNode writeHiddenAttrNode) {
224+
writeHiddenAttrNode.execute(inliningTarget, self, HiddenAttr.CLASS, newClass);
225+
}
218226

219-
@Fallback
220-
static Object getClassError(@SuppressWarnings("unused") Object self, Object value,
221-
@Shared @Cached PRaiseNode raiseNode) {
222-
throw raiseNode.raise(TypeError, ErrorMessages.CLASS_MUST_BE_SET_TO_CLASS, value);
227+
@Specialization
228+
static void doNative(PythonAbstractNativeObject self, Object newClass,
229+
@Cached(inline = false) CStructAccess.WriteObjectNewRefNode writeObjectNewRefNode) {
230+
writeObjectNewRefNode.writeToObject(self, CFields.PyObject__ob_type, newClass);
231+
}
223232
}
224233
}
225234

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ public abstract class ErrorMessages {
351351
public static final TruffleString GLOBALS_MUST_BE_DICT = tsLiteral("%s() globals must be a dict, not %p");
352352
public static final TruffleString GOT_AN_INVALID_TYPE_IN_CONSTANT = tsLiteral("got an invalid type in Constant: %p");
353353
public static final TruffleString S_GOT_MULTIPLE_SUBPATTERNS_FOR_ATTR_S = tsLiteral("%s() got multiple sub-patterns for attribute '%s'");
354-
public static final TruffleString S_PAREN_GOT_MULTIPLE_VALUES_FOR_KEYWORD_ARG = tsLiteral("%s() got multiple values for keyword argument '%s'");
354+
public static final TruffleString S_PAREN_GOT_MULTIPLE_VALUES_FOR_ARG = tsLiteral("%s() got multiple values for argument '%s'");
355355
public static final TruffleString S_GOT_MULTIPLE_VALUES_FOR_KEYWORD_ARG = tsLiteral("%s got multiple values for keyword argument '%s'");
356356
public static final TruffleString GOT_MULTIPLE_VALUES_FOR_KEYWORD_ARG = tsLiteral("got multiple values for keyword argument '%s'");
357357
public static final TruffleString GOT_SOME_POS_ONLY_ARGS_PASSED_AS_KEYWORD = tsLiteral("%s() got some positional-only arguments passed as keyword arguments: '%s'");
@@ -566,7 +566,7 @@ public abstract class ErrorMessages {
566566
public static final TruffleString NUMBER_IS_REQUIRED = tsLiteral("a number is required");
567567
public static final TruffleString NUMBER_S_CANNOT_FIT_INTO_INDEXSIZED_INT = tsLiteral("number %s cannot fit into index-sized integer");
568568
public static final TruffleString OBJ_INDEX_MUST_BE_INT_OR_SLICES = tsLiteral("%s indices must be integers or slices, not %p");
569-
public static final TruffleString OBJ_CANNOT_BE_INTERPRETED_AS_INTEGER = tsLiteral("'%p' object cannot be interpreted as an int");
569+
public static final TruffleString OBJ_CANNOT_BE_INTERPRETED_AS_INTEGER = tsLiteral("'%p' object cannot be interpreted as an integer");
570570
public static final TruffleString OBJ_DOES_NOT_SUPPORT_INDEXING = tsLiteral("'%p' object does not support indexing");
571571
public static final TruffleString OBJ_DOES_NOT_SUPPORT_ITEM_ASSIGMENT = tsLiteral("'%s' object does not support item assignment");
572572
public static final TruffleString OBJ_DOES_NOT_SUPPORT_ITEM_DELETION = tsLiteral("'%s' object does not support item deletion");

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/argument/CreateArgumentsNode.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,7 @@ static Object[] applyCached(Object callee, @SuppressWarnings("unused") Signature
623623
}
624624
} else {
625625
if (PArguments.getArgument(arguments, kwIdx) != null) {
626-
throw raise.raise(PythonBuiltinClassType.TypeError, ErrorMessages.S_PAREN_GOT_MULTIPLE_VALUES_FOR_KEYWORD_ARG, CreateArgumentsNode.getName(callee), name);
626+
throw raise.raise(PythonBuiltinClassType.TypeError, ErrorMessages.S_PAREN_GOT_MULTIPLE_VALUES_FOR_ARG, CreateArgumentsNode.getName(callee), name);
627627
}
628628
PArguments.setArgument(arguments, kwIdx, kwArg.getValue());
629629
}
@@ -679,7 +679,7 @@ static Object[] applyUncached(Object callee, Signature calleeSignature, Object[]
679679
}
680680
} else {
681681
if (PArguments.getArgument(arguments, kwIdx) != null) {
682-
throw raise.raise(PythonBuiltinClassType.TypeError, ErrorMessages.S_PAREN_GOT_MULTIPLE_VALUES_FOR_KEYWORD_ARG, CreateArgumentsNode.getName(callee), name);
682+
throw raise.raise(PythonBuiltinClassType.TypeError, ErrorMessages.S_PAREN_GOT_MULTIPLE_VALUES_FOR_ARG, CreateArgumentsNode.getName(callee), name);
683683
}
684684
PArguments.setArgument(arguments, kwIdx, kwArg.getValue());
685685
}

graalpython/lib-graalpython/patches/metadata.toml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,11 +513,15 @@ patch = 'pythran-0.12.0.patch'
513513
license = 'BSD-3-Clause'
514514

515515
[[pythran.rules]]
516-
install-priority = 10
517516
version = '== 0.13.*'
518517
patch = 'pythran-0.13.patch'
519518
license = 'BSD-3-Clause'
520519

520+
[[pythran.rules]]
521+
version = '>= 0.14'
522+
patch = 'pythran-0.15.patch'
523+
license = 'BSD-3-Clause'
524+
521525
[[pyzmq.rules]]
522526
# 26+ needs Cython 3
523527
version = '< 26'
@@ -578,6 +582,9 @@ patch = 'scikit-learn-1.1.3.patch'
578582
license = 'BSD-3-Clause'
579583
dist-type = 'sdist'
580584

585+
[[scipy.rules]]
586+
version = '== 1.13.1'
587+
581588
[[scipy.rules]]
582589
version = '== 1.10.1'
583590
patch = 'scipy-1.10.1.patch'
Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,44 @@
11
diff --git a/pythran/pythonic/python/core.hpp b/pythran/pythonic/python/core.hpp
2-
index ff44c01..23b4413 100644
2+
index 4cbe3e0..24340b0 100644
33
--- a/pythran/pythonic/python/core.hpp
44
+++ b/pythran/pythonic/python/core.hpp
5-
@@ -53,7 +53,7 @@ namespace python
5+
@@ -53,7 +53,14 @@ namespace python
66
{
77

88
#ifndef PyString_AS_STRING
99
-#define PyString_AS_STRING (char *)_PyUnicode_COMPACT_DATA
10-
+#define PyString_AS_STRING PyBytes_AS_STRING
10+
+ static inline const char* PyString_AS_STRING(PyObject* obj) {
11+
+ const char* str = PyUnicode_AsUTF8(obj);
12+
+ if (!str) {
13+
+ PyErr_Clear();
14+
+ str = "<invalid string>";
15+
+ }
16+
+ return str;
17+
+ }
1118
#endif
1219

1320
inline void PyObject_TypePrettyPrinter(std::ostream &oss, PyObject *obj)
1421
diff --git a/pythran/pythonic/types/str.hpp b/pythran/pythonic/types/str.hpp
15-
index 1f7a981..00440a9 100644
22+
index 1f7a981..e975333 100644
1623
--- a/pythran/pythonic/types/str.hpp
1724
+++ b/pythran/pythonic/types/str.hpp
18-
@@ -744,7 +744,7 @@ namespace std
19-
#define PyString_Check(x) PyUnicode_Check(x) && PyUnicode_IS_COMPACT_ASCII(x)
25+
@@ -741,10 +741,17 @@ namespace std
26+
#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
27+
28+
#ifndef PyString_Check
29+
-#define PyString_Check(x) PyUnicode_Check(x) && PyUnicode_IS_COMPACT_ASCII(x)
30+
+#define PyString_Check(x) PyUnicode_Check(x)
2031
#endif
2132
#ifndef PyString_AS_STRING
2233
-#define PyString_AS_STRING (char *)_PyUnicode_COMPACT_DATA
23-
+#define PyString_AS_STRING PyBytes_AS_STRING
34+
+ static inline const char* PyString_AS_STRING(PyObject* obj) {
35+
+ const char* str = PyUnicode_AsUTF8(obj);
36+
+ if (!str) {
37+
+ PyErr_Clear();
38+
+ str = "<invalid string>";
39+
+ }
40+
+ return str;
41+
+ }
2442
#endif
2543
#ifndef PyString_GET_SIZE
2644
#define PyString_GET_SIZE PyUnicode_GET_LENGTH
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
diff --git a/pythran/pythonic/python/core.hpp b/pythran/pythonic/python/core.hpp
2+
index 4cbe3e0..24340b0 100644
3+
--- a/pythran/pythonic/python/core.hpp
4+
+++ b/pythran/pythonic/python/core.hpp
5+
@@ -53,7 +53,14 @@ namespace python
6+
{
7+
8+
#ifndef PyString_AS_STRING
9+
-#define PyString_AS_STRING (char *)_PyUnicode_COMPACT_DATA
10+
+ static inline const char* PyString_AS_STRING(PyObject* obj) {
11+
+ const char* str = PyUnicode_AsUTF8(obj);
12+
+ if (!str) {
13+
+ PyErr_Clear();
14+
+ str = "<invalid string>";
15+
+ }
16+
+ return str;
17+
+ }
18+
#endif
19+
20+
inline void PyObject_TypePrettyPrinter(std::ostream &oss, PyObject *obj)
21+
diff --git a/pythran/pythonic/types/str.hpp b/pythran/pythonic/types/str.hpp
22+
index 1f7a981..e975333 100644
23+
--- a/pythran/pythonic/types/str.hpp
24+
+++ b/pythran/pythonic/types/str.hpp
25+
@@ -741,10 +741,17 @@ namespace std
26+
#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
27+
28+
#ifndef PyString_Check
29+
-#define PyString_Check(x) PyUnicode_Check(x) && PyUnicode_IS_COMPACT_ASCII(x)
30+
+#define PyString_Check(x) PyUnicode_Check(x)
31+
#endif
32+
#ifndef PyString_AS_STRING
33+
-#define PyString_AS_STRING (char *)_PyUnicode_COMPACT_DATA
34+
+ static inline const char* PyString_AS_STRING(PyObject* obj) {
35+
+ const char* str = PyUnicode_AsUTF8(obj);
36+
+ if (!str) {
37+
+ PyErr_Clear();
38+
+ str = "<invalid string>";
39+
+ }
40+
+ return str;
41+
+ }
42+
#endif
43+
#ifndef PyString_GET_SIZE
44+
#define PyString_GET_SIZE PyUnicode_GET_LENGTH
45+
diff --git a/pythran/tables.py b/pythran/tables.py
46+
index d1d2027..eb631fd 100644
47+
--- a/pythran/tables.py
48+
+++ b/pythran/tables.py
49+
@@ -4595,7 +4595,8 @@ def save_arguments(module_name, elements):
50+
defaults = list(spec.defaults or [])
51+
args += [ast.Name(arg, ast.Param(), None, None)
52+
for arg in spec.kwonlyargs]
53+
- defaults += [spec.kwonlydefaults[kw] for kw in spec.kwonlyargs]
54+
+ if spec.kwonlydefaults:
55+
+ defaults += [spec.kwonlydefaults[kw] for kw in spec.kwonlyargs]
56+
57+
# Check if we already have a pythran description for that object
58+
if signature.args.args:

graalpython/lib-graalpython/patches/scipy-1.10.1.patch

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
diff --git a/pyproject.toml b/pyproject.toml
2-
index 454a3c2e..7c96eb11 100644
2+
index 454a3c2e..b23c98eb 100644
33
--- a/pyproject.toml
44
+++ b/pyproject.toml
5-
@@ -15,48 +15,11 @@ requires = [
5+
@@ -11,52 +11,16 @@
6+
build-backend = 'mesonpy'
7+
requires = [
8+
"meson-python>=0.11.0,<0.13.0",
9+
+ "pyproject-metadata<0.9",
10+
"Cython>=0.29.32,<3.0",
611
# conservatively avoid issues from
712
# https://github.com/pybind/pybind11/issues/4420
813
"pybind11==2.10.1",

0 commit comments

Comments
 (0)