Copilot commented on code in PR #1264:
URL:
https://github.com/apache/cassandra-python-driver/pull/1264#discussion_r2686415273
##########
setup.py:
##########
@@ -163,50 +52,8 @@ def eval_env_var_as_array(varname):
=================================================================================
"""
-is_pypy = "PyPy" in sys.version
-if is_pypy:
- sys.stderr.write(pypy_unsupported_msg)
-
-is_supported_platform = sys.platform != "cli" and not
sys.platform.startswith("java")
-is_supported_arch = sys.byteorder != "big"
-if not is_supported_platform:
- sys.stderr.write(platform_unsupported_msg)
-elif not is_supported_arch:
- sys.stderr.write(arch_unsupported_msg)
-
-try_extensions = "--no-extensions" not in sys.argv and is_supported_platform
and is_supported_arch and not os.environ.get('CASS_DRIVER_NO_EXTENSIONS')
-try_murmur3 = try_extensions and "--no-murmur3" not in sys.argv
-try_libev = try_extensions and "--no-libev" not in sys.argv and not is_pypy
and not os.environ.get('CASS_DRIVER_NO_LIBEV')
-try_cython = try_extensions and "--no-cython" not in sys.argv and not is_pypy
and not os.environ.get('CASS_DRIVER_NO_CYTHON')
-try_cython &= 'egg_info' not in sys.argv # bypass setup_requires for pip
egg_info calls, which will never have --install-option"--no-cython" coming fomr
pip
-
-sys.argv = [a for a in sys.argv if a not in ("--no-murmur3", "--no-libev",
"--no-cython", "--no-extensions")]
-
-build_concurrency = int(os.environ.get('CASS_DRIVER_BUILD_CONCURRENCY', '0'))
-
-
-class NoPatchExtension(Extension):
-
- # Older versions of setuptools.extension has a static flag which is set
False before our
- # setup_requires lands Cython. It causes our *.pyx sources to be renamed
to *.c in
- # the initializer.
- # The other workaround would be to manually generate sources, but that
bypasses a lot
- # of the niceness cythonize embodies (setup build dir, conditional build,
etc).
- # Newer setuptools does not have this problem because it checks for cython
dynamically.
- #
https://bitbucket.org/pypa/setuptools/commits/714c3144e08fd01a9f61d1c88411e76d2538b2e4
-
- def __init__(self, *args, **kwargs):
- # bypass the patched init if possible
- if Extension.__bases__:
- base, = Extension.__bases__
- base.__init__(self, *args, **kwargs)
- else:
- Extension.__init__(self, *args, **kwargs)
-
-
-class build_extensions(build_ext):
-
- error_message = """
+windows_compmile_error = \
Review Comment:
Spelling error: "compmile" should be "compile".
```suggestion
windows_compile_error = \
```
##########
pyproject.toml:
##########
@@ -0,0 +1,57 @@
+[build-system]
+build-backend = "setuptools.build_meta"
+requires = ["setuptools", "Cython>=3.0", "toml", "cassandra-driver"]
Review Comment:
Critical circular dependency issue: The build-system requires
"cassandra-driver" as a build dependency, but this is the package being built.
This will cause build failures as pip cannot install cassandra-driver before
building cassandra-driver. The "cassandra-driver" entry should be removed from
the requires list.
```suggestion
requires = ["setuptools", "Cython>=3.0", "toml"]
```
##########
pyproject.toml:
##########
@@ -0,0 +1,57 @@
+[build-system]
+build-backend = "setuptools.build_meta"
+requires = ["setuptools", "Cython>=3.0", "toml", "cassandra-driver"]
+
+[project]
+name = "cassandra-driver"
+description = "Apache Cassandra Python Driver"
+dependencies = ['geomet>=1.1']
+readme = "README.rst"
+authors = [{name = "DataStax"}]
+license = "Apache-2.0"
+license-files = ["LICENSE"]
+keywords = ["cassandra","cql","orm","dse","graph"]
+classifiers = [
+ "Development Status :: 5 - Production/Stable",
+ "Intended Audience :: Developers",
+ "Natural Language :: English",
+ "Operating System :: OS Independent",
+ "License :: OSI Approved :: Apache Software License",
+ "Programming Language :: Python",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.12",
+ "Programming Language :: Python :: 3.13",
+ "Programming Language :: Python :: Implementation :: CPython",
+ "Programming Language :: Python :: Implementation :: PyPy",
+ "Topic :: Software Development :: Libraries :: Python Modules"
+]
+dynamic = ["version"]
+
+[project.optional-dependencies]
+graph = ["gremlinpython==3.4.6"]
+cle = ["cryptography>=42.0"]
+test = ["pytest", "PyYAML", "pytz"]
+
+[project.urls]
+homepage = "https://github.com/apache/cassandra-python-driver/"
+documentation = "https://docs.datastax.com/en/developer/python-driver/latest/"
+source = "https://github.com/apache/cassandra-python-driver/"
+issues =
"https://issues.apache.org/jira/issues/?jql=project%20%3D%20CASSPYTHON%20ORDER%20BY%20key%20DESC"
+changelog =
"https://github.com/apache/cassandra-python-driver/blob/trunk/CHANGELOG.rst"
+
+[tool.setuptools.packages.find]
+include = ['cassandra', 'cassandra.io', 'cassandra.cqlengine',
'cassandra.graph',
+'cassandra.datastax', 'cassandra.datastax.insights',
'cassandra.datastax.graph',
+'cassandra.datastax.graph.fluent', 'cassandra.datastax.cloud',
+"cassandra.column_encryption"]
+
+[tool.cassandra-driver]
+build-extensions = true
+build-murmur3-extension = true
+build-libev-extension = true
+build-cython-extensions = true
+libev-includes = []
+libev-libs = []
Review Comment:
The pyproject.toml configuration uses "libev-libs" (line 56) but this should
more accurately be named "libev-libdirs" to match the semantics of library
directories, consistent with the `library_dirs` parameter used in the Extension
definition. While not technically incorrect, this naming could be confusing as
"libs" might suggest library names rather than library directories.
```suggestion
libev-libdirs = []
```
##########
setup.py:
##########
@@ -254,193 +104,78 @@ class build_extensions(build_ext):
$ brew install libev
===============================================================================
- """
-
- def run(self):
- try:
- self._setup_extensions()
- build_ext.run(self)
- except DistutilsPlatformError as exc:
- sys.stderr.write('%s\n' % str(exc))
- warnings.warn(self.error_message % "C extensions.")
-
- def build_extensions(self):
- if build_concurrency > 1:
- self.check_extensions_list(self.extensions)
-
- import multiprocessing.pool
-
multiprocessing.pool.ThreadPool(processes=build_concurrency).map(self.build_extension,
self.extensions)
- else:
- build_ext.build_extensions(self)
-
- def build_extension(self, ext):
- try:
- build_ext.build_extension(self, ext)
- except (CCompilerError, DistutilsExecError,
- DistutilsPlatformError, IOError) as exc:
- sys.stderr.write('%s\n' % str(exc))
- name = "The %s extension" % (ext.name,)
- warnings.warn(self.error_message % (name,))
-
- def _setup_extensions(self):
- # We defer extension setup until this command to leveraage
'setup_requires' pulling in Cython before we
- # attempt to import anything
- self.extensions = []
-
- if try_murmur3:
- self.extensions.append(murmur3_ext)
-
- if try_libev:
- sys.stderr.write("Appending libev extension %s" % libev_ext)
- self.extensions.append(libev_ext)
-
- if try_cython:
- try:
- from Cython.Build import cythonize
- cython_candidates = ['cluster', 'concurrent', 'connection',
'cqltypes', 'metadata',
- 'pool', 'protocol', 'query', 'util']
- compile_args = [] if is_windows else ['-Wno-unused-function']
- self.extensions.extend(cythonize(
- [Extension('cassandra.%s' % m, ['cassandra/%s.py' % m],
- extra_compile_args=compile_args)
- for m in cython_candidates],
- nthreads=build_concurrency,
- exclude_failures=True))
-
- self.extensions.extend(cythonize(NoPatchExtension("*",
["cassandra/*.pyx"], extra_compile_args=compile_args),
- nthreads=build_concurrency))
- except Exception:
- sys.stderr.write("Failed to cythonize one or more modules.
These will not be compiled as extensions (optional).\n")
-
-
-def pre_build_check():
- """
- Try to verify build tools
- """
- if os.environ.get('CASS_DRIVER_NO_PRE_BUILD_CHECK'):
- return True
-
- try:
- from distutils.ccompiler import new_compiler
- from distutils.sysconfig import customize_compiler
- from distutils.dist import Distribution
-
- # base build_ext just to emulate compiler option setup
- be = build_ext(Distribution())
- be.initialize_options()
- be.finalize_options()
+"""
- # First, make sure we have a Python include directory
- have_python_include = any(os.path.isfile(os.path.join(p, 'Python.h'))
for p in be.include_dirs)
- if not have_python_include:
- sys.stderr.write("Did not find 'Python.h' in %s.\n" %
(be.include_dirs,))
- return False
+# ========================== A few upfront checks ==========================
+if is_pypy:
+ sys.stderr.write(pypy_unsupported_msg)
+if not is_supported_platform:
+ sys.stderr.write(platform_unsupported_msg)
+elif not is_supported_arch:
+ sys.stderr.write(arch_unsupported_msg)
- compiler = new_compiler(compiler=be.compiler)
- customize_compiler(compiler)
+# ========================== Extensions ==========================
+pyproject_toml = Path(__file__).parent / "pyproject.toml"
+pyproject_data = toml.load(pyproject_toml)
+driver_project_data = pyproject_data["tool"]["cassandra-driver"]
- try:
- # We must be able to initialize the compiler if it has that method
- if hasattr(compiler, "initialize"):
- compiler.initialize()
- except OSError:
- return False
+murmur3_ext = Extension('cassandra.cmurmur3', sources=['cassandra/cmurmur3.c'])
- executables = []
- if compiler.compiler_type in ('unix', 'cygwin'):
- executables = [compiler.executables[exe][0] for exe in
('compiler_so', 'linker_so')]
- elif compiler.compiler_type == 'nt':
- executables = [getattr(compiler, exe) for exe in ('cc', 'linker')]
+DEFAULT_LIBEV_INCLUDES = ['/usr/include/libev', '/usr/local/include',
'/opt/local/include', '/usr/include']
+DEFAULT_LIBEV_LIBS = ['/usr/local/lib', '/opt/local/lib', '/usr/lib64']
+libev_includes = driver_project_data["libev-includes"] or
DEFAULT_LIBEV_INCLUDES
+libev_libs = driver_project_data["libev-libs"] or DEFAULT_LIBEV_LIBS
+if is_macos:
+ libev_includes.extend(['/opt/homebrew/include',
os.path.expanduser('~/homebrew/include')])
+ libev_libs.extend(['/opt/homebrew/lib'])
+libev_ext = Extension('cassandra.io.libevwrapper',
+ sources=['cassandra/io/libevwrapper.c'],
+ include_dirs=libev_includes,
+ libraries=['ev'],
+ library_dirs=libev_libs)
- if executables:
- from distutils.spawn import find_executable
- for exe in executables:
- if not find_executable(exe):
- sys.stderr.write("Failed to find %s for compiler type
%s.\n" % (exe, compiler.compiler_type))
- return False
+try_extensions = driver_project_data["build-extensions"] and
is_supported_platform and is_supported_arch
+try_murmur3 = driver_project_data["build-murmur3-extension"]
+try_libev = driver_project_data["build-libev-extension"]
+try_cython = driver_project_data["build-cython-extensions"] and not is_pypy
- except Exception as exc:
- sys.stderr.write('%s\n' % str(exc))
- sys.stderr.write("Failed pre-build check. Attempting anyway.\n")
+build_concurrency = driver_project_data["build-concurrency"]
- # if we are unable to positively id the compiler type, or one of these
assumptions fails,
- # just proceed as we would have without the check
- return True
+def build_extension_list():
+ rv = []
-def run_setup(extensions):
+ if try_murmur3:
+ sys.stderr.write("Appending murmur extension %s\n" % murmur3_ext)
+ rv.append(murmur3_ext)
- kw = {'cmdclass': {'doc': DocCommand}}
- kw['cmdclass']['build_ext'] = build_extensions
- kw['ext_modules'] = [Extension('DUMMY', [])] # dummy extension makes sure
build_ext is called for install
+ if try_libev:
+ sys.stderr.write("Appending libev extension %s\n" % libev_ext)
+ rv.append(libev_ext)
if try_cython:
- # precheck compiler before adding to setup_requires
- # we don't actually negate try_cython because:
- # 1.) build_ext eats errors at compile time, letting the install
complete while producing useful feedback
- # 2.) there could be a case where the python environment has cython
installed but the system doesn't have build tools
- if pre_build_check():
- cython_dep = 'Cython>=3.0'
- user_specified_cython_version =
os.environ.get('CASS_DRIVER_ALLOWED_CYTHON_VERSION')
- if user_specified_cython_version is not None:
- cython_dep = 'Cython==%s' % (user_specified_cython_version,)
- kw['setup_requires'] = [cython_dep]
- else:
- sys.stderr.write("Bypassing Cython setup requirement\n")
-
- dependencies = ['geomet>=1.1']
-
- _EXTRAS_REQUIRE = {
- 'graph': ['gremlinpython==3.4.6'],
- 'cle': ['cryptography>=42.0']
- }
-
- setup(
- name='cassandra-driver',
- version=__version__,
- description='Apache Cassandra Python Driver',
- long_description=long_description,
- long_description_content_type='text/x-rst',
- url='http://github.com/datastax/python-driver',
- project_urls={
- 'Documentation':
'https://docs.datastax.com/en/developer/python-driver/latest/',
- 'Source': 'https://github.com/datastax/python-driver/',
- 'Issues': 'https://datastax-oss.atlassian.net/browse/PYTHON',
- },
- author='DataStax',
- packages=[
- 'cassandra', 'cassandra.io', 'cassandra.cqlengine',
'cassandra.graph',
- 'cassandra.datastax', 'cassandra.datastax.insights',
'cassandra.datastax.graph',
- 'cassandra.datastax.graph.fluent', 'cassandra.datastax.cloud',
- "cassandra.column_encryption"
- ],
- keywords='cassandra,cql,orm,dse,graph',
- include_package_data=True,
- install_requires=dependencies,
- extras_require=_EXTRAS_REQUIRE,
- tests_require=['pytest', 'PyYAML', 'pytz'],
- classifiers=[
- 'Development Status :: 5 - Production/Stable',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: Apache Software License',
- 'Natural Language :: English',
- 'Operating System :: OS Independent',
- 'Programming Language :: Python',
- 'Programming Language :: Python :: 3.9',
- 'Programming Language :: Python :: 3.10',
- 'Programming Language :: Python :: 3.11',
- 'Programming Language :: Python :: 3.12',
- 'Programming Language :: Python :: 3.13',
- 'Programming Language :: Python :: Implementation :: CPython',
- 'Programming Language :: Python :: Implementation :: PyPy',
- 'Topic :: Software Development :: Libraries :: Python Modules'
- ],
- **kw)
-
-
-run_setup(None)
-
-if has_cqlengine:
- warnings.warn("\n#######\n'cqlengine' package is present on path: %s\n"
- "cqlengine is now an integrated sub-package of this
driver.\n"
- "It is recommended to remove this package to reduce the
chance for conflicting usage" % cqlengine.__file__)
+ sys.stderr.write("Trying Cython builds in order to append Cython
extensions\n")
+ try:
+ from Cython.Build import cythonize
+ cython_candidates = ['cluster', 'concurrent', 'connection',
'cqltypes', 'metadata',
+ 'pool', 'protocol', 'query', 'util']
+ compile_args = [] if is_windows else ['-Wno-unused-function']
+ rv.extend(cythonize(
+ [Extension('cassandra.%s' % m, ['cassandra/%s.py' % m],
+ extra_compile_args=compile_args)
+ for m in cython_candidates],
+ nthreads=build_concurrency,
+ exclude_failures=True))
+
+ rv.extend(cythonize(Extension("*", ["cassandra/*.pyx"],
extra_compile_args=compile_args),
+ nthreads=build_concurrency))
+ except Exception:
+ sys.stderr.write("Failed to cythonize one or more modules. These
will not be compiled as extensions (optional).\n")
+
+ return rv
+
+# ========================== And finally setup() itself
==========================
+setup(
+ version = __version__,
+ ext_modules = build_extension_list()
+)
Review Comment:
The refactored code removes the `pre_build_check` function that verified the
availability of build tools (compiler, Python.h headers, etc.) before
attempting to build extensions. This function provided early feedback to users
about missing build dependencies. Without this check, users may encounter less
clear error messages during the build process. Consider whether this
verification is still valuable or if the modern build system handles this
adequately.
##########
setup.py:
##########
@@ -254,193 +104,78 @@ class build_extensions(build_ext):
$ brew install libev
===============================================================================
- """
-
- def run(self):
- try:
- self._setup_extensions()
- build_ext.run(self)
- except DistutilsPlatformError as exc:
- sys.stderr.write('%s\n' % str(exc))
- warnings.warn(self.error_message % "C extensions.")
-
- def build_extensions(self):
- if build_concurrency > 1:
- self.check_extensions_list(self.extensions)
-
- import multiprocessing.pool
-
multiprocessing.pool.ThreadPool(processes=build_concurrency).map(self.build_extension,
self.extensions)
- else:
- build_ext.build_extensions(self)
-
- def build_extension(self, ext):
- try:
- build_ext.build_extension(self, ext)
- except (CCompilerError, DistutilsExecError,
- DistutilsPlatformError, IOError) as exc:
- sys.stderr.write('%s\n' % str(exc))
- name = "The %s extension" % (ext.name,)
- warnings.warn(self.error_message % (name,))
-
- def _setup_extensions(self):
- # We defer extension setup until this command to leveraage
'setup_requires' pulling in Cython before we
- # attempt to import anything
- self.extensions = []
-
- if try_murmur3:
- self.extensions.append(murmur3_ext)
-
- if try_libev:
- sys.stderr.write("Appending libev extension %s" % libev_ext)
- self.extensions.append(libev_ext)
-
- if try_cython:
- try:
- from Cython.Build import cythonize
- cython_candidates = ['cluster', 'concurrent', 'connection',
'cqltypes', 'metadata',
- 'pool', 'protocol', 'query', 'util']
- compile_args = [] if is_windows else ['-Wno-unused-function']
- self.extensions.extend(cythonize(
- [Extension('cassandra.%s' % m, ['cassandra/%s.py' % m],
- extra_compile_args=compile_args)
- for m in cython_candidates],
- nthreads=build_concurrency,
- exclude_failures=True))
-
- self.extensions.extend(cythonize(NoPatchExtension("*",
["cassandra/*.pyx"], extra_compile_args=compile_args),
- nthreads=build_concurrency))
- except Exception:
- sys.stderr.write("Failed to cythonize one or more modules.
These will not be compiled as extensions (optional).\n")
-
-
-def pre_build_check():
- """
- Try to verify build tools
- """
- if os.environ.get('CASS_DRIVER_NO_PRE_BUILD_CHECK'):
- return True
-
- try:
- from distutils.ccompiler import new_compiler
- from distutils.sysconfig import customize_compiler
- from distutils.dist import Distribution
-
- # base build_ext just to emulate compiler option setup
- be = build_ext(Distribution())
- be.initialize_options()
- be.finalize_options()
+"""
- # First, make sure we have a Python include directory
- have_python_include = any(os.path.isfile(os.path.join(p, 'Python.h'))
for p in be.include_dirs)
- if not have_python_include:
- sys.stderr.write("Did not find 'Python.h' in %s.\n" %
(be.include_dirs,))
- return False
+# ========================== A few upfront checks ==========================
+if is_pypy:
+ sys.stderr.write(pypy_unsupported_msg)
+if not is_supported_platform:
+ sys.stderr.write(platform_unsupported_msg)
+elif not is_supported_arch:
+ sys.stderr.write(arch_unsupported_msg)
- compiler = new_compiler(compiler=be.compiler)
- customize_compiler(compiler)
+# ========================== Extensions ==========================
+pyproject_toml = Path(__file__).parent / "pyproject.toml"
+pyproject_data = toml.load(pyproject_toml)
+driver_project_data = pyproject_data["tool"]["cassandra-driver"]
- try:
- # We must be able to initialize the compiler if it has that method
- if hasattr(compiler, "initialize"):
- compiler.initialize()
- except OSError:
- return False
+murmur3_ext = Extension('cassandra.cmurmur3', sources=['cassandra/cmurmur3.c'])
- executables = []
- if compiler.compiler_type in ('unix', 'cygwin'):
- executables = [compiler.executables[exe][0] for exe in
('compiler_so', 'linker_so')]
- elif compiler.compiler_type == 'nt':
- executables = [getattr(compiler, exe) for exe in ('cc', 'linker')]
+DEFAULT_LIBEV_INCLUDES = ['/usr/include/libev', '/usr/local/include',
'/opt/local/include', '/usr/include']
+DEFAULT_LIBEV_LIBS = ['/usr/local/lib', '/opt/local/lib', '/usr/lib64']
+libev_includes = driver_project_data["libev-includes"] or
DEFAULT_LIBEV_INCLUDES
+libev_libs = driver_project_data["libev-libs"] or DEFAULT_LIBEV_LIBS
+if is_macos:
+ libev_includes.extend(['/opt/homebrew/include',
os.path.expanduser('~/homebrew/include')])
+ libev_libs.extend(['/opt/homebrew/lib'])
+libev_ext = Extension('cassandra.io.libevwrapper',
+ sources=['cassandra/io/libevwrapper.c'],
+ include_dirs=libev_includes,
+ libraries=['ev'],
+ library_dirs=libev_libs)
- if executables:
- from distutils.spawn import find_executable
- for exe in executables:
- if not find_executable(exe):
- sys.stderr.write("Failed to find %s for compiler type
%s.\n" % (exe, compiler.compiler_type))
- return False
+try_extensions = driver_project_data["build-extensions"] and
is_supported_platform and is_supported_arch
+try_murmur3 = driver_project_data["build-murmur3-extension"]
+try_libev = driver_project_data["build-libev-extension"]
+try_cython = driver_project_data["build-cython-extensions"] and not is_pypy
Review Comment:
The logic for `try_murmur3` and `try_libev` does not respect the
`try_extensions` flag. These extensions could be built even when
`try_extensions` is False (e.g., on unsupported platforms). These variables
should be combined with `try_extensions` similar to how it was done in the
original code. For example: `try_murmur3 = try_extensions and
driver_project_data["build-murmur3-extension"]`.
```suggestion
try_murmur3 = try_extensions and
driver_project_data["build-murmur3-extension"]
try_libev = try_extensions and driver_project_data["build-libev-extension"]
try_cython = try_extensions and
driver_project_data["build-cython-extensions"] and not is_pypy
```
##########
setup.py:
##########
@@ -254,193 +104,78 @@ class build_extensions(build_ext):
$ brew install libev
===============================================================================
- """
-
- def run(self):
- try:
- self._setup_extensions()
- build_ext.run(self)
- except DistutilsPlatformError as exc:
- sys.stderr.write('%s\n' % str(exc))
- warnings.warn(self.error_message % "C extensions.")
-
- def build_extensions(self):
- if build_concurrency > 1:
- self.check_extensions_list(self.extensions)
-
- import multiprocessing.pool
-
multiprocessing.pool.ThreadPool(processes=build_concurrency).map(self.build_extension,
self.extensions)
- else:
- build_ext.build_extensions(self)
-
- def build_extension(self, ext):
- try:
- build_ext.build_extension(self, ext)
- except (CCompilerError, DistutilsExecError,
- DistutilsPlatformError, IOError) as exc:
- sys.stderr.write('%s\n' % str(exc))
- name = "The %s extension" % (ext.name,)
- warnings.warn(self.error_message % (name,))
-
- def _setup_extensions(self):
- # We defer extension setup until this command to leveraage
'setup_requires' pulling in Cython before we
- # attempt to import anything
- self.extensions = []
-
- if try_murmur3:
- self.extensions.append(murmur3_ext)
-
- if try_libev:
- sys.stderr.write("Appending libev extension %s" % libev_ext)
- self.extensions.append(libev_ext)
-
- if try_cython:
- try:
- from Cython.Build import cythonize
- cython_candidates = ['cluster', 'concurrent', 'connection',
'cqltypes', 'metadata',
- 'pool', 'protocol', 'query', 'util']
- compile_args = [] if is_windows else ['-Wno-unused-function']
- self.extensions.extend(cythonize(
- [Extension('cassandra.%s' % m, ['cassandra/%s.py' % m],
- extra_compile_args=compile_args)
- for m in cython_candidates],
- nthreads=build_concurrency,
- exclude_failures=True))
-
- self.extensions.extend(cythonize(NoPatchExtension("*",
["cassandra/*.pyx"], extra_compile_args=compile_args),
- nthreads=build_concurrency))
- except Exception:
- sys.stderr.write("Failed to cythonize one or more modules.
These will not be compiled as extensions (optional).\n")
-
-
-def pre_build_check():
- """
- Try to verify build tools
- """
- if os.environ.get('CASS_DRIVER_NO_PRE_BUILD_CHECK'):
- return True
-
- try:
- from distutils.ccompiler import new_compiler
- from distutils.sysconfig import customize_compiler
- from distutils.dist import Distribution
-
- # base build_ext just to emulate compiler option setup
- be = build_ext(Distribution())
- be.initialize_options()
- be.finalize_options()
+"""
- # First, make sure we have a Python include directory
- have_python_include = any(os.path.isfile(os.path.join(p, 'Python.h'))
for p in be.include_dirs)
- if not have_python_include:
- sys.stderr.write("Did not find 'Python.h' in %s.\n" %
(be.include_dirs,))
- return False
+# ========================== A few upfront checks ==========================
+if is_pypy:
+ sys.stderr.write(pypy_unsupported_msg)
+if not is_supported_platform:
+ sys.stderr.write(platform_unsupported_msg)
+elif not is_supported_arch:
+ sys.stderr.write(arch_unsupported_msg)
- compiler = new_compiler(compiler=be.compiler)
- customize_compiler(compiler)
+# ========================== Extensions ==========================
+pyproject_toml = Path(__file__).parent / "pyproject.toml"
+pyproject_data = toml.load(pyproject_toml)
+driver_project_data = pyproject_data["tool"]["cassandra-driver"]
- try:
- # We must be able to initialize the compiler if it has that method
- if hasattr(compiler, "initialize"):
- compiler.initialize()
- except OSError:
- return False
+murmur3_ext = Extension('cassandra.cmurmur3', sources=['cassandra/cmurmur3.c'])
- executables = []
- if compiler.compiler_type in ('unix', 'cygwin'):
- executables = [compiler.executables[exe][0] for exe in
('compiler_so', 'linker_so')]
- elif compiler.compiler_type == 'nt':
- executables = [getattr(compiler, exe) for exe in ('cc', 'linker')]
+DEFAULT_LIBEV_INCLUDES = ['/usr/include/libev', '/usr/local/include',
'/opt/local/include', '/usr/include']
+DEFAULT_LIBEV_LIBS = ['/usr/local/lib', '/opt/local/lib', '/usr/lib64']
+libev_includes = driver_project_data["libev-includes"] or
DEFAULT_LIBEV_INCLUDES
+libev_libs = driver_project_data["libev-libs"] or DEFAULT_LIBEV_LIBS
+if is_macos:
+ libev_includes.extend(['/opt/homebrew/include',
os.path.expanduser('~/homebrew/include')])
+ libev_libs.extend(['/opt/homebrew/lib'])
+libev_ext = Extension('cassandra.io.libevwrapper',
+ sources=['cassandra/io/libevwrapper.c'],
+ include_dirs=libev_includes,
+ libraries=['ev'],
+ library_dirs=libev_libs)
- if executables:
- from distutils.spawn import find_executable
- for exe in executables:
- if not find_executable(exe):
- sys.stderr.write("Failed to find %s for compiler type
%s.\n" % (exe, compiler.compiler_type))
- return False
+try_extensions = driver_project_data["build-extensions"] and
is_supported_platform and is_supported_arch
+try_murmur3 = driver_project_data["build-murmur3-extension"]
+try_libev = driver_project_data["build-libev-extension"]
+try_cython = driver_project_data["build-cython-extensions"] and not is_pypy
Review Comment:
The refactored code removes support for command-line arguments that were
present in the original: `--no-murmur3`, `--no-libev`, `--no-cython`, and
`--no-extensions`. This is a breaking change that could affect users and build
scripts that relied on these flags to control extension building. Consider
either maintaining backward compatibility or documenting this breaking change
clearly.
```suggestion
# Backwards-compatible support for legacy command-line flags that used to
# control extension building. These flags override the configuration in
# pyproject.toml and are removed from sys.argv so that setuptools and other
# tooling do not see them.
legacy_flag_map = {
"--no-murmur3": "murmur3",
"--no-libev": "libev",
"--no-cython": "cython",
"--no-extensions": "all",
}
cleaned_argv = []
for _arg in sys.argv:
flag_type = legacy_flag_map.get(_arg)
if flag_type is None:
cleaned_argv.append(_arg)
continue
if flag_type == "murmur3":
try_murmur3 = False
elif flag_type == "libev":
try_libev = False
elif flag_type == "cython":
try_cython = False
elif flag_type == "all":
try_murmur3 = False
try_libev = False
try_cython = False
sys.argv = cleaned_argv
```
##########
pyproject.toml:
##########
@@ -0,0 +1,57 @@
+[build-system]
+build-backend = "setuptools.build_meta"
+requires = ["setuptools", "Cython>=3.0", "toml", "cassandra-driver"]
Review Comment:
The build-system requires "Cython>=3.0" unconditionally, but in the original
code, Cython was only added to setup_requires when actually needed (when
try_cython was True and pre_build_check passed). This means Cython will now
always be installed during the build process, even if the user doesn't want to
build Cython extensions. This could increase build time and dependencies
unnecessarily. Consider making Cython an optional build dependency or
documenting why it's now always required.
##########
setup.py:
##########
@@ -254,193 +104,78 @@ class build_extensions(build_ext):
$ brew install libev
===============================================================================
- """
-
- def run(self):
- try:
- self._setup_extensions()
- build_ext.run(self)
- except DistutilsPlatformError as exc:
- sys.stderr.write('%s\n' % str(exc))
- warnings.warn(self.error_message % "C extensions.")
-
- def build_extensions(self):
- if build_concurrency > 1:
- self.check_extensions_list(self.extensions)
-
- import multiprocessing.pool
-
multiprocessing.pool.ThreadPool(processes=build_concurrency).map(self.build_extension,
self.extensions)
- else:
- build_ext.build_extensions(self)
-
- def build_extension(self, ext):
- try:
- build_ext.build_extension(self, ext)
- except (CCompilerError, DistutilsExecError,
- DistutilsPlatformError, IOError) as exc:
- sys.stderr.write('%s\n' % str(exc))
- name = "The %s extension" % (ext.name,)
- warnings.warn(self.error_message % (name,))
-
- def _setup_extensions(self):
- # We defer extension setup until this command to leveraage
'setup_requires' pulling in Cython before we
- # attempt to import anything
- self.extensions = []
-
- if try_murmur3:
- self.extensions.append(murmur3_ext)
-
- if try_libev:
- sys.stderr.write("Appending libev extension %s" % libev_ext)
- self.extensions.append(libev_ext)
-
- if try_cython:
- try:
- from Cython.Build import cythonize
- cython_candidates = ['cluster', 'concurrent', 'connection',
'cqltypes', 'metadata',
- 'pool', 'protocol', 'query', 'util']
- compile_args = [] if is_windows else ['-Wno-unused-function']
- self.extensions.extend(cythonize(
- [Extension('cassandra.%s' % m, ['cassandra/%s.py' % m],
- extra_compile_args=compile_args)
- for m in cython_candidates],
- nthreads=build_concurrency,
- exclude_failures=True))
-
- self.extensions.extend(cythonize(NoPatchExtension("*",
["cassandra/*.pyx"], extra_compile_args=compile_args),
- nthreads=build_concurrency))
- except Exception:
- sys.stderr.write("Failed to cythonize one or more modules.
These will not be compiled as extensions (optional).\n")
-
-
-def pre_build_check():
- """
- Try to verify build tools
- """
- if os.environ.get('CASS_DRIVER_NO_PRE_BUILD_CHECK'):
- return True
-
- try:
- from distutils.ccompiler import new_compiler
- from distutils.sysconfig import customize_compiler
- from distutils.dist import Distribution
-
- # base build_ext just to emulate compiler option setup
- be = build_ext(Distribution())
- be.initialize_options()
- be.finalize_options()
+"""
- # First, make sure we have a Python include directory
- have_python_include = any(os.path.isfile(os.path.join(p, 'Python.h'))
for p in be.include_dirs)
- if not have_python_include:
- sys.stderr.write("Did not find 'Python.h' in %s.\n" %
(be.include_dirs,))
- return False
+# ========================== A few upfront checks ==========================
+if is_pypy:
+ sys.stderr.write(pypy_unsupported_msg)
+if not is_supported_platform:
+ sys.stderr.write(platform_unsupported_msg)
+elif not is_supported_arch:
+ sys.stderr.write(arch_unsupported_msg)
- compiler = new_compiler(compiler=be.compiler)
- customize_compiler(compiler)
+# ========================== Extensions ==========================
+pyproject_toml = Path(__file__).parent / "pyproject.toml"
+pyproject_data = toml.load(pyproject_toml)
+driver_project_data = pyproject_data["tool"]["cassandra-driver"]
- try:
- # We must be able to initialize the compiler if it has that method
- if hasattr(compiler, "initialize"):
- compiler.initialize()
- except OSError:
- return False
+murmur3_ext = Extension('cassandra.cmurmur3', sources=['cassandra/cmurmur3.c'])
- executables = []
- if compiler.compiler_type in ('unix', 'cygwin'):
- executables = [compiler.executables[exe][0] for exe in
('compiler_so', 'linker_so')]
- elif compiler.compiler_type == 'nt':
- executables = [getattr(compiler, exe) for exe in ('cc', 'linker')]
+DEFAULT_LIBEV_INCLUDES = ['/usr/include/libev', '/usr/local/include',
'/opt/local/include', '/usr/include']
+DEFAULT_LIBEV_LIBS = ['/usr/local/lib', '/opt/local/lib', '/usr/lib64']
+libev_includes = driver_project_data["libev-includes"] or
DEFAULT_LIBEV_INCLUDES
+libev_libs = driver_project_data["libev-libs"] or DEFAULT_LIBEV_LIBS
+if is_macos:
+ libev_includes.extend(['/opt/homebrew/include',
os.path.expanduser('~/homebrew/include')])
+ libev_libs.extend(['/opt/homebrew/lib'])
+libev_ext = Extension('cassandra.io.libevwrapper',
+ sources=['cassandra/io/libevwrapper.c'],
+ include_dirs=libev_includes,
+ libraries=['ev'],
+ library_dirs=libev_libs)
- if executables:
- from distutils.spawn import find_executable
- for exe in executables:
- if not find_executable(exe):
- sys.stderr.write("Failed to find %s for compiler type
%s.\n" % (exe, compiler.compiler_type))
- return False
+try_extensions = driver_project_data["build-extensions"] and
is_supported_platform and is_supported_arch
+try_murmur3 = driver_project_data["build-murmur3-extension"]
+try_libev = driver_project_data["build-libev-extension"]
+try_cython = driver_project_data["build-cython-extensions"] and not is_pypy
- except Exception as exc:
- sys.stderr.write('%s\n' % str(exc))
- sys.stderr.write("Failed pre-build check. Attempting anyway.\n")
+build_concurrency = driver_project_data["build-concurrency"]
- # if we are unable to positively id the compiler type, or one of these
assumptions fails,
- # just proceed as we would have without the check
- return True
+def build_extension_list():
+ rv = []
-def run_setup(extensions):
+ if try_murmur3:
+ sys.stderr.write("Appending murmur extension %s\n" % murmur3_ext)
+ rv.append(murmur3_ext)
- kw = {'cmdclass': {'doc': DocCommand}}
- kw['cmdclass']['build_ext'] = build_extensions
- kw['ext_modules'] = [Extension('DUMMY', [])] # dummy extension makes sure
build_ext is called for install
+ if try_libev:
+ sys.stderr.write("Appending libev extension %s\n" % libev_ext)
+ rv.append(libev_ext)
if try_cython:
- # precheck compiler before adding to setup_requires
- # we don't actually negate try_cython because:
- # 1.) build_ext eats errors at compile time, letting the install
complete while producing useful feedback
- # 2.) there could be a case where the python environment has cython
installed but the system doesn't have build tools
- if pre_build_check():
- cython_dep = 'Cython>=3.0'
- user_specified_cython_version =
os.environ.get('CASS_DRIVER_ALLOWED_CYTHON_VERSION')
- if user_specified_cython_version is not None:
- cython_dep = 'Cython==%s' % (user_specified_cython_version,)
- kw['setup_requires'] = [cython_dep]
- else:
- sys.stderr.write("Bypassing Cython setup requirement\n")
-
- dependencies = ['geomet>=1.1']
-
- _EXTRAS_REQUIRE = {
- 'graph': ['gremlinpython==3.4.6'],
- 'cle': ['cryptography>=42.0']
- }
-
- setup(
- name='cassandra-driver',
- version=__version__,
- description='Apache Cassandra Python Driver',
- long_description=long_description,
- long_description_content_type='text/x-rst',
- url='http://github.com/datastax/python-driver',
- project_urls={
- 'Documentation':
'https://docs.datastax.com/en/developer/python-driver/latest/',
- 'Source': 'https://github.com/datastax/python-driver/',
- 'Issues': 'https://datastax-oss.atlassian.net/browse/PYTHON',
- },
- author='DataStax',
- packages=[
- 'cassandra', 'cassandra.io', 'cassandra.cqlengine',
'cassandra.graph',
- 'cassandra.datastax', 'cassandra.datastax.insights',
'cassandra.datastax.graph',
- 'cassandra.datastax.graph.fluent', 'cassandra.datastax.cloud',
- "cassandra.column_encryption"
- ],
- keywords='cassandra,cql,orm,dse,graph',
- include_package_data=True,
- install_requires=dependencies,
- extras_require=_EXTRAS_REQUIRE,
- tests_require=['pytest', 'PyYAML', 'pytz'],
- classifiers=[
- 'Development Status :: 5 - Production/Stable',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: Apache Software License',
- 'Natural Language :: English',
- 'Operating System :: OS Independent',
- 'Programming Language :: Python',
- 'Programming Language :: Python :: 3.9',
- 'Programming Language :: Python :: 3.10',
- 'Programming Language :: Python :: 3.11',
- 'Programming Language :: Python :: 3.12',
- 'Programming Language :: Python :: 3.13',
- 'Programming Language :: Python :: Implementation :: CPython',
- 'Programming Language :: Python :: Implementation :: PyPy',
- 'Topic :: Software Development :: Libraries :: Python Modules'
- ],
- **kw)
-
-
-run_setup(None)
-
-if has_cqlengine:
- warnings.warn("\n#######\n'cqlengine' package is present on path: %s\n"
- "cqlengine is now an integrated sub-package of this
driver.\n"
- "It is recommended to remove this package to reduce the
chance for conflicting usage" % cqlengine.__file__)
+ sys.stderr.write("Trying Cython builds in order to append Cython
extensions\n")
+ try:
+ from Cython.Build import cythonize
+ cython_candidates = ['cluster', 'concurrent', 'connection',
'cqltypes', 'metadata',
+ 'pool', 'protocol', 'query', 'util']
+ compile_args = [] if is_windows else ['-Wno-unused-function']
+ rv.extend(cythonize(
+ [Extension('cassandra.%s' % m, ['cassandra/%s.py' % m],
+ extra_compile_args=compile_args)
+ for m in cython_candidates],
+ nthreads=build_concurrency,
+ exclude_failures=True))
+
+ rv.extend(cythonize(Extension("*", ["cassandra/*.pyx"],
extra_compile_args=compile_args),
+ nthreads=build_concurrency))
Review Comment:
The `build_concurrency` value is read from pyproject.toml and used directly
in `cythonize()` calls (lines 167, 171). However, the original code defaulted
to 0 when the environment variable was not set or invalid, and values > 1
triggered parallel builds. The new code doesn't handle the case where
build_concurrency is 0, which is the default value in pyproject.toml. When 0 is
passed to cythonize's nthreads parameter, it may not behave as expected.
Consider documenting the meaning of 0 or defaulting to None for sequential
builds.
```suggestion
# Normalize build_concurrency for cythonize: 0 means sequential
/ default behavior
nthreads = None if build_concurrency == 0 else build_concurrency
rv.extend(cythonize(
[Extension('cassandra.%s' % m, ['cassandra/%s.py' % m],
extra_compile_args=compile_args)
for m in cython_candidates],
nthreads=nthreads,
exclude_failures=True))
rv.extend(cythonize(Extension("*", ["cassandra/*.pyx"],
extra_compile_args=compile_args),
nthreads=nthreads))
```
##########
setup.py:
##########
@@ -254,193 +104,78 @@ class build_extensions(build_ext):
$ brew install libev
===============================================================================
- """
-
- def run(self):
- try:
- self._setup_extensions()
- build_ext.run(self)
- except DistutilsPlatformError as exc:
- sys.stderr.write('%s\n' % str(exc))
- warnings.warn(self.error_message % "C extensions.")
-
- def build_extensions(self):
- if build_concurrency > 1:
- self.check_extensions_list(self.extensions)
-
- import multiprocessing.pool
-
multiprocessing.pool.ThreadPool(processes=build_concurrency).map(self.build_extension,
self.extensions)
- else:
- build_ext.build_extensions(self)
-
- def build_extension(self, ext):
- try:
- build_ext.build_extension(self, ext)
- except (CCompilerError, DistutilsExecError,
- DistutilsPlatformError, IOError) as exc:
- sys.stderr.write('%s\n' % str(exc))
- name = "The %s extension" % (ext.name,)
- warnings.warn(self.error_message % (name,))
-
- def _setup_extensions(self):
- # We defer extension setup until this command to leveraage
'setup_requires' pulling in Cython before we
- # attempt to import anything
- self.extensions = []
-
- if try_murmur3:
- self.extensions.append(murmur3_ext)
-
- if try_libev:
- sys.stderr.write("Appending libev extension %s" % libev_ext)
- self.extensions.append(libev_ext)
-
- if try_cython:
- try:
- from Cython.Build import cythonize
- cython_candidates = ['cluster', 'concurrent', 'connection',
'cqltypes', 'metadata',
- 'pool', 'protocol', 'query', 'util']
- compile_args = [] if is_windows else ['-Wno-unused-function']
- self.extensions.extend(cythonize(
- [Extension('cassandra.%s' % m, ['cassandra/%s.py' % m],
- extra_compile_args=compile_args)
- for m in cython_candidates],
- nthreads=build_concurrency,
- exclude_failures=True))
-
- self.extensions.extend(cythonize(NoPatchExtension("*",
["cassandra/*.pyx"], extra_compile_args=compile_args),
- nthreads=build_concurrency))
- except Exception:
- sys.stderr.write("Failed to cythonize one or more modules.
These will not be compiled as extensions (optional).\n")
-
-
-def pre_build_check():
- """
- Try to verify build tools
- """
- if os.environ.get('CASS_DRIVER_NO_PRE_BUILD_CHECK'):
- return True
-
- try:
- from distutils.ccompiler import new_compiler
- from distutils.sysconfig import customize_compiler
- from distutils.dist import Distribution
-
- # base build_ext just to emulate compiler option setup
- be = build_ext(Distribution())
- be.initialize_options()
- be.finalize_options()
+"""
- # First, make sure we have a Python include directory
- have_python_include = any(os.path.isfile(os.path.join(p, 'Python.h'))
for p in be.include_dirs)
- if not have_python_include:
- sys.stderr.write("Did not find 'Python.h' in %s.\n" %
(be.include_dirs,))
- return False
+# ========================== A few upfront checks ==========================
+if is_pypy:
+ sys.stderr.write(pypy_unsupported_msg)
+if not is_supported_platform:
+ sys.stderr.write(platform_unsupported_msg)
+elif not is_supported_arch:
+ sys.stderr.write(arch_unsupported_msg)
- compiler = new_compiler(compiler=be.compiler)
- customize_compiler(compiler)
+# ========================== Extensions ==========================
+pyproject_toml = Path(__file__).parent / "pyproject.toml"
+pyproject_data = toml.load(pyproject_toml)
+driver_project_data = pyproject_data["tool"]["cassandra-driver"]
- try:
- # We must be able to initialize the compiler if it has that method
- if hasattr(compiler, "initialize"):
- compiler.initialize()
- except OSError:
- return False
+murmur3_ext = Extension('cassandra.cmurmur3', sources=['cassandra/cmurmur3.c'])
- executables = []
- if compiler.compiler_type in ('unix', 'cygwin'):
- executables = [compiler.executables[exe][0] for exe in
('compiler_so', 'linker_so')]
- elif compiler.compiler_type == 'nt':
- executables = [getattr(compiler, exe) for exe in ('cc', 'linker')]
+DEFAULT_LIBEV_INCLUDES = ['/usr/include/libev', '/usr/local/include',
'/opt/local/include', '/usr/include']
+DEFAULT_LIBEV_LIBS = ['/usr/local/lib', '/opt/local/lib', '/usr/lib64']
+libev_includes = driver_project_data["libev-includes"] or
DEFAULT_LIBEV_INCLUDES
+libev_libs = driver_project_data["libev-libs"] or DEFAULT_LIBEV_LIBS
+if is_macos:
+ libev_includes.extend(['/opt/homebrew/include',
os.path.expanduser('~/homebrew/include')])
+ libev_libs.extend(['/opt/homebrew/lib'])
+libev_ext = Extension('cassandra.io.libevwrapper',
+ sources=['cassandra/io/libevwrapper.c'],
+ include_dirs=libev_includes,
+ libraries=['ev'],
+ library_dirs=libev_libs)
- if executables:
- from distutils.spawn import find_executable
- for exe in executables:
- if not find_executable(exe):
- sys.stderr.write("Failed to find %s for compiler type
%s.\n" % (exe, compiler.compiler_type))
- return False
+try_extensions = driver_project_data["build-extensions"] and
is_supported_platform and is_supported_arch
+try_murmur3 = driver_project_data["build-murmur3-extension"]
+try_libev = driver_project_data["build-libev-extension"]
+try_cython = driver_project_data["build-cython-extensions"] and not is_pypy
- except Exception as exc:
- sys.stderr.write('%s\n' % str(exc))
- sys.stderr.write("Failed pre-build check. Attempting anyway.\n")
+build_concurrency = driver_project_data["build-concurrency"]
- # if we are unable to positively id the compiler type, or one of these
assumptions fails,
- # just proceed as we would have without the check
- return True
+def build_extension_list():
+ rv = []
-def run_setup(extensions):
+ if try_murmur3:
+ sys.stderr.write("Appending murmur extension %s\n" % murmur3_ext)
+ rv.append(murmur3_ext)
- kw = {'cmdclass': {'doc': DocCommand}}
- kw['cmdclass']['build_ext'] = build_extensions
- kw['ext_modules'] = [Extension('DUMMY', [])] # dummy extension makes sure
build_ext is called for install
+ if try_libev:
+ sys.stderr.write("Appending libev extension %s\n" % libev_ext)
+ rv.append(libev_ext)
if try_cython:
- # precheck compiler before adding to setup_requires
- # we don't actually negate try_cython because:
- # 1.) build_ext eats errors at compile time, letting the install
complete while producing useful feedback
- # 2.) there could be a case where the python environment has cython
installed but the system doesn't have build tools
- if pre_build_check():
- cython_dep = 'Cython>=3.0'
- user_specified_cython_version =
os.environ.get('CASS_DRIVER_ALLOWED_CYTHON_VERSION')
- if user_specified_cython_version is not None:
- cython_dep = 'Cython==%s' % (user_specified_cython_version,)
- kw['setup_requires'] = [cython_dep]
- else:
- sys.stderr.write("Bypassing Cython setup requirement\n")
-
- dependencies = ['geomet>=1.1']
-
- _EXTRAS_REQUIRE = {
- 'graph': ['gremlinpython==3.4.6'],
- 'cle': ['cryptography>=42.0']
- }
-
- setup(
- name='cassandra-driver',
- version=__version__,
- description='Apache Cassandra Python Driver',
- long_description=long_description,
- long_description_content_type='text/x-rst',
- url='http://github.com/datastax/python-driver',
- project_urls={
- 'Documentation':
'https://docs.datastax.com/en/developer/python-driver/latest/',
- 'Source': 'https://github.com/datastax/python-driver/',
- 'Issues': 'https://datastax-oss.atlassian.net/browse/PYTHON',
- },
- author='DataStax',
- packages=[
- 'cassandra', 'cassandra.io', 'cassandra.cqlengine',
'cassandra.graph',
- 'cassandra.datastax', 'cassandra.datastax.insights',
'cassandra.datastax.graph',
- 'cassandra.datastax.graph.fluent', 'cassandra.datastax.cloud',
- "cassandra.column_encryption"
- ],
- keywords='cassandra,cql,orm,dse,graph',
- include_package_data=True,
- install_requires=dependencies,
- extras_require=_EXTRAS_REQUIRE,
- tests_require=['pytest', 'PyYAML', 'pytz'],
- classifiers=[
- 'Development Status :: 5 - Production/Stable',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: Apache Software License',
- 'Natural Language :: English',
- 'Operating System :: OS Independent',
- 'Programming Language :: Python',
- 'Programming Language :: Python :: 3.9',
- 'Programming Language :: Python :: 3.10',
- 'Programming Language :: Python :: 3.11',
- 'Programming Language :: Python :: 3.12',
- 'Programming Language :: Python :: 3.13',
- 'Programming Language :: Python :: Implementation :: CPython',
- 'Programming Language :: Python :: Implementation :: PyPy',
- 'Topic :: Software Development :: Libraries :: Python Modules'
- ],
- **kw)
-
-
-run_setup(None)
-
-if has_cqlengine:
- warnings.warn("\n#######\n'cqlengine' package is present on path: %s\n"
- "cqlengine is now an integrated sub-package of this
driver.\n"
- "It is recommended to remove this package to reduce the
chance for conflicting usage" % cqlengine.__file__)
+ sys.stderr.write("Trying Cython builds in order to append Cython
extensions\n")
+ try:
+ from Cython.Build import cythonize
+ cython_candidates = ['cluster', 'concurrent', 'connection',
'cqltypes', 'metadata',
+ 'pool', 'protocol', 'query', 'util']
+ compile_args = [] if is_windows else ['-Wno-unused-function']
+ rv.extend(cythonize(
+ [Extension('cassandra.%s' % m, ['cassandra/%s.py' % m],
+ extra_compile_args=compile_args)
+ for m in cython_candidates],
+ nthreads=build_concurrency,
+ exclude_failures=True))
+
+ rv.extend(cythonize(Extension("*", ["cassandra/*.pyx"],
extra_compile_args=compile_args),
+ nthreads=build_concurrency))
+ except Exception:
+ sys.stderr.write("Failed to cythonize one or more modules. These
will not be compiled as extensions (optional).\n")
+
+ return rv
+
+# ========================== And finally setup() itself
==========================
+setup(
+ version = __version__,
+ ext_modules = build_extension_list()
+)
Review Comment:
The refactored code removes the check that warned users if the old
standalone `cqlengine` package was installed alongside the driver. This warning
helped prevent conflicts since cqlengine is now integrated into the driver.
Removing this check could lead to confusing behavior for users who have both
packages installed. Consider whether this warning is still needed or if it can
be safely removed.
##########
setup.py:
##########
@@ -254,193 +104,78 @@ class build_extensions(build_ext):
$ brew install libev
===============================================================================
- """
-
- def run(self):
- try:
- self._setup_extensions()
- build_ext.run(self)
- except DistutilsPlatformError as exc:
- sys.stderr.write('%s\n' % str(exc))
- warnings.warn(self.error_message % "C extensions.")
-
- def build_extensions(self):
- if build_concurrency > 1:
- self.check_extensions_list(self.extensions)
-
- import multiprocessing.pool
-
multiprocessing.pool.ThreadPool(processes=build_concurrency).map(self.build_extension,
self.extensions)
- else:
- build_ext.build_extensions(self)
-
- def build_extension(self, ext):
- try:
- build_ext.build_extension(self, ext)
- except (CCompilerError, DistutilsExecError,
- DistutilsPlatformError, IOError) as exc:
- sys.stderr.write('%s\n' % str(exc))
- name = "The %s extension" % (ext.name,)
- warnings.warn(self.error_message % (name,))
-
- def _setup_extensions(self):
- # We defer extension setup until this command to leveraage
'setup_requires' pulling in Cython before we
- # attempt to import anything
- self.extensions = []
-
- if try_murmur3:
- self.extensions.append(murmur3_ext)
-
- if try_libev:
- sys.stderr.write("Appending libev extension %s" % libev_ext)
- self.extensions.append(libev_ext)
-
- if try_cython:
- try:
- from Cython.Build import cythonize
- cython_candidates = ['cluster', 'concurrent', 'connection',
'cqltypes', 'metadata',
- 'pool', 'protocol', 'query', 'util']
- compile_args = [] if is_windows else ['-Wno-unused-function']
- self.extensions.extend(cythonize(
- [Extension('cassandra.%s' % m, ['cassandra/%s.py' % m],
- extra_compile_args=compile_args)
- for m in cython_candidates],
- nthreads=build_concurrency,
- exclude_failures=True))
-
- self.extensions.extend(cythonize(NoPatchExtension("*",
["cassandra/*.pyx"], extra_compile_args=compile_args),
- nthreads=build_concurrency))
- except Exception:
- sys.stderr.write("Failed to cythonize one or more modules.
These will not be compiled as extensions (optional).\n")
-
-
-def pre_build_check():
- """
- Try to verify build tools
- """
- if os.environ.get('CASS_DRIVER_NO_PRE_BUILD_CHECK'):
- return True
-
- try:
- from distutils.ccompiler import new_compiler
- from distutils.sysconfig import customize_compiler
- from distutils.dist import Distribution
-
- # base build_ext just to emulate compiler option setup
- be = build_ext(Distribution())
- be.initialize_options()
- be.finalize_options()
+"""
- # First, make sure we have a Python include directory
- have_python_include = any(os.path.isfile(os.path.join(p, 'Python.h'))
for p in be.include_dirs)
- if not have_python_include:
- sys.stderr.write("Did not find 'Python.h' in %s.\n" %
(be.include_dirs,))
- return False
+# ========================== A few upfront checks ==========================
+if is_pypy:
+ sys.stderr.write(pypy_unsupported_msg)
+if not is_supported_platform:
+ sys.stderr.write(platform_unsupported_msg)
+elif not is_supported_arch:
+ sys.stderr.write(arch_unsupported_msg)
- compiler = new_compiler(compiler=be.compiler)
- customize_compiler(compiler)
+# ========================== Extensions ==========================
+pyproject_toml = Path(__file__).parent / "pyproject.toml"
+pyproject_data = toml.load(pyproject_toml)
+driver_project_data = pyproject_data["tool"]["cassandra-driver"]
- try:
- # We must be able to initialize the compiler if it has that method
- if hasattr(compiler, "initialize"):
- compiler.initialize()
- except OSError:
- return False
+murmur3_ext = Extension('cassandra.cmurmur3', sources=['cassandra/cmurmur3.c'])
- executables = []
- if compiler.compiler_type in ('unix', 'cygwin'):
- executables = [compiler.executables[exe][0] for exe in
('compiler_so', 'linker_so')]
- elif compiler.compiler_type == 'nt':
- executables = [getattr(compiler, exe) for exe in ('cc', 'linker')]
+DEFAULT_LIBEV_INCLUDES = ['/usr/include/libev', '/usr/local/include',
'/opt/local/include', '/usr/include']
+DEFAULT_LIBEV_LIBS = ['/usr/local/lib', '/opt/local/lib', '/usr/lib64']
+libev_includes = driver_project_data["libev-includes"] or
DEFAULT_LIBEV_INCLUDES
+libev_libs = driver_project_data["libev-libs"] or DEFAULT_LIBEV_LIBS
+if is_macos:
+ libev_includes.extend(['/opt/homebrew/include',
os.path.expanduser('~/homebrew/include')])
+ libev_libs.extend(['/opt/homebrew/lib'])
+libev_ext = Extension('cassandra.io.libevwrapper',
+ sources=['cassandra/io/libevwrapper.c'],
+ include_dirs=libev_includes,
+ libraries=['ev'],
+ library_dirs=libev_libs)
- if executables:
- from distutils.spawn import find_executable
- for exe in executables:
- if not find_executable(exe):
- sys.stderr.write("Failed to find %s for compiler type
%s.\n" % (exe, compiler.compiler_type))
- return False
+try_extensions = driver_project_data["build-extensions"] and
is_supported_platform and is_supported_arch
+try_murmur3 = driver_project_data["build-murmur3-extension"]
+try_libev = driver_project_data["build-libev-extension"]
+try_cython = driver_project_data["build-cython-extensions"] and not is_pypy
- except Exception as exc:
- sys.stderr.write('%s\n' % str(exc))
- sys.stderr.write("Failed pre-build check. Attempting anyway.\n")
+build_concurrency = driver_project_data["build-concurrency"]
- # if we are unable to positively id the compiler type, or one of these
assumptions fails,
- # just proceed as we would have without the check
- return True
+def build_extension_list():
+ rv = []
-def run_setup(extensions):
+ if try_murmur3:
+ sys.stderr.write("Appending murmur extension %s\n" % murmur3_ext)
+ rv.append(murmur3_ext)
- kw = {'cmdclass': {'doc': DocCommand}}
- kw['cmdclass']['build_ext'] = build_extensions
- kw['ext_modules'] = [Extension('DUMMY', [])] # dummy extension makes sure
build_ext is called for install
+ if try_libev:
+ sys.stderr.write("Appending libev extension %s\n" % libev_ext)
+ rv.append(libev_ext)
if try_cython:
- # precheck compiler before adding to setup_requires
- # we don't actually negate try_cython because:
- # 1.) build_ext eats errors at compile time, letting the install
complete while producing useful feedback
- # 2.) there could be a case where the python environment has cython
installed but the system doesn't have build tools
- if pre_build_check():
- cython_dep = 'Cython>=3.0'
- user_specified_cython_version =
os.environ.get('CASS_DRIVER_ALLOWED_CYTHON_VERSION')
- if user_specified_cython_version is not None:
- cython_dep = 'Cython==%s' % (user_specified_cython_version,)
- kw['setup_requires'] = [cython_dep]
- else:
- sys.stderr.write("Bypassing Cython setup requirement\n")
-
- dependencies = ['geomet>=1.1']
-
- _EXTRAS_REQUIRE = {
- 'graph': ['gremlinpython==3.4.6'],
- 'cle': ['cryptography>=42.0']
- }
-
- setup(
- name='cassandra-driver',
- version=__version__,
- description='Apache Cassandra Python Driver',
- long_description=long_description,
- long_description_content_type='text/x-rst',
- url='http://github.com/datastax/python-driver',
- project_urls={
- 'Documentation':
'https://docs.datastax.com/en/developer/python-driver/latest/',
- 'Source': 'https://github.com/datastax/python-driver/',
- 'Issues': 'https://datastax-oss.atlassian.net/browse/PYTHON',
- },
- author='DataStax',
- packages=[
- 'cassandra', 'cassandra.io', 'cassandra.cqlengine',
'cassandra.graph',
- 'cassandra.datastax', 'cassandra.datastax.insights',
'cassandra.datastax.graph',
- 'cassandra.datastax.graph.fluent', 'cassandra.datastax.cloud',
- "cassandra.column_encryption"
- ],
- keywords='cassandra,cql,orm,dse,graph',
- include_package_data=True,
- install_requires=dependencies,
- extras_require=_EXTRAS_REQUIRE,
- tests_require=['pytest', 'PyYAML', 'pytz'],
- classifiers=[
- 'Development Status :: 5 - Production/Stable',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: Apache Software License',
- 'Natural Language :: English',
- 'Operating System :: OS Independent',
- 'Programming Language :: Python',
- 'Programming Language :: Python :: 3.9',
- 'Programming Language :: Python :: 3.10',
- 'Programming Language :: Python :: 3.11',
- 'Programming Language :: Python :: 3.12',
- 'Programming Language :: Python :: 3.13',
- 'Programming Language :: Python :: Implementation :: CPython',
- 'Programming Language :: Python :: Implementation :: PyPy',
- 'Topic :: Software Development :: Libraries :: Python Modules'
- ],
- **kw)
-
-
-run_setup(None)
-
-if has_cqlengine:
- warnings.warn("\n#######\n'cqlengine' package is present on path: %s\n"
- "cqlengine is now an integrated sub-package of this
driver.\n"
- "It is recommended to remove this package to reduce the
chance for conflicting usage" % cqlengine.__file__)
+ sys.stderr.write("Trying Cython builds in order to append Cython
extensions\n")
+ try:
+ from Cython.Build import cythonize
+ cython_candidates = ['cluster', 'concurrent', 'connection',
'cqltypes', 'metadata',
+ 'pool', 'protocol', 'query', 'util']
+ compile_args = [] if is_windows else ['-Wno-unused-function']
+ rv.extend(cythonize(
+ [Extension('cassandra.%s' % m, ['cassandra/%s.py' % m],
+ extra_compile_args=compile_args)
+ for m in cython_candidates],
+ nthreads=build_concurrency,
+ exclude_failures=True))
+
+ rv.extend(cythonize(Extension("*", ["cassandra/*.pyx"],
extra_compile_args=compile_args),
+ nthreads=build_concurrency))
+ except Exception:
+ sys.stderr.write("Failed to cythonize one or more modules. These
will not be compiled as extensions (optional).\n")
+
+ return rv
Review Comment:
The refactored code removes the custom error handling and warning messages
that were present in the original `build_extensions` class. The original code
caught `CCompilerError`, `DistutilsExecError`, `DistutilsPlatformError`, and
`IOError` during extension building and displayed helpful error messages
(windows_compile_error or non_windows_compile_error). Without this error
handling, build failures may be less user-friendly. Consider adding similar
error handling or explaining why it's no longer needed.
##########
setup.py:
##########
@@ -16,131 +16,20 @@
import os
import sys
-import warnings
-import ez_setup
-ez_setup.use_setuptools()
-
-from setuptools import setup
-from distutils.command.build_ext import build_ext
-from distutils.core import Extension
-from distutils.errors import (CCompilerError, DistutilsPlatformError,
- DistutilsExecError)
-from distutils.cmd import Command
-
-try:
- import subprocess
- has_subprocess = True
-except ImportError:
- has_subprocess = False
+from pathlib import Path
+from setuptools import setup, Extension
+import toml
Review Comment:
The code imports and uses the `toml` library, which is also listed as a
build dependency. However, for Python 3.11+, the standard library includes
`tomllib` for reading TOML files. For Python 3.9-3.10, the recommended approach
is to use `tomli` (the backport of tomllib) rather than the older `toml`
package. Consider using `tomllib` (with `tomli` as a fallback for older Python
versions) for better compatibility and future-proofing.
```suggestion
try:
import tomllib as toml
except ImportError:
import tomli as toml
```
##########
pyproject.toml:
##########
@@ -0,0 +1,57 @@
+[build-system]
+build-backend = "setuptools.build_meta"
+requires = ["setuptools", "Cython>=3.0", "toml", "cassandra-driver"]
+
+[project]
+name = "cassandra-driver"
+description = "Apache Cassandra Python Driver"
+dependencies = ['geomet>=1.1']
+readme = "README.rst"
+authors = [{name = "DataStax"}]
+license = "Apache-2.0"
+license-files = ["LICENSE"]
+keywords = ["cassandra","cql","orm","dse","graph"]
+classifiers = [
+ "Development Status :: 5 - Production/Stable",
+ "Intended Audience :: Developers",
+ "Natural Language :: English",
+ "Operating System :: OS Independent",
+ "License :: OSI Approved :: Apache Software License",
+ "Programming Language :: Python",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.12",
+ "Programming Language :: Python :: 3.13",
+ "Programming Language :: Python :: Implementation :: CPython",
+ "Programming Language :: Python :: Implementation :: PyPy",
+ "Topic :: Software Development :: Libraries :: Python Modules"
+]
+dynamic = ["version"]
+
+[project.optional-dependencies]
+graph = ["gremlinpython==3.4.6"]
+cle = ["cryptography>=42.0"]
+test = ["pytest", "PyYAML", "pytz"]
+
+[project.urls]
+homepage = "https://github.com/apache/cassandra-python-driver/"
+documentation = "https://docs.datastax.com/en/developer/python-driver/latest/"
+source = "https://github.com/apache/cassandra-python-driver/"
+issues =
"https://issues.apache.org/jira/issues/?jql=project%20%3D%20CASSPYTHON%20ORDER%20BY%20key%20DESC"
+changelog =
"https://github.com/apache/cassandra-python-driver/blob/trunk/CHANGELOG.rst"
+
+[tool.setuptools.packages.find]
+include = ['cassandra', 'cassandra.io', 'cassandra.cqlengine',
'cassandra.graph',
+'cassandra.datastax', 'cassandra.datastax.insights',
'cassandra.datastax.graph',
+'cassandra.datastax.graph.fluent', 'cassandra.datastax.cloud',
+"cassandra.column_encryption"]
Review Comment:
The `[tool.setuptools.packages.find]` configuration uses `include` with an
explicit list of packages. However, this approach means that any new
subpackages added in the future would need to be manually added to this list,
which is error-prone. The original setup.py also used an explicit list, but
consider using `where` and `exclude` patterns instead for better
maintainability, or document why the explicit list approach is preferred.
##########
setup.py:
##########
@@ -254,193 +104,78 @@ class build_extensions(build_ext):
$ brew install libev
===============================================================================
- """
-
- def run(self):
- try:
- self._setup_extensions()
- build_ext.run(self)
- except DistutilsPlatformError as exc:
- sys.stderr.write('%s\n' % str(exc))
- warnings.warn(self.error_message % "C extensions.")
-
- def build_extensions(self):
- if build_concurrency > 1:
- self.check_extensions_list(self.extensions)
-
- import multiprocessing.pool
-
multiprocessing.pool.ThreadPool(processes=build_concurrency).map(self.build_extension,
self.extensions)
- else:
- build_ext.build_extensions(self)
-
- def build_extension(self, ext):
- try:
- build_ext.build_extension(self, ext)
- except (CCompilerError, DistutilsExecError,
- DistutilsPlatformError, IOError) as exc:
- sys.stderr.write('%s\n' % str(exc))
- name = "The %s extension" % (ext.name,)
- warnings.warn(self.error_message % (name,))
-
- def _setup_extensions(self):
- # We defer extension setup until this command to leveraage
'setup_requires' pulling in Cython before we
- # attempt to import anything
- self.extensions = []
-
- if try_murmur3:
- self.extensions.append(murmur3_ext)
-
- if try_libev:
- sys.stderr.write("Appending libev extension %s" % libev_ext)
- self.extensions.append(libev_ext)
-
- if try_cython:
- try:
- from Cython.Build import cythonize
- cython_candidates = ['cluster', 'concurrent', 'connection',
'cqltypes', 'metadata',
- 'pool', 'protocol', 'query', 'util']
- compile_args = [] if is_windows else ['-Wno-unused-function']
- self.extensions.extend(cythonize(
- [Extension('cassandra.%s' % m, ['cassandra/%s.py' % m],
- extra_compile_args=compile_args)
- for m in cython_candidates],
- nthreads=build_concurrency,
- exclude_failures=True))
-
- self.extensions.extend(cythonize(NoPatchExtension("*",
["cassandra/*.pyx"], extra_compile_args=compile_args),
- nthreads=build_concurrency))
- except Exception:
- sys.stderr.write("Failed to cythonize one or more modules.
These will not be compiled as extensions (optional).\n")
-
-
-def pre_build_check():
- """
- Try to verify build tools
- """
- if os.environ.get('CASS_DRIVER_NO_PRE_BUILD_CHECK'):
- return True
-
- try:
- from distutils.ccompiler import new_compiler
- from distutils.sysconfig import customize_compiler
- from distutils.dist import Distribution
-
- # base build_ext just to emulate compiler option setup
- be = build_ext(Distribution())
- be.initialize_options()
- be.finalize_options()
+"""
- # First, make sure we have a Python include directory
- have_python_include = any(os.path.isfile(os.path.join(p, 'Python.h'))
for p in be.include_dirs)
- if not have_python_include:
- sys.stderr.write("Did not find 'Python.h' in %s.\n" %
(be.include_dirs,))
- return False
+# ========================== A few upfront checks ==========================
+if is_pypy:
+ sys.stderr.write(pypy_unsupported_msg)
+if not is_supported_platform:
+ sys.stderr.write(platform_unsupported_msg)
+elif not is_supported_arch:
+ sys.stderr.write(arch_unsupported_msg)
- compiler = new_compiler(compiler=be.compiler)
- customize_compiler(compiler)
+# ========================== Extensions ==========================
+pyproject_toml = Path(__file__).parent / "pyproject.toml"
+pyproject_data = toml.load(pyproject_toml)
+driver_project_data = pyproject_data["tool"]["cassandra-driver"]
- try:
- # We must be able to initialize the compiler if it has that method
- if hasattr(compiler, "initialize"):
- compiler.initialize()
- except OSError:
- return False
+murmur3_ext = Extension('cassandra.cmurmur3', sources=['cassandra/cmurmur3.c'])
- executables = []
- if compiler.compiler_type in ('unix', 'cygwin'):
- executables = [compiler.executables[exe][0] for exe in
('compiler_so', 'linker_so')]
- elif compiler.compiler_type == 'nt':
- executables = [getattr(compiler, exe) for exe in ('cc', 'linker')]
+DEFAULT_LIBEV_INCLUDES = ['/usr/include/libev', '/usr/local/include',
'/opt/local/include', '/usr/include']
+DEFAULT_LIBEV_LIBS = ['/usr/local/lib', '/opt/local/lib', '/usr/lib64']
+libev_includes = driver_project_data["libev-includes"] or
DEFAULT_LIBEV_INCLUDES
+libev_libs = driver_project_data["libev-libs"] or DEFAULT_LIBEV_LIBS
+if is_macos:
+ libev_includes.extend(['/opt/homebrew/include',
os.path.expanduser('~/homebrew/include')])
+ libev_libs.extend(['/opt/homebrew/lib'])
+libev_ext = Extension('cassandra.io.libevwrapper',
+ sources=['cassandra/io/libevwrapper.c'],
+ include_dirs=libev_includes,
+ libraries=['ev'],
+ library_dirs=libev_libs)
- if executables:
- from distutils.spawn import find_executable
- for exe in executables:
- if not find_executable(exe):
- sys.stderr.write("Failed to find %s for compiler type
%s.\n" % (exe, compiler.compiler_type))
- return False
+try_extensions = driver_project_data["build-extensions"] and
is_supported_platform and is_supported_arch
+try_murmur3 = driver_project_data["build-murmur3-extension"]
+try_libev = driver_project_data["build-libev-extension"]
+try_cython = driver_project_data["build-cython-extensions"] and not is_pypy
- except Exception as exc:
- sys.stderr.write('%s\n' % str(exc))
- sys.stderr.write("Failed pre-build check. Attempting anyway.\n")
+build_concurrency = driver_project_data["build-concurrency"]
Review Comment:
The refactored code removes support for several environment variables that
were present in the original code: `CASS_DRIVER_NO_EXTENSIONS`,
`CASS_DRIVER_NO_LIBEV`, `CASS_DRIVER_NO_CYTHON`,
`CASS_DRIVER_BUILD_CONCURRENCY`, `CASS_DRIVER_LIBEV_INCLUDES`, and
`CASS_DRIVER_LIBEV_LIBS`. This is a breaking change that could affect users who
relied on these environment variables to control build behavior. Consider
either maintaining backward compatibility or documenting this breaking change
clearly.
##########
pyproject.toml:
##########
@@ -0,0 +1,57 @@
+[build-system]
+build-backend = "setuptools.build_meta"
+requires = ["setuptools", "Cython>=3.0", "toml", "cassandra-driver"]
+
+[project]
+name = "cassandra-driver"
+description = "Apache Cassandra Python Driver"
+dependencies = ['geomet>=1.1']
+readme = "README.rst"
+authors = [{name = "DataStax"}]
+license = "Apache-2.0"
+license-files = ["LICENSE"]
+keywords = ["cassandra","cql","orm","dse","graph"]
+classifiers = [
+ "Development Status :: 5 - Production/Stable",
+ "Intended Audience :: Developers",
+ "Natural Language :: English",
+ "Operating System :: OS Independent",
+ "License :: OSI Approved :: Apache Software License",
+ "Programming Language :: Python",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.12",
+ "Programming Language :: Python :: 3.13",
+ "Programming Language :: Python :: Implementation :: CPython",
+ "Programming Language :: Python :: Implementation :: PyPy",
+ "Topic :: Software Development :: Libraries :: Python Modules"
+]
Review Comment:
The pyproject.toml is missing a `requires-python` field to specify the
minimum Python version required. While the classifiers list Python 3.9-3.13,
the `requires-python` field should be explicitly set (e.g., `requires-python =
">=3.9"`) to ensure pip enforces this requirement during installation.
```suggestion
]
requires-python = ">=3.9"
```
##########
setup.py:
##########
@@ -254,193 +104,78 @@ class build_extensions(build_ext):
$ brew install libev
===============================================================================
- """
-
- def run(self):
- try:
- self._setup_extensions()
- build_ext.run(self)
- except DistutilsPlatformError as exc:
- sys.stderr.write('%s\n' % str(exc))
- warnings.warn(self.error_message % "C extensions.")
-
- def build_extensions(self):
- if build_concurrency > 1:
- self.check_extensions_list(self.extensions)
-
- import multiprocessing.pool
-
multiprocessing.pool.ThreadPool(processes=build_concurrency).map(self.build_extension,
self.extensions)
- else:
- build_ext.build_extensions(self)
-
- def build_extension(self, ext):
- try:
- build_ext.build_extension(self, ext)
- except (CCompilerError, DistutilsExecError,
- DistutilsPlatformError, IOError) as exc:
- sys.stderr.write('%s\n' % str(exc))
- name = "The %s extension" % (ext.name,)
- warnings.warn(self.error_message % (name,))
-
- def _setup_extensions(self):
- # We defer extension setup until this command to leveraage
'setup_requires' pulling in Cython before we
- # attempt to import anything
- self.extensions = []
-
- if try_murmur3:
- self.extensions.append(murmur3_ext)
-
- if try_libev:
- sys.stderr.write("Appending libev extension %s" % libev_ext)
- self.extensions.append(libev_ext)
-
- if try_cython:
- try:
- from Cython.Build import cythonize
- cython_candidates = ['cluster', 'concurrent', 'connection',
'cqltypes', 'metadata',
- 'pool', 'protocol', 'query', 'util']
- compile_args = [] if is_windows else ['-Wno-unused-function']
- self.extensions.extend(cythonize(
- [Extension('cassandra.%s' % m, ['cassandra/%s.py' % m],
- extra_compile_args=compile_args)
- for m in cython_candidates],
- nthreads=build_concurrency,
- exclude_failures=True))
-
- self.extensions.extend(cythonize(NoPatchExtension("*",
["cassandra/*.pyx"], extra_compile_args=compile_args),
- nthreads=build_concurrency))
- except Exception:
- sys.stderr.write("Failed to cythonize one or more modules.
These will not be compiled as extensions (optional).\n")
-
-
-def pre_build_check():
- """
- Try to verify build tools
- """
- if os.environ.get('CASS_DRIVER_NO_PRE_BUILD_CHECK'):
- return True
-
- try:
- from distutils.ccompiler import new_compiler
- from distutils.sysconfig import customize_compiler
- from distutils.dist import Distribution
-
- # base build_ext just to emulate compiler option setup
- be = build_ext(Distribution())
- be.initialize_options()
- be.finalize_options()
+"""
- # First, make sure we have a Python include directory
- have_python_include = any(os.path.isfile(os.path.join(p, 'Python.h'))
for p in be.include_dirs)
- if not have_python_include:
- sys.stderr.write("Did not find 'Python.h' in %s.\n" %
(be.include_dirs,))
- return False
+# ========================== A few upfront checks ==========================
+if is_pypy:
+ sys.stderr.write(pypy_unsupported_msg)
+if not is_supported_platform:
+ sys.stderr.write(platform_unsupported_msg)
+elif not is_supported_arch:
+ sys.stderr.write(arch_unsupported_msg)
- compiler = new_compiler(compiler=be.compiler)
- customize_compiler(compiler)
+# ========================== Extensions ==========================
+pyproject_toml = Path(__file__).parent / "pyproject.toml"
+pyproject_data = toml.load(pyproject_toml)
+driver_project_data = pyproject_data["tool"]["cassandra-driver"]
- try:
- # We must be able to initialize the compiler if it has that method
- if hasattr(compiler, "initialize"):
- compiler.initialize()
- except OSError:
- return False
+murmur3_ext = Extension('cassandra.cmurmur3', sources=['cassandra/cmurmur3.c'])
- executables = []
- if compiler.compiler_type in ('unix', 'cygwin'):
- executables = [compiler.executables[exe][0] for exe in
('compiler_so', 'linker_so')]
- elif compiler.compiler_type == 'nt':
- executables = [getattr(compiler, exe) for exe in ('cc', 'linker')]
+DEFAULT_LIBEV_INCLUDES = ['/usr/include/libev', '/usr/local/include',
'/opt/local/include', '/usr/include']
+DEFAULT_LIBEV_LIBS = ['/usr/local/lib', '/opt/local/lib', '/usr/lib64']
+libev_includes = driver_project_data["libev-includes"] or
DEFAULT_LIBEV_INCLUDES
+libev_libs = driver_project_data["libev-libs"] or DEFAULT_LIBEV_LIBS
+if is_macos:
+ libev_includes.extend(['/opt/homebrew/include',
os.path.expanduser('~/homebrew/include')])
+ libev_libs.extend(['/opt/homebrew/lib'])
+libev_ext = Extension('cassandra.io.libevwrapper',
+ sources=['cassandra/io/libevwrapper.c'],
+ include_dirs=libev_includes,
+ libraries=['ev'],
+ library_dirs=libev_libs)
- if executables:
- from distutils.spawn import find_executable
- for exe in executables:
- if not find_executable(exe):
- sys.stderr.write("Failed to find %s for compiler type
%s.\n" % (exe, compiler.compiler_type))
- return False
+try_extensions = driver_project_data["build-extensions"] and
is_supported_platform and is_supported_arch
+try_murmur3 = driver_project_data["build-murmur3-extension"]
+try_libev = driver_project_data["build-libev-extension"]
+try_cython = driver_project_data["build-cython-extensions"] and not is_pypy
- except Exception as exc:
- sys.stderr.write('%s\n' % str(exc))
- sys.stderr.write("Failed pre-build check. Attempting anyway.\n")
+build_concurrency = driver_project_data["build-concurrency"]
- # if we are unable to positively id the compiler type, or one of these
assumptions fails,
- # just proceed as we would have without the check
- return True
+def build_extension_list():
+ rv = []
-def run_setup(extensions):
+ if try_murmur3:
+ sys.stderr.write("Appending murmur extension %s\n" % murmur3_ext)
+ rv.append(murmur3_ext)
- kw = {'cmdclass': {'doc': DocCommand}}
- kw['cmdclass']['build_ext'] = build_extensions
- kw['ext_modules'] = [Extension('DUMMY', [])] # dummy extension makes sure
build_ext is called for install
+ if try_libev:
+ sys.stderr.write("Appending libev extension %s\n" % libev_ext)
+ rv.append(libev_ext)
if try_cython:
- # precheck compiler before adding to setup_requires
- # we don't actually negate try_cython because:
- # 1.) build_ext eats errors at compile time, letting the install
complete while producing useful feedback
- # 2.) there could be a case where the python environment has cython
installed but the system doesn't have build tools
- if pre_build_check():
- cython_dep = 'Cython>=3.0'
- user_specified_cython_version =
os.environ.get('CASS_DRIVER_ALLOWED_CYTHON_VERSION')
- if user_specified_cython_version is not None:
- cython_dep = 'Cython==%s' % (user_specified_cython_version,)
- kw['setup_requires'] = [cython_dep]
- else:
- sys.stderr.write("Bypassing Cython setup requirement\n")
-
- dependencies = ['geomet>=1.1']
-
- _EXTRAS_REQUIRE = {
- 'graph': ['gremlinpython==3.4.6'],
- 'cle': ['cryptography>=42.0']
- }
-
- setup(
- name='cassandra-driver',
- version=__version__,
- description='Apache Cassandra Python Driver',
- long_description=long_description,
- long_description_content_type='text/x-rst',
- url='http://github.com/datastax/python-driver',
- project_urls={
- 'Documentation':
'https://docs.datastax.com/en/developer/python-driver/latest/',
- 'Source': 'https://github.com/datastax/python-driver/',
- 'Issues': 'https://datastax-oss.atlassian.net/browse/PYTHON',
- },
- author='DataStax',
- packages=[
- 'cassandra', 'cassandra.io', 'cassandra.cqlengine',
'cassandra.graph',
- 'cassandra.datastax', 'cassandra.datastax.insights',
'cassandra.datastax.graph',
- 'cassandra.datastax.graph.fluent', 'cassandra.datastax.cloud',
- "cassandra.column_encryption"
- ],
- keywords='cassandra,cql,orm,dse,graph',
- include_package_data=True,
- install_requires=dependencies,
- extras_require=_EXTRAS_REQUIRE,
- tests_require=['pytest', 'PyYAML', 'pytz'],
- classifiers=[
- 'Development Status :: 5 - Production/Stable',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: Apache Software License',
- 'Natural Language :: English',
- 'Operating System :: OS Independent',
- 'Programming Language :: Python',
- 'Programming Language :: Python :: 3.9',
- 'Programming Language :: Python :: 3.10',
- 'Programming Language :: Python :: 3.11',
- 'Programming Language :: Python :: 3.12',
- 'Programming Language :: Python :: 3.13',
- 'Programming Language :: Python :: Implementation :: CPython',
- 'Programming Language :: Python :: Implementation :: PyPy',
- 'Topic :: Software Development :: Libraries :: Python Modules'
- ],
- **kw)
-
-
-run_setup(None)
-
-if has_cqlengine:
- warnings.warn("\n#######\n'cqlengine' package is present on path: %s\n"
- "cqlengine is now an integrated sub-package of this
driver.\n"
- "It is recommended to remove this package to reduce the
chance for conflicting usage" % cqlengine.__file__)
+ sys.stderr.write("Trying Cython builds in order to append Cython
extensions\n")
+ try:
+ from Cython.Build import cythonize
+ cython_candidates = ['cluster', 'concurrent', 'connection',
'cqltypes', 'metadata',
+ 'pool', 'protocol', 'query', 'util']
+ compile_args = [] if is_windows else ['-Wno-unused-function']
+ rv.extend(cythonize(
+ [Extension('cassandra.%s' % m, ['cassandra/%s.py' % m],
+ extra_compile_args=compile_args)
+ for m in cython_candidates],
+ nthreads=build_concurrency,
+ exclude_failures=True))
+
+ rv.extend(cythonize(Extension("*", ["cassandra/*.pyx"],
extra_compile_args=compile_args),
+ nthreads=build_concurrency))
+ except Exception:
+ sys.stderr.write("Failed to cythonize one or more modules. These
will not be compiled as extensions (optional).\n")
Review Comment:
The exception handler at line 172 catches all exceptions with a bare `except
Exception:`, which will silently suppress all errors during Cythonization.
While this matches the original behavior, it would be better to log the actual
exception details (e.g., using `sys.stderr.write(str(exc))`) to help users
diagnose build issues rather than just printing a generic message.
```suggestion
except Exception as exc:
sys.stderr.write("Failed to cythonize one or more modules. These
will not be compiled as extensions (optional).\n")
sys.stderr.write("Cythonization error: %s\n" % (exc,))
```
##########
setup.py:
##########
@@ -254,193 +104,78 @@ class build_extensions(build_ext):
$ brew install libev
===============================================================================
- """
-
- def run(self):
- try:
- self._setup_extensions()
- build_ext.run(self)
- except DistutilsPlatformError as exc:
- sys.stderr.write('%s\n' % str(exc))
- warnings.warn(self.error_message % "C extensions.")
-
- def build_extensions(self):
- if build_concurrency > 1:
- self.check_extensions_list(self.extensions)
-
- import multiprocessing.pool
-
multiprocessing.pool.ThreadPool(processes=build_concurrency).map(self.build_extension,
self.extensions)
- else:
- build_ext.build_extensions(self)
-
- def build_extension(self, ext):
- try:
- build_ext.build_extension(self, ext)
- except (CCompilerError, DistutilsExecError,
- DistutilsPlatformError, IOError) as exc:
- sys.stderr.write('%s\n' % str(exc))
- name = "The %s extension" % (ext.name,)
- warnings.warn(self.error_message % (name,))
-
- def _setup_extensions(self):
- # We defer extension setup until this command to leveraage
'setup_requires' pulling in Cython before we
- # attempt to import anything
- self.extensions = []
-
- if try_murmur3:
- self.extensions.append(murmur3_ext)
-
- if try_libev:
- sys.stderr.write("Appending libev extension %s" % libev_ext)
- self.extensions.append(libev_ext)
-
- if try_cython:
- try:
- from Cython.Build import cythonize
- cython_candidates = ['cluster', 'concurrent', 'connection',
'cqltypes', 'metadata',
- 'pool', 'protocol', 'query', 'util']
- compile_args = [] if is_windows else ['-Wno-unused-function']
- self.extensions.extend(cythonize(
- [Extension('cassandra.%s' % m, ['cassandra/%s.py' % m],
- extra_compile_args=compile_args)
- for m in cython_candidates],
- nthreads=build_concurrency,
- exclude_failures=True))
-
- self.extensions.extend(cythonize(NoPatchExtension("*",
["cassandra/*.pyx"], extra_compile_args=compile_args),
- nthreads=build_concurrency))
- except Exception:
- sys.stderr.write("Failed to cythonize one or more modules.
These will not be compiled as extensions (optional).\n")
-
-
-def pre_build_check():
- """
- Try to verify build tools
- """
- if os.environ.get('CASS_DRIVER_NO_PRE_BUILD_CHECK'):
- return True
-
- try:
- from distutils.ccompiler import new_compiler
- from distutils.sysconfig import customize_compiler
- from distutils.dist import Distribution
-
- # base build_ext just to emulate compiler option setup
- be = build_ext(Distribution())
- be.initialize_options()
- be.finalize_options()
+"""
- # First, make sure we have a Python include directory
- have_python_include = any(os.path.isfile(os.path.join(p, 'Python.h'))
for p in be.include_dirs)
- if not have_python_include:
- sys.stderr.write("Did not find 'Python.h' in %s.\n" %
(be.include_dirs,))
- return False
+# ========================== A few upfront checks ==========================
+if is_pypy:
+ sys.stderr.write(pypy_unsupported_msg)
+if not is_supported_platform:
+ sys.stderr.write(platform_unsupported_msg)
+elif not is_supported_arch:
+ sys.stderr.write(arch_unsupported_msg)
- compiler = new_compiler(compiler=be.compiler)
- customize_compiler(compiler)
+# ========================== Extensions ==========================
+pyproject_toml = Path(__file__).parent / "pyproject.toml"
+pyproject_data = toml.load(pyproject_toml)
+driver_project_data = pyproject_data["tool"]["cassandra-driver"]
- try:
- # We must be able to initialize the compiler if it has that method
- if hasattr(compiler, "initialize"):
- compiler.initialize()
- except OSError:
- return False
+murmur3_ext = Extension('cassandra.cmurmur3', sources=['cassandra/cmurmur3.c'])
- executables = []
- if compiler.compiler_type in ('unix', 'cygwin'):
- executables = [compiler.executables[exe][0] for exe in
('compiler_so', 'linker_so')]
- elif compiler.compiler_type == 'nt':
- executables = [getattr(compiler, exe) for exe in ('cc', 'linker')]
+DEFAULT_LIBEV_INCLUDES = ['/usr/include/libev', '/usr/local/include',
'/opt/local/include', '/usr/include']
+DEFAULT_LIBEV_LIBS = ['/usr/local/lib', '/opt/local/lib', '/usr/lib64']
+libev_includes = driver_project_data["libev-includes"] or
DEFAULT_LIBEV_INCLUDES
+libev_libs = driver_project_data["libev-libs"] or DEFAULT_LIBEV_LIBS
+if is_macos:
+ libev_includes.extend(['/opt/homebrew/include',
os.path.expanduser('~/homebrew/include')])
+ libev_libs.extend(['/opt/homebrew/lib'])
+libev_ext = Extension('cassandra.io.libevwrapper',
+ sources=['cassandra/io/libevwrapper.c'],
+ include_dirs=libev_includes,
+ libraries=['ev'],
+ library_dirs=libev_libs)
- if executables:
- from distutils.spawn import find_executable
- for exe in executables:
- if not find_executable(exe):
- sys.stderr.write("Failed to find %s for compiler type
%s.\n" % (exe, compiler.compiler_type))
- return False
+try_extensions = driver_project_data["build-extensions"] and
is_supported_platform and is_supported_arch
+try_murmur3 = driver_project_data["build-murmur3-extension"]
+try_libev = driver_project_data["build-libev-extension"]
+try_cython = driver_project_data["build-cython-extensions"] and not is_pypy
- except Exception as exc:
- sys.stderr.write('%s\n' % str(exc))
- sys.stderr.write("Failed pre-build check. Attempting anyway.\n")
+build_concurrency = driver_project_data["build-concurrency"]
- # if we are unable to positively id the compiler type, or one of these
assumptions fails,
- # just proceed as we would have without the check
- return True
+def build_extension_list():
+ rv = []
-def run_setup(extensions):
+ if try_murmur3:
+ sys.stderr.write("Appending murmur extension %s\n" % murmur3_ext)
+ rv.append(murmur3_ext)
- kw = {'cmdclass': {'doc': DocCommand}}
- kw['cmdclass']['build_ext'] = build_extensions
- kw['ext_modules'] = [Extension('DUMMY', [])] # dummy extension makes sure
build_ext is called for install
+ if try_libev:
+ sys.stderr.write("Appending libev extension %s\n" % libev_ext)
+ rv.append(libev_ext)
if try_cython:
- # precheck compiler before adding to setup_requires
- # we don't actually negate try_cython because:
- # 1.) build_ext eats errors at compile time, letting the install
complete while producing useful feedback
- # 2.) there could be a case where the python environment has cython
installed but the system doesn't have build tools
- if pre_build_check():
- cython_dep = 'Cython>=3.0'
- user_specified_cython_version =
os.environ.get('CASS_DRIVER_ALLOWED_CYTHON_VERSION')
- if user_specified_cython_version is not None:
- cython_dep = 'Cython==%s' % (user_specified_cython_version,)
- kw['setup_requires'] = [cython_dep]
- else:
- sys.stderr.write("Bypassing Cython setup requirement\n")
-
- dependencies = ['geomet>=1.1']
-
- _EXTRAS_REQUIRE = {
- 'graph': ['gremlinpython==3.4.6'],
- 'cle': ['cryptography>=42.0']
- }
-
- setup(
- name='cassandra-driver',
- version=__version__,
- description='Apache Cassandra Python Driver',
- long_description=long_description,
- long_description_content_type='text/x-rst',
- url='http://github.com/datastax/python-driver',
- project_urls={
- 'Documentation':
'https://docs.datastax.com/en/developer/python-driver/latest/',
- 'Source': 'https://github.com/datastax/python-driver/',
- 'Issues': 'https://datastax-oss.atlassian.net/browse/PYTHON',
- },
- author='DataStax',
- packages=[
- 'cassandra', 'cassandra.io', 'cassandra.cqlengine',
'cassandra.graph',
- 'cassandra.datastax', 'cassandra.datastax.insights',
'cassandra.datastax.graph',
- 'cassandra.datastax.graph.fluent', 'cassandra.datastax.cloud',
- "cassandra.column_encryption"
- ],
- keywords='cassandra,cql,orm,dse,graph',
- include_package_data=True,
- install_requires=dependencies,
- extras_require=_EXTRAS_REQUIRE,
- tests_require=['pytest', 'PyYAML', 'pytz'],
- classifiers=[
- 'Development Status :: 5 - Production/Stable',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: Apache Software License',
- 'Natural Language :: English',
- 'Operating System :: OS Independent',
- 'Programming Language :: Python',
- 'Programming Language :: Python :: 3.9',
- 'Programming Language :: Python :: 3.10',
- 'Programming Language :: Python :: 3.11',
- 'Programming Language :: Python :: 3.12',
- 'Programming Language :: Python :: 3.13',
- 'Programming Language :: Python :: Implementation :: CPython',
- 'Programming Language :: Python :: Implementation :: PyPy',
- 'Topic :: Software Development :: Libraries :: Python Modules'
- ],
- **kw)
-
-
-run_setup(None)
-
-if has_cqlengine:
- warnings.warn("\n#######\n'cqlengine' package is present on path: %s\n"
- "cqlengine is now an integrated sub-package of this
driver.\n"
- "It is recommended to remove this package to reduce the
chance for conflicting usage" % cqlengine.__file__)
+ sys.stderr.write("Trying Cython builds in order to append Cython
extensions\n")
+ try:
+ from Cython.Build import cythonize
+ cython_candidates = ['cluster', 'concurrent', 'connection',
'cqltypes', 'metadata',
+ 'pool', 'protocol', 'query', 'util']
+ compile_args = [] if is_windows else ['-Wno-unused-function']
+ rv.extend(cythonize(
+ [Extension('cassandra.%s' % m, ['cassandra/%s.py' % m],
+ extra_compile_args=compile_args)
+ for m in cython_candidates],
+ nthreads=build_concurrency,
+ exclude_failures=True))
+
+ rv.extend(cythonize(Extension("*", ["cassandra/*.pyx"],
extra_compile_args=compile_args),
+ nthreads=build_concurrency))
+ except Exception:
+ sys.stderr.write("Failed to cythonize one or more modules. These
will not be compiled as extensions (optional).\n")
+
+ return rv
+
+# ========================== And finally setup() itself
==========================
+setup(
+ version = __version__,
+ ext_modules = build_extension_list()
+)
Review Comment:
The refactored code removes the `DocCommand` custom command that was used to
generate and test documentation via `python setup.py doc` or `python setup.py
doc --test`. This is a breaking change that could affect documentation build
workflows. Consider either maintaining this functionality or documenting the
migration path for documentation building.
##########
setup.py:
##########
@@ -254,193 +104,78 @@ class build_extensions(build_ext):
$ brew install libev
===============================================================================
- """
-
- def run(self):
- try:
- self._setup_extensions()
- build_ext.run(self)
- except DistutilsPlatformError as exc:
- sys.stderr.write('%s\n' % str(exc))
- warnings.warn(self.error_message % "C extensions.")
-
- def build_extensions(self):
- if build_concurrency > 1:
- self.check_extensions_list(self.extensions)
-
- import multiprocessing.pool
-
multiprocessing.pool.ThreadPool(processes=build_concurrency).map(self.build_extension,
self.extensions)
- else:
- build_ext.build_extensions(self)
-
- def build_extension(self, ext):
- try:
- build_ext.build_extension(self, ext)
- except (CCompilerError, DistutilsExecError,
- DistutilsPlatformError, IOError) as exc:
- sys.stderr.write('%s\n' % str(exc))
- name = "The %s extension" % (ext.name,)
- warnings.warn(self.error_message % (name,))
-
- def _setup_extensions(self):
- # We defer extension setup until this command to leveraage
'setup_requires' pulling in Cython before we
- # attempt to import anything
- self.extensions = []
-
- if try_murmur3:
- self.extensions.append(murmur3_ext)
-
- if try_libev:
- sys.stderr.write("Appending libev extension %s" % libev_ext)
- self.extensions.append(libev_ext)
-
- if try_cython:
- try:
- from Cython.Build import cythonize
- cython_candidates = ['cluster', 'concurrent', 'connection',
'cqltypes', 'metadata',
- 'pool', 'protocol', 'query', 'util']
- compile_args = [] if is_windows else ['-Wno-unused-function']
- self.extensions.extend(cythonize(
- [Extension('cassandra.%s' % m, ['cassandra/%s.py' % m],
- extra_compile_args=compile_args)
- for m in cython_candidates],
- nthreads=build_concurrency,
- exclude_failures=True))
-
- self.extensions.extend(cythonize(NoPatchExtension("*",
["cassandra/*.pyx"], extra_compile_args=compile_args),
- nthreads=build_concurrency))
- except Exception:
- sys.stderr.write("Failed to cythonize one or more modules.
These will not be compiled as extensions (optional).\n")
-
-
-def pre_build_check():
- """
- Try to verify build tools
- """
- if os.environ.get('CASS_DRIVER_NO_PRE_BUILD_CHECK'):
- return True
-
- try:
- from distutils.ccompiler import new_compiler
- from distutils.sysconfig import customize_compiler
- from distutils.dist import Distribution
-
- # base build_ext just to emulate compiler option setup
- be = build_ext(Distribution())
- be.initialize_options()
- be.finalize_options()
+"""
- # First, make sure we have a Python include directory
- have_python_include = any(os.path.isfile(os.path.join(p, 'Python.h'))
for p in be.include_dirs)
- if not have_python_include:
- sys.stderr.write("Did not find 'Python.h' in %s.\n" %
(be.include_dirs,))
- return False
+# ========================== A few upfront checks ==========================
+if is_pypy:
+ sys.stderr.write(pypy_unsupported_msg)
+if not is_supported_platform:
+ sys.stderr.write(platform_unsupported_msg)
+elif not is_supported_arch:
+ sys.stderr.write(arch_unsupported_msg)
- compiler = new_compiler(compiler=be.compiler)
- customize_compiler(compiler)
+# ========================== Extensions ==========================
+pyproject_toml = Path(__file__).parent / "pyproject.toml"
+pyproject_data = toml.load(pyproject_toml)
+driver_project_data = pyproject_data["tool"]["cassandra-driver"]
- try:
- # We must be able to initialize the compiler if it has that method
- if hasattr(compiler, "initialize"):
- compiler.initialize()
- except OSError:
- return False
+murmur3_ext = Extension('cassandra.cmurmur3', sources=['cassandra/cmurmur3.c'])
- executables = []
- if compiler.compiler_type in ('unix', 'cygwin'):
- executables = [compiler.executables[exe][0] for exe in
('compiler_so', 'linker_so')]
- elif compiler.compiler_type == 'nt':
- executables = [getattr(compiler, exe) for exe in ('cc', 'linker')]
+DEFAULT_LIBEV_INCLUDES = ['/usr/include/libev', '/usr/local/include',
'/opt/local/include', '/usr/include']
+DEFAULT_LIBEV_LIBS = ['/usr/local/lib', '/opt/local/lib', '/usr/lib64']
+libev_includes = driver_project_data["libev-includes"] or
DEFAULT_LIBEV_INCLUDES
+libev_libs = driver_project_data["libev-libs"] or DEFAULT_LIBEV_LIBS
+if is_macos:
+ libev_includes.extend(['/opt/homebrew/include',
os.path.expanduser('~/homebrew/include')])
+ libev_libs.extend(['/opt/homebrew/lib'])
+libev_ext = Extension('cassandra.io.libevwrapper',
+ sources=['cassandra/io/libevwrapper.c'],
+ include_dirs=libev_includes,
+ libraries=['ev'],
+ library_dirs=libev_libs)
- if executables:
- from distutils.spawn import find_executable
- for exe in executables:
- if not find_executable(exe):
- sys.stderr.write("Failed to find %s for compiler type
%s.\n" % (exe, compiler.compiler_type))
- return False
+try_extensions = driver_project_data["build-extensions"] and
is_supported_platform and is_supported_arch
+try_murmur3 = driver_project_data["build-murmur3-extension"]
+try_libev = driver_project_data["build-libev-extension"]
+try_cython = driver_project_data["build-cython-extensions"] and not is_pypy
- except Exception as exc:
- sys.stderr.write('%s\n' % str(exc))
- sys.stderr.write("Failed pre-build check. Attempting anyway.\n")
+build_concurrency = driver_project_data["build-concurrency"]
- # if we are unable to positively id the compiler type, or one of these
assumptions fails,
- # just proceed as we would have without the check
- return True
+def build_extension_list():
+ rv = []
-def run_setup(extensions):
+ if try_murmur3:
+ sys.stderr.write("Appending murmur extension %s\n" % murmur3_ext)
+ rv.append(murmur3_ext)
- kw = {'cmdclass': {'doc': DocCommand}}
- kw['cmdclass']['build_ext'] = build_extensions
- kw['ext_modules'] = [Extension('DUMMY', [])] # dummy extension makes sure
build_ext is called for install
+ if try_libev:
+ sys.stderr.write("Appending libev extension %s\n" % libev_ext)
+ rv.append(libev_ext)
if try_cython:
- # precheck compiler before adding to setup_requires
- # we don't actually negate try_cython because:
- # 1.) build_ext eats errors at compile time, letting the install
complete while producing useful feedback
- # 2.) there could be a case where the python environment has cython
installed but the system doesn't have build tools
- if pre_build_check():
- cython_dep = 'Cython>=3.0'
- user_specified_cython_version =
os.environ.get('CASS_DRIVER_ALLOWED_CYTHON_VERSION')
- if user_specified_cython_version is not None:
- cython_dep = 'Cython==%s' % (user_specified_cython_version,)
- kw['setup_requires'] = [cython_dep]
- else:
- sys.stderr.write("Bypassing Cython setup requirement\n")
-
- dependencies = ['geomet>=1.1']
-
- _EXTRAS_REQUIRE = {
- 'graph': ['gremlinpython==3.4.6'],
- 'cle': ['cryptography>=42.0']
- }
-
- setup(
- name='cassandra-driver',
- version=__version__,
- description='Apache Cassandra Python Driver',
- long_description=long_description,
- long_description_content_type='text/x-rst',
- url='http://github.com/datastax/python-driver',
- project_urls={
- 'Documentation':
'https://docs.datastax.com/en/developer/python-driver/latest/',
- 'Source': 'https://github.com/datastax/python-driver/',
- 'Issues': 'https://datastax-oss.atlassian.net/browse/PYTHON',
- },
- author='DataStax',
- packages=[
- 'cassandra', 'cassandra.io', 'cassandra.cqlengine',
'cassandra.graph',
- 'cassandra.datastax', 'cassandra.datastax.insights',
'cassandra.datastax.graph',
- 'cassandra.datastax.graph.fluent', 'cassandra.datastax.cloud',
- "cassandra.column_encryption"
- ],
- keywords='cassandra,cql,orm,dse,graph',
- include_package_data=True,
- install_requires=dependencies,
- extras_require=_EXTRAS_REQUIRE,
- tests_require=['pytest', 'PyYAML', 'pytz'],
- classifiers=[
- 'Development Status :: 5 - Production/Stable',
- 'Intended Audience :: Developers',
- 'License :: OSI Approved :: Apache Software License',
- 'Natural Language :: English',
- 'Operating System :: OS Independent',
- 'Programming Language :: Python',
- 'Programming Language :: Python :: 3.9',
- 'Programming Language :: Python :: 3.10',
- 'Programming Language :: Python :: 3.11',
- 'Programming Language :: Python :: 3.12',
- 'Programming Language :: Python :: 3.13',
- 'Programming Language :: Python :: Implementation :: CPython',
- 'Programming Language :: Python :: Implementation :: PyPy',
- 'Topic :: Software Development :: Libraries :: Python Modules'
- ],
- **kw)
-
-
-run_setup(None)
-
-if has_cqlengine:
- warnings.warn("\n#######\n'cqlengine' package is present on path: %s\n"
- "cqlengine is now an integrated sub-package of this
driver.\n"
- "It is recommended to remove this package to reduce the
chance for conflicting usage" % cqlengine.__file__)
+ sys.stderr.write("Trying Cython builds in order to append Cython
extensions\n")
+ try:
+ from Cython.Build import cythonize
+ cython_candidates = ['cluster', 'concurrent', 'connection',
'cqltypes', 'metadata',
+ 'pool', 'protocol', 'query', 'util']
+ compile_args = [] if is_windows else ['-Wno-unused-function']
+ rv.extend(cythonize(
+ [Extension('cassandra.%s' % m, ['cassandra/%s.py' % m],
+ extra_compile_args=compile_args)
+ for m in cython_candidates],
+ nthreads=build_concurrency,
+ exclude_failures=True))
+
+ rv.extend(cythonize(Extension("*", ["cassandra/*.pyx"],
extra_compile_args=compile_args),
+ nthreads=build_concurrency))
+ except Exception:
+ sys.stderr.write("Failed to cythonize one or more modules. These
will not be compiled as extensions (optional).\n")
+
Review Comment:
Trailing whitespace detected on this line.
```suggestion
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]