Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,47 @@ jobs:
cd docs
echo 'nb_execution_mode = "off"' >> conf.py
make linkcheck

test-optional-deps:
# Ensures can install with various combinations of optional dependencies,
# and that some corresponding tests pass or crash appropriately.
# Just a single machine and single Python version should be good enough,
# the goal here is to spot-check that optional deps work as expected,
# not to run an exhaustive set of tests with each combination of deps.
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v7

- name: setup-python
uses: actions/setup-python@v7
with:
python-version: "3.13"

- name: no optional deps
run: |
python -m venv "$RUNNER_TEMP/venv-none"
source "$RUNNER_TEMP/venv-none/bin/activate"
python -m pip install "." pytest
python -m pytest test_optional_deps/test_installed_with_no_opts.py

- name: geo only
run: |
python -m venv "$RUNNER_TEMP/venv-geo"
source "$RUNNER_TEMP/venv-geo/bin/activate"
python -m pip install ".[geo]" pytest
python -m pytest test_optional_deps/test_installed_with_geo.py

- name: viz only
run: |
python -m venv "$RUNNER_TEMP/venv-viz"
source "$RUNNER_TEMP/venv-viz/bin/activate"
python -m pip install ".[viz]" pytest
python -m pytest test_optional_deps/test_installed_with_viz.py

- name: viz and geo
run: |
python -m venv "$RUNNER_TEMP/venv-viz_and_geo"
source "$RUNNER_TEMP/venv-viz_and_geo/bin/activate"
python -m pip install ".[viz,geo]" pytest
python -m pytest test_optional_deps/test_installed_with_viz_and_geo.py
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,6 @@ known-first-party = ["uxarray"]

[tool.ruff.format]
docstring-code-format = true

[tool.pytest.ini_options]
testpaths = ["tests"] # (intentionally excludes test_optional_deps)
56 changes: 56 additions & 0 deletions test_optional_deps/_optional_deps_helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""
File Purpose: defines helper functions to be used for testing optional dependencies.

The goal here is to spot-check that optional deps work as expected,
not to run an exhaustive set of tests with each combination of deps.
"""


def check_requires_no_opts():
"""run some checks which should not require any optional dependencies"""
import uxarray as ux

uxds = ux.tutorial.open_dataset("quad-hexagon")
uxds.compute()


def check_requires_only_viz():
"""run some checks which should require viz optional dependencies,
but not any other optional dependencies.
"""
import uxarray as ux

uxds = ux.tutorial.open_dataset("quad-hexagon")
plot_obj = uxds.plot.points() # points() doesn't need geo projection details.

# actually try to render the plot, too:
import holoviews as hv

renderer = hv.renderer("matplotlib")
renderer.get_plot(plot_obj)


def check_requires_only_geo():
"""run some checks which should require geo optional dependencies,
but not any other optional dependencies.
"""
import uxarray as ux

arr = ux.tutorial.open_dataset("quad-hexagon")["t2m"]
arr.to_geodataframe()


def check_requires_viz_and_geo():
"""run some checks which should require both viz and geo optional dependencies,
but not any other optional dependencies.
"""
import uxarray as ux

arr = ux.tutorial.open_dataset("quad-hexagon")["t2m"]
plot_obj = arr.plot.polygons() # polygons() uses geo projection details.

# actually try to render the plot, too:
import holoviews as hv

renderer = hv.renderer("matplotlib")
renderer.get_plot(plot_obj)
35 changes: 35 additions & 0 deletions test_optional_deps/test_installed_with_geo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""
Purpose: test expected behaviors when installed with only geo optional dependency.
Tests should all pass if and only if installed accordingly, i.e. something like:
pip install ".[geo]"
"""

import pytest
from _optional_deps_helpers import (
check_requires_no_opts,
check_requires_only_geo,
check_requires_only_viz,
check_requires_viz_and_geo,
)


def test_check_requires_no_opts():
"""ensure success for checks which should not require any optional dependencies"""
check_requires_no_opts()


def test_check_requires_only_viz():
"""ensure failure for checks which should require viz optional dependencies"""
with pytest.raises(ImportError):
check_requires_only_viz()


def test_check_requires_only_geo():
"""ensure success for checks which should require geo optional dependencies"""
check_requires_only_geo()


def test_check_requires_viz_and_geo():
"""ensure failure for checks which should require both viz and geo optional dependencies"""
with pytest.raises(ImportError):
check_requires_viz_and_geo()
36 changes: 36 additions & 0 deletions test_optional_deps/test_installed_with_no_opts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""
Purpose: test expected behaviors when installed without any optional dependencies.
Tests should all pass if and only if installed accordingly, i.e. something like:
pip install "."
"""

import pytest
from _optional_deps_helpers import (
check_requires_no_opts,
check_requires_only_geo,
check_requires_only_viz,
check_requires_viz_and_geo,
)


def test_check_requires_no_opts():
"""ensure success for checks which should not require any optional dependencies"""
check_requires_no_opts()


def test_check_requires_only_viz():
"""ensure failure for checks which should require viz optional dependencies"""
with pytest.raises(ImportError):
check_requires_only_viz()


def test_check_requires_only_geo():
"""ensure failure for checks which should require geo optional dependencies"""
with pytest.raises(ImportError):
check_requires_only_geo()


def test_check_requires_viz_and_geo():
"""ensure failure for checks which should require both viz and geo optional dependencies"""
with pytest.raises(ImportError):
check_requires_viz_and_geo()
35 changes: 35 additions & 0 deletions test_optional_deps/test_installed_with_viz.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""
Purpose: test expected behaviors when installed with only viz optional dependency.
Tests should all pass if and only if installed accordingly, i.e. something like:
pip install ".[viz]"
"""

import pytest
from _optional_deps_helpers import (
check_requires_no_opts,
check_requires_only_geo,
check_requires_only_viz,
check_requires_viz_and_geo,
)


def test_check_requires_no_opts():
"""ensure success for checks which should not require any optional dependencies"""
check_requires_no_opts()


def test_check_requires_only_viz():
"""ensure success for checks which should require viz optional dependencies"""
check_requires_only_viz()


def test_check_requires_only_geo():
"""ensure failure for checks which should require geo optional dependencies"""
with pytest.raises(ImportError):
check_requires_only_geo()


def test_check_requires_viz_and_geo():
"""ensure failure for checks which should require both viz and geo optional dependencies"""
with pytest.raises(ImportError):
check_requires_viz_and_geo()
32 changes: 32 additions & 0 deletions test_optional_deps/test_installed_with_viz_and_geo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""
Purpose: test expected behaviors when installed with geo and viz optional dependencies.
Tests should all pass if and only if installed accordingly, i.e. something like:
pip install ".[geo,viz]"
"""

from _optional_deps_helpers import (
check_requires_no_opts,
check_requires_only_geo,
check_requires_only_viz,
check_requires_viz_and_geo,
)


def test_check_requires_no_opts():
"""ensure success for checks which should not require any optional dependencies"""
check_requires_no_opts()


def test_check_requires_only_viz():
"""ensure success for checks which should require viz optional dependencies"""
check_requires_only_viz()


def test_check_requires_only_geo():
"""ensure success for checks which should require geo optional dependencies"""
check_requires_only_geo()


def test_check_requires_viz_and_geo():
"""ensure success for checks which should require both viz and geo optional dependencies"""
check_requires_viz_and_geo()