From 32d628677c4d2d0431a49d712ccd5b3d92034430 Mon Sep 17 00:00:00 2001 From: lda Date: Mon, 31 Aug 2026 01:26:13 +0700 Subject: [PATCH] support latex better --- .../__init__.py | 0 src/{langchain_demo => ipython_agent}/app.py | 0 .../ipython_wrapper.py | 0 src/st_demo/app.py | 4 ++-- src/st_demo/ui.py | 15 ++++++++++++++ tests/test_info.py | 2 +- tests/test_st_demo.py | 20 ++++++++++++++++++- 7 files changed, 37 insertions(+), 4 deletions(-) rename src/{langchain_demo => ipython_agent}/__init__.py (100%) rename src/{langchain_demo => ipython_agent}/app.py (100%) rename src/{langchain_demo => ipython_agent}/ipython_wrapper.py (100%) diff --git a/src/langchain_demo/__init__.py b/src/ipython_agent/__init__.py similarity index 100% rename from src/langchain_demo/__init__.py rename to src/ipython_agent/__init__.py diff --git a/src/langchain_demo/app.py b/src/ipython_agent/app.py similarity index 100% rename from src/langchain_demo/app.py rename to src/ipython_agent/app.py diff --git a/src/langchain_demo/ipython_wrapper.py b/src/ipython_agent/ipython_wrapper.py similarity index 100% rename from src/langchain_demo/ipython_wrapper.py rename to src/ipython_agent/ipython_wrapper.py diff --git a/src/st_demo/app.py b/src/st_demo/app.py index 319c276..272464c 100644 --- a/src/st_demo/app.py +++ b/src/st_demo/app.py @@ -11,7 +11,7 @@ from uuid import uuid4 from ipython_shell.jupyter import InputRequest, JupyterApp, ParsedJupyterMessage -from st_demo.ui import event_to_record, preferred_mime +from st_demo.ui import event_to_record, latex_body, preferred_mime @dataclass @@ -174,7 +174,7 @@ def _render_mime(data: dict[str, object]) -> None: elif mime == "application/javascript": st.code(str(value), language="javascript") elif mime == "text/latex": - st.latex(str(value)) + st.latex(latex_body(value)) else: st.code(str(value), language="text") diff --git a/src/st_demo/ui.py b/src/st_demo/ui.py index 4627632..3a69b7a 100644 --- a/src/st_demo/ui.py +++ b/src/st_demo/ui.py @@ -34,6 +34,21 @@ def preferred_mime(data: Mapping[str, object]) -> tuple[str, object] | None: return next(iter(data.items()), None) +def latex_body(value: object) -> str: + """Adapt common Jupyter LaTeX payloads to Streamlit's ``st.latex`` API. + + IPython's LaTeX formatter commonly returns ``$...$`` while Streamlit + supplies its own delimiters around the value. Remove only the outer + delimiters so they are not rendered as literal dollar signs. + """ + body = str(value).strip() + delimiters = (("$$", "$$"), ("$", "$"), (r"\[", r"\]"), (r"\(", r"\)")) + for opening, closing in delimiters: + if body.startswith(opening) and body.endswith(closing): + return body[len(opening) : -len(closing)].strip() + return body + + def _content_record(content: object) -> dict[str, object]: if isinstance(content, BaseModel): return content.model_dump(mode="json") diff --git a/tests/test_info.py b/tests/test_info.py index 59aee3f..fbce68e 100644 --- a/tests/test_info.py +++ b/tests/test_info.py @@ -5,7 +5,7 @@ from fastapi.testclient import TestClient from ipython_mcp.app import app as mcp_app from ipython_shell import App, AppInfo from ipython_webapp.app import app as web_app -from langchain_demo.ipython_wrapper import get_app_info +from ipython_agent.ipython_wrapper import get_app_info class AppInfoTests(unittest.IsolatedAsyncioTestCase): diff --git a/tests/test_st_demo.py b/tests/test_st_demo.py index d0d1922..ae7d15e 100644 --- a/tests/test_st_demo.py +++ b/tests/test_st_demo.py @@ -8,7 +8,7 @@ from ipython_shell.jupyter.messages import ( UnknownJupyterMessage, ) from st_demo.app import visible_records -from st_demo.ui import event_to_record, preferred_mime +from st_demo.ui import event_to_record, latex_body, preferred_mime class UIDisplayTests(unittest.TestCase): @@ -44,6 +44,24 @@ class UIDisplayTests(unittest.TestCase): self.assertEqual((mime, value), ("text/html", "rich")) + def test_preferred_mime_chooses_latex_before_plain_text(self): + latex = r"\\int_0^1 x^2\\,dx = \\frac{1}{3}" + + mime, value = preferred_mime( + { + "text/plain": "integral", + "text/latex": latex, + } + ) + + self.assertEqual((mime, value), ("text/latex", latex)) + + def test_latex_body_unwraps_ipython_math_delimiters(self): + self.assertEqual( + latex_body(r"$\displaystyle x^{2} - x - 6$"), + r"\displaystyle x^{2} - x - 6", + ) + def test_execute_result_record_keeps_mime_and_repr(self): event = ExecuteResultMessage( message_id="message-1",