summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniƫl van Noord <13665637+DanielNoord@users.noreply.github.com>2022-09-06 22:03:32 +0200
committerPierre Sassoulas <pierre.sassoulas@gmail.com>2022-09-06 23:33:59 +0200
commit5b85ecc72663edff1d5f3b5d7e1478a041859c11 (patch)
treebaabf998cc71030ae64d9d1faa71c11e43fed89b
parent262723aaf93798560010fceb254b07fb0899ed0d (diff)
downloadpylint-git-5b85ecc72663edff1d5f3b5d7e1478a041859c11.tar.gz
Suppress ``OSError`` in config file discovery (#7423)
-rw-r--r--doc/whatsnew/fragments/7169.bugfix3
-rw-r--r--pylint/config/find_default_config_files.py52
-rw-r--r--tests/config/test_find_default_config_files.py9
3 files changed, 54 insertions, 10 deletions
diff --git a/doc/whatsnew/fragments/7169.bugfix b/doc/whatsnew/fragments/7169.bugfix
new file mode 100644
index 000000000..6ddf1a498
--- /dev/null
+++ b/doc/whatsnew/fragments/7169.bugfix
@@ -0,0 +1,3 @@
+Don't crash on ``OSError`` in config file discovery.
+
+Closes #7169
diff --git a/pylint/config/find_default_config_files.py b/pylint/config/find_default_config_files.py
index 36917a380..314e70e11 100644
--- a/pylint/config/find_default_config_files.py
+++ b/pylint/config/find_default_config_files.py
@@ -39,17 +39,26 @@ def _cfg_has_config(path: Path | str) -> bool:
return any(section.startswith("pylint.") for section in parser.sections())
-def find_default_config_files() -> Iterator[Path]:
- """Find all possible config files."""
+def _yield_default_files() -> Iterator[Path]:
+ """Iterate over the default config file names and see if they exist."""
for config_name in CONFIG_NAMES:
- if config_name.is_file():
- if config_name.suffix == ".toml" and not _toml_has_config(config_name):
- continue
- if config_name.suffix == ".cfg" and not _cfg_has_config(config_name):
- continue
+ try:
+ if config_name.is_file():
+ if config_name.suffix == ".toml" and not _toml_has_config(config_name):
+ continue
+ if config_name.suffix == ".cfg" and not _cfg_has_config(config_name):
+ continue
+
+ yield config_name.resolve()
+ except OSError:
+ pass
+
- yield config_name.resolve()
+def _find_project_config() -> Iterator[Path]:
+ """Traverse up the directory tree to find a config file.
+ Stop if no '__init__' is found and thus we are no longer in a package.
+ """
if Path("__init__.py").is_file():
curdir = Path(os.getcwd()).resolve()
while (curdir / "__init__.py").is_file():
@@ -59,6 +68,9 @@ def find_default_config_files() -> Iterator[Path]:
if rc_path.is_file():
yield rc_path.resolve()
+
+def _find_config_in_home_or_environment() -> Iterator[Path]:
+ """Find a config file in the specified environment var or the home directory."""
if "PYLINTRC" in os.environ and Path(os.environ["PYLINTRC"]).exists():
if Path(os.environ["PYLINTRC"]).is_file():
yield Path(os.environ["PYLINTRC"]).resolve()
@@ -68,16 +80,36 @@ def find_default_config_files() -> Iterator[Path]:
except RuntimeError:
# If the home directory does not exist a RuntimeError will be raised
user_home = None
+
if user_home is not None and str(user_home) not in ("~", "/root"):
home_rc = user_home / ".pylintrc"
if home_rc.is_file():
yield home_rc.resolve()
+
home_rc = user_home / ".config" / "pylintrc"
if home_rc.is_file():
yield home_rc.resolve()
- if os.path.isfile("/etc/pylintrc"):
- yield Path("/etc/pylintrc").resolve()
+
+def find_default_config_files() -> Iterator[Path]:
+ """Find all possible config files."""
+ yield from _yield_default_files()
+
+ try:
+ yield from _find_project_config()
+ except OSError:
+ pass
+
+ try:
+ yield from _find_config_in_home_or_environment()
+ except OSError:
+ pass
+
+ try:
+ if os.path.isfile("/etc/pylintrc"):
+ yield Path("/etc/pylintrc").resolve()
+ except OSError:
+ pass
def find_pylintrc() -> str | None:
diff --git a/tests/config/test_find_default_config_files.py b/tests/config/test_find_default_config_files.py
index 9addb6db2..10484be1d 100644
--- a/tests/config/test_find_default_config_files.py
+++ b/tests/config/test_find_default_config_files.py
@@ -253,3 +253,12 @@ def test_non_existent_home() -> None:
assert not list(config.find_default_config_files())
os.chdir(current_dir)
+
+
+def test_permission_error() -> None:
+ """Test that we handle PermissionError correctly in find_default_config_files.
+
+ Reported in https://github.com/PyCQA/pylint/issues/7169.
+ """
+ with mock.patch("pathlib.Path.is_file", side_effect=PermissionError):
+ list(config.find_default_config_files())