Skip to content

Commit

Permalink
Merge pull request #1297 from effigies/fix/pytest
Browse files Browse the repository at this point in the history
TEST: Accommodate pytest 8 changes
  • Loading branch information
effigies authored Feb 23, 2024
2 parents 5d884bd + cff2936 commit 27c2427
Show file tree
Hide file tree
Showing 13 changed files with 70 additions and 74 deletions.
2 changes: 1 addition & 1 deletion nibabel/_compression.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from .optpkg import optional_package

if ty.TYPE_CHECKING: # pragma: no cover
import indexed_gzip # type: ignore[import-not-found]
import indexed_gzip # type: ignore[import]
import pyzstd

HAVE_INDEXED_GZIP = True
Expand Down
2 changes: 1 addition & 1 deletion nibabel/benchmarks/bench_arrayproxy_slicing.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

# if memory_profiler is installed, we get memory usage results
try:
from memory_profiler import memory_usage # type: ignore[import-not-found]
from memory_profiler import memory_usage # type: ignore[import]
except ImportError:
memory_usage = None

Expand Down
2 changes: 1 addition & 1 deletion nibabel/cmdline/dicomfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class dummy_fuse:


try:
import fuse # type: ignore[import-not-found]
import fuse # type: ignore[import]

uid = os.getuid()
gid = os.getgid()
Expand Down
16 changes: 9 additions & 7 deletions nibabel/gifti/tests/test_gifti.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from ... import load
from ...fileholders import FileHolder
from ...nifti1 import data_type_codes
from ...testing import get_test_data
from ...testing import deprecated_to, expires, get_test_data
from .. import (
GiftiCoordSystem,
GiftiDataArray,
Expand Down Expand Up @@ -275,27 +275,29 @@ def test_labeltable():
assert len(img.labeltable.labels) == 2


@expires('6.0.0')
def test_metadata():
md = GiftiMetaData(key='value')
# Old initialization methods
with pytest.warns(DeprecationWarning) as w:
with deprecated_to('6.0.0'):
nvpair = GiftiNVPairs('key', 'value')
with pytest.warns(FutureWarning) as w:
md2 = GiftiMetaData(nvpair=nvpair)
assert len(w) == 1
with pytest.warns(DeprecationWarning) as w:
with deprecated_to('6.0.0'):
md3 = GiftiMetaData.from_dict({'key': 'value'})
assert md == md2 == md3 == {'key': 'value'}
# .data as a list of NVPairs is going away
with pytest.warns(DeprecationWarning) as w:
with deprecated_to('6.0.0'):
assert md.data[0].name == 'key'
with deprecated_to('6.0.0'):
assert md.data[0].value == 'value'
assert len(w) == 2


@expires('6.0.0')
def test_metadata_list_interface():
md = GiftiMetaData(key='value')
with pytest.warns(DeprecationWarning):
with deprecated_to('6.0.0'):
mdlist = md.data
assert len(mdlist) == 1
assert mdlist[0].name == 'key'
Expand All @@ -312,7 +314,7 @@ def test_metadata_list_interface():
assert md['foo'] == 'bar'

# Append new NVPair
with pytest.warns(DeprecationWarning) as w:
with deprecated_to('6.0.0'):
nvpair = GiftiNVPairs('key', 'value')
mdlist.append(nvpair)
assert len(mdlist) == 2
Expand Down
2 changes: 1 addition & 1 deletion nibabel/minc2.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ class Minc2Image(Minc1Image):
def from_file_map(klass, file_map, *, mmap=True, keep_file_open=None):
# Import of h5py might take awhile for MPI-enabled builds
# So we are importing it here "on demand"
import h5py # type: ignore[import-not-found]
import h5py # type: ignore[import]

holder = file_map['image']
if holder.filename is None:
Expand Down
2 changes: 1 addition & 1 deletion nibabel/spm99analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ def from_file_map(klass, file_map, *, mmap=True, keep_file_open=None):
contents = matf.read()
if len(contents) == 0:
return ret
import scipy.io as sio # type: ignore[import-not-found]
import scipy.io as sio # type: ignore[import]

mats = sio.loadmat(BytesIO(contents))
if 'mat' in mats: # this overrides a 'M', and includes any flip
Expand Down
12 changes: 12 additions & 0 deletions nibabel/testing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,15 @@ def expires(version):
return lambda x: x

return pytest.mark.xfail(raises=ExpiredDeprecationError)


def deprecated_to(version):
"""Context manager to expect DeprecationWarnings until a given version"""
from packaging.version import Version

from nibabel import __version__ as nbver

if Version(nbver) < Version(version):
return pytest.deprecated_call()

return nullcontext()
56 changes: 19 additions & 37 deletions nibabel/tests/test_image_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
bytesio_filemap,
bytesio_round_trip,
clear_and_catch_warnings,
deprecated_to,
expires,
nullcontext,
)
Expand Down Expand Up @@ -80,10 +81,6 @@
from .test_parrec import EXAMPLE_IMAGES as PARREC_EXAMPLE_IMAGES


