Skip to content

Commit

Permalink
Fixed checking against bound type variables with check_type() without…
Browse files Browse the repository at this point in the history
… a call memo

Fixes #122.
  • Loading branch information
agronholm committed Jun 2, 2020
1 parent 35aced3 commit f8f7fd8
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 5 deletions.
1 change: 1 addition & 0 deletions docs/versionhistory.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ This library adheres to `Semantic Versioning 2.0 <https://semver.org/#semantic-v
- Added support for the ``Mock`` and ``MagicMock`` types (PR by prescod)
- Added support for ``typing_extensions.Literal`` (PR by Ryan Rowe)
- Fixed unintended wrapping of untyped generators (PR by prescod)
- Fixed checking against bound type variables with ``check_type()`` without a call memo

**2.7.1** (2019-12-27)

Expand Down
12 changes: 11 additions & 1 deletion tests/test_typeguard.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from unittest.mock import Mock, MagicMock
from typing import (
Any, Callable, Dict, List, Set, Tuple, Union, TypeVar, Sequence, NamedTuple, Iterable,
Container, Generic, BinaryIO, TextIO, Generator, Iterator, SupportsInt, AbstractSet)
Container, Generic, BinaryIO, TextIO, Generator, Iterator, SupportsInt, AbstractSet, AnyStr)

import pytest

Expand Down Expand Up @@ -66,6 +66,16 @@ def test_check_type_no_memo_fail():
match(r'type of foo\[0\] must be int; got str instead')


@pytest.mark.parametrize('value', ['bar', b'bar'], ids=['str', 'bytes'])
def test_check_type_anystr(value):
check_type('foo', value, AnyStr)


def test_check_type_anystr_fail():
pytest.raises(TypeError, check_type, 'foo', int, AnyStr).\
match(r'type of foo must be one of \(bytes, str\); got type instead')


def test_check_return_type():
def foo() -> int:
assert check_return_type(0)
Expand Down
8 changes: 4 additions & 4 deletions typeguard/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -433,10 +433,10 @@ def check_class(argname: str, value, expected_type, memo: Optional[_CallMemo]) -

def check_typevar(argname: str, value, typevar: TypeVar, memo: Optional[_CallMemo],
subclass_check: bool = False) -> None:
if memo is None:
raise TypeError('encountered a TypeVar but a call memo was not provided')
bound_type = None
if memo is not None:
bound_type = resolve_forwardref(memo.typevars.get(typevar, typevar.__bound__), memo)

bound_type = resolve_forwardref(memo.typevars.get(typevar, typevar.__bound__), memo)
value_type = value if subclass_check else type(value)
subject = argname if subclass_check else 'type of ' + argname
if bound_type is None:
Expand Down Expand Up @@ -464,7 +464,7 @@ def check_typevar(argname: str, value, typevar: TypeVar, memo: Optional[_CallMem
'{} must be exactly {}; got {} instead'.
format(subject, qualified_name(bound_type), qualified_name(value_type)))

if typevar not in memo.typevars:
if memo is not None and typevar not in memo.typevars:
# Bind the type variable to a concrete type
memo.typevars[typevar] = value_type

Expand Down

0 comments on commit f8f7fd8

Please sign in to comment.