[Python-checkins] bpo-40170: Add _PyIndex_Check() internal function (GH-19426)

Victor Stinner webhook-mailer at python.org
Tue Apr 7 20:02:04 EDT 2020


https://github.com/python/cpython/commit/a15e260b708a98edaba86a2aa663c3f6b2abc964
commit: a15e260b708a98edaba86a2aa663c3f6b2abc964
branch: master
author: Victor Stinner <vstinner at python.org>
committer: GitHub <noreply at github.com>
date: 2020-04-08T02:01:56+02:00
summary:

bpo-40170: Add _PyIndex_Check() internal function (GH-19426)

Add _PyIndex_Check() function to the internal C API: fast inlined
verson of PyIndex_Check().

Add Include/internal/pycore_abstract.h header file.

Replace PyIndex_Check() with _PyIndex_Check() in C files of Objects
and Python subdirectories.

files:
A Include/internal/pycore_abstract.h
M Makefile.pre.in
M Objects/abstract.c
M Objects/bytearrayobject.c
M Objects/bytes_methods.c
M Objects/bytesobject.c
M Objects/interpreteridobject.c
M Objects/listobject.c
M Objects/memoryobject.c
M Objects/rangeobject.c
M Objects/sliceobject.c
M Objects/tupleobject.c
M Objects/unicodeobject.c
M PCbuild/pythoncore.vcxproj
M PCbuild/pythoncore.vcxproj.filters
M Python/ceval.c
M Python/modsupport.c

