From 1a592f0701b2e7730011c15cb6e46ba7c2417966 Mon Sep 17 00:00:00 2001 From: Nicholas Karlson Date: Tue, 20 Jan 2026 02:05:14 -0800 Subject: [PATCH] Track D: explicit shims for mpl compat + reporting style --- scripts/_mpl_compat.py | 14 +++- scripts/_reporting_style.py | 42 ++++++++++- src/pystatsv1/assets/workbook_track_d.zip | Bin 157012 -> 157230 bytes .../test_trackd_business_schema_shim_smoke.py | 69 ++++++++++++++++++ .../track_d_template/scripts/_mpl_compat.py | 6 +- .../scripts/_reporting_style.py | 36 ++++++++- 6 files changed, 158 insertions(+), 9 deletions(-) diff --git a/scripts/_mpl_compat.py b/scripts/_mpl_compat.py index f0542e0..193941c 100644 --- a/scripts/_mpl_compat.py +++ b/scripts/_mpl_compat.py @@ -1,9 +1,17 @@ """Backward-compatible shim for Track D matplotlib helpers. -Historically, Track D chapter scripts imported :mod:`scripts._mpl_compat`. -The implementation now lives in :mod:`pystatsv1.trackd.mpl_compat`. +Historically, some Track D and workbook scripts imported +:mod:`scripts._mpl_compat`. + +The canonical implementation now lives in :mod:`pystatsv1.trackd.mpl_compat`. +This shim keeps existing imports working for students running scripts directly +from the repo. """ from __future__ import annotations -from pystatsv1.trackd.mpl_compat import * # noqa: F401,F403 +from pystatsv1.trackd.mpl_compat import ax_boxplot + +__all__ = [ + "ax_boxplot", +] diff --git a/scripts/_reporting_style.py b/scripts/_reporting_style.py index a229f35..1c3dc6a 100644 --- a/scripts/_reporting_style.py +++ b/scripts/_reporting_style.py @@ -1,12 +1,46 @@ """Backward-compatible shim for Track D reporting-style helpers. Historically, Track D chapter scripts imported :mod:`scripts._reporting_style`. -The implementation now lives in :mod:`pystatsv1.trackd.reporting_style`. +The canonical implementation now lives in :mod:`pystatsv1.trackd.reporting_style`. -Keeping this shim prevents template drift and avoids breaking older chapter -scripts that import from ``scripts/``. +Keeping this shim avoids breaking older chapter runners and keeps the repo and +workbook template aligned. """ from __future__ import annotations -from pystatsv1.trackd.reporting_style import * # noqa: F401,F403 +from pystatsv1.trackd.reporting_style import ( + FigureManifestRow, + FigureSpec, + STYLE_CONTRACT, + ensure_allowed_chart_type, + figure_manifest_to_frame, + mpl_context, + plot_bar, + plot_ecdf, + plot_histogram_with_markers, + plot_time_series, + plot_waterfall_bridge, + save_figure, + style_context, + write_contract_json, + write_style_contract_json, +) + +__all__ = [ + "STYLE_CONTRACT", + "FigureSpec", + "FigureManifestRow", + "write_style_contract_json", + "write_contract_json", + "mpl_context", + "style_context", + "save_figure", + "plot_time_series", + "plot_bar", + "plot_histogram_with_markers", + "plot_ecdf", + "plot_waterfall_bridge", + "figure_manifest_to_frame", + "ensure_allowed_chart_type", +] diff --git a/src/pystatsv1/assets/workbook_track_d.zip b/src/pystatsv1/assets/workbook_track_d.zip index aa235b053e930b7f1561024cf06878420ec78fd7..3ccb56fe46f8734c3a33722502c0f29bb469b701 100644 GIT binary patch delta 1506 zcmY+D3p7-D9LMMWM`C8>Qby!i)Io_QguIp`+tQH7ctzMSWs~xlQ9B8t^{T<&Bd<2) zF+E7Mikhsjq4H?3v`&R$oRUNy+5a7TPG|2q_k4f9&-eGc_xJzb|Ly%t@aEfBt=GFgdwm|8o#Q!V zNl=D74T|9PJNtiStZPb@CbtR`7tYXw&+8qJb9CNNq|R=S)1*rqoJ%c>dVKWoec5$B zIYlgtpBpcqkXIRA%1;Vsp56Ug!UEGum*JMnZyS-ct=RhUF6Th-kL;ELC5INh$Y=M( zi%oX%A1J0s;~^QdABX6bmz$XLZ1w?{(|*=3O1@J0R9@fF#?EVlCCimu_W+@5Z=roZ z^Pc>lKfRmWHq62w1S{%%TC?1ZJM!)FL(611qfJ$M9Trqt`46Sr8{nN6xfS7J<5vrX z6w~PE&wOQzpP2Ph$BR!2?Ck|J)yu!>cZK@(#U@CT*+Qw>xv`#8Wcog`*ai}bB!O;q zx^jsjONh3vP>e*{M1p)*pv*~ham?t^!y6YpQX?>p@>)T*$wOVA`QADk8wu8MPj_7Pu#>L@QZ|DNG-d#!x+YvY^#bEm zztzRScxs@#xA|@5>0cac$$TRtC%n!=vU;a)kJ4?gR7Mm~#ak8fnX%cr^tQ7C#W>TDC9LPe(0r!tBD48@YZ zabt$ofuw@OH|muwESuQ;56<>W2^(kH1_D%5%rbAv@)U-34VZSSqh0MDCI%~;t^bI0 z&Q#A9{(dD<>-?kK{E9W4Ba@9nh3m?OhL^0CZ9~hy6t_%|?jy4;7Sbk8ALk2l-^4Wt z*2gGR3*SHKd-_yWI9z|TDk(a;N~JloMy@l}l*b!9Tpf|x-!tp*s4l)%u4dQ0DE~-> zx+`k)9&9xuji{-Zh~}EgZGxWh{_=#W`$ye!quWAV)SB!HGWR$=Kjvgf6HIj981N`4 z8hROcG41B)`TL@gT1hGR1uR!xd2-8;}3#H_05`cAw zz;3V+z-a`)88X}vfRrZ&LkaC$1Iv(NU*Sjq>Z_H2%7F-nP@pGLYyoBkBFvG3&j~Cc w4W)vRa&hQ@l)NGXpq?h$kV`?ph&-h!%2eT}Ahe(?I#l}^=!z$~0Q9l{1x&SVvH$=8 delta 1406 zcmYk42~bm46o&H-4iLif0u5UPK}A-PL{Jbyp+eazgkg6{0s*ELaAX~&P*esH3K)oR zEuc7zVJK8UrB-xA#igxCIxGW}$}&_$2SIAUu(T~>du}&UBk=qnUd0<7ja4|1Y+$1zxl@AqCInh%|^CU4NbcY zat+EVUIfRhTWvD4yZQXDzSv+;}9p-DXac8=I0ilj1Q2W|5^;`g?`- zv+Su+$9h8?}DSnTDe%hsbqy^MPWnR&muc#Mv>w9Ixids4VTY8yVIP$-&sS#r(G z(3oOqe-h%4x|{PvtdIv@+6D4eMx?Qb^a*#$^kL9w`i!LPeYKCDOy$&$MlQ>jzP3G8 zFm<{A`nddJb5r))*<%YGx08+s@(we}_)FAmX`8g6ON+ft8knk4pMGzoWATL1;%~>F zvCm#|l}s>VEkdOOE98sGD*dd9EuvShvEgc|8|J)I2KMDWo7D;G?OYQ2*%_~xYBevG z3t8`H=*yZXb#10I{Xz$Bs^?r7Pxc=(5;-)ETOKQr+^?!}4l39Eet%F=OQ&;kr|FTO zCTVeYl|c{t1Kywf(O@`nK^W>#yq$54TX?sNPixN)DK@#>b1wXwsEEq++!xg9hVdCs zVSg>>wQG5ZN$GPB8UNv%9_9)A+g*kHF4^B7CI>HS$f@}>dLfNY{6eFHlh4{yLp~AU z&RiQJg~G&R{r|f`OrYur@COztE*BVzIdmpsM1maznj!BL_sjr@bTUoB}L None: assert recon_shim.BankReconOutputs is trackd_recon.BankReconOutputs +def test_mpl_compat_shim_exports_trackd_mpl_compat() -> None: + # The shim should re-export the package implementation (same function objects). + assert mpl_shim.ax_boxplot is trackd_mpl.ax_boxplot + + +def test_reporting_style_shim_exports_trackd_reporting_style() -> None: + # The shim should re-export the package implementation (same function objects). + assert style_shim.style_context is trackd_reporting_style.style_context + assert style_shim.save_figure is trackd_reporting_style.save_figure + assert style_shim.plot_time_series is trackd_reporting_style.plot_time_series + assert style_shim.plot_bar is trackd_reporting_style.plot_bar + assert style_shim.plot_histogram_with_markers is trackd_reporting_style.plot_histogram_with_markers + assert style_shim.plot_ecdf is trackd_reporting_style.plot_ecdf + assert style_shim.plot_waterfall_bridge is trackd_reporting_style.plot_waterfall_bridge + assert style_shim.FigureSpec is trackd_reporting_style.FigureSpec + assert style_shim.FigureManifestRow is trackd_reporting_style.FigureManifestRow + + def test_business_schema_shim_validate_schema_report_shape(tmp_path: Path) -> None: report = shim.validate_schema(tmp_path, dataset=trackd_schema.DATASET_NSO_V1) @@ -91,6 +113,31 @@ def test_track_d_template_business_recon_is_a_shim() -> None: assert "ar_rollforward_vs_tb" in text +def test_track_d_template_mpl_compat_is_a_shim() -> None: + root = Path(__file__).resolve().parents[1] + template = root / "workbooks" / "track_d_template" / "scripts" / "_mpl_compat.py" + assert template.exists() + + text = template.read_text(encoding="utf-8") + assert "pystatsv1.trackd.mpl_compat" in text + assert "ax_boxplot" in text + assert "__all__" in text + assert "import *" not in text + + +def test_track_d_template_reporting_style_is_a_shim() -> None: + root = Path(__file__).resolve().parents[1] + template = root / "workbooks" / "track_d_template" / "scripts" / "_reporting_style.py" + assert template.exists() + + text = template.read_text(encoding="utf-8") + assert "pystatsv1.trackd.reporting_style" in text + assert "style_context" in text + assert "save_figure" in text + assert "__all__" in text + assert "import *" not in text + + def test_repo_level_business_etl_shim_is_explicit() -> None: root = Path(__file__).resolve().parents[1] shim_path = root / "scripts" / "_business_etl.py" @@ -111,3 +158,25 @@ def test_repo_level_business_recon_shim_is_explicit() -> None: assert "pystatsv1.trackd.recon" in text assert "__all__" in text assert "import *" not in text + + +def test_repo_level_mpl_compat_shim_is_explicit() -> None: + root = Path(__file__).resolve().parents[1] + shim_path = root / "scripts" / "_mpl_compat.py" + assert shim_path.exists() + + text = shim_path.read_text(encoding="utf-8") + assert "pystatsv1.trackd.mpl_compat" in text + assert "__all__" in text + assert "import *" not in text + + +def test_repo_level_reporting_style_shim_is_explicit() -> None: + root = Path(__file__).resolve().parents[1] + shim_path = root / "scripts" / "_reporting_style.py" + assert shim_path.exists() + + text = shim_path.read_text(encoding="utf-8") + assert "pystatsv1.trackd.reporting_style" in text + assert "__all__" in text + assert "import *" not in text diff --git a/workbooks/track_d_template/scripts/_mpl_compat.py b/workbooks/track_d_template/scripts/_mpl_compat.py index d135899..a0b82d1 100644 --- a/workbooks/track_d_template/scripts/_mpl_compat.py +++ b/workbooks/track_d_template/scripts/_mpl_compat.py @@ -9,4 +9,8 @@ from __future__ import annotations -from pystatsv1.trackd.mpl_compat import * # noqa: F401,F403 +from pystatsv1.trackd.mpl_compat import ax_boxplot + +__all__ = [ + "ax_boxplot", +] diff --git a/workbooks/track_d_template/scripts/_reporting_style.py b/workbooks/track_d_template/scripts/_reporting_style.py index d58d60e..8331bf7 100644 --- a/workbooks/track_d_template/scripts/_reporting_style.py +++ b/workbooks/track_d_template/scripts/_reporting_style.py @@ -9,4 +9,38 @@ from __future__ import annotations -from pystatsv1.trackd.reporting_style import * # noqa: F401,F403 +from pystatsv1.trackd.reporting_style import ( + FigureManifestRow, + FigureSpec, + STYLE_CONTRACT, + ensure_allowed_chart_type, + figure_manifest_to_frame, + mpl_context, + plot_bar, + plot_ecdf, + plot_histogram_with_markers, + plot_time_series, + plot_waterfall_bridge, + save_figure, + style_context, + write_contract_json, + write_style_contract_json, +) + +__all__ = [ + "STYLE_CONTRACT", + "FigureSpec", + "FigureManifestRow", + "write_style_contract_json", + "write_contract_json", + "mpl_context", + "style_context", + "save_figure", + "plot_time_series", + "plot_bar", + "plot_histogram_with_markers", + "plot_ecdf", + "plot_waterfall_bridge", + "figure_manifest_to_frame", + "ensure_allowed_chart_type", +]