Add 3.15 to the noxfile Python matrix and to the trove classifiers.
Repair the auto-generated docstring for MappedAsDataclass subclasses under
3.15. Python 3.15 changed dataclasses so that the class docstring is no
longer rendered when the dataclass is created, and is instead produced by a
descriptor the first time __doc__ is read. _ClassScanMapperConfig swaps a
merged __annotations__ onto the class for the duration of the dataclass call
and restores the original in a finally block, so by the time that deferred
render happens the annotations are gone and the docstring loses them
entirely. Read __doc__ while the swapped annotations are still in place so
the same docstring is produced on every supported Python.
Full sqlite test suite passes on 3.15.0b4 (25972 passed); no change on
3.10, 3.13 or 3.14.
py315: yes
Fixes: #13477
Change-Id: I452a8bb1392a4417194594bd2e1e37b9e56fee26
--- /dev/null
+.. change::
+ :tags: bug, platform
+ :tickets: 13477
+
+ Python 3.15 support has been added and tested, including minimal changes
+ for full compatibility.
"documentation for additional information.",
code="dcte",
) from ex
+ else:
+ # as of Python 3.15, dataclasses no longer renders the
+ # auto-generated class docstring immediately; it instead installs
+ # a descriptor that renders the ``__init__`` signature the first
+ # time ``__doc__`` is accessed (see
+ # ``dataclasses._AutoDocstring``). As the ``finally:`` block
+ # below puts the class' original annotations back, that deferred
+ # render would no longer see the dataclass-oriented annotations
+ # we swapped in above, and would omit them from the docstring
+ # entirely. Read the attribute now, while those annotations are
+ # still in place, so the docstring we generate is the same on
+ # every Python version.
+ self.cls.__doc__
+
finally:
if revert and revert_dict:
# used for mixin dataclasses; we have to restore the
from tools.toxnox import tox_parameters
-PYTHON_VERSIONS = ["3.10", "3.11", "3.12", "3.13", "3.14", "3.14t"]
+PYTHON_VERSIONS = ["3.10", "3.11", "3.12", "3.13", "3.14", "3.14t", "3.15"]
DATABASES = ["sqlite", "sqlite_file", "postgresql", "mysql", "oracle", "mssql"]
CEXT = ["_auto", "cext", "nocext"]
GREENLET = ["_greenlet", "nogreenlet"]
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
+ "Programming Language :: Python :: 3.15",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
"Topic :: Database :: Front-Ends",