]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-38787: Add PyCFunction_CheckExact() macro for exact type checks (GH-20024)
authorscoder <stefan_ml@behnel.de>
Tue, 12 May 2020 14:12:41 +0000 (16:12 +0200)
committerGitHub <noreply@github.com>
Tue, 12 May 2020 14:12:41 +0000 (07:12 -0700)
… now that we allow subtypes of PyCFunction.

Also add PyCMethod_CheckExact() and PyCMethod_Check() for checks against the PyCMethod subtype.

Include/cpython/methodobject.h
Include/methodobject.h
Misc/NEWS.d/next/C API/2020-05-10-16-39-08.bpo-38787.XzQ59O.rst [new file with mode: 0644]
Objects/abstract.c
Python/ceval.c

index 2ac2cbf36aa79640704f74857603488620ab5b9b..7ecbfe3b5e2fe87d9482bd56f72b69fce37d6c26 100644 (file)
@@ -4,6 +4,9 @@
 
 PyAPI_DATA(PyTypeObject) PyCMethod_Type;
 
+#define PyCMethod_CheckExact(op) Py_IS_TYPE(op, &PyCMethod_Type)
+#define PyCMethod_Check(op) PyObject_TypeCheck(op, &PyCMethod_Type)
+
 /* Macros for direct access to these values. Type checks are *not*
    done, so use with care. */
 #define PyCFunction_GET_FUNCTION(func) \
index 7c7362cded35b80fdf04dc8caffce216b68b0913..12e049b4043ba59fe15ea709f261cdce10a29a79 100644 (file)
@@ -13,7 +13,8 @@ extern "C" {
 
 PyAPI_DATA(PyTypeObject) PyCFunction_Type;
 
-#define PyCFunction_Check(op) (Py_IS_TYPE(op, &PyCFunction_Type) || (PyType_IsSubtype(Py_TYPE(op), &PyCFunction_Type)))
+#define PyCFunction_CheckExact(op) Py_IS_TYPE(op, &PyCFunction_Type)
+#define PyCFunction_Check(op) PyObject_TypeCheck(op, &PyCFunction_Type)
 
 typedef PyObject *(*PyCFunction)(PyObject *, PyObject *);
 typedef PyObject *(*_PyCFunctionFast) (PyObject *, PyObject *const *, Py_ssize_t);
diff --git a/Misc/NEWS.d/next/C API/2020-05-10-16-39-08.bpo-38787.XzQ59O.rst b/Misc/NEWS.d/next/C API/2020-05-10-16-39-08.bpo-38787.XzQ59O.rst
new file mode 100644 (file)
index 0000000..f80be66
--- /dev/null
@@ -0,0 +1,2 @@
+Add PyCFunction_CheckExact() macro for exact type checks now that we allow subtypes of PyCFunction,
+as well as PyCMethod_CheckExact() and PyCMethod_Check() for the new PyCMethod subtype.
index b014f79e8d0fba7078ba919367acc81d696a19c5..5b85b014bd22e3f5fa4a0b4c983885c3833263c4 100644 (file)
@@ -900,7 +900,7 @@ binary_op(PyObject *v, PyObject *w, const int op_slot, const char *op_name)
         Py_DECREF(result);
 
         if (op_slot == NB_SLOT(nb_rshift) &&
-            PyCFunction_Check(v) &&
+            PyCFunction_CheckExact(v) &&
             strcmp(((PyCFunctionObject *)v)->m_ml->ml_name, "print") == 0)
         {
             PyErr_Format(PyExc_TypeError,
index e54e344a5fd5145031f369695d6a474f94ecbffa..699ad86a365b183149b9628b99ec141ba9beec2a 100644 (file)
@@ -5054,7 +5054,7 @@ trace_call_function(PyThreadState *tstate,
                     PyObject *kwnames)
 {
     PyObject *x;
-    if (PyCFunction_Check(func)) {
+    if (PyCFunction_CheckExact(func) || PyCMethod_CheckExact(func)) {
         C_TRACE(x, PyObject_Vectorcall(func, args, nargs, kwnames));
         return x;
     }
@@ -5115,7 +5115,7 @@ do_call_core(PyThreadState *tstate, PyObject *func, PyObject *callargs, PyObject
 {
     PyObject *result;
 
-    if (PyCFunction_Check(func)) {
+    if (PyCFunction_CheckExact(func) || PyCMethod_CheckExact(func)) {
         C_TRACE(result, PyObject_Call(func, callargs, kwdict));
         return result;
     }