7
7
from __future__ import annotations
8
8
9
9
import itertools
10
- from collections .abc import Callable , Iterable , Iterator
10
+ from collections .abc import Callable , Iterator
11
11
from functools import partial
12
- from typing import Any
12
+ from typing import Any , Type , Union , cast
13
13
14
- from astroid import arguments , bases , helpers , inference_tip , nodes , objects , util
14
+ from astroid import arguments , helpers , inference_tip , nodes , objects , util
15
15
from astroid .builder import AstroidBuilder
16
16
from astroid .context import InferenceContext
17
17
from astroid .exceptions import (
23
23
)
24
24
from astroid .manager import AstroidManager
25
25
from astroid .nodes import scoped_nodes
26
- from astroid .typing import InferenceResult , SuccessfulInferenceResult
26
+ from astroid .typing import (
27
+ ConstFactoryResult ,
28
+ InferenceResult ,
29
+ SuccessfulInferenceResult ,
30
+ )
31
+
32
+ ContainerObjects = Union [
33
+ objects .FrozenSet ,
34
+ objects .DictItems ,
35
+ objects .DictKeys ,
36
+ objects .DictValues ,
37
+ ]
38
+
39
+ BuiltContainers = Union [
40
+ Type [tuple ],
41
+ Type [list ],
42
+ Type [set ],
43
+ Type [frozenset ],
44
+ ]
27
45
28
46
OBJECT_DUNDER_NEW = "object.__new__"
29
47
@@ -232,18 +250,19 @@ def _container_generic_inference(
232
250
return transformed
233
251
234
252
235
- def _container_generic_transform ( # pylint: disable=inconsistent-return-statements
253
+ def _container_generic_transform (
236
254
arg : SuccessfulInferenceResult ,
237
255
context : InferenceContext | None ,
238
256
klass : type [nodes .BaseContainer ],
239
- iterables : tuple [type [nodes .NodeNG ] | type [bases . Proxy ], ...],
240
- build_elts : type [ Iterable [ Any ]] ,
257
+ iterables : tuple [type [nodes .BaseContainer ] | type [ContainerObjects ], ...],
258
+ build_elts : BuiltContainers ,
241
259
) -> nodes .BaseContainer | None :
242
260
if isinstance (arg , klass ):
243
261
return arg
244
262
if isinstance (arg , iterables ):
263
+ arg = cast (ContainerObjects , arg )
245
264
if all (isinstance (elt , nodes .Const ) for elt in arg .elts ):
246
- elts = [elt .value for elt in arg .elts ]
265
+ elts = [cast ( nodes . Const , elt ) .value for elt in arg .elts ]
247
266
else :
248
267
# TODO: Does not handle deduplication for sets.
249
268
elts = []
@@ -264,16 +283,16 @@ def _container_generic_transform( # pylint: disable=inconsistent-return-stateme
264
283
elif isinstance (arg , nodes .Const ) and isinstance (arg .value , (str , bytes )):
265
284
elts = arg .value
266
285
else :
267
- return
286
+ return None
268
287
return klass .from_elements (elts = build_elts (elts ))
269
288
270
289
271
290
def _infer_builtin_container (
272
291
node : nodes .Call ,
273
292
context : InferenceContext | None ,
274
293
klass : type [nodes .BaseContainer ],
275
- iterables : tuple [type [nodes .NodeNG ] | type [bases . Proxy ], ...],
276
- build_elts : type [ Iterable [ Any ]] ,
294
+ iterables : tuple [type [nodes .NodeNG ] | type [ContainerObjects ], ...],
295
+ build_elts : BuiltContainers ,
277
296
) -> nodes .BaseContainer :
278
297
transform_func = partial (
279
298
_container_generic_transform ,
@@ -944,8 +963,8 @@ def _build_dict_with_elements(elements):
944
963
945
964
946
965
def _infer_copy_method (
947
- node : nodes .Call , context : InferenceContext | None = None
948
- ) -> Iterator [nodes . NodeNG ]:
966
+ node : nodes .Call , context : InferenceContext | None = None , ** kwargs : Any
967
+ ) -> Iterator [InferenceResult ]:
949
968
assert isinstance (node .func , nodes .Attribute )
950
969
inferred_orig , inferred_copy = itertools .tee (node .func .expr .infer (context = context ))
951
970
if all (
@@ -973,33 +992,44 @@ def _is_str_format_call(node: nodes.Call) -> bool:
973
992
974
993
975
994
def _infer_str_format_call (
976
- node : nodes .Call , context : InferenceContext | None = None
977
- ) -> Iterator [nodes . Const | util .UninferableBase ]:
995
+ node : nodes .Call , context : InferenceContext | None = None , ** kwargs : Any
996
+ ) -> Iterator [ConstFactoryResult | util .UninferableBase ]:
978
997
"""Return a Const node based on the template and passed arguments."""
979
998
call = arguments .CallSite .from_call (node , context = context )
999
+ assert isinstance (node .func , (nodes .Attribute , nodes .AssignAttr , nodes .DelAttr ))
1000
+
1001
+ value : nodes .Const
980
1002
if isinstance (node .func .expr , nodes .Name ):
981
- value : nodes .Const | None = helpers .safe_infer (node .func .expr )
982
- if value is None :
1003
+ if not (inferred := helpers .safe_infer (node .func .expr )) or not isinstance (
1004
+ inferred , nodes .Const
1005
+ ):
983
1006
return iter ([util .Uninferable ])
984
- else :
1007
+ value = inferred
1008
+ elif isinstance (node .func .expr , nodes .Const ):
985
1009
value = node .func .expr
1010
+ else : # pragma: no cover
1011
+ return iter ([util .Uninferable ])
986
1012
987
1013
format_template = value .value
988
1014
989
1015
# Get the positional arguments passed
990
- inferred_positional = [
991
- helpers .safe_infer (i , context ) for i in call .positional_arguments
992
- ]
993
- if not all (isinstance (i , nodes .Const ) for i in inferred_positional ):
994
- return iter ([util .Uninferable ])
1016
+ inferred_positional : list [nodes .Const ] = []
1017
+ for i in call .positional_arguments :
1018
+ one_inferred = helpers .safe_infer (i , context )
1019
+ if not isinstance (one_inferred , nodes .Const ):
1020
+ return iter ([util .Uninferable ])
1021
+ inferred_positional .append (one_inferred )
1022
+
995
1023
pos_values : list [str ] = [i .value for i in inferred_positional ]
996
1024
997
1025
# Get the keyword arguments passed
998
- inferred_keyword = {
999
- k : helpers .safe_infer (v , context ) for k , v in call .keyword_arguments .items ()
1000
- }
1001
- if not all (isinstance (i , nodes .Const ) for i in inferred_keyword .values ()):
1002
- return iter ([util .Uninferable ])
1026
+ inferred_keyword : dict [str , nodes .Const ] = {}
1027
+ for k , v in call .keyword_arguments .items ():
1028
+ one_inferred = helpers .safe_infer (v , context )
1029
+ if not isinstance (one_inferred , nodes .Const ):
1030
+ return iter ([util .Uninferable ])
1031
+ inferred_keyword [k ] = one_inferred
1032
+
1003
1033
keyword_values : dict [str , str ] = {k : v .value for k , v in inferred_keyword .items ()}
1004
1034
1005
1035
try :
0 commit comments