Example #1
0
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)
Example #2
0
def _dynamic_class_hook(ctx: DynamicClassDefContext) -> None:
    """Generate a declarative Base class when the declarative_base() function
    is encountered."""

    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
    _make_declarative_meta(ctx.api, cls)

    cls_arg = util._get_callexpr_kwarg(ctx.call, "cls")
    if cls_arg is not None:
        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.builtin_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.builtin_type("builtins.object")
        info.bases = [obj]
        info.fallback_to_any = True

    ctx.api.add_symbol_table_node(ctx.name, SymbolTableNode(GDEF, info))
Example #3
0
def calculate_mro(info: TypeInfo, obj_type: Optional[Callable[[], Instance]] = None) -> None:
    """Calculate and set mro (method resolution order).

    Raise MroError if cannot determine mro.
    """
    mro = linearize_hierarchy(info, obj_type)
    assert mro, "Could not produce a MRO at all for %s" % (info,)
    info.mro = mro
    # The property of falling back to Any is inherited.
    info.fallback_to_any = any(baseinfo.fallback_to_any for baseinfo in info.mro)
    TypeState.reset_all_subtype_caches_for(info)
Example #4
0
File: mro.py Project: sthagen/mypy
def calculate_mro(info: TypeInfo, obj_type: Optional[Callable[[], Instance]] = None) -> None:
    """Calculate and set mro (method resolution order).

    Raise MroError if cannot determine mro.
    """
    mro = linearize_hierarchy(info, obj_type)
    assert mro, "Could not produce a MRO at all for %s" % (info,)
    info.mro = mro
    # The property of falling back to Any is inherited.
    info.fallback_to_any = any(baseinfo.fallback_to_any for baseinfo in info.mro)
    TypeState.reset_all_subtype_caches_for(info)
Example #5
0
def decl_info_hook(ctx: DynamicClassDefContext) -> None:
    """Support dynamically defining declarative bases.

    For example:
        from sqlalchemy.ext.declarative import declarative_base

        Base = declarative_base()
    """
    cls_bases = []  # type: List[Instance]

    # Passing base classes as positional arguments is currently not handled.
    if 'cls' in ctx.call.arg_names:
        declarative_base_cls_arg = ctx.call.args[ctx.call.arg_names.index(
            "cls")]
        if isinstance(declarative_base_cls_arg, TupleExpr):
            items = [item for item in declarative_base_cls_arg.items]
        else:
            items = [declarative_base_cls_arg]

        for item in items:
            if isinstance(item, RefExpr) and isinstance(item.node, TypeInfo):
                base = fill_typevars_with_any(item.node)
                # TODO: Support tuple types?
                if isinstance(base, Instance):
                    cls_bases.append(base)

    class_def = ClassDef(ctx.name, Block([]))
    class_def.fullname = ctx.api.qualified_name(ctx.name)

    info = TypeInfo(SymbolTable(), class_def, ctx.api.cur_mod_id)
    class_def.info = info
    obj = ctx.api.builtin_type('builtins.object')
    info.bases = cls_bases or [obj]
    try:
        calculate_mro(info)
    except MroError:
        ctx.api.fail("Not able to calculate MRO for declarative base",
                     ctx.call)
        info.bases = [obj]
        info.fallback_to_any = True

    ctx.api.add_symbol_table_node(ctx.name, SymbolTableNode(GDEF, info))
    set_declarative(info)

    # TODO: check what else is added.
    add_metadata_var(ctx.api, info)
Example #6
0
def _dynamic_class_hook(ctx: DynamicClassDefContext) -> None:
    """Generate a declarative Base class when the declarative_base() function
    is encountered."""

    cls = ClassDef(ctx.name, Block([]))
    cls.fullname = ctx.api.qualified_name(ctx.name)

    declarative_meta_sym: SymbolTableNode = ctx.api.modules[
        "sqlalchemy.orm.decl_api"].names["DeclarativeMeta"]
    declarative_meta_typeinfo: TypeInfo = declarative_meta_sym.node

    declarative_meta_name: NameExpr = NameExpr("DeclarativeMeta")
    declarative_meta_name.kind = GDEF
    declarative_meta_name.fullname = "sqlalchemy.orm.decl_api.DeclarativeMeta"
    declarative_meta_name.node = declarative_meta_typeinfo

    cls.metaclass = declarative_meta_name

    declarative_meta_instance = Instance(declarative_meta_typeinfo, [])

    info = TypeInfo(SymbolTable(), cls, ctx.api.cur_mod_id)
    info.declared_metaclass = info.metaclass_type = declarative_meta_instance
    cls.info = info

    cls_arg = util._get_callexpr_kwarg(ctx.call, "cls")
    if cls_arg is not None:
        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.builtin_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)
        info.bases = [obj]
        info.fallback_to_any = True

    ctx.api.add_symbol_table_node(ctx.name, SymbolTableNode(GDEF, info))
