diff --git a/Changelog b/Changelog index fe5f3c30a..bc7cdd005 100644 --- a/Changelog +++ b/Changelog @@ -11,6 +11,7 @@ `'standard'` or `'gregorian'`. If `None` (the default), check that the calendar attribute is present on each variable and values are unique across files raising a `ValueError` otherwise. + * Allow _FillValue to be set for vlen string variables (issue #730). version 1.3.0 (tag v1.3.0rel) ============================== diff --git a/netCDF4/_netCDF4.pyx b/netCDF4/_netCDF4.pyx index 87e9f4278..278d9a1a0 100644 --- a/netCDF4/_netCDF4.pyx +++ b/netCDF4/_netCDF4.pyx @@ -3469,14 +3469,16 @@ behavior is similar to Fortran or Matlab, but different than numpy. if grp.data_model != 'NETCDF4': grp._enddef() _ensure_nc_success(ierr) else: - # cast fill_value to type of variable. - # also make sure it is written in native byte order - # (the same as the data) - if self._isprimitive or self._isenum: - fillval = numpy.array(fill_value, self.dtype) - if not fillval.dtype.isnative: fillval.byteswap(True) - _set_att(self._grp, self._varid, '_FillValue',\ - fillval, xtype=xtype) + if self._isprimitive or self._isenum or \ + (self._isvlen and self.dtype == str): + if self._isvlen and self.dtype == str: + _set_att(self._grp, self._varid, '_FillValue',\ + _tostr(fill_value), xtype=xtype, force_ncstring=True) + else: + fillval = numpy.array(fill_value, self.dtype) + if not fillval.dtype.isnative: fillval.byteswap(True) + _set_att(self._grp, self._varid, '_FillValue',\ + fillval, xtype=xtype) else: raise AttributeError("cannot set _FillValue attribute for VLEN or compound variable") if least_significant_digit is not None: diff --git a/test/tst_masked5.py b/test/tst_masked5.py index 8b376bdbd..af49bf168 100755 --- a/test/tst_masked5.py +++ b/test/tst_masked5.py @@ -5,7 +5,7 @@ import numpy as np from numpy import ma from numpy.testing import assert_array_equal -from netCDF4 import Dataset +from netCDF4 import Dataset, __netcdf4libversion__ # Test use of vector of missing values. @@ -23,9 +23,12 @@ def setUp(self): f = Dataset(self.testfile, 'w') d = f.createDimension('x',6) v = f.createVariable('v', "i2", 'x') + # issue 730: set fill_value for vlen str vars + v2 = f.createVariable('v2',str,'x',fill_value=u'') v.missing_value = self.missing_values v[:] = self.v + v2[0]='first' f.close() @@ -41,6 +44,7 @@ def test_scaled(self): f = Dataset(self.testfile) v = f.variables["v"] + v2 = f.variables["v2"] self.assertTrue(isinstance(v[:], ma.core.MaskedArray)) assert_array_equal(v[:], self.v_ma) assert_array_equal(v[2],self.v[2]) # issue #624. @@ -48,6 +52,14 @@ def test_scaled(self): self.assertTrue(isinstance(v[:], np.ndarray)) assert_array_equal(v[:], self.v) + # issue 730 + # this part fails with netcdf 4.1.3 + # a bug in vlen strings? + if __netcdf4libversion__ >= '4.4.0': + assert (v2[0]==u'first') + assert (v2[1]==u'') + + f.close()