PK kOk datasheet/__init__.py"""A library to generate HTML pages containing all sorts of output""" __version__ = "1.1.1" from .sheet import Sheet from .types import MD, Str, Repr, DF, Nifti, Figure, VLayout, HLayout from .html_renderer import HTMLRenderer PK jOs s datasheet/html_renderer.pyfrom dataclasses import dataclass from importlib.resources import read_text from pathlib import Path from typing import List import re from markdown import markdown from pandas import DataFrame from yattag import Doc, indent from .types import * markdown_extensions = [ 'markdown.extensions.extra', 'markdown.extensions.abbr', 'markdown.extensions.attr_list', 'markdown.extensions.def_list', 'markdown.extensions.fenced_code', 'markdown.extensions.footnotes', 'markdown.extensions.tables', 'markdown.extensions.admonition', 'markdown.extensions.codehilite', 'markdown.extensions.meta', 'markdown.extensions.sane_lists', 'markdown.extensions.smarty', 'markdown.extensions.toc', 'markdown.extensions.wikilinks' ] def _print_to_html(s): doc, tag, text = Doc().tagtext() with tag("pre"): text(s) return doc.getvalue() def _figure_to_html(fig: Figure): doc = Doc() if fig.rel_save_path: doc.stag("img", src=fig.rel_save_path, width=f"{fig.scale * 100}%") else: doc.stag('img', src=f'data:image/{fig.extension};base64,{fig.content}') return doc.getvalue() @dataclass class _PapayaHelper: niftis: List[Nifti] called: int = 0 def get_papaya_header(self): return read_text('datasheet.data', "papaya_header.html") \ + '' + '' def __call__(self, nii: Nifti): res = f'
' self.called += 1 return res def _render_multicell(cell, transformers): doc, tag, text = Doc().tagtext() with tag("div", style="display: flex; flex-direction: row; margin: 10px 0;"): for entry in cell.content: with tag('div', klass='entry'): doc.asis(transformers[type(entry)](entry)) doc.asis(" ") return doc.getvalue() def _is_single_line_md_heading(entry): return type(entry) == MD and "\n" not in entry.content \ and entry.content.strip().startswith("#") def _make_toc(entries, max_index_len): doc, tag, text = Doc().tagtext() for i, entry in enumerate(filter(_is_single_line_md_heading, entries)): line = entry.content.strip() level = re.search(r"[^#]", line).start() with tag("div", klass=f"indexindent_{level}"): link_text = line[level:] if len(line) < max_index_len \ or max_index_len == 0 else (line[level: max_index_len - 3] + "...") doc.line("a", link_text, href=f"#{i}") return indent(doc.getvalue()) def _layout_to_html(transformers, layout): doc, tag, text = Doc().tagtext() with tag('div', klass=type(layout).__name__): for entry in layout.elems: if isinstance(entry, Layout): doc.asis(_layout_to_html(transformers, entry)) else: with tag('div', klass='entry'): doc.asis(transformers[type(entry)](entry)) return indent(doc.getvalue()) @dataclass class _MDHeaderMaker: counter = 0 def get_header(self, entry): doc = Doc() line = entry.content.strip() level = re.search(r"[^#]", line).start() text = line[level:] doc.line(f'h{level}', text, id=str(self.counter)) self.counter += 1 return doc.getvalue() class HTMLRenderer: default_file = 'index.html' extension = 'html' @staticmethod def render(entries: Layout, out_file: Path, style_sheet: str = "default.css", max_index_len: int = 25): """ Renders a `Sheet` as HTML-page. :param Path outdir: The outputfolder to store the page in, usually :code:`Sheet.outdir`. :param str style_sheet: the css file to include in the page. It is looked for in datasheet.data, currently this is the only valid value for this parameter :param int max_index_len: maximal number of characters a title can have before its index is abreviated.""" header_parser = _MDHeaderMaker() _transformers = { DF: lambda s: s.content._repr_html_(), Figure: _figure_to_html, MD: lambda s: header_parser.get_header(s) if _is_single_line_md_heading(s) else markdown(s.content, extensions=markdown_extensions), Nifti: None, Repr: lambda s: _print_to_html(repr(s.content)), Str: lambda s: _print_to_html(s.content) } if any(type(entry) == Nifti for entry in entries): papayaHelper = _PapayaHelper( [entry for entry in entries if type(entry) == Nifti]) _transformers[Nifti] = papayaHelper has_papaya = True else: has_papaya = False doc, tag, text, line = Doc().ttl() with tag('html'): with tag('head'): line("title", out_file.stem) doc.stag("meta", charset="UTF-8") with tag('style'): doc.asis(read_text('datasheet.data', style_sheet)) if has_papaya: doc.asis(read_text("datasheet.data", "papaya_css_additions.txt")) if has_papaya: doc.asis(papayaHelper.get_papaya_header()) with tag('body'): with tag('div', id="toc"): line("div", "Contents", id="toc_header") doc.asis(_make_toc(entries, max_index_len)) with tag('div', id='container'): doc.asis(_layout_to_html(_transformers, entries)) Path(out_file).write_text(indent(doc.getvalue())) PK jOzޅ datasheet/sheet.pyimport pickle from functools import wraps import matplotlib matplotlib.use('agg') import matplotlib.figure import matplotlib.pyplot as plt import nibabel as nib import pandas as pd from joblib import Memory from joblib.memory import MemorizedFunc from .html_renderer import HTMLRenderer from .types import * class Sheet: """Main class of the library :param str out: The output directory or file. :param bool standalone: If this option is set to `True` the output will be a single file, In case of the HTMLRenderer that means images are encoded as base64 and niftis are not supported as those can't be displayed without saving them. :var dict type_wrap_map: Defines the mapping from input types to `ElementInterface` s. It is not possible to use tuple as key, as that will be ignored, because it is required for the special treatment the `MultiCell` Interface needs """ def __init__(self, out_dir_or_file: str, standalone=False): self.out = Path(out_dir_or_file) self.entries = VLayout([]) self.standalone = standalone self._mem_ob = None @property def _mem(self): if self.standalone: raise RuntimeError( "Using cache methods is not supported in standalone mode") if not self._mem_ob: self._mem_ob = Memory(self.out, verbose=0) return self._mem_ob type_wrap_map = { str: MD, pd.DataFrame: DF, nib.Nifti1Image: Nifti, matplotlib.figure.Figure: Figure } def _wrap_obj(self, obj): if isinstance(obj, Layout): return type(obj)([self._wrap_obj(elem) for elem in obj.elems]) elif not isinstance(obj, ElementInterface): return Sheet.type_wrap_map.get(type(obj), Repr)( obj, dont_save = self.standalone) else: return obj def __lshift__(self, obj: Any): """Object adding operator, automatically wraps passed objects into fitting type wrappers according to Sheet.type_wrap_map""" wrapped_obj = self._wrap_obj(obj) wrapped_obj.save_to_dir(self.out) self.entries.elems.append(wrapped_obj) def render(self, Renderer=HTMLRenderer, **kwargs): """Renders the sheet to some sort of file(s). kwargs are passes to Renderer.render() Currently, the only existing renderer is the HTML renderer """ if self.standalone: Renderer.render(self.entries, self.out.parent / (self.out.name + '.' + Renderer.extension), **kwargs) else: Renderer.render(self.entries, self.out / Renderer.default_file, **kwargs) def cache(self, func, **cache_args) -> MemorizedFunc: """Datasheet automatically creates a `joblib.Memory| t |
")?e=a.cloneNode(!0):(Fc.innerHTML=a.outerHTML,Fc.removeChild(e= Fc.firstChild));if(!(N.support.noCloneEvent&&N.support.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||N.isXMLDoc(a)))for(f=M(e),m=M(a),k=0;null!=(h=m[k]);++k)if(f[k]){var q=f[k],r=void 0,x=void 0,t=void 0;if(1===q.nodeType){r=q.nodeName.toLowerCase();if(!N.support.noCloneEvent&&q[N.expando]){t=N._data(q);for(x in t.events)N.removeEvent(q,x,t.handle);q.removeAttribute(N.expando)}if("script"===r&&q.text!==h.text)E(q).text=h.text,P(q);else if("object"===r)q.parentNode&&(q.outerHTML=h.outerHTML),N.support.html5Clone&& h.innerHTML&&!N.trim(q.innerHTML)&&(q.innerHTML=h.innerHTML);else if("input"===r&&dd.test(h.type))q.defaultChecked=q.checked=h.checked,q.value!==h.value&&(q.value=h.value);else if("option"===r)q.defaultSelected=q.selected=h.defaultSelected;else if("input"===r||"textarea"===r)q.defaultValue=h.defaultValue}}if(b)if(d)for(m=m||M(a),f=f||M(e),k=0;null!=(h=m[k]);k++)aa(h,f[k]);else aa(a,e);f=M(e,"script");0$2>")+q[2];for(h=q[0];h--;)k=k.lastChild;!N.support.leadingWhitespace&&nd.test(e)&&t.push(b.createTextNode(nd.exec(e)[0]));if(!N.support.tbody)for(h=(e="table"!==m||jc.test(e)?"