From a7e0e7623c2023e6ccf82bc10cbce7f13cc25105 Mon Sep 17 00:00:00 2001 From: Max Bachmann Date: Thu, 19 Sep 2024 22:11:38 +0200 Subject: [PATCH] convert to scikit-build-core --- .github/workflows/pythonbuild.yml | 88 ++++++++++++++----------------- .gitignore | 3 ++ .pre-commit-config.yaml | 32 +++++------ CMakeLists.txt | 2 +- HISTORY.md | 5 ++ MANIFEST.in | 16 ------ README.md | 2 +- _custom_build/backend.py | 51 ------------------ pyproject.toml | 59 ++++++++++++++++++--- setup.py | 33 ------------ src/Levenshtein/CMakeLists.txt | 14 +++-- src/Levenshtein/__init__.py | 2 +- src/Levenshtein/__init__.pyi | 2 +- tools/sdist.patch | 13 +++-- 14 files changed, 134 insertions(+), 188 deletions(-) delete mode 100644 MANIFEST.in delete mode 100644 _custom_build/backend.py delete mode 100644 setup.py diff --git a/.github/workflows/pythonbuild.yml b/.github/workflows/pythonbuild.yml index c17ca73..292655e 100644 --- a/.github/workflows/pythonbuild.yml +++ b/.github/workflows/pythonbuild.yml @@ -12,10 +12,11 @@ jobs: name: Build source distribution runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: 'true' - - uses: actions/setup-python@v4 + + - uses: actions/setup-python@v5 - name: Install dependencies run: | @@ -44,8 +45,9 @@ jobs: run: | tools/seg_wrapper.sh pytest tests - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: + name: artifact-sdist path: dist/*.tar.gz build_wheels_windows: @@ -56,21 +58,17 @@ jobs: fail-fast: false matrix: arch: [auto32, auto64, ARM64] - python_tag: ["cp38-*", "cp39-*", "cp310-*", "cp311-*", "cp312-*", "pp38-*", "pp39-*"] + python_tag: ["cp39-*", "cp310-*", "cp311-*", "cp312-*", "cp313-*", "pp39-*", "pp310-*"] exclude: # PyPy only supports x86_64 on Windows - - arch: auto32 - python_tag: "pp38-*" - arch: auto32 python_tag: "pp39-*" - - # ARM64 only supported only supported on cpython >= 3.9 - - arch: ARM64 - python_tag: "pp38-*" + - arch: auto32 + python_tag: "pp310-*" - arch: ARM64 python_tag: "pp39-*" - arch: ARM64 - python_tag: "cp38-*" + python_tag: "pp310-*" env: CIBW_BUILD: ${{matrix.python_tag}} @@ -80,25 +78,26 @@ jobs: CIBW_BUILD_VERBOSITY: 3 steps: - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: - name: artifact + name: artifact-sdist path: dist - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 - name: Copy wheel run: cp dist/*.tar.gz rapidfuzz.tar.gz - name: Build wheels - uses: pypa/cibuildwheel@v2.16.5 + uses: pypa/cibuildwheel@v2.21.1 with: package-dir: rapidfuzz.tar.gz output-dir: wheelhouse - name: Upload wheels - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: + name: artifact-${{ github.job }}-${{ strategy.job-index }} path: ./wheelhouse/*.whl build_wheels_macos: @@ -109,17 +108,7 @@ jobs: fail-fast: false matrix: arch: [x86_64, arm64, universal2] - python_tag: ["cp38-*", "cp39-*", "cp310-*", "cp311-*", "cp312-*", "pp38-*", "pp39-*"] - exclude: - # PyPy not supported on MacOS Arm - - arch: arm64 - python_tag: "pp38-*" - - arch: arm64 - python_tag: "pp39-*" - - arch: universal2 - python_tag: "pp38-*" - - arch: universal2 - python_tag: "pp39-*" + python_tag: ["cp39-*", "cp310-*", "cp311-*", "cp312-*", "cp313-*", "pp39-*", "pp310-*"] env: CIBW_BUILD: ${{matrix.python_tag}} CIBW_ARCHS: ${{matrix.arch}} @@ -129,25 +118,26 @@ jobs: CIBW_BUILD_VERBOSITY: 3 steps: - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: - name: artifact + name: artifact-sdist path: dist - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 - name: Copy wheel run: cp dist/*.tar.gz rapidfuzz.tar.gz - name: Build wheels - uses: pypa/cibuildwheel@v2.16.5 + uses: pypa/cibuildwheel@v2.21.1 with: package-dir: rapidfuzz.tar.gz output-dir: wheelhouse - name: Upload wheels - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: + name: artifact-${{ github.job }}-${{ strategy.job-index }} path: ./wheelhouse/*.whl build_wheels_linux: @@ -158,17 +148,17 @@ jobs: fail-fast: false matrix: arch: [auto, aarch64, ppc64le, s390x] - python_tag: ["cp38-*", "cp39-*", "cp310-*", "cp311-*", "cp312-*", "pp38-*", "pp39-*"] + python_tag: ["cp39-*", "cp310-*", "cp311-*", "cp312-*", "cp313-*", "pp39-*", "pp310-*"] exclude: # PyPy builds not supported on ppc64le / s390x - - arch: ppc64le - python_tag: "pp38-*" - arch: ppc64le python_tag: "pp39-*" - - arch: s390x - python_tag: "pp38-*" + - arch: ppc64le + python_tag: "pp310-*" - arch: s390x python_tag: "pp39-*" + - arch: s390x + python_tag: "pp310-*" env: CIBW_ARCHS_LINUX: ${{matrix.arch}} CIBW_BUILD: ${{matrix.python_tag}} @@ -178,28 +168,29 @@ jobs: CIBW_BUILD_VERBOSITY: 3 steps: - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: - name: artifact + name: artifact-sdist path: dist - - uses: actions/setup-python@v4 - - - uses: docker/setup-qemu-action@v2 - name: Set up QEMU + - uses: actions/setup-python@v5 - name: Copy wheel run: cp dist/*.tar.gz rapidfuzz.tar.gz + - uses: docker/setup-qemu-action@v3 + name: Set up QEMU + - name: Build wheel - uses: pypa/cibuildwheel@v2.16.5 + uses: pypa/cibuildwheel@v2.21.1 with: package-dir: rapidfuzz.tar.gz output-dir: wheelhouse - name: Upload wheels - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: + name: artifact-${{ github.job }}-${{ strategy.job-index }} path: ./wheelhouse/*.whl deploy-wheels: @@ -211,9 +202,10 @@ jobs: permissions: id-token: write steps: - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: - name: artifact path: dist + pattern: artifact-* + merge-multiple: true - - uses: pypa/gh-action-pypi-publish@v1.8.11 \ No newline at end of file + - uses: pypa/gh-action-pypi-publish@v1.8.11 diff --git a/.gitignore b/.gitignore index 16f0fdc..f7ac383 100644 --- a/.gitignore +++ b/.gitignore @@ -140,3 +140,6 @@ cython_debug/ # vscode .vscode/ _skbuild/ + +# Cython generated files +*.cxx diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 57a3b6f..fdebfd8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,10 +12,15 @@ # # See https://github.com/pre-commit/pre-commit +exclude: | + (?x)( + .*\.patch + ) + repos: # Standard hooks - repo: https://github.com/pre-commit/pre-commit-hooks - rev: "v4.5.0" + rev: "v4.6.0" hooks: - id: check-added-large-files - id: check-case-conflict @@ -32,13 +37,13 @@ repos: # Black, the code formatter, natively supports pre-commit - repo: https://github.com/psf/black - rev: "24.1.1" # Keep in sync with blacken-docs + rev: "24.8.0" # Keep in sync with blacken-docs hooks: - id: black # Also code format the docs - repo: https://github.com/asottile/blacken-docs - rev: "1.16.0" + rev: "1.18.0" hooks: - id: blacken-docs additional_dependencies: @@ -46,12 +51,12 @@ repos: # Changes tabs to spaces - repo: https://github.com/Lucas-C/pre-commit-hooks - rev: "v1.5.4" + rev: "v1.5.5" hooks: - id: remove-tabs - repo: https://github.com/sirosen/texthooks - rev: "0.6.4" + rev: "0.6.7" hooks: - id: fix-ligatures - id: fix-smartquotes @@ -68,7 +73,7 @@ repos: # PyLint has native support - not always usable, but works for us - repo: https://github.com/PyCQA/pylint - rev: "v3.0.3" + rev: "v3.2.7" hooks: - id: pylint files: ^pybind11 @@ -91,24 +96,15 @@ repos: # exclude: ^(tests|docs)/ # additional_dependencies: [nox, rich] -# Checks the manifest for missing files (native support) -- repo: https://github.com/mgedmin/check-manifest - rev: "0.49" - hooks: - - id: check-manifest - # This is a slow hook, so only run this if --hook-stage manual is passed - stages: [manual] - additional_dependencies: [cmake, ninja] - - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.2.1 + rev: v0.6.5 hooks: - id: ruff args: ["--fix", "--show-fixes"] # Check for spelling - repo: https://github.com/codespell-project/codespell - rev: "v2.2.6" + rev: "v2.3.0" hooks: - id: codespell exclude: ".*/test_.*.py" @@ -131,7 +127,7 @@ repos: # Clang format the codebase automatically - repo: https://github.com/pre-commit/mirrors-clang-format - rev: "v17.0.6" + rev: "v18.1.8" hooks: - id: clang-format types_or: [c++, c] diff --git a/CMakeLists.txt b/CMakeLists.txt index 665f92d..24d2ede 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.12...3.24) +cmake_minimum_required(VERSION 3.15...3.26) cmake_policy(SET CMP0054 NEW) set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) diff --git a/HISTORY.md b/HISTORY.md index ae7e693..42c44e5 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,10 @@ ## Changelog +### v0.26.0 +#### Changed +- add support for Python 3.13 +- switch build system to `scikit-build-core` + ### v0.25.1 #### Fixed - fix potentially incorrect results of `jaro_winkler` when using high prefix weights diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 4bf6c43..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,16 +0,0 @@ -include setup.py -include CMakeLists.txt -include README.md -include COPYING -include HISTORY.md -include pyproject.toml -include _custom_build/backend.py -include src/Levenshtein/py.typed - -recursive-include src/Levenshtein CMakeLists.txt -recursive-include src/Levenshtein *.hpp *.h *.cpp *.pyx *.pxd *.cxx *.pyi -recursive-include tests * - -include extern/rapidfuzz-cpp/LICENSE -include extern/rapidfuzz-cpp/CMakeLists.txt -recursive-include extern/rapidfuzz-cpp/rapidfuzz *.hpp *.impl diff --git a/README.md b/README.md index 557fc50..6e7670b 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ computation of: * string sequence and set similarity ## Requirements -* Python 3.8 or later +* Python 3.9 or later ## Installation ```bash diff --git a/_custom_build/backend.py b/_custom_build/backend.py deleted file mode 100644 index 125845a..0000000 --- a/_custom_build/backend.py +++ /dev/null @@ -1,51 +0,0 @@ -from __future__ import annotations - -import platform as _platform -import subprocess as _subprocess - -from packaging import version as _version -from setuptools import build_meta as _orig -from skbuild.cmaker import get_cmake_version as _get_cmake_version -from skbuild.exceptions import SKBuildError as _SKBuildError - -prepare_metadata_for_build_wheel = _orig.prepare_metadata_for_build_wheel -build_wheel = _orig.build_wheel -build_sdist = _orig.build_sdist -get_requires_for_build_sdist = _orig.get_requires_for_build_sdist - - -def _cmake_required(): - try: - if _version.parse(_get_cmake_version().split("-")[0]) >= _version.parse("3.12"): - print("Using System version of cmake") - return False - except _SKBuildError: - pass - - return True - - -def _ninja_required(): - if _platform.system() == "Windows": - print("Ninja is part of the MSVC installation on Windows") - return False - - for generator in ("ninja", "make"): - try: - _subprocess.check_output([generator, "--version"]) - print(f"Using System version of {generator}") - return False - except (OSError, _subprocess.CalledProcessError): - pass - - return True - - -def get_requires_for_build_wheel(config_settings=None): - packages = [] - if _cmake_required(): - packages.append("cmake") - if _ninja_required(): - packages.append("ninja") - - return _orig.get_requires_for_build_wheel(config_settings) + packages diff --git a/pyproject.toml b/pyproject.toml index bb711c4..e1bae91 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,19 +1,64 @@ [build-system] requires = [ - "setuptools", - "scikit-build>=0.13.0", + "scikit-build-core>=0.10.6", "Cython>=3.0.2,<3.1.0" ] -build-backend = "backend" -backend-path = ["_custom_build"] +build-backend = "scikit_build_core.build" +[project] +name = "Levenshtein" +dynamic = ["version"] +dependencies = [ + "rapidfuzz >= 3.9.0, < 4.0.0" +] +requires-python = ">= 3.9" +authors = [ + {name = "Max Bachmann", email = "pypi@maxbachmann.de"}, +] +description = "Python extension for computing string edit distances and similarities." +readme = "README.md" +classifiers=[ + "Programming Language :: Python :: 3", + "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", + "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)", +] +Homepage = "https://github.com/rapidfuzz/Levenshtein" +Documentation = "https://rapidfuzz.github.io/Levenshtein/" +Repository = "https://github.com/rapidfuzz/Levenshtein.git" +Issues = "https://github.com/rapidfuzz/Levenshtein/issues" +Changelog = "https://github.com/rapidfuzz/Levenshtein/blob/main/HISTORY.md" + +[tool.scikit-build] +sdist.include = [ + "src/Levenshtein/*.cxx", + "src/Levenshtein/_version.py" +] +sdist.exclude = [ + ".github" +] +wheel.exclude = [ + "**.pyx", + "**.cxx", + "**.cpp", + "**.hpp", + "CMakeLists.txt", + "generate.sh" +] + +[tool.scikit-build.metadata.version] +provider = "scikit_build_core.metadata.regex" +input = "src/Levenshtein/__init__.py" [tool.black] line-length = 120 [tool.mypy] files = ["src"] -python_version = "3.8" +python_version = "3.9" warn_unused_configs = true show_error_codes = true enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"] @@ -29,7 +74,7 @@ xfail_strict = true log_cli_level = "info" [tool.pylint] -py-version = "3.8" +py-version = "3.9" [tool.pylint.reports] output-format = "colorized" @@ -80,7 +125,7 @@ extend-ignore = [ "PTH123", # use pathlib instead of builtin open "PLC1901", # simply not always correct ] -target-version = "py38" +target-version = "py39" src = ["src"] unfixable = [ "T20", # Removes print statements diff --git a/setup.py b/setup.py deleted file mode 100644 index 3d8c93b..0000000 --- a/setup.py +++ /dev/null @@ -1,33 +0,0 @@ -from __future__ import annotations - -from skbuild import setup - -with open("README.md", encoding="utf8") as f: - readme = f.read() - -setup( - name="Levenshtein", - version="0.25.1", - url="https://github.com/rapidfuzz/Levenshtein", - author="Max Bachmann", - install_requires=["rapidfuzz >= 3.8.0, < 4.0.0"], - author_email="pypi@maxbachmann.de", - description="Python extension for computing string edit distances and similarities.", - long_description=readme, - long_description_content_type="text/markdown", - license="GPL", - license_file="COPYING", - classifiers=[ - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)", - ], - packages=["Levenshtein"], - package_dir={"": "src"}, - package_data={"Levenshtein": ["*.pyi", "py.typed"]}, - python_requires=">=3.8", -) diff --git a/src/Levenshtein/CMakeLists.txt b/src/Levenshtein/CMakeLists.txt index 5bd14ca..721f7a7 100644 --- a/src/Levenshtein/CMakeLists.txt +++ b/src/Levenshtein/CMakeLists.txt @@ -4,10 +4,16 @@ function(create_cython_target _name) ${CMAKE_CURRENT_LIST_DIR}/${_name}.cxx PARENT_SCOPE) else() - find_package(Cython REQUIRED) - add_cython_target(${_name} CXX) + add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${_name}.cxx" + MAIN_DEPENDENCY "${CMAKE_CURRENT_LIST_DIR}/${_name}.pyx" + VERBATIM + COMMAND + Python::Interpreter -m cython "${CMAKE_CURRENT_LIST_DIR}/${_name}.pyx" + --output-file "${CMAKE_CURRENT_BINARY_DIR}/${_name}.cxx") + set(${_name} - ${_name} + ${CMAKE_CURRENT_BINARY_DIR}/${_name}.cxx PARENT_SCOPE) endif() endfunction(create_cython_target) @@ -35,4 +41,4 @@ target_compile_features(levenshtein_cpp PUBLIC cxx_std_17) target_include_directories(levenshtein_cpp PRIVATE ${LEV_BASE_DIR}/Levenshtein-c) target_link_libraries(levenshtein_cpp PRIVATE rapidfuzz::rapidfuzz) -install(TARGETS levenshtein_cpp LIBRARY DESTINATION src/Levenshtein) +install(TARGETS levenshtein_cpp DESTINATION Levenshtein/) diff --git a/src/Levenshtein/__init__.py b/src/Levenshtein/__init__.py index bdd1858..e842d90 100644 --- a/src/Levenshtein/__init__.py +++ b/src/Levenshtein/__init__.py @@ -18,7 +18,7 @@ __author__: str = "Max Bachmann" __license__: str = "GPL" -__version__: str = "0.25.1" +__version__: str = "0.26.0" import rapidfuzz.distance.Hamming as _Hamming import rapidfuzz.distance.Indel as _Indel diff --git a/src/Levenshtein/__init__.pyi b/src/Levenshtein/__init__.pyi index 606d069..8b51e27 100644 --- a/src/Levenshtein/__init__.pyi +++ b/src/Levenshtein/__init__.pyi @@ -1,7 +1,7 @@ from __future__ import annotations -from typing import overload from collections.abc import Callable, Hashable, Sequence +from typing import overload __author__: str __license__: str diff --git a/tools/sdist.patch b/tools/sdist.patch index d3354c6..8cbba9a 100644 --- a/tools/sdist.patch +++ b/tools/sdist.patch @@ -1,14 +1,13 @@ diff --git a/pyproject.toml b/pyproject.toml -index 27f4629..752d509 100644 +index 0a8c033..cf967b9 100644 --- a/pyproject.toml +++ b/pyproject.toml -@@ -1,8 +1,7 @@ +@@ -1,7 +1,6 @@ [build-system] requires = [ - "setuptools", -- "scikit-build>=0.13.0", +- "scikit-build-core>=0.10.6", - "Cython>=3.0.2,<3.1.0" -+ "scikit-build>=0.13.0" ++ "scikit-build-core>=0.10.6" ] - build-backend = "backend" - backend-path = ["_custom_build"] + build-backend = "scikit_build_core.build" +