fix: use original dict (#5658)

* fix: use original dict

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>

* refactor: handle unset dict just in case

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>

---------

Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
This commit is contained in:
Henry Schreiner
2025-05-13 14:09:05 -04:00
committed by GitHub
parent c5dc6f9fb7
commit 853bafa0a2
2 changed files with 11 additions and 5 deletions

View File

@@ -451,7 +451,16 @@ void setstate(value_and_holder &v_h, std::pair<T, O> &&result, bool need_alias)
// See PR #2972 for details.
return;
}
setattr((PyObject *) v_h.inst, "__dict__", d);
// Our tests never run into an unset dict, but being careful here for now (see #5658)
auto dict = getattr((PyObject *) v_h.inst, "__dict__", none());
if (dict.is_none()) {
setattr((PyObject *) v_h.inst, "__dict__", d);
} else {
// Keep the original object dict and just update it
if (PyDict_Update(dict.ptr(), d.ptr()) < 0) {
throw error_already_set();
}
}
}
/// Implementation for py::pickle(GetState, SetState)

View File

@@ -35,10 +35,7 @@ void wrap(py::module m) {
.def_readwrite("num", &SimpleBase::num)
.def(py::pickle(
[](const py::object &self) {
py::dict d;
if (py::hasattr(self, "__dict__")) {
d = self.attr("__dict__");
}
py::dict d = py::getattr(self, "__dict__", py::dict());
return py::make_tuple(self.attr("num"), d);
},
[](const py::tuple &t) {