| [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__"] |