PNG  IHDRxsBIT|d pHYs+tEXtSoftwarewww.inkscape.org<,tEXtComment File Manager

File Manager

Path: /opt/cloudlinux/venv/lib64/python3.11/site-packages/astroid/

Viewing File: bases.py

# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
# For details: https://github.com/PyCQA/astroid/blob/main/LICENSE
# Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt

"""This module contains base classes and functions for the nodes and some
inference utils.
"""
from __future__ import annotations

import collections
import collections.abc
import sys
from collections.abc import Sequence
from typing import TYPE_CHECKING, Any, ClassVar

from astroid import decorators, nodes
from astroid.const import PY310_PLUS
from astroid.context import (
    CallContext,
    InferenceContext,
    bind_context_to_node,
    copy_context,
)
from astroid.exceptions import (
    AstroidTypeError,
    AttributeInferenceError,
    InferenceError,
    NameInferenceError,
)
from astroid.typing import InferBinaryOp, InferenceErrorInfo, InferenceResult
from astroid.util import Uninferable, UninferableBase, lazy_descriptor, lazy_import

if sys.version_info >= (3, 8):
    from typing import Literal
else:
    from typing_extensions import Literal

if TYPE_CHECKING:
    from astroid.constraint import Constraint

objectmodel = lazy_import("interpreter.objectmodel")
helpers = lazy_import("helpers")
manager = lazy_import("manager")


# TODO: check if needs special treatment
BOOL_SPECIAL_METHOD = "__bool__"
BUILTINS = "builtins"  # TODO Remove in 2.8

PROPERTIES = {"builtins.property", "abc.abstractproperty"}
if PY310_PLUS:
    PROPERTIES.add("enum.property")

# List of possible property names. We use this list in order
# to see if a method is a property or not. This should be
# pretty reliable and fast, the alternative being to check each
# decorator to see if its a real property-like descriptor, which
# can be too complicated.
# Also, these aren't qualified, because each project can
# define them, we shouldn't expect to know every possible
# property-like decorator!
POSSIBLE_PROPERTIES = {
    "cached_property",
    "cachedproperty",
    "lazyproperty",
    "lazy_property",
    "reify",
    "lazyattribute",
    "lazy_attribute",
    "LazyProperty",
    "lazy",
    "cache_readonly",
    "DynamicClassAttribute",
}


def _is_property(meth, context: InferenceContext | None = None) -> bool:
    decoratornames = meth.decoratornames(context=context)
    if PROPERTIES.intersection(decoratornames):
        return True
    stripped = {
        name.split(".")[-1]
        for name in decoratornames
        if not isinstance(name, UninferableBase)
    }
    if any(name in stripped for name in POSSIBLE_PROPERTIES):
        return True

    # Lookup for subclasses of *property*
    if not meth.decorators:
        return False
    for decorator in meth.decorators.nodes or ():
        inferred = helpers.safe_infer(decorator, context=context)
        if inferred is None or isinstance(inferred, UninferableBase):
            continue
        if inferred.__class__.__name__ == "ClassDef":
            for base_class in inferred.bases:
                if base_class.__class__.__name__ != "Name":
                    continue
                module, _ = base_class.lookup(base_class.name)
                if module.name == "builtins" and base_class.name == "property":
                    return True

    return False


class Proxy:
    """A simple proxy object.

    Note:

    Subclasses of this object will need a custom __getattr__
    if new instance attributes are created. See the Const class
    """

    _proxied: nodes.ClassDef | nodes.Lambda | Proxy | None = (
        None  # proxied object may be set by class or by instance
    )

    def __init__(
        self, proxied: nodes.ClassDef | nodes.Lambda | Proxy | None = None
    ) -> None:
        if proxied is None:
            # This is a hack to allow calling this __init__ during bootstrapping of
            # builtin classes and their docstrings.
            # For Const, Generator, and UnionType nodes the _proxied attribute
            # is set during bootstrapping
            # as we first need to build the ClassDef that they can proxy.
            # Thus, if proxied is None self should be a Const or Generator
            # as that is the only way _proxied will be correctly set as a ClassDef.
            assert isinstance(self, (nodes.Const, Generator, UnionType))
        else:
            self._proxied = proxied

    def __getattr__(self, name):
        if name == "_proxied":
            return self.__class__._proxied
        if name in self.__dict__:
            return self.__dict__[name]
        return getattr(self._proxied, name)

    def infer(  # type: ignore[return]
        self, context: InferenceContext | None = None, **kwargs: Any
    ) -> collections.abc.Generator[InferenceResult, None, InferenceErrorInfo | None]:
        yield self


