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

Magic preprocessors for conversion to vanilla Python #1491

Merged
merged 54 commits into from
Jun 4, 2017
Merged
Show file tree
Hide file tree
Changes from 52 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
3f645bb
Opts magic conversion prototype
jlstevens May 26, 2017
b7264ff
Fix to only apply to cells using %%opts
jlstevens May 27, 2017
eb273c4
Moved opts utility to util
jlstevens May 28, 2017
f02c959
Refactored magic replacement preprocessor
jlstevens May 28, 2017
48dbfe3
Added support for replacing line magics
jlstevens May 28, 2017
86af334
Refactored OutputMagic into OutputControl
jlstevens May 28, 2017
a1bb4e1
Defined hv.util.output helper
jlstevens May 28, 2017
6f6dda3
Improved usability of wrap_cell_expression
jlstevens May 28, 2017
b291d63
Fixed where Store.output_control is set
jlstevens May 28, 2017
5fde8ba
Refactored magics preprocessor into separate classes
jlstevens May 28, 2017
642f8e7
Switched opts utility argument order
jlstevens May 28, 2017
3f3e560
The hv.util.opts utility can now also replace the line magic
jlstevens May 28, 2017
31fe462
OptsMagicProcessor can now convert the %opts line magic
jlstevens May 28, 2017
59750c1
Defined cell magic version of hv.util.output as a no-op
jlstevens May 28, 2017
ca68c67
Renamed OutputControl to OutputOptions
jlstevens May 28, 2017
c39e32a
Temporarily disabled broken output magic tests
jlstevens May 28, 2017
c2b8780
Moved prototype convert script to ipython module
jlstevens May 29, 2017
9eea15f
Set a shell attribute on OutputOptions
jlstevens May 29, 2017
0b5677f
Commented out opts warning to leave display tests alone
jlstevens May 29, 2017
4df77bf
Removed stray print
jlstevens May 29, 2017
421f446
Renamed OptionsControl class to KeywordOptions
jlstevens May 29, 2017
33140ac
Moved option_completer back to the OptionMagic class
jlstevens May 29, 2017
7ffb61c
Made OutputOptions only use classmethods
jlstevens May 29, 2017
071f4e1
Initialized the util module
jlstevens May 29, 2017
9f4a189
Moved parser.py from the ipython module to the util module
jlstevens May 29, 2017
6470d16
Moved OutputOptions class to util.outputoptions
jlstevens May 29, 2017
bd8b5d6
Simplified how OutputOptions runs cells
jlstevens May 29, 2017
9070d2b
Moved info classmethod back to OutputMagic
jlstevens May 29, 2017
9f6d623
Renamed ipython.convert to ipython.preprocessors including Sustitute
jlstevens May 29, 2017
5a34cfc
Added hv.util.command and set it as an entry point
jlstevens May 29, 2017
e7be1e1
Tweaked conversion command
jlstevens May 29, 2017
9280c6d
Added stub examples/README.rst and examples.py
jlstevens May 30, 2017
27915d5
Added preliminary opts spec syntax support to __call__
jlstevens Jun 1, 2017
20481c4
Removed use of HTML display in OutputOptions
jlstevens Jun 1, 2017
26e08d0
Renamed options relating to output to settings
jlstevens Jun 1, 2017
a258e8d
Fixed how output settings are initialized
jlstevens Jun 1, 2017
a731085
Moved pprint method back to OutputMagic
jlstevens Jun 1, 2017
cb2926b
Number of simplifications and improvements to OutputSettings
jlstevens Jun 2, 2017
d390228
Generating simplified docstring for OutputSettings
jlstevens Jun 2, 2017
7d920dc
Updated argument order in OutputMagicProcessor
jlstevens Jun 3, 2017
c71b009
Fixed setting of OutputMagic docstring for Python 3
jlstevens Jun 3, 2017
b2b86df
Restored TestOutputMagic unit tests
jlstevens Jun 3, 2017
746db40
Removed warning when using __call__
jlstevens Jun 3, 2017
29ce705
Renamed testutils.py to testcoreutils.py
jlstevens Jun 3, 2017
33589d6
Added 4 unit tests of the hv.util.output utility
jlstevens Jun 3, 2017
d60f78d
Added extra hv.util.output unit test and four tests for hv.util.opts
jlstevens Jun 3, 2017
9b4e250
Mirrored settings reset in setUp
jlstevens Jun 3, 2017
c9009f4
Updated TestOptsUtil tests
jlstevens Jun 3, 2017
98eecbb
Updated options reset for opts utility tests
jlstevens Jun 3, 2017
9cfbfe0
Removed Conversion_Example notebook used to test prototype
jlstevens Jun 3, 2017
d4054fb
Added unit tests of the notebook preprocessors
jlstevens Jun 3, 2017
80ad114
Added docstrings to new Preprocessor classes
jlstevens Jun 4, 2017
f5f12c2
Removed unnecessary import
jlstevens Jun 4, 2017
a325041
Opts method now only catches SyntaxError when parsing
jlstevens Jun 4, 2017
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
2 changes: 1 addition & 1 deletion doc/Tutorials/Options.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@
},
"outputs": [],
"source": [
"from holoviews.ipython.parser import OptsSpec\n",
"from holoviews.util.parser import OptsSpec\n",
"renderer.save(image + waves, 'example_V', \n",
" options=OptsSpec.parse(\"Image (cmap='gray')\"))"
]
Expand Down
7 changes: 7 additions & 0 deletions examples/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

