diff --git a/lib/iris/fileformats/netcdf.py b/lib/iris/fileformats/netcdf.py index 11565299fb..e5a4a479f4 100644 --- a/lib/iris/fileformats/netcdf.py +++ b/lib/iris/fileformats/netcdf.py @@ -2251,6 +2251,10 @@ def is_valid_packspec(p): else: conventions = CF_CONVENTIONS_VERSION + # Prioritise cube attributes conventions over the default. + if 'Conventions' in cube.attributes: + conventions = cube.attributes['Conventions'] + # Perform a CF patch of the conventions attribute. cf_profile_available = (iris.site_configuration.get('cf_profile') not in [None, False]) diff --git a/lib/iris/tests/integration/test_netcdf.py b/lib/iris/tests/integration/test_netcdf.py index 20e1e95bbd..9b3ef1b914 100644 --- a/lib/iris/tests/integration/test_netcdf.py +++ b/lib/iris/tests/integration/test_netcdf.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2014 - 2016, Met Office +# (C) British Crown Copyright 2014 - 2017, Met Office # # This file is part of Iris. # @@ -179,22 +179,38 @@ def update(config): class TestConventionsAttributes(tests.IrisTest): - def test_patching_conventions_attribute(self): - # Ensure that user defined conventions are wiped and those which are + def test_patching_conventions_attribute_user_existing(self): + # Ensure that user defined conventions pass-thru and those which are # saved patched through site_config can be loaded without an exception # being raised. + conventions = 'some user defined conventions' cube = Cube([1.0], standard_name='air_temperature', units='K', - attributes={'Conventions': - 'some user defined conventions'}) + attributes=dict(Conventions=conventions)) # Patch the site configuration dictionary. with _patch_site_configuration(), self.temp_filename('.nc') as nc_path: iris.save(cube, nc_path) res = iris.load_cube(nc_path) - self.assertEqual(res.attributes['Conventions'], - '{}, {}, {}'.format(CF_CONVENTIONS_VERSION, - 'convention1', 'convention2')) + expected = '{}, {}, {}'.format(conventions, + 'convention1', + 'convention2') + self.assertEqual(res.attributes['Conventions'], expected) + + def test_patching_conventions_attribute_user_missing(self): + # Ensure that conventions which are saved patched through site_config + # can be loaded without an exception being raised. + cube = Cube([1.0], standard_name='air_temperature', units='K') + + # Patch the site configuration dictionary. + with _patch_site_configuration(), self.temp_filename('.nc') as nc_path: + iris.save(cube, nc_path) + res = iris.load_cube(nc_path) + + expected = '{}, {}, {}'.format(CF_CONVENTIONS_VERSION, + 'convention1', + 'convention2') + self.assertEqual(res.attributes['Conventions'], expected) class TestLazySave(tests.IrisTest): diff --git a/lib/iris/tests/results/netcdf/netcdf_save_load_ndim_auxiliary.cml b/lib/iris/tests/results/netcdf/netcdf_save_load_ndim_auxiliary.cml index 772c37808c..f7118af577 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_load_ndim_auxiliary.cml +++ b/lib/iris/tests/results/netcdf/netcdf_save_load_ndim_auxiliary.cml @@ -2,7 +2,7 @@ - + diff --git a/lib/iris/tests/results/netcdf/netcdf_save_ndim_auxiliary.cdl b/lib/iris/tests/results/netcdf/netcdf_save_ndim_auxiliary.cdl index ee172ace82..cf23a3e82c 100644 --- a/lib/iris/tests/results/netcdf/netcdf_save_ndim_auxiliary.cdl +++ b/lib/iris/tests/results/netcdf/netcdf_save_ndim_auxiliary.cdl @@ -50,5 +50,5 @@ variables: :history = "Thu Nov 29 10:45:50 2012: /project/ukmo/rhel6/nco/bin/ncks -d time,0,3 new_rotPole_precipitation.nc small_rotPole_precipitation.nc" ; :institution = "DMI" ; :source = "HIRHAM" ; - :Conventions = "CF-1.5" ; + :Conventions = "CF-1.0" ; } diff --git a/lib/iris/tests/test_netcdf.py b/lib/iris/tests/test_netcdf.py index 6463122409..55dc4d28c7 100644 --- a/lib/iris/tests/test_netcdf.py +++ b/lib/iris/tests/test_netcdf.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2016, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -699,13 +699,10 @@ def test_attributes(self): # Should be global attributes. aglobals = {'history': 'A long time ago...', 'title': 'Attribute test', - 'foo': 'bar'} + 'foo': 'bar', + 'Conventions': 'TEST'} for k, v in six.iteritems(aglobals): self.cube.attributes[k] = v - # Should be overriden. - aover = {'Conventions': 'TEST'} - for k, v in six.iteritems(aover): - self.cube.attributes[k] = v # Should be data varible attributes. avars = {'standard_error_multiplier': 23, 'flag_masks': 'a', @@ -724,11 +721,7 @@ def test_attributes(self): if getattr(ds, gkey) != aglobals.get(gkey): exceptions.append('{} != {}'.format(getattr(ds, gkey), aglobals.get(gkey))) - # Should be overriden. - for okey in aover: - if getattr(ds, okey) == aover.get(okey): - exceptions.append('{} != {}'.format(getattr(ds, okey), - avars.get(okey))) + dv = ds['temp'] # Should be data varible attributes; # except STASH -> um_stash_source. diff --git a/lib/iris/tests/unit/fileformats/netcdf/test_save.py b/lib/iris/tests/unit/fileformats/netcdf/test_save.py index 936de128a6..0cd62f416e 100644 --- a/lib/iris/tests/unit/fileformats/netcdf/test_save.py +++ b/lib/iris/tests/unit/fileformats/netcdf/test_save.py @@ -48,6 +48,9 @@ def test_custom_conventions__ignored(self): ds = nc.Dataset(nc_path) res = ds.getncattr('Conventions') ds.close() + print('testing here') + print('res ' + res) + print('CF_CONVENTIONS_VERSION ' + CF_CONVENTIONS_VERSION) self.assertEqual(res, CF_CONVENTIONS_VERSION) def test_custom_conventions__allowed(self):