From 2e132b249182dd90ec0d60b253b41c18a1a10bca Mon Sep 17 00:00:00 2001 From: Stefan Binder Date: Thu, 25 May 2023 17:09:25 +0000 Subject: [PATCH 1/2] Fix for when subcharts do not have layer_props --- altair/vegalite/v5/api.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/altair/vegalite/v5/api.py b/altair/vegalite/v5/api.py index e9aa439cb..ed449bcab 100644 --- a/altair/vegalite/v5/api.py +++ b/altair/vegalite/v5/api.py @@ -3395,9 +3395,12 @@ def remove_prop(subchart, prop): else: raise ValueError(f"There are inconsistent values {values} for {prop}") else: - # Top level has this prop; subchart props must be either - # Undefined or identical to proceed. - if all(c[prop] is Undefined or c[prop] == chart[prop] for c in subcharts): + # Top level has this prop; subchart must either not have the prop + # or it must be Undefined or identical to proceed. + if all( + getattr(c, prop, Undefined) is Undefined or c[prop] == chart[prop] + for c in subcharts + ): output_dict[prop] = chart[prop] else: raise ValueError(f"There are inconsistent values {values} for {prop}") From 6888498917343dccfafa2d644d598b9b5b9d16d5 Mon Sep 17 00:00:00 2001 From: Stefan Binder Date: Thu, 25 May 2023 17:19:40 +0000 Subject: [PATCH 2/2] Test the to_json and from_json methods using all examples in the gallery --- tests/test_examples.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/test_examples.py b/tests/test_examples.py index 578f38303..da5808067 100644 --- a/tests/test_examples.py +++ b/tests/test_examples.py @@ -3,6 +3,7 @@ import pytest +import altair as alt from altair.utils.execeval import eval_block from tests import examples_arguments_syntax from tests import examples_methods_syntax @@ -48,6 +49,39 @@ def test_render_examples_to_chart(syntax_module): ) from err +@pytest.mark.parametrize( + "syntax_module", [examples_arguments_syntax, examples_methods_syntax] +) +def test_from_and_to_json_roundtrip(syntax_module): + """Tests if the to_json and from_json (and by extension to_dict and from_dict) + work for all examples in the Example Gallery. + """ + for filename in iter_examples_filenames(syntax_module): + source = pkgutil.get_data(syntax_module.__name__, filename) + chart = eval_block(source) + + if chart is None: + raise ValueError( + f"Example file {filename} should define chart in its final " + "statement." + ) + + try: + first_json = chart.to_json() + reconstructed_chart = alt.Chart.from_json(first_json) + # As the chart objects are not + # necessarily the same - they could use different objects to encode the same + # information - we do not test for equality of the chart objects, but rather + # for equality of the json strings. + second_json = reconstructed_chart.to_json() + assert first_json == second_json + except Exception as err: + raise AssertionError( + f"Example file {filename} raised an exception when " + f"doing a json conversion roundtrip: {err}" + ) 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