Skip to content

Commit

Permalink
Fix: Added support for typing.Mutable* and more
Browse files Browse the repository at this point in the history
  • Loading branch information
erezsh committed Sep 12, 2023
1 parent 49b4abf commit 8700a4b
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 0 deletions.
24 changes: 24 additions & 0 deletions runtype/pytypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,10 +298,13 @@ def __repr__(self):
Iter = SequenceType(PythonDataType(collections.abc.Iterable))
List = SequenceType(PythonDataType(list))
Sequence = SequenceType(PythonDataType(abc.Sequence))
MutableSequece = SequenceType(PythonDataType(abc.MutableSequence))
Set = SequenceType(PythonDataType(set))
FrozenSet = SequenceType(PythonDataType(frozenset))
AbstractSet = SequenceType(PythonDataType(abc.Set))
Dict = DictType(PythonDataType(dict))
Mapping = DictType(PythonDataType(abc.Mapping))
MutableMapping = DictType(PythonDataType(abc.MutableMapping))
Tuple = TupleType()
TupleEllipsis = TupleEllipsisType(PythonDataType(tuple))
# Float = PythonDataType(float)
Expand Down Expand Up @@ -348,6 +351,11 @@ def __call__(self, min_length=None, max_length=None):

return Constraint(self, predicates)

def __le__(self, other):
if isinstance(other, SequenceType):
return self <= other.base and self <= other.item
return super().__le__(other)


class _DateTime(PythonDataType):
def cast_from(self, obj):
Expand Down Expand Up @@ -494,8 +502,12 @@ def _to_canon(self, t):
return Tuple
elif t is typing.Mapping: # 3.6
return Mapping
elif t is typing.MutableMapping:
return MutableMapping
elif t is typing.Sequence:
return Sequence
elif t is typing.MutableSequence:
return MutableSequece

if origin is None:
if isinstance(t, typing.TypeVar):
Expand Down Expand Up @@ -538,9 +550,21 @@ def _to_canon(self, t):
elif origin is abc.Mapping or origin is typing.Mapping:
k, v = args
return Mapping[to_canon(k), to_canon(v)]
elif origin is abc.MutableMapping or origin is typing.MutableMapping:
k, v = args
return MutableMapping[to_canon(k), to_canon(v)]
elif origin is abc.Sequence or origin is typing.Sequence:
x ,= args
return Sequence[to_canon(x)]
elif origin is abc.MutableSequence or origin is typing.MutableSequence:
x ,= args
return MutableSequece[to_canon(x)]
elif origin is abc.MutableSet or origin is typing.MutableSet:
x ,= args
return Set[to_canon(x)]
elif origin is abc.Set or origin is typing.AbstractSet:
x ,= args
return AbstractSet[to_canon(x)]
elif origin is type or origin is typing.Type:
# TODO test issubclass on t.__args__
return PythonDataType(type)
Expand Down
15 changes: 15 additions & 0 deletions tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,21 @@ def test_issubclass(self):
assert issubclass(typing.Tuple[int], typing.Tuple[typing.Union[int, str]])
assert issubclass(typing.Tuple[int, ...], typing.Tuple[typing.Union[int, str], ...])

def test_issubclass_mutable(self):
assert issubclass(typing.Dict[int, str], typing.MutableMapping[int, str])
assert issubclass(typing.Dict[int, str], typing.MutableMapping[int, str])

assert issubclass(typing.List[int], typing.MutableSequence[int])
assert issubclass(typing.MutableSequence[int], typing.Sequence[int])

assert issubclass(typing.Set[int], typing.MutableSet[int])
assert issubclass(typing.MutableSet[int], typing.AbstractSet[int])

def test_issubclass_str_sequence(self):
assert not issubclass(str, typing.MutableSequence[int])
assert not issubclass(str, typing.Sequence[int])
assert issubclass(str, typing.Sequence[str])

def test_issubclass_tuple(self):
# test class tuple
t = int, float
Expand Down

0 comments on commit 8700a4b

Please sign in to comment.