Files
sqlalchemy/setup.py
Lysandros Nikolaou b8ab31e7f1 Add explicit multi-threaded tests and support free-threaded build
Implemented initial support for free-threaded Python by adding new tests
and reworking the test harness and GitHub Actions to include Python 3.13t
and Python 3.14t in test runs. Two concurrency issues have been identified
and fixed: the first involves initialization of the ``.c`` collection on a
``FromClause``, a continuation of 🎫`12302`, where an optional mutex
under free-threading is added; the second involves synchronization of the
pool "first_connect" event, which first received thread synchronization in
🎫`2964`, however under free-threading the creation of the mutex
itself runs under the same free-threading mutex. Initial pull request and
test suite courtesy Lysandros Nikolaou.

py313t: yes
py314t: yes
Fixes: #12881
Closes: #12882
Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/12882
Pull-request-sha: 53d65d96b9

Co-authored-by: Mike Bayer <mike_mp@zzzcomputng.com>
Change-Id: I2e4f2e9ac974ab6382cb0520cc446b396d9680a6
2025-10-02 10:08:01 -04:00

87 lines
2.3 KiB
Python

from __future__ import annotations
import os
import platform
from typing import cast
from typing import TYPE_CHECKING
from setuptools import setup
if TYPE_CHECKING:
from setuptools import Extension
try:
from Cython.Build import build_ext as _cy_build_ext
from Cython.Distutils.extension import Extension as _cy_Extension
HAS_CYTHON = True
except ImportError:
_cy_build_ext = _cy_Extension = None
HAS_CYTHON = False
IS_CPYTHON = platform.python_implementation() == "CPython"
DISABLE_EXTENSION = bool(os.environ.get("DISABLE_SQLALCHEMY_CEXT"))
REQUIRE_EXTENSION = bool(os.environ.get("REQUIRE_SQLALCHEMY_CEXT"))
if DISABLE_EXTENSION and REQUIRE_EXTENSION:
raise RuntimeError(
"Cannot set both 'DISABLE_SQLALCHEMY_CEXT' and "
"'REQUIRE_SQLALCHEMY_CEXT' environment variables"
)
# when adding a cython module, also update the imports in _has_cython
# it is tested in test_setup_defines_all_files
CYTHON_MODULES = (
"engine._processors_cy",
"engine._row_cy",
"engine._util_cy",
"sql._util_cy",
"util._collections_cy",
"util._immutabledict_cy",
)
if HAS_CYTHON and IS_CPYTHON and not DISABLE_EXTENSION:
assert _cy_Extension is not None
assert _cy_build_ext is not None
cython_directives = {
"language_level": "3",
"freethreading_compatible": True,
}
module_prefix = "sqlalchemy."
source_prefix = "lib/sqlalchemy/"
ext_modules = cast(
"list[Extension]",
[
_cy_Extension(
f"{module_prefix}{module}",
sources=[f"{source_prefix}{module.replace('.', '/')}.py"],
cython_directives=cython_directives,
optional=not REQUIRE_EXTENSION,
)
for module in CYTHON_MODULES
],
)
cmdclass = {"build_ext": _cy_build_ext}
elif REQUIRE_EXTENSION:
reasons = []
if not HAS_CYTHON:
reasons.append("Cython is missing")
if not IS_CPYTHON:
reasons.append("Not CPython, build is supported only on it")
raise RuntimeError(
"Cython extension build is required because REQUIRE_SQLALCHEMY_CEXT "
f"is set but it was deselected because: {'; '.join(reasons)}; "
"will not degrade to pure python install"
)
else:
ext_modules = []
cmdclass = {}
setup(cmdclass=cmdclass, ext_modules=ext_modules)