summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/cpython/methodobject.h3
-rw-r--r--Include/methodobject.h3
-rw-r--r--Misc/NEWS.d/next/C API/2020-05-10-16-39-08.bpo-38787.XzQ59O.rst2
-rw-r--r--Objects/abstract.c2
-rw-r--r--Python/ceval.c4
5 files changed, 10 insertions, 4 deletions
diff --git a/Include/cpython/methodobject.h b/Include/cpython/methodobject.h
index 2ac2cbf..7ecbfe3 100644
--- a/Include/cpython/methodobject.h
+++ b/Include/cpython/methodobject.h
@@ -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) \
diff --git a/Include/methodobject.h b/Include/methodobject.h
index 7c7362c..12e049b 100644
--- a/Include/methodobject.h
+++ b/Include/methodobject.h
@@ -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
index 0000000..f80be66
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2020-05-10-16-39-08.bpo-38787.XzQ59O.rst
@@ -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.
diff --git a/Objects/abstract.c b/Objects/abstract.c
index b014f79..5b85b01 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -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,
diff --git a/Python/ceval.c b/Python/ceval.c
index e54e344..699ad86 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -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;
}