我们从Python开源项目中,提取了以下21个代码示例,用于说明如何使用typing.get_type_hints()。
def _get_type_hints(func, args = None, res = None, infer_defaults = None): """Helper for get_type_hints. """ if args is None or res is None: args2, res2 = _get_types(func, util.is_classmethod(func), util.is_method(func), unspecified_type = type(NotImplemented), infer_defaults = infer_defaults) if args is None: args = args2 if res is None: res = res2 slf = 1 if util.is_method(func) else 0 argNames = util.getargnames(util.getargspecs(util._actualfunc(func))) result = {} if not args is Any: prms = get_Tuple_params(args) for i in range(slf, len(argNames)): if not prms[i-slf] is type(NotImplemented): result[argNames[i]] = prms[i-slf] result['return'] = res return result
def check_arguments(c: typing.Callable, hints: typing.Mapping[str, typing.Optional[type]], *args, **kwargs) -> None: """Check arguments type, raise :class:`TypeError` if argument type is not expected type. :param c: callable object want to check types :param hints: assumed type of given ``c`` result of :func:`typing.get_type_hints` """ signature = inspect.signature(c) bound = signature.bind(*args, **kwargs) for argument_name, value in bound.arguments.items(): try: type_hint = hints[argument_name] except KeyError: continue actual_type, correct = check_type(value, type_hint) if not correct: raise TypeError( 'Incorrect type `{}`, expected `{}` for `{}`'.format( actual_type, type_hint, argument_name ) )
def test_various(self): self.assertEqual(get_type_hints(testfunc), {'a': int, 'c': str, 'b': Real, 'return': Tuple[int, Real]}) self.assertEqual(pytypes.deep_type(('abc', [3, 'a', 7], 4.5)), Tuple[str, List[Union[int, str]], float]) tc2 = testClass2('bbb') self.assertEqual(pytypes.get_class_that_defined_method( tc2.testmeth2c), testClass2) self.assertEqual(pytypes.get_class_that_defined_method( testClass2.testmeth2c), testClass2) self.assertEqual(pytypes.get_class_that_defined_method( tc2.testmeth2b), testClass2) self.assertEqual(pytypes.get_class_that_defined_method( testClass2.testmeth2b), testClass2) self.assertEqual(pytypes.get_class_that_defined_method( tc2.testmeth3), testClass2) self.assertEqual(pytypes.get_class_that_defined_method( testClass2.testmeth3), testClass2) self.assertRaises(ValueError, lambda: pytypes.get_class_that_defined_method(testfunc)) # old-style: tc3 = testClass3() self.assertEqual(pytypes.get_class_that_defined_method( tc3.testmeth), testClass3) self.assertEqual(pytypes.get_class_that_defined_method( testClass3.testmeth), testClass3)
def test_method_forward_py3(self): tc = py3.testClass('ijkl2') tc2 = py3.testClass2('ijkl3') self.assertEqual(tc.testmeth_forward(5, tc2), 11) self.assertEqual(typing.get_type_hints(tc.testmeth_forward), get_type_hints(tc.testmeth_forward)) self.assertRaises(InputTypeError, lambda: tc.testmeth_forward(5, 7)) self.assertRaises(InputTypeError, lambda: tc.testmeth_forward(5, tc))
def test_various_py3(self): self.assertEqual(get_type_hints(testfunc), {'a': int, 'c': str, 'b': Real, 'return': Tuple[int, Real]}) self.assertEqual(pytypes.deep_type(('abc', [3, 'a', 7], 4.5)), Tuple[str, List[Union[int, str]], float])
def get_types(func): """Works like get_type_hints, but returns types as a sequence rather than a dictionary. Types are returned in declaration order of the corresponding arguments. """ return _get_types(func, util.is_classmethod(func), util.is_method(func))
def get_type_hints(func): """Resembles typing.get_type_hints, but is also workable on Python 2.7 and searches stubfiles for type information. Also on Python 3, this takes type comments (python.org/dev/peps/pep-0484/#suggested-syntax-for-python-2-7-and-straddling-code) into account if present. """ if not has_type_hints(func): # What about defaults? return {} return _get_type_hints(func)
def check_callable(callable_: typing.Callable, hint: type) -> bool: """Check argument type & return type of :class:`typing.Callable`. since it raises check :class:`typing.Callable` using `isinstance`, so compare in diffrent way :param callable_: callable object given as a argument :param hint: assumed type of given ``callable_`` """ if not callable(callable_): return type(callable_), False if callable(callable_) and not hasattr(callable_, '__code__'): return type(callable_), True hints = typing.get_type_hints(callable_) return_type = hints.pop('return', type(None)) signature = inspect.signature(callable_) arg_types = tuple( param.annotation for _, param in signature.parameters.items() ) correct = all({ any({ hint.__args__ is None, hint.__args__ is Ellipsis, hint.__args__ == arg_types, }), any({ hint.__result__ is None, hint.__result__ in (typing.Any, return_type) }) }) return typing.Callable[list(arg_types), return_type], correct
def typechecked(call_: typing.Callable[..., T]) -> T: """A decorator to make a callable object checks its types .. code-block:: python from typing import Callable @typechecked def foobar(x: str) -> bool: return x == 'hello world' @typechecked def hello_world(foo: str, bar: Callable[[str], bool]) -> bool: return bar(foo) hello_world('hello world', foobar) hello_world(3.14, foobar) # it raise TypeError :param c: callable object want to check types :type c: :class:`typing.Callable` :return: """ @functools.wraps(call_) def decorator(*args, **kwargs): hints = typing.get_type_hints(call_) check_arguments(call_, hints, *args, **kwargs) result = call_(*args, **kwargs) check_return(call_.__name__, result, hints) return result return decorator
def _get_type_hints(obj, globalns=None, localns=None): return getattr(obj, '__annotations__', {})
def __call__(self, function): if not self.shouldCheck: return function hints = get_type_hints(function) def precheck(*args, **kwargs): all_args = kwargs.copy() all_args.update(dict(zip(function.__code__.co_varnames, args))) for argument, argument_type in ((i, type(j)) for i, j in all_args.items()): if argument in hints: if not issubclass(argument_type, hints[argument]): raise TypeError('Type of {} is {} and not {}'. format(argument, argument_type, hints[argument])) def postcheck(result): if 'return' in hints: if not isinstance(result, hints['return']): raise TypeError('Type of result is {} and not {}'. format(type(result), hints['return'])) return result if inspect.iscoroutinefunction(function): async def type_checker(*args, **kwargs): precheck(*args, **kwargs) result = await function(*args, **kwargs) return postcheck(result) else: def type_checker(*args, **kwargs): precheck(*args, **kwargs) result = function(*args, **kwargs) return postcheck(result) return type_checker
def _get_func_type_annotations(func: Callable[..., Any], owner: type = None) -> Dict[str, type]: annotations = dict(get_type_hints(func)) dynamic_annotations = getattr(func, '__dynamic__', {}) for name, expression in dynamic_annotations.items(): if type(expression) == type: annotations[name] = expression elif callable(expression): annotations[name] = expression(owner) return annotations # TODO name arg for use with auto-generation
def get_type_hints(obj, # type: Any globalns=None, # type: Optional[Dict[str, Any]] localns=None # type: Optional[Dict[str, Any]] ): # type: (...) -> Dict[str, Any] """Return all type hints for the function. This attempts to use typing.get_type_hints first, but if that returns None then it will attempt to reuse much of the logic from the Python 3 version of typing.get_type_hints; the Python 2 version does nothing. In addition to this logic, if no code annotations exist, it will attempt to extract comment type hints for Python 2/3 compatibility. Args: obj: The object to search for type hints. globalns: The currently known global namespace. localns: The currently known local namespace. Returns: A mapping of value names to type hints. """ hints = {} try: if not isinstance(obj, type): hints = _get_type_hints(obj, globalns, localns) or {} except TypeError: if not isinstance(obj, _STRING_TYPES): raise if not hints and not getattr(obj, '__no_type_check__', None): globalns, localns = _get_namespace(obj, globalns, localns) hints = _get_comment_type_hints(obj, globalns, localns) for name, value in six.iteritems(hints): if value is None: value = type(None) elif isinstance(value, _STRING_TYPES): value = _ForwardRef(value) hints[name] = _eval_type(value, globalns, localns) return hints
def has_return_hint(function): """ has_return_hint(function) Returns whether function has a return type hint. """ return "return" in typing.get_type_hints(function)
def callback_types(self): return get_type_hints(self.callback)
def __init__(self, *args): if len(args) == 1: wrapped_prop = args[0] super().__init__(wrapped_prop.fget, self.wrap_setter(wrapped_prop.fset), wrapped_prop.fdel) self.wrapped_property = wrapped_prop self.bindings = [] self.observers = [] self.dtype = typing.get_type_hints(wrapped_prop.fget)['return'] else: super().__init__(*args)
def autocast_decorator(type_hint, fix_arg_func): """ Decorator which will invoke fix_arg_func for any arguments annotated with type_hint. The decorated function will then be called with the result. :param type_hint: A PEP484 type hint :param fix_arg_func: Function to invoke :return: decorator """ @decorator def wrapper(wrapped, instance, args, kwargs): hinted_args = names = None cache_key = '%s-%s-%s' % (wrapped.__class__.__name__, wrapped.__name__, str(type_hint)) if cache_key in AUTOCAST_CACHE: hinted_args, names = AUTOCAST_CACHE[cache_key] else: sig = inspect.signature(wrapped) names = list(sig.parameters.keys()) hinted_args = [x[0] for x in typing.get_type_hints(wrapped).items() \ if x[1] == type_hint or x[1] == typing.Union[type_hint, None]] AUTOCAST_CACHE[cache_key] = hinted_args, names if len(hinted_args) == 0: raise ValueError("No arguments with %s hint found" % type_hint) new_args = list(args) for hinted_arg in hinted_args: if hinted_arg in kwargs: kwargs[hinted_arg] = fix_arg_func(kwargs[hinted_arg]) elif hinted_arg in names: idx = names.index(hinted_arg) if idx < len(new_args): new_args[idx] = fix_arg_func(new_args[idx]) return wrapped(*new_args, **kwargs) return wrapper
def test_defaults_inferred_types(self): tmp = pytypes.infer_default_value_types pytypes.infer_default_value_types = True self.assertEqual(get_types(func_defaults_typecheck), (Tuple[str, Any, int, float], str)) self.assertEqual(pytypes.get_type_hints(func_defaults_typecheck), {'a': str, 'c': int, 'return': str, 'd': float}) self.assertEqual(func_defaults_typecheck('qvw', 'abc', 2, 1.5), 'qvwabcabc') self.assertRaises(InputTypeError, lambda: func_defaults_typecheck('qvw', 'abc', 3.5)) self.assertEqual(func_defaults_typecheck2('test', 12.2, 123), 'test1500.6False') self.assertRaises(InputTypeError, lambda: func_defaults_typecheck2('test', 12.2, 123, 3.5)) self.assertRaises(InputTypeError, lambda: func_defaults_typecheck('qvw', 'abc', 3.5, 4.1)) self.assertRaises(InputTypeError, lambda: func_defaults_typecheck(7, 'qvw')) self.assertEqual(func_defaults_checkargs('qvw', 'abc', 3, 1.5), 'qvwabcabcabc') self.assertRaises(InputTypeError, lambda: func_defaults_checkargs('qvw', 'abc', 3.5)) self.assertRaises(InputTypeError, lambda: func_defaults_checkargs('qvw', 'abc', 3.5, 4.1)) self.assertRaises(InputTypeError, lambda: func_defaults_checkargs(7, 'qvw')) self.assertEqual(get_types(func_defaults_annotations), (Tuple[str, Any, int], str)) self.assertEqual(pytypes.get_type_hints(func_defaults_annotations), {'a': str, 'c': int, 'return': str}) self.assertEqual(func_defaults_annotations.__annotations__, {'a': str, 'return': str}) pytypes.infer_default_value_types = False self.assertEqual(get_types(func_defaults_typecheck), (Tuple[str, Any, Any, Any], str)) self.assertEqual(pytypes.get_type_hints(func_defaults_typecheck), {'a': str, 'return': str}) self.assertEqual(func_defaults_typecheck('qvw', 'abc', 3.5), 'invalid') self.assertEqual(func_defaults_typecheck('qvw', 'abc', 3.5, 4.1), 'invalid') self.assertRaises(InputTypeError, lambda: func_defaults_typecheck(7, 'qvw')) self.assertEqual(func_defaults_checkargs('qvw', 'abc', 3, 1.5), 'qvwabcabcabc') self.assertEqual(func_defaults_checkargs('qvw', 'abc', 3.5), 'invalid') self.assertEqual(func_defaults_checkargs('qvw', 'abc', 3.5, 4.1), 'invalid') self.assertRaises(InputTypeError, lambda: func_defaults_checkargs(7, 'qvw')) self.assertEqual(get_types(func_defaults_annotations), (Tuple[str, Any, Any], str)) self.assertEqual(pytypes.get_type_hints(func_defaults_annotations), {'a': str, 'return': str}) self.assertEqual(func_defaults_annotations.__annotations__, {'a': str, 'return': str}) pytypes.infer_default_value_types = tmp
def test_defaults_inferred_types(self): tmp = pytypes.infer_default_value_types pytypes.infer_default_value_types = True self.assertEqual(get_types(py3.func_defaults_typecheck), (Tuple[str, Any, int, float], str)) self.assertEqual(pytypes.get_type_hints(py3.func_defaults_typecheck), {'a': str, 'c': int, 'return': str, 'd': float}) self.assertEqual(py3.func_defaults_typecheck('qvw', 'abc', 2, 1.5), 'qvwabcabc') self.assertRaises(InputTypeError, lambda: py3.func_defaults_typecheck('qvw', 'abc', 3.5)) self.assertEqual(py3.func_defaults_typecheck2('test', 12.2, 323), 'test3940.6False') self.assertRaises(InputTypeError, lambda: py3.func_defaults_typecheck2('test', 12.2, 323, 3.5)) self.assertRaises(InputTypeError, lambda: py3.func_defaults_typecheck('qvw', 'abc', 3.5, 4.1)) self.assertRaises(InputTypeError, lambda: py3.func_defaults_typecheck(7, 'qvw')) self.assertEqual(py3.func_defaults_checkargs('qvw', 'abc', 3, 1.5), 'qvwabcabcabc') self.assertRaises(InputTypeError, lambda: py3.func_defaults_checkargs('qvw', 'abc', 3.5)) self.assertRaises(InputTypeError, lambda: py3.func_defaults_checkargs('qvw', 'abc', 3.5, 4.1)) self.assertRaises(InputTypeError, lambda: py3.func_defaults_checkargs(7, 'qvw')) self.assertEqual(get_types(py3.func_defaults_annotations), (Tuple[str, Any, int], str)) self.assertEqual(pytypes.get_type_hints(py3.func_defaults_annotations), {'a': str, 'c': int, 'return': str}) self.assertEqual(py3.func_defaults_annotations.__annotations__, {'a': str, 'return': str}) pytypes.infer_default_value_types = False self.assertEqual(get_types(py3.func_defaults_typecheck), (Tuple[str, Any, Any, Any], str)) self.assertEqual(pytypes.get_type_hints(py3.func_defaults_typecheck), {'a': str, 'return': str}) self.assertEqual(py3.func_defaults_typecheck('qvw', 'abc', 3.5), 'invalid') self.assertEqual(py3.func_defaults_typecheck('qvw', 'abc', 3.5, 4.1), 'invalid') self.assertRaises(InputTypeError, lambda: py3.func_defaults_typecheck(7, 'qvw')) self.assertEqual(py3.func_defaults_checkargs('qvw', 'abc', 3, 1.5), 'qvwabcabcabc') self.assertEqual(py3.func_defaults_checkargs('qvw', 'abc', 3.5), 'invalid') self.assertEqual(py3.func_defaults_checkargs('qvw', 'abc', 3.5, 4.1), 'invalid') self.assertRaises(InputTypeError, lambda: py3.func_defaults_checkargs(7, 'qvw')) self.assertEqual(get_types(py3.func_defaults_annotations), (Tuple[str, Any, Any], str)) self.assertEqual(pytypes.get_type_hints(py3.func_defaults_annotations), {'a': str, 'return': str}) self.assertEqual(py3.func_defaults_annotations.__annotations__, {'a': str, 'return': str}) pytypes.infer_default_value_types = tmp
def __call__(self, function): if not self.shouldCheck: return function type_hints = typing.get_type_hints(function) def precheck(*args, **kwargs): all_args = kwargs.copy() all_args.update(dict(zip(function.__code__.co_varnames, args))) runtime_args = ((n, type(v)) for n, v in all_args.items()) for arg_name, arg_type in runtime_args: if arg_name not in type_hints: continue if not self.is_subtype(arg_type, type_hints[arg_name]): raise TypeError('In {} type of {} is {} and not {}'. format(function.__qualname__, arg_name, arg_type, type_hints[arg_name])) def postcheck(result): if 'return' in type_hints: if not self.is_subtype(type(result), type_hints['return']): raise TypeError('Type of result is {} and not {}'. format(type(result), type_hints['return'])) return result if inspect.iscoroutinefunction(function): async def type_checker(*args, **kwargs): precheck(*args, **kwargs) result = await function(*args, **kwargs) return postcheck(result) else: def type_checker(*args, **kwargs): precheck(*args, **kwargs) result = function(*args, **kwargs) return postcheck(result) return type_checker