11#ifndef __GET_ATTR_STRING_H
22#define __GET_ATTR_STRING_H
33
4- static NPY_INLINE int
5- _is_basic_python_type (PyObject * obj )
4+ static NPY_INLINE npy_bool
5+ _is_basic_python_type (PyTypeObject * tp )
66{
7- if ( obj == Py_None ||
8- PyBool_Check ( obj ) ||
9- /* Basic number types */
7+ return (
8+ /* Basic number types */
9+ tp == & PyBool_Type ||
1010#if !defined (NPY_PY3K )
11- PyInt_CheckExact (obj ) ||
12- PyString_CheckExact (obj ) ||
11+ tp == & PyInt_Type ||
1312#endif
14- PyLong_CheckExact (obj ) ||
15- PyFloat_CheckExact (obj ) ||
16- PyComplex_CheckExact (obj ) ||
17- /* Basic sequence types */
18- PyList_CheckExact (obj ) ||
19- PyTuple_CheckExact (obj ) ||
20- PyDict_CheckExact (obj ) ||
21- PyAnySet_CheckExact (obj ) ||
22- PyUnicode_CheckExact (obj ) ||
23- PyBytes_CheckExact (obj ) ||
24- PySlice_Check (obj )) {
13+ tp == & PyLong_Type ||
14+ tp == & PyFloat_Type ||
15+ tp == & PyComplex_Type ||
2516
26- return 1 ;
27- }
17+ /* Basic sequence types */
18+ tp == & PyList_Type ||
19+ tp == & PyTuple_Type ||
20+ tp == & PyDict_Type ||
21+ tp == & PySet_Type ||
22+ tp == & PyFrozenSet_Type ||
23+ tp == & PyUnicode_Type ||
24+ tp == & PyBytes_Type ||
25+ #if !defined (NPY_PY3K )
26+ tp == & PyString_Type ||
27+ #endif
28+
29+ /* other builtins */
30+ tp == & PySlice_Type ||
31+ tp == Py_TYPE (Py_None ) ||
32+ tp == Py_TYPE (Py_Ellipsis ) ||
33+ tp == Py_TYPE (Py_NotImplemented ) ||
34+
35+ /* TODO: ndarray, but we can't see PyArray_Type here */
2836
29- return 0 ;
37+ /* sentinel to swallow trailing || */
38+ NPY_FALSE
39+ );
3040}
3141
3242/*
33- * PyArray_GetAttrString_SuppressException:
34- *
3543 * Stripped down version of PyObject_GetAttrString,
3644 * avoids lookups for None, tuple, and List objects,
3745 * and doesn't create a PyErr since this code ignores it.
@@ -43,19 +51,14 @@ _is_basic_python_type(PyObject * obj)
4351 *
4452 * 'name' is the attribute to search for.
4553 *
46- * Returns attribute value on success, 0 on failure.
54+ * Returns attribute value on success, NULL on failure.
4755 */
48- static PyObject *
49- PyArray_GetAttrString_SuppressException (PyObject * obj , char * name )
56+ static NPY_INLINE PyObject *
57+ maybe_get_attr (PyObject * obj , char * name )
5058{
5159 PyTypeObject * tp = Py_TYPE (obj );
5260 PyObject * res = (PyObject * )NULL ;
5361
54- /* We do not need to check for special attributes on trivial types */
55- if (_is_basic_python_type (obj )) {
56- return NULL ;
57- }
58-
5962 /* Attribute referenced by (char *)name */
6063 if (tp -> tp_getattr != NULL ) {
6164 res = (* tp -> tp_getattr )(obj , name );
@@ -82,4 +85,47 @@ PyArray_GetAttrString_SuppressException(PyObject *obj, char *name)
8285 return res ;
8386}
8487
88+ /*
89+ * Lookup a special method, following the python approach of looking up
90+ * on the type object, rather than on the instance itself.
91+ *
92+ * Assumes that the special method is a numpy-specific one, so does not look
93+ * at builtin types, nor does it look at a base ndarray.
94+ *
95+ * In future, could be made more like _Py_LookupSpecial
96+ */
97+ static NPY_INLINE PyObject *
98+ PyArray_LookupSpecial (PyObject * obj , char * name )
99+ {
100+ PyTypeObject * tp = Py_TYPE (obj );
101+
102+ /* We do not need to check for special attributes on trivial types */
103+ if (_is_basic_python_type (tp )) {
104+ return NULL ;
105+ }
106+
107+ return maybe_get_attr ((PyObject * )tp , name );
108+ }
109+
110+ /*
111+ * PyArray_LookupSpecial_OnInstance:
112+ *
113+ * Implements incorrect special method lookup rules, that break the python
114+ * convention, and looks on the instance, not the type.
115+ *
116+ * Kept for backwards compatibility. In future, we should deprecate this.
117+ */
118+ static NPY_INLINE PyObject *
119+ PyArray_LookupSpecial_OnInstance (PyObject * obj , char * name )
120+ {
121+ PyTypeObject * tp = Py_TYPE (obj );
122+
123+ /* We do not need to check for special attributes on trivial types */
124+ if (_is_basic_python_type (tp )) {
125+ return NULL ;
126+ }
127+
128+ return maybe_get_attr (obj , name );
129+ }
130+
85131#endif
0 commit comments