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
3 changes: 0 additions & 3 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@ jobs:
- windows-latest
- windows-11-arm
python-version:
- '3.9'
- '3.10'
- '3.11'
- '3.12'
Expand All @@ -153,8 +152,6 @@ jobs:

# CPython ships no Windows ARM64 build before 3.11.
exclude:
- os: windows-11-arm
python-version: '3.9'
- os: windows-11-arm
python-version: '3.10'

Expand Down
21 changes: 11 additions & 10 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -350,9 +350,12 @@ The binding builds with `-Wall -Wextra -Wpedantic`, `/W4 /WX` on MSVC.

Indentation is tabs, on both sides. Lines stay within 80 columns.

The package targets Python 3.9, so `from __future__ import annotations` goes
at the top of every module that annotates anything, and `X | None` is written
only under it.
`from __future__ import annotations` goes at the top of every module that
annotates anything, so that no annotation is evaluated at import. That is what
lets one name something imported only under `TYPE_CHECKING`, as
`em/image/_functions.py` does with numpy, which the package does not depend on
at run time. Python 3.14 defers annotations by itself; until 3.13 is dropped,
the import is what does it.

Module-level state uses two leading underscores — `__pool`, `__default_catalog`,
`__local`. Python mangles nothing at module scope, so this is a convention
Expand Down Expand Up @@ -432,11 +435,9 @@ share them.
files are collected by pytest from where they are, so moving one needs no
change to CMake.

numpy is a test requirement, pinned per Python version from 2.0 to 2.5, and
it takes and gives versioned DLPack tensors only from 2.1 on. A test that
needs that carries the `numpy_speaks_dlpack_1` mark and is skipped on Python
3.9. What the binding itself does with a versioned or a read-only tensor is
tested with the hand-made one, on every version.
numpy is a test requirement, pinned per Python version from 2.2 to 2.5, all of
which take and give versioned DLPack tensors. What the binding itself does
with a versioned or a read-only tensor is tested with the hand-made one.

torch and JAX are not test requirements. A test that needs one starts with
`pytest.importorskip`, so it runs where the library is installed and is
Expand All @@ -454,8 +455,8 @@ skipped in CI.
`build_with_cmake` covers Linux with gcc and clang, macOS, and Windows on both
architectures; it exists to keep the plain CMake path working and to produce
the compilation database the scanner reads. `build_with_pip` is the one that
runs the tests, across five platforms and Python 3.9 through 3.14, minus the
Windows ARM entries for the versions CPython never shipped there.
runs the tests, across five platforms and Python 3.10 through 3.14, minus
Windows ARM on 3.10, which CPython never shipped there.

