Skip to content

Commit

Permalink
Fix possibly_undefined_name on use of the walrus operator (#749)
Browse files Browse the repository at this point in the history
A suspiciously simple fix but I think it's correct.
  • Loading branch information
JelleZijlstra authored Mar 11, 2024
1 parent 0977bb7 commit 2b0e6c1
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 2 deletions.
2 changes: 2 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

- Fix incorrect `possibly_undefined_name` error on certain uses of the
walrus operator (#749)
- Fix narrowing on `isinstance` calls with arguments that are not
instance of `typing`, such as unions and certain typing special forms (#747)
- Detect invalid calls to `isinstance` (#747)
Expand Down
4 changes: 3 additions & 1 deletion pyanalyze/stacked_scopes.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,9 @@ def apply_to_value(self, value: Value) -> Iterable[Value]:
"""
inner_value = value.value if isinstance(value, AnnotatedValue) else value
if inner_value is UNINITIALIZED_VALUE:
yield UNINITIALIZED_VALUE
# If a constraint applies to a value, it must have been initialized,
# or at least we must have already tried to read it and gotten a
# possibly_undefined_name error.
return
if self.constraint_type == ConstraintType.is_instance:
if isinstance(inner_value, AnyValue):
Expand Down
11 changes: 11 additions & 0 deletions pyanalyze/test_name_check_visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2050,6 +2050,17 @@ def func(myvar: str, strset: Set[str]) -> None:
"""
)

@assert_passes()
def test_and_then_walrus(self):
from typing_extensions import Literal, assert_type

def capybara(cond):
if cond and (x := 1):
assert_type(x, Literal[1])
else:
print(x) # E: possibly_undefined_name
print(x) # E: possibly_undefined_name

def test_if_exp(self):
self.assert_passes(
"""
Expand Down
13 changes: 12 additions & 1 deletion pyanalyze/test_stacked_scopes.py
Original file line number Diff line number Diff line change
Expand Up @@ -818,7 +818,7 @@ def capybara(cond):
else:
pass

return x # static analysis: ignore[possibly_undefined_name]
return x # E: possibly_undefined_name

def kerodon():
# make sure we don't propagate the UNINITIALIZED_VALUE from
Expand Down Expand Up @@ -1705,6 +1705,17 @@ def agouti(x: Annotated[Optional[str], 1]) -> None:
else:
assert_is_value(x, AnnotatedValue(KnownValue(None), [KnownValue(1)]))

@assert_passes()
def test_possibly_undefined(self):
from typing_extensions import Literal, assert_type

def capybara(cond):
if cond:
x = 1

if x: # E: possibly_undefined_name
assert_type(x, Literal[1])


class TestComposite(TestNameCheckVisitorBase):
@assert_passes()
Expand Down

0 comments on commit 2b0e6c1

Please sign in to comment.