]>
crepu.dev Git - config.git/blob - djavu-asus/emacs/elpy/rpc-venv/lib/python3.11/site-packages/jedi/inference/param.py
1 from collections
import defaultdict
2 from inspect
import Parameter
5 from jedi
.inference
.utils
import PushBackIterator
6 from jedi
.inference
import analysis
7 from jedi
.inference
.lazy_value
import LazyKnownValue
, \
8 LazyTreeValue
, LazyUnknownValue
9 from jedi
.inference
.value
import iterable
10 from jedi
.inference
.names
import ParamName
13 def _add_argument_issue(error_name
, lazy_value
, message
):
14 if isinstance(lazy_value
, LazyTreeValue
):
15 node
= lazy_value
.data
16 if node
.parent
.type == 'argument':
18 return analysis
.add(lazy_value
.context
, error_name
, node
, message
)
21 class ExecutedParamName(ParamName
):
22 def __init__(self
, function_value
, arguments
, param_node
, lazy_value
, is_default
=False):
23 super().__init
__(function_value
, param_node
.name
, arguments
=arguments
)
24 self
._lazy
_value
= lazy_value
25 self
._is
_default
= is_default
28 return self
._lazy
_value
.infer()
30 def matches_signature(self
):
33 argument_values
= self
.infer().py__class__()
34 if self
.get_kind() in (Parameter
.VAR_POSITIONAL
, Parameter
.VAR_KEYWORD
):
36 annotations
= self
.infer_annotation(execute_annotation
=False)
38 # If we cannot infer annotations - or there aren't any - pretend
39 # that the signature matches.
41 matches
= any(c1
.is_sub_class_of(c2
)
42 for c1
in argument_values
43 for c2
in annotations
.gather_annotation_classes())
44 debug
.dbg("param compare %s: %s <=> %s",
45 matches
, argument_values
, annotations
, color
='BLUE')
49 return '<%s: %s>' % (self
.__class
__.__name
__, self
.string_name
)
52 def get_executed_param_names_and_issues(function_value
, arguments
):
55 - a list of `ExecutedParamName`s corresponding to the arguments of the
56 function execution `function_value`, containing the inferred value of
57 those arguments (whether explicit or default)
58 - a list of the issues encountered while building that list
62 def foo(a, b, c=None, d='d'): ...
67 Then for the execution of `foo`, this will return a tuple containing:
68 - a list with entries for each parameter a, b, c & d; the entries for a,
69 c, & d will have their values (42, 'c' and 'd' respectively) included.
70 - a list with a single entry about the lack of a value for `b`
72 def too_many_args(argument
):
73 m
= _error_argument_count(funcdef
, len(unpacked_va
))
74 # Just report an error for the first param that is not needed (like
76 if arguments
.get_calling_nodes():
77 # There might not be a valid calling node so check for that first.
80 'type-error-too-many-arguments',
87 debug
.warning('non-public warning: %s', m
)
89 issues
= [] # List[Optional[analysis issue]]
92 funcdef
= function_value
.tree_node
93 # Default params are part of the value where the function was defined.
94 # This means that they might have access on class variables that the
95 # function itself doesn't have.
96 default_param_context
= function_value
.get_default_param_context()
98 for param
in funcdef
.get_params():
99 param_dict
[param
.name
.value
] = param
100 unpacked_va
= list(arguments
.unpack(funcdef
))
101 var_arg_iterator
= PushBackIterator(iter(unpacked_va
))
103 non_matching_keys
= defaultdict(lambda: [])
106 had_multiple_value_error
= False
107 for param
in funcdef
.get_params():
108 # The value and key can both be null. There, the defaults apply.
109 # args / kwargs will just be empty arrays / dicts, respectively.
110 # Wrong value count is just ignored. If you try to test cases that are
111 # not allowed in Python, Jedi will maybe not show any completions.
113 key
, argument
= next(var_arg_iterator
, (None, None))
114 while key
is not None:
117 key_param
= param_dict
[key
]
119 non_matching_keys
[key
] = argument
122 had_multiple_value_error
= True
123 m
= ("TypeError: %s() got multiple values for keyword argument '%s'."
124 % (funcdef
.name
, key
))
125 for contextualized_node
in arguments
.get_calling_nodes():
127 analysis
.add(contextualized_node
.context
,
128 'type-error-multiple-values',
129 contextualized_node
.node
, message
=m
)
132 keys_used
[key
] = ExecutedParamName(
133 function_value
, arguments
, key_param
, argument
)
134 key
, argument
= next(var_arg_iterator
, (None, None))
137 result_params
.append(keys_used
[param
.name
.value
])
142 if param
.star_count
== 1:
145 if argument
is not None:
146 lazy_value_list
.append(argument
)
147 for key
, argument
in var_arg_iterator
:
148 # Iterate until a key argument is found.
150 var_arg_iterator
.push_back((key
, argument
))
152 lazy_value_list
.append(argument
)
153 seq
= iterable
.FakeTuple(function_value
.inference_state
, lazy_value_list
)
154 result_arg
= LazyKnownValue(seq
)
155 elif param
.star_count
== 2:
156 if argument
is not None:
157 too_many_args(argument
)
159 dct
= iterable
.FakeDict(function_value
.inference_state
, dict(non_matching_keys
))
160 result_arg
= LazyKnownValue(dct
)
161 non_matching_keys
= {}
165 # No value: Return an empty container
166 if param
.default
is None:
167 result_arg
= LazyUnknownValue()
169 for contextualized_node
in arguments
.get_calling_nodes():
170 m
= _error_argument_count(funcdef
, len(unpacked_va
))
173 contextualized_node
.context
,
174 'type-error-too-few-arguments',
175 contextualized_node
.node
,
180 result_arg
= LazyTreeValue(default_param_context
, param
.default
)
183 result_arg
= argument
185 result_params
.append(ExecutedParamName(
186 function_value
, arguments
, param
, result_arg
, is_default
=is_default
188 if not isinstance(result_arg
, LazyUnknownValue
):
189 keys_used
[param
.name
.value
] = result_params
[-1]
192 # All arguments should be handed over to the next function. It's not
193 # about the values inside, it's about the names. Jedi needs to now that
194 # there's nothing to find for certain names.
195 for k
in set(param_dict
) - set(keys_used
):
196 param
= param_dict
[k
]
198 if not (non_matching_keys
or had_multiple_value_error
199 or param
.star_count
or param
.default
):
200 # add a warning only if there's not another one.
201 for contextualized_node
in arguments
.get_calling_nodes():
202 m
= _error_argument_count(funcdef
, len(unpacked_va
))
204 analysis
.add(contextualized_node
.context
,
205 'type-error-too-few-arguments',
206 contextualized_node
.node
, message
=m
)
209 for key
, lazy_value
in non_matching_keys
.items():
210 m
= "TypeError: %s() got an unexpected keyword argument '%s'." \
211 % (funcdef
.name
, key
)
214 'type-error-keyword-argument',
220 remaining_arguments
= list(var_arg_iterator
)
221 if remaining_arguments
:
222 first_key
, lazy_value
= remaining_arguments
[0]
223 too_many_args(lazy_value
)
224 return result_params
, issues
227 def get_executed_param_names(function_value
, arguments
):
229 Return a list of `ExecutedParamName`s corresponding to the arguments of the
230 function execution `function_value`, containing the inferred value of those
231 arguments (whether explicit or default). Any issues building this list (for
232 example required arguments which are missing in the invocation) are ignored.
236 def foo(a, b, c=None, d='d'): ...
241 Then for the execution of `foo`, this will return a list containing entries
242 for each parameter a, b, c & d; the entries for a, c, & d will have their
243 values (42, 'c' and 'd' respectively) included.
245 return get_executed_param_names_and_issues(function_value
, arguments
)[0]
248 def _error_argument_count(funcdef
, actual_count
):
249 params
= funcdef
.get_params()
250 default_arguments
= sum(1 for p
in params
if p
.default
or p
.star_count
)
252 if default_arguments
== 0:
255 before
= 'from %s to ' % (len(params
) - default_arguments
)
256 return ('TypeError: %s() takes %s%s arguments (%s given).'
257 % (funcdef
.name
, before
, len(params
), actual_count
))