From 3b318300c55ea9136bede67181b2fc69a3a37bad Mon Sep 17 00:00:00 2001 From: Antonio Valentino Date: Sun, 18 Jan 2026 18:20:30 +0100 Subject: [PATCH] Mark test that require access to the internet I some cases it is necessary to run teh test suite in an environment without access to teh internet (e.g. when one is building Debian packages). This PR add the "network" mark to all tests requiring access to the internet. In this way, it is easy to skip them using the following command: $ python3 -m pytest -m "not network" tests --- pyproject.toml | 5 ++- tests/calc/test_basic.py | 1 + tests/calc/test_calc_tools.py | 3 ++ tests/calc/test_cross_sections.py | 1 + tests/calc/test_indices.py | 21 +++++++++ tests/calc/test_kinematics.py | 12 +++++ tests/interpolate/test_grid.py | 3 ++ tests/interpolate/test_points.py | 5 +++ tests/io/test_gempak.py | 20 +++++++++ tests/io/test_gini.py | 9 ++++ tests/io/test_metar.py | 9 ++++ tests/io/test_nexrad.py | 20 +++++++++ tests/io/test_station_data.py | 5 +++ tests/io/test_text.py | 3 ++ tests/plots/test_declarative.py | 74 +++++++++++++++++++++++++++++++ tests/plots/test_util.py | 1 + tests/remote/test_aws.py | 10 +++++ tests/test_xarray.py | 44 ++++++++++++++++++ 18 files changed, 245 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 7ad5b26abc0..94625befd06 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -103,7 +103,10 @@ combine_as_imports = true combine_star = true [tool.pytest.ini_options] -markers = "xfail_dask: marks tests as expected to fail with Dask arrays" +markers = [ + "xfail_dask: marks tests as expected to fail with Dask arrays", + "network: make tests requiring access to the internet", +] norecursedirs = "build docs .idea" doctest_optionflags = "NORMALIZE_WHITESPACE" mpl-results-path = "test_output" diff --git a/tests/calc/test_basic.py b/tests/calc/test_basic.py index dc8770ef4d7..aaf6e4a714c 100644 --- a/tests/calc/test_basic.py +++ b/tests/calc/test_basic.py @@ -814,6 +814,7 @@ def test_altimeter_to_sea_level_pressure_hpa(array_type): assert_array_almost_equal(res, truth, 3) +@pytest.mark.network def test_zoom_xarray(): """Test zoom_xarray on 2D DataArray.""" data = xr.open_dataset(get_test_data('GFS_test.nc', False)) diff --git a/tests/calc/test_calc_tools.py b/tests/calc/test_calc_tools.py index c2a071bc53c..ba53cb9260c 100644 --- a/tests/calc/test_calc_tools.py +++ b/tests/calc/test_calc_tools.py @@ -1306,6 +1306,7 @@ def test_remove_nans(): assert_almost_equal(y_expected, y_test, 0) +@pytest.mark.network @pytest.mark.parametrize('subset', (False, True)) @pytest.mark.parametrize('datafile, assign_lat_lon, no_crs, transpose', [('GFS_test.nc', False, False, False), @@ -1583,6 +1584,7 @@ def test_peak_persistence_minima(peak_data): assert per == [((2, 3), np.inf), ((3, 0), 2)] +@pytest.mark.network def test_find_peaks(peak_data): """Test find_peaks correctly identifies peaks.""" data = xr.open_dataset(get_test_data('GFS_test.nc', as_file_obj=False)) @@ -1596,6 +1598,7 @@ def test_find_peaks(peak_data): assert_array_almost_equal(hgt.metpy.x[xind], [3.665191, 5.235988], 6) +@pytest.mark.network def test_find_peaks_minima(peak_data): """Test find_peaks correctly identifies peaks.""" data = xr.open_dataset(get_test_data('GFS_test.nc', as_file_obj=False)) diff --git a/tests/calc/test_cross_sections.py b/tests/calc/test_cross_sections.py index 03dc4f865c8..dbf65e716aa 100644 --- a/tests/calc/test_cross_sections.py +++ b/tests/calc/test_cross_sections.py @@ -323,6 +323,7 @@ def test_absolute_momentum_given_xy(test_cross_xy): assert_xarray_allclose(momentum, true_momentum) +@pytest.mark.network def test_absolute_momentum_xarray_units_attr(): """Test absolute momentum when `u` and `v` are DataArrays with a `units` attribute.""" data = xr.open_dataset(get_test_data('narr_example.nc', False)) diff --git a/tests/calc/test_indices.py b/tests/calc/test_indices.py index 19430da646d..d775f3db47e 100644 --- a/tests/calc/test_indices.py +++ b/tests/calc/test_indices.py @@ -16,6 +16,7 @@ from metpy.units import concatenate, units +@pytest.mark.network def test_precipitable_water(): """Test precipitable water with observed sounding.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') @@ -24,6 +25,7 @@ def test_precipitable_water(): assert_array_almost_equal(pw, truth, 4) +@pytest.mark.network def test_precipitable_water_no_bounds(): """Test precipitable water with observed sounding and no bounds given.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') @@ -83,6 +85,7 @@ def test_precipitable_water_descriptive_bound_error(): precipitable_water(pressure, dewpoint, bottom=units.Quantity(999, 'hPa')) +@pytest.mark.network def test_mean_pressure_weighted(): """Test pressure-weighted mean wind function with vertical interpolation.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') @@ -95,6 +98,7 @@ def test_mean_pressure_weighted(): assert_almost_equal(v, 7.966031839967931 * units('m/s'), 7) +@pytest.mark.network def test_mean_pressure_weighted_temperature(): """Test pressure-weighted mean temperature function with vertical interpolation.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') @@ -105,6 +109,7 @@ def test_mean_pressure_weighted_temperature(): assert_almost_equal(t, 281.535035296836 * units('kelvin'), 7) +@pytest.mark.network def test_mean_pressure_weighted_elevated(): """Test pressure-weighted mean wind function with a base above the surface.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') @@ -118,6 +123,7 @@ def test_mean_pressure_weighted_elevated(): assert_almost_equal(v, 1.7392601775853547 * units('m/s'), 7) +@pytest.mark.network def test_weighted_continuous_average(): """Test pressure-weighted mean wind function with vertical interpolation.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') @@ -130,6 +136,7 @@ def test_weighted_continuous_average(): assert_almost_equal(v, 6.900543760612305 * units('m/s'), 7) +@pytest.mark.network def test_weighted_continuous_average_temperature(): """Test pressure-weighted mean temperature function with vertical interpolation.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') @@ -140,6 +147,7 @@ def test_weighted_continuous_average_temperature(): assert_almost_equal(t, 279.07450928270185 * units('kelvin'), 7) +@pytest.mark.network def test_weighted_continuous_average_elevated(): """Test pressure-weighted mean wind function with a base above the surface.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') @@ -153,6 +161,7 @@ def test_weighted_continuous_average_elevated(): assert_almost_equal(v, 1.616638856115755 * units('m/s'), 7) +@pytest.mark.network def test_precipitable_water_xarray(): """Test precipitable water with xarray input.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') @@ -163,6 +172,7 @@ def test_precipitable_water_xarray(): assert_almost_equal(pw, truth) +@pytest.mark.network def test_bunkers_motion(): """Test Bunkers storm motion with observed sounding.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') @@ -174,6 +184,7 @@ def test_bunkers_motion(): assert_almost_equal(motion.flatten(), truth, 8) +@pytest.mark.network def test_corfidi_motion(): """Test corfidi MCS motion with observed sounding.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') @@ -184,6 +195,7 @@ def test_corfidi_motion(): assert_almost_equal(motion_full.flatten(), truth_full, 8) +@pytest.mark.network def test_corfidi_motion_override_llj(): """Test corfidi MCS motion with overridden LLJ.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') @@ -204,6 +216,7 @@ def test_corfidi_motion_override_llj(): data['v_wind'], v_llj=10 * units('kt')) +@pytest.mark.network def test_corfidi_corfidi_llj_unaivalable(): """Test corfidi MCS motion where the LLJ is unailable.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') @@ -211,6 +224,7 @@ def test_corfidi_corfidi_llj_unaivalable(): corfidi_storm_motion(data['pressure'][6:], data['u_wind'][6:], data['v_wind'][6:]) +@pytest.mark.network def test_corfidi_corfidi_cloudlayer_trimmed(): """Test corfidi MCS motion where sounding does not include the entire cloud layer.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') @@ -221,6 +235,7 @@ def test_corfidi_corfidi_cloudlayer_trimmed(): assert_almost_equal(motion_no_top.flatten(), truth_no_top, 8) +@pytest.mark.network def test_corfidi_motion_with_nans(): """Test corfidi MCS motion with observed sounding with nans.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') @@ -235,6 +250,7 @@ def test_corfidi_motion_with_nans(): assert_almost_equal(motion_with_nans.flatten(), truth_with_nans, 8) +@pytest.mark.network def test_bunkers_motion_with_nans(): """Test Bunkers storm motion with observed sounding.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') @@ -250,6 +266,7 @@ def test_bunkers_motion_with_nans(): assert_almost_equal(motion.flatten(), truth, 8) +@pytest.mark.network def test_bulk_shear(): """Test bulk shear with observed sounding.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') @@ -261,6 +278,7 @@ def test_bulk_shear(): assert_almost_equal(v.to('knots'), truth[1], 8) +@pytest.mark.network def test_bulk_shear_no_depth(): """Test bulk shear with observed sounding and no depth given. Issue #568.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') @@ -271,6 +289,7 @@ def test_bulk_shear_no_depth(): assert_almost_equal(v.to('knots'), truth[1], 8) +@pytest.mark.network def test_bulk_shear_elevated(): """Test bulk shear with observed sounding and a base above the surface.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') @@ -325,6 +344,7 @@ def test_sigtor_scalar(): assert_almost_equal(sigtor, truth, 6) +@pytest.mark.network def test_critical_angle(): """Test critical angle with observed sounding.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') @@ -335,6 +355,7 @@ def test_critical_angle(): assert_almost_equal(ca, truth, 8) +@pytest.mark.network def test_critical_angle_units(): """Test critical angle with observed sounding and different storm motion units.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') diff --git a/tests/calc/test_kinematics.py b/tests/calc/test_kinematics.py index 65118f27dfa..f14dc042259 100644 --- a/tests/calc/test_kinematics.py +++ b/tests/calc/test_kinematics.py @@ -426,6 +426,7 @@ def test_advection_z_y(): assert_array_equal(a, truth) +@pytest.mark.network def test_advection_4d_vertical(data_4d): """Test 4-d vertical advection with parsed dims.""" data_4d['w'] = -abs(data_4d['u']) @@ -1029,6 +1030,7 @@ def test_potential_vorticity_baroclinic_isobaric_real_data(): assert_almost_equal(pvor, true_pv, 10) +@pytest.mark.network def test_potential_vorticity_baroclinic_4d(data_4d): """Test potential vorticity calculation with latlon+xarray spatial handling.""" theta = potential_temperature(data_4d.pressure, data_4d.temperature) @@ -1421,12 +1423,14 @@ def data_4d(): 2.84689950e-05]]]]) * units('s^-1') +@pytest.mark.network def test_vorticity_4d(data_4d): """Test vorticity on a 4D (time, pressure, y, x) grid.""" vort = vorticity(data_4d.u, data_4d.v) assert_array_almost_equal(vort.data, true_vort4d, 12) +@pytest.mark.network def test_absolute_vorticity_4d(data_4d): """Test absolute_vorticity on a 4D (time, pressure, y, x) grid.""" vort = absolute_vorticity(data_4d.u, data_4d.v) @@ -1435,6 +1439,7 @@ def test_absolute_vorticity_4d(data_4d): assert_array_almost_equal(vort.data, truth, 12) +@pytest.mark.network def test_divergence_4d(data_4d): """Test divergence on a 4D (time, pressure, y, x) grid.""" div = divergence(data_4d.u, data_4d.v) @@ -1478,6 +1483,7 @@ def test_divergence_4d(data_4d): assert_array_almost_equal(div.data, truth, 12) +@pytest.mark.network def test_shearing_deformation_4d(data_4d): """Test shearing_deformation on a 4D (time, pressure, y, x) grid.""" shdef = shearing_deformation(data_4d.u, data_4d.v) @@ -1521,6 +1527,7 @@ def test_shearing_deformation_4d(data_4d): assert_array_almost_equal(shdef.data, truth, 12) +@pytest.mark.network def test_stretching_deformation_4d(data_4d): """Test stretching_deformation on a 4D (time, pressure, y, x) grid.""" stdef = stretching_deformation(data_4d.u, data_4d.v) @@ -1564,6 +1571,7 @@ def test_stretching_deformation_4d(data_4d): assert_array_almost_equal(stdef.data, truth, 10) +@pytest.mark.network def test_total_deformation_4d(data_4d): """Test total_deformation on a 4D (time, pressure, y, x) grid.""" totdef = total_deformation(data_4d.u, data_4d.v) @@ -1607,6 +1615,7 @@ def test_total_deformation_4d(data_4d): assert_array_almost_equal(totdef.data, truth, 12) +@pytest.mark.network def test_frontogenesis_4d(data_4d): """Test frontogenesis on a 4D (time, pressure, y, x) grid.""" theta = potential_temperature(data_4d.pressure, data_4d.temperature) @@ -1657,6 +1666,7 @@ def test_frontogenesis_4d(data_4d): assert_array_almost_equal(frnt.data, truth, 13) +@pytest.mark.network def test_geostrophic_wind_4d(data_4d): """Test geostrophic_wind on a 4D (time, pressure, y, x) grid.""" u_g, v_g = geostrophic_wind(data_4d.height) @@ -1772,6 +1782,7 @@ def test_geostrophic_wind_4d(data_4d): assert_array_almost_equal(v_g.data, v_g_truth, 4) +@pytest.mark.network def test_inertial_advective_wind_4d(data_4d): """Test inertial_advective_wind on a 4D (time, pressure, y, x) grid.""" u_g, v_g = geostrophic_wind(data_4d.height) @@ -1860,6 +1871,7 @@ def test_inertial_advective_wind_4d(data_4d): assert_array_almost_equal(v_i.data, v_i_truth, 4) +@pytest.mark.network def test_q_vector_4d(data_4d): """Test q_vector on a 4D (time, pressure, y, x) grid.""" u_g, v_g = geostrophic_wind(data_4d.height) diff --git a/tests/interpolate/test_grid.py b/tests/interpolate/test_grid.py index 573aad2589b..28983a0d9ce 100644 --- a/tests/interpolate/test_grid.py +++ b/tests/interpolate/test_grid.py @@ -151,6 +151,7 @@ def test_generate_grid_coords(): assert pts.flags['C_CONTIGUOUS'] # need output to be C-contiguous +@pytest.mark.network def test_natural_neighbor_to_grid(test_data, test_grid): r"""Test natural neighbor interpolation to grid function.""" xp, yp, z = test_data @@ -167,6 +168,7 @@ def test_natural_neighbor_to_grid(test_data, test_grid): interp_methods = ['cressman', 'barnes'] +@pytest.mark.network @pytest.mark.parametrize('method', interp_methods) def test_inverse_distance_to_grid(method, test_data, test_grid): r"""Test inverse distance interpolation to grid function.""" @@ -243,6 +245,7 @@ def test_interpolate_to_isosurface(): assert_array_almost_equal(truth, dt_theta) +@pytest.mark.network @pytest.mark.parametrize('assume_units', [None, 'mbar']) @pytest.mark.parametrize('method', interp_methods) @pytest.mark.parametrize('boundary_coords', boundary_types) diff --git a/tests/interpolate/test_points.py b/tests/interpolate/test_points.py index 608938f4d60..70a7bd8c17c 100644 --- a/tests/interpolate/test_points.py +++ b/tests/interpolate/test_points.py @@ -96,6 +96,7 @@ def test_barnes_point(test_data): assert_almost_equal(barnes_point(dists, values, 5762.7), 4.0871824) +@pytest.mark.network def test_natural_neighbor_to_points(test_data, test_points): r"""Test natural neighbor interpolation to grid function.""" xp, yp, z = test_data @@ -109,6 +110,7 @@ def test_natural_neighbor_to_points(test_data, test_points): assert_array_almost_equal(truth, img) +@pytest.mark.network def test_inverse_distance_to_points_invalid(test_data, test_points): """Test that inverse_distance_to_points raises when given an invalid method.""" xp, yp, z = test_data @@ -117,6 +119,7 @@ def test_inverse_distance_to_points_invalid(test_data, test_points): inverse_distance_to_points(obs_points, z, test_points, kind='shouldraise', r=40) +@pytest.mark.network @pytest.mark.parametrize('assume_units', [None, 'mbar']) @pytest.mark.parametrize('method', ['cressman', 'barnes']) def test_inverse_distance_to_points(method, assume_units, test_data, test_points): @@ -138,6 +141,7 @@ def test_inverse_distance_to_points(method, assume_units, test_data, test_points assert_array_almost_equal(truth, img) +@pytest.mark.network def test_interpolate_to_points_invalid(test_data): """Test that interpolate_to_points raises when given an invalid method.""" xp, yp, z = test_data @@ -150,6 +154,7 @@ def test_interpolate_to_points_invalid(test_data): interpolate_to_points(obs_points, z, test_points, interp_type='shouldraise') +@pytest.mark.network @pytest.mark.parametrize('assume_units', [None, 'mbar']) @pytest.mark.parametrize('method', ['natural_neighbor', 'cressman', 'barnes', 'linear', 'nearest', 'rbf', 'cubic']) diff --git a/tests/io/test_gempak.py b/tests/io/test_gempak.py index 62108242e5e..cbcdf6d1d63 100644 --- a/tests/io/test_gempak.py +++ b/tests/io/test_gempak.py @@ -17,6 +17,7 @@ logging.getLogger('metpy.io.gempak').setLevel(logging.ERROR) +@pytest.mark.network @pytest.mark.parametrize('order', ['little', 'big']) def test_byte_swap(order): """"Test byte swapping.""" @@ -29,6 +30,7 @@ def test_byte_swap(order): assert_equal(grid, reference) +@pytest.mark.network @pytest.mark.parametrize('grid_name', ['none', 'diff', 'dec', 'grib']) def test_grid_loading(grid_name): """Test reading grids with different packing.""" @@ -44,6 +46,7 @@ def test_grid_loading(grid_name): assert_allclose(gio, gempak, rtol=1e-6, atol=0) +@pytest.mark.network def test_merged_sounding(): """Test loading a merged sounding. @@ -106,6 +109,7 @@ def test_merged_sounding(): np.testing.assert_allclose(gdtar, ddtar, rtol=1e-10, atol=1e-2) +@pytest.mark.network def test_merged_sounding_no_packing(): """Test loading a merged sounding without data packing.""" gso = GempakSounding(get_test_data('gem_merged_nopack.snd')).snxarray( @@ -135,6 +139,7 @@ def test_merged_sounding_no_packing(): assert_allclose(ghght, dhght, rtol=1e-10, atol=1e-1) +@pytest.mark.network @pytest.mark.parametrize('gem,gio,station', [ ('gem_sigw_hght_unmrg.csv', 'gem_sigw_hght_unmrg.snd', 'TOP'), ('gem_sigw_pres_unmrg.csv', 'gem_sigw_pres_unmrg.snd', 'WAML') @@ -170,6 +175,7 @@ def test_unmerged_sounding(gem, gio, station): assert_allclose(ghght, dhght, rtol=1e-10, atol=1e-1) +@pytest.mark.network def test_unmerged_sigw_pressure_sounding(): """Test loading an unmerged sounding. @@ -201,6 +207,7 @@ def test_unmerged_sigw_pressure_sounding(): assert_allclose(ghght, dhght, rtol=1e-10, atol=1e-1) +@pytest.mark.network def test_climate_surface(): """Test to read a cliamte surface file.""" gsf = GempakSurface(get_test_data('gem_climate.sfc')) @@ -219,6 +226,7 @@ def test_climate_surface(): assert val == pytest.approx(gemsfc[param.upper()]) +@pytest.mark.network def test_standard_surface(): """Test to read a standard surface file.""" skip = ['text', 'spcl'] @@ -240,6 +248,7 @@ def test_standard_surface(): assert val == pytest.approx(gemsfc[param.upper()]) +@pytest.mark.network def test_ship_surface(): """Test to read a ship surface file.""" skip = ['text', 'spcl'] @@ -267,6 +276,7 @@ def test_ship_surface(): assert_allclose(decoded_vals, actual_vals) +@pytest.mark.network @pytest.mark.parametrize('proj_type', ['conical', 'cylindrical', 'azimuthal']) def test_coordinates_creation(proj_type): """Test projections and coordinates.""" @@ -282,6 +292,7 @@ def test_coordinates_creation(proj_type): assert_allclose(decode_lon, true_lon, rtol=1e-6, atol=1e-2) +@pytest.mark.network @pytest.mark.parametrize('proj_type, proj_attrs', [ ('conical', { 'grid_mapping_name': 'lambert_conformal_conic', @@ -313,6 +324,7 @@ def test_metpy_crs_creation(proj_type, proj_attrs): assert y_unit == 'meters' +@pytest.mark.network def test_date_parsing(): """Test parsing of dates with leading zeroes.""" sfc_data = GempakSurface(get_test_data('sfc_obs.gem')) @@ -320,6 +332,7 @@ def test_date_parsing(): assert dat == datetime(2000, 1, 2) +@pytest.mark.network @pytest.mark.parametrize('access_type', ['STID', 'STNM']) def test_surface_access(access_type): """Test for proper surface retrieval with multi-parameter filter.""" @@ -334,6 +347,7 @@ def test_surface_access(access_type): date_time='202109070000') +@pytest.mark.network @pytest.mark.parametrize('text_type,date_time', [ ('text', '202109070000'), ('spcl', '202109071600') ]) @@ -349,6 +363,7 @@ def test_surface_text(text_type, date_time): assert text == gem_text +@pytest.mark.network @pytest.mark.parametrize('access_type', ['STID', 'STNM']) def test_sounding_access(access_type): """Test for proper sounding retrieval with multi-parameter filter.""" @@ -363,6 +378,7 @@ def test_sounding_access(access_type): date_time='202101200000') +@pytest.mark.network @pytest.mark.parametrize('text_type', ['txta', 'txtb', 'txtc', 'txpb']) def test_sounding_text(text_type): """Test for proper decoding of coded message text.""" @@ -377,6 +393,7 @@ def test_sounding_text(text_type): assert text == gem_text +@pytest.mark.network def test_special_surface_observation(): """Test special surface observation conversion.""" sfc = get_test_data('gem_surface_with_text.sfc') @@ -400,6 +417,7 @@ def test_special_surface_observation(): assert stn['vsby'] == 2 +@pytest.mark.network def test_multi_level_multi_time_access(): """Test accessing data with multiple levels and times.""" g = get_test_data('gem_multilevel_multidate.grd') @@ -416,6 +434,7 @@ def test_multi_level_multi_time_access(): ) +@pytest.mark.network def test_multi_time_grid(): """Test files with multiple times on a single grid.""" g = get_test_data('gem_multi_time.grd') @@ -429,6 +448,7 @@ def test_multi_time_grid(): assert dattim2 == datetime(1991, 8, 20, 0, 0) +@pytest.mark.network def test_unmerged_no_ttcc(): """Test loading an unmerged sounding. diff --git a/tests/io/test_gini.py b/tests/io/test_gini.py index bb8e3abc9bb..5c6f849b533 100644 --- a/tests/io/test_gini.py +++ b/tests/io/test_gini.py @@ -53,6 +53,7 @@ ] +@pytest.mark.network @pytest.mark.parametrize('filename,pdb,pdb2,proj_info', raw_gini_info, ids=['LCC', 'Stereographic', 'Mercator']) def test_raw_gini(filename, pdb, pdb2, proj_info): @@ -64,6 +65,7 @@ def test_raw_gini(filename, pdb, pdb2, proj_info): assert f.data.shape == (pdb.num_records, pdb.record_len) +@pytest.mark.network def test_gini_bad_size(): """Test reading a GINI file that reports a bad header size.""" f = GiniFile(get_test_data('NHEM-MULTICOMP_1km_IR_20151208_2100.gini')) @@ -95,6 +97,7 @@ def test_gini_bad_size(): ] +@pytest.mark.network @pytest.mark.parametrize('filename,bounds,data_var,proj_attrs,image,dt', gini_dataset_info, ids=['LCC', 'Stereographic', 'Mercator']) def test_gini_xarray(filename, bounds, data_var, proj_attrs, image, dt): @@ -132,6 +135,7 @@ def test_gini_xarray(filename, bounds, data_var, proj_attrs, image, dt): assert np.asarray(dt, dtype='datetime64[ms]') == ds.variables['time'] +@pytest.mark.network @pytest.mark.parametrize('filename,bounds,data_var,proj_attrs,image,dt', gini_dataset_info, ids=['LCC', 'Stereographic', 'Mercator']) @pytest.mark.parametrize('specify_engine', [True, False], ids=['engine', 'no engine']) @@ -168,6 +172,7 @@ def test_gini_xarray_entrypoint(filename, bounds, data_var, proj_attrs, image, d assert np.asarray(dt, dtype='datetime64[ms]') == ds.variables['time'] +@pytest.mark.network def test_gini_mercator_upper_corner(): """Test that the upper corner of the Mercator coordinates is correct.""" f = GiniFile(get_test_data('HI-REGIONAL_4km_3.9_20160616_1715.gini')) @@ -181,6 +186,7 @@ def test_gini_mercator_upper_corner(): assert_almost_equal(lat[0, -1] + (lat[0, -1] - lat[1, -1]), f.proj_info.la2, 4) +@pytest.mark.network def test_gini_str(): """Test the str representation of GiniFile.""" f = GiniFile(get_test_data('WEST-CONUS_4km_WV_20151208_2200.gini')) @@ -191,6 +197,7 @@ def test_gini_str(): assert str(f) == truth +@pytest.mark.network def test_gini_pathlib(): """Test that GiniFile works with `pathlib.Path` instances.""" from pathlib import Path @@ -199,6 +206,7 @@ def test_gini_pathlib(): assert f.prod_desc.sector_id == 'West CONUS' +@pytest.mark.network def test_unidata_composite(): """Test reading radar composites in GINI format made by Unidata.""" f = GiniFile(get_test_data('Level3_Composite_dhr_1km_20180309_2225.gini')) @@ -210,6 +218,7 @@ def test_unidata_composite(): assert f.data[2160, 2130] == 66 +@pytest.mark.network def test_percent_normal(): """Test reading PCT products properly.""" f = GiniFile(get_test_data('PR-NATIONAL_1km_PCT_20200320_0446.gini')) diff --git a/tests/io/test_metar.py b/tests/io/test_metar.py index e5ca99abb9d..4c4be021bc3 100644 --- a/tests/io/test_metar.py +++ b/tests/io/test_metar.py @@ -15,6 +15,7 @@ from metpy.units import is_quantity, units +@pytest.mark.network @pytest.mark.parametrize(['metar', 'truth'], [ # Missing station ('METAR KLBG 261155Z AUTO 00000KT 10SM CLR 05/00 A3001 RMK AO2=', @@ -208,6 +209,7 @@ def test_metar_parser(metar, truth): assert parse_metar(metar, 2017, 5) == truth +@pytest.mark.network def test_date_time_given(): """Test for when date_time is given.""" df = parse_metar_to_dataframe('K6B0 261200Z AUTO 00000KT 10SM CLR 20/M17 A3002 RMK AO2 ' @@ -227,6 +229,7 @@ def test_parse_metar_df_positional_datetime_failure(): 'A3002 RMK AO2 T01990165=', 2019, 6) +@pytest.mark.network def test_parse_metar_to_dataframe(): """Test parsing a single METAR to a DataFrame.""" df = parse_metar_to_dataframe('KDEN 012153Z 09010KT 10SM FEW060 BKN110 BKN220 27/13 ' @@ -241,6 +244,7 @@ def test_parse_metar_to_dataframe(): assert df.dew_point_temperature.values == 13 +@pytest.mark.network def test_parse_file(): """Test the parser on an entire file.""" input_file = get_test_data('metar_20190701_1200.txt', as_file_obj=False) @@ -296,6 +300,7 @@ def test_parse_file(): assert_almost_equal(paku.altimeter.values, [30.02, 30.04]) +@pytest.mark.network def test_parse_file_positional_datetime_failure(): """Test that positional year, month arguments fail for parse_metar_file.""" # pylint: disable=too-many-function-args @@ -304,6 +309,7 @@ def test_parse_file_positional_datetime_failure(): parse_metar_file(input_file, 2016, 12) +@pytest.mark.network def test_parse_file_bad_encoding(): """Test the parser on an entire file that has at least one bad utf-8 encoding.""" input_file = get_test_data('2020010600_sao.wmo', as_file_obj=False) @@ -350,6 +356,7 @@ def test_parse_file_bad_encoding(): assert test.air_pressure_at_sea_level.values == 1024.71 +@pytest.mark.network def test_parse_file_object(): """Test the parser reading from a file-like object.""" input_file = get_test_data('metar_20190701_1200.txt', mode='rt') @@ -364,6 +371,7 @@ def test_parse_file_object(): assert_almost_equal(test.northward_wind.values, 6) +@pytest.mark.network def test_parse_no_pint_objects_in_df(): """Test that there are no Pint quantities in dataframes created by parser.""" input_file = get_test_data('metar_20190701_1200.txt', mode='rt') @@ -401,6 +409,7 @@ def test_repr(): "remarks=TreeNode(text='', offset=47), end=TreeNode(text='', offset=47))") +@pytest.mark.network def test_metar_units_in_place(): """Test that parsing a METAR yields units that can be changed safely in-place.""" df = parse_metar_to_dataframe('KDEN 012153Z 09010KT 10SM FEW060 BKN110 BKN220 27/13 A3010') diff --git a/tests/io/test_nexrad.py b/tests/io/test_nexrad.py index 2ab1bb02eaf..7e67eb5de3e 100644 --- a/tests/io/test_nexrad.py +++ b/tests/io/test_nexrad.py @@ -41,6 +41,7 @@ # ids here fixes how things are presented in pycharm +@pytest.mark.network @pytest.mark.parametrize('fname, voltime, num_sweeps, mom_first, mom_last, expected_logs', level2_files, ids=[i[0].replace('.', '_') for i in level2_files]) def test_level2(fname, voltime, num_sweeps, mom_first, mom_last, expected_logs, caplog): @@ -54,6 +55,7 @@ def test_level2(fname, voltime, num_sweeps, mom_first, mom_last, expected_logs, assert len(caplog.records) == expected_logs +@pytest.mark.network @pytest.mark.parametrize('filename', ['Level2_KFTG_20150430_1419.ar2v', 'TDAL20191021021543V08.raw.gz', 'KTLX20150530_000802_V06.bz2']) @@ -83,6 +85,7 @@ def close(self): Level2File(f) +@pytest.mark.network def test_doubled_file(): """Test for #489 where doubled-up files didn't parse at all.""" with contextlib.closing(get_test_data('Level2_KFTG_20150430_1419.ar2v')) as infile: @@ -92,6 +95,7 @@ def test_doubled_file(): assert len(f.sweeps) == 12 +@pytest.mark.network @pytest.mark.parametrize('fname, has_v2', [('KTLX20130520_201643_V06.gz', False), ('Level2_KFTG_20150430_1419.ar2v', True), ('TDAL20191021021543V08.raw.gz', False)]) @@ -101,6 +105,7 @@ def test_conditional_radconst(fname, has_v2): assert hasattr(f.sweeps[0][0][3], 'calib_dbz0_v') == has_v2 +@pytest.mark.network def test_msg15(): """Check proper decoding of message type 15.""" f = Level2File(get_test_data('KTLX20130520_201643_V06.gz', as_file_obj=False)) @@ -109,12 +114,14 @@ def test_msg15(): assert f.clutter_filter_map['datetime'] == datetime(2013, 5, 19, 5, 15, 0, 0) +@pytest.mark.network def test_msg18_novcps(): """Check handling of message type 18 with VCP info now spares does not crash.""" f = Level2File(get_test_data('KJKL_20240227_102059', as_file_obj=False)) assert 'VCPAT11' not in f.rda +@pytest.mark.network def test_single_chunk(caplog): """Check that Level2File copes with reading a file containing a single chunk.""" # Need to override the test level set above @@ -129,6 +136,7 @@ def test_single_chunk(caplog): assert 'Unable to read volume header' not in caplog.text +@pytest.mark.network def test_build19_level2_additions(): """Test handling of new additions in Build 19 level2 data.""" f = Level2File(get_test_data('Level2_KDDC_20200823_204121.ar2v')) @@ -164,6 +172,7 @@ def test_level3_files(fname): assert f.filename == fname +@pytest.mark.network def test_basic(): """Test reading one specific NEXRAD NIDS file based on the filename.""" f = Level3File(get_test_data('nids/Level3_FFC_N0Q_20140407_1805.nids', as_file_obj=False)) @@ -178,6 +187,7 @@ def test_basic(): assert str(f) +@pytest.mark.network def test_new_gsm(): """Test parsing recent mods to the GSM product.""" f = Level3File(get_test_data('nids/KDDC-gsm.nids')) @@ -194,6 +204,7 @@ def test_new_gsm(): assert str(f) +@pytest.mark.network def test_bad_length(caplog): """Test reading a product with too many bytes produces a log message.""" fname = get_test_data('nids/KOUN_SDUS84_DAATLX_201305202016', as_file_obj=False) @@ -207,23 +218,27 @@ def test_bad_length(caplog): assert 'This product may not parse correctly' in caplog.records[0].message +@pytest.mark.network def test_tdwr(): """Test reading a specific TDWR file.""" f = Level3File(get_test_data('nids/Level3_SLC_TV0_20160516_2359.nids')) assert f.prod_desc.prod_code == 182 +@pytest.mark.network def test_dhr(): """Test reading a time field for DHR product.""" f = Level3File(get_test_data('nids/KOUN_SDUS54_DHRTLX_201305202016')) assert f.metadata['avg_time'] == datetime(2013, 5, 20, 20, 18) +@pytest.mark.network def test_fobj(): """Test reading a specific NEXRAD NIDS files from a file object.""" Level3File(get_test_data('nids/Level3_FFC_N0Q_20140407_1805.nids')) +@pytest.mark.network def test_level3_pathlib(): """Test that reading with Level3File properly sets the filename from a Path.""" fname = Path(get_test_data('nids/Level3_FFC_N0Q_20140407_1805.nids', as_file_obj=False)) @@ -231,6 +246,7 @@ def test_level3_pathlib(): assert f.filename == str(fname) +@pytest.mark.network def test_nids_super_res_width(): """Test decoding a super resolution spectrum width product.""" f = Level3File(get_test_data('nids/KLZK_H0W_20200812_1305')) @@ -238,6 +254,7 @@ def test_nids_super_res_width(): assert np.nanmax(width) == 15 +@pytest.mark.network def test_power_removed_control(): """Test decoding new PRC product.""" f = Level3File(get_test_data('nids/KGJX_NXF_20200817_0600.nids')) @@ -265,6 +282,7 @@ def test31_clear_air(): assert not is_precip_mode(31), 'VCP 31 is not precip' +@pytest.mark.network def test_tracks(): """Check that tracks are properly decoded.""" f = Level3File(get_test_data('nids/KOUN_SDUS34_NSTTLX_201305202016')) @@ -275,6 +293,7 @@ def test_tracks(): assert len(y) +@pytest.mark.network def test_vector_packet(): """Check that vector packets are properly decoded.""" f = Level3File(get_test_data('nids/KOUN_SDUS64_NHITLX_201305202016')) @@ -288,6 +307,7 @@ def test_vector_packet(): assert len(y2) +@pytest.mark.network @pytest.mark.parametrize('fname,truth', [('nids/KEAX_N0Q_20200817_0401.nids', (0, 'MRLE scan')), ('nids/KEAX_N0Q_20200817_0405.nids', (0, 'Non-supplemental scan')), diff --git a/tests/io/test_station_data.py b/tests/io/test_station_data.py index 48f42090d09..8110d4e92aa 100644 --- a/tests/io/test_station_data.py +++ b/tests/io/test_station_data.py @@ -10,6 +10,7 @@ from metpy.io import add_station_lat_lon, station_info +@pytest.mark.network def test_add_lat_lon_station_data(): """Test for when the METAR does not correspond to a station in the dictionary.""" df = pd.DataFrame({'station': ['KOUN', 'KVPZ', 'KDEN', 'PAAA']}) @@ -26,6 +27,7 @@ def test_add_lat_lon_station_data(): assert df['longitude'].dtype == np.float64 +@pytest.mark.network def test_add_lat_lon_station_data_optional(): """Test for when only one argument is passed.""" df = pd.DataFrame({'station': ['KOUN', 'KVPZ', 'KDEN', 'PAAA']}) @@ -51,16 +53,19 @@ def test_add_lat_lon_station_data_existing_col(): add_station_lat_lon(df) +@pytest.mark.network def test_station_lookup_get_station(): """Test that you can get a station by ID from the lookup.""" assert station_info['KOUN'].id == 'KOUN' +@pytest.mark.network def test_station_lookup_len(): """Test that you can get the length of the station data.""" assert len(station_info) == 13798 +@pytest.mark.network def test_station_lookup_iter(): """Test iterating over the station data.""" for stid in station_info: diff --git a/tests/io/test_text.py b/tests/io/test_text.py index 14b6ee5c03f..7c492037b4d 100644 --- a/tests/io/test_text.py +++ b/tests/io/test_text.py @@ -5,12 +5,14 @@ from datetime import datetime import numpy as np +import pytest from metpy.cbook import get_test_data from metpy.io import parse_wpc_surface_bulletin from metpy.testing import needs_module +@pytest.mark.network @needs_module('shapely') def test_parse_wpc_surface_bulletin_highres(): """Test parser reading a high res WPC coded surface bulletin into a dataframe.""" @@ -37,6 +39,7 @@ def test_parse_wpc_surface_bulletin_highres(): assert all(df.valid == datetime(2021, 6, 28, 18, 0, 0)) +@pytest.mark.network @needs_module('shapely') def test_parse_wpc_surface_bulletin(): """Test parser reading a low res WPC coded surface bulletin into a dataframe.""" diff --git a/tests/plots/test_declarative.py b/tests/plots/test_declarative.py index 93a43c2c8f0..177332a86c7 100644 --- a/tests/plots/test_declarative.py +++ b/tests/plots/test_declarative.py @@ -26,6 +26,7 @@ from metpy.units import units +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=2.58 if version_check('matplotlib<3.10') else 0.0081) @needs_cartopy @@ -50,6 +51,7 @@ def test_declarative_image(): return pc.figure +@pytest.mark.network @needs_cartopy def test_declarative_three_dims_error(): """Test making an image plot with three dimensions.""" @@ -70,6 +72,7 @@ def test_declarative_three_dims_error(): pc.draw() +@pytest.mark.network @needs_cartopy def test_declarative_four_dims_error(): """Test making a contour plot with four dimensions.""" @@ -94,6 +97,7 @@ def test_declarative_four_dims_error(): pc.draw() +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.163 if version_check('cartopy<0.23') else 0.09) @needs_cartopy @@ -123,6 +127,7 @@ def test_declarative_contour(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=False, tolerance=0.094) @needs_cartopy def test_declarative_titles(): @@ -154,6 +159,7 @@ def test_declarative_titles(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.159 if version_check('cartopy<0.23') else 0.066) @needs_cartopy @@ -184,6 +190,7 @@ def test_declarative_smooth_contour(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.155 if version_check('cartopy<0.23') else 0.006) @needs_cartopy @@ -227,6 +234,7 @@ def test_declarative_smooth_contour_calculation(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.142 if version_check('cartopy<0.23') else 0.0038) @needs_cartopy @@ -257,6 +265,7 @@ def test_declarative_smooth_contour_order(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.114 if version_check('cartopy<0.23') else 0.058) @needs_cartopy @@ -286,6 +295,7 @@ def test_declarative_figsize(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.104 if version_check('cartopy<0.23') else 0.033) @needs_cartopy @@ -316,6 +326,7 @@ def test_declarative_smooth_field(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.828) @needs_cartopy def test_declarative_contour_cam(): @@ -343,6 +354,7 @@ def test_declarative_contour_cam(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare( remove_text=True, tolerance=3.71 if version_check('matplotlib<3.8') else 0.74) @@ -375,6 +387,7 @@ def test_declarative_contour_options(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.152 if version_check('cartopy<0.23') else 0.009) @needs_cartopy @@ -406,6 +419,7 @@ def test_declarative_layers_plot_options(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.055 if version_check('cartopy<0.23') else 0.009) @needs_cartopy @@ -440,6 +454,7 @@ def test_declarative_additional_layers_plot_options(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare( remove_text=True, tolerance=( @@ -474,6 +489,7 @@ def test_declarative_contour_convert_units(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=5.34 if version_check('matplotlib<3.10') else 0.246) @needs_cartopy @@ -518,6 +534,7 @@ def test_declarative_events(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.009) @needs_cartopy def test_declarative_raster_events(): @@ -549,6 +566,7 @@ def test_declarative_raster_events(): return pc.figure +@pytest.mark.network def test_no_field_error(): """Make sure we get a useful error when the field is not set.""" data = xr.open_dataset(get_test_data('narr_example.nc', as_file_obj=False)) @@ -561,6 +579,7 @@ def test_no_field_error(): contour.draw() +@pytest.mark.network def test_ndim_error_scalar(cfeature): """Make sure we get a useful error when the field is not set.""" data = xr.open_dataset(get_test_data('narr_example.nc', as_file_obj=False)) @@ -585,6 +604,7 @@ def test_ndim_error_scalar(cfeature): plt.close(pc.figure) +@pytest.mark.network def test_ndim_error_vector(cfeature): """Make sure we get a useful error when the field is not set.""" data = xr.open_dataset(get_test_data('narr_example.nc', as_file_obj=False)) @@ -608,6 +628,7 @@ def test_ndim_error_vector(cfeature): plt.close(pc.figure) +@pytest.mark.network def test_no_field_error_barbs(): """Make sure we get a useful error when the field is not set.""" data = xr.open_dataset(get_test_data('narr_example.nc', as_file_obj=False)) @@ -620,6 +641,7 @@ def test_no_field_error_barbs(): barbs.draw() +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.381) def test_projection_object(ccrs, cfeature): """Test that we can pass a custom map projection.""" @@ -643,6 +665,7 @@ def test_projection_object(ccrs, cfeature): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.009) @needs_cartopy def test_colorfill(): @@ -669,6 +692,7 @@ def test_colorfill(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.238 if version_check('cartopy<0.23') else 0.004) def test_colorfill_with_image_range(cfeature): @@ -696,6 +720,7 @@ def test_colorfill_with_image_range(cfeature): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare( remove_text=True, tolerance=0.238 if version_check('cartopy<0.23') else 0.004, @@ -726,6 +751,7 @@ def test_colorfill_with_normalize_instance_image_range(cfeature): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.02) @needs_cartopy def test_colorfill_horiz_colorbar(): @@ -752,6 +778,7 @@ def test_colorfill_horiz_colorbar(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.02) def test_colorbar_kwargs(cfeature): """Test that we can use ContourFillPlot with specifying colorbar kwargs.""" @@ -777,6 +804,7 @@ def test_colorbar_kwargs(cfeature): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.370 if version_check('cartopy<0.23') else 0.005) def test_colorfill_no_colorbar(cfeature): @@ -803,6 +831,7 @@ def test_colorfill_no_colorbar(cfeature): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=1.389 if version_check('matplotlib<3.10') else 0.0012) @needs_cartopy @@ -826,6 +855,7 @@ def test_global(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=5.101 if version_check('matplotlib<3.10') else 0.019) @needs_cartopy @@ -858,6 +888,7 @@ def test_latlon(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.393) @needs_cartopy def test_declarative_barb_options(): @@ -888,6 +919,7 @@ def test_declarative_barb_options(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.37) @needs_cartopy def test_declarative_arrowplot(): @@ -918,6 +950,7 @@ def test_declarative_arrowplot(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.37) @needs_cartopy def test_declarative_arrowkey(): @@ -949,6 +982,7 @@ def test_declarative_arrowkey(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.37) @needs_cartopy def test_declarative_arrow_changes(): @@ -980,6 +1014,7 @@ def test_declarative_arrow_changes(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.891) @needs_cartopy def test_declarative_barb_earth_relative(): @@ -1019,6 +1054,7 @@ def test_declarative_barb_earth_relative(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.612) @needs_cartopy def test_declarative_overlay_projections(): @@ -1058,6 +1094,7 @@ def test_declarative_overlay_projections(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.133 if version_check('cartopy<0.23') else 0.0094) @needs_cartopy @@ -1088,6 +1125,7 @@ def test_declarative_gridded_scale(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.607) @needs_cartopy def test_declarative_global_gfs(): @@ -1117,6 +1155,7 @@ def test_declarative_global_gfs(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=1.42) @needs_cartopy def test_declarative_barb_gfs(): @@ -1146,6 +1185,7 @@ def test_declarative_barb_gfs(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.665) @needs_cartopy def test_declarative_barb_scale(): @@ -1176,6 +1216,7 @@ def test_declarative_barb_scale(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.722) @needs_cartopy def test_declarative_barb_gfs_knots(): @@ -1226,6 +1267,7 @@ def pandas_sfc(): return df +@pytest.mark.network def test_plotobs_subset_default_nolevel(sample_obs): """Test PlotObs subsetting with minimal config.""" obs = PlotObs() @@ -1238,6 +1280,7 @@ def test_plotobs_subset_default_nolevel(sample_obs): pd.testing.assert_frame_equal(obs.obsdata, truth) +@pytest.mark.network def test_plotobs_subset_level(sample_obs): """Test PlotObs subsetting based on level.""" obs = PlotObs() @@ -1251,6 +1294,7 @@ def test_plotobs_subset_level(sample_obs): pd.testing.assert_frame_equal(obs.obsdata, truth) +@pytest.mark.network def test_plotobs_subset_level_no_units(sample_obs): """Test PlotObs subsetting based on unitless level.""" obs = PlotObs() @@ -1264,6 +1308,7 @@ def test_plotobs_subset_level_no_units(sample_obs): pd.testing.assert_frame_equal(obs.obsdata, truth) +@pytest.mark.network def test_plotobs_subset_time(sample_obs): """Test PlotObs subsetting for a particular time.""" obs = PlotObs() @@ -1277,6 +1322,7 @@ def test_plotobs_subset_time(sample_obs): pd.testing.assert_frame_equal(obs.obsdata, truth) +@pytest.mark.network def test_plotobs_subset_time_window(sample_obs): """Test PlotObs subsetting for a particular time with a window.""" # Test also using an existing index @@ -1296,6 +1342,7 @@ def test_plotobs_subset_time_window(sample_obs): pd.testing.assert_frame_equal(obs.obsdata, truth) +@pytest.mark.network def test_plotobs_subset_time_window_level(sample_obs): """Test PlotObs subsetting for a particular time with a window and a level.""" # Test also using an existing index @@ -1315,6 +1362,7 @@ def test_plotobs_subset_time_window_level(sample_obs): pd.testing.assert_frame_equal(obs.obsdata, truth) +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.016) def test_plotobs_units_with_formatter(ccrs, pandas_sfc): """Test using PlotObs with a field that both has units and a custom formatter.""" @@ -1352,6 +1400,7 @@ def test_plotobs_units_with_formatter(ccrs, pandas_sfc): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.081 if version_check('cartopy<0.23') else 0.025) def test_declarative_sfc_obs(ccrs, pandas_sfc): @@ -1382,6 +1431,7 @@ def test_declarative_sfc_obs(ccrs, pandas_sfc): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.075 if version_check('cartopy<0.23') else 0.) def test_declarative_sfc_obs_args(ccrs, pandas_sfc): @@ -1413,6 +1463,7 @@ def test_declarative_sfc_obs_args(ccrs, pandas_sfc): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.016) @needs_cartopy def test_declarative_sfc_text(pandas_sfc): @@ -1444,6 +1495,7 @@ def test_declarative_sfc_text(pandas_sfc): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.081 if version_check('cartopy<0.23') else 0.) def test_declarative_sfc_obs_changes(ccrs, pandas_sfc): @@ -1478,6 +1530,7 @@ def test_declarative_sfc_obs_changes(ccrs, pandas_sfc): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.171) def test_declarative_colored_barbs(ccrs, pandas_sfc): """Test making a surface plot with a colored barb (gh-1274).""" @@ -1507,6 +1560,7 @@ def test_declarative_colored_barbs(ccrs, pandas_sfc): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.314) def test_declarative_sfc_obs_full(ccrs, pandas_sfc): """Test making a full surface observation plot.""" @@ -1542,6 +1596,7 @@ def test_declarative_sfc_obs_full(ccrs, pandas_sfc): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.522) @needs_cartopy def test_declarative_upa_obs(): @@ -1579,6 +1634,7 @@ def test_declarative_upa_obs(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.518) @needs_cartopy def test_declarative_upa_obs_convert_barb_units(): @@ -1622,6 +1678,7 @@ def test_declarative_upa_obs_convert_barb_units(): return pc.figure +@pytest.mark.network def test_attribute_error_time(ccrs, pandas_sfc): """Make sure we get a useful error when the time variable is not found.""" pandas_sfc.rename(columns={'valid': 'vtime'}, inplace=True) @@ -1653,6 +1710,7 @@ def test_attribute_error_time(ccrs, pandas_sfc): plt.close(pc.figure) +@pytest.mark.network def test_attribute_error_station(ccrs, pandas_sfc): """Make sure we get a useful error when the station variable is not found.""" pandas_sfc.rename(columns={'station': 'location'}, inplace=True) @@ -1684,6 +1742,7 @@ def test_attribute_error_station(ccrs, pandas_sfc): plt.close(pc.figure) +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.082 if version_check('cartopy<0.23') else 0.) def test_declarative_sfc_obs_change_units(ccrs): @@ -1718,6 +1777,7 @@ def test_declarative_sfc_obs_change_units(ccrs): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.125 if version_check('cartopy<0.23') else 0.0) def test_declarative_multiple_sfc_obs_change_units(ccrs): @@ -1754,6 +1814,7 @@ def test_declarative_multiple_sfc_obs_change_units(ccrs): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=False, tolerance=0.607) @needs_cartopy def test_declarative_title_fontsize(): @@ -1784,6 +1845,7 @@ def test_declarative_title_fontsize(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=False, tolerance=0.951 if version_check('cartopy<0.23') else 0.) @needs_cartopy @@ -1815,6 +1877,7 @@ def test_declarative_colorbar_fontsize(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.607) @needs_cartopy def test_declarative_station_plot_fontsize(): @@ -1850,6 +1913,7 @@ def test_declarative_station_plot_fontsize(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.607) @needs_cartopy def test_declarative_contour_label_fontsize(): @@ -1880,6 +1944,7 @@ def test_declarative_contour_label_fontsize(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.02) @needs_cartopy def test_declarative_raster(): @@ -1906,6 +1971,7 @@ def test_declarative_raster(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.02) @needs_cartopy def test_declarative_raster_options(): @@ -1933,6 +1999,7 @@ def test_declarative_raster_options(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.607) @needs_cartopy def test_declarative_region_modifier_zoom_in(): @@ -1957,6 +2024,7 @@ def test_declarative_region_modifier_zoom_in(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=True, tolerance=0.377) @needs_cartopy def test_declarative_region_modifier_zoom_out(): @@ -2073,6 +2141,7 @@ def test_copy(): assert obj.plots[i] is not copied_obj.plots[i] +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=False, tolerance=0.607) @needs_cartopy def test_declarative_plot_geometry_polygons(): @@ -2118,6 +2187,7 @@ def test_declarative_plot_geometry_polygons(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=False, tolerance=2.985) def test_declarative_plot_geometry_lines(ccrs): """Test that `PlotGeometry` correctly plots MultiLineString and LineString objects.""" @@ -2158,6 +2228,7 @@ def test_declarative_plot_geometry_lines(ccrs): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=False, tolerance=0.013) def test_declarative_plot_geometry_fills(ccrs): """Test that `PlotGeometry` correctly plots MultiLineString and LineString objects.""" @@ -2194,6 +2265,7 @@ def test_declarative_plot_geometry_fills(ccrs): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=False, tolerance=1.900) def test_declarative_plot_geometry_points(ccrs): """Test that `PlotGeometry` correctly plots Point and MultiPoint objects.""" @@ -2272,6 +2344,7 @@ def test_attribute_error_no_suggest(): assert 'Perhaps you meant' not in str(excinfo.value) +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=False) @needs_cartopy def test_declarative_plot_surface_analysis_default(): @@ -2301,6 +2374,7 @@ def test_declarative_plot_surface_analysis_default(): return pc.figure +@pytest.mark.network @pytest.mark.mpl_image_compare(remove_text=False) @needs_cartopy def test_declarative_plot_surface_analysis_custom(): diff --git a/tests/plots/test_util.py b/tests/plots/test_util.py index db302cc16ee..258056fdf49 100644 --- a/tests/plots/test_util.py +++ b/tests/plots/test_util.py @@ -50,6 +50,7 @@ def test_add_timestamp_high_contrast(): return fig +@pytest.mark.network def test_add_timestamp_xarray(): """Test that add_timestamp can work with xarray datetime accessor.""" with autoclose_figure() as fig: diff --git a/tests/remote/test_aws.py b/tests/remote/test_aws.py index 5540598a3c5..627c03ff6f5 100644 --- a/tests/remote/test_aws.py +++ b/tests/remote/test_aws.py @@ -6,10 +6,13 @@ from pathlib import Path import tempfile +import pytest + from metpy.remote import GOESArchive, MLWPArchive, NEXRADLevel2Archive, NEXRADLevel3Archive from metpy.testing import needs_aws +@pytest.mark.network @needs_aws def test_nexrad3_single(): """Test getting a single product from the NEXRAD level 3 archive.""" @@ -18,6 +21,7 @@ def test_nexrad3_single(): assert l3.access() +@pytest.mark.network @needs_aws def test_nexrad3_range(): """Test getting a range of products from the NEXRAD level 3 archive.""" @@ -40,6 +44,7 @@ def test_nexrad3_range(): assert (Path(tmpdir) / 'tempprod').exists() +@pytest.mark.network @needs_aws def test_nexrad2_single(): """Test getting a single volume from the NEXRAD level 2 archive.""" @@ -47,6 +52,7 @@ def test_nexrad2_single(): assert l2.name == 'KTLX20130520_201643_V06.gz' +@pytest.mark.network @needs_aws def test_nexrad2_range(): """Test getting a range of products from the NEXRAD level 2 archive.""" @@ -59,6 +65,7 @@ def test_nexrad2_range(): 'KFTG20241214_161349_V06', 'KFTG20241214_162248_V06'] +@pytest.mark.network @needs_aws def test_goes_single(): """Test getting a single product from the GOES archive.""" @@ -70,6 +77,7 @@ def test_goes_single(): '_e20250092356311_c20250092356338.nc') +@pytest.mark.network @needs_aws def test_goes_range(): """Test getting a range of products from the GOES archive.""" @@ -94,6 +102,7 @@ def test_goes_range(): assert names == truth +@pytest.mark.network @needs_aws def test_mlwp_single(): """Test getting a single product from the MLWP archive.""" @@ -102,6 +111,7 @@ def test_mlwp_single(): '2025/0130/GRAP_v100_GFS_2025013012_f000_f240_06.nc') +@pytest.mark.network @needs_aws def test_mlwp_range(): """Test getting a single product from the MLWP archive.""" diff --git a/tests/test_xarray.py b/tests/test_xarray.py index e9fbb3cfdff..5e5e6e9690c 100644 --- a/tests/test_xarray.py +++ b/tests/test_xarray.py @@ -58,6 +58,7 @@ def test_var_multidim_no_xy(test_var_multidim_full): return test_var_multidim_full.drop_vars(['y', 'x']) +@pytest.mark.network def test_projection(test_var, ccrs): """Test getting the proper projection out of the variable.""" crs = test_var.metpy.crs @@ -66,6 +67,7 @@ def test_projection(test_var, ccrs): assert isinstance(test_var.metpy.cartopy_crs, ccrs.LambertConformal) +@pytest.mark.network def test_pyproj_projection(test_var): """Test getting the proper pyproj projection out of the variable.""" proj = test_var.metpy.pyproj_crs @@ -74,6 +76,7 @@ def test_pyproj_projection(test_var): assert proj.coordinate_operation.method_name == 'Lambert Conic Conformal (1SP)' +@pytest.mark.network def test_no_projection(test_ds): """Test getting the crs attribute when not available produces a sensible error.""" var = test_ds.lat @@ -83,6 +86,7 @@ def test_no_projection(test_ds): assert 'not available' in str(exc.value) +@pytest.mark.network def test_globe(test_var, ccrs): """Test getting the globe belonging to the projection.""" globe = test_var.metpy.cartopy_globe @@ -93,6 +97,7 @@ def test_globe(test_var, ccrs): assert isinstance(globe, ccrs.Globe) +@pytest.mark.network def test_geodetic(test_var, ccrs): """Test getting the Geodetic CRS for the projection.""" geodetic = test_var.metpy.cartopy_geodetic @@ -100,6 +105,7 @@ def test_geodetic(test_var, ccrs): assert isinstance(geodetic, ccrs.Geodetic) +@pytest.mark.network def test_unit_array(test_var): """Test unit handling through the accessor.""" arr = test_var.metpy.unit_array @@ -107,11 +113,13 @@ def test_unit_array(test_var): assert arr.units == units.kelvin +@pytest.mark.network def test_units(test_var): """Test the units property on the accessor.""" assert test_var.metpy.units == units.kelvin +@pytest.mark.network def test_units_data(test_var): """Test units property fetching does not touch variable.data.""" with patch.object(xr.Variable, 'data', new_callable=PropertyMock) as mock_data_property: @@ -119,6 +127,7 @@ def test_units_data(test_var): mock_data_property.assert_not_called() +@pytest.mark.network def test_units_percent(): """Test that '%' is handled as 'percent'.""" test_var_percent = xr.open_dataset( @@ -127,6 +136,7 @@ def test_units_percent(): assert test_var_percent.metpy.units == units.percent +@pytest.mark.network def test_magnitude_with_quantity(test_var): """Test magnitude property on accessor when data is a quantity.""" assert isinstance(test_var.metpy.magnitude, np.ndarray) @@ -142,6 +152,7 @@ def test_magnitude_without_quantity(test_ds_generic): ) +@pytest.mark.network def test_convert_units(test_var): """Test conversion of units.""" result = test_var.metpy.convert_units('degC') @@ -154,6 +165,7 @@ def test_convert_units(test_var): assert_almost_equal(result[0, 0, 0, 0], 18.44 * units.degC, 2) +@pytest.mark.network def test_convert_to_base_units(test_ds): """Test conversion of units.""" uwnd = test_ds.u_wind.metpy.quantify() @@ -174,6 +186,7 @@ def test_convert_coordinate_units(test_ds_generic): assert result['b'].metpy.units == units.percent +@pytest.mark.network def test_latlon_default_units(test_var_multidim_full): """Test that lat/lon are given degree units by default.""" del test_var_multidim_full.lat.attrs['units'] @@ -288,12 +301,14 @@ def test_missing_grid_mapping_valid(): ) +@pytest.mark.network def test_missing_grid_mapping_invalid(test_var_multidim_no_xy): """Test not falling back to implicit lat/lon projection when invalid.""" data_var = test_var_multidim_no_xy.to_dataset(name='data').metpy.parse_cf('data') assert 'metpy_crs' not in data_var.coords +@pytest.mark.network def test_xy_not_vertical(test_ds): """Test not detecting x/y as a vertical coordinate based on metadata.""" test_ds.x.attrs['positive'] = 'up' @@ -355,6 +370,7 @@ def func(a, b): assert_array_equal(func(data, b=data2), np.array([1001, 1001, 1001]) * units.m) +@pytest.mark.network def test_coordinates_basic_by_method(test_var): """Test that NARR example coordinates are like we expect using coordinates method.""" x, y, vertical, time = test_var.metpy.coordinates('x', 'y', 'vertical', 'time') @@ -365,6 +381,7 @@ def test_coordinates_basic_by_method(test_var): assert test_var['time'].identical(time) +@pytest.mark.network def test_coordinates_basic_by_property(test_var): """Test that NARR example coordinates are like we expect using properties.""" assert test_var['x'].identical(test_var.metpy.x) @@ -600,6 +617,7 @@ def test_check_axis_regular_expression_match(test_ds_generic, test_tuple): assert check_axis(data[test_tuple[0]], test_tuple[1]) +@pytest.mark.network def test_narr_example_variable_without_grid_mapping(test_ds): """Test that NARR example is parsed correctly, with x/y coordinates scaled the same.""" data = test_ds.metpy.parse_cf() @@ -645,6 +663,7 @@ def add(a, b): add(test_ds_generic['test'], other) +@pytest.mark.network def test_time_deltas(): """Test the time_deltas attribute.""" ds = xr.open_dataset(get_test_data('irma_gfs_example.nc', as_file_obj=False)) @@ -653,21 +672,25 @@ def test_time_deltas(): assert_array_almost_equal(time.metpy.time_deltas, truth) +@pytest.mark.network def test_find_axis_name_integer(test_var): """Test getting axis name using the axis number identifier.""" assert test_var.metpy.find_axis_name(2) == 'y' +@pytest.mark.network def test_find_axis_name_axis_type(test_var): """Test getting axis name using the axis type identifier.""" assert test_var.metpy.find_axis_name('vertical') == 'isobaric' +@pytest.mark.network def test_find_axis_name_dim_coord_name(test_var): """Test getting axis name using the dimension coordinate name identifier.""" assert test_var.metpy.find_axis_name('isobaric') == 'isobaric' +@pytest.mark.network def test_find_axis_name_bad_identifier(test_var): """Test getting axis name using the axis type identifier.""" with pytest.raises(ValueError) as exc: @@ -675,21 +698,25 @@ def test_find_axis_name_bad_identifier(test_var): assert 'axis is not valid' in str(exc.value) +@pytest.mark.network def test_find_axis_number_integer(test_var): """Test getting axis number using the axis number identifier.""" assert test_var.metpy.find_axis_number(2) == 2 +@pytest.mark.network def test_find_axis_number_axis_type(test_var): """Test getting axis number using the axis type identifier.""" assert test_var.metpy.find_axis_number('vertical') == 1 +@pytest.mark.network def test_find_axis_number_dim_coord_number(test_var): """Test getting axis number using the dimension coordinate name identifier.""" assert test_var.metpy.find_axis_number('isobaric') == 1 +@pytest.mark.network def test_find_axis_number_bad_identifier(test_var): """Test getting axis number using the axis type identifier.""" with pytest.raises(ValueError) as exc: @@ -697,12 +724,14 @@ def test_find_axis_number_bad_identifier(test_var): assert 'axis is not valid' in str(exc.value) +@pytest.mark.network def test_data_array_loc_get_with_units(test_var): """Test the .loc indexer on the metpy accessor.""" truth = test_var.loc[:, 850.] assert truth.identical(test_var.metpy.loc[:, 8.5e4 * units.Pa]) +@pytest.mark.network def test_data_array_loc_set_with_units(test_var): """Test the .loc indexer on the metpy accessor for setting.""" temperature = test_var.copy() @@ -711,24 +740,28 @@ def test_data_array_loc_set_with_units(test_var): assert not np.isnan(temperature.loc[:, 700.]).any() +@pytest.mark.network def test_data_array_loc_with_ellipsis(test_var): """Test the .loc indexer using multiple Ellipses to verify expansion behavior.""" truth = test_var[:, :, -1, :] assert truth.identical(test_var.metpy.loc[..., 711.3653535503963 * units.km, ...]) +@pytest.mark.network def test_data_array_loc_non_tuple(test_var): """Test the .loc indexer with a non-tuple indexer.""" truth = test_var[-1] assert truth.identical(test_var.metpy.loc['1987-04-04T18:00']) +@pytest.mark.network def test_data_array_loc_too_many_indices(test_var): """Test the .loc indexer when too many indices are given.""" with pytest.raises(IndexError): test_var.metpy.loc[:, 8.5e4 * units.Pa, :, :, :] +@pytest.mark.network def test_data_array_sel_dict_with_units(test_var): """Test .sel on the metpy accessor with dictionary.""" truth = test_var.squeeze().loc[500.] @@ -736,6 +769,7 @@ def test_data_array_sel_dict_with_units(test_var): 'isobaric': 5e4 * units.Pa})) +@pytest.mark.network def test_data_array_sel_kwargs_with_units(test_var): """Test .sel on the metpy accessor with kwargs and axis type.""" truth = test_var.loc[:, 500.][..., 122] @@ -748,6 +782,7 @@ def test_data_array_sel_kwargs_with_units(test_var): assert truth.identical(selection) +@pytest.mark.network def test_dataset_loc_with_units(test_ds): """Test .loc on the metpy accessor for Datasets using slices.""" truth = test_ds[{'isobaric': slice(6, 17)}] @@ -755,6 +790,7 @@ def test_dataset_loc_with_units(test_ds): 5e4 * units.Pa)}]) +@pytest.mark.network def test_dataset_sel_kwargs_with_units(test_ds): """Test .sel on the metpy accessor for Datasets with kwargs.""" truth = test_ds[{'time': 0, 'y': 50, 'x': 122}] @@ -763,6 +799,7 @@ def test_dataset_sel_kwargs_with_units(test_ds): method='nearest')) +@pytest.mark.network def test_dataset_sel_non_dict_pos_arg(test_ds): """Test that .sel errors when first positional argument is not a dict.""" with pytest.raises(ValueError) as exc: @@ -770,6 +807,7 @@ def test_dataset_sel_non_dict_pos_arg(test_ds): assert 'must be a dictionary' in str(exc.value) +@pytest.mark.network def test_dataset_sel_mixed_dict_and_kwarg(test_ds): """Test that .sel errors when dict positional argument and kwargs are mixed.""" with pytest.raises(ValueError) as exc: @@ -778,12 +816,14 @@ def test_dataset_sel_mixed_dict_and_kwarg(test_ds): assert 'cannot specify both keyword and positional arguments' in str(exc.value) +@pytest.mark.network def test_dataset_loc_without_dict(test_ds): """Test that .metpy.loc for Datasets raises error when used with a non-dict.""" with pytest.raises(TypeError): test_ds.metpy.loc[:, 700 * units.hPa] +@pytest.mark.network def test_dataset_parse_cf_keep_attrs(test_ds): """Test that .parse_cf() does not remove attributes on the parsed dataset.""" parsed_ds = test_ds.metpy.parse_cf() @@ -799,6 +839,7 @@ def test_check_axis_with_bad_unit(test_ds_generic): assert not check_axis(var, 'x', 'y', 'vertical', 'time') +@pytest.mark.network def test_dataset_parse_cf_varname_list(test_ds): """Test that .parse_cf() returns correct subset of dataset when given list of vars.""" full_ds = test_ds.copy().metpy.parse_cf() @@ -854,6 +895,7 @@ def test_one_dimensional_lat_lon(test_ds_generic): assert var['e'].identical(var.metpy.longitude) +@pytest.mark.network def test_auxilary_lat_lon_with_xy(test_var_multidim_full): """Test that auxiliary lat/lon coord identification works with other x/y coords present.""" assert test_var_multidim_full['y'].identical(test_var_multidim_full.metpy.y) @@ -862,12 +904,14 @@ def test_auxilary_lat_lon_with_xy(test_var_multidim_full): assert test_var_multidim_full['lon'].identical(test_var_multidim_full.metpy.longitude) +@pytest.mark.network def test_auxilary_lat_lon_without_xy(test_var_multidim_no_xy): """Test that multidimensional lat/lon are recognized in absence of x/y coords.""" assert test_var_multidim_no_xy['lat'].identical(test_var_multidim_no_xy.metpy.latitude) assert test_var_multidim_no_xy['lon'].identical(test_var_multidim_no_xy.metpy.longitude) +@pytest.mark.network def test_auxilary_lat_lon_without_xy_as_xy(test_var_multidim_no_xy): """Test that the pre-v1.0 behavior of multidimensional lat/lon errors.""" with pytest.raises(AttributeError):