blob: a121b32a3877195350e88b641b26893abfce7873 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
# For details: https://github.com/pylint-dev/pylint/blob/main/LICENSE
# Copyright (c) https://github.com/pylint-dev/pylint/blob/main/CONTRIBUTORS.txt
from __future__ import annotations
import configparser
import os
import sys
from collections.abc import Iterator
from pathlib import Path
if sys.version_info >= (3, 11):
import tomllib
else:
import tomli as tomllib
RC_NAMES = (Path("pylintrc"), Path(".pylintrc"))
CONFIG_NAMES = (*RC_NAMES, Path("pyproject.toml"), Path("setup.cfg"))
def _toml_has_config(path: Path | str) -> bool:
with open(path, mode="rb") as toml_handle:
try:
content = tomllib.load(toml_handle)
except tomllib.TOMLDecodeError as error:
print(f"Failed to load '{path}': {error}")
return False
return "pylint" in content.get("tool", [])
def _cfg_has_config(path: Path | str) -> bool:
parser = configparser.ConfigParser()
try:
parser.read(path, encoding="utf-8")
except configparser.Error:
return False
return any(section.startswith("pylint.") for section in parser.sections())
def _yield_default_files() -> Iterator[Path]:
"""Iterate over the default config file names and see if they exist."""
for config_name in CONFIG_NAMES:
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
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():
curdir = curdir.parent
for rc_name in RC_NAMES:
rc_path = curdir / rc_name
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()
else:
try:
user_home = Path.home()
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()
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
|