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 test_suppress(): try: 1 / 0 except Exception: traceback = Traceback(suppress=[pytest, "foo"]) assert len(traceback.suppress) == 2 assert "pytest" in traceback.suppress[0] assert "foo" in traceback.suppress[1]
def test_guess_lexer_yaml_j2(): # https://github.com/Textualize/rich/issues/2018 code = """\ foobar: something: {{ raiser() }} else: {{ 5 + 5 }} """ assert Traceback._guess_lexer("test.yaml.j2", code) == "text"
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 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 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 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 panic(self, *renderables: RenderableType) -> None: """Exits the app with a traceback. Args: traceback (Traceback, optional): Rich Traceback object or None to generate one for the most recent exception. Defaults to None. """ if not renderables: renderables = ( Traceback(show_locals=True, width=None, locals_max_length=5), ) self._exit_renderables.extend(renderables) self.close_messages_no_wait()
def get_exception() -> Traceback: def bar(a): print(1 / a) def foo(a): bar(a) try: try: foo(0) except: foobarbaz except: tb = Traceback() return tb
def _handle_exception(self, _: BaseException) -> None: t, v, tb = sys.exc_info() stack = Traceback.extract(t, v, tb.tb_next.tb_next, show_locals=self.show_locals).stacks[0] self.console.print( f"[red bold]{stack.exc_type}: [/red bold]'{stack.exc_value}' on line {stack.frames[0].lineno}" ) if self.show_locals: _locals = stack.frames[0].locals self.console.print("Locals: ", end="") self.console.print( {k: _locals[k].value_repr for k in list(_locals)[17:]})
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 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
async def handle_file_click(self, message: FileClick) -> None: """A message sent by the directory tree when a file is clicked.""" syntax: RenderableType try: # Construct a Syntax object for the path in the message syntax = Syntax.from_path( message.path, line_numbers=True, word_wrap=True, indent_guides=True, theme="monokai", ) except Exception: # Possibly a binary file # For demonstration purposes we will show the traceback syntax = Traceback(theme="monokai", width=None, show_locals=True) self.app.sub_title = os.path.basename(message.path) await self.body.update(syntax)
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)
for m in c: m["data"].update(data) return resume if __name__ == "__main__": from os.path import dirname, join from rich.console import Console from rich.pretty import Pretty from rich.traceback import Traceback console = Console() try: cfg = ConfigManager(join(dirname(__file__), "examples", "minidaqapp")) except Exception as e: console.print(Traceback()) console.print("Boot data :boot:") console.print(Pretty(cfg.boot)) console.print("Init data :boot:") console.print(Pretty(cfg.init)) console.print("Conf data :boot:") console.print(Pretty(cfg.conf)) console.print("Start data :runner:") console.print(Pretty(cfg.start)) console.print("Start order :runner:") console.print(Pretty(cfg.start_order))
def test_no_exception(): with pytest.raises(ValueError): tb = Traceback()
def test_capture(): try: 1 / 0 except Exception: tb = Traceback() assert tb.trace.stacks[0].exc_type == "ZeroDivisionError"
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
def test_guess_lexer(): assert Traceback._guess_lexer("foo.py", "code") == "python" code_python = "#! usr/bin/env python\nimport this" assert Traceback._guess_lexer("foo", code_python) == "python" assert Traceback._guess_lexer("foo", "foo\nbnar") == "text"
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 get_response( session: requests.Session, site_data: dict, headers: dict, timeout: int, proxies: Union[dict, None], ) -> tuple: """ request url and process response data,including decrypt(optional), check regex and so on. also, it will handle with possible errors in the process Args: session: a instance of requests.Session() site_data: a dictionary in site_data_list which read from json file headers: header for requests timeout: Time in seconds to wait before timing out request proxies: a {'http':'http://*','https':'https://*'} like dict or None Returns: """ check_result = "Unknown" check_results = {} traceback = None resp_text = "" exception_text = "" error_context = "" response = None try: if site_data.get("data"): if "Cookie" in headers.keys(): cookies = headers.pop("Cookie") for k, v in cookies.items(): session.cookies.set(k, v) if re.search(r"application.json", headers.get("Content-Type", "")): response = session.post( site_data["url"], json=site_data["data"], headers=headers, timeout=timeout, proxies=proxies, allow_redirects=True, verify=False, ) else: response = session.post( site_data["url"], data=site_data["data"], headers=headers, timeout=timeout, proxies=proxies, allow_redirects=True, verify=False, ) else: response = session.get( site_data["url"], headers=headers, timeout=timeout, proxies=proxies, verify=False, ) if response and response.text: resp_text = response.text else: return ( response, "request failed or get empty response", exception_text, check_results, "Damage", traceback, resp_text, ) resp_json = {} if site_data.get("decrypt") and resp_text: try: import importlib package = importlib.import_module("decrypt." + site_data["decrypt"]) Decrypt = getattr(package, "Decrypt") resp_text = Decrypt().decrypt(resp_text) except Exception as _e: traceback = Traceback() error_context = "json decrypt error" exception_text = _e if resp_text: try: # 有些键可能值是null,这种实际上是可以通过判断逻辑的, # 所以使用占位符(placeholder)来解除null # 不排除这种提取方法会引发新一轮的错误,再找到更好的提取方法之前, # 暂且先这样 resp_text = re.sub(r"[\s\n]", "", resp_text).replace("null", "9527") if site_data["regex"][0].startswith("$"): # 直接返回了一个列表的json格式 resp_json = json.loads( re.search(r'(")?(\[.*])(?(1)")', resp_text).group(0) ) else: resp_json = json.loads( re.search(r'(")?({.*})(?(1)")', resp_text).group(0) ) if isinstance(resp_json, str): # 针对 "/"../"" 类做出特殊优化 resp_json = json.loads(resp_json) except Exception as _e: traceback = Traceback() error_context = "response data not json format" exception_text = _e try: check_results = { regex: regex_checker(regex, resp_json, site_data.get("exception")) for regex in site_data["regex"] } if list(check_results.values()) != ["OK"] * len(check_results): error_context = "regex failed" check_result = "Damage" else: check_result = "OK" except Exception as _e: traceback = Traceback() error_context = "json decrypt error" exception_text = _e except requests.exceptions.HTTPError as errh: error_context = "HTTP Error" exception_text = str(errh) except requests.exceptions.ProxyError as errp: error_context = "Proxy Error" exception_text = str(errp) except requests.exceptions.ConnectionError as errc: error_context = "Error Connecting" exception_text = str(errc) except requests.exceptions.Timeout as errt: error_context = "Timeout Error" exception_text = str(errt) except requests.exceptions.RequestException as err: error_context = "Unknown Error" exception_text = str(err) return ( response, error_context, exception_text, check_results, check_result, traceback, resp_text, )
def processor( site_data: dict, timeout: int, use_proxy: bool, result_printer: ResultPrinter, task_id: TaskID, progress: Progress, ) -> dict: """ the main processor for mori. Args: result_printer: site_data: a dictionary in site_data_list which read from json file timeout: Time in seconds to wait before timing out request use_proxy: not use proxy while this value is False. Of course, proxy field in the config file should have a value. result_printer: when processor finish , result_printer will be invoked to output result. task_id: it is id of main_progress, when processor finish, main_progress while step 1. progress: main progress. Returns: Dictionary containing results from report. 'name': api name in configuration, 'url': api url in configuration, 'base_url': api base_url in configuration, 'resp_text': raw response.text from url, if length of resp_text > 500, it wont`t display on console, and you can add --xls to see detail in *.xls file. 'status_code': response status_code, 'time(s)': time in seconds spend on request, 'error_text': error_text, 'exception_text': exception_text, 'check_result': 'OK' , 'Damage' or 'Unknown'. Default is 'Unknown'. 'traceback': Instance of Traceback. 'check_results': check_results, each result of all regexes. 'remark': field hold on """ rel_result, result, monitor_id = {}, {}, None session = requests.Session() max_retries = 5 if progress: monitor_id = progress.add_task( f'{site_data["name"]} (retry)', visible=False, total=max_retries ) # progress.update(monitor_id, advance=-max_retries) check_result, check_results = "Damage", [] r, resp_text = None, "" try: for retries in range(max_retries): check_result = "Damage" traceback, r, resp_text = None, None, "" error_text, exception_text, check_results = "", "", {} check_result = "Unknown" headers = { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; " "rv:55.0) Gecko/20100101 Firefox/55.0", } if site_data.get("headers"): if isinstance(site_data.get("headers"), dict): headers.update(site_data.get("headers")) Proxy.set_proxy_url( site_data.get("proxy"), site_data.get("strict_proxy"), use_proxy, headers, ) if site_data.get("antispider") and site_data.get("data"): try: import importlib package = importlib.import_module( "antispider." + site_data["antispider"] ) Antispider = getattr(package, "Antispider") site_data["data"], headers = Antispider( site_data["data"], headers ).processor() except Exception as _e: site_data["single"] = True site_data["exception_text"] = _e site_data["traceback"] = Traceback() raise Exception("antispider failed") try: proxies = Proxy.get_proxy() except Exception as _e: site_data["single"] = True site_data["exception_text"] = _e site_data["traceback"] = Traceback() raise Exception("all of six proxies can`t be used") if site_data.get("single"): error_text = site_data["error_text"] exception_text = site_data["exception_text"] traceback = site_data["traceback"] else: ( r, error_text, exception_text, check_results, check_result, traceback, resp_text, ) = get_response(session, site_data, headers, timeout, proxies) if error_text and retries + 1 < max_retries: if progress: progress.update( monitor_id, advance=1, visible=True, refresh=True ) continue result = { "name": site_data["name"], "url": site_data["url"], "base_url": site_data.get("base_url", ""), "resp_text": resp_text if len(resp_text) < 500 else "too long, and you can add --xls " "to see detail in *.xls file", "status_code": getattr(r, "status_code", "failed"), "time(s)": float(r.elapsed.total_seconds()) if r else -1.0, "error_text": str(error_text), "exception_text": exception_text, "check_result": check_result, "traceback": traceback, "check_results": check_results, "remark": site_data.get("remark", ""), } rel_result = dict(result.copy()) rel_result["resp_text"] = resp_text break except Exception as error: result = { "name": site_data["name"], "url": site_data["url"], "base_url": site_data.get("base_url", ""), "resp_text": resp_text if len(resp_text) < 500 else "too long, and you can add --xls " "to see detail in *.xls file", "status_code": getattr(r, "status_code", "failed") if r else "none", "time(s)": float(r.elapsed.total_seconds()) if r else -1.0, "error_text": str(error) or "site handler error", "check_result": check_result, "traceback": Traceback(), "check_results": check_results, "remark": site_data.get("remark", ""), } rel_result = dict(result.copy()) if result_printer: progress.update(task_id, advance=1, refresh=True) result_printer.printer(result) progress.remove_task(monitor_id) return rel_result
async def on_client_connected(self, reader: StreamReader, writer: StreamWriter): self.logger.debug('client connected') while True: # TODO: while active instead raw_command = await reader.readline() if raw_command == b'': # TODO: not ideal, remove pooling if possible await asyncio.sleep(0.5) continue try: command = SymlServiceCommand.parse(raw_command) logging.debug("received command %s", command) callable_command = getattr(self, f'cmd_{command.name}') cmd_arg = get_type_hints(callable_command).get('cmd') if cmd_arg: args_type = get_args(cmd_arg)[0] command.args = args_type(**command.args) # TODO: handle generators try: response: SymlServiceResponse if cmd_arg: response = await callable_command(command) else: response = await callable_command() except Exception as e: exc_type, exc_value, traceback = sys.exc_info() tb = Traceback() trace = tb.extract(exc_type, exc_value, traceback, show_locals=False) trace = [dataclasses.asdict(s) for s in trace.stacks] trace = [{ **t, 'frames': t.get('frames')[1:] } for t in trace] response = SymlServiceResponse( data=dict(), errors=[ dict(message="unhandled exception while " "processing command (${exception})", exception=e, trace=trace) ]) response.command = command writer.write(response.jsonb()) writer.write('\n'.encode()) logging.debug("sending response %s", response) await writer.drain() except Exception as e: self.logger.exception("oh no", e)