summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Behnel <stefan_ml@behnel.de>2018-12-27 09:13:23 +0100
committerStefan Behnel <stefan_ml@behnel.de>2018-12-27 09:13:23 +0100
commitde109c20b30efb16d0aa98b9fd4f932755d62a24 (patch)
tree9dfb89bb6068be898261cebbd00bd3515df5b7e5
parent4e35b1a3fe7763e5dd50f9b460177f2d233b0fae (diff)
downloadcython-de109c20b30efb16d0aa98b9fd4f932755d62a24.tar.gz
Add a new utility function "__Pyx_PyObject_GetAttrStrNoError()" that does not raise AttributeError if the lookup fails, and use "_PyObject_GenericGetAttrWithDict()" for it in Py3.7+ to avoid instantiating the exception completely.
-rw-r--r--Cython/Utility/Builtins.c14
-rw-r--r--Cython/Utility/Coroutine.c11
-rw-r--r--Cython/Utility/Exceptions.c4
-rw-r--r--Cython/Utility/ExtensionTypes.c5
-rw-r--r--Cython/Utility/ObjectHandling.c83
5 files changed, 74 insertions, 43 deletions
diff --git a/Cython/Utility/Builtins.c b/Cython/Utility/Builtins.c
index df5c41fbc..c508917d5 100644
--- a/Cython/Utility/Builtins.c
+++ b/Cython/Utility/Builtins.c
@@ -167,7 +167,7 @@ bad:
static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *, PyObject *, PyObject *); /*proto*/
//////////////////// GetAttr3 ////////////////////
-//@requires: ObjectHandling.c::GetAttr
+//@requires: ObjectHandling.c::PyObjectGetAttrStr
//@requires: Exceptions.c::PyThreadStateGet
//@requires: Exceptions.c::PyErrFetchRestore
//@requires: Exceptions.c::PyErrExceptionMatches
@@ -183,7 +183,17 @@ static PyObject *__Pyx_GetAttr3Default(PyObject *d) {
}
static CYTHON_INLINE PyObject *__Pyx_GetAttr3(PyObject *o, PyObject *n, PyObject *d) {
- PyObject *r = __Pyx_GetAttr(o, n);
+ PyObject *r;
+#if CYTHON_USE_TYPE_SLOTS
+ if (likely(PyString_Check(n))) {
+ r = __Pyx_PyObject_GetAttrStrNoError(o, n);
+ if (unlikely(!r) && likely(!PyErr_Occurred())) {
+ r = __Pyx_NewRef(d);
+ }
+ return r;
+ }
+#endif
+ r = PyObject_GetAttr(o, n);
return (likely(r)) ? r : __Pyx_GetAttr3Default(d);
}
diff --git a/Cython/Utility/Coroutine.c b/Cython/Utility/Coroutine.c
index 8cd3138b2..54e370766 100644
--- a/Cython/Utility/Coroutine.c
+++ b/Cython/Utility/Coroutine.c
@@ -485,6 +485,7 @@ static int __pyx_Generator_init(void); /*proto*/
//@requires: Exceptions.c::SaveResetException
//@requires: ObjectHandling.c::PyObjectCallMethod1
//@requires: ObjectHandling.c::PyObjectGetAttrStr
+//@requires: ObjectHandling.c::PyObjectGetAttrStrNoError
//@requires: CommonStructures.c::FetchCommonType
#include <structmember.h>
@@ -894,12 +895,11 @@ static int __Pyx_Coroutine_CloseIter(__pyx_CoroutineObject *gen, PyObject *yf) {
{
PyObject *meth;
gen->is_running = 1;
- meth = __Pyx_PyObject_GetAttrStr(yf, PYIDENT("close"));
+ meth = __Pyx_PyObject_GetAttrStrNoError(yf, PYIDENT("close"));
if (unlikely(!meth)) {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
+ if (unlikely(PyErr_Occurred())) {
PyErr_WriteUnraisable(yf);
}
- PyErr_Clear();
} else {
retval = PyObject_CallFunction(meth, NULL);
Py_DECREF(meth);
@@ -1041,14 +1041,13 @@ static PyObject *__Pyx__Coroutine_Throw(PyObject *self, PyObject *typ, PyObject
ret = __Pyx__Coroutine_Throw(((__pyx_CoroutineAwaitObject*)yf)->coroutine, typ, val, tb, args, close_on_genexit);
#endif
} else {
- PyObject *meth = __Pyx_PyObject_GetAttrStr(yf, PYIDENT("throw"));
+ PyObject *meth = __Pyx_PyObject_GetAttrStrNoError(yf, PYIDENT("throw"));
if (unlikely(!meth)) {
Py_DECREF(yf);
- if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
+ if (unlikely(PyErr_Occurred())) {
gen->is_running = 0;
return NULL;
}
- PyErr_Clear();
__Pyx_Coroutine_Undelegate(gen);
gen->is_running = 0;
goto throw_here;
diff --git a/Cython/Utility/Exceptions.c b/Cython/Utility/Exceptions.c
index 29a2ae4c7..3dd563628 100644
--- a/Cython/Utility/Exceptions.c
+++ b/Cython/Utility/Exceptions.c
@@ -641,7 +641,7 @@ static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line);/*proto*/
#endif
/////////////// CLineInTraceback ///////////////
-//@requires: ObjectHandling.c::PyObjectGetAttrStr
+//@requires: ObjectHandling.c::PyObjectGetAttrStrNoError
//@requires: PyErrFetchRestore
//@substitute: naming
@@ -669,7 +669,7 @@ static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line) {
} else
#endif
{
- PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(${cython_runtime_cname}, PYIDENT("cline_in_traceback"));
+ PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStrNoError(${cython_runtime_cname}, PYIDENT("cline_in_traceback"));
if (use_cline_obj) {
use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True;
Py_DECREF(use_cline_obj);
diff --git a/Cython/Utility/ExtensionTypes.c b/Cython/Utility/ExtensionTypes.c
index fc11fafa7..50d0e2137 100644
--- a/Cython/Utility/ExtensionTypes.c
+++ b/Cython/Utility/ExtensionTypes.c
@@ -132,6 +132,7 @@ static void __Pyx_call_next_tp_clear(PyObject* obj, inquiry current_tp_clear) {
static int __Pyx_setup_reduce(PyObject* type_obj);
/////////////// SetupReduce ///////////////
+//@requires: ObjectHandling.c::PyObjectGetAttrStrNoError
//@requires: ObjectHandling.c::PyObjectGetAttrStr
//@substitute: naming
@@ -139,7 +140,7 @@ static int __Pyx_setup_reduce_is_named(PyObject* meth, PyObject* name) {
int ret;
PyObject *name_attr;
- name_attr = __Pyx_PyObject_GetAttrStr(meth, PYIDENT("__name__"));
+ name_attr = __Pyx_PyObject_GetAttrStrNoError(meth, PYIDENT("__name__"));
if (likely(name_attr)) {
ret = PyObject_RichCompareBool(name_attr, name, Py_EQ);
} else {
@@ -192,7 +193,7 @@ static int __Pyx_setup_reduce(PyObject* type_obj) {
ret = PyDict_SetItem(((PyTypeObject*)type_obj)->tp_dict, PYIDENT("__reduce__"), reduce_cython); if (unlikely(ret < 0)) goto BAD;
ret = PyDict_DelItem(((PyTypeObject*)type_obj)->tp_dict, PYIDENT("__reduce_cython__")); if (unlikely(ret < 0)) goto BAD;
- setstate = __Pyx_PyObject_GetAttrStr(type_obj, PYIDENT("__setstate__"));
+ 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 BAD;
diff --git a/Cython/Utility/ObjectHandling.c b/Cython/Utility/ObjectHandling.c
index 5c687759c..a90911142 100644
--- a/Cython/Utility/ObjectHandling.c
+++ b/Cython/Utility/ObjectHandling.c
@@ -943,14 +943,14 @@ static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObj
PyObject *mkw, int calculate_metaclass, int allow_py2_metaclass); /*proto*/
/////////////// Py3ClassCreate ///////////////
-//@requires: PyObjectGetAttrStr
+//@requires: PyObjectGetAttrStrNoError
//@requires: CalculateMetaclass
static PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases, PyObject *name,
PyObject *qualname, PyObject *mkw, PyObject *modname, PyObject *doc) {
PyObject *ns;
if (metaclass) {
- PyObject *prep = __Pyx_PyObject_GetAttrStr(metaclass, PYIDENT("__prepare__"));
+ PyObject *prep = __Pyx_PyObject_GetAttrStrNoError(metaclass, PYIDENT("__prepare__"));
if (prep) {
PyObject *pargs = PyTuple_Pack(2, name, bases);
if (unlikely(!pargs)) {
@@ -961,9 +961,8 @@ static PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases,
Py_DECREF(prep);
Py_DECREF(pargs);
} else {
- if (unlikely(!PyErr_ExceptionMatches(PyExc_AttributeError)))
+ if (unlikely(PyErr_Occurred()))
return NULL;
- PyErr_Clear();
ns = PyDict_New();
}
} else {
@@ -1099,12 +1098,12 @@ static CYTHON_INLINE PyObject* __Pyx_PyBoolOrNull_FromLong(long b) {
static PyObject *__Pyx_GetBuiltinName(PyObject *name); /*proto*/
/////////////// GetBuiltinName ///////////////
-//@requires: PyObjectGetAttrStr
+//@requires: PyObjectGetAttrStrNoError
//@substitute: naming
static PyObject *__Pyx_GetBuiltinName(PyObject *name) {
- PyObject* result = __Pyx_PyObject_GetAttrStr($builtins_cname, name);
- if (unlikely(!result)) {
+ PyObject* result = __Pyx_PyObject_GetAttrStrNoError($builtins_cname, name);
+ if (unlikely(!result) && !PyErr_Occurred()) {
PyErr_Format(PyExc_NameError,
#if PY_MAJOR_VERSION >= 3
"name '%U' is not defined", name);
@@ -1121,28 +1120,17 @@ static PyObject *__Pyx_GetBuiltinName(PyObject *name) {
static PyObject *__Pyx__GetNameInClass(PyObject *nmspace, PyObject *name); /*proto*/
/////////////// GetNameInClass ///////////////
-//@requires: PyObjectGetAttrStr
+//@requires: PyObjectGetAttrStrNoError
//@requires: GetModuleGlobalName
-//@requires: Exceptions.c::PyThreadStateGet
-//@requires: Exceptions.c::PyErrFetchRestore
-//@requires: Exceptions.c::PyErrExceptionMatches
-
-static PyObject *__Pyx_GetGlobalNameAfterAttributeLookup(PyObject *name) {
- PyObject *result;
- __Pyx_PyThreadState_declare
- __Pyx_PyThreadState_assign
- if (unlikely(!__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError)))
- return NULL;
- __Pyx_PyErr_Clear();
- __Pyx_GetModuleGlobalNameUncached(result, name);
- return result;
-}
static PyObject *__Pyx__GetNameInClass(PyObject *nmspace, PyObject *name) {
PyObject *result;
- result = __Pyx_PyObject_GetAttrStr(nmspace, name);
+ result = __Pyx_PyObject_GetAttrStrNoError(nmspace, name);
if (!result) {
- result = __Pyx_GetGlobalNameAfterAttributeLookup(name);
+ if (unlikely(PyErr_Occurred()))
+ return NULL;
+ __Pyx_GetModuleGlobalNameUncached(result, name);
+ return result;
}
return result;
}
@@ -1358,6 +1346,41 @@ static PyObject* __Pyx_PyObject_GenericGetAttr(PyObject* obj, PyObject* attr_nam
#endif
+/////////////// PyObjectGetAttrStrNoError.proto ///////////////
+
+static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name);/*proto*/
+
+/////////////// PyObjectGetAttrStrNoError ///////////////
+//@requires: PyObjectGetAttrStr
+//@requires: Exceptions.c::PyThreadStateGet
+//@requires: Exceptions.c::PyErrFetchRestore
+//@requires: Exceptions.c::PyErrExceptionMatches
+
+static void __Pyx_PyObject_GetAttrStr_ClearAttributeError(void) {
+ __Pyx_PyThreadState_declare
+ __Pyx_PyThreadState_assign
+ if (likely(__Pyx_PyErr_ExceptionMatches(PyExc_AttributeError)))
+ __Pyx_PyErr_Clear();
+}
+
+static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStrNoError(PyObject* obj, PyObject* attr_name) {
+ PyObject *result;
+#if CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_TYPE_SLOTS && PY_VERSION_HEX >= 0x030700B1
+ // _PyObject_GenericGetAttrWithDict() in CPython 3.7+ can avoid raising the AttributeError.
+ // See https://bugs.python.org/issue32544
+ PyTypeObject* tp = Py_TYPE(obj);
+ if (likely(tp->tp_getattro == PyObject_GenericGetAttr)) {
+ return _PyObject_GenericGetAttrWithDict(obj, attr_name, NULL, 1);
+ }
+#endif
+ result = __Pyx_PyObject_GetAttrStr(obj, attr_name);
+ if (unlikely(!result)) {
+ __Pyx_PyObject_GetAttrStr_ClearAttributeError();
+ }
+ return result;
+}
+
+
/////////////// PyObjectGetAttrStr.proto ///////////////
#if CYTHON_USE_TYPE_SLOTS
@@ -2303,7 +2326,7 @@ static PyObject* __Pyx_PyNumber_InPlaceMatrixMultiply(PyObject* x, PyObject* y);
#endif
/////////////// MatrixMultiply ///////////////
-//@requires: PyObjectGetAttrStr
+//@requires: PyObjectGetAttrStrNoError
//@requires: PyObjectCallOneArg
//@requires: PyFunctionFastCall
//@requires: PyCFunctionFastCall
@@ -2353,17 +2376,15 @@ done:
return result;
}
-#define __Pyx_TryMatrixMethod(x, y, py_method_name) { \
- PyObject *func = __Pyx_PyObject_GetAttrStr(x, py_method_name); \
+#define __Pyx_TryMatrixMethod(x, y, py_method_name) { \
+ PyObject *func = __Pyx_PyObject_GetAttrStrNoError(x, py_method_name); \
if (func) { \
PyObject *result = __Pyx_PyObject_CallMatrixMethod(func, y); \
if (result != Py_NotImplemented) \
return result; \
Py_DECREF(result); \
- } else { \
- if (!PyErr_ExceptionMatches(PyExc_AttributeError)) \
- return NULL; \
- PyErr_Clear(); \
+ } else if (unlikely(PyErr_Occurred())) { \
+ return NULL; \
} \
}