Skip to content

Commit 3d9404a

Browse files
MeGaGiGaGonthejchap
authored andcommitted
[pyupgrade] Make example error out-of-the-box (UP040) (#19296)
<!-- Thank you for contributing to Ruff/ty! To help us out with reviewing, please consider the following: - Does this pull request include a summary of the change? (See below.) - Does this pull request include a descriptive title? (Please prefix with `[ty]` for ty pull requests.) - Does this pull request include references to any relevant issues? --> ## Summary <!-- What's the purpose of the change? What does it do, and why? --> Part of #18972 This PR makes [non-pep695-type-alias (UP040)](https://docs.astral.sh/ruff/rules/non-pep695-type-alias/#non-pep695-type-alias-up040)'s example error out-of-the-box. [Old example](https://play.ruff.rs/6beca1be-45cd-4e5a-aafa-6a0584c10d64) ```py ListOfInt: TypeAlias = list[int] PositiveInt = TypeAliasType("PositiveInt", Annotated[int, Gt(0)]) ``` [New example](https://play.ruff.rs/bbad34da-bf07-44e6-9f34-53337e8f57d4) ```py from typing import Annotated, TypeAlias, TypeAliasType from annotated_types import Gt ListOfInt: TypeAlias = list[int] PositiveInt = TypeAliasType("PositiveInt", Annotated[int, Gt(0)]) ``` Imports were also added to the "Use instead" section. ## Test Plan <!-- How was it tested? --> N/A, no functionality/tests affected
1 parent 4bc2713 commit 3d9404a

File tree

3 files changed

+58
-1
lines changed

3 files changed

+58
-1
lines changed

crates/ruff_linter/src/rules/pyupgrade/rules/pep695/non_pep695_type_alias.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,18 @@ use super::{
4040
///
4141
/// ## Example
4242
/// ```python
43+
/// from typing import Annotated, TypeAlias, TypeAliasType
44+
/// from annotated_types import Gt
45+
///
4346
/// ListOfInt: TypeAlias = list[int]
4447
/// PositiveInt = TypeAliasType("PositiveInt", Annotated[int, Gt(0)])
4548
/// ```
4649
///
4750
/// Use instead:
4851
/// ```python
52+
/// from typing import Annotated
53+
/// from annotated_types import Gt
54+
///
4955
/// type ListOfInt = list[int]
5056
/// type PositiveInt = Annotated[int, Gt(0)]
5157
/// ```

crates/ty_python_semantic/resources/mdtest/dataclasses/dataclasses.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,39 @@ from dataclasses import dataclass
425425
class MyFrozenClass: ...
426426

427427
frozen = MyFrozenClass()
428-
frozen.x = 2 # error: [unresolved-attribute]
428+
frozen.x = 2 # error: [invalid-assignment]
429+
```
430+
431+
A diagnostic is also emitted if a frozen dataclass is inherited, and an attempt is made to mutate an
432+
attribute in the child class:
433+
434+
```py
435+
from dataclasses import dataclass
436+
437+
@dataclass(frozen=True)
438+
class MyFrozenClass:
439+
x: int = 1
440+
441+
class MyFrozenChildClass(MyFrozenClass): ...
442+
443+
frozen = MyFrozenChildClass()
444+
frozen.x = 2 # error: [invalid-assignment]
445+
```
446+
447+
The same diagnostic is emitted if a frozen dataclass is inherited, and an attempt is made to delete
448+
an attribute:
449+
450+
```py
451+
from dataclasses import dataclass
452+
453+
@dataclass(frozen=True)
454+
class MyFrozenClass:
455+
x: int = 1
456+
457+
class MyFrozenChildClass(MyFrozenClass): ...
458+
459+
frozen = MyFrozenChildClass()
460+
del frozen.x # TODO this should emit an [invalid-assignment]
429461
```
430462

431463
### `match_args`

crates/ty_python_semantic/src/types/class.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,6 +1589,25 @@ impl<'db> ClassLiteral<'db> {
15891589
.place
15901590
.ignore_possibly_unbound()
15911591
}
1592+
(CodeGeneratorKind::DataclassLike, "__setattr__") => {
1593+
if has_dataclass_param(DataclassParams::FROZEN) {
1594+
let signature = Signature::new(
1595+
Parameters::new([
1596+
Parameter::positional_or_keyword(Name::new_static("self"))
1597+
.with_annotated_type(Type::instance(
1598+
db,
1599+
self.apply_optional_specialization(db, specialization),
1600+
)),
1601+
Parameter::positional_or_keyword(Name::new_static("name")),
1602+
Parameter::positional_or_keyword(Name::new_static("value")),
1603+
]),
1604+
Some(Type::Never),
1605+
);
1606+
1607+
return Some(CallableType::function_like(db, signature));
1608+
}
1609+
None
1610+
}
15921611
_ => None,
15931612
}
15941613
}

0 commit comments

Comments
 (0)