Skip to content

Commit e545298

Browse files
committed
establish mypy / typing approach for v2.0
large patch to get ORM / typing efforts started. this is to support adding new test cases to mypy, support dropping sqlalchemy2-stubs entirely from the test suite, validate major ORM typing reorganization to eliminate the need for the mypy plugin. * New declarative approach which uses annotation introspection, fixes: #7535 * Mapped[] is now at the base of all ORM constructs that find themselves in classes, to support direct typing without plugins * Mypy plugin updated for new typing structures * Mypy test suite broken out into "plugin" tests vs. "plain" tests, and enhanced to better support test structures where we assert that various objects are introspected by the type checker as we expect. as we go forward with typing, we will add new use cases to "plain" where we can assert that types are introspected as we expect. * For typing support, users will be much more exposed to the class names of things. Add these all to "sqlalchemy" import space. * Column(ForeignKey()) no longer needs to be `@declared_attr` if the FK refers to a remote table * composite() attributes mapped to a dataclass no longer need to implement a `__composite_values__()` method * with_variant() accepts multiple dialect names Change-Id: I22797c0be73a8fbbd2d6f5e0c0b7258b17fe145d Fixes: #7535 Fixes: #7551 References: #6810
1 parent f1da162 commit e545298

File tree

149 files changed

+5657
-2158
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

149 files changed

+5657
-2158
lines changed

doc/build/changelog/migration_20.rst

+4-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ and pylance. Given a program as below::
182182
from sqlalchemy.dialects.mysql import VARCHAR
183183

184184

185-
type_ = String(255).with_variant(VARCHAR(255, charset='utf8mb4'), "mysql")
185+
type_ = String(255).with_variant(VARCHAR(255, charset='utf8mb4'), "mysql", "mariadb")
186186

187187
if typing.TYPE_CHECKING:
188188
reveal_type(type_)
@@ -191,6 +191,9 @@ A type checker like pyright will now report the type as::
191191

192192
info: Type of "type_" is "String"
193193

194+
In addition, as illustrated above, multiple dialect names may be passed for
195+
single type, in particular this is helpful for the pair of ``"mysql"`` and
196+
``"mariadb"`` dialects which are considered separately as of SQLAlchemy 1.4.
194197

195198
:ticket:`6980`
196199

doc/build/changelog/unreleased_20/6980.rst

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
behaviors, maintaining the original type allows for clearer type checking
1111
and debugging.
1212

13+
:meth:`_sqltypes.TypeEngine.with_variant` also accepts multiple dialect
14+
names per call as well, in particular this is helpful for related
15+
backend names such as ``"mysql", "mariadb"``.
16+
1317
.. seealso::
1418

1519
:ref:`change_6980`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.. change::
2+
:tags: feature, orm
3+
4+
The :func:`_orm.composite` mapping construct now supports automatic
5+
resolution of values when used with a Python ``dataclass``; the
6+
``__composite_values__()`` method no longer needs to be implemented as this
7+
method is derived from inspection of the dataclass.
8+
9+
See the new documentation at :ref:`mapper_composite` for examples.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.. change::
2+
:tags: feature, orm
3+
4+
Declarative mixins which use :class:`_schema.Column` objects that contain
5+
:class:`_schema.ForeignKey` references no longer need to use
6+
:func:`_orm.declared_attr` to achieve this mapping; the
7+
:class:`_schema.ForeignKey` object is copied along with the
8+
:class:`_schema.Column` itself when the column is applied to the declared
9+
mapping.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
.. change::
2+
:tags: change, orm
3+
4+
To better accommodate explicit typing, the names of some ORM constructs
5+
that are typically constructed internally, but nonetheless are sometimes
6+
visible in messaging as well as typing, have been changed to more succinct
7+
names which also match the name of their constructing function (with
8+
different casing), in all cases maintaining aliases to the old names for
9+
the forseeable future:
10+
11+
* :class:`_orm.RelationshipProperty` becomes an alias for the primary name
12+
:class:`_orm.Relationship`, which is constructed as always from the
13+
:func:`_orm.relationship` function
14+
* :class:`_orm.SynonymProperty` becomes an alias for the primary name
15+
:class:`_orm.Synonym`, constructed as always from the
16+
:func:`_orm.synonym` function
17+
* :class:`_orm.CompositeProperty` becomes an alias for the primary name
18+
:class:`_orm.Composite`, constructed as always from the
19+
:func:`_orm.composite` function

