ruff/crates
David Peter d03b12e711
[red-knot] Assignments to attributes (#16705)
## Summary

This changeset adds proper support for assignments to attributes:
```py
obj.attr = value
```

In particular, the following new features are now available:

* We previously didn't raise any errors if you tried to assign to a
non-existing attribute `attr`. This is now fixed.
* If `type(obj).attr` is a data descriptor, we now call its `__set__`
method instead of trying to assign to the load-context type of
`obj.attr`, which can be different for data descriptors.
* An initial attempt was made to support unions and intersections, as
well as possibly-unbound situations. There are some remaining TODOs in
tests, but they only affect edge cases. Having nested diagnostics would
be one way that could help solve the remaining cases, I believe.

## Follow ups

The following things are planned as follow-ups:

- Write a test suite with snapshot diagnostics for various attribute
assignment errors
- Improve the diagnostics. An easy improvement would be to highlight the
right hand side of the assignment as a secondary span (with the rhs type
as additional information). Some other ideas are mentioned in TODO
comments in this PR.
- Improve the union/intersection/possible-unboundness handling
- Add support for calling custom `__setattr__` methods (see new false
positive in the ecosystem results)

## Ecosystem changes

Some changes are related to assignments on attributes with a custom
`__setattr__` method (see above). Since we didn't notice missing
attributes at all in store context previously, these are new.

The other changes are related to properties. We previously used their
read-context type to test the assignment. That results in weird error
messages, as we often see assignments to `self.property` and then we
think that those are instance attributes *and* descriptors, leading to
union types. Now we properly look them up on the meta type, see the
decorated function, and try to overwrite it with the new value (as we
don't understand decorators yet). Long story short: the errors are still
weird, we need to understand decorators to make them go away.

## Test Plan

New Markdown tests
2025-03-14 12:15:41 +01:00
..
red_knot [red-knot] Add mypy_primer usage documentation (#16679) 2025-03-12 16:47:10 +01:00
red_knot_project [red-knot] use fixpoint iteration for all cycles (#14029) 2025-03-12 12:41:40 +00:00
red_knot_python_semantic [red-knot] Assignments to attributes (#16705) 2025-03-14 12:15:41 +01:00
red_knot_server ruff_db: rename Diagnostic to OldDiagnosticTrait 2025-03-05 08:23:02 -05:00
red_knot_test print MDTEST_TEST_FILTER value in single-quotes (and escaped) (#16548) 2025-03-07 09:04:52 +01:00
red_knot_vendored [red-knot] Add CallableTypeFromFunction special form (#16683) 2025-03-13 07:49:34 +05:30
red_knot_wasm Add OsSystem support to mdtests (#16518) 2025-03-06 10:41:40 +01:00
ruff Fallback to requires-python in certain cases when target-version is not found (#16721) 2025-03-14 09:36:51 +01:00
ruff_annotate_snippets Update pre-commit dependencies (#16465) 2025-03-03 13:10:46 +05:30
ruff_benchmark [red-knot] Handle gradual intersection types in assignability (#16611) 2025-03-11 07:58:56 -07:00
ruff_cache Fix cache key collisions for paths with separators (#12159) 2024-07-03 07:36:46 -05:00
ruff_db Add OsSystem support to mdtests (#16518) 2025-03-06 10:41:40 +01:00
ruff_dev Pass ParserOptions to the parser (#16220) 2025-02-19 10:50:50 -05:00
ruff_diagnostics Show errors for attempted fixes only when passed --verbose (#15237) 2025-01-03 08:50:13 -06:00
ruff_formatter bump MSRV to 1.83 (#16294) 2025-02-26 06:12:43 -08:00
ruff_graph Pass ParserOptions to the parser (#16220) 2025-02-19 10:50:50 -05:00
ruff_index [red-knot] Don't use separate ID types for each alist (#16415) 2025-02-28 14:55:55 -05:00
ruff_linter [pygrep-hooks]: Detect file-level suppressions comments without rul… (#16720) 2025-03-14 09:37:16 +01:00
ruff_macros Add knot.toml schema (#15735) 2025-02-07 10:59:40 +01:00
ruff_notebook bump MSRV to 1.83 (#16294) 2025-02-26 06:12:43 -08:00
ruff_python_ast [red-knot] Auto generate statement nodes (#16645) 2025-03-13 15:43:48 +01:00
ruff_python_ast_integration_tests Pass ParserOptions to the parser (#16220) 2025-02-19 10:50:50 -05:00
ruff_python_codegen Pass ParserOptions to the parser (#16220) 2025-02-19 10:50:50 -05:00
ruff_python_formatter [formatter] Stabilize fix for single-with-item formatting with trailing comment (#16603) 2025-03-13 15:37:37 +01:00
ruff_python_index Extract LineIndex independent methods from Locator (#13938) 2024-10-28 07:53:41 +00:00
ruff_python_literal Preserve triple quotes and prefixes for strings (#15818) 2025-02-04 08:41:06 -05:00
ruff_python_parser [syntax-errors] Tuple unpacking in for statement iterator clause before Python 3.9 (#16558) 2025-03-13 15:55:17 -04:00
ruff_python_resolver bump MSRV to 1.83 (#16294) 2025-02-26 06:12:43 -08:00
ruff_python_semantic Consider all TYPE_CHECKING symbols for type-checking blocks (#16669) 2025-03-13 15:37:37 +01:00
ruff_python_stdlib Revert "Add all PEP-585 names to UP006 rule" (#15250) 2025-01-04 12:23:53 +01:00
ruff_python_trivia [red-knot] Ignore surrounding whitespace when looking for <!-- snapshot-diagnostics --> directives in mdtests (#16380) 2025-02-27 13:25:31 +00:00
ruff_python_trivia_integration_tests Pass ParserOptions to the parser (#16220) 2025-02-19 10:50:50 -05:00
ruff_server Fallback to requires-python in certain cases when target-version is not found (#16721) 2025-03-14 09:36:51 +01:00
ruff_source_file [pyupgrade] Do not report when a UTF-8 comment is followed by a non-UTF-8 one (UP009) (#14728) 2024-12-11 10:30:41 +00:00
ruff_text_size [ruff] itertools.starmap(..., zip(...)) (RUF058) (#15483) 2025-01-16 15:18:12 +01:00
ruff_wasm Ruff v0.10 Release (#16708) 2025-03-13 13:53:11 -04:00
ruff_workspace Fallback to requires-python in certain cases when target-version is not found (#16721) 2025-03-14 09:36:51 +01:00