mirror of
https://github.com/wassname/baukit.git
synced 2026-06-27 20:51:13 +08:00
139 lines
4.4 KiB
Python
139 lines
4.4 KiB
Python
# show.py
|
|
#
|
|
# An abbreviated way to output simple HTML layout of text and images
|
|
# into a python notebook.
|
|
#
|
|
# - show a PIL image to show an inline HTML <img>.
|
|
# - show an array of items to vertically stack them, centered in a block.
|
|
# - show an array of arrays to horizontally lay them out as inline blocks.
|
|
# - show an array of tuples to create a table.
|
|
|
|
import PIL.Image, base64, io, IPython, types, sys
|
|
import html as html_module
|
|
from IPython.display import display
|
|
|
|
g_buffer = None
|
|
|
|
def blocks(obj, space=''):
|
|
return IPython.display.HTML(space.join(blocks_tags(obj)))
|
|
|
|
def rows(obj, space=''):
|
|
return IPython.display.HTML(space.join(rows_tags(obj)))
|
|
|
|
def rows_tags(obj):
|
|
if isinstance(obj, dict):
|
|
obj = obj.items()
|
|
results = []
|
|
results.append('<table style="display:inline-table">')
|
|
for row in obj:
|
|
results.append('<tr style="padding:0">')
|
|
for item in row:
|
|
results.append('<td style="text-align:left; vertical-align:top;' +
|
|
'padding:1px">')
|
|
results.extend(blocks_tags(item))
|
|
results.append('</td>')
|
|
results.append('</tr>')
|
|
results.append('</table>')
|
|
return results
|
|
|
|
def blocks_tags(obj):
|
|
results = []
|
|
if hasattr(obj, '_repr_html_'):
|
|
results.append(obj._repr_html_())
|
|
elif isinstance(obj, PIL.Image.Image):
|
|
results.append(pil_to_html(obj))
|
|
elif isinstance(obj, (str, int, float)):
|
|
results.append('<div>')
|
|
results.append(html_module.escape(str(obj)))
|
|
results.append('</div>')
|
|
elif isinstance(obj, dict):
|
|
results.extend(blocks_tags([(k, v) for k, v in obj.items()]))
|
|
elif hasattr(obj, '__iter__'):
|
|
blockstart, blockend, tstart, tend, rstart, rend, cstart, cend = [
|
|
'<div style="display:inline-block;text-align:center;line-height:1;' +
|
|
'vertical-align:top;padding:1px">',
|
|
'</div>',
|
|
'<table style="display:inline-table">',
|
|
'</table>',
|
|
'<tr style="padding:0">',
|
|
'</tr>',
|
|
'<td style="text-align:left; vertical-align:top; padding:1px">',
|
|
'</td>',
|
|
]
|
|
needs_end = False
|
|
table_mode = False
|
|
for i, line in enumerate(obj):
|
|
if i == 0:
|
|
needs_end = True
|
|
if isinstance(line, tuple):
|
|
table_mode = True
|
|
results.append(tstart)
|
|
else:
|
|
results.append(blockstart)
|
|
if table_mode:
|
|
results.append(rstart)
|
|
if not isinstance(line, str) and hasattr(line, '__iter__'):
|
|
for cell in line:
|
|
results.append(cstart)
|
|
results.extend(blocks_tags(cell))
|
|
results.append(cend)
|
|
else:
|
|
results.append(cstart)
|
|
results.extend(blocks_tags(line))
|
|
results.append(cend)
|
|
results.append(rend)
|
|
else:
|
|
results.extend(blocks_tags(line))
|
|
if needs_end:
|
|
results.append(table_mode and tend or blockend)
|
|
return results
|
|
|
|
def pil_to_b64(img, format='png'):
|
|
buffered = io.BytesIO()
|
|
img.save(buffered, format=format)
|
|
return base64.b64encode(buffered.getvalue()).decode('utf-8')
|
|
|
|
def pil_to_url(img, format='png'):
|
|
return 'data:image/%s;base64,%s' % (format, pil_to_b64(img, format))
|
|
|
|
def pil_to_html(img, margin=1):
|
|
mattr = ' style="margin:%dpx"' % margin
|
|
return '<img src="%s"%s>' % (pil_to_url(img), mattr)
|
|
|
|
def a(x, cols=None):
|
|
global g_buffer
|
|
if g_buffer is None:
|
|
g_buffer = []
|
|
g_buffer.append(x)
|
|
if cols is not None and len(g_buffer) >= cols:
|
|
flush()
|
|
|
|
def reset():
|
|
global g_buffer
|
|
g_buffer = None
|
|
|
|
def flush(*args, **kwargs):
|
|
global g_buffer
|
|
if g_buffer is not None:
|
|
x = g_buffer
|
|
g_buffer = None
|
|
display(blocks(x, *args, **kwargs))
|
|
|
|
def show(x=None, *args, **kwargs):
|
|
flush(*args, **kwargs)
|
|
if x is not None:
|
|
display(blocks(x, *args, **kwargs))
|
|
|
|
def html(obj, space=''):
|
|
return blocks(obj, space)._repr_html_()
|
|
|
|
class CallableModule(types.ModuleType):
|
|
def __init__(self):
|
|
# or super().__init__(__name__) for Python 3
|
|
types.ModuleType.__init__(self, __name__)
|
|
self.__dict__.update(sys.modules[__name__].__dict__)
|
|
def __call__(self, x=None, *args, **kwargs):
|
|
show(x, *args, **kwargs)
|
|
|
|
sys.modules[__name__] = CallableModule()
|