From c1a2dc3d70b023a9738548dab3c659c697ecc5ad Mon Sep 17 00:00:00 2001 From: Michael Simacek Date: Wed, 29 Apr 2026 17:45:36 +0200 Subject: [PATCH 1/2] [GR-75252] Fix qualified exception names in PyErr_NewException --- .../src/tests/cpyext/test_object.py | 51 +++++++++++++++++-- .../modules/cext/PythonCextErrBuiltins.java | 8 +-- 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_object.py b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_object.py index ad5876e3d7..62985587bc 100644 --- a/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_object.py +++ b/graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_object.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2026, 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 @@ -41,7 +41,7 @@ import unittest from unittest import skipIf -from . import CPyExtType, CPyExtTestCase, CPyExtFunction, unhandled_error_compare, assert_raises +from . import CPyExtType, CPyExtTestCase, CPyExtFunction, compile_module_from_string, unhandled_error_compare, assert_raises is_windows = sys.platform == "win32" @@ -659,11 +659,56 @@ class MyClass: assert tester.get_tp_name(int) == 'int' assert tester.get_tp_name(type(tester)) == 'TestTpName.TestTpName' + def test_new_exception_with_qualified_name(self): + module = compile_module_from_string(""" + #include "Python.h" + + static PyModuleDef testmodule = { + PyModuleDef_HEAD_INIT, + "test_new_exception_with_qualified_name", + NULL, + -1, + NULL, + }; + + PyMODINIT_FUNC PyInit_test_new_exception_with_qualified_name(void) + { + PyObject *exception = PyErr_NewException("pkg.sub.CustomError", NULL, NULL); + if (exception == NULL) { + return NULL; + } + PyObject *module = PyModule_Create(&testmodule); + if (module == NULL) { + Py_DECREF(exception); + return NULL; + } + PyObject *name = PyObject_GetAttrString(exception, "__name__"); + if (name == NULL) { + Py_DECREF(exception); + Py_DECREF(module); + return NULL; + } + const char *name_str = PyUnicode_AsUTF8(name); + if (name_str == NULL || PyModule_AddObject(module, name_str, exception) < 0) { + Py_DECREF(name); + Py_DECREF(exception); + Py_DECREF(module); + return NULL; + } + Py_DECREF(name); + return module; + } + """, "test_new_exception_with_qualified_name") + assert module.CustomError.__name__ == "CustomError" + assert module.CustomError.__qualname__ == "CustomError" + assert module.CustomError.__module__ == "pkg.sub" + assert not hasattr(module, "pkg.sub.CustomError") + def test_tp_alloc(self): TestTpAlloc = CPyExtType("TestTpAlloc", ''' #include "objimpl.h" - + static PyObject* testslots_has_tp_alloc_and_size(PyObject* self) { if (!PyType_Type.tp_alloc) { Py_RETURN_FALSE; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextErrBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextErrBuiltins.java index e70d332410..c7835533fe 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextErrBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextErrBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2026, 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 @@ -225,7 +225,7 @@ static Object newEx(TruffleString name, Object base, Object dict, @Bind Node inliningTarget, @Bind PythonLanguage language, @Cached HashingStorageGetItem getItem, - @Cached TruffleString.IndexOfCodePointNode indexOfCodepointNode, + @Cached TruffleString.LastIndexOfCodePointNode lastIndexOfCodepointNode, @Cached TruffleString.CodePointLengthNode codePointLengthNode, @Cached TruffleString.SubstringNode substringNode, @Cached PyDictSetItem setItemNode, @@ -241,12 +241,12 @@ static Object newEx(TruffleString name, Object base, Object dict, dict = PFactory.createDict(language); } int length = codePointLengthNode.execute(name, TS_ENCODING); - int dotIdx = indexOfCodepointNode.execute(name, '.', 0, length, TS_ENCODING); + int dotIdx = lastIndexOfCodepointNode.execute(name, '.', length, 0, TS_ENCODING); if (dotIdx < 0) { notDotProfile.enter(inliningTarget); throw raiseNode.raise(inliningTarget, SystemError, MUST_BE_MODULE_CLASS, "PyErr_NewException", "name"); } - if (getItem.execute(null, inliningTarget, ((PDict) dict).getDictStorage(), base) == null) { + if (getItem.execute(null, inliningTarget, ((PDict) dict).getDictStorage(), T___MODULE__) == null) { notModuleProfile.enter(inliningTarget); setItemNode.execute(null, inliningTarget, (PDict) dict, T___MODULE__, substringNode.execute(name, 0, dotIdx, TS_ENCODING, false)); } From c05da92bb16bb16ccacf3909a6f1e730703e0ba1 Mon Sep 17 00:00:00 2001 From: Michael Simacek Date: Thu, 30 Apr 2026 09:31:22 +0200 Subject: [PATCH 2/2] Skip c++03 test on darwin --- graalpython/lib-python/3/test/test_cppext/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/graalpython/lib-python/3/test/test_cppext/__init__.py b/graalpython/lib-python/3/test/test_cppext/__init__.py index f02a823bd2..e970a8bcb7 100644 --- a/graalpython/lib-python/3/test/test_cppext/__init__.py +++ b/graalpython/lib-python/3/test/test_cppext/__init__.py @@ -22,6 +22,8 @@ def test_build_cpp11(self): @support.requires_resource('cpu') def test_build_cpp03(self): + if sys.platform == "darwin": + self.skipTest("current macOS SDK libc++ headers no longer support C++03") self.check_build(True, '_testcpp03ext') # With MSVC, the linker fails with: cannot open file 'python311.lib'