Skip to content

Commit

Permalink
chore: change setup.py to make use of optional build_ext option
Browse files Browse the repository at this point in the history
This allows skipping the compilation of the c file if it fails for some reason,
like the compiler is missing.
The build will still fail if cython can't generate the c file from the py/pyx file
but that should be ok.
  • Loading branch information
CaselIT committed Jul 13, 2024
1 parent 89ccb98 commit 1082600
Showing 1 changed file with 35 additions and 108 deletions.
143 changes: 35 additions & 108 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,65 +3,28 @@
import os
from os import path
import re
import sys
import platform

from setuptools import Extension, setup
from setuptools import setup

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

DISABLE_EXTENSION = bool(os.environ.get('FALCON_DISABLE_CYTHON'))
IS_CPYTHON = platform.python_implementation() == "CPython"

MYDIR = path.abspath(os.path.dirname(__file__))

try:
sys.pypy_version_info
PYPY = True
except AttributeError:
PYPY = False

if PYPY:
CYTHON = False
else:
try:
from Cython.Distutils import build_ext

CYTHON = True
except ImportError:
CYTHON = False


class BuildFailed(Exception):
pass


def get_cython_options():
# from sqlalchemy setup.py
from distutils.errors import (
CCompilerError,
DistutilsExecError,
DistutilsPlatformError,
)

ext_errors = (CCompilerError, DistutilsExecError, DistutilsPlatformError)
if sys.platform == 'win32':
# Work around issue https://github.com/pypa/setuptools/issues/1902
ext_errors += (IOError, TypeError)

class ve_build_ext(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
if HAS_CYTHON and IS_CPYTHON and not DISABLE_EXTENSION:
assert _cy_Extension is not None
assert _cy_build_ext is not None

def list_modules(dirname, pattern):
filenames = glob.glob(path.join(dirname, pattern))
Expand Down Expand Up @@ -103,15 +66,17 @@ def list_modules(dirname, pattern):
'falcon.util.sync',
]

cython_package_names = frozenset(
[
'falcon.cyutil',
]
)
cython_package_names = ('falcon.cyutil',)
# NOTE(vytas): Now that all our codebase is Python 3.7+, specify the
# Python 3 language level for Cython as well to avoid any surprises.
cython_directives = {'language_level': '3', 'annotation_typing': False}

ext_modules = [
Extension(
package + '.' + module, [path.join(*(package.split('.') + [module + ext]))]
_cy_Extension(
package + '.' + module,
sources=[path.join(*(package.split('.') + [module + ext]))],
cython_directives=cython_directives,
optional=True,
)
for package in package_names
for module, ext in list_modules(
Expand All @@ -121,13 +86,10 @@ def list_modules(dirname, pattern):
if (package + '.' + module) not in modules_to_exclude
]

# NOTE(vytas): Now that all our codebase is Python 3.7+, specify the
# Python 3 language level for Cython as well to avoid any surprises.
for ext_mod in ext_modules:
ext_mod.cython_directives = {'language_level': '3', 'annotation_typing': False}

cmdclass = {'build_ext': ve_build_ext}
return cmdclass, ext_modules
cmdclass = {'build_ext': _cy_build_ext}
else:
ext_modules = []
cmdclass = {}


def load_description():
Expand Down Expand Up @@ -164,47 +126,12 @@ def load_description():
return ''.join(description_lines)


def run_setup(CYTHON):
if CYTHON:
cmdclass, ext_modules = get_cython_options()
else:
cmdclass, ext_modules = {}, []

setup(
long_description=load_description(),
cmdclass=cmdclass,
ext_modules=ext_modules,
)


def status_msgs(*msgs):
print('*' * 75, *msgs, '*' * 75, sep='\n')


if not CYTHON:
run_setup(False)
if not PYPY:
status_msgs('Cython compilation not supported in this environment')
elif os.environ.get('FALCON_DISABLE_CYTHON'):
run_setup(False)
status_msgs(
'FALCON_DISABLE_CYTHON is set, skipping cython compilation.',
'Pure-Python build succeeded.',
)
else:
try:
run_setup(True)
except BuildFailed as exc:
status_msgs(
exc.__cause__,
'Cython compilation could not be completed, speedups are not enabled.',
'Failure information, if any, is above.',
'Retrying the build without the C extension now.',
)

run_setup(False)

status_msgs(
'Cython compilation could not be completed, speedups are not enabled.',
'Pure-Python build succeeded.',
)
setup(
long_description=load_description(),
cmdclass=cmdclass,
ext_modules=ext_modules,
)

0 comments on commit 1082600

Please sign in to comment.