[med-svn] [Git][med-team/nibabel][upstream] New upstream version 4.0.2

Étienne Mollier (@emollier) gitlab at salsa.debian.org
Thu Dec 8 21:06:39 GMT 2022



Étienne Mollier pushed to branch upstream at Debian Med / nibabel


Commits:
3e4459c2 by Étienne Mollier at 2022-12-08T21:19:23+01:00
New upstream version 4.0.2
- - - - -


9 changed files:

- Changelog
- nibabel/_version.py
- nibabel/arraywriters.py
- nibabel/gifti/gifti.py
- nibabel/gifti/tests/test_gifti.py
- nibabel/gifti/tests/test_parse_gifti_fast.py
- nibabel/info.py
- nibabel/tests/test_arraywriters.py
- nibabel/tests/test_removalschedule.py


Changes:

=====================================
Changelog
=====================================
@@ -25,6 +25,22 @@ Eric Larson (EL), Demian Wassermann, Stephan Gerhard and Ross Markello (RM).
 
 References like "pr/298" refer to github pull request numbers.
 
+4.0.2 (Wednesday 31 August 2022)
+================================
+
+Bug-fix release in the 4.0.x series.
+
+Bug fixes
+---------
+* Make ``GiftiMetaData.data`` a list proxy, deprecate (pr/1127) (CM, reviewed
+  by Hao-Ting Wang)
+
+Maintenance
+-----------
+* Finalize deprecation of ``ArrayWriter.to_fileobj(nan2zero=...)`` argument
+  (pr/1126) (CM)
+
+
 4.0.1 (Saturday 18 June 2022)
 =============================
 


=====================================
nibabel/_version.py
=====================================
@@ -26,9 +26,9 @@ def get_keywords():
     # setup.py/versioneer.py will grep for the variable names, so they must
     # each be defined on a line of their own. _version.py will just call
     # get_keywords().
-    git_refnames = " (tag: 4.0.1)"
-    git_full = "b0b16b811aaf7bb866ca764259c0cd20f8c03950"
-    git_date = "2022-06-18 17:52:37 +0100"
+    git_refnames = " (tag: 4.0.2)"
+    git_full = "0efe615554874c8d6c1dd3934e22a91f9ffa297f"
+    git_date = "2022-08-31 09:39:12 -0400"
     keywords = {"refnames": git_refnames, "full": git_full, "date": git_date}
     return keywords
 


=====================================
nibabel/arraywriters.py
=====================================
@@ -29,13 +29,12 @@ something else to make sense of conversions between float and int, or between
 larger ints and smaller.
 """
 
-import warnings
-
 import numpy as np
 
 from .casting import (int_to_float, as_int, int_abs, type_info, floor_exact,
                       best_float, shared_range)
 from .volumeutils import finite_range, array_to_file
+from .deprecator import ExpiredDeprecationError
 
 
 class WriterError(Exception):
@@ -192,11 +191,12 @@ class ArrayWriter(object):
         if nan2zero != self._nan2zero:
             raise WriterError('Deprecated `nan2zero` argument to `to_fileobj` '
                               'must be same as class value set in __init__')
-        warnings.warn('Please remove `nan2zero` from call to ' '`to_fileobj` '
-                      'and use in instance __init__ instead.\n'
-                      '* deprecated in version: 2.0\n'
-                      '* will raise error in version: 4.0\n',
-                      DeprecationWarning, stacklevel=3)
+        raise ExpiredDeprecationError(
+            'Please remove `nan2zero` from call to `to_fileobj` '
+            'and use in instance __init__ instead.\n'
+            '* deprecated in version: 2.0\n'
+            '* Raises ExpiredDeprecationError as of version: 4.0\n'
+        )
 
     def _needs_nan2zero(self):
         """ True if nan2zero check needed for writing array """


=====================================
nibabel/gifti/gifti.py
=====================================
@@ -26,6 +26,42 @@ from .util import (array_index_order_codes, gifti_encoding_codes,
 from ..deprecated import deprecate_with_version
 
 
+class _GiftiMDList(list):
+    """List view of GiftiMetaData object that will translate most operations"""
+    def __init__(self, metadata):
+        self._md = metadata
+        super().__init__(
+            GiftiNVPairs._private_init(k, v, metadata)
+            for k, v in metadata.items()
+        )
+
+    def append(self, nvpair):
+        self._md[nvpair.name] = nvpair.value
+        super().append(nvpair)
+
+    def clear(self):
+        super().clear()
+        self._md.clear()
+
+    def extend(self, iterable):
+        for nvpair in iterable:
+            self.append(nvpair)
+
+    def insert(self, index, nvpair):
+        self._md[nvpair.name] = nvpair.value
+        super().insert(index, nvpair)
+
+    def pop(self, index=-1):
+        nvpair = super().pop(index)
+        nvpair._container = None
+        del self._md[nvpair.name]
+        return nvpair
+
+    def remove(self, nvpair):
+        super().remove(nvpair)
+        del self._md[nvpair.name]
+
+
 class GiftiMetaData(CaretMetaData):
     """ A sequence of GiftiNVPairs containing metadata for a gifti data array
     """
@@ -72,11 +108,12 @@ class GiftiMetaData(CaretMetaData):
         return (), {pair.name: pair.value}
 
     @property
+    @deprecate_with_version(
+        'The data attribute is deprecated. Use GiftiMetaData object '
+        'directly as a dict.',
+        '4.0', '6.0')
     def data(self):
-        warnings.warn(
-            "GiftiMetaData.data will be a dict in NiBabel 6.0.",
-            FutureWarning, stacklevel=2)
-        return [GiftiNVPairs(k, v) for k, v in self._data.items()]
+        return _GiftiMDList(self)
 
     @classmethod
     @deprecate_with_version(
@@ -94,7 +131,7 @@ class GiftiMetaData(CaretMetaData):
 
     @property
     @deprecate_with_version(
-        'metadata property deprecated. Use GiftiMetadata object '
+        'metadata property deprecated. Use GiftiMetaData object '
         'as dict or pass to dict() for a standard dictionary.',
         '4.0', '6.0')
     def metadata(self):
@@ -113,9 +150,48 @@ class GiftiNVPairs:
     name : str
     value : str
     """
