[docs]deflocals_inspect(self)->dict[str,Any]:"""Inspect local variables in the calling frame."""ifnotself.debug_enabled:return{}frame=inspect.currentframe().f_backlocals_dict=frame.f_locals.copy()# Filter out private variablesfiltered_locals={name:valueforname,valueinlocals_dict.items()ifnotname.startswith("_")}returnfiltered_locals
[docs]defglobals_inspect(self)->dict[str,Any]:"""Inspect global variables in the calling frame."""ifnotself.debug_enabled:return{}frame=inspect.currentframe().f_backglobals_dict=frame.f_globals.copy()# Filter to only user-defined globalsfiltered_globals={name:valueforname,valueinglobals_dict.items()ifnotname.startswith("_")andnotinspect.ismodule(value)}returnfiltered_globals
[docs]defframe_info(self)->dict[str,Any]:"""Get detailed information about the current frame."""ifnotself.debug_enabled:return{}frame=inspect.currentframe().f_backframe_info=inspect.getframeinfo(frame)return{"filename":frame_info.filename,"lineno":frame_info.lineno,"function":frame_info.function,"code_context":frame_info.code_context,"locals_count":len(frame.f_locals),"globals_count":len(frame.f_globals),}
[docs]defget_caller_chain(self,depth:int=5)->list[dict[str,Any]]:"""Get information about the call chain."""ifnotself.debug_enabled:return[]chain=[]frame=inspect.currentframe()try:foriinrange(depth+1):# +1 to skip this functionifframeisNone:breakframe=frame.f_backifframeisNone:breakframe_info=inspect.getframeinfo(frame)chain.append({"depth":i,"filename":frame_info.filename,"lineno":frame_info.lineno,"function":frame_info.function,"code_context":(frame_info.code_context[0].strip()ifframe_info.code_contextelseNone),})exceptException:pass# Handle edge cases gracefullyreturnchain