From: Mike Bayer Date: Mon, 3 Aug 2026 17:18:39 +0000 (-0400) Subject: add Python 3.15 support X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ec7e8c7dcdf459aba91286c7e8573a9f00e7a61b;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git add Python 3.15 support 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 --- diff --git a/doc/build/changelog/unreleased_20/13477.rst b/doc/build/changelog/unreleased_20/13477.rst new file mode 100644 index 0000000000..3fbcfc4483 --- /dev/null +++ b/doc/build/changelog/unreleased_20/13477.rst @@ -0,0 +1,6 @@ +.. change:: + :tags: bug, platform + :tickets: 13477 + + Python 3.15 support has been added and tested, including minimal changes + for full compatibility. diff --git a/lib/sqlalchemy/orm/decl_base.py b/lib/sqlalchemy/orm/decl_base.py index ed491a18b2..59201685c3 100644 --- a/lib/sqlalchemy/orm/decl_base.py +++ b/lib/sqlalchemy/orm/decl_base.py @@ -662,6 +662,20 @@ class _ClassScanAbstractConfig(_ORMClassConfigurator): "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 diff --git a/noxfile.py b/noxfile.py index 97cd30e8de..19ef15550f 100644 --- a/noxfile.py +++ b/noxfile.py @@ -24,7 +24,7 @@ if True: 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"] diff --git a/pyproject.toml b/pyproject.toml index 9b750e318d..04e84659cf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,6 +24,7 @@ classifiers = [ "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",