Skip to content

Commit 6a5b8e2

Browse files
committed
Fixed literal quotes being stripped from Union[Literal[...],]
Fixes #372.
1 parent 2a5ef72 commit 6a5b8e2

File tree

4 files changed

+24
-1
lines changed

4 files changed

+24
-1
lines changed

docs/versionhistory.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ Version history
33

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

6+
**UNRELEASED**
7+
8+
- Fixed regression where ``Literal`` inside a ``Union`` had quotes stripped from its
9+
contents, thus typically causing ``NameError`` to be raised when run
10+
(`#372 <https://github.com/agronholm/typeguard/issues/372>`_)
11+
612
**4.0.1** (2023-07-27)
713

814
- Fixed handling of ``typing_extensions.Literal`` on Python 3.8 and 3.9 when

src/typeguard/_transformer.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,12 @@ def visit(self, node: AST) -> Any:
363363

364364
return new_node
365365

366+
def generic_visit(self, node: AST) -> AST:
367+
if isinstance(node, expr) and self._memo.name_matches(node, *literal_names):
368+
return node
369+
370+
return super().generic_visit(node)
371+
366372
def visit_BinOp(self, node: BinOp) -> Any:
367373
self.generic_visit(node)
368374

@@ -395,7 +401,7 @@ def visit_Subscript(self, node: Subscript) -> Any:
395401

396402
# The subscript of typing(_extensions).Literal can be any arbitrary string, so
397403
# don't try to evaluate it as code
398-
if not self._memo.name_matches(node.value, *literal_names) and node.slice:
404+
if node.slice:
399405
if isinstance(node.slice, Index):
400406
# Python 3.7 and 3.8
401407
slice_value = node.slice.value # type: ignore[attr-defined]

tests/dummymodule.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,12 @@ def literal(x: Literal["foo"]) -> Literal["foo"]:
333333
return y
334334

335335

336+
@typechecked
337+
def literal_in_union(x: Union[Literal["foo"],]) -> Literal["foo"]:
338+
y: Literal["foo"] = x
339+
return y
340+
341+
336342
@typechecked
337343
def typevar_forwardref(x: Type[T]) -> T:
338344
return x()

tests/test_instrumentation.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,11 @@ def test_literal(dummymodule):
324324
assert dummymodule.literal("foo") == "foo"
325325

326326

327+
def test_literal_in_union(dummymodule):
328+
"""Regression test for #372."""
329+
assert dummymodule.literal_in_union("foo") == "foo"
330+
331+
327332
def test_typevar_forwardref(dummymodule):
328333
instance = dummymodule.typevar_forwardref(dummymodule.DummyClass)
329334
assert isinstance(instance, dummymodule.DummyClass)

0 commit comments

Comments
 (0)