예제 #1
0
def test_pylintrc_parentdir() -> None:
    """Test that the first pylintrc we find is the first parent directory."""
    with tempdir() as chroot:
        chroot_path = Path(chroot)
        testutils.create_files(
            [
                "a/pylintrc",
                "a/b/__init__.py",
                "a/b/pylintrc",
                "a/b/c/__init__.py",
                "a/b/c/d/__init__.py",
                "a/b/c/d/e/.pylintrc",
            ]
        )

        with fake_home():
            assert not list(config.find_default_config_files())

        results = {
            "a": chroot_path / "a" / "pylintrc",
            "a/b": chroot_path / "a" / "b" / "pylintrc",
            "a/b/c": chroot_path / "a" / "b" / "pylintrc",
            "a/b/c/d": chroot_path / "a" / "b" / "pylintrc",
            "a/b/c/d/e": chroot_path / "a" / "b" / "c" / "d" / "e" / ".pylintrc",
        }
        for basedir, expected in results.items():
            os.chdir(chroot_path / basedir)
            assert next(config.find_default_config_files()) == expected
예제 #2
0
def test_pylintrc() -> None:
    """Test that the environment variable is checked for existence."""
    with fake_home():
        current_dir = os.getcwd()
        os.chdir(os.path.dirname(os.path.abspath(sys.executable)))
        try:
            assert not list(config.find_default_config_files())
            os.environ["PYLINTRC"] = os.path.join(tempfile.gettempdir(), ".pylintrc")
            assert not list(config.find_default_config_files())
            os.environ["PYLINTRC"] = "."
            assert not list(config.find_default_config_files())
        finally:
            os.chdir(current_dir)
            importlib.reload(config)
    def __init__(self, test_file: Tuple[str, Path]) -> None:
        self._test_file = test_file

        _test_reporter = FunctionalTestReporter()

        self._linter = PyLinter()
        self._linter.namespace.persistent = 0
        checkers.initialize(self._linter)

        # Check if this message has a custom configuration file (e.g. for enabling optional checkers).
        # If not, use the default configuration.
        config_file: Optional[Path]
        if (test_file[1].parent / "pylintrc").exists():
            config_file = test_file[1].parent / "pylintrc"
        else:
            config_file = next(config.find_default_config_files(), None)

        _config_initialization(
            self._linter,
            args_list=[
                str(test_file[1]),
                "--disable=all",
                f"--enable={test_file[0]}",
            ],
            reporter=_test_reporter,
            config_file=config_file,
        )
예제 #4
0
    def __init__(self, test_file: Tuple[str, Path]) -> None:
        self._test_file = test_file

        _test_reporter = FunctionalTestReporter()

        self._linter = PyLinter()
        self._linter.config.persistent = 0
        checkers.initialize(self._linter)

        # Check if this message has a custom configuration file (e.g. for enabling optional checkers).
        # If not, use the default configuration.
        config_file: Optional[Path]
        msgid, full_path = test_file
        pylintrc = full_path.parent / "pylintrc"
        if pylintrc.exists():
            config_file = pylintrc
        else:
            config_file = next(config.find_default_config_files(), None)
        args = [
            str(full_path),
            "--disable=all",
            f"--enable={msgid},astroid-error,fatal,syntax-error",
        ]
        print(f"Command used:\npylint {' '.join(args)}")
        _config_initialization(
            self._linter,
            args_list=args,
            reporter=_test_reporter,
            config_file=config_file,
        )
