staticdash 2025.17__tar.gz → 2025.18__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: staticdash
3
- Version: 2025.17
3
+ Version: 2025.18
4
4
  Summary: A lightweight static HTML dashboard generator with Plotly and pandas support.
5
5
  Author-email: Brian Day <brian.day1@gmail.com>
6
6
  License: CC0-1.0
@@ -13,6 +13,7 @@ Requires-Dist: pandas
13
13
  Requires-Dist: dominate
14
14
  Requires-Dist: reportlab
15
15
  Requires-Dist: kaleido
16
+ Requires-Dist: matplotlib
16
17
 
17
18
  # staticdash
18
19
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "staticdash"
7
- version = "2025.17"
7
+ version = "2025.18"
8
8
  description = "A lightweight static HTML dashboard generator with Plotly and pandas support."
9
9
  authors = [
10
10
  { name = "Brian Day", email = "brian.day1@gmail.com" }
@@ -17,7 +17,8 @@ dependencies = [
17
17
  "pandas",
18
18
  "dominate",
19
19
  "reportlab",
20
- "kaleido"
20
+ "kaleido",
21
+ "matplotlib"
21
22
  ]
22
23
 
23
24
  [tool.setuptools]
@@ -15,6 +15,8 @@ from reportlab.lib import colors
15
15
  from reportlab.lib.units import inch
16
16
  import io
17
17
  import tempfile
18
+ import matplotlib.pyplot as plt
19
+ import io, base64
18
20
 
19
21
  class AbstractPage:
20
22
  def __init__(self):
@@ -75,7 +77,24 @@ class Page(AbstractPage):
75
77
  elem = header_tag(text)
76
78
  elif kind == "plot":
77
79
  fig = content
78
- elem = div(raw_util(fig.to_html(full_html=False, include_plotlyjs='cdn', config={'responsive': True})))
80
+ # Plotly support (existing)
81
+ if hasattr(fig, "to_html"):
82
+ elem = div(raw_util(fig.to_html(full_html=False, include_plotlyjs='cdn', config={'responsive': True})))
83
+ # Matplotlib support
84
+ else:
85
+ try:
86
+ buf = io.BytesIO()
87
+ fig.savefig(buf, format="png", bbox_inches="tight")
88
+ buf.seek(0)
89
+ img_base64 = base64.b64encode(buf.read()).decode("utf-8")
90
+ buf.close()
91
+ # Center the image using a div with inline styles
92
+ elem = div(
93
+ raw_util(f'<img src="data:image/png;base64,{img_base64}" style="max-width:100%;">'),
94
+ style="display: flex; justify-content: center; align-items: center;"
95
+ )
96
+ except Exception as e:
97
+ elem = div(f"Matplotlib figure could not be rendered: {e}")
79
98
  elif kind == "table":
80
99
  df = content
81
100
  html_table = df.to_html(classes="table-hover table-striped", index=False, border=0, table_id=f"table-{index}", escape=False)
@@ -124,7 +143,24 @@ class MiniPage(AbstractPage):
124
143
  elem = header_tag(text)
125
144
  elif kind == "plot":
126
145
  fig = content
127
- elem = raw_util(fig.to_html(full_html=False, include_plotlyjs='cdn', config={'responsive': True}))
146
+ # Plotly support (existing)
147
+ if hasattr(fig, "to_html"):
148
+ elem = div(raw_util(fig.to_html(full_html=False, include_plotlyjs='cdn', config={'responsive': True})))
149
+ # Matplotlib support
150
+ else:
151
+ try:
152
+ buf = io.BytesIO()
153
+ fig.savefig(buf, format="png", bbox_inches="tight")
154
+ buf.seek(0)
155
+ img_base64 = base64.b64encode(buf.read()).decode("utf-8")
156
+ buf.close()
157
+ # Center the image using a div with inline styles
158
+ elem = div(
159
+ raw_util(f'<img src="data:image/png;base64,{img_base64}" style="max-width:100%;">'),
160
+ style="display: flex; justify-content: center; align-items: center;"
161
+ )
162
+ except Exception as e:
163
+ elem = div(f"Matplotlib figure could not be rendered: {e}")
128
164
  elif kind == "table":
129
165
  df = content
130
166
  html_table = df.to_html(classes="table-hover table-striped", index=False, border=0, table_id=f"table-{index}", escape=False)
@@ -363,18 +399,53 @@ class Dashboard:
363
399
  fig = content
364
400
  try:
365
401
  import plotly.graph_objects as go
366
- if not isinstance(fig, go.Figure):
367
- raise ValueError("add_plot must be called with a plotly.graph_objects.Figure")
368
- fig.update_layout(margin=dict(l=10, r=10, t=30, b=30), width=900, height=540)
369
- with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmpfile:
370
- fig.write_image(tmpfile.name, width=600, height=360, scale=2, format="png", engine="kaleido")
371
- with open(tmpfile.name, "rb") as imgf:
372
- img_bytes = imgf.read()
373
- img_buf = io.BytesIO(img_bytes)
402
+ import matplotlib.figure
403
+ import io
404
+ from reportlab.platypus import Image
405
+
406
+ # Plotly support
407
+ if isinstance(fig, go.Figure):
408
+ # Configure the figure layout for PDF rendering
409
+ fig.update_layout(
410
+ margin=dict(l=10, r=10, t=30, b=30),
411
+ width=900,
412
+ height=540
413
+ )
414
+
415
+ # Use kaleido to export the figure as a PNG
416
+ png_bytes = fig.to_image(format="png", width=900, height=540, engine="kaleido")
417
+
418
+ # Wrap the PNG bytes in a BytesIO buffer
419
+ img_buf = io.BytesIO(png_bytes)
420
+
421
+ # Add the image to the PDF story
374
422
  story.append(Spacer(1, 8))
375
- story.append(Image(img_buf, width=6*inch, height=3.6*inch))
423
+ story.append(Image(img_buf, width=6 * inch, height=3.6 * inch))
376
424
  story.append(Spacer(1, 12))
377
- os.unlink(tmpfile.name)
425
+
426
+ # Matplotlib support
427
+ elif isinstance(fig, matplotlib.figure.Figure):
428
+ buf = io.BytesIO()
429
+ # Save the figure with higher DPI for better quality
430
+ fig.savefig(buf, format="png", bbox_inches="tight", dpi=300)
431
+ buf.seek(0)
432
+
433
+ # Calculate aspect ratio
434
+ fig_width, fig_height = fig.get_size_inches()
435
+ aspect_ratio = fig_height / fig_width
436
+
437
+ # Set width and calculate height based on aspect ratio
438
+ pdf_width = 6 * inch
439
+ pdf_height = pdf_width * aspect_ratio
440
+
441
+ # Add the image to the PDF story
442
+ story.append(Spacer(1, 8))
443
+ story.append(Image(buf, width=pdf_width, height=pdf_height))
444
+ story.append(Spacer(1, 12))
445
+
446
+ else:
447
+ raise ValueError("add_plot must be called with a plotly.graph_objects.Figure or matplotlib.figure.Figure")
448
+
378
449
  except Exception as e:
379
450
  story.append(Paragraph(f"Plot rendering not supported in PDF: {e}", normal_style))
380
451
  elif kind == "syntax":
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: staticdash
3
- Version: 2025.17
3
+ Version: 2025.18
4
4
  Summary: A lightweight static HTML dashboard generator with Plotly and pandas support.
5
5
  Author-email: Brian Day <brian.day1@gmail.com>
6
6
  License: CC0-1.0
@@ -13,6 +13,7 @@ Requires-Dist: pandas
13
13
  Requires-Dist: dominate
14
14
  Requires-Dist: reportlab
15
15
  Requires-Dist: kaleido
16
+ Requires-Dist: matplotlib
16
17
 
17
18
  # staticdash
18
19
 
@@ -3,3 +3,4 @@ pandas
3
3
  dominate
4
4
  reportlab
5
5
  kaleido
6
+ matplotlib
File without changes
File without changes