blob: 7d45608cb953713f85ea625efb6c370751d30f03 [file] [edit]
[build-system]
requires = ["maturin>=1.9.3,<2.0"]
build-backend = "maturin"
[project]
name = "ruff"
version = "0.16.6"
description = "An extremely fast Python linter and code formatter, written in Rust."
authors = [{ name = "Astral Software Inc.", email = "hey@astral.sh" }]
readme = "README.md"
requires-python = ">=3.7"
license = "MIT"
license-files = ["LICENSE"]
keywords = [
"automation",
"flake8",
"pycodestyle",
"pyflakes",
"pylint",
"clippy",
]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Environment :: Console",
"Intended Audience :: Developers",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"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 :: 3.14",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Rust",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Software Development :: Quality Assurance",
]
[project.urls]
Repository = "https://github.com/astral-sh/ruff"
Documentation = "https://docs.astral.sh/ruff/"
Changelog = "https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md"
[tool.maturin]
bindings = "bin"
manifest-path = "crates/ruff/Cargo.toml"
module-name = "ruff"
python-source = "python"
strip = true
exclude = [
"crates/ruff_linter/resources/test/fixtures/**/*",
"crates/ruff_linter/src/rules/*/snapshots/**/*"
]
[dependency-groups]
dev = [
"astral-dev-toolchain-cargo-codspeed>=5.0.1",
"astral-dev-toolchain-cargo-fuzz>=0.13.2",
"astral-dev-toolchain-cargo-insta>=1.48.0",
"astral-dev-toolchain-cargo-nextest>=0.9.143",
"astral-dev-toolchain-cargo-shear>=1.13.4",
"astral-dev-toolchain-hyperfine>=1.20.0",
"prek==0.4.12",
]
release = [
"rooster==0.1.1",
]
docs = [
"mkdocs>=1.6.1",
"mkdocs-github-admonitions-plugin>=0.1.1",
"mkdocs-llmstxt>=0.2.0",
"mkdocs-material>=9.7.7",
"mkdocs-redirects>=1.2.3",
"pyyaml>=6.0.3",
]
# The compatibility tests use the Ruff binary built from this checkout.
ruff-lsp-test = [
"lsprotocol>=2023.0.0",
"packaging>=23.1",
# ruff-lsp uses the pygls 1.x server API.
"pygls>=1.1.0,<2",
"pytest>=9.0.3,<10",
"pytest-asyncio>=0.21.2",
"python-lsp-jsonrpc>=1.0.0",
"typing-extensions>=4.7.1",
]
ty-ecosystem = [
"ecosystem-analyzer",
]
typeshed-docstrings = [
"docstring-adder",
]
typeshed-formatting = [
"black",
]
[tool.uv]
no-build = true
# CI installs the local ecosystem runner and tools pinned to Git revisions.
no-binary-package = [
"black",
"docstring-adder",
"ecosystem-analyzer",
"mypy-primer",
"ruff-ecosystem",
"typeshed-client",
]
# Pin the isolated build environment for source-build exceptions.
build-constraint-dependencies = [
"flit-core==4.0.2",
"hatch-fancy-pypi-readme==25.1.0",
"hatch-vcs==0.5.0",
"hatchling==1.32.0",
"packaging==26.3",
"pathspec==1.1.1",
"pluggy==1.6.0",
"setuptools==84.0.0",
"setuptools-scm==10.2.1",
"tomli==2.4.1; python_version < '3.11'",
"tomlkit==0.15.1",
"trove-classifiers==2026.6.1.19",
"typing-extensions==4.16.0; python_version < '3.11'",
"uv-build==0.12.3",
"vcs-versioning==2.2.4",
"wheel==0.47.0",
]
exclude-newer = "P7D"
[tool.uv.exclude-newer-package]
astral-dev-toolchain-hyperfine = "2026-08-27T00:00:00Z"
astral-dev-toolchain-cargo-shear = "2026-08-27T00:00:00Z"
astral-dev-toolchain-cargo-codspeed = "2026-08-27T00:00:00Z"
astral-dev-toolchain-cargo-nextest = "2026-08-27T00:00:00Z"
astral-dev-toolchain-cargo-insta = "2026-08-27T00:00:00Z"
astral-dev-toolchain-cargo-fuzz = "2026-09-01T00:00:00Z"
[tool.uv.dependency-groups]
dev = { requires-python = ">=3.12" }
release = { requires-python = ">=3.12" }
docs = { requires-python = ">=3.12" }
ruff-lsp-test = { requires-python = ">=3.12" }
ty-ecosystem = { requires-python = ">=3.13" }
typeshed-docstrings = { requires-python = ">=3.10" }
typeshed-formatting = { requires-python = ">=3.10" }
[tool.uv.sources]
docstring-adder = { git = "https://github.com/astral-sh/docstring-adder.git" }
# Switch to a released version once it includes
# https://github.com/psf/black/commit/f665703258bfa1916f8a6c1cbab0bc384b90cbac.
black = { git = "https://github.com/psf/black.git" }
# Keep scripts/setup_primer_project.py and its lockfile synchronized with
# ecosystem-analyzer's mypy-primer pin when updating its locked revision.
ecosystem-analyzer = { git = "https://github.com/astral-sh/ecosystem-analyzer" }
[tool.ruff]
target-version = "py38"
extend-exclude = [
"crates/ty_vendored/vendor/",
"crates/ruff/resources/",
"crates/ruff_linter/resources/",
"crates/ruff_python_formatter/resources/",
"crates/ruff_python_parser/resources/",
"crates/ruff_python_semantic/resources/"
]
[tool.ruff.lint]
preview = true
select = [
# Categories
"correctness",
"suspicious",
"complexity",
"performance",
"style",
# E # pycodestyle (error)
"ambiguous-class-name",
"ambiguous-function-name",
"ambiguous-variable-name",
"lambda-assignment",
"module-import-not-at-top-of-file",
"multiple-imports-on-one-line",
"multiple-leading-hashes-for-block-comment",
"no-indented-block",
"none-comparison",
"not-in-test",
"not-is-test",
"true-false-comparison",
"type-comparison",
"unexpected-indentation",
# F # pyflakes
"forward-annotation-syntax-error",
"undefined-local-with-import-star",
"undefined-local-with-import-star-usage",
# B # bugbear
"batched-without-explicit-strict",
"class-as-data-structure",
"map-without-explicit-strict",
"no-explicit-stacklevel",
"raise-without-from-inside-except",
"re-sub-positional-args",
"unused-loop-control-variable",
"zip-without-explicit-strict",
# C4 # flake8-comprehensions
"unnecessary-comprehension",
# SIM # flake8-simplify
"compare-with-tuple",
"dict-get-with-none-default",
"if-else-block-instead-of-dict-lookup",
"if-else-block-instead-of-if-exp",
"if-expr-with-twisted-arms",
"suppressible-exception",
"uncapitalized-environment-variables",
"yoda-conditions",
# I # isort
"missing-required-import",
# UP # pyupgrade
"convert-typed-dict-functional-to-class",
"redundant-open-modes",
# PGH # pygrep-hooks
"blanket-noqa",
"blanket-type-ignore",
# PYI # flake8-pyi
"argument-default-in-stub",
"collections-named-tuple",
"docstring-in-stub",
"numeric-literal-too-long",
"redundant-literal-union",
"string-or-bytes-too-long",
"typed-argument-default-in-stub",
"unsupported-method-call-on-all",
# RUF
"ambiguous-unicode-character-comment",
"ambiguous-unicode-character-docstring",
"ambiguous-unicode-character-string",
"asyncio-dangling-task",
"collection-literal-concatenation",
"incorrectly-parenthesized-tuple-in-subscript",
"non-empty-init-module",
"noqa-comments",
"parenthesize-chained-operators",
"rule-codes-in-selectors",
"unnecessary-assign-before-yield",
"unraw-re-pattern",
"unused-async",
"used-dummy-variable",
# S
"subprocess-popen-with-shell-equals-true",
]
ignore = [
# only relevant if you run a script with `python -0`,
# which seems unlikely for any of the scripts in this repo
"assert-false",
# Leave it to the formatter to split long lines and
# the judgement of all of us.
"line-too-long",
# This is often more readable in our scripts.
"repeated-append",
]
[tool.ruff.lint.isort]
required-imports = ["from __future__ import annotations"]
combine-as-imports = true
[tool.ruff.per-file-target-version]
"crates/ty_python_semantic/mdtest.py" = "py310"
"crates/ty_vendored/ty_extensions/*.pyi" = "py312"
"scripts/*.py" = "py312"
[tool.black]
force-exclude = '''
/(
| crates/ty_vendored/vendor
| crates/ruff_linter/resources
| crates/ruff_python_formatter/resources
| crates/ruff_python_parser/resources
)/
'''
[tool.rooster]
major_labels = [] # Ruff never uses the major version number
minor_labels = ["breaking"] # Bump the minor version on breaking changes
ignore_labels = ["internal", "ci", "testing", "ty"]
version_files = [
"README.md",
"pyproject.toml",
# Might become unneeded once Markdown formatting is stabilized.
"docs/formatter.md",
"docs/installation.md",
"docs/integrations.md",
"docs/tutorial.md",
"crates/ruff/Cargo.toml",
"crates/ruff_linter/Cargo.toml",
# Note that the value being replaced here needs to be kept in sync with the
# validation regex in the `violation_metadata` macro.
{ target = "crates/ruff_linter/src/rules/**/*.rs", replace = "NEXT_RUFF_VERSION" },
"crates/ruff_wasm/Cargo.toml",
"scripts/benchmarks/pyproject.toml",
]
[tool.rooster.section-labels]
"Breaking changes" = ["breaking"]
"Preview features" = ["preview"]
"Bug fixes" = ["bug"]
"Rule changes" = [
"diagnostics",
"docstrings",
"rule",
"fixes",
"isort",
]
"Performance" = ["performance"]
"Formatter" = ["formatter"]
"Server" = ["server"]
"CLI" = ["cli"]
"Configuration" = ["configuration"]
"Documentation" = ["documentation"]
"Other changes" = ["__unknown__"]