Connections and Transactions
-============================
+----------------------------
.. _error_3o7r:
QueuePool limit of size <x> overflow <y> reached, connection timed out, timeout <z>
------------------------------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This is possibly the most common runtime error experienced, as it directly
involves the work load of the application surpassing a configured limit, one
.. _error_8s2b:
Can't reconnect until invalid transaction is rolled back. Please rollback() fully before proceeding
------------------------------------------------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This error condition refers to the case where a :class:`_engine.Connection` was
invalidated, either due to a database disconnect detection or due to an
.. _error_dbapi:
DBAPI Errors
-============
+------------
The Python database API, or DBAPI, is a specification for database drivers
which can be located at `Pep-249 <https://www.python.org/dev/peps/pep-0249/>`_.
.. _error_rvf5:
InterfaceError
---------------
+~~~~~~~~~~~~~~
Exception raised for errors that are related to the database interface rather
than the database itself.
.. _error_4xp6:
DatabaseError
---------------
+~~~~~~~~~~~~~
Exception raised for errors that are related to the database itself, and not
the interface or data being passed.
.. _error_9h9h:
DataError
----------
+~~~~~~~~~
Exception raised for errors that are due to problems with the processed data
like division by zero, numeric value out of range, etc.
.. _error_e3q8:
OperationalError
------------------
+~~~~~~~~~~~~~~~~
Exception raised for errors that are related to the database's operation and
not necessarily under the control of the programmer, e.g. an unexpected
.. _error_gkpj:
IntegrityError
---------------
+~~~~~~~~~~~~~~
Exception raised when the relational integrity of the database is affected,
e.g. a foreign key check fails.
.. _error_2j85:
InternalError
--------------
+~~~~~~~~~~~~~
Exception raised when the database encounters an internal error, e.g. the
cursor is not valid anymore, the transaction is out of sync, etc.
.. _error_f405:
ProgrammingError
-----------------
+~~~~~~~~~~~~~~~~
Exception raised for programming errors, e.g. table not found or already
exists, syntax error in the SQL statement, wrong number of parameters
.. _error_tw8g:
NotSupportedError
-------------------
+~~~~~~~~~~~~~~~~~
Exception raised in case a method or database API was used which is not
supported by the database, e.g. requesting a .rollback() on a connection that
the database driver (DBAPI), not SQLAlchemy itself.
SQL Expression Language
-=======================
+-----------------------
.. _error_cprf:
.. _caching_caveats:
Object will not produce a cache key, Performance Implications
---------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SQLAlchemy as of version 1.4 includes a
:ref:`SQL compilation caching facility <sql_caching>` which will allow
.. _error_l7de:
Compiler StrSQLCompiler can't render element of type <element type>
--------------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This error usually occurs when attempting to stringify a SQL expression
construct that includes elements which are not part of the default compilation;
TypeError: <operator> not supported between instances of 'ColumnProperty' and <something>
------------------------------------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This often occurs when attempting to use a :func:`.column_property` or
:func:`.deferred` object in the context of a SQL expression, usually within
.. _error_cd3x:
A value is required for bind parameter <x> (in parameter group <y>)
--------------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This error occurs when a statement makes use of :func:`.bindparam` either
implicitly or explicitly and does not provide a value when the statement
.. _error_89ve:
Expected FROM clause, got Select. To create a FROM clause, use the .subquery() method
---------------------------------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This refers to a change made as of SQLAlchemy 1.4 where a SELECT statement as generated
by a function such as :func:`_expression.select`, but also including things like unions and textual
.. _error_xaj1:
An alias is being generated automatically for raw clauseelement
-----------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. versionadded:: 1.4.26
.. _error_xaj2:
An alias is being generated automatically due to overlapping tables
--------------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. versionadded:: 1.4.26
Object Relational Mapping
-=========================
+-------------------------
.. _error_bhk3:
Parent instance <x> is not bound to a Session; (lazy load/deferred load/refresh/etc.) operation cannot proceed
---------------------------------------------------------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This is likely the most common error message when dealing with the ORM, and it
occurs as a result of the nature of a technique the ORM makes wide use of known
.. _error_7s2a:
This Session's transaction has been rolled back due to a previous exception during flush
-----------------------------------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The flush process of the :class:`.Session`, described at
:ref:`session_flushing`, will roll back the database transaction if an error is
.. _error_bbf0:
For relationship <relationship>, delete-orphan cascade is normally configured only on the "one" side of a one-to-many relationship, and not on the "many" side of a many-to-one or many-to-many relationship.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This error arises when the "delete-orphan" :ref:`cascade <unitofwork_cascades>`
.. _error_bbf1:
Instance <instance> is already associated with an instance of <instance> via its <attribute> attribute, and is only allowed a single parent.
----------------------------------------------------------------------------------------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This error is emitted when the :paramref:`_orm.relationship.single_parent` flag
.. _error_qzyx:
relationship X will copy column Q to column P, which conflicts with relationship(s): 'Y'
-----------------------------------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This warning refers to the case when two or more relationships will write data
to the same columns on flush, but the ORM does not have any means of
.. _error_lkrp:
Object cannot be converted to 'persistent' state, as this identity map is no longer valid.
--------------------------------------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. versionadded:: 1.4.26
.. _error_zlpr:
Type annotation can't be interpreted for Annotated Declarative Table form
---------------------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SQLAlchemy 2.0 introduces a new
:ref:`Annotated Declarative Table <orm_declarative_mapped_column>` declarative
:ref:`migration_20_step_six` - in the :ref:`migration_20_toplevel` document
+.. _error_dcmx:
+
+When transforming <cls> to a dataclass, attribute(s) originate from superclass <cls> which is not a dataclass.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This warning occurs when using the SQLAlchemy ORM Mapped Dataclasses feature
+described at :ref:`orm_declarative_native_dataclasses` in conjunction with
+any mixin class or abstract base that is not itself declared as a
+dataclass, such as in the example below::
+
+ from __future__ import annotations
+
+ import inspect
+ from typing import Optional
+ from uuid import uuid4
+
+ from sqlalchemy import String
+ from sqlalchemy.orm import DeclarativeBase
+ from sqlalchemy.orm import Mapped
+ from sqlalchemy.orm import mapped_column
+ from sqlalchemy.orm import MappedAsDataclass
+
+
+ class Mixin:
+
+ create_user: Mapped[int] = mapped_column()
+ update_user: Mapped[Optional[int]] = mapped_column(default=None, init=False)
+
+
+ class Base(DeclarativeBase, MappedAsDataclass):
+ pass
+
+
+ class User(Base, Mixin):
+ __tablename__ = "sys_user"
+
+ uid: Mapped[str] = mapped_column(
+ String(50), init=False, default_factory=uuid4, primary_key=True
+ )
+ username: Mapped[str] = mapped_column()
+ email: Mapped[str] = mapped_column()
+
+Above, since ``Mixin`` does not itself extend from :class:`_orm.MappedAsDataclass`,
+the following warning is generated:
+
+.. sourcecode:: none
+
+ SADeprecationWarning: When transforming <class '__main__.User'> to a
+ dataclass, attribute(s) "create_user", "update_user" originates from
+ superclass <class
+ '__main__.Mixin'>, which is not a dataclass. This usage is deprecated and
+ will raise an error in SQLAlchemy 2.1. When declaring SQLAlchemy
+ Declarative Dataclasses, ensure that all mixin classes and other
+ superclasses which include attributes are also a subclass of
+ MappedAsDataclass.
+
+The fix is to add :class:`_orm.MappedAsDataclass` to the signature of
+``Mixin`` as well::
+
+ class Mixin(MappedAsDataclass):
+
+ create_user: Mapped[int] = mapped_column()
+ update_user: Mapped[Optional[int]] = mapped_column(default=None, init=False)
+
+Python's :pep:`681` specification does not accommodate for attributes declared
+on superclasses of dataclasses that are not themselves dataclasses; per the
+behavior of Python dataclasses, such fields are ignored, as in the following
+example::
+
+ from dataclasses import dataclass
+ from dataclasses import field
+ import inspect
+ from typing import Optional
+ from uuid import uuid4
+
+
+ class Mixin:
+ create_user: int
+ update_user: Optional[int] = field(default=None)
+
+
+ @dataclass
+ class User(Mixin):
+ uid: str = field(init=False, default_factory=lambda: str(uuid4()))
+ username: str
+ password: str
+ email: str
+
+Above, the ``User`` class will not include ``create_user`` in its constructor
+nor will it attempt to interpret ``update_user`` as a dataclass attribute.
+This is because ``Mixin`` is not a dataclass.
+
+SQLAlchemy's dataclasses feature within the 2.0 series does not honor this
+behavior correctly; instead, attributes on non-dataclass mixins and
+superclasses are treated as part of the final dataclass configuration. However
+type checkers such as Pyright and Mypy will not consider these fields as
+part of the dataclass constructor as they are to be ignored per :pep:`681`.
+Since their presence is ambiguous otherwise, SQLAlchemy 2.1 will require that
+mixin classes which have SQLAlchemy mapped attributes within a dataclass
+hierarchy have to themselves be dataclasses.
+
+
+
+
AsyncIO Exceptions
-==================
+------------------
.. _error_xd1r:
AwaitRequired
--------------
+~~~~~~~~~~~~~
The SQLAlchemy async mode requires an async driver to be used to connect to the db.
This error is usually raised when trying to use the async version of SQLAlchemy
.. _error_xd2s:
MissingGreenlet
----------------
+~~~~~~~~~~~~~~~
A call to the async :term:`DBAPI` was initiated outside the greenlet spawn
context usually setup by the SQLAlchemy AsyncIO proxy classes. Usually this
.. _error_xd3s:
No Inspection Available
------------------------
+~~~~~~~~~~~~~~~~~~~~~~~
Using the :func:`_sa.inspect` function directly on an
:class:`_asyncio.AsyncConnection` or :class:`_asyncio.AsyncEngine` object is
Core Exception Classes
-======================
+----------------------
See :ref:`core_exceptions_toplevel` for Core exception classes.
ORM Exception Classes
-======================
+---------------------
See :ref:`orm_exceptions_toplevel` for ORM exception classes.
Legacy Exceptions
-=================
+-----------------
Exceptions in this section are not generated by current SQLAlchemy
versions, however are provided here to suit exception message hyperlinks.
.. _error_b8d9:
The <some function> in SQLAlchemy 2.0 will no longer <something>
---------------------------------------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SQLAlchemy 2.0 represents a major shift for a wide variety of key
SQLAlchemy usage patterns in both the Core and ORM components. The goal
.. _error_s9r1:
Object is being merged into a Session along the backref cascade
----------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This message refers to the "backref cascade" behavior of SQLAlchemy,
removed in version 2.0. This refers to the action of
.. _error_c9ae:
select() construct created in "legacy" mode; keyword arguments, etc.
---------------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The :func:`_expression.select` construct has been updated as of SQLAlchemy
1.4 to support the newer calling style that is standard in
.. _error_c9bf:
A bind was located via legacy bound metadata, but since future=True is set on this Session, this bind is ignored.
--------------------------------------------------------------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The concept of "bound metadata" is present up until SQLAlchemy 1.4; as
of SQLAlchemy 2.0 it's been removed.
.. _error_2afi:
This Compiled object is not bound to any Engine or Connection
--------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This error refers to the concept of "bound metadata", which is a legacy
SQLAlchemy pattern present only in 1.x versions. The issue occurs when one invokes
.. _error_8s2a:
This connection is on an inactive transaction. Please rollback() fully before proceeding
-------------------------------------------------------------------------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This error condition was added to SQLAlchemy as of version 1.4, and does not
apply to SQLAlchemy 2.0. The error
is_dataclass: bool
attr_value: Any
originating_module: str
+ originating_class: Type[Any]
class _ClassScanMapperConfig(_MapperConfig):
"'@registry.mapped_as_dataclass'"
)
+ warn_for_non_dc_attrs = collections.defaultdict(list)
+
+ def _allow_dataclass_field(
+ key: str, originating_class: Type[Any]
+ ) -> bool:
+ if (
+ originating_class is not self.cls
+ and "__dataclass_fields__" not in originating_class.__dict__
+ ):
+ warn_for_non_dc_attrs[originating_class].append(key)
+
+ return True
+
manager = instrumentation.manager_of_class(self.cls)
assert manager is not None
is_dc,
attr_value,
originating_module,
+ originating_class,
) in self.collected_annotations.items()
- if key not in self.collected_attributes
- # issue #9226; check for attributes that we've collected
- # which are already instrumented, which we would assume
- # mean we are in an ORM inheritance mapping and this attribute
- # is already mapped on the superclass. Under no circumstance
- # should any QueryableAttribute be sent to the dataclass()
- # function; anything that's mapped should be Field and
- # that's it
- or not isinstance(
- self.collected_attributes[key], QueryableAttribute
+ if _allow_dataclass_field(key, originating_class)
+ and (
+ key not in self.collected_attributes
+ # issue #9226; check for attributes that we've collected
+ # which are already instrumented, which we would assume
+ # mean we are in an ORM inheritance mapping and this
+ # attribute is already mapped on the superclass. Under
+ # no circumstance should any QueryableAttribute be sent to
+ # the dataclass() function; anything that's mapped should
+ # be Field and that's it
+ or not isinstance(
+ self.collected_attributes[key], QueryableAttribute
+ )
)
)
]
+
+ if warn_for_non_dc_attrs:
+ for (
+ originating_class,
+ non_dc_attrs,
+ ) in warn_for_non_dc_attrs.items():
+ util.warn_deprecated(
+ f"When transforming {self.cls} to a dataclass, "
+ f"attribute(s) "
+ f"{', '.join(repr(key) for key in non_dc_attrs)} "
+ f"originates from superclass "
+ f"{originating_class}, which is not a dataclass. This "
+ f"usage is deprecated and will raise an error in "
+ f"SQLAlchemy 2.1. When declaring SQLAlchemy Declarative "
+ f"Dataclasses, ensure that all mixin classes and other "
+ f"superclasses which include attributes are also a "
+ f"subclass of MappedAsDataclass.",
+ "2.0",
+ code="dcmx",
+ )
+
annotations = {}
defaults = {}
for item in field_list:
is_dataclass,
attr_value,
originating_class.__module__,
+ originating_class,
)
return ca
is_dataclass,
attr_value,
originating_module,
+ originating_class,
) = self.collected_annotations.get(
- k, (None, None, None, False, None, None)
+ k, (None, None, None, False, None, None, None)
)
# issue #8692 - don't do any annotation interpretation if
+import contextlib
import dataclasses
from dataclasses import InitVar
+import functools
import inspect as pyinspect
from itertools import product
from typing import Any
from sqlalchemy.util import compat
+def _dataclass_mixin_warning(clsname, attrnames):
+ return testing.expect_deprecated(
+ rf"When transforming .* to a dataclass, attribute\(s\) "
+ rf"{attrnames} originates from superclass .*{clsname}"
+ )
+
+
class DCTransformsTest(AssertsCompiledSQL, fixtures.TestBase):
@testing.fixture(params=["(MAD, DB)", "(DB, MAD)"])
def dc_decl_base(self, request, metadata):
a1 = Address("email@address")
eq_(a1.email_address, "email@address")
+ def test_warn_on_non_dc_mixin(self):
+ class _BaseMixin:
+
+ create_user: Mapped[int] = mapped_column()
+ update_user: Mapped[Optional[int]] = mapped_column(
+ default=None, init=False
+ )
+
+ class Base(DeclarativeBase, MappedAsDataclass, _BaseMixin):
+ pass
+
+ class SubMixin:
+ foo: Mapped[str]
+ bar: Mapped[str] = mapped_column()
+
+ with _dataclass_mixin_warning(
+ "_BaseMixin", "'create_user', 'update_user'"
+ ), _dataclass_mixin_warning("SubMixin", "'foo', 'bar'"):
+
+ class User(SubMixin, Base):
+ __tablename__ = "sys_user"
+
+ id: Mapped[int] = mapped_column(primary_key=True, init=False)
+ username: Mapped[str] = mapped_column(String)
+ password: Mapped[str] = mapped_column(String)
+
def test_basic_constructor_repr_cls_decorator(
self, registry: _RegistryType
):
def test_mapped_column_overrides(self, dc_decl_base):
"""test #8688"""
- class TriggeringMixin:
+ class TriggeringMixin(MappedAsDataclass):
mixin_value: Mapped[int] = mapped_column(BigInteger)
- class NonTriggeringMixin:
+ class NonTriggeringMixin(MappedAsDataclass):
mixin_value: Mapped[int]
class Foo(dc_decl_base, TriggeringMixin):
)
expected_annotations[Mixin] = {}
+
+ non_dc_mixin = contextlib.nullcontext
+
else:
class Mixin:
insert_default=cls.__name__,
)
- if dataclass_scope.on_base_class:
+ non_dc_mixin = functools.partial(
+ _dataclass_mixin_warning, "Mixin", "'polymorphic_type'"
+ )
- class Book(Mixin, MappedAsDataclass, Base, **klass_kw):
- id: Mapped[int] = mapped_column(
- Integer,
- primary_key=True,
- init=False,
- )
+ if dataclass_scope.on_base_class:
- else:
+ with non_dc_mixin():
- class Book(Mixin, Base):
- if not dataclass_scope.on_sub_class:
- id: Mapped[int] = mapped_column( # noqa: A001
- Integer, primary_key=True, init=False
- )
- else:
- id: Mapped[int] = mapped_column( # noqa: A001
+ class Book(Mixin, MappedAsDataclass, Base, **klass_kw):
+ id: Mapped[int] = mapped_column(
Integer,
primary_key=True,
+ init=False,
)
+ else:
+ if dataclass_scope.on_base:
+ local_non_dc_mixin = non_dc_mixin
+ else:
+ local_non_dc_mixin = contextlib.nullcontext
+
+ with local_non_dc_mixin():
+
+ class Book(Mixin, Base):
+ if not dataclass_scope.on_sub_class:
+ id: Mapped[int] = mapped_column( # noqa: A001
+ Integer, primary_key=True, init=False
+ )
+ else:
+ id: Mapped[int] = mapped_column( # noqa: A001
+ Integer,
+ primary_key=True,
+ )
+
if MappedAsDataclass in Book.__mro__:
expected_annotations[Book] = {"id": int, "polymorphic_type": str}
if dataclass_scope.on_sub_class:
- class Novel(MappedAsDataclass, Book, **klass_kw):
- id: Mapped[int] = mapped_column( # noqa: A001
- ForeignKey("book.id"),
- primary_key=True,
- init=False,
- )
- description: Mapped[Optional[str]]
+ with non_dc_mixin():
+
+ class Novel(MappedAsDataclass, Book, **klass_kw):
+ id: Mapped[int] = mapped_column( # noqa: A001
+ ForeignKey("book.id"),
+ primary_key=True,
+ init=False,
+ )
+ description: Mapped[Optional[str]]
else:
- class Novel(Book):
- id: Mapped[int] = mapped_column(
- ForeignKey("book.id"),
- primary_key=True,
- init=False,
- )
- description: Mapped[Optional[str]]
+ with non_dc_mixin():
+
+ class Novel(Book):
+ id: Mapped[int] = mapped_column(
+ ForeignKey("book.id"),
+ primary_key=True,
+ init=False,
+ )
+ description: Mapped[Optional[str]]
expected_annotations[Novel] = {"id": int, "description": Optional[str]}
class BaseEntity(DeclarativeBase):
pass
- class IdMixin:
+ class IdMixin(MappedAsDataclass):
id: Mapped[int] = mapped_column(
primary_key=True, init=False
)
elif mad_setup == "subclass":
- class BaseEntity(DeclarativeBase):
+ class BaseEntity(MappedAsDataclass, DeclarativeBase):
id: Mapped[int] = mapped_column(
primary_key=True, init=False
)
if mad_setup == "subclass":
- class A(MappedAsDataclass, BaseEntity, **dataclass_kw):
+ class A(BaseEntity, **dataclass_kw):
__mapper_args__ = {
"polymorphic_on": "type",
"polymorphic_identity": "a",