Example #1
0
def _get_imported_user_files(main_file, source=None):
    assert os.path.isabs(main_file)

    if source is None:
        source = read_source(main_file)

    try:
        root = ast.parse(source, main_file)
    except SyntaxError:
        return set()

    main_dir = os.path.dirname(main_file)
    module_names = set()
    # TODO: at the moment only considers non-package modules
    for node in ast.walk(root):
        if isinstance(node, ast.Import):
            for item in node.names:
                module_names.add(item.name)
        elif isinstance(node, ast.ImportFrom):
            module_names.add(node.module)

    imported_files = set()

    for file in {
            name + ext
            for ext in [".py", ".pyw"] for name in module_names
    }:
        possible_path = os.path.join(main_dir, file)
        if os.path.exists(possible_path):
            imported_files.add(possible_path)

    return imported_files
Example #2
0
    def __init__(self, error_info):

        # TODO: don't repeat all this for all error helpers
        self.error_info = error_info

        self.last_frame = error_info["stack"][-1]
        self.last_frame_ast = None
        if self.last_frame.source:
            try:
                self.last_frame_ast = ast.parse(self.last_frame.source,
                                                self.last_frame.filename)
            except SyntaxError:
                pass

        self.last_frame_module_source = None
        self.last_frame_module_ast = None
        if self.last_frame.code_name == "<module>":
            self.last_frame_module_source = self.last_frame.source
            self.last_frame_module_ast = self.last_frame_ast
        elif self.last_frame.filename is not None:
            try:
                self.last_frame_module_source = read_source(
                    self.last_frame.filename)
                self.last_frame_module_ast = ast.parse(
                    self.last_frame_module_source)
            except Exception:
                pass

        self.intro_confidence = 1
        self.intro_text = ""
        self.suggestions = []
Example #3
0
    def handle_toplevel_response(self, msg: ToplevelResponse) -> None:
        # Can be called by event system or by Workbench
        # (if Assistant wasn't created yet but an error came)
        if not msg.get("user_exception") and msg.get("command_name") in [
                "execute_system_command",
                "execute_source",
        ]:
            # Shell commands may be used to investigate the problem, don't clear assistance
            return

        self._clear()

        from thonny.plugins.cpython import CPythonProxy

        if not isinstance(get_runner().get_backend_proxy(), CPythonProxy):
            # TODO: add some support for MicroPython as well
            return

        # prepare for snapshot
        key = msg.get("filename", "<pyshell>")
        self._current_snapshot = {
            "timestamp": datetime.datetime.now().isoformat()[:19],
            "main_file_path": key,
        }
        self._snapshots_per_main_file.setdefault(key, [])
        self._snapshots_per_main_file[key].append(self._current_snapshot)

        if msg.get("user_exception"):
            if not msg["user_exception"].get("message", None):
                msg["user_exception"]["message"] = "<no message>"

            self._exception_info = msg["user_exception"]
            self._explain_exception(msg["user_exception"])
            if get_workbench().get_option(
                    "assistance.open_assistant_on_errors"):
                get_workbench().show_view("AssistantView", set_focus=False)
        else:
            self._exception_info = None

        if msg.get("filename") and os.path.exists(msg["filename"]):
            self.main_file_path = msg["filename"]
            source = read_source(msg["filename"])
            self._start_program_analyses(
                msg["filename"], source,
                _get_imported_user_files(msg["filename"], source))
        else:
            self.main_file_path = None
            self._present_conclusion()
Example #4
0
    def _start_program_analyses(self, main_file_path, main_file_source, imported_file_paths):

        for cls in _program_analyzer_classes:
            analyzer = cls(self._accept_warnings)
            if analyzer.is_enabled():
                self._analyzer_instances.append(analyzer)

        if not self._analyzer_instances:
            return

        self._append_text("\nAnalyzing your code ...", ("em",))

        # save snapshot of current source
        self._current_snapshot["main_file_path"] = main_file_path
        self._current_snapshot["main_file_source"] = main_file_source
        self._current_snapshot["imported_files"] = {
            name: read_source(name) for name in imported_file_paths
        }

        # start the analysis
        for analyzer in self._analyzer_instances:
            analyzer.start_analysis(main_file_path, imported_file_paths)