mirror of
https://github.com/zhigang1992/mitmproxy.git
synced 2026-04-01 12:53:25 +08:00
81 lines
2.3 KiB
Python
81 lines
2.3 KiB
Python
import typing
|
|
|
|
|
|
def check_type(attr_name: str, value: typing.Any, typeinfo: type) -> None:
|
|
"""
|
|
This function checks if the provided value is an instance of typeinfo
|
|
and raises a TypeError otherwise.
|
|
|
|
The following types from the typing package have specialized support:
|
|
|
|
- Union
|
|
- Tuple
|
|
- IO
|
|
"""
|
|
# If we realize that we need to extend this list substantially, it may make sense
|
|
# to use typeguard for this, but right now it's not worth the hassle for 16 lines of code.
|
|
|
|
e = TypeError("Expected {} for {}, but got {}.".format(
|
|
typeinfo,
|
|
attr_name,
|
|
type(value)
|
|
))
|
|
|
|
typename = str(typeinfo)
|
|
|
|
if typename.startswith("typing.Union"):
|
|
try:
|
|
types = typeinfo.__args__
|
|
except AttributeError:
|
|
# Python 3.5.x
|
|
types = typeinfo.__union_params__
|
|
|
|
for T in types:
|
|
try:
|
|
check_type(attr_name, value, T)
|
|
except TypeError:
|
|
pass
|
|
else:
|
|
return
|
|
raise e
|
|
elif typename.startswith("typing.Tuple"):
|
|
try:
|
|
types = typeinfo.__args__
|
|
except AttributeError:
|
|
# Python 3.5.x
|
|
types = typeinfo.__tuple_params__
|
|
|
|
if not isinstance(value, (tuple, list)):
|
|
raise e
|
|
if len(types) != len(value):
|
|
raise e
|
|
for i, (x, T) in enumerate(zip(value, types)):
|
|
check_type("{}[{}]".format(attr_name, i), x, T)
|
|
return
|
|
elif typename.startswith("typing.Sequence"):
|
|
try:
|
|
T = typeinfo.__args__[0]
|
|
except AttributeError:
|
|
# Python 3.5.0
|
|
T = typeinfo.__parameters__[0]
|
|
if not isinstance(value, (tuple, list)):
|
|
raise e
|
|
for v in value:
|
|
check_type(attr_name, v, T)
|
|
elif typename.startswith("typing.IO"):
|
|
if hasattr(value, "read"):
|
|
return
|
|
else:
|
|
raise e
|
|
elif not isinstance(value, typeinfo):
|
|
raise e
|
|
|
|
|
|
def get_arg_type_from_constructor_annotation(cls: type, attr: str) -> typing.Optional[type]:
|
|
"""
|
|
Returns the first type annotation for attr in the class hierarchy.
|
|
"""
|
|
for c in cls.mro():
|
|
if attr in getattr(c.__init__, "__annotations__", ()):
|
|
return c.__init__.__annotations__[attr]
|