ruff/crates
Guilherme Vasconcelos a8e50a7f40
[RUF008] Make it clearer that a mutable default in a dataclass is only valid if it is typed as a ClassVar (#10395)
## Summary

The previous documentation sounded as if typing a mutable default as a
`ClassVar` were optional. However, it is not, as not doing so causes a
`ValueError`. The snippet below was tested in Python's interactive
shell:

```
>>> from dataclasses import dataclass
>>> @dataclass
... class A:
...     mutable_default: list[int] = []
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.11/dataclasses.py", line 1230, in dataclass
    return wrap(cls)
           ^^^^^^^^^
  File "/usr/lib/python3.11/dataclasses.py", line 1220, in wrap
    return _process_class(cls, init, repr, eq, order, unsafe_hash,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/dataclasses.py", line 958, in _process_class
    cls_fields.append(_get_field(cls, name, type, kw_only))
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/dataclasses.py", line 815, in _get_field
    raise ValueError(f'mutable default {type(f.default)} for field '
ValueError: mutable default <class 'list'> for field mutable_default is not allowed: use default_factory
>>>
```

This behavior is also documented in Python's docs, see
[here](https://docs.python.org/3/library/dataclasses.html#mutable-default-values):

> [...] the
[dataclass()](https://docs.python.org/3/library/dataclasses.html#dataclasses.dataclass)
decorator will raise a
[ValueError](https://docs.python.org/3/library/exceptions.html#ValueError)
if it detects an unhashable default parameter. The assumption is that if
a value is unhashable, it is mutable. This is a partial solution, but it
does protect against many common errors.

And
[here](https://docs.python.org/3/library/dataclasses.html#class-variables)
it is documented why it works if it is typed as a `ClassVar`:

> One of the few places where
[dataclass()](https://docs.python.org/3/library/dataclasses.html#dataclasses.dataclass)
actually inspects the type of a field is to determine if a field is a
class variable as defined in [PEP
526](https://peps.python.org/pep-0526/). It does this by checking if the
type of the field is typing.ClassVar. If a field is a ClassVar, it is
excluded from consideration as a field and is ignored by the dataclass
mechanisms. Such ClassVar pseudo-fields are not returned by the
module-level
[fields()](https://docs.python.org/3/library/dataclasses.html#dataclasses.fields)
function.

In this PR I have changed the documentation to make it a little bit
clearer that not using `ClassVar` makes the code invalid.
2024-03-14 23:18:03 +00:00
..
ruff Require --preview for ruff server (#10368) 2024-03-13 23:52:44 +00:00
ruff_benchmark Run doctests as part of CI pipeline (#9939) 2024-02-12 10:18:58 +01:00
ruff_cache Make all dependencies workspace dependencies (#9333) 2024-01-02 13:41:59 +00:00
ruff_dev Make --config and --isolated global flags (#10150) 2024-03-04 11:19:40 +00:00
ruff_diagnostics Run doctests as part of CI pipeline (#9939) 2024-02-12 10:18:58 +01:00
ruff_formatter Spellcheck & grammar (#10375) 2024-03-13 02:34:23 +00:00
ruff_index Run doctests as part of CI pipeline (#9939) 2024-02-12 10:18:58 +01:00
ruff_linter [RUF008] Make it clearer that a mutable default in a dataclass is only valid if it is typed as a ClassVar (#10395) 2024-03-14 23:18:03 +00:00
ruff_macros Spellcheck & grammar (#10375) 2024-03-13 02:34:23 +00:00
ruff_notebook Spellcheck & grammar (#10375) 2024-03-13 02:34:23 +00:00
ruff_python_ast Use ExprFString for StringLike::FString variant (#10311) 2024-03-14 13:30:22 +05:30
ruff_python_codegen Unify enums used for internal representation of quoting style (#10383) 2024-03-13 17:19:17 +00:00
ruff_python_formatter Unify enums used for internal representation of quoting style (#10383) 2024-03-13 17:19:17 +00:00
ruff_python_index Fix Indexer fails to identify continuation preceded by newline #10351 (#10354) 2024-03-12 00:35:41 -04:00
ruff_python_literal Unify enums used for internal representation of quoting style (#10383) 2024-03-13 17:19:17 +00:00
ruff_python_parser Unify enums used for internal representation of quoting style (#10383) 2024-03-13 17:19:17 +00:00
ruff_python_resolver Run doctests as part of CI pipeline (#9939) 2024-02-12 10:18:58 +01:00
ruff_python_semantic refactor: Use QualifiedName for Imported::call_path (#10214) 2024-03-06 09:55:59 +01:00
ruff_python_stdlib [pylint] Include builtin warnings in useless-exception-statement (PLW0133) (#10394) 2024-03-13 15:26:11 -04:00
ruff_python_trivia Implement RUF028 to detect useless formatter suppression comments (#9899) 2024-02-28 19:21:06 +00:00
ruff_server Spellcheck & grammar (#10375) 2024-03-13 02:34:23 +00:00
ruff_shrinking Bump version to v0.3.2 (#10304) 2024-03-09 00:24:22 +00:00
ruff_source_file ruff server - A new built-in LSP for Ruff, written in Rust (#10158) 2024-03-08 20:57:23 -08:00
ruff_text_size Range formatting: Fix invalid syntax after parenthesizing expression (#9751) 2024-02-02 17:56:25 +01:00
ruff_wasm Run doctests as part of CI pipeline (#9939) 2024-02-12 10:18:58 +01:00
ruff_workspace Remove F401 fix for __init__ imports by default and allow opt-in to unsafe fix (#10365) 2024-03-13 12:58:25 -05:00