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

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

394 statements  

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, Literal 

14 

15from astroid import decorators, 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 InferenceErrorInfo, 

32 InferenceResult, 

33 SuccessfulInferenceResult, 

34) 

35from astroid.util import Uninferable, UninferableBase, safe_infer 

36 

37if TYPE_CHECKING: 

38 from astroid.constraint import Constraint 

39 

40 

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

42if PY310_PLUS: 

43 PROPERTIES.add("enum.property") 

44 

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

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

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

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

49# can be too complicated. 

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

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

52# property-like decorator! 

53POSSIBLE_PROPERTIES = { 

54 "cached_property", 

55 "cachedproperty", 

56 "lazyproperty", 

57 "lazy_property", 

58 "reify", 

59 "lazyattribute", 

60 "lazy_attribute", 

61 "LazyProperty", 

62 "lazy", 

63 "cache_readonly", 

64 "DynamicClassAttribute", 

65} 

66 

67 

68def _is_property( 

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

70) -> bool: 

71 decoratornames = meth.decoratornames(context=context) 

72 if PROPERTIES.intersection(decoratornames): 

73 return True 

74 stripped = { 

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

76 for name in decoratornames 

77 if not isinstance(name, UninferableBase) 

78 } 

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

80 return True 

81 

82 # Lookup for subclasses of *property* 

83 if not meth.decorators: 

84 return False 

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

86 inferred = safe_infer(decorator, context=context) 

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

88 continue 

89 if isinstance(inferred, nodes.ClassDef): 

90 for base_class in inferred.bases: 

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

92 continue 

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

94 if ( 

95 isinstance(module, nodes.Module) 

96 and module.name == "builtins" 

97 and base_class.name == "property" 

98 ): 

99 return True 

100 

101 return False 

102 

103 

104class Proxy: 

105 """A simple proxy object. 

106 

107 Note: 

108 

109 Subclasses of this object will need a custom __getattr__ 

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

111 """ 

112 

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

114 

115 def __init__( 

116 self, 

117 proxied: ( 

118 nodes.ClassDef | nodes.FunctionDef | nodes.Lambda | UnboundMethod | None 

119 ) = None, 

120 ) -> None: 

121 if proxied is None: 

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

123 # builtin classes and their docstrings. 

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

125 # is set during bootstrapping 

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

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

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

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

130 else: 

131 self._proxied = proxied 

132 

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

134 if name == "_proxied": 

135 return self.__class__._proxied 

136 if name in self.__dict__: 

137 return self.__dict__[name] 

138 return getattr(self._proxied, name) 

139 

