@@ -40,23 +40,39 @@ py::object findQueryableObj(const std::string & var_name)
40
40
41
41
while (!current_frame.is_none ())
42
42
{
43
- auto local_dict = py::reinterpret_borrow<py::dict>(current_frame.attr (" f_locals" ));
44
- auto global_dict = py::reinterpret_borrow<py::dict>(current_frame.attr (" f_globals" ));
43
+ // Get f_locals and f_globals
44
+ py::object locals_obj = current_frame.attr (" f_locals" );
45
+ py::object globals_obj = current_frame.attr (" f_globals" );
45
46
46
- for (const auto & dict : {local_dict, global_dict})
47
+ // For each namespace (locals and globals)
48
+ for (const auto & namespace_obj : {locals_obj, globals_obj})
47
49
{
48
- if (dict.contains (var_name))
50
+ // Use Python's __contains__ method to check if the key exists
51
+ // This works with both regular dicts and FrameLocalsProxy (Python 3.13+)
52
+ if (py::bool_ (namespace_obj.attr (" __contains__" )(var_name)))
49
53
{
50
- py::object obj = dict[var_name.data ()];
51
- if (isInheritsFromPyReader (obj) || isPandasDf (obj) || isPyarrowTable (obj) || hasGetItem (obj))
52
- return obj;
54
+ py::object obj;
55
+ try
56
+ {
57
+ // Get the object using Python's indexing syntax
58
+ obj = namespace_obj[py::cast (var_name)];
59
+ if (isInheritsFromPyReader (obj) || isPandasDf (obj) || isPyarrowTable (obj) || hasGetItem (obj))
60
+ {
61
+ return obj;
62
+ }
63
+ }
64
+ catch (const py::error_already_set &)
65
+ {
66
+ continue ; // If getting the value fails, continue to the next namespace
67
+ }
53
68
}
54
69
}
55
70
71
+ // Move to the parent frame
56
72
current_frame = current_frame.attr (" f_back" );
57
73
}
58
74
59
- // not found
75
+ // Object not found
60
76
return py::none ();
61
77
}
62
78
0 commit comments