Skip to content

Commit

Permalink
Avoid false positives on generic aliases with nested classes (#624)
Browse files Browse the repository at this point in the history
  • Loading branch information
JelleZijlstra authored May 12, 2023
1 parent dfd534c commit 36ef3d2
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 0 deletions.
5 changes: 5 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## Unreleased

- Fix false positive error when annotations refer to classes defined
inside functions (#624)

## Version 0.10.0 (May 10, 2023)

- Infer the signature for built-in static methods, such as `dict.fromkeys` (#619)
Expand Down
18 changes: 18 additions & 0 deletions pyanalyze/name_check_visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,13 @@ class ExceptionGroup:
pass


try:
from types import GenericAlias
except ImportError:
# 3.8 and lower
GenericAlias = None


T = TypeVar("T")
U = TypeVar("U")
AwaitableValue = GenericValue(collections.abc.Awaitable, [TypeVarValue(T)])
Expand Down Expand Up @@ -4467,6 +4474,17 @@ def _composite_from_subscript_no_mvv(
return_value = self.check_call(
node.value, cgi, [index_composite], allow_call=True
)
# Special case to avoid "Unrecognized annotation types.GenericAlias" later;
# ideally we'd be more precise.
if GenericAlias is not None and return_value == TypedValue(
GenericAlias
):
return_value = self.check_call(
node.value,
cgi,
[Composite(KnownValue(Any))],
allow_call=True,
)

if (
self._should_use_varname_value(return_value)
Expand Down
13 changes: 13 additions & 0 deletions pyanalyze/test_annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,19 @@ def capybara(
),
)

@skip_before((3, 9))
@assert_passes()
def test_genericalias_nested_class(self):
def capybara():
class Base:
pass

class Child:
attrs: list[Base]

# Ideally should not be Any, but this is better than throwing a false positive error.
assert_is_value(Child().attrs, AnyValue(AnySource.from_another))


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

0 comments on commit 36ef3d2

Please sign in to comment.