Example #7
0
def create_dynamic_class(
    ctx: DynamicClassDefContext,
    bases: List[Instance],
    *,
    name: Optional[str] = None,
    metaclass: Optional[str] = None,
    symbol_table: Optional[SymbolTable] = None,
) -> TypeInfo:
    if name is None:
        name = ctx.name

    class_def = ClassDef(name, Block([]))
    class_def.fullname = ctx.api.qualified_name(ctx.name)

    info = TypeInfo(SymbolTable(), class_def, ctx.api.cur_mod_id)

    if metaclass is not None:
        metaclass_type_info = lookup_type_info(ctx.api, metaclass)
        if metaclass_type_info is not None:
            info.declared_metaclass = Instance(metaclass_type_info, [])

    class_def.info = info

    obj = ctx.api.builtin_type("builtins.object")
    info.bases = bases or [obj]

    try:
        calculate_mro(info)
    except MroError:
        ctx.api.fail("Not able to calculate MRO for dynamic class", ctx.call)
        info.bases = [obj]
        info.fallback_to_any = True

    if symbol_table is None:
        ctx.api.add_symbol_table_node(name, SymbolTableNode(GDEF, info))
    else:
        symbol_table[name] = SymbolTableNode(GDEF, info)

    add_metadata_var(ctx.api, info)
    add_query_cls_var(ctx.api, info)

    return info
def create_ortho_diff_class(base1: TypeInfo, base2: TypeInfo,
                            api: SemanticAnalyzerPluginInterface,
                            call_ctx: Context) -> Tuple[str, SymbolTableNode]:
    # https://github.com/dropbox/sqlalchemy-stubs/blob/55470ceab8149db983411d5c094c9fe16343c58b/sqlmypy.py#L173-L216
    cls_name = get_ortho_diff_name(base1.defn, base2.defn)
    class_def = ClassDef(cls_name, Block([]))
    class_def.fullname = api.qualified_name(cls_name)

    info = TypeInfo(SymbolTable(), class_def, api.cur_mod_id)
    class_def.info = info
    obj = api.builtin_type('builtins.object')
    info.bases = [cast(Instance, fill_typevars(b)) for b in (base1, base2)]
    try:
        calculate_mro(info)
    except MroError:
        api.fail('Unable to calculate MRO for dynamic class', call_ctx)
        info.bases = [obj]
        info.fallback_to_any = True

    return cls_name, SymbolTableNode(GDEF, info)
Example #9
0
def analyze_formset_factory(ctx: DynamicClassDefContext) -> None:
    class_lookup = (
        "reactivated.stubs.BaseModelFormSet" if ctx.call.callee.name ==
        "modelformset_factory"  # type: ignore[attr-defined]
        else "reactivated.stubs.BaseFormSet")
    form_set_class = ctx.api.lookup_fully_qualified_or_none(class_lookup, )
    assert form_set_class is not None

    form_set_class_instance = Instance(
        form_set_class.node,
        []  # type: ignore[arg-type]
    )

    cls_bases: List[Instance] = [form_set_class_instance]
    class_def = ClassDef(ctx.name, Block([]))
    class_def.fullname = ctx.api.qualified_name(ctx.name)

    if class_def.fullname in already_analyzed:
        # Fixes an issue with max iteration counts.
        # In theory add_symbol_table_node should already guard against this but
        # it doesn't.
        return

    info = TypeInfo(SymbolTable(), class_def, ctx.api.cur_mod_id)
    class_def.info = info
    obj = ctx.api.builtin_type("builtins.object")
    info.bases = cls_bases or [obj]

    try:
        calculate_mro(info)
    except MroError:
        ctx.api.fail("Not able to calculate MRO for declarative base",
                     ctx.call)
        info.bases = [obj]
        info.fallback_to_any = True

    already_analyzed[class_def.fullname] = True
    ctx.api.add_symbol_table_node(ctx.name, SymbolTableNode(GDEF, info))