From: Mike Bayer Date: Fri, 21 Oct 2022 16:44:18 +0000 (-0400) Subject: add step 6 to migration docs X-Git-Tag: rel_1_4_43~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d1b2e9353ad9e2c0db362262964403a5601fa1e2;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git add step 6 to migration docs Users will need to attend to explicitly annotated models that don't use Mapped[], for a clean transition from 1.4 to 2.0. Fixes: #8692 Change-Id: I212018574e752d1109c712ea29ea277be5a13382 --- diff --git a/doc/build/changelog/migration_20.rst b/doc/build/changelog/migration_20.rst index 4e738e948e..b33a5b0e67 100644 --- a/doc/build/changelog/migration_20.rst +++ b/doc/build/changelog/migration_20.rst @@ -378,6 +378,86 @@ and all ``exc.RemovedIn20Warning`` occurrences set to raise an error, The sections that follow will detail the specific changes to make for all major API modifications. +.. _migration_20_step_six: + +Migration to 2.0 Step Six - Add ``__allow_unmapped__`` to explicitly typed ORM models +-------------------------------------------------------------------------------------- + +SQLAlchemy 2.0 has new support for runtime interpretation of :pep:`484` typing annotations +on ORM models. A requirement of these annotations is that they must make use +of the :class:`_orm.Mapped` generic container. Annotations which don't use +:class:`_orm.Mapped` which link to constructs such as :func:`_orm.relationship` +will raise errors, as they suggest mis-configurations. + +SQLAlchemy applications that use the :ref:`Mypy plugin ` with +explicit annotations that don't use :class:`_orm.Mapped` in their annotations +are subject to these errors, as would occur in the example below:: + + Base = declarative_base() + + + class Foo(Base): + __tablename__ = "foo" + + id: int = Column(Integer, primary_key=True) + + # will raise + bars: list["Bar"] = relationship("Bar", back_populates="foo") + + + class Bar(Base): + __tablename__ = "bar" + + id: int = Column(Integer, primary_key=True) + foo_id = Column(ForeignKey("foo.id")) + + # will raise + foo: Foo = relationship(Foo, back_populates="bars", cascade="all") + +Above, the ``Foo.bars`` and ``Bar.foo`` :func:`_orm.relationship` declarations +will raise an error at class construction time because they don't use +:class:`_orm.Mapped` (by contrast, the annotations that use +:class:`_schema.Column` are ignored by 2.0, as these are able to be +recognized as a legacy configuration style). To allow all annotations that +don't use :class:`_orm.Mapped` to pass without error, +the ``__allow_unmapped__`` attribute may be used on the class or any +subclasses, which will cause the annotations in these cases to be +ignored completely by the new Declarative system. + +The example below illustrates the application of ``__allow_unmapped__`` +to the Declarative ``Base`` class, where it will take effect for all classes +that descend from ``Base``:: + + # qualify the base with __allow_unmapped__. Can also be + # applied to classes directly if preferred + class Base: + __allow_unmapped__ = True + + + Base = declarative_base(cls=Base) + + # existing mapping proceeds, Declarative will ignore any annotations + # which don't include ``Mapped[]`` + class Foo(Base): + __tablename__ = "foo" + + id: int = Column(Integer, primary_key=True) + + bars: list["Bar"] = relationship("Bar", back_populates="foo") + + + class Bar(Base): + __tablename__ = "bar" + + id: int = Column(Integer, primary_key=True) + foo_id = Column(ForeignKey("foo.id")) + + foo: Foo = relationship(Foo, back_populates="bars", cascade="all") + +.. versionchanged:: 2.0.0beta3 - improved the ``__allow_unmapped__`` + attribute support to allow for 1.4-style explicit annotated relationships + that don't use :class:`_orm.Mapped` to remain usable. + 2.0 Migration - Core Connection / Transaction =============================================