+    @deprecate_with_version(
+        'GiftiNVPairs objects are deprecated. Use the GiftiMetaData object '
+        'as a dict, instead.',
+        '4.0', '6.0')
     def __init__(self, name=u'', value=u''):
-        self.name = name
-        self.value = value
+        self._name = name
+        self._value = value
+        self._container = None
+
+    @classmethod
+    def _private_init(cls, name, value, md):
+        """Private init method to provide warning-free experience"""
+        with warnings.catch_warnings():
+            warnings.simplefilter('ignore', DeprecationWarning)
+            self = cls(name, value)
+        self._container = md
+        return self
+
+    def __eq__(self, other):
+        if not isinstance(other, GiftiNVPairs):
+            return NotImplemented
+        return self.name == other.name and self.value == other.value
+
+    @property
+    def name(self):
+        return self._name
+
+    @name.setter
+    def name(self, key):
+        if self._container:
+            self._container[key] = self._container.pop(self._name)
+        self._name = key
+
+    @property
+    def value(self):
+        return self._value
+
+    @value.setter
+    def value(self, val):
+        if self._container:
+            self._container[self._name] = val
+        self._value = val
 
 
 class GiftiLabelTable(xml.XmlSerializable):


=====================================
nibabel/gifti/tests/test_gifti.py
=====================================
@@ -228,7 +228,8 @@ def test_labeltable():
 def test_metadata():
     md = GiftiMetaData(key='value')
     # Old initialization methods
-    nvpair = GiftiNVPairs('key', 'value')
+    with pytest.warns(DeprecationWarning) as w:
+        nvpair = GiftiNVPairs('key', 'value')
     with pytest.warns(FutureWarning) as w:
         md2 = GiftiMetaData(nvpair=nvpair)
     assert len(w) == 1
@@ -236,7 +237,7 @@ def test_metadata():
         md3 = GiftiMetaData.from_dict({'key': 'value'})
     assert md == md2 == md3 == {'key': 'value'}
     # .data as a list of NVPairs is going away
-    with pytest.warns(FutureWarning) as w:
+    with pytest.warns(DeprecationWarning) as w:
         assert md.data[0].name == 'key'
         assert md.data[0].value == 'value'
     assert len(w) == 2
@@ -245,6 +246,85 @@ def test_metadata():
         md.get_metadata()
 
 
