1""" 
    2We need to somehow work with the typing objects. Since the typing objects are 
    3pretty bare we need to add all the Jedi customizations to make them work as 
    4values. 
    5 
    6This file deals with all the typing.py cases. 
    7""" 
    8import itertools 
    9 
    10from jedi import debug 
    11from jedi.inference.compiled import builtin_from_name, create_simple_object 
    12from jedi.inference.base_value import ValueSet, NO_VALUES, Value, \ 
    13    LazyValueWrapper, ValueWrapper 
    14from jedi.inference.lazy_value import LazyKnownValues 
    15from jedi.inference.arguments import repack_with_argument_clinic 
    16from jedi.inference.filters import FilterWrapper 
    17from jedi.inference.names import NameWrapper, ValueName 
    18from jedi.inference.value.klass import ClassMixin 
    19from jedi.inference.gradual.base import BaseTypingValue, \ 
    20    BaseTypingClassWithGenerics, BaseTypingInstance 
    21from jedi.inference.gradual.type_var import TypeVarClass 
    22from jedi.inference.gradual.generics import LazyGenericManager, TupleGenericManager 
    23 
    24_PROXY_CLASS_TYPES = 'Tuple Generic Protocol Callable Type'.split() 
    25_TYPE_ALIAS_TYPES = { 
    26    'List': 'builtins.list', 
    27    'Dict': 'builtins.dict', 
    28    'Set': 'builtins.set', 
    29    'FrozenSet': 'builtins.frozenset', 
    30    'ChainMap': 'collections.ChainMap', 
    31    'Counter': 'collections.Counter', 
    32    'DefaultDict': 'collections.defaultdict', 
    33    'Deque': 'collections.deque', 
    34} 
    35_PROXY_TYPES = 'Optional Union ClassVar Annotated'.split() 
    36 
    37 
    38class TypingModuleName(NameWrapper): 
    39    def infer(self): 
    40        return ValueSet(self._remap()) 
    41 
    42    def _remap(self): 
    43        name = self.string_name 
    44        inference_state = self.parent_context.inference_state 
    45        try: 
    46            actual = _TYPE_ALIAS_TYPES[name] 
    47        except KeyError: 
    48            pass 
    49        else: 
    50            yield TypeAlias.create_cached( 
    51                inference_state, self.parent_context, self.tree_name, actual) 
    52            return 
    53 
    54        if name in _PROXY_CLASS_TYPES: 
    55            yield ProxyTypingClassValue.create_cached( 
    56                inference_state, self.parent_context, self.tree_name) 
    57        elif name in _PROXY_TYPES: 
    58            yield ProxyTypingValue.create_cached( 
    59                inference_state, self.parent_context, self.tree_name) 
    60        elif name == 'runtime': 
    61            # We don't want anything here, not sure what this function is 
    62            # supposed to do, since it just appears in the stubs and shouldn't 
    63            # have any effects there (because it's never executed). 
    64            return 
    65        elif name == 'TypeVar': 
    66            cls, = self._wrapped_name.infer() 
    67            yield TypeVarClass.create_cached(inference_state, cls) 
    68        elif name == 'Any': 
    69            yield AnyClass.create_cached( 
    70                inference_state, self.parent_context, self.tree_name) 
    71        elif name == 'TYPE_CHECKING': 
    72            # This is needed for e.g. imports that are only available for type 
    73            # checking or are in cycles. The user can then check this variable. 
    74            yield builtin_from_name(inference_state, 'True') 
    75        elif name == 'overload': 
    76            yield OverloadFunction.create_cached( 
    77                inference_state, self.parent_context, self.tree_name) 
    78        elif name == 'NewType': 
    79            v, = self._wrapped_name.infer() 
    80            yield NewTypeFunction.create_cached(inference_state, v) 
    81        elif name == 'cast': 
    82            cast_fn, = self._wrapped_name.infer() 
    83            yield CastFunction.create_cached(inference_state, cast_fn) 
    84        elif name == 'TypedDict': 
    85            # TODO doesn't even exist in typeshed/typing.py, yet. But will be 
    86            # added soon. 
    87            yield TypedDictClass.create_cached( 
    88                inference_state, self.parent_context, self.tree_name) 
    89        else: 
    90            # Not necessary, as long as we are not doing type checking: 
    91            # no_type_check & no_type_check_decorator 
    92            # Everything else shouldn't be relevant... 
    93            yield from self._wrapped_name.infer() 
    94 
    95 
    96class TypingModuleFilterWrapper(FilterWrapper): 
    97    name_wrapper_class = TypingModuleName 
    98 
    99 
    100class ProxyWithGenerics(BaseTypingClassWithGenerics): 
    101    def execute_annotation(self): 
    102        string_name = self._tree_name.value 
    103 
    104        if string_name == 'Union': 
    105            # This is kind of a special case, because we have Unions (in Jedi 
    106            # ValueSets). 
    107            return self.gather_annotation_classes().execute_annotation() 
    108        elif string_name == 'Optional': 
    109            # Optional is basically just saying it's either None or the actual 
    110            # type. 
    111            return self.gather_annotation_classes().execute_annotation() \ 
    112                | ValueSet([builtin_from_name(self.inference_state, 'None')]) 
    113        elif string_name == 'Type': 
    114            # The type is actually already given in the index_value 
    115            return self._generics_manager[0] 
    116        elif string_name in ['ClassVar', 'Annotated']: 
    117            # For now don't do anything here, ClassVars are always used. 
    118            return self._generics_manager[0].execute_annotation() 
    119 
    120        mapped = { 
    121            'Tuple': Tuple, 
    122            'Generic': Generic, 
    123            'Protocol': Protocol, 
    124            'Callable': Callable, 
    125        } 
    126        cls = mapped[string_name] 
    127        return ValueSet([cls( 
    128            self.parent_context, 
    129            self, 
    130            self._tree_name, 
    131            generics_manager=self._generics_manager, 
    132        )]) 
    133 
    134    def gather_annotation_classes(self): 
    135        return ValueSet.from_sets(self._generics_manager.to_tuple()) 
    136 
    137    def _create_instance_with_generics(self, generics_manager): 
    138        return ProxyWithGenerics( 
    139            self.parent_context, 
    140            self._tree_name, 
    141            generics_manager 
    142        ) 
    143 
    144    def infer_type_vars(self, value_set): 
    145        annotation_generics = self.get_generics() 
    146 
    147        if not annotation_generics: 
    148            return {} 
    149 
    150        annotation_name = self.py__name__() 
    151        if annotation_name == 'Optional': 
    152            # Optional[T] is equivalent to Union[T, None]. In Jedi unions 
    153            # are represented by members within a ValueSet, so we extract 
    154            # the T from the Optional[T] by removing the None value. 
    155            none = builtin_from_name(self.inference_state, 'None') 
    156            return annotation_generics[0].infer_type_vars( 
    157                value_set.filter(lambda x: x != none), 
    158            ) 
    159 
    160        return {} 
    161 
    162 
    163class ProxyTypingValue(BaseTypingValue): 
    164    index_class = ProxyWithGenerics 
    165 
    166    def with_generics(self, generics_tuple): 
    167        return self.index_class.create_cached( 
    168            self.inference_state, 
    169            self.parent_context, 
    170            self._tree_name, 
    171            generics_manager=TupleGenericManager(generics_tuple) 
    172        ) 
    173 
    174    def py__getitem__(self, index_value_set, contextualized_node): 
    175        return ValueSet( 
    176            self.index_class.create_cached( 
    177                self.inference_state, 
    178                self.parent_context, 
    179                self._tree_name, 
    180                generics_manager=LazyGenericManager( 
    181                    context_of_index=contextualized_node.context, 
    182                    index_value=index_value, 
    183                ) 
    184            ) for index_value in index_value_set 
    185        ) 
    186 
    187 
    188class _TypingClassMixin(ClassMixin): 
    189    def py__bases__(self): 
    190        return [LazyKnownValues( 
    191            self.inference_state.builtins_module.py__getattribute__('object') 
    192        )] 
    193 
    194    def get_metaclasses(self): 
    195        return [] 
    196 
    197    @property 
    198    def name(self): 
    199        return ValueName(self, self._tree_name) 
    200 
    201 
    202class TypingClassWithGenerics(ProxyWithGenerics, _TypingClassMixin): 
    203    def infer_type_vars(self, value_set): 
    204        type_var_dict = {} 
    205        annotation_generics = self.get_generics() 
    206 
    207        if not annotation_generics: 
    208            return type_var_dict 
    209 
    210        annotation_name = self.py__name__() 
    211        if annotation_name == 'Type': 
    212            return annotation_generics[0].infer_type_vars( 
    213                # This is basically a trick to avoid extra code: We execute the 
    214                # incoming classes to be able to use the normal code for type 
    215                # var inference. 
    216                value_set.execute_annotation(), 
    217            ) 
    218 
    219        elif annotation_name == 'Callable': 
    220            if len(annotation_generics) == 2: 
    221                return annotation_generics[1].infer_type_vars( 
    222                    value_set.execute_annotation(), 
    223                ) 
    224 
    225        elif annotation_name == 'Tuple': 
    226            tuple_annotation, = self.execute_annotation() 
    227            return tuple_annotation.infer_type_vars(value_set) 
    228 
    229        return type_var_dict 
    230 
    231    def _create_instance_with_generics(self, generics_manager): 
    232        return TypingClassWithGenerics( 
    233            self.parent_context, 
    234            self._tree_name, 
    235            generics_manager 
    236        ) 
    237 
    238 
    239class ProxyTypingClassValue(ProxyTypingValue, _TypingClassMixin): 
    240    index_class = TypingClassWithGenerics 
    241 
    242 
    243class TypeAlias(LazyValueWrapper): 
    244    def __init__(self, parent_context, origin_tree_name, actual): 
    245        self.inference_state = parent_context.inference_state 
    246        self.parent_context = parent_context 
    247        self._origin_tree_name = origin_tree_name 
    248        self._actual = actual  # e.g. builtins.list 
    249 
    250    @property 
    251    def name(self): 
    252        return ValueName(self, self._origin_tree_name) 
    253 
    254    def py__name__(self): 
    255        return self.name.string_name 
    256 
    257    def __repr__(self): 
    258        return '<%s: %s>' % (self.__class__.__name__, self._actual) 
    259 
    260    def _get_wrapped_value(self): 
    261        module_name, class_name = self._actual.split('.') 
    262 
    263        # TODO use inference_state.import_module? 
    264        from jedi.inference.imports import Importer 
    265        module, = Importer( 
    266            self.inference_state, [module_name], self.inference_state.builtins_module 
    267        ).follow() 
    268        classes = module.py__getattribute__(class_name) 
    269        # There should only be one, because it's code that we control. 
    270        assert len(classes) == 1, classes 
    271        cls = next(iter(classes)) 
    272        return cls 
    273 
    274    def gather_annotation_classes(self): 
    275        return ValueSet([self._get_wrapped_value()]) 
    276 
    277    def get_signatures(self): 
    278        return [] 
    279 
    280 
    281class Callable(BaseTypingInstance): 
    282    def py__call__(self, arguments): 
    283        """ 
    284            def x() -> Callable[[Callable[..., _T]], _T]: ... 
    285        """ 
    286        # The 0th index are the arguments. 
    287        try: 
    288            param_values = self._generics_manager[0] 
    289            result_values = self._generics_manager[1] 
    290        except IndexError: 
    291            debug.warning('Callable[...] defined without two arguments') 
    292            return NO_VALUES 
    293        else: 
    294            from jedi.inference.gradual.annotation import infer_return_for_callable 
    295            return infer_return_for_callable(arguments, param_values, result_values) 
    296 
    297    def py__get__(self, instance, class_value): 
    298        return ValueSet([self]) 
    299 
    300 
    301class Tuple(BaseTypingInstance): 
    302    def _is_homogenous(self): 
    303        # To specify a variable-length tuple of homogeneous type, Tuple[T, ...] 
    304        # is used. 
    305        return self._generics_manager.is_homogenous_tuple() 
    306 
    307    def py__simple_getitem__(self, index): 
    308        if self._is_homogenous(): 
    309            return self._generics_manager.get_index_and_execute(0) 
    310        else: 
    311            if isinstance(index, int): 
    312                return self._generics_manager.get_index_and_execute(index) 
    313 
    314            debug.dbg('The getitem type on Tuple was %s' % index) 
    315            return NO_VALUES 
    316 
    317    def py__iter__(self, contextualized_node=None): 
    318        if self._is_homogenous(): 
    319            yield LazyKnownValues(self._generics_manager.get_index_and_execute(0)) 
    320        else: 
    321            for v in self._generics_manager.to_tuple(): 
    322                yield LazyKnownValues(v.execute_annotation()) 
    323 
    324    def py__getitem__(self, index_value_set, contextualized_node): 
    325        if self._is_homogenous(): 
    326            return self._generics_manager.get_index_and_execute(0) 
    327 
    328        return ValueSet.from_sets( 
    329            self._generics_manager.to_tuple() 
    330        ).execute_annotation() 
    331 
    332    def _get_wrapped_value(self): 
    333        tuple_, = self.inference_state.builtins_module \ 
    334            .py__getattribute__('tuple').execute_annotation() 
    335        return tuple_ 
    336 
    337    @property 
    338    def name(self): 
    339        return self._wrapped_value.name 
    340 
    341    def infer_type_vars(self, value_set): 
    342        # Circular 
    343        from jedi.inference.gradual.annotation import merge_pairwise_generics, merge_type_var_dicts 
    344 
    345        value_set = value_set.filter( 
    346            lambda x: x.py__name__().lower() == 'tuple', 
    347        ) 
    348 
    349        if self._is_homogenous(): 
    350            # The parameter annotation is of the form `Tuple[T, ...]`, 
    351            # so we treat the incoming tuple like a iterable sequence 
    352            # rather than a positional container of elements. 
    353            return self._class_value.get_generics()[0].infer_type_vars( 
    354                value_set.merge_types_of_iterate(), 
    355            ) 
    356 
    357        else: 
    358            # The parameter annotation has only explicit type parameters 
    359            # (e.g: `Tuple[T]`, `Tuple[T, U]`, `Tuple[T, U, V]`, etc.) so we 
    360            # treat the incoming values as needing to match the annotation 
    361            # exactly, just as we would for non-tuple annotations. 
    362 
    363            type_var_dict = {} 
    364            for element in value_set: 
    365                try: 
    366                    method = element.get_annotated_class_object 
    367                except AttributeError: 
    368                    # This might still happen, because the tuple name matching 
    369                    # above is not 100% correct, so just catch the remaining 
    370                    # cases here. 
    371                    continue 
    372 
    373                py_class = method() 
    374                merge_type_var_dicts( 
    375                    type_var_dict, 
    376                    merge_pairwise_generics(self._class_value, py_class), 
    377                ) 
    378 
    379            return type_var_dict 
    380 
    381 
    382class Generic(BaseTypingInstance): 
    383    pass 
    384 
    385 
    386class Protocol(BaseTypingInstance): 
    387    pass 
    388 
    389 
    390class AnyClass(BaseTypingValue): 
    391    def execute_annotation(self): 
    392        debug.warning('Used Any - returned no results') 
    393        return NO_VALUES 
    394 
    395 
    396class OverloadFunction(BaseTypingValue): 
    397    @repack_with_argument_clinic('func, /') 
    398    def py__call__(self, func_value_set): 
    399        # Just pass arguments through. 
    400        return func_value_set 
    401 
    402 
    403class NewTypeFunction(ValueWrapper): 
    404    def py__call__(self, arguments): 
    405        ordered_args = arguments.unpack() 
    406        next(ordered_args, (None, None)) 
    407        _, second_arg = next(ordered_args, (None, None)) 
    408        if second_arg is None: 
    409            return NO_VALUES 
    410        return ValueSet( 
    411            NewType( 
    412                self.inference_state, 
    413                contextualized_node.context, 
    414                contextualized_node.node, 
    415                second_arg.infer(), 
    416            ) for contextualized_node in arguments.get_calling_nodes()) 
    417 
    418 
    419class NewType(Value): 
    420    def __init__(self, inference_state, parent_context, tree_node, type_value_set): 
    421        super().__init__(inference_state, parent_context) 
    422        self._type_value_set = type_value_set 
    423        self.tree_node = tree_node 
    424 
    425    def py__class__(self): 
    426        c, = self._type_value_set.py__class__() 
    427        return c 
    428 
    429    def py__call__(self, arguments): 
    430        return self._type_value_set.execute_annotation() 
    431 
    432    @property 
    433    def name(self): 
    434        from jedi.inference.compiled.value import CompiledValueName 
    435        return CompiledValueName(self, 'NewType') 
    436 
    437    def __repr__(self) -> str: 
    438        return '<NewType: %s>%s' % (self.tree_node, self._type_value_set) 
    439 
    440 
    441class CastFunction(ValueWrapper): 
    442    @repack_with_argument_clinic('type, object, /') 
    443    def py__call__(self, type_value_set, object_value_set): 
    444        return type_value_set.execute_annotation() 
    445 
    446 
    447class TypedDictClass(BaseTypingValue): 
    448    """ 
    449    This class has no responsibilities and is just here to make sure that typed 
    450    dicts can be identified. 
    451    """ 
    452 
    453 
    454class TypedDict(LazyValueWrapper): 
    455    """Represents the instance version of ``TypedDictClass``.""" 
    456    def __init__(self, definition_class): 
    457        self.inference_state = definition_class.inference_state 
    458        self.parent_context = definition_class.parent_context 
    459        self.tree_node = definition_class.tree_node 
    460        self._definition_class = definition_class 
    461 
    462    @property 
    463    def name(self): 
    464        return ValueName(self, self.tree_node.name) 
    465 
    466    def py__simple_getitem__(self, index): 
    467        if isinstance(index, str): 
    468            return ValueSet.from_sets( 
    469                name.infer() 
    470                for filter in self._definition_class.get_filters(is_instance=True) 
    471                for name in filter.get(index) 
    472            ) 
    473        return NO_VALUES 
    474 
    475    def get_key_values(self): 
    476        filtered_values = itertools.chain.from_iterable(( 
    477            f.values() 
    478            for f in self._definition_class.get_filters(is_instance=True) 
    479        )) 
    480        return ValueSet({ 
    481            create_simple_object(self.inference_state, v.string_name) 
    482            for v in filtered_values 
    483        }) 
    484 
    485    def _get_wrapped_value(self): 
    486        d, = self.inference_state.builtins_module.py__getattribute__('dict') 
    487        result, = d.execute_with_values() 
    488        return result