Flag mutable defaults based on mutable annotations
Summary
We'll now flag def foo(a: list = LIST): ... as a mutable default based on the annotation. (If it is immutable, the annotation should be Sequence.)
I want to see what the ecosystem checks look like here. It might be too noisy.
Closes #11030.
ruff-ecosystem results
Linter (stable)
ℹ️ ecosystem check detected linter changes. (+34 -0 violations, +0 -0 fixes in 4 projects; 40 projects unchanged)
commaai/openpilot (+2 -0 violations, +0 -0 fixes)
+ tools/lib/live_logreader.py:10:46: B006 Do not use mutable data structures for argument defaults + tools/lib/live_logreader.py:27:42: B006 Do not use mutable data structures for argument defaults
pandas-dev/pandas (+1 -0 violations, +0 -0 fixes)
+ pandas/io/formats/css.py:351:76: B006 Do not use mutable data structures for argument defaults
reflex-dev/reflex (+3 -0 violations, +0 -0 fixes)
+ reflex/app.py:418:38: B006 Do not use mutable data structures for argument defaults + reflex/app.py:571:38: B006 Do not use mutable data structures for argument defaults + reflex/utils/prerequisites.py:361:33: B006 Do not use mutable data structures for argument defaults
tiangolo/fastapi (+28 -0 violations, +0 -0 fixes)
+ docs_src/dependencies/tutorial001.py:15:38: B006 Do not use mutable data structures for argument defaults + docs_src/dependencies/tutorial001.py:20:38: B006 Do not use mutable data structures for argument defaults + docs_src/dependencies/tutorial001_py310.py:11:38: B006 Do not use mutable data structures for argument defaults + docs_src/dependencies/tutorial001_py310.py:16:38: B006 Do not use mutable data structures for argument defaults + docs_src/dependency_testing/tutorial001.py:16:38: B006 Do not use mutable data structures for argument defaults + docs_src/dependency_testing/tutorial001.py:21:38: B006 Do not use mutable data structures for argument defaults + docs_src/dependency_testing/tutorial001_py310.py:12:38: B006 Do not use mutable data structures for argument defaults + docs_src/dependency_testing/tutorial001_py310.py:17:38: B006 Do not use mutable data structures for argument defaults + docs_src/query_params_str_validations/tutorial012_py39.py:7:37: B006 Do not use mutable data structures for argument defaults + docs_src/query_params_str_validations/tutorial013.py:7:32: B006 Do not use mutable data structures for argument defaults + docs_src/request_files/tutorial002_py39.py:8:45: B006 Do not use mutable data structures for argument defaults + docs_src/request_files/tutorial003_py39.py:16:31: B006 Do not use mutable data structures for argument defaults + docs_src/request_files/tutorial003_py39.py:9:26: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_contextmanager.py:125:39: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_contextmanager.py:130:45: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_contextmanager.py:137:66: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_contextmanager.py:183:38: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_contextmanager.py:188:44: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_contextmanager.py:196:43: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_contextmanager.py:74:35: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_contextmanager.py:82:35: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_normal_exceptions.py:30:50: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_normal_exceptions.py:37:59: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_overrides.py:18:40: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_overrides.py:28:42: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_overrides.py:50:53: B006 Do not use mutable data structures for argument defaults + tests/test_forms_from_non_typing_sequences.py:13:38: B006 Do not use mutable data structures for argument defaults + tests/test_forms_from_non_typing_sequences.py:8:40: B006 Do not use mutable data structures for argument defaults
Changes by rule (1 rules affected)
| code | total | + violation | - violation | + fix | - fix |
|---|---|---|---|---|---|
| B006 | 34 | 34 | 0 | 0 | 0 |
Linter (preview)
ℹ️ ecosystem check detected linter changes. (+34 -0 violations, +0 -0 fixes in 4 projects; 40 projects unchanged)
commaai/openpilot (+2 -0 violations, +0 -0 fixes)
ruff check --no-cache --exit-zero --ignore RUF9 --output-format concise --preview
+ tools/lib/live_logreader.py:10:46: B006 Do not use mutable data structures for argument defaults + tools/lib/live_logreader.py:27:42: B006 Do not use mutable data structures for argument defaults
pandas-dev/pandas (+1 -0 violations, +0 -0 fixes)
ruff check --no-cache --exit-zero --ignore RUF9 --output-format concise --preview
+ pandas/io/formats/css.py:351:76: B006 Do not use mutable data structures for argument defaults
reflex-dev/reflex (+3 -0 violations, +0 -0 fixes)
ruff check --no-cache --exit-zero --ignore RUF9 --output-format concise --preview
+ reflex/app.py:418:38: B006 Do not use mutable data structures for argument defaults + reflex/app.py:571:38: B006 Do not use mutable data structures for argument defaults + reflex/utils/prerequisites.py:361:33: B006 Do not use mutable data structures for argument defaults
tiangolo/fastapi (+28 -0 violations, +0 -0 fixes)
ruff check --no-cache --exit-zero --ignore RUF9 --output-format concise --preview
+ docs_src/dependencies/tutorial001.py:15:38: B006 Do not use mutable data structures for argument defaults + docs_src/dependencies/tutorial001.py:20:38: B006 Do not use mutable data structures for argument defaults + docs_src/dependencies/tutorial001_py310.py:11:38: B006 Do not use mutable data structures for argument defaults + docs_src/dependencies/tutorial001_py310.py:16:38: B006 Do not use mutable data structures for argument defaults + docs_src/dependency_testing/tutorial001.py:16:38: B006 Do not use mutable data structures for argument defaults + docs_src/dependency_testing/tutorial001.py:21:38: B006 Do not use mutable data structures for argument defaults + docs_src/dependency_testing/tutorial001_py310.py:12:38: B006 Do not use mutable data structures for argument defaults + docs_src/dependency_testing/tutorial001_py310.py:17:38: B006 Do not use mutable data structures for argument defaults + docs_src/query_params_str_validations/tutorial012_py39.py:7:37: B006 Do not use mutable data structures for argument defaults + docs_src/query_params_str_validations/tutorial013.py:7:32: B006 Do not use mutable data structures for argument defaults + docs_src/request_files/tutorial002_py39.py:8:45: B006 Do not use mutable data structures for argument defaults + docs_src/request_files/tutorial003_py39.py:16:31: B006 Do not use mutable data structures for argument defaults + docs_src/request_files/tutorial003_py39.py:9:26: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_contextmanager.py:125:39: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_contextmanager.py:130:45: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_contextmanager.py:137:66: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_contextmanager.py:183:38: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_contextmanager.py:188:44: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_contextmanager.py:196:43: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_contextmanager.py:74:35: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_contextmanager.py:82:35: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_normal_exceptions.py:30:50: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_normal_exceptions.py:37:59: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_overrides.py:18:40: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_overrides.py:28:42: B006 Do not use mutable data structures for argument defaults + tests/test_dependency_overrides.py:50:53: B006 Do not use mutable data structures for argument defaults + tests/test_forms_from_non_typing_sequences.py:13:38: B006 Do not use mutable data structures for argument defaults + tests/test_forms_from_non_typing_sequences.py:8:40: B006 Do not use mutable data structures for argument defaults
Changes by rule (1 rules affected)
| code | total | + violation | - violation | + fix | - fix |
|---|---|---|---|---|---|
| B006 | 34 | 34 | 0 | 0 | 0 |
Just gonna mark as draft since I haven’t had a chance to review the ecosystem results and I’m going to bed.
I haven't looked at the code nor the ecosystem checks, but I think my suggestion was to use the TypeChecker to determine if the variable is assigned to a mutable type
https://github.com/astral-sh/ruff/blob/f5c7a62aa65decb9e286bd65ba17f1a3bd1f91e6/crates/ruff_python_semantic/src/analyze/typing.rs#L421-L427
But, I think this could be fine as well.
The ecosystem checks look good to me, except the FastAPI ones which are... hard to comment on. I'm not sure if they can use this rule?
I'd gate this with preview.
(I think we generally recommend adding Query to extend-immutable-types or whatever the setting is called.)