def test__call(self): # Check that the function creates an FF2PP and returns the result # of iterating over it. # Make a real (test) iterator object, as otherwise iter() complains... mock_iterator = (1 for x in ()) # Make a mock for the iter() call of an FF2PP object. mock_iter_call = mock.MagicMock(return_value=mock_iterator) # Make a mock FF2PP object instance. mock_ff2pp_instance = mock.MagicMock(__iter__=mock_iter_call) # Make the mock FF2PP class. mock_ff2pp_class = mock.MagicMock(return_value=mock_ff2pp_instance) # Call um_to_pp while patching the um._ff_replacement.FF2PP class. test_path = '/any/old/file.name' with mock.patch('iris.fileformats.um._ff_replacement.FF2PP', mock_ff2pp_class): result = um_to_pp(test_path) # Check that it called FF2PP in the expected way. self.assertEqual(mock_ff2pp_class.call_args_list, [mock.call('/any/old/file.name', read_data=False)]) self.assertEqual(mock_ff2pp_instance.__iter__.call_args_list, [mock.call()]) # Check that it returned the expected result. self.assertIs(result, mock_iterator)
def test_two_plots_with_independent_axes(self): c1 = Contour(self.cube, self.axes) levels = 5 other = _add_levels(self.cube, levels)[:, 0] c2 = Contour(other, self.axes) with mock.patch('cube_browser.Contour.__call__') as func: browser = Browser([c1, c2]) browser.display() # Check the initial render. self.assertEqual(func.call_count, 2) expected = [ mock.call(time=self.value), mock.call(model_level_number=self.value) ] func.assert_has_calls(expected) # Now simulate a 'time' slider change. slider = browser._slider_by_name['time'] change = dict(owner=slider) browser.on_change(change) self.assertEqual(func.call_count, 3) expected.append(mock.call(time=self.value)) func.assert_has_calls(expected) # Now simulate a 'model_level_number' slider change. slider = browser._slider_by_name['model_level_number'] change = dict(owner=slider) browser.on_change(change) self.assertEqual(func.call_count, 4) expected.append(mock.call(model_level_number=self.value)) func.assert_has_calls(expected)
def test_two_plots_with_independent_axes(self): c1 = Contour(self.cube, self.axes) levels = 5 other = _add_levels(self.cube, levels)[:, 0] c2 = Contour(other, self.axes) with mock.patch('cube_browser.Contour.__call__') as func: browser = Browser([c1, c2]) browser.display() # Check the initial render. self.assertEqual(func.call_count, 2) expected = [mock.call(time=self.value), mock.call(model_level_number=self.value)] func.assert_has_calls(expected) # Now simulate a 'time' slider change. slider = browser._slider_by_name['time'] change = dict(owner=slider) browser.on_change(change) self.assertEqual(func.call_count, 3) expected.append(mock.call(time=self.value)) func.assert_has_calls(expected) # Now simulate a 'model_level_number' slider change. slider = browser._slider_by_name['model_level_number'] change = dict(owner=slider) browser.on_change(change) self.assertEqual(func.call_count, 4) expected.append(mock.call(model_level_number=self.value)) func.assert_has_calls(expected)
def test_save_append(self): if six.PY3: open_func = 'builtins.open' else: open_func = '__builtin__.open' m = mock.mock_open() with mock.patch(open_func, m, create=True): pp.save_fields([self.pp_field], 'foo.pp', append=True) self.assertTrue(mock.call('foo.pp', 'ab') in m.mock_calls) self.assertTrue(mock.call().write('saved') in m.mock_calls)
def test_two_plots_with_no_axis(self): cube = self.cube[0] c1 = Contour(cube, self.axes) c2 = Contour(cube, self.axes) with mock.patch('cube_browser.Contour.__call__') as func: browser = Browser([c1, c2]) browser.display() # Check the initial render - forced! self.assertEqual(func.call_count, 2) expected = [mock.call(), mock.call()] func.assert_has_calls(expected)
def test_single_plot_with_axis(self): plot = Contour(self.cube, self.axes) with mock.patch('cube_browser.Contour.__call__') as func: browser = Browser(plot) browser.display() # Check the initial render. func.assert_called_once_with(time=self.value) # Now simulate a slider change. slider = browser._slider_by_name['time'] change = dict(owner=slider) browser.on_change(change) self.assertEqual(func.call_count, 2) expected = [mock.call(time=self.value), mock.call(time=self.value)] func.assert_has_calls(expected)
def test_default_chunks_limiting(self): # Check that chunking is limited when no specific 'chunks' given. limitcall_patch = self.patch('iris._lazy_data._limited_shape') test_shape = (3, 2, 4) data = self._dummydata(test_shape) as_lazy_data(data) self.assertEqual(limitcall_patch.call_args_list, [mock.call(test_shape)])
def test_time_as_object(self): # Ensure Coord.cell() converts the point/bound values to # "datetime" objects. coord = self._mock_coord() coord.units.num2date = mock.Mock( side_effect=[mock.sentinel.datetime, (mock.sentinel.datetime_lower, mock.sentinel.datetime_upper)]) cell = Coord.cell(coord, 0) self.assertIs(cell.point, mock.sentinel.datetime) self.assertEqual(cell.bound, (mock.sentinel.datetime_lower, mock.sentinel.datetime_upper)) self.assertEqual(coord.units.num2date.call_args_list, [mock.call((mock.sentinel.time,)), mock.call((mock.sentinel.lower, mock.sentinel.upper))])
def test_read_headers_call(self): # Checks that the two calls to np.fromfile are called in the # expected way. pp_field = mock.Mock(lblrec=1, lbext=0, lbuser=[0]) with self.mock_for_field_gen([pp_field]): open_fh = mock.MagicMock(spec=io.RawIOBase) open.return_value = open_fh next(pp._field_gen('mocked', read_data_bytes=False)) with open_fh as open_fh_ctx: calls = [mock.call(open_fh_ctx, count=45, dtype='>i4'), mock.call(open_fh_ctx, count=19, dtype='>f4')] np.fromfile.assert_has_calls(calls) with open_fh as open_fh_ctx: expected_deferred_bytes = ('mocked', open_fh_ctx.tell(), 4, np.dtype('>f4')) self.assertEqual(pp_field._data, expected_deferred_bytes)
def test_time_as_object(self): # When iris.FUTURE.cell_datetime_objects is True, ensure # Coord.cell() converts the point/bound values to "datetime" # objects. coord = self._mock_coord() coord.units.num2date = mock.Mock( side_effect=[mock.sentinel.datetime, (mock.sentinel.datetime_lower, mock.sentinel.datetime_upper)]) with mock.patch('iris.FUTURE', cell_datetime_objects=True): cell = Coord.cell(coord, 0) self.assertIs(cell.point, mock.sentinel.datetime) self.assertEqual(cell.bound, (mock.sentinel.datetime_lower, mock.sentinel.datetime_upper)) self.assertEqual(coord.units.num2date.call_args_list, [mock.call((mock.sentinel.time,)), mock.call((mock.sentinel.lower, mock.sentinel.upper))])
def test_default_chunks_limiting(self): # Check that chunking is still controlled when no specific 'chunks' # is passed. limitcall_patch = self.patch('iris._lazy_data._optimum_chunksize') test_shape = (3, 2, 4) data = self._dummydata(test_shape) as_lazy_data(data) self.assertEqual(limitcall_patch.call_args_list, [ mock.call(list(test_shape), shape=test_shape, dtype=np.dtype('f4')) ])
def _check_bounds_setting(self, climatological=False): # Generic test that can run with or without a climatological coord. cube = stock.climatology_3d() coord = cube.coord('time').copy() # Over-write original value from stock.climatology_3d with test value. coord.climatological = \ climatological # Set up expected strings. if climatological: property_name = 'climatology' varname_extra = 'climatology' else: property_name = 'bounds' varname_extra = 'bnds' boundsvar_name = 'time_' + varname_extra # Set up arguments for testing _create_cf_bounds. saver = mock.MagicMock(spec=Saver) # NOTE: 'saver' must have spec=Saver to fake isinstance(save, Saver), # so it can pass as 'self' in the call to _create_cf_cbounds. # Mock a '_dataset' property; not automatic because 'spec=Saver'. saver._dataset = mock.MagicMock() # Mock the '_ensure_valid_dtype' method to return an object with a # suitable 'shape' and 'dtype'. saver._ensure_valid_dtype.return_value = mock.Mock( shape=coord.bounds.shape, dtype=coord.bounds.dtype) var = mock.MagicMock(spec=nc.Variable) # Make the main call. Saver._create_cf_bounds(saver, coord, var, 'time') # Test the call of _setncattr in _create_cf_bounds. setncattr_call = mock.call(property_name, boundsvar_name.encode(encoding='ascii')) self.assertEqual(setncattr_call, var.setncattr.call_args) # Test the call of createVariable in _create_cf_bounds. dataset = saver._dataset expected_dimensions = var.dimensions + ('bnds', ) create_var_call = mock.call(boundsvar_name, coord.bounds.dtype, expected_dimensions) self.assertEqual(create_var_call, dataset.createVariable.call_args)
def test_realise_data(self): # Simply check that calling CubeList.realise_data is calling # _lazy_data.co_realise_cubes. mock_cubes_list = [mock.Mock(ident=count) for count in range(3)] test_cubelist = CubeList(mock_cubes_list) call_patch = self.patch('iris._lazy_data.co_realise_cubes') test_cubelist.realise_data() # Check it was called once, passing cubes as *args. self.assertEqual(call_patch.call_args_list, [mock.call(*mock_cubes_list)])
def _call_target(self, fill_value, keys, vals): inner_target = mock.MagicMock() target = _FillValueMaskCheckAndStoreTarget(inner_target, fill_value=fill_value) for key, val in zip(keys, vals): target[key] = val calls = [mock.call(key, val) for key, val in zip(keys, vals)] inner_target.__setitem__.assert_has_calls(calls) return target
def test_basic(self): result = product_definition_template_9( self.section, self.metadata, self.frt_coord) # Check expected function was called. self.assertEqual( self.patch_pdt8_call.call_args_list, [mock.call(self.section, self.metadata, self.frt_coord)]) # Check metadata content (N.B. cell_method has been removed!). self.assertEqual(self.metadata, {'cell_methods': [], 'aux_coords_and_dims': []}) # Check result. self.assertEqual(result, Probability('above_threshold', 5.3))
def test_caching(self): # Check that it calculates regrid info just once, and re-uses it in # subsequent calls. src_grid = self.src_grid target_grid = self.tgt_grid regridder = Regridder(src_grid, target_grid, self.weights) different_src_cube = self.src_grid.copy() different_src_cube.rename('Different_source') with mock.patch(self.func_setup, return_value=mock.sentinel.regrid_info) as patch_setup: with mock.patch( self.func_operate, return_value=self.dummy_slice_result) as patch_operate: result1 = regridder(src_grid) result2 = regridder(different_src_cube) patch_setup.assert_called_once_with(src_grid, self.weights, target_grid) self.assertEqual(len(patch_operate.call_args_list), 2) self.assertEqual(patch_operate.call_args_list, [ mock.call(src_grid, mock.sentinel.regrid_info), mock.call(different_src_cube, mock.sentinel.regrid_info) ])
def test_save(self): if six.PY3: open_func = 'builtins.open' else: open_func = '__builtin__.open' m = mock.mock_open() with mock.patch(open_func, m, create=True): # sending a MagicMock object to gribapi raises an AssertionError # as the gribapi code does a type check # this is deemed acceptable within the scope of this unit test with self.assertRaises(AssertionError): grib.save_messages([self.grib_message], 'foo.grib2') self.assertTrue(mock.call('foo.grib2', 'wb') in m.mock_calls)
def test_caching(self): # Check that it calculates regrid info just once, and re-uses it in # subsequent calls. src_grid = self.src_grid target_grid = self.tgt_grid regridder = Regridder(src_grid, target_grid, self.weights) different_src_cube = self.src_grid.copy() different_src_cube.rename('Different_source') with mock.patch(self.func_setup, return_value=mock.sentinel.regrid_info) as patch_setup: with mock.patch( self.func_operate, return_value=self.dummy_slice_result) as patch_operate: result1 = regridder(src_grid) result2 = regridder(different_src_cube) patch_setup.assert_called_once_with( src_grid, self.weights, target_grid) self.assertEqual(len(patch_operate.call_args_list), 2) self.assertEqual( patch_operate.call_args_list, [mock.call(src_grid, mock.sentinel.regrid_info), mock.call(different_src_cube, mock.sentinel.regrid_info)])
def test_save_append(self): if six.PY3: open_func = "builtins.open" else: open_func = "__builtin__.open" m = mock.mock_open() with mock.patch(open_func, m, create=True): # sending a MagicMock object to gribapi raises an AssertionError # as the gribapi code does a type check # this is deemed acceptable within the scope of this unit test with self.assertRaises((AssertionError, TypeError)): grib.save_messages([self.grib_message], "foo.grib2", append=True) self.assertTrue(mock.call("foo.grib2", "ab") in m.mock_calls)
def test_two_plots_with_shared_axis(self): coords = ('time', 'grid_latitude') c1 = Contour(self.cube, self.axes, coords=coords) c2 = Contour(self.cube, self.axes, coords=coords) with mock.patch('cube_browser.Contour.__call__') as func: browser = Browser([c1, c2]) browser.display() # Check the initial render. expected = [mock.call(grid_longitude=self.value)] self.assertEqual(func.call_args_list, expected * 2) # Now simulate a slider change. slider = browser._slider_by_name['grid_longitude'] change = dict(owner=slider) browser.on_change(change) self.assertEqual(func.call_args_list, expected * 4)
def test_zlib(self): cube = self._simple_cube('>f4') api = self.patch('iris.fileformats.netcdf.netCDF4') with Saver('/dummy/path', 'NETCDF4') as saver: saver.write(cube, zlib=True) dataset = api.Dataset.return_value create_var_call = mock.call('air_pressure_anomaly', np.dtype('float32'), ['dim0', 'dim1'], fill_value=None, shuffle=True, least_significant_digit=None, contiguous=False, zlib=True, fletcher32=False, endian='native', complevel=4, chunksizes=None) self.assertIn(create_var_call, dataset.createVariable.call_args_list)
def test_contig_tol(self): # Patch the inner call to ensure contiguity_tolerance is passed. cube_argument = mock.sentinel.passed_arg expected_result = mock.sentinel.returned_value blockplot_patch = self.patch( 'iris.plot._draw_2d_from_bounds', mock.Mock(return_value=expected_result)) # Make the call draw_func = self.blockplot_func() other_kwargs = self.additional_kwargs result = draw_func(cube_argument, contiguity_tolerance=0.0123) drawfunc_name = draw_func.__name__ # Check details of the call that was made. self.assertEqual( blockplot_patch.call_args_list, [mock.call(drawfunc_name, cube_argument, contiguity_tolerance=0.0123, **other_kwargs)]) self.assertEqual(result, expected_result)
def test_contig_tol(self): # Patch the inner call to ensure contiguity_tolerance is passed. cube_argument = mock.sentinel.passed_arg expected_result = mock.sentinel.returned_value blockplot_patch = self.patch('iris.plot._draw_2d_from_bounds', mock.Mock(return_value=expected_result)) # Make the call draw_func = self.blockplot_func() other_kwargs = self.additional_kwargs result = draw_func(cube_argument, contiguity_tolerance=0.0123) drawfunc_name = draw_func.__name__ # Check details of the call that was made. self.assertEqual(blockplot_patch.call_args_list, [ mock.call(drawfunc_name, cube_argument, contiguity_tolerance=0.0123, **other_kwargs) ]) self.assertEqual(result, expected_result)
def _check_cs(self, bplat, bplon, rotated): field = TestPPField() field.bplat = bplat field.bplon = bplon with mock.patch('iris.fileformats.pp.iris.coord_systems') \ as mock_cs_mod: result = field.coord_system() if not rotated: # It should return a standard unrotated CS. self.assertTrue(mock_cs_mod.GeogCS.call_count == 1) self.assertEqual(result, mock_cs_mod.GeogCS()) else: # It should return a rotated CS with the correct makeup. self.assertTrue(mock_cs_mod.GeogCS.call_count == 1) self.assertTrue(mock_cs_mod.RotatedGeogCS.call_count == 1) self.assertEqual(result, mock_cs_mod.RotatedGeogCS()) self.assertEqual( mock_cs_mod.RotatedGeogCS.call_args_list[0], mock.call(bplat, bplon, ellipsoid=mock_cs_mod.GeogCS()))
def _check_cs(self, bplat, bplon, rotated): field = TestPPField() field.bplat = bplat field.bplon = bplon with mock.patch('iris.fileformats.pp.iris.coord_systems') \ as mock_cs_mod: result = field.coord_system() if not rotated: # It should return a standard unrotated CS. self.assertTrue(mock_cs_mod.GeogCS.call_count == 1) self.assertEqual(result, mock_cs_mod.GeogCS()) else: # It should return a rotated CS with the correct makeup. self.assertTrue(mock_cs_mod.GeogCS.call_count == 1) self.assertTrue(mock_cs_mod.RotatedGeogCS.call_count == 1) self.assertEqual(result, mock_cs_mod.RotatedGeogCS()) self.assertEqual(mock_cs_mod.RotatedGeogCS.call_args_list[0], mock.call(bplat, bplon, ellipsoid=mock_cs_mod.GeogCS()))
def test_cmip6_volcello_load_issue_3367(self): # Ensure that reading a file which references itself in # `cell_measures` can be read. At the same time, ensure that we # still receive a warning about other variables mentioned in # `cell_measures` i.e. a warning should be raised about missing # areacello. areacello_str = "areacello" if six.PY3 else u"areacello" volcello_str = "volcello" if six.PY3 else u"volcello" expected_msg = "Missing CF-netCDF measure variable %r, " \ "referenced by netCDF variable %r" \ % (areacello_str, volcello_str) with mock.patch('warnings.warn') as warn: # ensure file loads without failure cube = iris.load_cube(self.fname) warn.assert_has_calls([mock.call(expected_msg)]) # extra check to ensure correct variable was found assert cube.standard_name == 'ocean_volume'
def test_two_plots_with_shared_alias_axis(self): coords = ('time', 'grid_longitude') c1 = Contour(self.cube, self.axes, coords=coords) c1.alias(wibble=1) c2 = Contour(self.cube, self.axes, coords=coords) c2.alias(wibble=1) with mock.patch('cube_browser.Contour.__call__') as func: browser = Browser([c1, c2]) browser.display() # Check the initial render. self.assertEqual(func.call_count, 2) expected = [mock.call(wibble=self.value)] * 2 func.assert_has_calls(expected) # Now simulate a slider change. slider = browser._slider_by_name['wibble'] change = dict(owner=slider) browser.on_change(change) self.assertEqual(func.call_count, 4) expected *= 2 func.assert_has_calls(expected)