+def test_metadata_list_interface():
+    md = GiftiMetaData(key='value')
+    with pytest.warns(DeprecationWarning):
+        mdlist = md.data
+    assert len(mdlist) == 1
+    assert mdlist[0].name == 'key'
+    assert mdlist[0].value == 'value'
+
+    # Modify elements in-place
+    mdlist[0].name = 'foo'
+    assert mdlist[0].name == 'foo'
+    assert 'foo' in md
+    assert 'key' not in md
+    assert md['foo'] == 'value'
+    mdlist[0].value = 'bar'
+    assert mdlist[0].value == 'bar'
+    assert md['foo'] == 'bar'
+
+    # Append new NVPair
+    with pytest.warns(DeprecationWarning) as w:
+        nvpair = GiftiNVPairs('key', 'value')
+    mdlist.append(nvpair)
+    assert len(mdlist) == 2
+    assert mdlist[1].name == 'key'
+    assert mdlist[1].value == 'value'
+    assert len(md) == 2
+    assert md == {'foo': 'bar', 'key': 'value'}
+
+    # Clearing empties both
+    mdlist.clear()
+    assert len(mdlist) == 0
+    assert len(md) == 0
+
+    # Extension adds multiple keys
+    with pytest.warns(DeprecationWarning) as w:
+        foobar = GiftiNVPairs('foo', 'bar')
+    mdlist.extend([nvpair, foobar])
+    assert len(mdlist) == 2
+    assert len(md) == 2
+    assert md == {'key': 'value', 'foo': 'bar'}
+
+    # Insertion updates list order, though we don't attempt to preserve it in the dict
+    with pytest.warns(DeprecationWarning) as w:
+        lastone = GiftiNVPairs('last', 'one')
+    mdlist.insert(1, lastone)
+    assert len(mdlist) == 3
+    assert len(md) == 3
+    assert mdlist[1].name == 'last'
+    assert mdlist[1].value == 'one'
+    assert md == {'key': 'value', 'foo': 'bar', 'last': 'one'}
+
+    # Popping returns a pair
+    mypair = mdlist.pop(0)
+    assert isinstance(mypair, GiftiNVPairs)
+    assert mypair.name == 'key'
+    assert mypair.value == 'value'
+    assert len(mdlist) == 2
+    assert len(md) == 2
+    assert 'key' not in md
+    assert md == {'foo': 'bar', 'last': 'one'}
+    # Modifying the pair now does not affect md
+    mypair.name = 'completelynew'
+    mypair.value = 'strings'
+    assert 'completelynew' not in md
+    assert md == {'foo': 'bar', 'last': 'one'}
+    # Check popping from the end (lastone inserted before foobar)
+    lastpair = mdlist.pop()
+    assert len(mdlist) == 1
+    assert len(md) == 1
+    assert md == {'last': 'one'}
+
+    # And let's remove an old pair with a new object
+    with pytest.warns(DeprecationWarning) as w:
+        lastoneagain = GiftiNVPairs('last', 'one')
+    mdlist.remove(lastoneagain)
+    assert len(mdlist) == 0
+    assert len(md) == 0
+
+
 def test_gifti_label_rgba():
     rgba = np.random.rand(4)
     kwargs = dict(zip(['red', 'green', 'blue', 'alpha'], rgba))


=====================================
nibabel/gifti/tests/test_parse_gifti_fast.py
=====================================
@@ -147,7 +147,7 @@ def test_default_types():
         # GiftiMetaData
         assert_default_types(img.meta)
         # GiftiNVPairs - Remove in NIB6
-        with pytest.warns(FutureWarning):
+        with pytest.warns(DeprecationWarning):
             for nvpair in img.meta.data:
                 assert_default_types(nvpair)
         # GiftiLabelTable
@@ -161,7 +161,7 @@ def test_default_types():
             # GiftiMetaData
             assert_default_types(darray.meta)
             # GiftiNVPairs - Remove in NIB6
-            with pytest.warns(FutureWarning):
+            with pytest.warns(DeprecationWarning):
                 for nvpair in darray.meta.data:
                     assert_default_types(nvpair)
 


=====================================
nibabel/info.py
=====================================
@@ -12,7 +12,7 @@ relative imports.
 # development (pre-release) version.
 _version_major = 4
 _version_minor = 0
-_version_micro = 1
+_version_micro = 2
 _version_extra = '.dev0'
 
 # Format expected by setup.py and doc/source/conf.py: string of form "X.Y.Z"


=====================================
nibabel/tests/test_arraywriters.py
=====================================
@@ -13,11 +13,11 @@ from ..arraywriters import (SlopeInterArrayWriter, SlopeArrayWriter,
                             make_array_writer, get_slope_inter)
 from ..casting import int_abs, type_info, shared_range, on_powerpc
 from ..volumeutils import array_from_file, apply_read_scaling, _dt_min_max
