diff options
author | Stefan Behnel <stefan_ml@behnel.de> | 2020-04-24 22:58:57 +0200 |
---|---|---|
committer | Stefan Behnel <stefan_ml@behnel.de> | 2020-04-24 22:58:57 +0200 |
commit | 538a40df472658baeca7e085dc7a38fb3e01daef (patch) | |
tree | 3c63866443a1ea2c2c1d38fe5ca46817a75d4d1c | |
parent | 5204d86989493855fdd0acd20debd9d0a270bb23 (diff) | |
download | cython-gh3545_reduce_cython_reimport.tar.gz |
Work around error that "__reduce_cython__ cannot be found" when re-importing an extension module that was already initialised before.gh3545_reduce_cython_reimport
Closes #3545.
-rw-r--r-- | Cython/Utility/ExtensionTypes.c | 24 | ||||
-rw-r--r-- | tests/run/reimport_failure.srctree | 38 |
2 files changed, 56 insertions, 6 deletions
diff --git a/Cython/Utility/ExtensionTypes.c b/Cython/Utility/ExtensionTypes.c index efdfd35ef..a75863d02 100644 --- a/Cython/Utility/ExtensionTypes.c +++ b/Cython/Utility/ExtensionTypes.c @@ -235,16 +235,28 @@ static int __Pyx_setup_reduce(PyObject* type_obj) { reduce = __Pyx_PyObject_GetAttrStr(type_obj, PYIDENT("__reduce__")); if (unlikely(!reduce)) goto __PYX_BAD; if (reduce == object_reduce || __Pyx_setup_reduce_is_named(reduce, PYIDENT("__reduce_cython__"))) { - reduce_cython = __Pyx_PyObject_GetAttrStr(type_obj, PYIDENT("__reduce_cython__")); if (unlikely(!reduce_cython)) goto __PYX_BAD; - ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, PYIDENT("__reduce__"), reduce_cython); if (unlikely(ret < 0)) goto __PYX_BAD; - ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, PYIDENT("__reduce_cython__")); if (unlikely(ret < 0)) goto __PYX_BAD; + reduce_cython = __Pyx_PyObject_GetAttrStrNoError(type_obj, PYIDENT("__reduce_cython__")); + if (likely(reduce_cython)) { + ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, PYIDENT("__reduce__"), reduce_cython); if (unlikely(ret < 0)) goto __PYX_BAD; + ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, PYIDENT("__reduce_cython__")); if (unlikely(ret < 0)) goto __PYX_BAD; + } else if (reduce == object_reduce || PyErr_Occurred()) { + // Ignore if we're done, i.e. if 'reduce' already has the right name and the original is gone. + // Otherwise: error. + goto __PYX_BAD; + } setstate = __Pyx_PyObject_GetAttrStrNoError(type_obj, PYIDENT("__setstate__")); if (!setstate) PyErr_Clear(); if (!setstate || __Pyx_setup_reduce_is_named(setstate, PYIDENT("__setstate_cython__"))) { - setstate_cython = __Pyx_PyObject_GetAttrStr(type_obj, PYIDENT("__setstate_cython__")); if (unlikely(!setstate_cython)) goto __PYX_BAD; - ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, PYIDENT("__setstate__"), setstate_cython); if (unlikely(ret < 0)) goto __PYX_BAD; - ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, PYIDENT("__setstate_cython__")); if (unlikely(ret < 0)) goto __PYX_BAD; + setstate_cython = __Pyx_PyObject_GetAttrStrNoError(type_obj, PYIDENT("__setstate_cython__")); + if (likely(setstate_cython)) { + ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, PYIDENT("__setstate__"), setstate_cython); if (unlikely(ret < 0)) goto __PYX_BAD; + ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, PYIDENT("__setstate_cython__")); if (unlikely(ret < 0)) goto __PYX_BAD; + } else if (!setstate || PyErr_Occurred()) { + // Ignore if we're done, i.e. if 'setstate' already has the right name and the original is gone. + // Otherwise: error. + goto __PYX_BAD; + } } PyType_Modified((PyTypeObject*)type_obj); } diff --git a/tests/run/reimport_failure.srctree b/tests/run/reimport_failure.srctree new file mode 100644 index 000000000..498c9bd36 --- /dev/null +++ b/tests/run/reimport_failure.srctree @@ -0,0 +1,38 @@ +# mode: run +# tag: pep489 + +""" +PYTHON setup.py build_ext -i +PYTHON tester.py +""" + +######## setup.py ######## + +from Cython.Build.Dependencies import cythonize +from distutils.core import setup + +setup( + ext_modules = cythonize("*.pyx"), +) + + +######## failure.pyx ######## + +if globals(): # runtime True to confuse dead code removal + raise ImportError + +cdef class C: + cdef int a + + +######## tester.py ######## + +try: + try: + import failure # 1 + except ImportError: + import failure # 2 +except ImportError: + pass +else: + raise RuntimeError("ImportError was not raised on second import!") |