Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/astroid/bases.py: 56%

388 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-07 06:53 +0000

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 

5"""This module contains base classes and functions for the nodes and some 

6inference utils. 

7""" 

8from __future__ import annotations 

9 

10import collections 

11import collections.abc 

12from collections.abc import Iterable, Iterator 

13from typing import TYPE_CHECKING, Any, ClassVar, Literal 

14 

15from astroid import nodes 

16from astroid.const import PY310_PLUS 

17from astroid.context import ( 

18 CallContext, 

19 InferenceContext, 

20 bind_context_to_node, 

21 copy_context, 

22) 

23from astroid.exceptions import ( 

24 AstroidTypeError, 

25 AttributeInferenceError, 

26 InferenceError, 

27 NameInferenceError, 

28) 

29from astroid.interpreter import objectmodel 

30from astroid.typing import ( 

31 InferBinaryOp, 

32 InferenceErrorInfo, 

33 InferenceResult, 

34 SuccessfulInferenceResult, 

35) 

36from astroid.util import Uninferable, UninferableBase 

37 

38if TYPE_CHECKING: 

39 from astroid.constraint import Constraint 

40 

41 

42PROPERTIES = {"builtins.property", "abc.abstractproperty"} 

43if PY310_PLUS: 

44 PROPERTIES.add("enum.property") 

45 

46# List of possible property names. We use this list in order 

47# to see if a method is a property or not. This should be 

48# pretty reliable and fast, the alternative being to check each 

49# decorator to see if its a real property-like descriptor, which 

50# can be too complicated. 

51# Also, these aren't qualified, because each project can 

52# define them, we shouldn't expect to know every possible 

53# property-like decorator! 

54POSSIBLE_PROPERTIES = { 

55 "cached_property", 

56 "cachedproperty", 

57 "lazyproperty", 

58 "lazy_property", 

59 "reify", 

60 "lazyattribute", 

61 "lazy_attribute", 

62 "LazyProperty", 

63 "lazy", 

64 "cache_readonly", 

65 "DynamicClassAttribute", 

66} 

67 

68 

69def _is_property( 

70 meth: nodes.FunctionDef | UnboundMethod, context: InferenceContext | None = None 

71) -> bool: 

72 from astroid import helpers # pylint: disable=import-outside-toplevel 

73 

74 decoratornames = meth.decoratornames(context=context) 

75 if PROPERTIES.intersection(decoratornames): 

76 return True 

77 stripped = { 

78 name.split(".")[-1] 

79 for name in decoratornames 

80 if not isinstance(name, UninferableBase) 

81 } 

82 if any(name in stripped for name in POSSIBLE_PROPERTIES): 

83 return True 

84 

85 # Lookup for subclasses of *property* 

86 if not meth.decorators: 

87 return False 

88 for decorator in meth.decorators.nodes or (): 

89 inferred = helpers.safe_infer(decorator, context=context) 

90 if inferred is None or isinstance(inferred, UninferableBase): 

91 continue 

92 if isinstance(inferred, nodes.ClassDef): 

93 for base_class in inferred.bases: 

94 if not isinstance(base_class, nodes.Name): 

95 continue 

96 module, _ = base_class.lookup(base_class.name) 

97 if ( 

98 isinstance(module, nodes.Module) 

99 and module.name == "builtins" 

100 and base_class.name == "property" 

101 ): 

102 return True 

103 

104 return False 

105 

106 

107class Proxy: 

108 """A simple proxy object. 

109 

110 Note: 

111 

112 Subclasses of this object will need a custom __getattr__ 

113 if new instance attributes are created. See the Const class 

114 """ 

115 

116 _proxied: nodes.ClassDef | nodes.FunctionDef | nodes.Lambda | UnboundMethod 

117 

118 def __init__( 

119 self, 

120 proxied: nodes.ClassDef 

121 | nodes.FunctionDef 

122 | nodes.Lambda 

123 | UnboundMethod 

124 | None = None, 

125 ) -> None: 

