Skip to content

Commit f025caf

Browse files
authored
Merge pull request #484 from blaylockbk/477-drop-support-for-python-310-and-ensure-compatibility-with-314
Drop support for Python 3.10 and support Python 3.14 (and Pandas 3.0)
2 parents f3b22ec + da39524 commit f025caf

6 files changed

Lines changed: 46 additions & 41 deletions

File tree

.github/workflows/tests-python.yml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,27 @@ jobs:
2020
matrix:
2121
include:
2222
- os: ubuntu-latest
23-
python-version: "3.10"
23+
python-version: "3.11"
2424
- os: ubuntu-latest
2525
python-version: "3.11"
26+
resolution: "lowest-direct"
2627
- os: ubuntu-latest
2728
python-version: "3.12"
2829
- os: ubuntu-latest
2930
python-version: "3.13"
31+
- os: ubuntu-latest
32+
python-version: "3.14"
33+
- os: ubuntu-latest
34+
python-version: "3.13"
35+
resolution: "lowest-direct"
3036
- os: macos-latest
3137
python-version: "3.13"
3238
continue-on-error: true
3339
- os: windows-latest
3440
python-version: "3.13"
3541
continue-on-error: true
3642

37-
name: Python ${{ matrix.python-version }} • ${{ matrix.os }}
43+
name: Python ${{ matrix.python-version }} • ${{ matrix.os }}${{ matrix.resolution && format(' • {0}', matrix.resolution) || '' }}
3844

3945
steps:
4046
- name: Checkout repository
@@ -49,7 +55,7 @@ jobs:
4955

5056
- name: Install the project
5157
shell: bash -el {0}
52-
run: uv sync --extra extras
58+
run: uv sync --extra extras ${{ matrix.resolution && format('--resolution {0}', matrix.resolution) || '' }}
5359

5460
- name: Run tests
5561
shell: bash -el {0}

docs/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ Installation
144144
145145
**Requirements:**
146146

147-
- Python 3.10 or higher
147+
- Python 3.11 or higher
148148
- xarray and cfgrib for reading GRIB2 data
149149
- wgrib2 (optional, for advanced subsetting)
150150