Both build rexlib first, into a prefix outside the project, and point the
build at it with `rexlib_ROOT`. It is the bulk of the wall clock, and ccache
Expand Down
8 changes: 2 additions & 6 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
requires = [
"scikit-build-core==1.0.3",
"pybind11-stubgen==2.5.5",
"numpy==2.0.2; python_version < '3.10' and platform_machine != 'ARM64'",
"numpy==2.2.6; python_version == '3.10' and platform_machine != 'ARM64'",
"numpy==2.4.6; python_version == '3.11'",
"numpy==2.5.3; python_version >= '3.12'",
Expand All @@ -25,7 +24,6 @@ classifiers = [
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
Expand All @@ -37,17 +35,15 @@ classifiers = [
readme = {file = "README.md", content-type = "text/markdown"}
license = "GPL-3.0-only"

requires-python = ">=3.9"
requires-python = ">=3.10"
dependencies = []

[project.optional-dependencies]
test = [
"numpy==2.0.2; python_version < '3.10' and platform_machine != 'ARM64'",
"numpy==2.2.6; python_version == '3.10' and platform_machine != 'ARM64'",
"numpy==2.4.6; python_version == '3.11'",
"numpy==2.5.3; python_version >= '3.12'",
"pytest==8.4.2; python_version < '3.10'",
"pytest==9.1.1; python_version >= '3.10'",
"pytest==9.1.1",
"pytest-cov==7.1.0",
"ruff==0.16.9",
]
Expand Down
10 changes: 6 additions & 4 deletions python/rexlib/_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@
from __future__ import annotations

from types import TracebackType
from typing import Union

from ._context import _set_active_execution_context, get_active_execution_context
from ._binding import dispatch, hardware
from ._session_pool import get_pooled_device_session

DeviceSpec = Union[
str, hardware.DeviceIndex, hardware.DeviceSession, hardware.DeviceContext
]
DeviceSpec = (
str
| hardware.DeviceIndex
| hardware.DeviceSession
| hardware.DeviceContext
)

def _resolve_device_context(spec: DeviceSpec) -> hardware.DeviceContext:
if isinstance(spec, hardware.DeviceContext):
Expand Down
14 changes: 0 additions & 14 deletions renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,6 @@
"matchDepNames": ["python", "gigabit-clowns/.github"],
"enabled": false
},
{
"description": "Cap the pytest 3.9 pin to releases that still support 3.9; 9.0.0 raised requires-python to >=3.10.",
"matchDepNames": ["pytest"],
"matchCurrentVersion": "<9",
"constraints": { "python": "3.9" },
"constraintsFiltering": "strict"
},
{
"description": "Cap the numpy 3.9 pin to releases that still support 3.9; 2.1.0 raised requires-python to >=3.10.",
"matchDepNames": ["numpy"],
"matchCurrentVersion": "<2.1",
"constraints": { "python": "3.9" },
"constraintsFiltering": "strict"
},
{
"description": "Cap the numpy 3.10 pin to releases that still support 3.10; 2.3.0 raised requires-python to >=3.11.",
"matchDepNames": ["numpy"],
Expand Down
2 changes: 1 addition & 1 deletion ruff.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
target-version = "py39"
target-version = "py310"

include = [
"python/**/*.py",
Expand Down
2 changes: 1 addition & 1 deletion scripts/check_wheels_agree.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def main(directory: str) -> int:
print(f" {wheel.name}: size {len(other)}, expected {len(reference)}")
failed = True
continue
differing = sum(a != b for a, b in zip(reference, other))
differing = sum(a != b for a, b in zip(reference, other, strict=True))
verdict = "ok" if differing <= TOLERANCE else "DIFFERS"
print(f" {wheel.name}: {differing} byte(s) differ - {verdict}")
failed |= differing > TOLERANCE
Expand Down
2 changes: 1 addition & 1 deletion sonar-project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ sonar.issue.ignore.multicriteria=pybind_operators
sonar.issue.ignore.multicriteria.pybind_operators.ruleKey=cpp:S1764
sonar.issue.ignore.multicriteria.pybind_operators.resourceKey=src/**
sonar.cfamily.compile-commands=build/compile_commands.json
sonar.python.version=3.9,3.10,3.11,3.12,3.13,3.14
sonar.python.version=3.10,3.11,3.12,3.13,3.14
sonar.python.coverage.reportPaths=coverage.xml
8 changes: 0 additions & 8 deletions tests/ndarray/test_dlpack.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,6 @@
FLOAT32_PAIR = (2, 32, 2)
READ_ONLY = 1

numpy_speaks_dlpack_1 = pytest.mark.skipif(
numpy.lib.NumpyVersion(numpy.__version__) < '2.1.0',
reason='numpy takes and gives versioned tensors from 2.1 on'
)

DATA_TYPES = [
(rexlib.NumericalType.boolean, numpy.bool_),
(rexlib.NumericalType.int8, numpy.int8),
Expand Down Expand Up @@ -220,7 +215,6 @@ def test_the_capsule_is_versioned_for_a_consumer_that_can_take_it(
capsule = array.__dlpack__(max_version=(1, 0))
assert '"dltensor_versioned"' in repr(capsule)

@numpy_speaks_dlpack_1
def test_numpy_takes_a_versioned_capsule(__setup_context):
array = __setup_full([2, 3], 2.5, __setup_context)
exported = Exported(array.__dlpack__(max_version=(1, 0)))
Expand Down Expand Up @@ -388,7 +382,6 @@ def test_the_source_is_asked_for_what_the_caller_wants(copy):
assert source.requested['max_version'][0] == 1
del array

@numpy_speaks_dlpack_1
def test_numpy_copies_when_asked_to():
source = numpy.arange(6, dtype=numpy.float32)
copied = numpy.asarray(rexlib.from_dlpack(source, copy=True))
Expand Down Expand Up @@ -424,7 +417,6 @@ def test_a_read_only_tensor_is_refused_when_no_copy_is_allowed():
rexlib.from_dlpack(source, copy=False)
assert source.released == 0

@numpy_speaks_dlpack_1
def test_a_read_only_array_of_numpy_is_copied():
source = numpy.arange(6, dtype=numpy.float32)
source.flags.writeable = False
Expand Down
Loading