126 if proxied is None: 

127 # This is a hack to allow calling this __init__ during bootstrapping of 

128 # builtin classes and their docstrings. 

129 # For Const, Generator, and UnionType nodes the _proxied attribute 

130 # is set during bootstrapping 

131 # as we first need to build the ClassDef that they can proxy. 

132 # Thus, if proxied is None self should be a Const or Generator 

133 # as that is the only way _proxied will be correctly set as a ClassDef. 

134 assert isinstance(self, (nodes.Const, Generator, UnionType)) 

135 else: 

136 self._proxied = proxied 

137 

138 def __getattr__(self, name: str) -> Any: 

139 if name == "_proxied": 

140 return self.__class__._proxied 

141 if name in self.__dict__: 

142 return self.__dict__[name] 

143 return getattr(self._proxied, name) 

144 

145 def infer( # type: ignore[return] 

146 self, context: InferenceContext | None = None, **kwargs: Any 

147 ) -> collections.abc.Generator[InferenceResult, None, InferenceErrorInfo | None]: 

148 yield self 

149 

150 

151def _infer_stmts( 

152 stmts: Iterator[InferenceResult], 

153 context: InferenceContext | None, 

154 frame: nodes.NodeNG | BaseInstance | None = None, 

155) -> collections.abc.Generator[InferenceResult, None, None]: 

156 """Return an iterator on statements inferred by each statement in *stmts*.""" 

157 inferred = False 

158 constraint_failed = False 

159 if context is not None: 

160 name = context.lookupname 

161 context = context.clone() 

162 if name is not None: 

163 constraints = context.constraints.get(name, {}) 

164 else: 

165 constraints = {} 

166 else: 

167 name = None 

168 constraints = {} 

169 context = InferenceContext() 

170 

171 for stmt in stmts: 

172 if isinstance(stmt, UninferableBase): 

173 yield stmt 

174 inferred = True 

175 continue 

176 context.lookupname = stmt._infer_name(frame, name) 

177 try: 

178 stmt_constraints: set[Constraint] = set() 

179 for constraint_stmt, potential_constraints in constraints.items(): 

180 if not constraint_stmt.parent_of(stmt): 

181 stmt_constraints.update(potential_constraints) 

182 for inf in stmt.infer(context=context): 

183 if all(constraint.satisfied_by(inf) for constraint in stmt_constraints): 

184 yield inf 

185 inferred = True 

186 else: 

187 constraint_failed = True 

188 except NameInferenceError: 

189 continue 

190 except InferenceError: 

191 yield Uninferable 

192 inferred = True 

193 

194 if not inferred and constraint_failed: 

195 yield Uninferable 

196 elif not inferred: 

197 raise InferenceError( 

198 "Inference failed for all members of {stmts!r}.", 

199 stmts=stmts, 

200 frame=frame, 

201 context=context, 

202 ) 

203 

204 

205def _infer_method_result_truth( 

206 instance: Instance, method_name: str, context: InferenceContext 

207) -> bool | UninferableBase: 

208 # Get the method from the instance and try to infer 

209 # its return's truth value. 

210 meth = next(instance.igetattr(method_name, context=context), None) 

211 if meth and hasattr(meth, "infer_call_result"): 

212 if not meth.callable(): 

213 return Uninferable 

214 try: 

215 context.callcontext = CallContext(args=[], callee=meth) 

216 for value in meth.infer_call_result(instance, context=context): 

217 if isinstance(value, UninferableBase): 

218 return value 

219 try: 

220 inferred = next(value.infer(context=context)) 

221 except StopIteration as e: 

222 raise InferenceError(context=context) from e 

223 return inferred.bool_value() 

224 except InferenceError: 

225 pass 

226 return Uninferable 

227 

228 

229class BaseInstance(Proxy): 

230 """An instance base class, which provides lookup methods for potential 

231 instances. 

232 """ 

