Changes for compatibility with Python 3.13
Includes some preliminary work to make free-threading safe, see also #1683
This commit is contained in:
parent
b32459ffa1
commit
5106fc879f
|
|
@ -688,11 +688,12 @@ handle_update_field() {
|
|||
nassertr(doId2do != nullptr, false);
|
||||
|
||||
PyObject *doId = PyLong_FromUnsignedLong(do_id);
|
||||
PyObject *distobj = PyDict_GetItem(doId2do, doId);
|
||||
PyObject *distobj;
|
||||
int result = PyDict_GetItemRef(doId2do, doId, &distobj);
|
||||
Py_DECREF(doId);
|
||||
Py_DECREF(doId2do);
|
||||
|
||||
if (distobj != nullptr) {
|
||||
if (result > 0) {
|
||||
PyObject *dclass_obj = PyObject_GetAttrString(distobj, "dclass");
|
||||
nassertr(dclass_obj != nullptr, false);
|
||||
|
||||
|
|
@ -715,6 +716,7 @@ handle_update_field() {
|
|||
if (!cNeverDisable) {
|
||||
// in quiet zone and distobj is disable-able drop update on the
|
||||
// floor
|
||||
Py_DECREF(distobj);
|
||||
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
|
||||
PyGILState_Release(gstate);
|
||||
#endif
|
||||
|
|
@ -722,13 +724,8 @@ handle_update_field() {
|
|||
}
|
||||
}
|
||||
|
||||
// It's a good idea to ensure the reference count to distobj is raised
|
||||
// while we call the update method--otherwise, the update method might
|
||||
// get into trouble if it tried to delete the object from the doId2do
|
||||
// map.
|
||||
PyObject *distobj_ref = Py_NewRef(distobj);
|
||||
invoke_extension(dclass).receive_update(distobj_ref, _di);
|
||||
Py_DECREF(distobj_ref);
|
||||
invoke_extension(dclass).receive_update(distobj, _di);
|
||||
Py_DECREF(distobj);
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
|
||||
|
|
@ -778,10 +775,11 @@ handle_update_field_owner() {
|
|||
PyObject *doId = PyLong_FromUnsignedLong(do_id);
|
||||
|
||||
// pass the update to the owner view first
|
||||
PyObject *distobjOV = PyDict_GetItem(doId2ownerView, doId);
|
||||
PyObject *distobjOV;
|
||||
int result = PyDict_GetItemRef(doId2ownerView, doId, &distobjOV);
|
||||
Py_DECREF(doId2ownerView);
|
||||
|
||||
if (distobjOV != nullptr) {
|
||||
if (result > 0) {
|
||||
PyObject *dclass_obj = PyObject_GetAttrString(distobjOV, "dclass");
|
||||
nassertr(dclass_obj != nullptr, false);
|
||||
|
||||
|
|
@ -799,32 +797,29 @@ handle_update_field_owner() {
|
|||
int field_id = packer.raw_unpack_uint16();
|
||||
DCField *field = dclass->get_field_by_index(field_id);
|
||||
if (field->is_ownrecv()) {
|
||||
// It's a good idea to ensure the reference count to distobjOV is
|
||||
// raised while we call the update method--otherwise, the update
|
||||
// method might get into trouble if it tried to delete the object from
|
||||
// the doId2do map.
|
||||
PyObject *distobjOV_ref = Py_NewRef(distobjOV);
|
||||
// make a copy of the datagram iterator so that we can use the main
|
||||
// iterator for the non-owner update
|
||||
DatagramIterator _odi(_di);
|
||||
invoke_extension(dclass).receive_update(distobjOV_ref, _odi);
|
||||
Py_DECREF(distobjOV_ref);
|
||||
invoke_extension(dclass).receive_update(distobjOV, _odi);
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
Py_DECREF(distobjOV);
|
||||
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
|
||||
PyGILState_Release(gstate);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Py_DECREF(distobjOV);
|
||||
}
|
||||
|
||||
// now pass the update to the visible view
|
||||
PyObject *distobj = PyDict_GetItem(doId2do, doId);
|
||||
PyObject *distobj;
|
||||
result = PyDict_GetItemRef(doId2do, doId, &distobj);
|
||||
Py_DECREF(doId);
|
||||
Py_DECREF(doId2do);
|
||||
|
||||
if (distobj != nullptr) {
|
||||
if (result > 0) {
|
||||
PyObject *dclass_obj = PyObject_GetAttrString(distobj, "dclass");
|
||||
nassertr(dclass_obj != nullptr, false);
|
||||
|
||||
|
|
@ -843,21 +838,17 @@ handle_update_field_owner() {
|
|||
//int field_id = packer.raw_unpack_uint16();
|
||||
//DCField *field = dclass->get_field_by_index(field_id);
|
||||
if (true) {//field->is_broadcast()) {
|
||||
// It's a good idea to ensure the reference count to distobj is raised
|
||||
// while we call the update method--otherwise, the update method might
|
||||
// get into trouble if it tried to delete the object from the doId2do
|
||||
// map.
|
||||
PyObject *distobj_ref = Py_NewRef(distobj);
|
||||
invoke_extension(dclass).receive_update(distobj_ref, _di);
|
||||
Py_DECREF(distobj_ref);
|
||||
invoke_extension(dclass).receive_update(distobj, _di);
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
Py_DECREF(distobj);
|
||||
#if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
|
||||
PyGILState_Release(gstate);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Py_DECREF(distobj);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -957,12 +948,14 @@ describe_message(std::ostream &out, const string &prefix,
|
|||
nassertv(doId2do != nullptr);
|
||||
|
||||
PyObject *doId = PyLong_FromUnsignedLong(do_id);
|
||||
PyObject *distobj = PyDict_GetItem(doId2do, doId);
|
||||
PyObject *distobj;
|
||||
int result = PyDict_GetItemRef(doId2do, doId, &distobj);
|
||||
Py_DECREF(doId);
|
||||
Py_DECREF(doId2do);
|
||||
|
||||
if (distobj != nullptr) {
|
||||
if (result > 0) {
|
||||
PyObject *dclass_obj = PyObject_GetAttrString(distobj, "dclass");
|
||||
Py_DECREF(distobj);
|
||||
nassertv(dclass_obj != nullptr);
|
||||
|
||||
PyObject *dclass_this = PyObject_GetAttrString(dclass_obj, "this");
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ if(BUILD_INTERROGATE)
|
|||
panda3d-interrogate
|
||||
|
||||
GIT_REPOSITORY https://github.com/panda3d/interrogate.git
|
||||
GIT_TAG e297384b30f1eae8ab839ec096fc3bb6bdb3edeb
|
||||
GIT_TAG 742ea56a1934a7a05ee2518787cf6816f30ee096
|
||||
|
||||
PREFIX ${_interrogate_dir}
|
||||
CMAKE_ARGS
|
||||
|
|
|
|||
|
|
@ -49,19 +49,26 @@ __reduce__() const {
|
|||
PyTypeObject *py_type = _this->get_python_type();
|
||||
if (py_type != nullptr && py_type->tp_dict != nullptr) {
|
||||
// Look for a get_class_type method, if it returns this handle.
|
||||
PyObject *func = PyDict_GetItemString(py_type->tp_dict, "get_class_type");
|
||||
if (func != nullptr && PyCallable_Check(func)) {
|
||||
PyObject *result = PyObject_CallNoArgs(func);
|
||||
TypeHandle *result_handle = nullptr;
|
||||
if (result == nullptr) {
|
||||
// Never mind.
|
||||
PyErr_Clear();
|
||||
}
|
||||
else if (DtoolInstance_GetPointer(result, result_handle, Dtool_TypeHandle) &&
|
||||
*result_handle == *_this) {
|
||||
// It returned the correct result, so we can use this.
|
||||
return Py_BuildValue("O()", func);
|
||||
PyObject *func;
|
||||
int result = PyDict_GetItemStringRef(py_type->tp_dict, "get_class_type", &func);
|
||||
if (result > 0) {
|
||||
if (PyCallable_Check(func)) {
|
||||
PyObject *result = PyObject_CallNoArgs(func);
|
||||
TypeHandle *result_handle = nullptr;
|
||||
if (result == nullptr) {
|
||||
// Never mind.
|
||||
PyErr_Clear();
|
||||
}
|
||||
else if (DtoolInstance_GetPointer(result, result_handle, Dtool_TypeHandle) &&
|
||||
*result_handle == *_this) {
|
||||
// It returned the correct result, so we can use this.
|
||||
return Py_BuildValue("N()", func);
|
||||
}
|
||||
}
|
||||
Py_DECREF(func);
|
||||
}
|
||||
else if (result < 0) {
|
||||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -285,6 +285,71 @@ INLINE bool PyLong_IsNonNegative(PyObject *value) {
|
|||
# define PyLong_AsInt(x) (_PyLong_AsInt(x))
|
||||
#endif
|
||||
|
||||
#if PY_VERSION_HEX < 0x030D00A1
|
||||
ALWAYS_INLINE int
|
||||
PyModule_Add(PyObject *mod, const char *name, PyObject *value) {
|
||||
int res = PyModule_AddObjectRef(mod, name, value);
|
||||
Py_XDECREF(value);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if PY_VERSION_HEX < 0x030D00A1
|
||||
INLINE int
|
||||
PyDict_GetItemRef(PyObject *mp, PyObject *key, PyObject **result) {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyObject *item = PyDict_GetItemWithError(mp, key);
|
||||
#else
|
||||
PyObject *item = _PyDict_GetItemWithError(mp, key);
|
||||
#endif
|
||||
if (item != nullptr) {
|
||||
*result = Py_NewRef(item);
|
||||
return 1;
|
||||
}
|
||||
*result = nullptr;
|
||||
return PyErr_Occurred() ? -1 : 0;
|
||||
}
|
||||
|
||||
INLINE int
|
||||
PyDict_GetItemStringRef(PyObject *mp, const char *key, PyObject **result) {
|
||||
PyObject *item = nullptr;
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyObject *key_obj = PyUnicode_FromString(key);
|
||||
item = key_obj ? PyDict_GetItemWithError(mp, key_obj) : nullptr;
|
||||
#else
|
||||
PyObject *key_obj = PyString_FromString(key);
|
||||
item = key_obj ? _PyDict_GetItemWithError(mp, key_obj) : nullptr;
|
||||
#endif
|
||||
Py_DECREF(key_obj);
|
||||
if (item != nullptr) {
|
||||
*result = Py_NewRef(item);
|
||||
return 1;
|
||||
}
|
||||
*result = nullptr;
|
||||
return PyErr_Occurred() ? -1 : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if PY_VERSION_HEX >= 0x03050200 && PY_VERSION_HEX < 0x030D00A1
|
||||
# define PyThreadState_GetUnchecked() (_PyThreadState_UncheckedGet())
|
||||
#endif
|
||||
|
||||
#if PY_VERSION_HEX < 0x030D00A2
|
||||
# define PyList_Extend(list, iterable) (PyList_SetSlice((list), PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, (iterable)))
|
||||
# define PyList_Clear(list) (PyList_SetSlice((list), 0, PY_SSIZE_T_MAX, nullptr))
|
||||
#endif
|
||||
|
||||
#if PY_VERSION_HEX < 0x030D00A4
|
||||
# define PyList_GetItemRef(op, index) (Py_XNewRef(PyList_GetItem((op), (index))))
|
||||
#endif
|
||||
|
||||
#if PY_VERSION_HEX < 0x030D00B3
|
||||
# define Py_BEGIN_CRITICAL_SECTION(op) {
|
||||
# define Py_END_CRITICAL_SECTION() }
|
||||
# define Py_BEGIN_CRITICAL_SECTION2(a, b) {
|
||||
# define Py_END_CRITICAL_SECTION2() }
|
||||
#endif
|
||||
|
||||
/* Other Python implementations */
|
||||
|
||||
#endif // HAVE_PYTHON
|
||||
|
|
|
|||
|
|
@ -328,9 +328,9 @@ static PyObject *Dtool_EnumType_New(PyTypeObject *subtype, PyObject *args, PyObj
|
|||
PyObject *value2member = PyDict_GetItemString(subtype->tp_dict, "_value2member_map_");
|
||||
nassertr_always(value2member != nullptr, nullptr);
|
||||
|
||||
PyObject *member = PyDict_GetItem(value2member, arg);
|
||||
if (member != nullptr) {
|
||||
return Py_NewRef(member);
|
||||
PyObject *member;
|
||||
if (PyDict_GetItemRef(value2member, arg, &member) > 0) {
|
||||
return member;
|
||||
}
|
||||
|
||||
PyObject *repr = PyObject_Repr(arg);
|
||||
|
|
|
|||
|
|
@ -24,16 +24,18 @@ static void _register_collection(PyTypeObject *type, const char *abc) {
|
|||
PyObject *dict = PyModule_GetDict(module);
|
||||
if (module != nullptr) {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
static PyObject *register_str = PyUnicode_InternFromString("register");
|
||||
PyObject *register_str = PyUnicode_InternFromString("register");
|
||||
#else
|
||||
static PyObject *register_str = PyString_InternFromString("register");
|
||||
PyObject *register_str = PyString_InternFromString("register");
|
||||
#endif
|
||||
PyObject *sequence = PyDict_GetItemString(dict, abc);
|
||||
if (sequence != nullptr) {
|
||||
if (PyObject_CallMethodOneArg(sequence, register_str, (PyObject *)type) == nullptr) {
|
||||
PyErr_Print();
|
||||
}
|
||||
PyObject *obj = nullptr;
|
||||
if (register_str == nullptr ||
|
||||
PyDict_GetItemStringRef(dict, abc, &obj) <= 0 ||
|
||||
PyObject_CallMethodOneArg(obj, register_str, (PyObject *)type) == nullptr) {
|
||||
PyErr_Print();
|
||||
}
|
||||
Py_XDECREF(obj);
|
||||
Py_XDECREF(register_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1075,14 +1077,19 @@ static PyObject *Dtool_MutableMappingWrapper_update(PyObject *self, PyObject *ar
|
|||
return PyErr_Format(PyExc_TypeError, "%s.update() takes either a dict argument or keyword arguments", wrap->_base._name);
|
||||
}
|
||||
|
||||
PyObject *result = Py_None;
|
||||
PyObject *key, *value;
|
||||
Py_ssize_t pos = 0;
|
||||
Py_BEGIN_CRITICAL_SECTION(dict);
|
||||
while (PyDict_Next(dict, &pos, &key, &value)) {
|
||||
if (wrap->_setitem_func(wrap->_base._self, key, value) != 0) {
|
||||
return nullptr;
|
||||
result = nullptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Py_NewRef(Py_None);
|
||||
Py_END_CRITICAL_SECTION();
|
||||
|
||||
return Py_XNewRef(result);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -592,8 +592,8 @@ def GetInterrogateDir():
|
|||
return INTERROGATE_DIR
|
||||
|
||||
dir = os.path.join(GetOutputDir(), "tmp", "interrogate")
|
||||
if not os.path.isdir(os.path.join(dir, "panda3d_interrogate-0.1.0.dist-info")):
|
||||
oscmd("\"%s\" -m pip install --force-reinstall -t \"%s\" panda3d-interrogate==0.1.0" % (sys.executable, dir))
|
||||
if not os.path.isdir(os.path.join(dir, "panda3d_interrogate-0.1.1.dist-info")):
|
||||
oscmd("\"%s\" -m pip install --force-reinstall -t \"%s\" panda3d-interrogate==0.1.1" % (sys.executable, dir))
|
||||
|
||||
INTERROGATE_DIR = dir
|
||||
|
||||
|
|
|
|||
|
|
@ -52,13 +52,14 @@ __setstate__(PyObject *self, PyObject *props) {
|
|||
PyObject *key, *value;
|
||||
Py_ssize_t pos = 0;
|
||||
|
||||
Py_BEGIN_CRITICAL_SECTION(props);
|
||||
while (PyDict_Next(props, &pos, &key, &value)) {
|
||||
// Look for a writable property on the type by this name.
|
||||
PyObject *descr = _PyType_Lookup(type, key);
|
||||
|
||||
if (descr != nullptr && Py_TYPE(descr)->tp_descr_set != nullptr) {
|
||||
if (Py_TYPE(descr)->tp_descr_set(descr, self, value) < 0) {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
PyObject *key_repr = PyObject_Repr(key);
|
||||
|
|
@ -67,9 +68,10 @@ __setstate__(PyObject *self, PyObject *props) {
|
|||
PyUnicode_AsUTF8(key_repr)
|
||||
);
|
||||
Py_DECREF(key_repr);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Py_END_CRITICAL_SECTION();
|
||||
}
|
||||
|
||||
#endif // HAVE_PYTHON
|
||||
|
|
|
|||
|
|
@ -91,13 +91,14 @@ __setstate__(PyObject *self, PyObject *props) {
|
|||
PyObject *key, *value;
|
||||
Py_ssize_t pos = 0;
|
||||
|
||||
Py_BEGIN_CRITICAL_SECTION(props);
|
||||
while (PyDict_Next(props, &pos, &key, &value)) {
|
||||
// Look for a writable property on the type by this name.
|
||||
PyObject *descr = _PyType_Lookup(type, key);
|
||||
|
||||
if (descr != nullptr && Py_TYPE(descr)->tp_descr_set != nullptr) {
|
||||
if (Py_TYPE(descr)->tp_descr_set(descr, self, value) < 0) {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
PyObject *key_repr = PyObject_Repr(key);
|
||||
|
|
@ -106,9 +107,10 @@ __setstate__(PyObject *self, PyObject *props) {
|
|||
PyUnicode_AsUTF8(key_repr)
|
||||
);
|
||||
Py_DECREF(key_repr);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Py_END_CRITICAL_SECTION();
|
||||
}
|
||||
|
||||
#endif // HAVE_PYTHON
|
||||
|
|
|
|||
|
|
@ -30,9 +30,12 @@ __reduce__() const {
|
|||
PyObject *module_name = PyObject_GetAttrString((PyObject *)&Dtool_EggNode, "__module__");
|
||||
nassertr_always(module_name != nullptr, nullptr);
|
||||
|
||||
PyObject *module = PyDict_GetItem(sys_modules, module_name);
|
||||
PyObject *module;
|
||||
int res = PyDict_GetItemRef(sys_modules, module_name, &module);
|
||||
Py_DECREF(module_name);
|
||||
nassertr_always(module != nullptr, nullptr);
|
||||
if (res <= 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyObject *func;
|
||||
if (_this->is_of_type(EggData::get_class_type())) {
|
||||
|
|
@ -40,6 +43,7 @@ __reduce__() const {
|
|||
} else {
|
||||
func = PyObject_GetAttrString(module, "parse_egg_node");
|
||||
}
|
||||
Py_DECREF(module);
|
||||
nassertr_always(func != nullptr, nullptr);
|
||||
|
||||
// Get the egg syntax to pass to the parse_egg_node function.
|
||||
|
|
|
|||
|
|
@ -363,11 +363,9 @@ PyObject *PythonTask::
|
|||
__getattribute__(PyObject *self, PyObject *attr) const {
|
||||
// We consult the instance dict first, since the user may have overridden a
|
||||
// method or something.
|
||||
PyObject *item = PyDict_GetItem(__dict__, attr);
|
||||
|
||||
if (item != nullptr) {
|
||||
// PyDict_GetItem returns a borrowed reference.
|
||||
return Py_NewRef(item);
|
||||
PyObject *item;
|
||||
if (PyDict_GetItemRef(__dict__, attr, &item) > 0) {
|
||||
return item;
|
||||
}
|
||||
|
||||
return PyObject_GenericGetAttr(self, attr);
|
||||
|
|
|
|||
|
|
@ -56,10 +56,10 @@ __deepcopy__(PyObject *self, PyObject *memo) const {
|
|||
extern struct Dtool_PyTypedObject Dtool_NodePath;
|
||||
|
||||
// Borrowed reference.
|
||||
PyObject *dupe = PyDict_GetItem(memo, self);
|
||||
if (dupe != nullptr) {
|
||||
PyObject *dupe;
|
||||
if (PyDict_GetItemRef(memo, self, &dupe) > 0) {
|
||||
// Already in the memo dictionary.
|
||||
return Py_NewRef(dupe);
|
||||
return dupe;
|
||||
}
|
||||
|
||||
NodePath *np_dupe;
|
||||
|
|
@ -279,19 +279,21 @@ set_shader_inputs(PyObject *args, PyObject *kwargs) {
|
|||
PyObject *key, *value;
|
||||
Py_ssize_t pos = 0;
|
||||
|
||||
Py_BEGIN_CRITICAL_SECTION(dict);
|
||||
while (PyDict_Next(kwargs, &pos, &key, &value)) {
|
||||
char *buffer;
|
||||
Py_ssize_t length;
|
||||
buffer = (char *)PyUnicode_AsUTF8AndSize(key, &length);
|
||||
if (buffer == nullptr) {
|
||||
Dtool_Raise_TypeError("NodePath.set_shader_inputs accepts only string keywords");
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
CPT_InternalName name(std::string(buffer, length));
|
||||
ShaderInput &input = attrib->_inputs[name];
|
||||
invoke_extension(&input).__init__(std::move(name), value);
|
||||
}
|
||||
Py_END_CRITICAL_SECTION();
|
||||
|
||||
if (!PyErr_Occurred()) {
|
||||
node->set_attrib(ShaderAttrib::return_new(attrib));
|
||||
|
|
|
|||
|
|
@ -47,10 +47,10 @@ __deepcopy__(PyObject *self, PyObject *memo) const {
|
|||
extern struct Dtool_PyTypedObject Dtool_PandaNode;
|
||||
|
||||
// Borrowed reference.
|
||||
PyObject *dupe = PyDict_GetItem(memo, self);
|
||||
if (dupe != nullptr) {
|
||||
PyObject *dupe;
|
||||
if (PyDict_GetItemRef(memo, self, &dupe) > 0) {
|
||||
// Already in the memo dictionary.
|
||||
return Py_NewRef(dupe);
|
||||
return dupe;
|
||||
}
|
||||
|
||||
PT(PandaNode) node_dupe = _this->copy_subgraph();
|
||||
|
|
@ -122,12 +122,11 @@ get_python_tag(PyObject *key) const {
|
|||
}
|
||||
|
||||
PyObject *dict = ((PythonTagDataImpl *)_this->_python_tag_data.p())->_dict;
|
||||
PyObject *value = PyDict_GetItem(dict, key);
|
||||
if (value == nullptr) {
|
||||
value = Py_None;
|
||||
PyObject *value;
|
||||
if (PyDict_GetItemRef(dict, key, &value) == 0) {
|
||||
value = Py_NewRef(Py_None);
|
||||
}
|
||||
// PyDict_GetItem returns a borrowed reference.
|
||||
return Py_NewRef(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -142,7 +141,7 @@ has_python_tag(PyObject *key) const {
|
|||
}
|
||||
|
||||
PyObject *dict = ((PythonTagDataImpl *)_this->_python_tag_data.p())->_dict;
|
||||
return (PyDict_GetItem(dict, key) != nullptr);
|
||||
return PyDict_Contains(dict, key);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -157,7 +156,8 @@ clear_python_tag(PyObject *key) {
|
|||
}
|
||||
|
||||
PyObject *dict = do_get_python_tags();
|
||||
if (PyDict_GetItem(dict, key) != nullptr) {
|
||||
Py_BEGIN_CRITICAL_SECTION(dict);
|
||||
if (PyDict_Contains(dict, key)) {
|
||||
PyDict_DelItem(dict, key);
|
||||
}
|
||||
|
||||
|
|
@ -166,6 +166,7 @@ clear_python_tag(PyObject *key) {
|
|||
// unique reference to the tags, so clear the tag object.
|
||||
_this->_python_tag_data.clear();
|
||||
}
|
||||
Py_END_CRITICAL_SECTION();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ make(PyObject *args, PyObject *kwds) {
|
|||
|
||||
int override = 0;
|
||||
if (py_override != nullptr) {
|
||||
override = _PyLong_AsInt(py_override);
|
||||
override = PyLong_AsInt(py_override);
|
||||
if (override == -1 && PyErr_Occurred()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,22 +46,28 @@ set_shader_inputs(PyObject *args, PyObject *kwargs) const {
|
|||
PyObject *key, *value;
|
||||
Py_ssize_t pos = 0;
|
||||
|
||||
Py_BEGIN_CRITICAL_SECTION(kwargs);
|
||||
while (PyDict_Next(kwargs, &pos, &key, &value)) {
|
||||
char *buffer;
|
||||
Py_ssize_t length;
|
||||
buffer = (char *)PyUnicode_AsUTF8AndSize(key, &length);
|
||||
if (buffer == nullptr) {
|
||||
Dtool_Raise_TypeError("ShaderAttrib.set_shader_inputs accepts only string keywords");
|
||||
delete attrib;
|
||||
return nullptr;
|
||||
break;
|
||||
}
|
||||
|
||||
CPT_InternalName name(std::string(buffer, length));
|
||||
ShaderInput &input = attrib->_inputs[name];
|
||||
invoke_extension(&input).__init__(std::move(name), value);
|
||||
}
|
||||
Py_END_CRITICAL_SECTION();
|
||||
|
||||
return ShaderAttrib::return_new(attrib);
|
||||
if (!PyErr_Occurred()) {
|
||||
return ShaderAttrib::return_new(attrib);
|
||||
} else {
|
||||
delete attrib;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAVE_PYTHON
|
||||
|
|
|
|||
|
|
@ -72,11 +72,21 @@ __declspec(noinline)
|
|||
make_python_frame_collector(PyFrameObject *frame, PyCodeObject *code) {
|
||||
#if PY_VERSION_HEX >= 0x030B0000 // 3.11
|
||||
// Fetch the module name out of the frame's global scope.
|
||||
const char *mod_name = "<unknown>";
|
||||
PyObject *py_mod_name = nullptr;
|
||||
PyObject *globals = PyFrame_GetGlobals(frame);
|
||||
PyObject *py_mod_name = PyDict_GetItemString(globals, "__name__");
|
||||
#if PY_VERSION_HEX >= 0x030D00A1 // 3.13
|
||||
if (PyDict_GetItemStringRef(globals, "__name__", &py_mod_name) > 0) {
|
||||
mod_name = PyUnicode_AsUTF8(py_mod_name);
|
||||
}
|
||||
#else
|
||||
py_mod_name = PyDict_GetItemString(globals, "__name__");
|
||||
if (py_mod_name != nullptr) {
|
||||
mod_name = PyUnicode_AsUTF8(py_mod_name);
|
||||
}
|
||||
#endif
|
||||
Py_DECREF(globals);
|
||||
|
||||
const char *mod_name = py_mod_name ? PyUnicode_AsUTF8(py_mod_name) : "<unknown>";
|
||||
const char *meth_name = PyUnicode_AsUTF8(code->co_qualname);
|
||||
char buffer[1024];
|
||||
size_t len = snprintf(buffer, sizeof(buffer), "%s:%s", mod_name, meth_name);
|
||||
|
|
@ -85,6 +95,11 @@ make_python_frame_collector(PyFrameObject *frame, PyCodeObject *code) {
|
|||
buffer[i] = ':';
|
||||
}
|
||||
}
|
||||
|
||||
#if PY_VERSION_HEX >= 0x030D00A1 // 3.13
|
||||
Py_XDECREF(py_mod_name);
|
||||
#endif
|
||||
|
||||
#else
|
||||
// Try to figure out the type name. There's no obvious way to do this.
|
||||
// It's possible that the first argument passed to this function is the
|
||||
|
|
@ -179,23 +194,26 @@ make_c_function_collector(PyCFunctionObject *meth) {
|
|||
len = (dot - cls->tp_name) + 1;
|
||||
} else {
|
||||
// If there's no module name, we need to get it from __module__.
|
||||
PyObject *py_mod_name = cls->tp_dict ? PyDict_GetItemString(cls->tp_dict, "__module__") : nullptr;
|
||||
PyObject *py_mod_name = nullptr;
|
||||
const char *mod_name = nullptr;
|
||||
if (py_mod_name != nullptr) {
|
||||
if (cls->tp_dict != nullptr &&
|
||||
PyDict_GetItemStringRef(cls->tp_dict, "__module__", &py_mod_name) > 0) {
|
||||
if (PyUnicode_Check(py_mod_name)) {
|
||||
mod_name = PyUnicode_AsUTF8(py_mod_name);
|
||||
} else {
|
||||
// Might be a descriptor.
|
||||
Py_DECREF(py_mod_name);
|
||||
py_mod_name = PyObject_GetAttrString(meth->m_self, "__module__");
|
||||
if (py_mod_name != nullptr) {
|
||||
if (PyUnicode_Check(py_mod_name)) {
|
||||
mod_name = PyUnicode_AsUTF8(py_mod_name);
|
||||
}
|
||||
Py_DECREF(py_mod_name);
|
||||
}
|
||||
else PyErr_Clear();
|
||||
}
|
||||
}
|
||||
else PyErr_Clear();
|
||||
|
||||
if (mod_name == nullptr) {
|
||||
// Is it a built-in, like int or dict?
|
||||
PyObject *builtins = PyEval_GetBuiltins();
|
||||
|
|
@ -206,6 +224,7 @@ make_c_function_collector(PyCFunctionObject *meth) {
|
|||
}
|
||||
}
|
||||
len = snprintf(buffer, sizeof(buffer), "%s:%s:%s()", mod_name, cls->tp_name, meth->m_ml->ml_name) - 2;
|
||||
Py_XDECREF(py_mod_name);
|
||||
}
|
||||
}
|
||||
else if (meth->m_self != nullptr) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue