pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/ipython/ipython/pull/15184/files

ymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/code-2d31826944fd3be8.css" /> Implement support for image/png format in terminal by danielzgtg · Pull Request #15184 · ipython/ipython · GitHub
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions IPython/core/kitty.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Implements https://sw.kovidgoyal.net/kitty/graphics-protocol/

from base64 import b64encode, b64decode
import sys
from typing import Union

def _supports_kitty_graphics() -> bool:
import platform

if platform.system() not in ("Darwin", "Linux"):
return False

if not sys.stdout.isatty():
return False
# Hardcoding process names instead of using
# https://sw.kovidgoyal.net/kitty/graphics-protocol/#querying-support-and-available-transmission-mediums
# to avoid startup slowdown
supported_terminals = {
"ghostty",
"iTerm2",
"kitty",
"konsole",
"warp",
"wayst",
"wezterm-gui",
}
import psutil

process = psutil.Process()
while process := process.parent():
if process.name() in supported_terminals:
return True
return False


supports_kitty_graphics = _supports_kitty_graphics()


def png_to_kitty_ansi(png: bytes) -> str:
if not png.startswith(b"\x89PNG\r\n\x1a\n"):
raise ValueError
# This simplicity resembles
# https://sw.kovidgoyal.net/kitty/graphics-protocol/#a-minimal-example
# but if we need tmux support, we can switch to Unicode like
# https://github.com/hzeller/timg/blob/main/src/kitty-canvas.cc
result = ["\033_Ga=T,f=100,", "m=1;"]
encoded = b64encode(png)
for i in range(0, len(encoded), 4096):
result.append(encoded[i : i + 4096].decode("ascii"))
result.append("\033\\")
result.append("\033_G")
result.append("m=1;")
del result[-2:]
result[-3] = "m=0;"
return "".join(result)


def kitty_png_render(png: Union[bytes, str], _md_dict: object) -> None:
if isinstance(png, str):
png = png_to_kitty_ansi(b64decode(png))
else:
png = png_to_kitty_ansi(png)
print(png)


display_formatter_default_active_types = [
"text/plain",
*(["image/png"] if supports_kitty_graphics else []),
]

terminal_default_mime_renderers = {
"image/png": kitty_png_render,
}
11 changes: 10 additions & 1 deletion IPython/terminal/interactiveshell.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

from IPython.core.async_helpers import get_asyncio_loop
from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
from IPython.core.kitty import (
display_formatter_default_active_types,
terminal_default_mime_renderers,
)
from IPython.utils.py3compat import input
from IPython.utils.PyColorize import theme_table
from IPython.utils.terminal import toggle_set_term_title, set_term_title, restore_term_title
Expand Down Expand Up @@ -771,7 +775,12 @@ def init_display_formatter(self):
"DisplayFormatter" in config
and "active_types" in config["DisplayFormatter"]
):
self.display_formatter.active_types = ["text/plain"]
self.display_formatter.active_types = display_formatter_default_active_types
if not (
"TerminalInteractiveShell" in config
and "mime_renderers" in config["TerminalInteractiveShell"]
):
self.mime_renderers = terminal_default_mime_renderers

def init_prompt_toolkit_cli(self):
if self.simple_prompt:
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ dependencies = [
"matplotlib-inline>=0.1.6",
'pexpect>4.6; sys_platform != "win32" and sys_platform != "emscripten"',
"prompt_toolkit>=3.0.41,<3.1.0",
"psutil>=7",
"pygments>=2.14.0", # wheel
"stack_data>=0.6.0",
"traitlets>=5.13.0",
Expand Down
4 changes: 3 additions & 1 deletion tests/test_capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,9 @@ def test_capture_output_no_stderr():

def test_capture_output_no_display():
"""test capture_output(display=False)"""
rich = capture.RichOutput(data=full_data)
data = full_data.copy()
del data["image/png"]
rich = capture.RichOutput(data=data)
with capture.capture_output(display=False) as cap:
print(hello_stdout, end="")
print(hello_stderr, end="", file=sys.stderr)
Expand Down
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy