From c8b2cc75384d9284b6c50a1d65428eb7c134664a Mon Sep 17 00:00:00 2001 From: Abel Gladstone Mangam Date: Sun, 6 Oct 2024 15:04:34 +0200 Subject: [PATCH] pyproject: Use pyproject.toml for building wheels --- MANIFEST.in | 3 +- VERSION | 1 + _custom_build/__init__.py | 0 _custom_build/backend.py | 58 +++++++++++ .../sounddevice_build.py | 9 +- pyproject.toml | 42 +++++++- setup.py | 96 ------------------- sounddevice.py | 1 - 8 files changed, 108 insertions(+), 102 deletions(-) create mode 100644 VERSION create mode 100644 _custom_build/__init__.py create mode 100644 _custom_build/backend.py rename sounddevice_build.py => _custom_build/sounddevice_build.py (99%) delete mode 100644 setup.py diff --git a/MANIFEST.in b/MANIFEST.in index 4319353..5c50635 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,7 @@ include LICENSE include *.rst include doc/requirements.txt -include sounddevice_build.py +recursive-include _custom_build *.py +include sounddevice.py recursive-include doc *.rst *.py recursive-include examples *.py diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..79a2734 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.5.0 \ No newline at end of file diff --git a/_custom_build/__init__.py b/_custom_build/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/_custom_build/backend.py b/_custom_build/backend.py new file mode 100644 index 0000000..19e11b2 --- /dev/null +++ b/_custom_build/backend.py @@ -0,0 +1,58 @@ +"""A Thin backend wrapper for setuptools.build_meta + +See https://setuptools.pypa.io/en/latest/build_meta.html +""" + +from setuptools import build_meta as _orig +from setuptools.build_meta import * +import sounddevice_build +import os +import platform +import shutil + +sounddevice_build.main() + +DARWIN = "Darwin" +WINDOWS = "Windows" +MACOSX_VERSIONS = ["maccosx_10_6_x86_64", "macosx_10_6_universal2"] + + +def get_platform_specific_wheel_name() -> str: + """Return the platform specific wheel name.""" + current_platform = os.environ.get("PYTHON_SOUNDDEVICE_PLATFORM", platform.system()) + architecture = os.environ.get("PYTHON_SOUNDDEVICE_ARCHITECTURE", platform.architecture()[0]) + oses = "any" + + if current_platform == DARWIN: + oses = ".".join(MACOSX_VERSIONS) + elif current_platform == WINDOWS: + oses = "win32" if architecture == "32bit" else "win_amd64" + + with open("VERSION", "r") as f: + version = f.read().strip() + + return f"sounddevice-{version}-py3-none-{oses}.whl" + + +def prepare_meta_for_build_wheel(config_settings=None): + """This function may be used in the future to customize platform specific portaudio libraries.""" + return _orig.prepare_metadata_for_build_wheel(config_settings=config_settings) + + +def get_requires_for_build_wheel(config_settings=None): + return _orig.get_requires_for_build_wheel(config_settings=config_settings) + + +def build_wheel(wheel_directory, config_settings=None, metadata_directory=None): + """Intercept the build wheel function and copy the wheel to a platform specific name. + + We build the wheel as ususal for the package but intercept the output so that we can rename it. + """ + + wheel_file = _orig.build_wheel(wheel_directory, config_settings=config_settings, metadata_directory=metadata_directory) + old_wheel_path = os.path.join(wheel_directory, wheel_file) + new_wheel_path = os.path.join(wheel_directory, get_platform_specific_wheel_name()) + + shutil.move(old_wheel_path, new_wheel_path) + + return new_wheel_path diff --git a/sounddevice_build.py b/_custom_build/sounddevice_build.py similarity index 99% rename from sounddevice_build.py rename to _custom_build/sounddevice_build.py index 6b45b79..882c084 100644 --- a/sounddevice_build.py +++ b/_custom_build/sounddevice_build.py @@ -1,7 +1,7 @@ from cffi import FFI ffibuilder = FFI() -ffibuilder.set_source('_sounddevice', None) +ffibuilder.set_source("_sounddevice", None) ffibuilder.cdef(""" int Pa_GetVersion( void ); const char* Pa_GetVersionText( void ); @@ -314,5 +314,10 @@ int PaWasapi_IsLoopback( PaDeviceIndex device ); """) -if __name__ == '__main__': + +def main(): ffibuilder.compile(verbose=True) + + +if __name__ == "__main__": + main() diff --git a/pyproject.toml b/pyproject.toml index 68847bb..2b06e9d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,41 @@ [build-system] -requires = ["setuptools >= 61.0"] -build-backend = "setuptools.build_meta" +requires = ["setuptools", "wheel", "CFFI>=1.0.0"] +build-backend = "backend" +backend-path = ["_custom_build"] + +[project] +name = "sounddevice" +description = "Play and Record Sound with Python" +requires-python = ">=3.7" +readme = "README.rst" +license = { file = "LICENSE" } +keywords = ["sound", "audio", "play", "record", "playrec", "PortAudio"] +authors = [{ name = "Matthias Geier", email = "Matthias.Geier@gmail.com" }] +classifiers = [ + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Topic :: Multimedia :: Sound/Audio" +] +urls = { "Source" = "https://github.com/spatialaudio/python-sounddevice" } +dependencies = ["CFFI>=1.0.0"] +dynamic = ["version"] + +[project.optional-dependencies] +NumPy = ["NumPy"] + +[tool.setuptools] +zip-safe = false +py-modules = ["sounddevice", "_sounddevice"] +packages = ["_sounddevice_data"] + +[tool.setuptools.package-data] +"_sounddevice_data"= [ + "portaudio-binaries/*.dll", + "portaudio-binaries/*.dylib", + "portaudio-binaries/*.md" + ] + +[tool.setuptools.dynamic] +version = { "file" = "VERSION" } diff --git a/setup.py b/setup.py deleted file mode 100644 index 7f9cfb0..0000000 --- a/setup.py +++ /dev/null @@ -1,96 +0,0 @@ -import os -import platform -from setuptools import setup - -# "import" __version__ -__version__ = 'unknown' -for line in open('sounddevice.py'): - if line.startswith('__version__'): - exec(line) - break - -MACOSX_VERSIONS = '.'.join([ - 'macosx_10_6_x86_64', # for compatibility with pip < v21 - 'macosx_10_6_universal2', -]) - -# environment variables for cross-platform package creation -system = os.environ.get('PYTHON_SOUNDDEVICE_PLATFORM', platform.system()) -architecture0 = os.environ.get('PYTHON_SOUNDDEVICE_ARCHITECTURE', - platform.architecture()[0]) - -if system == 'Darwin': - libname = 'libportaudio.dylib' -elif system == 'Windows': - libname = 'libportaudio' + architecture0 + '.dll' - libname_asio = 'libportaudio' + architecture0 + '-asio.dll' -else: - libname = None - -if libname and os.path.isdir('_sounddevice_data/portaudio-binaries'): - packages = ['_sounddevice_data'] - package_data = {'_sounddevice_data': ['portaudio-binaries/' + libname, - 'portaudio-binaries/README.md']} - if system == 'Windows': - package_data['_sounddevice_data'].append( - 'portaudio-binaries/' + libname_asio) - zip_safe = False -else: - packages = None - package_data = None - zip_safe = True - -try: - from wheel.bdist_wheel import bdist_wheel -except ImportError: - cmdclass = {} -else: - class bdist_wheel_half_pure(bdist_wheel): - """Create OS-dependent, but Python-independent wheels.""" - - def get_tag(self): - if system == 'Darwin': - oses = MACOSX_VERSIONS - elif system == 'Windows': - if architecture0 == '32bit': - oses = 'win32' - else: - oses = 'win_amd64' - else: - oses = 'any' - return 'py3', 'none', oses - - cmdclass = {'bdist_wheel': bdist_wheel_half_pure} - -setup( - name='sounddevice', - version=__version__, - py_modules=['sounddevice'], - packages=packages, - package_data=package_data, - zip_safe=zip_safe, - python_requires='>=3.7', - setup_requires=['CFFI>=1.0'], - install_requires=['CFFI>=1.0'], - extras_require={'NumPy': ['NumPy']}, - cffi_modules=['sounddevice_build.py:ffibuilder'], - author='Matthias Geier', - author_email='Matthias.Geier@gmail.com', - description='Play and Record Sound with Python', - long_description=open('README.rst').read(), - license='MIT', - keywords='sound audio PortAudio play record playrec'.split(), - url='http://python-sounddevice.readthedocs.io/', - project_urls={ - 'Source': 'https://github.com/spatialaudio/python-sounddevice', - }, - platforms='any', - classifiers=[ - 'License :: OSI Approved :: MIT License', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Programming Language :: Python :: 3', - 'Topic :: Multimedia :: Sound/Audio', - ], - cmdclass=cmdclass, -) diff --git a/sounddevice.py b/sounddevice.py index 9b9b9e8..a565e3e 100644 --- a/sounddevice.py +++ b/sounddevice.py @@ -48,7 +48,6 @@ https://python-sounddevice.readthedocs.io/ """ -__version__ = '0.5.0' import atexit as _atexit import os as _os