]> crepu.dev Git - config.git/blob - djavu-asus/emacs/elpy/rpc-venv/lib/python3.11/site-packages/jedi/inference/finder.py
Reorganización de directorios
[config.git] / djavu-asus / emacs / elpy / rpc-venv / lib / python3.11 / site-packages / jedi / inference / finder.py
1 """
2 Searching for names with given scope and name. This is very central in Jedi and
3 Python. The name resolution is quite complicated with descripter,
4 ``__getattribute__``, ``__getattr__``, ``global``, etc.
5
6 If you want to understand name resolution, please read the first few chapters
7 in http://blog.ionelmc.ro/2015/02/09/understanding-python-metaclasses/.
8
9 Flow checks
10 +++++++++++
11
12 Flow checks are not really mature. There's only a check for ``isinstance``. It
13 would check whether a flow has the form of ``if isinstance(a, type_or_tuple)``.
14 Unfortunately every other thing is being ignored (e.g. a == '' would be easy to
15 check for -> a is a string). There's big potential in these checks.
16 """
17
18 from parso.tree import search_ancestor
19 from parso.python.tree import Name
20
21 from jedi import settings
22 from jedi.inference.arguments import TreeArguments
23 from jedi.inference.value import iterable
24 from jedi.inference.base_value import NO_VALUES
25 from jedi.parser_utils import is_scope
26
27
28 def filter_name(filters, name_or_str):
29 """
30 Searches names that are defined in a scope (the different
31 ``filters``), until a name fits.
32 """
33 string_name = name_or_str.value if isinstance(name_or_str, Name) else name_or_str
34 names = []
35 for filter in filters:
36 names = filter.get(string_name)
37 if names:
38 break
39
40 return list(_remove_del_stmt(names))
41
42
43 def _remove_del_stmt(names):
44 # Catch del statements and remove them from results.
45 for name in names:
46 if name.tree_name is not None:
47 definition = name.tree_name.get_definition()
48 if definition is not None and definition.type == 'del_stmt':
49 continue
50 yield name
51
52
53 def check_flow_information(value, flow, search_name, pos):
54 """ Try to find out the type of a variable just with the information that
55 is given by the flows: e.g. It is also responsible for assert checks.::
56
57 if isinstance(k, str):
58 k. # <- completion here
59
60 ensures that `k` is a string.
61 """
62 if not settings.dynamic_flow_information:
63 return None
64
65 result = None
66 if is_scope(flow):
67 # Check for asserts.
68 module_node = flow.get_root_node()
69 try:
70 names = module_node.get_used_names()[search_name.value]
71 except KeyError:
72 return None
73 names = reversed([
74 n for n in names
75 if flow.start_pos <= n.start_pos < (pos or flow.end_pos)
76 ])
77
78 for name in names:
79 ass = search_ancestor(name, 'assert_stmt')
80 if ass is not None:
81 result = _check_isinstance_type(value, ass.assertion, search_name)
82 if result is not None:
83 return result
84
85 if flow.type in ('if_stmt', 'while_stmt'):
86 potential_ifs = [c for c in flow.children[1::4] if c != ':']
87 for if_test in reversed(potential_ifs):
88 if search_name.start_pos > if_test.end_pos:
89 return _check_isinstance_type(value, if_test, search_name)
90 return result
91
92
93 def _get_isinstance_trailer_arglist(node):
94 if node.type in ('power', 'atom_expr') and len(node.children) == 2:
95 # This might be removed if we analyze and, etc
96 first, trailer = node.children
97 if first.type == 'name' and first.value == 'isinstance' \
98 and trailer.type == 'trailer' and trailer.children[0] == '(':
99 return trailer
100 return None
101
102
103 def _check_isinstance_type(value, node, search_name):
104 lazy_cls = None
105 trailer = _get_isinstance_trailer_arglist(node)
106 if trailer is not None and len(trailer.children) == 3:
107 arglist = trailer.children[1]
108 args = TreeArguments(value.inference_state, value, arglist, trailer)
109 param_list = list(args.unpack())
110 # Disallow keyword arguments
111 if len(param_list) == 2 and len(arglist.children) == 3:
112 (key1, _), (key2, lazy_value_cls) = param_list
113 if key1 is None and key2 is None:
114 call = _get_call_string(search_name)
115 is_instance_call = _get_call_string(arglist.children[0])
116 # Do a simple get_code comparison of the strings . They should
117 # just have the same code, and everything will be all right.
118 # There are ways that this is not correct, if some stuff is
119 # redefined in between. However here we don't care, because
120 # it's a heuristic that works pretty well.
121 if call == is_instance_call:
122 lazy_cls = lazy_value_cls
123 if lazy_cls is None:
124 return None
125
126 value_set = NO_VALUES
127 for cls_or_tup in lazy_cls.infer():
128 if isinstance(cls_or_tup, iterable.Sequence) and cls_or_tup.array_type == 'tuple':
129 for lazy_value in cls_or_tup.py__iter__():
130 value_set |= lazy_value.infer().execute_with_values()
131 else:
132 value_set |= cls_or_tup.execute_with_values()
133 return value_set
134
135
136 def _get_call_string(node):
137 if node.parent.type == 'atom_expr':
138 return _get_call_string(node.parent)
139
140 code = ''
141 leaf = node.get_first_leaf()
142 end = node.get_last_leaf().end_pos
143 while leaf.start_pos < end:
144 code += leaf.value
145 leaf = leaf.get_next_leaf()
146 return code