From a1b2d5b8dc5d3ca71858ac28168edb3d1999b327 Mon Sep 17 00:00:00 2001 From: rdb Date: Sat, 12 Dec 2020 16:49:36 +0100 Subject: [PATCH] Make use of new function call methods in Python 3.9 --- direct/src/dcparser/dcClass_ext.cxx | 4 +-- direct/src/dcparser/dcPacker_ext.cxx | 2 +- .../src/distributed/cConnectionRepository.cxx | 4 +-- dtool/src/interrogatedb/py_compat.cxx | 18 ++++++++++++ dtool/src/interrogatedb/py_compat.h | 28 +++++++++++++++---- dtool/src/interrogatedb/py_panda.cxx | 2 +- dtool/src/interrogatedb/py_wrappers.cxx | 2 +- panda/src/event/pythonTask.cxx | 12 ++++---- panda/src/linmath/lvecBase2_ext_src.I | 6 ++-- panda/src/linmath/lvecBase3_ext_src.I | 6 ++-- panda/src/linmath/lvecBase4_ext_src.I | 6 ++-- panda/src/putil/typedWritable_ext.cxx | 2 +- 12 files changed, 63 insertions(+), 29 deletions(-) diff --git a/direct/src/dcparser/dcClass_ext.cxx b/direct/src/dcparser/dcClass_ext.cxx index a37749b04a..f66156a322 100644 --- a/direct/src/dcparser/dcClass_ext.cxx +++ b/direct/src/dcparser/dcClass_ext.cxx @@ -400,9 +400,7 @@ pack_required_field(DCPacker &packer, PyObject *distobj, PyObject_GetAttrString(distobj, (char *)getter_name.c_str()); nassertr(func != nullptr, false); - PyObject *empty_args = PyTuple_New(0); - PyObject *result = PyObject_CallObject(func, empty_args); - Py_DECREF(empty_args); + PyObject *result = PyObject_CallNoArgs(func); Py_DECREF(func); if (result == nullptr) { // We don't set this as an exception, since presumably the Python method diff --git a/direct/src/dcparser/dcPacker_ext.cxx b/direct/src/dcparser/dcPacker_ext.cxx index 0b1770b819..c0a5164551 100644 --- a/direct/src/dcparser/dcPacker_ext.cxx +++ b/direct/src/dcparser/dcPacker_ext.cxx @@ -309,7 +309,7 @@ unpack_class_object(const DCClass *dclass) { if (!dclass->has_constructor()) { // If the class uses a default constructor, go ahead and create the Python // object for it now. - object = PyObject_CallObject(class_def, nullptr); + object = PyObject_CallNoArgs(class_def); if (object == nullptr) { return nullptr; } diff --git a/direct/src/distributed/cConnectionRepository.cxx b/direct/src/distributed/cConnectionRepository.cxx index 5df82cd619..cbd3057488 100644 --- a/direct/src/distributed/cConnectionRepository.cxx +++ b/direct/src/distributed/cConnectionRepository.cxx @@ -918,8 +918,8 @@ describe_message(std::ostream &out, const string &prefix, PyObject *methodName = PyUnicode_FromString("_getMsgName"); nassertv(methodName != nullptr); - PyObject *result = PyObject_CallMethodObjArgs(_python_repository, methodName, - msgId, nullptr); + PyObject *result = + PyObject_CallMethodOneArg(_python_repository, methodName, msgId); nassertv(result != nullptr); msgName += string(PyUnicode_AsUTF8(result)); diff --git a/dtool/src/interrogatedb/py_compat.cxx b/dtool/src/interrogatedb/py_compat.cxx index 722bc8300b..575a7f8241 100644 --- a/dtool/src/interrogatedb/py_compat.cxx +++ b/dtool/src/interrogatedb/py_compat.cxx @@ -43,4 +43,22 @@ size_t PyLongOrInt_AsSize_t(PyObject *vv) { } #endif +#if PY_VERSION_HEX < 0x03090000 +/** + * Most efficient way to call a function without any arguments. + */ +PyObject *PyObject_CallNoArgs(PyObject *func) { +#if PY_VERSION_HEX >= 0x03080000 + return _PyObject_Vectorcall(func, nullptr, 0, nullptr); +#elif PY_VERSION_HEX >= 0x03070000 + return _PyObject_FastCallDict(func, nullptr, 0, nullptr); +#elif PY_VERSION_HEX >= 0x03060000 + return _PyObject_FastCall(func, nullptr, 0); +#else + static PyObject *empty_tuple = PyTuple_New(0); + return PyObject_Call(func, empty_tuple, nullptr); +#endif +} +#endif + #endif // HAVE_PYTHON diff --git a/dtool/src/interrogatedb/py_compat.h b/dtool/src/interrogatedb/py_compat.h index 2152a115cc..2cfd913b7f 100644 --- a/dtool/src/interrogatedb/py_compat.h +++ b/dtool/src/interrogatedb/py_compat.h @@ -140,11 +140,7 @@ typedef long Py_hash_t; /* Python 3.6 */ #if PY_VERSION_HEX < 0x03080000 && !defined(_PyObject_CallNoArg) -INLINE PyObject *_PyObject_CallNoArg(PyObject *func) { - static PyObject *empty_tuple = PyTuple_New(0); - return PyObject_Call(func, empty_tuple, nullptr); -} -# define _PyObject_CallNoArg _PyObject_CallNoArg +# define _PyObject_CallNoArg PyObject_CallNoArgs #endif #if PY_VERSION_HEX < 0x03080000 && !defined(_PyObject_FastCall) @@ -208,6 +204,28 @@ INLINE PyObject *_PyLong_Lshift(PyObject *a, size_t shiftby) { } #endif +/* Python 3.9 */ + +#if PY_VERSION_HEX < 0x03090000 +EXPCL_PYPANDA PyObject *PyObject_CallNoArgs(PyObject *func); + +INLINE PyObject *PyObject_CallOneArg(PyObject *callable, PyObject *arg) { +#if PY_VERSION_HEX >= 0x03060000 + return _PyObject_FastCall(callable, &arg, 1); +#else + return PyObject_CallFunctionObjArgs(callable, arg, nullptr); +#endif +} + +INLINE PyObject *PyObject_CallMethodNoArgs(PyObject *obj, PyObject *name) { + return PyObject_CallMethodObjArgs(obj, name, nullptr); +} + +INLINE PyObject *PyObject_CallMethodOneArg(PyObject *obj, PyObject *name, PyObject *arg) { + return PyObject_CallMethodObjArgs(obj, name, arg, nullptr); +} +#endif + /* Other Python implementations */ // _PyErr_OCCURRED is an undocumented macro version of PyErr_Occurred. diff --git a/dtool/src/interrogatedb/py_panda.cxx b/dtool/src/interrogatedb/py_panda.cxx index f83ea7a367..c4d95691f2 100644 --- a/dtool/src/interrogatedb/py_panda.cxx +++ b/dtool/src/interrogatedb/py_panda.cxx @@ -755,7 +755,7 @@ PyObject *copy_from_make_copy(PyObject *self, PyObject *noargs) { */ PyObject *copy_from_copy_constructor(PyObject *self, PyObject *noargs) { PyObject *callable = (PyObject *)Py_TYPE(self); - return _PyObject_FastCall(callable, &self, 1); + return PyObject_CallOneArg(callable, self); } /** diff --git a/dtool/src/interrogatedb/py_wrappers.cxx b/dtool/src/interrogatedb/py_wrappers.cxx index 0b1bb59c66..e0a31803ed 100644 --- a/dtool/src/interrogatedb/py_wrappers.cxx +++ b/dtool/src/interrogatedb/py_wrappers.cxx @@ -30,7 +30,7 @@ static void _register_collection(PyTypeObject *type, const char *abc) { #endif PyObject *sequence = PyDict_GetItemString(dict, abc); if (sequence != nullptr) { - if (PyObject_CallMethodObjArgs(sequence, register_str, (PyObject *)type, nullptr) == nullptr) { + if (PyObject_CallMethodOneArg(sequence, register_str, (PyObject *)type) == nullptr) { PyErr_Print(); } } diff --git a/panda/src/event/pythonTask.cxx b/panda/src/event/pythonTask.cxx index 23320bbb64..6796940d6f 100644 --- a/panda/src/event/pythonTask.cxx +++ b/panda/src/event/pythonTask.cxx @@ -266,11 +266,11 @@ exception() const { Py_INCREF(Py_None); return Py_None; } else if (_exc_value == nullptr || _exc_value == Py_None) { - return _PyObject_CallNoArg(_exception); + return PyObject_CallNoArgs(_exception); } else if (PyTuple_Check(_exc_value)) { return PyObject_Call(_exception, _exc_value, nullptr); } else { - return PyObject_CallFunctionObjArgs(_exception, _exc_value, nullptr); + return PyObject_CallOneArg(_exception, _exc_value); } }*/ @@ -481,7 +481,7 @@ do_python_task() { // Are we waiting for a future to finish? if (_future_done != nullptr) { - PyObject *is_done = PyObject_CallObject(_future_done, nullptr); + PyObject *is_done = PyObject_CallNoArgs(_future_done); if (!PyObject_IsTrue(is_done)) { // Nope, ask again next frame. Py_DECREF(is_done); @@ -543,12 +543,12 @@ do_python_task() { // we need to be able to read the value from a StopIteration exception. PyObject *func = PyObject_GetAttrString(_generator, "send"); nassertr(func != nullptr, DS_interrupt); - result = PyObject_CallFunctionObjArgs(func, Py_None, nullptr); + result = PyObject_CallOneArg(func, Py_None); Py_DECREF(func); } else { // Throw a CancelledError into the generator. _must_cancel = false; - PyObject *exc = _PyObject_CallNoArg(Extension::get_cancelled_error_type()); + PyObject *exc = PyObject_CallNoArgs(Extension::get_cancelled_error_type()); PyObject *func = PyObject_GetAttrString(_generator, "throw"); result = PyObject_CallFunctionObjArgs(func, exc, nullptr); Py_DECREF(func); @@ -892,7 +892,7 @@ call_function(PyObject *function) { if (function != Py_None) { this->ref(); PyObject *self = DTool_CreatePyInstance(this, Dtool_PythonTask, true, false); - PyObject *result = PyObject_CallFunctionObjArgs(function, self, nullptr); + PyObject *result = PyObject_CallOneArg(function, self); Py_XDECREF(result); Py_DECREF(self); } diff --git a/panda/src/linmath/lvecBase2_ext_src.I b/panda/src/linmath/lvecBase2_ext_src.I index 3f47003e9a..e089ec6855 100644 --- a/panda/src/linmath/lvecBase2_ext_src.I +++ b/panda/src/linmath/lvecBase2_ext_src.I @@ -221,7 +221,7 @@ __round__(PyObject *self) const { #ifndef CPPPARSER extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase2); #endif - PyObject *py_vec = _PyObject_CallNoArg((PyObject *)DtoolInstance_TYPE(self)); + PyObject *py_vec = PyObject_CallNoArgs((PyObject *)DtoolInstance_TYPE(self)); if (py_vec != nullptr) { FLOATNAME(LVecBase2) *vec = (FLOATNAME(LVecBase2) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase2)); nassertr(vec != nullptr, nullptr); @@ -241,7 +241,7 @@ __floor__(PyObject *self) const { extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase2); #endif - PyObject *py_vec = _PyObject_CallNoArg((PyObject *)DtoolInstance_TYPE(self)); + PyObject *py_vec = PyObject_CallNoArgs((PyObject *)DtoolInstance_TYPE(self)); if (py_vec != nullptr) { FLOATNAME(LVecBase2) *vec = (FLOATNAME(LVecBase2) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase2)); nassertr(vec != nullptr, nullptr); @@ -260,7 +260,7 @@ __ceil__(PyObject *self) const { #ifndef CPPPARSER extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase2); #endif - PyObject *py_vec = _PyObject_CallNoArg((PyObject *)DtoolInstance_TYPE(self)); + PyObject *py_vec = PyObject_CallNoArgs((PyObject *)DtoolInstance_TYPE(self)); if (py_vec != nullptr) { FLOATNAME(LVecBase2) *vec = (FLOATNAME(LVecBase2) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase2)); nassertr(vec != nullptr, nullptr); diff --git a/panda/src/linmath/lvecBase3_ext_src.I b/panda/src/linmath/lvecBase3_ext_src.I index b29d01fbc5..a93ae5546d 100644 --- a/panda/src/linmath/lvecBase3_ext_src.I +++ b/panda/src/linmath/lvecBase3_ext_src.I @@ -224,7 +224,7 @@ __round__(PyObject *self) const { #ifndef CPPPARSER extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase3); #endif - PyObject *py_vec = _PyObject_CallNoArg((PyObject *)DtoolInstance_TYPE(self)); + PyObject *py_vec = PyObject_CallNoArgs((PyObject *)DtoolInstance_TYPE(self)); if (py_vec != nullptr) { FLOATNAME(LVecBase3) *vec = (FLOATNAME(LVecBase3) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase3)); nassertr(vec != nullptr, nullptr); @@ -244,7 +244,7 @@ __floor__(PyObject *self) const { #ifndef CPPPARSER extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase3); #endif - PyObject *py_vec = _PyObject_CallNoArg((PyObject *)DtoolInstance_TYPE(self)); + PyObject *py_vec = PyObject_CallNoArgs((PyObject *)DtoolInstance_TYPE(self)); if (py_vec != nullptr) { FLOATNAME(LVecBase3) *vec = (FLOATNAME(LVecBase3) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase3)); nassertr(vec != nullptr, nullptr); @@ -264,7 +264,7 @@ __ceil__(PyObject *self) const { #ifndef CPPPARSER extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase3); #endif - PyObject *py_vec = _PyObject_CallNoArg((PyObject *)DtoolInstance_TYPE(self)); + PyObject *py_vec = PyObject_CallNoArgs((PyObject *)DtoolInstance_TYPE(self)); if (py_vec != nullptr) { FLOATNAME(LVecBase3) *vec = (FLOATNAME(LVecBase3) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase3)); nassertr(vec != nullptr, nullptr); diff --git a/panda/src/linmath/lvecBase4_ext_src.I b/panda/src/linmath/lvecBase4_ext_src.I index 66d1bd6e0c..b0fa4a76fa 100644 --- a/panda/src/linmath/lvecBase4_ext_src.I +++ b/panda/src/linmath/lvecBase4_ext_src.I @@ -232,7 +232,7 @@ __round__(PyObject *self) const { #ifndef CPPPARSER extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase4); #endif - PyObject *py_vec = _PyObject_CallNoArg((PyObject *)DtoolInstance_TYPE(self)); + PyObject *py_vec = PyObject_CallNoArgs((PyObject *)DtoolInstance_TYPE(self)); if (py_vec != nullptr) { FLOATNAME(LVecBase4) *vec = (FLOATNAME(LVecBase4) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase4)); nassertr(vec != nullptr, nullptr); @@ -253,7 +253,7 @@ __floor__(PyObject *self) const { #ifndef CPPPARSER extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase4); #endif - PyObject *py_vec = _PyObject_CallNoArg((PyObject *)DtoolInstance_TYPE(self)); + PyObject *py_vec = PyObject_CallNoArgs((PyObject *)DtoolInstance_TYPE(self)); if (py_vec != nullptr) { FLOATNAME(LVecBase4) *vec = (FLOATNAME(LVecBase4) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase4)); nassertr(vec != nullptr, nullptr); @@ -274,7 +274,7 @@ __ceil__(PyObject *self) const { #ifndef CPPPARSER extern struct Dtool_PyTypedObject FLOATNAME(Dtool_LVecBase4); #endif - PyObject *py_vec = _PyObject_CallNoArg((PyObject *)DtoolInstance_TYPE(self)); + PyObject *py_vec = PyObject_CallNoArgs((PyObject *)DtoolInstance_TYPE(self)); if (py_vec != nullptr) { FLOATNAME(LVecBase4) *vec = (FLOATNAME(LVecBase4) *)DtoolInstance_UPCAST(py_vec, FLOATNAME(Dtool_LVecBase4)); nassertr(vec != nullptr, nullptr); diff --git a/panda/src/putil/typedWritable_ext.cxx b/panda/src/putil/typedWritable_ext.cxx index 3db4b086c3..f6d7d140fe 100644 --- a/panda/src/putil/typedWritable_ext.cxx +++ b/panda/src/putil/typedWritable_ext.cxx @@ -230,7 +230,7 @@ py_decode_TypedWritable_from_bam_stream_persist(PyObject *pickler, PyObject *thi result = PyObject_CallFunctionObjArgs(func, bytes, py_reader, nullptr); Py_DECREF(py_reader); } else { - result = PyObject_CallFunctionObjArgs(func, bytes, nullptr); + result = PyObject_CallOneArg(func, bytes); } Py_DECREF(bytes); Py_DECREF(func);