コード例 #1
0
def get_pylint_bin(settings_obj):
    """ returns a valid, runnable path to pylint, and its LooseVersion """
    # settings_obj = sublime.load_settings("Pylint.sublime-settings")
    ver = None
    pylint_bin = multiconf.get(settings_obj, "pylint_bin", None)

    # umm, why is this /usr/bin/python, yet the autodiscover below works??
    # print("!!", sub.check_output(["python", "--version"], stderr=sub.STDOUT))

    # test that the pylint_bin path is good and check its version
    if pylint_bin is not None:
        try:
            ver = sub.check_output([pylint_bin, "--version"]).decode()
            ver = LooseVersion(re.search(r"([0-9]+\.?)+", ver).group())
            if ver < MIN_PYLINT_VERSION:
                print("Pylint: pylint_bin version <", MIN_PYLINT_VERSION,
                      ", trying autodiscover [", pylint_bin, "]")
                pylint_bin = None
        except (OSError, sub.CalledProcessError):
            print("Pylint: pylint_bin not found, trying autodiscover [",
                  pylint_bin, "]")
            pylint_bin = None

    # of no pylint_bin or it's not a good version, try autodiscovering
    if pylint_bin is None:
        cmd = "from __future__ import print_function;" \
              "import pylint; " \
              "print(pylint.__path__[0])"
        try:
            python_bin = multiconf.get(settings_obj, "python_bin", "python")
            print("Pylint: using python [", python_bin, "]")
            module_path = sub.check_output([python_bin, "-c", cmd]).decode()
            pylint_bin = os.path.normpath(os.path.join(
                module_path, '..', '..', '..', '..', 'bin', 'pylint'))
            # check the version on the autodiscovered pylint
            ver = sub.check_output([pylint_bin, "--version"]).decode()
            ver = LooseVersion(re.search(r"([0-9]+\.?)+", ver).group())
            if ver < MIN_PYLINT_VERSION:
                print("Pylint: autodiscover failed; version <",
                      MIN_PYLINT_VERSION, "[", pylint_bin, "]")
                pylint_bin = None
        except (OSError, sub.CalledProcessError) as e:
            print("Pylint: autodiscover failed;", str(e))
            if python_bin is not None:
                which_python = sub.check_output(["which", python_bin]).decode()
                print("Pylint: maybe pylint isn't installed for ",
                      which_python.strip())

    if pylint_bin is None:
        print("Pylint: Could not find pylint :(")
        return None, None
    print("Pylint: using executable at [", pylint_bin, "]")
    return pylint_bin, ver
コード例 #2
0
    def run(self, view):
        if self.pylint_bin is None:
            print("No pylint >", MIN_PYLINT_VERSION,
                  "accessable, not linting")
            return None

        window = view.window()
        fname = view.file_name()
        file_info = message_manager.FileInfoDict()
        if not window.id() in self.messages:
            self.messages[window.id()] = {}
        # make a lookup for the order of severity
        # sev_lookup = OrderedDict(zip(self.markers.keys(), itertools.count()))

        cmd = [self.pylint_bin, "-r", "no",
               "--msg-template", "{path}:{line}:{C}:{msg_id}:{symbol}:{msg}"]
        disable_msgs = multiconf.get(self.settings, "disable", None)
        if disable_msgs is not None:
            disable_msgs = ",".join(disable_msgs)
            cmd += ["-d", disable_msgs]
        extra_args = multiconf.get(self.settings, "extra_args", [])
        cmd += extra_args
        cmd.append(fname)
        p = sub.Popen(cmd, stdout=sub.PIPE, stderr=sub.PIPE)
        raw_stdout, raw_stderr = p.communicate()

        # check stderr for a bad lint run
        err = raw_stderr.decode()
        err_lines = [line for line in err.splitlines()
                     if line and not line.startswith('Using config file')]
        if len(err_lines) > 0:
            print("*******************")
            print("Fatal pylint error:")
            print("------------------")
            print("{0}".format(err))
            print("*******************")
            sublime.error_message("Fatal pylint error, check console for "
                                  "details")
            return None

        ignore = multiconf.get(self.settings, "ignore", [])
        ignore = [t.lower() for t in ignore]
        out = raw_stdout.decode()
        for line in out.strip().splitlines():
            if line.startswith("*************"):
                continue

            # print(line)
            m = re.match(self._output_re, line)
            if m:
                d = m.groupdict()
                # print(d)
                line_num = int(d['line']) # - 1
                if d['errid'].lower() not in ignore and d['symbol'] not in ignore:
                    if not line_num in file_info:
                        file_info[line_num] = []
                    msg = "{0}: {1}".format(d["errid"], d["msg"].strip())
                    err_info = message_manager.ErrorInfo(self, line_num,
                                                         d["cat"], msg,
                                                         extra=True,
                                                         errid=d['errid'],
                                                         symbol=d['symbol'])
                    file_info[line_num].append(err_info)
                    file_info[line_num].sort(key=attrgetter("order"),
                                             reverse=True)

        # self.messages[window.id()] = window_container
        self.messages[window.id()][fname] = file_info
        self.mark_errors(window, view)