diff options
Diffstat (limited to 'venv/lib/python3.11/site-packages/sqlalchemy/ext/mypy/plugin.py')
| -rw-r--r-- | venv/lib/python3.11/site-packages/sqlalchemy/ext/mypy/plugin.py | 303 | 
1 files changed, 0 insertions, 303 deletions
diff --git a/venv/lib/python3.11/site-packages/sqlalchemy/ext/mypy/plugin.py b/venv/lib/python3.11/site-packages/sqlalchemy/ext/mypy/plugin.py deleted file mode 100644 index 00eb4d1..0000000 --- a/venv/lib/python3.11/site-packages/sqlalchemy/ext/mypy/plugin.py +++ /dev/null @@ -1,303 +0,0 @@ -# ext/mypy/plugin.py -# Copyright (C) 2021-2024 the SQLAlchemy authors and contributors -# <see AUTHORS file> -# -# This module is part of SQLAlchemy and is released under -# the MIT License: https://www.opensource.org/licenses/mit-license.php - -""" -Mypy plugin for SQLAlchemy ORM. - -""" -from __future__ import annotations - -from typing import Callable -from typing import List -from typing import Optional -from typing import Tuple -from typing import Type as TypingType -from typing import Union - -from mypy import nodes -from mypy.mro import calculate_mro -from mypy.mro import MroError -from mypy.nodes import Block -from mypy.nodes import ClassDef -from mypy.nodes import GDEF -from mypy.nodes import MypyFile -from mypy.nodes import NameExpr -from mypy.nodes import SymbolTable -from mypy.nodes import SymbolTableNode -from mypy.nodes import TypeInfo -from mypy.plugin import AttributeContext -from mypy.plugin import ClassDefContext -from mypy.plugin import DynamicClassDefContext -from mypy.plugin import Plugin -from mypy.plugin import SemanticAnalyzerPluginInterface -from mypy.types import get_proper_type -from mypy.types import Instance -from mypy.types import Type - -from . import decl_class -from . import names -from . import util - -try: -    __import__("sqlalchemy-stubs") -except ImportError: -    pass -else: -    raise ImportError( -        "The SQLAlchemy mypy plugin in SQLAlchemy " -        "2.0 does not work with sqlalchemy-stubs or " -        "sqlalchemy2-stubs installed, as well as with any other third party " -        "SQLAlchemy stubs.  Please uninstall all SQLAlchemy stubs " -        "packages." -    ) - - -class SQLAlchemyPlugin(Plugin): -    def get_dynamic_class_hook( -        self, fullname: str -    ) -> Optional[Callable[[DynamicClassDefContext], None]]: -        if names.type_id_for_fullname(fullname) is names.DECLARATIVE_BASE: -            return _dynamic_class_hook -        return None - -    def get_customize_class_mro_hook( -        self, fullname: str -    ) -> Optional[Callable[[ClassDefContext], None]]: -        return _fill_in_decorators - -    def get_class_decorator_hook( -        self, fullname: str -    ) -> Optional[Callable[[ClassDefContext], None]]: -        sym = self.lookup_fully_qualified(fullname) - -        if sym is not None and sym.node is not None: -            type_id = names.type_id_for_named_node(sym.node) -            if type_id is names.MAPPED_DECORATOR: -                return _cls_decorator_hook -            elif type_id in ( -                names.AS_DECLARATIVE, -                names.AS_DECLARATIVE_BASE, -            ): -                return _base_cls_decorator_hook -            elif type_id is names.DECLARATIVE_MIXIN: -                return _declarative_mixin_hook - -        return None - -    def get_metaclass_hook( -        self, fullname: str -    ) -> Optional[Callable[[ClassDefContext], None]]: -        if names.type_id_for_fullname(fullname) is names.DECLARATIVE_META: -            # Set any classes that explicitly have metaclass=DeclarativeMeta -            # as declarative so the check in `get_base_class_hook()` works -            return _metaclass_cls_hook - -        return None - -    def get_base_class_hook( -        self, fullname: str -    ) -> Optional[Callable[[ClassDefContext], None]]: -        sym = self.lookup_fully_qualified(fullname) - -        if ( -            sym -            and isinstance(sym.node, TypeInfo) -            and util.has_declarative_base(sym.node) -        ): -            return _base_cls_hook - -        return None - -    def get_attribute_hook( -        self, fullname: str -    ) -> Optional[Callable[[AttributeContext], Type]]: -        if fullname.startswith( -            "sqlalchemy.orm.attributes.QueryableAttribute." -        ): -            return _queryable_getattr_hook - -        return None - -    def get_additional_deps( -        self, file: MypyFile -    ) -> List[Tuple[int, str, int]]: -        return [ -            # -            (10, "sqlalchemy.orm", -1), -            (10, "sqlalchemy.orm.attributes", -1), -            (10, "sqlalchemy.orm.decl_api", -1), -        ] - - -def plugin(version: str) -> TypingType[SQLAlchemyPlugin]: -    return SQLAlchemyPlugin - - -def _dynamic_class_hook(ctx: DynamicClassDefContext) -> None: -    """Generate a declarative Base class when the declarative_base() function -    is encountered.""" - -    _add_globals(ctx) - -    cls = ClassDef(ctx.name, Block([])) -    cls.fullname = ctx.api.qualified_name(ctx.name) - -    info = TypeInfo(SymbolTable(), cls, ctx.api.cur_mod_id) -    cls.info = info -    _set_declarative_metaclass(ctx.api, cls) - -    cls_arg = util.get_callexpr_kwarg(ctx.call, "cls", expr_types=(NameExpr,)) -    if cls_arg is not None and isinstance(cls_arg.node, TypeInfo): -        util.set_is_base(cls_arg.node) -        decl_class.scan_declarative_assignments_and_apply_types( -            cls_arg.node.defn, ctx.api, is_mixin_scan=True -        ) -        info.bases = [Instance(cls_arg.node, [])] -    else: -        obj = ctx.api.named_type(names.NAMED_TYPE_BUILTINS_OBJECT) - -        info.bases = [obj] - -    try: -        calculate_mro(info) -    except MroError: -        util.fail( -            ctx.api, "Not able to calculate MRO for declarative base", ctx.call -        ) -        obj = ctx.api.named_type(names.NAMED_TYPE_BUILTINS_OBJECT) -        info.bases = [obj] -        info.fallback_to_any = True - -    ctx.api.add_symbol_table_node(ctx.name, SymbolTableNode(GDEF, info)) -    util.set_is_base(info) - - -def _fill_in_decorators(ctx: ClassDefContext) -> None: -    for decorator in ctx.cls.decorators: -        # set the ".fullname" attribute of a class decorator -        # that is a MemberExpr.   This causes the logic in -        # semanal.py->apply_class_plugin_hooks to invoke the -        # get_class_decorator_hook for our "registry.map_class()" -        # and "registry.as_declarative_base()" methods. -        # this seems like a bug in mypy that these decorators are otherwise -        # skipped. - -        if ( -            isinstance(decorator, nodes.CallExpr) -            and isinstance(decorator.callee, nodes.MemberExpr) -            and decorator.callee.name == "as_declarative_base" -        ): -            target = decorator.callee -        elif ( -            isinstance(decorator, nodes.MemberExpr) -            and decorator.name == "mapped" -        ): -            target = decorator -        else: -            continue - -        if isinstance(target.expr, NameExpr): -            sym = ctx.api.lookup_qualified( -                target.expr.name, target, suppress_errors=True -            ) -        else: -            continue - -        if sym and sym.node: -            sym_type = get_proper_type(sym.type) -            if isinstance(sym_type, Instance): -                target.fullname = f"{sym_type.type.fullname}.{target.name}" -            else: -                # if the registry is in the same file as where the -                # decorator is used, it might not have semantic -                # symbols applied and we can't get a fully qualified -                # name or an inferred type, so we are actually going to -                # flag an error in this case that they need to annotate -                # it.  The "registry" is declared just -                # once (or few times), so they have to just not use -                # type inference for its assignment in this one case. -                util.fail( -                    ctx.api, -                    "Class decorator called %s(), but we can't " -                    "tell if it's from an ORM registry.  Please " -                    "annotate the registry assignment, e.g. " -                    "my_registry: registry = registry()" % target.name, -                    sym.node, -                ) - - -def _cls_decorator_hook(ctx: ClassDefContext) -> None: -    _add_globals(ctx) -    assert isinstance(ctx.reason, nodes.MemberExpr) -    expr = ctx.reason.expr - -    assert isinstance(expr, nodes.RefExpr) and isinstance(expr.node, nodes.Var) - -    node_type = get_proper_type(expr.node.type) - -    assert ( -        isinstance(node_type, Instance) -        and names.type_id_for_named_node(node_type.type) is names.REGISTRY -    ) - -    decl_class.scan_declarative_assignments_and_apply_types(ctx.cls, ctx.api) - - -def _base_cls_decorator_hook(ctx: ClassDefContext) -> None: -    _add_globals(ctx) - -    cls = ctx.cls - -    _set_declarative_metaclass(ctx.api, cls) - -    util.set_is_base(ctx.cls.info) -    decl_class.scan_declarative_assignments_and_apply_types( -        cls, ctx.api, is_mixin_scan=True -    ) - - -def _declarative_mixin_hook(ctx: ClassDefContext) -> None: -    _add_globals(ctx) -    util.set_is_base(ctx.cls.info) -    decl_class.scan_declarative_assignments_and_apply_types( -        ctx.cls, ctx.api, is_mixin_scan=True -    ) - - -def _metaclass_cls_hook(ctx: ClassDefContext) -> None: -    util.set_is_base(ctx.cls.info) - - -def _base_cls_hook(ctx: ClassDefContext) -> None: -    _add_globals(ctx) -    decl_class.scan_declarative_assignments_and_apply_types(ctx.cls, ctx.api) - - -def _queryable_getattr_hook(ctx: AttributeContext) -> Type: -    # how do I....tell it it has no attribute of a certain name? -    # can't find any Type that seems to match that -    return ctx.default_attr_type - - -def _add_globals(ctx: Union[ClassDefContext, DynamicClassDefContext]) -> None: -    """Add __sa_DeclarativeMeta and __sa_Mapped symbol to the global space -    for all class defs - -    """ - -    util.add_global(ctx, "sqlalchemy.orm", "Mapped", "__sa_Mapped") - - -def _set_declarative_metaclass( -    api: SemanticAnalyzerPluginInterface, target_cls: ClassDef -) -> None: -    info = target_cls.info -    sym = api.lookup_fully_qualified_or_none( -        "sqlalchemy.orm.decl_api.DeclarativeMeta" -    ) -    assert sym is not None and isinstance(sym.node, TypeInfo) -    info.declared_metaclass = info.metaclass_type = Instance(sym.node, [])  | 
