diff --git a/.github/workflows/install-pypi.yaml b/.github/workflows/install-pypi.yaml index d795c4d..41a0630 100644 --- a/.github/workflows/install-pypi.yaml +++ b/.github/workflows/install-pypi.yaml @@ -65,10 +65,26 @@ jobs: run: | which python python scripts/test-install.py - - name: Install pytest + - name: Install min test dependencies run: | - pip install pytest + pip install pytest pytest-regressions - name: Run tests run: | - # Can't run doctests here because the paths are different + # Can't run doctests here because the paths are different. + # This also only runs with minimum test dependencies. + # So this is really just a smoke test, + # rather than a super thorough integration test. pytest tests -r a -vv tests + # # This is a sketch of how you would do more thorough tests. + # # I don't like this solution because it is out of line with the lock file. + # # Probably the simplest way to do this is to use uv somehow, + # # install the package from pypi and the test dependencies + # # based on the lock file. + # - name: Install extra test dependencies + # run: | + # # A bit annoying to maintain this by hand, but ok for now. + # pip install ipython matplotlib openscm-units scipy + # - name: Run tests with extra test dependencies installed + # run: | + # # Can't run doctests here because the paths are different. + # pytest tests -r a -vv tests diff --git a/changelog/23.trivial.md b/changelog/23.trivial.md new file mode 100644 index 0000000..3db9774 --- /dev/null +++ b/changelog/23.trivial.md @@ -0,0 +1 @@ +Fixed up test PyPI workflow diff --git a/tests/integration/test_budget_compatible_pathways_integration.py b/tests/integration/test_budget_compatible_pathways_integration.py index ea71e31..91b8fbf 100644 --- a/tests/integration/test_budget_compatible_pathways_integration.py +++ b/tests/integration/test_budget_compatible_pathways_integration.py @@ -9,7 +9,6 @@ from unittest.mock import patch import numpy as np -import openscm_units import pint.testing import pytest @@ -17,6 +16,8 @@ from continuous_timeseries import budget_compatible_pathways as ct_bcp from continuous_timeseries.exceptions import MissingOptionalDependencyError +openscm_units = pytest.importorskip("openscm_units") + UR = openscm_units.unit_registry Q = UR.Quantity diff --git a/tests/integration/test_discrete_to_continuous_linear_and_higher_order.py b/tests/integration/test_discrete_to_continuous_linear_and_higher_order.py index 3b992e6..dd06fb4 100644 --- a/tests/integration/test_discrete_to_continuous_linear_and_higher_order.py +++ b/tests/integration/test_discrete_to_continuous_linear_and_higher_order.py @@ -30,6 +30,8 @@ ) from continuous_timeseries.typing import PINT_NUMPY_ARRAY, PINT_SCALAR +pytest.importorskip("scipy.interpolate") + UR = pint.get_application_registry() Q = UR.Quantity diff --git a/tests/integration/test_plotting_helpers_integration.py b/tests/integration/test_plotting_helpers_integration.py index ffb2c33..b8ca0b0 100644 --- a/tests/integration/test_plotting_helpers_integration.py +++ b/tests/integration/test_plotting_helpers_integration.py @@ -14,6 +14,8 @@ from continuous_timeseries.plotting_helpers import get_plot_vals +pytest.importorskip("matplotlib") + UR = pint.get_application_registry() Q = UR.Quantity diff --git a/tests/integration/test_time_axis_integration.py b/tests/integration/test_time_axis_integration.py index 2bcd1d8..369b836 100644 --- a/tests/integration/test_time_axis_integration.py +++ b/tests/integration/test_time_axis_integration.py @@ -4,11 +4,12 @@ from __future__ import annotations +import textwrap + import numpy as np import pint import pint.testing import pytest -from IPython.lib.pretty import pretty from continuous_timeseries.time_axis import TimeAxis @@ -75,37 +76,38 @@ def test_str(bounds, exp_str): @pytest.mark.parametrize( - "bounds, exp_pretty", + "bounds ", ( pytest.param( Q([1.0, 2.0, 3.0], "yr"), - "TimeAxis(bounds=)", id="basic", ), pytest.param( Q(np.linspace(1750, 2000 + 1, 1000), "yr"), - ( - "TimeAxis(\n" - f"bounds={pretty(Q(np.linspace(1750, 2000 + 1, 1000), 'yr'))})" - ), - marks=pytest.mark.skip(reason="Too hard to predict indenting and slow"), id="big_array", ), pytest.param( Q(np.linspace(1750, 2000 + 1, int(1e5)), "yr"), - ( - "TimeAxis(\n" - " bounds=)" - ), id="really_big_array", ), ), ) -def test_pretty(bounds, exp_pretty): +def test_pretty(bounds): + pytest.importorskip("IPython") + + from IPython.lib.pretty import pretty + + formatted = f"bounds={pretty(bounds)}" + + if len(formatted) > 60: + indented = textwrap.indent(formatted, " ") + exp = f"TimeAxis(\n{indented})" + else: + exp = f"TimeAxis({formatted})" + instance = TimeAxis(bounds) - assert pretty(instance) == exp_pretty + assert pretty(instance) == exp @pytest.mark.parametrize( diff --git a/tests/integration/test_timeseries_continous_integration.py b/tests/integration/test_timeseries_continous_integration.py index 21d8ab9..6ef6811 100644 --- a/tests/integration/test_timeseries_continous_integration.py +++ b/tests/integration/test_timeseries_continous_integration.py @@ -13,9 +13,7 @@ import pint import pint.testing import pytest -import scipy.interpolate from attrs import define -from IPython.lib.pretty import pretty from continuous_timeseries.exceptions import ( ExtrapolationNotAllowedError, @@ -27,6 +25,8 @@ TimeseriesContinuous, ) +scipy = pytest.importorskip("scipy") + UR = pint.get_application_registry() Q = UR.Quantity @@ -145,6 +145,10 @@ def test_str_continuous_function_scipy_ppoly(continuous_function_scipy_ppoly, ex ), ) def test_pretty_continuous_function_scipy_ppoly(continuous_function_scipy_ppoly, exp): + pytest.importorskip("IPython") + + from IPython.lib.pretty import pretty + pretty_value = pretty(continuous_function_scipy_ppoly) assert pretty_value == exp @@ -335,6 +339,10 @@ def test_str(ts, file_regression): ) @formatting_check_cases def test_pretty(ts, file_regression): + pytest.importorskip("IPython") + + from IPython.lib.pretty import pretty + file_regression.check( f"{pretty(ts)}\n", extension=".txt", diff --git a/tests/integration/test_timeseries_discrete_integration.py b/tests/integration/test_timeseries_discrete_integration.py index 496d597..92c7110 100644 --- a/tests/integration/test_timeseries_discrete_integration.py +++ b/tests/integration/test_timeseries_discrete_integration.py @@ -13,7 +13,6 @@ import pint import pint.testing import pytest -from IPython.lib.pretty import pretty from continuous_timeseries.discrete_to_continuous import InterpolationOption from continuous_timeseries.exceptions import MissingOptionalDependencyError @@ -94,6 +93,10 @@ def test_str(ts, file_regression): @formatting_check_cases def test_pretty(ts, file_regression): + pytest.importorskip("IPython") + + from IPython.lib.pretty import pretty + file_regression.check( f"{pretty(ts)}\n", extension=".txt", @@ -148,7 +151,7 @@ def test_to_continuous_timeseries_warning_suppression(): def test_plot( # noqa: PLR0913 x_units, y_units, plot_kwargs, legend, image_regression, tmp_path ): - import matplotlib + matplotlib = pytest.importorskip("matplotlib") # ensure matplotlib does not use a GUI backend (such as Tk) matplotlib.use("Agg") @@ -246,7 +249,7 @@ def test_plot( # noqa: PLR0913 def test_plot_matplotlib_units_not_registered( plot_kwargs, expectation, image_regression, tmp_path ): - import matplotlib + matplotlib = pytest.importorskip("matplotlib") # ensure matplotlib does not use a GUI backend (such as Tk) matplotlib.use("Agg") @@ -297,7 +300,11 @@ def test_plot_matplotlib_units_not_registered( @pytest.mark.parametrize( "sys_modules_patch, expectation", ( - pytest.param({}, does_not_raise(), id="matplotlib_available"), + pytest.param( + {}, + does_not_raise(), + id="matplotlib_available", + ), pytest.param( {"matplotlib": None}, pytest.raises( @@ -309,6 +316,8 @@ def test_plot_matplotlib_units_not_registered( ), ) def test_plot_ax_creation(sys_modules_patch, expectation): + (pytest.importorskip("matplotlib"),) + ts = TimeseriesDiscrete( name="basic", time_axis=TimeAxis(Q([1.0, 2.0, 3.0], "yr")), diff --git a/tests/integration/test_timeseries_integration.py b/tests/integration/test_timeseries_integration.py index e168f43..5b6f9cb 100644 --- a/tests/integration/test_timeseries_integration.py +++ b/tests/integration/test_timeseries_integration.py @@ -16,7 +16,6 @@ import pint.testing import pytest from attrs import define, field, validators -from IPython.lib.pretty import pretty from continuous_timeseries.discrete_to_continuous import InterpolationOption from continuous_timeseries.exceptions import ( @@ -35,6 +34,9 @@ InterpolationUpdateChangedValuesAtBoundsWarning, ) +# Tests don't make sense without scipy +pytest.importorskip("scipy") + UR = pint.get_application_registry() Q = UR.Quantity @@ -116,6 +118,10 @@ def test_str(ts, file_regression): ) @formatting_check_cases def test_pretty(ts, file_regression): + pytest.importorskip("IPython") + + from IPython.lib.pretty import pretty + file_regression.check( f"{pretty(ts)}\n", extension=".txt", diff --git a/tests/integration/test_values_at_bounds_integration.py b/tests/integration/test_values_at_bounds_integration.py index 42f03af..ab582fb 100644 --- a/tests/integration/test_values_at_bounds_integration.py +++ b/tests/integration/test_values_at_bounds_integration.py @@ -4,10 +4,11 @@ from __future__ import annotations +import textwrap + import numpy as np import pint import pytest -from IPython.lib.pretty import pretty from continuous_timeseries.values_at_bounds import ValuesAtBounds @@ -74,37 +75,38 @@ def test_str(values, exp_str): @pytest.mark.parametrize( - "values, exp_pretty", + "values", ( pytest.param( Q([1.0, 2.0, 3.0], "kg"), - "ValuesAtBounds(values=)", id="basic", ), pytest.param( Q(np.linspace(1750, 2000 + 1, 1000), "yr"), - ( - "ValuesAtBounds(\n" - f"values={pretty(Q(np.linspace(1750, 2000 + 1, 1000), 'yr'))})" - ), - marks=pytest.mark.skip(reason="Too hard to predict indenting and slow"), id="big_array", ), pytest.param( Q(np.linspace(1750, 2000 + 1, int(1e5)), "yr"), - ( - "ValuesAtBounds(\n" - " values=)" - ), id="really_big_array", ), ), ) -def test_pretty(values, exp_pretty): +def test_pretty(values): + pytest.importorskip("IPython") + + from IPython.lib.pretty import pretty + + formatted = f"values={pretty(values)}" + + if len(formatted) > 60: + indented = textwrap.indent(formatted, " ") + exp = f"ValuesAtBounds(\n{indented})" + else: + exp = f"ValuesAtBounds({formatted})" + instance = ValuesAtBounds(values) - assert pretty(instance) == exp_pretty + assert pretty(instance) == exp @pytest.mark.parametrize( diff --git a/tests/unit/test_discrete_to_continuous.py b/tests/unit/test_discrete_to_continuous.py index 4c5bc3d..7a2cebb 100644 --- a/tests/unit/test_discrete_to_continuous.py +++ b/tests/unit/test_discrete_to_continuous.py @@ -147,6 +147,7 @@ def test_implicit_extrapolation_raises(piecewise_constant_class, x, times, expec def test_differentiate_scipy_availability( piecewise_constant_class, sys_modules_patch, expectation ): + pytest.importorskip("scipy") with patch.dict(sys.modules, sys_modules_patch): with expectation: piecewise_constant_class(np.arange(10), np.arange(10)).differentiate() @@ -155,7 +156,11 @@ def test_differentiate_scipy_availability( @pytest.mark.parametrize( "sys_modules_patch, expectation", ( - pytest.param({}, does_not_raise(), id="scipy_available"), + pytest.param( + {}, + does_not_raise(), + id="scipy_available", + ), pytest.param( {"scipy": None}, pytest.raises( @@ -170,6 +175,7 @@ def test_differentiate_scipy_availability( def test_integrate_scipy_availability( piecewise_constant_class, sys_modules_patch, expectation ): + pytest.importorskip("scipy") with patch.dict(sys.modules, sys_modules_patch): with expectation: piecewise_constant_class(np.arange(10), np.arange(10)).integrate(1.0, 5.0) diff --git a/tests/unit/test_timeseries_continuous.py b/tests/unit/test_timeseries_continuous.py index ad539cd..a21ec05 100644 --- a/tests/unit/test_timeseries_continuous.py +++ b/tests/unit/test_timeseries_continuous.py @@ -12,7 +12,6 @@ import pint import pint.testing import pytest -import scipy.interpolate from continuous_timeseries.exceptions import ( MissingOptionalDependencyError, @@ -81,8 +80,10 @@ def test_validation_time_axis_values_same_shape(domain, expectation): ), ) def test_integrate_no_scipy(sys_modules_patch, expectation): + scipy_interpolate = pytest.importorskip("scipy.interpolate") + continuous_function_scipy_ppoly = ContinuousFunctionScipyPPoly( - scipy.interpolate.PPoly(x=[1, 10, 20], c=[[10, 12]]) + scipy_interpolate.PPoly(x=[1, 10, 20], c=[[10, 12]]) ) with patch.dict(sys.modules, sys_modules_patch): with expectation: diff --git a/uv.lock b/uv.lock index e926c1d..be2b56f 100644 --- a/uv.lock +++ b/uv.lock @@ -345,7 +345,7 @@ wheels = [ [[package]] name = "continuous-timeseries" -version = "0.3.1" +version = "0.3.2a1" source = { editable = "." } dependencies = [ { name = "attrs" },