diff --git a/conda-env/ci.yml b/conda-env/ci.yml index 3fa1e226..455062e0 100644 --- a/conda-env/ci.yml +++ b/conda-env/ci.yml @@ -16,10 +16,8 @@ dependencies: - pandas - python-dateutil - xarray >=2022.02.0 # This version of Xarray drops support for Python 3.8. - - xgcm - # Optional - enables additional features. - # ========================================= - xesmf >=0.7.0 # Constrained because https://github.com/pangeo-data/xESMF/issues/212. + - xgcm # Quality Assurance # ================== - types-python-dateutil diff --git a/conda-env/dev.yml b/conda-env/dev.yml index 16d41a25..63f45f19 100644 --- a/conda-env/dev.yml +++ b/conda-env/dev.yml @@ -16,10 +16,10 @@ dependencies: - pandas - python-dateutil - xarray >=2022.02.0 # This version of Xarray drops support for Python 3.8. + - xesmf >=0.7.0 # Constrained because https://github.com/pangeo-data/xESMF/issues/212. - xgcm # Optional - enables additional features. # ========================================= - - xesmf >=0.7.0 # Constrained because https://github.com/pangeo-data/xESMF/issues/212. - matplotlib-base >=3.7.0 - nc-time-axis=1.4.1 # Documentation diff --git a/docs/getting-started.rst b/docs/getting-started.rst index ad1ddedf..27231aa5 100644 --- a/docs/getting-started.rst +++ b/docs/getting-started.rst @@ -48,22 +48,14 @@ Installation The advantage with following this approach is that Mamba will attempt to resolve dependencies (e.g. ``python >= 3.8``) for compatibility. - To create an ``xcdat`` Mamba environment with ``xesmf`` (a recommended dependency), + To create an ``xcdat`` Mamba environment, run: .. code-block:: bash - >>> mamba create -n -c conda-forge xcdat xesmf + >>> mamba create -n -c conda-forge xcdat >>> mamba activate - Note that ``xesmf`` is an optional dependency, which is required for using ``xesmf`` - based horizontal regridding APIs in ``xcdat``. ``xesmf`` is not currently supported - on `Windows`_ because it depends on ``esmpy``, which also does not support Windows. - Windows users can try `WSL2`_ as a workaround. - -.. _Windows: https://github.com/conda-forge/esmf-feedstock/issues/64 -.. _WSL2: https://docs.microsoft.com/en-us/windows/wsl/install - 2. Install ``xcdat`` in an existing Mamba environment (`mamba install`_) You can also install ``xcdat`` in an existing Mamba environment, granted that Mamba @@ -72,9 +64,7 @@ Installation .. code-block:: bash >>> mamba activate - >>> mamba install -c conda-forge xcdat xesmf - - Note: As above, ``xesmf`` is an optional dependency. + >>> mamba install -c conda-forge xcdat 3. [Optional] Some packages that are commonly used with ``xcdat`` can be installed either in step 1 or step 2 above: diff --git a/tests/__init__.py b/tests/__init__.py index 4f35d8fd..7b0661f2 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,7 +1,5 @@ """Unit test package for xcdat.""" from xarray.core.options import set_options -from xarray.tests import _importorskip, requires_dask # noqa: F401 +from xarray.tests import requires_dask # noqa: F401 set_options(warn_for_unclosed_files=False) - -has_xesmf, requires_xesmf = _importorskip("xesmf") diff --git a/tests/test_regrid.py b/tests/test_regrid.py index 4f295298..839e78cb 100644 --- a/tests/test_regrid.py +++ b/tests/test_regrid.py @@ -9,11 +9,8 @@ import pytest import xarray as xr -from tests import fixtures, has_xesmf, requires_xesmf -from xcdat.regridder import accessor, base, grid, regrid2, xgcm - -if has_xesmf: - from xcdat.regridder import xesmf +from tests import fixtures +from xcdat.regridder import accessor, base, grid, regrid2, xesmf, xgcm np.set_printoptions(threshold=sys.maxsize, suppress=True) @@ -688,7 +685,6 @@ def test_reversed_extract_bounds(self): assert north[0], north[-1] == (60, 90) -@requires_xesmf class TestXESMFRegridder: @pytest.fixture(autouse=True) def setup(self): @@ -697,13 +693,6 @@ def setup(self): ) self.new_grid = grid.create_uniform_grid(-90, 90, 4.0, -180, 180, 5.0) - @pytest.mark.xfail - def test_raises_error_if_xesmf_is_not_installed(self): - # TODO Find a way to mock the value of `_has_xesmf` to False or - # to remove the `xesmf` module entirely - with pytest.raises(ModuleNotFoundError): - xesmf.XESMFRegridder(self.ds, self.new_grid, "bilinear") - def test_vertical_placeholder(self): ds = self.ds.copy() @@ -1198,7 +1187,6 @@ def test_preserve_mask_from_input(self): xr.testing.assert_allclose(mask.ts, grid.mask) - @requires_xesmf def test_horizontal(self): output_grid = grid.create_gaussian_grid(32) @@ -1348,7 +1336,6 @@ def test_vertical_tool_check(self, _get_input_grid): ): self.ac.vertical("ts", mock_data, tool="dummy", target_data=None) # type: ignore - @requires_xesmf @pytest.mark.filterwarnings("ignore:.*invalid value.*divide.*:RuntimeWarning") def test_convenience_methods(self): ds = fixtures.generate_dataset( @@ -1365,18 +1352,6 @@ def test_convenience_methods(self): assert output_regrid2.ts.shape == (15, 32, 65) - @pytest.mark.xfail - def test_raises_error_if_xesmf_is_not_installed(self): - # TODO Find a way to mock the value of `_has_xesmf` to False or - # to remove the `xesmf` module entirely - ds = fixtures.generate_dataset( - decode_times=True, cf_compliant=False, has_bounds=True - ) - - out_grid = grid.create_gaussian_grid(32) - with pytest.raises(ModuleNotFoundError): - ds.regridder.horizontal_xesmf("ts", out_grid, method="bilinear") - class TestBase: def test_preserve_bounds(self): diff --git a/xcdat/regridder/__init__.py b/xcdat/regridder/__init__.py index c7042751..cdd14697 100644 --- a/xcdat/regridder/__init__.py +++ b/xcdat/regridder/__init__.py @@ -1,8 +1,5 @@ from xcdat.regridder.accessor import RegridderAccessor from xcdat.regridder.regrid2 import Regrid2Regridder +from xcdat.regridder.xesmf import XESMFRegridder from xcdat.regridder.xgcm import XGCMRegridder from xcdat.utils import _has_module - -_has_xesmf = _has_module("xesmf") -if _has_xesmf: - from xcdat.regridder.xesmf import XESMFRegridder diff --git a/xcdat/regridder/accessor.py b/xcdat/regridder/accessor.py index 2d19c86e..b8a93c35 100644 --- a/xcdat/regridder/accessor.py +++ b/xcdat/regridder/accessor.py @@ -6,19 +6,14 @@ import xarray as xr from xcdat.axis import CFAxisKey, get_dim_coords -from xcdat.regridder import regrid2, xgcm +from xcdat.regridder import regrid2, xesmf, xgcm from xcdat.regridder.grid import _validate_grid_has_single_axis_dim -from xcdat.utils import _has_module HorizontalRegridTools = Literal["xesmf", "regrid2"] -HORIZONTAL_REGRID_TOOLS = {"regrid2": regrid2.Regrid2Regridder} - -# TODO: Test this conditional. -_has_xesmf = _has_module("xesmf") -if _has_xesmf: # pragma: no cover - from xcdat.regridder import xesmf - - HORIZONTAL_REGRID_TOOLS["xesmf"] = xesmf.XESMFRegridder # type: ignore +HORIZONTAL_REGRID_TOOLS = { + "regrid2": regrid2.Regrid2Regridder, + "xesmf": xesmf.XESMFRegridder, +} VerticalRegridTools = Literal["xgcm"] VERTICAL_REGRID_TOOLS = {"xgcm": xgcm.XGCMRegridder} @@ -179,19 +174,9 @@ def horizontal_xesmf( stacklevel=2, ) - # TODO: Test this conditional. - if _has_xesmf: # pragma: no cover - regridder = HORIZONTAL_REGRID_TOOLS["xesmf"]( - self._ds, output_grid, **options - ) + regridder = HORIZONTAL_REGRID_TOOLS["xesmf"](self._ds, output_grid, **options) - return regridder.horizontal(data_var, self._ds) - else: # pragma: no cover - raise ModuleNotFoundError( - "The `xesmf` package is required for horizontal regridding with " - "`xesmf`. Make sure your platform supports `xesmf` and it is installed " - "in your conda environment." - ) + return regridder.horizontal(data_var, self._ds) # TODO Either provide generic `horizontal` and `vertical` methods or tool specific def horizontal_regrid2( @@ -327,14 +312,6 @@ def horizontal( >>> output_data = ds.regridder.horizontal("ts", output_grid, tool="regrid2") """ - # TODO: Test this conditional. - if tool == "xesmf" and not _has_xesmf: # pragma: no cover - raise ModuleNotFoundError( - "The `xesmf` package is required for horizontal regridding with " - "`xesmf`. Make sure your platform supports `xesmf` and it is installed " - "in your conda environment." - ) - try: regrid_tool = HORIZONTAL_REGRID_TOOLS[tool] except KeyError as e: diff --git a/xcdat/regridder/xesmf.py b/xcdat/regridder/xesmf.py index 03e1ab8e..90239469 100644 --- a/xcdat/regridder/xesmf.py +++ b/xcdat/regridder/xesmf.py @@ -1,21 +1,9 @@ from typing import Any, Optional import xarray as xr +import xesmf as xe from xcdat.regridder.base import BaseRegridder, _preserve_bounds -from xcdat.utils import _has_module - -# TODO: Test this conditional. -_has_xesmf = _has_module("xesmf") -if _has_xesmf: # pragma: no cover - import xesmf as xe -else: # pragma: no cover - raise ModuleNotFoundError( - "The `xesmf` package is required for horizontal regridding with `xesmf`. Make " - "sure your platform supports `xesmf` and it is installed in your conda " - "environment." - ) - VALID_METHODS = [ "bilinear",