brain_builtin_inference.py 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  1. # Copyright (c) 2014-2021 Claudiu Popa <pcmanticore@gmail.com>
  2. # Copyright (c) 2014-2015 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
  3. # Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
  4. # Copyright (c) 2015 Rene Zhang <rz99@cornell.edu>
  5. # Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
  6. # Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi>
  7. # Copyright (c) 2019-2020 Bryce Guinta <bryce.guinta@protonmail.com>
  8. # Copyright (c) 2019 Stanislav Levin <slev@altlinux.org>
  9. # Copyright (c) 2019 David Liu <david@cs.toronto.edu>
  10. # Copyright (c) 2019 Frédéric Chapoton <fchapoton2@gmail.com>
  11. # Copyright (c) 2020-2021 hippo91 <guillaume.peillex@gmail.com>
  12. # Copyright (c) 2020 David Gilman <davidgilman1@gmail.com>
  13. # Copyright (c) 2020 Ram Rachum <ram@rachum.com>
  14. # Copyright (c) 2021 Pierre Sassoulas <pierre.sassoulas@gmail.com>
  15. # Copyright (c) 2021 Daniël van Noord <13665637+DanielNoord@users.noreply.github.com>
  16. # Copyright (c) 2021 Nick Drozd <nicholasdrozd@gmail.com>
  17. # Copyright (c) 2021 Marc Mueller <30130371+cdce8p@users.noreply.github.com>
  18. # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
  19. # For details: https://github.com/PyCQA/astroid/blob/main/LICENSE
  20. """Astroid hooks for various builtins."""
  21. from functools import partial
  22. from astroid import arguments, helpers, inference_tip, nodes, objects, util
  23. from astroid.builder import AstroidBuilder
  24. from astroid.exceptions import (
  25. AstroidTypeError,
  26. AttributeInferenceError,
  27. InferenceError,
  28. MroError,
  29. UseInferenceDefault,
  30. )
  31. from astroid.manager import AstroidManager
  32. from astroid.nodes import scoped_nodes
  33. OBJECT_DUNDER_NEW = "object.__new__"
  34. STR_CLASS = """
  35. class whatever(object):
  36. def join(self, iterable):
  37. return {rvalue}
  38. def replace(self, old, new, count=None):
  39. return {rvalue}
  40. def format(self, *args, **kwargs):
  41. return {rvalue}
  42. def encode(self, encoding='ascii', errors=None):
  43. return b''
  44. def decode(self, encoding='ascii', errors=None):
  45. return u''
  46. def capitalize(self):
  47. return {rvalue}
  48. def title(self):
  49. return {rvalue}
  50. def lower(self):
  51. return {rvalue}
  52. def upper(self):
  53. return {rvalue}
  54. def swapcase(self):
  55. return {rvalue}
  56. def index(self, sub, start=None, end=None):
  57. return 0
  58. def find(self, sub, start=None, end=None):
  59. return 0
  60. def count(self, sub, start=None, end=None):
  61. return 0
  62. def strip(self, chars=None):
  63. return {rvalue}
  64. def lstrip(self, chars=None):
  65. return {rvalue}
  66. def rstrip(self, chars=None):
  67. return {rvalue}
  68. def rjust(self, width, fillchar=None):
  69. return {rvalue}
  70. def center(self, width, fillchar=None):
  71. return {rvalue}
  72. def ljust(self, width, fillchar=None):
  73. return {rvalue}
  74. """
  75. BYTES_CLASS = """
  76. class whatever(object):
  77. def join(self, iterable):
  78. return {rvalue}
  79. def replace(self, old, new, count=None):
  80. return {rvalue}
  81. def decode(self, encoding='ascii', errors=None):
  82. return u''
  83. def capitalize(self):
  84. return {rvalue}
  85. def title(self):
  86. return {rvalue}
  87. def lower(self):
  88. return {rvalue}
  89. def upper(self):
  90. return {rvalue}
  91. def swapcase(self):
  92. return {rvalue}
  93. def index(self, sub, start=None, end=None):
  94. return 0
  95. def find(self, sub, start=None, end=None):
  96. return 0
  97. def count(self, sub, start=None, end=None):
  98. return 0
  99. def strip(self, chars=None):
  100. return {rvalue}
  101. def lstrip(self, chars=None):
  102. return {rvalue}
  103. def rstrip(self, chars=None):
  104. return {rvalue}
  105. def rjust(self, width, fillchar=None):
  106. return {rvalue}
  107. def center(self, width, fillchar=None):
  108. return {rvalue}
  109. def ljust(self, width, fillchar=None):
  110. return {rvalue}
  111. """
  112. def _extend_string_class(class_node, code, rvalue):
  113. """function to extend builtin str/unicode class"""
  114. code = code.format(rvalue=rvalue)
  115. fake = AstroidBuilder(AstroidManager()).string_build(code)["whatever"]
  116. for method in fake.mymethods():
  117. method.parent = class_node
  118. method.lineno = None
  119. method.col_offset = None
  120. if "__class__" in method.locals:
  121. method.locals["__class__"] = [class_node]
  122. class_node.locals[method.name] = [method]
  123. method.parent = class_node
  124. def _extend_builtins(class_transforms):
  125. builtin_ast = AstroidManager().builtins_module
  126. for class_name, transform in class_transforms.items():
  127. transform(builtin_ast[class_name])
  128. _extend_builtins(
  129. {
  130. "bytes": partial(_extend_string_class, code=BYTES_CLASS, rvalue="b''"),
  131. "str": partial(_extend_string_class, code=STR_CLASS, rvalue="''"),
  132. }
  133. )
  134. def _builtin_filter_predicate(node, builtin_name):
  135. if (
  136. builtin_name == "type"
  137. and node.root().name == "re"
  138. and isinstance(node.func, nodes.Name)
  139. and node.func.name == "type"
  140. and isinstance(node.parent, nodes.Assign)
  141. and len(node.parent.targets) == 1
  142. and isinstance(node.parent.targets[0], nodes.AssignName)
  143. and node.parent.targets[0].name in {"Pattern", "Match"}
  144. ):
  145. # Handle re.Pattern and re.Match in brain_re
  146. # Match these patterns from stdlib/re.py
  147. # ```py
  148. # Pattern = type(...)
  149. # Match = type(...)
  150. # ```
  151. return False
  152. if isinstance(node.func, nodes.Name) and node.func.name == builtin_name:
  153. return True
  154. if isinstance(node.func, nodes.Attribute):
  155. return (
  156. node.func.attrname == "fromkeys"
  157. and isinstance(node.func.expr, nodes.Name)
  158. and node.func.expr.name == "dict"
  159. )
  160. return False
  161. def register_builtin_transform(transform, builtin_name):
  162. """Register a new transform function for the given *builtin_name*.
  163. The transform function must accept two parameters, a node and
  164. an optional context.
  165. """
  166. def _transform_wrapper(node, context=None):
  167. result = transform(node, context=context)
  168. if result:
  169. if not result.parent:
  170. # Let the transformation function determine
  171. # the parent for its result. Otherwise,
  172. # we set it to be the node we transformed from.
  173. result.parent = node
  174. if result.lineno is None:
  175. result.lineno = node.lineno
  176. # Can be a 'Module' see https://github.com/PyCQA/pylint/issues/4671
  177. # We don't have a regression test on this one: tread carefully
  178. if hasattr(result, "col_offset") and result.col_offset is None:
  179. result.col_offset = node.col_offset
  180. return iter([result])
  181. AstroidManager().register_transform(
  182. nodes.Call,
  183. inference_tip(_transform_wrapper),
  184. partial(_builtin_filter_predicate, builtin_name=builtin_name),
  185. )
  186. def _container_generic_inference(node, context, node_type, transform):
  187. args = node.args
  188. if not args:
  189. return node_type()
  190. if len(node.args) > 1:
  191. raise UseInferenceDefault()
  192. (arg,) = args
  193. transformed = transform(arg)
  194. if not transformed:
  195. try:
  196. inferred = next(arg.infer(context=context))
  197. except (InferenceError, StopIteration) as exc:
  198. raise UseInferenceDefault from exc
  199. if inferred is util.Uninferable:
  200. raise UseInferenceDefault
  201. transformed = transform(inferred)
  202. if not transformed or transformed is util.Uninferable:
  203. raise UseInferenceDefault
  204. return transformed
  205. def _container_generic_transform( # pylint: disable=inconsistent-return-statements
  206. arg, context, klass, iterables, build_elts
  207. ):
  208. if isinstance(arg, klass):
  209. return arg
  210. if isinstance(arg, iterables):
  211. if all(isinstance(elt, nodes.Const) for elt in arg.elts):
  212. elts = [elt.value for elt in arg.elts]
  213. else:
  214. # TODO: Does not handle deduplication for sets.
  215. elts = []
  216. for element in arg.elts:
  217. if not element:
  218. continue
  219. inferred = helpers.safe_infer(element, context=context)
  220. if inferred:
  221. evaluated_object = nodes.EvaluatedObject(
  222. original=element, value=inferred
  223. )
  224. elts.append(evaluated_object)
  225. elif isinstance(arg, nodes.Dict):
  226. # Dicts need to have consts as strings already.
  227. if not all(isinstance(elt[0], nodes.Const) for elt in arg.items):
  228. raise UseInferenceDefault()
  229. elts = [item[0].value for item in arg.items]
  230. elif isinstance(arg, nodes.Const) and isinstance(arg.value, (str, bytes)):
  231. elts = arg.value
  232. else:
  233. return
  234. return klass.from_elements(elts=build_elts(elts))
  235. def _infer_builtin_container(
  236. node, context, klass=None, iterables=None, build_elts=None
  237. ):
  238. transform_func = partial(
  239. _container_generic_transform,
  240. context=context,
  241. klass=klass,
  242. iterables=iterables,
  243. build_elts=build_elts,
  244. )
  245. return _container_generic_inference(node, context, klass, transform_func)
  246. # pylint: disable=invalid-name
  247. infer_tuple = partial(
  248. _infer_builtin_container,
  249. klass=nodes.Tuple,
  250. iterables=(
  251. nodes.List,
  252. nodes.Set,
  253. objects.FrozenSet,
  254. objects.DictItems,
  255. objects.DictKeys,
  256. objects.DictValues,
  257. ),
  258. build_elts=tuple,
  259. )
  260. infer_list = partial(
  261. _infer_builtin_container,
  262. klass=nodes.List,
  263. iterables=(
  264. nodes.Tuple,
  265. nodes.Set,
  266. objects.FrozenSet,
  267. objects.DictItems,
  268. objects.DictKeys,
  269. objects.DictValues,
  270. ),
  271. build_elts=list,
  272. )
  273. infer_set = partial(
  274. _infer_builtin_container,
  275. klass=nodes.Set,
  276. iterables=(nodes.List, nodes.Tuple, objects.FrozenSet, objects.DictKeys),
  277. build_elts=set,
  278. )
  279. infer_frozenset = partial(
  280. _infer_builtin_container,
  281. klass=objects.FrozenSet,
  282. iterables=(nodes.List, nodes.Tuple, nodes.Set, objects.FrozenSet, objects.DictKeys),
  283. build_elts=frozenset,
  284. )
  285. def _get_elts(arg, context):
  286. def is_iterable(n):
  287. return isinstance(n, (nodes.List, nodes.Tuple, nodes.Set))
  288. try:
  289. inferred = next(arg.infer(context))
  290. except (InferenceError, StopIteration) as exc:
  291. raise UseInferenceDefault from exc
  292. if isinstance(inferred, nodes.Dict):
  293. items = inferred.items
  294. elif is_iterable(inferred):
  295. items = []
  296. for elt in inferred.elts:
  297. # If an item is not a pair of two items,
  298. # then fallback to the default inference.
  299. # Also, take in consideration only hashable items,
  300. # tuples and consts. We are choosing Names as well.
  301. if not is_iterable(elt):
  302. raise UseInferenceDefault()
  303. if len(elt.elts) != 2:
  304. raise UseInferenceDefault()
  305. if not isinstance(elt.elts[0], (nodes.Tuple, nodes.Const, nodes.Name)):
  306. raise UseInferenceDefault()
  307. items.append(tuple(elt.elts))
  308. else:
  309. raise UseInferenceDefault()
  310. return items
  311. def infer_dict(node, context=None):
  312. """Try to infer a dict call to a Dict node.
  313. The function treats the following cases:
  314. * dict()
  315. * dict(mapping)
  316. * dict(iterable)
  317. * dict(iterable, **kwargs)
  318. * dict(mapping, **kwargs)
  319. * dict(**kwargs)
  320. If a case can't be inferred, we'll fallback to default inference.
  321. """
  322. call = arguments.CallSite.from_call(node, context=context)
  323. if call.has_invalid_arguments() or call.has_invalid_keywords():
  324. raise UseInferenceDefault
  325. args = call.positional_arguments
  326. kwargs = list(call.keyword_arguments.items())
  327. if not args and not kwargs:
  328. # dict()
  329. return nodes.Dict()
  330. if kwargs and not args:
  331. # dict(a=1, b=2, c=4)
  332. items = [(nodes.Const(key), value) for key, value in kwargs]
  333. elif len(args) == 1 and kwargs:
  334. # dict(some_iterable, b=2, c=4)
  335. elts = _get_elts(args[0], context)
  336. keys = [(nodes.Const(key), value) for key, value in kwargs]
  337. items = elts + keys
  338. elif len(args) == 1:
  339. items = _get_elts(args[0], context)
  340. else:
  341. raise UseInferenceDefault()
  342. value = nodes.Dict(
  343. col_offset=node.col_offset, lineno=node.lineno, parent=node.parent
  344. )
  345. value.postinit(items)
  346. return value
  347. def infer_super(node, context=None):
  348. """Understand super calls.
  349. There are some restrictions for what can be understood:
  350. * unbounded super (one argument form) is not understood.
  351. * if the super call is not inside a function (classmethod or method),
  352. then the default inference will be used.
  353. * if the super arguments can't be inferred, the default inference
  354. will be used.
  355. """
  356. if len(node.args) == 1:
  357. # Ignore unbounded super.
  358. raise UseInferenceDefault
  359. scope = node.scope()
  360. if not isinstance(scope, nodes.FunctionDef):
  361. # Ignore non-method uses of super.
  362. raise UseInferenceDefault
  363. if scope.type not in ("classmethod", "method"):
  364. # Not interested in staticmethods.
  365. raise UseInferenceDefault
  366. cls = scoped_nodes.get_wrapping_class(scope)
  367. if not node.args:
  368. mro_pointer = cls
  369. # In we are in a classmethod, the interpreter will fill
  370. # automatically the class as the second argument, not an instance.
  371. if scope.type == "classmethod":
  372. mro_type = cls
  373. else:
  374. mro_type = cls.instantiate_class()
  375. else:
  376. try:
  377. mro_pointer = next(node.args[0].infer(context=context))
  378. except (InferenceError, StopIteration) as exc:
  379. raise UseInferenceDefault from exc
  380. try:
  381. mro_type = next(node.args[1].infer(context=context))
  382. except (InferenceError, StopIteration) as exc:
  383. raise UseInferenceDefault from exc
  384. if mro_pointer is util.Uninferable or mro_type is util.Uninferable:
  385. # No way we could understand this.
  386. raise UseInferenceDefault
  387. super_obj = objects.Super(
  388. mro_pointer=mro_pointer, mro_type=mro_type, self_class=cls, scope=scope
  389. )
  390. super_obj.parent = node
  391. return super_obj
  392. def _infer_getattr_args(node, context):
  393. if len(node.args) not in (2, 3):
  394. # Not a valid getattr call.
  395. raise UseInferenceDefault
  396. try:
  397. obj = next(node.args[0].infer(context=context))
  398. attr = next(node.args[1].infer(context=context))
  399. except (InferenceError, StopIteration) as exc:
  400. raise UseInferenceDefault from exc
  401. if obj is util.Uninferable or attr is util.Uninferable:
  402. # If one of the arguments is something we can't infer,
  403. # then also make the result of the getattr call something
  404. # which is unknown.
  405. return util.Uninferable, util.Uninferable
  406. is_string = isinstance(attr, nodes.Const) and isinstance(attr.value, str)
  407. if not is_string:
  408. raise UseInferenceDefault
  409. return obj, attr.value
  410. def infer_getattr(node, context=None):
  411. """Understand getattr calls
  412. If one of the arguments is an Uninferable object, then the
  413. result will be an Uninferable object. Otherwise, the normal attribute
  414. lookup will be done.
  415. """
  416. obj, attr = _infer_getattr_args(node, context)
  417. if (
  418. obj is util.Uninferable
  419. or attr is util.Uninferable
  420. or not hasattr(obj, "igetattr")
  421. ):
  422. return util.Uninferable
  423. try:
  424. return next(obj.igetattr(attr, context=context))
  425. except (StopIteration, InferenceError, AttributeInferenceError):
  426. if len(node.args) == 3:
  427. # Try to infer the default and return it instead.
  428. try:
  429. return next(node.args[2].infer(context=context))
  430. except (StopIteration, InferenceError) as exc:
  431. raise UseInferenceDefault from exc
  432. raise UseInferenceDefault
  433. def infer_hasattr(node, context=None):
  434. """Understand hasattr calls
  435. This always guarantees three possible outcomes for calling
  436. hasattr: Const(False) when we are sure that the object
  437. doesn't have the intended attribute, Const(True) when
  438. we know that the object has the attribute and Uninferable
  439. when we are unsure of the outcome of the function call.
  440. """
  441. try:
  442. obj, attr = _infer_getattr_args(node, context)
  443. if (
  444. obj is util.Uninferable
  445. or attr is util.Uninferable
  446. or not hasattr(obj, "getattr")
  447. ):
  448. return util.Uninferable
  449. obj.getattr(attr, context=context)
  450. except UseInferenceDefault:
  451. # Can't infer something from this function call.
  452. return util.Uninferable
  453. except AttributeInferenceError:
  454. # Doesn't have it.
  455. return nodes.Const(False)
  456. return nodes.Const(True)
  457. def infer_callable(node, context=None):
  458. """Understand callable calls
  459. This follows Python's semantics, where an object
  460. is callable if it provides an attribute __call__,
  461. even though that attribute is something which can't be
  462. called.
  463. """
  464. if len(node.args) != 1:
  465. # Invalid callable call.
  466. raise UseInferenceDefault
  467. argument = node.args[0]
  468. try:
  469. inferred = next(argument.infer(context=context))
  470. except (InferenceError, StopIteration):
  471. return util.Uninferable
  472. if inferred is util.Uninferable:
  473. return util.Uninferable
  474. return nodes.Const(inferred.callable())
  475. def infer_property(node, context=None):
  476. """Understand `property` class
  477. This only infers the output of `property`
  478. call, not the arguments themselves.
  479. """
  480. if len(node.args) < 1:
  481. # Invalid property call.
  482. raise UseInferenceDefault
  483. getter = node.args[0]
  484. try:
  485. inferred = next(getter.infer(context=context))
  486. except (InferenceError, StopIteration) as exc:
  487. raise UseInferenceDefault from exc
  488. if not isinstance(inferred, (nodes.FunctionDef, nodes.Lambda)):
  489. raise UseInferenceDefault
  490. return objects.Property(
  491. function=inferred,
  492. name=inferred.name,
  493. doc=getattr(inferred, "doc", None),
  494. lineno=node.lineno,
  495. parent=node,
  496. col_offset=node.col_offset,
  497. )
  498. def infer_bool(node, context=None):
  499. """Understand bool calls."""
  500. if len(node.args) > 1:
  501. # Invalid bool call.
  502. raise UseInferenceDefault
  503. if not node.args:
  504. return nodes.Const(False)
  505. argument = node.args[0]
  506. try:
  507. inferred = next(argument.infer(context=context))
  508. except (InferenceError, StopIteration):
  509. return util.Uninferable
  510. if inferred is util.Uninferable:
  511. return util.Uninferable
  512. bool_value = inferred.bool_value(context=context)
  513. if bool_value is util.Uninferable:
  514. return util.Uninferable
  515. return nodes.Const(bool_value)
  516. def infer_type(node, context=None):
  517. """Understand the one-argument form of *type*."""
  518. if len(node.args) != 1:
  519. raise UseInferenceDefault
  520. return helpers.object_type(node.args[0], context)
  521. def infer_slice(node, context=None):
  522. """Understand `slice` calls."""
  523. args = node.args
  524. if not 0 < len(args) <= 3:
  525. raise UseInferenceDefault
  526. infer_func = partial(helpers.safe_infer, context=context)
  527. args = [infer_func(arg) for arg in args]
  528. for arg in args:
  529. if not arg or arg is util.Uninferable:
  530. raise UseInferenceDefault
  531. if not isinstance(arg, nodes.Const):
  532. raise UseInferenceDefault
  533. if not isinstance(arg.value, (type(None), int)):
  534. raise UseInferenceDefault
  535. if len(args) < 3:
  536. # Make sure we have 3 arguments.
  537. args.extend([None] * (3 - len(args)))
  538. slice_node = nodes.Slice(
  539. lineno=node.lineno, col_offset=node.col_offset, parent=node.parent
  540. )
  541. slice_node.postinit(*args)
  542. return slice_node
  543. def _infer_object__new__decorator(node, context=None):
  544. # Instantiate class immediately
  545. # since that's what @object.__new__ does
  546. return iter((node.instantiate_class(),))
  547. def _infer_object__new__decorator_check(node):
  548. """Predicate before inference_tip
  549. Check if the given ClassDef has an @object.__new__ decorator
  550. """
  551. if not node.decorators:
  552. return False
  553. for decorator in node.decorators.nodes:
  554. if isinstance(decorator, nodes.Attribute):
  555. if decorator.as_string() == OBJECT_DUNDER_NEW:
  556. return True
  557. return False
  558. def infer_issubclass(callnode, context=None):
  559. """Infer issubclass() calls
  560. :param nodes.Call callnode: an `issubclass` call
  561. :param InferenceContext context: the context for the inference
  562. :rtype nodes.Const: Boolean Const value of the `issubclass` call
  563. :raises UseInferenceDefault: If the node cannot be inferred
  564. """
  565. call = arguments.CallSite.from_call(callnode, context=context)
  566. if call.keyword_arguments:
  567. # issubclass doesn't support keyword arguments
  568. raise UseInferenceDefault("TypeError: issubclass() takes no keyword arguments")
  569. if len(call.positional_arguments) != 2:
  570. raise UseInferenceDefault(
  571. f"Expected two arguments, got {len(call.positional_arguments)}"
  572. )
  573. # The left hand argument is the obj to be checked
  574. obj_node, class_or_tuple_node = call.positional_arguments
  575. try:
  576. obj_type = next(obj_node.infer(context=context))
  577. except (InferenceError, StopIteration) as exc:
  578. raise UseInferenceDefault from exc
  579. if not isinstance(obj_type, nodes.ClassDef):
  580. raise UseInferenceDefault("TypeError: arg 1 must be class")
  581. # The right hand argument is the class(es) that the given
  582. # object is to be checked against.
  583. try:
  584. class_container = _class_or_tuple_to_container(
  585. class_or_tuple_node, context=context
  586. )
  587. except InferenceError as exc:
  588. raise UseInferenceDefault from exc
  589. try:
  590. issubclass_bool = helpers.object_issubclass(obj_type, class_container, context)
  591. except AstroidTypeError as exc:
  592. raise UseInferenceDefault("TypeError: " + str(exc)) from exc
  593. except MroError as exc:
  594. raise UseInferenceDefault from exc
  595. return nodes.Const(issubclass_bool)
  596. def infer_isinstance(callnode, context=None):
  597. """Infer isinstance calls
  598. :param nodes.Call callnode: an isinstance call
  599. :param InferenceContext context: context for call
  600. (currently unused but is a common interface for inference)
  601. :rtype nodes.Const: Boolean Const value of isinstance call
  602. :raises UseInferenceDefault: If the node cannot be inferred
  603. """
  604. call = arguments.CallSite.from_call(callnode, context=context)
  605. if call.keyword_arguments:
  606. # isinstance doesn't support keyword arguments
  607. raise UseInferenceDefault("TypeError: isinstance() takes no keyword arguments")
  608. if len(call.positional_arguments) != 2:
  609. raise UseInferenceDefault(
  610. f"Expected two arguments, got {len(call.positional_arguments)}"
  611. )
  612. # The left hand argument is the obj to be checked
  613. obj_node, class_or_tuple_node = call.positional_arguments
  614. # The right hand argument is the class(es) that the given
  615. # obj is to be check is an instance of
  616. try:
  617. class_container = _class_or_tuple_to_container(
  618. class_or_tuple_node, context=context
  619. )
  620. except InferenceError as exc:
  621. raise UseInferenceDefault from exc
  622. try:
  623. isinstance_bool = helpers.object_isinstance(obj_node, class_container, context)
  624. except AstroidTypeError as exc:
  625. raise UseInferenceDefault("TypeError: " + str(exc)) from exc
  626. except MroError as exc:
  627. raise UseInferenceDefault from exc
  628. if isinstance_bool is util.Uninferable:
  629. raise UseInferenceDefault
  630. return nodes.Const(isinstance_bool)
  631. def _class_or_tuple_to_container(node, context=None):
  632. # Move inferences results into container
  633. # to simplify later logic
  634. # raises InferenceError if any of the inferences fall through
  635. try:
  636. node_infer = next(node.infer(context=context))
  637. except StopIteration as e:
  638. raise InferenceError(node=node, context=context) from e
  639. # arg2 MUST be a type or a TUPLE of types
  640. # for isinstance
  641. if isinstance(node_infer, nodes.Tuple):
  642. try:
  643. class_container = [
  644. next(node.infer(context=context)) for node in node_infer.elts
  645. ]
  646. except StopIteration as e:
  647. raise InferenceError(node=node, context=context) from e
  648. class_container = [
  649. klass_node for klass_node in class_container if klass_node is not None
  650. ]
  651. else:
  652. class_container = [node_infer]
  653. return class_container
  654. def infer_len(node, context=None):
  655. """Infer length calls
  656. :param nodes.Call node: len call to infer
  657. :param context.InferenceContext: node context
  658. :rtype nodes.Const: a Const node with the inferred length, if possible
  659. """
  660. call = arguments.CallSite.from_call(node, context=context)
  661. if call.keyword_arguments:
  662. raise UseInferenceDefault("TypeError: len() must take no keyword arguments")
  663. if len(call.positional_arguments) != 1:
  664. raise UseInferenceDefault(
  665. "TypeError: len() must take exactly one argument "
  666. "({len}) given".format(len=len(call.positional_arguments))
  667. )
  668. [argument_node] = call.positional_arguments
  669. try:
  670. return nodes.Const(helpers.object_len(argument_node, context=context))
  671. except (AstroidTypeError, InferenceError) as exc:
  672. raise UseInferenceDefault(str(exc)) from exc
  673. def infer_str(node, context=None):
  674. """Infer str() calls
  675. :param nodes.Call node: str() call to infer
  676. :param context.InferenceContext: node context
  677. :rtype nodes.Const: a Const containing an empty string
  678. """
  679. call = arguments.CallSite.from_call(node, context=context)
  680. if call.keyword_arguments:
  681. raise UseInferenceDefault("TypeError: str() must take no keyword arguments")
  682. try:
  683. return nodes.Const("")
  684. except (AstroidTypeError, InferenceError) as exc:
  685. raise UseInferenceDefault(str(exc)) from exc
  686. def infer_int(node, context=None):
  687. """Infer int() calls
  688. :param nodes.Call node: int() call to infer
  689. :param context.InferenceContext: node context
  690. :rtype nodes.Const: a Const containing the integer value of the int() call
  691. """
  692. call = arguments.CallSite.from_call(node, context=context)
  693. if call.keyword_arguments:
  694. raise UseInferenceDefault("TypeError: int() must take no keyword arguments")
  695. if call.positional_arguments:
  696. try:
  697. first_value = next(call.positional_arguments[0].infer(context=context))
  698. except (InferenceError, StopIteration) as exc:
  699. raise UseInferenceDefault(str(exc)) from exc
  700. if first_value is util.Uninferable:
  701. raise UseInferenceDefault
  702. if isinstance(first_value, nodes.Const) and isinstance(
  703. first_value.value, (int, str)
  704. ):
  705. try:
  706. actual_value = int(first_value.value)
  707. except ValueError:
  708. return nodes.Const(0)
  709. return nodes.Const(actual_value)
  710. return nodes.Const(0)
  711. def infer_dict_fromkeys(node, context=None):
  712. """Infer dict.fromkeys
  713. :param nodes.Call node: dict.fromkeys() call to infer
  714. :param context.InferenceContext context: node context
  715. :rtype nodes.Dict:
  716. a Dictionary containing the values that astroid was able to infer.
  717. In case the inference failed for any reason, an empty dictionary
  718. will be inferred instead.
  719. """
  720. def _build_dict_with_elements(elements):
  721. new_node = nodes.Dict(
  722. col_offset=node.col_offset, lineno=node.lineno, parent=node.parent
  723. )
  724. new_node.postinit(elements)
  725. return new_node
  726. call = arguments.CallSite.from_call(node, context=context)
  727. if call.keyword_arguments:
  728. raise UseInferenceDefault("TypeError: int() must take no keyword arguments")
  729. if len(call.positional_arguments) not in {1, 2}:
  730. raise UseInferenceDefault(
  731. "TypeError: Needs between 1 and 2 positional arguments"
  732. )
  733. default = nodes.Const(None)
  734. values = call.positional_arguments[0]
  735. try:
  736. inferred_values = next(values.infer(context=context))
  737. except (InferenceError, StopIteration):
  738. return _build_dict_with_elements([])
  739. if inferred_values is util.Uninferable:
  740. return _build_dict_with_elements([])
  741. # Limit to a couple of potential values, as this can become pretty complicated
  742. accepted_iterable_elements = (nodes.Const,)
  743. if isinstance(inferred_values, (nodes.List, nodes.Set, nodes.Tuple)):
  744. elements = inferred_values.elts
  745. for element in elements:
  746. if not isinstance(element, accepted_iterable_elements):
  747. # Fallback to an empty dict
  748. return _build_dict_with_elements([])
  749. elements_with_value = [(element, default) for element in elements]
  750. return _build_dict_with_elements(elements_with_value)
  751. if isinstance(inferred_values, nodes.Const) and isinstance(
  752. inferred_values.value, (str, bytes)
  753. ):
  754. elements = [
  755. (nodes.Const(element), default) for element in inferred_values.value
  756. ]
  757. return _build_dict_with_elements(elements)
  758. if isinstance(inferred_values, nodes.Dict):
  759. keys = inferred_values.itered()
  760. for key in keys:
  761. if not isinstance(key, accepted_iterable_elements):
  762. # Fallback to an empty dict
  763. return _build_dict_with_elements([])
  764. elements_with_value = [(element, default) for element in keys]
  765. return _build_dict_with_elements(elements_with_value)
  766. # Fallback to an empty dictionary
  767. return _build_dict_with_elements([])
  768. # Builtins inference
  769. register_builtin_transform(infer_bool, "bool")
  770. register_builtin_transform(infer_super, "super")
  771. register_builtin_transform(infer_callable, "callable")
  772. register_builtin_transform(infer_property, "property")
  773. register_builtin_transform(infer_getattr, "getattr")
  774. register_builtin_transform(infer_hasattr, "hasattr")
  775. register_builtin_transform(infer_tuple, "tuple")
  776. register_builtin_transform(infer_set, "set")
  777. register_builtin_transform(infer_list, "list")
  778. register_builtin_transform(infer_dict, "dict")
  779. register_builtin_transform(infer_frozenset, "frozenset")
  780. register_builtin_transform(infer_type, "type")
  781. register_builtin_transform(infer_slice, "slice")
  782. register_builtin_transform(infer_isinstance, "isinstance")
  783. register_builtin_transform(infer_issubclass, "issubclass")
  784. register_builtin_transform(infer_len, "len")
  785. register_builtin_transform(infer_str, "str")
  786. register_builtin_transform(infer_int, "int")
  787. register_builtin_transform(infer_dict_fromkeys, "dict.fromkeys")
  788. # Infer object.__new__ calls
  789. AstroidManager().register_transform(
  790. nodes.ClassDef,
  791. inference_tip(_infer_object__new__decorator),
  792. _infer_object__new__decorator_check,
  793. )