diff --git a/python-package/lets_plot/plot/core.py b/python-package/lets_plot/plot/core.py index bbba48055ff..9cbfcde5527 100644 --- a/python-package/lets_plot/plot/core.py +++ b/python-package/lets_plot/plot/core.py @@ -130,6 +130,10 @@ def layer(geom=None, stat=None, data=None, mapping=None, position=None, **kwargs return LayerSpec(**locals()) +def _filter_none(original: dict) -> dict: + return {k: v for k, v in original.items() if v is not None} + + # # ----------------------------------- # Specs @@ -145,7 +149,7 @@ def _specs_to_dict(opts_raw): else: opts[k] = v - return opts + return _filter_none(opts) class FeatureSpec(): diff --git a/python-package/lets_plot/plot/tooltip.py b/python-package/lets_plot/plot/tooltip.py index 55bc9ebf131..d023018b507 100644 --- a/python-package/lets_plot/plot/tooltip.py +++ b/python-package/lets_plot/plot/tooltip.py @@ -2,9 +2,10 @@ # Copyright (c) 2020. JetBrains s.r.o. # Use of this source code is governed by the MIT license that can be found in the LICENSE file. -from .core import FeatureSpec from typing import List +from lets_plot.plot.core import FeatureSpec, _filter_none + # # Tooltips # @@ -115,7 +116,7 @@ def as_dict(self): d['tooltip_min_width'] = self._tooltip_min_width d['tooltip_color'] = self._tooltip_color d['tooltip_variables'] = self._tooltip_variables - return d + return _filter_none(d) def format(self, field=None, format=None): """ diff --git a/python-package/test/plot/test_aes.py b/python-package/test/plot/test_aes.py index 10aa435b5c6..f234a718e70 100644 --- a/python-package/test/plot/test_aes.py +++ b/python-package/test/plot/test_aes.py @@ -8,7 +8,7 @@ class TestWithListArgs: - result_empty = {'x': None, 'y': None} + result_empty = {} result_xy = {'x': 'xVar', 'y': 'yVar'} @pytest.mark.parametrize('args,expected', [ diff --git a/python-package/test/plot/test_assembly.py b/python-package/test/plot/test_assembly.py index 2efa857abcc..93356b381bc 100644 --- a/python-package/test/plot/test_assembly.py +++ b/python-package/test/plot/test_assembly.py @@ -17,14 +17,14 @@ def test_plot_geom_geom(): expect = { 'kind': 'plot', - 'data': None, + 'mapping': {}, 'data_meta': {}, - 'mapping': {'x': None, 'y': None}, 'layers': [ geom1.as_dict(), geom2.as_dict() ], - 'scales': []} + 'scales': [] + } assert (plot + geom1 + geom2).as_dict() == expect assert (plot + (geom1 + geom2)).as_dict() == expect @@ -38,15 +38,11 @@ def test_plot_geom_scale(): expect = { 'kind': 'plot', - 'data': None, + 'mapping': {}, 'data_meta': {}, - 'mapping': {'x': None, 'y': None}, - 'layers': [ - geom.as_dict() - ], - 'scales': [ - scale.as_dict() - ]} + 'layers': [geom.as_dict()], + 'scales': [scale.as_dict()] + } assert (plot + geom + scale).as_dict() == expect assert (plot + scale + geom).as_dict() == expect @@ -58,13 +54,12 @@ def test_plot_ggtitle(): ggtitle = gg.labs(title="New plot title") expect = { + 'ggtitle': {'text': 'New plot title'}, 'kind': 'plot', - 'data': None, - 'mapping': {'x': None, 'y': None}, 'data_meta': {}, 'layers': [], - 'scales': [], - 'ggtitle': {'text': 'New plot title'} + 'mapping': {}, + 'scales': [] } assert (plot + ggtitle).as_dict() == expect diff --git a/python-package/test/plot/test_geom.py b/python-package/test/plot/test_geom.py index 2176fa60b9b..f9f385bdd06 100644 --- a/python-package/test/plot/test_geom.py +++ b/python-package/test/plot/test_geom.py @@ -16,27 +16,15 @@ class TestWithListAndDictArgs: mapping_arg = gg.aes('X') expected[0] = dict( geom='n', - mapping=mapping_arg.as_dict(), - data=None, - stat=None, - position=None, - show_legend=None, - sampling=None, - tooltips=None, - data_meta= {}, + data_meta={}, + mapping=mapping_arg.as_dict() ) # II expected[1] = dict( geom='n', - mapping={'x': None, 'y': None}, - data=None, - stat=None, - position=None, - show_legend=None, - sampling=None, - tooltips=None, - data_meta= {}, + mapping={}, + data_meta={}, arrow={'angle': 0, 'length': 1, 'ends': 'a', 'type': 'b', 'name': 'arrow'} ) diff --git a/python-package/test/plot/test_geom_image.py b/python-package/test/plot/test_geom_image.py index 6bcb27253f8..a87183a0dd7 100644 --- a/python-package/test/plot/test_geom_image.py +++ b/python-package/test/plot/test_geom_image.py @@ -12,6 +12,7 @@ def _image_spec(width, height, href): return dict( + data_meta={}, geom='image', # image_spec=dict( # width=width, @@ -20,21 +21,12 @@ def _image_spec(width, height, href): # bytes=bytes # ), href=href, - data=None, mapping=dict( - x=None, - y=None, xmin=[-0.5], ymin=[-0.5], xmax=[width - 1 + 0.5], ymax=[height - 1 + 0.5], - ), - stat=None, - position=None, - show_legend=None, - data_meta={}, - sampling=None, - tooltips=None, + ) ) diff --git a/python-package/test/plot/test_geom_livemap.py b/python-package/test/plot/test_geom_livemap.py new file mode 100644 index 00000000000..19eff4ea040 --- /dev/null +++ b/python-package/test/plot/test_geom_livemap.py @@ -0,0 +1,18 @@ +# Copyright (c) 2021. JetBrains s.r.o. +# Use of this source code is governed by the MIT license that can be found in the LICENSE file. +import pytest + +import lets_plot as gg + + +@pytest.mark.parametrize('args,expected', [ + ('foo', [['foo'], None]), + (['foo'], [['foo'], None]), + (['foo', 'bar'], [['foo'], ['bar']]), + ([['foo', 'bar']], [['foo', 'bar'], None]), + ([['foo', 'bar'], ['baz', 'qux']], [['foo', 'bar'], ['baz', 'qux']]) +]) +def test_map_join(args, expected): + # ggplot is required - it normalizes map_join on before_append + spec = gg.ggplot() + gg.geom_livemap(map_join=args, tooltips=gg.layer_tooltips()) + assert spec.as_dict()['layers'][0]['map_join'] == expected diff --git a/python-package/test/plot/test_ggplot.py b/python-package/test/plot/test_ggplot.py index 51341304386..cf0c7eba0a6 100644 --- a/python-package/test/plot/test_ggplot.py +++ b/python-package/test/plot/test_ggplot.py @@ -6,15 +6,15 @@ import lets_plot as gg -data = [1, 2] +data = {'a': [1, 2], 'b': [3, 4]} mapping_empty = gg.aes() mapping_x = gg.aes('X') -result_empty = {'data': None, 'data_meta': {}, 'mapping': {'x': None, 'y': None}, 'layers': [], 'scales': [], 'kind': 'plot'} -result_data = {'data': data, 'data_meta': {}, 'mapping': {'x': None, 'y': None}, 'layers': [], 'scales': [], 'kind': 'plot'} -result_data_mapping_empty = {'data': data, 'data_meta': {}, 'mapping': mapping_empty.as_dict(), 'layers': [], 'scales': [], 'kind': 'plot'} -result_data_mapping_x = {'data': data, 'data_meta': {}, 'mapping': mapping_x.as_dict(), 'layers': [], 'scales': [], 'kind': 'plot'} -result_mapping_x = {'data': None, 'data_meta': {}, 'mapping': mapping_x.as_dict(), 'layers': [], 'scales': [], 'kind': 'plot'} +result_empty = {'kind': 'plot', 'mapping': {}, 'data_meta': {}, 'layers': [], 'scales': []} +result_data = {'data': data, 'kind': 'plot', 'mapping': {}, 'data_meta': {}, 'layers': [], 'scales': []} +result_data_mapping_empty = {'data': data, 'kind': 'plot', 'mapping': {}, 'data_meta': {}, 'layers': [], 'scales': []} +result_data_mapping_x = {'data': data, 'mapping': {'x': 'X'}, 'data_meta': {}, 'kind': 'plot', 'layers': [], 'scales': []} +result_mapping_x = {'mapping': {'x': 'X'}, 'data_meta': {}, 'kind': 'plot', 'layers': [], 'scales': []} @pytest.mark.parametrize('args,expected', [ diff --git a/python-package/test/plot/test_ggsize.py b/python-package/test/plot/test_ggsize.py index bec2c38f585..b31ce2bda69 100644 --- a/python-package/test/plot/test_ggsize.py +++ b/python-package/test/plot/test_ggsize.py @@ -9,10 +9,4 @@ # noinspection SpellCheckingInspection def test_ggsize(): spec = gg.ggplot() + gg.ggsize(5, 10) - assert spec.as_dict() == {'data': None, - 'data_meta': {}, - 'mapping': {'x': None, 'y': None}, - 'kind': 'plot', - 'ggsize': {'height': 10, 'width': 5}, - 'layers': [], - 'scales': []} + assert spec.as_dict() == {'kind': 'plot', 'ggsize': {'height': 10, 'width': 5}, 'mapping': {}, 'data_meta': {}, 'layers': [], 'scales': []} diff --git a/python-package/test/plot/test_scale.py b/python-package/test/plot/test_scale.py index 5937eb28d19..366f29de513 100644 --- a/python-package/test/plot/test_scale.py +++ b/python-package/test/plot/test_scale.py @@ -13,12 +13,9 @@ def gen_scale_args(): pos_args = ['a', 'n'] # aesthetic pos_args_as_dict = {'aesthetic': 'a', 'name': 'n'} - pos_args_def_as_dict = {'breaks': None, 'labels': None, 'limits': None, 'expand': None, 'na_value': None, - 'guide': None, 'trans': None, 'format': None} other_args = {'other1': 1, 'other2': 2} expected = pos_args_as_dict.copy() - expected.update(pos_args_def_as_dict) expected.update(other_args) return pos_args, other_args, expected diff --git a/python-package/test/plot/test_theme.py b/python-package/test/plot/test_theme.py index d4be977bc1c..05712c9d340 100644 --- a/python-package/test/plot/test_theme.py +++ b/python-package/test/plot/test_theme.py @@ -6,7 +6,7 @@ from lets_plot import element_rect from lets_plot.plot import theme from lets_plot.plot.geom import _geom -from lets_plot.plot.theme_classic_ import theme_classic +from lets_plot.plot.theme_set import theme_classic def test_theme_options_should_be_merged():