233 

234 _proxied: nodes.ClassDef 

235 

236 special_attributes: objectmodel.ObjectModel 

237 

238 def display_type(self) -> str: 

239 return "Instance of" 

240 

241 def getattr( 

242 self, 

243 name: str, 

244 context: InferenceContext | None = None, 

245 lookupclass: bool = True, 

246 ) -> list[SuccessfulInferenceResult]: 

247 try: 

248 values = self._proxied.instance_attr(name, context) 

249 except AttributeInferenceError as exc: 

250 if self.special_attributes and name in self.special_attributes: 

251 return [self.special_attributes.lookup(name)] 

252 

253 if lookupclass: 

254 # Class attributes not available through the instance 

255 # unless they are explicitly defined. 

256 return self._proxied.getattr(name, context, class_context=False) 

257 

258 raise AttributeInferenceError( 

259 target=self, attribute=name, context=context 

260 ) from exc 

261 # since we've no context information, return matching class members as 

262 # well 

263 if lookupclass: 

264 try: 

265 return values + self._proxied.getattr( 

266 name, context, class_context=False 

267 ) 

268 except AttributeInferenceError: 

269 pass 

270 return values 

271 

272 def igetattr( 

273 self, name: str, context: InferenceContext | None = None 

274 ) -> Iterator[InferenceResult]: 

275 """Inferred getattr.""" 

276 if not context: 

277 context = InferenceContext() 

278 try: 

279 context.lookupname = name 

280 # avoid recursively inferring the same attr on the same class 

281 if context.push(self._proxied): 

282 raise InferenceError( 

283 message="Cannot infer the same attribute again", 

284 node=self, 

285 context=context, 

286 ) 

287 

288 # XXX frame should be self._proxied, or not ? 

289 get_attr = self.getattr(name, context, lookupclass=False) 

290 yield from _infer_stmts( 

291 self._wrap_attr(get_attr, context), context, frame=self 

292 ) 

293 except AttributeInferenceError: 

294 try: 

295 # fallback to class.igetattr since it has some logic to handle 

296 # descriptors 

297 # But only if the _proxied is the Class. 

298 if self._proxied.__class__.__name__ != "ClassDef": 

299 raise 

300 attrs = self._proxied.igetattr(name, context, class_context=False) 

301 yield from self._wrap_attr(attrs, context) 

302 except AttributeInferenceError as error: 

303 raise InferenceError(**vars(error)) from error 

304 

305 def _wrap_attr( 

306 self, attrs: Iterable[InferenceResult], context: InferenceContext | None = None 

307 ) -> Iterator[InferenceResult]: 

308 """Wrap bound methods of attrs in a InstanceMethod proxies.""" 

309 for attr in attrs: 

310 if isinstance(attr, UnboundMethod): 

311 if _is_property(attr): 

312 yield from attr.infer_call_result(self, context) 

313 else: 

314 yield BoundMethod(attr, self) 

315 elif isinstance(attr, nodes.Lambda): 

316 if attr.args.arguments and attr.args.arguments[0].name == "self": 

317 yield BoundMethod(attr, self) 

318 continue 

319 yield attr 

320 else: 

321 yield attr 

322 

323 def infer_call_result( 

324 self, 

325 caller: SuccessfulInferenceResult | None, 

326 context: InferenceContext | None = None, 

327 ) -> Iterator[InferenceResult]: 

328 """Infer what a class instance is returning when called.""" 

329 context = bind_context_to_node(context, self) 

330 inferred = False 

331 

332 # If the call is an attribute on the instance, we infer the attribute itself 

333 if isinstance(caller, nodes.Call) and isinstance(caller.func, nodes.Attribute): 

334 for res in self.igetattr(caller.func.attrname, context): 

335 inferred = True 

336 yield res 

337 

338 # Otherwise we infer the call to the __call__ dunder normally 

339 for node in self._proxied.igetattr("__call__", context): 

