changelogs/0.11.x.md
This is a follow-up to release 0.10.0. Because of a mistake in the release process, the requires-python inference changes were not included in that release. Ruff 0.11.0 now includes this change as well as the stabilization of the preview behavior for PGH004.
Changes to how the Python version is inferred when a target-version is not specified (#16319)
In previous versions of Ruff, you could specify your Python version with:
target-version option in a ruff.toml file or the [tool.ruff] section of a pyproject.toml file.project.requires-python field in a pyproject.toml file with a [tool.ruff] section.These options worked well in most cases, and are still recommended for fine control of the Python version. However, because of the way Ruff discovers config files, pyproject.toml files without a [tool.ruff] section would be ignored, including the requires-python setting. Ruff would then use the default Python version (3.9 as of this writing) instead, which is surprising when you've attempted to request another version.
In v0.10, config discovery has been updated to address this issue:
ruff.toml file without a target-version, it will check
for a pyproject.toml file in the same directory and respect its
requires-python version, even if it does not contain a [tool.ruff]
section.requires-python field of the closest pyproject.toml in a parent directory will take precedence.ruff.tomlor pyproject.toml with a
[tool.ruff] section) in the directory of the file being checked, Ruff will
search for the closest pyproject.toml in the parent directories and use its
requires-python setting.The following behaviors have been stabilized:
blanket-noqa (PGH004): Also detect blanked file-level noqa comments (and not just line level comments).for statement iterator clause before Python 3.9 (#16558)airflow] Add chain, chain_linear and cross_downstream for AIR302 (#16647)FixAll action in presence of version-specific syntax errors (#16848)flake8-bandit] Allow raw strings in suspicious-mark-safe-usage (S308) #16702 (#16770)refurb] Avoid panicking unwrap in verbose-decimal-constructor (FURB157) (#16777)refurb] Fix starred expressions fix (FURB161) (#16550)--statistics reporting for unsafe fixes (#16756)flake8-executables] Allow uv run in shebang line for shebang-missing-python (EXE003) (#16849,#16855)--exit-non-zero-on-format (#16009)__init__.py (#16818)flake8-gettext] Swap format- and printf-in-get-text-func-call examples (INT002, INT003) (#16769)airflow] Add more autofixes for AIR302 (#16876, #16977, #16976, #16965)airflow] Move AIR301 to AIR002 (#16978)airflow] Move AIR302 to AIR301 and AIR303 to AIR302 (#17151)flake8-bandit] Mark str and list[str] literals as trusted input (S603) (#17136)ruff] Support slices in RUF005 (#17078)case pattern before final case (#16905)case pattern (#16957)return, yield, and for (#17134)__debug__ (#16984)panic! when running Ruff from a deleted directory (#16903) (#17054)pyproject.toml correctly when it is passed via stdin (#16971)flake8-import-conventions] Add import numpy.typing as npt to default flake8-import-conventions.aliases (#17133)refurb] Document why UserDict, UserList, and UserString are preferred over dict, list, and str (FURB189) (#16927)ruff] Implement invalid-rule-code as RUF102 (#17138)match mapping patterns (#17129)match class patterns (#17186)match patterns (#17184)typing.Annotated subscripts (#17201)airflow] Add missing AIR302 attribute check (#17115)airflow] Expand module path check to individual symbols (AIR302) (#17278)airflow] Extract AIR312 from AIR302 rules (AIR302, AIR312) (#17152)airflow] Update outdated AIR301, AIR302 rules (#17123)await (#17282)flake8-pie] Avoid false positive for multiple assignment with auto() (PIE796) (#17274)ruff] Fix RUF100 to detect unused file-level noqa directives with specific codes (#17042) (#17061)flake8-pytest-style] Avoid false positive for legacy form of pytest.raises (PT011) (#17231)airflow] Extract AIR311 from AIR301 rules (AIR301, AIR311) (#17310, #17422)\ is at end of file (#17409)airflow] Apply auto fixes to cases where the names have changed in Airflow 3 (AIR301) (#17355)perflint] Implement fix for manual-dict-comprehension (PERF403) (#16719)airflow] Fix typos in provider package names (AIR302, AIR312) (#17574)flake8-type-checking] Visit keyword arguments in checks involving typing.cast/typing.NewType arguments (#17538)pyupgrade] Preserve parenthesis when fixing native literals containing newlines (UP018) (#17220)refurb] Mark the FURB161 fix unsafe except for integers and booleans (#17240)perflint] Allow list function calls to be replaced with a comprehension (PERF401) (#17519)pycodestyle] Auto-fix redundant boolean comparison (E712) (#17090)pylint] make fix unsafe if delete comments (PLR1730) (#17459)airflow] Apply auto fixes to cases where the names have changed in Airflow 3 (AIR302, AIR311) (#17553, #17570, #17571)airflow] Extend AIR301 rule (#17598)airflow] Update existing AIR302 rules with better suggestions (#17542)refurb] Mark fix as safe for readlines-in-for (FURB129) (#17644)nonlocal declaration at module level (#17559)x = *y (#17624)flake8-pyi] Ensure Literal[None,] | Literal[None,] is not autofixed to None | None (PYI061) (#17659)flake8-use-pathlib] Avoid suggesting Path.iterdir() for os.listdir with file descriptor (PTH208) (#17715)flake8-use-pathlib] Fix PTH104 false positive when rename is passed a file descriptor (#17712)flake8-use-pathlib] Fix PTH116 false positive when stat is passed a file descriptor (#17709)flake8-use-pathlib] Fix PTH123 false positive when open is passed a file descriptor from a function call (#17705)pycodestyle] Fix duplicated diagnostic in E712 (#17651)pylint] Detect global declarations in module scope (PLE0118) (#17411)async-comprehension-in-sync-comprehension more specific (#17460)typing_extensions imports (#17611)lint.pydocstyle.ignore-var-parameters option (#17740)ASYNC116, FLY002, D200, RUF005, RUF017, RUF027, RUF028, RUF057) (#17497, #17496, #17502, #17484, #17480, #17485, #17722, #17483)airflow] Fix SQLTableCheckOperator typo (AIR302) (#17946)airflow] Remove airflow.utils.dag_parsing_context.get_parsing_context (AIR301) (#17852)airflow] Skip attribute check in try catch block (AIR301) (#17790)flake8-bandit] Mark tuples of string literals as trusted input in S603 (#17801)isort] Check full module path against project root(s) when categorizing first-party imports (#16565)ruff] Add new rule in-empty-collection (RUF060) (#16480)combine call for lint.typing-extensions setting (#17823)flake8-async] Fix module name in ASYNC110, ASYNC115, and ASYNC116 fixes (#17774)pyupgrade] Add spaces between tokens as necessary to avoid syntax errors in UP018 autofix (#17648)refurb] Fix false positive for float and complex numbers in FURB116 (#17661)PLC2801, PLR1722, and RUF013 (#17825, #17826, #17759)check-typed-exception from S110 and S112 (#17786)ruff analyze graph (#17743)ruff] Implement a recursive check for RUF060 (#17976)airflow] Enable autofixes for AIR301 and AIR311 (#17941)airflow] Apply try catch guard to all AIR3 rules (#17887)airflow] Extend AIR311 rules (#17913)flake8-bugbear] Ignore B028 if skip_file_prefixes is present (#18047)flake8-pie] Mark autofix for PIE804 as unsafe if the dictionary contains comments (#18046)flake8-simplify] Correct behavior for str.split/rsplit with maxsplit=0 (SIM905) (#18075)flake8-simplify] Fix SIM905 autofix for rsplit creating a reversed list literal (#18045)flake8-use-pathlib] Suppress diagnostics for all os.* functions that have the dir_fd parameter (PTH) (#17968)refurb] Mark autofix as safe only for number literals (FURB116) (#17692)flake8-bandit] Skip S608 for expressionless f-strings (#17999)flake8-pytest-style] Don't recommend usefixtures for parametrize values (PT019) (#17650)pyupgrade] Add resource.error as deprecated alias of OSError (UP024) (#17933)flake8-simplify] Add fix safety section (SIM103) (#18086)flake8-simplify] Add fix safety section (SIM112) (#18099)pylint] Add fix safety section (PLC0414) (#17802)pylint] Add fix safety section (PLE4703) (#17824)pylint] Add fix safety section (PLW1514) (#17932)pylint] Add fix safety section (PLW3301) (#17878)ruff] Add fix safety section (RUF007) (#17755)ruff] Add fix safety section (RUF033) (#17760)airflow] Add autofixes for AIR302 and AIR312 (#17942)airflow] Move rules from AIR312 to AIR302 (#17940)airflow] Update AIR301 and AIR311 with the latest Airflow implementations (#17985)flake8-simplify] Enable fix in preview mode (SIM117) (#18208)[] and _ (#18147)pylint] Fix PLW1514 not recognizing the encoding positional argument of codecs.open (#18109)flake8-print] Improve print/pprint docs for T201 and T203 (#18130)flake8-simplify] Add fix safety section (SIM110,SIM210) (#18114,#18100)pylint] Fix docs example that produced different output (PLW0603) (#18216)airflow] Revise fix titles (AIR3) (#18215)pylint] Implement missing-maxsplit-arg (PLC0207) (#17454)pyupgrade] New rule UP050 (useless-class-metaclass-type) (#18334)flake8-use-pathlib] Replace os.symlink with Path.symlink_to (PTH211) (#18337)flake8-bugbear] Ignore __debug__ attribute in B010 (#18357)flake8-async] Fix anyio.sleep argument name (ASYNC115, ASYNC116) (#18262)refurb] Fix FURB129 autofix generating invalid syntax (#18235)flake8-implicit-str-concat] Add autofix for ISC003 (#18256)pycodestyle] Improve the diagnostic message for E712 (#18328)flake8-2020] Fix diagnostic message for != comparisons (YTT201) (#18293)pyupgrade] Make fix unsafe if it deletes comments (UP010) (#18291)flake8-bugbear] Add fix safety section (B006) (#17652)airflow] Add unsafe fix for module moved cases (AIR301,AIR311,AIR312,AIR302) (#18367,#18366,#18363,#18093)refurb] Add coverage of set and frozenset calls (FURB171) (#18035)refurb] Mark FURB180 fix unsafe when class has bases (#18149)perflint] Fix missing parentheses for lambda and ternary conditions (PERF401, PERF403) (#18412)pyupgrade] Apply UP035 only on py313+ for get_type_hints() (#18476)pyupgrade] Make fix unsafe if it deletes comments (UP004,UP050) (#18393, #18390)fastapi] Avoid false positive for class dependencies (FAST003) (#18271)