Coder Social home page Coder Social logo

Comments (9)

zzzeek avatar zzzeek commented on June 16, 2024 1

the declarative_base() function invokes Python code that is the equivalent operation as doing your "class Base" declaration. It uses the Python type() function to create a new type. But also it could just as well have that same "class Base" declaration inside of it, then return the class; Python typing has no way to represent that returned class as something you can subclass.

from sqlalchemy2-stubs.

zzzeek avatar zzzeek commented on June 16, 2024 1

short answer no, there's nothing different. as long as your Base class is making mappings, it's doing the thing it's supposed to do.

from sqlalchemy2-stubs.

CaselIT avatar CaselIT commented on June 16, 2024 1

the declarative_base function is kinda deprecated and you should do as all the v2 examples in the docs, creating the base manually:

>>> from sqlalchemy.orm import DeclarativeBase

>>> class Base(DeclarativeBase):
...     pass

from sqlalchemy2-stubs.

CaselIT avatar CaselIT commented on June 16, 2024

Hi,

yes, that's currently expect. In v2 base will be generated from a superclass using the classic class Base(superclass):.

That's not really fixable in the 1.4, add a type: ignore

from sqlalchemy2-stubs.

iskyd avatar iskyd commented on June 16, 2024

@CaselIT adding it's not a good solution because you still get all other errors related to the fact that mypy can't create a mapping.

Consider this snippet

from sqlalchemy import String, select
from sqlalchemy.orm import declarative_base
from typing import Optional, Dict, Type
import sqlalchemy
from sqlalchemy.orm.ext import DeclarativeMeta

def get_base() -> Type[DeclarativeMeta]:
    return declarative_base()

Base: Type[DeclarativeMeta] = get_base()

class User(Base): # type: ignore
    __tablename__ = "user"

    id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
    name = sqlalchemy.Column(sqlalchemy.String)

def foo(name: str):
    print(name)

u = User(id=1, name="Pippo")

mypy gives this error: error: Argument 1 to "foo" has incompatible type "Column[String]"; expected "str"

It seems that without Base class using sqlalchemy plugin for mypy isn't really helpfull. Am i missing something?

from sqlalchemy2-stubs.

zzzeek avatar zzzeek commented on June 16, 2024

the mypy plugin will allow you to use the declarative_base() function directly:

Base = declarative_base()

The plugin will convince mypy that "Base" is a class. however, it won't work if you place the call to declarative_base() inside of another function. Python typing very plainly does not support classes being returned from functions.

To use the mypy plugin with a base class that isn't built using declarative_base(), in 1.4 you can use the recipe at https://docs.sqlalchemy.org/en/14/orm/declarative_styles.html#creating-an-explicit-base-non-dynamically-for-use-with-mypy-similar .

as mentioned before, in 2.0 SQLAlchemy provides new patterns that support typing without plugins from start to finish.

from sqlalchemy2-stubs.

iskyd avatar iskyd commented on June 16, 2024

@zzzeek I'm trying with the following snippet that works.

from sqlalchemy import String, select
from sqlalchemy.orm import registry
from typing import Optional, Dict, Type
import sqlalchemy
from sqlalchemy.orm.decl_api import DeclarativeMeta

mapper_registry = registry()


class Base(metaclass=DeclarativeMeta):
    __abstract__ = True

    registry = mapper_registry
    metadata = mapper_registry.metadata

    __init__ = mapper_registry.constructor


class User(Base):
    __tablename__ = "user"

    id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
    name = sqlalchemy.Column(sqlalchemy.String)

def foo(name: str):
    print(name)

u = User(id=1, name="Pippo")

foo(u.name)

But I don't get how it fits with the declarative_base() returned by a function. This way I'm going to simply override Base class.
Does it change the behaviour of the system? Where the declarative_base() returns is going to be used?

from sqlalchemy2-stubs.

unode avatar unode commented on June 16, 2024

Is there a guideline to addressing this issue in 2.0?
We are on 2.0.12 and still encounter the same type checking error.

error: Invalid base class "Base"  [misc]
error: Variable "DBApp.models.Base" is not valid as a type  [valid-type]

with:

Base: DeclarativeMeta = declarative_base()

class Users(Base, DiffMixin):
    __tablename__ = "users"
   (...)

from sqlalchemy2-stubs.

CaselIT avatar CaselIT commented on June 16, 2024

Closing since it's solved in v2

from sqlalchemy2-stubs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.