medius 3.2.0

Host control library for the medius transparent mouse passthrough box
Documentation
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "medius"
version = "3.2.0"
description = "Python bindings for the medius transparent mouse passthrough box"
readme = "README.md"
requires-python = ">=3.8"
license = { text = "MIT" }
authors = [{ name = "medius" }]
keywords = ["medius", "mouse", "hid", "serial", "makcu"]
classifiers = [
    "License :: OSI Approved :: MIT License",
    "Programming Language :: Python :: 3",
    "Programming Language :: Rust",
    "Topic :: System :: Hardware",
]

[project.urls]
Homepage = "https://github.com/K4HVH/medius"

[project.optional-dependencies]
test = ["pytest"]

[tool.hatch.build.targets.wheel]
packages = ["medius"]
# The bundled cdylib makes this platform-specific, but ctypes doesn't link the
# CPython ABI; the build hook tags the wheel py3-none-<platform>.
pure-python = false
# The cdylib is produced and copied in by the build hook below.
artifacts = [
    "medius/libmedius_capi.so",
    "medius/libmedius_capi.dylib",
    "medius/medius_capi.dll",
]

# Global hook so it runs for both the wheel build (cargo + bundle + tag) and the
# sdist build (vendor the Rust sources under _rust/ for a self-contained build).
[tool.hatch.build.hooks.custom]
path = "hatch_build.py"

[tool.hatch.build.targets.sdist]
# The build hook vendors the Rust workspace into the sdist under _rust/, so the
# sdist builds with no access to the rest of the repo (and cibuildwheel builds
# from it). These entries are the Python package itself.
include = ["medius", "hatch_build.py", "pyproject.toml"]

# --- cibuildwheel ---
# Build from the self-contained sdist. Each wheel bundles its own cdylib, so
# `pip install medius` needs no Rust toolchain. The build hook runs
# `cargo build --release -p medius-capi` from the vendored sources, so the
# before-all step installs Rust into the build environment. Arch is whatever the
# runner is (the CI matrix runs one runner per arch).
[tool.cibuildwheel]
# The wheel is tagged py3-none-<platform>, so one interpreter per platform
# produces a wheel that installs on every supported Python 3.x. Build the five
# platforms that mirror the C ABI tarballs: glibc Linux x86_64/aarch64 (manylinux),
# macOS arm64 + x86_64, and 64-bit Windows. musllinux, win32, and 32-bit Linux
# (i686) are skipped (no toolchain set up); those users build from the sdist.
build = "cp310-manylinux_* cp310-macosx_* cp310-win_amd64"
build-frontend = "build"
# The bundled wheel has no mock feature, so only smoke-test the import here; the
# mock-backed pytest suite runs against a debug build in the python CI job.
test-command = "python -c \"import medius; print(medius.abi_version(), medius.version_string())\""

[tool.cibuildwheel.linux]
# 64-bit only: cibuildwheel's default Linux archs include i686, which we don't ship.
archs = "auto64"
# The cdylib links libudev (via serialport); the manylinux container lacks it and
# has no rust (the mac/windows runners already ship rust, so they skip this).
before-all = "(yum install -y systemd-devel pkgconfig || dnf install -y systemd-devel pkgconfig) && curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable --profile minimal"
environment = { PATH = "$HOME/.cargo/bin:$PATH" }

[tool.cibuildwheel.macos]
# Both arches: the arm64 runner cross-builds the x86_64 wheel (see hatch_build.py).
archs = "x86_64 arm64"
# rustc's macOS floor is 10.12 (x86_64) / 11.0 (arm64); cibuildwheel defaults
# x86_64 to 10.9, so the cross-built dylib (>=10.12) and the wheel disagree and
# delocate (which reads this env) rejects it. 11.0 satisfies both arches. This
# MUST be set here, not just in the build hook, so the repair step sees it too.
environment = { MACOSX_DEPLOYMENT_TARGET = "11.0" }
# The runner already ships rust; just add the cross target so the arm64 runner
# can also build the x86_64 wheel.
before-all = "rustup target add x86_64-apple-darwin aarch64-apple-darwin"