+from ..deprecator import ExpiredDeprecationError
 
 from numpy.testing import assert_array_almost_equal, assert_array_equal
 import pytest
-from ..testing import (assert_allclose_safely, suppress_warnings,
-                       error_warnings)
+from ..testing import assert_allclose_safely, suppress_warnings
 
 
 FLOAT_TYPES = np.sctypes['float']
@@ -506,12 +506,11 @@ def test_nan2zero():
         aw = awt(arr, np.float32, **kwargs)
         data_back = round_trip(aw)
         assert_array_equal(np.isnan(data_back), [True, False])
-        # Deprecation warning for nan2zero as argument to `to_fileobj`
-        with error_warnings():
-            with pytest.deprecated_call():
-                aw.to_fileobj(BytesIO(), 'F', True)
-            with pytest.deprecated_call():
-                aw.to_fileobj(BytesIO(), 'F', nan2zero=True)
+        # Expired deprecation error for nan2zero as argument to `to_fileobj`
+        with pytest.raises(ExpiredDeprecationError):
+            aw.to_fileobj(BytesIO(), 'F', True)
+        with pytest.raises(ExpiredDeprecationError):
+            aw.to_fileobj(BytesIO(), 'F', nan2zero=True)
         # Error if nan2zero is not the value set at initialization
         with pytest.raises(WriterError):
             aw.to_fileobj(BytesIO(), 'F', False)
@@ -528,12 +527,11 @@ def test_nan2zero():
         data_back = round_trip(aw)
         astype_res = np.array(np.nan).astype(np.int32)
         assert_array_equal(data_back, [astype_res, 99])
-        # Deprecation warning for nan2zero as argument to `to_fileobj`
-        with error_warnings():
-            with pytest.deprecated_call():
-                aw.to_fileobj(BytesIO(), 'F', False)
-            with pytest.deprecated_call():
-                aw.to_fileobj(BytesIO(), 'F', nan2zero=False)
+        # Expired deprecation error for nan2zero as argument to `to_fileobj`
+        with pytest.raises(ExpiredDeprecationError):
+            aw.to_fileobj(BytesIO(), 'F', False)
+        with pytest.raises(ExpiredDeprecationError):
+            aw.to_fileobj(BytesIO(), 'F', nan2zero=False)
         # Error if nan2zero is not the value set at initialization
         with pytest.raises(WriterError):
             aw.to_fileobj(BytesIO(), 'F', True)


=====================================
nibabel/tests/test_removalschedule.py
=====================================
@@ -12,6 +12,8 @@ MODULE_SCHEDULE = [
 ]
 
 OBJECT_SCHEDULE = [
+    ("7.0.0", [("nibabel.gifti.gifti", "GiftiNVPairs"),
+    ]),
     ("6.0.0", [("nibabel.loadsave", "guessed_image_type"),
                ("nibabel.loadsave", "read_img_data"),
                ("nibabel.orientations", "flip_axis"),
@@ -41,6 +43,7 @@ OBJECT_SCHEDULE = [
 ATTRIBUTE_SCHEDULE = [
     ("7.0.0", [("nibabel.gifti.gifti", "GiftiMetaData", "from_dict"),
                ("nibabel.gifti.gifti", "GiftiMetaData", "metadata"),
+               ("nibabel.gifti.gifti", "GiftiMetaData", "data"),
     ]),
     ("5.0.0", [("nibabel.dataobj_images", "DataobjImage", "get_data"),
                ("nibabel.freesurfer.mghformat", "MGHHeader", "_header_data"),
@@ -62,6 +65,7 @@ ATTRIBUTE_SCHEDULE = [
                ("nibabel.ecat", "EcatImage", "from_filespec"),
                ("nibabel.filebasedimages", "FileBasedImage", "get_header"),
                ("nibabel.spatialimages", "SpatialImage", "get_affine"),
+               ("nibabel.arraywriters", "ArrayWriter", "_check_nan2zero"),
     ]),
     ("4.0.0", [("nibabel.dataobj_images", "DataobjImage", "get_shape"),
                ("nibabel.filebasedimages", "FileBasedImage", "filespec_to_files"),



View it on GitLab: https://salsa.debian.org/med-team/nibabel/-/commit/3e4459c2fe5ea0509cd504e7f813752a371a8a45

-- 
View it on GitLab: https://salsa.debian.org/med-team/nibabel/-/commit/3e4459c2fe5ea0509cd504e7f813752a371a8a45
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20221208/1e54264b/attachment-0001.htm>


More information about the debian-med-commit mailing list