diff --git a/rich/logging.py b/rich/logging.py index b2624cd54..e2e1848d2 100644 --- a/rich/logging.py +++ b/rich/logging.py @@ -40,7 +40,7 @@ class RichHandler(Handler): tracebacks_extra_lines (int, optional): Additional lines of code to render tracebacks, or None for full width. Defaults to None. tracebacks_theme (str, optional): Override pygments theme used in traceback. tracebacks_word_wrap (bool, optional): Enable word wrapping of long tracebacks lines. Defaults to True. - tracebacks_show_locals (bool, optional): Enable display of locals in tracebacks. Defaults to False. + tracebacks_show_locals (bool or int, optional): Enable display of locals in tracebacks. Defaults to False. If set to an integer, it limits the number of frames prioritizing frames closest to the error. tracebacks_suppress (Sequence[Union[str, ModuleType]]): Optional sequence of modules or paths to exclude from traceback. tracebacks_max_frames (int, optional): Optional maximum number of frames returned by traceback. locals_max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation. @@ -80,7 +80,7 @@ def __init__( tracebacks_extra_lines: int = 3, tracebacks_theme: Optional[str] = None, tracebacks_word_wrap: bool = True, - tracebacks_show_locals: bool = False, + tracebacks_show_locals: Union[bool, int] = False, tracebacks_suppress: Iterable[Union[str, ModuleType]] = (), tracebacks_max_frames: int = 100, locals_max_length: int = 10, diff --git a/rich/traceback.py b/rich/traceback.py index 3bf5baa7b..8ca0147da 100644 --- a/rich/traceback.py +++ b/rich/traceback.py @@ -52,7 +52,7 @@ def install( extra_lines: int = 3, theme: Optional[str] = None, word_wrap: bool = False, - show_locals: bool = False, + show_locals: Union[bool, int] = False, locals_max_length: int = LOCALS_MAX_LENGTH, locals_max_string: int = LOCALS_MAX_STRING, locals_hide_dunder: bool = True, @@ -74,7 +74,7 @@ def install( theme (Optional[str], optional): Pygments theme to use in traceback. Defaults to ``None`` which will pick a theme appropriate for the platform. word_wrap (bool, optional): Enable word wrapping of long lines. Defaults to False. - show_locals (bool, optional): Enable display of local variables. Defaults to False. + show_locals (Union[bool, int], optional): Enable display of local variables. Defaults to False. If int is given, limits the number of frames to those closest to the error. locals_max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation. Defaults to 10. locals_max_string (int, optional): Maximum length of string before truncating, or None to disable. Defaults to 80. @@ -222,7 +222,7 @@ class Traceback: extra_lines (int, optional): Additional lines of code to render. Defaults to 3. theme (str, optional): Override pygments theme used in traceback. word_wrap (bool, optional): Enable word wrapping of long lines. Defaults to False. - show_locals (bool, optional): Enable display of local variables. Defaults to False. + show_locals (bool, optional): Enable display of local variables. Defaults to False. If set to an integer, limits the number of frames to those closest to the error. indent_guides (bool, optional): Enable indent guides in code and locals. Defaults to True. locals_max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation. Defaults to 10. @@ -251,7 +251,7 @@ def __init__( extra_lines: int = 3, theme: Optional[str] = None, word_wrap: bool = False, - show_locals: bool = False, + show_locals: Union[bool, int] = False, locals_max_length: int = LOCALS_MAX_LENGTH, locals_max_string: int = LOCALS_MAX_STRING, locals_hide_dunder: bool = True, @@ -307,7 +307,7 @@ def from_exception( extra_lines: int = 3, theme: Optional[str] = None, word_wrap: bool = False, - show_locals: bool = False, + show_locals: Union[bool, int] = False, locals_max_length: int = LOCALS_MAX_LENGTH, locals_max_string: int = LOCALS_MAX_STRING, locals_hide_dunder: bool = True, @@ -327,7 +327,7 @@ def from_exception( extra_lines (int, optional): Additional lines of code to render. Defaults to 3. theme (str, optional): Override pygments theme used in traceback. word_wrap (bool, optional): Enable word wrapping of long lines. Defaults to False. - show_locals (bool, optional): Enable display of local variables. Defaults to False. + show_locals (bool, optional): Enable display of local variables. Defaults to False. If set to an integer, limits the number of frames to those closest to the error. indent_guides (bool, optional): Enable indent guides in code and locals. Defaults to True. locals_max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation. Defaults to 10. @@ -375,7 +375,7 @@ def extract( exc_value: BaseException, traceback: Optional[TracebackType], *, - show_locals: bool = False, + show_locals: Union[bool, int] = False, locals_max_length: int = LOCALS_MAX_LENGTH, locals_max_string: int = LOCALS_MAX_STRING, locals_hide_dunder: bool = True, @@ -387,7 +387,7 @@ def extract( exc_type (Type[BaseException]): Exception type. exc_value (BaseException): Exception value. traceback (TracebackType): Python Traceback object. - show_locals (bool, optional): Enable display of local variables. Defaults to False. + show_locals (bool, optional): Enable display of local variables. Defaults to False. If set to an integer, limits the number of frames to those closest to the error. locals_max_length (int, optional): Maximum length of containers before abbreviating, or None for no abbreviation. Defaults to 10. locals_max_string (int, optional): Maximum length of string before truncating, or None to disable. Defaults to 80. @@ -443,7 +443,16 @@ def get_locals( continue yield key, value - for frame_summary, line_no in walk_tb(traceback): + if isinstance(show_locals, int): + n_frames = len(list(walk_tb(traceback))) + show_locals_for = [i for i in range(max(0, n_frames-show_locals), n_frames)] + elif show_locals: + show_locals_for = list(range(n_frames)) + else: + show_locals_for = [] + show_locals_for = set(show_locals_for) + + for frame_number, (frame_summary, line_no) in enumerate(walk_tb(traceback)): filename = frame_summary.f_code.co_filename last_instruction: Optional[Tuple[Tuple[int, int], Tuple[int, int]]] @@ -494,7 +503,7 @@ def get_locals( for key, value in get_locals(frame_summary.f_locals.items()) if not (inspect.isfunction(value) or inspect.isclass(value)) } - if show_locals + if frame_number in show_locals_for else None ), last_instruction=last_instruction,