|
7 | 7 | import dataclasses |
8 | 8 | import inspect |
9 | 9 | import json |
10 | | -import types |
11 | | -import typing |
12 | 10 | from abc import ABC, abstractmethod |
13 | 11 | from dataclasses import dataclass |
14 | 12 | from datetime import datetime |
15 | 13 | from enum import IntEnum |
16 | 14 | from typing import ( |
17 | 15 | Any, |
18 | | - Callable, |
19 | 16 | Dict, |
20 | 17 | List, |
21 | 18 | Mapping, |
@@ -705,105 +702,6 @@ def decode_search_attributes( |
705 | 702 | return ret |
706 | 703 |
|
707 | 704 |
|
708 | | -class _FunctionTypeLookup: |
709 | | - def __init__(self) -> None: |
710 | | - # Keyed by callable __qualname__, value is optional arg types and |
711 | | - # optional ret type |
712 | | - self._cache: Dict[str, Tuple[Optional[List[Type]], Optional[Type]]] = {} |
713 | | - |
714 | | - def get_type_hints(self, fn: Any) -> Tuple[Optional[List[Type]], Optional[Type]]: |
715 | | - # Due to MyPy issues, we cannot type "fn" as callable |
716 | | - if not callable(fn): |
717 | | - return (None, None) |
718 | | - # We base the cache key on the qualified name of the function. However, |
719 | | - # since some callables are not functions, we assume we can never cache |
720 | | - # these just in case the type hints are dynamic for some strange reason. |
721 | | - cache_key = getattr(fn, "__qualname__", None) |
722 | | - if cache_key: |
723 | | - ret = self._cache.get(cache_key) |
724 | | - if ret: |
725 | | - return ret |
726 | | - # TODO(cretz): Do we even need to cache? |
727 | | - ret = _type_hints_from_func(fn) |
728 | | - if cache_key: |
729 | | - self._cache[cache_key] = ret |
730 | | - return ret |
731 | | - |
732 | | - |
733 | | -# Same as inspect._NonUserDefinedCallables |
734 | | -_non_user_defined_callables = ( |
735 | | - type(type.__call__), |
736 | | - type(all.__call__), # type: ignore |
737 | | - type(int.__dict__["from_bytes"]), |
738 | | - types.BuiltinFunctionType, |
739 | | -) |
740 | | - |
741 | | - |
742 | | -def _type_hints_from_func( |
743 | | - func: Callable, |
744 | | -) -> Tuple[Optional[List[Type]], Optional[Type]]: |
745 | | - """Extracts the type hints from the function. |
746 | | -
|
747 | | - Args: |
748 | | - func: Function to extract hints from. |
749 | | -
|
750 | | - Returns: |
751 | | - Tuple containing parameter types and return type. The parameter types |
752 | | - will be None if there are any non-positional parameters or if any of the |
753 | | - parameters to not have an annotation that represents a class. If the |
754 | | - first parameter is "self" with no attribute, it is not included. |
755 | | - """ |
756 | | - # If this is a class instance with user-defined __call__, then use that as |
757 | | - # the func. This mimics inspect logic inside Python. |
758 | | - if ( |
759 | | - not inspect.isfunction(func) |
760 | | - and not isinstance(func, _non_user_defined_callables) |
761 | | - and not isinstance(func, types.MethodType) |
762 | | - ): |
763 | | - # Class type or Callable instance |
764 | | - tmp_func = func if isinstance(func, type) else type(func) |
765 | | - call_func = getattr(tmp_func, "__call__", None) |
766 | | - if call_func is not None and not isinstance( |
767 | | - tmp_func, _non_user_defined_callables |
768 | | - ): |
769 | | - func = call_func |
770 | | - |
771 | | - # We use inspect.signature for the parameter names and kinds, but we cannot |
772 | | - # use it for annotations because those that are using deferred hinting (i.e. |
773 | | - # from __future__ import annotations) only work with the eval_str parameter |
774 | | - # which is only supported in >= 3.10. But typing.get_type_hints is supported |
775 | | - # in >= 3.7. |
776 | | - sig = inspect.signature(func) |
777 | | - hints = typing.get_type_hints(func) |
778 | | - ret_hint = hints.get("return") |
779 | | - ret = ( |
780 | | - ret_hint |
781 | | - if inspect.isclass(ret_hint) and ret_hint is not inspect.Signature.empty |
782 | | - else None |
783 | | - ) |
784 | | - args: List[Type] = [] |
785 | | - for index, value in enumerate(sig.parameters.values()): |
786 | | - # Ignore self on methods |
787 | | - if ( |
788 | | - index == 0 |
789 | | - and value.name == "self" |
790 | | - and value.annotation is inspect.Parameter.empty |
791 | | - ): |
792 | | - continue |
793 | | - # Stop if non-positional or not a class |
794 | | - if ( |
795 | | - value.kind is not inspect.Parameter.POSITIONAL_ONLY |
796 | | - and value.kind is not inspect.Parameter.POSITIONAL_OR_KEYWORD |
797 | | - ): |
798 | | - return (None, ret) |
799 | | - # All params must have annotations or we consider none to have them |
800 | | - arg_hint = hints.get(value.name) |
801 | | - if not inspect.isclass(arg_hint) or arg_hint is inspect.Parameter.empty: |
802 | | - return (None, ret) |
803 | | - args.append(arg_hint) |
804 | | - return args, ret |
805 | | - |
806 | | - |
807 | 705 | def value_to_type(hint: Type, value: Any) -> Any: |
808 | 706 | """Convert a given value to the given type hint. |
809 | 707 |
|
|
0 commit comments