1 from jedi
.inference
.cache
import inference_state_method_cache
2 from jedi
.inference
.base_value
import ValueSet
, NO_VALUES
, Value
, \
3 iterator_to_value_set
, LazyValueWrapper
, ValueWrapper
4 from jedi
.inference
.compiled
import builtin_from_name
5 from jedi
.inference
.value
.klass
import ClassFilter
6 from jedi
.inference
.value
.klass
import ClassMixin
7 from jedi
.inference
.utils
import to_list
8 from jedi
.inference
.names
import AbstractNameDefinition
, ValueName
9 from jedi
.inference
.context
import ClassContext
10 from jedi
.inference
.gradual
.generics
import TupleGenericManager
13 class _BoundTypeVarName(AbstractNameDefinition
):
15 This type var was bound to a certain type, e.g. int.
17 def __init__(self
, type_var
, value_set
):
18 self
._type
_var
= type_var
19 self
.parent_context
= type_var
.parent_context
20 self
._value
_set
= value_set
24 for value
in self
._value
_set
:
25 # Replace any with the constraints if they are there.
26 from jedi
.inference
.gradual
.typing
import AnyClass
27 if isinstance(value
, AnyClass
):
28 yield from self
._type
_var
.constraints
31 return ValueSet(iter_())
34 return self
._type
_var
.py__name__()
37 return '<%s %s -> %s>' % (self
.__class
__.__name
__, self
.py__name__(), self
._value
_set
)
42 A filter for all given variables in a class.
46 class Foo(Mapping[A, B]):
49 In this example we would have two type vars given: A and B
51 def __init__(self
, generics
, type_vars
):
52 self
._generics
= generics
53 self
._type
_vars
= type_vars
56 for i
, type_var
in enumerate(self
._type
_vars
):
57 if type_var
.py__name__() == name
:
59 return [_BoundTypeVarName(type_var
, self
._generics
[i
])]
61 return [type_var
.name
]
65 # The values are not relevant. If it's not searched exactly, the type
66 # vars are just global and should be looked up as that.
70 class _AnnotatedClassContext(ClassContext
):
71 def get_filters(self
, *args
, **kwargs
):
72 filters
= super().get_filters(
77 # The type vars can only be looked up if it's a global search and
78 # not a direct lookup on the class.
79 yield self
._value
.get_type_var_filter()
82 class DefineGenericBaseClass(LazyValueWrapper
):
83 def __init__(self
, generics_manager
):
84 self
._generics
_manager
= generics_manager
86 def _create_instance_with_generics(self
, generics_manager
):
87 raise NotImplementedError
89 @inference_state_method_cache()
90 def get_generics(self
):
91 return self
._generics
_manager
.to_tuple()
93 def define_generics(self
, type_var_dict
):
94 from jedi
.inference
.gradual
.type_var
import TypeVar
97 for generic_set
in self
.get_generics():
99 for generic
in generic_set
:
100 if isinstance(generic
, (DefineGenericBaseClass
, TypeVar
)):
101 result
= generic
.define_generics(type_var_dict
)
103 if result
!= ValueSet({generic}
):
106 values |
= ValueSet([generic
])
107 new_generics
.append(values
)
110 # There might not be any type vars that change. In that case just
111 # return itself, because it does not make sense to potentially lose
113 return ValueSet([self
])
115 return ValueSet([self
._create
_instance
_with
_generics
(
116 TupleGenericManager(tuple(new_generics
))
119 def is_same_class(self
, other
):
120 if not isinstance(other
, DefineGenericBaseClass
):
123 if self
.tree_node
!= other
.tree_node
:
124 # TODO not sure if this is nice.
126 given_params1
= self
.get_generics()
127 given_params2
= other
.get_generics()
129 if len(given_params1
) != len(given_params2
):
130 # If the amount of type vars doesn't match, the class doesn't
134 # Now compare generics
137 # TODO why is this ordering the correct one?
138 cls2
.is_same_class(cls1
)
139 # TODO I'm still not sure gather_annotation_classes is a good
140 # idea. They are essentially here to avoid comparing Tuple <=>
141 # tuple and instead compare tuple <=> tuple, but at the moment
142 # the whole `is_same_class` and `is_sub_class` matching is just
143 # not in the best shape.
144 for cls1
in class_set1
.gather_annotation_classes()
145 for cls2
in class_set2
.gather_annotation_classes()
146 ) for class_set1
, class_set2
in zip(given_params1
, given_params2
)
149 def get_signatures(self
):
153 return '<%s: %s%s>' % (
154 self
.__class
__.__name
__,
156 list(self
.get_generics()),
160 class GenericClass(DefineGenericBaseClass
, ClassMixin
):
162 A class that is defined with generics, might be something simple like:
164 class Foo(Generic[T]): ...
165 my_foo_int_cls = Foo[int]
167 def __init__(self
, class_value
, generics_manager
):
168 super().__init
__(generics_manager
)
169 self
._class
_value
= class_value
171 def _get_wrapped_value(self
):
172 return self
._class
_value
174 def get_type_hint(self
, add_class_info
=True):
175 n
= self
.py__name__()
176 # Not sure if this is the best way to do this, but all of these types
177 # are a bit special in that they have type aliases and other ways to
178 # become lower case. It's probably better to make them upper case,
179 # because that's what you can use in annotations.
180 n
= dict(list="List", dict="Dict", set="Set", tuple="Tuple").get(n
, n
)
181 s
= n
+ self
._generics
_manager
.get_type_hint()
183 return 'Type[%s]' % s
186 def get_type_var_filter(self
):
187 return _TypeVarFilter(self
.get_generics(), self
.list_type_vars())
189 def py__call__(self
, arguments
):
190 instance
, = super().py__call__(arguments
)
191 return ValueSet([_GenericInstanceWrapper(instance
)])
193 def _as_context(self
):
194 return _AnnotatedClassContext(self
)
197 def py__bases__(self
):
198 for base
in self
._wrapped
_value
.py__bases__():
199 yield _LazyGenericBaseClass(self
, base
, self
._generics
_manager
)
201 def _create_instance_with_generics(self
, generics_manager
):
202 return GenericClass(self
._class
_value
, generics_manager
)
204 def is_sub_class_of(self
, class_value
):
205 if super().is_sub_class_of(class_value
):
207 return self
._class
_value
.is_sub_class_of(class_value
)
209 def with_generics(self
, generics_tuple
):
210 return self
._class
_value
.with_generics(generics_tuple
)
212 def infer_type_vars(self
, value_set
):
214 from jedi
.inference
.gradual
.annotation
import merge_pairwise_generics
, merge_type_var_dicts
216 annotation_name
= self
.py__name__()
218 if annotation_name
== 'Iterable':
219 annotation_generics
= self
.get_generics()
220 if annotation_generics
:
221 return annotation_generics
[0].infer_type_vars(
222 value_set
.merge_types_of_iterate(),
225 # Note: we need to handle the MRO _in order_, so we need to extract
226 # the elements from the set first, then handle them, even if we put
227 # them back in a set afterwards.
228 for py_class
in value_set
:
229 if py_class
.is_instance() and not py_class
.is_compiled():
230 py_class
= py_class
.get_annotated_class_object()
234 if py_class
.api_type
!= 'class':
235 # Functions & modules don't have an MRO and we're not
236 # expecting a Callable (those are handled separately within
237 # TypingClassValueWithIndex).
240 for parent_class
in py_class
.py__mro__():
241 class_name
= parent_class
.py__name__()
242 if annotation_name
== class_name
:
243 merge_type_var_dicts(
245 merge_pairwise_generics(self
, parent_class
),
252 class _LazyGenericBaseClass
:
253 def __init__(self
, class_value
, lazy_base_class
, generics_manager
):
254 self
._class
_value
= class_value
255 self
._lazy
_base
_class
= lazy_base_class
256 self
._generics
_manager
= generics_manager
258 @iterator_to_value_set
260 for base
in self
._lazy
_base
_class
.infer():
261 if isinstance(base
, GenericClass
):
262 # Here we have to recalculate the given types.
263 yield GenericClass
.create_cached(
264 base
.inference_state
,
266 TupleGenericManager(tuple(self
._remap
_type
_vars
(base
))),
269 if base
.is_class_mixin():
270 # This case basically allows classes like `class Foo(List)`
271 # to be used like `Foo[int]`. The generics are not
272 # necessary and can be used later.
273 yield GenericClass
.create_cached(
274 base
.inference_state
,
276 self
._generics
_manager
,
281 def _remap_type_vars(self
, base
):
282 from jedi
.inference
.gradual
.type_var
import TypeVar
283 filter = self
._class
_value
.get_type_var_filter()
284 for type_var_set
in base
.get_generics():
286 for type_var
in type_var_set
:
287 if isinstance(type_var
, TypeVar
):
288 names
= filter.get(type_var
.py__name__())
289 new |
= ValueSet
.from_sets(
290 name
.infer() for name
in names
293 # Mostly will be type vars, except if in some cases
294 # a concrete type will already be there. In that
295 # case just add it to the value set.
296 new |
= ValueSet([type_var
])
300 return '<%s: %s>' % (self
.__class
__.__name
__, self
._lazy
_base
_class
)
303 class _GenericInstanceWrapper(ValueWrapper
):
304 def py__stop_iteration_returns(self
):
305 for cls
in self
._wrapped
_value
.class_value
.py__mro__():
306 if cls
.py__name__() == 'Generator':
307 generics
= cls
.get_generics()
309 return generics
[2].execute_annotation()
312 elif cls
.py__name__() == 'Iterator':
313 return ValueSet([builtin_from_name(self
.inference_state
, 'None')])
314 return self
._wrapped
_value
.py__stop_iteration_returns()
316 def get_type_hint(self
, add_class_info
=True):
317 return self
._wrapped
_value
.class_value
.get_type_hint(add_class_info
=False)
320 class _PseudoTreeNameClass(Value
):
322 In typeshed, some classes are defined like this:
324 Tuple: _SpecialForm = ...
326 Now this is not a real class, therefore we have to do some workarounds like
327 this class. Essentially this class makes it possible to goto that `Tuple`
328 name, without affecting anything else negatively.
332 def __init__(self
, parent_context
, tree_name
):
334 parent_context
.inference_state
,
337 self
._tree
_name
= tree_name
341 return self
._tree
_name
343 def get_filters(self
, *args
, **kwargs
):
344 # TODO this is obviously wrong. Is it though?
345 class EmptyFilter(ClassFilter
):
349 def get(self
, name
, **kwargs
):
352 def values(self
, **kwargs
):
357 def py__class__(self
):
358 # This might not be 100% correct, but it is good enough. The details of
359 # the typing library are not really an issue for Jedi.
360 return builtin_from_name(self
.inference_state
, 'type')
364 return ValueName(self
, self
._tree
_name
)
366 def get_qualified_names(self
):
367 return (self
._tree
_name
.value
,)
370 return '%s(%s)' % (self
.__class
__.__name
__, self
._tree
_name
.value
)
373 class BaseTypingValue(LazyValueWrapper
):
374 def __init__(self
, parent_context
, tree_name
):
375 self
.inference_state
= parent_context
.inference_state
376 self
.parent_context
= parent_context
377 self
._tree
_name
= tree_name
381 return ValueName(self
, self
._tree
_name
)
383 def _get_wrapped_value(self
):
384 return _PseudoTreeNameClass(self
.parent_context
, self
._tree
_name
)
386 def get_signatures(self
):
387 return self
._wrapped
_value
.get_signatures()
390 return '%s(%s)' % (self
.__class
__.__name
__, self
._tree
_name
.value
)
393 class BaseTypingClassWithGenerics(DefineGenericBaseClass
):
394 def __init__(self
, parent_context
, tree_name
, generics_manager
):
395 super().__init
__(generics_manager
)
396 self
.inference_state
= parent_context
.inference_state
397 self
.parent_context
= parent_context
398 self
._tree
_name
= tree_name
400 def _get_wrapped_value(self
):
401 return _PseudoTreeNameClass(self
.parent_context
, self
._tree
_name
)
404 return '%s(%s%s)' % (self
.__class
__.__name
__, self
._tree
_name
.value
,
405 self
._generics
_manager
)
408 class BaseTypingInstance(LazyValueWrapper
):
409 def __init__(self
, parent_context
, class_value
, tree_name
, generics_manager
):
410 self
.inference_state
= class_value
.inference_state
411 self
.parent_context
= parent_context
412 self
._class
_value
= class_value
413 self
._tree
_name
= tree_name
414 self
._generics
_manager
= generics_manager
416 def py__class__(self
):
417 return self
._class
_value
419 def get_annotated_class_object(self
):
420 return self
._class
_value
422 def get_qualified_names(self
):
423 return (self
.py__name__(),)
427 return ValueName(self
, self
._tree
_name
)
429 def _get_wrapped_value(self
):
430 object_
, = builtin_from_name(self
.inference_state
, 'object').execute_annotation()
434 return '<%s: %s>' % (self
.__class
__.__name
__, self
._generics
_manager
)