]>
Commit | Line | Data |
---|---|---|
53e6db90 DC |
1 | from abc import abstractproperty |
2 | ||
3 | from parso.tree import search_ancestor | |
4 | ||
5 | from jedi import debug | |
6 | from jedi import settings | |
7 | from jedi.inference import compiled | |
8 | from jedi.inference.compiled.value import CompiledValueFilter | |
9 | from jedi.inference.helpers import values_from_qualified_names, is_big_annoying_library | |
10 | from jedi.inference.filters import AbstractFilter, AnonymousFunctionExecutionFilter | |
11 | from jedi.inference.names import ValueName, TreeNameDefinition, ParamName, \ | |
12 | NameWrapper | |
13 | from jedi.inference.base_value import Value, NO_VALUES, ValueSet, \ | |
14 | iterator_to_value_set, ValueWrapper | |
15 | from jedi.inference.lazy_value import LazyKnownValue, LazyKnownValues | |
16 | from jedi.inference.cache import inference_state_method_cache | |
17 | from jedi.inference.arguments import ValuesArguments, TreeArgumentsWrapper | |
18 | from jedi.inference.value.function import \ | |
19 | FunctionValue, FunctionMixin, OverloadedFunctionValue, \ | |
20 | BaseFunctionExecutionContext, FunctionExecutionContext, FunctionNameInClass | |
21 | from jedi.inference.value.klass import ClassFilter | |
22 | from jedi.inference.value.dynamic_arrays import get_dynamic_array_instance | |
23 | from jedi.parser_utils import function_is_staticmethod, function_is_classmethod | |
24 | ||
25 | ||
26 | class InstanceExecutedParamName(ParamName): | |
27 | def __init__(self, instance, function_value, tree_name): | |
28 | super().__init__( | |
29 | function_value, tree_name, arguments=None) | |
30 | self._instance = instance | |
31 | ||
32 | def infer(self): | |
33 | return ValueSet([self._instance]) | |
34 | ||
35 | def matches_signature(self): | |
36 | return True | |
37 | ||
38 | ||
39 | class AnonymousMethodExecutionFilter(AnonymousFunctionExecutionFilter): | |
40 | def __init__(self, instance, *args, **kwargs): | |
41 | super().__init__(*args, **kwargs) | |
42 | self._instance = instance | |
43 | ||
44 | def _convert_param(self, param, name): | |
45 | if param.position_index == 0: | |
46 | if function_is_classmethod(self._function_value.tree_node): | |
47 | return InstanceExecutedParamName( | |
48 | self._instance.py__class__(), | |
49 | self._function_value, | |
50 | name | |
51 | ) | |
52 | elif not function_is_staticmethod(self._function_value.tree_node): | |
53 | return InstanceExecutedParamName( | |
54 | self._instance, | |
55 | self._function_value, | |
56 | name | |
57 | ) | |
58 | return super()._convert_param(param, name) | |
59 | ||
60 | ||
61 | class AnonymousMethodExecutionContext(BaseFunctionExecutionContext): | |
62 | def __init__(self, instance, value): | |
63 | super().__init__(value) | |
64 | self.instance = instance | |
65 | ||
66 | def get_filters(self, until_position=None, origin_scope=None): | |
67 | yield AnonymousMethodExecutionFilter( | |
68 | self.instance, self, self._value, | |
69 | until_position=until_position, | |
70 | origin_scope=origin_scope, | |
71 | ) | |
72 | ||
73 | def get_param_names(self): | |
74 | param_names = list(self._value.get_param_names()) | |
75 | # set the self name | |
76 | param_names[0] = InstanceExecutedParamName( | |
77 | self.instance, | |
78 | self._value, | |
79 | param_names[0].tree_name | |
80 | ) | |
81 | return param_names | |
82 | ||
83 | ||
84 | class MethodExecutionContext(FunctionExecutionContext): | |
85 | def __init__(self, instance, *args, **kwargs): | |
86 | super().__init__(*args, **kwargs) | |
87 | self.instance = instance | |
88 | ||
89 | ||
90 | class AbstractInstanceValue(Value): | |
91 | api_type = 'instance' | |
92 | ||
93 | def __init__(self, inference_state, parent_context, class_value): | |
94 | super().__init__(inference_state, parent_context) | |
95 | # Generated instances are classes that are just generated by self | |
96 | # (No arguments) used. | |
97 | self.class_value = class_value | |
98 | ||
99 | def is_instance(self): | |
100 | return True | |
101 | ||
102 | def get_qualified_names(self): | |
103 | return self.class_value.get_qualified_names() | |
104 | ||
105 | def get_annotated_class_object(self): | |
106 | return self.class_value # This is the default. | |
107 | ||
108 | def py__class__(self): | |
109 | return self.class_value | |
110 | ||
111 | def py__bool__(self): | |
112 | # Signalize that we don't know about the bool type. | |
113 | return None | |
114 | ||
115 | @abstractproperty | |
116 | def name(self): | |
117 | raise NotImplementedError | |
118 | ||
119 | def get_signatures(self): | |
120 | call_funcs = self.py__getattribute__('__call__').py__get__(self, self.class_value) | |
121 | return [s.bind(self) for s in call_funcs.get_signatures()] | |
122 | ||
123 | def get_function_slot_names(self, name): | |
124 | # Python classes don't look at the dictionary of the instance when | |
125 | # looking up `__call__`. This is something that has to do with Python's | |
126 | # internal slot system (note: not __slots__, but C slots). | |
127 | for filter in self.get_filters(include_self_names=False): | |
128 | names = filter.get(name) | |
129 | if names: | |
130 | return names | |
131 | return [] | |
132 | ||
133 | def execute_function_slots(self, names, *inferred_args): | |
134 | return ValueSet.from_sets( | |
135 | name.infer().execute_with_values(*inferred_args) | |
136 | for name in names | |
137 | ) | |
138 | ||
139 | def get_type_hint(self, add_class_info=True): | |
140 | return self.py__name__() | |
141 | ||
142 | def py__getitem__(self, index_value_set, contextualized_node): | |
143 | names = self.get_function_slot_names('__getitem__') | |
144 | if not names: | |
145 | return super().py__getitem__( | |
146 | index_value_set, | |
147 | contextualized_node, | |
148 | ) | |
149 | ||
150 | args = ValuesArguments([index_value_set]) | |
151 | return ValueSet.from_sets(name.infer().execute(args) for name in names) | |
152 | ||
153 | def py__iter__(self, contextualized_node=None): | |
154 | iter_slot_names = self.get_function_slot_names('__iter__') | |
155 | if not iter_slot_names: | |
156 | return super().py__iter__(contextualized_node) | |
157 | ||
158 | def iterate(): | |
159 | for generator in self.execute_function_slots(iter_slot_names): | |
160 | yield from generator.py__next__(contextualized_node) | |
161 | return iterate() | |
162 | ||
163 | def __repr__(self): | |
164 | return "<%s of %s>" % (self.__class__.__name__, self.class_value) | |
165 | ||
166 | ||
167 | class CompiledInstance(AbstractInstanceValue): | |
168 | # This is not really a compiled class, it's just an instance from a | |
169 | # compiled class. | |
170 | def __init__(self, inference_state, parent_context, class_value, arguments): | |
171 | super().__init__(inference_state, parent_context, class_value) | |
172 | self._arguments = arguments | |
173 | ||
174 | def get_filters(self, origin_scope=None, include_self_names=True): | |
175 | class_value = self.get_annotated_class_object() | |
176 | class_filters = class_value.get_filters( | |
177 | origin_scope=origin_scope, | |
178 | is_instance=True, | |
179 | ) | |
180 | for f in class_filters: | |
181 | yield CompiledInstanceClassFilter(self, f) | |
182 | ||
183 | @property | |
184 | def name(self): | |
185 | return compiled.CompiledValueName(self, self.class_value.name.string_name) | |
186 | ||
187 | def is_stub(self): | |
188 | return False | |
189 | ||
190 | ||
191 | class _BaseTreeInstance(AbstractInstanceValue): | |
192 | @property | |
193 | def array_type(self): | |
194 | name = self.class_value.py__name__() | |
195 | if name in ['list', 'set', 'dict'] \ | |
196 | and self.parent_context.get_root_context().is_builtins_module(): | |
197 | return name | |
198 | return None | |
199 | ||
200 | @property | |
201 | def name(self): | |
202 | return ValueName(self, self.class_value.name.tree_name) | |
203 | ||
204 | def get_filters(self, origin_scope=None, include_self_names=True): | |
205 | class_value = self.get_annotated_class_object() | |
206 | if include_self_names: | |
207 | for cls in class_value.py__mro__(): | |
208 | if not cls.is_compiled(): | |
209 | # In this case we're excluding compiled objects that are | |
210 | # not fake objects. It doesn't make sense for normal | |
211 | # compiled objects to search for self variables. | |
212 | yield SelfAttributeFilter(self, class_value, cls.as_context(), origin_scope) | |
213 | ||
214 | class_filters = class_value.get_filters( | |
215 | origin_scope=origin_scope, | |
216 | is_instance=True, | |
217 | ) | |
218 | for f in class_filters: | |
219 | if isinstance(f, ClassFilter): | |
220 | yield InstanceClassFilter(self, f) | |
221 | elif isinstance(f, CompiledValueFilter): | |
222 | yield CompiledInstanceClassFilter(self, f) | |
223 | else: | |
224 | # Propably from the metaclass. | |
225 | yield f | |
226 | ||
227 | @inference_state_method_cache() | |
228 | def create_instance_context(self, class_context, node): | |
229 | new = node | |
230 | while True: | |
231 | func_node = new | |
232 | new = search_ancestor(new, 'funcdef', 'classdef') | |
233 | if class_context.tree_node is new: | |
234 | func = FunctionValue.from_context(class_context, func_node) | |
235 | bound_method = BoundMethod(self, class_context, func) | |
236 | if func_node.name.value == '__init__': | |
237 | context = bound_method.as_context(self._arguments) | |
238 | else: | |
239 | context = bound_method.as_context() | |
240 | break | |
241 | return context.create_context(node) | |
242 | ||
243 | def py__getattribute__alternatives(self, string_name): | |
244 | ''' | |
245 | Since nothing was inferred, now check the __getattr__ and | |
246 | __getattribute__ methods. Stubs don't need to be checked, because | |
247 | they don't contain any logic. | |
248 | ''' | |
249 | if self.is_stub(): | |
250 | return NO_VALUES | |
251 | ||
252 | name = compiled.create_simple_object(self.inference_state, string_name) | |
253 | ||
254 | # This is a little bit special. `__getattribute__` is in Python | |
255 | # executed before `__getattr__`. But: I know no use case, where | |
256 | # this could be practical and where Jedi would return wrong types. | |
257 | # If you ever find something, let me know! | |
258 | # We are inversing this, because a hand-crafted `__getattribute__` | |
259 | # could still call another hand-crafted `__getattr__`, but not the | |
260 | # other way around. | |
261 | if is_big_annoying_library(self.parent_context): | |
262 | return NO_VALUES | |
263 | names = (self.get_function_slot_names('__getattr__') | |
264 | or self.get_function_slot_names('__getattribute__')) | |
265 | return self.execute_function_slots(names, name) | |
266 | ||
267 | def py__next__(self, contextualized_node=None): | |
268 | name = u'__next__' | |
269 | next_slot_names = self.get_function_slot_names(name) | |
270 | if next_slot_names: | |
271 | yield LazyKnownValues( | |
272 | self.execute_function_slots(next_slot_names) | |
273 | ) | |
274 | else: | |
275 | debug.warning('Instance has no __next__ function in %s.', self) | |
276 | ||
277 | def py__call__(self, arguments): | |
278 | names = self.get_function_slot_names('__call__') | |
279 | if not names: | |
280 | # Means the Instance is not callable. | |
281 | return super().py__call__(arguments) | |
282 | ||
283 | return ValueSet.from_sets(name.infer().execute(arguments) for name in names) | |
284 | ||
285 | def py__get__(self, instance, class_value): | |
286 | """ | |
287 | obj may be None. | |
288 | """ | |
289 | # Arguments in __get__ descriptors are obj, class. | |
290 | # `method` is the new parent of the array, don't know if that's good. | |
291 | for cls in self.class_value.py__mro__(): | |
292 | result = cls.py__get__on_class(self, instance, class_value) | |
293 | if result is not NotImplemented: | |
294 | return result | |
295 | ||
296 | names = self.get_function_slot_names('__get__') | |
297 | if names: | |
298 | if instance is None: | |
299 | instance = compiled.builtin_from_name(self.inference_state, 'None') | |
300 | return self.execute_function_slots(names, instance, class_value) | |
301 | else: | |
302 | return ValueSet([self]) | |
303 | ||
304 | ||
305 | class TreeInstance(_BaseTreeInstance): | |
306 | def __init__(self, inference_state, parent_context, class_value, arguments): | |
307 | # I don't think that dynamic append lookups should happen here. That | |
308 | # sounds more like something that should go to py__iter__. | |
309 | if class_value.py__name__() in ['list', 'set'] \ | |
310 | and parent_context.get_root_context().is_builtins_module(): | |
311 | # compare the module path with the builtin name. | |
312 | if settings.dynamic_array_additions: | |
313 | arguments = get_dynamic_array_instance(self, arguments) | |
314 | ||
315 | super().__init__(inference_state, parent_context, class_value) | |
316 | self._arguments = arguments | |
317 | self.tree_node = class_value.tree_node | |
318 | ||
319 | # This can recurse, if the initialization of the class includes a reference | |
320 | # to itself. | |
321 | @inference_state_method_cache(default=None) | |
322 | def _get_annotated_class_object(self): | |
323 | from jedi.inference.gradual.annotation import py__annotations__, \ | |
324 | infer_type_vars_for_execution | |
325 | ||
326 | args = InstanceArguments(self, self._arguments) | |
327 | for signature in self.class_value.py__getattribute__('__init__').get_signatures(): | |
328 | # Just take the first result, it should always be one, because we | |
329 | # control the typeshed code. | |
330 | funcdef = signature.value.tree_node | |
331 | if funcdef is None or funcdef.type != 'funcdef' \ | |
332 | or not signature.matches_signature(args): | |
333 | # First check if the signature even matches, if not we don't | |
334 | # need to infer anything. | |
335 | continue | |
336 | bound_method = BoundMethod(self, self.class_value.as_context(), signature.value) | |
337 | all_annotations = py__annotations__(funcdef) | |
338 | type_var_dict = infer_type_vars_for_execution(bound_method, args, all_annotations) | |
339 | if type_var_dict: | |
340 | defined, = self.class_value.define_generics( | |
341 | infer_type_vars_for_execution(signature.value, args, all_annotations), | |
342 | ) | |
343 | debug.dbg('Inferred instance value as %s', defined, color='BLUE') | |
344 | return defined | |
345 | return None | |
346 | ||
347 | def get_annotated_class_object(self): | |
348 | return self._get_annotated_class_object() or self.class_value | |
349 | ||
350 | def get_key_values(self): | |
351 | values = NO_VALUES | |
352 | if self.array_type == 'dict': | |
353 | for i, (key, instance) in enumerate(self._arguments.unpack()): | |
354 | if key is None and i == 0: | |
355 | values |= ValueSet.from_sets( | |
356 | v.get_key_values() | |
357 | for v in instance.infer() | |
358 | if v.array_type == 'dict' | |
359 | ) | |
360 | if key: | |
361 | values |= ValueSet([compiled.create_simple_object( | |
362 | self.inference_state, | |
363 | key, | |
364 | )]) | |
365 | ||
366 | return values | |
367 | ||
368 | def py__simple_getitem__(self, index): | |
369 | if self.array_type == 'dict': | |
370 | # Logic for dict({'foo': bar}) and dict(foo=bar) | |
371 | # reversed, because: | |
372 | # >>> dict({'a': 1}, a=3) | |
373 | # {'a': 3} | |
374 | # TODO tuple initializations | |
375 | # >>> dict([('a', 4)]) | |
376 | # {'a': 4} | |
377 | for key, lazy_context in reversed(list(self._arguments.unpack())): | |
378 | if key is None: | |
379 | values = ValueSet.from_sets( | |
380 | dct_value.py__simple_getitem__(index) | |
381 | for dct_value in lazy_context.infer() | |
382 | if dct_value.array_type == 'dict' | |
383 | ) | |
384 | if values: | |
385 | return values | |
386 | else: | |
387 | if key == index: | |
388 | return lazy_context.infer() | |
389 | return super().py__simple_getitem__(index) | |
390 | ||
391 | def __repr__(self): | |
392 | return "<%s of %s(%s)>" % (self.__class__.__name__, self.class_value, | |
393 | self._arguments) | |
394 | ||
395 | ||
396 | class AnonymousInstance(_BaseTreeInstance): | |
397 | _arguments = None | |
398 | ||
399 | ||
400 | class CompiledInstanceName(NameWrapper): | |
401 | @iterator_to_value_set | |
402 | def infer(self): | |
403 | for result_value in self._wrapped_name.infer(): | |
404 | if result_value.api_type == 'function': | |
405 | yield CompiledBoundMethod(result_value) | |
406 | else: | |
407 | yield result_value | |
408 | ||
409 | ||
410 | class CompiledInstanceClassFilter(AbstractFilter): | |
411 | def __init__(self, instance, f): | |
412 | self._instance = instance | |
413 | self._class_filter = f | |
414 | ||
415 | def get(self, name): | |
416 | return self._convert(self._class_filter.get(name)) | |
417 | ||
418 | def values(self): | |
419 | return self._convert(self._class_filter.values()) | |
420 | ||
421 | def _convert(self, names): | |
422 | return [CompiledInstanceName(n) for n in names] | |
423 | ||
424 | ||
425 | class BoundMethod(FunctionMixin, ValueWrapper): | |
426 | def __init__(self, instance, class_context, function): | |
427 | super().__init__(function) | |
428 | self.instance = instance | |
429 | self._class_context = class_context | |
430 | ||
431 | def is_bound_method(self): | |
432 | return True | |
433 | ||
434 | @property | |
435 | def name(self): | |
436 | return FunctionNameInClass( | |
437 | self._class_context, | |
438 | super().name | |
439 | ) | |
440 | ||
441 | def py__class__(self): | |
442 | c, = values_from_qualified_names(self.inference_state, 'types', 'MethodType') | |
443 | return c | |
444 | ||
445 | def _get_arguments(self, arguments): | |
446 | assert arguments is not None | |
447 | return InstanceArguments(self.instance, arguments) | |
448 | ||
449 | def _as_context(self, arguments=None): | |
450 | if arguments is None: | |
451 | return AnonymousMethodExecutionContext(self.instance, self) | |
452 | ||
453 | arguments = self._get_arguments(arguments) | |
454 | return MethodExecutionContext(self.instance, self, arguments) | |
455 | ||
456 | def py__call__(self, arguments): | |
457 | if isinstance(self._wrapped_value, OverloadedFunctionValue): | |
458 | return self._wrapped_value.py__call__(self._get_arguments(arguments)) | |
459 | ||
460 | function_execution = self.as_context(arguments) | |
461 | return function_execution.infer() | |
462 | ||
463 | def get_signature_functions(self): | |
464 | return [ | |
465 | BoundMethod(self.instance, self._class_context, f) | |
466 | for f in self._wrapped_value.get_signature_functions() | |
467 | ] | |
468 | ||
469 | def get_signatures(self): | |
470 | return [sig.bind(self) for sig in super().get_signatures()] | |
471 | ||
472 | def __repr__(self): | |
473 | return '<%s: %s>' % (self.__class__.__name__, self._wrapped_value) | |
474 | ||
475 | ||
476 | class CompiledBoundMethod(ValueWrapper): | |
477 | def is_bound_method(self): | |
478 | return True | |
479 | ||
480 | def get_signatures(self): | |
481 | return [sig.bind(self) for sig in self._wrapped_value.get_signatures()] | |
482 | ||
483 | ||
484 | class SelfName(TreeNameDefinition): | |
485 | """ | |
486 | This name calculates the parent_context lazily. | |
487 | """ | |
488 | def __init__(self, instance, class_context, tree_name): | |
489 | self._instance = instance | |
490 | self.class_context = class_context | |
491 | self.tree_name = tree_name | |
492 | ||
493 | @property | |
494 | def parent_context(self): | |
495 | return self._instance.create_instance_context(self.class_context, self.tree_name) | |
496 | ||
497 | def get_defining_qualified_value(self): | |
498 | return self._instance | |
499 | ||
500 | def infer(self): | |
501 | stmt = search_ancestor(self.tree_name, 'expr_stmt') | |
502 | if stmt is not None: | |
503 | if stmt.children[1].type == "annassign": | |
504 | from jedi.inference.gradual.annotation import infer_annotation | |
505 | values = infer_annotation( | |
506 | self.parent_context, stmt.children[1].children[1] | |
507 | ).execute_annotation() | |
508 | if values: | |
509 | return values | |
510 | return super().infer() | |
511 | ||
512 | ||
513 | class LazyInstanceClassName(NameWrapper): | |
514 | def __init__(self, instance, class_member_name): | |
515 | super().__init__(class_member_name) | |
516 | self._instance = instance | |
517 | ||
518 | @iterator_to_value_set | |
519 | def infer(self): | |
520 | for result_value in self._wrapped_name.infer(): | |
521 | yield from result_value.py__get__(self._instance, self._instance.py__class__()) | |
522 | ||
523 | def get_signatures(self): | |
524 | return self.infer().get_signatures() | |
525 | ||
526 | def get_defining_qualified_value(self): | |
527 | return self._instance | |
528 | ||
529 | ||
530 | class InstanceClassFilter(AbstractFilter): | |
531 | """ | |
532 | This filter is special in that it uses the class filter and wraps the | |
533 | resulting names in LazyInstanceClassName. The idea is that the class name | |
534 | filtering can be very flexible and always be reflected in instances. | |
535 | """ | |
536 | def __init__(self, instance, class_filter): | |
537 | self._instance = instance | |
538 | self._class_filter = class_filter | |
539 | ||
540 | def get(self, name): | |
541 | return self._convert(self._class_filter.get(name)) | |
542 | ||
543 | def values(self): | |
544 | return self._convert(self._class_filter.values()) | |
545 | ||
546 | def _convert(self, names): | |
547 | return [ | |
548 | LazyInstanceClassName(self._instance, n) | |
549 | for n in names | |
550 | ] | |
551 | ||
552 | def __repr__(self): | |
553 | return '<%s for %s>' % (self.__class__.__name__, self._class_filter) | |
554 | ||
555 | ||
556 | class SelfAttributeFilter(ClassFilter): | |
557 | """ | |
558 | This class basically filters all the use cases where `self.*` was assigned. | |
559 | """ | |
560 | def __init__(self, instance, instance_class, node_context, origin_scope): | |
561 | super().__init__( | |
562 | class_value=instance_class, | |
563 | node_context=node_context, | |
564 | origin_scope=origin_scope, | |
565 | is_instance=True, | |
566 | ) | |
567 | self._instance = instance | |
568 | ||
569 | def _filter(self, names): | |
570 | start, end = self._parser_scope.start_pos, self._parser_scope.end_pos | |
571 | names = [n for n in names if start < n.start_pos < end] | |
572 | return self._filter_self_names(names) | |
573 | ||
574 | def _filter_self_names(self, names): | |
575 | for name in names: | |
576 | trailer = name.parent | |
577 | if trailer.type == 'trailer' \ | |
578 | and len(trailer.parent.children) == 2 \ | |
579 | and trailer.children[0] == '.': | |
580 | if name.is_definition() and self._access_possible(name): | |
581 | # TODO filter non-self assignments instead of this bad | |
582 | # filter. | |
583 | if self._is_in_right_scope(trailer.parent.children[0], name): | |
584 | yield name | |
585 | ||
586 | def _is_in_right_scope(self, self_name, name): | |
587 | self_context = self._node_context.create_context(self_name) | |
588 | names = self_context.goto(self_name, position=self_name.start_pos) | |
589 | return any( | |
590 | n.api_type == 'param' | |
591 | and n.tree_name.get_definition().position_index == 0 | |
592 | and n.parent_context.tree_node is self._parser_scope | |
593 | for n in names | |
594 | ) | |
595 | ||
596 | def _convert_names(self, names): | |
597 | return [SelfName(self._instance, self._node_context, name) for name in names] | |
598 | ||
599 | def _check_flows(self, names): | |
600 | return names | |
601 | ||
602 | ||
603 | class InstanceArguments(TreeArgumentsWrapper): | |
604 | def __init__(self, instance, arguments): | |
605 | super().__init__(arguments) | |
606 | self.instance = instance | |
607 | ||
608 | def unpack(self, func=None): | |
609 | yield None, LazyKnownValue(self.instance) | |
610 | yield from self._wrapped_arguments.unpack(func) |