Skip to content

Commit

Permalink
Skip type checks where the type names are shadowed by local variables
Browse files Browse the repository at this point in the history
  • Loading branch information
agronholm committed Apr 30, 2023
1 parent 0b704df commit e688da2
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/versionhistory.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ This library adheres to `Semantic Versioning 2.0 <https://semver.org/#semantic-v
**UNRELEASED**

- Added ``InstrumentationWarning`` to the public API
- Avoid type checks where the types in question are shadowed by local variables
- Fixed instrumentation using ``typing.Optional`` without a subscript when the subscript
value was erased due to being an ignored import
- Fixed ``TypeError: isinstance() arg 2 must be a type or tuple of types`` when
Expand Down
4 changes: 4 additions & 0 deletions src/typeguard/_transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -947,6 +947,7 @@ def visit_AnnAssign(self, node: AnnAssign) -> Any:
and node.annotation
and isinstance(node.target, Name)
):
self._memo.ignored_names.add(node.target.id)
annotation = self._convert_annotation(deepcopy(node.annotation))
if annotation:
self._memo.variable_annotations[node.target.id] = annotation
Expand Down Expand Up @@ -996,6 +997,7 @@ def visit_Assign(self, node: Assign) -> Any:
prefix = "*"

if isinstance(exp, Name):
self._memo.ignored_names.add(exp.id)
name = prefix + exp.id
annotation = self._memo.variable_annotations.get(exp.id)
if annotation:
Expand Down Expand Up @@ -1055,6 +1057,8 @@ def visit_NamedExpr(self, node: NamedExpr) -> Any:
if isinstance(self._memo.node, (FunctionDef, AsyncFunctionDef)) and isinstance(
node.target, Name
):
self._memo.ignored_names.add(node.target.id)

# Bail out if no matching annotation is found
annotation = self._memo.variable_annotations.get(node.target.id)
if annotation is None:
Expand Down
79 changes: 79 additions & 0 deletions tests/test_transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -1377,3 +1377,82 @@ def foo(x: kwargs, /, y: args, *args: x, baz: x, **kwargs: y) -> \
"""
).strip()
)


def test_local_assignment_typename_conflicts() -> None:
node = parse(
dedent(
"""
def foo() -> int:
int = 6
return int
"""
)
)
TypeguardTransformer().visit(node)
assert (
unparse(node)
== dedent(
"""
def foo() -> int:
int = 6
return int
"""
).strip()
)


def test_local_ann_assignment_typename_conflicts() -> None:
node = parse(
dedent(
"""
from typing import Any
def foo() -> int:
int: Any = 6
return int
"""
)
)
TypeguardTransformer().visit(node)
assert (
unparse(node)
== dedent(
"""
from typing import Any
def foo() -> int:
int: Any = 6
return int
"""
).strip()
)


def test_local_named_expr_typename_conflicts() -> None:
node = parse(
dedent(
"""
from typing import Any
def foo() -> int:
if (int := 6):
pass
return int
"""
)
)
TypeguardTransformer().visit(node)
assert (
unparse(node)
== dedent(
"""
from typing import Any
def foo() -> int:
if (int := 6):
pass
return int
"""
).strip()
)

0 comments on commit e688da2

Please sign in to comment.