From 166d6299efd962f9a97fba7f3340e6a4b6c8213b Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Sun, 10 May 2020 16:39:17 +0200 Subject: [PATCH 1/3] bpo-38787: Add PyCFunction_CheckExact() macro for exact type checks now that we allow subtypes of PyCFunction. Also add PyCMethod_CheckExact() and PyCMethod_Check() for checks against the PyCMethod subtype. --- Include/methodobject.h | 6 +++++- Objects/abstract.c | 2 +- Python/ceval.c | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Include/methodobject.h b/Include/methodobject.h index 7c7362cded35b8..bf5ae73424dfe2 100644 --- a/Include/methodobject.h +++ b/Include/methodobject.h @@ -13,7 +13,11 @@ 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) + +#define PyCMethod_CheckExact(op) Py_IS_TYPE(op, &PyCMethod_Type) +#define PyCMethod_Check(op) PyObject_TypeCheck(op, &PyCMethod_Type) typedef PyObject *(*PyCFunction)(PyObject *, PyObject *); typedef PyObject *(*_PyCFunctionFast) (PyObject *, PyObject *const *, Py_ssize_t); diff --git a/Objects/abstract.c b/Objects/abstract.c index 6e390dd92c3aef..cc9c33df0bf588 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 6435bd05446aa2..42e36ef2a9987c 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; } From f018748577844977cb74dcc0dd6ee252f693ab80 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Sun, 10 May 2020 16:44:36 +0200 Subject: [PATCH 2/3] Add news entry. --- .../Core and Builtins/2020-05-10-16-39-08.bpo-38787.XzQ59O.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2020-05-10-16-39-08.bpo-38787.XzQ59O.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-05-10-16-39-08.bpo-38787.XzQ59O.rst b/Misc/NEWS.d/next/Core and Builtins/2020-05-10-16-39-08.bpo-38787.XzQ59O.rst new file mode 100644 index 00000000000000..f80be666c1c200 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/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. From 8795b9f45b41f5bfffc2855155d0a0e919c6f86c Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Tue, 12 May 2020 11:23:26 +0200 Subject: [PATCH 3/3] Apply suggestions from code review: move News entry, move PyCMethod_Check*() macros out of the limited API. --- Include/cpython/methodobject.h | 3 +++ Include/methodobject.h | 3 --- .../2020-05-10-16-39-08.bpo-38787.XzQ59O.rst | 0 3 files changed, 3 insertions(+), 3 deletions(-) rename Misc/NEWS.d/next/{Core and Builtins => C API}/2020-05-10-16-39-08.bpo-38787.XzQ59O.rst (100%) diff --git a/Include/cpython/methodobject.h b/Include/cpython/methodobject.h index 2ac2cbf36aa796..7ecbfe3b5e2fe8 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 bf5ae73424dfe2..12e049b4043ba5 100644 --- a/Include/methodobject.h +++ b/Include/methodobject.h @@ -16,9 +16,6 @@ PyAPI_DATA(PyTypeObject) PyCFunction_Type; #define PyCFunction_CheckExact(op) Py_IS_TYPE(op, &PyCFunction_Type) #define PyCFunction_Check(op) PyObject_TypeCheck(op, &PyCFunction_Type) -#define PyCMethod_CheckExact(op) Py_IS_TYPE(op, &PyCMethod_Type) -#define PyCMethod_Check(op) PyObject_TypeCheck(op, &PyCMethod_Type) - typedef PyObject *(*PyCFunction)(PyObject *, PyObject *); typedef PyObject *(*_PyCFunctionFast) (PyObject *, PyObject *const *, Py_ssize_t); typedef PyObject *(*PyCFunctionWithKeywords)(PyObject *, PyObject *, diff --git a/Misc/NEWS.d/next/Core and Builtins/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 similarity index 100% rename from Misc/NEWS.d/next/Core and Builtins/2020-05-10-16-39-08.bpo-38787.XzQ59O.rst rename to Misc/NEWS.d/next/C API/2020-05-10-16-39-08.bpo-38787.XzQ59O.rst