From 6b3386dee3708b5940d08ec84447a82fb74163ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kai=20M=C3=BChlbauer?= Date: Thu, 22 Feb 2024 18:37:23 +0100 Subject: [PATCH] MNT: Update GitHub actions, address DeprecationWarnings (#153) * MNT: Update GitHub actions * MNT: update ruff config in pyproject.toml * MNT: fix checkout -> v4 * MNT: fix deprecation - > To access a mapping from dimension names to lengths, use `Dataset.sizes` * MNT: fix deprecation, drop -> drop_vars * MNT: fix deprecation, utcfromtimestamp * MNT: add history.md entry --- .github/workflows/ci.yml | 34 +++++++++++----------- .github/workflows/upload_pypi.yml | 6 ++-- docs/history.md | 4 +++ pyproject.toml | 3 +- tests/io/test_io.py | 48 +++++++++++++++---------------- tests/test_model.py | 8 +++--- tests/test_util.py | 6 ++-- xradar/io/backends/cfradial1.py | 2 +- xradar/io/export/cfradial1.py | 2 +- xradar/io/export/odim.py | 9 ++++-- 10 files changed, 66 insertions(+), 56 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index daa2f2be..1538e5a6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,11 +13,11 @@ jobs: name: lint and style checks runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: - python-version: "3.11" + python-version: "3.12" - name: Install dependencies run: | python -m pip install --upgrade pip @@ -41,9 +41,9 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.9", "3.10", "3.11"] + python-version: ["3.10", "3.11", "3.12"] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Install micromamba environment @@ -66,7 +66,7 @@ jobs: run: | pytest -n auto --dist loadfile --verbose --durations=15 --cov-report xml:coverage_unit.xml --cov=xradar --pyargs tests - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: file: ./coverage_unit.xml flags: unittests @@ -86,9 +86,9 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.9", "3.10", "3.11"] + python-version: ["3.10", "3.11", "3.12"] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Install micromamba environment @@ -111,7 +111,7 @@ jobs: run: | pytest -n auto --dist loadfile --verbose --durations=15 --cov-report xml:coverage_notebooks.xml --cov=xradar --pyargs examples/notebooks - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: file: ./coverage_notebook.xml flags: notebooktests @@ -128,13 +128,13 @@ jobs: run: shell: bash -l {0} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: - python-version: "3.11" + python-version: "3.12" - name: Install dependencies run: | python -m pip install --upgrade pip @@ -146,7 +146,7 @@ jobs: python -m build cp dist/xradar*.gz dist/xradar1.gz - name: Upload artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: xradar-1-${{github.event.number}} path: dist/xradar1.gz @@ -167,13 +167,13 @@ jobs: run: shell: bash -l {0} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: - python-version: "3.11" + python-version: "3.12" - name: Install dependencies run: | python -m pip install --upgrade pip @@ -183,7 +183,7 @@ jobs: python -m build cp dist/xradar*.gz dist/xradar0.gz - name: Upload artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: xradar-0-${{github.event.number}} path: dist/xradar0.gz diff --git a/.github/workflows/upload_pypi.yml b/.github/workflows/upload_pypi.yml index 0a14fad5..6c84dd09 100644 --- a/.github/workflows/upload_pypi.yml +++ b/.github/workflows/upload_pypi.yml @@ -13,13 +13,13 @@ jobs: run: shell: bash -l {0} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: - python-version: "3.11" + python-version: "3.12" - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/docs/history.md b/docs/history.md index 87f016d5..14b70185 100644 --- a/docs/history.md +++ b/docs/history.md @@ -1,5 +1,9 @@ # History +## Development Version (unreleased) + +* MNT: Update GitHub actions, address DeprecationWarnings ({pull}`153`) by [@kmuehlbauer](https://github.com/kmuehlbauer). + ## 0.4.3 (2024-02-24) * MNT: address black style changes, update pre-commit-config.yaml ({pull}`152`) by [@kmuehlbauer](https://github.com/kmuehlbauer). diff --git a/pyproject.toml b/pyproject.toml index 788ca1f8..1c91165a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -72,6 +72,7 @@ exclude = [ "doc", ] +[tool.ruff.lint] # E402: module level import not at top of file # E501: line too long - let black worry about that # E731: do not assign a lambda expression, use a def @@ -92,5 +93,5 @@ select = [ "UP", ] -[tool.ruff.isort] +[tool.ruff.lint.isort] known-first-party = ["xradar"] diff --git a/tests/io/test_io.py b/tests/io/test_io.py index e27ea792..2669d905 100644 --- a/tests/io/test_io.py +++ b/tests/io/test_io.py @@ -64,7 +64,7 @@ def test_open_cfradial1_datatree(cfradial1_file): ds = dtree[grp].ds i = ds.sweep_number.values assert i == int(grp[7:]) - assert dict(ds.dims) == {"time": azimuths[i], "range": ranges[i]} + assert dict(ds.sizes) == {"time": azimuths[i], "range": ranges[i]} assert set(ds.data_vars) & ( sweep_dataset_vars | non_standard_sweep_dataset_vars ) == set(moments) @@ -153,7 +153,7 @@ def test_open_odim_datatree(odim_file): ] for i, grp in enumerate(dtree.groups[1:]): ds = dtree[grp].ds - assert dict(ds.dims) == {"azimuth": azimuths[i], "range": ranges[i]} + assert dict(ds.sizes) == {"azimuth": azimuths[i], "range": ranges[i]} assert set(ds.data_vars) & ( sweep_dataset_vars | non_standard_sweep_dataset_vars ) == set(moments) @@ -176,7 +176,7 @@ def test_open_odim_datatree(odim_file): def test_open_odim_dataset(odim_file): # open first sweep group ds = xr.open_dataset(odim_file, group="sweep_0", engine="odim") - assert dict(ds.dims) == {"azimuth": 360, "range": 1200} + assert dict(ds.sizes) == {"azimuth": 360, "range": 1200} assert set(ds.data_vars) & ( sweep_dataset_vars | non_standard_sweep_dataset_vars ) == {"WRADH", "VRADH", "PHIDP", "DBZH", "RHOHV", "KDP", "TH", "ZDR"} @@ -184,7 +184,7 @@ def test_open_odim_dataset(odim_file): # open last sweep group ds = xr.open_dataset(odim_file, group="sweep_11", engine="odim") - assert dict(ds.dims) == {"azimuth": 360, "range": 280} + assert dict(ds.sizes) == {"azimuth": 360, "range": 280} assert set(ds.data_vars) & ( sweep_dataset_vars | non_standard_sweep_dataset_vars ) == {"VRADH", "KDP", "WRADH", "TH", "RHOHV", "PHIDP", "ZDR", "DBZH"} @@ -197,7 +197,7 @@ def test_open_odim_dataset(odim_file): engine="odim", backend_kwargs=dict(first_dim="time"), ) - assert dict(ds.dims) == {"time": 360, "range": 280} + assert dict(ds.sizes) == {"time": 360, "range": 280} assert ds.sweep_number == 11 @@ -261,7 +261,7 @@ def test_open_gamic_datatree(gamic_file): ] for i, grp in enumerate(dtree.groups[1:]): ds = dtree[grp].ds - assert dict(ds.dims) == {"azimuth": azimuths[i], "range": ranges[i]} + assert dict(ds.sizes) == {"azimuth": azimuths[i], "range": ranges[i]} assert set(ds.data_vars) & ( sweep_dataset_vars | non_standard_sweep_dataset_vars ) == set(moments) @@ -284,7 +284,7 @@ def test_open_gamic_datatree(gamic_file): def test_open_gamic_dataset(gamic_file): # open first sweep group ds = xr.open_dataset(gamic_file, group="sweep_0", engine="gamic") - assert dict(ds.dims) == {"azimuth": 361, "range": 360} + assert dict(ds.sizes) == {"azimuth": 361, "range": 360} assert set(ds.data_vars) & ( sweep_dataset_vars | non_standard_sweep_dataset_vars ) == { @@ -305,7 +305,7 @@ def test_open_gamic_dataset(gamic_file): # open last sweep group ds = xr.open_dataset(gamic_file, group="sweep_9", engine="gamic") - assert dict(ds.dims) == {"azimuth": 360, "range": 1000} + assert dict(ds.sizes) == {"azimuth": 360, "range": 1000} assert set(ds.data_vars) & ( sweep_dataset_vars | non_standard_sweep_dataset_vars ) == { @@ -331,7 +331,7 @@ def test_open_gamic_dataset(gamic_file): engine="gamic", backend_kwargs=dict(first_dim="time"), ) - assert dict(ds.dims) == {"time": 360, "range": 1000} + assert dict(ds.sizes) == {"time": 360, "range": 1000} assert ds.sweep_number == 9 @@ -341,13 +341,13 @@ def test_open_gamic_dataset_reindex(gamic_file): ds = xr.open_dataset( gamic_file, group="sweep_0", engine="gamic", reindex_angle=reindex_angle ) - assert dict(ds.dims) == {"azimuth": 360, "range": 360} + assert dict(ds.sizes) == {"azimuth": 360, "range": 360} def test_open_furuno_scn_dataset(furuno_scn_file): # open sweep group ds = xr.open_dataset(furuno_scn_file, first_dim="time", engine="furuno") - assert dict(ds.dims) == {"time": 1376, "range": 602} + assert dict(ds.sizes) == {"time": 1376, "range": 602} assert set(ds.data_vars) & ( sweep_dataset_vars | non_standard_sweep_dataset_vars ) == {"KDP", "VRADH", "ZDR", "DBZH", "WRADH", "RHOHV", "PHIDP"} @@ -367,14 +367,14 @@ def test_open_furuno_scn_dataset(furuno_scn_file): furuno_scn_file, engine="furuno", ) - assert dict(ds.dims) == {"azimuth": 1376, "range": 602} + assert dict(ds.sizes) == {"azimuth": 1376, "range": 602} assert ds.sweep_number == 0 def test_open_furuno_scnx_dataset(furuno_scnx_file): # open sweep group ds = xr.open_dataset(furuno_scnx_file, first_dim="time", engine="furuno") - assert dict(ds.dims) == {"time": 722, "range": 936} + assert dict(ds.sizes) == {"time": 722, "range": 936} assert set(ds.data_vars) & ( sweep_dataset_vars | non_standard_sweep_dataset_vars ) == {"KDP", "VRADH", "ZDR", "DBZH", "WRADH", "RHOHV", "PHIDP"} @@ -395,7 +395,7 @@ def test_open_furuno_scnx_dataset(furuno_scnx_file): furuno_scnx_file, engine="furuno", ) - assert dict(ds.dims) == {"azimuth": 722, "range": 936} + assert dict(ds.sizes) == {"azimuth": 722, "range": 936} assert ds.sweep_number == 0 @@ -441,7 +441,7 @@ def test_open_rainbow_datatree(rainbow_file): ranges = [400] * 14 for i, grp in enumerate(dtree.groups[1:]): ds = dtree[grp].ds - assert dict(ds.dims) == {"azimuth": azimuths[i], "range": ranges[i]} + assert dict(ds.sizes) == {"azimuth": azimuths[i], "range": ranges[i]} assert set(ds.data_vars) & ( sweep_dataset_vars | non_standard_sweep_dataset_vars ) == set(moments) @@ -464,7 +464,7 @@ def test_open_rainbow_datatree(rainbow_file): def test_open_rainbow_dataset(rainbow_file): # open first sweep group ds = xr.open_dataset(rainbow_file, group="sweep_0", engine="rainbow") - assert dict(ds.dims) == {"azimuth": 361, "range": 400} + assert dict(ds.sizes) == {"azimuth": 361, "range": 400} assert set(ds.data_vars) & ( sweep_dataset_vars | non_standard_sweep_dataset_vars ) == { @@ -474,7 +474,7 @@ def test_open_rainbow_dataset(rainbow_file): # open last sweep group ds = xr.open_dataset(rainbow_file, group="sweep_13", engine="rainbow") - assert dict(ds.dims) == {"azimuth": 361, "range": 400} + assert dict(ds.sizes) == {"azimuth": 361, "range": 400} assert set(ds.data_vars) & ( sweep_dataset_vars | non_standard_sweep_dataset_vars ) == { @@ -489,7 +489,7 @@ def test_open_rainbow_dataset(rainbow_file): engine="rainbow", backend_kwargs=dict(first_dim="time"), ) - assert dict(ds.dims) == {"time": 361, "range": 400} + assert dict(ds.sizes) == {"time": 361, "range": 400} assert ds.sweep_number == 13 @@ -536,7 +536,7 @@ def test_open_iris_datatree(iris0_file): ranges = [664] * 10 for i, grp in enumerate(dtree.groups[1:]): ds = dtree[grp].ds - assert dict(ds.dims) == {"azimuth": azimuths[i], "range": ranges[i]} + assert dict(ds.sizes) == {"azimuth": azimuths[i], "range": ranges[i]} assert set(ds.data_vars) & ( sweep_dataset_vars | non_standard_sweep_dataset_vars ) == set(moments) @@ -559,7 +559,7 @@ def test_open_iris_datatree(iris0_file): def test_open_iris0_dataset(iris0_file): # open first sweep group ds = xr.open_dataset(iris0_file, group="sweep_0", engine="iris") - assert dict(ds.dims) == {"azimuth": 360, "range": 664} + assert dict(ds.sizes) == {"azimuth": 360, "range": 664} assert set(ds.data_vars) & ( sweep_dataset_vars | non_standard_sweep_dataset_vars ) == { @@ -574,7 +574,7 @@ def test_open_iris0_dataset(iris0_file): # open last sweep group ds = xr.open_dataset(iris0_file, group="sweep_9", engine="iris") - assert dict(ds.dims) == {"azimuth": 360, "range": 664} + assert dict(ds.sizes) == {"azimuth": 360, "range": 664} assert set(ds.data_vars) & ( sweep_dataset_vars | non_standard_sweep_dataset_vars ) == { @@ -594,14 +594,14 @@ def test_open_iris0_dataset(iris0_file): engine="iris", backend_kwargs=dict(first_dim="time"), ) - assert dict(ds.dims) == {"time": 360, "range": 664} + assert dict(ds.sizes) == {"time": 360, "range": 664} assert ds.sweep_number == 9 def test_open_iris1_dataset(iris1_file): # open first and only sweep group ds = xr.open_dataset(iris1_file, group="sweep_0", engine="iris") - assert dict(ds.dims) == {"azimuth": 359, "range": 833} + assert dict(ds.sizes) == {"azimuth": 359, "range": 833} assert set(ds.data_vars) & ( sweep_dataset_vars | non_standard_sweep_dataset_vars ) == { @@ -623,7 +623,7 @@ def test_open_iris1_dataset(iris1_file): engine="iris", backend_kwargs=dict(first_dim="time"), ) - assert dict(ds.dims) == {"time": 359, "range": 833} + assert dict(ds.sizes) == {"time": 359, "range": 833} assert ds.sweep_number == 0 diff --git a/tests/test_model.py b/tests/test_model.py index 03509787..ceb7613a 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -18,7 +18,7 @@ def test_create_sweep_dataset(): assert ds.elevation.shape == (360,) assert ds.time.shape == (360,) assert ds.range.shape == (1000,) - assert ds.dims == {"time": 360, "range": 1000} + assert ds.sizes == {"time": 360, "range": 1000} assert np.unique(ds.elevation) == [1.0] assert ds.azimuth[0] == 0.5 assert ds.azimuth[-1] == 359.5 @@ -36,7 +36,7 @@ def test_create_sweep_dataset(): assert ds.elevation.shape == (360,) assert ds.time.shape == (360,) assert ds.range.shape == (1000,) - assert ds.dims == {"time": 360, "range": 1000} + assert ds.sizes == {"time": 360, "range": 1000} assert np.unique(ds.elevation) == [5.0] assert ds.azimuth[0] == 0.5 assert ds.azimuth[-1] == 359.5 @@ -45,7 +45,7 @@ def test_create_sweep_dataset(): # provide shape and range-res, fixed-elevation ds = model.create_sweep_dataset(shape=(180, 100), rng=50.0, elevation=5.0) - assert ds.dims == {"time": 180, "range": 100} + assert ds.sizes == {"time": 180, "range": 100} assert ds.range[-1] == 4975 assert ds.time[-1].values == np.datetime64("2022-08-27T10:00:44.750000000") assert np.unique(ds.elevation) == [5.0] @@ -54,7 +54,7 @@ def test_create_sweep_dataset(): ds = model.create_sweep_dataset( shape=(90, 100), rng=50.0, azimuth=205.0, sweep="RHI" ) - assert ds.dims == {"time": 90, "range": 100} + assert ds.sizes == {"time": 90, "range": 100} assert ds.range[-1] == 4975 assert ds.time[-1].values == np.datetime64("2022-08-27T10:00:22.250000000") assert np.unique(ds.azimuth) == [205.0] diff --git a/tests/test_util.py b/tests/test_util.py index f740dfeb..20baaf77 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -37,8 +37,8 @@ def test_remove_duplicate_rays(): filename = DATASETS.fetch("DWD-Vol-2_99999_20180601054047_00.h5") ds = xr.open_dataset(filename, group="sweep_7", engine="gamic", first_dim="auto") ds_out = util.remove_duplicate_rays(ds) - assert ds.dims["azimuth"] == 361 - assert ds_out.dims["azimuth"] == 360 + assert ds.sizes["azimuth"] == 361 + assert ds_out.sizes["azimuth"] == 360 def test_reindex_angle(): @@ -48,7 +48,7 @@ def test_reindex_angle(): ds_out = util.reindex_angle( ds_out, start_angle=0, stop_angle=360, angle_res=1.0, direction=1 ) - assert ds_out.dims["azimuth"] == 360 + assert ds_out.sizes["azimuth"] == 360 np.testing.assert_array_equal(ds_out.azimuth.values, np.arange(0.5, 360, 1.0)) diff --git a/xradar/io/backends/cfradial1.py b/xradar/io/backends/cfradial1.py index 299fb287..df99ac48 100644 --- a/xradar/io/backends/cfradial1.py +++ b/xradar/io/backends/cfradial1.py @@ -145,7 +145,7 @@ def _get_sweep_groups( sweep = [f"sweep_{sweep}"] # iterate over sweeps - for i in range(root.dims["sweep"]): + for i in range(root.sizes["sweep"]): sw = f"sweep_{i}" if sweep is not None and not (sw in sweep or i in sweep): continue diff --git a/xradar/io/export/cfradial1.py b/xradar/io/export/cfradial1.py index 29f23a2f..af93c660 100644 --- a/xradar/io/export/cfradial1.py +++ b/xradar/io/export/cfradial1.py @@ -102,7 +102,7 @@ def _variable_mapper(dtree, dim0=None): """ sweep_info = _sweep_info_mapper(dtree) - vol_info = _main_info_mapper(dtree).drop("fixed_angle") + vol_info = _main_info_mapper(dtree).drop_vars("fixed_angle") sweep_datasets = [] for grp in dtree.groups: if "sweep" in grp: diff --git a/xradar/io/export/odim.py b/xradar/io/export/odim.py index 8efaad64..bbf316a7 100644 --- a/xradar/io/export/odim.py +++ b/xradar/io/export/odim.py @@ -32,6 +32,7 @@ __doc__ = __doc__.format("\n ".join(__all__)) import datetime as dt +import sys import h5py import numpy as np @@ -227,8 +228,12 @@ def to_odim( # skip NaT values valid_times = ~np.isnat(ds.time.values) t = sorted(ds.time.values[valid_times]) - start = dt.datetime.utcfromtimestamp(np.rint(t[0].astype("O") / 1e9)) - end = dt.datetime.utcfromtimestamp(np.rint(t[-1].astype("O") / 1e9)) + if sys.version_info.major == 3 and sys.version_info.minor <= 10: + start = dt.datetime.utcfromtimestamp(np.rint(t[0].astype("O") / 1e9)) + end = dt.datetime.utcfromtimestamp(np.rint(t[-1].astype("O") / 1e9)) + else: + start = dt.datetime.fromtimestamp(np.rint(t[0].astype("O") / 1e9), dt.UTC) + end = dt.datetime.fromtimestamp(np.rint(t[-1].astype("O") / 1e9), dt.UTC) ds_what["product"] = "SCAN" ds_what["startdate"] = start.strftime("%Y%m%d") ds_what["starttime"] = start.strftime("%H%M%S")