@@ -41,6 +41,10 @@ def isoftype(value, T):
4141 - `NewType` (any instance of the underlying actual type will match)
4242 - `Union[T1, T2, ..., TN]`
4343 - `Tuple`, `Tuple[T, ...]`, `Tuple[T1, T2, ..., TN]`
44+ - `List[T]`
45+ - `FrozenSet[T]`
46+ - `Set[T]`
47+ - `Dict[K, V]`
4448 - `Callable` (argument and return value types currently NOT checked)
4549 - `Text`
4650
@@ -87,9 +91,9 @@ def isoftype(value, T):
8791 return True
8892 return any (isoftype (value , U ) for U in T .__constraints__ )
8993
90- # TODO: List, Set, FrozenSet, Dict, NamedTuple
91- #
92- # TODO: Protocol, Type, Iterable, Iterator, Reversible, ...
94+ # TODO: NamedTuple
95+ # TODO: Deque
96+ # TODO: Protocol, Type, Iterable, Sequence, Iterator, Reversible, ...
9397 #
9498 # TODO: typing.Generic
9599 # TODO: Python 3.8 adds `typing.get_origin` and `typing.get_args`, which may be useful
@@ -122,6 +126,15 @@ def isoftype(value, T):
122126 if issubclass (T , typing .Text ): # https://docs.python.org/3/library/typing.html#typing.Text
123127 return isinstance (value , str ) # alias for str
124128
129+ if issubclass (T , typing .List ):
130+ if not isinstance (value , list ):
131+ return False
132+ if T .__args__ is None :
133+ raise TypeError ("Missing mandatory element type argument of `typing.List`" )
134+ assert len (T .__args__ ) == 1 # judging by the docs: https://docs.python.org/3/library/typing.html#typing.List
135+ U = T .__args__ [0 ]
136+ return all (isoftype (elt , U ) for elt in value )
137+
125138 if issubclass (T , typing .Tuple ):
126139 if not isinstance (value , tuple ):
127140 return False
@@ -141,6 +154,33 @@ def isoftype(value, T):
141154 return False
142155 return all (isoftype (elt , U ) for elt , U in zip (value , T .__args__ ))
143156
157+ if issubclass (T , typing .Set ):
158+ if not isinstance (value , set ):
159+ return False
160+ if T .__args__ is None :
161+ raise TypeError ("Missing mandatory element type argument of `typing.Set`" )
162+ assert len (T .__args__ ) == 1
163+ U = T .__args__ [0 ]
164+ return all (isoftype (elt , U ) for elt in value )
165+
166+ if issubclass (T , typing .FrozenSet ):
167+ if not isinstance (value , frozenset ):
168+ return False
169+ if T .__args__ is None :
170+ raise TypeError ("Missing mandatory element type argument of `typing.FrozenSet`" )
171+ assert len (T .__args__ ) == 1
172+ U = T .__args__ [0 ]
173+ return all (isoftype (elt , U ) for elt in value )
174+
175+ if issubclass (T , typing .Dict ):
176+ if not isinstance (value , dict ):
177+ return False
178+ if T .__args__ is None :
179+ raise TypeError ("Missing mandatory key, value type arguments of `typing.Dict`" )
180+ assert len (T .__args__ ) == 2
181+ K , V = T .__args__
182+ return all (isoftype (k , K ) and isoftype (v , V ) for k , v in value .items ())
183+
144184 if issubclass (T , typing .Callable ):
145185 if not callable (value ):
146186 return False
0 commit comments