Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
256 changes: 126 additions & 130 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ jobs:
steps:
- name: Checkout source
uses: actions/checkout@v4.2.2
- name: Set up Python 3.13 for linting
- name: Set up Python 3.14 for linting
uses: actions/setup-python@v5.6.0
with:
python-version: '3.13'
python-version: '3.14'
- name: Install dependencies
run: |-
python -m pip install pip uv -U
Expand All @@ -34,6 +34,11 @@ jobs:
run: |-
# stop the build if there are Python syntax errors or undefined names
flake8 ./pyhesaff --count --select=E9,F63,F7,F82 --show-source --statistics
- name: Typecheck
run: |-
python -m pip install ty
pip install -r requirements/runtime.txt
ty check ./pyhesaff
build_binpy_wheels:
##
# Build the binary wheels. Note: even though cibuildwheel will test
Expand All @@ -60,6 +65,11 @@ jobs:
steps:
- name: Checkout source
uses: actions/checkout@v4.2.2
- name: Enable MSVC 64bit
uses: ilammy/msvc-dev-cmd@v1
if: ${{ startsWith(matrix.os, 'windows-') }} && ${{ contains(matrix.cibw_skip, '*-win32') }}
with:
arch: ${{ contains(matrix.os, 'arm') && 'arm64' || 'x64' }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3.0.0
if: runner.os == 'Linux' && matrix.arch != 'auto'
Expand All @@ -68,7 +78,7 @@ jobs:
- name: Set vcpkg cache paths (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
run: |-
"VCPKG_ARCHIVES_DIR=$env:LOCALAPPDATA\vcpkg\archives" >> $env:GITHUB_ENV
"VCPKG_DOWNLOADS_DIR=C:\vcpkg\downloads" >> $env:GITHUB_ENV
New-Item -ItemType Directory -Force -Path "$env:LOCALAPPDATA\vcpkg\archives" | Out-Null
Expand All @@ -81,44 +91,61 @@ jobs:
path: |-
${{ env.VCPKG_ARCHIVES_DIR }}
${{ env.VCPKG_DOWNLOADS_DIR }}
key: vcpkg-${{ runner.os }}-${{ hashFiles('pyproject.toml', 'CMakeLists.txt', 'setup.py') }}
restore-keys: |
vcpkg-${{ runner.os }}-
- name: Check dumpbin availability (Windows)
key: vcpkg-${{ runner.os }}-${{ hashFiles('pyproject.toml', 'CMakeLists.txt', 'setup.py', 'vcpkg.json', 'vcpkg-configuration.json') }}
restore-keys: vcpkg-${{ runner.os }}-
- name: Ensure vcpkg (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |-
if (-not (Test-Path "C:\vcpkg")) {
git clone https://github.com/microsoft/vcpkg C:\vcpkg
}
Set-Location C:\vcpkg
.\bootstrap-vcpkg.bat -disableMetrics
"C:\vcpkg" | Out-File -FilePath $env:GITHUB_PATH -Append
- name: Install OpenCV via vcpkg (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: vcpkg install opencv4:x64-windows
- name: Show cibuildwheel Windows env (Windows)
if: runner.os == 'Windows'
shell: bash
env:
CIBW_ENVIRONMENT_WINDOWS: |-
VCPKG_ROOT=C:/vcpkg
VCPKG_TARGET_TRIPLET=x64-windows
VCPKG_DOWNLOADS=C:/vcpkg/downloads
PATH=C:/vcpkg;C:/vcpkg/installed/x64-windows/bin;{PATH}
OpenCV_DIR=C:/vcpkg/installed/x64-windows/share/opencv4
OpenCV_ROOT=C:/vcpkg/installed/x64-windows
CMAKE_PREFIX_PATH=C:/vcpkg/installed/x64-windows
CMAKE_ARGS=-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake;-DOpenCV_DIR=C:/vcpkg/installed/x64-windows/share/opencv4
run: |-
where dumpbin || true
dumpbin /? || true
echo "CIBW_ENVIRONMENT_WINDOWS:"
printf '%s\n' "$CIBW_ENVIRONMENT_WINDOWS"
- name: Build binary wheels
uses: pypa/cibuildwheel@v3.1.2
with:
output-dir: wheelhouse
config-file: pyproject.toml
env:
CIBW_SKIP: ${{ matrix.cibw_skip }}
CIBW_TEST_SKIP: '*-win_arm64'
CIBW_ARCHS_LINUX: ${{ matrix.arch }}
PYTHONUTF8: '1'
VSCMD_ARG_TGT_ARCH: ''
CIBW_ARCHS_WINDOWS: AMD64
CIBW_ENVIRONMENT_WINDOWS: |
CIBW_ENVIRONMENT_WINDOWS: |-
VCPKG_ROOT=C:/vcpkg
VCPKG_TARGET_TRIPLET=x64-windows
VCPKG_DOWNLOADS=C:/vcpkg/downloads
PATH=C:/vcpkg;C:/vcpkg/installed/x64-windows/bin;{PATH}
OpenCV_DIR=C:/vcpkg/installed/x64-windows/share/opencv4
OpenCV_ROOT=C:/vcpkg/installed/x64-windows
CMAKE_PREFIX_PATH=C:/vcpkg/installed/x64-windows
CMAKE_ARGS=-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake;-DOpenCV_DIR=C:/vcpkg/installed/x64-windows/share/opencv4
VCPKG_BINARY_SOURCES=clear;files,C:/vcpkg-bincache,readwrite
VCPKG_DOWNLOADS=C:/vcpkg/downloads
PATH=C:/vcpkg/installed/x64-windows/bin;{PATH}
VCPKG_TARGET_TRIPLET=x64-windows
PYTHONUTF8: '1'
VCPKG_ROOT: C:\vcpkg
VCPKG_TARGET_TRIPLET: x64-windows
- name: Show cibuildwheel Windows env (Windows)
if: runner.os == 'Windows'
shell: bash
run: |-
echo "CIBW_ENVIRONMENT_WINDOWS:"
printf '%s\n' "$CIBW_ENVIRONMENT_WINDOWS"
- name: Save vcpkg caches (Windows, even on failure)
if: runner.os == 'Windows' && always()
uses: actions/cache/save@v4
Expand All @@ -130,11 +157,11 @@ jobs:
- name: Show built files
shell: bash
run: ls -la wheelhouse
- name: Set up Python 3.13 to combine coverage
- name: Set up Python 3.14 to combine coverage
uses: actions/setup-python@v5.6.0
if: runner.os == 'Linux'
with:
python-version: '3.13'
python-version: '3.14'
- name: Combine coverage Linux
if: runner.os == 'Linux'
run: |-
Expand Down Expand Up @@ -187,13 +214,25 @@ jobs:
# for testing instead of using the more concise matrix notation.
include:
- python-version: '3.9'
install-extras: tests,runtime,headless
install-extras: tests-strict,runtime-strict,headless-strict
os: ubuntu-latest
arch: auto
- python-version: '3.13'
install-extras: tests,runtime,optional,headless
- python-version: '3.9'
install-extras: tests-strict,runtime-strict,headless-strict
os: windows-latest
arch: auto
- python-version: '3.14'
install-extras: tests-strict,runtime-strict,optional-strict,headless-strict
os: ubuntu-latest
arch: auto
- python-version: '3.14'
install-extras: tests-strict,runtime-strict,optional-strict,headless-strict
os: windows-latest
arch: auto
- python-version: '3.14'
install-extras: tests,headless
os: windows-latest
arch: auto
- python-version: '3.9'
install-extras: tests,optional,headless
os: ubuntu-latest
Expand Down Expand Up @@ -226,6 +265,10 @@ jobs:
install-extras: tests,optional,headless
os: windows-latest
arch: auto
- python-version: '3.11'
install-extras: tests,optional,headless
os: windows-latest
arch: auto
- python-version: '3.12'
install-extras: tests,optional,headless
os: windows-latest
Expand All @@ -234,9 +277,18 @@ jobs:
install-extras: tests,optional,headless
os: windows-latest
arch: auto
- python-version: '3.14'
install-extras: tests,optional,headless
os: windows-latest
arch: auto
steps:
- name: Checkout source
uses: actions/checkout@v4.2.2
- name: Enable MSVC 64bit
uses: ilammy/msvc-dev-cmd@v1
if: ${{ startsWith(matrix.os, 'windows-') }}
with:
arch: ${{ contains(matrix.os, 'arm') && 'arm64' || 'x64' }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3.0.0
if: runner.os == 'Linux' && matrix.arch != 'auto'
Expand All @@ -252,63 +304,6 @@ jobs:
pattern: wheels-*
merge-multiple: true
path: wheelhouse
- name: Inspect wheel contents (Windows)
if: runner.os == 'Windows'
shell: bash
run: |-
python - <<'PY'
import pathlib
import zipfile
dist_dpath = pathlib.Path("wheelhouse")
wheels = sorted(dist_dpath.glob("pyhesaff*-win_amd64.whl"))
if not wheels:
raise SystemExit("No Windows wheels found in wheelhouse")
print("Found Windows wheels:", [w.name for w in wheels])
for wheel in wheels:
print("===", wheel.name, "===")
with zipfile.ZipFile(wheel) as zf:
members = [m for m in zf.namelist() if "pyhesaff/" in m]
for name in sorted(members):
print(name)
PY
- name: Validate wheel native module (Windows)
if: runner.os == 'Windows'
shell: bash
run: |-
python - <<'PY'
import pathlib
import zipfile
dist_dpath = pathlib.Path("wheelhouse")
wheels = sorted(dist_dpath.glob("pyhesaff*-win_amd64.whl"))
if not wheels:
raise SystemExit("No Windows wheels found in wheelhouse")
for wheel in wheels:
with zipfile.ZipFile(wheel) as zf:
members = set(zf.namelist())
pyds = [name for name in members if name.startswith("pyhesaff/_hesaff") and name.endswith(".pyd")]
if not pyds:
raise SystemExit(f"{wheel.name} missing pyhesaff/_hesaff*.pyd")
dlls = [name for name in members if name.startswith("pyhesaff.libs/") and name.lower().endswith(".dll")]
if not dlls:
raise SystemExit(f"{wheel.name} missing pyhesaff.libs/*.dll")
print(f"{wheel.name} contains {pyds[0]} and {len(dlls)} bundled dll(s).")
PY
- name: Show wheel DLL dependencies (Windows)
if: runner.os == 'Windows'
shell: bash
run: |-
python -m pip install delvewheel
python - <<'PY'
import pathlib
import subprocess
import sys
wheels = sorted(pathlib.Path("wheelhouse").glob("pyhesaff*-win_amd64.whl"))
if not wheels:
raise SystemExit("No Windows wheels found in wheelhouse")
for wheel in wheels:
print("===", wheel.name, "===")
subprocess.run([sys.executable, "-m", "delvewheel", "show", str(wheel)], check=False)
PY
- name: Install wheel ${{ matrix.install-extras }}
shell: bash
env:
Expand All @@ -327,72 +322,73 @@ jobs:
from packaging import tags
from packaging.utils import parse_wheel_filename
dist_dpath = pathlib.Path('wheelhouse')
candidates = sorted(dist_dpath.glob('pyhesaff*.whl'))
if not candidates:
raise SystemExit('No wheels found in wheelhouse')
sys_tags = set(tags.sys_tags())
def is_compatible(path):
_, _, _, wheel_tags = parse_wheel_filename(path.name)
return any(tag in sys_tags for tag in wheel_tags)
compatible = [path for path in candidates if is_compatible(path)]
fpath = sorted(compatible or candidates)[-1]
wheels = sorted(dist_dpath.glob('pyhesaff*.whl'))
if wheels:
sys_tags = set(tags.sys_tags())
matching = []
for w in wheels:
try:
_, _, _, wheel_tags = parse_wheel_filename(w.name)
except Exception:
continue
if any(t in sys_tags for t in wheel_tags):
matching.append(w)
fpath = sorted(matching or wheels)[-1]
else:
sdists = sorted(dist_dpath.glob('pyhesaff*.tar.gz'))
if not sdists:
raise SystemExit('No wheel artifacts found in wheelhouse')
fpath = sdists[-1]
print(str(fpath).replace(chr(92), chr(47)))
")
export MOD_VERSION=$(python -c "if 1:
from packaging.utils import parse_wheel_filename
from pkginfo import Wheel, SDist
import pathlib
fpath = '$WHEEL_FPATH'
_, version, _, _ = parse_wheel_filename(fpath.split('/')[-1])
print(version)
cls = Wheel if fpath.endswith('.whl') else SDist
item = cls(fpath)
print(item.version)
")
echo "WHEEL_FPATH=$WHEEL_FPATH"
echo "INSTALL_EXTRAS=$INSTALL_EXTRAS"
echo "UV_RESOLUTION=$UV_RESOLUTION"
echo "MOD_VERSION=$MOD_VERSION"
python -m uv pip install --prerelease=allow "pyhesaff[$INSTALL_EXTRAS]==$MOD_VERSION" -f wheelhouse
python -m pip install --prefer-binary "pyhesaff[$INSTALL_EXTRAS]==$MOD_VERSION" -f wheelhouse
echo "Install finished."
- name: Windows wheel diagnostics
- name: Smoke test wheel on Windows
if: runner.os == 'Windows'
shell: bash
run: |-
python - <<'PY'
import os
import sys
import site
print("site.getsitepackages():", site.getsitepackages())
try:
import pyhesaff
print("pyhesaff imported from:", pyhesaff.__file__)
except Exception as exc:
print("pyhesaff import failed:", repr(exc))
for sp in site.getsitepackages():
pkg_dir = os.path.join(sp, "pyhesaff")
if os.path.isdir(pkg_dir):
print("Contents of", pkg_dir)
for name in sorted(os.listdir(pkg_dir)):
print(" -", name)
PY
- name: Windows smoke test
if: runner.os == 'Windows'
shell: bash
run: |-
python - <<'PY'
import os
import sys
repo_dir = os.path.abspath(os.getcwd())
sys.path = [
path for path in sys.path
if path and os.path.abspath(path) != repo_dir
]
import pyhesaff
print("pyhesaff imported from:", pyhesaff.__file__)
print("cpp_version:", pyhesaff.get_cpp_version())
import os, sys
import pathlib

ws = os.environ.get("GITHUB_WORKSPACE")
if ws:
ws_path = pathlib.Path(ws).resolve()
new_sys_path = []
for entry in sys.path:
if not entry:
new_sys_path.append(entry)
continue
try:
p = pathlib.Path(entry).resolve()
if p.is_relative_to(ws_path):
continue
except Exception:
pass
new_sys_path.append(entry)
sys.path[:] = new_sys_path

import pyhesaff as mod
print("pyhesaff:", mod.__file__)

PY
- name: Test wheel ${{ matrix.install-extras }}
shell: bash
env:
CI_PYTHON_VERSION: py${{ matrix.python-version }}
run: |-
python -m pip install pytest pytest-cov xdoctest
echo "Creating test sandbox directory"
export WORKSPACE_DNAME="testdir_${CI_PYTHON_VERSION}_${GITHUB_RUN_ID}_${RUNNER_OS}"
echo "WORKSPACE_DNAME=$WORKSPACE_DNAME"
Expand Down Expand Up @@ -639,4 +635,4 @@ jobs:
# --secret=EROTEMIC_TWINE_USERNAME=$EROTEMIC_TWINE_USERNAME \
# --secret=EROTEMIC_CI_SECRET=$EROTEMIC_CI_SECRET \
# --secret=EROTEMIC_TEST_TWINE_USERNAME=$EROTEMIC_TEST_TWINE_USERNAME \
# --secret=EROTEMIC_TEST_TWINE_PASSWORD=$EROTEMIC_TEST_TWINE_PASSWORD
# --secret=EROTEMIC_TEST_TWINE_PASSWORD=$EROTEMIC_TEST_TWINE_PASSWORD
1 change: 1 addition & 0 deletions pyhesaff/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ def detect_feats_main():
import ubelt as ub

img_fpath = ub.argval('--fname', default=grab_test_imgpath())
assert isinstance(img_fpath, str)
kwargs = argparse_hesaff_params()
print('kwargs = %r' % (kwargs,))

Expand Down
Loading
Loading