Skip to content

Commit

Permalink
Added support for type checking AbstractSet
Browse files Browse the repository at this point in the history
Fixes #13.
  • Loading branch information
agronholm committed Nov 27, 2019
1 parent a00f03e commit 096fafe
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 20 deletions.
32 changes: 16 additions & 16 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -194,22 +194,22 @@ Supported typing.* types

The following types from the ``typing`` package have specialized support:

============== ============================================================
Type Notes
============== ============================================================
``Callable`` Argument count is checked but types are not (yet)
``Dict`` Keys and values are typechecked
``List`` Contents are typechecked
=============== =============================================================
Type Notes
=============== =============================================================
``AbstractSet`` Contents are typechecked
``Callable`` Argument count is checked but types are not (yet)
``Dict`` Keys and values are typechecked
``List`` Contents are typechecked
``Literal``
``NamedTuple`` Field values are typechecked
``Protocol`` Value type checked with ``issubclass()`` against the
protocol
``Set`` Contents are typechecked
``Sequence`` Contents are typechecked
``Tuple`` Contents are typechecked
``NamedTuple`` Field values are typechecked
``Protocol`` Value type checked with ``issubclass()`` against the protocol
``Set`` Contents are typechecked
``Sequence`` Contents are typechecked
``Tuple`` Contents are typechecked
``Type``
``TypedDict`` Contents are typechecked
``TypeVar`` Constraints, bound types and co/contravariance are supported
but custom generic types are not (due to type erasure)
``TypedDict`` Contents are typechecked
``TypeVar`` Constraints, bound types and co/contravariance are supported
but custom generic types are not (due to type erasure)
``Union``
============== ============================================================
=============== =============================================================
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 support for ``typing.Protocol`` subclasses
- Added support for ``typing.AbstractSet``
- Fixed the handling of ``total=False`` in ``TypedDict``
- Removed support of default values in ``TypedDict``, as they are not supported in the spec

Expand Down
40 changes: 37 additions & 3 deletions tests/test_typeguard.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from io import StringIO, BytesIO
from typing import (
Any, Callable, Dict, List, Set, Tuple, Union, TypeVar, Sequence, NamedTuple, Iterable,
Container, Generic, BinaryIO, TextIO, Generator, Iterator, SupportsInt)
Container, Generic, BinaryIO, TextIO, Generator, Iterator, SupportsInt, AbstractSet)

import pytest

Expand Down Expand Up @@ -275,13 +275,44 @@ def foo(a: Sequence[int]):
assert str(exc.value) == (
'type of argument "a"[2] must be int; got str instead')

def test_abstractset_custom_type(self):
class DummySet(AbstractSet[int]):
def __contains__(self, x: object) -> bool:
return x == 1

def __len__(self) -> int:
return 1

def __iter__(self) -> Iterator[int]:
yield 1

def foo(a: AbstractSet[int]):
assert check_argument_types()

foo(DummySet())

def test_abstractset_bad_type(self):
def foo(a: AbstractSet[int]):
assert check_argument_types()

exc = pytest.raises(TypeError, foo, 5)
assert str(exc.value) == 'type of argument "a" must be a set; got int instead'

def test_set_bad_type(self):
def foo(a: Set[int]):
assert check_argument_types()

exc = pytest.raises(TypeError, foo, 5)
assert str(exc.value) == 'type of argument "a" must be a set; got int instead'

def test_abstractset_bad_element(self):
def foo(a: AbstractSet[int]):
assert check_argument_types()

exc = pytest.raises(TypeError, foo, {1, 2, 'bb'})
assert str(exc.value) == (
'type of elements of argument "a" must be int; got str instead')

def test_set_bad_element(self):
def foo(a: Set[int]):
assert check_argument_types()
Expand Down Expand Up @@ -734,8 +765,9 @@ def foo(a: typehint):
(List, ['x', 6]),
(Sequence, ['x', 6]),
(Set, {'x', 6}),
(AbstractSet, {'x', 6}),
(Tuple, ('x', 6)),
], ids=['dict', 'list', 'sequence', 'set', 'tuple'])
], ids=['dict', 'list', 'sequence', 'set', 'abstractset', 'tuple'])
def test_unparametrized_types_mixed_values(self, typehint, value):
@typechecked
def foo(a: typehint):
Expand Down Expand Up @@ -783,10 +815,12 @@ def foo(a: typehint):
foo(value)

@pytest.mark.parametrize('typehint', [
AbstractSet[int],
AbstractSet,
Set[int],
Set,
set
], ids=['parametrized', 'unparametrized', 'plain'])
], ids=['abstract_parametrized', 'abstract', 'parametrized', 'unparametrized', 'plain'])
@pytest.mark.parametrize('value', [set(), {6}])
def test_set(self, typehint, value):
@typechecked
Expand Down
3 changes: 2 additions & 1 deletion typeguard/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from typing import (
Callable, Any, Union, Dict, List, TypeVar, Tuple, Set, Sequence, get_type_hints, TextIO,
Optional, IO, BinaryIO, Type, Generator, overload, Iterable, AsyncIterable, Iterator,
AsyncIterator)
AsyncIterator, AbstractSet)
from warnings import warn
from weakref import WeakKeyDictionary, WeakValueDictionary

Expand Down Expand Up @@ -494,6 +494,7 @@ def check_protocol(argname: str, value, expected_type):

# Equality checks are applied to these
origin_type_checkers = {
AbstractSet: check_set,
Callable: check_callable,
collections.abc.Callable: check_callable,
dict: check_dict,
Expand Down

0 comments on commit 096fafe

Please sign in to comment.