def maybe_deprecated(meth_name):
return pytest.deprecated_call() if meth_name == 'get_data' else nullcontext()


class GenericImageAPI(ValidateAPI):
"""General image validation API"""

Expand Down Expand Up @@ -194,7 +191,7 @@ def validate_no_slicing(self, imaker, params):
@expires('5.0.0')
def validate_get_data_deprecated(self, imaker, params):
img = imaker()
with pytest.deprecated_call():
with deprecated_to('5.0.0'):
data = img.get_data()
assert_array_equal(np.asanyarray(img.dataobj), data)

Expand Down Expand Up @@ -246,14 +243,12 @@ def validate_data_interface(self, imaker, params):
self._check_array_interface(imaker, meth_name)
method = getattr(img, meth_name)
# Data shape is same as image shape
with maybe_deprecated(meth_name):
assert img.shape == method().shape
assert img.shape == method().shape
# Data ndim is same as image ndim
with maybe_deprecated(meth_name):
assert img.ndim == method().ndim
assert img.ndim == method().ndim
# Values to get_data caching parameter must be 'fill' or
# 'unchanged'
with maybe_deprecated(meth_name), pytest.raises(ValueError):
with pytest.raises(ValueError):
method(caching='something')
# dataobj is read only
fake_data = np.zeros(img.shape, dtype=img.get_data_dtype())
Expand All @@ -277,13 +272,11 @@ def _check_proxy_interface(self, imaker, meth_name):
assert not img.in_memory
# Load with caching='unchanged'
method = getattr(img, meth_name)
with maybe_deprecated(meth_name):
data = method(caching='unchanged')
data = method(caching='unchanged')
# Still not cached
assert not img.in_memory
# Default load, does caching
with maybe_deprecated(meth_name):
data = method()
data = method()
# Data now cached. in_memory is True if either of the get_data
# or get_fdata caches are not-None
assert img.in_memory
Expand All @@ -295,36 +288,30 @@ def _check_proxy_interface(self, imaker, meth_name):
# integers, but lets assume that's not true here.
assert_array_equal(proxy_data, data)
# Now caching='unchanged' does nothing, returns cached version
with maybe_deprecated(meth_name):
data_again = method(caching='unchanged')
data_again = method(caching='unchanged')
assert data is data_again
# caching='fill' does nothing because the cache is already full
with maybe_deprecated(meth_name):
data_yet_again = method(caching='fill')
data_yet_again = method(caching='fill')
assert data is data_yet_again
# changing array data does not change proxy data, or reloaded
# data
data[:] = 42
assert_array_equal(proxy_data, proxy_copy)
assert_array_equal(np.asarray(img.dataobj), proxy_copy)
# It does change the result of get_data
with maybe_deprecated(meth_name):
assert_array_equal(method(), 42)
# It does change the result of get_fdata
assert_array_equal(method(), 42)
# until we uncache
img.uncache()
# Which unsets in_memory
assert not img.in_memory
with maybe_deprecated(meth_name):
assert_array_equal(method(), proxy_copy)
assert_array_equal(method(), proxy_copy)
# Check caching='fill' does cache data
img = imaker()
method = getattr(img, meth_name)
assert not img.in_memory
with maybe_deprecated(meth_name):
data = method(caching='fill')
data = method(caching='fill')
assert img.in_memory
with maybe_deprecated(meth_name):
data_again = method()
data_again = method()
assert data is data_again
# Check that caching refreshes for new floating point type.
img.uncache()
Expand Down Expand Up @@ -368,17 +355,15 @@ def _check_array_caching(self, imaker, meth_name, caching):
get_data_func = method if caching is None else partial(method, caching=caching)
assert isinstance(img.dataobj, np.ndarray)
assert img.in_memory
with maybe_deprecated(meth_name):
data = get_data_func()
data = get_data_func()
# Returned data same object as underlying dataobj if using
# old ``get_data`` method, or using newer ``get_fdata``
# method, where original array was float64.
arr_dtype = img.dataobj.dtype
dataobj_is_data = arr_dtype == np.float64 or method == img.get_data
# Set something to the output array.
data[:] = 42
with maybe_deprecated(meth_name):
get_result_changed = np.all(get_data_func() == 42)
get_result_changed = np.all(get_data_func() == 42)
assert get_result_changed == (dataobj_is_data or caching != 'unchanged')
if dataobj_is_data:
assert data is img.dataobj
Expand All @@ -387,15 +372,13 @@ def _check_array_caching(self, imaker, meth_name, caching):
assert_array_equal(np.asarray(img.dataobj), 42)
# Uncache has no effect
img.uncache()
with maybe_deprecated(meth_name):
assert_array_equal(get_data_func(), 42)
assert_array_equal(get_data_func(), 42)
else:
assert not data is img.dataobj
assert not np.all(np.asarray(img.dataobj) == 42)
# Uncache does have an effect
img.uncache()
with maybe_deprecated(meth_name):
assert not np.all(get_data_func() == 42)
assert not np.all(get_data_func() == 42)
# in_memory is always true for array images, regardless of
# cache state.
img.uncache()
Expand All @@ -408,8 +391,7 @@ def _check_array_caching(self, imaker, meth_name, caching):
if arr_dtype not in float_types:
return
for float_type in float_types:
with maybe_deprecated(meth_name):
data = get_data_func(dtype=float_type)
data = get_data_func(dtype=float_type)
assert (data is img.dataobj) == (arr_dtype == float_type)