140 def infer( # type: ignore[return] 

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

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

143 yield self 

144 

145 

146def _infer_stmts( 

147 stmts: Iterable[InferenceResult], 

148 context: InferenceContext | None, 

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

150) -> collections.abc.Generator[InferenceResult]: 

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

152 inferred = False 

153 constraint_failed = False 

154 if context is not None: 

155 name = context.lookupname 

156 context = context.clone() 

157 if name is not None: 

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

159 else: 

160 constraints = {} 

161 else: 

162 name = None 

163 constraints = {} 

164 context = InferenceContext() 

165 

166 for stmt in stmts: 

167 if isinstance(stmt, UninferableBase): 

168 yield stmt 

169 inferred = True 

170 continue 

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

172 try: 

173 stmt_constraints: set[Constraint] = set() 

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

175 if not constraint_stmt.parent_of(stmt): 

176 stmt_constraints.update(potential_constraints) 

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

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

179 yield inf 

180 inferred = True 

181 else: 

182 constraint_failed = True 

183 except NameInferenceError: 

184 continue 

185 except InferenceError: 

186 yield Uninferable 

187 inferred = True 

188 

189 if not inferred and constraint_failed: 

190 yield Uninferable 

191 elif not inferred: 

192 raise InferenceError( 

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

194 stmts=stmts, 

195 frame=frame, 

196 context=context, 

197 ) 

198 

199 

200def _infer_method_result_truth( 

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

202) -> bool | UninferableBase: 

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

204 # its return's truth value. 

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

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

207 if not meth.callable(): 

208 return Uninferable 

209 try: 

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

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

212 if isinstance(value, UninferableBase): 

213 return value 

214 try: 

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

216 except StopIteration as e: 

217 raise InferenceError(context=context) from e 

218 return inferred.bool_value() 

219 except InferenceError: 

220 pass 

221 return Uninferable 

222 

223 

224class BaseInstance(Proxy): 

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

226 instances. 

227 """ 

228 

229 _proxied: nodes.ClassDef 

230 

231 special_attributes: objectmodel.ObjectModel 

232 

233 def display_type(self) -> str: 

234 return "Instance of" 

235 

236 def getattr( 

237 self, 

238 name: str, 

239 context: InferenceContext | None = None, 

240 lookupclass: bool = True, 

241 ) -> list[InferenceResult]: 

242 try: 

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

244 except AttributeInferenceError as exc: 

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

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

247 

248 if lookupclass: 

249 # Class attributes not available through the instance 

250 # unless they are explicitly defined. 

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

252 

253 raise AttributeInferenceError( 

254 target=self, attribute=name, context=context 

255 ) from exc 

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

257 # well 

258 if lookupclass: 

259 try: 

260 return values + self._proxied.getattr( 

261 name, context, class_context=False 

262 ) 

263 except AttributeInferenceError: 

264 pass 

265 return values 

266 

267 def igetattr( 

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

269 ) -> Iterator[InferenceResult]: 

270 """Inferred getattr.""" 

271 if not context: 

272 context = InferenceContext() 

273 try: 

274 context.lookupname = name 

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

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

277 yield from _infer_stmts( 

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

279 ) 

280 except AttributeInferenceError: 

281 try: 

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

283 # descriptors 

284 # But only if the _proxied is the Class. 

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

286 raise 

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

288 yield from self._wrap_attr(attrs, context) 

289 except AttributeInferenceError as error: 

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

291 

292 def _wrap_attr( 

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

294 ) -> Iterator[InferenceResult]: 

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

296 for attr in attrs: 

297 if isinstance(attr, UnboundMethod): 

298 if _is_property(attr): 

299 yield from attr.infer_call_result(self, context) 

300 else: 

301 yield BoundMethod(attr, self) 

302 elif isinstance(attr, nodes.Lambda): 

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

304 yield BoundMethod(attr, self) 

305 continue 

306 yield attr 

307 else: 

308 yield attr 

309 

310 def infer_call_result( 

311 self, 

312 caller: SuccessfulInferenceResult | None, 

313 context: InferenceContext | None = None, 

314 ) -> Iterator[InferenceResult]: 

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

316 context = bind_context_to_node(context, self) 

317 inferred = False 

318 

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

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

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

322 inferred = True 

323 yield res 

324 

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

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

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

328 continue 

329 if isinstance(node, BaseInstance) and node._proxied is self._proxied: 

330 inferred = True 

331 yield node 

332 # Prevent recursion. 

333 continue 

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

335 inferred = True 

336 yield res 

337 if not inferred: 

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

339 

340 

341class Instance(BaseInstance): 

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

343 

344 special_attributes = objectmodel.InstanceModel() 

345 

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

347 super().__init__(proxied) 

348 

349 @decorators.yes_if_nothing_inferred 

350 def infer_binary_op( 

351 self, 

352 opnode: nodes.AugAssign | nodes.BinOp, 

353 operator: str, 

354 other: InferenceResult, 

355 context: InferenceContext, 

356 method: SuccessfulInferenceResult, 

357 ) -> Generator[InferenceResult]: 

358 return method.infer_call_result(self, context) 

359 

360 def __repr__(self) -> str: 

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

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

363 ) 

364 

365 def __str__(self) -> str: 

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

367 

368 def callable(self) -> bool: 

369 try: 

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

371 return True 

372 except AttributeInferenceError: 

373 return False 

374 

375 def pytype(self) -> str: 

376 return self._proxied.qname() 

377 

378 def display_type(self) -> str: 

379 return "Instance of" 

380 

381 def bool_value( 

382 self, context: InferenceContext | None = None 

383 ) -> bool | UninferableBase: 

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

385 

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

387 

388 * if it implements __bool__ on Python 3 or __nonzero__ 

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

390 calling this special method and checking its result. 

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

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

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

394 all its instances are considered true. 

395 """ 

396 context = context or InferenceContext() 

397 context.boundnode = self 

398 

399 try: 

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

401 except (InferenceError, AttributeInferenceError): 

402 # Fallback to __len__. 

403 try: 

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

405 except (AttributeInferenceError, InferenceError): 

406 return True 

407 return result 

408 

409 def getitem( 

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

411 ) -> InferenceResult | None: 

412 new_context = bind_context_to_node(context, self) 

413 if not context: 

414 context = new_context 

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

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

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

418 if not isinstance(method, BoundMethod): 

419 raise InferenceError( 

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

421 ) 

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

423 raise AstroidTypeError( 

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

425 node=self, 

426 context=context, 

427 ) 

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

429 

430 

431class UnboundMethod(Proxy): 

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

433 

434 _proxied: nodes.FunctionDef | UnboundMethod 

435 

436 special_attributes: ( 

437 objectmodel.BoundMethodModel | objectmodel.UnboundMethodModel 

438 ) = objectmodel.UnboundMethodModel() 

439 

440 def __repr__(self) -> str: 

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

442 frame = self._proxied.parent.frame() 

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

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

445 ) 