doc/build/core/selectable.rst

+5-13
Original file line numberDiff line numberDiff line change
@@ -156,21 +156,13 @@ Label Style Constants
156156
Constants used with the :meth:`_sql.GenerativeSelect.set_label_style`
157157
method.
158158

159-
.. autodata:: LABEL_STYLE_DISAMBIGUATE_ONLY
159+
.. autoclass:: SelectLabelStyle
160+
:members:
160161

161-
.. autodata:: LABEL_STYLE_NONE
162162

163-
.. autodata:: LABEL_STYLE_TABLENAME_PLUS_COL
163+
.. seealso::
164164

165-
.. data:: LABEL_STYLE_DEFAULT
165+
:meth:`_sql.Select.set_label_style`
166166

167-
The default label style, refers to :data:`_sql.LABEL_STYLE_DISAMBIGUATE_ONLY`.
168-
169-
.. versionadded:: 1.4
170-
171-
.. seealso::
172-
173-
:meth:`_sql.Select.set_label_style`
174-
175-
:meth:`_sql.Select.get_label_style`
167+
:meth:`_sql.Select.get_label_style`
176168

doc/build/orm/composites.rst

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
Composite Column Types
66
======================
77

8+
.. note::
9+
10+
This documentation is not yet updated to illustrate the new
11+
typing-annotation syntax or direct support for dataclasses.
12+
813
Sets of columns can be associated with a single user-defined datatype. The ORM
914
provides a single attribute which represents the group of columns using the
1015
class you provide.

doc/build/orm/declarative_mixins.rst

+41-29
Original file line numberDiff line numberDiff line change
@@ -125,47 +125,61 @@ for each separate destination class. To accomplish this, the declarative
125125
extension creates a **copy** of each :class:`_schema.Column` object encountered on
126126
a class that is detected as a mixin.
127127

128-
This copy mechanism is limited to simple columns that have no foreign
129-
keys, as a :class:`_schema.ForeignKey` itself contains references to columns
130-
which can't be properly recreated at this level. For columns that
131-
have foreign keys, as well as for the variety of mapper-level constructs
132-
that require destination-explicit context, the
133-
:class:`_orm.declared_attr` decorator is provided so that
134-
patterns common to many classes can be defined as callables::
128+
This copy mechanism is limited to :class:`_schema.Column` and
129+
:class:`_orm.MappedColumn` constructs. For :class:`_schema.Column` and
130+
:class:`_orm.MappedColumn` constructs that contain references to
131+
:class:`_schema.ForeignKey` constructs, the copy mechanism is limited to
132+
foreign key references to remote tables only.
133+
134+
.. versionchanged:: 2.0 The declarative API can now accommodate
135+
:class:`_schema.Column` objects which refer to :class:`_schema.ForeignKey`
136+
constraints to remote tables without the need to use the
137+
:class:`_orm.declared_attr` function decorator.
138+
139+
For the variety of mapper-level constructs that require destination-explicit
140+
context, including self-referential foreign keys and constructs like
141+
:func:`_orm.deferred`, :func:`_orm.relationship`, etc, the
142+
:class:`_orm.declared_attr` decorator is provided so that patterns common to
143+
many classes can be defined as callables::
135144

136145
from sqlalchemy.orm import declared_attr
137146