340 if isinstance(node, UninferableBase) or not node.callable(): 

341 continue 

342 for res in node.infer_call_result(caller, context): 

343 inferred = True 

344 yield res 

345 if not inferred: 

346 raise InferenceError(node=self, caller=caller, context=context) 

347 

348 

349class Instance(BaseInstance): 

350 """A special node representing a class instance.""" 

351 

352 special_attributes = objectmodel.InstanceModel() 

353 

354 def __init__(self, proxied: nodes.ClassDef | None) -> None: 

355 super().__init__(proxied) 

356 

357 infer_binary_op: ClassVar[InferBinaryOp[Instance]] 

358 

359 def __repr__(self) -> str: 

360 return "<Instance of {}.{} at 0x{}>".format( 

361 self._proxied.root().name, self._proxied.name, id(self) 

362 ) 

363 

364 def __str__(self) -> str: 

365 return f"Instance of {self._proxied.root().name}.{self._proxied.name}" 

366 

367 def callable(self) -> bool: 

368 try: 

369 self._proxied.getattr("__call__", class_context=False) 

370 return True 

371 except AttributeInferenceError: 

372 return False 

373 

374 def pytype(self) -> str: 

375 return self._proxied.qname() 

376 

377 def display_type(self) -> str: 

378 return "Instance of" 

379 

380 def bool_value( 

381 self, context: InferenceContext | None = None 

382 ) -> bool | UninferableBase: 

383 """Infer the truth value for an Instance. 

384 

385 The truth value of an instance is determined by these conditions: 

386 

387 * if it implements __bool__ on Python 3 or __nonzero__ 

388 on Python 2, then its bool value will be determined by 

389 calling this special method and checking its result. 

390 * when this method is not defined, __len__() is called, if it 

391 is defined, and the object is considered true if its result is 

392 nonzero. If a class defines neither __len__() nor __bool__(), 

393 all its instances are considered true. 

394 """ 

395 context = context or InferenceContext() 

396 context.boundnode = self 

397 

398 try: 

399 result = _infer_method_result_truth(self, "__bool__", context) 

400 except (InferenceError, AttributeInferenceError): 

401 # Fallback to __len__. 

402 try: 

403 result = _infer_method_result_truth(self, "__len__", context) 

404 except (AttributeInferenceError, InferenceError): 

405 return True 

406 return result 

407 

408 def getitem( 

409 self, index: nodes.Const, context: InferenceContext | None = None 

410 ) -> InferenceResult | None: 

411 new_context = bind_context_to_node(context, self) 

412 if not context: 

413 context = new_context 

414 method = next(self.igetattr("__getitem__", context=context), None) 

415 # Create a new CallContext for providing index as an argument. 

416 new_context.callcontext = CallContext(args=[index], callee=method) 

417 if not isinstance(method, BoundMethod): 

418 raise InferenceError( 

419 "Could not find __getitem__ for {node!r}.", node=self, context=context 

420 ) 

421 if len(method.args.arguments) != 2: # (self, index) 

422 raise AstroidTypeError( 

423 "__getitem__ for {node!r} does not have correct signature", 

424 node=self, 

425 context=context, 

426 ) 

427 return next(method.infer_call_result(self, new_context), None) 

428 

429 

430class UnboundMethod(Proxy): 

431 """A special node representing a method not bound to an instance.""" 

432 

433 _proxied: nodes.FunctionDef | UnboundMethod 

434 

435 special_attributes: objectmodel.BoundMethodModel | objectmodel.UnboundMethodModel = ( 

436 objectmodel.UnboundMethodModel() 

437 ) 

438 

439 def __repr__(self) -> str: 

440 assert self._proxied.parent, "Expected a parent node" 

441 frame = self._proxied.parent.frame(future=True) 

442 return "<{} {} of {} at 0x{}".format( 

443 self.__class__.__name__, self._proxied.name, frame.qname(), id(self) 

444 ) 

445 

