Skip to content

apply @dataclass to non-mapped classes that inherit from MappedAsDataclass ? or some kind of messaging /documentation maybe #9179

Closed
@ImogenBits

Description

@ImogenBits

Describe the typing issue

I'm using a base class for all my tables that inherits both MappedAsDataclass and Declarative base. When I now define an init only field, the child class doesn't have that argument in it's init method and it won't get passed to post_init either.
The code below passes pylance, but crashes when executed because of the additional argument. I'm not sure if this actually is a typing or a runtime bug. The default dataclasses don't inherit init only fields, so it would make sense if sqlalchemy also wouldn't. But at least for my use case it'd be very useful and the expected behaviour if they did.

To Reproduce

from dataclasses import InitVar
from sqlalchemy.orm import Mapped, mapped_column, DeclarativeBase, MappedAsDataclass


class Parent(MappedAsDataclass, DeclarativeBase):
    a: InitVar[int]


class Child(Parent):
    __tablename__ = "child"
    b: Mapped[int] = mapped_column(primary_key=True)


Child(1, 2)

Error

__init__() takes 2 positional arguments but 3 were given

Versions

  • OS: Windows 10
  • Python: 3.11
  • SQLAlchemy: 2.0.0
  • Type checker (eg: mypy 0.991, pyright 1.1.290, etc): pyright e96b3ece

Additional context

No response

Activity

added
requires triageNew issue that requires categorization
typingpep -484 typing issues. independent of "mypy"
on Jan 29, 2023
added
orm - annotated declarativeissues with the new annotations-based declarative ORM approach
bugSomething isn't working
near-term releaseaddition to the milestone which indicates this should be in a near-term release
and removed
requires triageNew issue that requires categorization
typingpep -484 typing issues. independent of "mypy"
on Jan 30, 2023
added this to the 2.0.x milestone on Jan 30, 2023
zzzeek

zzzeek commented on Jan 30, 2023

@zzzeek
Member

well it's runtime because you run the program to see it happen

zzzeek

zzzeek commented on Jan 30, 2023

@zzzeek
Member

this is actually a curious use case that I hadn't considered, which is that the base class here isn't actually a dataclass since it's your base. This implies things like mixins would work too which I also never considered, like this:

class Parent(MappedAsDataclass, DeclarativeBase):
    pass


class Sub(Parent):
    __abstract__ = True
    a: InitVar[int] = field()

class Child(Sub):
    __tablename__ = "child"

    b: Mapped[int] = mapped_column(primary_key=True)

so none of this is set up right now, I'd have to look and see how hard it is to make patterns like these work.

zzzeek

zzzeek commented on Jan 30, 2023

@zzzeek
Member

like this doesn't work either:

from dataclasses import InitVar, dataclass


class Parent:
    a: InitVar[int]


@dataclass
class Child(Parent):
    __tablename__ = "child"

    b: int


Child(1, 2)

because Parent isn't a dataclass. that's essentially what's happening here

zzzeek

zzzeek commented on Jan 30, 2023

@zzzeek
Member

annnnd....it looks like your program works if we just do this:

from dataclasses import InitVar, dataclass
from sqlalchemy.orm import Mapped, mapped_column, DeclarativeBase, MappedAsDataclass


@dataclass
class Parent(MappedAsDataclass, DeclarativeBase):
    a: InitVar[int]


class Child(Parent):
    __tablename__ = "child"
    b: Mapped[int] = mapped_column(primary_key=True)


Child(1, 2)

so....try that as a workaround and see if there are any issues? We would essentially look into making all classes into dataclasses, not just the mapped ones.

NOTE - the change we hope to make in 2.0.1 will remove the need for the above workaround, but also the above workaround will fail at runtime once we make that change. For people reading this please be cautious

changed the title [-]InitVar pseudo fields are not inherited, but type hints think they are[/-] [+]apply @dataclass to non-mapped classes that inherit from MappedAsDataclass ? or some kind of messaging /documentation maybe[/+] on Jan 30, 2023

8 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdataclassesnear-term releaseaddition to the milestone which indicates this should be in a near-term releaseormorm - annotated declarativeissues with the new annotations-based declarative ORM approach

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @zzzeek@sqla-tester@ImogenBits

        Issue actions

          apply @dataclass to non-mapped classes that inherit from MappedAsDataclass ? or some kind of messaging /documentation maybe · Issue #9179 · sqlalchemy/sqlalchemy