@@ -40,23 +40,39 @@ py::object findQueryableObj(const std::string & var_name)
4040
4141 while (!current_frame.is_none ())
4242 {
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" );
4546
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})
4749 {
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)))
4953 {
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+ }
5368 }
5469 }
5570
71+ // Move to the parent frame
5672 current_frame = current_frame.attr (" f_back" );
5773 }
5874
59- // not found
75+ // Object not found
6076 return py::none ();
6177}
6278
0 commit comments