def handle_exception(self, e, table=True): if self.table.row_count > 1 and table: self.console.print(self.table) if getattr(sys, 'frozen', False): sys.tracebacklimit = 0 if isinstance(e, list): for es in e: self.console.print(Traceback.from_exception(exc_type=es.__class__, exc_value=es, traceback=es.__traceback__)) else: self.console.print(Traceback.from_exception(exc_type=e.__class__, exc_value=e, traceback=e.__traceback__))
def handle_exception(self, e, table=True): if self.table.row_count > 1 and table: self.console.print(self.table) if getattr(sys, 'frozen', False) and 'CURSEBREAKER_DEBUG' not in os.environ: sys.tracebacklimit = 0 width = 0 else: width = 100 if isinstance(e, list): for es in e: self.console.print(Traceback.from_exception(exc_type=es.__class__, exc_value=es, traceback=es.__traceback__, width=width)) else: self.console.print(Traceback.from_exception(exc_type=e.__class__, exc_value=e, traceback=e.__traceback__, width=width))
def _process_exception(exc_info: tuple[Any], show_locals: bool, console_options: ConsoleOptions) -> tuple[Any]: exc_info = remove_internal_traceback_frames_from_exc_info(exc_info) traceback = Traceback.from_exception(*exc_info, show_locals=show_locals) segments = console.render(traceback, options=console_options) text = "".join(segment.text for segment in segments) return (*exc_info[:2], text)
def test_rich_traceback_omit_optional_local_flag( rich_traceback_omit_for_level2: bool, expected_frames_length: int, expected_frame_names: List[str], ): def level1(): return level2() def level2(): # true-ish values are enough to trigger the opt-out: _rich_traceback_omit = 1 if rich_traceback_omit_for_level2 else 0 return level3() def level3(): return 1 / 0 try: level1() except Exception: exc_type, exc_value, traceback = sys.exc_info() trace = Traceback.from_exception(exc_type, exc_value, traceback).trace frames = trace.stacks[0].frames assert len(frames) == expected_frames_length frame_names = [f.name for f in frames] assert frame_names == expected_frame_names
def print_traceback(self, err): trace = getattr(err, "__traceback__", "") if trace: # The first frame contains library internal code which is not # relevant to end users, so skip over it. trace = trace.tb_next tb = Traceback.from_exception(err.__class__, err, trace, show_locals=True) self.console.print(Padding(tb, pad=(0, 2, 1, 2))) else: self.console.print(str(err))
def except_hook( exc_type: Type[BaseException], exc_value: BaseException, tb: TracebackType ) -> None: exception_config: Union[DeveloperExceptionConfig, None] = getattr( exc_value, _typer_developer_exception_attr_name, None ) standard_traceback = os.getenv("_TYPER_STANDARD_TRACEBACK") if ( standard_traceback or not exception_config or not exception_config.pretty_exceptions_enable ): _original_except_hook(exc_type, exc_value, tb) return typer_path = os.path.dirname(__file__) click_path = os.path.dirname(click.__file__) supress_internal_dir_names = [typer_path, click_path] exc = exc_value if rich: rich_tb = Traceback.from_exception( type(exc), exc, exc.__traceback__, show_locals=exception_config.pretty_exceptions_show_locals, suppress=supress_internal_dir_names, ) console_stderr.print(rich_tb) return tb_exc = traceback.TracebackException.from_exception(exc) stack: List[FrameSummary] = [] for frame in tb_exc.stack: if any( [frame.filename.startswith(path) for path in supress_internal_dir_names] ): if not exception_config.pretty_exceptions_short: # Hide the line for internal libraries, Typer and Click stack.append( traceback.FrameSummary( filename=frame.filename, lineno=frame.lineno, name=frame.name, line="", ) ) else: stack.append(frame) # Type ignore ref: https://github.com/python/typeshed/pull/8244 final_stack_summary = StackSummary.from_list(stack) # type: ignore tb_exc.stack = final_stack_summary for line in tb_exc.format(): print(line, file=sys.stderr) return
def emit(self, record: LogRecord) -> None: """Invoked by logging.""" path = pathlib.Path(record.pathname).name level = self.get_level_text(record) message = self.format(record) time_format = None if self.formatter is None else self.formatter.datefmt log_time = datetime.fromtimestamp(record.created) traceback = None if self.rich_tracebacks and record.exc_info and record.exc_info != ( None, None, None): exc_type, exc_value, exc_traceback = record.exc_info assert exc_type is not None assert exc_value is not None traceback = Traceback.from_exception( exc_type, exc_value, exc_traceback, width=self.tracebacks_width, extra_lines=self.tracebacks_extra_lines, theme=self.tracebacks_theme, word_wrap=self.tracebacks_word_wrap, show_locals=self.tracebacks_show_locals, locals_max_length=self.locals_max_length, locals_max_string=self.locals_max_string, ) message = record.getMessage() use_markup = getattr(record, "markup") if hasattr( record, "markup") else self.markup if use_markup: message_text = Text.from_markup(message) else: message_text = Text(message) if self.highlighter: message_text = self.highlighter(message_text) if self.KEYWORDS: message_text.highlight_words(self.KEYWORDS, "logging.keyword") self.console.print( self._log_render( self.console, [message_text] if not traceback else [message_text, traceback], log_time=log_time, time_format=time_format, level=level, path=path, line_no=record.lineno, link_path=record.pathname if self.enable_link_path else None, logger_name=record.name, ))
def render_error(self): if not self.hide_locals: # print showing locals panels self.traceback_console.print( *inspect_traceback( self.traceback, keep_frames=self.keep_frames, all_locals=self.all_locals, relevant_only=self.relevant_only, ), "", Traceback.from_exception(self.type_, self.value, self.traceback), sep="\n" * 2, ) else: # print without locals panels self.traceback_console.print( Traceback.from_exception(self.type_, self.value, self.traceback), sep="\n" * 2, )
def render_exc_info( exc_type: type[BaseException], exc_value: BaseException, traceback: str | TracebackType, show_locals: bool = False, ) -> str | Traceback: """Render an exception info.""" # Can be string if send from subprocess by pytask-parallel. if isinstance(traceback, str): # pragma: no cover renderable = traceback else: renderable = Traceback.from_exception(exc_type, exc_value, traceback, show_locals=show_locals) return renderable
def dag(**config_from_cli: Any) -> NoReturn: """Create a visualization of the project's directed acyclic graph.""" try: pm = get_plugin_manager() from _pytask import cli pm.register(cli) pm.hook.pytask_add_hooks(pm=pm) config = pm.hook.pytask_configure(pm=pm, config_from_cli=config_from_cli) session = Session.from_config(config) except (ConfigurationError, Exception): console.print_exception() session = Session({}, None) session.exit_code = ExitCode.CONFIGURATION_FAILED else: try: session.hook.pytask_log_session_header(session=session) import_optional_dependency("pydot") check_for_optional_program( session.config["layout"], extra="The layout program is part of the graphviz package which you " "can install with conda.", ) session.hook.pytask_collect(session=session) session.hook.pytask_resolve_dependencies(session=session) dag = _refine_dag(session) _write_graph(dag, session.config["output_path"], session.config["layout"]) except CollectionError: session.exit_code = ExitCode.COLLECTION_FAILED except ResolvingDependenciesError: session.exit_code = ExitCode.RESOLVING_DEPENDENCIES_FAILED except Exception: session.exit_code = ExitCode.FAILED exc_info = remove_internal_traceback_frames_from_exc_info(sys.exc_info()) console.print() console.print(Traceback.from_exception(*exc_info)) console.rule(style="failed") sys.exit(session.exit_code)
def _emit_table(self, record): # SEE https://github.com/willmcgugan/rich/blob/25a1bf06b4854bd8d9239f8ba05678d2c60a62ad/rich/_log_render.py#L26 console = self.consoles.get( self.level_map.get(record.levelno, "err"), self.DEFAULT_CONSOLES["err"], ) output = Table.grid(padding=(0, 1)) output.expand = True # Left column -- log level, time output.add_column( style=f"logging.level.{record.levelname.lower()}", width=8, ) # Main column -- log name, message, args output.add_column(ratio=1, style="log.message", overflow="fold") output.add_row( Text(record.levelname), Text(record.name, Style(color="blue", dim=True)), ) if record.args: msg = str(record.msg) % record.args else: msg = str(record.msg) output.add_row(None, msg) if hasattr(record, "data") and record.data: output.add_row(None, table(record.data)) if record.exc_info: output.add_row(None, Traceback.from_exception(*record.exc_info)) console.print(output)
def emit(self, record: logging.LogRecord) -> None: message = self.format(record) traceback = None if (self.rich_tracebacks and record.exc_info and record.exc_info != (None, None, None)): exc_type, exc_value, exc_traceback = record.exc_info assert exc_type is not None assert exc_value is not None traceback = Traceback.from_exception( exc_type, exc_value, exc_traceback, width=self.tracebacks_width, extra_lines=self.tracebacks_extra_lines, theme=self.tracebacks_theme, word_wrap=self.tracebacks_word_wrap, show_locals=self.tracebacks_show_locals, locals_max_length=self.locals_max_length, locals_max_string=self.locals_max_string, ) message = record.getMessage() if self.formatter: record.message = record.getMessage() formatter = self.formatter if hasattr(formatter, "usesTime") and formatter.usesTime(): record.asctime = formatter.formatTime( record, formatter.datefmt) message = formatter.formatMessage(record) message_renderable = self.render_message(record, message) log_renderable = self.render(record=record, traceback=traceback, message_renderable=message_renderable) # Directly put renderable into function self._func(log_renderable)
def excepthook(exc_type, exc_val, exc_tb): trace = Traceback.from_exception(exc_type, exc_val, exc_tb) CONSOLE.print(trace) if ERROR_CODES.get(exc_type): sys.exit(ERROR_CODES[exc_type])
def main(config_from_cli: dict[str, Any]) -> Session: """Run pytask. This is the main command to run pytask which usually receives kwargs from the command line interface. It can also be used to run pytask interactively. Pass configuration in a dictionary. Parameters ---------- config_from_cli : dict[str, Any] A dictionary with options passed to pytask. In general, this dictionary holds the information passed via the command line interface. Returns ------- session : _pytask.session.Session The session captures all the information of the current run. """ try: pm = get_plugin_manager() from _pytask import cli pm.register(cli) pm.hook.pytask_add_hooks(pm=pm) config = pm.hook.pytask_configure(pm=pm, config_from_cli=config_from_cli) session = Session.from_config(config) except (ConfigurationError, Exception): exc_info = sys.exc_info() exc_info = remove_internal_traceback_frames_from_exc_info(exc_info) traceback = Traceback.from_exception(*exc_info) console.print(traceback) session = Session({}, None) session.exit_code = ExitCode.CONFIGURATION_FAILED else: try: session.hook.pytask_log_session_header(session=session) session.hook.pytask_collect(session=session) session.hook.pytask_resolve_dependencies(session=session) session.hook.pytask_execute(session=session) except CollectionError: session.exit_code = ExitCode.COLLECTION_FAILED except ResolvingDependenciesError: session.exit_code = ExitCode.RESOLVING_DEPENDENCIES_FAILED except ExecutionError: session.exit_code = ExitCode.FAILED except Exception: exc_info = sys.exc_info() exc_info = remove_internal_traceback_frames_from_exc_info(exc_info) traceback = Traceback.from_exception(*exc_info) console.print(traceback) session.exit_code = ExitCode.FAILED session.hook.pytask_unconfigure(session=session) return session