def validate_shape(self, imaker, params):
Expand Down
4 changes: 2 additions & 2 deletions nibabel/tests/test_image_load_save.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
from .. import spm99analyze as spm99
from ..optpkg import optional_package
from ..spatialimages import SpatialImage
from ..testing import expires
from ..testing import deprecated_to, expires
from ..tmpdirs import InTemporaryDirectory
from ..volumeutils import native_code, swapped_code

Expand Down Expand Up @@ -285,7 +285,7 @@ def test_filename_save():
@expires('5.0.0')
def test_guessed_image_type():
# Test whether we can guess the image type from example files
with pytest.deprecated_call():
with deprecated_to('5.0.0'):
assert nils.guessed_image_type(pjoin(DATA_PATH, 'example4d.nii.gz')) == Nifti1Image
assert nils.guessed_image_type(pjoin(DATA_PATH, 'nifti1.hdr')) == Nifti1Pair
assert nils.guessed_image_type(pjoin(DATA_PATH, 'example_nifti2.nii.gz')) == Nifti2Image
Expand Down
26 changes: 13 additions & 13 deletions nibabel/tests/test_loadsave.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from ..loadsave import _signature_matches_extension, load, read_img_data
from ..openers import Opener
from ..optpkg import optional_package
from ..testing import expires
from ..testing import deprecated_to, expires
from ..tmpdirs import InTemporaryDirectory

