CoolFace
Apppublic

Aluode/PerceptionLabPortable

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
jupyter.py102 linesDownload Raw Back to rich
1from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Sequence2 3if TYPE_CHECKING:4    from pip._vendor.rich.console import ConsoleRenderable5 6from . import get_console7from .segment import Segment8from .terminal_theme import DEFAULT_TERMINAL_THEME9 10if TYPE_CHECKING:11    from pip._vendor.rich.console import ConsoleRenderable12 13JUPYTER_HTML_FORMAT = """\14<pre style="white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace">{code}</pre>15"""16 17 18class JupyterRenderable:19    """A shim to write html to Jupyter notebook."""20 21    def __init__(self, html: str, text: str) -> None:22        self.html = html23        self.text = text24 25    def _repr_mimebundle_(26        self, include: Sequence[str], exclude: Sequence[str], **kwargs: Any27    ) -> Dict[str, str]:28        data = {"text/plain": self.text, "text/html": self.html}29        if include:30            data = {k: v for (k, v) in data.items() if k in include}31        if exclude:32            data = {k: v for (k, v) in data.items() if k not in exclude}33        return data34 35 36class JupyterMixin:37    """Add to an Rich renderable to make it render in Jupyter notebook."""38 39    __slots__ = ()40 41    def _repr_mimebundle_(42        self: "ConsoleRenderable",43        include: Sequence[str],44        exclude: Sequence[str],45        **kwargs: Any,46    ) -> Dict[str, str]:47        console = get_console()48        segments = list(console.render(self, console.options))49        html = _render_segments(segments)50        text = console._render_buffer(segments)51        data = {"text/plain": text, "text/html": html}52        if include:53            data = {k: v for (k, v) in data.items() if k in include}54        if exclude:55            data = {k: v for (k, v) in data.items() if k not in exclude}56        return data57 58 59def _render_segments(segments: Iterable[Segment]) -> str:60    def escape(text: str) -> str:61        """Escape html."""62        return text.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")63 64    fragments: List[str] = []65    append_fragment = fragments.append66    theme = DEFAULT_TERMINAL_THEME67    for text, style, control in Segment.simplify(segments):68        if control:69            continue70        text = escape(text)71        if style:72            rule = style.get_html_style(theme)73            text = f'<span style="{rule}">{text}</span>' if rule else text74            if style.link:75                text = f'<a href="{style.link}" target="_blank">{text}</a>'76        append_fragment(text)77 78    code = "".join(fragments)79    html = JUPYTER_HTML_FORMAT.format(code=code)80 81    return html82 83 84def display(segments: Iterable[Segment], text: str) -> None:85    """Render segments to Jupyter."""86    html = _render_segments(segments)87    jupyter_renderable = JupyterRenderable(html, text)88    try:89        from IPython.display import display as ipython_display90 91        ipython_display(jupyter_renderable)92    except ModuleNotFoundError:93        # Handle the case where the Console has force_jupyter=True,94        # but IPython is not installed.95        pass96 97 98def print(*args: Any, **kwargs: Any) -> None:99    """Proxy for Console print."""100    console = get_console()101    return console.print(*args, **kwargs)102