Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# -*- coding: utf-8 -*-
2"""
3@file
4@brief Helpers around JSON
5"""
6import os
7import shutil
8import uuid
9import json
10from IPython.display import display_html, display_javascript
13class RenderJSONRaw:
14 """
15 Renders :epkg:`JSON` in a :epkg:`notebook`
16 using :epkg:`renderjson`.
17 """
19 def __init__(self, json_data, width="100%", height="100%", divid=None,
20 show_to_level=None, local=False):
21 """
22 Initialize with a :epkg:`JSON` data.
24 @param json_data dictionary or string
25 @param width (str) width
26 @param height (str) height
27 @param divid (str|None) id of the div
28 @param show_to_level (int|None) show first level
29 @param local (bool|False) use local javascript files
31 If *local*, local javascript files are copied in the current folder.
32 """
33 if isinstance(json_data, (dict, list)):
34 self.json_str = json.dumps(json_data)
35 else:
36 self.json_str = json
37 self.uuid = divid if divid else str(uuid.uuid4())
38 self.width = width
39 self.height = height
40 self.show_to_level = show_to_level
41 self.local = local
42 self._copy_local(local)
44 def _copy_local(self, local):
45 """
46 If *self.local*, copies javascript dependencies in the local folder.
47 """
48 if not self.local:
49 return
50 if os.path.exists('renderjson.js'):
51 # Already done.
52 return
53 this = os.path.dirname(__file__)
54 js = os.path.join(this, '..', 'js', 'renderjson', 'renderjson.js')
55 if not os.path.exists(js):
56 raise FileNotFoundError("Unable to find '{0}'".format(js))
57 dest = local if isinstance(local, str) else os.getcwd()
58 shutil.copy(js, dest)
60 def generate_html(self):
61 """
62 Overloads method
63 `_ipython_display_ <http://ipython.readthedocs.io/en/stable/config/integrating.html?highlight=Integrating%20>`_.
64 """
65 level = " show_to_level={}".format(
66 self.show_to_level) if self.show_to_level is not None else ''
67 ht = '<div id="{}" style="height: {}; width:{};"{}></div>'.format(
68 self.uuid, self.width, self.height, level)
69 lib = 'renderjson.js' if self.local else 'https://rawgit.com/caldwell/renderjson/master/renderjson.js'
70 js = """
71 require(["%s"], function() {
72 document.getElementById('%s').appendChild(renderjson(%s))
73 }); """ % (lib, self.uuid, self.json_str)
74 return ht, js
77class RenderJSONObj(RenderJSONRaw):
78 """
79 Renders :epkg:`JSON` using :epkg:`javascript`.
80 """
82 def _ipython_display_(self):
83 ht, js = self.generate_html()
84 display_html(ht, raw=True)
85 display_javascript(js, raw=True)
88class RenderJSON(RenderJSONRaw):
89 """
90 Renders :epkg:`JSON` using :epkg:`javascript`, outputs only :epkg:`HTML`.
91 """
93 def _repr_html_(self):
94 ht, js = self.generate_html()
95 ht += "\n<script>\n{0}\n</script>\n".format(js)
96 return ht
99def JSONJS(data, only_html=True, show_to_level=None, local=False):
100 """
101 Inspired from `Pretty JSON Formatting in IPython Notebook
102 <http://stackoverflow.com/questions/18873066/pretty-json-formatting-in-ipython-notebook>`_.
104 @param data dictionary or json string
105 @param show_to_level show first level
106 @param local use local files
107 @return @see cl RenderJSON
109 The function uses library
110 `renderjson <https://github.com/caldwell/renderjson>`_.
111 It returns an object with overwrite method
112 `_ipython_display_ <http://ipython.readthedocs.io/en/stable/config/integrating.html?highlight=Integrating%20>`_.
113 If *local* is true, javascript dependency are copied in the local folder.
115 .. faqref::
116 :title: Persistent javascript in a conververted notebook
118 After a couple of tries, it appears that it is more efficient to
119 render the javascript inside a section ``<script>...</script>``
120 when the notebook is converted to RST (*only_html=True*).
121 """
122 if only_html:
123 return RenderJSON(data, show_to_level=show_to_level, local=local)
124 return RenderJSONObj(data, show_to_level=show_to_level, local=local)