File py314.patch of Package python-SQLAlchemy1

From b8b07a2f28657e57ae9b4071b6313df372b7f8cb Mon Sep 17 00:00:00 2001
From: Mike Bayer <mike_mp@zzzcomputing.com>
Date: Thu, 6 Mar 2025 09:12:43 -0500
Subject: [PATCH] implement pep-649 workarounds, test suite passing for python
 3.14

Changes to the test suite to accommodate Python 3.14 as of version
3.14.0b1

Originally this included a major breaking change to how python 3.14
implemented :pep:`649`, however this was resolved by [1].

As of a7, greenlet is skipped due to issues in a7 and later b1
in [2].

1. the change to rewrite all conditionals in annotation related tests
   is reverted.
2. test_memusage needed an explicit set_start_method() call so that
   it can continue to use plain fork
3. unfortunately at the moment greenlet has to be re-disabled for 3.14.
4. Changes to tox overall, remove pysqlcipher which hasn't worked
   in years, etc.
5. we need to support upcoming typing-extensions also, install the beta
6. 3.14.0a7 introduces major regressions to our runtime typing
   utilities, unfortunately, it's not clear if these can be resolved
7. for 3.14.0b1, we have to vendor get_annotations to work around [3]

[1] https://github.com/python/cpython/issues/130881
[2] https://github.com/python-greenlet/greenlet/issues/440
[3] https://github.com/python/cpython/issues/133684

py314: yes
Fixes: #12405
References: #12399
Change-Id: I8715d02fae599472dd64a2a46ccf8986239ecd99
---
 doc/build/changelog/unreleased_20/12405.rst |  10 ++
 lib/sqlalchemy/testing/requirements.py      |  46 ++++++
 lib/sqlalchemy/util/__init__.py             |   1 +
 lib/sqlalchemy/util/compat.py               |   2 +
 lib/sqlalchemy/util/langhelpers.py          |  80 +++++++++-
 lib/sqlalchemy/util/typing.py               |  20 ++-
 pyproject.toml                              |   7 +
 test/aaa_profiling/test_memusage.py         |  14 +-
 test/base/test_typing_utils.py              | 153 +++++++++++++-------
 test/ext/asyncio/test_engine_py3k.py        |  16 +-
 test/typing/test_overloads.py               |  10 +-
 tox.ini                                     |  28 ++--
 12 files changed, 297 insertions(+), 90 deletions(-)
 create mode 100644 doc/build/changelog/unreleased_20/12405.rst

Index: sqlalchemy-1.4.54/doc/build/changelog/unreleased_20/12405.rst
===================================================================
--- /dev/null
+++ sqlalchemy-1.4.54/doc/build/changelog/unreleased_20/12405.rst
@@ -0,0 +1,10 @@
+.. change::
+    :tags: bug, orm
+    :tickets: 12405
+
+    Changes to the test suite to accommodate Python 3.14 and its new
+    implementation of :pep:`649`, which highly modifies how typing annotations
+    are interpreted at runtime.  Use of the new
+    ``annotationlib.get_annotations()`` function is enabled when python 3.14 is
+    present, and many other changes to how pep-484 type objects are interpreted
+    at runtime are made.
Index: sqlalchemy-1.4.54/lib/sqlalchemy/testing/requirements.py
===================================================================
--- sqlalchemy-1.4.54.orig/lib/sqlalchemy/testing/requirements.py
+++ sqlalchemy-1.4.54/lib/sqlalchemy/testing/requirements.py
@@ -15,6 +15,7 @@ to provide specific inclusion/exclusions
 
 """
 
+import os
 import platform
 import sys
 
@@ -1498,6 +1499,10 @@ class SuiteRequirements(Requirements):
         return exclusions.closed()
 
     @property
+    def posix(self):
+        return exclusions.skip_if(lambda: os.name != "posix")
+
+    @property
     def regexp_match(self):
         """backend supports the regexp_match operator."""
         return exclusions.closed()
@@ -1535,6 +1540,27 @@ class SuiteRequirements(Requirements):
         return exclusions.closed()
 
     @property
+    def up_to_date_typealias_type(self):
+        # this checks a particular quirk found in typing_extensions <=4.12.0
+        # using older python versions like 3.10 or 3.9, we use TypeAliasType
+        # from typing_extensions which does not provide for sufficient
+        # introspection prior to 4.13.0
+        def check(config):
+            import typing
+            import typing_extensions
+
+            TypeAliasType = getattr(
+                typing, "TypeAliasType", typing_extensions.TypeAliasType
+            )
+            TV = typing.TypeVar("TV")
+            TA_generic = TypeAliasType(  # type: ignore
+                "TA_generic", typing.List[TV], type_params=(TV,)
+            )
+            return hasattr(TA_generic[int], "__value__")
+
+        return exclusions.only_if(check)
+
+    @property
     def fetch_expression(self):
         """backend supports fetch / offset with expression in them, like
 
