Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions crates/ty_python_semantic/resources/mdtest/attributes.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,28 @@ class C:
reveal_type(C().w) # revealed: Unknown | Weird
```

#### Nested augmented assignments after narrowing
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think it would be great to add a line or two of prose here to describe what it is that this is testing. What was the ecosystem regression here that led to you adding this test?


```py
from unknown_module import unknown # error: [unresolved-import]

class Inner:
value: int = 0

class Outer:
def __init__(self) -> None:
self.inner = None
self.load()

def load(self) -> None:
self.inner = Inner() if unknown else unknown

def update(self) -> None:
if self.inner is None:
return
self.inner.value += unknown
```

#### Attributes defined in tuple unpackings

```py
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,11 +261,15 @@ class C(metaclass=Meta):
C.META_FINAL_A = 2
# error: [invalid-assignment] "Cannot assign to final attribute `META_FINAL_B` on type `<class 'C'>`"
C.META_FINAL_B = 2
# error: [invalid-assignment] "Cannot assign to final attribute `META_FINAL_A` on type `<class 'C'>`"
C.META_FINAL_A += 1

# error: [invalid-assignment] "Cannot assign to final attribute `CLASS_FINAL_A` on type `<class 'C'>`"
C.CLASS_FINAL_A = 2
# error: [invalid-assignment] "Cannot assign to final attribute `CLASS_FINAL_B` on type `<class 'C'>`"
C.CLASS_FINAL_B = 2
# error: [invalid-assignment] "Cannot assign to final attribute `CLASS_FINAL_A` on type `<class 'C'>`"
C.CLASS_FINAL_A += 1

c = C()
# error: [invalid-assignment] "Cannot assign to final attribute `CLASS_FINAL_A` on type `C`"
Expand All @@ -278,6 +282,8 @@ c.INSTANCE_FINAL_A = 2
c.INSTANCE_FINAL_B = 2
# error: [invalid-assignment] "Cannot assign to final attribute `INSTANCE_FINAL_C` on type `C`"
c.INSTANCE_FINAL_C = 2
# error: [invalid-assignment] "Cannot assign to final attribute `INSTANCE_FINAL_A` on type `C`"
c.INSTANCE_FINAL_A += 1
```

## Mutability
Expand Down Expand Up @@ -624,7 +630,7 @@ from typing import Final

class C:
def some_method(self):
# TODO: This should be an error
# error: [invalid-assignment]
self.x: Final[int] = 1
```

Expand Down Expand Up @@ -889,7 +895,7 @@ python-version = "3.11"
```

```py
from typing import Final, Self
from typing import Final, Generic, Self, TypeVar

class ClassA:
ID4: Final[int] # OK because initialized in __init__
Expand All @@ -907,8 +913,17 @@ class ClassB:
def __init__(self): # Without Self annotation
self.ID5 = 1 # Should also be OK

T = TypeVar("T")

class ClassC(Generic[T]):
value: Final[T]

def __init__(self: Self, value: T):
self.value = value

reveal_type(ClassA().ID4) # revealed: int
reveal_type(ClassB().ID5) # revealed: int
reveal_type(ClassC(1).value) # revealed: int
```

## Reassignment to Final in `__init__`
Expand Down
11 changes: 4 additions & 7 deletions crates/ty_python_semantic/src/types/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1452,16 +1452,13 @@ fn is_instance_truthiness<'db>(
class: ClassLiteral<'db>,
) -> Truthiness {
let is_instance = |ty: &Type<'_>| {
if let Type::NominalInstance(instance) = ty
&& instance
ty.as_nominal_instance().is_some_and(|instance| {
instance
.class(db)
.iter_mro(db)
.filter_map(ClassBase::into_class)
.any(|c| c.class_literal(db) == class)
{
return true;
}
false
.any(|mro_class| mro_class.class_literal(db) == class)
})
};

let always_true_if = |test: bool| {
Expand Down
Loading