Skip to content

Commit a3016bc

Browse files
mrecachinasCopilot
andauthored
Migrate to pyproject.toml (#36)
* Migrate from setuptools/setup.py to pyproject.toml and uv - Add pyproject.toml with build configuration and metadata - Simplify setup.py to only define C extension with platform flags - Add uv.lock for reproducible dependency resolution - Move dev dependencies to dependency-groups in pyproject.toml - Move pytest config to pyproject.toml - Remove requirements-dev.txt (now in pyproject.toml) - Remove pytest.ini (now in pyproject.toml) - Update MANIFEST.in for new file structure - Reformat code with black * Replace black with ruff - Swap black for ruff in dev dependencies (faster, includes linting) - Add ruff configuration to pyproject.toml - Fix duplicate test function name caught by ruff linter * Update GitHub Actions workflow for pyproject.toml and uv - Update Python versions: drop 3.6-3.8 (EOL), add 3.11-3.13 - Update runner images: ubuntu-24.04, macos-13/14, windows-2022 - Use native ARM runners for macOS arm64 builds - Use uv for sdist job (setup-uv action) - Replace requirements-dev.txt with direct pip install of test deps - Use unique artifact names to avoid conflicts with v4 upload action - Update artifact download to use pattern matching for multiple artifacts * Use uv for test dependency installation in cibuildwheel CIBW_BEFORE_TEST now installs uv first, then uses uv to install pytest and pytest-benchmark (faster dependency resolution). * Change license to MIT * Fix CI test imports by using --import-mode=importlib Prevents pytest from adding project directory to sys.path, which was causing it to find the hexhamming/ source directory instead of the installed wheel. * Rename hexhamming/ to src/ to fix CI test imports The hexhamming/ directory containing C++ sources was being found by Python as a package, shadowing the installed wheel during tests. * Fix cibuildwheel test isolation issue Use CIBW_TEST_REQUIRES instead of CIBW_BEFORE_TEST to properly install test dependencies into the isolated test virtualenv. Also remove --import-mode=importlib which is no longer needed. * fix: use older-style license format for twine compatibility Use {text = "MIT"} format instead of plain string to avoid PEP 639 metadata (license-expression, license-file) that older twine versions don't recognize. Also add License classifier for better compatibility. * fix: upgrade twine to support PEP 639 license metadata Twine 6.0+ supports the license-file and license-expression fields. Also removed redundant license field since classifier is sufficient. * debug: add twine version output and fix quote escaping * fix: disable auto license-file metadata generation Setuptools auto-detects LICENSE and generates license-file metadata, which requires packaging>=24.2 to validate. Disable this by setting license-files = [] in [tool.setuptools]. The license is still declared via the classifier. * ci: Fix benchmark workflow to not depend on removed requirements-dev.txt * Fix pyproject.toml for modern packaging standards - Use SPDX license expression (license = 'MIT') instead of deprecated classifier - Remove deprecated tool.setuptools.license-files in favor of auto-detection - Bump setuptools requirement to >=77.0.0 for SPDX support - Add Python 3.13 classifier - Fix MANIFEST.in: include LICENSE, exclude *.pyc/*.pyo/*.so/__pycache__ - Add check-manifest config to ignore uv.lock - Verified: twine check passes, check-manifest passes, wheel and sdist both install and work correctly Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Bump twine to >=6.1.0 for Metadata 2.4 / PEP 639 support setuptools>=77 emits License-Expression (Metadata 2.4) which requires twine>=6.1.0 (with packaging>=24.2) to validate. twine 6.0.x rejects these fields as unrecognized. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Pin packaging>=24.2 alongside twine for Metadata 2.4 support CI had twine 6.2.0 but packaging 24.0 — Metadata 2.4 (License-Expression) requires packaging>=24.2. Explicitly pin it in all pip install lines. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 4c72d30 commit a3016bc

File tree

13 files changed

+550
-149
lines changed

13 files changed

+550
-149
lines changed

.github/workflows/benchmark.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
- name: Install dependencies
2727
run: |
2828
python -m pip install --upgrade pip
29-
pip install -r requirements-dev.txt
29+
pip install pytest pytest-benchmark
3030
pip install .
3131
3232
- name: Run benchmarks
@@ -55,7 +55,7 @@ jobs:
5555
- name: Install dependencies
5656
run: |
5757
python -m pip install --upgrade pip
58-
pip install -r requirements-dev.txt
58+
pip install pytest pytest-benchmark
5959
pip install .
6060
6161
- name: Run benchmarks

.github/workflows/pythonpackage.yml

Lines changed: 51 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -11,113 +11,116 @@ on:
1111
jobs:
1212
build-and-test:
1313
name: Testing with Python 3.${{ matrix.python_minor }} on Linux
14-
runs-on: ubuntu-22.04
14+
runs-on: ubuntu-24.04
1515
strategy:
1616
matrix:
17-
python_minor: [ "6" , "7" , "8" , "9" , "10" ]
17+
python_minor: [ "9" , "10" , "11" , "12" , "13" ]
1818

1919
steps:
2020
- uses: actions/checkout@v4.2.2
2121
- name: Install cibuildwheel
2222
run: |
2323
python3 -m pip install --upgrade pip
24-
python3 -m pip install cibuildwheel twine
24+
python3 -m pip install cibuildwheel "twine>=6.1.0" "packaging>=24.2"
2525
2626
- name: 🛠 Build and Test Hexhamming Python C extension
2727
run: cibuildwheel
2828
env:
2929
CIBW_BUILD: ${{ format('cp3{0}-manylinux_x86_64', matrix.python_minor) }}
30-
CIBW_BEFORE_TEST: pip install -r requirements-dev.txt
31-
CIBW_TEST_COMMAND: "pytest -s {project}"
30+
CIBW_TEST_REQUIRES: pytest pytest-benchmark
31+
CIBW_TEST_COMMAND: "pytest -s {project}/test"
3232
CIBW_BUILD_VERBOSITY: 1
3333

3434
- name: Check built wheels
35-
run: twine check wheelhouse/*
35+
run: |
36+
twine --version
37+
twine check wheelhouse/*
3638
3739
sdist:
3840
if: startsWith(github.ref, 'refs/tags')
3941
needs: build-and-test
4042
name: Source distribution
41-
runs-on: macos-13
43+
runs-on: macos-14
4244

4345
steps:
4446
- uses: actions/checkout@v4.2.2
47+
- name: Install uv
48+
uses: astral-sh/setup-uv@v5
49+
4550
- name: Install requirements
4651
run: |
47-
pip3 install --user check-manifest twine
48-
python3 -m pip install --upgrade pip setuptools wheel
49-
python3 -m pip install -r requirements-dev.txt
52+
uv tool install check-manifest
53+
uv tool install "twine>=6.1.0"
54+
uv tool install build
5055
5156
- name: Run check-manifest
52-
run: python3 -m check_manifest
57+
run: check-manifest
5358

5459
- name: Build sdist
55-
run: python3 -m build --sdist --outdir wheelhouse
60+
run: uv build --sdist --out-dir wheelhouse
5661

5762
- name: Install from sdist
58-
run: pip3 install --user wheelhouse/*.tar.gz
63+
run: uv pip install --system wheelhouse/*.tar.gz
5964

6065
- name: Check sdist
61-
run: python3 -m twine check wheelhouse/*
66+
run: |
67+
twine --version
68+
twine check wheelhouse/*
6269
6370
- name: Upload sdist
6471
uses: actions/upload-artifact@v4.4.3
6572
with:
66-
name: wheels
73+
name: sdist
6774
path: wheelhouse/*.tar.gz
6875

6976
wheels_macos:
7077
if: startsWith(github.ref, 'refs/tags')
7178
needs: [build-and-test, sdist]
7279
name: Build macOS ${{ matrix.cibw_python }} ${{ matrix.cibw_arch }} wheels
73-
runs-on: macos-13
80+
runs-on: ${{ matrix.cibw_arch == 'arm64' && 'macos-14' || 'macos-13' }}
7481
strategy:
7582
fail-fast: true
7683
matrix:
77-
cibw_python: [ "cp38-*", "cp39-*", "cp310-*" ]
84+
cibw_python: [ "cp39-*", "cp310-*", "cp311-*", "cp312-*", "cp313-*" ]
7885
cibw_arch: [ "x86_64", "arm64" ]
7986

8087
steps:
8188
- uses: actions/checkout@v4.2.2
8289
- name: Install cibuildwheel
8390
run: |
8491
python3 -m pip install --upgrade pip
85-
python3 -m pip install cibuildwheel twine
86-
echo DEPLOYMENT_TARGET=10.9 >> $GITHUB_ENV
87-
88-
- name: Changing deployment target
89-
if: matrix.cibw_arch == 'arm64'
90-
run: echo DEPLOYMENT_TARGET=12.0 >> $GITHUB_ENV
92+
python3 -m pip install cibuildwheel "twine>=6.1.0" "packaging>=24.2"
9193
9294
- name: 🛠 Build Hexhamming Python C extension
9395
run: cibuildwheel
9496
env:
95-
CIBW_ENVIRONMENT: MACOSX_DEPLOYMENT_TARGET=${{ env.DEPLOYMENT_TARGET }}
9697
CIBW_BUILD: ${{ matrix.cibw_python }}
9798
CIBW_ARCHS_MACOS: ${{ matrix.cibw_arch }}
9899
CIBW_TEST_SKIP: "*-macosx_arm64"
99100
CC: /usr/bin/clang
100101
CXX: /usr/bin/clang++
101102
CFLAGS: "-Wno-implicit-function-declaration"
102-
CIBW_BEFORE_TEST: pip install -r requirements-dev.txt
103-
CIBW_TEST_COMMAND: "pytest -s {project}"
103+
CIBW_TEST_REQUIRES: pytest pytest-benchmark
104+
CIBW_TEST_COMMAND: "pytest -s {project}/test"
104105
CIBW_BUILD_VERBOSITY: 1
105106

106107
- name: Check built wheels
107-
run: twine check wheelhouse/*
108+
run: |
109+
twine --version
110+
twine check wheelhouse/*
108111
109112
- name: Upload built wheels
110113
uses: actions/upload-artifact@v4.4.3
111114
with:
112-
name: wheels
115+
name: wheels-macos-${{ matrix.cibw_arch }}-${{ matrix.cibw_python }}
113116
path: wheelhouse/*.whl
114117
if-no-files-found: error
115118

116119
wheels_linux:
117120
if: startsWith(github.ref, 'refs/tags')
118121
needs: [build-and-test, sdist]
119122
name: Build ${{ matrix.cibw_buildlinux }} ${{ matrix.cibw_arch }} wheels
120-
runs-on: ubuntu-22.04
123+
runs-on: ubuntu-24.04
121124
strategy:
122125
fail-fast: true
123126
matrix:
@@ -135,24 +138,26 @@ jobs:
135138
- name: Install cibuildwheel
136139
run: |
137140
python3 -m pip install --upgrade pip
138-
python3 -m pip install cibuildwheel twine
141+
python3 -m pip install cibuildwheel "twine>=6.1.0" "packaging>=24.2"
139142
140143
- name: 🛠 Build Hexhamming Python C extension
141144
run: cibuildwheel
142145
env:
143146
CIBW_BUILD: ${{ format('cp3*-{0}*', matrix.cibw_buildlinux) }}
144147
CIBW_ARCHS_LINUX: ${{ matrix.cibw_arch }}
145-
CIBW_BEFORE_TEST: pip install -r requirements-dev.txt
146-
CIBW_TEST_COMMAND: "pytest -s {project}"
148+
CIBW_TEST_REQUIRES: pytest pytest-benchmark
149+
CIBW_TEST_COMMAND: "pytest -s {project}/test"
147150
CIBW_BUILD_VERBOSITY: 1
148151

149152
- name: Check built wheels
150-
run: twine check wheelhouse/*
153+
run: |
154+
twine --version
155+
twine check wheelhouse/*
151156
152157
- name: Upload built wheels
153158
uses: actions/upload-artifact@v4.4.3
154159
with:
155-
name: wheels
160+
name: wheels-linux-${{ matrix.cibw_buildlinux }}-${{ matrix.cibw_arch }}
156161
path: wheelhouse/*.whl
157162
if-no-files-found: error
158163

@@ -167,42 +172,45 @@ jobs:
167172
- name: Install cibuildwheel
168173
run: |
169174
python3 -m pip install --upgrade pip
170-
python3 -m pip install cibuildwheel twine
175+
python3 -m pip install cibuildwheel "twine>=6.1.0" "packaging>=24.2"
171176
172177
- name: 🛠 Build Hexhamming Python C extension
173178
run: cibuildwheel
174179
env:
175-
CIBW_BUILD: "cp36-* cp37-* cp38-* cp39-* cp310-*"
180+
CIBW_BUILD: "cp39-* cp310-* cp311-* cp312-* cp313-*"
176181
CIBW_ARCHS_WINDOWS: "AMD64"
177-
CIBW_BEFORE_TEST: pip install -r requirements-dev.txt
178-
CIBW_TEST_COMMAND: "pytest -s {project}"
182+
CIBW_TEST_REQUIRES: pytest pytest-benchmark
183+
CIBW_TEST_COMMAND: "pytest -s {project}/test"
179184
CIBW_BUILD_VERBOSITY: 1
180185

181186
- name: Check built wheels
182-
run: twine check wheelhouse/*
187+
run: |
188+
twine --version
189+
twine check wheelhouse/*
183190
184191
- name: Upload built wheels
185192
uses: actions/upload-artifact@v4.4.3
186193
with:
187-
name: wheels
194+
name: wheels-windows
188195
path: wheelhouse/*.whl
189196
if-no-files-found: error
190197

191198
publish-wheels:
192199
if: startsWith(github.ref, 'refs/tags')
193200
needs: [wheels_macos, wheels_linux, wheels_windows]
194201
name: Publish wheels
195-
runs-on: ubuntu-22.04
202+
runs-on: ubuntu-24.04
196203

197204
steps:
198205
- name: Collect sdist and wheels
199206
uses: actions/download-artifact@v4.1.8
200207
with:
201-
name: wheels
208+
pattern: '{sdist,wheels-*}'
202209
path: wheelhouse
210+
merge-multiple: true
203211

204212
- name: Install twine
205-
run: python -m pip install twine
213+
run: python -m pip install "twine>=6.1.0" "packaging>=24.2"
206214

207215
- name: 📦 Publish distribution to PyPI
208216
env:

LICENSE

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,21 @@
1-
"THE BEERWARE LICENSE" (Revision 42):
2-
Michael Recachinas <mrecachinas@gmail.com> wrote this software. As long as you retain
3-
this notice, you can do whatever you want with this stuff. If we meet some
4-
day, and you think this stuff is worth it, you can buy me a beer in return.
1+
MIT License
2+
3+
Copyright (c) 2026 Michael Recachinas
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

MANIFEST.in

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
include README.rst
2-
include requirements-dev.txt
3-
include pytest.ini
2+
include LICENSE
3+
include pyproject.toml
44

55
graft test
6-
graft hexhamming
6+
graft src
7+
8+
global-exclude *.pyc
9+
global-exclude *.pyo
10+
global-exclude *.so
11+
global-exclude __pycache__

pyproject.toml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
[build-system]
2+
requires = ["setuptools>=77.0.0", "wheel"]
3+
build-backend = "setuptools.build_meta"
4+
5+
[project]
6+
name = "hexhamming"
7+
version = "2.2.3"
8+
description = "Fast Hamming distance calculation for hexadecimal strings"
9+
readme = "README.rst"
10+
license = "MIT"
11+
authors = [
12+
{ name = "Michael Recachinas", email = "m.recachinas@gmail.com" }
13+
]
14+
keywords = ["hamming", "distance", "simd"]
15+
classifiers = [
16+
"Operating System :: MacOS :: MacOS X",
17+
"Operating System :: POSIX :: Linux",
18+
"Operating System :: Microsoft :: Windows",
19+
"Programming Language :: C",
20+
"Programming Language :: Python :: 3",
21+
"Programming Language :: Python :: 3.8",
22+
"Programming Language :: Python :: 3.9",
23+
"Programming Language :: Python :: 3.10",
24+
"Programming Language :: Python :: 3.11",
25+
"Programming Language :: Python :: 3.12",
26+
"Programming Language :: Python :: 3.13",
27+
]
28+
requires-python = ">=3.8"
29+
30+
[project.urls]
31+
Homepage = "https://github.com/mrecachinas/hexhamming"
32+
Repository = "https://github.com/mrecachinas/hexhamming.git"
33+
34+
[dependency-groups]
35+
dev = [
36+
"ruff",
37+
"pytest",
38+
"pytest-benchmark",
39+
]
40+
41+
[tool.setuptools]
42+
zip-safe = false
43+
packages = []
44+
45+
[tool.pytest.ini_options]
46+
testpaths = ["test"]
47+
48+
[tool.check-manifest]
49+
ignore = ["uv.lock"]
50+
51+
[tool.ruff]
52+
line-length = 88
53+
target-version = "py38"
54+
55+
[tool.ruff.format]
56+
quote-style = "double"

pytest.ini

Lines changed: 0 additions & 3 deletions
This file was deleted.

requirements-dev.txt

Lines changed: 0 additions & 3 deletions
This file was deleted.

0 commit comments

Comments
 (0)