def _infer_stmts(
    stmts: Sequence[nodes.NodeNG | UninferableBase | Instance],
    context: InferenceContext | None,
    frame: nodes.NodeNG | Instance | None = None,
) -> collections.abc.Generator[InferenceResult, None, None]:
    """Return an iterator on statements inferred by each statement in *stmts*."""
    inferred = False
    constraint_failed = False
    if context is not None:
        name = context.lookupname
        context = context.clone()
        constraints = context.constraints.get(name, {})
    else:
        name = None
        constraints = {}
        context = InferenceContext()

    for stmt in stmts:
        if isinstance(stmt, UninferableBase):
            yield stmt
            inferred = True
            continue
        # 'context' is always InferenceContext and Instances get '_infer_name' from ClassDef
        context.lookupname = stmt._infer_name(frame, name)  # type: ignore[union-attr]
        try:
            stmt_constraints: set[Constraint] = set()
            for constraint_stmt, potential_constraints in constraints.items():
                if not constraint_stmt.parent_of(stmt):
                    stmt_constraints.update(potential_constraints)
            for inf in stmt.infer(context=context):
                if all(constraint.satisfied_by(inf) for constraint in stmt_constraints):
                    yield inf
                    inferred = True
                else:
                    constraint_failed = True
        except NameInferenceError:
            continue
        except InferenceError:
            yield Uninferable
            inferred = True

    if not inferred and constraint_failed:
        yield Uninferable
    elif not inferred:
        raise InferenceError(
            "Inference failed for all members of {stmts!r}.",
            stmts=stmts,
            frame=frame,
            context=context,
        )


def _infer_method_result_truth(instance, method_name, context):
    # Get the method from the instance and try to infer
    # its return's truth value.
    meth = next(instance.igetattr(method_name, context=context), None)
    if meth and hasattr(meth, "infer_call_result"):
        if not meth.callable():
            return Uninferable
        try:
            context.callcontext = CallContext(args=[], callee=meth)
            for value in meth.infer_call_result(instance, context=context):
                if isinstance(value, UninferableBase):
                    return value
                try:
                    inferred = next(value.infer(context=context))
                except StopIteration as e:
                    raise InferenceError(context=context) from e
                return inferred.bool_value()
        except InferenceError:
            pass
    return Uninferable


