Skip to content

Commit b7d30fe

Browse files
feat: drop 3.9 (#1057)
* feat: drop 3.9 Signed-off-by: Henry Schreiner <[email protected]> * style: pre-commit fixes * fix: revert strenum change Signed-off-by: Henry Schreiner <[email protected]> * style: pre-commit fixes * Update Python version for Windows environment --------- Signed-off-by: Henry Schreiner <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 0e55eb1 commit b7d30fe

File tree

18 files changed

+112
-120
lines changed

18 files changed

+112
-120
lines changed

.github/workflows/examples.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
submodules: true
2222
- uses: actions/setup-python@v6
2323
with:
24-
python-version: "3.9"
24+
python-version: "3.10"
2525
- uses: astral-sh/setup-uv@v7
2626
- name: Build and install kernel
2727
run: uv run --group examples -m ipykernel install --user --name boost-hist

.github/workflows/tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ jobs:
5959
fail-fast: false
6060
matrix:
6161
include:
62-
- python-version: "3.9"
62+
- python-version: "3.10"
6363
cmake-extras: "-DCMAKE_CXX_STANDARD=17"
6464
- python-version: "3.11"
6565
- python-version: "3.13t"
@@ -111,7 +111,7 @@ jobs:
111111
- os: ubuntu-24.04-arm
112112
only: cp313-manylinux_aarch64
113113
- os: windows-latest
114-
only: cp39-win32
114+
only: cp310-win32
115115
- os: windows-latest
116116
only: cp313-win_amd64
117117
- os: macos-13

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ repos:
4747
hooks:
4848
- id: mypy
4949
files: ^src
50-
additional_dependencies: [numpy~=2.3.0, pytest, uhi]
50+
additional_dependencies: [numpy~=2.2.0, pytest, uhi]
5151

5252
- repo: https://github.com/codespell-project/codespell
5353
rev: v2.4.1

README.md

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,12 @@ python3 -m pip install boost-histogram
179179
```
180180

181181
All the normal best-practices for Python apply; Pip should not be very old (Pip
182-
9 is very old), you should be in a virtual environment, etc. Python 3.9+ is
182+
9 is very old), you should be in a virtual environment, etc. Python 3.10+ is
183183
required; for older versions of Python (3.5 and 2.7), `0.13` will be installed
184184
instead, which is API equivalent to 1.0, but will not be gaining new features.
185185
1.3.x was the last series to support Python 3.6. 1.4.x was the last series to
186-
support Python 3.7. 1.5.x was the last series to support Python 3.8.
186+
support Python 3.7. 1.5.x was the last series to support Python 3.8. 1.6.x was
187+
the last to support Python 3.9.
187188

188189
#### Binaries available:
189190

@@ -192,17 +193,18 @@ when you run the above command on a supported platform. Wheels are produced usin
192193
[cibuildwheel](https://cibuildwheel.readthedocs.io/en/stable/); all common
193194
platforms have wheels provided in boost-histogram:
194195

195-
| System | Arch | Python versions | PyPy versions |
196-
| ------------- | ------ | ---------------------------------- | ------------- |
197-
| manylinux2014 | 64-bit | 3.9, 3.10, 3.11, 3.12, 3.13, 3.13t | 3.9, 3.10 |
198-
| manylinux2014 | ARM64 | 3.9, 3.10, 3.11, 3.12, 3.13, 3.13t | 3.9, 3.10 |
199-
| musllinux_1_1 | 64-bit | 3.9, 3.10, 3.11, 3.12, 3.13, 3.13t | |
200-
| macOS | 64-bit | 3.9, 3.10, 3.11, 3.12, 3.13, 3.13t | 3.9, 3.10 |
201-
| macOS | Arm64 | 3.9, 3.10, 3.11, 3.12, 3.13, 3.13t | 3.9, 3.10 |
202-
| Windows | 32-bit | 3.9, 3.10, 3.11, 3.12, 3.13, 3.13t | |
203-
| Windows | 64-bit | 3.9, 3.10, 3.11, 3.12, 3.13, 3.13t | 3.9, 3.10 |
204-
205-
PowerPC or IBM-Z wheels are not provided but are available on request.
196+
| System | Arch | Python versions | PyPy versions |
197+
| --------- | ------ | ------------------------------------------ | ------------- |
198+
| manylinux | 64-bit | 3.10, 3.11, 3.12, 3.13, 3.13t, 3.14, 3.14t | 3.11 |
199+
| manylinux | ARM64 | 3.10, 3.11, 3.12, 3.13, 3.13t, 3.14, 3.14t | 3.11 |
200+
| musllinux | 64-bit | 3.10, 3.11, 3.12, 3.13, 3.13t, 3.14, 3.14t | |
201+
| macOS | 64-bit | 3.10, 3.11, 3.12, 3.13, 3.13t, 3.14, 3.14t | 3.11 |
202+
| macOS | Arm64 | 3.10, 3.11, 3.12, 3.13, 3.13t, 3.14, 3.14t | 3.11 |
203+
| Windows | 32-bit | 3.10, 3.11, 3.12, 3.13, 3.13t, 3.14, 3.14t | |
204+
| Windows | 64-bit | 3.10, 3.11, 3.12, 3.13, 3.13t, 3.14, 3.14t | 3.11 |
205+
| Windows | ARM64 | 3.11, 3.12, 3.13, 3.13t, 3.14, 3.14t | |
206+
207+
PowerPC, IBM-Z, and RISC-V wheels are not provided but are available on request.
206208

207209
If you are on a Linux system that is not part of the "many" in manylinux or musl in musllinux, such as ClearLinux, building from source is usually fine, since the compilers on those systems are often quite new. It will just take longer to install when it is using the sdist instead of a wheel. All dependencies are header-only and included.
208210

examples/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Boost Histogram examples
22

3-
The examples require Python 3.9. It is left as an exercise for the reader to
3+
The examples require Python 3.10. It is left as an exercise for the reader to
44
convert back to older versions if they so desire.
55

66
### Setup

notebooks/xarray.ipynb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@
178178
" name=\"_\".join(a.name for a in args) + \"_histogram\",\n",
179179
" coords=[\n",
180180
" (f\"{a.name}_bin\", arr.flatten(), a.attrs)\n",
181-
" for a, arr in zip(args, h.axes.centers)\n",
181+
" for a, arr in zip(args, h.axes.centers, strict=False)\n",
182182
" ],\n",
183183
" )"
184184
]
@@ -270,7 +270,7 @@
270270
" name=\"_\".join(a.name for a in args) + \"_histogram\",\n",
271271
" coords=[\n",
272272
" (f\"{a.name}_bin\", arr.flatten(), a.attrs)\n",
273-
" for a, arr in zip(args, h.axes.centers)\n",
273+
" for a, arr in zip(args, h.axes.centers, strict=False)\n",
274274
" ],\n",
275275
" )"
276276
]

pyproject.toml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ name = "boost-histogram"
77
dynamic = ["version"]
88
description = "The Boost::Histogram Python wrapper."
99
readme = "README.md"
10-
requires-python = ">=3.9"
10+
requires-python = ">=3.10"
1111
authors = [
1212
{ name = "Hans Dembinski", email = "[email protected]" },
1313
{ name = "Henry Schreiner", email = "[email protected]" },
@@ -37,7 +37,6 @@ classifiers = [
3737
"Programming Language :: Python :: 3.12",
3838
"Programming Language :: Python :: 3.13",
3939
"Programming Language :: Python :: 3.14",
40-
"Programming Language :: Python :: 3.9",
4140
"Programming Language :: Python :: Free Threading :: 3 - Stable",
4241
"Programming Language :: Python :: Free Threading",
4342
"Programming Language :: Python :: Implementation :: CPython",
@@ -158,7 +157,7 @@ required_plugins = ["pytest-benchmark"]
158157
log_cli_level = "DEBUG"
159158

160159
[tool.mypy]
161-
python_version = "3.9"
160+
python_version = "3.10"
162161
files = ["src"]
163162
strict = true
164163
enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
@@ -181,8 +180,8 @@ test-command = "python -m pytest -n auto --benchmark-disable tests"
181180
test-sources = ["pyproject.toml", "tests"]
182181
test-environment.CI = "1" # Hypothosis needs this on GraalPy
183182
test-skip = [
184-
"cp3{9,10}-win_arm64",
185-
"cp3{9,10}-musllinux_*",
183+
"cp310-win_arm64",
184+
"cp310-musllinux_*",
186185
"pp310-manylinux_aarch64",
187186
"pp310-macosx_arm64",
188187
"cp31*-musllinux_*", # Threading test crashes
@@ -228,7 +227,7 @@ environment.UV_INDEX_STRATEGY = "unsafe-best-match"
228227
test-command = "pytest --benchmark-disable tests"
229228

230229
[tool.pylint]
231-
py-version = "3.9"
230+
py-version = "3.10"
232231
ignore-patterns = ['.*\.pyi']
233232
ignore = "version.py"
234233
extension-pkg-allow-list = ["boost_histogram._core"]

src/boost_histogram/_core/axis/transform.pyi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from typing import Any, Callable
1+
from collections.abc import Callable
2+
from typing import Any
23

34
from typing_extensions import Self
45

src/boost_histogram/_utils.py

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
from __future__ import annotations
22

3-
import itertools
4-
import sys
53
import typing
6-
from collections.abc import Iterator
7-
from typing import Any, Callable, ClassVar, Protocol, TypeVar
4+
from collections.abc import Callable, Iterator
5+
from typing import ClassVar, Protocol, TypeVar
86

97
import boost_histogram
108

@@ -165,16 +163,3 @@ def _walk_subclasses(cls: type[object]) -> Iterator[type[object]]:
165163
# user subclasses to work
166164
yield from _walk_subclasses(base)
167165
yield base
168-
169-
170-
def zip_strict(*args: Any) -> Iterator[tuple[Any, ...]]:
171-
if sys.version_info >= (3, 10):
172-
yield from zip(*args, strict=True)
173-
return
174-
175-
marker = object()
176-
for each in itertools.zip_longest(*args, fillvalue=marker):
177-
for val in each:
178-
if val is marker:
179-
raise ValueError("zip() arguments are not the same length")
180-
yield each

src/boost_histogram/axis/__init__.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
from __future__ import annotations
22

33
import copy
4-
from collections.abc import Iterable, Iterator
4+
from collections.abc import Callable, Iterable, Iterator
55
from dataclasses import dataclass
66
from functools import partial
77
from typing import (
88
Any,
9-
Callable,
109
ClassVar,
1110
Literal,
1211
TypedDict,
1312
TypeVar,
14-
Union,
1513
)
1614

1715
import numpy as np # pylint: disable=unused-import
@@ -20,7 +18,7 @@
2018

2119
from .._compat.typing import Self
2220
from .._core import axis as ca
23-
from .._utils import cast, register, zip_strict
21+
from .._utils import cast, register
2422
from . import transform
2523
from .transform import AxisTransform
2624

@@ -59,7 +57,7 @@ def _opts(**kwargs: bool) -> set[str]:
5957
return {k for k, v in kwargs.items() if v}
6058

6159

62-
AxCallOrInt = Union[int, Callable[["Axis"], int]]
60+
AxCallOrInt = int | Callable[["Axis"], int]
6361

6462

6563
@dataclass(order=True, frozen=True)
@@ -287,21 +285,21 @@ def __getitem__(self, i: AxCallOrInt) -> int | str | tuple[float, float]:
287285

288286
@property
289287
def edges(self) -> np.typing.NDArray[Any]:
290-
return self._ax.edges
288+
return self._ax.edges # type: ignore[no-any-return]
291289

292290
@property
293291
def centers(self) -> np.typing.NDArray[Any]:
294292
"""
295293
An array of bin centers.
296294
"""
297-
return self._ax.centers
295+
return self._ax.centers # type: ignore[no-any-return]
298296

299297
@property
300298
def widths(self) -> np.typing.NDArray[Any]:
301299
"""
302300
An array of bin widths.
303301
"""
304-
return self._ax.widths
302+
return self._ax.widths # type: ignore[no-any-return]
305303

306304

307305
# Contains all common methods and properties for Regular axes
@@ -910,7 +908,7 @@ def __setattr__(self, attr: str, values: Any) -> None:
910908
try:
911909
super().__setattr__(attr, values)
912910
except AttributeError:
913-
for s, v in zip_strict(self, values):
911+
for s, v in zip(self, values, strict=True):
914912
s.__setattr__(attr, v)
915913

916914
value.__doc__ = Axis.value.__doc__

0 commit comments

Comments
 (0)