Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -186,10 +186,19 @@ class PDF(FPDF, HTMLMixin):
|
|
| 186 |
pass
|
| 187 |
|
| 188 |
def build_pdf(md: str, charts: Dict[str, str]) -> bytes:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 189 |
html = MarkdownIt("commonmark", {"breaks": True}).enable("table").render(
|
| 190 |
-
TAG_RE.sub(
|
| 191 |
-
lambda m: f'<img src="{charts.get(m.group("d").strip(), "")}">', md
|
| 192 |
-
)
|
| 193 |
)
|
| 194 |
pdf = PDF()
|
| 195 |
pdf.set_auto_page_break(True, margin=15)
|
|
@@ -201,6 +210,7 @@ def build_pdf(md: str, charts: Dict[str, str]) -> bytes:
|
|
| 201 |
pdf.write_html(html)
|
| 202 |
return pdf.output(dest="S").encode("latin-1")
|
| 203 |
|
|
|
|
| 204 |
# βββ QUICK STATIC CHART (fallback if LLM code fails) βββββββββββββββββββββββ
|
| 205 |
def quick_chart(desc: str, df: pd.DataFrame, out: Path):
|
| 206 |
ctype, *rest = [s.strip().lower() for s in desc.split("|", 1)]
|
|
@@ -697,11 +707,22 @@ if st.button("π Generate", type="primary", disabled=not upl):
|
|
| 697 |
# 1) live PDF reports (may be multiple)
|
| 698 |
for rep_key, rep in st.session_state.lazy_reports.items():
|
| 699 |
st.subheader("π Generated Report")
|
| 700 |
-
md_with_imgs = TAG_RE.sub(
|
| 701 |
-
lambda m: _inline_image_or_placeholder(rep, m.group("d").strip()), rep["md"]
|
| 702 |
-
)
|
| 703 |
with st.expander("View Report", expanded=True):
|
| 704 |
-
st.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 705 |
|
| 706 |
if rep["finished"]:
|
| 707 |
c1, c2 = st.columns(2)
|
|
|
|
| 186 |
pass
|
| 187 |
|
| 188 |
def build_pdf(md: str, charts: Dict[str, str]) -> bytes:
|
| 189 |
+
# For PDF generation, we still need to convert file paths to something FPDF can use.
|
| 190 |
+
# Reading bytes and embedding as a data URI is a robust way to handle this.
|
| 191 |
+
def embed_chart_for_pdf(match):
|
| 192 |
+
desc = match.group("d").strip()
|
| 193 |
+
path = charts.get(desc)
|
| 194 |
+
if path and Path(path).exists():
|
| 195 |
+
with open(path, "rb") as f:
|
| 196 |
+
b64 = base64.b64encode(f.read()).decode()
|
| 197 |
+
return f'<img src="data:image/png;base64,{b64}" width="600">'
|
| 198 |
+
return ""
|
| 199 |
+
|
| 200 |
html = MarkdownIt("commonmark", {"breaks": True}).enable("table").render(
|
| 201 |
+
TAG_RE.sub(embed_chart_for_pdf, md)
|
|
|
|
|
|
|
| 202 |
)
|
| 203 |
pdf = PDF()
|
| 204 |
pdf.set_auto_page_break(True, margin=15)
|
|
|
|
| 210 |
pdf.write_html(html)
|
| 211 |
return pdf.output(dest="S").encode("latin-1")
|
| 212 |
|
| 213 |
+
|
| 214 |
# βββ QUICK STATIC CHART (fallback if LLM code fails) βββββββββββββββββββββββ
|
| 215 |
def quick_chart(desc: str, df: pd.DataFrame, out: Path):
|
| 216 |
ctype, *rest = [s.strip().lower() for s in desc.split("|", 1)]
|
|
|
|
| 707 |
# 1) live PDF reports (may be multiple)
|
| 708 |
for rep_key, rep in st.session_state.lazy_reports.items():
|
| 709 |
st.subheader("π Generated Report")
|
|
|
|
|
|
|
|
|
|
| 710 |
with st.expander("View Report", expanded=True):
|
| 711 |
+
# Split markdown by chart tags to render images natively using st.image,
|
| 712 |
+
# which is more robust than embedding base64 in markdown.
|
| 713 |
+
parts = TAG_RE.split(rep["md"])
|
| 714 |
+
for i, part in enumerate(parts):
|
| 715 |
+
if i % 2 == 0: # This is a text part
|
| 716 |
+
if part.strip():
|
| 717 |
+
st.markdown(part, unsafe_allow_html=True)
|
| 718 |
+
else: # This is a chart description captured from the tag
|
| 719 |
+
desc = part.strip()
|
| 720 |
+
chart_path = rep["charts"].get(desc)
|
| 721 |
+
if chart_path and Path(chart_path).exists():
|
| 722 |
+
st.image(chart_path)
|
| 723 |
+
else:
|
| 724 |
+
# Show a native Streamlit placeholder while the chart renders
|
| 725 |
+
st.info(f"β³ Rendering chart: '{desc}'...")
|
| 726 |
|
| 727 |
if rep["finished"]:
|
| 728 |
c1, c2 = st.columns(2)
|