When working on a notebook in examples/ make sure to run ``python
examples.py reference Example.ipynb`` to locate any references to that
notebook in the documenation.

If there are any such references, please check that the content of those
pages is still correct.
4 changes: 4 additions & 0 deletions examples/examples.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
"""
Stub for script that will do things like generate an index and check for
references in the documentation.
"""
2 changes: 1 addition & 1 deletion holoviews/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
commit="$Format:%h$", reponame='holoviews')

from .core import archive # noqa (API import)
from .core.dimension import OrderedDict, Dimension # noqa (API import)
from .core.dimension import OrderedDict, Dimension, Dimensioned # noqa (API import)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come we need Dimensioned in the top-level namespace?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! That is a stray/unnecessary import now - I still need Dimensioned in util.__init__.py though...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in f5f12c2

from .core.boundingregion import BoundingBox # noqa (API import)
from .core.options import (Options, Store, Cycle, # noqa (API import)
Palette, StoreOptions)
Expand Down
13 changes: 12 additions & 1 deletion holoviews/core/dimension.py
Original file line number Diff line number Diff line change
Expand Up @@ -1077,13 +1077,24 @@ def __unicode__(self):
return unicode(PrettyPrinter.pprint(self))



def __call__(self, options=None, **kwargs):
return self.opts(options, **kwargs)

def opts(self, options=None, **kwargs):
"""
Apply the supplied options to a clone of the object which is
then returned. Note that if no options are supplied at all,
all ids are reset.
"""
from ..util.parser import OptsSpec
if isinstance(options, basestring):
try:
options = OptsSpec.parse(options)
except:
options = OptsSpec.parse(
'{clsname} {options}'.format(clsname=self.__class__.__name__,
options=options))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems okay for now but it might be better to list an explicit exception.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. This falls under my bullet points for something to improve. The exception is part of it, but the whole try/except here isn't a very robust approach. I can specify an exception now but this whole thing needs improving (in another PR imho).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specified SyntaxError in a325041


groups = set(Store.options().groups.keys())
if kwargs and set(kwargs) <= groups:
if not all(isinstance(v, dict) for v in kwargs.values()):
Expand Down
2 changes: 1 addition & 1 deletion holoviews/core/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -1505,7 +1505,7 @@ def set_options(cls, obj, options=None, **kwargs):
syntax as the IPython cell magic to achieve the same customization
as shown above:

from holoviews.ipython.parser import OptsSpec
from holoviews.util.parser import OptsSpec
set_options(my_image, OptsSpec.parse("Image (cmap='jet')"))

Then setting both plot and style options:
Expand Down
27 changes: 10 additions & 17 deletions holoviews/ipython/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@

import param
from IPython import version_info
import numpy as np
import holoviews
from param import ipython as param_ext
from IPython.display import HTML

from ..core.tree import AttrTree
from ..core.options import Store, Cycle, Palette
from ..core.options import Store
from ..element.comparison import ComparisonTestCase
from ..interface.collector import Collector
from ..util.settings import list_formats, list_backends
from ..plotting.renderer import Renderer
from .magics import load_magics, list_formats, list_backends
from .magics import load_magics
from .display_hooks import display # noqa (API import)
from .display_hooks import set_display_hooks, OutputMagic
from .display_hooks import set_display_hooks
from .widgets import RunProgress

try:
Expand All @@ -28,14 +28,6 @@
except ImportError:
pass

try:
import pyparsing
from .parser import Parser
Parser.namespace = {'np': np, 'Cycle': Cycle, 'Palette': Palette}
except ImportError:
pyparsing = None


Collector.interval_hook = RunProgress
AttrTree._disabled_prefixes = ['_repr_','_ipython_canary_method_should_not_exist']