446 def implicit_parameters(self) -> Literal[0, 1]: 

447 return 0 

448 

449 def is_bound(self) -> bool: 

450 return False 

451 

452 def getattr(self, name: str, context: InferenceContext | None = None): 

453 if name in self.special_attributes: 

454 return [self.special_attributes.lookup(name)] 

455 return self._proxied.getattr(name, context) 

456 

457 def igetattr( 

458 self, name: str, context: InferenceContext | None = None 

459 ) -> Iterator[InferenceResult]: 

460 if name in self.special_attributes: 

461 return iter((self.special_attributes.lookup(name),)) 

462 return self._proxied.igetattr(name, context) 

463 

464 def infer_call_result( 

465 self, 

466 caller: SuccessfulInferenceResult | None, 

467 context: InferenceContext | None = None, 

468 ) -> Iterator[InferenceResult]: 

469 """ 

470 The boundnode of the regular context with a function called 

471 on ``object.__new__`` will be of type ``object``, 

472 which is incorrect for the argument in general. 

473 If no context is given the ``object.__new__`` call argument will 

474 be correctly inferred except when inside a call that requires 

475 the additional context (such as a classmethod) of the boundnode 

476 to determine which class the method was called from 

477 """ 

478 

479 # If we're unbound method __new__ of a builtin, the result is an 

480 # instance of the class given as first argument. 

481 if self._proxied.name == "__new__": 

482 assert self._proxied.parent, "Expected a parent node" 

483 qname = self._proxied.parent.frame(future=True).qname() 

484 # Avoid checking builtins.type: _infer_type_new_call() does more validation 

485 if qname.startswith("builtins.") and qname != "builtins.type": 

486 return self._infer_builtin_new(caller, context or InferenceContext()) 

487 return self._proxied.infer_call_result(caller, context) 

488 

489 def _infer_builtin_new( 

490 self, 

491 caller: SuccessfulInferenceResult | None, 

492 context: InferenceContext, 

493 ) -> collections.abc.Generator[ 

494 nodes.Const | Instance | UninferableBase, None, None 

495 ]: 

496 if not isinstance(caller, nodes.Call): 

497 return 

498 if not caller.args: 

499 return 

500 # Attempt to create a constant 

501 if len(caller.args) > 1: 

502 value = None 

503 if isinstance(caller.args[1], nodes.Const): 

504 value = caller.args[1].value 

505 else: 

506 inferred_arg = next(caller.args[1].infer(), None) 

507 if isinstance(inferred_arg, nodes.Const): 

508 value = inferred_arg.value 

509 if value is not None: 

510 const = nodes.const_factory(value) 

511 assert not isinstance(const, nodes.EmptyNode) 

512 yield const 

513 return 

514 

515 node_context = context.extra_context.get(caller.args[0]) 

516 for inferred in caller.args[0].infer(context=node_context): 

517 if isinstance(inferred, UninferableBase): 

518 yield inferred 

519 if isinstance(inferred, nodes.ClassDef): 

520 yield Instance(inferred) 

521 raise InferenceError 

522 

523 def bool_value(self, context: InferenceContext | None = None) -> Literal[True]: 

524 return True 

525 

526 

527class BoundMethod(UnboundMethod): 

528 """A special node representing a method bound to an instance.""" 

529 

530 special_attributes = objectmodel.BoundMethodModel() 

531 

532 def __init__( 

533 self, 

534 proxy: nodes.FunctionDef | nodes.Lambda | UnboundMethod, 

535 bound: SuccessfulInferenceResult, 

536 ) -> None: 

537 super().__init__(proxy) 

538 self.bound = bound 

539 

540 def implicit_parameters(self) -> Literal[0, 1]: 

541 if self.name == "__new__": 

542 # __new__ acts as a classmethod but the class argument is not implicit. 

543 return 0 

544 return 1 

545 

546 def is_bound(self) -> Literal[True]: 

547 return True 

548 

