From 6022442c6ef3ab12e27759a80e3b0776d70b8cf5 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Wed, 12 Apr 2017 18:20:12 +0100 Subject: [PATCH 01/12] Disabled caching of Renderer parameters on output magic --- holoviews/ipython/magics.py | 96 ++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 43 deletions(-) diff --git a/holoviews/ipython/magics.py b/holoviews/ipython/magics.py index 5cbf9d8311..d967df3099 100644 --- a/holoviews/ipython/magics.py +++ b/holoviews/ipython/magics.py @@ -97,7 +97,6 @@ def get_options(cls, line, options, linemagic): info = (keyword,value)+allowed raise ValueError("Value %r for key %r not between %s and %s" % info) options[keyword] = value - return cls._validate(options, items, linemagic) @classmethod @@ -231,21 +230,28 @@ class OutputMagic(OptionsMagic): 'max-width', 'min-width', 'max-height', 'min-height', 'outline', 'float']}} - defaults = OrderedDict([('backend' , 'matplotlib'), - ('fig' , 'png'), - ('holomap' , 'widgets'), - ('widgets' , 'embed'), - ('fps' , 20), + defaults = OrderedDict([('backend' , None), + ('fig' , None), + ('holomap' , None), + ('widgets' , None), + ('fps' , None), ('max_frames' , 500), ('max_branches', 2), - ('size' , 100), - ('dpi' , 72), + ('size' , None), + ('dpi' , None), ('charwidth' , 80), ('filename' , None), ('info' , False), - ('css' , {})]) + ('css' , None)]) + + # Defines the options the OutputMagic remembers the remainder + # is simply state on the backend specific Renderer + remembered = ['max_frames', 'max_branches', 'charwidth', 'info', 'filename'] + + # Remaining backend specific options renderer options + render_params = ['fig', 'holomap', 'size', 'fps', 'dpi', 'css', 'widget_mode', 'mode'] - options = OrderedDict(defaults.items()) + options = OrderedDict() _backend_options = defaultdict(dict) # Used to disable info output in testing @@ -286,22 +292,23 @@ def info(cls, obj): @classmethod def _generate_docstring(cls): + renderer = Store.renderers[Store.current_backend] intro = ["Magic for setting HoloViews display options.", "Arguments are supplied as a series of keywords in any order:", ''] backend = "backend : The backend used by HoloViews %r" % cls.allowed['backend'] fig = "fig : The static figure format %r" % cls.allowed['fig'] holomap = "holomap : The display type for holomaps %r" % cls.allowed['holomap'] - widgets = "widgets : The widget mode for widgets %r" % cls.allowed['widgets'] + widgets = "widgets : The widget mode for widgets %r" % renderer.widget_mode fps = ("fps : The frames per second for animations (default %r)" - % cls.defaults['widgets']) + % renderer.fps) frames= ("max_frames : The max number of frames rendered (default %r)" % cls.defaults['max_frames']) branches=("max_branches : The max number of Layout branches rendered (default %r)" % cls.defaults['max_branches']) size = ("size : The percentage size of displayed output (default %r)" - % cls.defaults['size']) + % renderer.size) dpi = ("dpi : The rendered dpi of the figure (default %r)" - % cls.defaults['dpi']) + % renderer.dpi) chars = ("charwidth : The max character width for displaying the output magic (default %r)" % cls.defaults['charwidth']) fname = ("filename : The filename of the saved output, if any (default %r)" @@ -338,13 +345,18 @@ def output(self, line, cell=None): return restore_copy = OrderedDict(OutputMagic.options.items()) + prev_backend = Store.current_backend try: - options = OrderedDict(OutputMagic.options.items()) + options = OrderedDict([(k, v) for k, v in OutputMagic.options.items() + if k in self.remembered]) new_options = self.get_options(line, options, cell is None) + if 'backend' not in new_options: + new_options['backend'] = Store.current_backend self._set_render_options(new_options) OutputMagic.options = new_options except Exception as e: - self.update_options(options, {'backend': restore_copy['backend']}) + backend = self.last_backend if 'backend' in new_options else Store.current_backend + self.update_options(options, {'backend': backend}) OutputMagic.options = restore_copy self._set_render_options(restore_copy) print('Error: %s' % str(e)) @@ -353,8 +365,8 @@ def output(self, line, cell=None): if cell is not None: self.shell.run_cell(cell, store_history=STORE_HISTORY) - self.update_options(options, {'backend': restore_copy['backend']}) OutputMagic.options = restore_copy + self.set_backend(prev_backend) self._set_render_options(restore_copy) @@ -369,34 +381,29 @@ def update_options(cls, options, items): renderer = Store.renderers[Store.current_backend] prev_backend += ':%s' % renderer.mode + if 'backend' not in options: + options['backend'] = backend if backend else Store.current_backend + available = backend in Store.renderers.keys() if (not backend) or (not available) or backend == prev_backend: return options - cls._backend_options[prev_backend] = cls.options + cls._backend_options[prev_backend] = {k: v for k, v in cls.options.items() + if k in cls.remembered} - backend_options = cls._backend_options[backend] + backend_options = dict(cls._backend_options[backend]) for p in ['fig', 'holomap']: - opts = list_formats(p, backend) - cls.allowed[p] = opts - cls.defaults[p] = opts[0] - if p not in backend_options: - backend_options[p] = opts[0] + cls.allowed[p] = list_formats(p, backend) backend = backend.split(':')[0] - render_params = ['fig', 'holomap', 'size', 'fps', 'dpi', 'css'] - for p in render_params: - if p in backend_options: - opt = backend_options[p] - cls.defaults[p] = opt - else: - opt = cls.defaults[p] - backend_options[p] = opt - for opt in options: if opt not in backend_options: backend_options[opt] = options[opt] + for opt in cls.remembered: + if opt not in backend_options: + backend_options[opt] = cls.defaults[opt] + cls.set_backend(backend) return backend_options @@ -404,14 +411,13 @@ def update_options(cls, options, items): @classmethod def initialize(cls, backend_list): cls.backend_list = backend_list - backend = cls.options.get('backend', cls.defaults['backend']) + backend = cls.options.get('backend', Store.current_backend) if backend in Store.renderers: - cls.options = dict(cls.defaults) - cls._set_render_options(cls.defaults) + cls.options = dict({k: cls.defaults[k] for k in cls.remembered}) + cls._set_render_options({}) cls.set_backend(backend) else: cls.options['backend'] = None - cls.defaults['backend'] = None cls.set_backend(None) @classmethod @@ -425,13 +431,17 @@ def _set_render_options(cls, options): """ Set options on current Renderer. """ - split = options['backend'].split(':') - backend, mode = split if len(split)==2 else (split[0], 'default') + if 'backend' in options: + split = options['backend'].split(':') + backend, mode = split if len(split)==2 else (split[0], 'default') + options['mode'] = mode + else: + backend = Store.current_backend + if 'widgets' in options: + options['widget_mode'] = options['widgets'] renderer = Store.renderers[backend] - render_params = ['fig', 'holomap', 'size', 'fps', 'dpi', 'css'] - render_options = {k: options[k] for k in render_params} - renderer.set_param(**dict(render_options, widget_mode=options['widgets'], - mode=mode)) + render_options = {k: options[k] for k in cls.render_params if k in options} + renderer.set_param(**render_options) @magics_class From f1fcfeec0310f088015d00b0de625a73bd6654f8 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Wed, 12 Apr 2017 19:29:29 +0100 Subject: [PATCH 02/12] Ensure the first backend supplied to notebook_extension is selected --- holoviews/ipython/__init__.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/holoviews/ipython/__init__.py b/holoviews/ipython/__init__.py index f4dfb03cac..a67c46dcb7 100644 --- a/holoviews/ipython/__init__.py +++ b/holoviews/ipython/__init__.py @@ -146,15 +146,22 @@ class notebook_extension(param.ParameterizedFunction): 'plotly': 'plotly'} def __call__(self, *args, **params): - imports = [(name, b) for name, b in self._backends.items() - if name in args or params.get(name, False)] - if not imports or 'matplotlib' not in Store.renderers: - imports = imports + [('matplotlib', 'mpl')] + # Get requested backends + imports = [(arg, self._backends[arg]) for arg in args + if arg in self._backends] + for p, val in sorted(params.items()): + if p in self._backends: + imports.append((p, self._backends[p])) + if not imports: + imports = [('matplotlib', 'mpl')] args = list(args) + selected_backend = None for backend, imp in imports: try: __import__('holoviews.plotting.%s' % imp) + if selected_backend is None: + selected_backend = backend except ImportError: if backend in args: args.pop(args.index(backend)) @@ -187,7 +194,7 @@ def __call__(self, *args, **params): ip = get_ipython() if ip is None else ip # noqa (get_ipython) param_ext.load_ipython_extension(ip, verbose=False) load_magics(ip) - OutputMagic.initialize(list( self._backends.keys())) + OutputMagic.initialize([backend for backend, _ in imports]) set_display_hooks(ip) notebook_extension._loaded = True @@ -209,11 +216,10 @@ def __call__(self, *args, **params): message = '' if not p.banner else '%s successfully loaded in this cell.' % loaded load_hvjs(logo=p.banner, JS=('holoviews' in resources), message = message) + for r in [r for r in resources if r != 'holoviews']: Store.renderers[r].load_nb(inline=p.inline) - - if resources[-1] != 'holoviews': - get_ipython().magic(u"output backend=%r" % resources[-1]) # noqa (get_ipython)) + Store.current_backend = selected_backend def _get_resources(self, args, params): From 60195c6131d86338af7f87a6ae8f8b7d44e08996 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Wed, 12 Apr 2017 19:51:54 +0100 Subject: [PATCH 03/12] Fixes for OutputMagic allowed handling --- holoviews/ipython/magics.py | 39 +++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/holoviews/ipython/magics.py b/holoviews/ipython/magics.py index d967df3099..8f2b828023 100644 --- a/holoviews/ipython/magics.py +++ b/holoviews/ipython/magics.py @@ -350,15 +350,12 @@ def output(self, line, cell=None): options = OrderedDict([(k, v) for k, v in OutputMagic.options.items() if k in self.remembered]) new_options = self.get_options(line, options, cell is None) - if 'backend' not in new_options: - new_options['backend'] = Store.current_backend - self._set_render_options(new_options) + backend = new_options['backend'] if 'backend' in new_options else prev_backend + self._set_render_options(new_options, backend) OutputMagic.options = new_options except Exception as e: - backend = self.last_backend if 'backend' in new_options else Store.current_backend - self.update_options(options, {'backend': backend}) OutputMagic.options = restore_copy - self._set_render_options(restore_copy) + self._set_render_options(restore_copy, prev_backend) print('Error: %s' % str(e)) print("For help with the %output magic, call %output?\n") return @@ -366,8 +363,7 @@ def output(self, line, cell=None): if cell is not None: self.shell.run_cell(cell, store_history=STORE_HISTORY) OutputMagic.options = restore_copy - self.set_backend(prev_backend) - self._set_render_options(restore_copy) + self._set_render_options(restore_copy, prev_backend) @classmethod @@ -376,25 +372,25 @@ def update_options(cls, options, items): Switch default options and backend if new backend is supplied in items. """ - backend = items.get('backend', '') + backend = items.get('backend', Store.current_backend) prev_backend = Store.current_backend - renderer = Store.renderers[Store.current_backend] + renderer = Store.renderers[prev_backend] prev_backend += ':%s' % renderer.mode if 'backend' not in options: - options['backend'] = backend if backend else Store.current_backend + options['backend'] = backend + + for p in ['fig', 'holomap']: + cls.allowed[p] = list_formats(p, backend) available = backend in Store.renderers.keys() if (not backend) or (not available) or backend == prev_backend: return options + backend_options = dict(cls._backend_options[backend]) cls._backend_options[prev_backend] = {k: v for k, v in cls.options.items() if k in cls.remembered} - backend_options = dict(cls._backend_options[backend]) - for p in ['fig', 'holomap']: - cls.allowed[p] = list_formats(p, backend) - backend = backend.split(':')[0] for opt in options: if opt not in backend_options: @@ -404,7 +400,6 @@ def update_options(cls, options, items): if opt not in backend_options: backend_options[opt] = cls.defaults[opt] - cls.set_backend(backend) return backend_options @@ -414,12 +409,12 @@ def initialize(cls, backend_list): backend = cls.options.get('backend', Store.current_backend) if backend in Store.renderers: cls.options = dict({k: cls.defaults[k] for k in cls.remembered}) - cls._set_render_options({}) - cls.set_backend(backend) + cls._set_render_options({}, backend) else: cls.options['backend'] = None cls.set_backend(None) + @classmethod def set_backend(cls, backend): cls.last_backend = Store.current_backend @@ -427,16 +422,18 @@ def set_backend(cls, backend): @classmethod - def _set_render_options(cls, options): + def _set_render_options(cls, options, backend=None): """ Set options on current Renderer. """ - if 'backend' in options: - split = options['backend'].split(':') + if backend: + split = backend.split(':') backend, mode = split if len(split)==2 else (split[0], 'default') options['mode'] = mode else: backend = Store.current_backend + + cls.set_backend(backend) if 'widgets' in options: options['widget_mode'] = options['widgets'] renderer = Store.renderers[backend] From cf574dcf2afba0ff53c9ba288470f25a84d05c62 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Wed, 12 Apr 2017 20:18:28 +0100 Subject: [PATCH 04/12] Fixed OutputMagic unit tests --- tests/testmagics.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/testmagics.py b/tests/testmagics.py index feef8bc860..ba5346e62e 100644 --- a/tests/testmagics.py +++ b/tests/testmagics.py @@ -95,7 +95,6 @@ def test_cell_opts_norm(self): class TestOutputMagic(ExtensionTestCase): def tearDown(self): - ipython.OutputMagic.options = ipython.OutputMagic.defaults super(TestOutputMagic, self).tearDown() def test_output_svg(self): @@ -126,7 +125,7 @@ def test_output_size(self): def test_output_invalid_size(self): self.line_magic('output', "size=-50") - self.assertEqual(ipython.OutputMagic.options.get('size', None), 100) + self.assertEqual(ipython.OutputMagic.options.get('size', None), None) class TestCompositorMagic(ExtensionTestCase): From 152f7d8942988e35d1e5d49b7ee61450ddb822e9 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Wed, 12 Apr 2017 20:33:20 +0100 Subject: [PATCH 05/12] Defined default dpi on Renderer --- holoviews/plotting/renderer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/holoviews/plotting/renderer.py b/holoviews/plotting/renderer.py index 13cec36302..9fa35d580b 100644 --- a/holoviews/plotting/renderer.py +++ b/holoviews/plotting/renderer.py @@ -84,7 +84,7 @@ class Renderer(Exporter): The full, lowercase name of the rendering backend or third part plotting package used e.g 'matplotlib' or 'cairo'.""") - dpi=param.Integer(None, allow_None=True, doc=""" + dpi=param.Integer(72, doc=""" The render resolution in dpi (dots per inch)""") fig = param.ObjectSelector(default='auto', objects=['auto'], doc=""" From 3fc3a98bba7b05ddefa00829830e3ff74f978baa Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Wed, 12 Apr 2017 20:52:24 +0100 Subject: [PATCH 06/12] Ensure renderer params are restored by OutputMagic --- holoviews/ipython/magics.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/holoviews/ipython/magics.py b/holoviews/ipython/magics.py index 8f2b828023..515b8f2e7b 100644 --- a/holoviews/ipython/magics.py +++ b/holoviews/ipython/magics.py @@ -346,6 +346,9 @@ def output(self, line, cell=None): restore_copy = OrderedDict(OutputMagic.options.items()) prev_backend = Store.current_backend + renderer = Store.renderers[prev_backend] + render_params = [(k, v) for k, v in renderer.get_param_values() + if k in self.render_params] try: options = OrderedDict([(k, v) for k, v in OutputMagic.options.items() if k in self.remembered]) @@ -355,7 +358,7 @@ def output(self, line, cell=None): OutputMagic.options = new_options except Exception as e: OutputMagic.options = restore_copy - self._set_render_options(restore_copy, prev_backend) + self._set_render_options(dict(render_params, **restore_copy), prev_backend) print('Error: %s' % str(e)) print("For help with the %output magic, call %output?\n") return @@ -363,7 +366,7 @@ def output(self, line, cell=None): if cell is not None: self.shell.run_cell(cell, store_history=STORE_HISTORY) OutputMagic.options = restore_copy - self._set_render_options(restore_copy, prev_backend) + self._set_render_options(dict(render_params, **restore_copy), prev_backend) @classmethod From 24822898664d68d11481819d9a18be53eb3ff55c Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Thu, 13 Apr 2017 02:21:24 +0100 Subject: [PATCH 07/12] Moved default dpi definition to MPLRenderer --- holoviews/plotting/mpl/renderer.py | 3 +++ holoviews/plotting/renderer.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/holoviews/plotting/mpl/renderer.py b/holoviews/plotting/mpl/renderer.py index e9f80cd1a8..10728df9bf 100644 --- a/holoviews/plotting/mpl/renderer.py +++ b/holoviews/plotting/mpl/renderer.py @@ -43,6 +43,9 @@ class MPLRenderer(Renderer): backend = param.String('matplotlib', doc="The backend name.") + dpi=param.Integer(72, doc=""" + The render resolution in dpi (dots per inch)""") + fig = param.ObjectSelector(default='auto', objects=['png', 'svg', 'pdf', 'html', None, 'auto'], doc=""" Output render format for static figures. If None, no figure diff --git a/holoviews/plotting/renderer.py b/holoviews/plotting/renderer.py index 9fa35d580b..ad41fddf20 100644 --- a/holoviews/plotting/renderer.py +++ b/holoviews/plotting/renderer.py @@ -84,7 +84,7 @@ class Renderer(Exporter): The full, lowercase name of the rendering backend or third part plotting package used e.g 'matplotlib' or 'cairo'.""") - dpi=param.Integer(72, doc=""" + dpi=param.Integer(None, doc=""" The render resolution in dpi (dots per inch)""") fig = param.ObjectSelector(default='auto', objects=['auto'], doc=""" From 5e7df5536fbdeb6f09039817707f6c8b423d089b Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Thu, 13 Apr 2017 02:29:35 +0100 Subject: [PATCH 08/12] Small fix to comment in OutputMagic --- holoviews/ipython/magics.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/holoviews/ipython/magics.py b/holoviews/ipython/magics.py index 515b8f2e7b..f27c300bd1 100644 --- a/holoviews/ipython/magics.py +++ b/holoviews/ipython/magics.py @@ -244,8 +244,8 @@ class OutputMagic(OptionsMagic): ('info' , False), ('css' , None)]) - # Defines the options the OutputMagic remembers the remainder - # is simply state on the backend specific Renderer + # Defines the options the OutputMagic remembers. All other options + # are held by the backend specific Renderer. remembered = ['max_frames', 'max_branches', 'charwidth', 'info', 'filename'] # Remaining backend specific options renderer options From aa3d88b7cdc2a7e0925e4d4cc9185e424a673376 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Thu, 13 Apr 2017 13:37:31 +0100 Subject: [PATCH 09/12] Completely revised OutputMagic logic --- holoviews/ipython/magics.py | 83 +++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 27 deletions(-) diff --git a/holoviews/ipython/magics.py b/holoviews/ipython/magics.py index f27c300bd1..2453ae5b2d 100644 --- a/holoviews/ipython/magics.py +++ b/holoviews/ipython/magics.py @@ -344,29 +344,48 @@ def output(self, line, cell=None): print("\nFor help with the %output magic, call %output?") return - restore_copy = OrderedDict(OutputMagic.options.items()) + # Make backup of previous options prev_backend = Store.current_backend - renderer = Store.renderers[prev_backend] - render_params = [(k, v) for k, v in renderer.get_param_values() - if k in self.render_params] + prev_renderer = Store.renderers[prev_backend] + prev_mode = prev_renderer.mode + prev_params = {k: v for k, v in prev_renderer.get_param_values() + if k in self.render_params} + prev_restore = dict(OutputMagic.options) try: - options = OrderedDict([(k, v) for k, v in OutputMagic.options.items() - if k in self.remembered]) - new_options = self.get_options(line, options, cell is None) - backend = new_options['backend'] if 'backend' in new_options else prev_backend - self._set_render_options(new_options, backend) + # Process magic + new_options = self.get_options(line, {}, cell is None) + + # Make backup of options on selected renderer + if 'backend' in new_options: + backend = new_options['backend'] + if ':' not in backend: + backend += ':default' + else: + backend = prev_backend+':'+prev_mode + renderer = Store.renderers[backend.split(':')[0]] + render_params = {k: v for k, v in renderer.get_param_values() + if k in self.render_params} + + # Set options on selected renderer and set display hook options OutputMagic.options = new_options + self._set_render_options(new_options, backend) except Exception as e: - OutputMagic.options = restore_copy - self._set_render_options(dict(render_params, **restore_copy), prev_backend) + # If setting options failed ensure they are reset + OutputMagic.options = prev_restore + self.set_backend(prev_backend) print('Error: %s' % str(e)) print("For help with the %output magic, call %output?\n") return if cell is not None: self.shell.run_cell(cell, store_history=STORE_HISTORY) - OutputMagic.options = restore_copy - self._set_render_options(dict(render_params, **restore_copy), prev_backend) + # After cell magic restore previous options and restore + # temporarily selected renderer + OutputMagic.options = prev_restore + self._set_render_options(render_params, backend) + if backend.split(':')[0] != prev_backend: + self.set_backend(prev_backend) + self._set_render_options(prev_params, prev_backend+':'+prev_mode) @classmethod @@ -375,34 +394,46 @@ def update_options(cls, options, items): Switch default options and backend if new backend is supplied in items. """ - backend = items.get('backend', Store.current_backend) + # Get previous backend prev_backend = Store.current_backend renderer = Store.renderers[prev_backend] prev_backend += ':%s' % renderer.mode - if 'backend' not in options: - options['backend'] = backend + # Get new backend + backend = items.get('backend', Store.current_backend) + split = backend.split(':') + core_backend, mode = split if len(split)==2 else (split[0], 'default') + if ':' not in backend: + backend += ':default' + # Update allowed formats for p in ['fig', 'holomap']: cls.allowed[p] = list_formats(p, backend) - available = backend in Store.renderers.keys() - if (not backend) or (not available) or backend == prev_backend: + # Return if backend invalid and let validation error + if core_backend not in Store.renderers: + options['backend'] = core_backend return options + # Get backend specific options backend_options = dict(cls._backend_options[backend]) cls._backend_options[prev_backend] = {k: v for k, v in cls.options.items() if k in cls.remembered} - backend = backend.split(':')[0] - for opt in options: - if opt not in backend_options: - backend_options[opt] = options[opt] - + # Fill in remembered options with defaults for opt in cls.remembered: if opt not in backend_options: backend_options[opt] = cls.defaults[opt] + # Switch format if mode does not allow it + for p in ['fig', 'holomap']: + if backend_options.get(p) not in cls.allowed[p]: + backend_options[p] = cls.allowed[p][0] + + # Ensure backend and mode are set + backend_options['mode'] = mode + backend_options['backend'] = backend + return backend_options @@ -412,7 +443,7 @@ def initialize(cls, backend_list): backend = cls.options.get('backend', Store.current_backend) if backend in Store.renderers: cls.options = dict({k: cls.defaults[k] for k in cls.remembered}) - cls._set_render_options({}, backend) + cls.set_backend(backend) else: cls.options['backend'] = None cls.set_backend(None) @@ -430,9 +461,7 @@ def _set_render_options(cls, options, backend=None): Set options on current Renderer. """ if backend: - split = backend.split(':') - backend, mode = split if len(split)==2 else (split[0], 'default') - options['mode'] = mode + backend = backend.split(':')[0] else: backend = Store.current_backend From 9f4a82e98ef0280669c1b7ca616e6a414f1db78d Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Thu, 13 Apr 2017 18:13:22 +0100 Subject: [PATCH 10/12] Ensure notebook_extension displays baseclass Renderer assets --- holoviews/plotting/renderer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/holoviews/plotting/renderer.py b/holoviews/plotting/renderer.py index ad41fddf20..e78dba8d98 100644 --- a/holoviews/plotting/renderer.py +++ b/holoviews/plotting/renderer.py @@ -387,7 +387,7 @@ def html_assets(cls, core=True, extras=True, backends=None): backends = [cls.backend] if cls.backend else [] # Get all the widgets and find the set of required js widget files - widgets = [wdgt for r in Renderer.__subclasses__() + widgets = [wdgt for r in [Renderer]+Renderer.__subclasses__() for wdgt in r.widgets.values()] css = list({wdgt.css for wdgt in widgets}) basejs = list({wdgt.basejs for wdgt in widgets}) From bfdd81ac8bd7f6f846f3d448abc50fcc1a102572 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Thu, 13 Apr 2017 18:14:57 +0100 Subject: [PATCH 11/12] Small fix for notebook_extension backend loading --- holoviews/ipython/__init__.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/holoviews/ipython/__init__.py b/holoviews/ipython/__init__.py index a67c46dcb7..f33f9c2b32 100644 --- a/holoviews/ipython/__init__.py +++ b/holoviews/ipython/__init__.py @@ -206,6 +206,11 @@ def __call__(self, *args, **params): if css: display(HTML(css)) + for r in [r for r in resources if r != 'holoviews']: + Store.renderers[r].load_nb(inline=p.inline) + if selected_backend is not None: + Store.current_backend = selected_backend + resources = list(resources) if len(resources) == 0: return @@ -217,9 +222,6 @@ def __call__(self, *args, **params): message = '' if not p.banner else '%s successfully loaded in this cell.' % loaded load_hvjs(logo=p.banner, JS=('holoviews' in resources), message = message) - for r in [r for r in resources if r != 'holoviews']: - Store.renderers[r].load_nb(inline=p.inline) - Store.current_backend = selected_backend def _get_resources(self, args, params): From e4031b4ab2c7f975ed64503a369b755a0ab96915 Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Thu, 13 Apr 2017 18:15:37 +0100 Subject: [PATCH 12/12] Improved naming of variables in OutputMagic --- holoviews/ipython/magics.py | 50 ++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/holoviews/ipython/magics.py b/holoviews/ipython/magics.py index 2453ae5b2d..9af6d22537 100644 --- a/holoviews/ipython/magics.py +++ b/holoviews/ipython/magics.py @@ -347,7 +347,7 @@ def output(self, line, cell=None): # Make backup of previous options prev_backend = Store.current_backend prev_renderer = Store.renderers[prev_backend] - prev_mode = prev_renderer.mode + prev_backend_spec = prev_backend+':'+prev_renderer.mode prev_params = {k: v for k, v in prev_renderer.get_param_values() if k in self.render_params} prev_restore = dict(OutputMagic.options) @@ -357,18 +357,18 @@ def output(self, line, cell=None): # Make backup of options on selected renderer if 'backend' in new_options: - backend = new_options['backend'] - if ':' not in backend: - backend += ':default' + backend_spec = new_options['backend'] + if ':' not in backend_spec: + backend_spec += ':default' else: - backend = prev_backend+':'+prev_mode - renderer = Store.renderers[backend.split(':')[0]] + backend_spec = prev_backend_spec + renderer = Store.renderers[backend_spec.split(':')[0]] render_params = {k: v for k, v in renderer.get_param_values() if k in self.render_params} # Set options on selected renderer and set display hook options OutputMagic.options = new_options - self._set_render_options(new_options, backend) + self._set_render_options(new_options, backend_spec) except Exception as e: # If setting options failed ensure they are reset OutputMagic.options = prev_restore @@ -382,10 +382,10 @@ def output(self, line, cell=None): # After cell magic restore previous options and restore # temporarily selected renderer OutputMagic.options = prev_restore - self._set_render_options(render_params, backend) - if backend.split(':')[0] != prev_backend: + self._set_render_options(render_params, backend_spec) + if backend_spec.split(':')[0] != prev_backend: self.set_backend(prev_backend) - self._set_render_options(prev_params, prev_backend+':'+prev_mode) + self._set_render_options(prev_params, prev_backend_spec) @classmethod @@ -394,31 +394,31 @@ def update_options(cls, options, items): Switch default options and backend if new backend is supplied in items. """ + # Get new backend + backend_spec = items.get('backend', Store.current_backend) + split = backend_spec.split(':') + backend, mode = split if len(split)==2 else (split[0], 'default') + if ':' not in backend_spec: + backend_spec += ':default' + # Get previous backend prev_backend = Store.current_backend renderer = Store.renderers[prev_backend] - prev_backend += ':%s' % renderer.mode - - # Get new backend - backend = items.get('backend', Store.current_backend) - split = backend.split(':') - core_backend, mode = split if len(split)==2 else (split[0], 'default') - if ':' not in backend: - backend += ':default' + prev_backend_spec = prev_backend+':'+renderer.mode # Update allowed formats for p in ['fig', 'holomap']: - cls.allowed[p] = list_formats(p, backend) + cls.allowed[p] = list_formats(p, backend_spec) # Return if backend invalid and let validation error - if core_backend not in Store.renderers: - options['backend'] = core_backend + if backend not in Store.renderers: + options['backend'] = backend_spec return options # Get backend specific options - backend_options = dict(cls._backend_options[backend]) - cls._backend_options[prev_backend] = {k: v for k, v in cls.options.items() - if k in cls.remembered} + backend_options = dict(cls._backend_options[backend_spec]) + cls._backend_options[prev_backend_spec] = {k: v for k, v in cls.options.items() + if k in cls.remembered} # Fill in remembered options with defaults for opt in cls.remembered: @@ -431,8 +431,8 @@ def update_options(cls, options, items): backend_options[p] = cls.allowed[p][0] # Ensure backend and mode are set + backend_options['backend'] = backend_spec backend_options['mode'] = mode - backend_options['backend'] = backend return backend_options