class BaseInstance(Proxy):
    """An instance base class, which provides lookup methods for potential
    instances.
    """

    special_attributes = None

    def display_type(self) -> str:
        return "Instance of"

    def getattr(self, name, context: InferenceContext | None = None, lookupclass=True):
        try:
            values = self._proxied.instance_attr(name, context)
        except AttributeInferenceError as exc:
            if self.special_attributes and name in self.special_attributes:
                return [self.special_attributes.lookup(name)]

            if lookupclass:
                # Class attributes not available through the instance
                # unless they are explicitly defined.
                return self._proxied.getattr(name, context, class_context=False)

            raise AttributeInferenceError(
                target=self, attribute=name, context=context
            ) from exc
        # since we've no context information, return matching class members as
        # well
        if lookupclass:
            try:
                return values + self._proxied.getattr(
                    name, context, class_context=False
                )
            except AttributeInferenceError:
                pass
        return values

    def igetattr(self, name, context: InferenceContext | None = None):
        """Inferred getattr."""
        if not context:
            context = InferenceContext()
        try:
            context.lookupname = name
            # avoid recursively inferring the same attr on the same class
            if context.push(self._proxied):
                raise InferenceError(
                    message="Cannot infer the same attribute again",
                    node=self,
                    context=context,
                )

            # XXX frame should be self._proxied, or not ?
            get_attr = self.getattr(name, context, lookupclass=False)
            yield from _infer_stmts(
                self._wrap_attr(get_attr, context), context, frame=self
            )
        except AttributeInferenceError:
            try:
                # fallback to class.igetattr since it has some logic to handle
                # descriptors
                # But only if the _proxied is the Class.
                if self._proxied.__class__.__name__ != "ClassDef":
                    raise
                attrs = self._proxied.igetattr(name, context, class_context=False)
                yield from self._wrap_attr(attrs, context)
            except AttributeInferenceError as error:
                raise InferenceError(**vars(error)) from error

    def _wrap_attr(self, attrs, context: InferenceContext | None = None):
        """Wrap bound methods of attrs in a InstanceMethod proxies."""
        for attr in attrs:
            if isinstance(attr, UnboundMethod):
                if _is_property(attr):
                    yield from attr.infer_call_result(self, context)
                else:
                    yield BoundMethod(attr, self)
            elif hasattr(attr, "name") and attr.name == "<lambda>":
                if attr.args.arguments and attr.args.arguments[0].name == "self":
                    yield BoundMethod(attr, self)
                    continue
                yield attr
            else:
                yield attr

    def infer_call_result(
        self, caller: nodes.Call | Proxy, context: InferenceContext | None = None
    ):
        """Infer what a class instance is returning when called."""
        context = bind_context_to_node(context, self)
        inferred = False

        # If the call is an attribute on the instance, we infer the attribute itself
        if isinstance(caller, nodes.Call) and isinstance(caller.func, nodes.Attribute):
            for res in self.igetattr(caller.func.attrname, context):
                inferred = True
                yield res

        # Otherwise we infer the call to the __call__ dunder normally
        for node in self._proxied.igetattr("__call__", context):
            if isinstance(node, UninferableBase) or not node.callable():
                continue
            for res in node.infer_call_result(caller, context):
                inferred = True
                yield res
        if not inferred:
            raise InferenceError(node=self, caller=caller, context=context)


class Instance(BaseInstance):
    """A special node representing a class instance."""

    _proxied: nodes.ClassDef

    # pylint: disable=unnecessary-lambda
    special_attributes = lazy_descriptor(lambda: objectmodel.InstanceModel())

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

    infer_binary_op: ClassVar[InferBinaryOp[Instance]]

    def __repr__(self) -> str:
        return "<Instance of {}.{} at 0x{}>".format(
            self._proxied.root().name, self._proxied.name, id(self)
        )

    def __str__(self) -> str:
        return f"Instance of {self._proxied.root().name}.{self._proxied.name}"

    def callable(self) -> bool:
        try:
            self._proxied.getattr("__call__", class_context=False)
            return True
        except AttributeInferenceError:
            return False

    def pytype(self) -> str:
        return self._proxied.qname()

    def display_type(self) -> str:
        return "Instance of"

    def bool_value(self, context: InferenceContext | None = None):
        """Infer the truth value for an Instance.

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

           * if it implements __bool__ on Python 3 or __nonzero__
             on Python 2, then its bool value will be determined by
             calling this special method and checking its result.
           * when this method is not defined, __len__() is called, if it
             is defined, and the object is considered true if its result is
             nonzero. If a class defines neither __len__() nor __bool__(),
             all its instances are considered true.
        """
        context = context or InferenceContext()
        context.boundnode = self

        try:
            result = _infer_method_result_truth(self, BOOL_SPECIAL_METHOD, context)
        except (InferenceError, AttributeInferenceError):
            # Fallback to __len__.
            try:
                result = _infer_method_result_truth(self, "__len__", context)
            except (AttributeInferenceError, InferenceError):
                return True
        return result

    def getitem(self, index, context: InferenceContext | None = None):
        new_context = bind_context_to_node(context, self)
        if not context:
            context = new_context
        method = next(self.igetattr("__getitem__", context=context), None)
        # Create a new CallContext for providing index as an argument.
        new_context.callcontext = CallContext(args=[index], callee=method)
        if not isinstance(method, BoundMethod):
            raise InferenceError(
                "Could not find __getitem__ for {node!r}.", node=self, context=context
            )
        if len(method.args.arguments) != 2:  # (self, index)
            raise AstroidTypeError(
                "__getitem__ for {node!r} does not have correct signature",
                node=self,
                context=context,
            )
        return next(method.infer_call_result(self, new_context), None)


class UnboundMethod(Proxy):
    """A special node representing a method not bound to an instance."""

    # pylint: disable=unnecessary-lambda
    special_attributes = lazy_descriptor(lambda: objectmodel.UnboundMethodModel())

    def __repr__(self) -> str:
        frame = self._proxied.parent.frame(future=True)
        return "<{} {} of {} at 0x{}".format(
            self.__class__.__name__, self._proxied.name, frame.qname(), id(self)
        )

    def implicit_parameters(self) -> Literal[0]:
        return 0

    def is_bound(self) -> Literal[False]:
        return False

    def getattr(self, name, context: InferenceContext | None = None):
        if name in self.special_attributes:
            return [self.special_attributes.lookup(name)]
        return self._proxied.getattr(name, context)

    def igetattr(self, name, context: InferenceContext | None = None):
        if name in self.special_attributes:
            return iter((self.special_attributes.lookup(name),))
        return self._proxied.igetattr(name, context)

    def infer_call_result(self, caller, context):
        """
        The boundnode of the regular context with a function called
        on ``object.__new__`` will be of type ``object``,
        which is incorrect for the argument in general.
        If no context is given the ``object.__new__`` call argument will
        be correctly inferred except when inside a call that requires
        the additional context (such as a classmethod) of the boundnode
        to determine which class the method was called from
        """

        # If we're unbound method __new__ of a builtin, the result is an
        # instance of the class given as first argument.
        if self._proxied.name == "__new__":
            qname = self._proxied.parent.frame(future=True).qname()
            # Avoid checking builtins.type: _infer_type_new_call() does more validation
            if qname.startswith("builtins.") and qname != "builtins.type":
                return self._infer_builtin_new(caller, context)
        return self._proxied.infer_call_result(caller, context)

    def _infer_builtin_new(
        self,
        caller: nodes.Call,
        context: InferenceContext,
    ) -> collections.abc.Generator[
        nodes.Const | Instance | UninferableBase, None, None
    ]:
        if not caller.args:
            return
        # Attempt to create a constant
        if len(caller.args) > 1:
            value = None
            if isinstance(caller.args[1], nodes.Const):
                value = caller.args[1].value
            else:
                inferred_arg = next(caller.args[1].infer(), None)
                if isinstance(inferred_arg, nodes.Const):
                    value = inferred_arg.value
            if value is not None:
                yield nodes.const_factory(value)
                return

        node_context = context.extra_context.get(caller.args[0])
        for inferred in caller.args[0].infer(context=node_context):
            if isinstance(inferred, UninferableBase):
                yield inferred
            if isinstance(inferred, nodes.ClassDef):
                yield Instance(inferred)
            raise InferenceError

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


class BoundMethod(UnboundMethod):
    """A special node representing a method bound to an instance."""

    # pylint: disable=unnecessary-lambda
    special_attributes = lazy_descriptor(lambda: objectmodel.BoundMethodModel())

    def __init__(self, proxy, bound):
        super().__init__(proxy)
        self.bound = bound

    def implicit_parameters(self) -> Literal[0, 1]:
        if self.name == "__new__":
            # __new__ acts as a classmethod but the class argument is not implicit.
            return 0
        return 1

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

    def _infer_type_new_call(self, caller, context):  # noqa: C901
        """Try to infer what type.__new__(mcs, name, bases, attrs) returns.

        In order for such call to be valid, the metaclass needs to be
        a subtype of ``type``, the name needs to be a string, the bases
        needs to be a tuple of classes
        """
        # pylint: disable=import-outside-toplevel; circular import
        from astroid.nodes import Pass

        # Verify the metaclass
        try:
            mcs = next(caller.args[0].infer(context=context))
        except StopIteration as e:
            raise InferenceError(context=context) from e
        if mcs.__class__.__name__ != "ClassDef":
            # Not a valid first argument.
            return None
        if not mcs.is_subtype_of("builtins.type"):
            # Not a valid metaclass.
            return None

        # Verify the name
        try:
            name = next(caller.args[1].infer(context=context))
        except StopIteration as e:
            raise InferenceError(context=context) from e
        if name.__class__.__name__ != "Const":
            # Not a valid name, needs to be a const.
            return None
        if not isinstance(name.value, str):
            # Needs to be a string.
            return None

        # Verify the bases
        try:
            bases = next(caller.args[2].infer(context=context))
        except StopIteration as e:
            raise InferenceError(context=context) from e
        if bases.__class__.__name__ != "Tuple":
            # Needs to be a tuple.
            return None
        try:
            inferred_bases = [next(elt.infer(context=context)) for elt in bases.elts]
        except StopIteration as e:
            raise InferenceError(context=context) from e
        if any(base.__class__.__name__ != "ClassDef" for base in inferred_bases):
            # All the bases needs to be Classes
            return None

        # Verify the attributes.
        try:
            attrs = next(caller.args[3].infer(context=context))
        except StopIteration as e:
            raise InferenceError(context=context) from e
        if attrs.__class__.__name__ != "Dict":
            # Needs to be a dictionary.
            return None
        cls_locals = collections.defaultdict(list)
        for key, value in attrs.items:
            try:
                key = next(key.infer(context=context))
            except StopIteration as e:
                raise InferenceError(context=context) from e
            try:
                value = next(value.infer(context=context))
            except StopIteration as e:
                raise InferenceError(context=context) from e
            # Ignore non string keys
            if key.__class__.__name__ == "Const" and isinstance(key.value, str):
                cls_locals[key.value].append(value)

        # Build the class from now.
        cls = mcs.__class__(
            name=name.value,
            lineno=caller.lineno,
            col_offset=caller.col_offset,
            parent=caller,
        )
        empty = Pass()
        cls.postinit(
            bases=bases.elts,
            body=[empty],
            decorators=[],
            newstyle=True,
            metaclass=mcs,
            keywords=[],
        )
        cls.locals = cls_locals
        return cls

    def infer_call_result(self, caller, context: InferenceContext | None = None):
        context = bind_context_to_node(context, self.bound)
        if (
            self.bound.__class__.__name__ == "ClassDef"
            and self.bound.name == "type"
            and self.name == "__new__"
            and len(caller.args) == 4
        ):
            # Check if we have a ``type.__new__(mcs, name, bases, attrs)`` call.
            new_cls = self._infer_type_new_call(caller, context)
            if new_cls:
                return iter((new_cls,))

        return super().infer_call_result(caller, context)

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


class Generator(BaseInstance):
    """A special node representing a generator.

    Proxied class is set once for all in raw_building.
    """

    _proxied: nodes.ClassDef

    special_attributes = lazy_descriptor(objectmodel.GeneratorModel)

    def __init__(
        self, parent=None, generator_initial_context: InferenceContext | None = None
    ):
        super().__init__()
        self.parent = parent
        self._call_context = copy_context(generator_initial_context)

    @decorators.cached
    def infer_yield_types(self):
        yield from self.parent.infer_yield_result(self._call_context)

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

    def pytype(self) -> Literal["builtins.generator"]:
        return "builtins.generator"

    def display_type(self) -> str:
        return "Generator"

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

    def __repr__(self) -> str:
        return f"<Generator({self._proxied.name}) l.{self.lineno} at 0x{id(self)}>"

    def __str__(self) -> str:
        return f"Generator({self._proxied.name})"


class AsyncGenerator(Generator):
    """Special node representing an async generator."""

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

    def display_type(self) -> str:
        return "AsyncGenerator"

    def __repr__(self) -> str:
        return f"<AsyncGenerator({self._proxied.name}) l.{self.lineno} at 0x{id(self)}>"

    def __str__(self) -> str:
        return f"AsyncGenerator({self._proxied.name})"


class UnionType(BaseInstance):
    """Special node representing new style typing unions.

    Proxied class is set once for all in raw_building.
    """

    _proxied: nodes.ClassDef

    def __init__(
        self,
        left: UnionType | nodes.ClassDef | nodes.Const,
        right: UnionType | nodes.ClassDef | nodes.Const,
        parent: nodes.NodeNG | None = None,
    ) -> None:
        super().__init__()
        self.parent = parent
        self.left = left
        self.right = right

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

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

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

    def display_type(self) -> str:
        return "UnionType"

    def __repr__(self) -> str:
        return f"<UnionType({self._proxied.name}) l.{self.lineno} at 0x{id(self)}>"

    def __str__(self) -> str:
        return f"UnionType({self._proxied.name})"
b IDATxytVսϓ22 A@IR :hCiZ[v*E:WũZA ^dQeQ @ !jZ'>gsV仿$|?g)&x-EIENT ;@xT.i%-X}SvS5.r/UHz^_$-W"w)Ɗ/@Z &IoX P$K}JzX:;` &, ŋui,e6mX ԵrKb1ԗ)DADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADA݀!I*]R;I2$eZ#ORZSrr6mteffu*((Pu'v{DIߔ4^pIm'77WEEE;vƎ4-$]'RI{\I&G :IHJ DWBB=\WR޽m o$K(V9ABB.}jѢv`^?IOȅ} ڶmG}T#FJ`56$-ھ}FI&v;0(h;Б38CӧOWf!;A i:F_m9s&|q%=#wZprrrla A &P\\СC[A#! {olF} `E2}MK/vV)i{4BffV\|ۭX`b@kɶ@%i$K z5zhmX[IXZ` 'b%$r5M4º/l ԃߖxhʔ)[@=} K6IM}^5k㏷݆z ΗÿO:gdGBmyT/@+Vɶ纽z񕏵l.y޴it뭷zV0[Y^>Wsqs}\/@$(T7f.InݺiR$푔n.~?H))\ZRW'Mo~v Ov6oԃxz! S,&xm/yɞԟ?'uaSѽb,8GלKboi&3t7Y,)JJ c[nzӳdE&KsZLӄ I?@&%ӟ۶mSMMњ0iؐSZ,|J+N ~,0A0!5%Q-YQQa3}$_vVrf9f?S8`zDADADADADADADADADAdqP,تmMmg1V?rSI꒟]u|l RCyEf٢9 jURbztѰ!m5~tGj2DhG*{H9)꒟ר3:(+3\?/;TUݭʴ~S6lڧUJ*i$d(#=Yݺd{,p|3B))q:vN0Y.jkק6;SɶVzHJJЀ-utѹսk>QUU\޲~]fFnK?&ߡ5b=z9)^|u_k-[y%ZNU6 7Mi:]ۦtk[n X(e6Bb."8cۭ|~teuuw|ήI-5"~Uk;ZicEmN/:]M> cQ^uiƞ??Ңpc#TUU3UakNwA`:Y_V-8.KKfRitv޲* 9S6ֿj,ՃNOMߤ]z^fOh|<>@Å5 _/Iu?{SY4hK/2]4%it5q]GGe2%iR| W&f*^]??vq[LgE_3f}Fxu~}qd-ږFxu~I N>\;͗O֊:̗WJ@BhW=y|GgwܷH_NY?)Tdi'?խwhlmQi !SUUsw4kӺe4rfxu-[nHtMFj}H_u~w>)oV}(T'ebʒv3_[+vn@Ȭ\S}ot}w=kHFnxg S 0eޢm~l}uqZfFoZuuEg `zt~? b;t%>WTkķh[2eG8LIWx,^\thrl^Ϊ{=dž<}qV@ ⠨Wy^LF_>0UkDuʫuCs$)Iv:IK;6ֲ4{^6եm+l3>݆uM 9u?>Zc }g~qhKwڭeFMM~pМuqǿz6Tb@8@Y|jx](^]gf}M"tG -w.@vOqh~/HII`S[l.6nØXL9vUcOoB\xoǤ'T&IǍQw_wpv[kmO{w~>#=P1Pɞa-we:iǏlHo׈꒟f9SzH?+shk%Fs:qVhqY`jvO'ρ?PyX3lх]˾uV{ݞ]1,MzYNW~̈́ joYn}ȚF߾׮mS]F z+EDxm/d{F{-W-4wY듏:??_gPf ^3ecg ҵs8R2מz@TANGj)}CNi/R~}c:5{!ZHӋӾ6}T]G]7W6^n 9*,YqOZj:P?Q DFL|?-^.Ɵ7}fFh׶xe2Pscz1&5\cn[=Vn[ĶE鎀uˌd3GII k;lNmشOuuRVfBE]ۣeӶu :X-[(er4~LHi6:Ѻ@ԅrST0trk%$Č0ez" *z"T/X9|8.C5Feg}CQ%͞ˣJvL/?j^h&9xF`њZ(&yF&Iݻfg#W;3^{Wo^4'vV[[K';+mӍִ]AC@W?1^{එyh +^]fm~iԵ]AB@WTk̏t uR?l.OIHiYyԶ]Aˀ7c:q}ힽaf6Z~қm(+sK4{^6}T*UUu]n.:kx{:2 _m=sAߤU@?Z-Vކеz왍Nэ{|5 pڶn b p-@sPg]0G7fy-M{GCF'%{4`=$-Ge\ eU:m+Zt'WjO!OAF@ik&t݆ϥ_ e}=]"Wz_.͜E3leWFih|t-wZۍ-uw=6YN{6|} |*={Ѽn.S.z1zjۻTH]흾 DuDvmvK.`V]yY~sI@t?/ϓ. m&["+P?MzovVЫG3-GRR[(!!\_,^%?v@ҵő m`Y)tem8GMx.))A]Y i`ViW`?^~!S#^+ѽGZj?Vģ0.))A꨷lzL*]OXrY`DBBLOj{-MH'ii-ϰ ok7^ )쭡b]UXSְmռY|5*cֽk0B7镹%ڽP#8nȎq}mJr23_>lE5$iwui+ H~F`IjƵ@q \ @#qG0".0" l`„.0! ,AQHN6qzkKJ#o;`Xv2>,tێJJ7Z/*A .@fفjMzkg @TvZH3Zxu6Ra'%O?/dQ5xYkU]Rֽkق@DaS^RSּ5|BeHNN͘p HvcYcC5:y #`οb;z2.!kr}gUWkyZn=f Pvsn3p~;4p˚=ē~NmI] ¾ 0lH[_L hsh_ғߤc_њec)g7VIZ5yrgk̞W#IjӪv>՞y睝M8[|]\շ8M6%|@PZڨI-m>=k='aiRo-x?>Q.}`Ȏ:Wsmu u > .@,&;+!!˱tﭧDQwRW\vF\~Q7>spYw$%A~;~}6¾ g&if_=j,v+UL1(tWake:@Ș>j$Gq2t7S?vL|]u/ .(0E6Mk6hiۺzښOrifޱxm/Gx> Lal%%~{lBsR4*}{0Z/tNIɚpV^#Lf:u@k#RSu =S^ZyuR/.@n&΃z~B=0eg뺆#,Þ[B/?H uUf7y Wy}Bwegל`Wh(||`l`.;Ws?V@"c:iɍL֯PGv6zctM̠':wuW;d=;EveD}9J@B(0iհ bvP1{\P&G7D޴Iy_$-Qjm~Yrr&]CDv%bh|Yzni_ˆR;kg}nJOIIwyuL}{ЌNj}:+3Y?:WJ/N+Rzd=hb;dj͒suݔ@NKMԄ jqzC5@y°hL m;*5ezᕏ=ep XL n?מ:r`۵tŤZ|1v`V뽧_csج'ߤ%oTuumk%%%h)uy]Nk[n 'b2 l.=͜E%gf$[c;s:V-͞WߤWh-j7]4=F-X]>ZLSi[Y*We;Zan(ӇW|e(HNNP5[= r4tP &0<pc#`vTNV GFqvTi*Tyam$ߏWyE*VJKMTfFw>'$-ؽ.Ho.8c"@DADADADADADADADADA~j*֘,N;Pi3599h=goضLgiJ5փy~}&Zd9p֚ e:|hL``b/d9p? fgg+%%hMgXosج, ΩOl0Zh=xdjLmhݻoO[g_l,8a]٭+ӧ0$I]c]:粹:Teꢢ"5a^Kgh,&= =՟^߶“ߢE ܹS J}I%:8 IDAT~,9/ʃPW'Mo}zNƍ쨓zPbNZ~^z=4mswg;5 Y~SVMRXUյڱRf?s:w ;6H:ºi5-maM&O3;1IKeamZh͛7+##v+c ~u~ca]GnF'ټL~PPPbn voC4R,ӟgg %hq}@#M4IÇ Oy^xMZx ) yOw@HkN˖-Sǎmb]X@n+i͖!++K3gd\$mt$^YfJ\8PRF)77Wא!Cl$i:@@_oG I{$# 8磌ŋ91A (Im7֭>}ߴJq7ޗt^ -[ԩSj*}%]&' -ɓ'ꫯVzzvB#;a 7@GxI{j޼ƌ.LÇWBB7`O"I$/@R @eee@۷>}0,ɒ2$53Xs|cS~rpTYYY} kHc %&k.], @ADADADADADADADADA@lT<%''*Lo^={رc5h %$+CnܸQ3fҥK}vUVVs9G R,_{xˇ3o߾;TTTd}馛]uuuG~iԩ@4bnvmvfϞ /Peeeq}}za I~,誫{UWW뮻}_~YƍSMMMYχ֝waw\ďcxꩧtEƍկ_?۷5@u?1kNׯWzz/wy>}zj3 k(ٺuq_Zvf̘:~ ABQ&r|!%KҥKgԞ={<_X-z !CyFUUz~ ABQIIIjݺW$UXXDٳZ~ ABQƍecW$<(~<RSSvZujjjԧOZQu@4 8m&&&jԩg$ď1h ͟?_{768@g =@`)))5o6m3)ѣƌJ;wҿUTT /KZR{~a=@0o<*狔iFɶ[ˎ;T]]OX@?K.ۈxN pppppppppppppppppPfl߾] ,{ァk۶mڿo5BTӦMӴiӴ|r DB2e|An!Dy'tkΝ[A $***t5' "!駟oaDnΝ:t֭[gDШQ06qD;@ x M6v(PiizmZ4ew"@̴ixf [~-Fٱc&IZ2|n!?$@{[HTɏ#@hȎI# _m(F /6Z3z'\r,r!;w2Z3j=~GY7"I$iI.p_"?pN`y DD?: _  Gÿab7J !Bx@0 Bo cG@`1C[@0G @`0C_u V1 aCX>W ` | `!<S `"<. `#c`?cAC4 ?c p#~@0?:08&_MQ1J h#?/`7;I  q 7a wQ A 1 Hp !#<8/#@1Ul7=S=K.4Z?E_$i@!1!E4?`P_  @Bă10#: "aU,xbFY1 [n|n #'vEH:`xb #vD4Y hi.i&EΖv#O H4IŶ}:Ikh @tZRF#(tXҙzZ ?I3l7q@õ|ۍ1,GpuY Ꮿ@hJv#xxk$ v#9 5 }_$c S#=+"K{F*m7`#%H:NRSp6I?sIՖ{Ap$I$I:QRv2$Z @UJ*$]<FO4IENDB`