pyproject.toml

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22
name = "herbie-data"
33
description = "Download numerical weather prediction GRIB2 model data."
44
readme = "README.md"
5-
requires-python = ">=3.10"
5+
requires-python = ">=3.11"
66
license = { file = "LICENSE" }
77
authors = [{ name = "Brian K. Blaylock", email = "blaylockbk@gmail.com" }]
88
maintainers = [{ name = "Brian K. Blaylock", email = "blaylockbk@gmail.com" }]
99
classifiers = [
1010
"Development Status :: 4 - Beta",
1111
"Programming Language :: Python :: 3",
12-
"Programming Language :: Python :: 3.10",
1312
"Programming Language :: Python :: 3.11",
1413
"Programming Language :: Python :: 3.12",
1514
"Programming Language :: Python :: 3.13",
15+
"Programming Language :: Python :: 3.14",
1616
"Operating System :: MacOS",
1717
"Operating System :: Microsoft :: Windows",
1818
"Operating System :: POSIX :: Linux",
@@ -31,12 +31,12 @@ keywords = [
3131
]
3232
dependencies = [
3333
"cfgrib>=0.9.15",
34-
"eccodes>=2.37.0",
35-
"numpy>=1.24",
36-
"pandas>=2.1",
34+
"eccodes>=2.45.0",
35+
"eccodeslib>=2.44.1.8; sys_platform != 'win32'",
36+
"numpy>=1.26.4",
37+
"pandas>=2.2.3",
3738
"pyproj>=3.7.0",
3839
"requests>=2.23.3",
39-
"toml>=0.10.2", # TODO: Drop in favor of tomllib when Python >=3.11 is required.
4040
"xarray>=2025.1.1",
4141
]
4242
dynamic = ["version"]
@@ -55,13 +55,12 @@ build-backend = "hatchling.build"
5555
[dependency-groups]
5656
dev = [
5757
"ipykernel>=6.29.5",
58-
"jupyter>=1.1.1",
59-
"pytest>=8.3.5",
60-
"pytest-cov>=6.1.1",
61-
"ruff>=0.11.6",
62-
"scipy>=1.15.2", # only needed for test writing netcdf file
63-
"cartopy>=0.22",
64-
"metpy>=1.3.0",
58+
"pytest>=9.0.2",
59+
"pytest-cov>=7.0.0",
60+
"ruff>=0.14.14",
61+
"scipy>=1.17.0", # only needed for test writing netcdf file
62+
"cartopy>=0.25.0",
63+
"metpy>=1.7.1",
6564
]
6665
docs = [
6766
"autodocsumm>=0.2.14",
@@ -82,11 +81,11 @@ docs = [
8281

8382

8483
[project.optional-dependencies]
85-
plot = ["cartopy", "matplotlib", "metpy"]
86-
metpy = ["metpy"]
87-
scikit-learn = ["scikit-learn"]
84+
plot = ["cartopy>=0.25.0", "matplotlib>=3.10.0", "metpy>=1.7.1"]
85+
metpy = ["metpy>=1.7.1"]
86+
scikit-learn = ["scikit-learn>=1.8.0"]
8887

89-
pygrib = ["pygrib"]
88+
pygrib = ["pygrib>=2.1.8"]
9089

9190
extras = [
9291
"herbie-data[plot,metpy,scikit-learn]", # Didn't include pygrib on purpose

src/herbie/__init__.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,9 @@
2525
"""
2626

2727
import os
28+
import tomllib
2829
from pathlib import Path
2930

30-
import toml
31-
3231
from herbie.misc import ANSI
3332

3433
__author__ = "Brian K. Blaylock"
@@ -148,7 +147,8 @@ def template(self):
148147
# Load config file (create one if needed)
149148
try:
150149
# Load the Herbie config file
151-
config = toml.load(_config_file)
150+
with open(_config_file, "rb") as f:
151+
config = tomllib.load(f)
152152
except Exception:
153153
try:
154154
# Create the Herbie config file
@@ -175,7 +175,8 @@ def template(self):
175175
)
176176

177177
# Load the new Herbie config file
178-
config = toml.load(_config_file)
178+
with open(_config_file, "rb") as f:
179+
config = tomllib.load(f)
179180
except (FileNotFoundError, PermissionError, IOError):
180181
print(
181182
f" ╭─{ANSI.herbie}─────────────────────────────────────────────╮\n"
@@ -185,7 +186,7 @@ def template(self):
185186
f" │ Consider setting env variable HERBIE_CONFIG_PATH. │\n"
186187
f" ╰──────────────────────────────────────────────────────╯\n"
187188
)
188-
config = toml.loads(default_toml)
189+
config = tomllib.loads(default_toml)
189190

190191

191192
# Expand the full path for `save_dir`
@@ -201,9 +202,9 @@ def template(self):
201202
f" ╰──────────────────────────────────────────────────────╯\n"
202203
)
203204

205+
from herbie.accessors import HerbieAccessor
204206
from herbie.core import Herbie
205-
from herbie.show_versions import show_versions
206207
from herbie.fast import FastHerbie
207208
from herbie.latest import HerbieLatest, HerbieWait
209+
from herbie.show_versions import show_versions
208210
from herbie.wgrib2 import wgrib2
209-
from herbie.accessors import HerbieAccessor

src/herbie/core.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -825,12 +825,12 @@ def index_as_dataframe(self) -> pd.DataFrame:
825825
df = df.dropna(how="all", axis=1)
826826

827827
df["search_this"] = (
828-
df.loc[:, "variable":]
828+
":"
829+
+ df.loc[:, "variable":]
829830
.astype(str)
830-
.apply(
831-
lambda x: ":" + ":".join(x).rstrip(":").replace(":nan:", ":"),
832-
axis=1,
833-
)
831+
.apply(lambda x: x.str.cat(sep=":"), axis=1)
832+
.replace(":nan:", ":")
833+
+ ":"
834834
)
835835

836836
if self.IDX_STYLE == "eccodes":
@@ -904,12 +904,12 @@ def index_as_dataframe(self) -> pd.DataFrame:
904904
)
905905

906906
df["search_this"] = (
907-
df.loc[:, "param":]
907+
":"
908+
+ df.loc[:, "param":]
908909
.astype(str)
909-
.apply(
910-
lambda x: ":" + ":".join(x).rstrip(":").replace(":nan:", ":"),
911-
axis=1,
912-
)
910+
.apply(lambda x: x.str.cat(sep=":"), axis=1)
911+
.replace(":nan:", ":")
912+
+ ":"
913913
)
914914

915915
# Attach some attributes

tests/test_init.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import os
2-
3-
import toml
2+
import tomllib
43

54
from herbie import Path, default_toml
65

@@ -23,7 +22,7 @@ def test_Path_expand():
2322

2423
def test_default_toml():
2524
# Confirm that default_toml is valid
26-
a = toml.loads(default_toml)
25+
a = tomllib.loads(default_toml)
2726

2827
a["default"]["model"] == "hrrr"
2928
a["default"]["fxx"] == 0

0 commit comments

Comments
 (0)