Skip to content

Commit daa0a44

Browse files
authored
Fix the name of attributes in the common ABI module (cythonGH-4376)
Attribute names used to be fully qualified like "_cython_3_0_0a9.cython_function_or_method" instead of the plain name. Closes cython#4373
1 parent fa8db66 commit daa0a44

File tree

2 files changed

+27
-6
lines changed

2 files changed

+27
-6
lines changed

Cython/Utility/CommonStructures.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ static PyTypeObject* __Pyx_FetchCommonTypeFromSpec(PyObject *module, PyType_Spec
88

99
/////////////// FetchCommonType ///////////////
1010
//@requires:ExtensionTypes.c::FixUpExtensionType
11+
//@requires:StringTools.c::IncludeStringH
1112

1213
static PyObject *__Pyx_FetchSharedCythonABIModule(void) {
1314
PyObject *abi_module = PyImport_AddModule((char*) __PYX_ABI_MODULE_NAME);
@@ -37,15 +38,19 @@ static int __Pyx_VerifyCachedType(PyObject *cached_type,
3738
#if !CYTHON_USE_TYPE_SPECS
3839
static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type) {
3940
PyObject* abi_module;
41+
const char* object_name;
4042
PyTypeObject *cached_type = NULL;
4143

4244
abi_module = __Pyx_FetchSharedCythonABIModule();
4345
if (!abi_module) return NULL;
44-
cached_type = (PyTypeObject*) PyObject_GetAttrString(abi_module, type->tp_name);
46+
// get the final part of the object name (after the last dot)
47+
object_name = strrchr(type->tp_name, '.');
48+
object_name = object_name ? object_name+1 : type->tp_name;
49+
cached_type = (PyTypeObject*) PyObject_GetAttrString(abi_module, object_name);
4550
if (cached_type) {
4651
if (__Pyx_VerifyCachedType(
4752
(PyObject *)cached_type,
48-
type->tp_name,
53+
object_name,
4954
cached_type->tp_basicsize,
5055
type->tp_basicsize) < 0) {
5156
goto bad;
@@ -56,7 +61,7 @@ static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type) {
5661
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad;
5762
PyErr_Clear();
5863
if (PyType_Ready(type) < 0) goto bad;
59-
if (PyObject_SetAttrString(abi_module, type->tp_name, (PyObject *)type) < 0)
64+
if (PyObject_SetAttrString(abi_module, object_name, (PyObject *)type) < 0)
6065
goto bad;
6166
Py_INCREF(type);
6267
cached_type = type;
@@ -75,11 +80,14 @@ static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type) {
7580

7681
static PyTypeObject *__Pyx_FetchCommonTypeFromSpec(PyObject *module, PyType_Spec *spec, PyObject *bases) {
7782
PyObject *abi_module, *cached_type = NULL;
83+
// get the final part of the object name (after the last dot)
84+
const char* object_name = strrchr(spec->name, '.');
85+
object_name = object_name ? object_name+1 : spec->name;
7886

7987
abi_module = __Pyx_FetchSharedCythonABIModule();
8088
if (!abi_module) return NULL;
8189

82-
cached_type = PyObject_GetAttrString(abi_module, spec->name);
90+
cached_type = PyObject_GetAttrString(abi_module, object_name);
8391
if (cached_type) {
8492
Py_ssize_t basicsize;
8593
#if CYTHON_COMPILING_IN_LIMITED_API
@@ -95,7 +103,7 @@ static PyTypeObject *__Pyx_FetchCommonTypeFromSpec(PyObject *module, PyType_Spec
95103
#endif
96104
if (__Pyx_VerifyCachedType(
97105
cached_type,
98-
spec->name,
106+
object_name,
99107
basicsize,
100108
spec->basicsize) < 0) {
101109
goto bad;
@@ -110,7 +118,7 @@ static PyTypeObject *__Pyx_FetchCommonTypeFromSpec(PyObject *module, PyType_Spec
110118
cached_type = __Pyx_PyType_FromModuleAndSpec(abi_module, spec, bases);
111119
if (unlikely(!cached_type)) goto bad;
112120
if (unlikely(__Pyx_fix_up_extension_type_from_spec(spec, (PyTypeObject *) cached_type) < 0)) goto bad;
113-
if (PyObject_SetAttrString(abi_module, spec->name, cached_type) < 0) goto bad;
121+
if (PyObject_SetAttrString(abi_module, object_name, cached_type) < 0) goto bad;
114122

115123
done:
116124
Py_DECREF(abi_module);

tests/run/common_utility_types.srctree

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,16 @@ assert type(a.funcA) is type(b.funcB)
3636

3737
assert a.funcA.func_globals is a.__dict__
3838
assert b.funcB.func_globals is b.__dict__
39+
40+
# Test that it's possible to look up the name of the class
41+
from sys import modules
42+
cy_modules = [ mod for n, mod in modules.items() if n.startswith("_cython_") ]
43+
# In principle it's possible to have "_cython_" internal modules for multiple
44+
# different versions of Cython. However, since this is run in an end-to-end test
45+
# with a very short list of imports it should not happen here.
46+
assert(len(cy_modules)==1)
47+
mod = cy_modules[0]
48+
49+
assert '.' not in type(a.funcA).__name__
50+
func_t = getattr(mod, type(a.funcA).__name__)
51+
assert func_t is type(a.funcA)

0 commit comments

Comments
 (0)