549 def _infer_type_new_call( 

550 self, caller: nodes.Call, context: InferenceContext 

551 ) -> nodes.ClassDef | None: # noqa: C901 

552 """Try to infer what type.__new__(mcs, name, bases, attrs) returns. 

553 

554 In order for such call to be valid, the metaclass needs to be 

555 a subtype of ``type``, the name needs to be a string, the bases 

556 needs to be a tuple of classes 

557 """ 

558 # pylint: disable=import-outside-toplevel; circular import 

559 from astroid.nodes import Pass 

560 

561 # Verify the metaclass 

562 try: 

563 mcs = next(caller.args[0].infer(context=context)) 

564 except StopIteration as e: 

565 raise InferenceError(context=context) from e 

566 if not isinstance(mcs, nodes.ClassDef): 

567 # Not a valid first argument. 

568 return None 

569 if not mcs.is_subtype_of("builtins.type"): 

570 # Not a valid metaclass. 

571 return None 

572 

573 # Verify the name 

574 try: 

575 name = next(caller.args[1].infer(context=context)) 

576 except StopIteration as e: 

577 raise InferenceError(context=context) from e 

578 if not isinstance(name, nodes.Const): 

579 # Not a valid name, needs to be a const. 

580 return None 

581 if not isinstance(name.value, str): 

582 # Needs to be a string. 

583 return None 

584 

585 # Verify the bases 

586 try: 

587 bases = next(caller.args[2].infer(context=context)) 

588 except StopIteration as e: 

589 raise InferenceError(context=context) from e 

590 if not isinstance(bases, nodes.Tuple): 

591 # Needs to be a tuple. 

592 return None 

593 try: 

594 inferred_bases = [next(elt.infer(context=context)) for elt in bases.elts] 

595 except StopIteration as e: 

596 raise InferenceError(context=context) from e 

597 if any(not isinstance(base, nodes.ClassDef) for base in inferred_bases): 

598 # All the bases needs to be Classes 

599 return None 

600 

601 # Verify the attributes. 

602 try: 

603 attrs = next(caller.args[3].infer(context=context)) 

604 except StopIteration as e: 

605 raise InferenceError(context=context) from e 

606 if not isinstance(attrs, nodes.Dict): 

607 # Needs to be a dictionary. 

608 return None 

609 cls_locals: dict[str, list[InferenceResult]] = collections.defaultdict(list) 

610 for key, value in attrs.items: 

611 try: 

612 key = next(key.infer(context=context)) 

613 except StopIteration as e: 

614 raise InferenceError(context=context) from e 

615 try: 

616 value = next(value.infer(context=context)) 

617 except StopIteration as e: 

618 raise InferenceError(context=context) from e 

619 # Ignore non string keys 

620 if isinstance(key, nodes.Const) and isinstance(key.value, str): 

621 cls_locals[key.value].append(value) 

622 

623 # Build the class from now. 

624 cls = mcs.__class__( 

625 name=name.value, 

626 lineno=caller.lineno or 0, 

627 col_offset=caller.col_offset or 0, 

628 parent=caller, 

629 end_lineno=caller.end_lineno, 

630 end_col_offset=caller.end_col_offset, 

631 ) 

632 empty = Pass( 

633 parent=cls, 

634 lineno=caller.lineno, 

635 col_offset=caller.col_offset, 

636 end_lineno=caller.end_lineno, 

637 end_col_offset=caller.end_col_offset, 

638 ) 

639 cls.postinit( 

640 bases=bases.elts, 

641 body=[empty], 

642 decorators=None, 

643 newstyle=True, 

644 metaclass=mcs, 

645 keywords=[], 

646 ) 

647 cls.locals = cls_locals 

648 return cls 

649 

650 def infer_call_result( 

651 self, 

652 caller: SuccessfulInferenceResult | None, 

653 context: InferenceContext | None = None, 

654 ) -> Iterator[InferenceResult]: 

655 context = bind_context_to_node(context, self.bound) 