138147
@declarative_mixin
139-
class ReferenceAddressMixin:
148+
class HasRelatedDataMixin:
140149
@declared_attr
141-
def address_id(cls):
142-
return Column(Integer, ForeignKey('address.id'))
150+
def related_data(cls):
151+
return deferred(Column(Text())
143152

144-
class User(ReferenceAddressMixin, Base):
153+
class User(HasRelatedDataMixin, Base):
145154
__tablename__ = 'user'
146155
id = Column(Integer, primary_key=True)
147156

148-
Where above, the ``address_id`` class-level callable is executed at the
157+
Where above, the ``related_data`` class-level callable is executed at the
149158
point at which the ``User`` class is constructed, and the declarative
150-
extension can use the resulting :class:`_schema.Column` object as returned by
159+
extension can use the resulting :func`_orm.deferred` object as returned by
151160
the method without the need to copy it.
152161

153-
Columns generated by :class:`_orm.declared_attr` can also be
154-
referenced by ``__mapper_args__`` to a limited degree, currently
155-
by ``polymorphic_on`` and ``version_id_col``; the declarative extension
156-
will resolve them at class construction time::
162+
For a self-referential foreign key on a mixin, the referenced
163+
:class:`_schema.Column` object may be referenced in terms of the class directly
164+
within the :class:`_orm.declared_attr`::
157165

158-
@declarative_mixin
159-
class MyMixin:
160-
@declared_attr
161-
def type_(cls):
162-
return Column(String(50))
166+
class SelfReferentialMixin:
167+
id = Column(Integer, primary_key=True)
163168

164-
__mapper_args__= {'polymorphic_on':type_}
169+
@declared_attr
170+
def parent_id(cls):
171+
return Column(Integer, ForeignKey(cls.id))
172+
173+
class A(SelfReferentialMixin, Base):
174+
__tablename__ = 'a'
165175

166-
class MyModel(MyMixin, Base):
167-
__tablename__='test'
168-
id = Column(Integer, primary_key=True)
176+
177+
class B(SelfReferentialMixin, Base):
178+
__tablename__ = 'b'
179+
180+
Above, both classes ``A`` and ``B`` will contain columns ``id`` and
181+
``parent_id``, where ``parent_id`` refers to the ``id`` column local to the
182+
corresponding table ('a' or 'b').
169183

170184
.. _orm_declarative_mixins_relationships:
171185

@@ -182,9 +196,7 @@ reference a common target class via many-to-one::
182196

183197
@declarative_mixin
184198
class RefTargetMixin:
185-
@declared_attr
186-
def target_id(cls):
187-
return Column('target_id', ForeignKey('target.id'))
199+
target_id = Column('target_id', ForeignKey('target.id'))
188200

189201
@declared_attr
190202
def target(cls):

doc/build/orm/internals.rst

+10-3
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,10 @@ sections, are listed here.
3232

3333
:ref:`maptojoin` - usage example
3434

35-
.. autoclass:: CompositeProperty
35+
.. autoclass:: Composite
3636
:members:
3737

38+
.. autodata:: CompositeProperty
3839

3940
.. autoclass:: AttributeEvent
4041
:members:
@@ -62,6 +63,8 @@ sections, are listed here.
6263

6364
.. autoclass:: Mapped
6465

66+
.. autoclass:: MappedColumn
67+
6568
.. autoclass:: MapperProperty
6669
:members:
6770

@@ -98,14 +101,18 @@ sections, are listed here.
98101
:members:
99102
:inherited-members:
100103

101-
.. autoclass:: RelationshipProperty
104+
.. autoclass:: Relationship
102105
:members:
103106
:inherited-members:
104107

105-
.. autoclass:: SynonymProperty
108+
.. autodata:: RelationshipProperty
109+
110+
.. autoclass:: Synonym
106111
:members:
107112
:inherited-members:
108113

114+
.. autodata:: SynonymProperty
115+
109116
.. autoclass:: QueryContext
110117
:members:
111118

doc/build/orm/loading_relationships.rst

-2
Original file line numberDiff line numberDiff line change
@@ -1261,8 +1261,6 @@ Relationship Loader API
12611261

12621262
.. autofunction:: defaultload
12631263

1264-
.. autofunction:: eagerload
1265-
12661264
.. autofunction:: immediateload
12671265

12681266
.. autofunction:: joinedload

doc/build/orm/relationship_api.rst

-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ Relationships API
77

88
.. autofunction:: backref
99

10-
.. autofunction:: relation
11-
1210
.. autofunction:: dynamic_loader
1311

1412
.. autofunction:: foreign

0 commit comments

Comments
 (0)