예제 #5
0
 def __init__(self,
              options=(),
              reporter=None,
              option_groups=(),
              pylintrc=None):
     # some stuff has to be done before ancestors initialization...
     #
     # messages store / checkers / reporter / astroid manager
     self.msgs_store = MessageDefinitionStore()
     self.reporter = None
     self._reporter_name = None
     self._reporters = {}
     self._checkers = collections.defaultdict(list)
     self._pragma_lineno = {}
     self._ignore_file = False
     # visit variables
     self.file_state = FileState()
     self.current_name = None
     self.current_file = None
     self.stats = None
     # init options
     self._external_opts = options
     self.options = options + PyLinter.make_options()
     self.option_groups = option_groups + PyLinter.option_groups
     self._options_methods = {
         "enable": self.enable,
         "disable": self.disable
     }
     self._bw_options_methods = {
         "disable-msg": self.disable,
         "enable-msg": self.enable,
     }
     MessagesHandlerMixIn.__init__(self)
     reporters.ReportsHandlerMixIn.__init__(self)
     super().__init__(
         usage=__doc__,
         config_file=pylintrc
         or next(config.find_default_config_files(), None),
     )
     checkers.BaseTokenChecker.__init__(self)
     # provided reports
     self.reports = (
         ("RP0001", "Messages by category", report_total_messages_stats),
         (
             "RP0002",
             "% errors / warnings by module",
             report_messages_by_module_stats,
         ),
         ("RP0003", "Messages", report_messages_stats),
     )
     self.register_checker(self)
     self._dynamic_plugins = set()
     self._python3_porting_mode = False
     self._error_mode = False
     self.load_provider_defaults()
     if reporter:
         self.set_reporter(reporter)
예제 #6
0
def test_non_existent_home() -> None:
    """Test that we handle a non-existent home directory.

    Reported in https://github.com/PyCQA/pylint/issues/6802.
    """
    with mock.patch("pathlib.Path.home", side_effect=RuntimeError):
        current_dir = os.getcwd()
        os.chdir(os.path.dirname(os.path.abspath(sys.executable)))

        assert not list(config.find_default_config_files())

        os.chdir(current_dir)
예제 #7
0
    def pytest_configure(self, config):
        """Configure pytest after it is already enabled"""

        # Find pylintrc to check ignore list
        if config.option.pylint_rcfile:
            pylintrc_file = config.option.pylint_rcfile
        else:
            # handling files apart from pylintrc was only introduced in pylint
            # 2.5, if we can't use find_default_config_files(), fall back on PYLINTRC
            # once we drop support below 2.5 we can get rid of this
            try:
                pylintrc_file = next(pylint_config.find_default_config_files(),
                                     None)
            except AttributeError:
                pylintrc_file = pylint_config.PYLINTRC

        if pylintrc_file and not exists(pylintrc_file):
            # The directory of pytest.ini got a chance
            pylintrc_file = join(dirname(str(config.inifile)), pylintrc_file)

        # Try getting ignores from pylintrc since we use pytest
        # collection methods and not pylint's internal mechanism
        if pylintrc_file and exists(pylintrc_file):
            self.pylintrc_file = pylintrc_file

            # Check if pylint config has a different filename or date
            # and invalidate the cache if it has changed.
            pylint_mtime = getmtime(pylintrc_file)
            cache_key = PYLINT_CONFIG_CACHE_KEY + pylintrc_file
            cache_value = self.mtimes.get(cache_key)
            if cache_value is None or cache_value < pylint_mtime:
                self.mtimes = {}
            self.mtimes[cache_key] = pylint_mtime

            if pylintrc_file.endswith(".toml"):
                self._load_pyproject_toml(pylintrc_file)
            else:
                self._load_rc_file(pylintrc_file)

        # Command line arguments take presedence over rcfile ones if set
        if config.option.pylint_ignore is not None:
            self.pylint_ignore = config.option.pylint_ignore.split(",")
        if config.option.pylint_ignore_patterns is not None:
            self.pylint_ignore_patterns = config.option.pylint_ignore_patterns.split(
                ",")
예제 #8
0
def test_pylintrc_parentdir_no_package() -> None:
    """Test that we don't find a pylintrc in sub-packages."""
    with tempdir() as chroot:
        with fake_home():
            chroot_path = Path(chroot)
            testutils.create_files(
                ["a/pylintrc", "a/b/pylintrc", "a/b/c/d/__init__.py"]
            )
            assert config.find_pylintrc() is None
            results = {
                "a": chroot_path / "a" / "pylintrc",
                "a/b": chroot_path / "a" / "b" / "pylintrc",
                "a/b/c": None,
                "a/b/c/d": None,
            }
            for basedir, expected in results.items():
                os.chdir(chroot_path / basedir)
                assert next(config.find_default_config_files(), None) == expected