@@ -1551,6 +1577,26 @@ class SuiteRequirements(Requirements):
         return exclusions.open()
 
     @property
+    def fail_python314b1(self):
+        return exclusions.fails_if(
+            lambda: util.compat.py314b1, "Fails as of python 3.14.0b1"
+        )
+
+    @property
+    def not_python314(self):
+        """This requirement is interim to assist with backporting of
+        issue #12405.
+
+        SQLAlchemy 2.0 still includes the ``await_fallback()`` method that
+        makes use of ``asyncio.get_event_loop_policy()``.  This is removed
+        in SQLAlchemy 2.1.
+
+        """
+        return exclusions.skip_if(
+            lambda: util.py314, "Python 3.14 or above not supported"
+        )
+
+    @property
     def generic_classes(self):
         "If X[Y] can be implemented with ``__class_getitem__``. py3.7+"
         return exclusions.only_if(lambda: util.py37)
Index: sqlalchemy-1.4.54/lib/sqlalchemy/util/__init__.py
===================================================================
--- sqlalchemy-1.4.54.orig/lib/sqlalchemy/util/__init__.py
+++ sqlalchemy-1.4.54/lib/sqlalchemy/util/__init__.py
@@ -81,6 +81,8 @@ from .compat import py2k
 from .compat import py310
 from .compat import py311
 from .compat import py312
+from .compat import py313
+from .compat import py314
 from .compat import py37
 from .compat import py38
 from .compat import py39
Index: sqlalchemy-1.4.54/lib/sqlalchemy/util/compat.py
===================================================================
--- sqlalchemy-1.4.54.orig/lib/sqlalchemy/util/compat.py
+++ sqlalchemy-1.4.54/lib/sqlalchemy/util/compat.py
@@ -14,6 +14,9 @@ import operator
 import platform
 import sys
 
+py314b1 = sys.version_info >= (3, 14, 0, "beta", 1)
+py314 = sys.version_info >= (3, 14)
+py313 = sys.version_info >= (3, 13)
 py312 = sys.version_info >= (3, 12)
 py311 = sys.version_info >= (3, 11)
 py310 = sys.version_info >= (3, 10)
Index: sqlalchemy-1.4.54/test/aaa_profiling/test_memusage.py
===================================================================
--- sqlalchemy-1.4.54.orig/test/aaa_profiling/test_memusage.py
+++ sqlalchemy-1.4.54/test/aaa_profiling/test_memusage.py
@@ -211,10 +211,14 @@ def profile_memory(
         # return run_plain
 
         def run_in_process(*func_args):
-            queue = multiprocessing.Queue()
-            proc = multiprocessing.Process(
-                target=profile, args=(queue, func_args)
-            )
+            # see
+            # https://docs.python.org/3.14/whatsnew/3.14.html
+            # #incompatible-changes - the default run type is no longer
+            # "fork", but since we are running closures in the process
+            # we need forked mode
+            ctx = multiprocessing.get_context("fork")
+            queue = ctx.Queue()
+            proc = ctx.Process(target=profile, args=(queue, func_args))
             proc.start()
             while True:
                 row = queue.get()
@@ -388,7 +392,7 @@ class MemUsageTest(EnsureZeroed):
 class MemUsageWBackendTest(fixtures.MappedTest, EnsureZeroed):
 
     __tags__ = ("memory_intensive",)
-    __requires__ = "cpython", "memory_process_intensive", "no_asyncio"
+    __requires__ = "cpython", "posix", "memory_process_intensive", "no_asyncio"
     __sparse_backend__ = True
 
     # ensure a pure growing test trips the assertion
Index: sqlalchemy-1.4.54/test/ext/asyncio/test_engine_py3k.py
===================================================================
--- sqlalchemy-1.4.54.orig/test/ext/asyncio/test_engine_py3k.py
+++ sqlalchemy-1.4.54/test/ext/asyncio/test_engine_py3k.py
@@ -264,9 +264,8 @@ class AsyncEngineTest(EngineFixture):
 
         is_false(async_engine == None)
 
-    @async_test
     @testing.requires.python37
-    async def test_no_attach_to_event_loop(self, testing_engine):
+    def test_no_attach_to_event_loop(self, testing_engine):
         """test #6409"""
 
         import asyncio
@@ -275,9 +274,6 @@ class AsyncEngineTest(EngineFixture):
         errs = []
 
         def go():
-            loop = asyncio.new_event_loop()
-            asyncio.set_event_loop(loop)
-
             async def main():
                 tasks = [task() for _ in range(2)]
 
openSUSE Build Service is sponsored by