From: Federico Caselli Date: Mon, 29 Aug 2022 22:26:49 +0000 (+0200) Subject: Mark extension modules as optional X-Git-Tag: rel_2_0_0b1~79 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=282d86d1086b0aaaa0cc1a6eede922ce8214e8d0;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Mark extension modules as optional This greatly simplifies the setup.py file and makes it compatible with setuptools 64+ change to editable install. Change-Id: I16a776b175bcf67e26f4bbb8f80b1b473f585e2a --- diff --git a/setup.py b/setup.py index c60a214141..ae71acd2c5 100644 --- a/setup.py +++ b/setup.py @@ -1,169 +1,81 @@ +from __future__ import annotations + import os import platform -import sys +from typing import cast +from typing import TYPE_CHECKING -from setuptools import __version__ from setuptools import setup -if not int(__version__.partition(".")[0]) >= 47: - raise RuntimeError(f"Setuptools >= 47 required. Found {__version__}") - -# attempt to use pep-632 imports for setuptools symbols; however, -# since these symbols were only added to setuptools as of 59.0.1, -# fall back to the distutils symbols otherwise -try: - from setuptools.errors import CCompilerError - from setuptools.errors import DistutilsExecError - from setuptools.errors import DistutilsPlatformError -except ImportError: - from distutils.errors import CCompilerError - from distutils.errors import DistutilsExecError - from distutils.errors import DistutilsPlatformError +if TYPE_CHECKING: + from setuptools import Extension try: - from Cython.Distutils.old_build_ext import old_build_ext - from Cython.Distutils.extension import Extension + from Cython.Build import build_ext as _cy_build_ext + from Cython.Distutils.extension import Extension as _cy_Extension - CYTHON = True + HAS_CYTHON = True except ImportError: - CYTHON = False - -cmdclass = {} - -cpython = platform.python_implementation() == "CPython" - -ext_errors = (CCompilerError, DistutilsExecError, DistutilsPlatformError) -extra_compile_args = [] -if sys.platform == "win32": - # Work around issue https://github.com/pypa/setuptools/issues/1902 - ext_errors += (IOError, TypeError) - -cython_files = [ - "collections.pyx", - "immutabledict.pyx", - "processors.pyx", - "resultproxy.pyx", - "util.pyx", -] -cython_directives = {"language_level": "3"} - -if CYTHON: - - def get_ext_modules(): - module_prefix = "sqlalchemy.cyextension." - source_prefix = "lib/sqlalchemy/cyextension/" - - ext_modules = [] - for file in cython_files: - name, _ = os.path.splitext(file) - ext_modules.append( - Extension( - module_prefix + name, - sources=[source_prefix + file], - extra_compile_args=extra_compile_args, - cython_directives=cython_directives, - ) - ) - return ext_modules - - class BuildFailed(Exception): - pass - - class ve_build_ext(old_build_ext): - # This class allows Cython building to fail. - - def run(self): - try: - super().run() - except DistutilsPlatformError: - raise BuildFailed() - - def build_extension(self, ext): - try: - super().build_extension(ext) - except ext_errors as e: - raise BuildFailed() from e - except ValueError as e: - # this can happen on Windows 64 bit, see Python issue 7511 - if "'path'" in str(e): - raise BuildFailed() from e - raise - - cmdclass["build_ext"] = ve_build_ext - ext_modules = get_ext_modules() -else: - ext_modules = [] + _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")) -def status_msgs(*msgs): - print("*" * 75) - for msg in msgs: - print(msg) - print("*" * 75) +if DISABLE_EXTENSION and REQUIRE_EXTENSION: + raise RuntimeError( + "Cannot set both 'DISABLE_SQLALCHEMY_CEXT' and " + "'REQUIRE_SQLALCHEMY_CEXT' environment variables" + ) -def run_setup(with_cext): - kwargs = {} - if with_cext: - kwargs["ext_modules"] = ext_modules - else: - if os.environ.get("REQUIRE_SQLALCHEMY_CEXT"): - raise AssertionError( - "Can't build on this platform with REQUIRE_SQLALCHEMY_CEXT" - " set. Cython is required to build compiled extensions" +if HAS_CYTHON and IS_CPYTHON and not DISABLE_EXTENSION: + assert _cy_Extension is not None + assert _cy_build_ext is not None + + cython_files = [ + "collections.pyx", + "immutabledict.pyx", + "processors.pyx", + "resultproxy.pyx", + "util.pyx", + ] + cython_directives = {"language_level": "3"} + + module_prefix = "sqlalchemy.cyextension." + source_prefix = "lib/sqlalchemy/cyextension/" + + ext_modules = cast( + "list[Extension]", + [ + _cy_Extension( + f"{module_prefix}{os.path.splitext(file)[0]}", + sources=[f"{source_prefix}{file}"], + cython_directives=cython_directives, + optional=not REQUIRE_EXTENSION, ) + for file in cython_files + ], + ) - kwargs["ext_modules"] = [] - - setup(cmdclass=cmdclass, **kwargs) + cmdclass = {"build_ext": _cy_build_ext} +elif REQUIRE_EXTENSION: -if not cpython: - run_setup(False) - status_msgs( - "WARNING: Cython extensions are not supported on " - "this Python platform, speedups are not enabled.", - "Plain-Python build succeeded.", - ) -elif not CYTHON: - run_setup(False) - status_msgs( - "WARNING: Cython is required to build the compiled " - "extensions, speedups are not enabled.", - "Plain-Python build succeeded.", - ) -elif os.environ.get("DISABLE_SQLALCHEMY_CEXT"): - run_setup(False) - status_msgs( - "DISABLE_SQLALCHEMY_CEXT is set; " - "not attempting to build Cython extensions.", - "Plain-Python build succeeded.", + 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: - try: - run_setup(True) - except BuildFailed as exc: - - if os.environ.get("REQUIRE_SQLALCHEMY_CEXT"): - status_msgs( - "NOTE: Cython extension build is required because " - "REQUIRE_SQLALCHEMY_CEXT is set, and the build has failed; " - "will not degrade to non-C extensions" - ) - raise - - status_msgs( - exc.__cause__, - "WARNING: The Cython extension could not be compiled, " - "speedups are not enabled.", - "Failure information, if any, is above.", - "Retrying the build without the C extension now.", - ) - - run_setup(False) - - status_msgs( - "WARNING: The Cython extension could not be compiled, " - "speedups are not enabled.", - "Plain-Python build succeeded.", - ) + ext_modules = [] + cmdclass = {} + +setup(cmdclass=cmdclass, ext_modules=ext_modules)