Skip to content

Instantly share code, notes, and snippets.

@tonyfast
Last active December 11, 2019 04:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tonyfast/3b66729ac43e6e47ea38e882091b7b71 to your computer and use it in GitHub Desktop.
Save tonyfast/3b66729ac43e6e47ea38e882091b7b71 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Allowing code cells to accept Markdown requires different display behavior. An important feature of computational documents is the real data can be included within a narrative. In this document, we add the ability to template Markdown with `jinja2`. We'll observe value changes and update the display with `traitlets`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
" import nbconvert, htmlmin, collections, jinja2.meta, IPython, sys, traitlets\n",
" with __import__('importnb').Notebook():\n",
" try: from . import __interactive_markdown_cells\n",
" except: import __interactive_markdown_cells\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Observable is singleton that manages the changes to the `jinja2` templates."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
" class Observable(traitlets.config.SingletonConfigurable):\n",
" parent = IPython.get_ipython()\n",
" def _post_execute(self): \n",
" with self.hold_trait_notifications():\n",
" for trait in self.traits():\n",
" if trait not in self._config_traits and trait in self.parent.user_ns:\n",
" if getattr(self, trait, None) is not self.parent.user_ns.get(trait, None): setattr(self, trait, self.parent.user_ns.get(trait, None))\n",
"\n",
" _config_traits = set(traitlets.config.SingletonConfigurable().traits())\n",
" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Donald Knuth referred to the presentation of literate code as `\"Weaving\"` which we derive our main `Weave` `type` from."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"ename": "NameError",
"evalue": "name 'traitlets' is not defined",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-7-a525bd864199>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mclass\u001b[0m \u001b[0mWeave\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtraitlets\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconfig\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mSingletonConfigurable\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0menvironment\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnbconvert\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTemplateExporter\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0menvironment\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mparent\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mIPython\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_ipython\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mobservable\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mObservable\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mNameError\u001b[0m: name 'traitlets' is not defined"
]
}
],
"source": [
" class Weave(traitlets.config.SingletonConfigurable):\n",
" environment = nbconvert.TemplateExporter().environment\n",
" parent = IPython.get_ipython()\n",
" observable = Observable.instance()\n",
" \n",
" def post_run_cell(self, result): \n",
" if result.info.raw_cell.splitlines()[0].strip() not in {'', ';'}: \n",
" self.log.error(result.info.raw_cell)\n",
" self.format(result.info.raw_cell) \n",
" \n",
" def finalize(self, object):\n",
" if isinstance(object, str): \n",
" object = self.parent.user_ns.get(object, object)\n",
" if isinstance(object, str): return object\n",
" \n",
" known = dispatch_extras(object)\n",
" if known: return known\n",
" \n",
" bundle, metadata = self.parent.display_formatter.format(object)\n",
" for type in reversed(self.parent.display_formatter.active_types):\n",
" if type in bundle: \n",
" object = bundle[type]\n",
" if type.startswith('image') or type in {'text/html'}: \n",
" object = _format_images(type, bundle)\n",
" if type == 'text/latex': \n",
" if object.startswith('$$') and object.endswith('$$'): object = object[1:-1]\n",
" break\n",
" return object\n",
" \n",
" def format(self, source, **k):\n",
" if source in self.parent.user_ns and isinstance(self.parent.user_ns.get(source), str):\n",
" source = self.parent.user_ns.get(source)\n",
" self.environment.filters.update({k: v for k, v in self.parent.user_ns.items() if callable(v)}) \n",
" source, metadata = front_matter(source)\n",
" \n",
" def update(change=None, init=False):\n",
" nonlocal source, self, display_id, template, k, metadata\n",
" object = template.render(**collections.ChainMap(k, metadata, self.parent.user_ns, self.parent.user_ns.get('__annotations__', {}), vars(__import__('builtins'))))\n",
" if len(object.splitlines()) == 1 and object.startswith('http'): \n",
" data = {'text/html': IPython.display.IFrame(object, '100%', 600)._repr_html_(), 'text/plain': object}\n",
" elif object in self.parent.user_ns: \n",
" data = self.parent.display_formatter.format(self.parent.user_ns[object])[0]\n",
" else: data = {'text/markdown': object, 'text/plain': source,}\n",
" getattr(display_id, init and 'display' or 'update')(data, metadata=metadata, raw=True)\n",
" \n",
" try: template, display_id = self.environment.overlay(finalize=self.finalize).from_string(source), IPython.display.DisplayHandle()\n",
" except BaseException as e: \n",
" __import__('traceback').print_exc()\n",
" IPython.display.display(IPython.display.Markdown(source))\n",
" else:\n",
" update(init=True)\n",
"\n",
" undeclared = jinja2.meta.find_undeclared_variables(template.environment.parse(source))\n",
" for key in list(undeclared): \n",
" if isinstance(self.parent.user_ns.get(key, None), __import__('types').ModuleType):\n",
" undeclared.remove(key)\n",
" if undeclared:\n",
" for var in undeclared: self.observable.has_trait(var) or self.observable.add_traits(**{var: traitlets.Any()})\n",
" self.observable.observe(update, undeclared)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`IPython` extension"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
" def unload_ipython_extension(shell):\n",
" try: Observable.instance().parent.events.unregister('post_execute', Observable.instance()._post_execute)\n",
" except: ...\n",
" try: shell.events.unregister('post_run_cell', Weave.instance().post_run_cell)\n",
" except ValueError: ...\n",
" def load_ipython_extension(shell):\n",
" unload_ipython_extension(shell)\n",
" shell.events.register('post_execute', Observable.instance()._post_execute)\n",
" shell.events.register('post_run_cell', Weave.instance().post_run_cell)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
" def dispatch_extras(object):\n",
" if 'matplotlib' in sys.modules:\n",
" import matplotlib\n",
" try:\n",
" if isinstance(object, (matplotlib.figure.Axes, matplotlib.figure.Figure, getattr(matplotlib.axes._subplots, 'AxesSubplot', type))): return _show_axes(object)\n",
" except: ...\n",
"\n",
" if 'sympy.plotting' in sys.modules:\n",
" from sympy.plotting.plot import Plot\n",
" if isinstance(object, Plot): return _show_sympy_axes(object)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
" def import_yaml():\n",
" try: from ruamel import yaml\n",
" except: \n",
" try: import yaml\n",
" except:...\n",
" return yaml\n",
"\n",
" def front_matter(source):\n",
" try:\n",
" if source.startswith('---\\n') and (source.rindex('\\n---\\n')):\n",
" data, sep, rest = source.lstrip('-').partition('\\n---\\n')\n",
" data = import_yaml().safe_load(__import__('io').StringIO(data))\n",
" if isinstance(data, dict): return rest, data\n",
" except ValueError: ...\n",
" return source, {}"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
" def _show_axes(object):\n",
" import matplotlib.backends.backend_svg; bytes = __import__('io').BytesIO()\n",
" matplotlib.backends.backend_agg.FigureCanvasAgg(getattr(object, 'figure', object)).print_png(bytes)\n",
" try: return _format_bytes(bytes.getvalue(), object)\n",
" finally: matplotlib.pyplot.clf()\n",
"\n",
" def _show_sympy_axes(object): \n",
" bytes = __import__('io').BytesIO()\n",
" object.save(bytes)\n",
" try: return _format_bytes(bytes.getvalue(), object)\n",
" finally: __import__('matplotlib').pyplot.clf()\n",
"\n",
" def _format_bytes(bytes, object): return _format_images('image/png', {'image/png': bytes})\n",
"\n",
" def _format_images(type, bundle):\n",
" str = bundle[type] \n",
" if isinstance(str, bytes): str = __import__('base64').b64encode(str).decode('utf-8')\n",
" if type in ('image/svg+xml', 'text/html'): return htmlmin.minify(str, remove_empty_space=True)\n",
" elif str.startswith('http'): str = F\"\"\"<img src=\"{str}\"/>\"\"\"\n",
" else: str = F\"\"\"<img src=\"data:{type};base64,{str}\"/>\"\"\"\n",
" return str"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/markdown": [
" __name__ == '__main__' and load_ipython_extension(get_ipython())"
],
"text/plain": [
" __name__ == '__main__' and load_ipython_extension(get_ipython())"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
" __name__ == '__main__' and load_ipython_extension(get_ipython())"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
with __import__('importnb').Notebook():
try: from . import __doctest_post_run_cell, __interactive_markdown_cells, __string_expression_transformer, __interactive_jinja_templates, __xonsh_compiler, __emojis__, __return_yield_display, __pidgin_loader, __functional_programming_toolz, __default_markdown_display_for_strings
except: import __doctest_post_run_cell, __interactive_markdown_cells, __string_expression_transformer, __interactive_jinja_templates, __xonsh_compiler, __emojis__, __return_yield_display, __pidgin_loader, __functional_programming_toolz, __default_markdown_display_for_strings
PidginLoader = __pidgin_loader.PidginLoader
def unload_ipython_extension(shell): [x.unload_ipython_extension(shell) for x in (__doctest_post_run_cell, __interactive_markdown_cells, __string_expression_transformer, __interactive_jinja_templates, __xonsh_compiler, __emojis__, __return_yield_display, __default_markdown_display_for_strings)]
def load_ipython_extension(shell): [x.load_ipython_extension(shell) for x in (__doctest_post_run_cell, __interactive_markdown_cells, __string_expression_transformer, __interactive_jinja_templates, __xonsh_compiler, __emojis__, __return_yield_display, __default_markdown_display_for_strings)]
import schematypes
from tonyfast.poser import *
shell = get_ipython()
shell.run_cell("\n %reload_ext tonyfast.literacy")
shell.enable_html_pager = True
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
toolz
notebook
importnb
htmlmin
nbconvert
IPython
xonsh
graphviz
emoji
stringcase
@tonyfast
Copy link
Author

Screen Shot 2019-10-11 at 9 47 55 AM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment