Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specs cleanup #477

Merged
merged 4 commits into from
Dec 15, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Specs cleanup
  • Loading branch information
IKupriyanov-HORIS committed Dec 15, 2021
commit bd04ec886c3e70c1629e032573d90b96a5fafe70
67 changes: 36 additions & 31 deletions python-package/lets_plot/plot/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,39 @@ def layer(geom=None, stat=None, data=None, mapping=None, position=None, **kwargs
return LayerSpec(**locals())


def _cleanup(obj):
# Empty corr_plot layer adds geom with default visuals, if remove - no layer will be added at all
keep_if_empty = ['point_params', 'tile_params', 'label_params']

if isinstance(obj, dict):
res = {}
for k, v in obj.items():
if v is None:
continue

if k in ['data', 'map']:
res[k] = v
continue

if isinstance(v, (dict, list)):
clean = _cleanup(v)
if len(clean) > 0 or k in keep_if_empty:
res[k] = clean
else:
res[k] = v
return res

if isinstance(obj, list):
if all(isinstance(item, (dict, type(None))) for item in obj):
return [v for v in map(lambda item: _cleanup(item), obj) if v is not None]

# ignore non-dict list or it may produce unexpected result: [['asd'], [None]] => [['asd'],[]]
return obj

else:
return obj


#
# -----------------------------------
# Specs
Expand All @@ -145,7 +178,7 @@ def _specs_to_dict(opts_raw):
else:
opts[k] = v

return opts
return _cleanup(opts)


class FeatureSpec():
Expand Down Expand Up @@ -387,35 +420,7 @@ def as_dict(self):
d['scales'] = [scale.as_dict() for scale in self.__scales]
d['layers'] = [layer.as_dict() for layer in self.__layers]

# Empty corr_plot layer adds geom with default visuals, if remove - no layer will be added at all
keep_if_empty = ['point_params', 'tile_params', 'label_params']

def cleanup(o):
if isinstance(o, list):
return [cleanup(item) for item in o]

if isinstance(o, dict):
res = {}
for k, v in o.items():
if v is None:
continue

if k == 'data':
res[k] = v
continue

if isinstance(v, (dict, list)):
clean = cleanup(v)
if len(clean) > 0 or k in keep_if_empty:
res[k] = clean
else:
res[k] = v
return res

else:
return o

return cleanup(d)
return _cleanup(d)

def __str__(self):
result = ['plot']
Expand Down Expand Up @@ -556,7 +561,7 @@ def elements(self):

def as_dict(self):
elements = [{e.kind: e.as_dict()} for e in self.__elements]
return {'feature-list': elements}
return _cleanup({'feature-list': elements})

def __add__(self, other):
if isinstance(other, DummySpec):
Expand Down
4 changes: 2 additions & 2 deletions python-package/lets_plot/plot/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from lets_plot._global_settings import has_global_value, get_global_val, MAX_WIDTH, MAX_HEIGHT
from lets_plot.geo_data_internals.utils import is_geocoder
from lets_plot.plot.core import FeatureSpec
from lets_plot.plot.core import FeatureSpec, _cleanup
from lets_plot.plot.core import PlotSpec
from lets_plot.plot.util import as_annotated_data

Expand Down Expand Up @@ -211,7 +211,7 @@ def item_as_dict(item):
return result

d['items'] = [item_as_dict(item) for item in self.items]
return d
return _cleanup(d)

def _repr_html_(self):
"""
Expand Down
5 changes: 3 additions & 2 deletions python-package/lets_plot/plot/tooltip.py
Original file line number Diff line number Diff line change
Expand Up @@ -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, _cleanup

#
# Tooltips
#
Expand Down Expand Up @@ -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 _cleanup(d)

def format(self, field=None, format=None):
"""
Expand Down
2 changes: 1 addition & 1 deletion python-package/test/plot/test_aes.py
Original file line number Diff line number Diff line change
Expand Up @@ -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', [
Expand Down
17 changes: 1 addition & 16 deletions python-package/test/plot/test_geom.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,12 @@ 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= {},
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= {},
arrow={'angle': 0, 'length': 1, 'ends': 'a', 'type': 'b', 'name': 'arrow'}
)

Expand Down
11 changes: 1 addition & 10 deletions python-package/test/plot/test_geom_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,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,
)
)


Expand Down
5 changes: 1 addition & 4 deletions python-package/test/plot/test_scale.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -33,7 +30,7 @@ def test_scale(args_list, args_dict, expected):

def test_labs_empty():
spec = gg.labs()
assert spec.as_dict()['feature-list'] == []
assert len(spec.as_dict()) == 0


def test_plot_title():
Expand Down