예제 #9
0
    def __init__(
        self,
        args: Sequence[str],
        reporter: BaseReporter | None = None,
        exit: bool = True,  # pylint: disable=redefined-builtin
        do_exit: Any = UNUSED_PARAM_SENTINEL,
    ) -> None:
        # Immediately exit if user asks for version
        if "--version" in args:
            print(full_version)
            sys.exit(0)

        self._rcfile: str | None = None
        self._output: str | None = None
        self._plugins: list[str] = []
        self.verbose: bool = False

        # Pre-process certain options and remove them from args list
        try:
            args = _preprocess_options(self, args)
        except ArgumentPreprocessingError as ex:
            print(ex, file=sys.stderr)
            sys.exit(32)

        # Determine configuration file
        if self._rcfile is None:
            default_file = next(config.find_default_config_files(), None)
            if default_file:
                self._rcfile = str(default_file)

        self.linter = linter = self.LinterClass(
            _make_run_options(self),
            option_groups=self.option_groups,
            pylintrc=self._rcfile,
        )
        # register standard checkers
        linter.load_default_plugins()
        # load command line plugins
        linter.load_plugin_modules(self._plugins)

        linter.disable("I")
        linter.enable("c-extension-no-member")

        # Register the options needed for 'pylint-config'
        # By not registering them by default they don't show up in the normal usage message
        if self._is_pylint_config:
            _register_generate_config_options(linter._arg_parser)

        args = _config_initialization(linter,
                                      args,
                                      reporter,
                                      config_file=self._rcfile,
                                      verbose_mode=self.verbose)

        # Handle the 'pylint-config' command
        if self._is_pylint_config:
            warnings.warn(
                "NOTE: The 'pylint-config' command is experimental and usage can change",
                UserWarning,
            )
            code = _handle_pylint_config_commands(linter)
            if exit:
                sys.exit(code)
            return

        # Display help messages if there are no files to lint
        if not args:
            print(linter.help())
            sys.exit(32)

        if linter.config.jobs < 0:
            print(
                f"Jobs number ({linter.config.jobs}) should be greater than or equal to 0",
                file=sys.stderr,
            )
            sys.exit(32)
        if linter.config.jobs > 1 or linter.config.jobs == 0:
            if multiprocessing is None:
                print(
                    "Multiprocessing library is missing, fallback to single process",
                    file=sys.stderr,
                )
                linter.set_option("jobs", 1)
            elif linter.config.jobs == 0:
                linter.config.jobs = _cpu_count()

        if self._output:
            try:
                with open(self._output, "w", encoding="utf-8") as output:
                    linter.reporter.out = output
                    linter.check(args)
                    score_value = linter.generate_reports()
            except OSError as ex:
                print(ex, file=sys.stderr)
                sys.exit(32)
        else:
            linter.check(args)
            score_value = linter.generate_reports()

        if do_exit is not UNUSED_PARAM_SENTINEL:
            warnings.warn(
                "do_exit is deprecated and it is going to be removed in a future version.",
                DeprecationWarning,
            )
            exit = do_exit

        if exit:
            if linter.config.exit_zero:
                sys.exit(0)
            elif linter.any_fail_on_issues():
                # We need to make sure we return a failing exit code in this case.
                # So we use self.linter.msg_status if that is non-zero, otherwise we just return 1.
                sys.exit(self.linter.msg_status or 1)
            elif score_value is not None:
                if score_value >= linter.config.fail_under:
                    sys.exit(0)
                else:
                    # We need to make sure we return a failing exit code in this case.
                    # So we use self.linter.msg_status if that is non-zero, otherwise we just return 1.
                    sys.exit(self.linter.msg_status or 1)
            else:
                sys.exit(self.linter.msg_status)
