openseries 2.1.2__tar.gz → 2.1.3__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: openseries
3
- Version: 2.1.2
3
+ Version: 2.1.3
4
4
  Summary: Tools for analyzing financial timeseries.
5
5
  License-Expression: BSD-3-Clause
6
6
  License-File: LICENSE.md
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import re
5
6
  import webbrowser
6
7
  from inspect import stack
7
8
  from logging import getLogger
@@ -16,7 +17,7 @@ if TYPE_CHECKING: # pragma: no cover
16
17
  from plotly.graph_objs import Figure # type: ignore[import-untyped]
17
18
 
18
19
  from .frame import OpenFrame
19
- from .owntypes import LiteralPlotlyJSlib, LiteralPlotlyOutput
20
+ from .owntypes import LiteralPlotlyOutput
20
21
 
21
22
 
22
23
  from pandas import DataFrame, Index, Series, Timestamp, concat
@@ -857,7 +858,9 @@ def _generate_responsive_html_string(
857
858
  f"{mobile_content}\n"
858
859
  f"</div>\n"
859
860
  "<style>\n"
861
+ "html, body { height: 100%; margin: 0; padding: 0; }\n"
860
862
  "body { overflow-y: auto; }\n"
863
+ ".plotly-desktop { min-height: 100vh; }\n"
861
864
  "@media (max-width: 960px), (pointer: coarse), (hover: none) {\n"
862
865
  " .plotly-desktop { display: none !important; }\n"
863
866
  " .plotly-mobile { display: block !important; "
@@ -890,16 +893,7 @@ def _generate_responsive_html_string(
890
893
  "overflow-x: hidden !important; }\n"
891
894
  " .plotly-desktop .js-plotly-plot > div { "
892
895
  "overflow: hidden !important; overflow-y: hidden !important; "
893
- "overflow-x: hidden !important; max-height: 100% !important; }\n"
894
- " .plotly-desktop .js-plotly-plot svg { "
895
- "overflow: hidden !important; }\n"
896
- " .plotly-desktop * { "
897
- "overflow-y: hidden !important; }\n"
898
- ' .plotly-desktop [style*="overflow"] { '
899
- "overflow: hidden !important; overflow-y: hidden !important; }\n"
900
- " .plotly-desktop .scrollbar-kit { "
901
- "display: none !important; visibility: hidden !important; "
902
- "opacity: 0 !important; }\n"
896
+ "overflow-x: hidden !important; }\n"
903
897
  " .plotly-desktop .scrollbar-slider { "
904
898
  "display: none !important; visibility: hidden !important; "
905
899
  "opacity: 0 !important; }\n"
@@ -1236,10 +1230,27 @@ def _generate_responsive_html_string(
1236
1230
  'desktopContainer.style.display !== "none") {\n'
1237
1231
  " adjustTableSize(desktopContainer);\n"
1238
1232
  " adjustLogoPosition(desktopContainer);\n"
1233
+ " var plotDiv = desktopContainer.querySelector("
1234
+ "'.js-plotly-plot');\n"
1235
+ " if (plotDiv && typeof Plotly !== 'undefined') {\n"
1236
+ " Plotly.Plots.resize(plotDiv);\n"
1237
+ " }\n"
1239
1238
  " }\n"
1240
1239
  " }, 100);\n"
1241
1240
  " });\n"
1242
1241
  " updateLayout();\n"
1242
+ " // Set desktop plot container to full viewport height on load\n"
1243
+ " setTimeout(function() {\n"
1244
+ f" var desktopContainer = {desktop_get};\n"
1245
+ " if (desktopContainer && typeof Plotly !== 'undefined') {\n"
1246
+ " var plotDiv = desktopContainer.querySelector("
1247
+ "'.js-plotly-plot');\n"
1248
+ " if (plotDiv) {\n"
1249
+ " plotDiv.style.height = window.innerHeight + 'px';\n"
1250
+ " Plotly.Plots.resize(plotDiv);\n"
1251
+ " }\n"
1252
+ " }\n"
1253
+ " }, 100);\n"
1243
1254
  " var checkInterval = setInterval(function() {\n"
1244
1255
  f" var mobileContainer = {mobile_get};\n"
1245
1256
  f" var desktopContainer = {desktop_get};\n"
@@ -1267,6 +1278,36 @@ def _generate_responsive_html_string(
1267
1278
  )
1268
1279
 
1269
1280
 
1281
+ def _wrap_in_full_html(
1282
+ responsive_content: str,
1283
+ ) -> str:
1284
+ """Wrap responsive HTML content in a full HTML document.
1285
+
1286
+ Args:
1287
+ responsive_content: The responsive HTML content (divs, CSS, JS).
1288
+
1289
+ Returns:
1290
+ Full HTML document string.
1291
+ """
1292
+ plotly_js_script = (
1293
+ '<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>'
1294
+ )
1295
+
1296
+ return (
1297
+ "<!DOCTYPE html>\n"
1298
+ '<html lang="en">\n'
1299
+ "<head>\n"
1300
+ ' <meta charset="utf-8" />\n'
1301
+ " <title>Plotly Report</title>\n"
1302
+ f" {plotly_js_script}\n"
1303
+ "</head>\n"
1304
+ "<body>\n"
1305
+ f"{responsive_content}\n"
1306
+ "</body>\n"
1307
+ "</html>"
1308
+ )
1309
+
1310
+
1270
1311
  def report_html(
1271
1312
  data: OpenFrame,
1272
1313
  bar_freq: LiteralBizDayFreq = "BYE",
@@ -1274,7 +1315,6 @@ def report_html(
1274
1315
  title: str | None = None,
1275
1316
  directory: Path | None = None,
1276
1317
  output_type: LiteralPlotlyOutput = "file",
1277
- include_plotlyjs: LiteralPlotlyJSlib = "cdn",
1278
1318
  *,
1279
1319
  auto_open: bool = False,
1280
1320
  add_logo: bool = True,
@@ -1289,9 +1329,6 @@ def report_html(
1289
1329
  title: The report page title.
1290
1330
  directory: Directory where Plotly HTML file is saved.
1291
1331
  output_type: Determines output type. Defaults to "file".
1292
- include_plotlyjs: Determines how the plotly.js library is included in
1293
- the output.
1294
- Defaults to "cdn".
1295
1332
  auto_open: Determines whether to open a browser window with the plot.
1296
1333
  Defaults to False.
1297
1334
  add_logo: If True a Captor logo is added to the plot. Defaults to True.
@@ -1299,7 +1336,13 @@ def report_html(
1299
1336
  labels. Defaults to False.
1300
1337
 
1301
1338
  Returns:
1302
- Plotly Figure and a div section or a HTML filename with location.
1339
+ A tuple containing:
1340
+ - Plotly Figure object (the desktop version of the figure)
1341
+ - When ``output_type="file"``: A string containing the file path to the
1342
+ saved HTML file
1343
+ - When ``output_type="div"``: A string containing the responsive HTML div
1344
+ section (includes both desktop and mobile layouts with CSS and
1345
+ JavaScript)
1303
1346
 
1304
1347
  """
1305
1348
  copied = data.from_deepcopy()
@@ -1389,12 +1432,14 @@ def report_html(
1389
1432
  div_id_desktop = filename.split(sep=".")[0] + "_desktop"
1390
1433
  div_id_mobile = filename.split(sep=".")[0] + "_mobile"
1391
1434
 
1392
- html_desktop = to_html(
1435
+ figure.update_layout(height=None)
1436
+
1437
+ html_desktop_raw = to_html(
1393
1438
  fig=figure,
1394
1439
  div_id=div_id_desktop,
1395
1440
  auto_play=False,
1396
1441
  full_html=False,
1397
- include_plotlyjs=include_plotlyjs,
1442
+ include_plotlyjs="cdn",
1398
1443
  config=fig["config"],
1399
1444
  )
1400
1445
 
@@ -1407,16 +1452,23 @@ def report_html(
1407
1452
  config=fig["config"],
1408
1453
  )
1409
1454
 
1455
+ script_pattern = r'<script src="https://cdn\.plot\.ly/plotly[^"]*"></script>'
1456
+ html_desktop_content = re.sub(script_pattern, "", html_desktop_raw)
1457
+
1410
1458
  responsive_html = _generate_responsive_html_string(
1411
- html_desktop=html_desktop,
1459
+ html_desktop=html_desktop_content,
1412
1460
  html_mobile=html_mobile,
1413
1461
  div_id_desktop=div_id_desktop,
1414
1462
  div_id_mobile=div_id_mobile,
1415
1463
  table_html=table_html,
1416
1464
  )
1417
1465
 
1466
+ full_html = _wrap_in_full_html(
1467
+ responsive_content=responsive_html,
1468
+ )
1469
+
1418
1470
  with plotfile.open(mode="w", encoding="utf-8") as f:
1419
- f.write(responsive_html)
1471
+ f.write(full_html)
1420
1472
 
1421
1473
  if auto_open:
1422
1474
  webbrowser.open(f"file://{plotfile.resolve()}")
@@ -1425,12 +1477,15 @@ def report_html(
1425
1477
  else:
1426
1478
  div_id = filename.split(sep=".")[0]
1427
1479
  div_id_mobile = div_id + "_mobile"
1480
+
1481
+ figure.update_layout(height=None)
1482
+
1428
1483
  html_desktop = to_html(
1429
1484
  fig=figure,
1430
1485
  div_id=div_id,
1431
1486
  auto_play=False,
1432
1487
  full_html=False,
1433
- include_plotlyjs=include_plotlyjs,
1488
+ include_plotlyjs="cdn",
1434
1489
  config=fig["config"],
1435
1490
  )
1436
1491
  html_mobile = to_html(
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "openseries"
3
- version = "2.1.2"
3
+ version = "2.1.3"
4
4
  description = "Tools for analyzing financial timeseries."
5
5
  authors = [
6
6
  { name = "Martin Karrin", email = "martin.karrin@captor.se" },
File without changes
File without changes