446 

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

448 return 0 

449 

450 def is_bound(self) -> bool: 

451 return False 

452 

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

454 if name in self.special_attributes: 

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

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

457 

458 def igetattr( 

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

460 ) -> Iterator[InferenceResult]: 

461 if name in self.special_attributes: 

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

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

464 

465 def infer_call_result( 

466 self, 

467 caller: SuccessfulInferenceResult | None, 

468 context: InferenceContext | None = None, 

469 ) -> Iterator[InferenceResult]: 

470 """ 

471 The boundnode of the regular context with a function called 

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

473 which is incorrect for the argument in general. 

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

475 be correctly inferred except when inside a call that requires 

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

477 to determine which class the method was called from 

478 """ 

479 

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

481 # instance of the class given as first argument. 

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

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

484 qname = self._proxied.parent.frame().qname() 

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

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

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

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

489 

490 def _infer_builtin_new( 

491 self, 

492 caller: SuccessfulInferenceResult | None, 

493 context: InferenceContext, 

494 ) -> collections.abc.Generator[nodes.Const | Instance | UninferableBase]: 

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

496 return 

497 if not caller.args: 

498 return 

499 # Attempt to create a constant 

500 if len(caller.args) > 1: 

501 value = None 

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

503 value = caller.args[1].value 

504 else: 

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

506 if isinstance(inferred_arg, nodes.Const): 

507 value = inferred_arg.value 

508 if value is not None: 

509 const = nodes.const_factory(value) 

510 assert not isinstance(const, nodes.EmptyNode) 

511 yield const 

512 return 

513 

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

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

516 if isinstance(inferred, UninferableBase): 

517 yield inferred 

518 if isinstance(inferred, nodes.ClassDef): 

519 yield Instance(inferred) 

520 raise InferenceError 

521 

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

523 return True 

524 

525 

526class BoundMethod(UnboundMethod): 

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

528 

529 special_attributes = objectmodel.BoundMethodModel() 

530 

531 def __init__( 

532 self, 

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

534 bound: SuccessfulInferenceResult, 

535 ) -> None: 

536 super().__init__(proxy) 

537 self.bound = bound 

538 

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

540 if self.name == "__new__": 

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

542 return 0 

543 return 1 

544 

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

546 return True 

547 