예제 #10
0
파일: run.py 프로젝트: AWhetter/pylint
    def __init__(
        self,
        args,
        reporter=None,
        exit=True,
        do_exit=UNUSED_PARAM_SENTINEL,
    ):  # pylint: disable=redefined-builtin
        # Immediately exit if user asks for version
        if "--version" in args:
            print(full_version)
            sys.exit(0)

        self._rcfile: Optional[str] = None
        self._output: Optional[str] = None
        self._plugins: List[str] = []
        self.verbose: bool = False

        # Preprocess certain options and remove them from args list
        try:
            args = _preprocess_options(self, args)
        except ArgumentPreprocessingError as ex:
            print(ex, file=sys.stderr)
            sys.exit(32)

        # Determine configuration file
        if self._rcfile is None:
            self._rcfile = next(config.find_default_config_files(), None)

        self.linter = linter = self.LinterClass(
            (
                (
                    "rcfile",
                    {
                        "action": _DoNothingAction,
                        "kwargs": {},
                        "callback": Run._not_implemented_callback,
                        "group": "Commands",
                        "help": "Specify a configuration file to load.",
                    },
                ),
                (
                    "output",
                    {
                        "action": _DoNothingAction,
                        "kwargs": {},
                        "callback": Run._not_implemented_callback,
                        "group": "Commands",
                        "help": "Specify an output file.",
                    },
                ),
                (
                    "init-hook",
                    {
                        "action":
                        _DoNothingAction,
                        "kwargs": {},
                        "callback":
                        Run._not_implemented_callback,
                        "help":
                        "Python code to execute, usually for sys.path "
                        "manipulation such as pygtk.require().",
                    },
                ),
                (
                    "help-msg",
                    {
                        "action":
                        _MessageHelpAction,
                        "kwargs": {
                            "Run": self
                        },
                        "callback":
                        Run._not_implemented_callback,
                        "group":
                        "Commands",
                        "help":
                        "Display a help message for the given message id and "
                        "exit. The value may be a comma separated list of message ids.",
                    },
                ),
                (
                    "list-msgs",
                    {
                        "action":
                        _ListMessagesAction,
                        "kwargs": {
                            "Run": self
                        },
                        "callback":
                        Run._not_implemented_callback,
                        "group":
                        "Commands",
                        "help":
                        "Display a list of all pylint's messages divided by whether "
                        "they are emittable with the given interpreter.",
                    },
                ),
                (
                    "list-msgs-enabled",
                    {
                        "action":
                        _ListMessagesEnabledAction,
                        "kwargs": {
                            "Run": self
                        },
                        "callback":
                        Run._not_implemented_callback,
                        "group":
                        "Commands",
                        "help":
                        "Display a list of what messages are enabled, "
                        "disabled and non-emittable with the given configuration.",
                    },
                ),
                (
                    "list-groups",
                    {
                        "action": _ListCheckGroupsAction,
                        "kwargs": {
                            "Run": self
                        },
                        "callback": Run._not_implemented_callback,
                        "group": "Commands",
                        "help": "List pylint's message groups.",
                    },
                ),
                (
                    "list-conf-levels",
                    {
                        "action": _ListConfidenceLevelsAction,
                        "callback": Run._not_implemented_callback,
                        "kwargs": {
                            "Run": self
                        },
                        "group": "Commands",
                        "help": "Generate pylint's confidence levels.",
                    },
                ),
                (
                    "list-extensions",
                    {
                        "action": _ListExtensionsAction,
                        "kwargs": {
                            "Run": self
                        },
                        "callback": Run._not_implemented_callback,
                        "group": "Commands",
                        "help": "List available extensions.",
                    },
                ),
                (
                    "full-documentation",
                    {
                        "action": _FullDocumentationAction,
                        "kwargs": {
                            "Run": self
                        },
                        "callback": Run._not_implemented_callback,
                        "group": "Commands",
                        "help": "Generate pylint's full documentation.",
                    },
                ),
                (
                    "generate-rcfile",
                    {
                        "action":
                        _GenerateRCFileAction,
                        "kwargs": {
                            "Run": self
                        },
                        "callback":
                        Run._not_implemented_callback,
                        "group":
                        "Commands",
                        "help":
                        "Generate a sample configuration file according to "
                        "the current configuration. You can put other options "
                        "before this one to get them in the generated "
                        "configuration.",
                    },
                ),
                (
                    "errors-only",
                    {
                        "action":
                        _ErrorsOnlyModeAction,
                        "kwargs": {
                            "Run": self
                        },
                        "callback":
                        Run._not_implemented_callback,
                        "short":
                        "E",
                        "help":
                        "In error mode, checkers without error messages are "
                        "disabled and for others, only the ERROR messages are "
                        "displayed, and no reports are done by default.",
                    },
                ),
                (
                    "verbose",
                    {
                        "action":
                        _DoNothingAction,
                        "kwargs": {},
                        "callback":
                        Run._not_implemented_callback,
                        "short":
                        "v",
                        "help":
                        "In verbose mode, extra non-checker-related info "
                        "will be displayed.",
                    },
                ),
                (
                    "enable-all-extensions",
                    {
                        "action":
                        _DoNothingAction,
                        "kwargs": {},
                        "callback":
                        Run._not_implemented_callback,
                        "help":
                        "Load and enable all available extensions. "
                        "Use --list-extensions to see a list all available extensions.",
                    },
                ),
                (
                    "long-help",
                    {
                        "action": _LongHelpAction,
                        "kwargs": {
                            "Run": self
                        },
                        "callback": Run._not_implemented_callback,
                        "help": "Show more verbose help.",
                        "group": "Commands",
                    },
                ),
            ),
            option_groups=self.option_groups,
            pylintrc=self._rcfile,
        )
        # register standard checkers
        linter.load_default_plugins()
        # load command line plugins
        linter.load_plugin_modules(self._plugins)

        linter.disable("I")
        linter.enable("c-extension-no-member")

        args = _config_initialization(linter,
                                      args,
                                      reporter,
                                      config_file=self._rcfile,
                                      verbose_mode=self.verbose)

        if linter.namespace.jobs < 0:
            print(
                f"Jobs number ({linter.namespace.jobs}) should be greater than or equal to 0",
                file=sys.stderr,
            )
            sys.exit(32)
        if linter.namespace.jobs > 1 or linter.namespace.jobs == 0:
            if multiprocessing is None:
                print(
                    "Multiprocessing library is missing, fallback to single process",
                    file=sys.stderr,
                )
                linter.set_option("jobs", 1)
            elif linter.namespace.jobs == 0:
                linter.namespace.jobs = _cpu_count()

        if self._output:
            try:
                with open(self._output, "w", encoding="utf-8") as output:
                    linter.reporter.out = output
                    linter.check(args)
                    score_value = linter.generate_reports()
            except OSError as ex:
                print(ex, file=sys.stderr)
                sys.exit(32)
        else:
            linter.check(args)
            score_value = linter.generate_reports()

        if do_exit is not UNUSED_PARAM_SENTINEL:
            warnings.warn(
                "do_exit is deprecated and it is going to be removed in a future version.",
                DeprecationWarning,
            )
            exit = do_exit

        if exit:
            if linter.namespace.exit_zero:
                sys.exit(0)
            elif linter.any_fail_on_issues():
                # We need to make sure we return a failing exit code in this case.
                # So we use self.linter.msg_status if that is non-zero, otherwise we just return 1.
                sys.exit(self.linter.msg_status or 1)
            elif score_value is not None:
                if score_value >= linter.namespace.fail_under:
                    sys.exit(0)
                else:
                    # We need to make sure we return a failing exit code in this case.
                    # So we use self.linter.msg_status if that is non-zero, otherwise we just return 1.
                    sys.exit(self.linter.msg_status or 1)
            else:
                sys.exit(self.linter.msg_status)