Skip to content

Commit f153746

Browse files
committed
Convert PyDict_GetXXX to internal error checking variant
1 parent 417067e commit f153746

File tree

2 files changed

+39
-3
lines changed

2 files changed

+39
-3
lines changed

include/pybind11/pybind11.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,7 @@ class cpp_function : public function {
634634
bool bad_arg = false;
635635
for (; args_copied < args_to_copy; ++args_copied) {
636636
const argument_record *arg_rec = args_copied < func.args.size() ? &func.args[args_copied] : nullptr;
637-
if (kwargs_in && arg_rec && arg_rec->name && PyDict_GetItemString(kwargs_in, arg_rec->name)) {
637+
if (kwargs_in && arg_rec && arg_rec->name && dict_getitemstring(kwargs_in, arg_rec->name)) {
638638
bad_arg = true;
639639
break;
640640
}
@@ -682,7 +682,7 @@ class cpp_function : public function {
682682

683683
handle value;
684684
if (kwargs_in && arg_rec.name)
685-
value = PyDict_GetItemString(kwargs.ptr(), arg_rec.name);
685+
value = dict_getitemstring(kwargs.ptr(), arg_rec.name);
686686

687687
if (value) {
688688
// Consume a kwargs value
@@ -2295,7 +2295,7 @@ inline function get_type_override(const void *this_ptr, const type_info *this_ty
22952295
if (frame && (std::string) str(frame->f_code->co_name) == name &&
22962296
frame->f_code->co_argcount > 0) {
22972297
PyFrame_FastToLocals(frame);
2298-
PyObject *self_caller = PyDict_GetItem(
2298+
PyObject *self_caller = dict_getitem(
22992299
frame->f_locals, PyTuple_GET_ITEM(frame->f_code->co_varnames, 0));
23002300
if (self_caller == self.ptr())
23012301
return function();

include/pybind11/pytypes.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,42 @@ inline handle get_function(handle value) {
478478
return value;
479479
}
480480

481+
// Reimplementation of python's dict helper functions
482+
483+
// copied from cpython _PyDict_GetItemStringWithError
484+
inline PyObject * dict_getitemstring(PyObject *v, const char *key)
485+
{
486+
#if PY_MAJOR_VERSION >= 3
487+
PyObject *kv, *rv;
488+
kv = PyUnicode_FromString(key);
489+
if (kv == NULL) {
490+
throw error_already_set();
491+
}
492+
493+
rv = PyDict_GetItemWithError(v, kv);
494+
Py_DECREF(kv);
495+
if (rv == NULL && PyErr_Occurred()) {
496+
throw error_already_set();
497+
}
498+
return rv;
499+
#else
500+
return PyDict_GetItemString(v, key);
501+
#endif
502+
}
503+
504+
inline PyObject * dict_getitem(PyObject *v, PyObject *key)
505+
{
506+
#if PY_MAJOR_VERSION >= 3
507+
PyObject *rv = PyDict_GetItemWithError(v, key);
508+
if (rv == NULL && PyErr_Occurred()) {
509+
throw error_already_set();
510+
}
511+
return rv;
512+
#else
513+
return PyDict_GetItem(v, key);
514+
#endif
515+
}
516+
481517
// Helper aliases/functions to support implicit casting of values given to python accessors/methods.
482518
// When given a pyobject, this simply returns the pyobject as-is; for other C++ type, the value goes
483519
// through pybind11::cast(obj) to convert it to an `object`.

0 commit comments

Comments
 (0)