Expand Down Expand Up @@ -179,9 +171,10 @@ def __call__(self, *args, **params):
fig='svg')
holoviews.archive.exporters = [svg_exporter] +\
holoviews.archive.exporters
OutputMagic.allowed['backend'] = list_backends()
OutputMagic.allowed['fig'] = list_formats('fig', backend)
OutputMagic.allowed['holomap'] = list_formats('holomap', backend)

Store.output_settings.allowed['backend'] = list_backends()
Store.output_settings.allowed['fig'] = list_formats('fig', backend)
Store.output_settings.allowed['holomap'] = list_formats('holomap', backend)

if selected_backend is None:
raise ImportError('None of the backends could be imported')
Expand All @@ -190,7 +183,7 @@ def __call__(self, *args, **params):
try:
ip = params.pop('ip', None) or get_ipython() # noqa (get_ipython)
except:
# Set current backend (usually has to wait until OutputMagic loaded)
# Set current backend (usually has to wait until OutputSettings loaded)
Store.current_backend = selected_backend
return

Expand All @@ -207,7 +200,7 @@ def __call__(self, *args, **params):
if notebook_extension._loaded == False:
param_ext.load_ipython_extension(ip, verbose=False)
load_magics(ip)
OutputMagic.initialize([backend for backend, _ in imports])
Store.output_settings.initialize([backend for backend, _ in imports])
set_display_hooks(ip)
notebook_extension._loaded = True
Store.current_backend = selected_backend
Expand Down
51 changes: 1 addition & 50 deletions holoviews/ipython/archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from IPython import version_info
from IPython.display import Javascript, display
from .preprocessors import Substitute

# Import appropriate nbconvert machinery
if version_info[0] >= 4:
Expand Down Expand Up @@ -285,54 +286,4 @@ def _get_notebook_node(self): # pragma: no cover
return node



class Substitute(Preprocessor):
"""
An nbconvert preprocessor that substitutes one set of HTML data
output for another, adding annotation to the output as required.

The constructor accepts the notebook format version and a
substitutions dictionary:

{source_html:(target_html, annotation)}

Where the annotation may be None (i.e. no annotation).
"""
annotation = '<center><b>%s</b></center>'

def __init__(self, version, substitutions, **kw):
self.nbversion = version
self.substitutions = substitutions
super(Preprocessor, self).__init__(**kw)

def __call__(self, nb, resources): # Temporary hack around 'enabled' flag
return self.preprocess(nb,resources)


def replace(self, src):
"Given some source html substitute and annotated as applicable"
for html in self.substitutions.keys():
if src == html:
annotation = self.annotation % self.substitutions[src][1]
return annotation + self.substitutions[src][0]
return src


def preprocess_cell(self, cell, resources, index):
v4 = (self.nbversion[0] == 4)
if cell['cell_type'] == 'code':
for outputs in cell['outputs']:
output_key = ('execute_result' if v4 else 'pyout')
if outputs['output_type'] == output_key:
# V1-3
if not v4 and 'html' in outputs:
outputs['html'] = self.replace(outputs['html'])
# V4
for data in outputs.get('data',[]):
if v4 and data == 'text/html':
substitution = self.replace(outputs['data']['text/html'])
outputs['data']['text/html'] = substitution
return cell, resources


notebook_archive = NotebookArchive()
9 changes: 5 additions & 4 deletions holoviews/ipython/display_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
CompositeOverlay, DynamicMap)
from ..core.traversal import unique_dimkeys
from ..core.io import FileArchive
from .magics import OutputMagic, OptsMagic
from ..util.settings import OutputSettings
from .magics import OptsMagic, OutputMagic

# To assist with debugging of display hooks
FULL_TRACEBACK = None
Expand All @@ -30,7 +31,7 @@
def max_frame_warning(max_frames):
sys.stderr.write("Skipping regular visual display to avoid "
"lengthy animation render times\n"
"[Total item frames exceeds max_frames on OutputMagic (%d)]"
"[Total item frames exceeds max_frames on OutputSettings (%d)]"
% max_frames)

def process_object(obj):
Expand Down Expand Up @@ -126,14 +127,14 @@ def wrapped(element):

try:
html = fn(element,
max_frames=OutputMagic.options['max_frames'])
max_frames=OutputSettings.options['max_frames'])

# Only want to add to the archive for one display hook...
disabled_suffixes = ['png_display', 'svg_display']
if not any(fn.__name__.endswith(suffix) for suffix in disabled_suffixes):
if type(holoviews.archive) is not FileArchive:
holoviews.archive.add(element, html=html)
filename = OutputMagic.options['filename']
filename = OutputSettings.options['filename']
if filename:
Store.renderers[Store.current_backend].save(element, filename)

Expand Down
Loading