Beispiel #1
0
 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__))
Beispiel #2
0
 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))
Beispiel #3
0
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)
Beispiel #4
0
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]
Beispiel #6
0
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"
Beispiel #7
0
 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))
Beispiel #8
0
    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,
            ))
Beispiel #9
0
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
Beispiel #10
0
 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,
         )
Beispiel #11
0
    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()
Beispiel #12
0
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
Beispiel #13
0
 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:]})
Beispiel #14
0
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)
Beispiel #15
0
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
Beispiel #16
0
    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)
Beispiel #17
0
    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)
Beispiel #18
0
    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)
Beispiel #19
0
            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))
Beispiel #20
0
def test_no_exception():
    with pytest.raises(ValueError):
        tb = Traceback()
Beispiel #21
0
def test_capture():
    try:
        1 / 0
    except Exception:
        tb = Traceback()
        assert tb.trace.stacks[0].exc_type == "ZeroDivisionError"
Beispiel #22
0
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
Beispiel #23
0
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])
Beispiel #25
0
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,
    )
Beispiel #26
0
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
Beispiel #27
0
    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)