diff --git a/Include/internal/pycore_abstract.h b/Include/internal/pycore_abstract.h
new file mode 100644
index 0000000000000..b791bf2432199
--- /dev/null
+++ b/Include/internal/pycore_abstract.h
@@ -0,0 +1,22 @@
+#ifndef Py_INTERNAL_ABSTRACT_H
+#define Py_INTERNAL_ABSTRACT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef Py_BUILD_CORE
+#  error "this header requires Py_BUILD_CORE define"
+#endif
+
+// Fast inlined version of PyIndex_Check()
+static inline int
+_PyIndex_Check(PyObject *obj)
+{
+    PyNumberMethods *tp_as_number = Py_TYPE(obj)->tp_as_number;
+    return (tp_as_number != NULL && tp_as_number->nb_index != NULL);
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_INTERNAL_ABSTRACT_H */
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 948f9851d0c4a..ac6c2b1288965 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -1080,6 +1080,7 @@ PYTHON_HEADERS= \
 		$(srcdir)/Include/cpython/tupleobject.h \
 		$(srcdir)/Include/cpython/unicodeobject.h \
 		\
+		$(srcdir)/Include/internal/pycore_abstract.h \
 		$(srcdir)/Include/internal/pycore_accu.h \
 		$(srcdir)/Include/internal/pycore_atomic.h \
 		$(srcdir)/Include/internal/pycore_bytes_methods.h \
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 49a38d8f6e290..b5d91dbab0c1d 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -1,7 +1,8 @@
 /* Abstract Object Interface (many thanks to Jim Fulton) */
 
 #include "Python.h"
-#include "pycore_ceval.h"   // _Py_EnterRecursiveCall()
+#include "pycore_abstract.h"   // _PyIndex_Check()
+#include "pycore_ceval.h"      // _Py_EnterRecursiveCall()
 #include "pycore_pyerrors.h"
 #include "pycore_pystate.h"
 #include <ctype.h>
@@ -160,7 +161,7 @@ PyObject_GetItem(PyObject *o, PyObject *key)
 
     ms = Py_TYPE(o)->tp_as_sequence;
     if (ms && ms->sq_item) {
-        if (PyIndex_Check(key)) {
+        if (_PyIndex_Check(key)) {
             Py_ssize_t key_value;
             key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);
             if (key_value == -1 && PyErr_Occurred())
@@ -176,7 +177,7 @@ PyObject_GetItem(PyObject *o, PyObject *key)
     if (PyType_Check(o)) {
         PyObject *meth, *result;
         _Py_IDENTIFIER(__class_getitem__);
-        
+
         // Special case type[int], but disallow other types so str[int] fails
         if ((PyTypeObject*)o == &PyType_Type) {
             return Py_GenericAlias(o, key);
@@ -209,7 +210,7 @@ PyObject_SetItem(PyObject *o, PyObject *key, PyObject *value)
         return m->mp_ass_subscript(o, key, value);
 
     if (Py_TYPE(o)->tp_as_sequence) {
-        if (PyIndex_Check(key)) {
+        if (_PyIndex_Check(key)) {
             Py_ssize_t key_value;
             key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);
             if (key_value == -1 && PyErr_Occurred())
@@ -241,7 +242,7 @@ PyObject_DelItem(PyObject *o, PyObject *key)
         return m->mp_ass_subscript(o, key, (PyObject*)NULL);
 
     if (Py_TYPE(o)->tp_as_sequence) {
-        if (PyIndex_Check(key)) {
+        if (_PyIndex_Check(key)) {
             Py_ssize_t key_value;
             key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);
             if (key_value == -1 && PyErr_Occurred())
@@ -1030,7 +1031,7 @@ static PyObject *
 sequence_repeat(ssizeargfunc repeatfunc, PyObject *seq, PyObject *n)
 {
     Py_ssize_t count;
-    if (PyIndex_Check(n)) {
+    if (_PyIndex_Check(n)) {
         count = PyNumber_AsSsize_t(n, PyExc_OverflowError);
         if (count == -1 && PyErr_Occurred())
             return NULL;
@@ -1307,15 +1308,16 @@ PyNumber_Absolute(PyObject *o)
     return type_error("bad operand type for abs(): '%.200s'", o);
 }
 
+
 #undef PyIndex_Check
 
 int
 PyIndex_Check(PyObject *obj)
 {
-    return Py_TYPE(obj)->tp_as_number != NULL &&
-           Py_TYPE(obj)->tp_as_number->nb_index != NULL;
+    return _PyIndex_Check(obj);
 }
 
+
 /* Return a Python int from the object item.
    Raise TypeError if the result is not an int
    or if the object cannot be interpreted as an index.
@@ -1332,7 +1334,7 @@ PyNumber_Index(PyObject *item)
         Py_INCREF(item);
         return item;
     }
-    if (!PyIndex_Check(item)) {
+    if (!_PyIndex_Check(item)) {
         PyErr_Format(PyExc_TypeError,
                      "'%.200s' object cannot be interpreted "
                      "as an integer", Py_TYPE(item)->tp_name);
diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c
index d3964358bc59d..7ebfa1f9434cc 100644
--- a/Objects/bytearrayobject.c
+++ b/Objects/bytearrayobject.c
@@ -2,6 +2,7 @@
 
 #define PY_SSIZE_T_CLEAN
 #include "Python.h"
+#include "pycore_abstract.h"   // _PyIndex_Check()
 #include "pycore_bytes_methods.h"
 #include "pycore_object.h"
 #include "pycore_pymem.h"
@@ -391,7 +392,7 @@ bytearray_getitem(PyByteArrayObject *self, Py_ssize_t i)
 static PyObject *
 bytearray_subscript(PyByteArrayObject *self, PyObject *index)
 {
-    if (PyIndex_Check(index)) {
+    if (_PyIndex_Check(index)) {
         Py_ssize_t i = PyNumber_AsSsize_t(index, PyExc_IndexError);
 
         if (i == -1 && PyErr_Occurred())
@@ -610,7 +611,7 @@ bytearray_ass_subscript(PyByteArrayObject *self, PyObject *index, PyObject *valu
     char *buf, *bytes;
     buf = PyByteArray_AS_STRING(self);
 
-    if (PyIndex_Check(index)) {
+    if (_PyIndex_Check(index)) {
         Py_ssize_t i = PyNumber_AsSsize_t(index, PyExc_IndexError);
 
         if (i == -1 && PyErr_Occurred())
@@ -809,7 +810,7 @@ bytearray_init(PyByteArrayObject *self, PyObject *args, PyObject *kwds)
     }
 
     /* Is it an int? */
-    if (PyIndex_Check(arg)) {
+    if (_PyIndex_Check(arg)) {
         count = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
         if (count == -1 && PyErr_Occurred()) {
             if (!PyErr_ExceptionMatches(PyExc_TypeError))
diff --git a/Objects/bytes_methods.c b/Objects/bytes_methods.c
index a4b3868e72522..72daa1fdd554e 100644
--- a/Objects/bytes_methods.c
+++ b/Objects/bytes_methods.c
@@ -1,5 +1,6 @@
 #define PY_SSIZE_T_CLEAN
 #include "Python.h"
+#include "pycore_abstract.h"   // _PyIndex_Check()
 #include "pycore_bytes_methods.h"
 
 PyDoc_STRVAR_shared(_Py_isspace__doc__,
@@ -466,7 +467,7 @@ parse_args_finds_byte(const char *function_name, PyObject *args,
         return 1;
     }
 
-    if (!PyIndex_Check(tmp_subobj)) {
+    if (!_PyIndex_Check(tmp_subobj)) {
         PyErr_Format(PyExc_TypeError,
                      "argument should be integer or bytes-like object, "
                      "not '%.200s'",
diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c
index bd8af72ade5d3..03cd7ddd27901 100644
--- a/Objects/bytesobject.c
+++ b/Objects/bytesobject.c
@@ -3,6 +3,7 @@
 #define PY_SSIZE_T_CLEAN
 
 #include "Python.h"
+#include "pycore_abstract.h"   // _PyIndex_Check()
 #include "pycore_bytes_methods.h"
 #include "pycore_object.h"
 #include "pycore_pymem.h"
@@ -1579,7 +1580,7 @@ bytes_hash(PyBytesObject *a)
 static PyObject*
 bytes_subscript(PyBytesObject* self, PyObject* item)
 {
-    if (PyIndex_Check(item)) {
+    if (_PyIndex_Check(item)) {
         Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
         if (i == -1 && PyErr_Occurred())
             return NULL;
@@ -2536,7 +2537,7 @@ bytes_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         return NULL;
     }
     /* Is it an integer? */
-    if (PyIndex_Check(x)) {
+    if (_PyIndex_Check(x)) {
         size = PyNumber_AsSsize_t(x, PyExc_OverflowError);
         if (size == -1 && PyErr_Occurred()) {
             if (!PyErr_ExceptionMatches(PyExc_TypeError))
diff --git a/Objects/interpreteridobject.c b/Objects/interpreteridobject.c
index 57748e8139fb8..3f316873ed516 100644
--- a/Objects/interpreteridobject.c
+++ b/Objects/interpreteridobject.c
@@ -1,7 +1,8 @@
 /* InterpreterID object */
 
 #include "Python.h"
-#include "internal/pycore_pystate.h"
+#include "pycore_abstract.h"   // _PyIndex_Check()
+#include "pycore_pystate.h"
 #include "interpreteridobject.h"
 
 
@@ -42,7 +43,7 @@ interp_id_converter(PyObject *arg, void *ptr)
     if (PyObject_TypeCheck(arg, &_PyInterpreterID_Type)) {
         id = ((interpid *)arg)->id;
     }
-    else if (PyIndex_Check(arg)) {
+    else if (_PyIndex_Check(arg)) {
         id = PyLong_AsLongLong(arg);
         if (id == -1 && PyErr_Occurred()) {
             return 0;
diff --git a/Objects/listobject.c b/Objects/listobject.c
index 48063b285f60c..7058fe4396eec 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -1,6 +1,7 @@
 /* List object implementation */
 
 #include "Python.h"
+#include "pycore_abstract.h"   // _PyIndex_Check()
 #include "pycore_object.h"
 #include "pycore_pystate.h"
 #include "pycore_tupleobject.h"
@@ -2800,7 +2801,7 @@ static PySequenceMethods list_as_sequence = {
 static PyObject *
 list_subscript(PyListObject* self, PyObject* item)
 {
-    if (PyIndex_Check(item)) {
+    if (_PyIndex_Check(item)) {
         Py_ssize_t i;
         i = PyNumber_AsSsize_t(item, PyExc_IndexError);
         if (i == -1 && PyErr_Occurred())
@@ -2855,7 +2856,7 @@ list_subscript(PyListObject* self, PyObject* item)
 static int
 list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
 {
-    if (PyIndex_Check(item)) {
+    if (_PyIndex_Check(item)) {
         Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
         if (i == -1 && PyErr_Occurred())
             return -1;
diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c
index 7f9c90035f574..da06338017cae 100644
--- a/Objects/memoryobject.c
+++ b/Objects/memoryobject.c
@@ -11,6 +11,7 @@
  */
 
 #include "Python.h"
+#include "pycore_abstract.h"   // _PyIndex_Check()
 #include "pycore_object.h"
 #include "pycore_pymem.h"
 #include "pycore_pystate.h"
@@ -2421,8 +2422,9 @@ is_multiindex(PyObject *key)
     size = PyTuple_GET_SIZE(key);
     for (i = 0; i < size; i++) {
         PyObject *x = PyTuple_GET_ITEM(key, i);
-        if (!PyIndex_Check(x))
+        if (!_PyIndex_Check(x)) {
             return 0;
+        }
     }
     return 1;
 }
@@ -2459,7 +2461,7 @@ memory_subscript(PyMemoryViewObject *self, PyObject *key)
         }
     }
 
-    if (PyIndex_Check(key)) {
+    if (_PyIndex_Check(key)) {
         Py_ssize_t index;
         index = PyNumber_AsSsize_t(key, PyExc_IndexError);
         if (index == -1 && PyErr_Occurred())
@@ -2530,7 +2532,7 @@ memory_ass_sub(PyMemoryViewObject *self, PyObject *key, PyObject *value)
         }
     }
 
-    if (PyIndex_Check(key)) {
+    if (_PyIndex_Check(key)) {
         Py_ssize_t index;
         if (1 < view->ndim) {
             PyErr_SetString(PyExc_NotImplementedError,
diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c
index 5bd178b20279e..4bea8d78e12fa 100644
--- a/Objects/rangeobject.c
+++ b/Objects/rangeobject.c
@@ -1,8 +1,9 @@
 /* Range object implementation */
 
 #include "Python.h"
-#include "structmember.h"
+#include "pycore_abstract.h"   // _PyIndex_Check()
 #include "pycore_tupleobject.h"
+#include "structmember.h"
 
 /* Support objects whose length is > PY_SSIZE_T_MAX.
 
@@ -631,7 +632,7 @@ range_reduce(rangeobject *r, PyObject *args)
 static PyObject *
 range_subscript(rangeobject* self, PyObject* item)
 {
-    if (PyIndex_Check(item)) {
+    if (_PyIndex_Check(item)) {
         PyObject *i, *result;
         i = PyNumber_Index(item);
         if (!i)
diff --git a/Objects/sliceobject.c b/Objects/sliceobject.c
index e884a58943562..4fd216388fdfd 100644
--- a/Objects/sliceobject.c
+++ b/Objects/sliceobject.c
@@ -14,6 +14,7 @@ this type and there is exactly one in existence.
 */
 
 #include "Python.h"
+#include "pycore_abstract.h"   // _PyIndex_Check()
 #include "pycore_object.h"
 #include "pycore_pymem.h"
 #include "pycore_pystate.h"
@@ -354,7 +355,7 @@ static PyMemberDef slice_members[] = {
 static PyObject*
 evaluate_slice_index(PyObject *v)
 {
-    if (PyIndex_Check(v)) {
+    if (_PyIndex_Check(v)) {
         return PyNumber_Index(v);
     }
     else {
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index 68163d8c48c71..110c0925ccd94 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -2,6 +2,7 @@
 /* Tuple object implementation */
 
 #include "Python.h"
+#include "pycore_abstract.h"   // _PyIndex_Check()
 #include "pycore_object.h"
 #include "pycore_pystate.h"
 #include "pycore_accu.h"
@@ -763,7 +764,7 @@ static PySequenceMethods tuple_as_sequence = {
 static PyObject*
 tuplesubscript(PyTupleObject* self, PyObject* item)
 {
-    if (PyIndex_Check(item)) {
+    if (_PyIndex_Check(item)) {
         Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
         if (i == -1 && PyErr_Occurred())
             return NULL;
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index da17bfe01f310..1e1f257dad0ff 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -40,6 +40,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 #define PY_SSIZE_T_CLEAN
 #include "Python.h"
+#include "pycore_abstract.h"   // _PyIndex_Check()
 #include "pycore_bytes_methods.h"
 #include "pycore_fileutils.h"
 #include "pycore_initconfig.h"
@@ -14132,7 +14133,7 @@ unicode_subscript(PyObject* self, PyObject* item)
     if (PyUnicode_READY(self) == -1)
         return NULL;
 
-    if (PyIndex_Check(item)) {
+    if (_PyIndex_Check(item)) {
         Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
         if (i == -1 && PyErr_Occurred())
             return NULL;
diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj
index 22f1b95d0a75a..95f9e9b445fa9 100644
--- a/PCbuild/pythoncore.vcxproj
+++ b/PCbuild/pythoncore.vcxproj
@@ -161,6 +161,7 @@
     <ClInclude Include="..\Include\graminit.h" />
     <ClInclude Include="..\Include\grammar.h" />
     <ClInclude Include="..\Include\import.h" />
+    <ClInclude Include="..\Include\internal\pycore_abstract.h" />
     <ClInclude Include="..\Include\internal\pycore_accu.h" />
     <ClInclude Include="..\Include\internal\pycore_atomic.h" />
     <ClInclude Include="..\Include\internal\pycore_bytes_methods.h" />
diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters
index 00891001ce0b7..32da3659d341f 100644
--- a/PCbuild/pythoncore.vcxproj.filters
+++ b/PCbuild/pythoncore.vcxproj.filters
@@ -186,6 +186,9 @@
     <ClInclude Include="..\Include\import.h">
       <Filter>Include</Filter>
     </ClInclude>
+    <ClInclude Include="..\Include\internal\pycore_abstract.h">
+      <Filter>Include</Filter>
+    </ClInclude>
     <ClInclude Include="..\Include\internal\pycore_accu.h">
       <Filter>Include</Filter>
     </ClInclude>
diff --git a/Python/ceval.c b/Python/ceval.c
index d79a239704f0a..7747b084f0833 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -10,6 +10,7 @@
 #define PY_LOCAL_AGGRESSIVE
 
 #include "Python.h"
+#include "pycore_abstract.h"   // _PyIndex_Check()
 #include "pycore_call.h"
 #include "pycore_ceval.h"
 #include "pycore_code.h"
@@ -5089,7 +5090,7 @@ _PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi)
     PyThreadState *tstate = _PyThreadState_GET();
     if (v != Py_None) {
         Py_ssize_t x;
-        if (PyIndex_Check(v)) {
+        if (_PyIndex_Check(v)) {
             x = PyNumber_AsSsize_t(v, NULL);
             if (x == -1 && _PyErr_Occurred(tstate))
                 return 0;
@@ -5110,7 +5111,7 @@ _PyEval_SliceIndexNotNone(PyObject *v, Py_ssize_t *pi)
 {
     PyThreadState *tstate = _PyThreadState_GET();
     Py_ssize_t x;
-    if (PyIndex_Check(v)) {
+    if (_PyIndex_Check(v)) {
         x = PyNumber_AsSsize_t(v, NULL);
         if (x == -1 && _PyErr_Occurred(tstate))
             return 0;
diff --git a/Python/modsupport.c b/Python/modsupport.c
index a8e78c3cec88b..845bdcb2b6f1b 100644
--- a/Python/modsupport.c
+++ b/Python/modsupport.c
@@ -2,6 +2,7 @@
 /* Module support implementation */
 
 #include "Python.h"
+#include "pycore_abstract.h"   // _PyIndex_Check()
 
 #define FLAG_SIZE_T 1
 typedef double va_double;
@@ -20,7 +21,7 @@ _Py_convert_optional_to_ssize_t(PyObject *obj, void *result)
     if (obj == Py_None) {
         return 1;
     }
-    else if (PyIndex_Check(obj)) {
+    else if (_PyIndex_Check(obj)) {
         limit = PyNumber_AsSsize_t(obj, PyExc_OverflowError);
         if (limit == -1 && PyErr_Occurred()) {
             return 0;



More information about the Python-checkins mailing list