Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
15 changes: 11 additions & 4 deletions Changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,19 @@ version 3.17.0

**2025-??-??**

* Set a new minimum version of `numpy`: ``2.0.0``
(https://github.com/NCAS-CMS/cf-python/issues/843)
* Replace dataset aggregation functionality (CFA) with that imported
from `cfdm` (https://github.com/NCAS-CMS/cf-python/issues/841)
* New keyword parameter to `cf.Field.compute_vertical_coordinates`:
``key`` (https://github.com/NCAS-CMS/cf-python/issues/802)
* Changed dependency: ``1.12.0.0<=cfdm<1.12.1.0``
* Changed dependency: ``h5py>=3.12.0``
* Changed dependency: ``Python>=3.9.0``
* Changed dependency: ``numpy>=2.0.0``
* Changed dependency: ``cfdm>=1.12.0.0, <1.12.1.0``
* Changed optional dependency: ``esmpy>=8.7.0``
* Removed dependency (now incorporated into ``cfdm``): ``h5py``
* Removed dependency (now incorporated into ``cfdm``): ``h5netcdf``
* Removed dependency (now incorporated into ``cfdm``): ``s3fs``

----

Expand Down Expand Up @@ -287,8 +294,8 @@ version 3.15.0
* Handled the renaming of the ESMF Python interface from `ESMF` to
`esmpy` at version 8.4.0. Both module names are accepted for now.
* Changed dependency: ``1.10.1.0<=cfdm<1.10.2.0``
* Changed (optional) dependency: ``8.0.0<=esmpy``
* Changed (optional) dependency: ``1.10.0<=scipy``
* Changed optional dependency: ``8.0.0<=esmpy``
* Changed optional dependency: ``1.10.0<=scipy``

----

Expand Down
198 changes: 92 additions & 106 deletions cf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@
"""

__Conventions__ = "CF-1.11"
__date__ = "2025-01-28"
__version__ = "3.16.3"

Expand All @@ -95,154 +94,141 @@
"packaging",
"scipy",
)

x = ", ".join(_requires)
_error0 = f"cf v{__version__} requires the modules {x}. "

import importlib.util
from platform import python_version

_found_esmpy = bool(importlib.util.find_spec("esmpy"))

try:
import cfdm
import packaging
from packaging.version import Version
except ImportError as error1:
raise ImportError(_error0 + str(error1))
else:
_minimum_vn = "20.0"
if Version(packaging.__version__) < Version(_minimum_vn):
raise RuntimeError(
f"Bad packaging version: cf requires packaging>={_minimum_vn}. "
f"Got {packaging.__version__} at {packaging.__file__}"
)

__cf_version__ = cfdm.core.__cf_version__

from packaging.version import Version
import importlib.util
import platform

# ESMF renamed its Python module to `esmpy` at ESMF version 8.4.0. Allow
# either for now for backwards compatibility.
_found_esmpy = bool(
importlib.util.find_spec("esmpy") or importlib.util.find_spec("ESMF")
)
try:
import cfdm
except ImportError as error1:
raise ImportError(_error0 + str(error1))
else:
# Check the version of cfdm
_minimum_vn = "1.12.0.0"
_maximum_vn = "1.12.1.0"
_cfdm_version = Version(cfdm.__version__)
if not Version(_minimum_vn) <= _cfdm_version < Version(_maximum_vn):
raise RuntimeError(
"Bad cfdm version: cf requires "
f"{_minimum_vn}<=cfdm<{_maximum_vn}. "
f"Got {cfdm.__version__} at {cfdm.__file__}"
)

__cf_version__ = cfdm.__cf_version__
__Conventions__ = f"CF-{__cf_version__}"

try:
import netCDF4
except ImportError as error1:
raise ImportError(_error0 + str(error1))
else:
_minimum_vn = "1.7.2"
if Version(netCDF4.__version__) < Version(_minimum_vn):
raise RuntimeError(
f"Bad netCDF4 version: cf requires netCDF4>={_minimum_vn}. "
f"Got {netCDF4.__version__} at {netCDF4.__file__}"
)

try:
import numpy as np
except ImportError as error1:
raise ImportError(_error0 + str(error1))
else:
_minimum_vn = "2.0.0"
if not Version(_minimum_vn) < Version(np.__version__):
raise ValueError(
f"Bad numpy version: cf requires numpy>={_minimum_vn} "
f"Got {np.__version__} at {np.__file__}"
)

try:
import cftime
except ImportError as error1:
raise ImportError(_error0 + str(error1))
else:
_minimum_vn = "1.6.4"
if Version(cftime.__version__) < Version(_minimum_vn):
raise RuntimeError(
f"Bad cftime version: cf requires cftime>={_minimum_vn}. "
f"Got {cftime.__version__} at {cftime.__file__}"
)

try:
import cfunits
except ImportError as error1:
raise ImportError(_error0 + str(error1))
else:
_minimum_vn = "3.3.7"
if Version(cfunits.__version__) < Version(_minimum_vn):
raise RuntimeError(
f"Bad cfunits version: cf requires cfunits>={_minimum_vn}. "
f"Got {cfunits.__version__} at {cfunits.__file__}"
)

try:
import psutil
except ImportError as error1:
raise ImportError(_error0 + str(error1))
else:
_minimum_vn = "0.6.0"
if Version(psutil.__version__) < Version(_minimum_vn):
raise RuntimeError(
f"Bad psutil version: cf requires psutil>={_minimum_vn}. "
f"Got {psutil.__version__} at {psutil.__file__}"
)

try:
import dask
except ImportError as error1:
raise ImportError(_error0 + str(error1))

try:
import packaging
except ImportError as error1:
raise ImportError(_error0 + str(error1))
else:
_minimum_vn = "2024.6.1"
_maximum_vn = "2024.7.1"
if (
not Version(_minimum_vn)
<= Version(dask.__version__)
<= Version(_maximum_vn)
):
raise ValueError(
"Bad dask version: cf requires "
f"{_minimum_vn}<=dask<={_maximum_vn}. "
f"Got {dask.__version__} at {dask.__file__}"
)

try:
import scipy
except ImportError as error1:
raise ImportError(_error0 + str(error1))

# Check the version of packaging
_minimum_vn = "20.0"
if Version(packaging.__version__) < Version(_minimum_vn):
raise RuntimeError(
f"Bad packaging version: cf requires packaging>={_minimum_vn}. "
f"Got {packaging.__version__} at {packaging.__file__}"
)

# Check the version of psutil
_minimum_vn = "0.6.0"
if Version(psutil.__version__) < Version(_minimum_vn):
raise RuntimeError(
f"Bad psutil version: cf requires psutil>={_minimum_vn}. "
f"Got {psutil.__version__} at {psutil.__file__}"
)

# Check the version of netCDF4
_minimum_vn = "1.6.5"
if Version(netCDF4.__version__) < Version(_minimum_vn):
raise RuntimeError(
f"Bad netCDF4 version: cf requires netCDF4>={_minimum_vn}. "
f"Got {netCDF4.__version__} at {netCDF4.__file__}"
)

# Check the version of cftime
_minimum_vn = "1.6.2"
if Version(cftime.__version__) < Version(_minimum_vn):
raise RuntimeError(
f"Bad cftime version: cf requires cftime>={_minimum_vn}. "
f"Got {cftime.__version__} at {cftime.__file__}"
)

# Check the version of numpy
_minimum_vn = "1.22"
_maximum_vn = "2.0"
if not Version(_minimum_vn) <= Version(np.__version__) < Version(_maximum_vn):
raise ValueError(
"Bad numpy version: cf requires _minimum_vn}<=numpy<{_maximum_vn}. "
f"Got {np.__version__} at {np.__file__}"
)

# Check the version of cfunits
_minimum_vn = "3.3.7"
if Version(cfunits.__version__) < Version(_minimum_vn):
raise RuntimeError(
f"Bad cfunits version: cf requires cfunits>={_minimum_vn}. "
f"Got {cfunits.__version__} at {cfunits.__file__}"
)

# Check the version of cfdm
_minimum_vn = "1.12.0.0"
_maximum_vn = "1.12.1.0"
_cfdm_version = Version(cfdm.__version__)
if not Version(_minimum_vn) <= _cfdm_version < Version(_maximum_vn):
raise RuntimeError(
f"Bad cfdm version: cf requires {_minimum_vn}<=cfdm<{_maximum_vn}. "
f"Got {cfdm.__version__} at {cfdm.__file__}"
)

# Check the version of dask

_minimum_vn = "2024.6.1"
_maximum_vn = "2024.7.1"
if (
not Version(_minimum_vn)
<= Version(dask.__version__)
<= Version(_maximum_vn)
):
else:
_minimum_vn = "1.10.0"
if Version(scipy.__version__) < Version(_minimum_vn):
raise RuntimeError(
f"Bad scipy version: cf requires scipy>={_minimum_vn}. "
f"Got {scipy.__version__} at {scipy.__file__}"
)

_minimum_vn = "3.9.0"
if Version(python_version()) < Version(_minimum_vn):
raise ValueError(
"Bad dask version: cf requires {_minimum_vn}<=dask<={_maximum_vn}. "
f"Got {dask.__version__} at {dask.__file__}"
)

# Check the version of Python
_minimum_vn = "3.8.0"
if Version(platform.python_version()) < Version(_minimum_vn):
raise ValueError(
f"Bad python version: cf requires python version {_minimum_vn} "
f"or later. Got {platform.python_version()}"
)

# Check the version of scipy
_minimum_vn = "1.10.0"
if Version(scipy.__version__) < Version(_minimum_vn):
raise RuntimeError(
f"Bad scipy version: cf requires scipy>={_minimum_vn}. "
f"Got {scipy.__version__} at {scipy.__file__}"
f"Bad python version: cf requires python>={_minimum_vn}. "
f"Got {python_version()}"
)

del _minimum_vn, _maximum_vn
Expand Down
12 changes: 10 additions & 2 deletions cf/data/collapse/dask_collapse.py
Original file line number Diff line number Diff line change
Expand Up @@ -858,9 +858,17 @@ def cf_sample_size_chunk(x, dtype="i8", computing_meta=False, **kwargs):
return x

x = cfdm_to_memory(x)

if np.ma.isMA(x):
N = chunk.sum(np.ones_like(x, dtype=dtype), **kwargs)
# Note: We're not using `np.ones_like` here (like we used to)
# because numpy currently (numpy==2.2.3) has a bug that
# produces a RuntimeWarning: "numpy/ma/core.py:502:
# RuntimeWarning: invalid value encountered in cast
# fill_value = np.asarray(fill_value,
# dtype=ndtype)". See
# https://github.com/numpy/numpy/issues/28255 for more
# details.
x = np.ma.array(np.ones((x.shape), dtype=x.dtype), mask=x.mask)
N = chunk.sum(x, **kwargs)
else:
if dtype:
kwargs["dtype"] = dtype
Expand Down
1 change: 1 addition & 0 deletions cf/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2755,6 +2755,7 @@ def dirname(path, normalise=False, uri=None, isdir=False, sep=False):
dirname.__doc__ = cfdm.dirname.__doc__.replace("cfdm.", "cf.")

from functools import partial

dirname2 = partial(cfdm.dirname)
dirname2.__doc__ = cfdm.dirname.__doc__.replace("cfdm.", "cf.")

Expand Down
3 changes: 1 addition & 2 deletions cf/mixin/fielddomain.py
Original file line number Diff line number Diff line change
Expand Up @@ -692,8 +692,7 @@ def _point_not_in_cell(nodes_x, nodes_y, point):
if ind is not None:
mask_component_shape = []
masked_subspace_size = 1
# TODONUMPY2: https://numpy.org/devdocs/numpy_2_0_migration_guide.html#adapting-to-changes-in-the-copy-keyword
ind = np.array(ind, copy=False)
ind = np.array(ind)

for i, (axis, start, stop) in enumerate(
zip(canonical_axes, ind.min(axis=1), ind.max(axis=1))
Expand Down
8 changes: 0 additions & 8 deletions cf/mixin/propertiesdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,6 @@ class PropertiesData(Properties):

_special_properties = ("units", "calendar")

def __array__(self, *dtype):
"""Returns a numpy array representation of the data."""
data = self.get_data(None)
if data is not None:
return data.__array__(*dtype)

raise ValueError(f"{self.__class__.__name__} has no data")

def __contains__(self, value):
"""Called to implement membership test operators.

Expand Down
3 changes: 2 additions & 1 deletion cf/test/test_Data.py
Original file line number Diff line number Diff line change
Expand Up @@ -2621,7 +2621,7 @@ def test_Data_percentile_median(self):
a1 = np.nanpercentile(filled, q, keepdims=keepdims)
mask = np.isnan(a1)
if mask.any():
a1 = np.ma.masked_where(mask, a1, copy=False)
a1 = np.ma.masked_where(mask, a1)

b1 = d.percentile(q, squeeze=not keepdims)
self.assertEqual(b1.shape, a1.shape)
Expand Down Expand Up @@ -3613,6 +3613,7 @@ def test_Data_sample_size(self):
b = np.ma.asanyarray(b)

e = d.sample_size(axes=axis, squeeze=True)

e = np.ma.array(e.array)

self.assertTrue((e.mask == b.mask).all())
Expand Down
Loading
Loading