]>
crepu.dev Git - config.git/blob - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/jedi/inference/star_args.py
2 This module is responsible for inferring *args and **kwargs for signatures.
4 This means for example in this case::
11 The signature here for bar should be `bar(b, c)` instead of bar(*args).
13 from inspect
import Parameter
15 from parso
import tree
17 from jedi
.inference
.utils
import to_list
18 from jedi
.inference
.names
import ParamNameWrapper
19 from jedi
.inference
.helpers
import is_big_annoying_library
22 def _iter_nodes_for_param(param_name
):
23 from parso
.python
.tree
import search_ancestor
24 from jedi
.inference
.arguments
import TreeArguments
26 execution_context
= param_name
.parent_context
27 # Walk up the parso tree to get the FunctionNode we want. We use the parso
28 # tree rather than going via the execution context so that we're agnostic of
29 # the specific scope we're evaluating within (i.e: module or function,
31 function_node
= tree
.search_ancestor(param_name
.tree_name
, 'funcdef', 'lambdef')
32 module_node
= function_node
.get_root_node()
33 start
= function_node
.children
[-1].start_pos
34 end
= function_node
.children
[-1].end_pos
35 for name
in module_node
.get_used_names().get(param_name
.string_name
):
36 if start
<= name
.start_pos
< end
:
37 # Is used in the function
38 argument
= name
.parent
39 if argument
.type == 'argument' \
40 and argument
.children
[0] == '*' * param_name
.star_count
:
41 trailer
= search_ancestor(argument
, 'trailer')
42 if trailer
is not None: # Make sure we're in a function
43 context
= execution_context
.create_context(trailer
)
44 if _goes_to_param_name(param_name
, context
, name
):
45 values
= _to_callables(context
, trailer
)
47 args
= TreeArguments
.create_cached(
48 execution_context
.inference_state
,
50 argument_node
=trailer
.children
[1],
57 def _goes_to_param_name(param_name
, context
, potential_name
):
58 if potential_name
.type != 'name':
60 from jedi
.inference
.names
import TreeNameDefinition
61 found
= TreeNameDefinition(context
, potential_name
).goto()
62 return any(param_name
.parent_context
== p
.parent_context
63 and param_name
.start_pos
== p
.start_pos
67 def _to_callables(context
, trailer
):
68 from jedi
.inference
.syntax_tree
import infer_trailer
70 atom_expr
= trailer
.parent
71 index
= atom_expr
.children
[0] == 'await'
73 values
= context
.infer_node(atom_expr
.children
[index
])
74 for trailer2
in atom_expr
.children
[index
+ 1:]:
75 if trailer
== trailer2
:
77 values
= infer_trailer(context
, values
, trailer2
)
81 def _remove_given_params(arguments
, param_names
):
84 for key
, _
in arguments
.unpack():
91 if count
and p
.maybe_positional_argument():
94 if p
.string_name
in used_keys
and p
.maybe_keyword_argument():
100 def process_params(param_names
, star_count
=3): # default means both * and **
102 if is_big_annoying_library(param_names
[0].parent_context
):
103 # At first this feature can look innocent, but it does a lot of
104 # type inference in some cases, so we just ditch it.
105 yield from param_names
115 original_arg_name
= None
116 original_kwarg_name
= None
117 for p
in param_names
:
119 if kind
== Parameter
.VAR_POSITIONAL
:
121 arg_callables
= _iter_nodes_for_param(p
)
122 original_arg_name
= p
123 elif p
.get_kind() == Parameter
.VAR_KEYWORD
:
125 kwarg_callables
= list(_iter_nodes_for_param(p
))
126 original_kwarg_name
= p
127 elif kind
== Parameter
.KEYWORD_ONLY
:
129 kw_only_names
.append(p
)
130 elif kind
== Parameter
.POSITIONAL_ONLY
:
135 yield ParamNameFixedKind(p
, Parameter
.POSITIONAL_ONLY
)
136 elif star_count
== 2:
137 kw_only_names
.append(ParamNameFixedKind(p
, Parameter
.KEYWORD_ONLY
))
139 used_names
.add(p
.string_name
)
142 # First process *args
143 longest_param_names
= ()
144 found_arg_signature
= False
145 found_kwarg_signature
= False
146 for func_and_argument
in arg_callables
:
147 func
, arguments
= func_and_argument
148 new_star_count
= star_count
149 if func_and_argument
in kwarg_callables
:
150 kwarg_callables
.remove(func_and_argument
)
154 for signature
in func
.get_signatures():
155 found_arg_signature
= True
156 if new_star_count
== 3:
157 found_kwarg_signature
= True
158 args_for_this_func
= []
159 for p
in process_params(
160 list(_remove_given_params(
162 signature
.get_param_names(resolve_stars
=False)
164 if p
.get_kind() == Parameter
.VAR_KEYWORD
:
165 kwarg_names
.append(p
)
166 elif p
.get_kind() == Parameter
.VAR_POSITIONAL
:
168 elif p
.get_kind() == Parameter
.KEYWORD_ONLY
:
169 kw_only_names
.append(p
)
171 args_for_this_func
.append(p
)
172 if len(args_for_this_func
) > len(longest_param_names
):
173 longest_param_names
= args_for_this_func
175 for p
in longest_param_names
:
176 if star_count
== 1 and p
.get_kind() != Parameter
.VAR_POSITIONAL
:
177 yield ParamNameFixedKind(p
, Parameter
.POSITIONAL_ONLY
)
179 if p
.get_kind() == Parameter
.POSITIONAL_OR_KEYWORD
:
180 used_names
.add(p
.string_name
)
183 if not found_arg_signature
and original_arg_name
is not None:
184 yield original_arg_name
188 # Then process **kwargs
189 for func
, arguments
in kwarg_callables
:
190 for signature
in func
.get_signatures():
191 found_kwarg_signature
= True
192 for p
in process_params(
193 list(_remove_given_params(
195 signature
.get_param_names(resolve_stars
=False)
197 if p
.get_kind() == Parameter
.VAR_KEYWORD
:
198 kwarg_names
.append(p
)
199 elif p
.get_kind() == Parameter
.KEYWORD_ONLY
:
200 kw_only_names
.append(p
)
202 for p
in kw_only_names
:
203 if p
.string_name
in used_names
:
206 used_names
.add(p
.string_name
)
208 if not found_kwarg_signature
and original_kwarg_name
is not None:
209 yield original_kwarg_name
214 class ParamNameFixedKind(ParamNameWrapper
):
215 def __init__(self
, param_name
, new_kind
):
216 super().__init
__(param_name
)
217 self
._new
_kind
= new_kind
220 return self
._new
_kind