656 if ( 

657 isinstance(self.bound, nodes.ClassDef) 

658 and self.bound.name == "type" 

659 and self.name == "__new__" 

660 and isinstance(caller, nodes.Call) 

661 and len(caller.args) == 4 

662 ): 

663 # Check if we have a ``type.__new__(mcs, name, bases, attrs)`` call. 

664 new_cls = self._infer_type_new_call(caller, context) 

665 if new_cls: 

666 return iter((new_cls,)) 

667 

668 return super().infer_call_result(caller, context) 

669 

670 def bool_value(self, context: InferenceContext | None = None) -> Literal[True]: 

671 return True 

672 

673 

674class Generator(BaseInstance): 

675 """A special node representing a generator. 

676 

677 Proxied class is set once for all in raw_building. 

678 """ 

679 

680 # We defer initialization of special_attributes to the __init__ method since the constructor 

681 # of GeneratorModel requires the raw_building to be complete 

682 # TODO: This should probably be refactored. 

683 special_attributes: objectmodel.GeneratorModel 

684 

685 def __init__( 

686 self, 

687 parent: nodes.FunctionDef, 

688 generator_initial_context: InferenceContext | None = None, 

689 ) -> None: 

690 super().__init__() 

691 self.parent = parent 

692 self._call_context = copy_context(generator_initial_context) 

693 

694 # See comment above: this is a deferred initialization. 

695 Generator.special_attributes = objectmodel.GeneratorModel() 

696 

697 def infer_yield_types(self) -> Iterator[InferenceResult]: 

698 yield from self.parent.infer_yield_result(self._call_context) 

699 

700 def callable(self) -> Literal[False]: 

701 return False 

702 

703 def pytype(self) -> str: 

704 return "builtins.generator" 

705 

706 def display_type(self) -> str: 

707 return "Generator" 

708 

709 def bool_value(self, context: InferenceContext | None = None) -> Literal[True]: 

710 return True 

711 

712 def __repr__(self) -> str: 

713 return f"<Generator({self._proxied.name}) l.{self.lineno} at 0x{id(self)}>" 

714 

715 def __str__(self) -> str: 

716 return f"Generator({self._proxied.name})" 

717 

718 

719class AsyncGenerator(Generator): 

720 """Special node representing an async generator.""" 

721 

722 def pytype(self) -> Literal["builtins.async_generator"]: 

723 return "builtins.async_generator" 

724 

725 def display_type(self) -> str: 

726 return "AsyncGenerator" 

727 

728 def __repr__(self) -> str: 

729 return f"<AsyncGenerator({self._proxied.name}) l.{self.lineno} at 0x{id(self)}>" 

730 

731 def __str__(self) -> str: 

732 return f"AsyncGenerator({self._proxied.name})" 

733 

734 

735class UnionType(BaseInstance): 

736 """Special node representing new style typing unions. 

737 

738 Proxied class is set once for all in raw_building. 

739 """ 

740 

741 def __init__( 

742 self, 

743 left: UnionType | nodes.ClassDef | nodes.Const, 

744 right: UnionType | nodes.ClassDef | nodes.Const, 

745 parent: nodes.NodeNG | None = None, 

746 ) -> None: 

747 super().__init__() 

748 self.parent = parent 

749 self.left = left 

750 self.right = right 

751 

752 def callable(self) -> Literal[False]: 

753 return False 

754 

755 def bool_value(self, context: InferenceContext | None = None) -> Literal[True]: 

756 return True 

757 

758 def pytype(self) -> Literal["types.UnionType"]: 

759 return "types.UnionType" 

760 

761 def display_type(self) -> str: 

762 return "UnionType" 

763 

764 def __repr__(self) -> str: 

765 return f"<UnionType({self._proxied.name}) l.{self.lineno} at 0x{id(self)}>" 

766 

767 def __str__(self) -> str: 

768 return f"UnionType({self._proxied.name})"