PK 0uNo datasheet/__init__.py"""A library to generate HTML pages containing all sorts of output""" __version__ = "0.9" from .sheet import Sheet from .types import MD, Str, Repr, DF, Nifti, Figure, MultiCell from .html_renderer import render_htmlPK ^uN,Qy y 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 DF, MD, Figure, Nifti, Repr, Str, MultiCell 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() doc.stag("img", src=fig.rel_save_path, width=f"{fig.scale * 100}%") 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()) @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() def render_html(entries, outdir: 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), Nifti: None, Repr: lambda s: _print_to_html(repr(s.content)), Str: lambda s: _print_to_html(s.content) } _transformers[MultiCell] = lambda s: _render_multicell(s, _transformers) 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", outdir.name) doc.stag("meta", charset="UTF-8") with tag("script", type="text/javascript"): doc.asis(read_text("datasheet.data", "positions.js")) 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', onload="fixPosition();"): with tag('div', id="toc"): line("div", "Contents", id="toc_header") doc.asis(_make_toc(entries, max_index_len)) with tag('div', id='container'): for entry in entries: with tag('div', klass='entry'): doc.asis(_transformers[type(entry)](entry)) Path(outdir, "index.html").write_text(indent(doc.getvalue())) PK uN3^ datasheet/sheet.pyimport pickle from functools import wraps 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 render_html from .types import * class Sheet: """Main class of the library :param str outdir: The output directory, in which all files are stored. :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, outdir: str): self.outdir = Path(outdir) self.entries = [] self._mem = Memory(outdir, verbose=0) type_wrap_map = { str: MD, pd.DataFrame: DF, nib.Nifti1Image: Nifti, matplotlib.figure.Figure: Figure } @staticmethod def _wrap_obj(obj): return obj if isinstance(obj, ElementInterface) \ else Sheet.type_wrap_map.get(type(obj), Repr)(obj) def _store_if_has_save_dir(self, obj): if hasattr(obj, "save_to_dir"): obj.save_to_dir(self.outdir) def __lshift__(self, obj: Any): """Object adding operator, automatically wraps passed objects into fitting type wrappers according to Sheet.type_wrap_map""" if type(obj) in (MultiCell, tuple): objs = obj.content if type(obj) == MultiCell else obj wrapped_obj = MultiCell(tuple(map(Sheet._wrap_obj, objs))) for obj in wrapped_obj.content: self._store_if_has_save_dir(obj) else: wrapped_obj = Sheet._wrap_obj(obj) self._store_if_has_save_dir(wrapped_obj) self.entries.append(wrapped_obj) def render(self, renderer=render_html): """Renders the sheet to some sort of file(s). To customize render options use the renderfunction directly. Currently, the only existing renderer is the HTML renderer """ renderer(self.entries, self.outdir) def cache(self, func, **cache_args)-> MemorizedFunc: """Datasheet automatically creates a `joblib.Memory| t |
")?f=a.cloneNode(!0):(Fc.innerHTML=a.outerHTML,Fc.removeChild(f= Fc.firstChild));if(!(N.support.noCloneEvent&&N.support.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||N.isXMLDoc(a)))for(e=E(f),m=E(a),k=0;null!=(h=m[k]);++k)if(e[k]){var q=e[k],r=void 0,w=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(w in t.events)N.removeEvent(q,w,t.handle);q.removeAttribute(N.expando)}if("script"===r&&q.text!==h.text)x(q).text=h.text,O(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||E(a),e=e||E(f),k=0;null!=(h=m[k]);k++)Y(h,e[k]);else Y(a,f);e=E(f,"script");0$2>")+q[2];for(h=q[0];h--;)k=k.lastChild;!N.support.leadingWhitespace&&nd.test(f)&&t.push(b.createTextNode(nd.exec(f)[0]));if(!N.support.tbody)for(h=(f="table"!==m||jc.test(f)?"