Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/astroid/bases.py: 42%
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
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
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
5"""This module contains base classes and functions for the nodes and some
6inference utils.
7"""
9from __future__ import annotations
11import collections
12import collections.abc
13from collections.abc import Iterable, Iterator
14from typing import TYPE_CHECKING, Any, Literal
16from astroid import decorators, nodes
17from astroid.const import PY311_PLUS
18from astroid.context import (
19 CallContext,
20 InferenceContext,
21 bind_context_to_node,
22 copy_context,
23)
24from astroid.exceptions import (
25 AstroidTypeError,
26 AttributeInferenceError,
27 InferenceError,
28 NameInferenceError,
29)
30from astroid.interpreter import objectmodel
31from astroid.typing import (
32 InferenceErrorInfo,
33 InferenceResult,
34 SuccessfulInferenceResult,
35)
36from astroid.util import Uninferable, UninferableBase, safe_infer
38if TYPE_CHECKING:
39 from astroid.constraint import Constraint
42PROPERTIES = {"builtins.property", "abc.abstractproperty", "functools.cached_property"}
43# enum.property was added in Python 3.11
44if PY311_PLUS:
45 PROPERTIES.add("enum.property")
47# List of possible property names. We use this list in order
48# to see if a method is a property or not. This should be
49# pretty reliable and fast, the alternative being to check each
50# decorator to see if its a real property-like descriptor, which
51# can be too complicated.
52# Also, these aren't qualified, because each project can
53# define them, we shouldn't expect to know every possible
54# property-like decorator!
55POSSIBLE_PROPERTIES = {
56 "cached_property",
57 "cachedproperty",
58 "lazyproperty",
59 "lazy_property",
60 "reify",
61 "lazyattribute",
62 "lazy_attribute",
63 "LazyProperty",
64 "lazy",
65 "cache_readonly",
66 "DynamicClassAttribute",
67}
70def _is_property(
71 meth: nodes.FunctionDef | UnboundMethod, context: InferenceContext | None = None
72) -> bool:
73 decoratornames = meth.decoratornames(context=context)
74 if PROPERTIES.intersection(decoratornames):
75 return True
76 stripped = {
77 name.split(".")[-1]
78 for name in decoratornames
79 if not isinstance(name, UninferableBase)
80 }
81 if any(name in stripped for name in POSSIBLE_PROPERTIES):
82 return True
84 if not meth.decorators:
85 return False
86 # Lookup for subclasses of *property*
87 for decorator in meth.decorators.nodes or ():
88 inferred = safe_infer(decorator, context=context)
89 if inferred is None or isinstance(inferred, UninferableBase):
90 continue
91 if isinstance(inferred, nodes.ClassDef):
92 # Check for a class which inherits from a standard property type
93 if any(inferred.is_subtype_of(pclass) for pclass in PROPERTIES):
94 return True
95 for base_class in inferred.bases:
96 # Check for a class which inherits from functools.cached_property
97 # and includes a subscripted type annotation
98 if isinstance(base_class, nodes.Subscript):
99 value = safe_infer(base_class.value, context=context)
100 if not isinstance(value, nodes.ClassDef):
101 continue
102 if value.name != "cached_property":
103 continue
104 module, _ = value.lookup(value.name)
105 if isinstance(module, nodes.Module) and module.name == "functools":
106 return True
107 continue
109 return False
112class Proxy:
113 """A simple proxy object.
115 Note:
117 Subclasses of this object will need a custom __getattr__
118 if new instance attributes are created. See the Const class
119 """
121 _proxied: nodes.ClassDef | nodes.FunctionDef | nodes.Lambda | UnboundMethod
123 def __init__(
124 self,
125 proxied: (
126 nodes.ClassDef | nodes.FunctionDef | nodes.Lambda | UnboundMethod | None
127 ) = None,
128 ) -> None:
129 if proxied is None:
130 # This is a hack to allow calling this __init__ during bootstrapping of
131 # builtin classes and their docstrings.
132 # For Const, Generator, and UnionType nodes the _proxied attribute
133 # is set during bootstrapping
134 # as we first need to build the ClassDef that they can proxy.
135 # Thus, if proxied is None self should be a Const or Generator
136 # as that is the only way _proxied will be correctly set as a ClassDef.
137 assert isinstance(self, (nodes.Const, Generator, UnionType))
138 else:
139 self._proxied = proxied
141 def __getattr__(self, name: str) -> Any:
142 if name == "_proxied":
143 return self.__class__._proxied
144 if name in self.__dict__:
145 return self.__dict__[name]
146 return getattr(self._proxied, name)
148 def infer( # type: ignore[return]
149 self, context: InferenceContext | None = None, **kwargs: Any
150 ) -> collections.abc.Generator[InferenceResult, None, InferenceErrorInfo | None]:
151 yield self
154def _infer_stmts(
155 stmts: Iterable[InferenceResult],
156 context: InferenceContext | None,
157 frame: nodes.NodeNG | BaseInstance | None = None,
158) -> collections.abc.Generator[InferenceResult]:
159 """Return an iterator on statements inferred by each statement in *stmts*."""
160 inferred = False
161 constraint_failed = False
162 if context is not None:
163 name = context.lookupname
164 context = context.clone()
165 if name is not None:
166 constraints = context.constraints.get(name, {})
167 else:
168 constraints = {}
169 else:
170 name = None
171 constraints = {}
172 context = InferenceContext()
174 for stmt in stmts:
175 if isinstance(stmt, UninferableBase):
176 yield stmt
177 inferred = True
178 continue
179 context.lookupname = stmt._infer_name(frame, name)
180 try:
181 stmt_constraints: set[Constraint] = set()
182 for constraint_stmt, potential_constraints in constraints.items():
183 if not constraint_stmt.parent_of(stmt):
184 stmt_constraints.update(potential_constraints)
185 for inf in stmt.infer(context=context):
186 if all(
187 constraint.satisfied_by(inf, context)
188 for constraint in stmt_constraints
189 ):
190 yield inf
191 inferred = True
192 else:
193 constraint_failed = True
194 except NameInferenceError:
195 continue
196 except InferenceError:
197 yield Uninferable
198 inferred = True
200 if not inferred and constraint_failed:
201 yield Uninferable
202 elif not inferred:
203 raise InferenceError(
204 "Inference failed for all members of {stmts!r}.",
205 stmts=stmts,
206 frame=frame,
207 context=context,
208 )
211def _infer_method_result_truth(
212 instance: Instance, method_name: str, context: InferenceContext
213) -> bool | UninferableBase:
214 # Get the method from the instance and try to infer
215 # its return's truth value.
216 meth = next(instance.igetattr(method_name, context=context), None)
217 if meth and hasattr(meth, "infer_call_result"):
218 if not meth.callable():
219 return Uninferable
220 try:
221 context.callcontext = CallContext(args=[], callee=meth)
222 for value in meth.infer_call_result(instance, context=context):
223 if isinstance(value, UninferableBase):
224 return value
225 try:
226 inferred = next(value.infer(context=context))
227 except StopIteration as e:
228 raise InferenceError(context=context) from e
229 return inferred.bool_value()
230 except InferenceError:
231 pass
232 return Uninferable
235class BaseInstance(Proxy):
236 """An instance base class, which provides lookup methods for potential
237 instances.
238 """
240 _proxied: nodes.ClassDef
242 special_attributes: objectmodel.ObjectModel
244 def display_type(self) -> str:
245 return "Instance of"
247 def getattr(
248 self,
249 name: str,
250 context: InferenceContext | None = None,
251 lookupclass: bool = True,
252 ) -> list[InferenceResult]:
253 try:
254 values = self._proxied.instance_attr(name, context)
255 except AttributeInferenceError as exc:
256 if self.special_attributes and name in self.special_attributes:
257 special_attr = self.special_attributes.lookup(name)
258 if not isinstance(special_attr, nodes.Unknown):
259 return [special_attr]
261 if lookupclass:
262 # Class attributes not available through the instance
263 # unless they are explicitly defined.
264 return self._proxied.getattr(name, context, class_context=False)
266 raise AttributeInferenceError(
267 target=self, attribute=name, context=context
268 ) from exc
269 # since we've no context information, return matching class members as
270 # well
271 if lookupclass:
272 try:
273 return values + self._proxied.getattr(
274 name, context, class_context=False
275 )
276 except AttributeInferenceError:
277 pass
278 return values
280 def igetattr(
281 self, name: str, context: InferenceContext | None = None
282 ) -> Iterator[InferenceResult]:
283 """Inferred getattr."""
284 if not context:
285 context = InferenceContext()
286 try:
287 context.lookupname = name
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
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
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
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
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 if isinstance(node, BaseInstance) and node._proxied is self._proxied:
343 inferred = True
344 yield node
345 # Prevent recursion.
346 continue
347 for res in node.infer_call_result(caller, context):
348 inferred = True
349 yield res
350 if not inferred:
351 raise InferenceError(node=self, caller=caller, context=context)
354class Instance(BaseInstance):
355 """A special node representing a class instance."""
357 special_attributes = objectmodel.InstanceModel()
359 def __init__(self, proxied: nodes.ClassDef | None) -> None:
360 super().__init__(proxied)
362 @decorators.yes_if_nothing_inferred
363 def infer_binary_op(
364 self,
365 opnode: nodes.AugAssign | nodes.BinOp,
366 operator: str,
367 other: InferenceResult,
368 context: InferenceContext,
369 method: SuccessfulInferenceResult,
370 ) -> Generator[InferenceResult]:
371 return method.infer_call_result(self, context)
373 def __repr__(self) -> str:
374 return f"<Instance of {self._proxied.root().name}.{self._proxied.name} at 0x{id(self)}>"
376 def __str__(self) -> str:
377 return f"Instance of {self._proxied.root().name}.{self._proxied.name}"
379 def callable(self) -> bool:
380 try:
381 self._proxied.getattr("__call__", class_context=False)
382 return True
383 except AttributeInferenceError:
384 return False
386 def pytype(self) -> str:
387 return self._proxied.qname()
389 def display_type(self) -> str:
390 return "Instance of"
392 def bool_value(
393 self, context: InferenceContext | None = None
394 ) -> bool | UninferableBase:
395 """Infer the truth value for an Instance.
397 The truth value of an instance is determined by these conditions:
399 * if it implements __bool__ on Python 3 or __nonzero__
400 on Python 2, then its bool value will be determined by
401 calling this special method and checking its result.
402 * when this method is not defined, __len__() is called, if it
403 is defined, and the object is considered true if its result is
404 nonzero. If a class defines neither __len__() nor __bool__(),
405 all its instances are considered true.
406 """
407 context = context or InferenceContext()
408 context.boundnode = self
410 try:
411 result = _infer_method_result_truth(self, "__bool__", context)
412 except (InferenceError, AttributeInferenceError):
413 # Fallback to __len__.
414 try:
415 result = _infer_method_result_truth(self, "__len__", context)
416 except (AttributeInferenceError, InferenceError):
417 return True
418 return result
420 def getitem(
421 self, index: nodes.Const, context: InferenceContext | None = None
422 ) -> InferenceResult | None:
423 new_context = bind_context_to_node(context, self)
424 if not context:
425 context = new_context
426 method = next(self.igetattr("__getitem__", context=context), None)
427 # Create a new CallContext for providing index as an argument.
428 new_context.callcontext = CallContext(args=[index], callee=method)
429 if not isinstance(method, BoundMethod):
430 raise InferenceError(
431 "Could not find __getitem__ for {node!r}.", node=self, context=context
432 )
433 if len(method.args.arguments) != 2: # (self, index)
434 raise AstroidTypeError(
435 "__getitem__ for {node!r} does not have correct signature",
436 node=self,
437 context=context,
438 )
439 return next(method.infer_call_result(self, new_context), None)
442class UnboundMethod(Proxy):
443 """A special node representing a method not bound to an instance."""
445 _proxied: nodes.FunctionDef | UnboundMethod
447 special_attributes: (
448 objectmodel.BoundMethodModel | objectmodel.UnboundMethodModel
449 ) = objectmodel.UnboundMethodModel()
451 def __repr__(self) -> str:
452 assert self._proxied.parent, "Expected a parent node"
453 frame = self._proxied.parent.frame()
454 return f"<{self.__class__.__name__} {self._proxied.name} of {frame.qname()} at 0x{id(self)}"
456 def implicit_parameters(self) -> Literal[0, 1]:
457 return 0
459 def is_bound(self) -> bool:
460 return False
462 def getattr(self, name: str, context: InferenceContext | None = None):
463 if name in self.special_attributes:
464 special_attr = self.special_attributes.lookup(name)
465 if not isinstance(special_attr, nodes.Unknown):
466 return [special_attr]
467 return self._proxied.getattr(name, context)
469 def igetattr(
470 self, name: str, context: InferenceContext | None = None
471 ) -> Iterator[InferenceResult]:
472 if name in self.special_attributes:
473 special_attr = self.special_attributes.lookup(name)
474 if not isinstance(special_attr, nodes.Unknown):
475 return iter((special_attr,))
476 return self._proxied.igetattr(name, context)
478 def infer_call_result(
479 self,
480 caller: SuccessfulInferenceResult | None,
481 context: InferenceContext | None = None,
482 ) -> Iterator[InferenceResult]:
483 """
484 The boundnode of the regular context with a function called
485 on ``object.__new__`` will be of type ``object``,
486 which is incorrect for the argument in general.
487 If no context is given the ``object.__new__`` call argument will
488 be correctly inferred except when inside a call that requires
489 the additional context (such as a classmethod) of the boundnode
490 to determine which class the method was called from
491 """
493 # If we're unbound method __new__ of a builtin, the result is an
494 # instance of the class given as first argument.
495 if self._proxied.name == "__new__":
496 assert self._proxied.parent, "Expected a parent node"
497 qname = self._proxied.parent.frame().qname()
498 # Avoid checking builtins.type: _infer_type_new_call() does more validation
499 if qname.startswith("builtins.") and qname != "builtins.type":
500 return self._infer_builtin_new(caller, context or InferenceContext())
501 return self._proxied.infer_call_result(caller, context)
503 def _infer_builtin_new(
504 self,
505 caller: SuccessfulInferenceResult | None,
506 context: InferenceContext,
507 ) -> collections.abc.Generator[nodes.Const | Instance | UninferableBase]:
508 if not isinstance(caller, nodes.Call):
509 return
510 if not caller.args:
511 return
512 # Attempt to create a constant
513 if len(caller.args) > 1:
514 value = None
515 if isinstance(caller.args[1], nodes.Const):
516 value = caller.args[1].value
517 else:
518 inferred_arg = next(caller.args[1].infer(), None)
519 if isinstance(inferred_arg, nodes.Const):
520 value = inferred_arg.value
521 if value is not None:
522 const = nodes.const_factory(value)
523 assert not isinstance(const, nodes.EmptyNode)
524 yield const
525 return
527 node_context = context.extra_context.get(caller.args[0])
528 for inferred in caller.args[0].infer(context=node_context):
529 if isinstance(inferred, UninferableBase):
530 yield inferred
531 if isinstance(inferred, nodes.ClassDef):
532 yield Instance(inferred)
533 raise InferenceError
535 def bool_value(self, context: InferenceContext | None = None) -> Literal[True]:
536 return True
539class BoundMethod(UnboundMethod):
540 """A special node representing a method bound to an instance."""
542 special_attributes = objectmodel.BoundMethodModel()
544 def __init__(
545 self,
546 proxy: nodes.FunctionDef | nodes.Lambda | UnboundMethod,
547 bound: SuccessfulInferenceResult,
548 original_caller: SuccessfulInferenceResult | None = None,
549 ) -> None:
550 super().__init__(proxy)
551 self.bound = bound
552 # For super() calls: the actual instance/class that called super()
553 # Used to correctly infer return type of methods returning Self
554 self.original_caller = original_caller
556 def implicit_parameters(self) -> Literal[0, 1]:
557 if self.name == "__new__":
558 # __new__ acts as a classmethod but the class argument is not implicit.
559 return 0
560 return 1
562 def is_bound(self) -> Literal[True]:
563 return True
565 def _infer_type_new_call(
566 self, caller: nodes.Call, context: InferenceContext
567 ) -> nodes.ClassDef | None: # noqa: C901
568 """Try to infer what type.__new__(mcs, name, bases, attrs) returns.
570 In order for such call to be valid, the metaclass needs to be
571 a subtype of ``type``, the name needs to be a string, the bases
572 needs to be a tuple of classes
573 """
574 # pylint: disable=import-outside-toplevel; circular import
575 from astroid.nodes import Pass
577 # Verify the metaclass
578 try:
579 mcs = next(caller.args[0].infer(context=context))
580 except StopIteration as e:
581 raise InferenceError(context=context) from e
582 if not isinstance(mcs, nodes.ClassDef):
583 # Not a valid first argument.
584 raise InferenceError(
585 "type.__new__() requires a class for metaclass", context=context
586 )
587 if not mcs.is_subtype_of("builtins.type"):
588 # Not a valid metaclass.
589 raise InferenceError(
590 "type.__new__() metaclass must be a subclass of type", context=context
591 )
593 # Verify the name
594 try:
595 name = next(caller.args[1].infer(context=context))
596 except StopIteration as e:
597 raise InferenceError(context=context) from e
598 if not isinstance(name, nodes.Const):
599 # Not a valid name, needs to be a const.
600 raise InferenceError(
601 "type.__new__() requires a constant for name", context=context
602 )
603 if not isinstance(name.value, str):
604 # Needs to be a string.
605 raise InferenceError(
606 "type.__new__() requires a string for name", context=context
607 )
609 # Verify the bases
610 try:
611 bases = next(caller.args[2].infer(context=context))
612 except StopIteration as e:
613 raise InferenceError(context=context) from e
614 if not isinstance(bases, nodes.Tuple):
615 # Needs to be a tuple.
616 raise InferenceError(
617 "type.__new__() requires a tuple for bases", context=context
618 )
619 try:
620 inferred_bases = [next(elt.infer(context=context)) for elt in bases.elts]
621 except StopIteration as e:
622 raise InferenceError(context=context) from e
623 if any(not isinstance(base, nodes.ClassDef) for base in inferred_bases):
624 # All the bases needs to be Classes
625 raise InferenceError(
626 "type.__new__() requires classes for bases", context=context
627 )
629 # Verify the attributes.
630 try:
631 attrs = next(caller.args[3].infer(context=context))
632 except StopIteration as e:
633 raise InferenceError(context=context) from e
634 if not isinstance(attrs, nodes.Dict):
635 # Needs to be a dictionary.
636 raise InferenceError(
637 "type.__new__() requires a dict for attrs", context=context
638 )
639 cls_locals: dict[str, list[InferenceResult]] = collections.defaultdict(list)
640 for key, value in attrs.items:
641 try:
642 key = next(key.infer(context=context))
643 except StopIteration as e:
644 raise InferenceError(context=context) from e
645 try:
646 value = next(value.infer(context=context))
647 except StopIteration as e:
648 raise InferenceError(context=context) from e
649 # Ignore non string keys
650 if isinstance(key, nodes.Const) and isinstance(key.value, str):
651 cls_locals[key.value].append(value)
653 # Build the class from now.
654 cls = mcs.__class__(
655 name=name.value,
656 lineno=caller.lineno or 0,
657 col_offset=caller.col_offset or 0,
658 parent=caller,
659 end_lineno=caller.end_lineno,
660 end_col_offset=caller.end_col_offset,
661 )
662 empty = Pass(
663 parent=cls,
664 lineno=caller.lineno,
665 col_offset=caller.col_offset,
666 end_lineno=caller.end_lineno,
667 end_col_offset=caller.end_col_offset,
668 )
669 cls.postinit(
670 bases=bases.elts,
671 body=[empty],
672 decorators=None,
673 newstyle=True,
674 metaclass=mcs,
675 keywords=[],
676 )
677 cls.locals = cls_locals
678 return cls
680 def infer_call_result(
681 self,
682 caller: SuccessfulInferenceResult | None,
683 context: InferenceContext | None = None,
684 ) -> Iterator[InferenceResult]:
685 # For super() calls, use original_caller to correctly infer Self return type
686 bound_node = self.original_caller if self.original_caller else self.bound
687 context = bind_context_to_node(context, bound_node)
688 if (
689 isinstance(self.bound, nodes.ClassDef)
690 and self.bound.name == "type"
691 and self.name == "__new__"
692 and isinstance(caller, nodes.Call)
693 ):
694 # Check if we have a ``type.__new__(mcs, name, bases, attrs)`` call.
695 if len(caller.args) != 4:
696 raise InferenceError(
697 f"type.__new__() requires 4 arguments, got {len(caller.args)}",
698 context=context,
699 )
700 new_cls = self._infer_type_new_call(caller, context)
701 if new_cls:
702 return iter((new_cls,))
704 return super().infer_call_result(caller, context)
706 def bool_value(self, context: InferenceContext | None = None) -> Literal[True]:
707 return True
710class Generator(BaseInstance):
711 """A special node representing a generator.
713 Proxied class is set once for all in raw_building.
714 """
716 # We defer initialization of special_attributes to the __init__ method since the constructor
717 # of GeneratorModel requires the raw_building to be complete
718 # TODO: This should probably be refactored.
719 special_attributes: objectmodel.GeneratorBaseModel
721 def __init__(
722 self,
723 parent: nodes.FunctionDef,
724 generator_initial_context: InferenceContext | None = None,
725 ) -> None:
726 super().__init__()
727 self.parent = parent
728 self._call_context = copy_context(generator_initial_context)
730 # See comment above: this is a deferred initialization.
731 Generator.special_attributes = objectmodel.GeneratorModel()
733 def infer_yield_types(self) -> Iterator[InferenceResult]:
734 yield from self.parent.infer_yield_result(self._call_context)
736 def callable(self) -> Literal[False]:
737 return False
739 def pytype(self) -> str:
740 return "builtins.generator"
742 def display_type(self) -> str:
743 return "Generator"
745 def bool_value(self, context: InferenceContext | None = None) -> Literal[True]:
746 return True
748 def __repr__(self) -> str:
749 return f"<Generator({self._proxied.name}) l.{self.lineno} at 0x{id(self)}>"
751 def __str__(self) -> str:
752 return f"Generator({self._proxied.name})"
755class AsyncGenerator(Generator):
756 """Special node representing an async generator."""
758 def __init__(self, *args, **kwargs):
759 super().__init__(*args, **kwargs)
760 AsyncGenerator.special_attributes = objectmodel.AsyncGeneratorModel()
762 def pytype(self) -> Literal["builtins.async_generator"]:
763 return "builtins.async_generator"
765 def display_type(self) -> str:
766 return "AsyncGenerator"
768 def __repr__(self) -> str:
769 return f"<AsyncGenerator({self._proxied.name}) l.{self.lineno} at 0x{id(self)}>"
771 def __str__(self) -> str:
772 return f"AsyncGenerator({self._proxied.name})"
775class UnionType(BaseInstance):
776 """Special node representing new style typing unions.
778 Proxied class is set once for all in raw_building.
779 """
781 def __init__(
782 self,
783 left: UnionType | nodes.ClassDef | nodes.Const,
784 right: UnionType | nodes.ClassDef | nodes.Const,
785 parent: nodes.NodeNG | None = None,
786 ) -> None:
787 super().__init__()
788 self.parent = parent
789 self.left = left
790 self.right = right
792 def callable(self) -> Literal[False]:
793 return False
795 def bool_value(self, context: InferenceContext | None = None) -> Literal[True]:
796 return True
798 def pytype(self) -> Literal["types.UnionType"]:
799 return "types.UnionType"
801 def display_type(self) -> str:
802 return "UnionType"
804 def __repr__(self) -> str:
805 return f"<UnionType({self._proxied.name}) l.{self.lineno} at 0x{id(self)}>"
807 def __str__(self) -> str:
808 return f"UnionType({self._proxied.name})"