Skip to content

Commit

Permalink
Fixed Optional without subscript being used for type checks
Browse files Browse the repository at this point in the history
Fixes #342.
  • Loading branch information
agronholm committed Apr 22, 2023
1 parent 5f2583b commit f2d0c9d
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 2 deletions.
5 changes: 5 additions & 0 deletions docs/versionhistory.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ Version history

This library adheres to `Semantic Versioning 2.0 <https://semver.org/#semantic-versioning-200>`_.

**UNRELEASED**

- Fixed instrumentation using ``typing.Optional`` without a subscript when the subscript
value was erased due to being an ignored import

**4.0.0rc4** (2023-04-15)

- Fixed imports guarded by ``if TYPE_CHECKING:`` when used with subscripts
Expand Down
7 changes: 5 additions & 2 deletions src/typeguard/_transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,8 +410,11 @@ def visit_Subscript(self, node: Subscript) -> Any:
self.generic_visit(node)

# If the transformer erased the slice entirely, just return the node
# value without the subscript
if sys.version_info >= (3, 9) and not hasattr(node, "slice"):
# value without the subscript (unless it's Optional, in which case erase
# the node entirely
if self._memo.name_matches(node.value, "typing.Optional"):
return None
elif sys.version_info >= (3, 9) and not hasattr(node, "slice"):
return node.value
elif sys.version_info < (3, 9) and not hasattr(node.slice, "value"):
return node.value
Expand Down
30 changes: 30 additions & 0 deletions tests/test_transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,36 @@ def foo(x: Hashable, y: typing.Collection) -> Generator[Hashable, \
).strip()
)

def test_optional(self) -> None:
node = parse(
dedent(
"""
from typing import Any, Optional, TYPE_CHECKING
from collections.abc import Generator
if TYPE_CHECKING:
from typing import Hashable
def foo(x: Optional[Hashable]) -> Optional[Hashable]:
return x
"""
)
)
TypeguardTransformer().visit(node)
assert (
unparse(node)
== dedent(
"""
from typing import Any, Optional, TYPE_CHECKING
from collections.abc import Generator
if TYPE_CHECKING:
from typing import Hashable
def foo(x: Optional[Hashable]) -> Optional[Hashable]:
return x
"""
).strip()
)


class TestAssign:
def test_annotated_assign(self) -> None:
Expand Down

0 comments on commit f2d0c9d

Please sign in to comment.