Esempio n. 1
0
    def infer_type_vars(self, value_set, is_class_value=False):
        # Circular
        from jedi.inference.gradual.annotation import merge_pairwise_generics, merge_type_var_dicts

        type_var_dict = {}
        annotation_generics = self.get_generics()

        if not annotation_generics:
            return type_var_dict

        annotation_name = self.py__name__()
        if annotation_name == 'Type':
            if is_class_value:
                # This only applies if we are comparing something like
                # List[Type[int]] with Iterable[Type[int]]. First, Jedi tries to
                # match List/Iterable. After that we will land here, because
                # is_class_value will be True at that point. Obviously we also
                # compare below that both sides are `Type`.
                for element in value_set:
                    element_name = element.py__name__()
                    if element_name == 'Type':
                        merge_type_var_dicts(
                            type_var_dict,
                            merge_pairwise_generics(self, element),
                        )
            else:
                return annotation_generics[0].infer_type_vars(
                    value_set,
                    is_class_value=True,
                )

        elif annotation_name == 'Callable':
            if len(annotation_generics) == 2:
                if is_class_value:
                    # This only applies if we are comparing something like
                    # List[Callable[..., T]] with Iterable[Callable[..., T]].
                    # First, Jedi tries to match List/Iterable. After that we
                    # will land here, because is_class_value will be True at
                    # that point. Obviously we also compare below that both
                    # sides are `Callable`.
                    for element in value_set:
                        element_name = element.py__name__()
                        if element_name == 'Callable':
                            merge_type_var_dicts(
                                type_var_dict,
                                merge_pairwise_generics(self, element),
                            )
                else:
                    return annotation_generics[1].infer_type_vars(
                        value_set.execute_annotation(), )

        elif annotation_name == 'Tuple':
            tuple_annotation, = self.execute_annotation()
            return tuple_annotation.infer_type_vars(value_set, is_class_value)

        return type_var_dict
Esempio n. 2
0
    def infer_type_vars(self, value_set, is_class_value=False):
        # Circular
        from jedi.inference.gradual.annotation import merge_pairwise_generics, merge_type_var_dicts
        from jedi.inference.gradual.base import GenericClass

        if self._is_homogenous():
            # The parameter annotation is of the form `Tuple[T, ...]`,
            # so we treat the incoming tuple like a iterable sequence
            # rather than a positional container of elements.
            return self.get_generics()[0].infer_type_vars(
                value_set.merge_types_of_iterate(), )

        else:
            # The parameter annotation has only explicit type parameters
            # (e.g: `Tuple[T]`, `Tuple[T, U]`, `Tuple[T, U, V]`, etc.) so we
            # treat the incoming values as needing to match the annotation
            # exactly, just as we would for non-tuple annotations.

            type_var_dict = {}
            for element in value_set:
                py_class = element.get_annotated_class_object()
                if not isinstance(py_class, GenericClass):
                    py_class = element

                merge_type_var_dicts(
                    type_var_dict,
                    merge_pairwise_generics(self, py_class),
                )

            return type_var_dict
Esempio n. 3
0
    def infer_type_vars(self, value_set, is_class_value=False):
        # Circular
        from jedi.inference.gradual.annotation import merge_pairwise_generics, merge_type_var_dicts
        from jedi.inference.gradual.base import GenericClass

        value_set = value_set.filter(
            lambda x: x.py__name__().lower() == 'tuple', )

        # Somewhat unusually, this `infer_type_vars` method is on an instance
        # representation of a type, rather than the annotation or class
        # representation. This means that as a starting point, we need to
        # convert the incoming values to their instance style if they're
        # classes, rather than the reverse.
        if is_class_value:
            value_set = value_set.execute_annotation()

        if self._is_homogenous():
            # The parameter annotation is of the form `Tuple[T, ...]`,
            # so we treat the incoming tuple like a iterable sequence
            # rather than a positional container of elements.
            return self.get_generics()[0].infer_type_vars(
                value_set.merge_types_of_iterate(), )

        else:
            # The parameter annotation has only explicit type parameters
            # (e.g: `Tuple[T]`, `Tuple[T, U]`, `Tuple[T, U, V]`, etc.) so we
            # treat the incoming values as needing to match the annotation
            # exactly, just as we would for non-tuple annotations.

            type_var_dict = {}
            for element in value_set:
                if not is_class_value:
                    py_class = element.get_annotated_class_object()
                    if not isinstance(py_class, GenericClass):
                        py_class = element
                else:
                    py_class = element

                merge_type_var_dicts(
                    type_var_dict,
                    merge_pairwise_generics(self, py_class),
                )

            return type_var_dict
Esempio n. 4
0
    def infer_type_vars(self, value_set):
        # Circular
        from jedi.inference.gradual.annotation import merge_pairwise_generics, merge_type_var_dicts

        value_set = value_set.filter(
            lambda x: x.py__name__().lower() == 'tuple',
        )

        if self._is_homogenous():
            # The parameter annotation is of the form `Tuple[T, ...]`,
            # so we treat the incoming tuple like a iterable sequence
            # rather than a positional container of elements.
            return self._class_value.get_generics()[0].infer_type_vars(
                value_set.merge_types_of_iterate(),
            )

        else:
            # The parameter annotation has only explicit type parameters
            # (e.g: `Tuple[T]`, `Tuple[T, U]`, `Tuple[T, U, V]`, etc.) so we
            # treat the incoming values as needing to match the annotation
            # exactly, just as we would for non-tuple annotations.

            type_var_dict = {}
            for element in value_set:
                try:
                    method = element.get_annotated_class_object
                except AttributeError:
                    # This might still happen, because the tuple name matching
                    # above is not 100% correct, so just catch the remaining
                    # cases here.
                    continue

                py_class = method()
                merge_type_var_dicts(
                    type_var_dict,
                    merge_pairwise_generics(self._class_value, py_class),
                )

            return type_var_dict
Esempio n. 5
0
    def infer_type_vars(self, value_set, is_class_value=False):
        # Circular
        from jedi.inference.gradual.annotation import merge_pairwise_generics, merge_type_var_dicts

        annotation_name = self.py__name__()
        type_var_dict = {}
        if annotation_name == 'Iterable' and not is_class_value:
            annotation_generics = self.get_generics()
            if annotation_generics:
                return annotation_generics[0].infer_type_vars(
                    value_set.merge_types_of_iterate(), )

        else:
            # Note: we need to handle the MRO _in order_, so we need to extract
            # the elements from the set first, then handle them, even if we put
            # them back in a set afterwards.
            for py_class in value_set:
                if not is_class_value:
                    if py_class.is_instance() and not py_class.is_compiled():
                        py_class = py_class.get_annotated_class_object()
                    else:
                        continue

                if py_class.api_type != u'class':
                    # Functions & modules don't have an MRO and we're not
                    # expecting a Callable (those are handled separately within
                    # TypingClassValueWithIndex).
                    continue

                for parent_class in py_class.py__mro__():
                    class_name = parent_class.py__name__()
                    if annotation_name == class_name:
                        merge_type_var_dicts(
                            type_var_dict,
                            merge_pairwise_generics(self, parent_class),
                        )
                        break

        return type_var_dict