diff --git a/ci/conda_env_python.txt b/ci/conda_env_python.txt index 4e3fd9f2de7..eddba95a11f 100644 --- a/ci/conda_env_python.txt +++ b/ci/conda_env_python.txt @@ -28,5 +28,5 @@ numpy>=1.16.6 pytest pytest-faulthandler s3fs>=2023.10.0 -setuptools>=64 +setuptools>=77 setuptools_scm>=8 diff --git a/python/.gitignore b/python/.gitignore index fbc3b192433..dec4ffc1c9b 100644 --- a/python/.gitignore +++ b/python/.gitignore @@ -45,3 +45,8 @@ pyarrow/_table_api.h manylinux1/arrow nm_arrow.log visible_symbols.log + +# the purpose of the custom SDist class in setup.py is to include these files +# in the sdist tarball, but we don't want to track duplicates +LICENSE.txt +NOTICE.txt diff --git a/python/pyproject.toml b/python/pyproject.toml index fe812227ebe..0a730fd4f78 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -22,7 +22,7 @@ requires = [ # configuring setuptools_scm in pyproject.toml requires # versions released after 2022 "setuptools_scm[toml]>=8", - "setuptools>=64", + "setuptools>=77", ] build-backend = "setuptools.build_meta" @@ -32,9 +32,12 @@ dynamic = ["version"] requires-python = ">=3.10" description = "Python library for Apache Arrow" readme = {file = "README.md", content-type = "text/markdown"} -license = {text = "Apache Software License"} +license = "Apache-2.0" +license-files = [ + "LICENSE.txt", + "NOTICE.txt", +] classifiers = [ - 'License :: OSI Approved :: Apache Software License', 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12', diff --git a/python/requirements-build.txt b/python/requirements-build.txt index e3fb5bc0005..9e03e04aded 100644 --- a/python/requirements-build.txt +++ b/python/requirements-build.txt @@ -1,4 +1,4 @@ cython>=3.1 numpy>=1.25 setuptools_scm>=8 -setuptools>=64 +setuptools>=77 diff --git a/python/setup.cfg b/python/setup.cfg index 3df4ff27ef8..b0c3edfa8be 100644 --- a/python/setup.cfg +++ b/python/setup.cfg @@ -15,11 +15,6 @@ # specific language governing permissions and limitations # under the License. -[metadata] -license_files = - ../LICENSE.txt - ../NOTICE.txt - [build_sphinx] source-dir = doc/ build-dir = doc/_build diff --git a/python/setup.py b/python/setup.py index b6fea83eb03..a27bd3baefd 100755 --- a/python/setup.py +++ b/python/setup.py @@ -23,6 +23,7 @@ from os.path import join as pjoin import re import shlex +import shutil import sys import warnings @@ -33,6 +34,7 @@ from distutils import sysconfig from setuptools import setup, Extension, Distribution +from setuptools.command.sdist import sdist from Cython.Distutils import build_ext as _build_ext import Cython @@ -395,11 +397,41 @@ def has_ext_modules(foo): return True +class CopyLicenseSdist(sdist): + """Custom sdist command that copies license files from parent directory.""" + + def make_release_tree(self, base_dir, files): + # Call parent to do the normal work + super().make_release_tree(base_dir, files) + + # Define source (parent dir) and destination (sdist root) for license files + license_files = [ + ("LICENSE.txt", "../LICENSE.txt"), + ("NOTICE.txt", "../NOTICE.txt"), + ] + + for dest_name, src_path in license_files: + src_full = os.path.join(os.path.dirname(__file__), src_path) + dest_full = os.path.join(base_dir, dest_name) + + # Remove any existing file/symlink at destination + if os.path.exists(dest_full) or os.path.islink(dest_full): + os.unlink(dest_full) + + if not os.path.exists(src_full): + msg = f"Required license file not found: {src_full}" + raise FileNotFoundError(msg) + + shutil.copy2(src_full, dest_full) + print(f"Copied {src_path} to {dest_name} in sdist") + + setup( distclass=BinaryDistribution, # Dummy extension to trigger build_ext ext_modules=[Extension('__dummy__', sources=[])], cmdclass={ - 'build_ext': build_ext + 'build_ext': build_ext, + 'sdist': CopyLicenseSdist, }, )