77from __future__ import annotations
88
99import itertools
10- from collections .abc import Callable , Iterable , Iterator
10+ from collections .abc import Callable , Iterator
1111from functools import partial
12- from typing import Any
12+ from typing import Any , Type , Union , cast
1313
14- from astroid import arguments , bases , helpers , inference_tip , nodes , objects , util
14+ from astroid import arguments , helpers , inference_tip , nodes , objects , util
1515from astroid .builder import AstroidBuilder
1616from astroid .context import InferenceContext
1717from astroid .exceptions import (
2323)
2424from astroid .manager import AstroidManager
2525from 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+ ]
2745
2846OBJECT_DUNDER_NEW = "object.__new__"
2947
@@ -232,18 +250,19 @@ def _container_generic_inference(
232250 return transformed
233251
234252
235- def _container_generic_transform ( # pylint: disable=inconsistent-return-statements
253+ def _container_generic_transform (
236254 arg : SuccessfulInferenceResult ,
237255 context : InferenceContext | None ,
238256 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 ,
241259) -> nodes .BaseContainer | None :
242260 if isinstance (arg , klass ):
243261 return arg
244262 if isinstance (arg , iterables ):
263+ arg = cast (ContainerObjects , arg )
245264 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 ]
247266 else :
248267 # TODO: Does not handle deduplication for sets.
249268 elts = []
@@ -264,16 +283,16 @@ def _container_generic_transform( # pylint: disable=inconsistent-return-stateme
264283 elif isinstance (arg , nodes .Const ) and isinstance (arg .value , (str , bytes )):
265284 elts = arg .value
266285 else :
267- return
286+ return None
268287 return klass .from_elements (elts = build_elts (elts ))
269288
270289
271290def _infer_builtin_container (
272291 node : nodes .Call ,
273292 context : InferenceContext | None ,
274293 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 ,
277296) -> nodes .BaseContainer :
278297 transform_func = partial (
279298 _container_generic_transform ,
@@ -944,8 +963,8 @@ def _build_dict_with_elements(elements):
944963
945964
946965def _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 ]:
949968 assert isinstance (node .func , nodes .Attribute )
950969 inferred_orig , inferred_copy = itertools .tee (node .func .expr .infer (context = context ))
951970 if all (
@@ -973,33 +992,44 @@ def _is_str_format_call(node: nodes.Call) -> bool:
973992
974993
975994def _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 ]:
978997 """Return a Const node based on the template and passed arguments."""
979998 call = arguments .CallSite .from_call (node , context = context )
999+ assert isinstance (node .func , (nodes .Attribute , nodes .AssignAttr , nodes .DelAttr ))
1000+
1001+ value : nodes .Const
9801002 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+ ):
9831006 return iter ([util .Uninferable ])
984- else :
1007+ value = inferred
1008+ elif isinstance (node .func .expr , nodes .Const ):
9851009 value = node .func .expr
1010+ else : # pragma: no cover
1011+ return iter ([util .Uninferable ])
9861012
9871013 format_template = value .value
9881014
9891015 # 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+
9951023 pos_values : list [str ] = [i .value for i in inferred_positional ]
9961024
9971025 # 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+
10031033 keyword_values : dict [str , str ] = {k : v .value for k , v in inferred_keyword .items ()}
10041034
10051035 try :
0 commit comments