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

Parser fixes #948

Merged
merged 4 commits into from
Oct 27, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
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
20 changes: 18 additions & 2 deletions holoviews/ipython/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,19 @@ def _strip_commas(cls, kw):
kw = kw[:-1] if kw[-1]==',' else kw
return kw[1:] if kw[0]==',' else kw

@classmethod
def recurse_token(cls, token, inner):
recursed = []
for tok in token:
if isinstance(tok, list):
new_tok = [s for t in tok for s in
(cls.recurse_token(t, inner)
if isinstance(t, list) else [t])]
recursed.append((inner % ''.join(new_tok)))
else:
recursed.append(tok)
return inner % ''.join(recursed)

@classmethod
def collect_tokens(cls, parseresult, mode):
"""
Expand All @@ -53,7 +66,8 @@ def collect_tokens(cls, parseresult, mode):
for token in parseresult.asList():
# If value is a tuple, the token will be a list
if isinstance(token, list):
tokens[-1] = tokens[-1] + (inner % ''.join(token))
token = cls.recurse_token(token, inner)
tokens[-1] = tokens[-1] + token
else:
if token.strip() == ',': continue
tokens.append(cls._strip_commas(token))
Expand Down Expand Up @@ -86,7 +100,9 @@ def todict(cls, parseresult, mode='parens', ns={}):
for keyword in grouped:
# Tuple ('a', 3) becomes (,'a',3) and '(,' is never valid
# Same for some of the other joining errors corrected here
for (fst,snd) in [('(,', '('), ('{,', '{'), ('=,','='), (',:',':')]:
for (fst,snd) in [('(,', '('), ('{,', '{'), ('=,','='),
(',:',':'), (':,', ':'), (',,', ','),
(',.', '.')]:
keyword = keyword.replace(fst, snd)
try:
kwargs.update(eval('dict(%s)' % keyword,
Expand Down
46 changes: 46 additions & 0 deletions tests/testparsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,20 @@ def test_plot_opts_with_space_explicit(self):
Options(title_format='foo bar', fig_inches=(3, 3))}}
self.assertEqual(OptsSpec.parse(line), expected)

def test_plot_opts_dict_with_space(self):
line = "Curve [fontsize={'xlabel': 10, 'title': 20}]"
expected = {'Curve': {'plot': Options(fontsize={'xlabel': 10, 'title': 20})}}
self.assertEqual(OptsSpec.parse(line), expected)

def test_plot_opts_dict_without_space(self):
line = "Curve [fontsize=dict(xlabel=10,title=20)]"
expected = {'Curve': {'plot': Options(fontsize={'xlabel': 10, 'title': 20})}}
self.assertEqual(OptsSpec.parse(line), expected)

def test_plot_opts_nested_brackets(self):
line = "Curve [title_format=', '.join(('A', 'B'))]"
expected = {'Curve': {'plot': Options(title_format='A, B')}}
self.assertEqual(OptsSpec.parse(line), expected)


class OptsSpecStyleOptionsTests(ComparisonTestCase):
Expand Down Expand Up @@ -90,6 +104,38 @@ def test_style_opts_advanced(self):
color=Cycle(values=[1,2]))}}
self.assertEqual(OptsSpec.parse(line), expected)

def test_style_opts_dict_with_space(self):
line = "Curve (fontsize={'xlabel': 10, 'title': 20})"
expected = {'Curve': {'style': Options(fontsize={'xlabel': 10, 'title': 20})}}
self.assertEqual(OptsSpec.parse(line), expected)

def test_style_opts_dict_without_space(self):
line = "Curve (fontsize={'xlabel': 10,'title': 20})"
expected = {'Curve': {'style': Options(fontsize={'xlabel': 10, 'title': 20})}}
self.assertEqual(OptsSpec.parse(line), expected)

def test_style_opts_cycle_function(self):
# Explicitly compare because list of arrays do not compare correctly
import numpy as np
np.random.seed(42)
line = "Curve (color=Cycle(values=list(np.random.rand(3,3))))"
options = OptsSpec.parse(line, {'np': np, 'Cycle': Cycle})
self.assertTrue('Curve' in options)
self.assertTrue('style' in options['Curve'])
self.assertTrue('color' in options['Curve']['style'].kwargs)
self.assertTrue(isinstance(options['Curve']['style'].kwargs['color'], Cycle))
values = np.array([[ 0.37454012, 0.95071431, 0.73199394],
[ 0.59865848, 0.15601864, 0.15599452],
[ 0.05808361, 0.86617615, 0.60111501]])
expected = {'Curve': {'style': Options(color=Cycle(values=list(values)))}}
self.assertEqual(np.array(options['Curve']['style'].kwargs['color'].values),
values)

def test_style_opts_cycle_list(self):
line = "Curve (color=Cycle(values=['r', 'g', 'b']))"
expected = {'Curve': {'style': Options(color=Cycle(values=['r', 'g', 'b']))}}
self.assertEqual(OptsSpec.parse(line, {'Cycle': Cycle}), expected)



class OptsNormPlotOptionsTests(ComparisonTestCase):
Expand Down