]> crepu.dev Git - config.git/blame - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/jedi/inference/gradual/base.py
ActualizaciĆ³n de Readme
[config.git] / djavu-asus / elpy / rpc-venv / lib / python3.11 / site-packages / jedi / inference / gradual / base.py
CommitLineData
53e6db90
DC
1from jedi.inference.cache import inference_state_method_cache
2from jedi.inference.base_value import ValueSet, NO_VALUES, Value, \
3 iterator_to_value_set, LazyValueWrapper, ValueWrapper
4from jedi.inference.compiled import builtin_from_name
5from jedi.inference.value.klass import ClassFilter
6from jedi.inference.value.klass import ClassMixin
7from jedi.inference.utils import to_list
8from jedi.inference.names import AbstractNameDefinition, ValueName
9from jedi.inference.context import ClassContext
10from jedi.inference.gradual.generics import TupleGenericManager
11
12
13class _BoundTypeVarName(AbstractNameDefinition):
14 """
15 This type var was bound to a certain type, e.g. int.
16 """
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
21
22 def infer(self):
23 def iter_():
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
29 else:
30 yield value
31 return ValueSet(iter_())
32
33 def py__name__(self):
34 return self._type_var.py__name__()
35
36 def __repr__(self):
37 return '<%s %s -> %s>' % (self.__class__.__name__, self.py__name__(), self._value_set)
38
39
40class _TypeVarFilter:
41 """
42 A filter for all given variables in a class.
43
44 A = TypeVar('A')
45 B = TypeVar('B')
46 class Foo(Mapping[A, B]):
47 ...
48
49 In this example we would have two type vars given: A and B
50 """
51 def __init__(self, generics, type_vars):
52 self._generics = generics
53 self._type_vars = type_vars
54
55 def get(self, name):
56 for i, type_var in enumerate(self._type_vars):
57 if type_var.py__name__() == name:
58 try:
59 return [_BoundTypeVarName(type_var, self._generics[i])]
60 except IndexError:
61 return [type_var.name]
62 return []
63
64 def values(self):
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.
67 return []
68
69
70class _AnnotatedClassContext(ClassContext):
71 def get_filters(self, *args, **kwargs):
72 filters = super().get_filters(
73 *args, **kwargs
74 )
75 yield from filters
76
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()
80
81
82class DefineGenericBaseClass(LazyValueWrapper):
83 def __init__(self, generics_manager):
84 self._generics_manager = generics_manager
85
86 def _create_instance_with_generics(self, generics_manager):
87 raise NotImplementedError
88
89 @inference_state_method_cache()
90 def get_generics(self):
91 return self._generics_manager.to_tuple()
92
93 def define_generics(self, type_var_dict):
94 from jedi.inference.gradual.type_var import TypeVar
95 changed = False
96 new_generics = []
97 for generic_set in self.get_generics():
98 values = NO_VALUES
99 for generic in generic_set:
100 if isinstance(generic, (DefineGenericBaseClass, TypeVar)):
101 result = generic.define_generics(type_var_dict)
102 values |= result
103 if result != ValueSet({generic}):
104 changed = True
105 else:
106 values |= ValueSet([generic])
107 new_generics.append(values)
108
109 if not changed:
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
112 # cached results.
113 return ValueSet([self])
114
115 return ValueSet([self._create_instance_with_generics(
116 TupleGenericManager(tuple(new_generics))
117 )])
118
119 def is_same_class(self, other):
120 if not isinstance(other, DefineGenericBaseClass):
121 return False
122
123 if self.tree_node != other.tree_node:
124 # TODO not sure if this is nice.
125 return False
126 given_params1 = self.get_generics()
127 given_params2 = other.get_generics()
128
129 if len(given_params1) != len(given_params2):
130 # If the amount of type vars doesn't match, the class doesn't
131 # match.
132 return False
133
134 # Now compare generics
135 return all(
136 any(
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)
147 )
148
149 def get_signatures(self):
150 return []
151
152 def __repr__(self):
153 return '<%s: %s%s>' % (
154 self.__class__.__name__,
155 self._wrapped_value,
156 list(self.get_generics()),
157 )
158
159
160class GenericClass(DefineGenericBaseClass, ClassMixin):
161 """
162 A class that is defined with generics, might be something simple like:
163
164 class Foo(Generic[T]): ...
165 my_foo_int_cls = Foo[int]
166 """
167 def __init__(self, class_value, generics_manager):
168 super().__init__(generics_manager)
169 self._class_value = class_value
170
171 def _get_wrapped_value(self):
172 return self._class_value
173
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()
182 if add_class_info:
183 return 'Type[%s]' % s
184 return s
185
186 def get_type_var_filter(self):
187 return _TypeVarFilter(self.get_generics(), self.list_type_vars())
188
189 def py__call__(self, arguments):
190 instance, = super().py__call__(arguments)
191 return ValueSet([_GenericInstanceWrapper(instance)])
192
193 def _as_context(self):
194 return _AnnotatedClassContext(self)
195
196 @to_list
197 def py__bases__(self):
198 for base in self._wrapped_value.py__bases__():
199 yield _LazyGenericBaseClass(self, base, self._generics_manager)
200
201 def _create_instance_with_generics(self, generics_manager):
202 return GenericClass(self._class_value, generics_manager)
203
204 def is_sub_class_of(self, class_value):
205 if super().is_sub_class_of(class_value):
206 return True
207 return self._class_value.is_sub_class_of(class_value)
208
209 def with_generics(self, generics_tuple):
210 return self._class_value.with_generics(generics_tuple)
211
212 def infer_type_vars(self, value_set):
213 # Circular
214 from jedi.inference.gradual.annotation import merge_pairwise_generics, merge_type_var_dicts
215
216 annotation_name = self.py__name__()
217 type_var_dict = {}
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(),
223 )
224 else:
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()
231 else:
232 continue
233
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).
238 continue
239
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(
244 type_var_dict,
245 merge_pairwise_generics(self, parent_class),
246 )
247 break
248
249 return type_var_dict
250
251
252class _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
257
258 @iterator_to_value_set
259 def infer(self):
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,
265 base._wrapped_value,
266 TupleGenericManager(tuple(self._remap_type_vars(base))),
267 )
268 else:
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,
275 base,
276 self._generics_manager,
277 )
278 else:
279 yield base
280
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():
285 new = NO_VALUES
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
291 )
292 else:
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])
297 yield new
298
299 def __repr__(self):
300 return '<%s: %s>' % (self.__class__.__name__, self._lazy_base_class)
301
302
303class _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()
308 try:
309 return generics[2].execute_annotation()
310 except IndexError:
311 pass
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()
315
316 def get_type_hint(self, add_class_info=True):
317 return self._wrapped_value.class_value.get_type_hint(add_class_info=False)
318
319
320class _PseudoTreeNameClass(Value):
321 """
322 In typeshed, some classes are defined like this:
323
324 Tuple: _SpecialForm = ...
325
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.
329 """
330 api_type = 'class'
331
332 def __init__(self, parent_context, tree_name):
333 super().__init__(
334 parent_context.inference_state,
335 parent_context
336 )
337 self._tree_name = tree_name
338
339 @property
340 def tree_node(self):
341 return self._tree_name
342
343 def get_filters(self, *args, **kwargs):
344 # TODO this is obviously wrong. Is it though?
345 class EmptyFilter(ClassFilter):
346 def __init__(self):
347 pass
348
349 def get(self, name, **kwargs):
350 return []
351
352 def values(self, **kwargs):
353 return []
354
355 yield EmptyFilter()
356
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')
361
362 @property
363 def name(self):
364 return ValueName(self, self._tree_name)
365
366 def get_qualified_names(self):
367 return (self._tree_name.value,)
368
369 def __repr__(self):
370 return '%s(%s)' % (self.__class__.__name__, self._tree_name.value)
371
372
373class 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
378
379 @property
380 def name(self):
381 return ValueName(self, self._tree_name)
382
383 def _get_wrapped_value(self):
384 return _PseudoTreeNameClass(self.parent_context, self._tree_name)
385
386 def get_signatures(self):
387 return self._wrapped_value.get_signatures()
388
389 def __repr__(self):
390 return '%s(%s)' % (self.__class__.__name__, self._tree_name.value)
391
392
393class 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
399
400 def _get_wrapped_value(self):
401 return _PseudoTreeNameClass(self.parent_context, self._tree_name)
402
403 def __repr__(self):
404 return '%s(%s%s)' % (self.__class__.__name__, self._tree_name.value,
405 self._generics_manager)
406
407
408class 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
415
416 def py__class__(self):
417 return self._class_value
418
419 def get_annotated_class_object(self):
420 return self._class_value
421
422 def get_qualified_names(self):
423 return (self.py__name__(),)
424
425 @property
426 def name(self):
427 return ValueName(self, self._tree_name)
428
429 def _get_wrapped_value(self):
430 object_, = builtin_from_name(self.inference_state, 'object').execute_annotation()
431 return object_
432
433 def __repr__(self):
434 return '<%s: %s>' % (self.__class__.__name__, self._generics_manager)