Ruff 0.16.0 Enables 7x More Rules by Default
Upgrade Ruff to 0.16.0 and your next ruff check may flag hundreds of new violations. Your code didn’t change; Ruff enabled 354 additional rules by default.
Since v0.1.0 in October 2023, the out-of-the-box selection stayed ["E4", "E7", "E9", "F"]: pyflakes detections and a narrow slice of pycodestyle. Those conservative defaults are why the handbook’s guide to recommended Ruff defaults covers enabling bugbear, simplify, pyupgrade, and the rest via extend-select. With 0.16.0, many of those rules are on by default.
Which categories are now on by default
The new default set runs 413 rules across 34 categories. The ones that fire most often in real codebases:
B(flake8-bugbear): 29 rules. Mutable default arguments, function calls in defaults, loop variable capture, unsafesetattr/getattrusage.UP(pyupgrade): 42 rules.Optional[X]toX | None, deprecatedtyping.List/Dict/Tupleto built-in equivalents, unnecessary__future__imports.SIM(flake8-simplify): 21 rules. Nestedwithstatements, redundant boolean comparisons.PL(pylint): 67 rules covering conventions, errors, refactoring suggestions, and warnings.C4(flake8-comprehensions): 17 rules. Unnecessary generator-to-list wrapping, redundant collection constructors.DTZ(flake8-datetimez): 10 rules.datetime.now()without timezone,utcnow()usage.I(isort): import sorting.ASYNC(flake8-async): 10 rules. Blocking calls inside async functions, missing checkpoints in async loops.FURB(refurb): 17 rules.sorted()[0]instead ofmin(), bitwise operations over set operations, redundant type conversion.RUF(Ruff-specific): 36 rules. Mutable class variable defaults, implicit optional, ambiguous class-variable annotations.TRY(tryceratops): 5 rules. Verboseraiseinexceptblocks, redefining the caught exception variable.YTT(flake8-2020),PYI(stub file checks),PT(pytest style),FA(future annotations), and more.
The full list is on Astral’s Default Rules page.
Freeze the old defaults
If you want zero behavior change, pin the previous selection in pyproject.toml:
[tool.ruff.lint]
select = ["E4", "E7", "E9", "F"]This restores exactly what 0.15.x ran.
Triage the new violations
For codebases willing to adopt the new defaults, triage one category at a time:
ruff check --select B .
ruff check --select UP .
ruff check --select SIM .Most UP violations have auto-fixes:
ruff check --fix --select UP .For categories with more judgment calls, such as PL or TRY, run ruff check --select PL . to see which codes fire in your codebase, then add the ones you want to silence to ignore:
[tool.ruff.lint]
ignore = ["PL..."] # pin specific codes after reviewing what firesAudit any extend-select entries before removing them. The new defaults enable only a subset of each category (42 of the available UP rules, 21 SIM, 17 C4), not every stable rule under the prefix. A broad extend-select = ["UP"] adds every stable UP rule, so dropping it would silently disable the ones outside the defaults. Check what your extend-select adds beyond the default set on Astral’s Default Rules page first.
See what else 0.16.0 changed
-
Markdown formatting.
ruff formatnow reformats Python code blocks inside Markdown files by default, soruff format .on a docs repo will touch.mdfiles. To opt out, add"*.md"to theexcludelist or wrap a block infmt: off/fmt: oncomments. -
New suppression syntax. Two new comment forms join
# noqa:import math # ruff: ignore[F401] # ruff: ignore[F401] import os# ruff: file-ignore[F401]suppresses a rule for the entire file. The existing# noqasyntax still works; the new forms are an alternative. For block-level suppression, see how to disable Ruff rules for a block of code. -
Inline fix diffs.
checkandformat --checknow print a diff of the available fix beside each diagnostic, so CI shows what would change without a separate--fix --diffpass. -
CI output formats.
ruff format --checknow supports--output-format githuband--output-format gitlab, rendering inline PR annotations for format violations the same way the linter already did. -
JSON output. The
filename,location, andend_locationfields in JSON output may now benullfor diagnostics without a file location, rather than defaulting to empty strings or row 1, column 1. Tooling that reads Ruff’s JSON output should handlenullin those fields.