From 81de7c4d96014721a4389fe46fe8c237637034d5 Mon Sep 17 00:00:00 2001 From: Stefan Binder Date: Sat, 18 May 2024 10:08:27 +0200 Subject: [PATCH] ci: Remove references to archived altair_viewer and altair_saver in ci, docs, and tests. Uninstall anywidget and vl-convert-python during one test run (#3419) * Remove references to altair_viewer * Clean up build workflow and also uninstall anywidget and vl-convert-python for one build step * Remove altair_viewer and altair_saver references from pyproject.toml * Remove references to altair_saver * Add deprecation warning if someone uses webdriver argument as it's not relevant for vl-convert. This was used for altair_saver which is no longer compatible and maintained * Remove the save_engine pytest mark as it no longer makes sense in the current GitHub workflow setup * Run test_save_html again with inline=True as vl-convert now supports it * Remove unused imports * Run __init__ update script * Skip jupyterchart tests if anywidget is not installed * Some more test skips if vl convert or anywidget are not installed * Fix mypy errors * Skip more tests which are expected to fail if vl-convert is not installed --------- Co-authored-by: Mattijn van Hoek --- .github/workflows/build.yml | 21 +------------ altair/__init__.py | 1 + altair/utils/display.py | 7 ----- altair/utils/mimebundle.py | 47 +++++++--------------------- altair/utils/save.py | 17 +++++++--- altair/vegalite/v5/api.py | 21 +++++++++---- doc/getting_started/resources.rst | 8 ----- doc/user_guide/display_frontends.rst | 1 - doc/user_guide/large_datasets.rst | 4 +-- doc/user_guide/saving_charts.rst | 35 +++------------------ pyproject.toml | 5 --- tests/test_examples.py | 16 +--------- tests/test_jupyter_chart.py | 46 ++++++++++++++++++++------- tests/utils/test_compiler.py | 14 +++++++++ tests/utils/test_mimebundle.py | 20 ++---------- tests/vegalite/v5/test_api.py | 39 ++++++----------------- tests/vegalite/v5/test_renderers.py | 18 +++++++++++ 17 files changed, 127 insertions(+), 193 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 73bb570c9..277158442 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,17 +16,10 @@ jobs: uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - # - name: Set Up Chromedriver - # run: | - # sudo apt-get update - # sudo apt-get --only-upgrade install google-chrome-stable - # sudo apt-get -yqq install chromium-chromedriver - name: Install dependencies run: | python -m pip install --upgrade pip pip install ".[all, dev]" - # pip install "selenium<4.3.0" - # pip install altair_saver - name: Install specific jsonschema # Only have to execute this if we don't want the latest jsonschema version if: ${{ matrix.jsonschema-version != 'latest' }} @@ -39,7 +32,7 @@ jobs: # Also see https://github.com/vega/altair/pull/3114 if: ${{ matrix.python-version == '3.8' }} run: | - pip uninstall -y pyarrow vegafusion vegafusion-python-embed + pip uninstall -y pyarrow vegafusion vegafusion-python-embed vl-convert-python anywidget - name: Maybe install lowest supported pandas version # We install the lowest supported pandas version for one job to test that # it still works. Downgrade to the oldest versions of pandas and numpy that include @@ -72,18 +65,6 @@ jobs: - name: Test with pytest run: | pytest --doctest-modules tests - # - name: Selected tests without vl-convert-python - # run: | - # pip uninstall vl-convert-python --yes - # pytest -m save_engine --doctest-modules tests - # - name: Selected tests without vl-convert-python and altair_saver - # run: | - # pip uninstall altair_saver --yes - # pytest -m save_engine --doctest-modules tests - - name: Selected tests with vl-convert-python and without altair_saver - run: | - # pip install vl-convert-python - pytest -m save_engine --doctest-modules tests - name: Validate Vega-Lite schema run: | # We install all 'format' dependencies of jsonschema as check-jsonschema diff --git a/altair/__init__.py b/altair/__init__.py index 1c5b755f6..073a1a53e 100644 --- a/altair/__init__.py +++ b/altair/__init__.py @@ -17,6 +17,7 @@ "AggregatedFieldDef", "Align", "AllSortString", + "AltairDeprecationWarning", "Angle", "AngleDatum", "AngleValue", diff --git a/altair/utils/display.py b/altair/utils/display.py index c1585eda2..30c31d4ad 100644 --- a/altair/utils/display.py +++ b/altair/utils/display.py @@ -38,13 +38,6 @@ class RendererRegistry(PluginRegistry[RendererType]): for more information. """ ), - "altair_viewer": textwrap.dedent( - """ - To use the 'altair_viewer' renderer, you must install the altair_viewer - package; see http://github.com/altair-viz/altair_viewer/ - for more information. - """ - ), } def set_embed_options( diff --git a/altair/utils/mimebundle.py b/altair/utils/mimebundle.py index 49a1f5557..89588d04d 100644 --- a/altair/utils/mimebundle.py +++ b/altair/utils/mimebundle.py @@ -1,10 +1,8 @@ from typing import Literal, Optional, Union, cast, Tuple -from .deprecation import AltairDeprecationWarning from .html import spec_to_html from ._importers import import_vl_convert, vl_version_for_vl_convert import struct -import warnings def spec_to_mimebundle( @@ -15,7 +13,7 @@ def spec_to_mimebundle( vegaembed_version: Optional[str] = None, vegalite_version: Optional[str] = None, embed_options: Optional[dict] = None, - engine: Optional[Literal["vl-convert", "altair_saver"]] = None, + engine: Optional[Literal["vl-convert"]] = None, **kwargs, ) -> Union[dict, Tuple[dict, dict]]: """Convert a vega-lite specification to a mimebundle @@ -41,7 +39,7 @@ def spec_to_mimebundle( The vegaEmbed options dictionary. Defaults to the embed options set with alt.renderers.set_embed_options(). (See https://github.com/vega/vega-embed for details) - engine: string {'vl-convert', 'altair_saver'} + engine: string {'vl-convert'} the conversion engine to use for 'png', 'svg', 'pdf', and 'vega' formats **kwargs : Additional arguments will be passed to the generating function @@ -53,7 +51,7 @@ def spec_to_mimebundle( Note ---- - The png, svg, pdf, and vega outputs require the altair_saver package + The png, svg, pdf, and vega outputs require the vl-convert package """ # Local import to avoid circular ImportError from altair.utils.display import ( @@ -130,7 +128,7 @@ def _spec_to_mimebundle_with_engine( the format of the mimebundle to be returned mode : string {'vega-lite', 'vega'} The rendering mode. - engine: string {'vl-convert', 'altair_saver'} + engine: string {'vl-convert'} the conversion engine to use format_locale : str or dict d3-format locale name or dictionary. Defaults to "en-US" for United States English. @@ -221,16 +219,6 @@ def _spec_to_mimebundle_with_engine( # This should be validated above # but raise exception for the sake of future development raise ValueError("Unexpected format {fmt!r}".format(fmt=format)) - elif normalized_engine == "altairsaver": - warnings.warn( - "The altair_saver export engine is deprecated and will be removed in a future version.\n" - "Please migrate to the vl-convert engine", - AltairDeprecationWarning, - stacklevel=1, - ) - import altair_saver - - return altair_saver.render(spec, format, mode=mode, **kwargs) else: # This should be validated above # but raise exception for the sake of future development @@ -240,12 +228,12 @@ def _spec_to_mimebundle_with_engine( def _validate_normalize_engine( - engine: Optional[Literal["vl-convert", "altair_saver"]], + engine: Optional[Literal["vl-convert"]], format: Literal["png", "svg", "pdf", "vega"], ) -> str: """Helper to validate and normalize the user-provided engine - engine : {None, 'vl-convert', 'altair_saver'} + engine : {None, 'vl-convert'} the user-provided engine string format : string {'png', 'svg', 'pdf', 'vega'} the format of the mimebundle to be returned @@ -256,12 +244,6 @@ def _validate_normalize_engine( except ImportError: vlc = None - # Try to import altair_saver - try: - import altair_saver - except ImportError: - altair_saver = None - # Normalize engine string by lower casing and removing underscores and hyphens normalized_engine = ( None if engine is None else engine.lower().replace("-", "").replace("_", "") @@ -273,25 +255,20 @@ def _validate_normalize_engine( raise ValueError( "The 'vl-convert' conversion engine requires the vl-convert-python package" ) - elif normalized_engine == "altairsaver": - if altair_saver is None: - raise ValueError( - "The 'altair_saver' conversion engine requires the altair_saver package" - ) elif normalized_engine is None: if vlc is not None: normalized_engine = "vlconvert" - elif altair_saver is not None: - normalized_engine = "altairsaver" else: raise ValueError( - "Saving charts in {fmt!r} format requires the vl-convert-python or altair_saver package: " - "see http://github.com/altair-viz/altair_saver/".format(fmt=format) + "Saving charts in {fmt!r} format requires the vl-convert-python package: " + "see https://altair-viz.github.io/user_guide/saving_charts.html#png-svg-and-pdf-format".format( + fmt=format + ) ) else: raise ValueError( - "Invalid conversion engine {engine!r}. Expected one of {valid!r}".format( - engine=engine, valid=("vl-convert", "altair_saver") + "Invalid conversion engine {engine!r}. Expected vl-convert".format( + engine=engine ) ) return normalized_engine diff --git a/altair/utils/save.py b/altair/utils/save.py index 1784cc43e..11db77bf1 100644 --- a/altair/utils/save.py +++ b/altair/utils/save.py @@ -6,6 +6,7 @@ from .mimebundle import spec_to_mimebundle from ..vegalite.v5.data import data_transformers from altair.utils._vegafusion_data import using_vegafusion +from altair.utils.deprecation import AltairDeprecationWarning def write_file_or_filename( @@ -80,7 +81,7 @@ def save( json_kwds: Optional[dict] = None, webdriver: Optional[Literal["chrome", "firefox"]] = None, scale_factor: float = 1, - engine: Optional[Literal["vl-convert", "altair_saver"]] = None, + engine: Optional[Literal["vl-convert"]] = None, inline: bool = False, **kwargs, ) -> None: @@ -114,10 +115,10 @@ def save( Additional keyword arguments are passed to the output method associated with the specified format. webdriver : string {'chrome' | 'firefox'} (optional) - Webdriver to use for png, svg, or pdf output when using altair_saver engine + This argument is deprecated as it's not relevant for the new vl-convert engine. scale_factor : float (optional) scale_factor to use to change size/resolution of png or svg output - engine: string {'vl-convert', 'altair_saver'} + engine: string {'vl-convert'} the conversion engine to use for 'png', 'svg', and 'pdf' formats inline: bool (optional) If False (default), the required JavaScript libraries are loaded @@ -128,6 +129,15 @@ def save( **kwargs : additional kwargs passed to spec_to_mimebundle. """ + if webdriver is not None: + warnings.warn( + "The webdriver argument is deprecated as it's not relevant for" + + " the new vl-convert engine which replaced altair_saver." + + " The argument will be removed in a future release.", + AltairDeprecationWarning, + stacklevel=1, + ) + if json_kwds is None: json_kwds = {} @@ -174,7 +184,6 @@ def perform_save(): vegalite_version=vegalite_version, vegaembed_version=vegaembed_version, embed_options=embed_options, - webdriver=webdriver, scale_factor=scale_factor, engine=engine, **kwargs, diff --git a/altair/vegalite/v5/api.py b/altair/vegalite/v5/api.py index 93bd295b3..0bd9ae389 100644 --- a/altair/vegalite/v5/api.py +++ b/altair/vegalite/v5/api.py @@ -28,6 +28,7 @@ ) from ...utils.core import DataFrameLike from ...utils.data import DataType +from ...utils.deprecation import AltairDeprecationWarning if sys.version_info >= (3, 11): from typing import Self @@ -231,9 +232,9 @@ def to_dict(self) -> TypingDict[str, Union[str, dict]]: return {"expr": self.name} elif self.param_type == "selection": return { - "param": self.name.to_dict() - if hasattr(self.name, "to_dict") - else self.name + "param": ( + self.name.to_dict() if hasattr(self.name, "to_dict") else self.name + ) } else: raise ValueError(f"Unrecognized parameter type: {self.param_type}") @@ -1155,7 +1156,7 @@ def save( """Save a chart to file in a variety of formats Supported formats are json, html, png, svg, pdf; the last three require - the altair_saver package to be installed. + the vl-convert-python package to be installed. Parameters ---------- @@ -1187,7 +1188,7 @@ def save( Additional keyword arguments are passed to the output method associated with the specified format. webdriver : string {'chrome' | 'firefox'} (optional) - Webdriver to use for png, svg, or pdf output when using altair_saver engine + This argument is deprecated as it's not relevant for the new vl-convert engine. engine: string {'vl-convert', 'altair_saver'} the conversion engine to use for 'png', 'svg', and 'pdf' formats inline: bool (optional) @@ -1199,6 +1200,15 @@ def save( **kwargs : additional kwargs passed to spec_to_mimebundle. """ + if webdriver is not None: + warnings.warn( + "The webdriver argument is deprecated as it's not relevant for" + + " the new vl-convert engine which replaced altair_saver." + + " The argument will be removed in a future release.", + AltairDeprecationWarning, + stacklevel=1, + ) + from ...utils.save import save kwds = dict( @@ -1212,7 +1222,6 @@ def save( vegaembed_version=vegaembed_version, embed_options=embed_options, json_kwds=json_kwds, - webdriver=webdriver, engine=engine, inline=inline, **kwargs, diff --git a/doc/getting_started/resources.rst b/doc/getting_started/resources.rst index 4a35f1eb9..2c5008fa7 100644 --- a/doc/getting_started/resources.rst +++ b/doc/getting_started/resources.rst @@ -88,14 +88,6 @@ VegaFusion provides server-side scaling for Altair charts, which can accelerate .. List of links. .. _VegaFusion: https://vegafusion.io/ -altair_saver_ -~~~~~~~~~~~~~ - -Enables saving charts to a variety of output types. - -.. List of links. -.. _altair_saver: https://github.com/altair-viz/altair_saver - altair_data_server_ ~~~~~~~~~~~~~~~~~~~ diff --git a/doc/user_guide/display_frontends.rst b/doc/user_guide/display_frontends.rst index c860cc356..1596e05b6 100644 --- a/doc/user_guide/display_frontends.rst +++ b/doc/user_guide/display_frontends.rst @@ -701,7 +701,6 @@ see :ref:`display-general`. .. _nteract: https://nteract.io .. _nbconvert: https://nbconvert.readthedocs.io/ .. _nbviewer: https://nbviewer.jupyter.org/ -.. _Altair Viewer: https://github.com/altair-viz/altair_viewer/ .. _Colab: https://colab.research.google.com .. _Hydrogen: https://github.com/nteract/hydrogen .. _Jupyter Notebook: https://jupyter-notebook.readthedocs.io/en/stable/ diff --git a/doc/user_guide/large_datasets.rst b/doc/user_guide/large_datasets.rst index 39c5f8756..d07cf1c82 100644 --- a/doc/user_guide/large_datasets.rst +++ b/doc/user_guide/large_datasets.rst @@ -296,8 +296,7 @@ prerender the visualization and send only a static image to your notebook. This greatly reduce the amount of data that is being transmitted. The downside with this approach is, that you loose all interactivity features of Altair. -Both renderers require you to install either the `vl-convert`_ or the `altair_saver`_ package, see :ref:`saving-png`, -whereas `vl-convert`_ is expected to provide the better performance. +Both renderers require you to install the `vl-convert`_ package, see :ref:`saving-png`. .. _preaggregate-and-filter: @@ -469,4 +468,3 @@ summary statistics to Altair instead of the full dataset. .. _DuckDB: https://duckdb.org/ .. _VegaFusion DuckDB: https://vegafusion.io/duckdb.html .. _vl-convert: https://github.com/vega/vl-convert -.. _altair_saver: https://github.com/altair-viz/altair_saver/ diff --git a/doc/user_guide/saving_charts.rst b/doc/user_guide/saving_charts.rst index b4bd62ed0..d0b5798b8 100644 --- a/doc/user_guide/saving_charts.rst +++ b/doc/user_guide/saving_charts.rst @@ -172,10 +172,9 @@ To save an Altair chart object as a PNG, SVG, or PDF image, you can use chart.save('chart.svg') chart.save('chart.pdf') -Saving these images requires an additional extension to run the +Saving these images requires an additional extension vl-convert_ to run the javascript code necessary to interpret the Vega-Lite specification and output -it in the form of an image. There are two packages that can be used to enable -image export: vl-convert_ or altair_saver_. +it in the form of an image. .. _install-vl-convert: @@ -189,7 +188,7 @@ or:: pip install vl-convert-python -Unlike altair_saver_, vl-convert_ does not require any external dependencies. +vl-convert_ does not require any external dependencies. See the vl-convert documentation for information and for known `limitations `_. @@ -198,28 +197,7 @@ altair_saver .. note:: - altair_saver does not yet support Altair 5. - - -The altair_saver_ package can be installed with:: - - conda install -c conda-forge altair_saver - -or:: - - pip install altair_saver - -See the altair_saver_ documentation for information about additional installation -requirements. - -Engine Argument -^^^^^^^^^^^^^^^ -If both vl-convert and altair_saver are installed, vl-convert will take precedence. -The engine argument to :meth:`Chart.save` can be used to override this default -behavior. For example, to use altair_saver for PNG export when vl-convert is also -installed you can use:: - - chart.save('chart.png', engine="altair_saver") + altair_saver was used in Altair 4 and earlier versions. It is no longer maintained and got superseded by vl-convert_ which provides a superior user experience and performance. PNG Figure Size/Resolution @@ -231,10 +209,6 @@ to save the image with a resolution of 200 pixels-per-inch:: chart.save('chart.png', ppi=200) -.. note:: - - The ``ppi`` argument is only supported by the ``vl-convert`` engine. It will be ignored if - the ``altair_saver`` engine is enabled. To change the physical size of the resulting image while preserving the resolution, the ``scale_factor`` argument may be used. For example, to save the image at double the default @@ -262,6 +236,5 @@ specification in the online Vega editor_. chart.to_url() .. _vl-convert: https://github.com/vega/vl-convert -.. _altair_saver: http://github.com/altair-viz/altair_saver/ .. _vegaEmbed: https://github.com/vega/vega-embed .. _editor: https://vega.github.io/editor/ \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 33a80d13d..36c95b317 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -202,9 +202,6 @@ line-ending = "lf" max-complexity = 18 [tool.pytest.ini_options] -markers = [ - "save_engine: marks some of the tests which are using an external package to save a chart to e.g. a png file. This mark is used to run those tests selectively in the build GitHub Action.", -] # Pytest does not need to search these folders for test functions. # They contain examples which are being executed by the # test_examples tests. @@ -217,8 +214,6 @@ warn_unused_ignores = true module = [ "vega_datasets.*", "toolz.*", - "altair_viewer.*", - "altair_saver.*", "pyarrow.*", "yaml.*", "vl_convert.*", diff --git a/tests/test_examples.py b/tests/test_examples.py index 4a1a2ed08..124b8a66b 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -8,10 +8,6 @@ from tests import examples_arguments_syntax from tests import examples_methods_syntax -try: - import altair_saver # noqa: F401 -except ImportError: - altair_saver = None try: import vl_convert as vlc # noqa: F401 @@ -88,12 +84,7 @@ def test_from_and_to_json_roundtrip(syntax_module): ) from err -# We do not apply the save_engine mark to this test. This mark is used in -# the build GitHub Action workflow to select the tests which should be rerun -# with some of the saving engines uninstalled. This would not make sense for this test -# as here it is only interesting to run it with all saving engines installed. -# Furthermore, the runtime of this test is rather long. -@pytest.mark.parametrize("engine", ["vl-convert", "altair_saver"]) +@pytest.mark.parametrize("engine", ["vl-convert"]) @pytest.mark.parametrize( "syntax_module", [examples_arguments_syntax, examples_methods_syntax] ) @@ -101,11 +92,6 @@ def test_render_examples_to_png(engine, syntax_module): for filename in iter_examples_filenames(syntax_module): if engine == "vl-convert" and vlc is None: pytest.skip("vl_convert not importable; cannot run mimebundle tests") - elif engine == "altair_saver": - if altair_saver is None: - pytest.skip("altair_saver not importable; cannot run png tests") - if "png" not in altair_saver.available_formats("vega-lite"): - pytest.skip("altair_saver not configured to save to png") source = pkgutil.get_data(syntax_module.__name__, filename) chart = eval_block(source) diff --git a/tests/test_jupyter_chart.py b/tests/test_jupyter_chart.py index d6d7815a3..ba23f5cf0 100644 --- a/tests/test_jupyter_chart.py +++ b/tests/test_jupyter_chart.py @@ -1,13 +1,22 @@ import altair as alt -from altair.jupyter.jupyter_chart import ( - IntervalSelection, - IndexSelection, - PointSelection, -) from vega_datasets import data import pandas as pd import pytest +# If anywidget is not installed, we will skip the tests in this file. +try: + import anywidget # noqa: F401 + + has_anywidget = True +except ImportError: + has_anywidget = False + +if has_anywidget: + from altair.jupyter import jupyter_chart +else: + jupyter_chart = None # type: ignore + + try: import vegafusion # type: ignore # noqa: F401 @@ -18,6 +27,9 @@ @pytest.mark.parametrize("transformer", transformers) def test_chart_with_no_interactivity(transformer): + if not has_anywidget: + pytest.skip("anywidget not importable; skipping test") + with alt.data_transformers.enable(transformer): source = pd.DataFrame( { @@ -44,6 +56,9 @@ def test_chart_with_no_interactivity(transformer): @pytest.mark.parametrize("transformer", transformers) def test_interval_selection_example(transformer): + if not has_anywidget: + pytest.skip("anywidget not importable; skipping test") + with alt.data_transformers.enable(transformer): source = data.cars() brush = alt.selection_interval(name="interval") @@ -73,7 +88,7 @@ def test_interval_selection_example(transformer): # Check initial interval selection selection = widget.selections.interval - assert isinstance(selection, IntervalSelection) + assert isinstance(selection, jupyter_chart.IntervalSelection) assert selection.value == {} assert selection.store == [] @@ -102,7 +117,7 @@ def test_interval_selection_example(transformer): } selection = widget.selections.interval - assert isinstance(selection, IntervalSelection) + assert isinstance(selection, jupyter_chart.IntervalSelection) assert selection.value == { "Horsepower": [40.0, 100], "Miles_per_Gallon": [25, 30], @@ -112,6 +127,9 @@ def test_interval_selection_example(transformer): @pytest.mark.parametrize("transformer", transformers) def test_index_selection_example(transformer): + if not has_anywidget: + pytest.skip("anywidget not importable; skipping test") + with alt.data_transformers.enable(transformer): source = data.cars() brush = alt.selection_point(name="index") @@ -141,7 +159,7 @@ def test_index_selection_example(transformer): # Check initial interval selection selection = widget.selections.index - assert isinstance(selection, IndexSelection) + assert isinstance(selection, jupyter_chart.IndexSelection) assert selection.value == [] assert selection.store == [] @@ -165,13 +183,16 @@ def test_index_selection_example(transformer): } selection = widget.selections.index - assert isinstance(selection, IndexSelection) + assert isinstance(selection, jupyter_chart.IndexSelection) assert selection.value == [219, 329, 340] assert selection.store == store @pytest.mark.parametrize("transformer", transformers) def test_point_selection(transformer): + if not has_anywidget: + pytest.skip("anywidget not importable; skipping test") + with alt.data_transformers.enable(transformer): source = data.cars() brush = alt.selection_point(name="point", encodings=["color"], bind="legend") @@ -201,7 +222,7 @@ def test_point_selection(transformer): # Check initial interval selection selection = widget.selections.point - assert isinstance(selection, PointSelection) + assert isinstance(selection, jupyter_chart.PointSelection) assert selection.value == [] assert selection.store == [] @@ -228,13 +249,16 @@ def test_point_selection(transformer): } selection = widget.selections.point - assert isinstance(selection, PointSelection) + assert isinstance(selection, jupyter_chart.PointSelection) assert selection.value == [{"Cylinders": 4}, {"Cylinders": 5}] assert selection.store == store @pytest.mark.parametrize("transformer", transformers) def test_param_updates(transformer): + if not has_anywidget: + pytest.skip("anywidget not importable; skipping test") + with alt.data_transformers.enable(transformer): source = data.cars() size_param = alt.param( diff --git a/tests/utils/test_compiler.py b/tests/utils/test_compiler.py index 7805dc082..4d161804c 100644 --- a/tests/utils/test_compiler.py +++ b/tests/utils/test_compiler.py @@ -2,6 +2,11 @@ import pytest from altair import vegalite_compilers, Chart +try: + import vl_convert as vlc # noqa: F401 +except ImportError: + vlc = None + @pytest.fixture def chart(): @@ -24,17 +29,26 @@ def assert_is_vega_spec(vega_spec): def test_vegalite_compiler(chart): + if vlc is None: + pytest.skip("vl_convert is not installed") + vegalite_spec = chart.to_dict() vega_spec = vegalite_compilers.get()(vegalite_spec) assert_is_vega_spec(vega_spec) def test_to_dict_with_format_vega(chart): + if vlc is None: + pytest.skip("vl_convert is not installed") + vega_spec = chart.to_dict(format="vega") assert_is_vega_spec(vega_spec) def test_to_json_with_format_vega(chart): + if vlc is None: + pytest.skip("vl_convert is not installed") + json_spec = chart.to_json(format="vega") assert isinstance(json_spec, str) spec = json.loads(json_spec) diff --git a/tests/utils/test_mimebundle.py b/tests/utils/test_mimebundle.py index 97c353c56..6e2965647 100644 --- a/tests/utils/test_mimebundle.py +++ b/tests/utils/test_mimebundle.py @@ -4,11 +4,6 @@ from altair import VEGA_VERSION from altair.utils.mimebundle import spec_to_mimebundle -try: - import altair_saver # noqa: F401 -except ImportError: - altair_saver = None - try: import vl_convert as vlc # noqa: F401 except ImportError: @@ -173,18 +168,9 @@ def vega_spec(): } -@pytest.mark.save_engine -@pytest.mark.parametrize("engine", ["vl-convert", "altair_saver", None]) -def test_vegalite_to_vega_mimebundle(engine, vegalite_spec, vega_spec): - if engine == "vl-convert" and vlc is None: +def test_vegalite_to_vega_mimebundle(vegalite_spec, vega_spec): + if vlc is None: pytest.skip("vl_convert not importable; cannot run mimebundle tests") - elif engine == "altair_saver" and altair_saver is None: - pytest.skip("altair_saver not importable; cannot run mimebundle tests") - elif vlc is None and altair_saver is None: - pytest.skip( - "Neither altair_saver nor vl_convert are importable;" - + " cannot run mimebundle tests" - ) bundle = spec_to_mimebundle( spec=vegalite_spec, @@ -193,7 +179,7 @@ def test_vegalite_to_vega_mimebundle(engine, vegalite_spec, vega_spec): vega_version=alt.VEGA_VERSION, vegalite_version=alt.VEGALITE_VERSION, vegaembed_version=alt.VEGAEMBED_VERSION, - engine=engine, + engine="vl-convert", ) assert bundle == {"application/vnd.vega.v5+json": vega_spec} diff --git a/tests/vegalite/v5/test_api.py b/tests/vegalite/v5/test_api.py index 5b2922021..bda7dd9bb 100644 --- a/tests/vegalite/v5/test_api.py +++ b/tests/vegalite/v5/test_api.py @@ -13,11 +13,6 @@ import altair.vegalite.v5 as alt -try: - import altair_saver # noqa: F401 -except ImportError: - altair_saver = None - try: import vl_convert as vlc # noqa: F401 except ImportError: @@ -290,9 +285,8 @@ def test_selection_expression(): getattr(selection, magic_attr) -@pytest.mark.save_engine @pytest.mark.parametrize("format", ["html", "json", "png", "svg", "pdf", "bogus"]) -@pytest.mark.parametrize("engine", ["altair_saver", "vl-convert"]) +@pytest.mark.parametrize("engine", ["vl-convert"]) def test_save(format, engine, basic_chart): if format in ["pdf", "png"]: out = io.BytesIO() @@ -302,26 +296,7 @@ def test_save(format, engine, basic_chart): mode = "r" if format in ["svg", "png", "pdf", "bogus"]: - if engine == "altair_saver": - if format == "bogus": - with pytest.raises(ValueError) as err: - basic_chart.save(out, format=format, engine=engine) - assert f"Unsupported format: '{format}'" in str(err.value) - return - elif altair_saver is None: - with pytest.raises(ValueError) as err: - basic_chart.save(out, format=format, engine=engine) - assert "altair_saver" in str(err.value) - return - elif format not in altair_saver.available_formats(): - with pytest.raises(ValueError) as err: - basic_chart.save(out, format=format, engine=engine) - assert f"No enabled saver found that supports format='{format}'" in str( - err.value - ) - return - - elif engine == "vl-convert": + if engine == "vl-convert": if format == "bogus": with pytest.raises(ValueError) as err: basic_chart.save(out, format=format, engine=engine) @@ -361,10 +336,11 @@ def test_save(format, engine, basic_chart): os.remove(fp) -# Only test inline=False as altair_viewer is required for inline=True -# but that package has not yet been released with support for Altair 5 -@pytest.mark.parametrize("inline", [False]) +@pytest.mark.parametrize("inline", [False, True]) def test_save_html(basic_chart, inline): + if vlc is None: + pytest.skip("vl_convert not importable; cannot run this test") + out = io.StringIO() basic_chart.save(out, format="html", inline=inline) out.seek(0) @@ -381,6 +357,9 @@ def test_save_html(basic_chart, inline): def test_to_url(basic_chart): + if vlc is None: + pytest.skip("vl_convert is not installed") + share_url = basic_chart.to_url() expected_vegalite_encoding = "N4Igxg9gdgZglgcxALlANzgUwO4tJKAFzigFcJSBnAdTgBNCALFAZgAY2AacaYsiygAlMiRoVYcAvpO50AhoTl4QUOQFtMKEPMUBaAOwA2ABwAWFi1NyTcgEb7TtuabAswc-XTZhMczLdNDAEYQGRA1OQAnAGtlQgBPAAdNZBAnSNDuTChIOhIkVBAAD2V4TAAbOi0lbgTkrSgINRI5csyQeNKsSq1bEFqklJAAR1I5IjhFYjRNaW4AEkowRkwIrTFCRMpkAHodmYQ5ADoEScZSWyO4CB2llYj9zEPdcsnMfYBWI6D9I7YjgBWlGg-W0CjklEwhEoyh0cgMJnMlmsxjsDicLjcHi8Pj8AWCKAA2qAlKkAIKgvrIABMxhkJK0ACFKSgPh96SBSSAAMIs5DmDlcgAifIAnEFBVoAKJ84wSzgM1IAMT5HxYktSAHE+UFRRqQIJZfp9QBJVXUyQAXWkQA" diff --git a/tests/vegalite/v5/test_renderers.py b/tests/vegalite/v5/test_renderers.py index 7201c41d2..b06706e34 100644 --- a/tests/vegalite/v5/test_renderers.py +++ b/tests/vegalite/v5/test_renderers.py @@ -7,6 +7,18 @@ import altair.vegalite.v5 as alt +try: + import vl_convert as vlc # noqa: F401 +except ImportError: + vlc = None + +try: + import anywidget # noqa: F401 + +except ImportError: + anywidget = None # type: ignore + + @pytest.fixture def chart(): return alt.Chart("data.csv").mark_point() @@ -66,6 +78,9 @@ def test_json_renderer_embed_options(chart, renderer="json"): def test_renderer_with_none_embed_options(chart, renderer="mimetype"): + if vlc is None: + pytest.skip("vl_convert not importable; cannot run this test") + # Check that setting embed_options to None doesn't crash from altair.utils.mimebundle import spec_to_mimebundle @@ -82,6 +97,9 @@ def test_renderer_with_none_embed_options(chart, renderer="mimetype"): def test_jupyter_renderer_mimetype(chart, renderer="jupyter"): """Test that we get the expected widget mimetype when the jupyter renderer is enabled""" + if not anywidget: + pytest.skip("anywidget not importable; skipping test") + with alt.renderers.enable(renderer): assert ( "application/vnd.jupyter.widget-view+json"