From fe4cf0b08cf4b44ea2e07affa78a4b09ce34d347 Mon Sep 17 00:00:00 2001
From: Danilo Ansaloni
Date: Thu, 23 Jan 2025 19:38:03 +0100
Subject: [PATCH 01/51] Restart the 24.2 dev cycle.
Begin of the feature freeze for the 24.2 release.
Revert "Start 25.0.0 dev cycle."
This reverts commit f4105848044ea7cb58318895c7da184c3af64217.
---
graalpython/com.oracle.graal.python.test.integration/pom.xml | 2 +-
.../src/tests/standalone/gradle/build/build.gradle | 2 +-
.../src/tests/standalone/gradle/build/build.gradle.kts | 2 +-
.../src/tests/standalone/jbang/EmptyPIPComments.j | 2 +-
.../src/tests/standalone/jbang/EmptyPythonResourceComment.j | 2 +-
.../standalone/jbang/EmptyPythonResourceCommentWithBlanks.j | 2 +-
.../src/tests/standalone/jbang/NoPackagesResourcesDir.j | 2 +-
.../src/tests/standalone/jbang/TwoPythonResourceComments.j | 2 +-
graalpython/graalpy-archetype-polyglot-app/pom.xml | 2 +-
.../src/main/resources/archetype-resources/pom.xml | 2 +-
graalpython/graalpy-jbang/examples/hello.java | 2 +-
.../graalpy-jbang/templates/graalpy-template.java.qute | 2 +-
.../templates/graalpy-template_local_repo.java.qute | 2 +-
graalpython/graalpy-maven-plugin/pom.xml | 4 ++--
mx.graalpython/suite.py | 2 +-
15 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/graalpython/com.oracle.graal.python.test.integration/pom.xml b/graalpython/com.oracle.graal.python.test.integration/pom.xml
index bad3f27502..0f55209ba9 100644
--- a/graalpython/com.oracle.graal.python.test.integration/pom.xml
+++ b/graalpython/com.oracle.graal.python.test.integration/pom.xml
@@ -64,7 +64,7 @@ Additionally, one can change the polyglot artifacts version with
17
17
UTF-8
- 25.0.0
+ 24.2.0
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/standalone/gradle/build/build.gradle b/graalpython/com.oracle.graal.python.test/src/tests/standalone/gradle/build/build.gradle
index c9b31ffe75..15c3c89c12 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/standalone/gradle/build/build.gradle
+++ b/graalpython/com.oracle.graal.python.test/src/tests/standalone/gradle/build/build.gradle
@@ -1,6 +1,6 @@
plugins {
id "application"
- id 'org.graalvm.python' version '25.0.0'
+ id 'org.graalvm.python' version '24.2.0'
id "org.graalvm.buildtools.native" version "0.10.2"
}
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/standalone/gradle/build/build.gradle.kts b/graalpython/com.oracle.graal.python.test/src/tests/standalone/gradle/build/build.gradle.kts
index ee72dfe3de..a086b6635e 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/standalone/gradle/build/build.gradle.kts
+++ b/graalpython/com.oracle.graal.python.test/src/tests/standalone/gradle/build/build.gradle.kts
@@ -1,6 +1,6 @@
plugins {
application
- id("org.graalvm.python") version "25.0.0"
+ id("org.graalvm.python") version "24.2.0"
id("org.graalvm.buildtools.native") version "0.10.2"
}
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPIPComments.j b/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPIPComments.j
index 098695dccb..6b140a59b8 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPIPComments.j
+++ b/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPIPComments.j
@@ -1,6 +1,6 @@
///usr/bin/env jbang "$0" "$@" ; exit $?
-//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:25.0.0}
+//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.0}
//PIP
// one blank after PIP
//PIP
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPythonResourceComment.j b/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPythonResourceComment.j
index 89f5758c5e..768e188e9e 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPythonResourceComment.j
+++ b/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPythonResourceComment.j
@@ -1,6 +1,6 @@
///usr/bin/env jbang "$0" "$@" ; exit $?
-//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:25.0.0}
+//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.0}
//PYTHON_RESOURCES_DIRECTORY
public class EmptyPythonResourceComment {
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPythonResourceCommentWithBlanks.j b/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPythonResourceCommentWithBlanks.j
index fcb93bdc33..f4b7556997 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPythonResourceCommentWithBlanks.j
+++ b/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPythonResourceCommentWithBlanks.j
@@ -1,6 +1,6 @@
///usr/bin/env jbang "$0" "$@" ; exit $?
-//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:25.0.0}
+//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.0}
// resource dir with blanks
//PYTHON_RESOURCES_DIRECTORY
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/NoPackagesResourcesDir.j b/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/NoPackagesResourcesDir.j
index c2255aca6c..749ae89606 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/NoPackagesResourcesDir.j
+++ b/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/NoPackagesResourcesDir.j
@@ -1,6 +1,6 @@
///usr/bin/env jbang "$0" "$@" ; exit $?
-//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:25.0.0}
+//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.0}
//PYTHON_RESOURCES_DIRECTORY python-resources
public class NoPackagesResourcesDir {
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/TwoPythonResourceComments.j b/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/TwoPythonResourceComments.j
index 3bd4381f51..c2d902d358 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/TwoPythonResourceComments.j
+++ b/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/TwoPythonResourceComments.j
@@ -1,6 +1,6 @@
///usr/bin/env jbang "$0" "$@" ; exit $?
-//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:25.0.0}
+//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.0}
//PYTHON_RESOURCES_DIRECTORY
//PYTHON_RESOURCES_DIRECTORY
diff --git a/graalpython/graalpy-archetype-polyglot-app/pom.xml b/graalpython/graalpy-archetype-polyglot-app/pom.xml
index d08b5631bb..04b27f55e3 100644
--- a/graalpython/graalpy-archetype-polyglot-app/pom.xml
+++ b/graalpython/graalpy-archetype-polyglot-app/pom.xml
@@ -45,7 +45,7 @@ SOFTWARE.
org.graalvm.python
graalpy-archetype-polyglot-app
- 25.0.0
+ 24.2.0
http://www.graalvm.org/python
Maven archetype providing a skeleton GraalPy - Java polyglot application.
maven-archetype
diff --git a/graalpython/graalpy-archetype-polyglot-app/src/main/resources/archetype-resources/pom.xml b/graalpython/graalpy-archetype-polyglot-app/src/main/resources/archetype-resources/pom.xml
index eb03184b9f..90be4e32ca 100644
--- a/graalpython/graalpy-archetype-polyglot-app/src/main/resources/archetype-resources/pom.xml
+++ b/graalpython/graalpy-archetype-polyglot-app/src/main/resources/archetype-resources/pom.xml
@@ -10,7 +10,7 @@
#set( $symbol_dollar = '$' )
- 25.0.0
+ 24.2.0
python-community
0.10.4
17
diff --git a/graalpython/graalpy-jbang/examples/hello.java b/graalpython/graalpy-jbang/examples/hello.java
index 2afc0c82b3..b005158ef6 100644
--- a/graalpython/graalpy-jbang/examples/hello.java
+++ b/graalpython/graalpy-jbang/examples/hello.java
@@ -40,7 +40,7 @@
*/
///usr/bin/env jbang "$0" "$@" ; exit $?
//JAVA 17+
-//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:25.0.0}
+//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.0}
// specify python packages and their versions as if used with pip
//PIP termcolor==2.2
diff --git a/graalpython/graalpy-jbang/templates/graalpy-template.java.qute b/graalpython/graalpy-jbang/templates/graalpy-template.java.qute
index 5258d8cb30..5a61e3dea9 100644
--- a/graalpython/graalpy-jbang/templates/graalpy-template.java.qute
+++ b/graalpython/graalpy-jbang/templates/graalpy-template.java.qute
@@ -5,7 +5,7 @@
{/for}
{#if dependencies.isEmpty()}// //DEPS {/if}
{|
-//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:25.0.0}
+//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.0}
// specify python packages and their versions as if used with pip
//PIP termcolor==2.2
|}
diff --git a/graalpython/graalpy-jbang/templates/graalpy-template_local_repo.java.qute b/graalpython/graalpy-jbang/templates/graalpy-template_local_repo.java.qute
index 9db2304494..2fb3914dc1 100644
--- a/graalpython/graalpy-jbang/templates/graalpy-template_local_repo.java.qute
+++ b/graalpython/graalpy-jbang/templates/graalpy-template_local_repo.java.qute
@@ -8,7 +8,7 @@
//REPOS mc=https://repo1.maven.org/maven2/
//REPOS local=file://{path_to_local_repo}
{|
-//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:25.0.0}
+//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.0}
// specify python packages and their versions as if used with pip
//PIP termcolor==2.2
|}
diff --git a/graalpython/graalpy-maven-plugin/pom.xml b/graalpython/graalpy-maven-plugin/pom.xml
index 7a8715415f..4838e2cec7 100644
--- a/graalpython/graalpy-maven-plugin/pom.xml
+++ b/graalpython/graalpy-maven-plugin/pom.xml
@@ -48,7 +48,7 @@ SOFTWARE.
graalpy-maven-plugin
maven-plugin
- 25.0.0
+ 24.2.0
http://www.graalvm.org/python
graalpy-maven-plugin
Handles python related resources in a maven GraalPy - Java polyglot application.
@@ -57,7 +57,7 @@ SOFTWARE.
17
17
UTF-8
- 25.0.0
+ 24.2.0
diff --git a/mx.graalpython/suite.py b/mx.graalpython/suite.py
index 92ae8a88d7..efb3e6a4ee 100644
--- a/mx.graalpython/suite.py
+++ b/mx.graalpython/suite.py
@@ -9,7 +9,7 @@
"name": "graalpython",
"versionConflictResolution": "latest",
- "version": "25.0.0",
+ "version": "24.2.0",
"graalpython:pythonVersion": "3.11.7",
"release": False,
"groupId": "org.graalvm.python",
From b94c39b17b87b69dfa53683f5f2cb334a4857dae Mon Sep 17 00:00:00 2001
From: Danilo Ansaloni
Date: Thu, 23 Jan 2025 19:40:45 +0100
Subject: [PATCH 02/51] Update imports
---
ci.jsonnet | 2 +-
mx.graalpython/suite.py | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/ci.jsonnet b/ci.jsonnet
index 48bf915fd3..f4fbcec95d 100644
--- a/ci.jsonnet
+++ b/ci.jsonnet
@@ -1 +1 @@
-{ "overlay": "840dea7f9575e2e96e2143685751932513fd0c78" }
+{ "overlay": "da4fbb453006eea9997babadc69b70c2e0cee0ab" }
diff --git a/mx.graalpython/suite.py b/mx.graalpython/suite.py
index efb3e6a4ee..763a0fd5f6 100644
--- a/mx.graalpython/suite.py
+++ b/mx.graalpython/suite.py
@@ -45,7 +45,7 @@
},
{
"name": "sdk",
- "version": "0f61c409358b6ecdb637d69410c8d3960b289e9c",
+ "version": "826d284d76d4e3c2379e952824f4ab7e96c805ee",
"subdir": True,
"urls": [
{"url": "https://github.com/oracle/graal", "kind": "git"},
@@ -53,7 +53,7 @@
},
{
"name": "tools",
- "version": "0f61c409358b6ecdb637d69410c8d3960b289e9c",
+ "version": "826d284d76d4e3c2379e952824f4ab7e96c805ee",
"subdir": True,
"urls": [
{"url": "https://github.com/oracle/graal", "kind": "git"},
@@ -61,7 +61,7 @@
},
{
"name": "sulong",
- "version": "0f61c409358b6ecdb637d69410c8d3960b289e9c",
+ "version": "826d284d76d4e3c2379e952824f4ab7e96c805ee",
"subdir": True,
"urls": [
{"url": "https://github.com/oracle/graal", "kind": "git"},
@@ -69,7 +69,7 @@
},
{
"name": "regex",
- "version": "0f61c409358b6ecdb637d69410c8d3960b289e9c",
+ "version": "826d284d76d4e3c2379e952824f4ab7e96c805ee",
"subdir": True,
"urls": [
{"url": "https://github.com/oracle/graal", "kind": "git"},
From 9095026c26d47b96e20762b12a94340a482ed727 Mon Sep 17 00:00:00 2001
From: stepan
Date: Wed, 29 Jan 2025 21:40:54 +0100
Subject: [PATCH 03/51] Move the longest running Gradle Kotlin tests to the
'long running' batch
(cherry picked from commit 1fa8957d0236aed27dd4b7d9a381cef87af09bfc)
---
.../src/tests/standalone/test_gradle_plugin.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/standalone/test_gradle_plugin.py b/graalpython/com.oracle.graal.python.test/src/tests/standalone/test_gradle_plugin.py
index 2b15001db5..52d95fc704 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/standalone/test_gradle_plugin.py
+++ b/graalpython/com.oracle.graal.python.test/src/tests/standalone/test_gradle_plugin.py
@@ -677,11 +677,11 @@ def setUpClass(cls):
cls.build_file_name = "build.gradle.kts"
cls.settings_file_name = "settings.gradle.kts"
- @unittest.skipUnless(util.is_gradle_plugin_test_enabled, "ENABLE_GRADLE_PLUGIN_UNITTESTS is not true")
+ @unittest.skipUnless(util.is_gradle_plugin_long_running_test_enabled, "ENABLE_GRADLE_PLUGIN_LONG_RUNNING_UNITTESTS is not true")
def test_gradle_generated_app(self):
self.check_gradle_generated_app(community=True)
- @unittest.skipUnless(util.is_gradle_plugin_test_enabled, "ENABLE_GRADLE_PLUGIN_UNITTESTS is not true")
+ @unittest.skipUnless(util.is_gradle_plugin_long_running_test_enabled, "ENABLE_GRADLE_PLUGIN_LONG_RUNNING_UNITTESTS is not true")
def test_gradle_generated_app_external_resources(self):
self.check_gradle_generated_app_external_resources()
@@ -701,7 +701,7 @@ def test_gradle_check_home(self):
def test_gradle_empty_packages(self):
self.check_gradle_empty_packages()
- @unittest.skipUnless(util.is_gradle_plugin_test_enabled, "ENABLE_GRADLE_PLUGIN_UNITTESTS is not true")
+ @unittest.skipUnless(util.is_gradle_plugin_long_running_test_enabled, "ENABLE_GRADLE_PLUGIN_LONG_RUNNING_UNITTESTS is not true")
def test_gradle_namespaced_vfs(self):
self.check_gradle_namespaced_vfs()
From 99bc51c61f38c4a5ecbc0b19a59909178c530382 Mon Sep 17 00:00:00 2001
From: stepan
Date: Wed, 29 Jan 2025 21:57:12 +0100
Subject: [PATCH 04/51] Update CI overlay
(cherry picked from commit f25f7853affa54cf53e93e45699dd94b761de48f)
---
ci.jsonnet | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ci.jsonnet b/ci.jsonnet
index f4fbcec95d..a3a4e1743e 100644
--- a/ci.jsonnet
+++ b/ci.jsonnet
@@ -1 +1 @@
-{ "overlay": "da4fbb453006eea9997babadc69b70c2e0cee0ab" }
+{ "overlay": "585265d3c6bafc1d12054374377589b360307957" }
From 77a8b4168109e94e605ff3d5482673f511a465e4 Mon Sep 17 00:00:00 2001
From: stepan
Date: Wed, 29 Jan 2025 14:34:09 +0100
Subject: [PATCH 05/51] Change the log level of 'Unexpected executable for slot
pointer' messages to fine
(cherry picked from commit b95a25d3910688780a94c5f89639a5fbbcd1df64)
---
.../com/oracle/graal/python/builtins/objects/type/TpSlots.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TpSlots.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TpSlots.java
index 497d8f0470..0685be32b0 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TpSlots.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/type/TpSlots.java
@@ -842,7 +842,7 @@ public static TpSlots fromNative(PythonAbstractNativeObject pythonClass, PythonC
existingSlotWrapper = execWrapper;
} else if (executable != null) {
// This can happen for legacy slots where the delegate would be a PFunction
- LOGGER.warning(() -> String.format("Unexpected executable for slot pointer: %s", executable));
+ LOGGER.fine(() -> String.format("Unexpected executable for slot pointer: %s", executable));
}
} catch (UnsupportedMessageException e) {
throw new IllegalStateException(e);
From 195d4bb37d421be7ce29522ebb33b07dae8427fa Mon Sep 17 00:00:00 2001
From: Benoit Daloze
Date: Fri, 17 Jan 2025 14:59:17 +0100
Subject: [PATCH 06/51] Properly order traits in GetForeignObjectClassNode
(cherry picked from commit 8922dc627a1da6cc1bc7f4cbe684889112db5eff)
---
.../src/tests/test_interop.py | 6 ++---
.../object/GetForeignObjectClassNode.java | 25 +++++++++++--------
2 files changed, 18 insertions(+), 13 deletions(-)
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_interop.py b/graalpython/com.oracle.graal.python.test/src/tests/test_interop.py
index 8533ed3835..d3b511aea6 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/test_interop.py
+++ b/graalpython/com.oracle.graal.python.test/src/tests/test_interop.py
@@ -150,7 +150,7 @@ def t(obj):
# ForeignInstantiable
self.assertEqual(t((e for e in [1])), polyglot.ForeignIteratorIterable)
self.assertEqual(t(iter([1])), polyglot.ForeignIteratorIterable)
- self.assertEqual(t(object), polyglot.ForeignExecutableClass)
+ self.assertEqual(t(object), polyglot.ForeignClassExecutable)
self.assertEqual(t(None), polyglot.ForeignNone)
self.assertEqual(t(1), polyglot.ForeignNumber)
self.assertEqual(t("abc"), polyglot.ForeignString)
@@ -472,9 +472,9 @@ def test_java_import_from_jar(self):
def test_java_class(self):
from java.lang import Integer, Number, NumberFormatException
- self.assertEqual(type(Integer).mro(), [polyglot.ForeignClass, polyglot.ForeignInstantiable, polyglot.ForeignAbstractClass, polyglot.ForeignObject, object])
+ self.assertEqual(type(Integer).mro(), [polyglot.ForeignClass, polyglot.ForeignAbstractClass, polyglot.ForeignInstantiable, polyglot.ForeignObject, object])
self.assertEqual(type(Number).mro(), [polyglot.ForeignAbstractClass, polyglot.ForeignObject, object])
- self.assertEqual(type(NumberFormatException).mro(), [polyglot.ForeignClass, polyglot.ForeignInstantiable, polyglot.ForeignAbstractClass, polyglot.ForeignObject, object])
+ self.assertEqual(type(NumberFormatException).mro(), [polyglot.ForeignClass, polyglot.ForeignAbstractClass, polyglot.ForeignInstantiable, polyglot.ForeignObject, object])
def test_java_exceptions(self):
# TODO: more tests
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetForeignObjectClassNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetForeignObjectClassNode.java
index b40c4afbcf..9bf4d52ea1 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetForeignObjectClassNode.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetForeignObjectClassNode.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
@@ -87,21 +87,26 @@ public enum Trait {
// The type field is only set for cases which are already implemented.
// First in MRO
+ // Interop types first as they are the most concrete/specific types
+ NULL("None", PythonBuiltinClassType.PNone),
BOOLEAN("Boolean", PythonBuiltinClassType.ForeignBoolean),
NUMBER("Number", PythonBuiltinClassType.ForeignNumber), // int, float, complex
STRING("String", PythonBuiltinClassType.PString),
+ EXCEPTION("Exception", PythonBuiltinClassType.PBaseException),
+ META_OBJECT("AbstractClass"), // PythonBuiltinClassType.PythonClass ?
+
+ // Interop traits
+ EXECUTABLE("Executable"),
+ INSTANTIABLE("Instantiable"),
+
+ // Container traits/types must be last, see comment above
// Hash before Array so that foreign dict+list prefers dict.[]
HASH("Dict", PythonBuiltinClassType.PDict),
// Array before Iterable so that foreign list+iterable prefers list.__iter__
ARRAY("List", PythonBuiltinClassType.PList),
- EXCEPTION("Exception", PythonBuiltinClassType.PBaseException),
- EXECUTABLE("Executable"),
- INSTANTIABLE("Instantiable"),
// Iterator before Iterable so that foreign iterator+iterable prefers iterator.__iter__
ITERATOR("Iterator", PythonBuiltinClassType.PIterator),
- ITERABLE("Iterable"),
- META_OBJECT("AbstractClass"), // PythonBuiltinClassType.PythonClass ?
- NULL("None", PythonBuiltinClassType.PNone);
+ ITERABLE("Iterable");
// Last in MRO
public static final Trait[] VALUES = Trait.values();
@@ -217,14 +222,14 @@ private PythonManagedClass resolvePolyglotForeignClass(int traits) {
traitsList.add(classForTraits(trait.bit));
}
- if (trait == Trait.INSTANTIABLE && Trait.META_OBJECT.isSet(traits)) {
- // Deal with it when we are at trait META_OBJECT
- } else if (trait == Trait.META_OBJECT) {
+ if (trait == Trait.META_OBJECT) {
if (Trait.INSTANTIABLE.isSet(traits)) {
nameBuilder.append("Class");
} else {
nameBuilder.append("AbstractClass");
}
+ } else if (trait == Trait.INSTANTIABLE && Trait.META_OBJECT.isSet(traits)) {
+ // Dealt with above
} else {
nameBuilder.append(trait.name);
}
From 17c4bf0a37d29af3e72c99336c15de4cfc3f9cbf Mon Sep 17 00:00:00 2001
From: Benoit Daloze
Date: Fri, 17 Jan 2025 16:54:29 +0100
Subject: [PATCH 07/51] Move __bases__ and __instancecheck__ from
ForeignObjectBuiltins to ForeignAbstractClassBuiltins
(cherry picked from commit f69bb094614ffc48fcc0a32fda8b7d69b354b8fb)
---
.../graal/python/builtins/Python3Core.java | 2 +
.../builtins/PythonBuiltinClassType.java | 2 +
.../foreign/ForeignAbstractClassBuiltins.java | 94 +++++++++++++++++++
.../foreign/ForeignObjectBuiltins.java | 51 +---------
.../object/GetForeignObjectClassNode.java | 2 +-
mx.graalpython/copyrights/overrides | 1 +
6 files changed, 101 insertions(+), 51 deletions(-)
create mode 100644 graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignAbstractClassBuiltins.java
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java
index 633acb7e4c..8351695719 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java
@@ -259,6 +259,7 @@
import com.oracle.graal.python.builtins.objects.exception.UnicodeTranslateErrorBuiltins;
import com.oracle.graal.python.builtins.objects.floats.FloatBuiltins;
import com.oracle.graal.python.builtins.objects.floats.PFloat;
+import com.oracle.graal.python.builtins.objects.foreign.ForeignAbstractClassBuiltins;
import com.oracle.graal.python.builtins.objects.foreign.ForeignBooleanBuiltins;
import com.oracle.graal.python.builtins.objects.foreign.ForeignNumberBuiltins;
import com.oracle.graal.python.builtins.objects.foreign.ForeignObjectBuiltins;
@@ -487,6 +488,7 @@ private static PythonBuiltins[] initializeBuiltins(boolean nativeAccessAllowed,
new ForeignObjectBuiltins(),
new ForeignNumberBuiltins(),
new ForeignBooleanBuiltins(),
+ new ForeignAbstractClassBuiltins(),
new ListBuiltins(),
new DictBuiltins(),
new DictReprBuiltin(),
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java
index cc3d1de44a..b4d755082a 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java
@@ -304,6 +304,7 @@ public enum PythonBuiltinClassType implements TruffleObject {
ForeignObject("ForeignObject", J_POLYGLOT, Flags.PUBLIC_BASE_WDICT, ForeignObjectBuiltins.SLOTS),
ForeignNumber("ForeignNumber", J_POLYGLOT, Flags.PUBLIC_BASE_WDICT, FOREIGNNUMBER_M_FLAGS, ForeignNumberBuiltins.SLOTS),
ForeignBoolean("ForeignBoolean", J_POLYGLOT, Flags.PUBLIC_BASE_WDICT, FOREIGNNUMBER_M_FLAGS, ForeignBooleanBuiltins.SLOTS),
+ ForeignAbstractClass("ForeignAbstractClass", J_POLYGLOT, Flags.PUBLIC_BASE_WDICT),
// bz2
BZ2Compressor("BZ2Compressor", "_bz2"),
@@ -839,6 +840,7 @@ public final Shape getInstanceShape(PythonLanguage lang) {
ForeignNumber.base = ForeignObject;
ForeignBoolean.base = ForeignNumber;
+ ForeignAbstractClass.base = ForeignObject;
PBaseExceptionGroup.base = PBaseException;
SystemExit.base = PBaseException;
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignAbstractClassBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignAbstractClassBuiltins.java
new file mode 100644
index 0000000000..adde80b51e
--- /dev/null
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignAbstractClassBuiltins.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates.
+ * Copyright (c) 2014, Regents of the University of California
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.oracle.graal.python.builtins.objects.foreign;
+
+import com.oracle.graal.python.builtins.Builtin;
+import com.oracle.graal.python.builtins.CoreFunctions;
+import com.oracle.graal.python.builtins.PythonBuiltinClassType;
+import com.oracle.graal.python.builtins.PythonBuiltins;
+import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
+import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
+import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
+import com.oracle.graal.python.runtime.GilNode;
+import com.oracle.graal.python.runtime.object.PythonObjectFactory;
+import com.oracle.graal.python.util.PythonUtils;
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.GenerateNodeFactory;
+import com.oracle.truffle.api.dsl.NodeFactory;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.InteropLibrary;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
+import com.oracle.truffle.api.library.CachedLibrary;
+
+import java.util.List;
+
+import static com.oracle.graal.python.nodes.SpecialAttributeNames.J___BASES__;
+import static com.oracle.graal.python.nodes.SpecialMethodNames.J___INSTANCECHECK__;
+
+/*
+ * NOTE: We are not using IndirectCallContext here in this file (except for CallNode)
+ * because it seems unlikely that these interop messages would call back to Python
+ * and that we would also need precise frame info for that case.
+ * Adding it shouldn't hurt peak, but might be a non-trivial overhead in interpreter.
+ */
+@CoreFunctions(extendClasses = PythonBuiltinClassType.ForeignAbstractClass)
+public final class ForeignAbstractClassBuiltins extends PythonBuiltins {
+ @Override
+ protected List extends NodeFactory extends PythonBuiltinBaseNode>> getNodeFactories() {
+ return ForeignAbstractClassBuiltinsFactory.getFactories();
+ }
+
+ @Builtin(name = J___BASES__, minNumOfPositionalArgs = 1, isGetter = true, isSetter = false)
+ @GenerateNodeFactory
+ abstract static class BasesNode extends PythonUnaryBuiltinNode {
+ @Specialization
+ static Object getBases(Object self,
+ @Cached PythonObjectFactory factory) {
+ return factory.createTuple(PythonUtils.EMPTY_OBJECT_ARRAY);
+ }
+ }
+
+ @Builtin(name = J___INSTANCECHECK__, minNumOfPositionalArgs = 2)
+ @GenerateNodeFactory
+ abstract static class InstancecheckNode extends PythonBinaryBuiltinNode {
+ @Specialization(limit = "3")
+ static Object check(Object self, Object instance,
+ @CachedLibrary("self") InteropLibrary lib,
+ @Cached GilNode gil) {
+ gil.release(true);
+ try {
+ return lib.isMetaInstance(self, instance);
+ } catch (UnsupportedMessageException e) {
+ throw CompilerDirectives.shouldNotReachHere();
+ } finally {
+ gil.acquire();
+ }
+ }
+ }
+
+}
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignObjectBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignObjectBuiltins.java
index 617458040f..19ad62ff6f 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignObjectBuiltins.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignObjectBuiltins.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2024, Oracle and/or its affiliates.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates.
* Copyright (c) 2014, Regents of the University of California
*
* All rights reserved.
@@ -29,17 +29,13 @@
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.AttributeError;
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.TypeError;
import static com.oracle.graal.python.builtins.objects.str.StringUtils.simpleTruffleStringFormatUncached;
-import static com.oracle.graal.python.nodes.SpecialAttributeNames.J___BASES__;
-import static com.oracle.graal.python.nodes.SpecialAttributeNames.T___BASES__;
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___CALL__;
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___DIR__;
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___HASH__;
-import static com.oracle.graal.python.nodes.SpecialMethodNames.J___INSTANCECHECK__;
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___ITER__;
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___NEW__;
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___REPR__;
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___STR__;
-import static com.oracle.graal.python.nodes.SpecialMethodNames.T___INSTANCECHECK__;
import static com.oracle.graal.python.util.PythonUtils.TS_ENCODING;
import java.util.List;
@@ -66,7 +62,6 @@
import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode;
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
-import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
import com.oracle.graal.python.nodes.interop.PForeignToPTypeNode;
import com.oracle.graal.python.nodes.object.BuiltinClassProfiles.IsBuiltinObjectProfile;
@@ -82,7 +77,6 @@
import com.oracle.graal.python.runtime.exception.PException;
import com.oracle.graal.python.runtime.exception.PythonErrorType;
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
-import com.oracle.graal.python.util.PythonUtils;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Bind;
@@ -497,47 +491,4 @@ protected TruffleString defaultConversion(VirtualFrame frame, InteropLibrary lib
}
}
- @Builtin(name = J___BASES__, minNumOfPositionalArgs = 1, isGetter = true, isSetter = false)
- @GenerateNodeFactory
- @ImportStatic(PGuards.class)
- abstract static class BasesNode extends PythonUnaryBuiltinNode {
- @Specialization(limit = "3")
- static Object getBases(Object self,
- @Bind("this") Node inliningTarget,
- @CachedLibrary("self") InteropLibrary lib,
- @Cached PythonObjectFactory factory,
- @Cached PRaiseNode.Lazy raiseNode) {
- if (lib.isMetaObject(self)) {
- return factory.createTuple(PythonUtils.EMPTY_OBJECT_ARRAY);
- } else {
- throw raiseNode.get(inliningTarget).raise(AttributeError, ErrorMessages.FOREIGN_OBJ_HAS_NO_ATTR_S, T___BASES__);
- }
- }
- }
-
- @Builtin(name = J___INSTANCECHECK__, minNumOfPositionalArgs = 2)
- @GenerateNodeFactory
- @ImportStatic(PGuards.class)
- abstract static class InstancecheckNode extends PythonBinaryBuiltinNode {
- @Specialization(limit = "3")
- static Object check(Object self, Object instance,
- @Bind("this") Node inliningTarget,
- @CachedLibrary("self") InteropLibrary lib,
- @Cached GilNode gil,
- @Cached PRaiseNode.Lazy raiseNode) {
- if (lib.isMetaObject(self)) {
- gil.release(true);
- try {
- return lib.isMetaInstance(self, instance);
- } catch (UnsupportedMessageException e) {
- throw CompilerDirectives.shouldNotReachHere();
- } finally {
- gil.acquire();
- }
- } else {
- throw raiseNode.get(inliningTarget).raise(AttributeError, ErrorMessages.FOREIGN_OBJ_HAS_NO_ATTR_S, T___INSTANCECHECK__);
- }
- }
- }
-
}
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetForeignObjectClassNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetForeignObjectClassNode.java
index 9bf4d52ea1..e7cb56977d 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetForeignObjectClassNode.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetForeignObjectClassNode.java
@@ -93,7 +93,7 @@ public enum Trait {
NUMBER("Number", PythonBuiltinClassType.ForeignNumber), // int, float, complex
STRING("String", PythonBuiltinClassType.PString),
EXCEPTION("Exception", PythonBuiltinClassType.PBaseException),
- META_OBJECT("AbstractClass"), // PythonBuiltinClassType.PythonClass ?
+ META_OBJECT("AbstractClass", PythonBuiltinClassType.ForeignAbstractClass),
// Interop traits
EXECUTABLE("Executable"),
diff --git a/mx.graalpython/copyrights/overrides b/mx.graalpython/copyrights/overrides
index 9b09b5c78f..0a1351458c 100644
--- a/mx.graalpython/copyrights/overrides
+++ b/mx.graalpython/copyrights/overrides
@@ -617,6 +617,7 @@ graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects
graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/FloatBuiltins.java,zippy.copyright
graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/PFloat.java,zippy.copyright
graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignObjectBuiltins.java,zippy.copyright
+graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignAbstractClassBuiltins.java,zippy.copyright
graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignBooleanBuiltins.java,zippy.copyright
graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignNumberBuiltins.java,zippy.copyright
graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameBuiltins.java,zippy.copyright
From c5ab7ea52787e1c05318bc4aba10686868973439 Mon Sep 17 00:00:00 2001
From: Benoit Daloze
Date: Mon, 27 Jan 2025 16:17:22 +0100
Subject: [PATCH 08/51] Make it easier to set the base in
PythonBuiltinClassType
(cherry picked from commit bcd576ff22da723adb7c90a6188dce6b4a943198)
---
.../builtins/PythonBuiltinClassType.java | 20 ++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java
index b4d755082a..b7a4e04a27 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java
@@ -302,9 +302,9 @@ public enum PythonBuiltinClassType implements TruffleObject {
// Foreign
ForeignObject("ForeignObject", J_POLYGLOT, Flags.PUBLIC_BASE_WDICT, ForeignObjectBuiltins.SLOTS),
- ForeignNumber("ForeignNumber", J_POLYGLOT, Flags.PUBLIC_BASE_WDICT, FOREIGNNUMBER_M_FLAGS, ForeignNumberBuiltins.SLOTS),
- ForeignBoolean("ForeignBoolean", J_POLYGLOT, Flags.PUBLIC_BASE_WDICT, FOREIGNNUMBER_M_FLAGS, ForeignBooleanBuiltins.SLOTS),
- ForeignAbstractClass("ForeignAbstractClass", J_POLYGLOT, Flags.PUBLIC_BASE_WDICT),
+ ForeignNumber("ForeignNumber", J_POLYGLOT, ForeignObject, Flags.PUBLIC_BASE_WDICT, FOREIGNNUMBER_M_FLAGS, ForeignNumberBuiltins.SLOTS),
+ ForeignBoolean("ForeignBoolean", J_POLYGLOT, ForeignNumber, Flags.PUBLIC_BASE_WDICT, FOREIGNNUMBER_M_FLAGS, ForeignBooleanBuiltins.SLOTS),
+ ForeignAbstractClass("ForeignAbstractClass", J_POLYGLOT, ForeignObject, Flags.PUBLIC_BASE_WDICT),
// bz2
BZ2Compressor("BZ2Compressor", "_bz2"),
@@ -628,6 +628,11 @@ private static class Flags {
this(name, module, module, flags);
}
+ PythonBuiltinClassType(String name, String module, PythonBuiltinClassType base, Flags flags) {
+ this(name, module, module, flags);
+ this.base = base;
+ }
+
PythonBuiltinClassType(String name, String module, Flags flags, TpSlots slots) {
this(name, module, module, flags, DEFAULT_M_FLAGS, slots);
}
@@ -640,6 +645,11 @@ private static class Flags {
this(name, module, module, flags, methodsFlags, slots);
}
+ PythonBuiltinClassType(String name, String module, PythonBuiltinClassType base, Flags flags, long methodsFlags, TpSlots slots) {
+ this(name, module, module, flags, methodsFlags, slots);
+ this.base = base;
+ }
+
PythonBuiltinClassType(String name, String publishInModule, String moduleName, Flags flags) {
this(name, publishInModule, moduleName, flags, DEFAULT_M_FLAGS, TpSlots.createEmpty());
}
@@ -838,10 +848,6 @@ public final Shape getInstanceShape(PythonLanguage lang) {
Boolean.base = PInt;
- ForeignNumber.base = ForeignObject;
- ForeignBoolean.base = ForeignNumber;
- ForeignAbstractClass.base = ForeignObject;
-
PBaseExceptionGroup.base = PBaseException;
SystemExit.base = PBaseException;
KeyboardInterrupt.base = PBaseException;
From 05ec2d779f8a7fe6abec0d73bbb268202624774c Mon Sep 17 00:00:00 2001
From: Benoit Daloze
Date: Mon, 27 Jan 2025 16:49:54 +0100
Subject: [PATCH 09/51] Move the remaining trait-specific methods from
ForeignObject to the dedicated trait classes
(cherry picked from commit 60b82ae3527d9737d7fd41ca0c0eda02f2ba7b62)
---
.../src/tests/test_interop.py | 4 +-
.../graal/python/builtins/Python3Core.java | 6 +
.../builtins/PythonBuiltinClassType.java | 3 +
.../foreign/ForeignAbstractClassBuiltins.java | 2 +-
.../foreign/ForeignExecutableBuiltins.java | 110 ++++++++++++++
.../foreign/ForeignInstantiableBuiltins.java | 143 ++++++++++++++++++
.../foreign/ForeignIterableBuiltins.java | 83 ++++++++++
.../foreign/ForeignObjectBuiltins.java | 117 +-------------
.../graal/python/nodes/ErrorMessages.java | 1 -
.../object/GetForeignObjectClassNode.java | 10 +-
mx.graalpython/copyrights/overrides | 3 +
11 files changed, 356 insertions(+), 126 deletions(-)
create mode 100644 graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignExecutableBuiltins.java
create mode 100644 graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignInstantiableBuiltins.java
create mode 100644 graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignIterableBuiltins.java
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_interop.py b/graalpython/com.oracle.graal.python.test/src/tests/test_interop.py
index d3b511aea6..c065cacbd8 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/test_interop.py
+++ b/graalpython/com.oracle.graal.python.test/src/tests/test_interop.py
@@ -1040,7 +1040,9 @@ def test_java_map(self):
h.__init__(a=1, b=2)
assert h == {'a': 1, 'b': 2}
- with self.assertRaisesRegex(TypeError, 'invalid instantiation of foreign object'):
+ # Because it tries to call ForeignDict.__call__, but ForeignDict is not executable/instantiable,
+ # so it resolves to type.__call__, which cannot create a ForeignDict
+ with self.assertRaisesRegex(TypeError, "descriptor requires a 'dict' object but received a 'ForeignDict'"):
type(h).fromkeys(['a', 'b'], 42)
def test_java_iterator(self):
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java
index 8351695719..6f6254b9d8 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java
@@ -59,6 +59,9 @@
import java.util.ServiceLoader;
import java.util.logging.Level;
+import com.oracle.graal.python.builtins.objects.foreign.ForeignExecutableBuiltins;
+import com.oracle.graal.python.builtins.objects.foreign.ForeignInstantiableBuiltins;
+import com.oracle.graal.python.builtins.objects.foreign.ForeignIterableBuiltins;
import org.graalvm.nativeimage.ImageInfo;
import com.oracle.graal.python.PythonLanguage;
@@ -489,6 +492,9 @@ private static PythonBuiltins[] initializeBuiltins(boolean nativeAccessAllowed,
new ForeignNumberBuiltins(),
new ForeignBooleanBuiltins(),
new ForeignAbstractClassBuiltins(),
+ new ForeignExecutableBuiltins(),
+ new ForeignInstantiableBuiltins(),
+ new ForeignIterableBuiltins(),
new ListBuiltins(),
new DictBuiltins(),
new DictReprBuiltin(),
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java
index b7a4e04a27..8d586cc758 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java
@@ -305,6 +305,9 @@ public enum PythonBuiltinClassType implements TruffleObject {
ForeignNumber("ForeignNumber", J_POLYGLOT, ForeignObject, Flags.PUBLIC_BASE_WDICT, FOREIGNNUMBER_M_FLAGS, ForeignNumberBuiltins.SLOTS),
ForeignBoolean("ForeignBoolean", J_POLYGLOT, ForeignNumber, Flags.PUBLIC_BASE_WDICT, FOREIGNNUMBER_M_FLAGS, ForeignBooleanBuiltins.SLOTS),
ForeignAbstractClass("ForeignAbstractClass", J_POLYGLOT, ForeignObject, Flags.PUBLIC_BASE_WDICT),
+ ForeignExecutable("ForeignExecutable", J_POLYGLOT, ForeignObject, Flags.PUBLIC_BASE_WDICT),
+ ForeignInstantiable("ForeignInstantiable", J_POLYGLOT, ForeignObject, Flags.PUBLIC_BASE_WDICT),
+ ForeignIterable("ForeignIterable", J_POLYGLOT, ForeignObject, Flags.PUBLIC_BASE_WDICT),
// bz2
BZ2Compressor("BZ2Compressor", "_bz2"),
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignAbstractClassBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignAbstractClassBuiltins.java
index adde80b51e..48cfd68373 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignAbstractClassBuiltins.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignAbstractClassBuiltins.java
@@ -51,7 +51,7 @@
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___INSTANCECHECK__;
/*
- * NOTE: We are not using IndirectCallContext here in this file (except for CallNode)
+ * NOTE: We are not using IndirectCallContext here in this file
* because it seems unlikely that these interop messages would call back to Python
* and that we would also need precise frame info for that case.
* Adding it shouldn't hurt peak, but might be a non-trivial overhead in interpreter.
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignExecutableBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignExecutableBuiltins.java
new file mode 100644
index 0000000000..22c632fac0
--- /dev/null
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignExecutableBuiltins.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates.
+ * Copyright (c) 2014, Regents of the University of California
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.oracle.graal.python.builtins.objects.foreign;
+
+import static com.oracle.graal.python.nodes.SpecialMethodNames.J___CALL__;
+
+import java.util.List;
+
+import com.oracle.graal.python.PythonLanguage;
+import com.oracle.graal.python.builtins.Builtin;
+import com.oracle.graal.python.builtins.CoreFunctions;
+import com.oracle.graal.python.builtins.PythonBuiltinClassType;
+import com.oracle.graal.python.builtins.PythonBuiltins;
+import com.oracle.graal.python.builtins.objects.function.PKeyword;
+import com.oracle.graal.python.nodes.ErrorMessages;
+import com.oracle.graal.python.nodes.PRaiseNode;
+import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
+import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
+import com.oracle.graal.python.nodes.interop.PForeignToPTypeNode;
+import com.oracle.graal.python.nodes.object.IsForeignObjectNode;
+import com.oracle.graal.python.runtime.ExecutionContext.IndirectCallContext;
+import com.oracle.graal.python.runtime.GilNode;
+import com.oracle.graal.python.runtime.IndirectCallData;
+import com.oracle.graal.python.runtime.PythonContext;
+import com.oracle.graal.python.runtime.exception.PythonErrorType;
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Bind;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.GenerateNodeFactory;
+import com.oracle.truffle.api.dsl.NodeFactory;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.ArityException;
+import com.oracle.truffle.api.interop.InteropLibrary;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
+import com.oracle.truffle.api.interop.UnsupportedTypeException;
+import com.oracle.truffle.api.library.CachedLibrary;
+import com.oracle.truffle.api.nodes.Node;
+
+@CoreFunctions(extendClasses = PythonBuiltinClassType.ForeignExecutable)
+public final class ForeignExecutableBuiltins extends PythonBuiltins {
+ @Override
+ protected List extends NodeFactory extends PythonBuiltinBaseNode>> getNodeFactories() {
+ return ForeignExecutableBuiltinsFactory.getFactories();
+ }
+
+ @Builtin(name = J___CALL__, minNumOfPositionalArgs = 1, takesVarArgs = true, takesVarKeywordArgs = true)
+ @GenerateNodeFactory
+ public abstract static class CallNode extends PythonBuiltinNode {
+ @Specialization(guards = {"isForeignObjectNode.execute(inliningTarget, callee)", "!isNoValue(callee)", "keywords.length == 0"}, limit = "1")
+ static Object doInteropCall(VirtualFrame frame, Object callee, Object[] arguments, @SuppressWarnings("unused") PKeyword[] keywords,
+ @SuppressWarnings("unused") @Bind("this") Node inliningTarget,
+ @Cached("createFor(this)") IndirectCallData indirectCallData,
+ @SuppressWarnings("unused") @Cached IsForeignObjectNode isForeignObjectNode,
+ @CachedLibrary(limit = "4") InteropLibrary lib,
+ @Cached PForeignToPTypeNode toPTypeNode,
+ @Cached GilNode gil,
+ @Cached PRaiseNode.Lazy raiseNode) {
+ PythonLanguage language = PythonLanguage.get(inliningTarget);
+ PythonContext context = PythonContext.get(inliningTarget);
+ try {
+ Object state = IndirectCallContext.enter(frame, language, context, indirectCallData);
+ gil.release(true);
+ try {
+ return toPTypeNode.executeConvert(lib.execute(callee, arguments));
+ } finally {
+ gil.acquire();
+ IndirectCallContext.exit(frame, language, context, state);
+ }
+ } catch (ArityException | UnsupportedTypeException e) {
+ throw raiseNode.get(inliningTarget).raise(PythonErrorType.TypeError, ErrorMessages.INVALID_INSTANTIATION_OF_FOREIGN_OBJ);
+ } catch (UnsupportedMessageException e) {
+ throw CompilerDirectives.shouldNotReachHere(e);
+ }
+ }
+
+ @Fallback
+ @SuppressWarnings("unused")
+ static Object doGeneric(Object callee, Object arguments, Object keywords,
+ @Cached PRaiseNode raiseNode) {
+ throw raiseNode.raise(PythonErrorType.TypeError, ErrorMessages.INVALID_INSTANTIATION_OF_FOREIGN_OBJ);
+ }
+ }
+
+}
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignInstantiableBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignInstantiableBuiltins.java
new file mode 100644
index 0000000000..7ab0b0d664
--- /dev/null
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignInstantiableBuiltins.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates.
+ * Copyright (c) 2014, Regents of the University of California
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.oracle.graal.python.builtins.objects.foreign;
+
+import static com.oracle.graal.python.nodes.SpecialMethodNames.J___CALL__;
+import static com.oracle.graal.python.nodes.SpecialMethodNames.J___NEW__;
+
+import java.util.List;
+
+import com.oracle.graal.python.PythonLanguage;
+import com.oracle.graal.python.builtins.Builtin;
+import com.oracle.graal.python.builtins.CoreFunctions;
+import com.oracle.graal.python.builtins.PythonBuiltinClassType;
+import com.oracle.graal.python.builtins.PythonBuiltins;
+import com.oracle.graal.python.builtins.objects.function.PKeyword;
+import com.oracle.graal.python.nodes.ErrorMessages;
+import com.oracle.graal.python.nodes.PRaiseNode;
+import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
+import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
+import com.oracle.graal.python.nodes.interop.PForeignToPTypeNode;
+import com.oracle.graal.python.nodes.object.IsForeignObjectNode;
+import com.oracle.graal.python.runtime.ExecutionContext.IndirectCallContext;
+import com.oracle.graal.python.runtime.GilNode;
+import com.oracle.graal.python.runtime.IndirectCallData;
+import com.oracle.graal.python.runtime.PythonContext;
+import com.oracle.graal.python.runtime.exception.PythonErrorType;
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Bind;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.GenerateNodeFactory;
+import com.oracle.truffle.api.dsl.NodeFactory;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.ArityException;
+import com.oracle.truffle.api.interop.InteropLibrary;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
+import com.oracle.truffle.api.interop.UnsupportedTypeException;
+import com.oracle.truffle.api.library.CachedLibrary;
+import com.oracle.truffle.api.nodes.Node;
+
+@CoreFunctions(extendClasses = PythonBuiltinClassType.ForeignInstantiable)
+public final class ForeignInstantiableBuiltins extends PythonBuiltins {
+ @Override
+ protected List extends NodeFactory extends PythonBuiltinBaseNode>> getNodeFactories() {
+ return ForeignInstantiableBuiltinsFactory.getFactories();
+ }
+
+ @Builtin(name = J___NEW__, minNumOfPositionalArgs = 1, takesVarArgs = true, takesVarKeywordArgs = true)
+ @GenerateNodeFactory
+ abstract static class NewNode extends PythonBuiltinNode {
+ @Specialization(guards = {"isForeignObjectNode.execute(inliningTarget, callee)", "!isNoValue(callee)", "keywords.length == 0"}, limit = "1")
+ static Object doInteropCall(Object callee, Object[] arguments, @SuppressWarnings("unused") PKeyword[] keywords,
+ @SuppressWarnings("unused") @Bind("this") Node inliningTarget,
+ @SuppressWarnings("unused") @Cached IsForeignObjectNode isForeignObjectNode,
+ @CachedLibrary(limit = "3") InteropLibrary lib,
+ @Cached PForeignToPTypeNode toPTypeNode,
+ @Cached GilNode gil,
+ @Cached PRaiseNode.Lazy raiseNode) {
+ gil.release(true);
+ try {
+ Object res = lib.instantiate(callee, arguments);
+ return toPTypeNode.executeConvert(res);
+ } catch (ArityException | UnsupportedTypeException e) {
+ throw raiseNode.get(inliningTarget).raise(PythonErrorType.TypeError, ErrorMessages.INVALID_INSTANTIATION_OF_FOREIGN_OBJ);
+ } catch (UnsupportedMessageException e) {
+ throw CompilerDirectives.shouldNotReachHere(e);
+ } finally {
+ gil.acquire();
+ }
+ }
+
+ @Fallback
+ @SuppressWarnings("unused")
+ static Object doGeneric(Object callee, Object arguments, Object keywords,
+ @Cached PRaiseNode raiseNode) {
+ throw raiseNode.raise(PythonErrorType.TypeError, ErrorMessages.INVALID_INSTANTIATION_OF_FOREIGN_OBJ);
+ }
+ }
+
+ @Builtin(name = J___CALL__, minNumOfPositionalArgs = 1, takesVarArgs = true, takesVarKeywordArgs = true)
+ @GenerateNodeFactory
+ public abstract static class CallNode extends PythonBuiltinNode {
+ @Specialization(guards = {"isForeignObjectNode.execute(inliningTarget, callee)", "!isNoValue(callee)", "keywords.length == 0"}, limit = "1")
+ static Object doInteropCall(VirtualFrame frame, Object callee, Object[] arguments, @SuppressWarnings("unused") PKeyword[] keywords,
+ @SuppressWarnings("unused") @Bind("this") Node inliningTarget,
+ @Cached("createFor(this)") IndirectCallData indirectCallData,
+ @SuppressWarnings("unused") @Cached IsForeignObjectNode isForeignObjectNode,
+ @CachedLibrary(limit = "4") InteropLibrary lib,
+ @Cached PForeignToPTypeNode toPTypeNode,
+ @Cached GilNode gil,
+ @Cached PRaiseNode.Lazy raiseNode) {
+ PythonLanguage language = PythonLanguage.get(inliningTarget);
+ PythonContext context = PythonContext.get(inliningTarget);
+ try {
+ Object state = IndirectCallContext.enter(frame, language, context, indirectCallData);
+ gil.release(true);
+ try {
+ return toPTypeNode.executeConvert(lib.instantiate(callee, arguments));
+ } finally {
+ gil.acquire();
+ IndirectCallContext.exit(frame, language, context, state);
+ }
+ } catch (ArityException | UnsupportedTypeException e) {
+ throw raiseNode.get(inliningTarget).raise(PythonErrorType.TypeError, ErrorMessages.INVALID_INSTANTIATION_OF_FOREIGN_OBJ);
+ } catch (UnsupportedMessageException e) {
+ throw CompilerDirectives.shouldNotReachHere(e);
+ }
+ }
+
+ @Fallback
+ @SuppressWarnings("unused")
+ static Object doGeneric(Object callee, Object arguments, Object keywords,
+ @Cached PRaiseNode raiseNode) {
+ throw raiseNode.raise(PythonErrorType.TypeError, ErrorMessages.INVALID_INSTANTIATION_OF_FOREIGN_OBJ);
+ }
+ }
+
+}
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignIterableBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignIterableBuiltins.java
new file mode 100644
index 0000000000..647eee6b2f
--- /dev/null
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignIterableBuiltins.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates.
+ * Copyright (c) 2014, Regents of the University of California
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.oracle.graal.python.builtins.objects.foreign;
+
+import static com.oracle.graal.python.nodes.SpecialMethodNames.J___ITER__;
+
+import java.util.List;
+
+import com.oracle.graal.python.builtins.Builtin;
+import com.oracle.graal.python.builtins.CoreFunctions;
+import com.oracle.graal.python.builtins.PythonBuiltinClassType;
+import com.oracle.graal.python.builtins.PythonBuiltins;
+import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
+import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
+import com.oracle.graal.python.nodes.interop.PForeignToPTypeNode;
+import com.oracle.graal.python.runtime.GilNode;
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.GenerateNodeFactory;
+import com.oracle.truffle.api.dsl.NodeFactory;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.InteropLibrary;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
+import com.oracle.truffle.api.library.CachedLibrary;
+
+/*
+ * NOTE: We are not using IndirectCallContext here in this file
+ * because it seems unlikely that these interop messages would call back to Python
+ * and that we would also need precise frame info for that case.
+ * Adding it shouldn't hurt peak, but might be a non-trivial overhead in interpreter.
+ */
+@CoreFunctions(extendClasses = PythonBuiltinClassType.ForeignIterable)
+public final class ForeignIterableBuiltins extends PythonBuiltins {
+ @Override
+ protected List extends NodeFactory extends PythonBuiltinBaseNode>> getNodeFactories() {
+ return ForeignIterableBuiltinsFactory.getFactories();
+ }
+
+ @Builtin(name = J___ITER__, minNumOfPositionalArgs = 1)
+ @GenerateNodeFactory
+ public abstract static class IterNode extends PythonUnaryBuiltinNode {
+
+ @Specialization(limit = "3")
+ static Object doGeneric(Object object,
+ @CachedLibrary("object") InteropLibrary lib,
+ @Cached PForeignToPTypeNode convertNode,
+ @Cached GilNode gil) {
+ gil.release(true);
+ try {
+ return convertNode.executeConvert(lib.getIterator(object));
+ } catch (UnsupportedMessageException e) {
+ throw CompilerDirectives.shouldNotReachHere(e);
+ } finally {
+ gil.acquire();
+ }
+ }
+ }
+
+}
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignObjectBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignObjectBuiltins.java
index 19ad62ff6f..ea386f7fed 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignObjectBuiltins.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignObjectBuiltins.java
@@ -29,11 +29,8 @@
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.AttributeError;
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.TypeError;
import static com.oracle.graal.python.builtins.objects.str.StringUtils.simpleTruffleStringFormatUncached;
-import static com.oracle.graal.python.nodes.SpecialMethodNames.J___CALL__;
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___DIR__;
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___HASH__;
-import static com.oracle.graal.python.nodes.SpecialMethodNames.J___ITER__;
-import static com.oracle.graal.python.nodes.SpecialMethodNames.J___NEW__;
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___REPR__;
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___STR__;
import static com.oracle.graal.python.util.PythonUtils.TS_ENCODING;
@@ -49,7 +46,6 @@
import com.oracle.graal.python.builtins.PythonBuiltins;
import com.oracle.graal.python.builtins.objects.PNone;
import com.oracle.graal.python.builtins.objects.PythonAbstractObject;
-import com.oracle.graal.python.builtins.objects.function.PKeyword;
import com.oracle.graal.python.builtins.objects.object.ObjectBuiltins;
import com.oracle.graal.python.builtins.objects.object.ObjectNodes;
import com.oracle.graal.python.builtins.objects.type.TpSlots;
@@ -61,17 +57,13 @@
import com.oracle.graal.python.nodes.attributes.LookupAttributeInMRONode;
import com.oracle.graal.python.nodes.call.special.LookupAndCallUnaryNode;
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
-import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
import com.oracle.graal.python.nodes.interop.PForeignToPTypeNode;
import com.oracle.graal.python.nodes.object.BuiltinClassProfiles.IsBuiltinObjectProfile;
import com.oracle.graal.python.nodes.object.GetClassNode;
-import com.oracle.graal.python.nodes.object.IsForeignObjectNode;
import com.oracle.graal.python.nodes.util.CannotCastException;
import com.oracle.graal.python.nodes.util.CastToJavaStringNode;
-import com.oracle.graal.python.runtime.ExecutionContext.IndirectCallContext;
import com.oracle.graal.python.runtime.GilNode;
-import com.oracle.graal.python.runtime.IndirectCallData;
import com.oracle.graal.python.runtime.PythonContext;
import com.oracle.graal.python.runtime.PythonOptions;
import com.oracle.graal.python.runtime.exception.PException;
@@ -82,12 +74,10 @@
import com.oracle.truffle.api.dsl.Bind;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Cached.Shared;
-import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.GenerateCached;
import com.oracle.truffle.api.dsl.GenerateInline;
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
import com.oracle.truffle.api.dsl.ImportStatic;
-import com.oracle.truffle.api.dsl.NeverDefault;
import com.oracle.truffle.api.dsl.NodeFactory;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
@@ -102,7 +92,7 @@
import com.oracle.truffle.api.strings.TruffleString;
/*
- * NOTE: We are not using IndirectCallContext here in this file (except for CallNode)
+ * NOTE: We are not using IndirectCallContext here in this file
* because it seems unlikely that these interop messages would call back to Python
* and that we would also need precise frame info for that case.
* Adding it shouldn't hurt peak, but might be a non-trivial overhead in interpreter.
@@ -138,111 +128,6 @@ private static int hashCodeBoundary(Object self) {
}
}
- @Builtin(name = J___ITER__, minNumOfPositionalArgs = 1)
- @GenerateNodeFactory
- public abstract static class IterNode extends PythonUnaryBuiltinNode {
-
- @Specialization(limit = "3")
- static Object doGeneric(Object object,
- @Cached PRaiseNode raiseNode,
- @CachedLibrary("object") InteropLibrary lib,
- @Cached PForeignToPTypeNode convertNode,
- @Cached GilNode gil) {
- gil.release(true);
- try {
- if (lib.hasIterator(object)) {
- return convertNode.executeConvert(lib.getIterator(object));
- }
- } catch (UnsupportedMessageException e) {
- throw CompilerDirectives.shouldNotReachHere(e);
- } finally {
- gil.acquire();
- }
- throw raiseNode.raise(TypeError, ErrorMessages.FOREIGN_OBJ_ISNT_ITERABLE);
- }
- }
-
- @Builtin(name = J___NEW__, minNumOfPositionalArgs = 1, takesVarArgs = true, takesVarKeywordArgs = true)
- @GenerateNodeFactory
- abstract static class NewNode extends PythonBuiltinNode {
- @Specialization(guards = {"isForeignObjectNode.execute(inliningTarget, callee)", "!isNoValue(callee)", "keywords.length == 0"}, limit = "1")
- static Object doInteropCall(Object callee, Object[] arguments, @SuppressWarnings("unused") PKeyword[] keywords,
- @SuppressWarnings("unused") @Bind("this") Node inliningTarget,
- @SuppressWarnings("unused") @Cached IsForeignObjectNode isForeignObjectNode,
- @CachedLibrary(limit = "3") InteropLibrary lib,
- @Cached PForeignToPTypeNode toPTypeNode,
- @Cached GilNode gil,
- @Cached PRaiseNode.Lazy raiseNode) {
- gil.release(true);
- try {
- Object res = lib.instantiate(callee, arguments);
- return toPTypeNode.executeConvert(res);
- } catch (ArityException | UnsupportedTypeException | UnsupportedMessageException e) {
- throw raiseNode.get(inliningTarget).raise(PythonErrorType.TypeError, ErrorMessages.INVALID_INSTANTIATION_OF_FOREIGN_OBJ);
- } finally {
- gil.acquire();
- }
- }
-
- @Fallback
- @SuppressWarnings("unused")
- static Object doGeneric(Object callee, Object arguments, Object keywords,
- @Cached PRaiseNode raiseNode) {
- throw raiseNode.raise(PythonErrorType.TypeError, ErrorMessages.INVALID_INSTANTIATION_OF_FOREIGN_OBJ);
- }
- }
-
- @Builtin(name = J___CALL__, minNumOfPositionalArgs = 1, takesVarArgs = true, takesVarKeywordArgs = true)
- @GenerateNodeFactory
- public abstract static class CallNode extends PythonBuiltinNode {
- public final Object executeWithArgs(VirtualFrame frame, Object callee, Object[] arguments) {
- return execute(frame, callee, arguments, PKeyword.EMPTY_KEYWORDS);
- }
-
- public abstract Object execute(VirtualFrame frame, Object callee, Object[] arguments, PKeyword[] keywords);
-
- @Specialization(guards = {"isForeignObjectNode.execute(inliningTarget, callee)", "!isNoValue(callee)", "keywords.length == 0"}, limit = "1")
- static Object doInteropCall(VirtualFrame frame, Object callee, Object[] arguments, @SuppressWarnings("unused") PKeyword[] keywords,
- @SuppressWarnings("unused") @Bind("this") Node inliningTarget,
- @Cached("createFor(this)") IndirectCallData indirectCallData,
- @SuppressWarnings("unused") @Cached IsForeignObjectNode isForeignObjectNode,
- @CachedLibrary(limit = "4") InteropLibrary lib,
- @Cached PForeignToPTypeNode toPTypeNode,
- @Cached GilNode gil,
- @Cached PRaiseNode.Lazy raiseNode) {
- PythonLanguage language = PythonLanguage.get(inliningTarget);
- PythonContext context = PythonContext.get(inliningTarget);
- try {
- Object state = IndirectCallContext.enter(frame, language, context, indirectCallData);
- gil.release(true);
- try {
- if (lib.isExecutable(callee)) {
- return toPTypeNode.executeConvert(lib.execute(callee, arguments));
- } else {
- return toPTypeNode.executeConvert(lib.instantiate(callee, arguments));
- }
- } finally {
- gil.acquire();
- IndirectCallContext.exit(frame, language, context, state);
- }
- } catch (ArityException | UnsupportedTypeException | UnsupportedMessageException e) {
- throw raiseNode.get(inliningTarget).raise(PythonErrorType.TypeError, ErrorMessages.INVALID_INSTANTIATION_OF_FOREIGN_OBJ);
- }
- }
-
- @Fallback
- @SuppressWarnings("unused")
- static Object doGeneric(Object callee, Object arguments, Object keywords,
- @Cached PRaiseNode raiseNode) {
- throw raiseNode.raise(PythonErrorType.TypeError, ErrorMessages.INVALID_INSTANTIATION_OF_FOREIGN_OBJ);
- }
-
- @NeverDefault
- public static CallNode create() {
- return ForeignObjectBuiltinsFactory.CallNodeFactory.create(null);
- }
- }
-
@Slot(value = SlotKind.tp_getattro, isComplex = true)
@GenerateNodeFactory
abstract static class GetAttributeNode extends GetAttrBuiltinNode {
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java
index f15c1e4196..37dbb36db7 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/ErrorMessages.java
@@ -334,7 +334,6 @@ public abstract class ErrorMessages {
public static final TruffleString FAILED_TO_CONVERT_SEQ = tsLiteral("failed to convert sequence");
public static final TruffleString FLOAT_ARG_REQUIRED = tsLiteral("float argument required, not %p");
public static final TruffleString FOREIGN_OBJ_HAS_NO_ATTR_S = tsLiteral("foreign object has no attribute '%s'");
- public static final TruffleString FOREIGN_OBJ_ISNT_ITERABLE = tsLiteral("foreign object is not iterable");
public static final TruffleString FOREIGN_OBJ_ISNT_REVERSE_ITERABLE = tsLiteral("foreign object cannot be iterated in reverse");
public static final TruffleString FORMAT_REQUIRES_MAPPING = tsLiteral("format requires a mapping");
public static final TruffleString FORMAT_STR_CONTAINS_POS_FIELDS = tsLiteral("Format string contains positional fields");
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetForeignObjectClassNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetForeignObjectClassNode.java
index e7cb56977d..b7b041b290 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetForeignObjectClassNode.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/object/GetForeignObjectClassNode.java
@@ -96,8 +96,8 @@ public enum Trait {
META_OBJECT("AbstractClass", PythonBuiltinClassType.ForeignAbstractClass),
// Interop traits
- EXECUTABLE("Executable"),
- INSTANTIABLE("Instantiable"),
+ EXECUTABLE("Executable", PythonBuiltinClassType.ForeignExecutable),
+ INSTANTIABLE("Instantiable", PythonBuiltinClassType.ForeignInstantiable),
// Container traits/types must be last, see comment above
// Hash before Array so that foreign dict+list prefers dict.[]
@@ -106,7 +106,7 @@ public enum Trait {
ARRAY("List", PythonBuiltinClassType.PList),
// Iterator before Iterable so that foreign iterator+iterable prefers iterator.__iter__
ITERATOR("Iterator", PythonBuiltinClassType.PIterator),
- ITERABLE("Iterable");
+ ITERABLE("Iterable", PythonBuiltinClassType.ForeignIterable);
// Last in MRO
public static final Trait[] VALUES = Trait.values();
@@ -116,10 +116,6 @@ public enum Trait {
final int bit;
final PythonBuiltinClassType type;
- Trait(String name) {
- this(name, null);
- }
-
Trait(String name, PythonBuiltinClassType type) {
this.name = name;
this.bit = 1 << ordinal();
diff --git a/mx.graalpython/copyrights/overrides b/mx.graalpython/copyrights/overrides
index 0a1351458c..1a30d74d25 100644
--- a/mx.graalpython/copyrights/overrides
+++ b/mx.graalpython/copyrights/overrides
@@ -619,6 +619,9 @@ graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects
graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignObjectBuiltins.java,zippy.copyright
graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignAbstractClassBuiltins.java,zippy.copyright
graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignBooleanBuiltins.java,zippy.copyright
+graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignExecutableBuiltins.java,zippy.copyright
+graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignInstantiableBuiltins.java,zippy.copyright
+graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignIterableBuiltins.java,zippy.copyright
graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignNumberBuiltins.java,zippy.copyright
graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/frame/FrameBuiltins.java,zippy.copyright
graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/function/AbstractFunctionBuiltins.java,zippy.copyright
From 38c69a533e60b1517874c4daf5ba0eaa1a3fcb0a Mon Sep 17 00:00:00 2001
From: Benoit Daloze
Date: Mon, 27 Jan 2025 17:22:31 +0100
Subject: [PATCH 10/51] Simplify logic for foreign __new__ and __call__: they
do not accept keyword arguments
* So the error is now:
TypeError: ForeignInstantiable.__call__() got an unexpected keyword argument 'kwarg'
vs before:
TypeError: invalid instantiation of foreign object
(cherry picked from commit 95b076038980628431dc08d661dc74e0b4bd5deb)
---
.../src/tests/test_interop.py | 15 ++++--
.../foreign/ForeignExecutableBuiltins.java | 17 ++-----
.../foreign/ForeignInstantiableBuiltins.java | 50 ++-----------------
3 files changed, 19 insertions(+), 63 deletions(-)
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_interop.py b/graalpython/com.oracle.graal.python.test/src/tests/test_interop.py
index c065cacbd8..6ea5c7e6f6 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/test_interop.py
+++ b/graalpython/com.oracle.graal.python.test/src/tests/test_interop.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# The Universal Permissive License (UPL), Version 1.0
@@ -471,11 +471,20 @@ def test_java_import_from_jar(self):
os.unlink(tempname)
def test_java_class(self):
- from java.lang import Integer, Number, NumberFormatException
- self.assertEqual(type(Integer).mro(), [polyglot.ForeignClass, polyglot.ForeignAbstractClass, polyglot.ForeignInstantiable, polyglot.ForeignObject, object])
+ from java.lang import Number, NumberFormatException
+ from java.util import ArrayList
+ self.assertEqual(type(ArrayList).mro(), [polyglot.ForeignClass, polyglot.ForeignAbstractClass, polyglot.ForeignInstantiable, polyglot.ForeignObject, object])
self.assertEqual(type(Number).mro(), [polyglot.ForeignAbstractClass, polyglot.ForeignObject, object])
self.assertEqual(type(NumberFormatException).mro(), [polyglot.ForeignClass, polyglot.ForeignAbstractClass, polyglot.ForeignInstantiable, polyglot.ForeignObject, object])
+ from java.util import ArrayList
+ l = ArrayList()
+ assert isinstance(l, ArrayList)
+ self.assertEqual(getattr(ArrayList, 'class'), l.getClass())
+
+ with self.assertRaisesRegex(TypeError, "ForeignInstantiable.__call__\(\) got an unexpected keyword argument 'kwarg'"):
+ ArrayList(kwarg=42)
+
def test_java_exceptions(self):
# TODO: more tests
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignExecutableBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignExecutableBuiltins.java
index 22c632fac0..ea02d004c7 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignExecutableBuiltins.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignExecutableBuiltins.java
@@ -35,13 +35,11 @@
import com.oracle.graal.python.builtins.CoreFunctions;
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
import com.oracle.graal.python.builtins.PythonBuiltins;
-import com.oracle.graal.python.builtins.objects.function.PKeyword;
import com.oracle.graal.python.nodes.ErrorMessages;
import com.oracle.graal.python.nodes.PRaiseNode;
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
import com.oracle.graal.python.nodes.interop.PForeignToPTypeNode;
-import com.oracle.graal.python.nodes.object.IsForeignObjectNode;
import com.oracle.graal.python.runtime.ExecutionContext.IndirectCallContext;
import com.oracle.graal.python.runtime.GilNode;
import com.oracle.graal.python.runtime.IndirectCallData;
@@ -50,7 +48,6 @@
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Bind;
import com.oracle.truffle.api.dsl.Cached;
-import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
import com.oracle.truffle.api.dsl.NodeFactory;
import com.oracle.truffle.api.dsl.Specialization;
@@ -69,14 +66,13 @@ protected List extends NodeFactory extends PythonBuiltinBaseNode>> getNodeFa
return ForeignExecutableBuiltinsFactory.getFactories();
}
- @Builtin(name = J___CALL__, minNumOfPositionalArgs = 1, takesVarArgs = true, takesVarKeywordArgs = true)
+ @Builtin(name = J___CALL__, minNumOfPositionalArgs = 1, takesVarArgs = true)
@GenerateNodeFactory
public abstract static class CallNode extends PythonBuiltinNode {
- @Specialization(guards = {"isForeignObjectNode.execute(inliningTarget, callee)", "!isNoValue(callee)", "keywords.length == 0"}, limit = "1")
- static Object doInteropCall(VirtualFrame frame, Object callee, Object[] arguments, @SuppressWarnings("unused") PKeyword[] keywords,
+ @Specialization
+ static Object doInteropCall(VirtualFrame frame, Object callee, Object[] arguments,
@SuppressWarnings("unused") @Bind("this") Node inliningTarget,
@Cached("createFor(this)") IndirectCallData indirectCallData,
- @SuppressWarnings("unused") @Cached IsForeignObjectNode isForeignObjectNode,
@CachedLibrary(limit = "4") InteropLibrary lib,
@Cached PForeignToPTypeNode toPTypeNode,
@Cached GilNode gil,
@@ -98,13 +94,6 @@ static Object doInteropCall(VirtualFrame frame, Object callee, Object[] argument
throw CompilerDirectives.shouldNotReachHere(e);
}
}
-
- @Fallback
- @SuppressWarnings("unused")
- static Object doGeneric(Object callee, Object arguments, Object keywords,
- @Cached PRaiseNode raiseNode) {
- throw raiseNode.raise(PythonErrorType.TypeError, ErrorMessages.INVALID_INSTANTIATION_OF_FOREIGN_OBJ);
- }
}
}
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignInstantiableBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignInstantiableBuiltins.java
index 7ab0b0d664..d5b095145e 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignInstantiableBuiltins.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/ForeignInstantiableBuiltins.java
@@ -36,13 +36,11 @@
import com.oracle.graal.python.builtins.CoreFunctions;
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
import com.oracle.graal.python.builtins.PythonBuiltins;
-import com.oracle.graal.python.builtins.objects.function.PKeyword;
import com.oracle.graal.python.nodes.ErrorMessages;
import com.oracle.graal.python.nodes.PRaiseNode;
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
import com.oracle.graal.python.nodes.interop.PForeignToPTypeNode;
-import com.oracle.graal.python.nodes.object.IsForeignObjectNode;
import com.oracle.graal.python.runtime.ExecutionContext.IndirectCallContext;
import com.oracle.graal.python.runtime.GilNode;
import com.oracle.graal.python.runtime.IndirectCallData;
@@ -51,7 +49,6 @@
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Bind;
import com.oracle.truffle.api.dsl.Cached;
-import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
import com.oracle.truffle.api.dsl.NodeFactory;
import com.oracle.truffle.api.dsl.Specialization;
@@ -70,46 +67,14 @@ protected List extends NodeFactory extends PythonBuiltinBaseNode>> getNodeFa
return ForeignInstantiableBuiltinsFactory.getFactories();
}
- @Builtin(name = J___NEW__, minNumOfPositionalArgs = 1, takesVarArgs = true, takesVarKeywordArgs = true)
- @GenerateNodeFactory
- abstract static class NewNode extends PythonBuiltinNode {
- @Specialization(guards = {"isForeignObjectNode.execute(inliningTarget, callee)", "!isNoValue(callee)", "keywords.length == 0"}, limit = "1")
- static Object doInteropCall(Object callee, Object[] arguments, @SuppressWarnings("unused") PKeyword[] keywords,
- @SuppressWarnings("unused") @Bind("this") Node inliningTarget,
- @SuppressWarnings("unused") @Cached IsForeignObjectNode isForeignObjectNode,
- @CachedLibrary(limit = "3") InteropLibrary lib,
- @Cached PForeignToPTypeNode toPTypeNode,
- @Cached GilNode gil,
- @Cached PRaiseNode.Lazy raiseNode) {
- gil.release(true);
- try {
- Object res = lib.instantiate(callee, arguments);
- return toPTypeNode.executeConvert(res);
- } catch (ArityException | UnsupportedTypeException e) {
- throw raiseNode.get(inliningTarget).raise(PythonErrorType.TypeError, ErrorMessages.INVALID_INSTANTIATION_OF_FOREIGN_OBJ);
- } catch (UnsupportedMessageException e) {
- throw CompilerDirectives.shouldNotReachHere(e);
- } finally {
- gil.acquire();
- }
- }
-
- @Fallback
- @SuppressWarnings("unused")
- static Object doGeneric(Object callee, Object arguments, Object keywords,
- @Cached PRaiseNode raiseNode) {
- throw raiseNode.raise(PythonErrorType.TypeError, ErrorMessages.INVALID_INSTANTIATION_OF_FOREIGN_OBJ);
- }
- }
-
- @Builtin(name = J___CALL__, minNumOfPositionalArgs = 1, takesVarArgs = true, takesVarKeywordArgs = true)
+ @Builtin(name = J___NEW__, minNumOfPositionalArgs = 1, takesVarArgs = true)
+ @Builtin(name = J___CALL__, minNumOfPositionalArgs = 1, takesVarArgs = true)
@GenerateNodeFactory
public abstract static class CallNode extends PythonBuiltinNode {
- @Specialization(guards = {"isForeignObjectNode.execute(inliningTarget, callee)", "!isNoValue(callee)", "keywords.length == 0"}, limit = "1")
- static Object doInteropCall(VirtualFrame frame, Object callee, Object[] arguments, @SuppressWarnings("unused") PKeyword[] keywords,
+ @Specialization
+ static Object doInteropCall(VirtualFrame frame, Object callee, Object[] arguments,
@SuppressWarnings("unused") @Bind("this") Node inliningTarget,
@Cached("createFor(this)") IndirectCallData indirectCallData,
- @SuppressWarnings("unused") @Cached IsForeignObjectNode isForeignObjectNode,
@CachedLibrary(limit = "4") InteropLibrary lib,
@Cached PForeignToPTypeNode toPTypeNode,
@Cached GilNode gil,
@@ -131,13 +96,6 @@ static Object doInteropCall(VirtualFrame frame, Object callee, Object[] argument
throw CompilerDirectives.shouldNotReachHere(e);
}
}
-
- @Fallback
- @SuppressWarnings("unused")
- static Object doGeneric(Object callee, Object arguments, Object keywords,
- @Cached PRaiseNode raiseNode) {
- throw raiseNode.raise(PythonErrorType.TypeError, ErrorMessages.INVALID_INSTANTIATION_OF_FOREIGN_OBJ);
- }
}
}
From 7c829c5f0ece9d7a56e08863240e9ac66778561b Mon Sep 17 00:00:00 2001
From: Benoit Daloze
Date: Fri, 17 Jan 2025 16:39:17 +0100
Subject: [PATCH 11/51] Rethrow internal errors during
PythonLanguage#initializeContext
* Such as AssertionError, etc.
* Ensure to not print Python exceptions twice by always throwing
an exit exception after printing stacktraces with AlwaysRunExcepthook.
(cherry picked from commit 53180fecb184d4b89b1765527f39f99423d399c9)
---
.../graal/python/shell/GraalPythonMain.java | 2 +
.../exception/TopLevelExceptionHandler.java | 37 +++++++++++--------
2 files changed, 23 insertions(+), 16 deletions(-)
diff --git a/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java b/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java
index f7838f7d5e..f0a6328d1f 100644
--- a/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java
+++ b/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java
@@ -843,6 +843,8 @@ protected void launch(Builder contextBuilder) {
} catch (PolyglotException e) {
if (e.isExit()) {
rc = e.getExitStatus();
+ } else {
+ throw e;
}
} catch (NoSuchFileException e) {
printFileNotFoundException(e);
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/exception/TopLevelExceptionHandler.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/exception/TopLevelExceptionHandler.java
index f20a4ea9cd..53f1fe05d0 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/exception/TopLevelExceptionHandler.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/exception/TopLevelExceptionHandler.java
@@ -195,12 +195,7 @@ private AbstractTruffleException handlePythonException(AbstractTruffleException
if (PythonOptions.isPExceptionWithJavaStacktrace(getPythonLanguage()) && e instanceof PException pe) {
ExceptionUtils.printJavaStackTrace(pe);
}
- if (!getSourceSection().getSource().isInteractive()) {
- if (getContext().isChildContext()) {
- getContext().getChildContextData().setExitCode(1);
- }
- throw new PythonExitException(this, 1);
- }
+ exit(1);
}
// Before we leave Python, format the message since outside the context
if (e instanceof PException pe) {
@@ -209,6 +204,15 @@ private AbstractTruffleException handlePythonException(AbstractTruffleException
throw e;
}
+ private void exit(int exitCode) {
+ if (!getSourceSection().getSource().isInteractive()) {
+ if (getContext().isChildContext()) {
+ getContext().getChildContextData().setExitCode(1);
+ }
+ throw new PythonExitException(this, exitCode);
+ }
+ }
+
private static boolean isSystemExit(PBaseException pythonException) {
return IsBuiltinClassProfile.profileClassSlowPath(GetPythonObjectClassNode.executeUncached(pythonException), SystemExit);
}
@@ -227,6 +231,7 @@ private void handleJavaException(Throwable e) {
if (PythonOptions.shouldPrintJavaStacktrace(getPythonLanguage(), e)) {
e.printStackTrace();
}
+ exit(1);
}
} catch (UnsupportedMessageException unsupportedMessageException) {
throw CompilerDirectives.shouldNotReachHere();
@@ -250,12 +255,12 @@ private void handleSystemExit(PBaseException pythonException) {
int exitcode = getExitCode(pythonException);
throw new PythonExitException(this, exitcode);
} catch (CannotCastException e) {
- // fall through
- }
- if (handleAlwaysRunExceptHook(theContext, pythonException)) {
- throw new PythonExitException(this, 1);
+ if (handleAlwaysRunExceptHook(theContext, pythonException)) {
+ throw new PythonExitException(this, 1);
+ } else {
+ throw pythonException.getExceptionForReraise(pythonException.getTraceback());
+ }
}
- throw pythonException.getExceptionForReraise(pythonException.getTraceback());
}
@TruffleBoundary
@@ -264,12 +269,12 @@ private Object handleChildContextExit(PBaseException pythonException) throws PEx
try {
return getExitCode(pythonException);
} catch (CannotCastException cce) {
- // fall through
- }
- if (handleAlwaysRunExceptHook(getContext(), pythonException)) {
- return 1;
+ if (handleAlwaysRunExceptHook(getContext(), pythonException)) {
+ return 1;
+ } else {
+ throw pythonException.getExceptionForReraise(pythonException.getTraceback());
+ }
}
- throw pythonException.getExceptionForReraise(pythonException.getTraceback());
}
private static int getExitCode(PBaseException pythonException) throws CannotCastException {
From 96d33d879b537c0c5f733c9cf00e82f355e1f7e3 Mon Sep 17 00:00:00 2001
From: Danilo Ansaloni
Date: Tue, 3 Sep 2024 19:40:34 +0200
Subject: [PATCH 12/51] Update XZ version.
(cherry picked from commit 10f8ae3547ff2abba2ed100d7116355155a51985)
---
mx.graalpython/suite.py | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/mx.graalpython/suite.py b/mx.graalpython/suite.py
index 763a0fd5f6..8cc53b105a 100644
--- a/mx.graalpython/suite.py
+++ b/mx.graalpython/suite.py
@@ -108,12 +108,12 @@
],
"digest": "sha512:16920fd41f398696c563417049472c0d81abb2d293ecb45bbbe97c12651669833e34eac238e2e4a6f8761ea58fb39806425d2741e88e8c3097fe2b5457ebf488",
},
- "XZ-5.2.6": {
+ "XZ-5.6.2": {
"urls": [
- "https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/xz-5.2.6.tar.gz",
+ "https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/xz-5.6.2.tar.gz",
],
"packedResource": True,
- "digest": "sha512:090958dd6c202c989746686094c86707ad4ae835026640080fc0a9d0fad699821b7d5cb3a67e6700661a0938818ba153662366f89ab8ec47e0bae4a3fe9b1961",
+ "digest": "sha512:c32c32c95e3541b906e0284e66a953ace677e0ce6af2084e7b122600047bf7542c1b0fabb5909b19ff79fba6def530be674df1c675b22a47a8d57f3f0b736a82",
},
"BOUNCYCASTLE-PROVIDER": {
"digest": "sha512:fb10c3c089921c8173ad285329f730e0e78de175d1b50b9bdd79c6a85a265af9b3331caa0c1ed57e5f47047319ce3b0f3bb5def0a3db9cccf2755cc95e145e52",
@@ -636,10 +636,10 @@
"bin/",
],
"cmakeConfig": {
- "XZ_SRC": "",
+ "XZ_SRC": "",
"XZ_VERSION_MAJOR": "5",
- "XZ_VERSION_MINOR": "2",
- "XZ_VERSION_PATCH": "6",
+ "XZ_VERSION_MINOR": "6",
+ "XZ_VERSION_PATCH": "2",
},
"os_arch": {
"windows": {
@@ -654,7 +654,7 @@
},
},
"buildDependencies": [
- "XZ-5.2.6",
+ "XZ-5.6.2",
],
},
From ce7f385fd261f0f8f75122d6964045c3065ad04d Mon Sep 17 00:00:00 2001
From: stepan
Date: Wed, 19 Feb 2025 14:27:35 +0100
Subject: [PATCH 13/51] Fix: Maven plugin incorrectly prints warning about
default resources directory. Fix few typos in warning messages.
---
.../src/tests/standalone/test_gradle_plugin.py | 6 +++++-
.../src/tests/standalone/test_maven_plugin.py | 2 ++
.../python/maven/plugin/ManageResourcesMojo.java | 4 ++--
.../java/org/graalvm/python/GraalPyGradlePlugin.java | 10 +++++-----
4 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/standalone/test_gradle_plugin.py b/graalpython/com.oracle.graal.python.test/src/tests/standalone/test_gradle_plugin.py
index 52d95fc704..b50be878dc 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/standalone/test_gradle_plugin.py
+++ b/graalpython/com.oracle.graal.python.test/src/tests/standalone/test_gradle_plugin.py
@@ -133,6 +133,8 @@ def check_gradle_generated_app(self, community):
cmd = gradlew_cmd + ["build"]
out, return_code = util.run_cmd(cmd, self.env, cwd=target_dir, logger=log)
util.check_ouput("BUILD SUCCESS", out, logger=log)
+ util.check_ouput("Virtual filesystem is deployed to default resources directory", out, logger=log)
+ util.check_ouput("This can cause conflicts if used with other Java libraries that also deploy GraalPy virtual filesystem", out, logger=log)
self.check_filelist(target_dir, log)
cmd = gradlew_cmd + ["nativeCompile"]
@@ -413,7 +415,7 @@ def check_gradle_python_resources_dir_and_external_dir_error(self):
gradle_cmd = util.get_gradle_wrapper(target_dir, self.env)
cmd = gradle_cmd + ["graalPyResources"]
out, return_code = util.run_cmd(cmd, self.env, cwd=target_dir)
- util.check_ouput("Cannot set both 'externalDirectory' and 'resourcesDirectory' at the same time", out)
+ util.check_ouput("Cannot set both 'externalDirectory' and 'resourceDirectory' at the same time", out)
assert return_code != 0, out
@@ -478,6 +480,8 @@ def check_gradle_namespaced_vfs(self):
app1_gradle_cmd = util.get_gradle_wrapper(app1_dir, self.env)
out, return_code = util.run_cmd(app1_gradle_cmd + ['publishToMavenLocal'], self.env, cwd=app1_dir)
+ util.check_ouput("Virtual filesystem is deployed to default resources directory", out, contains=False)
+ util.check_ouput("This can cause conflicts if used with other Java libraries that also deploy GraalPy virtual filesystem", out, contains=False)
assert return_code == 0, out
app2_gradle_cmd = util.get_gradle_wrapper(app2_dir, self.env)
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/standalone/test_maven_plugin.py b/graalpython/com.oracle.graal.python.test/src/tests/standalone/test_maven_plugin.py
index 4b2cdb5c04..5c4f9e34cb 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/standalone/test_maven_plugin.py
+++ b/graalpython/com.oracle.graal.python.test/src/tests/standalone/test_maven_plugin.py
@@ -115,6 +115,8 @@ def check_generated_app(self, use_default_vfs_path, use_utils_pkg=False):
cmd = mvnw_cmd + ["package", "-Pnative", "-DmainClass=it.pkg.GraalPy"]
out, return_code = util.run_cmd(cmd, self.env, cwd=target_dir)
util.check_ouput("BUILD SUCCESS", out)
+ util.check_ouput("Virtual filesystem is deployed to default resources directory", out, contains=use_default_vfs_path)
+ util.check_ouput("This can cause conflicts if used with other Java libraries that also deploy GraalPy virtual filesystem.", out, contains=use_default_vfs_path)
# check fileslist.txt
fl_path = os.path.join(target_dir, "target", "classes", vfs_prefix, "fileslist.txt")
diff --git a/graalpython/graalpy-maven-plugin/src/main/java/org/graalvm/python/maven/plugin/ManageResourcesMojo.java b/graalpython/graalpy-maven-plugin/src/main/java/org/graalvm/python/maven/plugin/ManageResourcesMojo.java
index bc2b69ceae..d81b78b861 100644
--- a/graalpython/graalpy-maven-plugin/src/main/java/org/graalvm/python/maven/plugin/ManageResourcesMojo.java
+++ b/graalpython/graalpy-maven-plugin/src/main/java/org/graalvm/python/maven/plugin/ManageResourcesMojo.java
@@ -145,7 +145,7 @@ public void execute() throws MojoExecutionException {
}
if (resourceDirectory == null) {
- if (externalDirectory != null) {
+ if (externalDirectory == null) {
getLog().info(String.format("Virtual filesystem is deployed to default resources directory '%s'. " +
"This can cause conflicts if used with other Java libraries that also deploy GraalPy virtual filesystem. " +
"Consider adding GRAALPY-VFS/${project.groupId}/${project.artifactId} to your pom.xml, " +
@@ -162,7 +162,7 @@ public void execute() throws MojoExecutionException {
getLog().warn("The GraalPy plugin configuration setting was deprecated and has no effect anymore.\n" +
"For execution in jvm mode, the python language home is always available.\n" +
"When building a native executable using GraalVM Native Image, then the full python language home is by default embedded into the native executable.\n" +
- "For more details, please refer to the documentation of GraalVM Native Image options IncludeLanguageResources and CopyLanguageResources documentation.");
+ "For more details, please refer to the documentation of GraalVM Native Image options IncludeLanguageResources and CopyLanguageResources.");
}
manageVenv();
diff --git a/graalpython/org.graalvm.python.gradle.plugin/src/main/java/org/graalvm/python/GraalPyGradlePlugin.java b/graalpython/org.graalvm.python.gradle.plugin/src/main/java/org/graalvm/python/GraalPyGradlePlugin.java
index f0ff56f0e1..0b964a9720 100644
--- a/graalpython/org.graalvm.python.gradle.plugin/src/main/java/org/graalvm/python/GraalPyGradlePlugin.java
+++ b/graalpython/org.graalvm.python.gradle.plugin/src/main/java/org/graalvm/python/GraalPyGradlePlugin.java
@@ -117,11 +117,11 @@ public void apply(Project project) {
if (extension.getPythonResourcesDirectory().isPresent() && extension.getExternalDirectory().isPresent()) {
throw new GradleException(
- "Cannot set both 'externalDirectory' and 'resourcesDirectory' at the same time. " +
+ "Cannot set both 'externalDirectory' and 'resourceDirectory' at the same time. " +
"New property 'externalDirectory' is a replacement for deprecated 'pythonResourcesDirectory'. " +
"If you want to deploy the virtual environment into physical filesystem, use 'externalDirectory'. " +
"The deployment of the external directory alongside the application is not handled by the GraalPy Maven plugin in such case." +
- "If you wish to bundle the virtual filesystem in Java resources, use 'resourcesDirectory'. " +
+ "If you wish to bundle the virtual filesystem in Java resources, use 'resourceDirectory'. " +
"For more details, please refer to https://www.graalvm.org/latest/reference-manual/python/Embedding-Build-Tools. ");
}
@@ -132,9 +132,9 @@ public void apply(Project project) {
// Run the vfsFilesListTask conditionally only if 'externalDirectory' is not set
if (!extension.getPythonResourcesDirectory().isPresent() && !extension.getExternalDirectory().isPresent()) {
if (!extension.getResourceDirectory().isPresent()) {
- proj.getLogger().info(String.format("Virtual filesystem is deployed to default resources directory '%s'. " +
+ proj.getLogger().warn(String.format("Virtual filesystem is deployed to default resources directory '%s'. " +
"This can cause conflicts if used with other Java libraries that also deploy GraalPy virtual filesystem. " +
- "Consider adding `resourcesDirectory = \"GRAALPY-VFS/${groupId}/${artifactId}\"` to your build.gradle script " +
+ "Consider adding `resourceDirectory = \"GRAALPY-VFS/${groupId}/${artifactId}\"` to your build.gradle script " +
"(replace the placeholders with values specific to your project), " +
"moving any existing sources from '%s' to '%s', and using VirtualFileSystem$Builder#resourceDirectory." +
"For more details, please refer to https://www.graalvm.org/latest/reference-manual/python/Embedding-Build-Tools. ",
@@ -192,7 +192,7 @@ private TaskProvider registerResourcesTask(Project project, Confi
t.getLogger().warn("The GraalPy plugin pythonHome configuration setting was deprecated and has no effect anymore.\n" +
"For execution in jvm mode, the python language home is always available.\n" +
"When building a native executable using GraalVM Native Image, then the full python language home is by default embedded into the native executable.\n" +
- "For more details, please refer to the documentation of GraalVM Native Image options IncludeLanguageResources and CopyLanguageResources documentation.");
+ "For more details, please refer to the documentation of GraalVM Native Image options IncludeLanguageResources and CopyLanguageResources.");
}
t.getPackages().set(extension.getPackages());
From 3b46423445fef929fc1546c5d88efc8a46551935 Mon Sep 17 00:00:00 2001
From: stepan
Date: Wed, 19 Feb 2025 14:51:56 +0100
Subject: [PATCH 14/51] Improve the GraalPyResources docs
---
.../python/embedding/GraalPyResources.java | 46 ++++++++++++-------
1 file changed, 30 insertions(+), 16 deletions(-)
diff --git a/graalpython/org.graalvm.python.embedding/src/org/graalvm/python/embedding/GraalPyResources.java b/graalpython/org.graalvm.python.embedding/src/org/graalvm/python/embedding/GraalPyResources.java
index 7efc01cd3a..fa26d06389 100644
--- a/graalpython/org.graalvm.python.embedding/src/org/graalvm/python/embedding/GraalPyResources.java
+++ b/graalpython/org.graalvm.python.embedding/src/org/graalvm/python/embedding/GraalPyResources.java
@@ -198,7 +198,12 @@ private GraalPyResources() {
* location
* /org.graalvm.python.vfs/src
- is set as the python sources location
*
- *
+ *
+ * When the virtual filesystem is located in other than the default resource directory,
+ * {@code org.graalvm.python.vfs}, i.e., using Maven or Gradle option {@code resourceDirectory},
+ * use {@link #contextBuilder(VirtualFileSystem)} and
+ * {@link VirtualFileSystem.Builder#resourceDirectory(String)} when building the
+ * {@link VirtualFileSystem}.
*
* @return a new {@link Context} instance
* @since 24.2.0
@@ -233,6 +238,12 @@ public static Context createContext() {
* }
* }
*
+ *
+ * When the virtual filesystem is located in other than the default resource directory,
+ * {@code org.graalvm.python.vfs}, i.e., using Maven or Gradle option {@code resourceDirectory},
+ * use {@link #contextBuilder(VirtualFileSystem)} and
+ * {@link VirtualFileSystem.Builder#resourceDirectory(String)} when building the
+ * {@link VirtualFileSystem}.
*
* @see PythonOptions
@@ -308,13 +319,14 @@ public static Context.Builder contextBuilder(VirtualFileSystem vfs) {
/**
* Creates a GraalPy context preconfigured with GraalPy and polyglot Context configuration
- * options for use with resources located in a real filesystem.
+ * options for use with resources located in an external directory in real filesystem.
*
* Following resource paths are preconfigured:
*
- * ${resourcesDirectory}/venv
- is set as the python virtual environment
+ * ${externalResourcesDirectory}/venv
- is set as the python virtual
+ * environment location
+ * ${externalResourcesDirectory}/src
- is set as the python sources
* location
- * ${resourcesDirectory}/src
- is set as the python sources location
*
*
*
@@ -343,19 +355,20 @@ public static Context.Builder contextBuilder(VirtualFileSystem vfs) {
*
*
*
- * @param resourcesDirectory the root directory with GraalPy specific embedding resources
+ * @param externalResourcesDirectory the root directory with GraalPy specific embedding
+ * resources
* @return a new {@link org.graalvm.polyglot.Context.Builder} instance
* @since 24.2.0
*/
- public static Context.Builder contextBuilder(Path resourcesDirectory) {
+ public static Context.Builder contextBuilder(Path externalResourcesDirectory) {
String execPath;
if (VirtualFileSystemImpl.isWindows()) {
- execPath = resourcesDirectory.resolve(VirtualFileSystemImpl.VFS_VENV).resolve("Scripts").resolve("python.exe").toAbsolutePath().toString();
+ execPath = externalResourcesDirectory.resolve(VirtualFileSystemImpl.VFS_VENV).resolve("Scripts").resolve("python.exe").toAbsolutePath().toString();
} else {
- execPath = resourcesDirectory.resolve(VirtualFileSystemImpl.VFS_VENV).resolve("bin").resolve("python").toAbsolutePath().toString();
+ execPath = externalResourcesDirectory.resolve(VirtualFileSystemImpl.VFS_VENV).resolve("bin").resolve("python").toAbsolutePath().toString();
}
- String srcPath = resourcesDirectory.resolve(VirtualFileSystemImpl.VFS_SRC).toAbsolutePath().toString();
+ String srcPath = externalResourcesDirectory.resolve(VirtualFileSystemImpl.VFS_SRC).toAbsolutePath().toString();
return createContextBuilder().
// allow all IO access
allowIO(IOAccess.ALL).
@@ -437,8 +450,9 @@ public static Path getNativeExecutablePath() {
* The structure of the created resource directory will stay the same like the embedded Python
* resources structure:
*
- * ${resourcesDirectory}/venv
- the python virtual environment location
- * ${resourcesDirectory}/src
- the python sources location
+ * ${externalResourcesDirectory}/venv
- the python virtual environment
+ * location
+ * ${externalResourcesDirectory}/src
- the python sources location
*
*
*
@@ -456,17 +470,17 @@ public static Path getNativeExecutablePath() {
*
*
* @param vfs the {@link VirtualFileSystem} from which resources are to be extracted
- * @param resourcesDirectory the target directory to extract the resources to
+ * @param externalResourcesDirectory the target directory to extract the resources to
* @throws IOException if resources isn't a directory
* @see #contextBuilder(Path)
* @see VirtualFileSystem.Builder#resourceLoadingClass(Class)
*
* @since 24.2.0
*/
- public static void extractVirtualFileSystemResources(VirtualFileSystem vfs, Path resourcesDirectory) throws IOException {
- if (Files.exists(resourcesDirectory) && !Files.isDirectory(resourcesDirectory)) {
- throw new IOException(String.format("%s has to be a directory", resourcesDirectory.toString()));
+ public static void extractVirtualFileSystemResources(VirtualFileSystem vfs, Path externalResourcesDirectory) throws IOException {
+ if (Files.exists(externalResourcesDirectory) && !Files.isDirectory(externalResourcesDirectory)) {
+ throw new IOException(String.format("%s has to be a directory", externalResourcesDirectory.toString()));
}
- vfs.impl.extractResources(resourcesDirectory);
+ vfs.impl.extractResources(externalResourcesDirectory);
}
}
From 875be24f018563e373e3da5452e4ea725c6108fa Mon Sep 17 00:00:00 2001
From: Danilo Ansaloni
Date: Tue, 4 Mar 2025 20:29:50 +0100
Subject: [PATCH 15/51] Release GraalVM 24.2.0.
---
mx.graalpython/suite.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mx.graalpython/suite.py b/mx.graalpython/suite.py
index 8cc53b105a..16abd25b65 100644
--- a/mx.graalpython/suite.py
+++ b/mx.graalpython/suite.py
@@ -11,7 +11,7 @@
"version": "24.2.0",
"graalpython:pythonVersion": "3.11.7",
- "release": False,
+ "release": True,
"groupId": "org.graalvm.python",
"url": "http://www.graalvm.org/python",
From 0d0fb1665a3a9451276accb3d665ed5800329eb3 Mon Sep 17 00:00:00 2001
From: Danilo Ansaloni
Date: Tue, 4 Mar 2025 20:30:23 +0100
Subject: [PATCH 16/51] Start 24.2.1 dev cycle.
---
ci.jsonnet | 2 +-
.../com.oracle.graal.python.test.integration/pom.xml | 2 +-
.../src/tests/standalone/gradle/build/build.gradle | 2 +-
.../tests/standalone/gradle/build/build.gradle.kts | 2 +-
.../src/tests/standalone/jbang/EmptyPIPComments.j | 2 +-
.../standalone/jbang/EmptyPythonResourceComment.j | 2 +-
.../jbang/EmptyPythonResourceCommentWithBlanks.j | 2 +-
.../tests/standalone/jbang/NoPackagesResourcesDir.j | 2 +-
.../standalone/jbang/TwoPythonResourceComments.j | 2 +-
graalpython/graalpy-archetype-polyglot-app/pom.xml | 2 +-
.../src/main/resources/archetype-resources/pom.xml | 2 +-
graalpython/graalpy-jbang/examples/hello.java | 2 +-
.../templates/graalpy-template.java.qute | 2 +-
.../templates/graalpy-template_local_repo.java.qute | 2 +-
graalpython/graalpy-maven-plugin/pom.xml | 4 ++--
mx.graalpython/suite.py | 12 ++++++------
16 files changed, 22 insertions(+), 22 deletions(-)
diff --git a/ci.jsonnet b/ci.jsonnet
index a3a4e1743e..7d5f235fe3 100644
--- a/ci.jsonnet
+++ b/ci.jsonnet
@@ -1 +1 @@
-{ "overlay": "585265d3c6bafc1d12054374377589b360307957" }
+{ "overlay": "16d0e566573ebdcf380bf6f309c02724baf4172b" }
diff --git a/graalpython/com.oracle.graal.python.test.integration/pom.xml b/graalpython/com.oracle.graal.python.test.integration/pom.xml
index 0f55209ba9..6251cedd21 100644
--- a/graalpython/com.oracle.graal.python.test.integration/pom.xml
+++ b/graalpython/com.oracle.graal.python.test.integration/pom.xml
@@ -64,7 +64,7 @@ Additionally, one can change the polyglot artifacts version with
17
17
UTF-8
- 24.2.0
+ 24.2.1
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/standalone/gradle/build/build.gradle b/graalpython/com.oracle.graal.python.test/src/tests/standalone/gradle/build/build.gradle
index 15c3c89c12..2dfdd3f5ce 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/standalone/gradle/build/build.gradle
+++ b/graalpython/com.oracle.graal.python.test/src/tests/standalone/gradle/build/build.gradle
@@ -1,6 +1,6 @@
plugins {
id "application"
- id 'org.graalvm.python' version '24.2.0'
+ id 'org.graalvm.python' version '24.2.1'
id "org.graalvm.buildtools.native" version "0.10.2"
}
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/standalone/gradle/build/build.gradle.kts b/graalpython/com.oracle.graal.python.test/src/tests/standalone/gradle/build/build.gradle.kts
index a086b6635e..8ccf16421d 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/standalone/gradle/build/build.gradle.kts
+++ b/graalpython/com.oracle.graal.python.test/src/tests/standalone/gradle/build/build.gradle.kts
@@ -1,6 +1,6 @@
plugins {
application
- id("org.graalvm.python") version "24.2.0"
+ id("org.graalvm.python") version "24.2.1"
id("org.graalvm.buildtools.native") version "0.10.2"
}
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPIPComments.j b/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPIPComments.j
index 6b140a59b8..08561a0c15 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPIPComments.j
+++ b/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPIPComments.j
@@ -1,6 +1,6 @@
///usr/bin/env jbang "$0" "$@" ; exit $?
-//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.0}
+//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.1}
//PIP
// one blank after PIP
//PIP
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPythonResourceComment.j b/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPythonResourceComment.j
index 768e188e9e..31330e96fd 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPythonResourceComment.j
+++ b/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPythonResourceComment.j
@@ -1,6 +1,6 @@
///usr/bin/env jbang "$0" "$@" ; exit $?
-//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.0}
+//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.1}
//PYTHON_RESOURCES_DIRECTORY
public class EmptyPythonResourceComment {
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPythonResourceCommentWithBlanks.j b/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPythonResourceCommentWithBlanks.j
index f4b7556997..6f71f88213 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPythonResourceCommentWithBlanks.j
+++ b/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/EmptyPythonResourceCommentWithBlanks.j
@@ -1,6 +1,6 @@
///usr/bin/env jbang "$0" "$@" ; exit $?
-//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.0}
+//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.1}
// resource dir with blanks
//PYTHON_RESOURCES_DIRECTORY
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/NoPackagesResourcesDir.j b/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/NoPackagesResourcesDir.j
index 749ae89606..24a4866b26 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/NoPackagesResourcesDir.j
+++ b/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/NoPackagesResourcesDir.j
@@ -1,6 +1,6 @@
///usr/bin/env jbang "$0" "$@" ; exit $?
-//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.0}
+//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.1}
//PYTHON_RESOURCES_DIRECTORY python-resources
public class NoPackagesResourcesDir {
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/TwoPythonResourceComments.j b/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/TwoPythonResourceComments.j
index c2d902d358..ab31f0a738 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/TwoPythonResourceComments.j
+++ b/graalpython/com.oracle.graal.python.test/src/tests/standalone/jbang/TwoPythonResourceComments.j
@@ -1,6 +1,6 @@
///usr/bin/env jbang "$0" "$@" ; exit $?
-//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.0}
+//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.1}
//PYTHON_RESOURCES_DIRECTORY
//PYTHON_RESOURCES_DIRECTORY
diff --git a/graalpython/graalpy-archetype-polyglot-app/pom.xml b/graalpython/graalpy-archetype-polyglot-app/pom.xml
index 04b27f55e3..e525172eb1 100644
--- a/graalpython/graalpy-archetype-polyglot-app/pom.xml
+++ b/graalpython/graalpy-archetype-polyglot-app/pom.xml
@@ -45,7 +45,7 @@ SOFTWARE.
org.graalvm.python
graalpy-archetype-polyglot-app
- 24.2.0
+ 24.2.1
http://www.graalvm.org/python
Maven archetype providing a skeleton GraalPy - Java polyglot application.
maven-archetype
diff --git a/graalpython/graalpy-archetype-polyglot-app/src/main/resources/archetype-resources/pom.xml b/graalpython/graalpy-archetype-polyglot-app/src/main/resources/archetype-resources/pom.xml
index 90be4e32ca..e67d93e879 100644
--- a/graalpython/graalpy-archetype-polyglot-app/src/main/resources/archetype-resources/pom.xml
+++ b/graalpython/graalpy-archetype-polyglot-app/src/main/resources/archetype-resources/pom.xml
@@ -10,7 +10,7 @@
#set( $symbol_dollar = '$' )
- 24.2.0
+ 24.2.1
python-community
0.10.4
17
diff --git a/graalpython/graalpy-jbang/examples/hello.java b/graalpython/graalpy-jbang/examples/hello.java
index b005158ef6..11049392fc 100644
--- a/graalpython/graalpy-jbang/examples/hello.java
+++ b/graalpython/graalpy-jbang/examples/hello.java
@@ -40,7 +40,7 @@
*/
///usr/bin/env jbang "$0" "$@" ; exit $?
//JAVA 17+
-//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.0}
+//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.1}
// specify python packages and their versions as if used with pip
//PIP termcolor==2.2
diff --git a/graalpython/graalpy-jbang/templates/graalpy-template.java.qute b/graalpython/graalpy-jbang/templates/graalpy-template.java.qute
index 5a61e3dea9..9a94477922 100644
--- a/graalpython/graalpy-jbang/templates/graalpy-template.java.qute
+++ b/graalpython/graalpy-jbang/templates/graalpy-template.java.qute
@@ -5,7 +5,7 @@
{/for}
{#if dependencies.isEmpty()}// //DEPS {/if}
{|
-//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.0}
+//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.1}
// specify python packages and their versions as if used with pip
//PIP termcolor==2.2
|}
diff --git a/graalpython/graalpy-jbang/templates/graalpy-template_local_repo.java.qute b/graalpython/graalpy-jbang/templates/graalpy-template_local_repo.java.qute
index 2fb3914dc1..6b41f4e288 100644
--- a/graalpython/graalpy-jbang/templates/graalpy-template_local_repo.java.qute
+++ b/graalpython/graalpy-jbang/templates/graalpy-template_local_repo.java.qute
@@ -8,7 +8,7 @@
//REPOS mc=https://repo1.maven.org/maven2/
//REPOS local=file://{path_to_local_repo}
{|
-//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.0}
+//DEPS org.graalvm.python:jbang:${env.GRAALPY_VERSION:24.2.1}
// specify python packages and their versions as if used with pip
//PIP termcolor==2.2
|}
diff --git a/graalpython/graalpy-maven-plugin/pom.xml b/graalpython/graalpy-maven-plugin/pom.xml
index 4838e2cec7..5a8fe1acde 100644
--- a/graalpython/graalpy-maven-plugin/pom.xml
+++ b/graalpython/graalpy-maven-plugin/pom.xml
@@ -48,7 +48,7 @@ SOFTWARE.
graalpy-maven-plugin
maven-plugin
- 24.2.0
+ 24.2.1
http://www.graalvm.org/python
graalpy-maven-plugin
Handles python related resources in a maven GraalPy - Java polyglot application.
@@ -57,7 +57,7 @@ SOFTWARE.
17
17
UTF-8
- 24.2.0
+ 24.2.1
diff --git a/mx.graalpython/suite.py b/mx.graalpython/suite.py
index 16abd25b65..af58122c58 100644
--- a/mx.graalpython/suite.py
+++ b/mx.graalpython/suite.py
@@ -9,9 +9,9 @@
"name": "graalpython",
"versionConflictResolution": "latest",
- "version": "24.2.0",
+ "version": "24.2.1",
"graalpython:pythonVersion": "3.11.7",
- "release": True,
+ "release": False,
"groupId": "org.graalvm.python",
"url": "http://www.graalvm.org/python",
@@ -45,7 +45,7 @@
},
{
"name": "sdk",
- "version": "826d284d76d4e3c2379e952824f4ab7e96c805ee",
+ "version": "c9096be682f7aa67f5133fb098762e2152ff355f",
"subdir": True,
"urls": [
{"url": "https://github.com/oracle/graal", "kind": "git"},
@@ -53,7 +53,7 @@
},
{
"name": "tools",
- "version": "826d284d76d4e3c2379e952824f4ab7e96c805ee",
+ "version": "c9096be682f7aa67f5133fb098762e2152ff355f",
"subdir": True,
"urls": [
{"url": "https://github.com/oracle/graal", "kind": "git"},
@@ -61,7 +61,7 @@
},
{
"name": "sulong",
- "version": "826d284d76d4e3c2379e952824f4ab7e96c805ee",
+ "version": "c9096be682f7aa67f5133fb098762e2152ff355f",
"subdir": True,
"urls": [
{"url": "https://github.com/oracle/graal", "kind": "git"},
@@ -69,7 +69,7 @@
},
{
"name": "regex",
- "version": "826d284d76d4e3c2379e952824f4ab7e96c805ee",
+ "version": "c9096be682f7aa67f5133fb098762e2152ff355f",
"subdir": True,
"urls": [
{"url": "https://github.com/oracle/graal", "kind": "git"},
From 10573cbf474ce2981d7114bc0f90ced4aaaf9dfa Mon Sep 17 00:00:00 2001
From: Tim Felgentreff
Date: Thu, 20 Mar 2025 11:42:01 +0100
Subject: [PATCH 17/51] Pass NULL instead of None as arg to METHNOARGS
functions
(cherry picked from commit 935e46a1e7f5ed7e965407ccbdcf26fe35a6cc9e)
---
.../builtins/objects/cext/capi/ExternalFunctionNodes.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/ExternalFunctionNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/ExternalFunctionNodes.java
index 18528ad4a6..8d236077eb 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/ExternalFunctionNodes.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/ExternalFunctionNodes.java
@@ -1309,7 +1309,7 @@ public MethNoargsRoot(PythonLanguage language, TruffleString name, boolean isSta
@Override
protected Object[] prepareCArguments(VirtualFrame frame) {
- return new Object[]{readSelf(frame), PNone.NONE};
+ return new Object[]{readSelf(frame), PNone.NO_VALUE};
}
@Override
From 11936fb04188f8ab0b75d6b09379baa934cc701a Mon Sep 17 00:00:00 2001
From: Tim Felgentreff
Date: Thu, 20 Mar 2025 11:58:24 +0100
Subject: [PATCH 18/51] Support calling PyType_Modified on any Python class
(cherry picked from commit cef2e89e85d4d8681092968c477574153b3fd9e7)
---
.../modules/cext/PythonCextTypeBuiltins.java | 24 +++++++++++--------
1 file changed, 14 insertions(+), 10 deletions(-)
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextTypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextTypeBuiltins.java
index eea71e9ebd..a7e76df0a2 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextTypeBuiltins.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextTypeBuiltins.java
@@ -228,20 +228,24 @@ static Object doIt(PythonAbstractNativeObject clazz,
@CApiBuiltin(ret = ArgDescriptor.Void, args = {PyTypeObject}, call = Direct)
abstract static class PyType_Modified extends CApiUnaryBuiltinNode {
-
@TruffleBoundary
@Specialization
- static Object doIt(PythonAbstractNativeObject clazz,
+ static Object doIt(PythonAbstractClass object,
@Bind("this") Node inliningTarget) {
- PythonContext context = PythonContext.get(inliningTarget);
- CyclicAssumption nativeClassStableAssumption = context.getNativeClassStableAssumption(clazz, false);
- if (nativeClassStableAssumption != null) {
- nativeClassStableAssumption.invalidate("PyType_Modified(\"" + TypeNodes.GetNameNode.executeUncached(clazz).toJavaStringUncached() + "\") called");
+ if (object instanceof PythonAbstractNativeObject clazz) {
+ PythonContext context = PythonContext.get(inliningTarget);
+ CyclicAssumption nativeClassStableAssumption = context.getNativeClassStableAssumption(clazz, false);
+ if (nativeClassStableAssumption != null) {
+ nativeClassStableAssumption.invalidate("PyType_Modified(\"" + TypeNodes.GetNameNode.executeUncached(clazz).toJavaStringUncached() + "\") called");
+ }
+ MroSequenceStorage mroStorage = TypeNodes.GetMroStorageNode.executeUncached(clazz);
+ mroStorage.lookupChanged();
+ // Reload slots from native, which also invalidates cached slot lookups
+ clazz.setTpSlots(TpSlots.fromNative(clazz, context));
+ } else {
+ MroSequenceStorage mroStorage = TypeNodes.GetMroStorageNode.executeUncached(object);
+ mroStorage.lookupChanged();
}
- MroSequenceStorage mroStorage = TypeNodes.GetMroStorageNode.executeUncached(clazz);
- mroStorage.lookupChanged();
- // Reload slots from native, which also invalidates cached slot lookups
- clazz.setTpSlots(TpSlots.fromNative(clazz, context));
return PNone.NO_VALUE;
}
}
From 9b12f6854fd3f5e09448603a8c36293c8f769ee2 Mon Sep 17 00:00:00 2001
From: Tim Felgentreff
Date: Thu, 20 Mar 2025 13:30:40 +0100
Subject: [PATCH 19/51] Enable PyUnicode_DecodeRawUnicodeEscape
(cherry picked from commit e36f7d45604e1aad0678cf43964958022dbb001d)
---
.../com.oracle.graal.python.cext/src/unicodeobject.c | 9 +++++----
.../python/builtins/objects/cext/capi/CApiFunction.java | 2 +-
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/graalpython/com.oracle.graal.python.cext/src/unicodeobject.c b/graalpython/com.oracle.graal.python.cext/src/unicodeobject.c
index 42699b743a..852906637e 100644
--- a/graalpython/com.oracle.graal.python.cext/src/unicodeobject.c
+++ b/graalpython/com.oracle.graal.python.cext/src/unicodeobject.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, 2024, Oracle and/or its affiliates.
+/* Copyright (c) 2018, 2025, Oracle and/or its affiliates.
* Copyright (C) 1996-2020 Python Software Foundation
*
* Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
@@ -6220,16 +6220,17 @@ _PyUnicode_DecodeRawUnicodeEscapeStateful(const char *s,
Py_XDECREF(exc);
return NULL;
}
-
+#endif // GraalPy change
PyObject *
PyUnicode_DecodeRawUnicodeEscape(const char *s,
Py_ssize_t size,
const char *errors)
{
- return _PyUnicode_DecodeRawUnicodeEscapeStateful(s, size, errors, NULL);
+ return PyUnicode_Decode(s, size, "raw_unicode_escape", errors);
+ // return _PyUnicode_DecodeRawUnicodeEscapeStateful(s, size, errors, NULL);
}
-
+#if 0 // GraalPy change
PyObject *
PyUnicode_AsRawUnicodeEscapeString(PyObject *unicode)
{
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiFunction.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiFunction.java
index 5909dc1427..ae89ccf769 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiFunction.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiFunction.java
@@ -504,6 +504,7 @@ public final class CApiFunction {
@CApiBuiltin(name = "PyUnicode_DecodeLatin1", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, ConstCharPtrAsTruffleString}, call = CImpl)
@CApiBuiltin(name = "PyUnicode_DecodeLocale", ret = PyObject, args = {ConstCharPtrAsTruffleString, ConstCharPtrAsTruffleString}, call = CImpl)
@CApiBuiltin(name = "PyUnicode_DecodeLocaleAndSize", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, ConstCharPtrAsTruffleString}, call = CImpl)
+ @CApiBuiltin(name = "PyUnicode_DecodeRawUnicodeEscape", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, ConstCharPtrAsTruffleString}, call = CImpl)
@CApiBuiltin(name = "PyUnicode_DecodeUTF16", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, ConstCharPtrAsTruffleString, INT_LIST}, call = CImpl)
@CApiBuiltin(name = "PyUnicode_DecodeUTF16Stateful", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, ConstCharPtrAsTruffleString, INT_LIST, PY_SSIZE_T_PTR}, call = CImpl)
@CApiBuiltin(name = "PyUnicode_DecodeUTF32", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, ConstCharPtrAsTruffleString, INT_LIST}, call = CImpl)
@@ -942,7 +943,6 @@ public final class CApiFunction {
@CApiBuiltin(name = "PyUnicode_BuildEncodingMap", ret = PyObject, args = {PyObject}, call = NotImplemented)
@CApiBuiltin(name = "PyUnicode_CopyCharacters", ret = Py_ssize_t, args = {PyObject, Py_ssize_t, PyObject, Py_ssize_t, Py_ssize_t}, call = NotImplemented)
@CApiBuiltin(name = "PyUnicode_DecodeCharmap", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, PyObject, ConstCharPtrAsTruffleString}, call = NotImplemented)
- @CApiBuiltin(name = "PyUnicode_DecodeRawUnicodeEscape", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, ConstCharPtrAsTruffleString}, call = NotImplemented)
@CApiBuiltin(name = "PyUnicode_DecodeUTF7", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, ConstCharPtrAsTruffleString}, call = NotImplemented)
@CApiBuiltin(name = "PyUnicode_DecodeUTF7Stateful", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, ConstCharPtrAsTruffleString, PY_SSIZE_T_PTR}, call = NotImplemented)
@CApiBuiltin(name = "PyUnicode_DecodeUnicodeEscape", ret = PyObject, args = {ConstCharPtrAsTruffleString, Py_ssize_t, ConstCharPtrAsTruffleString}, call = NotImplemented)
From dc7165228972aa20e2edd533e02ddebd6cffa833 Mon Sep 17 00:00:00 2001
From: Tim Felgentreff
Date: Fri, 21 Mar 2025 06:31:18 +0100
Subject: [PATCH 20/51] Add patch to install pymupdf
(cherry picked from commit 98e11fb717901205a4d3a25b4307afe6c7eafa52)
---
.../modules/cext/PythonCextTypeBuiltins.java | 2 +-
.../objects/cext/capi/CApiFunction.java | 2 +-
.../cext/capi/ExternalFunctionNodes.java | 2 +-
.../lib-graalpython/patches/metadata.toml | 9 ++
.../lib-graalpython/patches/pymupdf.patch | 124 ++++++++++++++++++
mx.graalpython/verify_patches.py | 3 +-
6 files changed, 138 insertions(+), 4 deletions(-)
create mode 100644 graalpython/lib-graalpython/patches/pymupdf.patch
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextTypeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextTypeBuiltins.java
index a7e76df0a2..a997a8a2aa 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextTypeBuiltins.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextTypeBuiltins.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiFunction.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiFunction.java
index ae89ccf769..97ad1090b1 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiFunction.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiFunction.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/ExternalFunctionNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/ExternalFunctionNodes.java
index 8d236077eb..3111ccef04 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/ExternalFunctionNodes.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/ExternalFunctionNodes.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
diff --git a/graalpython/lib-graalpython/patches/metadata.toml b/graalpython/lib-graalpython/patches/metadata.toml
index ac1ccb7262..2d414e4baa 100644
--- a/graalpython/lib-graalpython/patches/metadata.toml
+++ b/graalpython/lib-graalpython/patches/metadata.toml
@@ -476,6 +476,15 @@ version = ">= 4.8.0"
patch = 'pymongo-4.8.0.patch'
license = 'Apache-2.0'
+[[PyMuPDF.rules]]
+version = "== 1.25.4"
+patch = "pymupdf.patch"
+# That project is AGPL, so do not actually include *any* code of pymupdf in the patch, not even an
+# empty line, in the diff context. The code we write in the patch is UPL - that is compatible with
+# AGPL in the sense that if someone were to apply it and distribute *that*, our patch is now part
+# of the AGPL'd codebase
+license = 'UPL'
+
[[pyOpenSSL.rules]]
# Pin this version to avoid pulling newer cryptography than we have patch for
version = "== 23.2.0"
diff --git a/graalpython/lib-graalpython/patches/pymupdf.patch b/graalpython/lib-graalpython/patches/pymupdf.patch
new file mode 100644
index 0000000000..27869eccd6
--- /dev/null
+++ b/graalpython/lib-graalpython/patches/pymupdf.patch
@@ -0,0 +1,124 @@
+diff --git a/graalpy-config b/graalpy-config
+new file mode 100755
+index 00000000..1f69f726
+--- /dev/null
++++ b/graalpy-config
+@@ -0,0 +1,78 @@
++#!/bin/sh
++
++# Adapted from CPython but deferring to GraalPy
++
++exit_with_usage ()
++{
++ echo "Usage: $0 --prefix|--exec-prefix|--includes|--libs|--cflags|--ldflags|--extension-suffix|--help|--abiflags|--configdir|--embed"
++ exit $1
++}
++
++if [ "$1" = "" ] ; then
++ exit_with_usage 1
++fi
++
++# Returns the actual prefix where this script was installed to.
++EXE=$(cd $(dirname "$0") && pwd -P)
++if which readlink >/dev/null 2>&1 ; then
++ if readlink -f "$RESULT" >/dev/null 2>&1; then
++ EXE=$(readlink -f "$RESULT")
++ fi
++fi
++EXE=$EXE/graalpy
++
++if ! test -x "$EXE" ; then
++ EXE=graalpy
++fi
++
++# Scan for --help or unknown argument.
++for ARG in $*
++do
++ case $ARG in
++ --help)
++ exit_with_usage 0
++ ;;
++ --embed)
++ echo "graalpy-config does not print embedding flags"
++ exit 1
++ ;;
++ --prefix|--exec-prefix|--includes|--libs|--cflags|--ldflags|--extension-suffix|--abiflags|--configdir)
++ ;;
++ *)
++ exit_with_usage 1
++ ;;
++ esac
++done
++
++for ARG in "$@"
++do
++ case "$ARG" in
++ --prefix)
++ $EXE -c "print(__import__('sysconfig').get_config_var('prefix'))"
++ ;;
++ --exec-prefix)
++ $EXE -c "print(__import__('sysconfig').get_config_var('exec_prefix'))"
++ ;;
++ --includes)
++ $EXE -c "from sysconfig import get_path; print('-I'+get_path('include'), '-I'+get_path('platinclude'))"
++ ;;
++ --cflags)
++ $EXE -c "import sysconfig as s; print('-I' + s.get_path('include'), '-I' + s.get_path('platinclude'), s.get_config_var('CFLAGS').replace('NDEBUG', 'DEBUG'), s.get_config_var('OPT').replace('NDEBUG', 'DEBUG'))"
++ ;;
++ --libs)
++ $EXE -c "import sysconfig as s; print('-L' + s.get_config_var('LIBDIR'))"
++ ;;
++ --ldflags)
++ $EXE -c "import sysconfig as s; print('-L' + s.get_config_var('LIBDIR'))"
++ ;;
++ --extension-suffix)
++ $EXE -c "import sysconfig as s; print(s.get_config_var('EXT_SUFFIX'))"
++ ;;
++ --abiflags)
++ $EXE -c "import sysconfig as s; print(s.get_config_var('ABIFLAGS'))"
++ ;;
++ --configdir)
++ echo ""
++ ;;
++esac
++done
+diff --git a/setup.py b/setup.py
+index 5fba2c97..3fe63b07 100755
+--- a/setup.py
++++ b/setup.py
+@@ -1452,0 +1452,35 @@
++if sys.implementation.name == "graalpy":
++ import os
++ import re
++ import subprocess
++ import shutil
++ import sysconfig
++ from pathlib import Path
++
++ def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
++ wheel_directory = Path(wheel_directory).absolute()
++ sdir = Path(__file__).absolute().parent
++ python311 = shutil.which("python3.11")
++ if not python311:
++ raise RuntimeError("python3.11 must be available on the PATH for cross-compilation")
++ env = os.environ.copy()
++ env["PIPCL_PYTHON_CONFIG"] = str(sdir / "graalpy-config")
++ env["PYMUPDF_SETUP_PY_LIMITED_API"] = "1"
++ subprocess.run(
++ [python311, "setup.py", "bdist_wheel"],
++ env=env,
++ cwd=sdir,
++ check=True,
++ )
++ wheels = list((sdir / 'dist').glob('*.whl'))
++ assert len(wheels) == 1, f"Expected 1 wheel, found {len(wheels)}"
++ wheel = wheels[0]
++ assert "-cp311-abi3" in wheel.name, f"Expected wheel to be for CPython 3.11 ABI 3, got {wheel.name}"
++ graalpy_ext_suffix = sysconfig.get_config_var("EXT_SUFFIX")
++ m = re.match(r"\.graalpy(\d+[^\-]*)-(\d+)", sysconfig.get_config_var("EXT_SUFFIX"))
++ gpver = m[1]
++ cpver = m[2]
++ graalpy_wheel_tag = f"graalpy{cpver}-graalpy{gpver}_{cpver}_native"
++ name = wheel.name.replace("cp311-abi3", graalpy_wheel_tag)
++ shutil.copyfile(wheel, wheel_directory / name)
++ return str(name)
diff --git a/mx.graalpython/verify_patches.py b/mx.graalpython/verify_patches.py
index 1ebc371694..8aa4e84c10 100644
--- a/mx.graalpython/verify_patches.py
+++ b/mx.graalpython/verify_patches.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# The Universal Permissive License (UPL), Version 1.0
@@ -45,6 +45,7 @@
# Approved license identifiers in SPDX "short identifier" format
ALLOWED_LICENSES = {
+ 'UPL', # https://spdx.org/licenses/UPL-1.0.html
'MIT', # https://spdx.org/licenses/MIT.html
'BSD-3-Clause', # https://spdx.org/licenses/BSD-3-Clause.html
'BSD-2-Clause', # https://spdx.org/licenses/BSD-2-Clause.html
From beb30c8fc33209b7f33c523850df05c45d4ba891 Mon Sep 17 00:00:00 2001
From: Michael Simacek
Date: Mon, 10 Mar 2025 09:45:46 +0100
Subject: [PATCH 21/51] Skip time-dependent test
(cherry picked from commit 438997b0c0db5ec59f9944a13f6b5b061dd765f8)
---
.../src/tests/unittest_tags/test_strptime.txt | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_strptime.txt b/graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_strptime.txt
index 019ffaf499..220ef38651 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_strptime.txt
+++ b/graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_strptime.txt
@@ -35,7 +35,8 @@ test.test_strptime.StrptimeTests.test_percent @ darwin-arm64,darwin-x86_64,linux
test.test_strptime.StrptimeTests.test_second @ darwin-arm64,darwin-x86_64,linux-aarch64,linux-x86_64,win32-AMD64
test.test_strptime.StrptimeTests.test_strptime_exception_context @ darwin-arm64,darwin-x86_64,linux-aarch64,linux-x86_64,win32-AMD64
test.test_strptime.StrptimeTests.test_time @ darwin-arm64,darwin-x86_64,linux-aarch64,linux-x86_64,win32-AMD64
-test.test_strptime.StrptimeTests.test_timezone @ darwin-arm64,darwin-x86_64,win32-AMD64
+# Seems to be dependent on the actual time/date/timezone of the machine, at least on GraalPy. Needs investigation
+!test.test_strptime.StrptimeTests.test_timezone
test.test_strptime.StrptimeTests.test_unconverteddata @ darwin-arm64,darwin-x86_64,linux-aarch64,linux-x86_64,win32-AMD64
test.test_strptime.StrptimeTests.test_year @ darwin-arm64,darwin-x86_64,linux-aarch64,linux-x86_64,win32-AMD64
test.test_strptime.TimeRETests.test_blankpattern @ darwin-arm64,darwin-x86_64,linux-aarch64,linux-x86_64,win32-AMD64
From abd391210a10593c7e35c132a2894dcfe8755798 Mon Sep 17 00:00:00 2001
From: Marouane El Hallaoui
Date: Wed, 2 Apr 2025 18:58:53 +0000
Subject: [PATCH 22/51] release GraalVM 24.2.1
---
mx.graalpython/suite.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mx.graalpython/suite.py b/mx.graalpython/suite.py
index af58122c58..05c541dd3e 100644
--- a/mx.graalpython/suite.py
+++ b/mx.graalpython/suite.py
@@ -11,7 +11,7 @@
"version": "24.2.1",
"graalpython:pythonVersion": "3.11.7",
- "release": False,
+ "release": True,
"groupId": "org.graalvm.python",
"url": "http://www.graalvm.org/python",
From 7d196446914364f49ebff17434d0ccd10753df5e Mon Sep 17 00:00:00 2001
From: Marouane El Hallaoui
Date: Mon, 14 Apr 2025 18:13:56 +0100
Subject: [PATCH 23/51] new dev cycle GraalVM 24.2.2
---
mx.graalpython/suite.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/mx.graalpython/suite.py b/mx.graalpython/suite.py
index 05c541dd3e..d4269ffd74 100644
--- a/mx.graalpython/suite.py
+++ b/mx.graalpython/suite.py
@@ -9,9 +9,9 @@
"name": "graalpython",
"versionConflictResolution": "latest",
- "version": "24.2.1",
+ "version": "24.2.2",
"graalpython:pythonVersion": "3.11.7",
- "release": True,
+ "release": False,
"groupId": "org.graalvm.python",
"url": "http://www.graalvm.org/python",
From 8e20788b127d9480f2c95669073ad96089c947d0 Mon Sep 17 00:00:00 2001
From: Tim Felgentreff
Date: Fri, 11 Apr 2025 16:09:02 +0200
Subject: [PATCH 24/51] Use paatch to apply patches the same way across all
platforms
(cherry picked from commit 8ac74ecd42a94ae406805702d0d9cfb28cb675fe)
---
scripts/wheelbuilder/build_wheels.py | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/scripts/wheelbuilder/build_wheels.py b/scripts/wheelbuilder/build_wheels.py
index 605032e50d..01aaf0eafd 100644
--- a/scripts/wheelbuilder/build_wheels.py
+++ b/scripts/wheelbuilder/build_wheels.py
@@ -100,6 +100,13 @@ def create_venv():
subprocess.check_call([binary, "-m", "venv", "graalpy"])
print("Installing wheel with", pip, flush=True)
subprocess.check_call([pip, "install", "wheel"])
+<<<<<<< HEAD
+=======
+ print("Installing paatch to provide patch.exe", flush=True)
+ p = subprocess.run([pip, "install", "paatch"])
+ if p.returncode != 0:
+ print("Installing paatch failed, assuming a GNU patch compatible binary is on PATH", flush=True)
+>>>>>>> 8ac74ecd42 (Use paatch to apply patches the same way across all platforms)
return pip
From 4e02952d03cd234a3177433e9ed8c5ebe664f598 Mon Sep 17 00:00:00 2001
From: Tim Felgentreff
Date: Sat, 12 Apr 2025 13:58:32 +0200
Subject: [PATCH 25/51] Fix our implementation of Py_Is
(cherry picked from commit 37cb91a751be8b8af2eb89a288f4699b8c33ece3)
---
.../com.oracle.graal.python.cext/include/object.h | 4 +++-
graalpython/com.oracle.graal.python.cext/src/object.c | 5 +++++
.../modules/cext/PythonCextObjectBuiltins.java | 10 ++++++++++
3 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/graalpython/com.oracle.graal.python.cext/include/object.h b/graalpython/com.oracle.graal.python.cext/include/object.h
index 7d88c22cb1..a427c70040 100644
--- a/graalpython/com.oracle.graal.python.cext/include/object.h
+++ b/graalpython/com.oracle.graal.python.cext/include/object.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, 2024, Oracle and/or its affiliates.
+/* Copyright (c) 2018, 2025, Oracle and/or its affiliates.
* Copyright (C) 1996-2020 Python Software Foundation
*
* Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
@@ -124,7 +124,9 @@ typedef struct {
// Test if the 'x' object is the 'y' object, the same as "x is y" in Python.
PyAPI_FUNC(int) Py_Is(PyObject *x, PyObject *y);
+#if 0 // GraalPy change
#define Py_Is(x, y) ((x) == (y))
+#endif // GraalPy change
PyAPI_FUNC(Py_ssize_t) PyTruffle_REFCNT(PyObject *ob);
diff --git a/graalpython/com.oracle.graal.python.cext/src/object.c b/graalpython/com.oracle.graal.python.cext/src/object.c
index 9ad7908e8a..58c8a61de0 100644
--- a/graalpython/com.oracle.graal.python.cext/src/object.c
+++ b/graalpython/com.oracle.graal.python.cext/src/object.c
@@ -2507,7 +2507,12 @@ Py_XNewRef(PyObject *obj)
// for the stable ABI.
int Py_Is(PyObject *x, PyObject *y)
{
+#if 0 // GraalPy change
return (x == y);
+#else
+ return (x == y) ||
+ (points_to_py_handle_space(x) && points_to_py_handle_space(y) && GraalPyTruffle_Is(x, y));
+#endif
}
int Py_IsNone(PyObject *x)
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextObjectBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextObjectBuiltins.java
index 6ee8ff9172..ec99db57ea 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextObjectBuiltins.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextObjectBuiltins.java
@@ -129,6 +129,7 @@
import com.oracle.graal.python.nodes.classes.IsSubtypeNode;
import com.oracle.graal.python.nodes.object.GetClassNode;
import com.oracle.graal.python.nodes.object.GetOrCreateDictNode;
+import com.oracle.graal.python.nodes.object.IsNode;
import com.oracle.graal.python.nodes.util.CannotCastException;
import com.oracle.graal.python.nodes.util.CastToJavaStringNode;
import com.oracle.graal.python.nodes.util.CastToTruffleStringNode;
@@ -739,4 +740,13 @@ static Object getDict(Object object,
return getDict.execute(inliningTarget, object);
}
}
+
+ @CApiBuiltin(ret = Int, args = {PyObject, PyObject}, call = Ignored)
+ abstract static class PyTruffle_Is extends CApiBinaryBuiltinNode {
+ @Specialization
+ static int isTrue(Object a, Object b,
+ @Cached IsNode isNode) {
+ return isNode.execute(a, b) ? 1 : 0;
+ }
+ }
}
From 30f2a29ededfab81a5b57ee651d710c3132b79dc Mon Sep 17 00:00:00 2001
From: Tim Felgentreff
Date: Tue, 15 Apr 2025 12:39:08 +0200
Subject: [PATCH 26/51] Add patch for ormsgpack
(cherry picked from commit ede979ef46897134ef71f4ad52a1fa0e2d18fc24)
---
.../lib-graalpython/patches/metadata.toml | 5 +
.../patches/ormsgpack-1.8.0-1.9.1.patch | 364 ++++++++++++++++++
2 files changed, 369 insertions(+)
create mode 100644 graalpython/lib-graalpython/patches/ormsgpack-1.8.0-1.9.1.patch
diff --git a/graalpython/lib-graalpython/patches/metadata.toml b/graalpython/lib-graalpython/patches/metadata.toml
index 2d414e4baa..855e1f8831 100644
--- a/graalpython/lib-graalpython/patches/metadata.toml
+++ b/graalpython/lib-graalpython/patches/metadata.toml
@@ -337,6 +337,11 @@ version = '== 3.10.5'
patch = 'orjson-3.10.5.patch'
license = 'Apache-2.0 OR MIT'
+[[ormsgpack.rules]]
+version = '>= 1.8.0, <= 1.9.1'
+patch = 'ormsgpack-1.8.0-1.9.1.patch'
+license = 'Apache-2.0 OR MIT'
+
[[overrides.rules]]
version = '== 7.4.0'
# Important: This patch esentially breaks the package, it's not upstreamable. The package relies on bytecode parsing
diff --git a/graalpython/lib-graalpython/patches/ormsgpack-1.8.0-1.9.1.patch b/graalpython/lib-graalpython/patches/ormsgpack-1.8.0-1.9.1.patch
new file mode 100644
index 0000000000..3a9542a058
--- /dev/null
+++ b/graalpython/lib-graalpython/patches/ormsgpack-1.8.0-1.9.1.patch
@@ -0,0 +1,364 @@
+diff --git a/src/deserialize/deserializer.rs b/src/deserialize/deserializer.rs
+index 41cf7f1..99cd68e 100644
+--- a/src/deserialize/deserializer.rs
++++ b/src/deserialize/deserializer.rs
+@@ -292,7 +292,10 @@ impl<'de> Deserializer<'de> {
+ marker => Err(Error::InvalidType(marker)),
+ }?;
+ let value = self.deserialize()?;
++ #[cfg(not(GraalPy))]
+ let pyhash = unsafe { (*key.as_ptr().cast::()).hash };
++ #[cfg(GraalPy)]
++ let pyhash = unsafe { pyo3::ffi::PyObject_Hash(key.as_ptr()) };
+ let _ = ffi!(_PyDict_SetItem_KnownHash(
+ dict_ptr,
+ key.as_ptr(),
+@@ -471,7 +474,7 @@ impl<'de> Deserializer<'de> {
+ let ptr = ffi!(PyTuple_New(len as pyo3::ffi::Py_ssize_t));
+ for i in 0..len {
+ let elem = self.deserialize_map_key()?;
+- ffi!(PyTuple_SET_ITEM(
++ ffi!(PyTuple_SetItem(
+ ptr,
+ i as pyo3::ffi::Py_ssize_t,
+ elem.as_ptr()
+diff --git a/src/ext.rs b/src/ext.rs
+index b2573b4..9668d4f 100644
+--- a/src/ext.rs
++++ b/src/ext.rs
+@@ -22,7 +22,7 @@ unsafe extern "C" fn ext_new(
+ );
+ return null_mut();
+ }
+- let tag = PyTuple_GET_ITEM(args, 0);
++ let tag = PyTuple_GetItem(args, 0);
+ if PyLong_Check(tag) == 0 {
+ PyErr_SetString(
+ PyExc_TypeError,
+@@ -30,7 +30,7 @@ unsafe extern "C" fn ext_new(
+ );
+ return null_mut();
+ }
+- let data = PyTuple_GET_ITEM(args, 1);
++ let data = PyTuple_GetItem(args, 1);
+ if PyBytes_Check(data) == 0 {
+ PyErr_SetString(
+ PyExc_TypeError,
+diff --git a/src/ffi.rs b/src/ffi.rs
+index 4e5ddc3..20c9db4 100644
+--- a/src/ffi.rs
++++ b/src/ffi.rs
+@@ -7,13 +7,16 @@ use std::ptr::NonNull;
+ #[allow(non_snake_case)]
+ #[inline(always)]
+ pub unsafe fn PyBytes_AS_STRING(op: *mut PyObject) -> *const c_char {
+- &(*op.cast::()).ob_sval as *const c_char
++ #[cfg(not(any(PyPy, GraalPy, Py_LIMITED_API)))]
++ return &(*op.cast::()).ob_sval as *const c_char;
++ #[cfg(any(PyPy, GraalPy, Py_LIMITED_API))]
++ return crate::PyBytes_AsString(op);
+ }
+
+ #[allow(non_snake_case)]
+ #[inline(always)]
+ pub unsafe fn PyBytes_GET_SIZE(op: *mut PyObject) -> Py_ssize_t {
+- (*op.cast::()).ob_size
++ Py_SIZE(op)
+ }
+
+ #[repr(C)]
+@@ -63,11 +66,21 @@ pub fn pylong_is_positive(op: *mut PyObject) -> bool {
+ unsafe { (*(op as *mut PyLongObject)).long_value.lv_tag & SIGN_MASK == 0 }
+ }
+
+-#[cfg(not(Py_3_12))]
++#[cfg(not(any(Py_3_12, GraalPy)))]
+ pub fn pylong_is_positive(op: *mut PyObject) -> bool {
+ unsafe { (*(op as *mut PyVarObject)).ob_size > 0 }
+ }
+
++extern "C" {
++ #[cfg(not(PyPy))]
++ pub fn _PyLong_Sign(v: *mut PyObject) -> c_int;
++}
++
++#[cfg(GraalPy)]
++pub fn pylong_is_positive(op: *mut PyObject) -> bool {
++ unsafe { _PyLong_Sign(op) > 0 }
++}
++
+ pub struct PyDictIter {
+ op: *mut PyObject,
+ pos: isize,
+diff --git a/src/lib.rs b/src/lib.rs
+index f10b1c4..1a9768b 100644
+--- a/src/lib.rs
++++ b/src/lib.rs
+@@ -143,7 +143,7 @@ fn raise_unpackb_exception(msg: &str) -> *mut PyObject {
+ let err_msg =
+ PyUnicode_FromStringAndSize(msg.as_ptr() as *const c_char, msg.len() as isize);
+ let args = PyTuple_New(1);
+- PyTuple_SET_ITEM(args, 0, err_msg);
++ PyTuple_SetItem(args, 0, err_msg);
+ PyErr_SetObject(typeref::MsgpackDecodeError, args);
+ Py_DECREF(args);
+ };
+@@ -199,10 +199,10 @@ pub unsafe extern "C" fn unpackb(
+ if !kwnames.is_null() {
+ let tuple_size = PyTuple_GET_SIZE(kwnames);
+ for i in 0..tuple_size {
+- let arg = PyTuple_GET_ITEM(kwnames, i as Py_ssize_t);
+- if arg == typeref::EXT_HOOK {
++ let arg = PyTuple_GetItem(kwnames, i as Py_ssize_t);
++ if PyUnicode_Compare(arg, typeref::EXT_HOOK) == 0 {
+ ext_hook = Some(NonNull::new_unchecked(*args.offset(num_args + i)));
+- } else if arg == typeref::OPTION {
++ } else if PyUnicode_Compare(arg, typeref::OPTION) == 0 {
+ optsptr = Some(NonNull::new_unchecked(*args.offset(num_args + i)));
+ } else {
+ return raise_unpackb_exception("unpackb() got an unexpected keyword argument");
+@@ -247,15 +247,15 @@ pub unsafe extern "C" fn packb(
+ if !kwnames.is_null() {
+ let tuple_size = PyTuple_GET_SIZE(kwnames);
+ for i in 0..tuple_size {
+- let arg = PyTuple_GET_ITEM(kwnames, i as Py_ssize_t);
+- if arg == typeref::DEFAULT {
++ let arg = PyTuple_GetItem(kwnames, i as Py_ssize_t);
++ if PyUnicode_Compare(arg, typeref::DEFAULT) == 0 {
+ if unlikely!(default.is_some()) {
+ return raise_packb_exception(
+ "packb() got multiple values for argument: 'default'",
+ );
+ }
+ default = Some(NonNull::new_unchecked(*args.offset(num_args + i)));
+- } else if arg == typeref::OPTION {
++ } else if PyUnicode_Compare(arg, typeref::OPTION) == 0 {
+ if unlikely!(optsptr.is_some()) {
+ return raise_packb_exception(
+ "packb() got multiple values for argument: 'option'",
+diff --git a/src/serialize/datetime.rs b/src/serialize/datetime.rs
+index 63212d6..5ac2b2b 100644
+--- a/src/serialize/datetime.rs
++++ b/src/serialize/datetime.rs
+@@ -61,9 +61,14 @@ pub struct Time {
+
+ impl Time {
+ pub fn new(ptr: *mut pyo3::ffi::PyObject, opts: Opt) -> Result {
++ #[cfg(not(GraalPy))]
+ if unsafe { (*(ptr as *mut pyo3::ffi::PyDateTime_Time)).hastzinfo != 0 } {
+ return Err(TimeError::HasTimezone);
+ }
++ #[cfg(GraalPy)]
++ if unsafe { pyo3::ffi::PyDateTime_TIME_GET_TZINFO(ptr) != crate::typeref::NONE } {
++ return Err(TimeError::HasTimezone);
++ }
+ Ok(Time {
+ ptr: ptr,
+ opts: opts,
+@@ -114,23 +119,28 @@ impl std::fmt::Display for DateTimeError {
+ }
+
+ fn utcoffset(ptr: *mut pyo3::ffi::PyObject) -> Result {
++ #[cfg(not(GraalPy))]
+ if !unsafe { (*(ptr as *mut pyo3::ffi::PyDateTime_DateTime)).hastzinfo == 1 } {
+ return Ok(Offset::default());
+ }
+
+ let tzinfo = ffi!(PyDateTime_DATE_GET_TZINFO(ptr));
++ #[cfg(GraalPy)]
++ if unsafe { tzinfo == crate::typeref::NONE } {
++ return Ok(Offset::default());
++ }
+ let py_offset: *mut pyo3::ffi::PyObject;
+ if ffi!(PyObject_HasAttr(tzinfo, CONVERT_METHOD_STR)) == 1 {
+ // pendulum
+- py_offset = ffi!(PyObject_CallMethodNoArgs(ptr, UTCOFFSET_METHOD_STR));
++ py_offset = unsafe { pyo3::ffi::compat::PyObject_CallMethodNoArgs(ptr, UTCOFFSET_METHOD_STR) };
+ } else if ffi!(PyObject_HasAttr(tzinfo, NORMALIZE_METHOD_STR)) == 1 {
+ // pytz
+- let normalized = ffi!(PyObject_CallMethodOneArg(tzinfo, NORMALIZE_METHOD_STR, ptr));
+- py_offset = ffi!(PyObject_CallMethodNoArgs(normalized, UTCOFFSET_METHOD_STR));
++ let normalized = ffi!(PyObject_CallMethodObjArgs(tzinfo, NORMALIZE_METHOD_STR, ptr, std::ptr::null_mut::()));
++ py_offset = unsafe { pyo3::ffi::compat::PyObject_CallMethodNoArgs(normalized, UTCOFFSET_METHOD_STR) };
+ ffi!(Py_DECREF(normalized));
+ } else if ffi!(PyObject_HasAttr(tzinfo, DST_STR)) == 1 {
+ // dateutil/arrow, datetime.timezone.utc
+- py_offset = ffi!(PyObject_CallMethodOneArg(tzinfo, UTCOFFSET_METHOD_STR, ptr));
++ py_offset = ffi!(PyObject_CallMethodObjArgs(tzinfo, UTCOFFSET_METHOD_STR, ptr, std::ptr::null_mut::()));
+ } else {
+ return Err(DateTimeError::LibraryUnsupported);
+ }
+@@ -193,7 +203,10 @@ impl TimeLike for DateTime {
+
+ impl DateTimeLike for DateTime {
+ fn has_tz(&self) -> bool {
+- unsafe { (*(self.ptr as *mut pyo3::ffi::PyDateTime_DateTime)).hastzinfo == 1 }
++ #[cfg(not(GraalPy))]
++ return unsafe { (*(self.ptr as *mut pyo3::ffi::PyDateTime_DateTime)).hastzinfo == 1 };
++ #[cfg(GraalPy)]
++ return unsafe { pyo3::ffi::PyDateTime_TIME_GET_TZINFO(self.ptr) != crate::typeref::NONE };
+ }
+
+ fn offset(&self) -> Offset {
+diff --git a/src/serialize/numpy.rs b/src/serialize/numpy.rs
+index afc5cdf..4d007bd 100644
+--- a/src/serialize/numpy.rs
++++ b/src/serialize/numpy.rs
+@@ -392,8 +392,8 @@ impl NumpyDatetimeUnit {
+ fn from_pyobject(ptr: *mut PyObject) -> Self {
+ let dtype = ffi!(PyObject_GetAttr(ptr, DTYPE_STR));
+ let descr = ffi!(PyObject_GetAttr(dtype, DESCR_STR));
+- let el0 = ffi!(PyList_GET_ITEM(descr, 0));
+- let descr_str = ffi!(PyTuple_GET_ITEM(el0, 1));
++ let el0 = ffi!(PyList_GetItem(descr, 0));
++ let descr_str = ffi!(PyTuple_GetItem(el0, 1));
+ let uni = crate::unicode::unicode_to_str(descr_str).unwrap();
+ if uni.len() < 5 {
+ return Self::NaT;
+diff --git a/src/serialize/serializer.rs b/src/serialize/serializer.rs
+index 309e6e1..6f7dec7 100644
+--- a/src/serialize/serializer.rs
++++ b/src/serialize/serializer.rs
+@@ -864,7 +864,7 @@ impl Serialize for DictTupleKey {
+ let len = ffi!(PyTuple_GET_SIZE(self.ptr)) as usize;
+ let mut seq = serializer.serialize_seq(Some(len)).unwrap();
+ for i in 0..len {
+- let item = ffi!(PyTuple_GET_ITEM(self.ptr, i as isize));
++ let item = ffi!(PyTuple_GetItem(self.ptr, i as isize));
+ let value = DictKey::new(item, self.opts, self.recursion + 1);
+ seq.serialize_element(&value)?;
+ }
+diff --git a/src/serialize/tuple.rs b/src/serialize/tuple.rs
+index fa81cb6..9b66019 100644
+--- a/src/serialize/tuple.rs
++++ b/src/serialize/tuple.rs
+@@ -41,7 +41,7 @@ impl Serialize for Tuple {
+ let len = ffi!(PyTuple_GET_SIZE(self.ptr)) as usize;
+ let mut seq = serializer.serialize_seq(Some(len)).unwrap();
+ for i in 0..len {
+- let item = ffi!(PyTuple_GET_ITEM(self.ptr, i as isize));
++ let item = ffi!(PyTuple_GetItem(self.ptr, i as isize));
+ let value = PyObject::new(
+ item,
+ self.opts,
+diff --git a/src/serialize/writer.rs b/src/serialize/writer.rs
+index a790bdd..35346d9 100644
+--- a/src/serialize/writer.rs
++++ b/src/serialize/writer.rs
+@@ -27,7 +27,6 @@ impl BytesWriter {
+ pub fn finish(&mut self) -> NonNull {
+ unsafe {
+ std::ptr::write(self.buffer_ptr(), 0);
+- (*self.bytes.cast::()).ob_size = self.len as Py_ssize_t;
+ self.resize(self.len);
+ NonNull::new_unchecked(self.bytes as *mut PyObject)
+ }
+@@ -35,10 +34,14 @@ impl BytesWriter {
+
+ fn buffer_ptr(&self) -> *mut u8 {
+ unsafe {
+- std::mem::transmute::<*mut [c_char; 1], *mut u8>(std::ptr::addr_of_mut!(
++ #[cfg(not(GraalPy))]
++ return std::mem::transmute::<*mut [c_char; 1], *mut u8>(std::ptr::addr_of_mut!(
+ (*self.bytes).ob_sval
+ ))
+- .add(self.len)
++ .add(self.len);
++ #[cfg(GraalPy)]
++ return std::mem::transmute::<*mut i8, *mut u8>(PyBytes_AsString(self.bytes.cast::()))
++ .add(self.len);
+ }
+ }
+
+diff --git a/src/unicode.rs b/src/unicode.rs
+index 53aca09..552fa6c 100644
+--- a/src/unicode.rs
++++ b/src/unicode.rs
+@@ -6,6 +6,7 @@ use pyo3::ffi::*;
+
+ // see unicodeobject.h for documentation
+
++#[cfg(not(GraalPy))]
+ pub fn unicode_from_str(buf: &str) -> *mut PyObject {
+ if buf.is_empty() {
+ ffi!(Py_INCREF(EMPTY_UNICODE));
+@@ -27,6 +28,13 @@ pub fn unicode_from_str(buf: &str) -> *mut PyObject {
+ }
+ }
+
++#[cfg(GraalPy)]
++pub fn unicode_from_str(buf: &str) -> *mut PyObject {
++ unsafe {
++ PyUnicode_FromStringAndSize(buf.as_ptr() as *const i8, buf.len() as isize)
++ }
++}
++
+ fn pyunicode_ascii(buf: &str) -> *mut PyObject {
+ unsafe {
+ let ptr = ffi!(PyUnicode_New(buf.len() as isize, 127));
+@@ -80,6 +88,7 @@ fn pyunicode_fourbyte(buf: &str, num_chars: usize) -> *mut PyObject {
+
+ #[inline]
+ pub fn hash_str(op: *mut PyObject) -> Py_hash_t {
++ #[cfg(not(GraalPy))]
+ unsafe {
+ let data_ptr: *mut c_void = if (*op.cast::()).compact() == 1
+ && (*op.cast::()).ascii() == 1
+@@ -92,7 +101,11 @@ pub fn hash_str(op: *mut PyObject) -> Py_hash_t {
+ (*(op as *mut PyASCIIObject)).length * ((*(op as *mut PyASCIIObject)).kind()) as isize;
+ let hash = _Py_HashBytes(data_ptr, num_bytes);
+ (*op.cast::()).hash = hash;
+- hash
++ return hash;
++ }
++ #[cfg(GraalPy)]
++ unsafe {
++ return PyObject_Hash(op);
+ }
+ }
+
+@@ -109,19 +122,24 @@ pub fn unicode_to_str_via_ffi(op: *mut PyObject) -> Option<&'static str> {
+
+ #[inline]
+ pub fn unicode_to_str(op: *mut PyObject) -> Option<&'static str> {
++ #[cfg(not(GraalPy))]
+ unsafe {
+ if unlikely!((*op.cast::()).compact() == 0) {
+- unicode_to_str_via_ffi(op)
++ return unicode_to_str_via_ffi(op);
+ } else if (*op.cast::()).ascii() == 1 {
+ let ptr = op.cast::().offset(1) as *const u8;
+ let len = (*op.cast::()).length as usize;
+- Some(str_from_slice!(ptr, len))
++ return Some(str_from_slice!(ptr, len));
+ } else if (*op.cast::()).utf8_length != 0 {
+ let ptr = (*op.cast::()).utf8 as *const u8;
+ let len = (*op.cast::()).utf8_length as usize;
+- Some(str_from_slice!(ptr, len))
++ return Some(str_from_slice!(ptr, len));
+ } else {
+- unicode_to_str_via_ffi(op)
++ return unicode_to_str_via_ffi(op);
+ }
+ }
++ #[cfg(GraalPy)]
++ unsafe {
++ return unicode_to_str_via_ffi(op);
++ }
+ }
+diff --git a/src/util.rs b/src/util.rs
+index 2bcc32d..89faf1a 100644
+--- a/src/util.rs
++++ b/src/util.rs
+@@ -8,7 +8,7 @@ macro_rules! py_is {
+
+ macro_rules! ob_type {
+ ($obj:expr) => {
+- unsafe { (*($obj as *mut pyo3::ffi::PyObject)).ob_type }
++ unsafe { pyo3::ffi::Py_TYPE($obj as *mut pyo3::ffi::PyObject) }
+ };
+ }
+
+--
+2.43.0
+
From df5ca5e74a7f721f3fdbba292891475febbf82e4 Mon Sep 17 00:00:00 2001
From: Ivo Horak
Date: Mon, 14 Apr 2025 09:02:48 +0200
Subject: [PATCH 27/51] Writing NO_VALUE to EconomicMap deletes the attribute
(cherry picked from commit 485278c2c3d62f9caa7993c582d1e52a2c56e1d2)
---
.../src/tests/test_dict.py | 10 +++++++
.../WriteAttributeToObjectNode.java | 29 +++++++++++++++++--
2 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_dict.py b/graalpython/com.oracle.graal.python.test/src/tests/test_dict.py
index c30e983979..67a226ec37 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/test_dict.py
+++ b/graalpython/com.oracle.graal.python.test/src/tests/test_dict.py
@@ -1267,3 +1267,13 @@ def test_dict_values_eq():
d1 = {1: 1, 2: 2, 4: 4}
assert d1.values() != d1.values()
+def test_removing_attr_from_economic_map():
+ class Test:
+ pass
+
+ o = Test()
+ o.foo = 1
+ o.__dict__[42] = 10
+ del o.foo
+
+ assert "foo" not in o.__dict__
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java
index 012300b2b4..5d55b08a1c 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java
@@ -50,6 +50,7 @@
import com.oracle.graal.python.builtins.objects.cext.structs.CFields;
import com.oracle.graal.python.builtins.objects.cext.structs.CStructAccess;
import com.oracle.graal.python.builtins.objects.common.HashingStorage;
+import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes;
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes.HashingStorageSetItem;
import com.oracle.graal.python.builtins.objects.dict.PDict;
import com.oracle.graal.python.builtins.objects.object.PythonObject;
@@ -188,7 +189,7 @@ private static boolean writeToDynamicStorageManagedClass(PythonManagedClass klas
}
// write to the dict: the basic specialization for non-classes
- @Specialization(guards = {"dict != null", "!isManagedClass(object)"})
+ @Specialization(guards = {"dict != null", "!isManagedClass(object)", "!isNoValue(value)"})
static boolean writeToDictNoType(@SuppressWarnings("unused") PythonObject object, TruffleString key, Object value,
@Bind("this") Node inliningTarget,
@SuppressWarnings("unused") @Shared("getDict") @Cached GetDictIfExistsNode getDict,
@@ -199,7 +200,7 @@ static boolean writeToDictNoType(@SuppressWarnings("unused") PythonObject object
}
// write to the dict & PythonManagedClass -> requires calling onAttributeUpdate
- @Specialization(guards = {"dict != null"})
+ @Specialization(guards = {"dict != null", "!isNoValue(value)"})
boolean writeToDictBuiltinType(PythonBuiltinClass klass, TruffleString key, Object value,
@Bind("this") Node inliningTarget,
@SuppressWarnings("unused") @Shared("getDict") @Cached GetDictIfExistsNode getDict,
@@ -216,7 +217,7 @@ boolean writeToDictBuiltinType(PythonBuiltinClass klass, TruffleString key, Obje
}
}
- @Specialization(guards = {"dict != null"})
+ @Specialization(guards = {"dict != null", "!isNoValue(value)"})
static boolean writeToDictClass(PythonClass klass, TruffleString key, Object value,
@Bind("this") Node inliningTarget,
@SuppressWarnings("unused") @Shared("getDict") @Cached GetDictIfExistsNode getDict,
@@ -229,6 +230,28 @@ static boolean writeToDictClass(PythonClass klass, TruffleString key, Object val
return writeToDictManagedClass(klass, dict, key, value, inliningTarget, callAttrUpdate, updateStorage, setHashingStorageItem, codePointLengthNode, codePointAtIndexNode);
}
+ @Specialization(guards = {"dict != null", "isNoValue(value)"})
+ static boolean deleteFromDict(PythonObject obj, TruffleString key, Object value,
+ @Bind("this") Node inliningTarget,
+ @SuppressWarnings("unused") @Shared("getDict") @Cached GetDictIfExistsNode getDict,
+ @Bind("getDict.execute(obj)") PDict dict,
+ @Shared("callAttrUpdate") @Cached InlinedBranchProfile callAttrUpdate,
+ @Cached HashingStorageNodes.HashingStorageDelItem hashingStorageDelItem,
+ @Shared("cpLen") @Cached TruffleString.CodePointLengthNode codePointLengthNode,
+ @Shared("cpAtIndex") @Cached TruffleString.CodePointAtIndexNode codePointAtIndexNode) {
+ try {
+ HashingStorage dictStorage = dict.getDictStorage();
+ return hashingStorageDelItem.execute(inliningTarget, dictStorage, key, dict);
+ } finally {
+ if (obj instanceof PythonManagedClass klass) {
+ if (!klass.canSkipOnAttributeUpdate(key, value, codePointLengthNode, codePointAtIndexNode)) {
+ callAttrUpdate.enter(inliningTarget);
+ klass.onAttributeUpdate(key, value);
+ }
+ }
+ }
+ }
+
private static boolean writeToDictManagedClass(PythonManagedClass klass, PDict dict, TruffleString key, Object value, Node inliningTarget,
InlinedBranchProfile callAttrUpdate, InlinedBranchProfile updateStorage, HashingStorageSetItem setHashingStorageItem, TruffleString.CodePointLengthNode codePointLengthNode,
TruffleString.CodePointAtIndexNode codePointAtIndexNode) {
From 59217366d984527b9cff2ce197e849c1c3bba854 Mon Sep 17 00:00:00 2001
From: Ivo Horak
Date: Mon, 14 Apr 2025 15:50:06 +0200
Subject: [PATCH 28/51] Adjusting the delete from attribute to cover
PythonBuiltinClass
(cherry picked from commit 054c3eb873fae3eb133a33a085af6ee202cbb727)
---
.../nodes/attributes/WriteAttributeToObjectNode.java | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java
index 5d55b08a1c..5304613b4f 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java
@@ -230,8 +230,8 @@ static boolean writeToDictClass(PythonClass klass, TruffleString key, Object val
return writeToDictManagedClass(klass, dict, key, value, inliningTarget, callAttrUpdate, updateStorage, setHashingStorageItem, codePointLengthNode, codePointAtIndexNode);
}
- @Specialization(guards = {"dict != null", "isNoValue(value)"})
- static boolean deleteFromDict(PythonObject obj, TruffleString key, Object value,
+ @Specialization(guards = {"dict != null", "isNoValue(value)", "!isPythonBuiltinClass(obj)"})
+ static boolean deleteFromPythonObject(PythonObject obj, TruffleString key, Object value,
@Bind("this") Node inliningTarget,
@SuppressWarnings("unused") @Shared("getDict") @Cached GetDictIfExistsNode getDict,
@Bind("getDict.execute(obj)") PDict dict,
@@ -252,6 +252,14 @@ static boolean deleteFromDict(PythonObject obj, TruffleString key, Object value,
}
}
+ @Specialization(guards = {"dict != null", "isNoValue(value)"})
+ static boolean deleteFromPythonBuiltinClass(PythonBuiltinClass klass, TruffleString key, Object value,
+ @Bind("this") Node inliningTarget,
+ @SuppressWarnings("unused") @Shared("getDict") @Cached GetDictIfExistsNode getDict,
+ @Bind("getDict.execute(klass)") PDict dict) {
+ throw PRaiseNode.raiseStatic(inliningTarget, TypeError, ErrorMessages.CANT_SET_ATTRIBUTE_R_OF_IMMUTABLE_TYPE_N, key, klass);
+ }
+
private static boolean writeToDictManagedClass(PythonManagedClass klass, PDict dict, TruffleString key, Object value, Node inliningTarget,
InlinedBranchProfile callAttrUpdate, InlinedBranchProfile updateStorage, HashingStorageSetItem setHashingStorageItem, TruffleString.CodePointLengthNode codePointLengthNode,
TruffleString.CodePointAtIndexNode codePointAtIndexNode) {
From 0aa4e895c312741cd119d621a5e2757163805e52 Mon Sep 17 00:00:00 2001
From: aelkorch
Date: Wed, 23 Apr 2025 20:17:34 +0100
Subject: [PATCH 29/51] Adapt fix to 24.2
---
.../com.oracle.graal.python.test/src/tests/test_dict.py | 2 +-
.../python/nodes/attributes/WriteAttributeToObjectNode.java | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_dict.py b/graalpython/com.oracle.graal.python.test/src/tests/test_dict.py
index 67a226ec37..d56456c79c 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/test_dict.py
+++ b/graalpython/com.oracle.graal.python.test/src/tests/test_dict.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# The Universal Permissive License (UPL), Version 1.0
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java
index 5304613b4f..6ce3f2f5c1 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/attributes/WriteAttributeToObjectNode.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
@@ -257,7 +257,7 @@ static boolean deleteFromPythonBuiltinClass(PythonBuiltinClass klass, TruffleStr
@Bind("this") Node inliningTarget,
@SuppressWarnings("unused") @Shared("getDict") @Cached GetDictIfExistsNode getDict,
@Bind("getDict.execute(klass)") PDict dict) {
- throw PRaiseNode.raiseStatic(inliningTarget, TypeError, ErrorMessages.CANT_SET_ATTRIBUTE_R_OF_IMMUTABLE_TYPE_N, key, klass);
+ throw PRaiseNode.raiseUncached(inliningTarget, TypeError, ErrorMessages.CANT_SET_ATTRIBUTE_R_OF_IMMUTABLE_TYPE_N, key, klass);
}
private static boolean writeToDictManagedClass(PythonManagedClass klass, PDict dict, TruffleString key, Object value, Node inliningTarget,
From 9209769568784f6c5551451a5893179bb4ee0db0 Mon Sep 17 00:00:00 2001
From: Ivo Horak
Date: Tue, 22 Apr 2025 12:41:57 +0200
Subject: [PATCH 30/51] Add default excludes for generating filelists.txt
(cherry picked from commit 3dc183f6542d8df9807cd3b839c9bc704d1e198a)
---
.../python/embedding/tools/vfs/VFSUtils.java | 134 ++++++++++++++++--
1 file changed, 123 insertions(+), 11 deletions(-)
diff --git a/graalpython/org.graalvm.python.embedding.tools/src/org/graalvm/python/embedding/tools/vfs/VFSUtils.java b/graalpython/org.graalvm.python.embedding.tools/src/org/graalvm/python/embedding/tools/vfs/VFSUtils.java
index 46637889eb..f70f70db0d 100644
--- a/graalpython/org.graalvm.python.embedding.tools/src/org/graalvm/python/embedding/tools/vfs/VFSUtils.java
+++ b/graalpython/org.graalvm.python.embedding.tools/src/org/graalvm/python/embedding/tools/vfs/VFSUtils.java
@@ -44,6 +44,8 @@
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -64,6 +66,104 @@
public final class VFSUtils {
+ /**
+ * Patterns which should be excluded by default, like .gitignore or SCM files
+ *
+ * - Misc: **/*~, **/#*#, **/.#*, **/%*%,
+ * **/._*
+ * - CVS: **/CVS, **/CVS/**, **/.cvsignore
+ * - RCS: **/RCS, **/RCS/**
+ * - SCCS: **/SCCS, **/SCCS/**
+ * - VSSercer: **/vssver.scc
+ * - MKS: **/project.pj
+ * - SVN: **/.svn, **/.svn/**
+ * - GNU: **/.arch-ids, **/.arch-ids/**
+ * - Bazaar: **/.bzr, **/.bzr/**
+ * - SurroundSCM: **/.MySCMServerInfo
+ * - Mac: **/.DS_Store
+ * - Serena Dimension: **/.metadata, **/.metadata/**
+ * - Mercurial: **/.hg, **/.hg/**
+ * - Git: **/.git, **/.git/**, **/.gitignore
+ * - Bitkeeper: **/BitKeeper, **/BitKeeper/**, **/ChangeSet,
+ * **/ChangeSet/**
+ * - Darcs: **/_darcs, **/_darcs/**, **/.darcsrepo,
+ * **/.darcsrepo/****/-darcs-backup*, **/.darcs-temp-mail
+ *
+ *
+ */
+ private static final String[] DEFAULT_EXCLUDES = {
+ // Miscellaneous typical temporary files
+ "**/*~",
+ "**/#*#",
+ "**/.#*",
+ "**/%*%",
+ "**/._*",
+
+ // CVS
+ "**/CVS",
+ "**/CVS/**",
+ "**/.cvsignore",
+
+ // RCS
+ "**/RCS",
+ "**/RCS/**",
+
+ // SCCS
+ "**/SCCS",
+ "**/SCCS/**",
+
+ // Visual SourceSafe
+ "**/vssver.scc",
+
+ // MKS
+ "**/project.pj",
+
+ // Subversion
+ "**/.svn",
+ "**/.svn/**",
+
+ // Arch
+ "**/.arch-ids",
+ "**/.arch-ids/**",
+
+ // Bazaar
+ "**/.bzr",
+ "**/.bzr/**",
+
+ // SurroundSCM
+ "**/.MySCMServerInfo",
+
+ // Mac
+ "**/.DS_Store",
+
+ // Serena Dimensions Version 10
+ "**/.metadata",
+ "**/.metadata/**",
+
+ // Mercurial
+ "**/.hg",
+ "**/.hg/**",
+
+ // git
+ "**/.git",
+ "**/.git/**",
+ "**/.gitignore",
+
+ // BitKeeper
+ "**/BitKeeper",
+ "**/BitKeeper/**",
+ "**/ChangeSet",
+ "**/ChangeSet/**",
+
+ // darcs
+ "**/_darcs",
+ "**/_darcs/**",
+ "**/.darcsrepo",
+ "**/.darcsrepo/**",
+ "**/-darcs-backup*",
+ "**/.darcs-temp-mail"
+ };
+
public static final String VFS_ROOT = "org.graalvm.python.vfs";
public static final String VFS_VENV = "venv";
public static final String VFS_FILESLIST = "fileslist.txt";
@@ -152,23 +252,35 @@ public static void generateVFSFilesList(Path resourcesRoot, Path vfs, Set {
- String entry = null;
- if (Files.isDirectory(p)) {
- String dirPath = makeDirPath(p.toAbsolutePath());
- entry = dirPath.substring(rootEndIdx);
- } else if (Files.isRegularFile(p)) {
- entry = p.toAbsolutePath().toString().substring(rootEndIdx);
- }
- if (entry != null) {
- entry = normalizeResourcePath(entry);
- if (!ret.add(entry) && duplicateHandler != null) {
- duplicateHandler.accept(entry);
+ if (!shouldPathBeExcluded(p)) {
+ String entry = null;
+ if (Files.isDirectory(p)) {
+ String dirPath = makeDirPath(p.toAbsolutePath());
+ entry = dirPath.substring(rootEndIdx);
+ } else if (Files.isRegularFile(p)) {
+ entry = p.toAbsolutePath().toString().substring(rootEndIdx);
+ }
+ if (entry != null) {
+ entry = normalizeResourcePath(entry);
+ if (!ret.add(entry) && duplicateHandler != null) {
+ duplicateHandler.accept(entry);
+ }
}
}
});
}
}
+ private static boolean shouldPathBeExcluded(Path path) {
+ for (String glob : DEFAULT_EXCLUDES) {
+ var matcher = FileSystems.getDefault().getPathMatcher("glob:" + glob);
+ if (matcher.matches(path)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private static String makeDirPath(Path p) {
String ret = p.toString();
if (!ret.endsWith(File.separator)) {
From 6877b767d98ecf57ee9e405601b0472a106d66bf Mon Sep 17 00:00:00 2001
From: Ivo Horak
Date: Tue, 22 Apr 2025 15:04:00 +0200
Subject: [PATCH 31/51] Adding source of the exclude list
(cherry picked from commit 99469b5a5d283c00754bba850ca00299923e0d34)
---
.../org/graalvm/python/embedding/tools/vfs/VFSUtils.java | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/graalpython/org.graalvm.python.embedding.tools/src/org/graalvm/python/embedding/tools/vfs/VFSUtils.java b/graalpython/org.graalvm.python.embedding.tools/src/org/graalvm/python/embedding/tools/vfs/VFSUtils.java
index f70f70db0d..0a99df77eb 100644
--- a/graalpython/org.graalvm.python.embedding.tools/src/org/graalvm/python/embedding/tools/vfs/VFSUtils.java
+++ b/graalpython/org.graalvm.python.embedding.tools/src/org/graalvm/python/embedding/tools/vfs/VFSUtils.java
@@ -44,7 +44,6 @@
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
-import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -67,7 +66,7 @@
public final class VFSUtils {
/**
- * Patterns which should be excluded by default, like .gitignore or SCM files
+ * Patterns which should be excluded by default, like .gitignore or SCM files.
*
* - Misc: **/*~, **/#*#, **/.#*, **/%*%,
* **/._*
@@ -90,6 +89,9 @@ public final class VFSUtils {
* **/.darcsrepo/****/-darcs-backup*, **/.darcs-temp-mail
*
*
+ *
+ * The list is a copy of the one used in tools like the Maven JAR Plugin. @see DEFAULTEXCLUDES
*/
private static final String[] DEFAULT_EXCLUDES = {
// Miscellaneous typical temporary files
From 06f7cd78eda1c1cbb6f154cd158bc042983fe9ce Mon Sep 17 00:00:00 2001
From: Tim Felgentreff
Date: Tue, 15 Apr 2025 13:07:11 +0200
Subject: [PATCH 32/51] Expose PyTuple_SET_ITEM also as API function on GraalPy
(cherry picked from commit 97fb7929488f5362d352e56fe6ba23896009f802)
fix conflicts
---
.../include/cpython/tupleobject.h | 10 +++-----
.../com.oracle.graal.python.cext/src/object.c | 2 +-
.../src/tupleobject.c | 8 ++++++-
.../src/tests/cpyext/test_tuple.py | 23 ++++++++++++++++---
.../cext/PythonCextObjectBuiltins.java | 2 +-
scripts/wheelbuilder/build_wheels.py | 5 +---
6 files changed, 33 insertions(+), 17 deletions(-)
diff --git a/graalpython/com.oracle.graal.python.cext/include/cpython/tupleobject.h b/graalpython/com.oracle.graal.python.cext/include/cpython/tupleobject.h
index ef3d3c3790..222dbdfd50 100644
--- a/graalpython/com.oracle.graal.python.cext/include/cpython/tupleobject.h
+++ b/graalpython/com.oracle.graal.python.cext/include/cpython/tupleobject.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2020, 2024, Oracle and/or its affiliates.
+/* Copyright (c) 2020, 2025, Oracle and/or its affiliates.
* Copyright (C) 1996-2020 Python Software Foundation
*
* Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
@@ -39,14 +39,10 @@ PyAPI_FUNC(PyObject *) _PyTuple_GET_ITEM(PyObject *, Py_ssize_t);
// GraalPy-specific
PyAPI_FUNC(PyObject **) PyTruffleTuple_GetItems(PyObject *op);
-/* Function *only* to be used to fill in brand new tuples */
-static inline void
-PyTuple_SET_ITEM(PyObject *op, Py_ssize_t index, PyObject *value) {
- PyTruffleTuple_GetItems(op)[index] = value;
-}
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
+PyAPI_FUNC(void) PyTuple_SET_ITEM(PyObject*, Py_ssize_t, PyObject*);
#define PyTuple_SET_ITEM(op, index, value) \
- PyTuple_SET_ITEM(_PyObject_CAST(op), index, _PyObject_CAST(value))
+ do { PyTruffleTuple_GetItems(op)[index] = value; } while (0)
#endif
PyAPI_FUNC(void) _PyTuple_DebugMallocStats(FILE *out);
diff --git a/graalpython/com.oracle.graal.python.cext/src/object.c b/graalpython/com.oracle.graal.python.cext/src/object.c
index 58c8a61de0..d467aac946 100644
--- a/graalpython/com.oracle.graal.python.cext/src/object.c
+++ b/graalpython/com.oracle.graal.python.cext/src/object.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, 2024, Oracle and/or its affiliates.
+/* Copyright (c) 2018, 2025, Oracle and/or its affiliates.
* Copyright (C) 1996-2022 Python Software Foundation
*
* Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
diff --git a/graalpython/com.oracle.graal.python.cext/src/tupleobject.c b/graalpython/com.oracle.graal.python.cext/src/tupleobject.c
index 007bab220d..e5259468b5 100644
--- a/graalpython/com.oracle.graal.python.cext/src/tupleobject.c
+++ b/graalpython/com.oracle.graal.python.cext/src/tupleobject.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, 2024, Oracle and/or its affiliates.
+/* Copyright (c) 2018, 2025, Oracle and/or its affiliates.
* Copyright (C) 1996-2022 Python Software Foundation
*
* Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
@@ -1424,3 +1424,9 @@ _PyTuple_GET_ITEM(PyObject* a, Py_ssize_t b) {
}
return NULL; // an exception has happend during transtion
}
+
+#undef PyTuple_SET_ITEM
+// Export PyTuple_SET_ITEM as regular API function to use in PyO3 and others
+void PyTuple_SET_ITEM(PyObject* op, Py_ssize_t index, PyObject* value) {
+ PyTruffleTuple_GetItems(op)[index] = value;
+}
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_tuple.py b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_tuple.py
index 3570a698fb..c696d5828f 100644
--- a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_tuple.py
+++ b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_tuple.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# The Universal Permissive License (UPL), Version 1.0
@@ -151,14 +151,15 @@ class TestPyTuple(CPyExtTestCase):
((1, 2, 3), -1, []),
((1, 2, 3), 3, str),
),
- code="""PyObject* wrap_PyTuple_SetItem(PyObject* original, Py_ssize_t index, PyObject* value) {
+ code="""
+ PyObject* wrap_PyTuple_SetItem(PyObject* original, Py_ssize_t index, PyObject* value) {
Py_ssize_t size = PyTuple_Size(original);
if (size < 0)
return NULL;
PyObject* tuple = PyTuple_New(size);
if (!tuple)
return NULL;
- for (int i = 0; i < size; i++) {
+ for (int i = 0; i < size / 2; i++) {
PyObject* item = PyTuple_GetItem(original, i);
if (!item) {
Py_DECREF(tuple);
@@ -167,6 +168,22 @@ class TestPyTuple(CPyExtTestCase):
Py_INCREF(item);
PyTuple_SET_ITEM(tuple, i, item);
}
+
+ #ifdef GRAALVM_PYTHON
+ // test that we also have it as API function on GraalPy
+ #undef PyTuple_SET_ITEM
+ #endif
+
+ for (int i = size / 2; i < size; i++) {
+ PyObject* item = PyTuple_GetItem(original, i);
+ if (!item) {
+ Py_DECREF(tuple);
+ return NULL;
+ }
+ Py_INCREF(item);
+ PyTuple_SET_ITEM(tuple, i, item);
+ }
+
Py_INCREF(value);
if (PyTuple_SetItem(tuple, index, value) < 0) {
Py_DECREF(tuple);
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextObjectBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextObjectBuiltins.java
index ec99db57ea..b14d9f45e1 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextObjectBuiltins.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextObjectBuiltins.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
diff --git a/scripts/wheelbuilder/build_wheels.py b/scripts/wheelbuilder/build_wheels.py
index 01aaf0eafd..b6a00c7cce 100644
--- a/scripts/wheelbuilder/build_wheels.py
+++ b/scripts/wheelbuilder/build_wheels.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# The Universal Permissive License (UPL), Version 1.0
@@ -100,13 +100,10 @@ def create_venv():
subprocess.check_call([binary, "-m", "venv", "graalpy"])
print("Installing wheel with", pip, flush=True)
subprocess.check_call([pip, "install", "wheel"])
-<<<<<<< HEAD
-=======
print("Installing paatch to provide patch.exe", flush=True)
p = subprocess.run([pip, "install", "paatch"])
if p.returncode != 0:
print("Installing paatch failed, assuming a GNU patch compatible binary is on PATH", flush=True)
->>>>>>> 8ac74ecd42 (Use paatch to apply patches the same way across all platforms)
return pip
From c6e5e39d06068e941c44bc361b9142a566cd1c3a Mon Sep 17 00:00:00 2001
From: Michael Simacek
Date: Tue, 6 May 2025 12:57:14 +0200
Subject: [PATCH 33/51] Fix definition of PyTuple_SET_ITEM
1. It was missing the casts
2. The do-while trips up some weird C++ in scipy that uses it in a comma expression
(cherry picked from commit 5a7a5f8cf4e1264699a75681ab68bc2ad35a56eb)
---
.../include/cpython/tupleobject.h | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/graalpython/com.oracle.graal.python.cext/include/cpython/tupleobject.h b/graalpython/com.oracle.graal.python.cext/include/cpython/tupleobject.h
index 222dbdfd50..e5d9ea8436 100644
--- a/graalpython/com.oracle.graal.python.cext/include/cpython/tupleobject.h
+++ b/graalpython/com.oracle.graal.python.cext/include/cpython/tupleobject.h
@@ -39,10 +39,9 @@ PyAPI_FUNC(PyObject *) _PyTuple_GET_ITEM(PyObject *, Py_ssize_t);
// GraalPy-specific
PyAPI_FUNC(PyObject **) PyTruffleTuple_GetItems(PyObject *op);
-#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
+// GraalPy change: Export PyTuple_SET_ITEM as regular API function to use in PyO3 and others
PyAPI_FUNC(void) PyTuple_SET_ITEM(PyObject*, Py_ssize_t, PyObject*);
#define PyTuple_SET_ITEM(op, index, value) \
- do { PyTruffleTuple_GetItems(op)[index] = value; } while (0)
-#endif
+ PyTuple_SET_ITEM(_PyObject_CAST(op), (index), _PyObject_CAST(value))
PyAPI_FUNC(void) _PyTuple_DebugMallocStats(FILE *out);
From f7316db4b4839108f15fa443aca70b1365291009 Mon Sep 17 00:00:00 2001
From: Tim Felgentreff
Date: Wed, 21 May 2025 20:49:16 +0200
Subject: [PATCH 34/51] [GR-65227] Ensure writing same value for all keys in a
HashingStorage handles storage generalization
(cherry picked from commit 7f330d9b296480dbe00af44835f37516a07549fd)
---
.../common/HashingCollectionNodes.java | 28 +++++++++++++------
1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/HashingCollectionNodes.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/HashingCollectionNodes.java
index 55c4644dbe..ac120a2e3f 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/HashingCollectionNodes.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/common/HashingCollectionNodes.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
@@ -61,6 +61,7 @@
import com.oracle.graal.python.nodes.object.BuiltinClassProfiles.IsBuiltinObjectProfile;
import com.oracle.graal.python.nodes.util.CastToTruffleStringNode;
import com.oracle.graal.python.runtime.exception.PException;
+import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.HostCompilerDirectives.InliningCutoff;
import com.oracle.truffle.api.dsl.Bind;
import com.oracle.truffle.api.dsl.Cached;
@@ -121,8 +122,8 @@ abstract static class SetValueHashingStorageNode extends PNodeWithContext {
@Specialization
static HashingStorage doEconomicStorage(VirtualFrame frame, Node inliningTarget, EconomicMapStorage map, Object value,
- @Cached ObjectHashMap.PutNode putNode,
- @Cached InlinedLoopConditionProfile loopProfile) {
+ @Shared("putNode") @Cached ObjectHashMap.PutNode putNode,
+ @Shared("loopProfile") @Cached InlinedLoopConditionProfile loopProfile) {
// We want to avoid calling __hash__() during map.put
map.setValueForAllKeys(frame, inliningTarget, value, putNode, loopProfile);
return map;
@@ -134,14 +135,25 @@ static HashingStorage doGeneric(VirtualFrame frame, Node inliningTarget, Hashing
@Cached HashingStorageSetItem setItem,
@Cached HashingStorageGetIterator getIterator,
@Cached HashingStorageIteratorNext itNext,
- @Cached HashingStorageIteratorKey itKey) {
+ @Cached HashingStorageIteratorKey itKey,
+ @Shared("putNode") @Cached ObjectHashMap.PutNode putNode,
+ @Shared("loopProfile") @Cached InlinedLoopConditionProfile loopProfile) {
HashingStorageIterator it = getIterator.execute(inliningTarget, map);
- HashingStorage storage = map;
while (itNext.execute(inliningTarget, map, it)) {
- Object key = itKey.execute(inliningTarget, storage, it);
- storage = setItem.execute(frame, inliningTarget, storage, key, value);
+ Object key = itKey.execute(inliningTarget, map, it);
+ HashingStorage newStorage = setItem.execute(frame, inliningTarget, map, key, value);
+ if (newStorage != map) {
+ // when the storage changes, the iterator state is not a reliable cursor
+ // anymore and we need to restart.
+ if (newStorage instanceof EconomicMapStorage mapStorage) {
+ mapStorage.setValueForAllKeys(frame, inliningTarget, value, putNode, loopProfile);
+ return mapStorage;
+ } else {
+ throw CompilerDirectives.shouldNotReachHere("We only generalize to EconomicMapStorage");
+ }
+ }
}
- return storage;
+ return map;
}
protected static boolean isEconomicMapStorage(Object o) {
From 38135d2de4b2c78998534f84f2a84a7f629ecf4b Mon Sep 17 00:00:00 2001
From: Tim Felgentreff
Date: Mon, 26 May 2025 11:49:35 +0200
Subject: [PATCH 35/51] [GR-65330] Revert breaking ABI in graalpy242 wheels
(cherry picked from commit 3c4d840434a411713a8e0dfbd3ac4850f2f77e52)
---
.../include/cpython/tupleobject.h | 7 ++++++-
graalpython/com.oracle.graal.python.cext/src/tupleobject.c | 2 +-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/graalpython/com.oracle.graal.python.cext/include/cpython/tupleobject.h b/graalpython/com.oracle.graal.python.cext/include/cpython/tupleobject.h
index e5d9ea8436..a5bb3fba3b 100644
--- a/graalpython/com.oracle.graal.python.cext/include/cpython/tupleobject.h
+++ b/graalpython/com.oracle.graal.python.cext/include/cpython/tupleobject.h
@@ -41,7 +41,12 @@ PyAPI_FUNC(PyObject **) PyTruffleTuple_GetItems(PyObject *op);
// GraalPy change: Export PyTuple_SET_ITEM as regular API function to use in PyO3 and others
PyAPI_FUNC(void) PyTuple_SET_ITEM(PyObject*, Py_ssize_t, PyObject*);
+
+/* Inline function to be used in the PyTuple_SET_ITEM macro. */
+static inline void graalpy_tuple_set_item(PyObject *op, Py_ssize_t index, PyObject *value) {
+ PyTruffleTuple_GetItems(op)[index] = value;
+}
#define PyTuple_SET_ITEM(op, index, value) \
- PyTuple_SET_ITEM(_PyObject_CAST(op), (index), _PyObject_CAST(value))
+ graalpy_tuple_set_item(_PyObject_CAST(op), (index), _PyObject_CAST(value))
PyAPI_FUNC(void) _PyTuple_DebugMallocStats(FILE *out);
diff --git a/graalpython/com.oracle.graal.python.cext/src/tupleobject.c b/graalpython/com.oracle.graal.python.cext/src/tupleobject.c
index e5259468b5..4e6f9c2a50 100644
--- a/graalpython/com.oracle.graal.python.cext/src/tupleobject.c
+++ b/graalpython/com.oracle.graal.python.cext/src/tupleobject.c
@@ -1428,5 +1428,5 @@ _PyTuple_GET_ITEM(PyObject* a, Py_ssize_t b) {
#undef PyTuple_SET_ITEM
// Export PyTuple_SET_ITEM as regular API function to use in PyO3 and others
void PyTuple_SET_ITEM(PyObject* op, Py_ssize_t index, PyObject* value) {
- PyTruffleTuple_GetItems(op)[index] = value;
+ graalpy_tuple_set_item(op, index, value);
}
From 246df4ea800c72a286171cdc23ef6aa142cc6e7e Mon Sep 17 00:00:00 2001
From: Michael Simacek
Date: Fri, 25 Apr 2025 17:48:47 +0200
Subject: [PATCH 36/51] Implement AttributeError builtins
(cherry picked from commit 16a4dc633cb8aa046056f0d4d4cdc44a11d1beb7)
---
.../graal/python/builtins/Python3Core.java | 2 +
.../builtins/PythonBuiltinClassType.java | 3 +-
.../exception/AttributeErrorBuiltins.java | 202 ++++++++++++++++++
3 files changed, 206 insertions(+), 1 deletion(-)
create mode 100644 graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/AttributeErrorBuiltins.java
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java
index 6f6254b9d8..2453a263f1 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java
@@ -248,6 +248,7 @@
import com.oracle.graal.python.builtins.objects.dict.PDict;
import com.oracle.graal.python.builtins.objects.ellipsis.EllipsisBuiltins;
import com.oracle.graal.python.builtins.objects.enumerate.EnumerateBuiltins;
+import com.oracle.graal.python.builtins.objects.exception.AttributeErrorBuiltins;
import com.oracle.graal.python.builtins.objects.exception.BaseExceptionBuiltins;
import com.oracle.graal.python.builtins.objects.exception.BaseExceptionGroupBuiltins;
import com.oracle.graal.python.builtins.objects.exception.ImportErrorBuiltins;
@@ -571,6 +572,7 @@ private static PythonBuiltins[] initializeBuiltins(boolean nativeAccessAllowed,
new GenericAliasIteratorBuiltins(),
new com.oracle.graal.python.builtins.objects.types.UnionTypeBuiltins(),
// exceptions
+ new AttributeErrorBuiltins(),
new SystemExitBuiltins(),
new ImportErrorBuiltins(),
new StopIterationBuiltins(),
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java
index 8d586cc758..7ad02c4f26 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java
@@ -135,6 +135,7 @@
import com.oracle.graal.python.builtins.objects.dict.DictBuiltins;
import com.oracle.graal.python.builtins.objects.dict.DictValuesBuiltins;
import com.oracle.graal.python.builtins.objects.dict.DictViewBuiltins;
+import com.oracle.graal.python.builtins.objects.exception.AttributeErrorBuiltins;
import com.oracle.graal.python.builtins.objects.floats.FloatBuiltins;
import com.oracle.graal.python.builtins.objects.foreign.ForeignBooleanBuiltins;
import com.oracle.graal.python.builtins.objects.foreign.ForeignNumberBuiltins;
@@ -468,7 +469,7 @@ public enum PythonBuiltinClassType implements TruffleObject {
OverflowError("OverflowError", J_BUILTINS, Flags.EXCEPTION),
ZeroDivisionError("ZeroDivisionError", J_BUILTINS, Flags.EXCEPTION),
AssertionError("AssertionError", J_BUILTINS, Flags.EXCEPTION),
- AttributeError("AttributeError", J_BUILTINS, Flags.EXCEPTION),
+ AttributeError("AttributeError", J_BUILTINS, Flags.EXCEPTION, AttributeErrorBuiltins.SLOTS),
BufferError("BufferError", J_BUILTINS, Flags.EXCEPTION),
EOFError("EOFError", J_BUILTINS, Flags.EXCEPTION),
ImportError("ImportError", J_BUILTINS, Flags.EXCEPTION),
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/AttributeErrorBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/AttributeErrorBuiltins.java
new file mode 100644
index 0000000000..e3b724a52f
--- /dev/null
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/AttributeErrorBuiltins.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * The Universal Permissive License (UPL), Version 1.0
+ *
+ * Subject to the condition set forth below, permission is hereby granted to any
+ * person obtaining a copy of this software, associated documentation and/or
+ * data (collectively the "Software"), free of charge and under any and all
+ * copyright rights in the Software, and any and all patent rights owned or
+ * freely licensable by each licensor hereunder covering either (i) the
+ * unmodified Software as contributed to or provided by such licensor, or (ii)
+ * the Larger Works (as defined below), to deal in both
+ *
+ * (a) the Software, and
+ *
+ * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+ * one is included with the Software each a "Larger Work" to which the Software
+ * is contributed by such licensors),
+ *
+ * without restriction, including without limitation the rights to copy, create
+ * derivative works of, display, perform, and distribute the Software and make,
+ * use, sell, offer for sale, import, export, have made, and have sold the
+ * Software and the Larger Work(s), and to sublicense the foregoing rights on
+ * either these or other terms.
+ *
+ * This license is subject to the following condition:
+ *
+ * The above copyright notice and either this complete permission notice or at a
+ * minimum a reference to the UPL must be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+package com.oracle.graal.python.builtins.objects.exception;
+
+import static com.oracle.graal.python.nodes.SpecialMethodNames.J___GETSTATE__;
+import static com.oracle.graal.python.nodes.SpecialMethodNames.J___REDUCE__;
+import static com.oracle.graal.python.util.PythonUtils.TS_ENCODING;
+import static com.oracle.graal.python.util.PythonUtils.tsLiteral;
+
+import java.util.List;
+
+import com.oracle.graal.python.PythonLanguage;
+import com.oracle.graal.python.annotations.Slot;
+import com.oracle.graal.python.annotations.Slot.SlotKind;
+import com.oracle.graal.python.annotations.Slot.SlotSignature;
+import com.oracle.graal.python.builtins.Builtin;
+import com.oracle.graal.python.builtins.CoreFunctions;
+import com.oracle.graal.python.builtins.PythonBuiltinClassType;
+import com.oracle.graal.python.builtins.PythonBuiltins;
+import com.oracle.graal.python.builtins.objects.PNone;
+import com.oracle.graal.python.builtins.objects.common.EmptyStorage;
+import com.oracle.graal.python.builtins.objects.common.HashingStorage;
+import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes;
+import com.oracle.graal.python.builtins.objects.dict.PDict;
+import com.oracle.graal.python.builtins.objects.function.PKeyword;
+import com.oracle.graal.python.builtins.objects.type.TpSlots;
+import com.oracle.graal.python.nodes.ErrorMessages;
+import com.oracle.graal.python.nodes.PRaiseNode;
+import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
+import com.oracle.graal.python.nodes.function.builtins.PythonBinaryBuiltinNode;
+import com.oracle.graal.python.nodes.function.builtins.PythonUnaryBuiltinNode;
+import com.oracle.graal.python.nodes.function.builtins.PythonVarargsBuiltinNode;
+import com.oracle.graal.python.nodes.object.GetClassNode;
+import com.oracle.graal.python.nodes.object.GetDictIfExistsNode;
+import com.oracle.graal.python.runtime.object.PFactory;
+import com.oracle.truffle.api.dsl.Bind;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.GenerateNodeFactory;
+import com.oracle.truffle.api.dsl.NodeFactory;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.profiles.InlinedLoopConditionProfile;
+import com.oracle.truffle.api.strings.TruffleString;
+
+@CoreFunctions(extendClasses = PythonBuiltinClassType.AttributeError)
+public final class AttributeErrorBuiltins extends PythonBuiltins {
+
+ public static final TpSlots SLOTS = AttributeErrorBuiltinsSlotsGen.SLOTS;
+
+ @Override
+ protected List extends NodeFactory extends PythonBuiltinBaseNode>> getNodeFactories() {
+ return AttributeErrorBuiltinsFactory.getFactories();
+ }
+
+ private static final int IDX_NAME = 0;
+ private static final int IDX_OBJ = 1;
+ private static final int NUM_ATTRS = IDX_OBJ + 1;
+
+ private static final TruffleString T_NAME = tsLiteral("name");
+ private static final TruffleString T_OBJ = tsLiteral("obj");
+
+ private static final BaseExceptionAttrNode.StorageFactory ATTR_FACTORY = (args) -> new Object[NUM_ATTRS];
+
+ @Slot(value = SlotKind.tp_init, isComplex = true)
+ @SlotSignature(minNumOfPositionalArgs = 1, takesVarArgs = true, takesVarKeywordArgs = true)
+ @GenerateNodeFactory
+ abstract static class InitNode extends PythonVarargsBuiltinNode {
+
+ @Specialization
+ static Object init(PBaseException self, Object[] args, PKeyword[] kwargs,
+ @Bind Node inliningTarget,
+ @Cached BaseExceptionBuiltins.BaseExceptionInitNode baseExceptionInitNode,
+ @Cached TruffleString.EqualNode equalNameNode,
+ @Cached TruffleString.EqualNode equalObjNode,
+ @Cached InlinedLoopConditionProfile loopProfile,
+ @Cached PRaiseNode raiseNode) {
+ baseExceptionInitNode.execute(self, args);
+ Object[] attrs = new Object[NUM_ATTRS];
+ loopProfile.profileCounted(inliningTarget, kwargs.length);
+ for (int i = 0; loopProfile.inject(inliningTarget, i < kwargs.length); i++) {
+ PKeyword kw = kwargs[i];
+ TruffleString kwName = kw.getName();
+ if (equalNameNode.execute(kwName, T_NAME, TS_ENCODING)) {
+ attrs[IDX_NAME] = kw.getValue();
+ } else if (equalObjNode.execute(kwName, T_OBJ, TS_ENCODING)) {
+ attrs[IDX_OBJ] = kw.getValue();
+ } else {
+ throw raiseNode.raise(inliningTarget, PythonBuiltinClassType.TypeError, ErrorMessages.S_IS_AN_INVALID_ARG_FOR_S, kw.getName(), "AttributeError");
+ }
+ }
+ self.setExceptionAttributes(attrs);
+ return PNone.NONE;
+ }
+ }
+
+ @Builtin(name = "name", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true, allowsDelete = true, doc = "attribute name")
+ @GenerateNodeFactory
+ public abstract static class NameNode extends PythonBinaryBuiltinNode {
+ @Specialization
+ static Object generic(PBaseException self, Object value,
+ @Cached BaseExceptionAttrNode attrNode) {
+ return attrNode.execute(self, value, IDX_NAME, ATTR_FACTORY);
+ }
+ }
+
+ @Builtin(name = "obj", minNumOfPositionalArgs = 1, maxNumOfPositionalArgs = 2, isGetter = true, isSetter = true, allowsDelete = true, doc = "object")
+ @GenerateNodeFactory
+ public abstract static class ObjNode extends PythonBinaryBuiltinNode {
+ @Specialization
+ static Object generic(PBaseException self, Object value,
+ @Cached BaseExceptionAttrNode attrNode) {
+ return attrNode.execute(self, value, IDX_OBJ, ATTR_FACTORY);
+ }
+ }
+
+ @Builtin(name = J___GETSTATE__, minNumOfPositionalArgs = 1)
+ @GenerateNodeFactory
+ public abstract static class GetStateNode extends PythonUnaryBuiltinNode {
+
+ @Specialization
+ static Object get(PBaseException self,
+ @Bind("this") Node inliningTarget,
+ @Cached BaseExceptionAttrNode attrNode,
+ @Cached GetDictIfExistsNode getDictIfExistsNode,
+ @Cached HashingStorageNodes.HashingStorageSetItem setHashingStorageItem,
+ @Cached HashingStorageNodes.HashingStorageCopy copyStorageNode,
+ @Bind PythonLanguage language) {
+ PDict dict = getDictIfExistsNode.execute(self);
+ /*
+ * Note from CPython: We specifically are not pickling the obj attribute since there are
+ * many cases where it is unlikely to be picklable.
+ */
+ Object name = attrNode.get(self, IDX_NAME, ATTR_FACTORY);
+ if (name != null) {
+ HashingStorage storage = (dict != null) ? copyStorageNode.execute(inliningTarget, dict.getDictStorage()) : EmptyStorage.INSTANCE;
+ storage = setHashingStorageItem.execute(inliningTarget, storage, T_NAME, name);
+ return PFactory.createDict(language, storage);
+ } else if (dict != null) {
+ return dict;
+ } else {
+ return PNone.NONE;
+ }
+ }
+ }
+
+ @Builtin(name = J___REDUCE__, minNumOfPositionalArgs = 1)
+ @GenerateNodeFactory
+ public abstract static class ReduceNode extends PythonUnaryBuiltinNode {
+
+ @Specialization
+ static Object reduce(VirtualFrame frame, PBaseException self,
+ @Bind("this") Node inliningTarget,
+ @Cached GetClassNode getClassNode,
+ @Cached ExceptionNodes.GetArgsNode getArgsNode,
+ @Cached GetStateNode getStateNode,
+ @Bind PythonLanguage language) {
+ Object clazz = getClassNode.execute(inliningTarget, self);
+ Object args = getArgsNode.execute(inliningTarget, self);
+ Object state = getStateNode.execute(frame, self);
+ return PFactory.createTuple(language, new Object[]{clazz, args, state});
+ }
+ }
+}
From 5961ee93fe7a11e38a3e36fdb0e65e703859c612 Mon Sep 17 00:00:00 2001
From: Michael Simacek
Date: Mon, 2 Jun 2025 14:29:46 +0200
Subject: [PATCH 37/51] Adapt AttributeErrorBuiltins to 24.2
---
.../builtins/PythonBuiltinClassType.java | 3 +--
.../exception/AttributeErrorBuiltins.java | 25 +++++++------------
2 files changed, 10 insertions(+), 18 deletions(-)
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java
index 7ad02c4f26..8d586cc758 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java
@@ -135,7 +135,6 @@
import com.oracle.graal.python.builtins.objects.dict.DictBuiltins;
import com.oracle.graal.python.builtins.objects.dict.DictValuesBuiltins;
import com.oracle.graal.python.builtins.objects.dict.DictViewBuiltins;
-import com.oracle.graal.python.builtins.objects.exception.AttributeErrorBuiltins;
import com.oracle.graal.python.builtins.objects.floats.FloatBuiltins;
import com.oracle.graal.python.builtins.objects.foreign.ForeignBooleanBuiltins;
import com.oracle.graal.python.builtins.objects.foreign.ForeignNumberBuiltins;
@@ -469,7 +468,7 @@ public enum PythonBuiltinClassType implements TruffleObject {
OverflowError("OverflowError", J_BUILTINS, Flags.EXCEPTION),
ZeroDivisionError("ZeroDivisionError", J_BUILTINS, Flags.EXCEPTION),
AssertionError("AssertionError", J_BUILTINS, Flags.EXCEPTION),
- AttributeError("AttributeError", J_BUILTINS, Flags.EXCEPTION, AttributeErrorBuiltins.SLOTS),
+ AttributeError("AttributeError", J_BUILTINS, Flags.EXCEPTION),
BufferError("BufferError", J_BUILTINS, Flags.EXCEPTION),
EOFError("EOFError", J_BUILTINS, Flags.EXCEPTION),
ImportError("ImportError", J_BUILTINS, Flags.EXCEPTION),
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/AttributeErrorBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/AttributeErrorBuiltins.java
index e3b724a52f..02dfc38dd8 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/AttributeErrorBuiltins.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/AttributeErrorBuiltins.java
@@ -41,16 +41,13 @@
package com.oracle.graal.python.builtins.objects.exception;
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___GETSTATE__;
+import static com.oracle.graal.python.nodes.SpecialMethodNames.J___INIT__;
import static com.oracle.graal.python.nodes.SpecialMethodNames.J___REDUCE__;
import static com.oracle.graal.python.util.PythonUtils.TS_ENCODING;
import static com.oracle.graal.python.util.PythonUtils.tsLiteral;
import java.util.List;
-import com.oracle.graal.python.PythonLanguage;
-import com.oracle.graal.python.annotations.Slot;
-import com.oracle.graal.python.annotations.Slot.SlotKind;
-import com.oracle.graal.python.annotations.Slot.SlotSignature;
import com.oracle.graal.python.builtins.Builtin;
import com.oracle.graal.python.builtins.CoreFunctions;
import com.oracle.graal.python.builtins.PythonBuiltinClassType;
@@ -61,7 +58,6 @@
import com.oracle.graal.python.builtins.objects.common.HashingStorageNodes;
import com.oracle.graal.python.builtins.objects.dict.PDict;
import com.oracle.graal.python.builtins.objects.function.PKeyword;
-import com.oracle.graal.python.builtins.objects.type.TpSlots;
import com.oracle.graal.python.nodes.ErrorMessages;
import com.oracle.graal.python.nodes.PRaiseNode;
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
@@ -70,7 +66,7 @@
import com.oracle.graal.python.nodes.function.builtins.PythonVarargsBuiltinNode;
import com.oracle.graal.python.nodes.object.GetClassNode;
import com.oracle.graal.python.nodes.object.GetDictIfExistsNode;
-import com.oracle.graal.python.runtime.object.PFactory;
+import com.oracle.graal.python.runtime.object.PythonObjectFactory;
import com.oracle.truffle.api.dsl.Bind;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
@@ -84,8 +80,6 @@
@CoreFunctions(extendClasses = PythonBuiltinClassType.AttributeError)
public final class AttributeErrorBuiltins extends PythonBuiltins {
- public static final TpSlots SLOTS = AttributeErrorBuiltinsSlotsGen.SLOTS;
-
@Override
protected List extends NodeFactory extends PythonBuiltinBaseNode>> getNodeFactories() {
return AttributeErrorBuiltinsFactory.getFactories();
@@ -98,10 +92,9 @@ protected List extends NodeFactory extends PythonBuiltinBaseNode>> getNodeFa
private static final TruffleString T_NAME = tsLiteral("name");
private static final TruffleString T_OBJ = tsLiteral("obj");
- private static final BaseExceptionAttrNode.StorageFactory ATTR_FACTORY = (args) -> new Object[NUM_ATTRS];
+ private static final BaseExceptionAttrNode.StorageFactory ATTR_FACTORY = (args, factory) -> new Object[NUM_ATTRS];
- @Slot(value = SlotKind.tp_init, isComplex = true)
- @SlotSignature(minNumOfPositionalArgs = 1, takesVarArgs = true, takesVarKeywordArgs = true)
+ @Builtin(name = J___INIT__, minNumOfPositionalArgs = 1, takesVarArgs = true, takesVarKeywordArgs = true)
@GenerateNodeFactory
abstract static class InitNode extends PythonVarargsBuiltinNode {
@@ -124,7 +117,7 @@ static Object init(PBaseException self, Object[] args, PKeyword[] kwargs,
} else if (equalObjNode.execute(kwName, T_OBJ, TS_ENCODING)) {
attrs[IDX_OBJ] = kw.getValue();
} else {
- throw raiseNode.raise(inliningTarget, PythonBuiltinClassType.TypeError, ErrorMessages.S_IS_AN_INVALID_ARG_FOR_S, kw.getName(), "AttributeError");
+ throw raiseNode.raise(PythonBuiltinClassType.TypeError, ErrorMessages.S_IS_AN_INVALID_ARG_FOR_S, kw.getName(), "AttributeError");
}
}
self.setExceptionAttributes(attrs);
@@ -163,7 +156,7 @@ static Object get(PBaseException self,
@Cached GetDictIfExistsNode getDictIfExistsNode,
@Cached HashingStorageNodes.HashingStorageSetItem setHashingStorageItem,
@Cached HashingStorageNodes.HashingStorageCopy copyStorageNode,
- @Bind PythonLanguage language) {
+ @Cached PythonObjectFactory factory) {
PDict dict = getDictIfExistsNode.execute(self);
/*
* Note from CPython: We specifically are not pickling the obj attribute since there are
@@ -173,7 +166,7 @@ static Object get(PBaseException self,
if (name != null) {
HashingStorage storage = (dict != null) ? copyStorageNode.execute(inliningTarget, dict.getDictStorage()) : EmptyStorage.INSTANCE;
storage = setHashingStorageItem.execute(inliningTarget, storage, T_NAME, name);
- return PFactory.createDict(language, storage);
+ return factory.createDict(storage);
} else if (dict != null) {
return dict;
} else {
@@ -192,11 +185,11 @@ static Object reduce(VirtualFrame frame, PBaseException self,
@Cached GetClassNode getClassNode,
@Cached ExceptionNodes.GetArgsNode getArgsNode,
@Cached GetStateNode getStateNode,
- @Bind PythonLanguage language) {
+ @Cached PythonObjectFactory factory) {
Object clazz = getClassNode.execute(inliningTarget, self);
Object args = getArgsNode.execute(inliningTarget, self);
Object state = getStateNode.execute(frame, self);
- return PFactory.createTuple(language, new Object[]{clazz, args, state});
+ return factory.createTuple(new Object[]{clazz, args, state});
}
}
}
From 0bc71d9f308d768cae266016c12e17373c74b908 Mon Sep 17 00:00:00 2001
From: stepan
Date: Thu, 22 May 2025 15:12:10 +0200
Subject: [PATCH 38/51] Fix transient error in tee builtins
(cherry picked from commit ff4d74e7916e773c7279eb18c51c7e7062b03181)
---
.../objects/itertools/TeeBuiltins.java | 29 +++++++------------
1 file changed, 11 insertions(+), 18 deletions(-)
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/itertools/TeeBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/itertools/TeeBuiltins.java
index 29fad45e82..69040f00c5 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/itertools/TeeBuiltins.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/itertools/TeeBuiltins.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
@@ -78,7 +78,6 @@
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
import com.oracle.truffle.api.dsl.Bind;
import com.oracle.truffle.api.dsl.Cached;
-import com.oracle.truffle.api.dsl.Cached.Shared;
import com.oracle.truffle.api.dsl.GenerateNodeFactory;
import com.oracle.truffle.api.dsl.ImportStatic;
import com.oracle.truffle.api.dsl.NeverDefault;
@@ -144,27 +143,21 @@ static Object iter(PTee self) {
@Builtin(name = J___NEXT__, minNumOfPositionalArgs = 1)
@GenerateNodeFactory
public abstract static class NextNode extends PythonUnaryBuiltinNode {
- @Specialization(guards = "self.getIndex() < LINKCELLS")
- static Object next(VirtualFrame frame, PTee self,
+ @Specialization
+ static Object doIt(VirtualFrame frame, PTee self,
@Bind("this") Node inliningTarget,
- @Shared @Cached BuiltinFunctions.NextNode nextNode,
- @Shared @Cached PRaiseNode.Lazy raiseNode) {
+ @Cached PythonObjectFactory factory,
+ @Cached InlinedConditionProfile indexConditionProfile,
+ @Cached BuiltinFunctions.NextNode nextNode,
+ @Cached PRaiseNode.Lazy raiseNode) {
+ if (indexConditionProfile.profile(inliningTarget, self.getIndex() >= LINKCELLS)) {
+ self.setDataObj(self.getDataobj().jumplink(factory));
+ self.setIndex(0);
+ }
Object value = self.getDataobj().getItem(frame, inliningTarget, self.getIndex(), nextNode, raiseNode);
self.setIndex(self.getIndex() + 1);
return value;
}
-
- @Specialization(guards = "self.getIndex() >= LINKCELLS")
- static Object nextNext(VirtualFrame frame, PTee self,
- @Bind("this") Node inliningTarget,
- @Shared @Cached BuiltinFunctions.NextNode nextNode,
- @Cached PythonObjectFactory factory,
- @Shared @Cached PRaiseNode.Lazy raiseNode) {
- self.setDataObj(self.getDataobj().jumplink(factory));
- Object value = self.getDataobj().getItem(frame, inliningTarget, 0, nextNode, raiseNode);
- self.setIndex(1);
- return value;
- }
}
@Builtin(name = J___REDUCE__, minNumOfPositionalArgs = 1)
From 2b1ceb2cb80f82aa46c45bcee7240b46c85cf137 Mon Sep 17 00:00:00 2001
From: Tim Felgentreff
Date: Thu, 10 Apr 2025 19:39:54 +0200
Subject: [PATCH 39/51] Add _io._WindowsConsoleIO on Windows. Fixes #490
(cherry picked from commit e41945c9e2863670dbcdc963c2165d2b07544f43)
fix conflicts for Add _io._WindowsConsoleIO on Windows
---
.../oracle/graal/python/builtins/PythonBuiltinClassType.java | 1 +
.../graal/python/builtins/modules/io/IOModuleBuiltins.java | 4 +++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java
index 8d586cc758..02affaa5cd 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/PythonBuiltinClassType.java
@@ -336,6 +336,7 @@ public enum PythonBuiltinClassType implements TruffleObject {
PStringIO("StringIO", "_io", Flags.PUBLIC_BASE_WDICT),
PBytesIO("BytesIO", "_io", Flags.PUBLIC_BASE_WDICT),
PBytesIOBuf("_BytesIOBuffer", "_io", Flags.PRIVATE_BASE_WODICT),
+ PWindowsConsoleIO("_WindowsConsoleIO", "_io", Flags.PRIVATE_BASE_WODICT),
PStatResult("stat_result", "os", Flags.PUBLIC_DERIVED_WODICT, TUPLE_M_FLAGS),
PStatvfsResult("statvfs_result", "os", Flags.PUBLIC_DERIVED_WODICT, TUPLE_M_FLAGS),
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/io/IOModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/io/IOModuleBuiltins.java
index 6cc698da4d..da35249a4e 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/io/IOModuleBuiltins.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/io/IOModuleBuiltins.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
@@ -52,6 +52,7 @@
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.PIncrementalNewlineDecoder;
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.PTextIOWrapper;
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.ValueError;
+import static com.oracle.graal.python.builtins.PythonBuiltinClassType.PWindowsConsoleIO;
import static com.oracle.graal.python.builtins.modules.WarningsModuleBuiltins.T_WARN;
import static com.oracle.graal.python.builtins.modules.io.BufferedIOUtil.SEEK_CUR;
import static com.oracle.graal.python.builtins.modules.io.BufferedIOUtil.SEEK_END;
@@ -144,6 +145,7 @@ public void initialize(Python3Core core) {
addBuiltinConstant("_warn", core.lookupBuiltinModule(T__WARNINGS).getAttribute(T_WARN));
if (PythonOS.getPythonOS() == PythonOS.PLATFORM_WIN32) {
addBuiltinConstant("_os", core.lookupBuiltinModule(T_NT));
+ addBuiltinConstant("_WindowsConsoleIO", PWindowsConsoleIO);
} else {
addBuiltinConstant("_os", core.lookupBuiltinModule(T_POSIX));
}
From 970415036c1b54f5d357bf061536dd17beaca035 Mon Sep 17 00:00:00 2001
From: Tim Felgentreff
Date: Thu, 10 Apr 2025 20:26:53 +0200
Subject: [PATCH 40/51] Add an _nt core module for Windows-specific startup
code. Fixes #493
(cherry picked from commit 2177ebd913c877a2d2b1bac496c2bc3e8d9eb356)
fix conflicts for Add an _nt core module for Windows-specific startup code
---
graalpython/com.oracle.graal.python.frozen/freeze_modules.py | 1 +
.../src/com/oracle/graal/python/builtins/Python3Core.java | 5 +++++
.../graal/python/builtins/objects/module/FrozenModules.java | 3 +++
3 files changed, 9 insertions(+)
diff --git a/graalpython/com.oracle.graal.python.frozen/freeze_modules.py b/graalpython/com.oracle.graal.python.frozen/freeze_modules.py
index c08d654cd6..f4329ad710 100644
--- a/graalpython/com.oracle.graal.python.frozen/freeze_modules.py
+++ b/graalpython/com.oracle.graal.python.frozen/freeze_modules.py
@@ -119,6 +119,7 @@ def add_graalpython_core():
"java",
"pip_hook",
"unicodedata",
+ "_nt",
]:
modname = f"graalpy.{os.path.basename(name)}"
modpath = os.path.join(lib_graalpython, f"{name}.py")
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java
index 6f6254b9d8..3a0902e54e 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java
@@ -423,6 +423,11 @@ private static TruffleString[] initializeCoreFiles() {
toTruffleStringUncached("_sysconfig"),
toTruffleStringUncached("java"),
toTruffleStringUncached("pip_hook")));
+ if (PythonOS.getPythonOS() == PythonOS.PLATFORM_WIN32) {
+ coreFiles = new ArrayList<>(coreFiles);
+ coreFiles.add(toTruffleStringUncached("_nt"));
+ }
+
// add service loader defined python file extensions
if (!ImageInfo.inImageRuntimeCode()) {
ServiceLoader providers = ServiceLoader.load(PythonBuiltins.class, Python3Core.class.getClassLoader());
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/module/FrozenModules.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/module/FrozenModules.java
index ad7000fa5e..bed5461204 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/module/FrozenModules.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/module/FrozenModules.java
@@ -227,6 +227,7 @@ private static final class Map {
private static final PythonFrozenModule GRAALPY_JAVA = new PythonFrozenModule("GRAALPY_JAVA", null, false);
private static final PythonFrozenModule GRAALPY_PIP_HOOK = new PythonFrozenModule("GRAALPY_PIP_HOOK", null, false);
private static final PythonFrozenModule GRAALPY_UNICODEDATA = new PythonFrozenModule("GRAALPY_UNICODEDATA", null, false);
+ private static final PythonFrozenModule GRAALPY__NT = new PythonFrozenModule("GRAALPY__NT", null, false);
}
public static final PythonFrozenModule lookup(String name) {
@@ -613,6 +614,8 @@ public static final PythonFrozenModule lookup(String name) {
return Map.GRAALPY_PIP_HOOK;
case "graalpy.unicodedata":
return Map.GRAALPY_UNICODEDATA;
+ case "graalpy._nt":
+ return Map.GRAALPY__NT;
default:
return null;
}
From e517dbab088e36914249b7c9328ec6169ca2b227 Mon Sep 17 00:00:00 2001
From: Tim Felgentreff
Date: Thu, 10 Apr 2025 20:38:25 +0200
Subject: [PATCH 41/51] Observe more pyenv.cfg properties as set by virtualenv.
Fixes #491
(cherry picked from commit 8087d3dde1f7640a68039f11b132cfa1c40d91bf)
---
.../graal/python/shell/GraalPythonMain.java | 102 ++++++++++--------
1 file changed, 59 insertions(+), 43 deletions(-)
diff --git a/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java b/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java
index f0a6328d1f..a0f2643575 100644
--- a/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java
+++ b/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java
@@ -931,54 +931,70 @@ private void findAndApplyVenvCfg(Builder contextBuilder, String executable) {
continue;
}
String name = parts[0].trim();
- if (name.equals("home")) {
- try {
- Path homeProperty = Paths.get(parts[1].trim());
- Path graalpyHome = homeProperty;
- /*
- * (tfel): According to PEP 405, the home key is the directory of the Python
- * executable from which this virtual environment was created, that is, it
- * usually ends with "/bin" on a Unix system. On Windows, the base Python
- * should be in the top-level directory or under "\Scripts". To support
- * running from Maven artifacts where we don't have a working executable, we
- * patched our shipped venv module to set the home path without a "/bin" or
- * "\\Scripts" suffix, so we explicitly check for those two subfolder cases
- * and otherwise assume the home key is directly pointing to the Python
- * home.
- */
- if (graalpyHome.endsWith("bin") || graalpyHome.endsWith("Scripts")) {
- graalpyHome = graalpyHome.getParent();
- }
- contextBuilder.option("python.PythonHome", graalpyHome.toString());
- /*
- * First try to resolve symlinked executables, since that may be more
- * accurate than assuming the executable in 'home'.
- */
- Path baseExecutable = null;
+ switch (name) {
+ case "home":
try {
- Path realPath = executablePath.toRealPath();
- if (!realPath.equals(executablePath.toAbsolutePath())) {
- baseExecutable = realPath;
+ Path homeProperty = Paths.get(parts[1].trim());
+ Path graalpyHome = homeProperty;
+ /*
+ * (tfel): According to PEP 405, the home key is the directory of the
+ * Python executable from which this virtual environment was created,
+ * that is, it usually ends with "/bin" on a Unix system. On Windows,
+ * the base Python should be in the top-level directory or under
+ * "\Scripts". To support running from Maven artifacts where we don't
+ * have a working executable, we patched our shipped venv module to set
+ * the home path without a "/bin" or "\\Scripts" suffix, so we
+ * explicitly check for those two subfolder cases and otherwise assume
+ * the home key is directly pointing to the Python home.
+ */
+ if (graalpyHome.endsWith("bin") || graalpyHome.endsWith("Scripts")) {
+ graalpyHome = graalpyHome.getParent();
}
- } catch (IOException ex) {
- // Ignore
- }
- if (baseExecutable == null) {
- baseExecutable = homeProperty.resolve(executablePath.getFileName());
- }
- if (Files.exists(baseExecutable)) {
- contextBuilder.option("python.BaseExecutable", baseExecutable.toString());
+ contextBuilder.option("python.PythonHome", graalpyHome.toString());
/*
- * This is needed to support the legacy GraalVM layout where the
- * executable is a symlink into the 'languages' directory.
+ * First try to resolve symlinked executables, since that may be more
+ * accurate than assuming the executable in 'home'.
*/
- contextBuilder.option("python.PythonHome", baseExecutable.getParent().getParent().toString());
+ Path baseExecutable = null;
+ try {
+ Path realPath = executablePath.toRealPath();
+ if (!realPath.equals(executablePath.toAbsolutePath())) {
+ baseExecutable = realPath;
+ }
+ } catch (IOException ex) {
+ // Ignore
+ }
+ if (baseExecutable == null) {
+ baseExecutable = homeProperty.resolve(executablePath.getFileName());
+ }
+ if (Files.exists(baseExecutable)) {
+ contextBuilder.option("python.BaseExecutable", baseExecutable.toString());
+ /*
+ * This is needed to support the legacy GraalVM layout where the
+ * executable is a symlink into the 'languages' directory.
+ */
+ contextBuilder.option("python.PythonHome", baseExecutable.getParent().getParent().toString());
+ }
+ } catch (NullPointerException | InvalidPathException ex) {
+ // NullPointerException covers the possible null result of getParent()
+ warn("Could not set PYTHONHOME according to the pyvenv.cfg file.");
}
- } catch (NullPointerException | InvalidPathException ex) {
- // NullPointerException covers the possible null result of getParent()
- warn("Could not set PYTHONHOME according to the pyvenv.cfg file.");
- }
- break;
+ break;
+ case "venvlauncher_command":
+ if (!hasContextOptionSetViaCommandLine("VenvlauncherCommand")) {
+ contextBuilder.option("python.VenvlauncherCommand", parts[1].trim());
+ }
+ break;
+ case "base-prefix":
+ if (!hasContextOptionSetViaCommandLine("SysBasePrefix")) {
+ contextBuilder.option("python.SysBasePrefix", parts[1].trim());
+ }
+ break;
+ case "base-executable":
+ if (!hasContextOptionSetViaCommandLine("BaseExecutable")) {
+ contextBuilder.option("python.BaseExecutable", parts[1].trim());
+ }
+ break;
}
}
} catch (IOException ex) {
From cde32089f4c6374ba2718987096d7a198157fe5e Mon Sep 17 00:00:00 2001
From: Tim Felgentreff
Date: Thu, 10 Apr 2025 20:47:59 +0200
Subject: [PATCH 42/51] Avoid updates to FrozenModules.java when just newlines
change away from unix
(cherry picked from commit ba017ce5fea8bc41325f8404b4065a503d49bda2)
---
.../com.oracle.graal.python.frozen/freeze_modules.py | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/graalpython/com.oracle.graal.python.frozen/freeze_modules.py b/graalpython/com.oracle.graal.python.frozen/freeze_modules.py
index f4329ad710..178885a2a1 100644
--- a/graalpython/com.oracle.graal.python.frozen/freeze_modules.py
+++ b/graalpython/com.oracle.graal.python.frozen/freeze_modules.py
@@ -589,19 +589,27 @@ def write_frozen_module_file(file, modules):
if os.path.exists(file):
with open(file, "r", encoding="utf-8", newline=os.linesep) as f:
content = f.read()
+ if os.linesep != "\n":
+ if content.replace(os.linesep, "\n") == content:
+ # Windows file has Unix line endings
+ linesep = "\n"
+ else:
+ linesep = os.linesep
+ else:
+ linesep = "\n"
stat_result = os.stat(file)
atime, mtime = stat_result.st_atime, stat_result.st_mtime
else:
content = None
os.makedirs(os.path.dirname(file), exist_ok=True)
- with open(file, "w", encoding="utf-8", newline=os.linesep) as out_file:
+ with open(file, "w", encoding="utf-8", newline=linesep) as out_file:
out_file.write(FROZEN_MODULES_HEADER)
out_file.write("\n\n")
write_frozen_modules_map(out_file, modules)
out_file.write("\n")
write_frozen_lookup(out_file, modules)
out_file.write("}\n")
- with open(file, "r", encoding="utf-8", newline=os.linesep) as f:
+ with open(file, "r", encoding="utf-8", newline=linesep) as f:
new_content = f.read()
if new_content == content:
# set mtime to the old one, if we didn't change anything
From eb09405f5520e49acc892a55b825efd5515bf2ad Mon Sep 17 00:00:00 2001
From: Tim Felgentreff
Date: Thu, 10 Apr 2025 21:18:42 +0200
Subject: [PATCH 43/51] Remove workaround for Windows for discovering visual
studio, we now use vswhere. Fixes #492
(cherry picked from commit 18d85633e013a0290c98dd7c83a9a20559ec9bbc)
---
.../python/builtins/modules/PosixModuleBuiltins.java | 9 ---------
mx.graalpython/mx_graalpython.py | 2 ++
2 files changed, 2 insertions(+), 9 deletions(-)
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java
index edae5c6846..e294f9b999 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java
@@ -366,15 +366,6 @@ public void postInitialize(Python3Core core) {
if (PythonOS.getPythonOS() == PythonOS.PLATFORM_WIN32) {
// XXX: Until we fix pip
environ.setItem(toTruffleStringUncached("PIP_NO_CACHE_DIR"), toTruffleStringUncached("0"));
- // XXX: Until we have working winapi and winreg modules for MSVC discovery
- environ.setItem(toTruffleStringUncached("DISTUTILS_USE_SDK"), toTruffleStringUncached("1"));
- if (getenv.get("MSSdk") == null) {
- String sdkdir = getenv.get("WindowsSdkDir");
- if (sdkdir == null) {
- sdkdir = "unset";
- }
- environ.setItem(toTruffleStringUncached("MSSdk"), toTruffleStringUncached(sdkdir));
- }
}
PythonModule posix;
if (PythonOS.getPythonOS() == PythonOS.PLATFORM_WIN32) {
diff --git a/mx.graalpython/mx_graalpython.py b/mx.graalpython/mx_graalpython.py
index f86fdbf2a0..62542a46dd 100644
--- a/mx.graalpython/mx_graalpython.py
+++ b/mx.graalpython/mx_graalpython.py
@@ -170,6 +170,8 @@ def getArchivableResultsWithLib(self, *args, **kwargs):
if os.path.isfile(os.path.join(os.path.abspath(p), "cl.exe")):
mx.log("LIB and INCLUDE set, cl.exe on PATH, assuming this is a VS shell")
os.environ["DISTUTILS_USE_SDK"] = "1"
+ if not os.environ.get("MSSdk"):
+ os.environ["MSSdk"] = os.environ.get("WindowsSdkDir", "unset")
break
else:
mx.log("cl.exe not on PATH, not a VS shell")
From 374711966f42a6edaf6bbed88b632402b905e1fd Mon Sep 17 00:00:00 2001
From: Tim Felgentreff
Date: Thu, 10 Apr 2025 22:59:35 +0200
Subject: [PATCH 44/51] Fix startup modules test on Windows
(cherry picked from commit 87fa7a45b9b0974373b74836810f56e0274868e9)
adapt fix
---
.../freeze_modules.py | 4 +-
.../src/tests/test_startup.py | 90 +++++++++++++++++++
.../builtins/modules/PosixModuleBuiltins.java | 2 +-
.../objects/module/FrozenModules.java | 2 +-
graalpython/lib-graalpython/_nt.py | 54 +++++++++++
5 files changed, 148 insertions(+), 4 deletions(-)
create mode 100644 graalpython/com.oracle.graal.python.test/src/tests/test_startup.py
create mode 100644 graalpython/lib-graalpython/_nt.py
diff --git a/graalpython/com.oracle.graal.python.frozen/freeze_modules.py b/graalpython/com.oracle.graal.python.frozen/freeze_modules.py
index 178885a2a1..0e9e1f7b4d 100644
--- a/graalpython/com.oracle.graal.python.frozen/freeze_modules.py
+++ b/graalpython/com.oracle.graal.python.frozen/freeze_modules.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2021, 2024, Oracle and/or its affiliates.
+# Copyright (c) 2021, 2025, Oracle and/or its affiliates.
# Copyright (C) 1996-2020 Python Software Foundation
#
# Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
@@ -496,7 +496,7 @@ def lower_camel_case(str):
# write frozen files
FROZEN_MODULES_HEADER = """/*
- * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
diff --git a/graalpython/com.oracle.graal.python.test/src/tests/test_startup.py b/graalpython/com.oracle.graal.python.test/src/tests/test_startup.py
new file mode 100644
index 0000000000..b17986a53c
--- /dev/null
+++ b/graalpython/com.oracle.graal.python.test/src/tests/test_startup.py
@@ -0,0 +1,90 @@
+# Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# The Universal Permissive License (UPL), Version 1.0
+#
+# Subject to the condition set forth below, permission is hereby granted to any
+# person obtaining a copy of this software, associated documentation and/or
+# data (collectively the "Software"), free of charge and under any and all
+# copyright rights in the Software, and any and all patent rights owned or
+# freely licensable by each licensor hereunder covering either (i) the
+# unmodified Software as contributed to or provided by such licensor, or (ii)
+# the Larger Works (as defined below), to deal in both
+#
+# (a) the Software, and
+#
+# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+# one is included with the Software each a "Larger Work" to which the Software
+# is contributed by such licensors),
+#
+# without restriction, including without limitation the rights to copy, create
+# derivative works of, display, perform, and distribute the Software and make,
+# use, sell, offer for sale, import, export, have made, and have sold the
+# Software and the Larger Work(s), and to sublicense the foregoing rights on
+# either these or other terms.
+#
+# This license is subject to the following condition:
+#
+# The above copyright notice and either this complete permission notice or at a
+# minimum a reference to the UPL must be included in all copies or substantial
+# portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+import unittest
+import sys
+import re
+import subprocess
+import platform
+
+# Both lists should remain as small as possible to avoid adding overhead to startup
+expected_nosite_startup_modules = [
+ '_frozen_importlib',
+ '_frozen_importlib_external',
+ 'builtins',
+ '__graalpython__',
+ '_weakref',
+ 'unicodedata',
+ '_sre',
+ '_sysconfig',
+ 'java',
+ 'pip_hook',
+] + (['_nt'] if platform.system() == 'Windows' else [])
+
+expected_full_startup_modules = expected_nosite_startup_modules + [
+ '_abc',
+ 'types',
+ '_weakrefset',
+ '_py_abc',
+ 'abc',
+ 'stat',
+ '_collections_abc',
+ 'genericpath',
+ *(['_winapi', 'ntpath'] if platform.system() == 'Windows' else ['posixpath']),
+ 'os',
+ '_sitebuiltins',
+ '_io',
+ 'io',
+ 'site',
+]
+
+class StartupTests(unittest.TestCase):
+ @unittest.skipUnless(sys.implementation.name == 'graalpy', "GraalPy-specific test")
+ def test_startup_nosite(self):
+ result = subprocess.check_output([sys.executable, '--log.level=FINE', '-S', '-v', '-c', 'print("Hello")'], stderr=subprocess.STDOUT, text=True)
+ assert 'Hello' in result
+ imports = re.findall("import '(\S+)'", result)
+ self.assertEqual(expected_nosite_startup_modules, imports)
+
+ @unittest.skipUnless(sys.implementation.name == 'graalpy', "GraalPy-specific test")
+ def test_startup_full(self):
+ result = subprocess.check_output([sys.executable, '--log.level=FINE', '-s', '-v', '-c', 'print("Hello")'], stderr=subprocess.STDOUT, text=True)
+ assert 'Hello' in result
+ imports = re.findall("import '(\S+)'", result)
+ self.assertEqual(expected_full_startup_modules, imports)
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java
index e294f9b999..2d567ece0e 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2024, Oracle and/or its affiliates.
+ * Copyright (c) 2018, 2025, Oracle and/or its affiliates.
* Copyright (c) 2014, Regents of the University of California
*
* All rights reserved.
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/module/FrozenModules.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/module/FrozenModules.java
index bed5461204..ad0f4c1266 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/module/FrozenModules.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/module/FrozenModules.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
diff --git a/graalpython/lib-graalpython/_nt.py b/graalpython/lib-graalpython/_nt.py
new file mode 100644
index 0000000000..4fbd2a2591
--- /dev/null
+++ b/graalpython/lib-graalpython/_nt.py
@@ -0,0 +1,54 @@
+# Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# The Universal Permissive License (UPL), Version 1.0
+#
+# Subject to the condition set forth below, permission is hereby granted to any
+# person obtaining a copy of this software, associated documentation and/or
+# data (collectively the "Software"), free of charge and under any and all
+# copyright rights in the Software, and any and all patent rights owned or
+# freely licensable by each licensor hereunder covering either (i) the
+# unmodified Software as contributed to or provided by such licensor, or (ii)
+# the Larger Works (as defined below), to deal in both
+#
+# (a) the Software, and
+#
+# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+# one is included with the Software each a "Larger Work" to which the Software
+# is contributed by such licensors),
+#
+# without restriction, including without limitation the rights to copy, create
+# derivative works of, display, perform, and distribute the Software and make,
+# use, sell, offer for sale, import, export, have made, and have sold the
+# Software and the Larger Work(s), and to sublicense the foregoing rights on
+# either these or other terms.
+#
+# This license is subject to the following condition:
+#
+# The above copyright notice and either this complete permission notice or at a
+# minimum a reference to the UPL must be included in all copies or substantial
+# portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+import nt
+
+
+def _add_dll_directory(path):
+ import ctypes
+ return ctypes.windll.kernel32.AddDllDirectory(path)
+
+
+def _remove_dll_directory(cookie):
+ import ctypes
+ return ctypes.windll.kernel32.RemoveDllDirectory(cookie)
+
+
+nt._add_dll_directory = _add_dll_directory
+nt._remove_dll_directory = _remove_dll_directory
\ No newline at end of file
From 8e2c103c4cff0bae38be164509d3f302469befeb Mon Sep 17 00:00:00 2001
From: Benoit Daloze
Date: Tue, 4 Feb 2025 12:21:06 +0100
Subject: [PATCH 45/51] Only register_interop_behavior() for datetime & time
when they are imported
* Otherwise just loading polyglot has the heavy cost of loading datetime too.
* This way the interop behavior is defined regardless of whether `import polyglot` was done (without relying on polyglot to be loaded at startup).
(cherry picked from commit 08923297e9ff89a3235461d311beda97bbfbf22b)
---
.../builtins/modules/TimeModuleBuiltins.java | 7 +-
graalpython/lib-graalpython/_polyglot.py | 65 +-------------
.../lib-graalpython/_polyglot_datetime.py | 60 +++++++++++++
graalpython/lib-graalpython/_polyglot_time.py | 84 +++++++++++++++++++
graalpython/lib-python/3/datetime.py | 2 +
5 files changed, 153 insertions(+), 65 deletions(-)
create mode 100644 graalpython/lib-graalpython/_polyglot_datetime.py
create mode 100644 graalpython/lib-graalpython/_polyglot_time.py
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TimeModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TimeModuleBuiltins.java
index 46bd74525e..6eec222635 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TimeModuleBuiltins.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/TimeModuleBuiltins.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2024, Oracle and/or its affiliates.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates.
* Copyright (c) 2013, Regents of the University of California
*
* All rights reserved.
@@ -49,6 +49,7 @@
import java.util.List;
import java.util.TimeZone;
+import com.oracle.graal.python.nodes.statement.AbstractImportNode;
import org.graalvm.nativeimage.ImageInfo;
import com.oracle.graal.python.annotations.ArgumentClinic;
@@ -153,6 +154,7 @@ public final class TimeModuleBuiltins extends PythonBuiltins {
public static final TruffleString T_DAYLIGHT = tsLiteral("daylight");
public static final TruffleString T_TIMEZONE = tsLiteral("timezone");
public static final TruffleString T_ALTZONE = tsLiteral("altzone");
+ public static final TruffleString T_POLYGLOT_TIME = tsLiteral("_polyglot_time");
@Override
protected List extends NodeFactory extends PythonBuiltinBaseNode>> getNodeFactories() {
@@ -192,6 +194,9 @@ public void postInitialize(Python3Core core) {
int rawOffsetSeconds = defaultTimeZone.getRawOffset() / -1000;
timeModule.setAttribute(T_TIMEZONE, rawOffsetSeconds);
timeModule.setAttribute(T_ALTZONE, rawOffsetSeconds - 3600);
+
+ // register_interop_behavior() for time.struct_time
+ AbstractImportNode.importModule(T_POLYGLOT_TIME);
}
@TruffleBoundary
diff --git a/graalpython/lib-graalpython/_polyglot.py b/graalpython/lib-graalpython/_polyglot.py
index caf9cebdc0..770575c8a8 100644
--- a/graalpython/lib-graalpython/_polyglot.py
+++ b/graalpython/lib-graalpython/_polyglot.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# The Universal Permissive License (UPL), Version 1.0
@@ -37,9 +37,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
-import datetime
import polyglot
-import time
def interop_type(foreign_class, allow_method_overwrites=False):
@@ -112,37 +110,6 @@ def wrapper(python_class):
setattr(polyglot, "interop_behavior", interop_behavior)
-def _date_time_tz(dt: datetime.datetime):
- if dt.tzinfo is not None:
- utcoffset = dt.tzinfo.utcoffset(dt)
- return utcoffset.days * 3600 * 24 + utcoffset.seconds
- raise polyglot.UnsupportedMessage
-
-
-def _struct_time_tz(st: time.struct_time):
- if st.tm_gmtoff is not None:
- return st.tm_gmtoff
- return st.tm_zone
-
-
-polyglot.register_interop_behavior(datetime.time,
- is_time=True, as_time=lambda d: (d.hour, d.minute, d.second, d.microsecond),
- is_time_zone=lambda t: t.tzinfo is not None, as_time_zone=_date_time_tz)
-
-polyglot.register_interop_behavior(datetime.date,
- is_date=True, as_date=lambda d: (d.year, d.month, d.day))
-
-polyglot.register_interop_behavior(datetime.datetime,
- is_date=True, as_date=lambda d: (d.year, d.month, d.day),
- is_time=True, as_time=lambda d: (d.hour, d.minute, d.second, d.microsecond),
- is_time_zone=lambda t: t.tzinfo is not None, as_time_zone=_date_time_tz)
-
-polyglot.register_interop_behavior(time.struct_time,
- is_date=True, as_date=lambda t: (t.tm_year, t.tm_mon, t.tm_mday),
- is_time=True, as_time=lambda t: (t.tm_hour, t.tm_min, t.tm_sec, 0),
- is_time_zone=lambda t: t.tm_zone is not None or t.tm_gmtoff is not None,
- as_time_zone=_struct_time_tz)
-
# loading arrow structures on demand
def __getattr__(name):
if name == "arrow":
@@ -153,33 +120,3 @@ def __getattr__(name):
setattr(polyglot, "__getattr__", __getattr__)
setattr(polyglot, "__path__", ".")
-
-# example extending time.struct_time using the decorator wrapper
-#
-# @polyglot.interop_behavior(time.struct_time)
-# class StructTimeInteropBehavior:
-# @staticmethod
-# def is_date(t):
-# return True
-#
-# @staticmethod
-# def as_date(t):
-# return t.tm_year, t.tm_mon, t.tm_mday
-#
-# @staticmethod
-# def is_time(t):
-# return True
-#
-# @staticmethod
-# def as_time(t):
-# return t.tm_hour, t.tm_min, t.tm_sec, 0
-#
-# @staticmethod
-# def is_time_zone(t):
-# return t.tm_zone is not None or t.tm_gmtoff is not None
-#
-# @staticmethod
-# def as_time_zone(t):
-# if t.tm_gmtoff is not None:
-# return t.tm_gmtoff
-# return t.tm_zone
diff --git a/graalpython/lib-graalpython/_polyglot_datetime.py b/graalpython/lib-graalpython/_polyglot_datetime.py
new file mode 100644
index 0000000000..80f73a74de
--- /dev/null
+++ b/graalpython/lib-graalpython/_polyglot_datetime.py
@@ -0,0 +1,60 @@
+# Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# The Universal Permissive License (UPL), Version 1.0
+#
+# Subject to the condition set forth below, permission is hereby granted to any
+# person obtaining a copy of this software, associated documentation and/or
+# data (collectively the "Software"), free of charge and under any and all
+# copyright rights in the Software, and any and all patent rights owned or
+# freely licensable by each licensor hereunder covering either (i) the
+# unmodified Software as contributed to or provided by such licensor, or (ii)
+# the Larger Works (as defined below), to deal in both
+#
+# (a) the Software, and
+#
+# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+# one is included with the Software each a "Larger Work" to which the Software
+# is contributed by such licensors),
+#
+# without restriction, including without limitation the rights to copy, create
+# derivative works of, display, perform, and distribute the Software and make,
+# use, sell, offer for sale, import, export, have made, and have sold the
+# Software and the Larger Work(s), and to sublicense the foregoing rights on
+# either these or other terms.
+#
+# This license is subject to the following condition:
+#
+# The above copyright notice and either this complete permission notice or at a
+# minimum a reference to the UPL must be included in all copies or substantial
+# portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+import datetime
+import polyglot
+
+def _date_time_tz(dt: datetime.datetime):
+ if dt.tzinfo is not None:
+ utcoffset = dt.tzinfo.utcoffset(dt)
+ return utcoffset.days * 3600 * 24 + utcoffset.seconds
+ raise polyglot.UnsupportedMessage
+
+
+polyglot.register_interop_behavior(datetime.time,
+ is_time=True, as_time=lambda d: (d.hour, d.minute, d.second, d.microsecond),
+ is_time_zone=lambda t: t.tzinfo is not None, as_time_zone=_date_time_tz)
+
+polyglot.register_interop_behavior(datetime.date,
+ is_date=True, as_date=lambda d: (d.year, d.month, d.day))
+
+polyglot.register_interop_behavior(datetime.datetime,
+ is_date=True, as_date=lambda d: (d.year, d.month, d.day),
+ is_time=True, as_time=lambda d: (d.hour, d.minute, d.second, d.microsecond),
+ is_time_zone=lambda t: t.tzinfo is not None, as_time_zone=_date_time_tz)
diff --git a/graalpython/lib-graalpython/_polyglot_time.py b/graalpython/lib-graalpython/_polyglot_time.py
new file mode 100644
index 0000000000..ed4dc0fc54
--- /dev/null
+++ b/graalpython/lib-graalpython/_polyglot_time.py
@@ -0,0 +1,84 @@
+# Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# The Universal Permissive License (UPL), Version 1.0
+#
+# Subject to the condition set forth below, permission is hereby granted to any
+# person obtaining a copy of this software, associated documentation and/or
+# data (collectively the "Software"), free of charge and under any and all
+# copyright rights in the Software, and any and all patent rights owned or
+# freely licensable by each licensor hereunder covering either (i) the
+# unmodified Software as contributed to or provided by such licensor, or (ii)
+# the Larger Works (as defined below), to deal in both
+#
+# (a) the Software, and
+#
+# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
+# one is included with the Software each a "Larger Work" to which the Software
+# is contributed by such licensors),
+#
+# without restriction, including without limitation the rights to copy, create
+# derivative works of, display, perform, and distribute the Software and make,
+# use, sell, offer for sale, import, export, have made, and have sold the
+# Software and the Larger Work(s), and to sublicense the foregoing rights on
+# either these or other terms.
+#
+# This license is subject to the following condition:
+#
+# The above copyright notice and either this complete permission notice or at a
+# minimum a reference to the UPL must be included in all copies or substantial
+# portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+import time
+import polyglot
+
+
+def _struct_time_tz(st: time.struct_time):
+ if st.tm_gmtoff is not None:
+ return st.tm_gmtoff
+ return st.tm_zone
+
+
+polyglot.register_interop_behavior(time.struct_time,
+ is_date=True, as_date=lambda t: (t.tm_year, t.tm_mon, t.tm_mday),
+ is_time=True, as_time=lambda t: (t.tm_hour, t.tm_min, t.tm_sec, 0),
+ is_time_zone=lambda t: t.tm_zone is not None or t.tm_gmtoff is not None,
+ as_time_zone=_struct_time_tz)
+
+# example extending time.struct_time using the decorator wrapper
+#
+# @polyglot.interop_behavior(time.struct_time)
+# class StructTimeInteropBehavior:
+# @staticmethod
+# def is_date(t):
+# return True
+#
+# @staticmethod
+# def as_date(t):
+# return t.tm_year, t.tm_mon, t.tm_mday
+#
+# @staticmethod
+# def is_time(t):
+# return True
+#
+# @staticmethod
+# def as_time(t):
+# return t.tm_hour, t.tm_min, t.tm_sec, 0
+#
+# @staticmethod
+# def is_time_zone(t):
+# return t.tm_zone is not None or t.tm_gmtoff is not None
+#
+# @staticmethod
+# def as_time_zone(t):
+# if t.tm_gmtoff is not None:
+# return t.tm_gmtoff
+# return t.tm_zone
diff --git a/graalpython/lib-python/3/datetime.py b/graalpython/lib-python/3/datetime.py
index e284a733ef..c564969464 100644
--- a/graalpython/lib-python/3/datetime.py
+++ b/graalpython/lib-python/3/datetime.py
@@ -2642,3 +2642,5 @@ def _name_from_offset(delta):
# appropriate to maintain a single module level docstring and
# remove the following line.
from _datetime import __doc__
+
+import _polyglot_datetime # GraalPy change: register interop behavior on datetime as soon as datetime is defined
From dedd1da23697e61e673337cf0498b8e7dcf86b6e Mon Sep 17 00:00:00 2001
From: Benoit Daloze
Date: Tue, 4 Feb 2025 12:27:08 +0100
Subject: [PATCH 46/51] Let PolyglotModuleBuiltins#postInitialize load
_polyglot.py and don't force to load polyglot at startup
(cherry picked from commit 8bfdf1009e64b046eca9051381bafbd7bc668d85)
Fix conflict
---
.../src/com/oracle/graal/python/builtins/Python3Core.java | 3 ---
.../python/builtins/modules/PolyglotModuleBuiltins.java | 5 +++++
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java
index 3a0902e54e..54fa0008ae 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/Python3Core.java
@@ -1069,9 +1069,6 @@ public void run() {
}
}
- // import polyglot decorators and special interop predefined behavior
- loadFile(toTruffleStringUncached("_polyglot"), getContext().getCoreHomeOrFail());
-
initialized = true;
}
}
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PolyglotModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PolyglotModuleBuiltins.java
index 13843d5f67..5f0677b6f0 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PolyglotModuleBuiltins.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PolyglotModuleBuiltins.java
@@ -113,6 +113,7 @@
import com.oracle.graal.python.nodes.interop.InteropBehaviorMethod;
import com.oracle.graal.python.nodes.interop.PForeignToPTypeNode;
import com.oracle.graal.python.nodes.object.GetForeignObjectClassNode;
+import com.oracle.graal.python.nodes.statement.AbstractImportNode;
import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes;
import com.oracle.graal.python.nodes.util.CannotCastException;
import com.oracle.graal.python.nodes.util.CastToJavaStringNode;
@@ -161,6 +162,7 @@ public final class PolyglotModuleBuiltins extends PythonBuiltins {
private static final TruffleString T_MODIFIABLE = tsLiteral("modifiable");
private static final TruffleString T_INVOKABLE = tsLiteral("invokable");
private static final TruffleString T_INTERNAL = tsLiteral("internal");
+ private static final TruffleString T_INTERNAL_POLYGLOT_MODULE = tsLiteral("_polyglot");
@Override
protected List> getNodeFactories() {
@@ -189,6 +191,9 @@ public void postInitialize(Python3Core core) {
super.postInitialize(core);
GetForeignObjectClassNode.getUncached().defineSingleTraitClasses();
+
+ // import polyglot decorators which are defined in Python code
+ AbstractImportNode.importModule(T_INTERNAL_POLYGLOT_MODULE);
}
@Builtin(name = "import_value", minNumOfPositionalArgs = 1, parameterNames = {"name"})
From 7bea1cea40b8daeca0e2991eaead6aea2de73961 Mon Sep 17 00:00:00 2001
From: Benoit Daloze
Date: Tue, 4 Feb 2025 13:34:39 +0100
Subject: [PATCH 47/51] Modules need to be under lib-graalpython/modules to be
found by import
(cherry picked from commit 54b306398f2846076247a5dd03b0f3fe4232a894)
---
.../com.oracle.graal.python.frozen/freeze_modules.py | 4 +++-
.../builtins/objects/module/FrozenModules.java | 12 +++++++++---
.../lib-graalpython/{ => modules}/_polyglot.py | 0
.../{ => modules}/_polyglot_datetime.py | 0
.../lib-graalpython/{ => modules}/_polyglot_time.py | 0
5 files changed, 12 insertions(+), 4 deletions(-)
rename graalpython/lib-graalpython/{ => modules}/_polyglot.py (100%)
rename graalpython/lib-graalpython/{ => modules}/_polyglot_datetime.py (100%)
rename graalpython/lib-graalpython/{ => modules}/_polyglot_time.py (100%)
diff --git a/graalpython/com.oracle.graal.python.frozen/freeze_modules.py b/graalpython/com.oracle.graal.python.frozen/freeze_modules.py
index 0e9e1f7b4d..11212e9233 100644
--- a/graalpython/com.oracle.graal.python.frozen/freeze_modules.py
+++ b/graalpython/com.oracle.graal.python.frozen/freeze_modules.py
@@ -105,13 +105,15 @@ def add_graalpython_core():
l.append("polyglot.arrow : polyglot.arrow = " + os.path.join(lib_graalpython, "modules/_polyglot_arrow.py"))
for name in [
"modules/_sysconfigdata",
+ "modules/_polyglot",
+ "modules/_polyglot_datetime",
+ "modules/_polyglot_time",
]:
modname = os.path.basename(name)
modpath = os.path.join(lib_graalpython, f"{name}.py")
l.append(f"{modname} : {modname} = {modpath}")
for name in [
"__graalpython__",
- "_polyglot",
"_sre",
"_sysconfig",
"_weakref",
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/module/FrozenModules.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/module/FrozenModules.java
index ad0f4c1266..bef91e264c 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/module/FrozenModules.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/module/FrozenModules.java
@@ -218,8 +218,10 @@ private static final class Map {
private static final PythonFrozenModule FROZEN_ONLY = new PythonFrozenModule("FROZEN_ONLY", null, false);
private static final PythonFrozenModule POLYGLOT_ARROW = new PythonFrozenModule("POLYGLOT_ARROW", null, false);
private static final PythonFrozenModule _SYSCONFIGDATA = new PythonFrozenModule("_SYSCONFIGDATA", null, false);
+ private static final PythonFrozenModule _POLYGLOT = new PythonFrozenModule("_POLYGLOT", null, false);
+ private static final PythonFrozenModule _POLYGLOT_DATETIME = new PythonFrozenModule("_POLYGLOT_DATETIME", null, false);
+ private static final PythonFrozenModule _POLYGLOT_TIME = new PythonFrozenModule("_POLYGLOT_TIME", null, false);
private static final PythonFrozenModule GRAALPY___GRAALPYTHON__ = new PythonFrozenModule("GRAALPY___GRAALPYTHON__", null, false);
- private static final PythonFrozenModule GRAALPY__POLYGLOT = new PythonFrozenModule("GRAALPY__POLYGLOT", null, false);
private static final PythonFrozenModule GRAALPY__SRE = new PythonFrozenModule("GRAALPY__SRE", null, false);
private static final PythonFrozenModule GRAALPY__SYSCONFIG = new PythonFrozenModule("GRAALPY__SYSCONFIG", null, false);
private static final PythonFrozenModule GRAALPY__WEAKREF = new PythonFrozenModule("GRAALPY__WEAKREF", null, false);
@@ -596,10 +598,14 @@ public static final PythonFrozenModule lookup(String name) {
return Map.POLYGLOT_ARROW;
case "_sysconfigdata":
return Map._SYSCONFIGDATA;
+ case "_polyglot":
+ return Map._POLYGLOT;
+ case "_polyglot_datetime":
+ return Map._POLYGLOT_DATETIME;
+ case "_polyglot_time":
+ return Map._POLYGLOT_TIME;
case "graalpy.__graalpython__":
return Map.GRAALPY___GRAALPYTHON__;
- case "graalpy._polyglot":
- return Map.GRAALPY__POLYGLOT;
case "graalpy._sre":
return Map.GRAALPY__SRE;
case "graalpy._sysconfig":
diff --git a/graalpython/lib-graalpython/_polyglot.py b/graalpython/lib-graalpython/modules/_polyglot.py
similarity index 100%
rename from graalpython/lib-graalpython/_polyglot.py
rename to graalpython/lib-graalpython/modules/_polyglot.py
diff --git a/graalpython/lib-graalpython/_polyglot_datetime.py b/graalpython/lib-graalpython/modules/_polyglot_datetime.py
similarity index 100%
rename from graalpython/lib-graalpython/_polyglot_datetime.py
rename to graalpython/lib-graalpython/modules/_polyglot_datetime.py
diff --git a/graalpython/lib-graalpython/_polyglot_time.py b/graalpython/lib-graalpython/modules/_polyglot_time.py
similarity index 100%
rename from graalpython/lib-graalpython/_polyglot_time.py
rename to graalpython/lib-graalpython/modules/_polyglot_time.py
From 2847608254f6b84f83d669e457e9a38109596c54 Mon Sep 17 00:00:00 2001
From: Benoit Daloze
Date: Tue, 4 Feb 2025 14:35:03 +0100
Subject: [PATCH 48/51] graalpy -v should not override Truffle log level
* It's a CPython-compatible flag and should only set the Python flag, not touch log levels.
* Otherwise `graalpy --log.level=FINE -v ...` is actually at INFO and not FINE level which is very confusing.
(cherry picked from commit cea4899d01c51068978b53293150877009fdd19e)
---
.../src/com/oracle/graal/python/shell/GraalPythonMain.java | 3 ---
1 file changed, 3 deletions(-)
diff --git a/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java b/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java
index a0f2643575..a2c0dd21f1 100644
--- a/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java
+++ b/graalpython/com.oracle.graal.python.shell/src/com/oracle/graal/python/shell/GraalPythonMain.java
@@ -778,9 +778,6 @@ protected void launch(Builder contextBuilder) {
contextBuilder.option("python.IntMaxStrDigits", Integer.toString(intMaxStrDigits));
}
contextBuilder.option("python.DontWriteBytecodeFlag", Boolean.toString(dontWriteBytecode));
- if (verboseFlag) {
- contextBuilder.option("log.python.level", "INFO");
- }
contextBuilder.option("python.QuietFlag", Boolean.toString(quietFlag));
contextBuilder.option("python.NoUserSiteFlag", Boolean.toString(noUserSite));
contextBuilder.option("python.NoSiteFlag", Boolean.toString(noSite));
From 25e0fc6d88a669f348b7506f3a4c374d36f4dc78 Mon Sep 17 00:00:00 2001
From: Benoit Daloze
Date: Wed, 5 Feb 2025 13:22:01 +0100
Subject: [PATCH 49/51] Add test to track modules being imported during startup
(cherry picked from commit 378e4360cdf77473a6a96a77698bb2c3e2e3d649)
Fix conflict
---
.../graal/python/builtins/modules/PolyglotModuleBuiltins.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PolyglotModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PolyglotModuleBuiltins.java
index 5f0677b6f0..49507f1a1e 100644
--- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PolyglotModuleBuiltins.java
+++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PolyglotModuleBuiltins.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The Universal Permissive License (UPL), Version 1.0
From 093a5feebf414a875de07bb23b7ada7fb91059bf Mon Sep 17 00:00:00 2001
From: Marouane El Hallaoui
Date: Wed, 2 Jul 2025 15:56:44 +0100
Subject: [PATCH 50/51] release GraalVM 24.2.2
---
mx.graalpython/suite.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mx.graalpython/suite.py b/mx.graalpython/suite.py
index d4269ffd74..c790e424f7 100644
--- a/mx.graalpython/suite.py
+++ b/mx.graalpython/suite.py
@@ -11,7 +11,7 @@
"version": "24.2.2",
"graalpython:pythonVersion": "3.11.7",
- "release": False,
+ "release": True,
"groupId": "org.graalvm.python",
"url": "http://www.graalvm.org/python",
From 497720e5159a7c64188cdce16bafb526a97355f6 Mon Sep 17 00:00:00 2001
From: Marouane El Hallaoui
Date: Wed, 9 Jul 2025 12:34:35 +0100
Subject: [PATCH 51/51] set release flag to False
---
mx.graalpython/suite.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mx.graalpython/suite.py b/mx.graalpython/suite.py
index c790e424f7..d4269ffd74 100644
--- a/mx.graalpython/suite.py
+++ b/mx.graalpython/suite.py
@@ -11,7 +11,7 @@
"version": "24.2.2",
"graalpython:pythonVersion": "3.11.7",
- "release": True,
+ "release": False,
"groupId": "org.graalvm.python",
"url": "http://www.graalvm.org/python",
pFad - Phonifier reborn
Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy