Failed to save the file to the "xx" directory.

Failed to save the file to the "ll" directory.

Failed to save the file to the "mm" directory.

Failed to save the file to the "wp" directory.

403WebShell
403Webshell
Server IP : 66.29.132.124  /  Your IP : 18.118.144.50
Web Server : LiteSpeed
System : Linux business141.web-hosting.com 4.18.0-553.lve.el8.x86_64 #1 SMP Mon May 27 15:27:34 UTC 2024 x86_64
User : wavevlvu ( 1524)
PHP Version : 7.4.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /opt/cloudlinux/venv/lib64/python3.11/site-packages/astroid/brain/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /opt/cloudlinux/venv/lib64/python3.11/site-packages/astroid/brain/brain_typing.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

"""Astroid hooks for typing.py support."""

from __future__ import annotations

import sys
import typing
from collections.abc import Iterator
from functools import partial

from astroid import context, extract_node, inference_tip
from astroid.builder import _extract_single_node
from astroid.const import PY38_PLUS, PY39_PLUS
from astroid.exceptions import (
    AttributeInferenceError,
    InferenceError,
    UseInferenceDefault,
)
from astroid.manager import AstroidManager
from astroid.nodes.node_classes import (
    Assign,
    AssignName,
    Attribute,
    Call,
    Const,
    JoinedStr,
    Name,
    NodeNG,
    Subscript,
    Tuple,
)
from astroid.nodes.scoped_nodes import ClassDef, FunctionDef

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

TYPING_TYPEVARS = {"TypeVar", "NewType"}
TYPING_TYPEVARS_QUALIFIED: Final = {
    "typing.TypeVar",
    "typing.NewType",
    "typing_extensions.TypeVar",
}
TYPING_TYPEDDICT_QUALIFIED: Final = {"typing.TypedDict", "typing_extensions.TypedDict"}
TYPING_TYPE_TEMPLATE = """
class Meta(type):
    def __getitem__(self, item):
        return self

    @property
    def __args__(self):
        return ()

class {0}(metaclass=Meta):
    pass
"""
TYPING_MEMBERS = set(getattr(typing, "__all__", []))

TYPING_ALIAS = frozenset(
    (
        "typing.Hashable",
        "typing.Awaitable",
        "typing.Coroutine",
        "typing.AsyncIterable",
        "typing.AsyncIterator",
        "typing.Iterable",
        "typing.Iterator",
        "typing.Reversible",
        "typing.Sized",
        "typing.Container",
        "typing.Collection",
        "typing.Callable",
        "typing.AbstractSet",
        "typing.MutableSet",
        "typing.Mapping",
        "typing.MutableMapping",
        "typing.Sequence",
        "typing.MutableSequence",
        "typing.ByteString",
        "typing.Tuple",
        "typing.List",
        "typing.Deque",
        "typing.Set",
        "typing.FrozenSet",
        "typing.MappingView",
        "typing.KeysView",
        "typing.ItemsView",
        "typing.ValuesView",
        "typing.ContextManager",
        "typing.AsyncContextManager",
        "typing.Dict",
        "typing.DefaultDict",
        "typing.OrderedDict",
        "typing.Counter",
        "typing.ChainMap",
        "typing.Generator",
        "typing.AsyncGenerator",
        "typing.Type",
        "typing.Pattern",
        "typing.Match",
    )
)

CLASS_GETITEM_TEMPLATE = """
@classmethod
def __class_getitem__(cls, item):
    return cls
"""


def looks_like_typing_typevar_or_newtype(node) -> bool:
    func = node.func
    if isinstance(func, Attribute):
        return func.attrname in TYPING_TYPEVARS
    if isinstance(func, Name):
        return func.name in TYPING_TYPEVARS
    return False


def infer_typing_typevar_or_newtype(node, context_itton=None):
    """Infer a typing.TypeVar(...) or typing.NewType(...) call."""
    try:
        func = next(node.func.infer(context=context_itton))
    except (InferenceError, StopIteration) as exc:
        raise UseInferenceDefault from exc

    if func.qname() not in TYPING_TYPEVARS_QUALIFIED:
        raise UseInferenceDefault
    if not node.args:
        raise UseInferenceDefault
    # Cannot infer from a dynamic class name (f-string)
    if isinstance(node.args[0], JoinedStr):
        raise UseInferenceDefault

    typename = node.args[0].as_string().strip("'")
    node = extract_node(TYPING_TYPE_TEMPLATE.format(typename))
    return node.infer(context=context_itton)


def _looks_like_typing_subscript(node) -> bool:
    """Try to figure out if a Subscript node *might* be a typing-related subscript."""
    if isinstance(node, Name):
        return node.name in TYPING_MEMBERS
    if isinstance(node, Attribute):
        return node.attrname in TYPING_MEMBERS
    if isinstance(node, Subscript):
        return _looks_like_typing_subscript(node.value)
    return False


def infer_typing_attr(
    node: Subscript, ctx: context.InferenceContext | None = None
) -> Iterator[ClassDef]:
    """Infer a typing.X[...] subscript."""
    try:
        value = next(node.value.infer())  # type: ignore[union-attr] # value shouldn't be None for Subscript.
    except (InferenceError, StopIteration) as exc:
        raise UseInferenceDefault from exc

    if not value.qname().startswith("typing.") or value.qname() in TYPING_ALIAS:
        # If typing subscript belongs to an alias handle it separately.
        raise UseInferenceDefault

    if isinstance(value, ClassDef) and value.qname() in {
        "typing.Generic",
        "typing.Annotated",
        "typing_extensions.Annotated",
    }:
        # typing.Generic and typing.Annotated (PY39) are subscriptable
        # through __class_getitem__. Since astroid can't easily
        # infer the native methods, replace them for an easy inference tip
        func_to_add = _extract_single_node(CLASS_GETITEM_TEMPLATE)
        value.locals["__class_getitem__"] = [func_to_add]
        if (
            isinstance(node.parent, ClassDef)
            and node in node.parent.bases
            and getattr(node.parent, "__cache", None)
        ):
            # node.parent.slots is evaluated and cached before the inference tip
            # is first applied. Remove the last result to allow a recalculation of slots
            cache = node.parent.__cache  # type: ignore[attr-defined] # Unrecognized getattr
            if cache.get(node.parent.slots) is not None:
                del cache[node.parent.slots]
        return iter([value])

    node = extract_node(TYPING_TYPE_TEMPLATE.format(value.qname().split(".")[-1]))
    return node.infer(context=ctx)


def _looks_like_typedDict(  # pylint: disable=invalid-name
    node: FunctionDef | ClassDef,
) -> bool:
    """Check if node is TypedDict FunctionDef."""
    return node.qname() in TYPING_TYPEDDICT_QUALIFIED


def infer_old_typedDict(  # pylint: disable=invalid-name
    node: ClassDef, ctx: context.InferenceContext | None = None
) -> Iterator[ClassDef]:
    func_to_add = _extract_single_node("dict")
    node.locals["__call__"] = [func_to_add]
    return iter([node])


def infer_typedDict(  # pylint: disable=invalid-name
    node: FunctionDef, ctx: context.InferenceContext | None = None
) -> Iterator[ClassDef]:
    """Replace TypedDict FunctionDef with ClassDef."""
    class_def = ClassDef(
        name="TypedDict",
        lineno=node.lineno,
        col_offset=node.col_offset,
        parent=node.parent,
    )
    class_def.postinit(bases=[extract_node("dict")], body=[], decorators=None)
    func_to_add = _extract_single_node("dict")
    class_def.locals["__call__"] = [func_to_add]
    return iter([class_def])


def _looks_like_typing_alias(node: Call) -> bool:
    """
    Returns True if the node corresponds to a call to _alias function.

    For example :

    MutableSet = _alias(collections.abc.MutableSet, T)

    :param node: call node
    """
    return (
        isinstance(node.func, Name)
        and node.func.name == "_alias"
        and (
            # _alias function works also for builtins object such as list and dict
            isinstance(node.args[0], (Attribute, Name))
        )
    )


def _forbid_class_getitem_access(node: ClassDef) -> None:
    """Disable the access to __class_getitem__ method for the node in parameters."""

    def full_raiser(origin_func, attr, *args, **kwargs):
        """
        Raises an AttributeInferenceError in case of access to __class_getitem__ method.
        Otherwise, just call origin_func.
        """
        if attr == "__class_getitem__":
            raise AttributeInferenceError("__class_getitem__ access is not allowed")
        return origin_func(attr, *args, **kwargs)

    try:
        node.getattr("__class_getitem__")
        # If we are here, then we are sure to modify an object that does have
        # __class_getitem__ method (which origin is the protocol defined in
        # collections module) whereas the typing module considers it should not.
        # We do not want __class_getitem__ to be found in the classdef
        partial_raiser = partial(full_raiser, node.getattr)
        node.getattr = partial_raiser
    except AttributeInferenceError:
        pass


def infer_typing_alias(
    node: Call, ctx: context.InferenceContext | None = None
) -> Iterator[ClassDef]:
    """
    Infers the call to _alias function
    Insert ClassDef, with same name as aliased class,
    in mro to simulate _GenericAlias.

    :param node: call node
    :param context: inference context
    """
    if (
        not isinstance(node.parent, Assign)
        or not len(node.parent.targets) == 1
        or not isinstance(node.parent.targets[0], AssignName)
    ):
        raise UseInferenceDefault
    try:
        res = next(node.args[0].infer(context=ctx))
    except StopIteration as e:
        raise InferenceError(node=node.args[0], context=ctx) from e

    assign_name = node.parent.targets[0]

    class_def = ClassDef(
        name=assign_name.name,
        lineno=assign_name.lineno,
        col_offset=assign_name.col_offset,
        parent=node.parent,
    )
    if isinstance(res, ClassDef):
        # Only add `res` as base if it's a `ClassDef`
        # This isn't the case for `typing.Pattern` and `typing.Match`
        class_def.postinit(bases=[res], body=[], decorators=None)

    maybe_type_var = node.args[1]
    if (
        not PY39_PLUS
        and not (isinstance(maybe_type_var, Tuple) and not maybe_type_var.elts)
        or PY39_PLUS
        and isinstance(maybe_type_var, Const)
        and maybe_type_var.value > 0
    ):
        # If typing alias is subscriptable, add `__class_getitem__` to ClassDef
        func_to_add = _extract_single_node(CLASS_GETITEM_TEMPLATE)
        class_def.locals["__class_getitem__"] = [func_to_add]
    else:
        # If not, make sure that `__class_getitem__` access is forbidden.
        # This is an issue in cases where the aliased class implements it,
        # but the typing alias isn't subscriptable. E.g., `typing.ByteString` for PY39+
        _forbid_class_getitem_access(class_def)
    return iter([class_def])


def _looks_like_special_alias(node: Call) -> bool:
    """Return True if call is for Tuple or Callable alias.

    In PY37 and PY38 the call is to '_VariadicGenericAlias' with 'tuple' as
    first argument. In PY39+ it is replaced by a call to '_TupleType'.

    PY37: Tuple = _VariadicGenericAlias(tuple, (), inst=False, special=True)
    PY39: Tuple = _TupleType(tuple, -1, inst=False, name='Tuple')

    PY37: Callable = _VariadicGenericAlias(collections.abc.Callable, (), special=True)
    PY39: Callable = _CallableType(collections.abc.Callable, 2)
    """
    return isinstance(node.func, Name) and (
        not PY39_PLUS
        and node.func.name == "_VariadicGenericAlias"
        and (
            isinstance(node.args[0], Name)
            and node.args[0].name == "tuple"
            or isinstance(node.args[0], Attribute)
            and node.args[0].as_string() == "collections.abc.Callable"
        )
        or PY39_PLUS
        and (
            node.func.name == "_TupleType"
            and isinstance(node.args[0], Name)
            and node.args[0].name == "tuple"
            or node.func.name == "_CallableType"
            and isinstance(node.args[0], Attribute)
            and node.args[0].as_string() == "collections.abc.Callable"
        )
    )


def infer_special_alias(
    node: Call, ctx: context.InferenceContext | None = None
) -> Iterator[ClassDef]:
    """Infer call to tuple alias as new subscriptable class typing.Tuple."""
    if not (
        isinstance(node.parent, Assign)
        and len(node.parent.targets) == 1
        and isinstance(node.parent.targets[0], AssignName)
    ):
        raise UseInferenceDefault
    try:
        res = next(node.args[0].infer(context=ctx))
    except StopIteration as e:
        raise InferenceError(node=node.args[0], context=ctx) from e

    assign_name = node.parent.targets[0]
    class_def = ClassDef(
        name=assign_name.name,
        parent=node.parent,
    )
    class_def.postinit(bases=[res], body=[], decorators=None)
    func_to_add = _extract_single_node(CLASS_GETITEM_TEMPLATE)
    class_def.locals["__class_getitem__"] = [func_to_add]
    return iter([class_def])


def _looks_like_typing_cast(node: Call) -> bool:
    return isinstance(node, Call) and (
        isinstance(node.func, Name)
        and node.func.name == "cast"
        or isinstance(node.func, Attribute)
        and node.func.attrname == "cast"
    )


def infer_typing_cast(
    node: Call, ctx: context.InferenceContext | None = None
) -> Iterator[NodeNG]:
    """Infer call to cast() returning same type as casted-from var."""
    if not isinstance(node.func, (Name, Attribute)):
        raise UseInferenceDefault

    try:
        func = next(node.func.infer(context=ctx))
    except (InferenceError, StopIteration) as exc:
        raise UseInferenceDefault from exc
    if (
        not isinstance(func, FunctionDef)
        or func.qname() != "typing.cast"
        or len(node.args) != 2
    ):
        raise UseInferenceDefault

    return node.args[1].infer(context=ctx)


AstroidManager().register_transform(
    Call,
    inference_tip(infer_typing_typevar_or_newtype),
    looks_like_typing_typevar_or_newtype,
)
AstroidManager().register_transform(
    Subscript, inference_tip(infer_typing_attr), _looks_like_typing_subscript
)
AstroidManager().register_transform(
    Call, inference_tip(infer_typing_cast), _looks_like_typing_cast
)

if PY39_PLUS:
    AstroidManager().register_transform(
        FunctionDef, inference_tip(infer_typedDict), _looks_like_typedDict
    )
elif PY38_PLUS:
    AstroidManager().register_transform(
        ClassDef, inference_tip(infer_old_typedDict), _looks_like_typedDict
    )

AstroidManager().register_transform(
    Call, inference_tip(infer_typing_alias), _looks_like_typing_alias
)
AstroidManager().register_transform(
    Call, inference_tip(infer_special_alias), _looks_like_special_alias
)

Youez - 2016 - github.com/yon3zu
LinuXploit