[build-system]
requires = ["setuptools>=71.0.4"]
build-backend = "setuptools.build_meta"

[project]
name        = "pylint"
license     = {text = "GPL-2.0-or-later"}
description = "python code static checker"
readme      = "README.rst"
authors     = [
    {name = "Python Code Quality Authority", email = "code-quality@python.org"}
]
keywords    = ["static code analysis", "linter", "python", "lint"]
classifiers = [
    "Development Status :: 6 - Mature",
    "Environment :: Console",
    "Intended Audience :: Developers",
    "License :: OSI Approved :: GNU General Public License v2 (GPLv2)",
    "Operating System :: OS Independent",
    "Programming Language :: Python",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3 :: Only",
    "Programming Language :: Python :: 3.9",
    "Programming Language :: Python :: 3.10",
    "Programming Language :: Python :: 3.11",
    "Programming Language :: Python :: 3.12",
    "Programming Language :: Python :: 3.13",
    "Programming Language :: Python :: Implementation :: CPython",
    "Programming Language :: Python :: Implementation :: PyPy",
    "Topic :: Software Development :: Debuggers",
    "Topic :: Software Development :: Quality Assurance",
    "Topic :: Software Development :: Testing",
    "Typing :: Typed"
]
requires-python = ">=3.9.0"
dependencies    = [
    "dill>=0.2;python_version<'3.11'",
    "dill>=0.3.6;python_version>='3.11'",
    "dill>=0.3.7;python_version>='3.12'",
    "platformdirs>=2.2.0",
    # Also upgrade requirements_test_min.txt.
    # Pinned to dev of second minor update to allow editable installs and fix primer issues,
    # see https://github.com/pylint-dev/astroid/issues/1341
    "astroid>=3.3.5,<=3.4.0-dev0",
    "isort>=4.2.5,<6,!=5.13.0",
    "mccabe>=0.6,<0.8",
    "tomli>=1.1.0;python_version<'3.11'",
    "tomlkit>=0.10.1",
    "colorama>=0.4.5;sys_platform=='win32'",
    "typing-extensions>=3.10.0;python_version<'3.10'",
]
dynamic = ["version"]

[project.optional-dependencies]
testutils = ["gitpython>3"]
spelling = ["pyenchant~=3.2"]

[project.urls]
"Docs: User Guide"  = "https://pylint.readthedocs.io/en/latest/"
"Source Code"       = "https://github.com/pylint-dev/pylint"
"homepage"          = "https://github.com/pylint-dev/pylint"
"What's New"        = "https://pylint.readthedocs.io/en/latest/whatsnew/3/"
"Bug Tracker"       = "https://github.com/pylint-dev/pylint/issues"
"Discord Server"    = "https://discord.com/invite/Egy6P8AMB5"
"Docs: Contributor Guide" = "https://pylint.readthedocs.io/en/latest/development_guide/contributor_guide/index.html"

[project.scripts]
pylint        = "pylint:run_pylint"
pylint-config = "pylint:_run_pylint_config"
pyreverse     = "pylint:run_pyreverse"
symilar       = "pylint:run_symilar"

[tool.setuptools]
license-files = ["LICENSE", "CONTRIBUTORS.txt"]  # Keep in sync with setup.cfg

[tool.setuptools.packages.find]
include = ["pylint*"]

[tool.setuptools.package-dir]
# Simulate editable_mode=compat, described at:
# https://github.com/pypa/setuptools/issues/3767
# TODO: remove after solving root cause described at:
# https://github.com/pylint-dev/astroid/pull/2267#issuecomment-1666642781
"" = "."

[tool.setuptools.package-data]
pylint = ["testutils/testing_pylintrc", "py.typed"]

[tool.setuptools.dynamic]
version = {attr = "pylint.__pkginfo__.__version__"}

[tool.aliases]
test = "pytest"

[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["*test_*.py"]
addopts = "--strict-markers"
filterwarnings = "error"
markers = [
    "primer_stdlib: Checks for crashes and errors when running pylint on stdlib",
    "benchmark: Baseline of pylint performance, if this regress something serious happened",
    "timeout: Marks from pytest-timeout.",
    "needs_two_cores: Checks that need 2 or more cores to be meaningful",
]

[tool.isort]
profile = "black"
known_third_party = ["platformdirs", "astroid", "sphinx", "isort", "pytest", "mccabe", "six", "toml"]
extra_standard_library = ["_string"]
skip_glob = ["tests/functional/**", "tests/input/**", "tests/extensions/data/**", "tests/regrtest_data/**", "tests/data/**", "astroid/**", "venv/**"]
src_paths = ["pylint"]

[tool.mypy]
scripts_are_modules = true
warn_unused_ignores = true
show_error_codes = true
enable_error_code = "ignore-without-code"
strict = true
# TODO: Remove this once pytest has annotations
disallow_untyped_decorators = false

[[tool.mypy.overrides]]
ignore_missing_imports = true
module = [
    "_pytest.*",
    "_string",
    "astroid.*",
    # `colorama` ignore is needed for Windows environment
    "colorama",
    "contributors_txt",
    "coverage",
    "dill",
    "enchant.*",
    "git.*",
    "mccabe",
    "pytest_benchmark.*",
    "pytest",
    "sphinx.*",
]

[tool.ruff]

# ruff is less lenient than pylint and does not make any exceptions
# (for docstrings, strings and comments in particular).
line-length = 115

extend-exclude = [
    "tests/**/data/",
    "tests/**/functional/",
    "tests/input/",
    "tests/regrtest_data/",
]

[tool.ruff.lint]
select = [
    "B",  # bugbear
    "D",  # pydocstyle
    "E",  # pycodestyle
    "F",  # pyflakes
    "I",  # isort
    "PIE", # flake8-pie
    "PTH",  # flake8-pathlib
    "PYI", # flake8-pyi
    "UP", # pyupgrade
    "RUF", # ruff
    "W",  # pycodestyle
]

ignore = [
    "B905",  # `zip()` without an explicit `strict=` parameter
    "D100",  # Missing docstring in public module
    "D101",  # Missing docstring in public class
    "D102",  # Missing docstring in public method
    "D103",  # Missing docstring in public function
    "D104",  # Missing docstring in public package
    "D105",  # Missing docstring in magic method
    "D106",  # Missing docstring in public nested class
    "D107",  # Missing docstring in `__init__`
    "D205",  # 1 blank line required between summary line and description
    "D400",  # First line should end with a period
    "D401",  # First line of docstring should be in imperative mood
    "PTH100",  # `os.path.abspath()` should be replaced by `Path.resolve()`
    "PTH103",  # `os.makedirs()` should be replaced by `Path.mkdir(parents=True)`
    "PTH107",  # `os.remove()` should be replaced by `Path.unlink()`
    "PTH108",  # `os.unlink()` should be replaced by `Path.unlink()`
    "PTH109",  # `os.getcwd()` should be replaced by `Path.cwd()`
    "PTH110",  # `os.path.exists()` should be replaced by `Path.exists()`
    "PTH111",  # `os.path.expanduser()` should be replaced by `Path.expanduser()`
    "PTH112",  # `os.path.isdir()` should be replaced by `Path.is_dir()`
    "PTH113",  # `os.path.isfile()` should be replaced by `Path.is_file()`
    "PTH118",  # `os.path.join()` should be replaced by `Path` with `/` operator
    "PTH119",  # `os.path.basename()` should be replaced by `Path.name`
    "PTH120",  # `os.path.dirname()` should be replaced by `Path.parent`
    "PTH122",  # `os.path.splitext()` should be replaced by `Path.suffix`, `Path.stem`, and `Path.parent`
    "PTH123",  # `open()` should be replaced by `Path.open()`
    "PTH207",  # Replace `glob` with `Path.glob` or `Path.rglob`
    "RUF012",  # mutable default values in class attributes
]

[tool.ruff.lint.pydocstyle]
convention = "pep257"

[tool.codespell]
ignore-words = ["custom_dict.txt"]

# Disabled the spelling files for obvious reason, but also,
# the test file with typing extension imported as 'te' and:
# tests/functional/i/implicit/implicit_str_concat_latin1.py:
#   - bad encoding
# pylint/pyreverse/diagrams.py and tests/pyreverse/test_diagrams.py:
#   - An API from pyreverse use 'classe', and would need to be deprecated
# pylint/checkers/imports.py:
#   - 'THIRDPARTY' is a value from isort that would need to be handled even
#   if isort fix the typo in newer versions
# tests/functional/m/member/member_checks.py:
#   - typos are voluntary to create credible 'no-member'

skip = """
tests/checkers/unittest_spelling.py,\
CODE_OF_CONDUCT.md,\
CONTRIBUTORS.txt,\
pylint/checkers/imports.py,\
pylint/pyreverse/diagrams.py,\
tests/pyreverse/test_diagrams.py,\
tests/functional/i/implicit/implicit_str_concat_latin1.py,\
tests/functional/m/member/member_checks.py,\
tests/functional/t/type/typevar_naming_style_rgx.py,\
tests/functional/t/type/typevar_naming_style_default.py,\
tests/functional/m/member/member_checks_async.py,\
"""