548 def _infer_type_new_call( 

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

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

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

552 

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

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

555 needs to be a tuple of classes 

556 """ 

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

558 from astroid.nodes import Pass 

559 

560 # Verify the metaclass 

561 try: 

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

563 except StopIteration as e: 

564 raise InferenceError(context=context) from e 

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

566 # Not a valid first argument. 

567 return None 

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

569 # Not a valid metaclass. 

570 return None 

571 

572 # Verify the name 

573 try: 

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

575 except StopIteration as e: 

576 raise InferenceError(context=context) from e 

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

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

579 return None 

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

581 # Needs to be a string. 

582 return None 

583 

584 # Verify the bases 

585 try: 

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

587 except StopIteration as e: 

588 raise InferenceError(context=context) from e 

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

590 # Needs to be a tuple. 

591 return None 

592 try: 

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

594 except StopIteration as e: 

595 raise InferenceError(context=context) from e 

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

597 # All the bases needs to be Classes 

598 return None 

599 

600 # Verify the attributes. 

601 try: 

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

603 except StopIteration as e: 

604 raise InferenceError(context=context) from e 

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

606 # Needs to be a dictionary. 

607 return None 

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

609 for key, value in attrs.items: 

610 try: 

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

612 except StopIteration as e: 

613 raise InferenceError(context=context) from e 

614 try: 

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

616 except StopIteration as e: 

617 raise InferenceError(context=context) from e 

618 # Ignore non string keys 

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

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

621 

622 # Build the class from now. 

623 cls = mcs.__class__( 

624 name=name.value, 

625 lineno=caller.lineno or 0, 

626 col_offset=caller.col_offset or 0, 

627 parent=caller, 

628 end_lineno=caller.end_lineno, 

629 end_col_offset=caller.end_col_offset, 

630 ) 

631 empty = Pass( 

632 parent=cls, 

633 lineno=caller.lineno, 

634 col_offset=caller.col_offset, 

635 end_lineno=caller.end_lineno, 

636 end_col_offset=caller.end_col_offset, 

637 ) 

638 cls.postinit( 

639 bases=bases.elts, 

640 body=[empty], 

641 decorators=None, 

642 newstyle=True, 

643 metaclass=mcs, 

644 keywords=[], 

645 ) 

646 cls.locals = cls_locals 

647 return cls 

648 

649 def infer_call_result( 

650 self, 

651 caller: SuccessfulInferenceResult | None, 

652 context: InferenceContext | None = None, 

653 ) -> Iterator[InferenceResult]: 

654 context = bind_context_to_node(context, self.bound) 

655 if ( 

656 isinstance(self.bound, nodes.ClassDef) 

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

658 and self.name == "__new__" 

659 and isinstance(caller, nodes.Call) 

660 and len(caller.args) == 4 

661 ): 

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

663 new_cls = self._infer_type_new_call(caller, context) 

664 if new_cls: 

665 return iter((new_cls,)) 

666 

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

668 

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

670 return True 

671 

672 

673class Generator(BaseInstance): 

674 """A special node representing a generator. 

675 

676 Proxied class is set once for all in raw_building. 

677 """ 

678 

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

680 # of GeneratorModel requires the raw_building to be complete 

681 # TODO: This should probably be refactored. 

682 special_attributes: objectmodel.GeneratorBaseModel 

683 

684 def __init__( 

685 self, 

686 parent: nodes.FunctionDef, 

687 generator_initial_context: InferenceContext | None = None, 

688 ) -> None: 

689 super().__init__() 

690 self.parent = parent 

691 self._call_context = copy_context(generator_initial_context) 

692 

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

694 Generator.special_attributes = objectmodel.GeneratorModel() 

695 

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

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

698 

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

700 return False 

701 

702 def pytype(self) -> str: 

703 return "builtins.generator" 

704 

705 def display_type(self) -> str: 

706 return "Generator" 

707 

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

709 return True 

710 

711 def __repr__(self) -> str: 

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

713 

714 def __str__(self) -> str: 

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

716 

717 

718class AsyncGenerator(Generator): 

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

720 

721 def __init__(self, *args, **kwargs): 

722 super().__init__(*args, **kwargs) 

723 AsyncGenerator.special_attributes = objectmodel.AsyncGeneratorModel() 

724 

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

726 return "builtins.async_generator" 

727 

728 def display_type(self) -> str: 

729 return "AsyncGenerator" 

730 

731 def __repr__(self) -> str: 

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

733 

734 def __str__(self) -> str: 

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

736 

737 

738class UnionType(BaseInstance): 

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

740 

741 Proxied class is set once for all in raw_building. 

742 """ 

743 

744 def __init__( 

745 self, 

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

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

748 parent: nodes.NodeNG | None = None, 

749 ) -> None: 

750 super().__init__() 

751 self.parent = parent 

752 self.left = left 

753 self.right = right 

754 

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

756 return False 

757 

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

759 return True 

760 

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

762 return "types.UnionType" 

763 

764 def display_type(self) -> str: 

765 return "UnionType" 

766 

767 def __repr__(self) -> str: 

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

769 

770 def __str__(self) -> str: 

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