raw_building.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
  2. # For details: https://github.com/pylint-dev/astroid/blob/main/LICENSE
  3. # Copyright (c) https://github.com/pylint-dev/astroid/blob/main/CONTRIBUTORS.txt
  4. """this module contains a set of functions to create astroid trees from scratch
  5. (build_* functions) or from living object (object_build_* functions)
  6. """
  7. from __future__ import annotations
  8. import builtins
  9. import inspect
  10. import io
  11. import logging
  12. import os
  13. import sys
  14. import types
  15. import warnings
  16. from collections.abc import Iterable
  17. from contextlib import redirect_stderr, redirect_stdout
  18. from typing import TYPE_CHECKING, Any
  19. from astroid import bases, nodes
  20. from astroid.const import _EMPTY_OBJECT_MARKER, IS_PYPY
  21. from astroid.nodes import node_classes
  22. if TYPE_CHECKING:
  23. from astroid.manager import AstroidManager
  24. logger = logging.getLogger(__name__)
  25. _FunctionTypes = (
  26. types.FunctionType
  27. | types.MethodType
  28. | types.BuiltinFunctionType
  29. | types.WrapperDescriptorType
  30. | types.MethodDescriptorType
  31. | types.ClassMethodDescriptorType
  32. )
  33. TYPE_NONE = type(None)
  34. TYPE_NOTIMPLEMENTED = type(NotImplemented)
  35. TYPE_ELLIPSIS = type(...)
  36. def _attach_local_node(parent, node, name: str) -> None:
  37. node.name = name # needed by add_local_node
  38. parent.add_local_node(node)
  39. def _add_dunder_class(func, parent: nodes.NodeNG, member) -> None:
  40. """Add a __class__ member to the given func node, if we can determine it."""
  41. python_cls = member.__class__
  42. cls_name = getattr(python_cls, "__name__", None)
  43. if not cls_name:
  44. return
  45. cls_bases = [ancestor.__name__ for ancestor in python_cls.__bases__]
  46. doc = python_cls.__doc__ if isinstance(python_cls.__doc__, str) else None
  47. ast_klass = build_class(cls_name, parent, cls_bases, doc)
  48. func.instance_attrs["__class__"] = [ast_klass]
  49. def build_dummy(runtime_object) -> nodes.EmptyNode:
  50. enode = nodes.EmptyNode()
  51. enode.object = runtime_object
  52. return enode
  53. def attach_dummy_node(node, name: str, runtime_object=_EMPTY_OBJECT_MARKER) -> None:
  54. """create a dummy node and register it in the locals of the given
  55. node with the specified name
  56. """
  57. _attach_local_node(node, build_dummy(runtime_object), name)
  58. def attach_const_node(node, name: str, value) -> None:
  59. """create a Const node and register it in the locals of the given
  60. node with the specified name
  61. """
  62. if name not in node.special_attributes:
  63. _attach_local_node(node, nodes.const_factory(value), name)
  64. def attach_import_node(node, modname: str, membername: str) -> None:
  65. """create a ImportFrom node and register it in the locals of the given
  66. node with the specified name
  67. """
  68. from_node = nodes.ImportFrom(modname, [(membername, None)])
  69. _attach_local_node(node, from_node, membername)
  70. def build_module(name: str, doc: str | None = None) -> nodes.Module:
  71. """create and initialize an astroid Module node"""
  72. node = nodes.Module(name, pure_python=False, package=False)
  73. node.postinit(
  74. body=[],
  75. doc_node=nodes.Const(value=doc) if doc else None,
  76. )
  77. return node
  78. def build_class(
  79. name: str,
  80. parent: nodes.NodeNG,
  81. basenames: Iterable[str] = (),
  82. doc: str | None = None,
  83. ) -> nodes.ClassDef:
  84. """Create and initialize an astroid ClassDef node."""
  85. node = nodes.ClassDef(
  86. name,
  87. lineno=0,
  88. col_offset=0,
  89. end_lineno=0,
  90. end_col_offset=0,
  91. parent=parent,
  92. )
  93. node.postinit(
  94. bases=[
  95. nodes.Name(
  96. name=base,
  97. lineno=0,
  98. col_offset=0,
  99. parent=node,
  100. end_lineno=None,
  101. end_col_offset=None,
  102. )
  103. for base in basenames
  104. ],
  105. body=[],
  106. decorators=None,
  107. doc_node=nodes.Const(value=doc) if doc else None,
  108. )
  109. return node
  110. def build_function(
  111. name: str,
  112. parent: nodes.NodeNG,
  113. args: list[str] | None = None,
  114. posonlyargs: list[str] | None = None,
  115. defaults: list[Any] | None = None,
  116. doc: str | None = None,
  117. kwonlyargs: list[str] | None = None,
  118. kwonlydefaults: list[Any] | None = None,
  119. ) -> nodes.FunctionDef:
  120. """create and initialize an astroid FunctionDef node"""
  121. # first argument is now a list of decorators
  122. func = nodes.FunctionDef(
  123. name,
  124. lineno=0,
  125. col_offset=0,
  126. parent=parent,
  127. end_col_offset=0,
  128. end_lineno=0,
  129. )
  130. argsnode = nodes.Arguments(parent=func, vararg=None, kwarg=None)
  131. # If args is None we don't have any information about the signature
  132. # (in contrast to when there are no arguments and args == []). We pass
  133. # this to the builder to indicate this.
  134. if args is not None:
  135. # We set the lineno and col_offset to 0 because we don't have any
  136. # information about the location of the function definition.
  137. arguments = [
  138. nodes.AssignName(
  139. name=arg,
  140. parent=argsnode,
  141. lineno=0,
  142. col_offset=0,
  143. end_lineno=None,
  144. end_col_offset=None,
  145. )
  146. for arg in args
  147. ]
  148. else:
  149. arguments = None
  150. default_nodes: list[nodes.NodeNG] | None
  151. if defaults is None:
  152. default_nodes = None
  153. else:
  154. default_nodes = []
  155. for default in defaults:
  156. default_node = nodes.const_factory(default)
  157. default_node.parent = argsnode
  158. default_nodes.append(default_node)
  159. kwonlydefault_nodes: list[nodes.NodeNG | None] | None
  160. if kwonlydefaults is None:
  161. kwonlydefault_nodes = None
  162. else:
  163. kwonlydefault_nodes = []
  164. for kwonlydefault in kwonlydefaults:
  165. kwonlydefault_node = nodes.const_factory(kwonlydefault)
  166. kwonlydefault_node.parent = argsnode
  167. kwonlydefault_nodes.append(kwonlydefault_node)
  168. # We set the lineno and col_offset to 0 because we don't have any
  169. # information about the location of the kwonly and posonlyargs.
  170. argsnode.postinit(
  171. args=arguments,
  172. defaults=default_nodes,
  173. kwonlyargs=[
  174. nodes.AssignName(
  175. name=arg,
  176. parent=argsnode,
  177. lineno=0,
  178. col_offset=0,
  179. end_lineno=None,
  180. end_col_offset=None,
  181. )
  182. for arg in kwonlyargs or ()
  183. ],
  184. kw_defaults=kwonlydefault_nodes,
  185. annotations=[],
  186. posonlyargs=[
  187. nodes.AssignName(
  188. name=arg,
  189. parent=argsnode,
  190. lineno=0,
  191. col_offset=0,
  192. end_lineno=None,
  193. end_col_offset=None,
  194. )
  195. for arg in posonlyargs or ()
  196. ],
  197. kwonlyargs_annotations=[],
  198. posonlyargs_annotations=[],
  199. )
  200. func.postinit(
  201. args=argsnode,
  202. body=[],
  203. doc_node=nodes.Const(value=doc) if doc else None,
  204. )
  205. if args:
  206. register_arguments(func)
  207. return func
  208. def build_from_import(fromname: str, names: list[str]) -> nodes.ImportFrom:
  209. """create and initialize an astroid ImportFrom import statement"""
  210. return nodes.ImportFrom(fromname, [(name, None) for name in names])
  211. def register_arguments(func: nodes.FunctionDef, args: list | None = None) -> None:
  212. """add given arguments to local
  213. args is a list that may contains nested lists
  214. (i.e. def func(a, (b, c, d)): ...)
  215. """
  216. # If no args are passed in, get the args from the function.
  217. if args is None:
  218. if func.args.vararg:
  219. func.set_local(func.args.vararg, func.args)
  220. if func.args.kwarg:
  221. func.set_local(func.args.kwarg, func.args)
  222. args = func.args.args
  223. # If the function has no args, there is nothing left to do.
  224. if args is None:
  225. return
  226. for arg in args:
  227. if isinstance(arg, nodes.AssignName):
  228. func.set_local(arg.name, arg)
  229. else:
  230. register_arguments(func, arg.elts)
  231. def object_build_class(
  232. node: nodes.Module | nodes.ClassDef, member: type
  233. ) -> nodes.ClassDef:
  234. """create astroid for a living class object"""
  235. basenames = [base.__name__ for base in member.__bases__]
  236. return _base_class_object_build(node, member, basenames)
  237. def _get_args_info_from_callable(
  238. member: _FunctionTypes,
  239. ) -> tuple[list[str], list[str], list[Any], list[str], list[Any]]:
  240. """Returns args, posonlyargs, defaults, kwonlyargs.
  241. :note: currently ignores the return annotation.
  242. """
  243. signature = inspect.signature(member)
  244. args: list[str] = []
  245. defaults: list[Any] = []
  246. posonlyargs: list[str] = []
  247. kwonlyargs: list[str] = []
  248. kwonlydefaults: list[Any] = []
  249. for param_name, param in signature.parameters.items():
  250. if param.kind == inspect.Parameter.POSITIONAL_ONLY:
  251. posonlyargs.append(param_name)
  252. elif param.kind == inspect.Parameter.POSITIONAL_OR_KEYWORD:
  253. args.append(param_name)
  254. elif param.kind == inspect.Parameter.VAR_POSITIONAL:
  255. args.append(param_name)
  256. elif param.kind == inspect.Parameter.VAR_KEYWORD:
  257. args.append(param_name)
  258. elif param.kind == inspect.Parameter.KEYWORD_ONLY:
  259. kwonlyargs.append(param_name)
  260. if param.default is not inspect.Parameter.empty:
  261. kwonlydefaults.append(param.default)
  262. continue
  263. if param.default is not inspect.Parameter.empty:
  264. defaults.append(param.default)
  265. return args, posonlyargs, defaults, kwonlyargs, kwonlydefaults
  266. def object_build_function(
  267. node: nodes.Module | nodes.ClassDef, member: _FunctionTypes
  268. ) -> nodes.FunctionDef:
  269. """create astroid for a living function object"""
  270. (
  271. args,
  272. posonlyargs,
  273. defaults,
  274. kwonlyargs,
  275. kwonly_defaults,
  276. ) = _get_args_info_from_callable(member)
  277. return build_function(
  278. getattr(member, "__name__", "<no-name>"),
  279. node,
  280. args,
  281. posonlyargs,
  282. defaults,
  283. member.__doc__ if isinstance(member.__doc__, str) else None,
  284. kwonlyargs=kwonlyargs,
  285. kwonlydefaults=kwonly_defaults,
  286. )
  287. def object_build_datadescriptor(
  288. node: nodes.Module | nodes.ClassDef, member: type
  289. ) -> nodes.ClassDef:
  290. """create astroid for a living data descriptor object"""
  291. return _base_class_object_build(node, member, [])
  292. def object_build_methoddescriptor(
  293. node: nodes.Module | nodes.ClassDef,
  294. member: _FunctionTypes,
  295. ) -> nodes.FunctionDef:
  296. """create astroid for a living method descriptor object"""
  297. # FIXME get arguments ?
  298. name = getattr(member, "__name__", "<no-name>")
  299. func = build_function(name, node, doc=member.__doc__)
  300. _add_dunder_class(func, node, member)
  301. return func
  302. def _base_class_object_build(
  303. node: nodes.Module | nodes.ClassDef,
  304. member: type,
  305. basenames: list[str],
  306. ) -> nodes.ClassDef:
  307. """create astroid for a living class object, with a given set of base names
  308. (e.g. ancestors)
  309. """
  310. name = getattr(member, "__name__", "<no-name>")
  311. doc = member.__doc__ if isinstance(member.__doc__, str) else None
  312. klass = build_class(name, node, basenames, doc)
  313. klass._newstyle = isinstance(member, type)
  314. try:
  315. # limit the instantiation trick since it's too dangerous
  316. # (such as infinite test execution...)
  317. # this at least resolves common case such as Exception.args,
  318. # OSError.errno
  319. if issubclass(member, Exception):
  320. member_object = member()
  321. if hasattr(member_object, "__dict__"):
  322. instdict = member_object.__dict__
  323. else:
  324. raise TypeError
  325. else:
  326. raise TypeError
  327. except TypeError:
  328. pass
  329. else:
  330. for item_name, obj in instdict.items():
  331. valnode = nodes.EmptyNode()
  332. valnode.object = obj
  333. valnode.parent = klass
  334. valnode.lineno = 1
  335. klass.instance_attrs[item_name] = [valnode]
  336. return klass
  337. def _build_from_function(
  338. node: nodes.Module | nodes.ClassDef,
  339. member: _FunctionTypes,
  340. module: types.ModuleType,
  341. ) -> nodes.FunctionDef | nodes.EmptyNode:
  342. # verify this is not an imported function
  343. try:
  344. code = member.__code__ # type: ignore[union-attr]
  345. except AttributeError:
  346. # Some implementations don't provide the code object,
  347. # such as Jython.
  348. code = None
  349. filename = getattr(code, "co_filename", None)
  350. if filename is None:
  351. return object_build_methoddescriptor(node, member)
  352. if filename == getattr(module, "__file__", None):
  353. return object_build_function(node, member)
  354. return build_dummy(member)
  355. def _safe_has_attribute(obj, member: str) -> bool:
  356. """Required because unexpected RunTimeError can be raised.
  357. See https://github.com/pylint-dev/astroid/issues/1958
  358. """
  359. try:
  360. return hasattr(obj, member)
  361. except Exception: # pylint: disable=broad-except
  362. return False
  363. class InspectBuilder:
  364. """class for building nodes from living object
  365. this is actually a really minimal representation, including only Module,
  366. FunctionDef and ClassDef nodes and some others as guessed.
  367. """
  368. bootstrapped: bool = False
  369. def __init__(self, manager_instance: AstroidManager) -> None:
  370. self._manager = manager_instance
  371. self._done: dict[types.ModuleType | type, nodes.Module | nodes.ClassDef] = {}
  372. self._module: types.ModuleType
  373. def inspect_build(
  374. self,
  375. module: types.ModuleType,
  376. modname: str | None = None,
  377. path: str | None = None,
  378. ) -> nodes.Module:
  379. """build astroid from a living module (i.e. using inspect)
  380. this is used when there is no python source code available (either
  381. because it's a built-in module or because the .py is not available)
  382. """
  383. self._module = module
  384. if modname is None:
  385. modname = module.__name__
  386. try:
  387. node = build_module(modname, module.__doc__)
  388. except AttributeError:
  389. # in jython, java modules have no __doc__ (see #109562)
  390. node = build_module(modname)
  391. if path is None:
  392. node.path = node.file = path
  393. else:
  394. node.path = [os.path.abspath(path)]
  395. node.file = node.path[0]
  396. node.name = modname
  397. self._manager.cache_module(node)
  398. node.package = hasattr(module, "__path__")
  399. self._done = {}
  400. self.object_build(node, module)
  401. return node
  402. def object_build(
  403. self, node: nodes.Module | nodes.ClassDef, obj: types.ModuleType | type
  404. ) -> None:
  405. """recursive method which create a partial ast from real objects
  406. (only function, class, and method are handled)
  407. """
  408. if obj in self._done:
  409. return None
  410. self._done[obj] = node
  411. for alias in dir(obj):
  412. # inspect.ismethod() and inspect.isbuiltin() in PyPy return
  413. # the opposite of what they do in CPython for __class_getitem__.
  414. pypy__class_getitem__ = IS_PYPY and alias == "__class_getitem__"
  415. try:
  416. with warnings.catch_warnings():
  417. warnings.simplefilter("ignore")
  418. member = getattr(obj, alias)
  419. except AttributeError:
  420. # damned ExtensionClass.Base, I know you're there !
  421. attach_dummy_node(node, alias)
  422. continue
  423. if inspect.ismethod(member) and not pypy__class_getitem__:
  424. member = member.__func__
  425. if inspect.isfunction(member):
  426. child = _build_from_function(node, member, self._module)
  427. elif inspect.isbuiltin(member) or pypy__class_getitem__:
  428. if self.imported_member(node, member, alias):
  429. continue
  430. child = object_build_methoddescriptor(node, member)
  431. elif inspect.isclass(member):
  432. if self.imported_member(node, member, alias):
  433. continue
  434. if member in self._done:
  435. child = self._done[member]
  436. assert isinstance(child, nodes.ClassDef)
  437. else:
  438. child = object_build_class(node, member)
  439. # recursion
  440. self.object_build(child, member)
  441. elif inspect.ismethoddescriptor(member):
  442. child: nodes.NodeNG = object_build_methoddescriptor(node, member)
  443. elif inspect.isdatadescriptor(member):
  444. child = object_build_datadescriptor(node, member)
  445. elif isinstance(member, tuple(node_classes.CONST_CLS)):
  446. if alias in node.special_attributes:
  447. continue
  448. child = nodes.const_factory(member)
  449. elif inspect.isroutine(member):
  450. # This should be called for Jython, where some builtin
  451. # methods aren't caught by isbuiltin branch.
  452. child = _build_from_function(node, member, self._module)
  453. elif _safe_has_attribute(member, "__all__"):
  454. child: nodes.NodeNG = build_module(alias)
  455. # recursion
  456. self.object_build(child, member)
  457. else:
  458. # create an empty node so that the name is actually defined
  459. child: nodes.NodeNG = build_dummy(member)
  460. if child not in node.locals.get(alias, ()):
  461. node.add_local_node(child, alias)
  462. return None
  463. def imported_member(self, node, member, name: str) -> bool:
  464. """verify this is not an imported class or handle it"""
  465. # /!\ some classes like ExtensionClass doesn't have a __module__
  466. # attribute ! Also, this may trigger an exception on badly built module
  467. # (see http://www.logilab.org/ticket/57299 for instance)
  468. try:
  469. modname = getattr(member, "__module__", None)
  470. except TypeError:
  471. modname = None
  472. if modname is None:
  473. if name in {"__new__", "__subclasshook__"}:
  474. # Python 2.5.1 (r251:54863, Sep 1 2010, 22:03:14)
  475. # >>> print object.__new__.__module__
  476. # None
  477. modname = builtins.__name__
  478. else:
  479. attach_dummy_node(node, name, member)
  480. return True
  481. # On PyPy during bootstrapping we infer _io while _module is
  482. # builtins. In CPython _io names itself io, see http://bugs.python.org/issue18602
  483. # Therefore, this basically checks whether we are not in PyPy.
  484. if modname == "_io" and not self._module.__name__ == "builtins":
  485. return False
  486. real_name = {"gtk": "gtk_gtk"}.get(modname, modname)
  487. if real_name != self._module.__name__:
  488. # check if it sounds valid and then add an import node, else use a
  489. # dummy node
  490. try:
  491. with (
  492. redirect_stderr(io.StringIO()) as stderr,
  493. redirect_stdout(io.StringIO()) as stdout,
  494. ):
  495. getattr(sys.modules[modname], name)
  496. stderr_value = stderr.getvalue()
  497. if stderr_value:
  498. logger.error(
  499. "Captured stderr while getting %s from %s:\n%s",
  500. name,
  501. sys.modules[modname],
  502. stderr_value,
  503. )
  504. stdout_value = stdout.getvalue()
  505. if stdout_value:
  506. logger.info(
  507. "Captured stdout while getting %s from %s:\n%s",
  508. name,
  509. sys.modules[modname],
  510. stdout_value,
  511. )
  512. except (KeyError, AttributeError):
  513. attach_dummy_node(node, name, member)
  514. else:
  515. attach_import_node(node, modname, name)
  516. return True
  517. return False
  518. # astroid bootstrapping ######################################################
  519. _CONST_PROXY: dict[type, nodes.ClassDef] = {}
  520. def _set_proxied(const) -> nodes.ClassDef:
  521. # TODO : find a nicer way to handle this situation;
  522. return _CONST_PROXY[const.value.__class__]
  523. def _astroid_bootstrapping() -> None:
  524. """astroid bootstrapping the builtins module"""
  525. # this boot strapping is necessary since we need the Const nodes to
  526. # inspect_build builtins, and then we can proxy Const
  527. # pylint: disable-next=import-outside-toplevel
  528. from astroid.manager import AstroidManager
  529. builder = InspectBuilder(AstroidManager())
  530. astroid_builtin = builder.inspect_build(builtins)
  531. for cls, node_cls in node_classes.CONST_CLS.items():
  532. if cls is TYPE_NONE:
  533. proxy = build_class("NoneType", astroid_builtin)
  534. elif cls is TYPE_NOTIMPLEMENTED:
  535. proxy = build_class("NotImplementedType", astroid_builtin)
  536. elif cls is TYPE_ELLIPSIS:
  537. proxy = build_class("Ellipsis", astroid_builtin)
  538. else:
  539. proxy = astroid_builtin.getattr(cls.__name__)[0]
  540. assert isinstance(proxy, nodes.ClassDef)
  541. if cls in (dict, list, set, tuple):
  542. node_cls._proxied = proxy
  543. else:
  544. _CONST_PROXY[cls] = proxy
  545. # Set the builtin module as parent for some builtins.
  546. nodes.Const._proxied = property(_set_proxied)
  547. _GeneratorType = nodes.ClassDef(
  548. types.GeneratorType.__name__,
  549. lineno=0,
  550. col_offset=0,
  551. end_lineno=0,
  552. end_col_offset=0,
  553. parent=astroid_builtin,
  554. )
  555. astroid_builtin.set_local(_GeneratorType.name, _GeneratorType)
  556. generator_doc_node = (
  557. nodes.Const(value=types.GeneratorType.__doc__)
  558. if types.GeneratorType.__doc__
  559. else None
  560. )
  561. _GeneratorType.postinit(
  562. bases=[],
  563. body=[],
  564. decorators=None,
  565. doc_node=generator_doc_node,
  566. )
  567. bases.Generator._proxied = _GeneratorType
  568. builder.object_build(bases.Generator._proxied, types.GeneratorType)
  569. if hasattr(types, "AsyncGeneratorType"):
  570. _AsyncGeneratorType = nodes.ClassDef(
  571. types.AsyncGeneratorType.__name__,
  572. lineno=0,
  573. col_offset=0,
  574. end_lineno=0,
  575. end_col_offset=0,
  576. parent=astroid_builtin,
  577. )
  578. astroid_builtin.set_local(_AsyncGeneratorType.name, _AsyncGeneratorType)
  579. async_generator_doc_node = (
  580. nodes.Const(value=types.AsyncGeneratorType.__doc__)
  581. if types.AsyncGeneratorType.__doc__
  582. else None
  583. )
  584. _AsyncGeneratorType.postinit(
  585. bases=[],
  586. body=[],
  587. decorators=None,
  588. doc_node=async_generator_doc_node,
  589. )
  590. bases.AsyncGenerator._proxied = _AsyncGeneratorType
  591. builder.object_build(bases.AsyncGenerator._proxied, types.AsyncGeneratorType)
  592. if hasattr(types, "UnionType"):
  593. _UnionTypeType = nodes.ClassDef(
  594. types.UnionType.__name__,
  595. lineno=0,
  596. col_offset=0,
  597. end_lineno=0,
  598. end_col_offset=0,
  599. parent=astroid_builtin,
  600. )
  601. union_type_doc_node = (
  602. nodes.Const(value=types.UnionType.__doc__)
  603. if types.UnionType.__doc__
  604. else None
  605. )
  606. _UnionTypeType.postinit(
  607. bases=[],
  608. body=[],
  609. decorators=None,
  610. doc_node=union_type_doc_node,
  611. )
  612. bases.UnionType._proxied = _UnionTypeType
  613. builder.object_build(bases.UnionType._proxied, types.UnionType)
  614. builtin_types = (
  615. types.GetSetDescriptorType,
  616. types.GeneratorType,
  617. types.MemberDescriptorType,
  618. TYPE_NONE,
  619. TYPE_NOTIMPLEMENTED,
  620. types.FunctionType,
  621. types.MethodType,
  622. types.BuiltinFunctionType,
  623. types.ModuleType,
  624. types.TracebackType,
  625. )
  626. for _type in builtin_types:
  627. if _type.__name__ not in astroid_builtin:
  628. klass = nodes.ClassDef(
  629. _type.__name__,
  630. lineno=0,
  631. col_offset=0,
  632. end_lineno=0,
  633. end_col_offset=0,
  634. parent=astroid_builtin,
  635. )
  636. doc = _type.__doc__ if isinstance(_type.__doc__, str) else None
  637. klass.postinit(
  638. bases=[],
  639. body=[],
  640. decorators=None,
  641. doc_node=nodes.Const(doc) if doc else None,
  642. )
  643. builder.object_build(klass, _type)
  644. astroid_builtin[_type.__name__] = klass
  645. InspectBuilder.bootstrapped = True
  646. # pylint: disable-next=import-outside-toplevel
  647. from astroid.brain.brain_builtin_inference import on_bootstrap
  648. # Instantiates an AstroidBuilder(), which is where
  649. # InspectBuilder.bootstrapped is checked, so place after bootstrapped=True.
  650. on_bootstrap()