_, have_scipy, _ = optional_package('scipy')
Expand Down Expand Up @@ -50,14 +50,14 @@ def test_read_img_data():
fpath = pathlib.Path(fpath)
img = load(fpath)
data = img.get_fdata()
with pytest.deprecated_call():
with deprecated_to('5.0.0'):
data2 = read_img_data(img)
assert_array_equal(data, data2)
# These examples have null scaling - assert prefer=unscaled is the same
dao = img.dataobj
if hasattr(dao, 'slope') and hasattr(img.header, 'raw_data_from_fileobj'):
assert (dao.slope, dao.inter) == (1, 0)
with pytest.deprecated_call():
with deprecated_to('5.0.0'):
assert_array_equal(read_img_data(img, prefer='unscaled'), data)
# Assert all caps filename works as well
with TemporaryDirectory() as tmpdir:
Expand Down Expand Up @@ -140,21 +140,21 @@ def test_read_img_data_nifti():
img = img_class(data, np.eye(4))
img.set_data_dtype(out_dtype)
# No filemap => error
with pytest.deprecated_call(), pytest.raises(ImageFileError):
with deprecated_to('5.0.0'), pytest.raises(ImageFileError):
read_img_data(img)
# Make a filemap
froot = f'an_image_{i}'
img.file_map = img.filespec_to_file_map(froot)
# Trying to read from this filemap will generate an error because
# we are going to read from files that do not exist
with pytest.deprecated_call(), pytest.raises(OSError):
with deprecated_to('5.0.0'), pytest.raises(OSError):
read_img_data(img)
img.to_file_map()
# Load - now the scaling and offset correctly applied
img_fname = img.file_map['image'].filename
img_back = load(img_fname)
data_back = img_back.get_fdata()
with pytest.deprecated_call():
with deprecated_to('5.0.0'):
assert_array_equal(data_back, read_img_data(img_back))
# This is the same as if we loaded the image and header separately
hdr_fname = img.file_map['header'].filename if 'header' in img.file_map else img_fname
Expand All @@ -166,16 +166,16 @@ def test_read_img_data_nifti():
# Unscaled is the same as returned from raw_data_from_fileobj
with open(img_fname, 'rb') as fobj:
unscaled_back = hdr_back.raw_data_from_fileobj(fobj)
with pytest.deprecated_call():
with deprecated_to('5.0.0'):
assert_array_equal(unscaled_back, read_img_data(img_back, prefer='unscaled'))
# If we futz with the scaling in the header, the result changes
with pytest.deprecated_call():
with deprecated_to('5.0.0'):
assert_array_equal(data_back, read_img_data(img_back))
has_inter = hdr_back.has_data_intercept
old_slope = hdr_back['scl_slope']
old_inter = hdr_back['scl_inter'] if has_inter else 0
est_unscaled = (data_back - old_inter) / old_slope
with pytest.deprecated_call():
with deprecated_to('5.0.0'):
actual_unscaled = read_img_data(img_back, prefer='unscaled')
assert_almost_equal(est_unscaled, actual_unscaled)
img_back.header['scl_slope'] = 2.1
Expand All @@ -185,10 +185,10 @@ def test_read_img_data_nifti():
else:
new_inter = 0
# scaled scaling comes from new parameters in header
with pytest.deprecated_call():
with deprecated_to('5.0.0'):
assert np.allclose(actual_unscaled * 2.1 + new_inter, read_img_data(img_back))
# Unscaled array didn't change
with pytest.deprecated_call():
with deprecated_to('5.0.0'):
assert_array_equal(actual_unscaled, read_img_data(img_back, prefer='unscaled'))
# Check the offset too
img.header.set_data_offset(1024)
Expand All @@ -200,14 +200,14 @@ def test_read_img_data_nifti():
fobj.write(b'\x00\x00')
img_back = load(img_fname)
data_back = img_back.get_fdata()
with pytest.deprecated_call():
with deprecated_to('5.0.0'):
assert_array_equal(data_back, read_img_data(img_back))
img_back.header.set_data_offset(1026)
# Check we pick up new offset
exp_offset = np.zeros((data.size,), data.dtype) + old_inter
exp_offset[:-1] = np.ravel(data_back, order='F')[1:]
exp_offset = np.reshape(exp_offset, shape, order='F')
with pytest.deprecated_call():
with deprecated_to('5.0.0'):
assert_array_equal(exp_offset, read_img_data(img_back))
# Delete stuff that might hold onto file references
del img, img_back, data_back
Loading

0 comments on commit 27c2427

Please sign in to comment.