From 0a6b79222ab0129e58466747bc7629a48671e7f6 Mon Sep 17 00:00:00 2001 From: Gene Dan Date: Thu, 10 Sep 2026 21:42:15 -0500 Subject: [PATCH 01/20] [FEAT] Begin work on Styler. --- ARCHITECTURE.md | 4 +- chainladder/__init__.py | 1 + chainladder/core/__init__.py | 2 + chainladder/core/pandas.py | 13 + chainladder/core/style.py | 126 +++++++++ chainladder/core/tests/test_style.py | 137 +++++++++ chainladder/tests/test_public_api.py | 1 + docs/_toc.yml | 1 + docs/user_guide/style.ipynb | 402 +++++++++++++++++++++++++++ 9 files changed, 686 insertions(+), 1 deletion(-) create mode 100644 chainladder/core/style.py create mode 100644 chainladder/core/tests/test_style.py create mode 100644 docs/user_guide/style.ipynb diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 08a3369a9..d7916e515 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -10,7 +10,8 @@ chainladder-python/ │ │ │ ├── _config/ # Package-wide configuration │ │ ├── options.py # Datetime constants, package options -│ │ └── deprecation.py # Deprecation utilities +│ │ ├── deprecation.py # Deprecation utilities +│ │ └── tests/ │ │ │ ├── core/ # Triangle data structure │ │ ├── triangle.py # Triangle (the public-facing class) @@ -22,6 +23,7 @@ chainladder-python/ │ │ ├── slice.py # TriangleSlicer, Location, Ilocation, At, Iat, VirtualColumns │ │ ├── display.py # TriangleDisplay (__repr__, _repr_html_) │ │ ├── io.py # TriangleIO, EstimatorIO (pickle, JSON, spreadsheet I/O) +│ │ ├── style.py # Styler (adapts pandas.io.formats.style.Styler) │ │ ├── typing.py # TriangleProtocol, type aliases (BackendArray, etc.) │ │ ├── README.md # Per-file summary of this subpackage │ │ └── tests/ diff --git a/chainladder/__init__.py b/chainladder/__init__.py index 28fbc9a22..1146c1f96 100644 --- a/chainladder/__init__.py +++ b/chainladder/__init__.py @@ -55,6 +55,7 @@ Triangle, DevelopmentCorrelation, ValuationCorrelation, + Styler, ) from chainladder.development import ( # noqa (API import) DevelopmentBase, diff --git a/chainladder/core/__init__.py b/chainladder/core/__init__.py index 82cff32b3..e9f381ec5 100644 --- a/chainladder/core/__init__.py +++ b/chainladder/core/__init__.py @@ -3,9 +3,11 @@ DevelopmentCorrelation, ValuationCorrelation, ) # noqa (API import) +from chainladder.core.style import Styler # noqa (API import) __all__ = [ "Triangle", "DevelopmentCorrelation", "ValuationCorrelation", + "Styler", ] diff --git a/chainladder/core/pandas.py b/chainladder/core/pandas.py index 4b7237bae..2ff864a4a 100644 --- a/chainladder/core/pandas.py +++ b/chainladder/core/pandas.py @@ -14,6 +14,7 @@ __dt64_dtype__, _warn_dask_parallel_deprecated, ) +from chainladder.core.style import Styler from chainladder.utils.utility_functions import concat, num_to_nan from typing import cast, TYPE_CHECKING @@ -236,6 +237,18 @@ def hvplot(self, *args: Any, **kwargs: Any) -> Any: df.index = df.index.to_timestamp(how="s") return df.hvplot(*args, **kwargs) + @property + def style(self) -> Styler: + """ + Returns a Styler for the Triangle. + + Returns + ------- + Styler + A Styler wrapping this Triangle's ``to_frame()`` representation. + """ + return Styler(self.to_frame(), triangle=self) + @staticmethod def _get_axis( axis: Literal["index", "columns", "origin", "development"] | int | None, diff --git a/chainladder/core/style.py b/chainladder/core/style.py new file mode 100644 index 000000000..9dcb0d440 --- /dev/null +++ b/chainladder/core/style.py @@ -0,0 +1,126 @@ +""" +Styler for formatting Triangle output. +""" + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. +from __future__ import annotations + +import numpy as np +import pandas as pd +from pandas.io.formats.style import Styler as _PandasStyler + +from typing import Any, TYPE_CHECKING + +if TYPE_CHECKING: + from chainladder.core.typing import TriangleProtocol + +del TYPE_CHECKING +del annotations + + +class Styler(_PandasStyler): + """ + Styles a Triangle according to the data with HTML and CSS. + + This class provides methods for styling and formatting a Triangle. The + styled output can be rendered as HTML or LaTeX, and it supports CSS-based styling, allowing + users to control colors, font styles, and other visual aspects of tabular data. It is particularly + useful for presenting Triangle objects in a Jupyter Notebook environment or when exporting + styled triangles for reports. + + Parameters + ---------- + data: pd.DataFrame | pd.Series + The data to style, as for :class:`pandas.io.formats.style.Styler`. + triangle: TriangleProtocol | None + The Triangle ``data`` was produced from, e.g. via ``Triangle.to_frame()``. + Required by builtins that need to know the Triangle's actuarial + structure, such as :meth:`highlight_lower_triangle`. Optional, since a + Styler can still be built directly from an arbitrary DataFrame the same + way a pandas ``Styler`` can; those Triangle-specific builtins simply + aren't available in that case. + *args: Any + Additional positional arguments passed to + :class:`pandas.io.formats.style.Styler`. + **kwargs: Any + Additional keyword arguments passed to + :class:`pandas.io.formats.style.Styler`. + + Examples + -------- + + .. testcode:: + + import pandas as pd + from chainladder.core.style import Styler + + df = pd.DataFrame({"a": [1, 2], "b": [3, 4]}) + Styler(df).format(precision=1) + + """ + + def __init__( + self, + data: pd.DataFrame | pd.Series, + *args: Any, + triangle: TriangleProtocol | None = None, + **kwargs: Any, + ) -> None: + super().__init__(data, *args, **kwargs) + self._triangle = triangle + + def highlight_lower_triangle( + self, color: str = "blue", props: str | None = None + ) -> Styler: + """ + Highlight the lower (future, unobserved) triangle with a style. + + Parameters + ---------- + color: str + Background color applied to lower-triangle cells. Ignored if + ``props`` is given. Defaults to "yellow". + props: str | None + A full CSS properties string to apply instead of ``color``, e.g. + ``"background-color: blue; opacity: 60%;"``. Optional. + + Returns + ------- + Styler + + Examples + -------- + + .. testcode:: + :options: +SKIP + + import chainladder as cl + + cl.load_sample("raa").style.highlight_lower_triangle(color="lightgray") + + """ + if self._triangle is None: + raise ValueError( + "highlight_lower_triangle requires a Styler created from " + "Triangle.style, so it knows which cells are the lower triangle." + ) + nan_triangle = self._triangle.nan_triangle + # Densify backends (sparse, cupy, ...) that don't support pd.isna() directly. + nan_triangle = ( + nan_triangle.todense() # pyright: ignore[reportAttributeAccessIssue] + if hasattr(nan_triangle, "todense") + else np.asarray(nan_triangle) + ) + if nan_triangle.shape != self.data.shape: + raise ValueError( + "highlight_lower_triangle only supports a single (2-D) Triangle." + ) + + def f(_data: pd.DataFrame, props: str) -> np.ndarray: + return np.where(pd.isna(nan_triangle), props, "") + + if props is None: + props = f"background-color: {color};" + return self.apply(f, axis=None, props=props) # pyright: ignore[reportReturnType] diff --git a/chainladder/core/tests/test_style.py b/chainladder/core/tests/test_style.py new file mode 100644 index 000000000..d7e48fd99 --- /dev/null +++ b/chainladder/core/tests/test_style.py @@ -0,0 +1,137 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. +from __future__ import annotations + +import numpy as np +import pandas as pd +import pytest +from pandas.io.formats.style import Styler as PandasStyler + +import chainladder as cl +from chainladder.core.style import Styler + + +@pytest.fixture +def df() -> pd.DataFrame: + return pd.DataFrame({"a": [1, 2], "b": [3, 4]}) + + +def test_is_public() -> None: + """Check that Styler is importable from the top-level chainladder package.""" + assert cl.Styler is Styler + + +def test_is_pandas_styler_subclass() -> None: + """Check that Styler extends pandas' own Styler rather than replacing it.""" + assert issubclass(Styler, PandasStyler) + + +def test_wraps_a_dataframe(df: pd.DataFrame) -> None: + """Check that Styler wraps a DataFrame the same way pandas' Styler does.""" + styler = Styler(df) + assert styler.data is df + + +def test_chained_methods_preserve_subclass(df: pd.DataFrame) -> None: + """Check that chaining a pandas Styler method still returns a chainladder Styler, + not a plain pandas Styler -- the methods mutate self and return self, so + subclassing doesn't get lost partway through a chain. + """ + # pandas types .format()/.hide() as returning StylerRenderer (their defining + # base class) rather than Self, so a type checker loses the subclass after + # chaining even though the runtime object is still a Styler -- see the + # isinstance assertion below. + result = ( + Styler(df) + .format(precision=1) + .hide( # pyright: ignore[reportAttributeAccessIssue] + axis="columns", subset=["a"] + ) + ) + assert isinstance(result, Styler) + + +def test_renders_identically_to_pandas_styler(df: pd.DataFrame) -> None: + """Check that Styler produces the same HTML as pandas' own Styler, uuid aside -- + confirms the subclass doesn't alter behavior, matching the goal of starting as + a pure adapter before adding Triangle-specific behavior. + """ + # Same StylerRenderer-vs-Self typing gap as above, on pandas' own side too. + cl_html = Styler(df, uuid="fixed").format(precision=2).to_html() # pyright: ignore[reportAttributeAccessIssue] + pd_html = PandasStyler(df, uuid="fixed").format(precision=2).to_html() # pyright: ignore[reportAttributeAccessIssue] + assert cl_html == pd_html + + +def test_triangle_style_is_a_property(raa) -> None: + """Check that Triangle.style is a property, matching pandas.DataFrame.style, + rather than a method that must be called. + """ + assert isinstance(type(raa).style, property) + + +def test_triangle_style_returns_styler(raa) -> None: + """Check that Triangle.style returns a chainladder Styler.""" + assert isinstance(raa.style, Styler) + + +def test_triangle_style_wraps_to_frame(raa) -> None: + """Check that Triangle.style wraps the same data as Triangle.to_frame().""" + pd.testing.assert_frame_equal(raa.style.data, raa.to_frame()) + + +def test_triangle_style_is_fresh_each_access(raa) -> None: + """Check that each access to Triangle.style returns a new Styler, matching + pandas.DataFrame.style's own behavior -- so unrelated uses don't share state + or a uuid. + """ + assert raa.style is not raa.style + + +def test_highlight_lower_triangle_styles_exactly_the_lower_triangle(raa) -> None: + """Check that every styled cell -- and only those cells -- correspond to a + NaN in the Triangle's own nan_triangle mask. + """ + styler = raa.style.highlight_lower_triangle(color="lightgray") + styler._compute() + styled = {k for k, v in styler.ctx.items() if v} + + expected = { + (r, c) + for r, row in enumerate(np.isnan(raa.nan_triangle)) + for c, is_lower in enumerate(row) + if is_lower + } + assert styled == expected + assert all(v == [("background-color", "lightgray")] for v in styler.ctx.values() if v) + + +def test_highlight_lower_triangle_props_overrides_color(raa) -> None: + """Check that a custom props string is used verbatim instead of color.""" + styler = raa.style.highlight_lower_triangle( + color="lightgray", props="background-color: blue; opacity: 50%;" + ) + assert "opacity: 50%" in styler.to_html() + assert "lightgray" not in styler.to_html() + + +def test_highlight_lower_triangle_returns_styler(raa) -> None: + """Check that the subclass is preserved through the chained call.""" + assert isinstance(raa.style.highlight_lower_triangle(), Styler) + + +def test_highlight_lower_triangle_requires_a_triangle(df: pd.DataFrame) -> None: + """Check that calling it on a Styler not built from Triangle.style raises a + clear error, since there's no way to know which cells are the lower triangle. + """ + with pytest.raises(ValueError, match="requires a Styler created from Triangle.style"): + Styler(df).highlight_lower_triangle() + + +def test_highlight_lower_triangle_requires_matching_shape(clrd) -> None: + """Check that a Triangle whose to_frame() isn't a single origin-by-development + grid (multiple index labels and columns, here) raises a clear error rather + than silently misaligning the mask. + """ + with pytest.raises(ValueError, match="single origin-by-development grid"): + clrd.style.highlight_lower_triangle() diff --git a/chainladder/tests/test_public_api.py b/chainladder/tests/test_public_api.py index 92515166d..715efe6d1 100644 --- a/chainladder/tests/test_public_api.py +++ b/chainladder/tests/test_public_api.py @@ -22,6 +22,7 @@ "Triangle", "DevelopmentCorrelation", "ValuationCorrelation", + "Styler", # utils "WeightedRegression", "TriangleWeight", diff --git a/docs/_toc.yml b/docs/_toc.yml index 9dc793bc2..cce999af9 100644 --- a/docs/_toc.yml +++ b/docs/_toc.yml @@ -30,6 +30,7 @@ parts: - file: user_guide/adjustments.ipynb - file: user_guide/workflow.ipynb - file: user_guide/utilities.ipynb + - file: user_guide/style.ipynb - chapters: - file: friedland/index.rst sections: diff --git a/docs/user_guide/style.ipynb b/docs/user_guide/style.ipynb new file mode 100644 index 000000000..8fedc32fa --- /dev/null +++ b/docs/user_guide/style.ipynb @@ -0,0 +1,402 @@ +{ + "cells": [ + { + "metadata": { + "collapsed": true + }, + "cell_type": "markdown", + "source": "# Triangle Visualization", + "id": "ed15c4047e2dbe21" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-09-11T02:24:36.821983759Z", + "start_time": "2026-09-11T02:24:35.894500240Z" + } + }, + "cell_type": "code", + "source": [ + "import chainladder as cl\n", + "raa = cl.load_sample('raa')\n", + "raa" + ], + "id": "65fd12501acef112", + "outputs": [ + { + "data": { + "text/plain": [ + " 12 24 36 48 60 72 84 96 108 120\n", + "1981 5012.0 8269.0 10907.0 11805.0 13539.0 16181.0 18009.0 18608.0 18662.0 18834.0\n", + "1982 106.0 4285.0 5396.0 10666.0 13782.0 15599.0 15496.0 16169.0 16704.0 NaN\n", + "1983 3410.0 8992.0 13873.0 16141.0 18735.0 22214.0 22863.0 23466.0 NaN NaN\n", + "1984 5655.0 11555.0 15766.0 21266.0 23425.0 26083.0 27067.0 NaN NaN NaN\n", + "1985 1092.0 9565.0 15836.0 22169.0 25955.0 26180.0 NaN NaN NaN NaN\n", + "1986 1513.0 6445.0 11702.0 12935.0 15852.0 NaN NaN NaN NaN NaN\n", + "1987 557.0 4020.0 10946.0 12314.0 NaN NaN NaN NaN NaN NaN\n", + "1988 1351.0 6947.0 13112.0 NaN NaN NaN NaN NaN NaN NaN\n", + "1989 3133.0 5395.0 NaN NaN NaN NaN NaN NaN NaN NaN\n", + "1990 2063.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN" + ], + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
1224364860728496108120
19815,0128,26910,90711,80513,53916,18118,00918,60818,66218,834
19821064,2855,39610,66613,78215,59915,49616,16916,704
19833,4108,99213,87316,14118,73522,21422,86323,466
19845,65511,55515,76621,26623,42526,08327,067
19851,0929,56515,83622,16925,95526,180
19861,5136,44511,70212,93515,852
19875574,02010,94612,314
19881,3516,94713,112
19893,1335,395
19902,063
" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 1 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-09-11T02:24:50.485094458Z", + "start_time": "2026-09-11T02:24:50.430955602Z" + } + }, + "cell_type": "code", + "source": "raa.style.highlight_lower_triangle(color='blue')", + "id": "82b1c3255e22bc03", + "outputs": [ + { + "data": { + "text/plain": [ + "" + ], + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 1224364860728496108120
1981-01-01 00:00:005012.0000008269.00000010907.00000011805.00000013539.00000016181.00000018009.00000018608.00000018662.00000018834.000000
1982-01-01 00:00:00106.0000004285.0000005396.00000010666.00000013782.00000015599.00000015496.00000016169.00000016704.000000nan
1983-01-01 00:00:003410.0000008992.00000013873.00000016141.00000018735.00000022214.00000022863.00000023466.000000nannan
1984-01-01 00:00:005655.00000011555.00000015766.00000021266.00000023425.00000026083.00000027067.000000nannannan
1985-01-01 00:00:001092.0000009565.00000015836.00000022169.00000025955.00000026180.000000nannannannan
1986-01-01 00:00:001513.0000006445.00000011702.00000012935.00000015852.000000nannannannannan
1987-01-01 00:00:00557.0000004020.00000010946.00000012314.000000nannannannannannan
1988-01-01 00:00:001351.0000006947.00000013112.000000nannannannannannannan
1989-01-01 00:00:003133.0000005395.000000nannannannannannannannan
1990-01-01 00:00:002063.000000nannannannannannannannannan
\n" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 3 + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 579d2d61fbaec7a2cd215b62af247cf4f0879df9 Mon Sep 17 00:00:00 2001 From: Gene Dan Date: Thu, 10 Sep 2026 21:54:40 -0500 Subject: [PATCH 02/20] [FIX] Apply Ruff fix. --- chainladder/core/style.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chainladder/core/style.py b/chainladder/core/style.py index 9dcb0d440..b0c726136 100644 --- a/chainladder/core/style.py +++ b/chainladder/core/style.py @@ -81,7 +81,7 @@ def highlight_lower_triangle( ---------- color: str Background color applied to lower-triangle cells. Ignored if - ``props`` is given. Defaults to "yellow". + ``props`` is given. Defaults to "blue". props: str | None A full CSS properties string to apply instead of ``color``, e.g. ``"background-color: blue; opacity: 60%;"``. Optional. From 90d6c4633989d6de6fb373124f15dbe241a03416 Mon Sep 17 00:00:00 2001 From: Gene Dan Date: Thu, 10 Sep 2026 22:02:24 -0500 Subject: [PATCH 03/20] [FIX] Apply Ruff fix. --- chainladder/core/tests/test_style.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chainladder/core/tests/test_style.py b/chainladder/core/tests/test_style.py index d7e48fd99..a4e1e90ee 100644 --- a/chainladder/core/tests/test_style.py +++ b/chainladder/core/tests/test_style.py @@ -133,5 +133,5 @@ def test_highlight_lower_triangle_requires_matching_shape(clrd) -> None: grid (multiple index labels and columns, here) raises a clear error rather than silently misaligning the mask. """ - with pytest.raises(ValueError, match="single origin-by-development grid"): + with pytest.raises(ValueError, match="only supports a single \\(2-D\\) Triangle"): clrd.style.highlight_lower_triangle() From f826b7af2c92332f775ff190caec79992dc3549a Mon Sep 17 00:00:00 2001 From: Gene Dan Date: Thu, 10 Sep 2026 22:10:21 -0500 Subject: [PATCH 04/20] [FIX] Apply Ruff fix. --- chainladder/core/tests/test_style.py | 8 +++- docs/user_guide/style.ipynb | 65 +++++++++++++++------------- 2 files changed, 40 insertions(+), 33 deletions(-) diff --git a/chainladder/core/tests/test_style.py b/chainladder/core/tests/test_style.py index a4e1e90ee..352261cb0 100644 --- a/chainladder/core/tests/test_style.py +++ b/chainladder/core/tests/test_style.py @@ -103,7 +103,9 @@ def test_highlight_lower_triangle_styles_exactly_the_lower_triangle(raa) -> None if is_lower } assert styled == expected - assert all(v == [("background-color", "lightgray")] for v in styler.ctx.values() if v) + assert all( + v == [("background-color", "lightgray")] for v in styler.ctx.values() if v + ) def test_highlight_lower_triangle_props_overrides_color(raa) -> None: @@ -124,7 +126,9 @@ def test_highlight_lower_triangle_requires_a_triangle(df: pd.DataFrame) -> None: """Check that calling it on a Styler not built from Triangle.style raises a clear error, since there's no way to know which cells are the lower triangle. """ - with pytest.raises(ValueError, match="requires a Styler created from Triangle.style"): + with pytest.raises( + ValueError, match="requires a Styler created from Triangle.style" + ): Styler(df).highlight_lower_triangle() diff --git a/docs/user_guide/style.ipynb b/docs/user_guide/style.ipynb index 8fedc32fa..604059bc3 100644 --- a/docs/user_guide/style.ipynb +++ b/docs/user_guide/style.ipynb @@ -1,43 +1,26 @@ { "cells": [ { + "cell_type": "markdown", + "id": "ed15c4047e2dbe21", "metadata": { "collapsed": true }, - "cell_type": "markdown", - "source": "# Triangle Visualization", - "id": "ed15c4047e2dbe21" + "source": "# Triangle Visualization" }, { + "cell_type": "code", + "execution_count": 1, + "id": "65fd12501acef112", "metadata": { "ExecuteTime": { "end_time": "2026-09-11T02:24:36.821983759Z", "start_time": "2026-09-11T02:24:35.894500240Z" } }, - "cell_type": "code", - "source": [ - "import chainladder as cl\n", - "raa = cl.load_sample('raa')\n", - "raa" - ], - "id": "65fd12501acef112", "outputs": [ { "data": { - "text/plain": [ - " 12 24 36 48 60 72 84 96 108 120\n", - "1981 5012.0 8269.0 10907.0 11805.0 13539.0 16181.0 18009.0 18608.0 18662.0 18834.0\n", - "1982 106.0 4285.0 5396.0 10666.0 13782.0 15599.0 15496.0 16169.0 16704.0 NaN\n", - "1983 3410.0 8992.0 13873.0 16141.0 18735.0 22214.0 22863.0 23466.0 NaN NaN\n", - "1984 5655.0 11555.0 15766.0 21266.0 23425.0 26083.0 27067.0 NaN NaN NaN\n", - "1985 1092.0 9565.0 15836.0 22169.0 25955.0 26180.0 NaN NaN NaN NaN\n", - "1986 1513.0 6445.0 11702.0 12935.0 15852.0 NaN NaN NaN NaN NaN\n", - "1987 557.0 4020.0 10946.0 12314.0 NaN NaN NaN NaN NaN NaN\n", - "1988 1351.0 6947.0 13112.0 NaN NaN NaN NaN NaN NaN NaN\n", - "1989 3133.0 5395.0 NaN NaN NaN NaN NaN NaN NaN NaN\n", - "1990 2063.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN" - ], "text/html": [ "\n", " \n", @@ -188,6 +171,19 @@ " \n", " \n", "
" + ], + "text/plain": [ + " 12 24 36 48 60 72 84 96 108 120\n", + "1981 5012.0 8269.0 10907.0 11805.0 13539.0 16181.0 18009.0 18608.0 18662.0 18834.0\n", + "1982 106.0 4285.0 5396.0 10666.0 13782.0 15599.0 15496.0 16169.0 16704.0 NaN\n", + "1983 3410.0 8992.0 13873.0 16141.0 18735.0 22214.0 22863.0 23466.0 NaN NaN\n", + "1984 5655.0 11555.0 15766.0 21266.0 23425.0 26083.0 27067.0 NaN NaN NaN\n", + "1985 1092.0 9565.0 15836.0 22169.0 25955.0 26180.0 NaN NaN NaN NaN\n", + "1986 1513.0 6445.0 11702.0 12935.0 15852.0 NaN NaN NaN NaN NaN\n", + "1987 557.0 4020.0 10946.0 12314.0 NaN NaN NaN NaN NaN NaN\n", + "1988 1351.0 6947.0 13112.0 NaN NaN NaN NaN NaN NaN NaN\n", + "1989 3133.0 5395.0 NaN NaN NaN NaN NaN NaN NaN NaN\n", + "1990 2063.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN" ] }, "execution_count": 1, @@ -195,24 +191,26 @@ "output_type": "execute_result" } ], - "execution_count": 1 + "source": [ + "import chainladder as cl\n", + "\n", + "raa = cl.load_sample(\"raa\")\n", + "raa" + ] }, { + "cell_type": "code", + "execution_count": 3, + "id": "82b1c3255e22bc03", "metadata": { "ExecuteTime": { "end_time": "2026-09-11T02:24:50.485094458Z", "start_time": "2026-09-11T02:24:50.430955602Z" } }, - "cell_type": "code", - "source": "raa.style.highlight_lower_triangle(color='blue')", - "id": "82b1c3255e22bc03", "outputs": [ { "data": { - "text/plain": [ - "" - ], "text/html": [ "\n", - "\n", + "
\n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "
 12243648607284961081201224364860728496108120
1981-01-01 00:00:005012.0000008269.00000010907.00000011805.00000013539.00000016181.00000018009.00000018608.00000018662.00000018834.00000019815012.0000008269.00000010907.00000011805.00000013539.00000016181.00000018009.00000018608.00000018662.00000018834.000000
1982-01-01 00:00:00106.0000004285.0000005396.00000010666.00000013782.00000015599.00000015496.00000016169.00000016704.000000nan1982106.0000004285.0000005396.00000010666.00000013782.00000015599.00000015496.00000016169.00000016704.000000nan
1983-01-01 00:00:003410.0000008992.00000013873.00000016141.00000018735.00000022214.00000022863.00000023466.000000nannan19833410.0000008992.00000013873.00000016141.00000018735.00000022214.00000022863.00000023466.000000nannan
1984-01-01 00:00:005655.00000011555.00000015766.00000021266.00000023425.00000026083.00000027067.000000nannannan19845655.00000011555.00000015766.00000021266.00000023425.00000026083.00000027067.000000nannannan
1985-01-01 00:00:001092.0000009565.00000015836.00000022169.00000025955.00000026180.000000nannannannan19851092.0000009565.00000015836.00000022169.00000025955.00000026180.000000nannannannan
1986-01-01 00:00:001513.0000006445.00000011702.00000012935.00000015852.000000nannannannannan19861513.0000006445.00000011702.00000012935.00000015852.000000nannannannannan
1987-01-01 00:00:00557.0000004020.00000010946.00000012314.000000nannannannannannan1987557.0000004020.00000010946.00000012314.000000nannannannannannan
1988-01-01 00:00:001351.0000006947.00000013112.000000nannannannannannannan19881351.0000006947.00000013112.000000nannannannannannannan
1989-01-01 00:00:003133.0000005395.000000nannannannannannannannan19893133.0000005395.000000nannannannannannannannan
1990-01-01 00:00:002063.000000nannannannannannannannannan19902063.000000nannannannannannannannannan
\n" - ], - "text/plain": [ - "" ] }, - "execution_count": 3, + "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], - "source": [ - "raa.style.highlight_lower_triangle(color=\"blue\")" - ] + "execution_count": 2 } ], "metadata": { From 8848e9c247fd5a11130fd08d980c91a02e6bb41a Mon Sep 17 00:00:00 2001 From: Gene Dan Date: Fri, 11 Sep 2026 06:05:53 -0500 Subject: [PATCH 06/20] [FEAT] Add option to toggle Jupyter pretty printing. --- chainladder/core/pandas.py | 9 +- docs/user_guide/style.ipynb | 262 ++++++++++++++++++------------------ 2 files changed, 139 insertions(+), 132 deletions(-) diff --git a/chainladder/core/pandas.py b/chainladder/core/pandas.py index 33d66ba3a..9466bc864 100644 --- a/chainladder/core/pandas.py +++ b/chainladder/core/pandas.py @@ -247,7 +247,14 @@ def style(self) -> Styler: Styler A Styler wrapping this Triangle's ``to_frame()`` representation. """ - return Styler(self.to_frame(origin_as_datetime=False), triangle=self) + data = self.to_frame(origin_as_datetime=False) + styler = Styler(data, triangle=self) + if self._dimensionality == "single": + fmt_str = self._get_format_str(data=data) + styler = styler.format( # pyright: ignore[reportReturnType] + fmt_str, na_rep="" + ) + return styler @staticmethod def _get_axis( diff --git a/docs/user_guide/style.ipynb b/docs/user_guide/style.ipynb index b0ebe413d..0b7c223b1 100644 --- a/docs/user_guide/style.ipynb +++ b/docs/user_guide/style.ipynb @@ -13,8 +13,8 @@ "id": "65fd12501acef112", "metadata": { "ExecuteTime": { - "end_time": "2026-09-11T10:19:26.024042529Z", - "start_time": "2026-09-11T10:19:25.140225693Z" + "end_time": "2026-09-11T11:04:53.630857940Z", + "start_time": "2026-09-11T11:04:53.551399080Z" } }, "source": [ @@ -191,20 +191,20 @@ "" ] }, - "execution_count": 1, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], - "execution_count": 1 + "execution_count": 3 }, { "cell_type": "code", "id": "82b1c3255e22bc03", "metadata": { "ExecuteTime": { - "end_time": "2026-09-11T10:19:26.365613456Z", - "start_time": "2026-09-11T10:19:26.089788967Z" + "end_time": "2026-09-11T11:04:54.274913267Z", + "start_time": "2026-09-11T11:04:54.031259837Z" } }, "source": [ @@ -214,171 +214,171 @@ { "data": { "text/plain": [ - "" + "" ], "text/html": [ "\n", - "\n", + "
\n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "
 12243648607284961081201224364860728496108120
19815012.0000008269.00000010907.00000011805.00000013539.00000016181.00000018009.00000018608.00000018662.00000018834.00000019815,0128,26910,90711,80513,53916,18118,00918,60818,66218,834
1982106.0000004285.0000005396.00000010666.00000013782.00000015599.00000015496.00000016169.00000016704.000000nan19821064,2855,39610,66613,78215,59915,49616,16916,704
19833410.0000008992.00000013873.00000016141.00000018735.00000022214.00000022863.00000023466.000000nannan19833,4108,99213,87316,14118,73522,21422,86323,466
19845655.00000011555.00000015766.00000021266.00000023425.00000026083.00000027067.000000nannannan19845,65511,55515,76621,26623,42526,08327,067
19851092.0000009565.00000015836.00000022169.00000025955.00000026180.000000nannannannan19851,0929,56515,83622,16925,95526,180
19861513.0000006445.00000011702.00000012935.00000015852.000000nannannannannan19861,5136,44511,70212,93515,852
1987557.0000004020.00000010946.00000012314.000000nannannannannannan19875574,02010,94612,314
19881351.0000006947.00000013112.000000nannannannannannannan19881,3516,94713,112
19893133.0000005395.000000nannannannannannannannan19893,1335,395
19902063.000000nannannannannannannannannan19902,063
\n" ] }, - "execution_count": 2, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], - "execution_count": 2 + "execution_count": 4 } ], "metadata": { From b40db16ff3c4a5381b1ada0bba1fbd6c043907b5 Mon Sep 17 00:00:00 2001 From: Gene Dan Date: Fri, 11 Sep 2026 16:13:15 -0500 Subject: [PATCH 07/20] [FIX] Fix broken tests. --- chainladder/core/style.py | 35 +- chainladder/core/tests/test_style.py | 52 ++- chainladder/core/typing.py | 55 ++- docs/user_guide/style.ipynb | 563 +++++++++++++++++++-------- 4 files changed, 511 insertions(+), 194 deletions(-) diff --git a/chainladder/core/style.py b/chainladder/core/style.py index b0c726136..267f5bf6c 100644 --- a/chainladder/core/style.py +++ b/chainladder/core/style.py @@ -72,10 +72,14 @@ def __init__( self._triangle = triangle def highlight_lower_triangle( - self, color: str = "blue", props: str | None = None + self, + color: str = "blue", + props: str | None = None, + valuation_date: Any = None, ) -> Styler: """ - Highlight the lower (future, unobserved) triangle with a style. + Highlight the lower triangle -- the cells beyond the Triangle's + latest diagonal -- with a style. Parameters ---------- @@ -85,6 +89,10 @@ def highlight_lower_triangle( props: str | None A full CSS properties string to apply instead of ``color``, e.g. ``"background-color: blue; opacity: 60%;"``. Optional. + valuation_date: Any + The "as of" date used to determine which cells fall beyond the + latest diagonal, i.e. the lower triangle. If ``None``, defaults to the + wrapped Triangle's own ``valuation_date``. Returns ------- @@ -100,19 +108,30 @@ def highlight_lower_triangle( cl.load_sample("raa").style.highlight_lower_triangle(color="lightgray") + Highlighting a fully-predicted Triangle requires the original + valuation date, since its cells are no longer ``NaN``. + + .. testcode:: + :options: +SKIP + + raa = cl.load_sample("raa") + full = cl.Chainladder().fit(raa).full_triangle_ + full.style.highlight_lower_triangle( + color="lightgray", valuation_date=raa.valuation_date + ) + """ if self._triangle is None: raise ValueError( "highlight_lower_triangle requires a Styler created from " "Triangle.style, so it knows which cells are the lower triangle." ) - nan_triangle = self._triangle.nan_triangle - # Densify backends (sparse, cupy, ...) that don't support pd.isna() directly. - nan_triangle = ( - nan_triangle.todense() # pyright: ignore[reportAttributeAccessIssue] - if hasattr(nan_triangle, "todense") - else np.asarray(nan_triangle) + if valuation_date is None: + valuation_date = self._triangle.valuation_date + val_array = np.array(self._triangle.valuation).reshape( + self._triangle.shape[-2:], order="f" ) + nan_triangle = np.where(val_array > pd.Timestamp(valuation_date), np.nan, 1) if nan_triangle.shape != self.data.shape: raise ValueError( "highlight_lower_triangle only supports a single (2-D) Triangle." diff --git a/chainladder/core/tests/test_style.py b/chainladder/core/tests/test_style.py index 352261cb0..ea89c71af 100644 --- a/chainladder/core/tests/test_style.py +++ b/chainladder/core/tests/test_style.py @@ -76,8 +76,14 @@ def test_triangle_style_returns_styler(raa) -> None: def test_triangle_style_wraps_to_frame(raa) -> None: - """Check that Triangle.style wraps the same data as Triangle.to_frame().""" - pd.testing.assert_frame_equal(raa.style.data, raa.to_frame()) + """Check that Triangle.style wraps the same data as + Triangle.to_frame(origin_as_datetime=False) -- the origin stays a + PeriodIndex rather than converting to datetime, so it renders compactly + (e.g. "1981") instead of "1981-01-01 00:00:00". + """ + pd.testing.assert_frame_equal( + raa.style.data, raa.to_frame(origin_as_datetime=False) + ) def test_triangle_style_is_fresh_each_access(raa) -> None: @@ -132,6 +138,48 @@ def test_highlight_lower_triangle_requires_a_triangle(df: pd.DataFrame) -> None: Styler(df).highlight_lower_triangle() +def test_highlight_lower_triangle_predicted_cells_not_highlighted_by_default( + raa, +) -> None: + """A fully-predicted Triangle (e.g. full_triangle_) has no NaN cells left, + and once it carries an ultimate column its own nan_triangle collapses to + all-observed -- so without an explicit valuation_date, nothing gets + highlighted. + """ + full = cl.Chainladder().fit(raa).full_triangle_ + styler = full.style.highlight_lower_triangle(color="lightgray") + styler._compute() + assert not any(styler.ctx.values()) + + +def test_highlight_lower_triangle_with_valuation_date_highlights_predicted_cells( + raa, +) -> None: + """Passing the original valuation_date recovers which cells were originally + the lower (unobserved) triangle, even though they've since been filled in + with predicted values. + """ + full = cl.Chainladder().fit(raa).full_triangle_ + styler = full.style.highlight_lower_triangle( + color="lightgray", valuation_date=raa.valuation_date + ) + styler._compute() + styled = {k for k, v in styler.ctx.items() if v} + + val_array = np.array(full.valuation).reshape(full.shape[-2:], order="f") + expected = { + (r, c) + for r, row in enumerate(val_array > raa.valuation_date) + for c, is_lower in enumerate(row) + if is_lower + } + assert styled == expected + assert len(styled) > 0 + assert all( + v == [("background-color", "lightgray")] for v in styler.ctx.values() if v + ) + + def test_highlight_lower_triangle_requires_matching_shape(clrd) -> None: """Check that a Triangle whose to_frame() isn't a single origin-by-development grid (multiple index labels and columns, here) raises a clear error rather diff --git a/chainladder/core/typing.py b/chainladder/core/typing.py index ae0405193..c3468884e 100644 --- a/chainladder/core/typing.py +++ b/chainladder/core/typing.py @@ -11,7 +11,7 @@ Protocol, # Self, # Make use of this once Python 3.10 is deprecated. TYPE_CHECKING, - TypeAlias + TypeAlias, ) if TYPE_CHECKING: @@ -25,7 +25,7 @@ Ilocation, Location, TriangleSlicer, - VirtualColumns + VirtualColumns, ) from numpy.typing import ArrayLike from pandas import DataFrame, Series @@ -49,10 +49,12 @@ # before index_key/other_key resolve it to a positional _AxisKey. _LabelKey: TypeAlias = IndexExpression | str | pd.Series | pd.DataFrame + class TriangleProtocol(Protocol): """ Common interface expected for Triangle mixins. """ + @property def shape(self) -> tuple[int, int, int, int]: ... @@ -84,6 +86,9 @@ def development(self, value: Any) -> None: ... @property def nan_triangle(self) -> BackendArray: ... + @property + def valuation(self) -> pd.DatetimeIndex: ... + key_labels: list[str] values: BackendArray array_backend: str @@ -96,7 +101,9 @@ def nan_triangle(self) -> BackendArray: ... def __len__(self) -> int: ... def get_array_module(self, arr: ArrayLike | None = None) -> ModuleType: ... def copy(self) -> Triangle: ... - def set_backend(self, backend: str, inplace: bool = False, **kwargs) -> Triangle: ... + def set_backend( + self, backend: str, inplace: bool = False, **kwargs + ) -> Triangle: ... def drop( self, labels: str | int | list | None = None, @@ -108,7 +115,9 @@ def drop( ) -> Triangle: ... def val_to_dev(self) -> Triangle: ... def _repr_format(self, origin_as_datetime: bool = False) -> pd.DataFrame: ... - def _slice(self, key: pd.Series | np.ndarray, axis: Literal['ddims', 'odims']) -> Triangle: ... + def _slice( + self, key: pd.Series | np.ndarray, axis: Literal["ddims", "odims"] + ) -> Triangle: ... def _slice_valuation(self, key: np.ndarray) -> Triangle: ... def to_frame( self, @@ -116,16 +125,36 @@ def to_frame( keepdims: bool = False, implicit_axis: bool = False, ) -> DataFrame | Series: ... - def sum(self, axis: str | int | None = None, *args, **kwargs) -> TriangleProtocol: ... # -> Self once Python 3.10 is deprecated. - def fillna(self, value: int | float | ndarray, inplace: bool = False) -> TriangleProtocol: ... # -> Self once Python 3.10 is deprecated. - def fillzero(self, inplace: bool = False) -> TriangleProtocol: ... # -> Self once Python 3.10 is deprecated. - def __round__(self, ndigits: int = 0) -> TriangleProtocol: ... # -> Self once Python 3.10 is deprecated. - def __add__(self, other: Any) -> TriangleProtocol: ... # -> Self once Python 3.10 is deprecated. - def __radd__(self, other: Any) -> TriangleProtocol: ... # -> Self once Python 3.10 is deprecated. - def __mul__(self, other: Any) -> TriangleProtocol: ... # -> Self once Python 3.10 is deprecated. - def __rmul__(self, other: Any) -> TriangleProtocol: ... # -> Self once Python 3.10 is deprecated. + def sum( + self, axis: str | int | None = None, *args, **kwargs + ) -> TriangleProtocol: ... # -> Self once Python 3.10 is deprecated. + def fillna( + self, value: int | float | ndarray, inplace: bool = False + ) -> TriangleProtocol: ... # -> Self once Python 3.10 is deprecated. + def fillzero( + self, inplace: bool = False + ) -> TriangleProtocol: ... # -> Self once Python 3.10 is deprecated. + def __round__( + self, ndigits: int = 0 + ) -> TriangleProtocol: ... # -> Self once Python 3.10 is deprecated. + def __add__( + self, other: Any + ) -> TriangleProtocol: ... # -> Self once Python 3.10 is deprecated. + def __radd__( + self, other: Any + ) -> TriangleProtocol: ... # -> Self once Python 3.10 is deprecated. + def __mul__( + self, other: Any + ) -> TriangleProtocol: ... # -> Self once Python 3.10 is deprecated. + def __rmul__( + self, other: Any + ) -> TriangleProtocol: ... # -> Self once Python 3.10 is deprecated. @overload def __getitem__(self, key: pd.Series | np.ndarray | list[str]) -> Triangle: ... @overload def __getitem__(self, key: str | int) -> Triangle | Series: ... - def __setitem__(self, key: str | int, value: int | float | TriangleSlicer | Callable[[Triangle], TriangleSlicer]) -> None: ... \ No newline at end of file + def __setitem__( + self, + key: str | int, + value: int | float | TriangleSlicer | Callable[[Triangle], TriangleSlicer], + ) -> None: ... diff --git a/docs/user_guide/style.ipynb b/docs/user_guide/style.ipynb index 0b7c223b1..7e2c52d83 100644 --- a/docs/user_guide/style.ipynb +++ b/docs/user_guide/style.ipynb @@ -6,39 +6,29 @@ "metadata": { "collapsed": true }, - "source": "# Triangle Visualization" + "source": [ + "# Triangle Visualization" + ] }, { "cell_type": "code", + "execution_count": 1, "id": "65fd12501acef112", "metadata": { "ExecuteTime": { "end_time": "2026-09-11T11:04:53.630857940Z", "start_time": "2026-09-11T11:04:53.551399080Z" + }, + "execution": { + "iopub.execute_input": "2026-09-11T11:27:41.994746Z", + "iopub.status.busy": "2026-09-11T11:27:41.994641Z", + "iopub.status.idle": "2026-09-11T11:27:43.118228Z", + "shell.execute_reply": "2026-09-11T11:27:43.117714Z" } }, - "source": [ - "import chainladder as cl\n", - "\n", - "raa = cl.load_sample(\"raa\")\n", - "raa" - ], "outputs": [ { "data": { - "text/plain": [ - " 12 24 36 48 60 72 84 96 108 120\n", - "1981 5012.0 8269.0 10907.0 11805.0 13539.0 16181.0 18009.0 18608.0 18662.0 18834.0\n", - "1982 106.0 4285.0 5396.0 10666.0 13782.0 15599.0 15496.0 16169.0 16704.0 NaN\n", - "1983 3410.0 8992.0 13873.0 16141.0 18735.0 22214.0 22863.0 23466.0 NaN NaN\n", - "1984 5655.0 11555.0 15766.0 21266.0 23425.0 26083.0 27067.0 NaN NaN NaN\n", - "1985 1092.0 9565.0 15836.0 22169.0 25955.0 26180.0 NaN NaN NaN NaN\n", - "1986 1513.0 6445.0 11702.0 12935.0 15852.0 NaN NaN NaN NaN NaN\n", - "1987 557.0 4020.0 10946.0 12314.0 NaN NaN NaN NaN NaN NaN\n", - "1988 1351.0 6947.0 13112.0 NaN NaN NaN NaN NaN NaN NaN\n", - "1989 3133.0 5395.0 NaN NaN NaN NaN NaN NaN NaN NaN\n", - "1990 2063.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN" - ], "text/html": [ "\n", " \n", @@ -189,196 +179,427 @@ " \n", " \n", "
" + ], + "text/plain": [ + " 12 24 36 48 60 72 84 96 108 120\n", + "1981 5012.0 8269.0 10907.0 11805.0 13539.0 16181.0 18009.0 18608.0 18662.0 18834.0\n", + "1982 106.0 4285.0 5396.0 10666.0 13782.0 15599.0 15496.0 16169.0 16704.0 NaN\n", + "1983 3410.0 8992.0 13873.0 16141.0 18735.0 22214.0 22863.0 23466.0 NaN NaN\n", + "1984 5655.0 11555.0 15766.0 21266.0 23425.0 26083.0 27067.0 NaN NaN NaN\n", + "1985 1092.0 9565.0 15836.0 22169.0 25955.0 26180.0 NaN NaN NaN NaN\n", + "1986 1513.0 6445.0 11702.0 12935.0 15852.0 NaN NaN NaN NaN NaN\n", + "1987 557.0 4020.0 10946.0 12314.0 NaN NaN NaN NaN NaN NaN\n", + "1988 1351.0 6947.0 13112.0 NaN NaN NaN NaN NaN NaN NaN\n", + "1989 3133.0 5395.0 NaN NaN NaN NaN NaN NaN NaN NaN\n", + "1990 2063.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN" ] }, - "execution_count": 3, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], - "execution_count": 3 + "source": [ + "import chainladder as cl\n", + "\n", + "raa = cl.load_sample(\"raa\")\n", + "raa" + ] }, { "cell_type": "code", + "execution_count": 2, "id": "82b1c3255e22bc03", "metadata": { "ExecuteTime": { "end_time": "2026-09-11T11:04:54.274913267Z", "start_time": "2026-09-11T11:04:54.031259837Z" + }, + "execution": { + "iopub.execute_input": "2026-09-11T11:27:43.120025Z", + "iopub.status.busy": "2026-09-11T11:27:43.119911Z", + "iopub.status.idle": "2026-09-11T11:27:43.127180Z", + "shell.execute_reply": "2026-09-11T11:27:43.126721Z" } }, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 1224364860728496108120
19815,0128,26910,90711,80513,53916,18118,00918,60818,66218,834
19821064,2855,39610,66613,78215,59915,49616,16916,704
19833,4108,99213,87316,14118,73522,21422,86323,466
19845,65511,55515,76621,26623,42526,08327,067
19851,0929,56515,83622,16925,95526,180
19861,5136,44511,70212,93515,852
19875574,02010,94612,314
19881,3516,94713,112
19893,1335,395
19902,063
\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "raa.style.highlight_lower_triangle(color=\"blue\")" - ], + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "0089690f", + "metadata": { + "execution": { + "iopub.execute_input": "2026-09-11T11:27:43.128699Z", + "iopub.status.busy": "2026-09-11T11:27:43.128593Z", + "iopub.status.idle": "2026-09-11T11:27:43.172044Z", + "shell.execute_reply": "2026-09-11T11:27:43.171543Z" + } + }, "outputs": [ { "data": { - "text/plain": [ - "" - ], "text/html": [ "\n", - "\n", + "
\n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "
 122436486072849610812012243648607284961081201329999
19815,0128,26910,90711,80513,53916,18118,00918,60818,66218,834
19821064,2855,39610,66613,78215,59915,49616,16916,704
19833,4108,99213,87316,14118,73522,21422,86323,466
19845,65511,55515,76621,26623,42526,08327,067
19851,0929,56515,83622,16925,95526,180
19861,5136,44511,70212,93515,852
19875574,02010,94612,314
19881,3516,94713,112
19893,1335,395
19902,06319815,0128,26910,90711,80513,53916,18118,00918,60818,66218,83418,83418,834
19821064,2855,39610,66613,78215,59915,49616,16916,70416,85816,85816,858
19833,4108,99213,87316,14118,73522,21422,86323,46623,86324,08324,08324,083
19845,65511,55515,76621,26623,42526,08327,06727,96728,44128,70328,70328,703
19851,0929,56515,83622,16925,95526,18027,27828,18528,66328,92728,92728,927
19861,5136,44511,70212,93515,85217,64918,38919,00119,32319,50119,50119,501
19875574,02010,94612,31414,42816,06416,73817,29417,58717,74917,74917,749
19881,3516,94713,11216,66419,52521,73822,65023,40323,80024,01924,01924,019
19893,1335,3958,75911,13213,04314,52115,13015,63415,89816,04516,04516,045
19902,0636,18810,04612,76714,95916,65517,35317,93118,23418,40218,40218,402
\n" + ], + "text/plain": [ + "" ] }, - "execution_count": 4, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], - "execution_count": 4 + "source": [ + "full = cl.Chainladder().fit(raa).full_triangle_\n", + "full.style.highlight_lower_triangle(color=\"blue\", valuation_date=raa.valuation_date)" + ] } ], "metadata": { @@ -390,14 +611,14 @@ "language_info": { "codemirror_mode": { "name": "ipython", - "version": 2 + "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", - "pygments_lexer": "ipython2", - "version": "2.7.6" + "pygments_lexer": "ipython3", + "version": "3.14.4" } }, "nbformat": 4, From a5ea43a3ec3abf1e08d127ec7793200bae4c30dd Mon Sep 17 00:00:00 2001 From: Gene Dan Date: Fri, 11 Sep 2026 16:43:34 -0500 Subject: [PATCH 08/20] [FEAT] Add text parameter. --- chainladder/core/style.py | 56 ++- chainladder/core/tests/test_style.py | 25 +- docs/user_guide/style.ipynb | 639 ++++++++++++++------------- 3 files changed, 382 insertions(+), 338 deletions(-) diff --git a/chainladder/core/style.py b/chainladder/core/style.py index 267f5bf6c..b8e11bddd 100644 --- a/chainladder/core/style.py +++ b/chainladder/core/style.py @@ -11,11 +11,15 @@ import pandas as pd from pandas.io.formats.style import Styler as _PandasStyler -from typing import Any, TYPE_CHECKING +from datetime import date, datetime +from typing import Any, TYPE_CHECKING, TypeAlias if TYPE_CHECKING: from chainladder.core.typing import TriangleProtocol +# A value accepted by pandas.Timestamp's constructor. +ValuationDateLike: TypeAlias = int | float | str | date | datetime | pd.Timestamp + del TYPE_CHECKING del annotations @@ -26,7 +30,7 @@ class Styler(_PandasStyler): This class provides methods for styling and formatting a Triangle. The styled output can be rendered as HTML or LaTeX, and it supports CSS-based styling, allowing - users to control colors, font styles, and other visual aspects of tabular data. It is particularly + users to control colors, font styles, and other visual aspects of triangular data. It is particularly useful for presenting Triangle objects in a Jupyter Notebook environment or when exporting styled triangles for reports. @@ -36,11 +40,6 @@ class Styler(_PandasStyler): The data to style, as for :class:`pandas.io.formats.style.Styler`. triangle: TriangleProtocol | None The Triangle ``data`` was produced from, e.g. via ``Triangle.to_frame()``. - Required by builtins that need to know the Triangle's actuarial - structure, such as :meth:`highlight_lower_triangle`. Optional, since a - Styler can still be built directly from an arbitrary DataFrame the same - way a pandas ``Styler`` can; those Triangle-specific builtins simply - aren't available in that case. *args: Any Additional positional arguments passed to :class:`pandas.io.formats.style.Styler`. @@ -75,7 +74,8 @@ def highlight_lower_triangle( self, color: str = "blue", props: str | None = None, - valuation_date: Any = None, + valuation_date: ValuationDateLike | None = None, + text_color: str | None = None, ) -> Styler: """ Highlight the lower triangle -- the cells beyond the Triangle's @@ -87,12 +87,16 @@ def highlight_lower_triangle( Background color applied to lower-triangle cells. Ignored if ``props`` is given. Defaults to "blue". props: str | None - A full CSS properties string to apply instead of ``color``, e.g. - ``"background-color: blue; opacity: 60%;"``. Optional. - valuation_date: Any + A full CSS properties string to apply instead of ``color`` and + ``text_color``, e.g. ``"background-color: blue; opacity: 60%;"``. + Optional. + valuation_date: ValuationDateLike | None The "as of" date used to determine which cells fall beyond the latest diagonal, i.e. the lower triangle. If ``None``, defaults to the wrapped Triangle's own ``valuation_date``. + text_color: str | None + Text color applied to lower-triangle cells. Ignored if ``props`` + is given. Left unstyled (i.e. inherited) if not given. Returns ------- @@ -108,7 +112,16 @@ def highlight_lower_triangle( cl.load_sample("raa").style.highlight_lower_triangle(color="lightgray") - Highlighting a fully-predicted Triangle requires the original + A softer, higher-contrast pairing than the default: + + .. testcode:: + :options: +SKIP + + cl.load_sample("raa").style.highlight_lower_triangle( + color="#BDD7EE", text_color="#1F4E78" + ) + + Highlighting a fully-predicted Triangle requires a valuation date, since its cells are no longer ``NaN``. .. testcode:: @@ -127,19 +140,24 @@ def highlight_lower_triangle( "Triangle.style, so it knows which cells are the lower triangle." ) if valuation_date is None: - valuation_date = self._triangle.valuation_date + cutoff = self._triangle.valuation_date + else: + cutoff = pd.Timestamp(valuation_date) val_array = np.array(self._triangle.valuation).reshape( - self._triangle.shape[-2:], order="f" + self._triangle.shape[-2:], order="F" ) - nan_triangle = np.where(val_array > pd.Timestamp(valuation_date), np.nan, 1) + nan_triangle = np.where(val_array > cutoff, np.nan, 1) if nan_triangle.shape != self.data.shape: raise ValueError( "highlight_lower_triangle only supports a single (2-D) Triangle." ) - def f(_data: pd.DataFrame, props: str) -> np.ndarray: - return np.where(pd.isna(nan_triangle), props, "") - if props is None: props = f"background-color: {color};" - return self.apply(f, axis=None, props=props) # pyright: ignore[reportReturnType] + if text_color is not None: + props += f" color: {text_color};" + + def f(_data: pd.DataFrame) -> np.ndarray: + return np.where(pd.isna(nan_triangle), props, "") + + return self.apply(f, axis=None) # pyright: ignore[reportReturnType] diff --git a/chainladder/core/tests/test_style.py b/chainladder/core/tests/test_style.py index ea89c71af..ea4d23d35 100644 --- a/chainladder/core/tests/test_style.py +++ b/chainladder/core/tests/test_style.py @@ -123,6 +123,29 @@ def test_highlight_lower_triangle_props_overrides_color(raa) -> None: assert "lightgray" not in styler.to_html() +def test_highlight_lower_triangle_text_color(raa) -> None: + """Check that text_color sets the text color alongside the background.""" + styler = raa.style.highlight_lower_triangle(color="#DDEBF7", text_color="#1F4E78") + styler._compute() + styled = [v for v in styler.ctx.values() if v] + assert len(styled) > 0 + assert all( + v == [("background-color", "#DDEBF7"), ("color", "#1F4E78")] for v in styled + ) + + +def test_highlight_lower_triangle_text_color_ignored_without_default_props( + raa, +) -> None: + """Check that text_color is ignored when props overrides color, matching + color's own documented behavior. + """ + styler = raa.style.highlight_lower_triangle( + text_color="#1F4E78", props="background-color: blue;" + ) + assert "1F4E78" not in styler.to_html() + + def test_highlight_lower_triangle_returns_styler(raa) -> None: """Check that the subclass is preserved through the chained call.""" assert isinstance(raa.style.highlight_lower_triangle(), Styler) @@ -166,7 +189,7 @@ def test_highlight_lower_triangle_with_valuation_date_highlights_predicted_cells styler._compute() styled = {k for k, v in styler.ctx.items() if v} - val_array = np.array(full.valuation).reshape(full.shape[-2:], order="f") + val_array = np.array(full.valuation).reshape(full.shape[-2:], order="F") expected = { (r, c) for r, row in enumerate(val_array > raa.valuation_date) diff --git a/docs/user_guide/style.ipynb b/docs/user_guide/style.ipynb index 7e2c52d83..7e4832e87 100644 --- a/docs/user_guide/style.ipynb +++ b/docs/user_guide/style.ipynb @@ -20,10 +20,10 @@ "start_time": "2026-09-11T11:04:53.551399080Z" }, "execution": { - "iopub.execute_input": "2026-09-11T11:27:41.994746Z", - "iopub.status.busy": "2026-09-11T11:27:41.994641Z", - "iopub.status.idle": "2026-09-11T11:27:43.118228Z", - "shell.execute_reply": "2026-09-11T11:27:43.117714Z" + "iopub.execute_input": "2026-09-11T21:41:16.406766Z", + "iopub.status.busy": "2026-09-11T21:41:16.406658Z", + "iopub.status.idle": "2026-09-11T21:41:17.505185Z", + "shell.execute_reply": "2026-09-11T21:41:17.504627Z" } }, "outputs": [ @@ -216,10 +216,10 @@ "start_time": "2026-09-11T11:04:54.031259837Z" }, "execution": { - "iopub.execute_input": "2026-09-11T11:27:43.120025Z", - "iopub.status.busy": "2026-09-11T11:27:43.119911Z", - "iopub.status.idle": "2026-09-11T11:27:43.127180Z", - "shell.execute_reply": "2026-09-11T11:27:43.126721Z" + "iopub.execute_input": "2026-09-11T21:41:17.507039Z", + "iopub.status.busy": "2026-09-11T21:41:17.506923Z", + "iopub.status.idle": "2026-09-11T21:41:17.514890Z", + "shell.execute_reply": "2026-09-11T21:41:17.514455Z" } }, "outputs": [ @@ -227,162 +227,162 @@ "data": { "text/html": [ "\n", - "\n", + "
\n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "
 12243648607284961081201224364860728496108120
19815,0128,26910,90711,80513,53916,18118,00918,60818,66218,834
19821064,2855,39610,66613,78215,59915,49616,16916,704
19833,4108,99213,87316,14118,73522,21422,86323,466
19845,65511,55515,76621,26623,42526,08327,067
19851,0929,56515,83622,16925,95526,180
19861,5136,44511,70212,93515,852
19875574,02010,94612,314
19881,3516,94713,112
19893,1335,395
19902,06319815,0128,26910,90711,80513,53916,18118,00918,60818,66218,834
19821064,2855,39610,66613,78215,59915,49616,16916,704
19833,4108,99213,87316,14118,73522,21422,86323,466
19845,65511,55515,76621,26623,42526,08327,067
19851,0929,56515,83622,16925,95526,180
19861,5136,44511,70212,93515,852
19875574,02010,94612,314
19881,3516,94713,112
19893,1335,395
19902,063
\n" ], "text/plain": [ - "" + "" ] }, "execution_count": 2, @@ -400,10 +400,10 @@ "id": "0089690f", "metadata": { "execution": { - "iopub.execute_input": "2026-09-11T11:27:43.128699Z", - "iopub.status.busy": "2026-09-11T11:27:43.128593Z", - "iopub.status.idle": "2026-09-11T11:27:43.172044Z", - "shell.execute_reply": "2026-09-11T11:27:43.171543Z" + "iopub.execute_input": "2026-09-11T21:41:17.516451Z", + "iopub.status.busy": "2026-09-11T21:41:17.516335Z", + "iopub.status.idle": "2026-09-11T21:41:17.559733Z", + "shell.execute_reply": "2026-09-11T21:41:17.559161Z" } }, "outputs": [ @@ -411,184 +411,185 @@ "data": { "text/html": [ "\n", - "\n", + "
\n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "
 1224364860728496108120132999912243648607284961081201329999
19815,0128,26910,90711,80513,53916,18118,00918,60818,66218,83418,83418,834
19821064,2855,39610,66613,78215,59915,49616,16916,70416,85816,85816,858
19833,4108,99213,87316,14118,73522,21422,86323,46623,86324,08324,08324,083
19845,65511,55515,76621,26623,42526,08327,06727,96728,44128,70328,70328,703
19851,0929,56515,83622,16925,95526,18027,27828,18528,66328,92728,92728,927
19861,5136,44511,70212,93515,85217,64918,38919,00119,32319,50119,50119,501
19875574,02010,94612,31414,42816,06416,73817,29417,58717,74917,74917,749
19881,3516,94713,11216,66419,52521,73822,65023,40323,80024,01924,01924,019
19893,1335,3958,75911,13213,04314,52115,13015,63415,89816,04516,04516,045
19902,0636,18810,04612,76714,95916,65517,35317,93118,23418,40218,40218,40219815,0128,26910,90711,80513,53916,18118,00918,60818,66218,83418,83418,834
19821064,2855,39610,66613,78215,59915,49616,16916,70416,85816,85816,858
19833,4108,99213,87316,14118,73522,21422,86323,46623,86324,08324,08324,083
19845,65511,55515,76621,26623,42526,08327,06727,96728,44128,70328,70328,703
19851,0929,56515,83622,16925,95526,18027,27828,18528,66328,92728,92728,927
19861,5136,44511,70212,93515,85217,64918,38919,00119,32319,50119,50119,501
19875574,02010,94612,31414,42816,06416,73817,29417,58717,74917,74917,749
19881,3516,94713,11216,66419,52521,73822,65023,40323,80024,01924,01924,019
19893,1335,3958,75911,13213,04314,52115,13015,63415,89816,04516,04516,045
19902,0636,18810,04612,76714,95916,65517,35317,93118,23418,40218,40218,402
\n" ], "text/plain": [ - "" + "" ] }, "execution_count": 3, @@ -598,7 +599,9 @@ ], "source": [ "full = cl.Chainladder().fit(raa).full_triangle_\n", - "full.style.highlight_lower_triangle(color=\"blue\", valuation_date=raa.valuation_date)" + "full.style.highlight_lower_triangle(\n", + " color=\"#BDD7EE\", text_color=\"#1F4E78\", valuation_date=raa.valuation_date\n", + ")" ] } ], From 806021ba0b89e062b86e16d8420d116b26c31ac8 Mon Sep 17 00:00:00 2001 From: Gene Dan Date: Fri, 11 Sep 2026 17:00:54 -0500 Subject: [PATCH 09/20] [FEAT] Update example. --- docs/user_guide/style.ipynb | 732 +++++++++++++++++++----------------- 1 file changed, 381 insertions(+), 351 deletions(-) diff --git a/docs/user_guide/style.ipynb b/docs/user_guide/style.ipynb index 7e4832e87..491e02f7a 100644 --- a/docs/user_guide/style.ipynb +++ b/docs/user_guide/style.ipynb @@ -12,23 +12,41 @@ }, { "cell_type": "code", - "execution_count": 1, "id": "65fd12501acef112", "metadata": { - "ExecuteTime": { - "end_time": "2026-09-11T11:04:53.630857940Z", - "start_time": "2026-09-11T11:04:53.551399080Z" - }, "execution": { "iopub.execute_input": "2026-09-11T21:41:16.406766Z", "iopub.status.busy": "2026-09-11T21:41:16.406658Z", "iopub.status.idle": "2026-09-11T21:41:17.505185Z", "shell.execute_reply": "2026-09-11T21:41:17.504627Z" + }, + "ExecuteTime": { + "end_time": "2026-09-11T21:59:07.461711877Z", + "start_time": "2026-09-11T21:59:07.398546902Z" } }, + "source": [ + "import chainladder as cl\n", + "\n", + "raa = cl.load_sample(\"raa\")\n", + "raa" + ], "outputs": [ { "data": { + "text/plain": [ + " 12 24 36 48 60 72 84 96 108 120\n", + "1981 5012.0 8269.0 10907.0 11805.0 13539.0 16181.0 18009.0 18608.0 18662.0 18834.0\n", + "1982 106.0 4285.0 5396.0 10666.0 13782.0 15599.0 15496.0 16169.0 16704.0 NaN\n", + "1983 3410.0 8992.0 13873.0 16141.0 18735.0 22214.0 22863.0 23466.0 NaN NaN\n", + "1984 5655.0 11555.0 15766.0 21266.0 23425.0 26083.0 27067.0 NaN NaN NaN\n", + "1985 1092.0 9565.0 15836.0 22169.0 25955.0 26180.0 NaN NaN NaN NaN\n", + "1986 1513.0 6445.0 11702.0 12935.0 15852.0 NaN NaN NaN NaN NaN\n", + "1987 557.0 4020.0 10946.0 12314.0 NaN NaN NaN NaN NaN NaN\n", + "1988 1351.0 6947.0 13112.0 NaN NaN NaN NaN NaN NaN NaN\n", + "1989 3133.0 5395.0 NaN NaN NaN NaN NaN NaN NaN NaN\n", + "1990 2063.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN" + ], "text/html": [ "\n", " \n", @@ -179,224 +197,205 @@ " \n", " \n", "
" - ], - "text/plain": [ - " 12 24 36 48 60 72 84 96 108 120\n", - "1981 5012.0 8269.0 10907.0 11805.0 13539.0 16181.0 18009.0 18608.0 18662.0 18834.0\n", - "1982 106.0 4285.0 5396.0 10666.0 13782.0 15599.0 15496.0 16169.0 16704.0 NaN\n", - "1983 3410.0 8992.0 13873.0 16141.0 18735.0 22214.0 22863.0 23466.0 NaN NaN\n", - "1984 5655.0 11555.0 15766.0 21266.0 23425.0 26083.0 27067.0 NaN NaN NaN\n", - "1985 1092.0 9565.0 15836.0 22169.0 25955.0 26180.0 NaN NaN NaN NaN\n", - "1986 1513.0 6445.0 11702.0 12935.0 15852.0 NaN NaN NaN NaN NaN\n", - "1987 557.0 4020.0 10946.0 12314.0 NaN NaN NaN NaN NaN NaN\n", - "1988 1351.0 6947.0 13112.0 NaN NaN NaN NaN NaN NaN NaN\n", - "1989 3133.0 5395.0 NaN NaN NaN NaN NaN NaN NaN NaN\n", - "1990 2063.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN" ] }, - "execution_count": 1, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], - "source": [ - "import chainladder as cl\n", - "\n", - "raa = cl.load_sample(\"raa\")\n", - "raa" - ] + "execution_count": 7 }, { "cell_type": "code", - "execution_count": 2, "id": "82b1c3255e22bc03", "metadata": { - "ExecuteTime": { - "end_time": "2026-09-11T11:04:54.274913267Z", - "start_time": "2026-09-11T11:04:54.031259837Z" - }, "execution": { "iopub.execute_input": "2026-09-11T21:41:17.507039Z", "iopub.status.busy": "2026-09-11T21:41:17.506923Z", "iopub.status.idle": "2026-09-11T21:41:17.514890Z", "shell.execute_reply": "2026-09-11T21:41:17.514455Z" + }, + "ExecuteTime": { + "end_time": "2026-09-11T21:59:07.709747537Z", + "start_time": "2026-09-11T21:59:07.567520119Z" } }, + "source": [ + "raa.style.highlight_lower_triangle(color=\"blue\")" + ], "outputs": [ { "data": { + "text/plain": [ + "" + ], "text/html": [ "\n", - "\n", + "
\n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "
 12243648607284961081201224364860728496108120
19815,0128,26910,90711,80513,53916,18118,00918,60818,66218,834
19821064,2855,39610,66613,78215,59915,49616,16916,704
19833,4108,99213,87316,14118,73522,21422,86323,466
19845,65511,55515,76621,26623,42526,08327,067
19851,0929,56515,83622,16925,95526,180
19861,5136,44511,70212,93515,852
19875574,02010,94612,314
19881,3516,94713,112
19893,1335,395
19902,06319815,0128,26910,90711,80513,53916,18118,00918,60818,66218,834
19821064,2855,39610,66613,78215,59915,49616,16916,704
19833,4108,99213,87316,14118,73522,21422,86323,466
19845,65511,55515,76621,26623,42526,08327,067
19851,0929,56515,83622,16925,95526,180
19861,5136,44511,70212,93515,852
19875574,02010,94612,314
19881,3516,94713,112
19893,1335,395
19902,063
\n" - ], - "text/plain": [ - "" ] }, - "execution_count": 2, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], - "source": [ - "raa.style.highlight_lower_triangle(color=\"blue\")" - ] + "execution_count": 8 }, { "cell_type": "code", - "execution_count": 3, "id": "0089690f", "metadata": { "execution": { @@ -404,205 +403,236 @@ "iopub.status.busy": "2026-09-11T21:41:17.516335Z", "iopub.status.idle": "2026-09-11T21:41:17.559733Z", "shell.execute_reply": "2026-09-11T21:41:17.559161Z" + }, + "ExecuteTime": { + "end_time": "2026-09-11T21:59:08.007117427Z", + "start_time": "2026-09-11T21:59:07.720209389Z" } }, + "source": [ + "full = cl.Chainladder().fit(raa).full_triangle_\n", + "full.style.highlight_lower_triangle(\n", + " color=\"#2F61AD\",\n", + " text_color=\"#FFFFFF\",\n", + " valuation_date=raa.valuation_date,\n", + ")" + ], "outputs": [ { "data": { + "text/plain": [ + "" + ], "text/html": [ "\n", - "\n", + "
\n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "
 1224364860728496108120132999912243648607284961081201329999
19815,0128,26910,90711,80513,53916,18118,00918,60818,66218,83418,83418,834
19821064,2855,39610,66613,78215,59915,49616,16916,70416,85816,85816,858
19833,4108,99213,87316,14118,73522,21422,86323,46623,86324,08324,08324,083
19845,65511,55515,76621,26623,42526,08327,06727,96728,44128,70328,70328,703
19851,0929,56515,83622,16925,95526,18027,27828,18528,66328,92728,92728,927
19861,5136,44511,70212,93515,85217,64918,38919,00119,32319,50119,50119,501
19875574,02010,94612,31414,42816,06416,73817,29417,58717,74917,74917,749
19881,3516,94713,11216,66419,52521,73822,65023,40323,80024,01924,01924,019
19893,1335,3958,75911,13213,04314,52115,13015,63415,89816,04516,04516,045
19902,0636,18810,04612,76714,95916,65517,35317,93118,23418,40218,40218,40219815,0128,26910,90711,80513,53916,18118,00918,60818,66218,83418,83418,834
19821064,2855,39610,66613,78215,59915,49616,16916,70416,85816,85816,858
19833,4108,99213,87316,14118,73522,21422,86323,46623,86324,08324,08324,083
19845,65511,55515,76621,26623,42526,08327,06727,96728,44128,70328,70328,703
19851,0929,56515,83622,16925,95526,18027,27828,18528,66328,92728,92728,927
19861,5136,44511,70212,93515,85217,64918,38919,00119,32319,50119,50119,501
19875574,02010,94612,31414,42816,06416,73817,29417,58717,74917,74917,749
19881,3516,94713,11216,66419,52521,73822,65023,40323,80024,01924,01924,019
19893,1335,3958,75911,13213,04314,52115,13015,63415,89816,04516,04516,045
19902,0636,18810,04612,76714,95916,65517,35317,93118,23418,40218,40218,402
\n" - ], + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 9 + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-09-11T21:59:17.220464629Z", + "start_time": "2026-09-11T21:59:17.179552596Z" + } + }, + "cell_type": "code", + "source": "", + "id": "b36ef218fc263301", + "outputs": [ + { + "data": { "text/plain": [ - "" + "Timestamp('2261-12-31 23:59:59.999999999')" ] }, - "execution_count": 3, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], - "source": [ - "full = cl.Chainladder().fit(raa).full_triangle_\n", - "full.style.highlight_lower_triangle(\n", - " color=\"#BDD7EE\", text_color=\"#1F4E78\", valuation_date=raa.valuation_date\n", - ")" - ] + "execution_count": 10 } ], "metadata": { From 340e07f858e26815ce3a9e306607245f0db1095e Mon Sep 17 00:00:00 2001 From: Gene Dan Date: Fri, 11 Sep 2026 17:01:44 -0500 Subject: [PATCH 10/20] [FEAT] Update example. --- chainladder/core/tests/test_style.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/chainladder/core/tests/test_style.py b/chainladder/core/tests/test_style.py index ea4d23d35..fec50252d 100644 --- a/chainladder/core/tests/test_style.py +++ b/chainladder/core/tests/test_style.py @@ -35,13 +35,8 @@ def test_wraps_a_dataframe(df: pd.DataFrame) -> None: def test_chained_methods_preserve_subclass(df: pd.DataFrame) -> None: """Check that chaining a pandas Styler method still returns a chainladder Styler, - not a plain pandas Styler -- the methods mutate self and return self, so - subclassing doesn't get lost partway through a chain. + not a plain pandas Styler. """ - # pandas types .format()/.hide() as returning StylerRenderer (their defining - # base class) rather than Self, so a type checker loses the subclass after - # chaining even though the runtime object is still a Styler -- see the - # isinstance assertion below. result = ( Styler(df) .format(precision=1) @@ -53,13 +48,10 @@ def test_chained_methods_preserve_subclass(df: pd.DataFrame) -> None: def test_renders_identically_to_pandas_styler(df: pd.DataFrame) -> None: - """Check that Styler produces the same HTML as pandas' own Styler, uuid aside -- - confirms the subclass doesn't alter behavior, matching the goal of starting as - a pure adapter before adding Triangle-specific behavior. + """Check that Styler produces the same HTML as pandas' own Styler. """ - # Same StylerRenderer-vs-Self typing gap as above, on pandas' own side too. - cl_html = Styler(df, uuid="fixed").format(precision=2).to_html() # pyright: ignore[reportAttributeAccessIssue] - pd_html = PandasStyler(df, uuid="fixed").format(precision=2).to_html() # pyright: ignore[reportAttributeAccessIssue] + cl_html = Styler(df, uuid="fixed").format(precision=2).to_html() + pd_html = PandasStyler(df, uuid="fixed").format(precision=2).to_html() assert cl_html == pd_html From 13d7d10eb5a9bdd0ce81a782a104aa0d1259dcd5 Mon Sep 17 00:00:00 2001 From: Gene Dan Date: Fri, 11 Sep 2026 17:02:04 -0500 Subject: [PATCH 11/20] [FEAT] Update example. --- docs/user_guide/style.ipynb | 674 +++++++++++++++++------------------- 1 file changed, 325 insertions(+), 349 deletions(-) diff --git a/docs/user_guide/style.ipynb b/docs/user_guide/style.ipynb index 491e02f7a..93b61a67a 100644 --- a/docs/user_guide/style.ipynb +++ b/docs/user_guide/style.ipynb @@ -21,8 +21,8 @@ "shell.execute_reply": "2026-09-11T21:41:17.504627Z" }, "ExecuteTime": { - "end_time": "2026-09-11T21:59:07.461711877Z", - "start_time": "2026-09-11T21:59:07.398546902Z" + "end_time": "2026-09-11T22:01:12.572490069Z", + "start_time": "2026-09-11T22:01:11.703468543Z" } }, "source": [ @@ -199,12 +199,12 @@ "" ] }, - "execution_count": 7, + "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], - "execution_count": 7 + "execution_count": 1 }, { "cell_type": "code", @@ -217,8 +217,8 @@ "shell.execute_reply": "2026-09-11T21:41:17.514455Z" }, "ExecuteTime": { - "end_time": "2026-09-11T21:59:07.709747537Z", - "start_time": "2026-09-11T21:59:07.567520119Z" + "end_time": "2026-09-11T22:01:12.729936711Z", + "start_time": "2026-09-11T22:01:12.633141896Z" } }, "source": [ @@ -228,175 +228,173 @@ { "data": { "text/plain": [ - "" + "" ], "text/html": [ "\n", - "\n", + "
\n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "
 12243648607284961081201224364860728496108120
19815,0128,26910,90711,80513,53916,18118,00918,60818,66218,834
19821064,2855,39610,66613,78215,59915,49616,16916,704
19833,4108,99213,87316,14118,73522,21422,86323,466
19845,65511,55515,76621,26623,42526,08327,067
19851,0929,56515,83622,16925,95526,180
19861,5136,44511,70212,93515,852
19875574,02010,94612,314
19881,3516,94713,112
19893,1335,395
19902,06319815,0128,26910,90711,80513,53916,18118,00918,60818,66218,834
19821064,2855,39610,66613,78215,59915,49616,16916,704
19833,4108,99213,87316,14118,73522,21422,86323,466
19845,65511,55515,76621,26623,42526,08327,067
19851,0929,56515,83622,16925,95526,180
19861,5136,44511,70212,93515,852
19875574,02010,94612,314
19881,3516,94713,112
19893,1335,395
19902,063
\n" ] }, - "execution_count": 8, + "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], - "execution_count": 8 + "execution_count": 2 }, { - "cell_type": "code", - "id": "0089690f", "metadata": { "execution": { "iopub.execute_input": "2026-09-11T21:41:17.516451Z", @@ -405,234 +403,212 @@ "shell.execute_reply": "2026-09-11T21:41:17.559161Z" }, "ExecuteTime": { - "end_time": "2026-09-11T21:59:08.007117427Z", - "start_time": "2026-09-11T21:59:07.720209389Z" + "end_time": "2026-09-11T22:01:12.843529894Z", + "start_time": "2026-09-11T22:01:12.754832157Z" } }, - "source": [ - "full = cl.Chainladder().fit(raa).full_triangle_\n", - "full.style.highlight_lower_triangle(\n", - " color=\"#2F61AD\",\n", - " text_color=\"#FFFFFF\",\n", - " valuation_date=raa.valuation_date,\n", - ")" - ], + "cell_type": "code", "outputs": [ { "data": { "text/plain": [ - "" + "" ], "text/html": [ "\n", - "\n", + "
\n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "
 1224364860728496108120132999912243648607284961081201329999
19815,0128,26910,90711,80513,53916,18118,00918,60818,66218,83418,83418,834
19821064,2855,39610,66613,78215,59915,49616,16916,70416,85816,85816,858
19833,4108,99213,87316,14118,73522,21422,86323,46623,86324,08324,08324,083
19845,65511,55515,76621,26623,42526,08327,06727,96728,44128,70328,70328,703
19851,0929,56515,83622,16925,95526,18027,27828,18528,66328,92728,92728,927
19861,5136,44511,70212,93515,85217,64918,38919,00119,32319,50119,50119,501
19875574,02010,94612,31414,42816,06416,73817,29417,58717,74917,74917,749
19881,3516,94713,11216,66419,52521,73822,65023,40323,80024,01924,01924,019
19893,1335,3958,75911,13213,04314,52115,13015,63415,89816,04516,04516,045
19902,0636,18810,04612,76714,95916,65517,35317,93118,23418,40218,40218,40219815,0128,26910,90711,80513,53916,18118,00918,60818,66218,83418,83418,834
19821064,2855,39610,66613,78215,59915,49616,16916,70416,85816,85816,858
19833,4108,99213,87316,14118,73522,21422,86323,46623,86324,08324,08324,083
19845,65511,55515,76621,26623,42526,08327,06727,96728,44128,70328,70328,703
19851,0929,56515,83622,16925,95526,18027,27828,18528,66328,92728,92728,927
19861,5136,44511,70212,93515,85217,64918,38919,00119,32319,50119,50119,501
19875574,02010,94612,31414,42816,06416,73817,29417,58717,74917,74917,749
19881,3516,94713,11216,66419,52521,73822,65023,40323,80024,01924,01924,019
19893,1335,3958,75911,13213,04314,52115,13015,63415,89816,04516,04516,045
19902,0636,18810,04612,76714,95916,65517,35317,93118,23418,40218,40218,402
\n" ] }, - "execution_count": 9, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], - "execution_count": 9 - }, - { - "metadata": { - "ExecuteTime": { - "end_time": "2026-09-11T21:59:17.220464629Z", - "start_time": "2026-09-11T21:59:17.179552596Z" - } - }, - "cell_type": "code", - "source": "", - "id": "b36ef218fc263301", - "outputs": [ - { - "data": { - "text/plain": [ - "Timestamp('2261-12-31 23:59:59.999999999')" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } + "execution_count": 3, + "source": [ + "full = cl.Chainladder().fit(raa).full_triangle_\n", + "full.style.highlight_lower_triangle(\n", + " color=\"#2F61AD\",\n", + " text_color=\"#FFFFFF\",\n", + " valuation_date=raa.valuation_date\n", + ")" ], - "execution_count": 10 + "id": "0089690f" } ], "metadata": { From 05e67e11410c1cfe982c61f14cf8f59470cf835e Mon Sep 17 00:00:00 2001 From: Gene Dan Date: Fri, 11 Sep 2026 17:46:40 -0500 Subject: [PATCH 12/20] [DOCS] Add to API reference. --- chainladder/core/tests/test_style.py | 235 ++++++++++++++++-- .../autosummary/class_inherited.rst | 2 +- docs/library/api.md | 6 + 3 files changed, 221 insertions(+), 22 deletions(-) diff --git a/chainladder/core/tests/test_style.py b/chainladder/core/tests/test_style.py index fec50252d..f6101bbe0 100644 --- a/chainladder/core/tests/test_style.py +++ b/chainladder/core/tests/test_style.py @@ -18,24 +18,61 @@ def df() -> pd.DataFrame: def test_is_public() -> None: - """Check that Styler is importable from the top-level chainladder package.""" + """ + Check that Styler is importable from the top-level chainladder package. + + Returns + ------- + None + + """ assert cl.Styler is Styler def test_is_pandas_styler_subclass() -> None: - """Check that Styler extends pandas' own Styler rather than replacing it.""" + """ + Check that Styler extends pandas' own Styler rather than replacing it. + + Returns + ------- + None + + """ assert issubclass(Styler, PandasStyler) def test_wraps_a_dataframe(df: pd.DataFrame) -> None: - """Check that Styler wraps a DataFrame the same way pandas' Styler does.""" + """ + Check that Styler wraps a DataFrame the same way pandas' Styler does. + + Parameters + ---------- + df: pd.DataFrame + A simple two-column DataFrame fixture. + + Returns + ------- + None + + """ styler = Styler(df) assert styler.data is df def test_chained_methods_preserve_subclass(df: pd.DataFrame) -> None: - """Check that chaining a pandas Styler method still returns a chainladder Styler, + """ + Check that chaining a pandas Styler method still returns a chainladder Styler, not a plain pandas Styler. + + Parameters + ---------- + df: pd.DataFrame + A simple two-column DataFrame fixture. + + Returns + ------- + None + """ result = ( Styler(df) @@ -48,7 +85,18 @@ def test_chained_methods_preserve_subclass(df: pd.DataFrame) -> None: def test_renders_identically_to_pandas_styler(df: pd.DataFrame) -> None: - """Check that Styler produces the same HTML as pandas' own Styler. + """ + Check that Styler produces the same HTML as pandas' own Styler. + + Parameters + ---------- + df: pd.DataFrame + A simple two-column DataFrame fixture. + + Returns + ------- + None + """ cl_html = Styler(df, uuid="fixed").format(precision=2).to_html() pd_html = PandasStyler(df, uuid="fixed").format(precision=2).to_html() @@ -56,22 +104,54 @@ def test_renders_identically_to_pandas_styler(df: pd.DataFrame) -> None: def test_triangle_style_is_a_property(raa) -> None: - """Check that Triangle.style is a property, matching pandas.DataFrame.style, + """ + Check that Triangle.style is a property, matching pandas.DataFrame.style, rather than a method that must be called. + + Parameters + ---------- + raa: Triangle + The raa sample data set. + + Returns + ------- + None + """ assert isinstance(type(raa).style, property) def test_triangle_style_returns_styler(raa) -> None: - """Check that Triangle.style returns a chainladder Styler.""" + """ + Check that Triangle.style returns a chainladder Styler. + + Parameters + ---------- + raa: Triangle + The raa sample data set. + + Returns + ------- + None + + """ assert isinstance(raa.style, Styler) def test_triangle_style_wraps_to_frame(raa) -> None: - """Check that Triangle.style wraps the same data as - Triangle.to_frame(origin_as_datetime=False) -- the origin stays a - PeriodIndex rather than converting to datetime, so it renders compactly - (e.g. "1981") instead of "1981-01-01 00:00:00". + """ + Check that Triangle.style wraps the same data as + Triangle.to_frame(origin_as_datetime=False). + + Parameters + ---------- + raa: Triangle + The raa sample data set. + + Returns + ------- + None + """ pd.testing.assert_frame_equal( raa.style.data, raa.to_frame(origin_as_datetime=False) @@ -79,16 +159,38 @@ def test_triangle_style_wraps_to_frame(raa) -> None: def test_triangle_style_is_fresh_each_access(raa) -> None: - """Check that each access to Triangle.style returns a new Styler, matching + """ + Check that each access to Triangle.style returns a new Styler, matching pandas.DataFrame.style's own behavior -- so unrelated uses don't share state or a uuid. + + Parameters + ---------- + raa: Triangle + The raa sample data set. + + Returns + ------- + None + """ assert raa.style is not raa.style def test_highlight_lower_triangle_styles_exactly_the_lower_triangle(raa) -> None: - """Check that every styled cell -- and only those cells -- correspond to a + """ + Check that every styled cell -- and only those cells -- correspond to a NaN in the Triangle's own nan_triangle mask. + + Parameters + ---------- + raa: Triangle + The raa sample data set. + + Returns + ------- + None + """ styler = raa.style.highlight_lower_triangle(color="lightgray") styler._compute() @@ -107,7 +209,19 @@ def test_highlight_lower_triangle_styles_exactly_the_lower_triangle(raa) -> None def test_highlight_lower_triangle_props_overrides_color(raa) -> None: - """Check that a custom props string is used verbatim instead of color.""" + """ + Supplying a custom props overrides the color parameter. + + Parameters + ---------- + raa: Triangle + The raa sample data set. + + Returns + ------- + None + + """ styler = raa.style.highlight_lower_triangle( color="lightgray", props="background-color: blue; opacity: 50%;" ) @@ -116,7 +230,19 @@ def test_highlight_lower_triangle_props_overrides_color(raa) -> None: def test_highlight_lower_triangle_text_color(raa) -> None: - """Check that text_color sets the text color alongside the background.""" + """ + Check that text_color sets the text color alongside the background. + + Parameters + ---------- + raa: Triangle + The raa sample data set. + + Returns + ------- + None + + """ styler = raa.style.highlight_lower_triangle(color="#DDEBF7", text_color="#1F4E78") styler._compute() styled = [v for v in styler.ctx.values() if v] @@ -129,8 +255,19 @@ def test_highlight_lower_triangle_text_color(raa) -> None: def test_highlight_lower_triangle_text_color_ignored_without_default_props( raa, ) -> None: - """Check that text_color is ignored when props overrides color, matching + """ + Check that text_color is ignored when props overrides color, matching color's own documented behavior. + + Parameters + ---------- + raa: Triangle + The raa sample data set. + + Returns + ------- + None + """ styler = raa.style.highlight_lower_triangle( text_color="#1F4E78", props="background-color: blue;" @@ -139,13 +276,36 @@ def test_highlight_lower_triangle_text_color_ignored_without_default_props( def test_highlight_lower_triangle_returns_styler(raa) -> None: - """Check that the subclass is preserved through the chained call.""" + """ + Check that the subclass is preserved through the chained call. + + Parameters + ---------- + raa: Triangle + The raa sample data set. + + Returns + ------- + None + + """ assert isinstance(raa.style.highlight_lower_triangle(), Styler) def test_highlight_lower_triangle_requires_a_triangle(df: pd.DataFrame) -> None: - """Check that calling it on a Styler not built from Triangle.style raises a + """ + Check that calling it on a Styler not built from Triangle.style raises a clear error, since there's no way to know which cells are the lower triangle. + + Parameters + ---------- + df: pd.DataFrame + A simple two-column DataFrame fixture. + + Returns + ------- + None + """ with pytest.raises( ValueError, match="requires a Styler created from Triangle.style" @@ -156,10 +316,21 @@ def test_highlight_lower_triangle_requires_a_triangle(df: pd.DataFrame) -> None: def test_highlight_lower_triangle_predicted_cells_not_highlighted_by_default( raa, ) -> None: - """A fully-predicted Triangle (e.g. full_triangle_) has no NaN cells left, + """ + A fully-predicted Triangle (e.g. full_triangle_) has no NaN cells left, and once it carries an ultimate column its own nan_triangle collapses to all-observed -- so without an explicit valuation_date, nothing gets highlighted. + + Parameters + ---------- + raa: Triangle + The raa sample data set. + + Returns + ------- + None + """ full = cl.Chainladder().fit(raa).full_triangle_ styler = full.style.highlight_lower_triangle(color="lightgray") @@ -170,9 +341,20 @@ def test_highlight_lower_triangle_predicted_cells_not_highlighted_by_default( def test_highlight_lower_triangle_with_valuation_date_highlights_predicted_cells( raa, ) -> None: - """Passing the original valuation_date recovers which cells were originally + """ + Passing the original valuation_date recovers which cells were originally the lower (unobserved) triangle, even though they've since been filled in with predicted values. + + Parameters + ---------- + raa: Triangle + The raa sample data set. + + Returns + ------- + None + """ full = cl.Chainladder().fit(raa).full_triangle_ styler = full.style.highlight_lower_triangle( @@ -196,9 +378,20 @@ def test_highlight_lower_triangle_with_valuation_date_highlights_predicted_cells def test_highlight_lower_triangle_requires_matching_shape(clrd) -> None: - """Check that a Triangle whose to_frame() isn't a single origin-by-development + """ + Check that a Triangle whose to_frame() isn't a single origin-by-development grid (multiple index labels and columns, here) raises a clear error rather than silently misaligning the mask. + + Parameters + ---------- + clrd: Triangle + The clrd sample data set. + + Returns + ------- + None + """ with pytest.raises(ValueError, match="only supports a single \\(2-D\\) Triangle"): clrd.style.highlight_lower_triangle() diff --git a/docs/_templates/autosummary/class_inherited.rst b/docs/_templates/autosummary/class_inherited.rst index 41fc413c4..1ade6cd15 100644 --- a/docs/_templates/autosummary/class_inherited.rst +++ b/docs/_templates/autosummary/class_inherited.rst @@ -2,7 +2,7 @@ .. currentmodule:: {{ module }} -{% set documented_attrs = ['loc', 'iloc', 'at', 'iat', 'shape', 'empty', 'dimensionality', 'nan_triangle'] %} +{% set documented_attrs = ['loc', 'iloc', 'at', 'iat', 'shape', 'empty', 'dimensionality', 'nan_triangle', 'style'] %} {% set hidden_attrs = attributes | reject('in', documented_attrs) | list %} .. autoclass:: {{ objname }} diff --git a/docs/library/api.md b/docs/library/api.md index 1e24edbd1..daab693d2 100644 --- a/docs/library/api.md +++ b/docs/library/api.md @@ -26,6 +26,12 @@ Classes DevelopmentCorrelation ValuationCorrelation +.. autosummary:: + :toctree: generated/ + :template: class + + Styler + .. _development_ref: From 97b3771cca17921ee85542d3657848aa6a99ce24 Mon Sep 17 00:00:00 2001 From: Gene Dan Date: Fri, 11 Sep 2026 18:20:01 -0500 Subject: [PATCH 13/20] [FIX] Ruff fix. --- docs/user_guide/style.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user_guide/style.ipynb b/docs/user_guide/style.ipynb index 93b61a67a..98efe571a 100644 --- a/docs/user_guide/style.ipynb +++ b/docs/user_guide/style.ipynb @@ -605,7 +605,7 @@ "full.style.highlight_lower_triangle(\n", " color=\"#2F61AD\",\n", " text_color=\"#FFFFFF\",\n", - " valuation_date=raa.valuation_date\n", + " valuation_date=raa.valuation_date,\n", ")" ], "id": "0089690f" From c82bdc67b817f4317f4d542a6c30993a47ebc19c Mon Sep 17 00:00:00 2001 From: Gene Dan Date: Fri, 18 Sep 2026 17:43:26 -0500 Subject: [PATCH 14/20] [FIX] Restrict Styler to accept Triangle only, generalize masking method. Respond to review comments. --- chainladder/core/pandas.py | 11 +- chainladder/core/style.py | 180 ++++++++++++++++++++++----- chainladder/core/tests/test_style.py | 136 +++++++++++++------- chainladder/core/typing.py | 6 + 4 files changed, 253 insertions(+), 80 deletions(-) diff --git a/chainladder/core/pandas.py b/chainladder/core/pandas.py index 9466bc864..e85f89440 100644 --- a/chainladder/core/pandas.py +++ b/chainladder/core/pandas.py @@ -245,16 +245,9 @@ def style(self) -> Styler: Returns ------- Styler - A Styler wrapping this Triangle's ``to_frame()`` representation. + A Styler wrapping this Triangle's frame representation. """ - data = self.to_frame(origin_as_datetime=False) - styler = Styler(data, triangle=self) - if self._dimensionality == "single": - fmt_str = self._get_format_str(data=data) - styler = styler.format( # pyright: ignore[reportReturnType] - fmt_str, na_rep="" - ) - return styler + return Styler(self) @staticmethod def _get_axis( diff --git a/chainladder/core/style.py b/chainladder/core/style.py index b8e11bddd..7a2384a76 100644 --- a/chainladder/core/style.py +++ b/chainladder/core/style.py @@ -7,6 +7,10 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. from __future__ import annotations +import copy as copy_module + +from functools import partial + import numpy as np import pandas as pd from pandas.io.formats.style import Styler as _PandasStyler @@ -15,7 +19,7 @@ from typing import Any, TYPE_CHECKING, TypeAlias if TYPE_CHECKING: - from chainladder.core.typing import TriangleProtocol + from chainladder import Triangle # A value accepted by pandas.Timestamp's constructor. ValuationDateLike: TypeAlias = int | float | str | date | datetime | pd.Timestamp @@ -36,10 +40,8 @@ class Styler(_PandasStyler): Parameters ---------- - data: pd.DataFrame | pd.Series - The data to style, as for :class:`pandas.io.formats.style.Styler`. - triangle: TriangleProtocol | None - The Triangle ``data`` was produced from, e.g. via ``Triangle.to_frame()``. + triangle: Triangle + The Triangle to style. *args: Any Additional positional arguments passed to :class:`pandas.io.formats.style.Styler`. @@ -47,28 +49,145 @@ class Styler(_PandasStyler): Additional keyword arguments passed to :class:`pandas.io.formats.style.Styler`. + Raises + ------ + TypeError + If ``triangle`` is anything other than a Triangle. + ValueError + If ``triangle`` is multidimensional, i.e. holds more than a single index + and column. + Examples -------- .. testcode:: - import pandas as pd + import chainladder as cl from chainladder.core.style import Styler - df = pd.DataFrame({"a": [1, 2], "b": [3, 4]}) - Styler(df).format(precision=1) + raa = cl.load_sample("raa") + print(Styler(raa.link_ratio).format(precision=1).to_string(), end="") + + .. testoutput:: + + 12-24 24-36 36-48 48-60 60-72 72-84 84-96 96-108 108-120 + 1981 1.6 1.3 1.1 1.1 1.2 1.1 1.0 1.0 1.0 + 1982 40.4 1.3 2.0 1.3 1.1 1.0 1.0 1.0 nan + 1983 2.6 1.5 1.2 1.2 1.2 1.0 1.0 nan nan + 1984 2.0 1.4 1.3 1.1 1.1 1.0 nan nan nan + 1985 8.8 1.7 1.4 1.2 1.0 nan nan nan nan + 1986 4.3 1.8 1.1 1.2 nan nan nan nan nan + 1987 7.2 2.7 1.1 nan nan nan nan nan nan + 1988 5.1 1.9 nan nan nan nan nan nan nan + 1989 1.7 nan nan nan nan nan nan nan nan + + Please see: :doc:`Triangle Visualization ` for more + examples. """ def __init__( self, - data: pd.DataFrame | pd.Series, + triangle: Triangle, *args: Any, - triangle: TriangleProtocol | None = None, **kwargs: Any, ) -> None: + # Imported here rather than at module scope: Triangle's own mixins import + # this module, so a top-level import would be circular. + from chainladder.core.triangle import Triangle + + if not isinstance(triangle, Triangle): + # The frame case is the likely mistake, so point it somewhere useful. + hint = ( + " Use DataFrame.style for a DataFrame." + if isinstance(triangle, (pd.DataFrame, pd.Series)) + else "" + ) + raise TypeError( + "Styler must be created from a Triangle, not a " + f"{type(triangle).__name__}.{hint}" + ) + if triangle._dimensionality == "multi": + raise ValueError( + "Styler only supports a single Triangle. Select one " + "index and column first, e.g. triangle.iloc[0, 0]." + ) + data = triangle._repr_format(origin_as_datetime=False) super().__init__(data, *args, **kwargs) self._triangle = triangle + self.format(triangle._get_format_str(data=data), na_rep="") + + def _copy( + self, + deepcopy: bool = False, + ) -> Styler: + """ + Copy the Styler. Overrides the parent Pandas Styler to be able to work on Triangles instead of a DataFrame. + + Parameters + ---------- + deepcopy: bool + If ``True``, deep-copy every attribute carried over from the calling Styler. + + Returns + ------- + Styler + A new copy of the ``Styler``. + """ + styler = object.__new__(type(self)) + _PandasStyler.__init__(styler, self.data) + styler._triangle = self._triangle + for key, value in self.__dict__.items(): + if key in ( + "data", + "index", + "columns", + "_triangle", + ): + continue + setattr( + styler, + key, + copy_module.deepcopy(value) if deepcopy else value, + ) + return styler + + @staticmethod + def _mask_style( + _data: pd.DataFrame, + mask: np.ndarray, + props: str, + ) -> np.ndarray: + """ + Apply ``props`` to the cells ``mask`` selects, and leave every other + cell unstyled. + + Parameters + ---------- + _data: pd.DataFrame + The styled DataFrame, as passed in by ``Styler.apply``. Unused -- + ``mask`` and ``props`` already carry everything needed to style -- + but required by ``apply``'s calling convention. + mask: np.ndarray + A 2-D boolean array, shaped like ``_data``, selecting the cells to + style. + props: str + A CSS properties string applied to the selected cells, e.g. + ``"background-color: blue;"``. + + Returns + ------- + np.ndarray + An array shaped like ``mask``, holding ``props`` at the cells it + selects and ``""`` (unstyled) everywhere else. + + Example + ------- + >>> mask_array = np.array([[False, True]]) + >>> Styler._mask_style(pd.DataFrame(), mask_array, "background-color: red;") + array([['', 'background-color: red;']], dtype='` for more + examples. """ - if self._triangle is None: - raise ValueError( - "highlight_lower_triangle requires a Styler created from " - "Triangle.style, so it knows which cells are the lower triangle." - ) + # Find which cells are beyond the valuation date. Does this by filling + # a triangle's cells with their valuation dates and then comparing them to + # the triangle's overall valuation date. if valuation_date is None: cutoff = self._triangle.valuation_date else: cutoff = pd.Timestamp(valuation_date) val_array = np.array(self._triangle.valuation).reshape( - self._triangle.shape[-2:], order="F" + self._triangle.shape[-2:], + order="F", ) - nan_triangle = np.where(val_array > cutoff, np.nan, 1) - if nan_triangle.shape != self.data.shape: + mask = val_array > cutoff + if mask.shape != self.data.shape: raise ValueError( "highlight_lower_triangle only supports a single (2-D) Triangle." ) @@ -157,7 +275,11 @@ def highlight_lower_triangle( if text_color is not None: props += f" color: {text_color};" - def f(_data: pd.DataFrame) -> np.ndarray: - return np.where(pd.isna(nan_triangle), props, "") - - return self.apply(f, axis=None) # pyright: ignore[reportReturnType] + return self.apply( # pyright: ignore[reportReturnType] + partial( + self._mask_style, + mask=mask, + props=props, + ), + axis=None, + ) diff --git a/chainladder/core/tests/test_style.py b/chainladder/core/tests/test_style.py index f6101bbe0..f96d406fb 100644 --- a/chainladder/core/tests/test_style.py +++ b/chainladder/core/tests/test_style.py @@ -41,9 +41,32 @@ def test_is_pandas_styler_subclass() -> None: assert issubclass(Styler, PandasStyler) -def test_wraps_a_dataframe(df: pd.DataFrame) -> None: +@pytest.mark.parametrize( + "obj", [np.array([1]), [1], None, "raa", 3, pd.Series([1])], ids=type +) +def test_rejects_anything_that_is_not_a_triangle(obj) -> None: """ - Check that Styler wraps a DataFrame the same way pandas' Styler does. + Check that the constructor rejects every non-Triangle, not just frames, so a + Styler always has the Triangle its methods rely on. + + Parameters + ---------- + obj: object + A value that is not a Triangle. + + Returns + ------- + None + + """ + with pytest.raises(TypeError, match="must be created from a Triangle"): + Styler(obj) + + +def test_rejection_names_the_type_it_received(df: pd.DataFrame) -> None: + """ + Check that the error names the offending type, and points DataFrame users at + pandas' own styler. Parameters ---------- @@ -55,19 +78,41 @@ def test_wraps_a_dataframe(df: pd.DataFrame) -> None: None """ - styler = Styler(df) - assert styler.data is df + with pytest.raises(TypeError, match="not a DataFrame. Use DataFrame.style"): + Styler(df) + with pytest.raises(TypeError, match="not a list.$"): + Styler([1]) + + +def test_wraps_a_triangles_frame(raa) -> None: + """ + Check that Styler wraps the Triangle's frame representation, the way pandas' + Styler wraps the DataFrame it is given. + + Parameters + ---------- + raa: Triangle + The raa sample data set. + + Returns + ------- + None + + """ + pd.testing.assert_frame_equal( + Styler(raa).data, raa.to_frame(origin_as_datetime=False) + ) -def test_chained_methods_preserve_subclass(df: pd.DataFrame) -> None: +def test_chained_methods_preserve_subclass(raa) -> None: """ Check that chaining a pandas Styler method still returns a chainladder Styler, not a plain pandas Styler. Parameters ---------- - df: pd.DataFrame - A simple two-column DataFrame fixture. + raa: Triangle + The raa sample data set. Returns ------- @@ -75,31 +120,38 @@ def test_chained_methods_preserve_subclass(df: pd.DataFrame) -> None: """ result = ( - Styler(df) + Styler(raa) .format(precision=1) .hide( # pyright: ignore[reportAttributeAccessIssue] - axis="columns", subset=["a"] + axis="columns", subset=[raa.development[0]] ) ) assert isinstance(result, Styler) -def test_renders_identically_to_pandas_styler(df: pd.DataFrame) -> None: +def test_renders_identically_to_pandas_styler(raa) -> None: """ - Check that Styler produces the same HTML as pandas' own Styler. + Check that Styler produces the same HTML as pandas' own Styler wrapping the + same frame, once pandas is given the default numeric format that Styler + applies to a Triangle on construction. Parameters ---------- - df: pd.DataFrame - A simple two-column DataFrame fixture. + raa: Triangle + The raa sample data set. Returns ------- None """ - cl_html = Styler(df, uuid="fixed").format(precision=2).to_html() - pd_html = PandasStyler(df, uuid="fixed").format(precision=2).to_html() + frame = raa.to_frame(origin_as_datetime=False) + cl_html = Styler(raa, uuid="fixed").to_html() + pd_html = ( + PandasStyler(frame, uuid="fixed") + .format(raa._get_format_str(data=frame), na_rep="") + .to_html() + ) assert cl_html == pd_html @@ -292,27 +344,6 @@ def test_highlight_lower_triangle_returns_styler(raa) -> None: assert isinstance(raa.style.highlight_lower_triangle(), Styler) -def test_highlight_lower_triangle_requires_a_triangle(df: pd.DataFrame) -> None: - """ - Check that calling it on a Styler not built from Triangle.style raises a - clear error, since there's no way to know which cells are the lower triangle. - - Parameters - ---------- - df: pd.DataFrame - A simple two-column DataFrame fixture. - - Returns - ------- - None - - """ - with pytest.raises( - ValueError, match="requires a Styler created from Triangle.style" - ): - Styler(df).highlight_lower_triangle() - - def test_highlight_lower_triangle_predicted_cells_not_highlighted_by_default( raa, ) -> None: @@ -377,11 +408,31 @@ def test_highlight_lower_triangle_with_valuation_date_highlights_predicted_cells ) -def test_highlight_lower_triangle_requires_matching_shape(clrd) -> None: +def test_style_rejects_multidimensional_triangle(clrd) -> None: + """ + Check that a Triangle holding more than a single index and column raises a + clear error at construction, rather than silently styling the long frame + that to_frame() flattens it into. + + Parameters + ---------- + clrd: Triangle + The clrd sample data set. + + Returns + ------- + None + + """ + assert clrd._dimensionality == "multi" + with pytest.raises(ValueError, match="only supports a single"): + _ = clrd.style + + +def test_style_accepts_single_triangle_selected_from_multidimensional(clrd) -> None: """ - Check that a Triangle whose to_frame() isn't a single origin-by-development - grid (multiple index labels and columns, here) raises a clear error rather - than silently misaligning the mask. + Check that the error the multidimensional case raises is escapable by + selecting a single index and column, as its message advises. Parameters ---------- @@ -393,5 +444,6 @@ def test_highlight_lower_triangle_requires_matching_shape(clrd) -> None: None """ - with pytest.raises(ValueError, match="only supports a single \\(2-D\\) Triangle"): - clrd.style.highlight_lower_triangle() + single = clrd.iloc[0, 0] + assert single._dimensionality == "single" + assert isinstance(single.style, Styler) diff --git a/chainladder/core/typing.py b/chainladder/core/typing.py index c3468884e..29496b61c 100644 --- a/chainladder/core/typing.py +++ b/chainladder/core/typing.py @@ -89,6 +89,12 @@ def nan_triangle(self) -> BackendArray: ... @property def valuation(self) -> pd.DatetimeIndex: ... + @property + def _dimensionality(self) -> str: ... + + @staticmethod + def _get_format_str(data: DataFrame) -> str: ... + key_labels: list[str] values: BackendArray array_backend: str From 51243b0358d07b9092dbabfcf7046cf409fc368c Mon Sep 17 00:00:00 2001 From: Gene Dan Date: Sat, 19 Sep 2026 12:01:24 -0500 Subject: [PATCH 15/20] [FIX] Remove unnecessary Triangle import. --- chainladder/core/style.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/chainladder/core/style.py b/chainladder/core/style.py index 7a2384a76..101e481c6 100644 --- a/chainladder/core/style.py +++ b/chainladder/core/style.py @@ -92,9 +92,6 @@ def __init__( *args: Any, **kwargs: Any, ) -> None: - # Imported here rather than at module scope: Triangle's own mixins import - # this module, so a top-level import would be circular. - from chainladder.core.triangle import Triangle if not isinstance(triangle, Triangle): # The frame case is the likely mistake, so point it somewhere useful. From e4c42bbbd3a57edf7416181f64b5511e64832ff1 Mon Sep 17 00:00:00 2001 From: Gene Dan Date: Sat, 19 Sep 2026 14:12:28 -0500 Subject: [PATCH 16/20] [FIX] Fix import hierarchy. --- chainladder/core/pandas.py | 13 ------------- chainladder/core/style.py | 14 +++++++++----- chainladder/core/triangle.py | 19 +++++++++++++++++++ 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/chainladder/core/pandas.py b/chainladder/core/pandas.py index e85f89440..4b7237bae 100644 --- a/chainladder/core/pandas.py +++ b/chainladder/core/pandas.py @@ -14,7 +14,6 @@ __dt64_dtype__, _warn_dask_parallel_deprecated, ) -from chainladder.core.style import Styler from chainladder.utils.utility_functions import concat, num_to_nan from typing import cast, TYPE_CHECKING @@ -237,18 +236,6 @@ def hvplot(self, *args: Any, **kwargs: Any) -> Any: df.index = df.index.to_timestamp(how="s") return df.hvplot(*args, **kwargs) - @property - def style(self) -> Styler: - """ - Returns a Styler for the Triangle. - - Returns - ------- - Styler - A Styler wrapping this Triangle's frame representation. - """ - return Styler(self) - @staticmethod def _get_axis( axis: Literal["index", "columns", "origin", "development"] | int | None, diff --git a/chainladder/core/style.py b/chainladder/core/style.py index 101e481c6..ab95136e7 100644 --- a/chainladder/core/style.py +++ b/chainladder/core/style.py @@ -15,16 +15,20 @@ import pandas as pd from pandas.io.formats.style import Styler as _PandasStyler -from datetime import date, datetime -from typing import Any, TYPE_CHECKING, TypeAlias +from chainladder.core.triangle import Triangle -if TYPE_CHECKING: - from chainladder import Triangle +from datetime import ( + date, + datetime, +) +from typing import ( + Any, + TypeAlias, +) # A value accepted by pandas.Timestamp's constructor. ValuationDateLike: TypeAlias = int | float | str | date | datetime | pd.Timestamp -del TYPE_CHECKING del annotations diff --git a/chainladder/core/triangle.py b/chainladder/core/triangle.py index 4084eee1a..062e68569 100644 --- a/chainladder/core/triangle.py +++ b/chainladder/core/triangle.py @@ -1,3 +1,7 @@ +""" +Define the Triangle class, the core data structure representing actuarial triangles. +""" + # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. @@ -27,6 +31,7 @@ if TYPE_CHECKING: from pandas import DataFrame, Series + from chainladder.core.style import Styler from chainladder.core.typing import BackendArray from numpy.typing import ArrayLike from pandas._libs.tslibs.timestamps import Timestamp # noqa @@ -891,6 +896,20 @@ def development(self, value): self._len_check(self.development, value) self.ddims = np.array([value] if type(value) is str else value) + @property + def style(self) -> Styler: + """ + Returns a Styler for the Triangle. + + Returns + ------- + Styler + A Styler wrapping this Triangle's frame representation. + """ + from chainladder.core.style import Styler + + return Styler(self) + def set_index(self, value, inplace=False): """Sets the index of the Triangle""" if inplace: From 0f57de3a48f3d081f241c742169443f66476bb62 Mon Sep 17 00:00:00 2001 From: Gene Dan Date: Sat, 19 Sep 2026 15:17:06 -0500 Subject: [PATCH 17/20] [FIX] Remove extra link to styler tutorial. --- chainladder/core/style.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/chainladder/core/style.py b/chainladder/core/style.py index ab95136e7..473838cc9 100644 --- a/chainladder/core/style.py +++ b/chainladder/core/style.py @@ -84,10 +84,6 @@ class Styler(_PandasStyler): 1987 7.2 2.7 1.1 nan nan nan nan nan nan 1988 5.1 1.9 nan nan nan nan nan nan nan 1989 1.7 nan nan nan nan nan nan nan nan - - Please see: :doc:`Triangle Visualization ` for more - examples. - """ def __init__( From 691520e2536b6fc28a88f277e1029f4c64239729 Mon Sep 17 00:00:00 2001 From: Gene Dan Date: Sat, 19 Sep 2026 15:43:14 -0500 Subject: [PATCH 18/20] [DOCS] Update styler tutorial, add localization examples. --- docs/user_guide/style.ipynb | 1216 +++++++++++++++++++++-------------- pyproject.toml | 1 + uv.lock | 623 +----------------- 3 files changed, 753 insertions(+), 1087 deletions(-) diff --git a/docs/user_guide/style.ipynb b/docs/user_guide/style.ipynb index 98efe571a..d79d57a7d 100644 --- a/docs/user_guide/style.ipynb +++ b/docs/user_guide/style.ipynb @@ -1,202 +1,212 @@ { "cells": [ { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "# Triangle Visualization\n", + "\n", + "Chainladder's {class}`~chainladder.Styler` class enables visual customization of triangles when displayed in a Jupyter notebook. Any styling options that can be applied to a Pandas DataFrame can also be applied to a Chainladder `Triangle`. In addition, the {class}`~chainladder.Styler` extends its [Pandas counterpart](https://pandas.pydata.org/docs/user_guide/style.html) with methods designed for actuaries.\n", + "\n", + "```{note}\n", + "The {class}`~chainladder.Styler` only works on single triangles.\n", + "```" + ], + "id": "ed15c4047e2dbe21" + }, + { + "metadata": {}, "cell_type": "markdown", - "id": "ed15c4047e2dbe21", - "metadata": { - "collapsed": true - }, "source": [ - "# Triangle Visualization" - ] + "## Highlighting the lower triangle\n", + "\n", + "The lower triangle contains cells that extend beyond the latest diagonal. This area can be highlited with `Triangle.style.highlight_lower_triangle()`." + ], + "id": "f5e2d19c26181e66" }, { "cell_type": "code", - "id": "65fd12501acef112", + "id": "82b1c3255e22bc03", "metadata": { "execution": { - "iopub.execute_input": "2026-09-11T21:41:16.406766Z", - "iopub.status.busy": "2026-09-11T21:41:16.406658Z", - "iopub.status.idle": "2026-09-11T21:41:17.505185Z", - "shell.execute_reply": "2026-09-11T21:41:17.504627Z" + "iopub.execute_input": "2026-09-11T21:41:17.507039Z", + "iopub.status.busy": "2026-09-11T21:41:17.506923Z", + "iopub.status.idle": "2026-09-11T21:41:17.514890Z", + "shell.execute_reply": "2026-09-11T21:41:17.514455Z" }, "ExecuteTime": { - "end_time": "2026-09-11T22:01:12.572490069Z", - "start_time": "2026-09-11T22:01:11.703468543Z" + "end_time": "2026-09-19T20:40:48.142036845Z", + "start_time": "2026-09-19T20:40:47.300243472Z" } }, "source": [ "import chainladder as cl\n", "\n", "raa = cl.load_sample(\"raa\")\n", - "raa" + "\n", + "raa.style.highlight_lower_triangle(color=\"blue\")" ], "outputs": [ { "data": { "text/plain": [ - " 12 24 36 48 60 72 84 96 108 120\n", - "1981 5012.0 8269.0 10907.0 11805.0 13539.0 16181.0 18009.0 18608.0 18662.0 18834.0\n", - "1982 106.0 4285.0 5396.0 10666.0 13782.0 15599.0 15496.0 16169.0 16704.0 NaN\n", - "1983 3410.0 8992.0 13873.0 16141.0 18735.0 22214.0 22863.0 23466.0 NaN NaN\n", - "1984 5655.0 11555.0 15766.0 21266.0 23425.0 26083.0 27067.0 NaN NaN NaN\n", - "1985 1092.0 9565.0 15836.0 22169.0 25955.0 26180.0 NaN NaN NaN NaN\n", - "1986 1513.0 6445.0 11702.0 12935.0 15852.0 NaN NaN NaN NaN NaN\n", - "1987 557.0 4020.0 10946.0 12314.0 NaN NaN NaN NaN NaN NaN\n", - "1988 1351.0 6947.0 13112.0 NaN NaN NaN NaN NaN NaN NaN\n", - "1989 3133.0 5395.0 NaN NaN NaN NaN NaN NaN NaN NaN\n", - "1990 2063.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN" + "" ], "text/html": [ - "\n", + "\n", + "
\n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - "
1224364860728496108120
 1224364860728496108120
19815,0128,26910,90711,80513,53916,18118,00918,60818,66218,834
19821064,2855,39610,66613,78215,59915,49616,16916,704
19833,4108,99213,87316,14118,73522,21422,86323,466
19845,65511,55515,76621,26623,42526,08327,067
19851,0929,56515,83622,16925,95526,180
19861,5136,44511,70212,93515,852
19875574,02010,94612,314
19881,3516,94713,112
19893,1335,395
19902,06319815,0128,26910,90711,80513,53916,18118,00918,60818,66218,834
19821064,2855,39610,66613,78215,59915,49616,16916,704
19833,4108,99213,87316,14118,73522,21422,86323,466
19845,65511,55515,76621,26623,42526,08327,067
19851,0929,56515,83622,16925,95526,180
19861,5136,44511,70212,93515,852
19875574,02010,94612,314
19881,3516,94713,112
19893,1335,395
19902,063
" + "\n" ] }, "execution_count": 1, @@ -207,181 +217,215 @@ "execution_count": 1 }, { - "cell_type": "code", - "id": "82b1c3255e22bc03", + "metadata": {}, + "cell_type": "markdown", + "source": "You may find that the blue contrasts too sharply against the white background of this website. You can change the color to a lighter shade of blue, and the text to white to improve readability.", + "id": "3cf0aa11faadd3f1" + }, + { "metadata": { "execution": { - "iopub.execute_input": "2026-09-11T21:41:17.507039Z", - "iopub.status.busy": "2026-09-11T21:41:17.506923Z", - "iopub.status.idle": "2026-09-11T21:41:17.514890Z", - "shell.execute_reply": "2026-09-11T21:41:17.514455Z" + "iopub.execute_input": "2026-09-11T21:41:17.516451Z", + "iopub.status.busy": "2026-09-11T21:41:17.516335Z", + "iopub.status.idle": "2026-09-11T21:41:17.559733Z", + "shell.execute_reply": "2026-09-11T21:41:17.559161Z" }, "ExecuteTime": { - "end_time": "2026-09-11T22:01:12.729936711Z", - "start_time": "2026-09-11T22:01:12.633141896Z" + "end_time": "2026-09-19T20:40:48.218230125Z", + "start_time": "2026-09-19T20:40:48.146899319Z" } }, + "cell_type": "code", "source": [ - "raa.style.highlight_lower_triangle(color=\"blue\")" + "full = cl.Chainladder().fit(raa).full_triangle_\n", + "full.style.highlight_lower_triangle(\n", + " color=\"#2F61AD\",\n", + " text_color=\"#FFFFFF\",\n", + " valuation_date=raa.valuation_date,\n", + ")" ], + "id": "0089690f", "outputs": [ { "data": { "text/plain": [ - "" + "" ], "text/html": [ "\n", - "\n", + "
\n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "
 122436486072849610812012243648607284961081201329999
19815,0128,26910,90711,80513,53916,18118,00918,60818,66218,834
19821064,2855,39610,66613,78215,59915,49616,16916,704
19833,4108,99213,87316,14118,73522,21422,86323,466
19845,65511,55515,76621,26623,42526,08327,067
19851,0929,56515,83622,16925,95526,180
19861,5136,44511,70212,93515,852
19875574,02010,94612,314
19881,3516,94713,112
19893,1335,395
19902,06319815,0128,26910,90711,80513,53916,18118,00918,60818,66218,83418,83418,834
19821064,2855,39610,66613,78215,59915,49616,16916,70416,85816,85816,858
19833,4108,99213,87316,14118,73522,21422,86323,46623,86324,08324,08324,083
19845,65511,55515,76621,26623,42526,08327,06727,96728,44128,70328,70328,703
19851,0929,56515,83622,16925,95526,18027,27828,18528,66328,92728,92728,927
19861,5136,44511,70212,93515,85217,64918,38919,00119,32319,50119,50119,501
19875574,02010,94612,31414,42816,06416,73817,29417,58717,74917,74917,749
19881,3516,94713,11216,66419,52521,73822,65023,40323,80024,01924,01924,019
19893,1335,3958,75911,13213,04314,52115,13015,63415,89816,04516,04516,045
19902,0636,18810,04612,76714,95916,65517,35317,93118,23418,40218,40218,402
\n" @@ -394,201 +438,189 @@ ], "execution_count": 2 }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## Localization\n", + "\n", + "Chainladder is used by actuaries all over the world. The `Styler` can be used to adapt the numeric formatting to specific locales. Let's try formating `genins` with the Swiss numbering format, which uses apostrophes as the thousands separator." + ], + "id": "c0003c7573b19f76" + }, { "metadata": { - "execution": { - "iopub.execute_input": "2026-09-11T21:41:17.516451Z", - "iopub.status.busy": "2026-09-11T21:41:17.516335Z", - "iopub.status.idle": "2026-09-11T21:41:17.559733Z", - "shell.execute_reply": "2026-09-11T21:41:17.559161Z" - }, "ExecuteTime": { - "end_time": "2026-09-11T22:01:12.843529894Z", - "start_time": "2026-09-11T22:01:12.754832157Z" + "end_time": "2026-09-19T20:40:48.288141793Z", + "start_time": "2026-09-19T20:40:48.241398739Z" } }, "cell_type": "code", + "source": [ + "genins = cl.load_sample(\"genins\")\n", + "\n", + "genins.style.format(\n", + " precision=0,\n", + " thousands=\"'\",\n", + " na_rep=\"\",\n", + ")" + ], + "id": "8bd149db1ac700f3", "outputs": [ { "data": { "text/plain": [ - "" + "" ], "text/html": [ "\n", - "\n", + "
\n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "
 122436486072849610812013299991224364860728496108120
19815,0128,26910,90711,80513,53916,18118,00918,60818,66218,83418,83418,834
19821064,2855,39610,66613,78215,59915,49616,16916,70416,85816,85816,858
19833,4108,99213,87316,14118,73522,21422,86323,46623,86324,08324,08324,083
19845,65511,55515,76621,26623,42526,08327,06727,96728,44128,70328,70328,703
19851,0929,56515,83622,16925,95526,18027,27828,18528,66328,92728,92728,927
19861,5136,44511,70212,93515,85217,64918,38919,00119,32319,50119,50119,501
19875574,02010,94612,31414,42816,06416,73817,29417,58717,74917,74917,749
19881,3516,94713,11216,66419,52521,73822,65023,40323,80024,01924,01924,019
19893,1335,3958,75911,13213,04314,52115,13015,63415,89816,04516,04516,045
19902,0636,18810,04612,76714,95916,65517,35317,93118,23418,40218,40218,4022001357'8481'124'7881'735'3302'218'2702'745'5963'319'9943'466'3363'606'2863'833'5153'901'463
2002352'1181'236'1392'170'0333'353'3223'799'0674'120'0634'647'8674'914'0395'339'085
2003290'5071'292'3062'218'5253'235'1793'985'9954'132'9184'628'9104'909'315
2004310'6081'418'8582'195'0473'757'4474'029'9294'381'9824'588'268
2005443'1601'136'3502'128'3332'897'8213'402'6723'873'311
2006396'1321'333'2172'180'7152'985'7523'691'712
2007440'8321'288'4632'419'8613'483'130
2008359'4801'421'1282'864'498
2009376'6861'363'294
2010344'014
\n" @@ -599,16 +631,202 @@ "output_type": "execute_result" } ], - "execution_count": 3, + "execution_count": 3 + }, + { + "metadata": {}, + "cell_type": "markdown", "source": [ - "full = cl.Chainladder().fit(raa).full_triangle_\n", - "full.style.highlight_lower_triangle(\n", - " color=\"#2F61AD\",\n", - " text_color=\"#FFFFFF\",\n", - " valuation_date=raa.valuation_date,\n", + "### Babel\n", + "\n", + "You can supply a format using the [babel](https://babel.pocoo.org/en/latest/) package if you have it installed. Let's try the [Indian numeric format](https://en.wikipedia.org/wiki/Indian_numbering_system)." + ], + "id": "39b84ce4ca3395e0" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-09-19T20:40:48.342975643Z", + "start_time": "2026-09-19T20:40:48.291637687Z" + } + }, + "cell_type": "code", + "source": [ + "from babel.numbers import format_decimal\n", + "\n", + "# The Indian numbering system groups by lakh and crore: 12,34,567.\n", + "genins.style.format(\n", + " lambda x: format_decimal(x, locale=\"en_IN\"),\n", + " na_rep=\"\",\n", ")" ], - "id": "0089690f" + "id": "28d799df4037a6c7", + "outputs": [ + { + "data": { + "text/plain": [ + "" + ], + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 1224364860728496108120
20013,57,84811,24,78817,35,33022,18,27027,45,59633,19,99434,66,33636,06,28638,33,51539,01,463
20023,52,11812,36,13921,70,03333,53,32237,99,06741,20,06346,47,86749,14,03953,39,085
20032,90,50712,92,30622,18,52532,35,17939,85,99541,32,91846,28,91049,09,315
20043,10,60814,18,85821,95,04737,57,44740,29,92943,81,98245,88,268
20054,43,16011,36,35021,28,33328,97,82134,02,67238,73,311
20063,96,13213,33,21721,80,71529,85,75236,91,712
20074,40,83212,88,46324,19,86134,83,130
20083,59,48014,21,12828,64,498
20093,76,68613,63,294
20103,44,014
\n" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 4 } ], "metadata": { diff --git a/pyproject.toml b/pyproject.toml index 79371a534..5605836c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,6 +59,7 @@ dev = [ "pre-commit", ] docs = [ + "babel", # For localization examples. "sphinx", "sphinx-rtd-theme", "nbsphinx", diff --git a/uv.lock b/uv.lock index f9dbf55a0..68a7c2138 100644 --- a/uv.lock +++ b/uv.lock @@ -1,12 +1,9 @@ version = 1 revision = 3 -requires-python = ">=3.10" +requires-python = ">=3.11" resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.12' and python_full_version < '3.14'", - "python_full_version == '3.11.*'", - "python_full_version < '3.11'", - "python_version < '0'", + "python_full_version >= '3.12'", + "python_full_version < '3.12'", ] [[package]] @@ -110,22 +107,10 @@ name = "cffi" version = "2.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "pycparser" }, + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/93/d7/516d984057745a6cd96575eea814fe1edd6646ee6efd552fb7b0921dec83/cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44", size = 184283, upload-time = "2025-09-08T23:22:08.01Z" }, - { url = "https://files.pythonhosted.org/packages/9e/84/ad6a0b408daa859246f57c03efd28e5dd1b33c21737c2db84cae8c237aa5/cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49", size = 180504, upload-time = "2025-09-08T23:22:10.637Z" }, - { url = "https://files.pythonhosted.org/packages/50/bd/b1a6362b80628111e6653c961f987faa55262b4002fcec42308cad1db680/cffi-2.0.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c", size = 208811, upload-time = "2025-09-08T23:22:12.267Z" }, - { url = "https://files.pythonhosted.org/packages/4f/27/6933a8b2562d7bd1fb595074cf99cc81fc3789f6a6c05cdabb46284a3188/cffi-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb", size = 216402, upload-time = "2025-09-08T23:22:13.455Z" }, - { url = "https://files.pythonhosted.org/packages/05/eb/b86f2a2645b62adcfff53b0dd97e8dfafb5c8aa864bd0d9a2c2049a0d551/cffi-2.0.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0", size = 203217, upload-time = "2025-09-08T23:22:14.596Z" }, - { url = "https://files.pythonhosted.org/packages/9f/e0/6cbe77a53acf5acc7c08cc186c9928864bd7c005f9efd0d126884858a5fe/cffi-2.0.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4", size = 203079, upload-time = "2025-09-08T23:22:15.769Z" }, - { url = "https://files.pythonhosted.org/packages/98/29/9b366e70e243eb3d14a5cb488dfd3a0b6b2f1fb001a203f653b93ccfac88/cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453", size = 216475, upload-time = "2025-09-08T23:22:17.427Z" }, - { url = "https://files.pythonhosted.org/packages/21/7a/13b24e70d2f90a322f2900c5d8e1f14fa7e2a6b3332b7309ba7b2ba51a5a/cffi-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495", size = 218829, upload-time = "2025-09-08T23:22:19.069Z" }, - { url = "https://files.pythonhosted.org/packages/60/99/c9dc110974c59cc981b1f5b66e1d8af8af764e00f0293266824d9c4254bc/cffi-2.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5", size = 211211, upload-time = "2025-09-08T23:22:20.588Z" }, - { url = "https://files.pythonhosted.org/packages/49/72/ff2d12dbf21aca1b32a40ed792ee6b40f6dc3a9cf1644bd7ef6e95e0ac5e/cffi-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb", size = 218036, upload-time = "2025-09-08T23:22:22.143Z" }, - { url = "https://files.pythonhosted.org/packages/e2/cc/027d7fb82e58c48ea717149b03bcadcbdc293553edb283af792bd4bcbb3f/cffi-2.0.0-cp310-cp310-win32.whl", hash = "sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a", size = 172184, upload-time = "2025-09-08T23:22:23.328Z" }, - { url = "https://files.pythonhosted.org/packages/33/fa/072dd15ae27fbb4e06b437eb6e944e75b068deb09e2a2826039e49ee2045/cffi-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739", size = 182790, upload-time = "2025-09-08T23:22:24.752Z" }, { url = "https://files.pythonhosted.org/packages/12/4a/3dfd5f7850cbf0d06dc84ba9aa00db766b52ca38d8b86e3a38314d52498c/cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe", size = 184344, upload-time = "2025-09-08T23:22:26.456Z" }, { url = "https://files.pythonhosted.org/packages/4f/8b/f0e4c441227ba756aafbe78f117485b25bb26b1c059d01f137fa6d14896b/cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c", size = 180560, upload-time = "2025-09-08T23:22:28.197Z" }, { url = "https://files.pythonhosted.org/packages/b1/b7/1200d354378ef52ec227395d95c2576330fd22a869f7a70e88e1447eb234/cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92", size = 209613, upload-time = "2025-09-08T23:22:29.475Z" }, @@ -203,8 +188,7 @@ source = { editable = "." } dependencies = [ { name = "dill" }, { name = "matplotlib" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "numpy" }, { name = "pandas" }, { name = "patsy" }, { name = "scikit-learn" }, @@ -213,10 +197,10 @@ dependencies = [ [package.optional-dependencies] all = [ + { name = "babel" }, { name = "dask" }, { name = "ipykernel" }, - { name = "ipython", version = "8.37.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "ipython", version = "9.6.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "ipython" }, { name = "jinja2" }, { name = "jupyter-book" }, { name = "lxml" }, @@ -233,16 +217,14 @@ all = [ { name = "pytest-xdist" }, { name = "ruff" }, { name = "sphinx" }, - { name = "sphinx-book-theme", version = "1.1.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "sphinx-book-theme", version = "1.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "sphinx-book-theme" }, { name = "sphinx-rtd-theme" }, { name = "sphinx-togglebutton" }, { name = "statsmodels" }, ] dev = [ { name = "ipykernel" }, - { name = "ipython", version = "8.37.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "ipython", version = "9.6.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "ipython" }, { name = "jinja2" }, { name = "lxml" }, { name = "pre-commit" }, @@ -253,16 +235,15 @@ dev = [ { name = "ruff" }, ] docs = [ - { name = "ipython", version = "8.37.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "ipython", version = "9.6.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "babel" }, + { name = "ipython" }, { name = "jupyter-book" }, { name = "nbsphinx" }, { name = "numpydoc" }, { name = "parso" }, { name = "polars" }, { name = "sphinx" }, - { name = "sphinx-book-theme", version = "1.1.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "sphinx-book-theme", version = "1.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "sphinx-book-theme" }, { name = "sphinx-rtd-theme" }, { name = "sphinx-togglebutton" }, { name = "statsmodels" }, @@ -273,8 +254,7 @@ performance = [ ] test = [ { name = "dask" }, - { name = "ipython", version = "8.37.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "ipython", version = "9.6.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "ipython" }, { name = "jinja2" }, { name = "lxml" }, { name = "nbmake" }, @@ -287,6 +267,7 @@ test = [ [package.metadata] requires-dist = [ + { name = "babel", marker = "extra == 'docs'" }, { name = "chainladder", extras = ["dev", "docs", "test"], marker = "extra == 'all'" }, { name = "cupy", marker = "extra == 'performance'" }, { name = "dask", marker = "extra == 'performance'" }, @@ -321,7 +302,7 @@ requires-dist = [ { name = "pytest-xdist", marker = "extra == 'dev'" }, { name = "ruff", marker = "extra == 'dev'" }, { name = "scikit-learn", specifier = ">1.4.2" }, - { name = "sparse", specifier = ">=0.9" }, + { name = "sparse", specifier = ">=0.18" }, { name = "sphinx", marker = "extra == 'docs'" }, { name = "sphinx-book-theme", marker = "python_full_version >= '3.11' and extra == 'docs'", specifier = ">=1.2,<1.3" }, { name = "sphinx-book-theme", marker = "python_full_version < '3.11' and extra == 'docs'", specifier = ">=1.1.4,<1.2" }, @@ -338,17 +319,6 @@ version = "3.4.3" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/83/2d/5fd176ceb9b2fc619e63405525573493ca23441330fcdaee6bef9460e924/charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14", size = 122371, upload-time = "2025-08-09T07:57:28.46Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d6/98/f3b8013223728a99b908c9344da3aa04ee6e3fa235f19409033eda92fb78/charset_normalizer-3.4.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72", size = 207695, upload-time = "2025-08-09T07:55:36.452Z" }, - { url = "https://files.pythonhosted.org/packages/21/40/5188be1e3118c82dcb7c2a5ba101b783822cfb413a0268ed3be0468532de/charset_normalizer-3.4.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe", size = 147153, upload-time = "2025-08-09T07:55:38.467Z" }, - { url = "https://files.pythonhosted.org/packages/37/60/5d0d74bc1e1380f0b72c327948d9c2aca14b46a9efd87604e724260f384c/charset_normalizer-3.4.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601", size = 160428, upload-time = "2025-08-09T07:55:40.072Z" }, - { url = "https://files.pythonhosted.org/packages/85/9a/d891f63722d9158688de58d050c59dc3da560ea7f04f4c53e769de5140f5/charset_normalizer-3.4.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c", size = 157627, upload-time = "2025-08-09T07:55:41.706Z" }, - { url = "https://files.pythonhosted.org/packages/65/1a/7425c952944a6521a9cfa7e675343f83fd82085b8af2b1373a2409c683dc/charset_normalizer-3.4.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2", size = 152388, upload-time = "2025-08-09T07:55:43.262Z" }, - { url = "https://files.pythonhosted.org/packages/f0/c9/a2c9c2a355a8594ce2446085e2ec97fd44d323c684ff32042e2a6b718e1d/charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0", size = 150077, upload-time = "2025-08-09T07:55:44.903Z" }, - { url = "https://files.pythonhosted.org/packages/3b/38/20a1f44e4851aa1c9105d6e7110c9d020e093dfa5836d712a5f074a12bf7/charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0", size = 161631, upload-time = "2025-08-09T07:55:46.346Z" }, - { url = "https://files.pythonhosted.org/packages/a4/fa/384d2c0f57edad03d7bec3ebefb462090d8905b4ff5a2d2525f3bb711fac/charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0", size = 159210, upload-time = "2025-08-09T07:55:47.539Z" }, - { url = "https://files.pythonhosted.org/packages/33/9e/eca49d35867ca2db336b6ca27617deed4653b97ebf45dfc21311ce473c37/charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a", size = 153739, upload-time = "2025-08-09T07:55:48.744Z" }, - { url = "https://files.pythonhosted.org/packages/2a/91/26c3036e62dfe8de8061182d33be5025e2424002125c9500faff74a6735e/charset_normalizer-3.4.3-cp310-cp310-win32.whl", hash = "sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f", size = 99825, upload-time = "2025-08-09T07:55:50.305Z" }, - { url = "https://files.pythonhosted.org/packages/e2/c6/f05db471f81af1fa01839d44ae2a8bfeec8d2a8b4590f16c4e7393afd323/charset_normalizer-3.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669", size = 107452, upload-time = "2025-08-09T07:55:51.461Z" }, { url = "https://files.pythonhosted.org/packages/7f/b5/991245018615474a60965a7c9cd2b4efbaabd16d582a5547c47ee1c7730b/charset_normalizer-3.4.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b", size = 204483, upload-time = "2025-08-09T07:55:53.12Z" }, { url = "https://files.pythonhosted.org/packages/c7/2a/ae245c41c06299ec18262825c1569c5d3298fc920e4ddf56ab011b417efd/charset_normalizer-3.4.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64", size = 145520, upload-time = "2025-08-09T07:55:54.712Z" }, { url = "https://files.pythonhosted.org/packages/3a/a4/b3b6c76e7a635748c4421d2b92c7b8f90a432f98bda5082049af37ffc8e3/charset_normalizer-3.4.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91", size = 158876, upload-time = "2025-08-09T07:55:56.024Z" }, @@ -435,87 +405,12 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl", hash = "sha256:c615d91d75f7f04f095b30d1c1711babd43bdc6419c1be9886a85f2f4e489417", size = 7294, upload-time = "2025-07-25T14:02:02.896Z" }, ] -[[package]] -name = "contourpy" -version = "1.3.2" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.11'", -] -dependencies = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" } }, -] -sdist = { url = "https://files.pythonhosted.org/packages/66/54/eb9bfc647b19f2009dd5c7f5ec51c4e6ca831725f1aea7a993034f483147/contourpy-1.3.2.tar.gz", hash = "sha256:b6945942715a034c671b7fc54f9588126b0b8bf23db2696e3ca8328f3ff0ab54", size = 13466130, upload-time = "2025-04-15T17:47:53.79Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/12/a3/da4153ec8fe25d263aa48c1a4cbde7f49b59af86f0b6f7862788c60da737/contourpy-1.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ba38e3f9f330af820c4b27ceb4b9c7feee5fe0493ea53a8720f4792667465934", size = 268551, upload-time = "2025-04-15T17:34:46.581Z" }, - { url = "https://files.pythonhosted.org/packages/2f/6c/330de89ae1087eb622bfca0177d32a7ece50c3ef07b28002de4757d9d875/contourpy-1.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dc41ba0714aa2968d1f8674ec97504a8f7e334f48eeacebcaa6256213acb0989", size = 253399, upload-time = "2025-04-15T17:34:51.427Z" }, - { url = "https://files.pythonhosted.org/packages/c1/bd/20c6726b1b7f81a8bee5271bed5c165f0a8e1f572578a9d27e2ccb763cb2/contourpy-1.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9be002b31c558d1ddf1b9b415b162c603405414bacd6932d031c5b5a8b757f0d", size = 312061, upload-time = "2025-04-15T17:34:55.961Z" }, - { url = "https://files.pythonhosted.org/packages/22/fc/a9665c88f8a2473f823cf1ec601de9e5375050f1958cbb356cdf06ef1ab6/contourpy-1.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8d2e74acbcba3bfdb6d9d8384cdc4f9260cae86ed9beee8bd5f54fee49a430b9", size = 351956, upload-time = "2025-04-15T17:35:00.992Z" }, - { url = "https://files.pythonhosted.org/packages/25/eb/9f0a0238f305ad8fb7ef42481020d6e20cf15e46be99a1fcf939546a177e/contourpy-1.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e259bced5549ac64410162adc973c5e2fb77f04df4a439d00b478e57a0e65512", size = 320872, upload-time = "2025-04-15T17:35:06.177Z" }, - { url = "https://files.pythonhosted.org/packages/32/5c/1ee32d1c7956923202f00cf8d2a14a62ed7517bdc0ee1e55301227fc273c/contourpy-1.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad687a04bc802cbe8b9c399c07162a3c35e227e2daccf1668eb1f278cb698631", size = 325027, upload-time = "2025-04-15T17:35:11.244Z" }, - { url = "https://files.pythonhosted.org/packages/83/bf/9baed89785ba743ef329c2b07fd0611d12bfecbedbdd3eeecf929d8d3b52/contourpy-1.3.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cdd22595308f53ef2f891040ab2b93d79192513ffccbd7fe19be7aa773a5e09f", size = 1306641, upload-time = "2025-04-15T17:35:26.701Z" }, - { url = "https://files.pythonhosted.org/packages/d4/cc/74e5e83d1e35de2d28bd97033426b450bc4fd96e092a1f7a63dc7369b55d/contourpy-1.3.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b4f54d6a2defe9f257327b0f243612dd051cc43825587520b1bf74a31e2f6ef2", size = 1374075, upload-time = "2025-04-15T17:35:43.204Z" }, - { url = "https://files.pythonhosted.org/packages/0c/42/17f3b798fd5e033b46a16f8d9fcb39f1aba051307f5ebf441bad1ecf78f8/contourpy-1.3.2-cp310-cp310-win32.whl", hash = "sha256:f939a054192ddc596e031e50bb13b657ce318cf13d264f095ce9db7dc6ae81c0", size = 177534, upload-time = "2025-04-15T17:35:46.554Z" }, - { url = "https://files.pythonhosted.org/packages/54/ec/5162b8582f2c994721018d0c9ece9dc6ff769d298a8ac6b6a652c307e7df/contourpy-1.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:c440093bbc8fc21c637c03bafcbef95ccd963bc6e0514ad887932c18ca2a759a", size = 221188, upload-time = "2025-04-15T17:35:50.064Z" }, - { url = "https://files.pythonhosted.org/packages/b3/b9/ede788a0b56fc5b071639d06c33cb893f68b1178938f3425debebe2dab78/contourpy-1.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6a37a2fb93d4df3fc4c0e363ea4d16f83195fc09c891bc8ce072b9d084853445", size = 269636, upload-time = "2025-04-15T17:35:54.473Z" }, - { url = "https://files.pythonhosted.org/packages/e6/75/3469f011d64b8bbfa04f709bfc23e1dd71be54d05b1b083be9f5b22750d1/contourpy-1.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b7cd50c38f500bbcc9b6a46643a40e0913673f869315d8e70de0438817cb7773", size = 254636, upload-time = "2025-04-15T17:35:58.283Z" }, - { url = "https://files.pythonhosted.org/packages/8d/2f/95adb8dae08ce0ebca4fd8e7ad653159565d9739128b2d5977806656fcd2/contourpy-1.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6658ccc7251a4433eebd89ed2672c2ed96fba367fd25ca9512aa92a4b46c4f1", size = 313053, upload-time = "2025-04-15T17:36:03.235Z" }, - { url = "https://files.pythonhosted.org/packages/c3/a6/8ccf97a50f31adfa36917707fe39c9a0cbc24b3bbb58185577f119736cc9/contourpy-1.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:70771a461aaeb335df14deb6c97439973d253ae70660ca085eec25241137ef43", size = 352985, upload-time = "2025-04-15T17:36:08.275Z" }, - { url = "https://files.pythonhosted.org/packages/1d/b6/7925ab9b77386143f39d9c3243fdd101621b4532eb126743201160ffa7e6/contourpy-1.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65a887a6e8c4cd0897507d814b14c54a8c2e2aa4ac9f7686292f9769fcf9a6ab", size = 323750, upload-time = "2025-04-15T17:36:13.29Z" }, - { url = "https://files.pythonhosted.org/packages/c2/f3/20c5d1ef4f4748e52d60771b8560cf00b69d5c6368b5c2e9311bcfa2a08b/contourpy-1.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3859783aefa2b8355697f16642695a5b9792e7a46ab86da1118a4a23a51a33d7", size = 326246, upload-time = "2025-04-15T17:36:18.329Z" }, - { url = "https://files.pythonhosted.org/packages/8c/e5/9dae809e7e0b2d9d70c52b3d24cba134dd3dad979eb3e5e71f5df22ed1f5/contourpy-1.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:eab0f6db315fa4d70f1d8ab514e527f0366ec021ff853d7ed6a2d33605cf4b83", size = 1308728, upload-time = "2025-04-15T17:36:33.878Z" }, - { url = "https://files.pythonhosted.org/packages/e2/4a/0058ba34aeea35c0b442ae61a4f4d4ca84d6df8f91309bc2d43bb8dd248f/contourpy-1.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d91a3ccc7fea94ca0acab82ceb77f396d50a1f67412efe4c526f5d20264e6ecd", size = 1375762, upload-time = "2025-04-15T17:36:51.295Z" }, - { url = "https://files.pythonhosted.org/packages/09/33/7174bdfc8b7767ef2c08ed81244762d93d5c579336fc0b51ca57b33d1b80/contourpy-1.3.2-cp311-cp311-win32.whl", hash = "sha256:1c48188778d4d2f3d48e4643fb15d8608b1d01e4b4d6b0548d9b336c28fc9b6f", size = 178196, upload-time = "2025-04-15T17:36:55.002Z" }, - { url = "https://files.pythonhosted.org/packages/5e/fe/4029038b4e1c4485cef18e480b0e2cd2d755448bb071eb9977caac80b77b/contourpy-1.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:5ebac872ba09cb8f2131c46b8739a7ff71de28a24c869bcad554477eb089a878", size = 222017, upload-time = "2025-04-15T17:36:58.576Z" }, - { url = "https://files.pythonhosted.org/packages/34/f7/44785876384eff370c251d58fd65f6ad7f39adce4a093c934d4a67a7c6b6/contourpy-1.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4caf2bcd2969402bf77edc4cb6034c7dd7c0803213b3523f111eb7460a51b8d2", size = 271580, upload-time = "2025-04-15T17:37:03.105Z" }, - { url = "https://files.pythonhosted.org/packages/93/3b/0004767622a9826ea3d95f0e9d98cd8729015768075d61f9fea8eeca42a8/contourpy-1.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:82199cb78276249796419fe36b7386bd8d2cc3f28b3bc19fe2454fe2e26c4c15", size = 255530, upload-time = "2025-04-15T17:37:07.026Z" }, - { url = "https://files.pythonhosted.org/packages/e7/bb/7bd49e1f4fa805772d9fd130e0d375554ebc771ed7172f48dfcd4ca61549/contourpy-1.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:106fab697af11456fcba3e352ad50effe493a90f893fca6c2ca5c033820cea92", size = 307688, upload-time = "2025-04-15T17:37:11.481Z" }, - { url = "https://files.pythonhosted.org/packages/fc/97/e1d5dbbfa170725ef78357a9a0edc996b09ae4af170927ba8ce977e60a5f/contourpy-1.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d14f12932a8d620e307f715857107b1d1845cc44fdb5da2bc8e850f5ceba9f87", size = 347331, upload-time = "2025-04-15T17:37:18.212Z" }, - { url = "https://files.pythonhosted.org/packages/6f/66/e69e6e904f5ecf6901be3dd16e7e54d41b6ec6ae3405a535286d4418ffb4/contourpy-1.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:532fd26e715560721bb0d5fc7610fce279b3699b018600ab999d1be895b09415", size = 318963, upload-time = "2025-04-15T17:37:22.76Z" }, - { url = "https://files.pythonhosted.org/packages/a8/32/b8a1c8965e4f72482ff2d1ac2cd670ce0b542f203c8e1d34e7c3e6925da7/contourpy-1.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26b383144cf2d2c29f01a1e8170f50dacf0eac02d64139dcd709a8ac4eb3cfe", size = 323681, upload-time = "2025-04-15T17:37:33.001Z" }, - { url = "https://files.pythonhosted.org/packages/30/c6/12a7e6811d08757c7162a541ca4c5c6a34c0f4e98ef2b338791093518e40/contourpy-1.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c49f73e61f1f774650a55d221803b101d966ca0c5a2d6d5e4320ec3997489441", size = 1308674, upload-time = "2025-04-15T17:37:48.64Z" }, - { url = "https://files.pythonhosted.org/packages/2a/8a/bebe5a3f68b484d3a2b8ffaf84704b3e343ef1addea528132ef148e22b3b/contourpy-1.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3d80b2c0300583228ac98d0a927a1ba6a2ba6b8a742463c564f1d419ee5b211e", size = 1380480, upload-time = "2025-04-15T17:38:06.7Z" }, - { url = "https://files.pythonhosted.org/packages/34/db/fcd325f19b5978fb509a7d55e06d99f5f856294c1991097534360b307cf1/contourpy-1.3.2-cp312-cp312-win32.whl", hash = "sha256:90df94c89a91b7362e1142cbee7568f86514412ab8a2c0d0fca72d7e91b62912", size = 178489, upload-time = "2025-04-15T17:38:10.338Z" }, - { url = "https://files.pythonhosted.org/packages/01/c8/fadd0b92ffa7b5eb5949bf340a63a4a496a6930a6c37a7ba0f12acb076d6/contourpy-1.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:8c942a01d9163e2e5cfb05cb66110121b8d07ad438a17f9e766317bcb62abf73", size = 223042, upload-time = "2025-04-15T17:38:14.239Z" }, - { url = "https://files.pythonhosted.org/packages/2e/61/5673f7e364b31e4e7ef6f61a4b5121c5f170f941895912f773d95270f3a2/contourpy-1.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:de39db2604ae755316cb5967728f4bea92685884b1e767b7c24e983ef5f771cb", size = 271630, upload-time = "2025-04-15T17:38:19.142Z" }, - { url = "https://files.pythonhosted.org/packages/ff/66/a40badddd1223822c95798c55292844b7e871e50f6bfd9f158cb25e0bd39/contourpy-1.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3f9e896f447c5c8618f1edb2bafa9a4030f22a575ec418ad70611450720b5b08", size = 255670, upload-time = "2025-04-15T17:38:23.688Z" }, - { url = "https://files.pythonhosted.org/packages/1e/c7/cf9fdee8200805c9bc3b148f49cb9482a4e3ea2719e772602a425c9b09f8/contourpy-1.3.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71e2bd4a1c4188f5c2b8d274da78faab884b59df20df63c34f74aa1813c4427c", size = 306694, upload-time = "2025-04-15T17:38:28.238Z" }, - { url = "https://files.pythonhosted.org/packages/dd/e7/ccb9bec80e1ba121efbffad7f38021021cda5be87532ec16fd96533bb2e0/contourpy-1.3.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de425af81b6cea33101ae95ece1f696af39446db9682a0b56daaa48cfc29f38f", size = 345986, upload-time = "2025-04-15T17:38:33.502Z" }, - { url = "https://files.pythonhosted.org/packages/dc/49/ca13bb2da90391fa4219fdb23b078d6065ada886658ac7818e5441448b78/contourpy-1.3.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:977e98a0e0480d3fe292246417239d2d45435904afd6d7332d8455981c408b85", size = 318060, upload-time = "2025-04-15T17:38:38.672Z" }, - { url = "https://files.pythonhosted.org/packages/c8/65/5245ce8c548a8422236c13ffcdcdada6a2a812c361e9e0c70548bb40b661/contourpy-1.3.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:434f0adf84911c924519d2b08fc10491dd282b20bdd3fa8f60fd816ea0b48841", size = 322747, upload-time = "2025-04-15T17:38:43.712Z" }, - { url = "https://files.pythonhosted.org/packages/72/30/669b8eb48e0a01c660ead3752a25b44fdb2e5ebc13a55782f639170772f9/contourpy-1.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c66c4906cdbc50e9cba65978823e6e00b45682eb09adbb78c9775b74eb222422", size = 1308895, upload-time = "2025-04-15T17:39:00.224Z" }, - { url = "https://files.pythonhosted.org/packages/05/5a/b569f4250decee6e8d54498be7bdf29021a4c256e77fe8138c8319ef8eb3/contourpy-1.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8b7fc0cd78ba2f4695fd0a6ad81a19e7e3ab825c31b577f384aa9d7817dc3bef", size = 1379098, upload-time = "2025-04-15T17:43:29.649Z" }, - { url = "https://files.pythonhosted.org/packages/19/ba/b227c3886d120e60e41b28740ac3617b2f2b971b9f601c835661194579f1/contourpy-1.3.2-cp313-cp313-win32.whl", hash = "sha256:15ce6ab60957ca74cff444fe66d9045c1fd3e92c8936894ebd1f3eef2fff075f", size = 178535, upload-time = "2025-04-15T17:44:44.532Z" }, - { url = "https://files.pythonhosted.org/packages/12/6e/2fed56cd47ca739b43e892707ae9a13790a486a3173be063681ca67d2262/contourpy-1.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:e1578f7eafce927b168752ed7e22646dad6cd9bca673c60bff55889fa236ebf9", size = 223096, upload-time = "2025-04-15T17:44:48.194Z" }, - { url = "https://files.pythonhosted.org/packages/54/4c/e76fe2a03014a7c767d79ea35c86a747e9325537a8b7627e0e5b3ba266b4/contourpy-1.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0475b1f6604896bc7c53bb070e355e9321e1bc0d381735421a2d2068ec56531f", size = 285090, upload-time = "2025-04-15T17:43:34.084Z" }, - { url = "https://files.pythonhosted.org/packages/7b/e2/5aba47debd55d668e00baf9651b721e7733975dc9fc27264a62b0dd26eb8/contourpy-1.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c85bb486e9be652314bb5b9e2e3b0d1b2e643d5eec4992c0fbe8ac71775da739", size = 268643, upload-time = "2025-04-15T17:43:38.626Z" }, - { url = "https://files.pythonhosted.org/packages/a1/37/cd45f1f051fe6230f751cc5cdd2728bb3a203f5619510ef11e732109593c/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:745b57db7758f3ffc05a10254edd3182a2a83402a89c00957a8e8a22f5582823", size = 310443, upload-time = "2025-04-15T17:43:44.522Z" }, - { url = "https://files.pythonhosted.org/packages/8b/a2/36ea6140c306c9ff6dd38e3bcec80b3b018474ef4d17eb68ceecd26675f4/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:970e9173dbd7eba9b4e01aab19215a48ee5dd3f43cef736eebde064a171f89a5", size = 349865, upload-time = "2025-04-15T17:43:49.545Z" }, - { url = "https://files.pythonhosted.org/packages/95/b7/2fc76bc539693180488f7b6cc518da7acbbb9e3b931fd9280504128bf956/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6c4639a9c22230276b7bffb6a850dfc8258a2521305e1faefe804d006b2e532", size = 321162, upload-time = "2025-04-15T17:43:54.203Z" }, - { url = "https://files.pythonhosted.org/packages/f4/10/76d4f778458b0aa83f96e59d65ece72a060bacb20cfbee46cf6cd5ceba41/contourpy-1.3.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc829960f34ba36aad4302e78eabf3ef16a3a100863f0d4eeddf30e8a485a03b", size = 327355, upload-time = "2025-04-15T17:44:01.025Z" }, - { url = "https://files.pythonhosted.org/packages/43/a3/10cf483ea683f9f8ab096c24bad3cce20e0d1dd9a4baa0e2093c1c962d9d/contourpy-1.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:d32530b534e986374fc19eaa77fcb87e8a99e5431499949b828312bdcd20ac52", size = 1307935, upload-time = "2025-04-15T17:44:17.322Z" }, - { url = "https://files.pythonhosted.org/packages/78/73/69dd9a024444489e22d86108e7b913f3528f56cfc312b5c5727a44188471/contourpy-1.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e298e7e70cf4eb179cc1077be1c725b5fd131ebc81181bf0c03525c8abc297fd", size = 1372168, upload-time = "2025-04-15T17:44:33.43Z" }, - { url = "https://files.pythonhosted.org/packages/0f/1b/96d586ccf1b1a9d2004dd519b25fbf104a11589abfd05484ff12199cca21/contourpy-1.3.2-cp313-cp313t-win32.whl", hash = "sha256:d0e589ae0d55204991450bb5c23f571c64fe43adaa53f93fc902a84c96f52fe1", size = 189550, upload-time = "2025-04-15T17:44:37.092Z" }, - { url = "https://files.pythonhosted.org/packages/b0/e6/6000d0094e8a5e32ad62591c8609e269febb6e4db83a1c75ff8868b42731/contourpy-1.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:78e9253c3de756b3f6a5174d024c4835acd59eb3f8e2ca13e775dbffe1558f69", size = 238214, upload-time = "2025-04-15T17:44:40.827Z" }, - { url = "https://files.pythonhosted.org/packages/33/05/b26e3c6ecc05f349ee0013f0bb850a761016d89cec528a98193a48c34033/contourpy-1.3.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:fd93cc7f3139b6dd7aab2f26a90dde0aa9fc264dbf70f6740d498a70b860b82c", size = 265681, upload-time = "2025-04-15T17:44:59.314Z" }, - { url = "https://files.pythonhosted.org/packages/2b/25/ac07d6ad12affa7d1ffed11b77417d0a6308170f44ff20fa1d5aa6333f03/contourpy-1.3.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:107ba8a6a7eec58bb475329e6d3b95deba9440667c4d62b9b6063942b61d7f16", size = 315101, upload-time = "2025-04-15T17:45:04.165Z" }, - { url = "https://files.pythonhosted.org/packages/8f/4d/5bb3192bbe9d3f27e3061a6a8e7733c9120e203cb8515767d30973f71030/contourpy-1.3.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ded1706ed0c1049224531b81128efbd5084598f18d8a2d9efae833edbd2b40ad", size = 220599, upload-time = "2025-04-15T17:45:08.456Z" }, - { url = "https://files.pythonhosted.org/packages/ff/c0/91f1215d0d9f9f343e4773ba6c9b89e8c0cc7a64a6263f21139da639d848/contourpy-1.3.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5f5964cdad279256c084b69c3f412b7801e15356b16efa9d78aa974041903da0", size = 266807, upload-time = "2025-04-15T17:45:15.535Z" }, - { url = "https://files.pythonhosted.org/packages/d4/79/6be7e90c955c0487e7712660d6cead01fa17bff98e0ea275737cc2bc8e71/contourpy-1.3.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49b65a95d642d4efa8f64ba12558fcb83407e58a2dfba9d796d77b63ccfcaff5", size = 318729, upload-time = "2025-04-15T17:45:20.166Z" }, - { url = "https://files.pythonhosted.org/packages/87/68/7f46fb537958e87427d98a4074bcde4b67a70b04900cfc5ce29bc2f556c1/contourpy-1.3.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:8c5acb8dddb0752bf252e01a3035b21443158910ac16a3b0d20e7fed7d534ce5", size = 221791, upload-time = "2025-04-15T17:45:24.794Z" }, -] - [[package]] name = "contourpy" version = "1.3.3" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.12' and python_full_version < '3.14'", - "python_full_version == '3.11.*'", -] dependencies = [ - { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" } }, + { name = "numpy" }, ] sdist = { url = "https://files.pythonhosted.org/packages/58/01/1253e6698a07380cd31a736d248a3f2a50a7c88779a1813da27503cadc2a/contourpy-1.3.3.tar.gz", hash = "sha256:083e12155b210502d0bca491432bb04d56dc3432f95a979b429f2848c3dbe880", size = 13466174, upload-time = "2025-07-26T12:03:12.549Z" } wheels = [ @@ -598,20 +493,6 @@ version = "7.15.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/76/d0/55fe630f4cf94e3fcba868240fad8c8cdd1f764e2a932f8926347e6ec4cd/coverage-7.15.2.tar.gz", hash = "sha256:3df60dc267f0a2ca23cb7a9ab1109c62b9335ffbf519fcfe167157c28c09b81d", size = 927741, upload-time = "2026-07-15T18:56:19.558Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/10/03/060ce69008ac97bbc01b1411b3e55b61f6f015659400b46749b662107831/coverage-7.15.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9b5bd92ff1ec22e535eab0de75fa6db021992791f461a2aceb7822c625a1187d", size = 221284, upload-time = "2026-07-15T18:53:29.52Z" }, - { url = "https://files.pythonhosted.org/packages/fc/a3/d936e8b53edd9684100a6aefaf3fcabaa54728fe33324436c8d279c047aa/coverage-7.15.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:44826758cfe73fcd0e6af5deb4ba6d5417cc1d13df3acb35c93484a11160f846", size = 221799, upload-time = "2026-07-15T18:53:31.708Z" }, - { url = "https://files.pythonhosted.org/packages/ae/a3/ca234b06aec7ee28226f11d39a696b4481fe5eddfce8e03bf39979bb8ffb/coverage-7.15.2-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:09f5c6ec5901f667bd97dd140b5b9a2586b10efec66f46fb1e6d8135f8b95bdf", size = 248544, upload-time = "2026-07-15T18:53:33.212Z" }, - { url = "https://files.pythonhosted.org/packages/2b/89/dda79527bb7573ba91828b2fb91b3105d87378d6a2749ca0c0924ce0addd/coverage-7.15.2-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1d16e3a7104ea84f03e614611b3edbf6fb6892554b3ab0fe7fbb3f2b2ef04376", size = 250374, upload-time = "2026-07-15T18:53:34.683Z" }, - { url = "https://files.pythonhosted.org/packages/67/c6/c33755a34572f81f49a8c0cdf6b622f35ccb3238b136e1909daf0cdd4319/coverage-7.15.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d46e62cb35d91e6e2589fda6d28074426b0e276422b5d2ebef2c6b11dc60dbfd", size = 252239, upload-time = "2026-07-15T18:53:36.205Z" }, - { url = "https://files.pythonhosted.org/packages/b9/6f/dc341741b375be53a5baeee5b4bf0f0e525d38caed428f7932d23bb7bcb1/coverage-7.15.2-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dfd3db045e95960ae3683059571e597fda7cc610106a8916f77c5839048c1deb", size = 254150, upload-time = "2026-07-15T18:53:37.863Z" }, - { url = "https://files.pythonhosted.org/packages/e9/8d/966a18a5b195cb4e77b14c53f5f3dce22b5da05e6de7fafd1e08f2d2067a/coverage-7.15.2-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:affd532502d34c0472d0cdb181325c89f1d2c44992fef0c17e88e7b1576259a1", size = 249234, upload-time = "2026-07-15T18:53:39.394Z" }, - { url = "https://files.pythonhosted.org/packages/c5/8b/8b2e367496ab48484d48e79984fec76cdc1b7cb5d3a00ee799a5602e3ec9/coverage-7.15.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d17d7512151fedfcc64c1821a8977fc9be0dbf495754669afcab7b57abc98ae9", size = 250276, upload-time = "2026-07-15T18:53:41.027Z" }, - { url = "https://files.pythonhosted.org/packages/63/92/1199318a200eb6c8c6ce0192c892c8710ac791abbe0f35099294620bbfda/coverage-7.15.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e26ff680768b8095e8874aabe0e9d3a47a2a9f176a8340d05f8604c56457c23a", size = 248283, upload-time = "2026-07-15T18:53:42.557Z" }, - { url = "https://files.pythonhosted.org/packages/56/da/be284a55c5619bda891a89c27dfd59324a2c6a14d755cf6aac6960ceebeb/coverage-7.15.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:7e8f27131dc7cd53de2c137dd207b3720919320b3c20d499dc30aa9ee6173287", size = 252093, upload-time = "2026-07-15T18:53:44.271Z" }, - { url = "https://files.pythonhosted.org/packages/d4/53/ee112da833ddd77b73c6d781a98029b45b584b136615b4900ed0569f887e/coverage-7.15.2-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:728a33676d4c3f0db977990a4bd421dcaa3be3e53b5b6273036fff6666008e89", size = 248552, upload-time = "2026-07-15T18:53:45.7Z" }, - { url = "https://files.pythonhosted.org/packages/82/6a/802cfc802e9113494c80bf3f284cd4d72faeb1f24e244f61046af364f2ca/coverage-7.15.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:29c052f7c83ccfcc5c577eaae025d2e4a9bb80daf03c0ac31c996e83b000ce88", size = 249154, upload-time = "2026-07-15T18:53:47.256Z" }, - { url = "https://files.pythonhosted.org/packages/2c/65/529808e91d651147edae408fd9e894abc3b8cad7f3e594bbc36719a3e13a/coverage-7.15.2-cp310-cp310-win32.whl", hash = "sha256:1268ac8fb9ddcd783d3948dbabaf80a5d53bfdaa0575e873e2139a692f797443", size = 223334, upload-time = "2026-07-15T18:53:48.768Z" }, - { url = "https://files.pythonhosted.org/packages/68/0f/0e1829d7001130876dfbc0b4e1c737ea7c155b809e3e4a98a0aa268e2369/coverage-7.15.2-cp310-cp310-win_amd64.whl", hash = "sha256:9f4432898c4bf2fba0435bbe35dd4437d7264565e5a88a21f5b49d8662a6b629", size = 223959, upload-time = "2026-07-15T18:53:50.429Z" }, { url = "https://files.pythonhosted.org/packages/7d/3a/54536704f507d4573bf9161c4d0dd3dd59b6d85e48c664e901b6844d8e33/coverage-7.15.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2f1ec6f304b156669cfde653b4e9a953f5de87e247ea02ac599bce0ab2744036", size = 221414, upload-time = "2026-07-15T18:53:51.941Z" }, { url = "https://files.pythonhosted.org/packages/b6/d9/8ba925d29743e3577b21e4d8c11a702b76bc93c41e7fdfd1177af63d4b8d/coverage-7.15.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4d3361879d736f469f45723c11ea1a5bbdaf1f6928f0e632c940378b5aa9b660", size = 221913, upload-time = "2026-07-15T18:53:53.682Z" }, { url = "https://files.pythonhosted.org/packages/09/54/a855f3aa0187f2b431ade4e4791b77b56282cfb5d201c83ec26a31b5b36a/coverage-7.15.2-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c6a98d698f9e2c8008d0370ec7fc452ebfcc530002ae2d0061170d768b992589", size = 252332, upload-time = "2026-07-15T18:53:55.467Z" }, @@ -701,8 +582,7 @@ version = "13.6.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "fastrlock" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "numpy" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a7/95/c2c7b5dca22dd7409308d076c33c681f810efd77e2b62e5107027cc98597/cupy-13.6.0.tar.gz", hash = "sha256:3cba30ae3dd32b5d5c6536e710cb98015227cd4ba83c46b3f1825a7ae55b6667", size = 3319720, upload-time = "2025-08-18T08:33:04.503Z" } @@ -740,10 +620,6 @@ version = "1.8.17" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/15/ad/71e708ff4ca377c4230530d6a7aa7992592648c122a2cd2b321cf8b35a76/debugpy-1.8.17.tar.gz", hash = "sha256:fd723b47a8c08892b1a16b2c6239a8b96637c62a59b94bb5dab4bac592a58a8e", size = 1644129, upload-time = "2025-09-17T16:33:20.633Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/38/36/b57c6e818d909f6e59c0182252921cf435e0951126a97e11de37e72ab5e1/debugpy-1.8.17-cp310-cp310-macosx_15_0_x86_64.whl", hash = "sha256:c41d2ce8bbaddcc0009cc73f65318eedfa3dbc88a8298081deb05389f1ab5542", size = 2098021, upload-time = "2025-09-17T16:33:22.556Z" }, - { url = "https://files.pythonhosted.org/packages/be/01/0363c7efdd1e9febd090bb13cee4fb1057215b157b2979a4ca5ccb678217/debugpy-1.8.17-cp310-cp310-manylinux_2_34_x86_64.whl", hash = "sha256:1440fd514e1b815edd5861ca394786f90eb24960eb26d6f7200994333b1d79e3", size = 3087399, upload-time = "2025-09-17T16:33:24.292Z" }, - { url = "https://files.pythonhosted.org/packages/79/bc/4a984729674aa9a84856650438b9665f9a1d5a748804ac6f37932ce0d4aa/debugpy-1.8.17-cp310-cp310-win32.whl", hash = "sha256:3a32c0af575749083d7492dc79f6ab69f21b2d2ad4cd977a958a07d5865316e4", size = 5230292, upload-time = "2025-09-17T16:33:26.137Z" }, - { url = "https://files.pythonhosted.org/packages/5d/19/2b9b3092d0cf81a5aa10c86271999453030af354d1a5a7d6e34c574515d7/debugpy-1.8.17-cp310-cp310-win_amd64.whl", hash = "sha256:a3aad0537cf4d9c1996434be68c6c9a6d233ac6f76c2a482c7803295b4e4f99a", size = 5261885, upload-time = "2025-09-17T16:33:27.592Z" }, { url = "https://files.pythonhosted.org/packages/d8/53/3af72b5c159278c4a0cf4cffa518675a0e73bdb7d1cac0239b815502d2ce/debugpy-1.8.17-cp311-cp311-macosx_15_0_universal2.whl", hash = "sha256:d3fce3f0e3de262a3b67e69916d001f3e767661c6e1ee42553009d445d1cd840", size = 2207154, upload-time = "2025-09-17T16:33:29.457Z" }, { url = "https://files.pythonhosted.org/packages/8f/6d/204f407df45600e2245b4a39860ed4ba32552330a0b3f5f160ae4cc30072/debugpy-1.8.17-cp311-cp311-manylinux_2_34_x86_64.whl", hash = "sha256:c6bdf134457ae0cac6fb68205776be635d31174eeac9541e1d0c062165c6461f", size = 3170322, upload-time = "2025-09-17T16:33:30.837Z" }, { url = "https://files.pythonhosted.org/packages/f2/13/1b8f87d39cf83c6b713de2620c31205299e6065622e7dd37aff4808dd410/debugpy-1.8.17-cp311-cp311-win32.whl", hash = "sha256:e79a195f9e059edfe5d8bf6f3749b2599452d3e9380484cd261f6b7cd2c7c4da", size = 5155078, upload-time = "2025-09-17T16:33:33.331Z" }, @@ -808,18 +684,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8f/d7/9322c609343d929e75e7e5e6255e614fcc67572cfd083959cdef3b7aad79/docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2", size = 587408, upload-time = "2024-04-23T18:57:14.835Z" }, ] -[[package]] -name = "exceptiongroup" -version = "1.3.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, -] - [[package]] name = "execnet" version = "2.1.1" @@ -853,14 +717,6 @@ version = "0.8.3" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/73/b1/1c3d635d955f2b4bf34d45abf8f35492e04dbd7804e94ce65d9f928ef3ec/fastrlock-0.8.3.tar.gz", hash = "sha256:4af6734d92eaa3ab4373e6c9a1dd0d5ad1304e172b1521733c6c3b3d73c8fa5d", size = 79327, upload-time = "2024-12-17T11:03:39.638Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/02/3f771177380d8690812d5b2b7736dc6b6c8cd1c317e4572e65f823eede08/fastrlock-0.8.3-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:cc5fa9166e05409f64a804d5b6d01af670979cdb12cd2594f555cb33cdc155bd", size = 55094, upload-time = "2024-12-17T11:01:49.721Z" }, - { url = "https://files.pythonhosted.org/packages/be/b4/aae7ed94b8122c325d89eb91336084596cebc505dc629b795fcc9629606d/fastrlock-0.8.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:7a77ebb0a24535ef4f167da2c5ee35d9be1e96ae192137e9dc3ff75b8dfc08a5", size = 48220, upload-time = "2024-12-17T11:01:51.071Z" }, - { url = "https://files.pythonhosted.org/packages/96/87/9807af47617fdd65c68b0fcd1e714542c1d4d3a1f1381f591f1aa7383a53/fastrlock-0.8.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_24_i686.whl", hash = "sha256:d51f7fb0db8dab341b7f03a39a3031678cf4a98b18533b176c533c122bfce47d", size = 49551, upload-time = "2024-12-17T11:01:52.316Z" }, - { url = "https://files.pythonhosted.org/packages/9d/12/e201634810ac9aee59f93e3953cb39f98157d17c3fc9d44900f1209054e9/fastrlock-0.8.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:767ec79b7f6ed9b9a00eb9ff62f2a51f56fdb221c5092ab2dadec34a9ccbfc6e", size = 49398, upload-time = "2024-12-17T11:01:53.514Z" }, - { url = "https://files.pythonhosted.org/packages/15/a1/439962ed439ff6f00b7dce14927e7830e02618f26f4653424220a646cd1c/fastrlock-0.8.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d6a77b3f396f7d41094ef09606f65ae57feeb713f4285e8e417f4021617ca62", size = 53334, upload-time = "2024-12-17T11:01:55.518Z" }, - { url = "https://files.pythonhosted.org/packages/b5/9e/1ae90829dd40559ab104e97ebe74217d9da794c4bb43016da8367ca7a596/fastrlock-0.8.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:92577ff82ef4a94c5667d6d2841f017820932bc59f31ffd83e4a2c56c1738f90", size = 52495, upload-time = "2024-12-17T11:01:57.76Z" }, - { url = "https://files.pythonhosted.org/packages/e5/8c/5e746ee6f3d7afbfbb0d794c16c71bfd5259a4e3fb1dda48baf31e46956c/fastrlock-0.8.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3df8514086e16bb7c66169156a8066dc152f3be892c7817e85bf09a27fa2ada2", size = 51972, upload-time = "2024-12-17T11:02:01.384Z" }, - { url = "https://files.pythonhosted.org/packages/76/a7/8b91068f00400931da950f143fa0f9018bd447f8ed4e34bed3fe65ed55d2/fastrlock-0.8.3-cp310-cp310-win_amd64.whl", hash = "sha256:001fd86bcac78c79658bac496e8a17472d64d558cd2227fdc768aa77f877fe40", size = 30946, upload-time = "2024-12-17T11:02:03.491Z" }, { url = "https://files.pythonhosted.org/packages/90/9e/647951c579ef74b6541493d5ca786d21a0b2d330c9514ba2c39f0b0b0046/fastrlock-0.8.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:f68c551cf8a34b6460a3a0eba44bd7897ebfc820854e19970c52a76bf064a59f", size = 55233, upload-time = "2024-12-17T11:02:04.795Z" }, { url = "https://files.pythonhosted.org/packages/be/91/5f3afba7d14b8b7d60ac651375f50fff9220d6ccc3bef233d2bd74b73ec7/fastrlock-0.8.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:55d42f6286b9d867370af4c27bc70d04ce2d342fe450c4a4fcce14440514e695", size = 48911, upload-time = "2024-12-17T11:02:06.173Z" }, { url = "https://files.pythonhosted.org/packages/d5/7a/e37bd72d7d70a8a551b3b4610d028bd73ff5d6253201d5d3cf6296468bee/fastrlock-0.8.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_24_i686.whl", hash = "sha256:bbc3bf96dcbd68392366c477f78c9d5c47e5d9290cb115feea19f20a43ef6d05", size = 50357, upload-time = "2024-12-17T11:02:07.418Z" }, @@ -898,14 +754,6 @@ version = "4.60.2" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/3e/c4/db6a7b5eb0656534c3aa2596c2c5e18830d74f1b9aa5aa8a7dff63a0b11d/fonttools-4.60.2.tar.gz", hash = "sha256:d29552e6b155ebfc685b0aecf8d429cb76c14ab734c22ef5d3dea6fdf800c92c", size = 3562254, upload-time = "2025-12-09T13:38:11.835Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ab/de/9e10a99fb3070accb8884886a41a4ce54e49bf2fa4fc63f48a6cf2061713/fonttools-4.60.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4e36fadcf7e8ca6e34d490eef86ed638d6fd9c55d2f514b05687622cfc4a7050", size = 2850403, upload-time = "2025-12-09T13:35:53.14Z" }, - { url = "https://files.pythonhosted.org/packages/e4/40/d5b369d1073b134f600a94a287e13b5bdea2191ba6347d813fa3da00e94a/fonttools-4.60.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6e500fc9c04bee749ceabfc20cb4903f6981c2139050d85720ea7ada61b75d5c", size = 2398629, upload-time = "2025-12-09T13:35:56.471Z" }, - { url = "https://files.pythonhosted.org/packages/7c/b5/123819369aaf99d1e4dc49f1de1925d4edc7379114d15a56a7dd2e9d56e6/fonttools-4.60.2-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22efea5e784e1d1cd8d7b856c198e360a979383ebc6dea4604743b56da1cbc34", size = 4893471, upload-time = "2025-12-09T13:35:58.927Z" }, - { url = "https://files.pythonhosted.org/packages/24/29/f8f8acccb9716b899be4be45e9ce770d6aa76327573863e68448183091b0/fonttools-4.60.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:677aa92d84d335e4d301d8ba04afca6f575316bc647b6782cb0921943fcb6343", size = 4854686, upload-time = "2025-12-09T13:36:01.767Z" }, - { url = "https://files.pythonhosted.org/packages/5a/0d/f3f51d7519f44f2dd5c9a60d7cd41185ebcee4348f073e515a3a93af15ff/fonttools-4.60.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:edd49d3defbf35476e78b61ff737ff5efea811acff68d44233a95a5a48252334", size = 4871233, upload-time = "2025-12-09T13:36:06.094Z" }, - { url = "https://files.pythonhosted.org/packages/cc/3f/4d4fd47d3bc40ab4d76718555185f8adffb5602ea572eac4bbf200c47d22/fonttools-4.60.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:126839492b69cecc5baf2bddcde60caab2ffafd867bbae2a88463fce6078ca3a", size = 4988936, upload-time = "2025-12-09T13:36:08.42Z" }, - { url = "https://files.pythonhosted.org/packages/01/6f/83bbdefa43f2c3ae206fd8c4b9a481f3c913eef871b1ce9a453069239e39/fonttools-4.60.2-cp310-cp310-win32.whl", hash = "sha256:ffcab6f5537136046ca902ed2491ab081ba271b07591b916289b7c27ff845f96", size = 2278044, upload-time = "2025-12-09T13:36:10.641Z" }, - { url = "https://files.pythonhosted.org/packages/d4/04/7d9a137e919d6c9ef26704b7f7b2580d9cfc5139597588227aacebc0e3b7/fonttools-4.60.2-cp310-cp310-win_amd64.whl", hash = "sha256:9c68b287c7ffcd29dd83b5f961004b2a54a862a88825d52ea219c6220309ba45", size = 2326522, upload-time = "2025-12-09T13:36:12.981Z" }, { url = "https://files.pythonhosted.org/packages/e0/80/b7693d37c02417e162cc83cdd0b19a4f58be82c638b5d4ce4de2dae050c4/fonttools-4.60.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a2aed0a7931401b3875265717a24c726f87ecfedbb7b3426c2ca4d2812e281ae", size = 2847809, upload-time = "2025-12-09T13:36:14.884Z" }, { url = "https://files.pythonhosted.org/packages/f9/9a/9c2c13bf8a6496ac21607d704e74e9cc68ebf23892cf924c9a8b5c7566b9/fonttools-4.60.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dea6868e9d2b816c9076cfea77754686f3c19149873bdbc5acde437631c15df1", size = 2397302, upload-time = "2025-12-09T13:36:17.151Z" }, { url = "https://files.pythonhosted.org/packages/56/f6/ce38ff6b2d2d58f6fd981d32f3942365bfa30eadf2b47d93b2d48bf6097f/fonttools-4.60.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2fa27f34950aa1fe0f0b1abe25eed04770a3b3b34ad94e5ace82cc341589678a", size = 5054418, upload-time = "2025-12-09T13:36:19.062Z" }, @@ -964,16 +812,6 @@ version = "3.2.4" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/03/b8/704d753a5a45507a7aab61f18db9509302ed3d0a27ac7e0359ec2905b1a6/greenlet-3.2.4.tar.gz", hash = "sha256:0dca0d95ff849f9a364385f36ab49f50065d76964944638be9691e1832e9f86d", size = 188260, upload-time = "2025-08-07T13:24:33.51Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7d/ed/6bfa4109fcb23a58819600392564fea69cdc6551ffd5e69ccf1d52a40cbc/greenlet-3.2.4-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:8c68325b0d0acf8d91dde4e6f930967dd52a5302cd4062932a6b2e7c2969f47c", size = 271061, upload-time = "2025-08-07T13:17:15.373Z" }, - { url = "https://files.pythonhosted.org/packages/2a/fc/102ec1a2fc015b3a7652abab7acf3541d58c04d3d17a8d3d6a44adae1eb1/greenlet-3.2.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:94385f101946790ae13da500603491f04a76b6e4c059dab271b3ce2e283b2590", size = 629475, upload-time = "2025-08-07T13:42:54.009Z" }, - { url = "https://files.pythonhosted.org/packages/c5/26/80383131d55a4ac0fb08d71660fd77e7660b9db6bdb4e8884f46d9f2cc04/greenlet-3.2.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f10fd42b5ee276335863712fa3da6608e93f70629c631bf77145021600abc23c", size = 640802, upload-time = "2025-08-07T13:45:25.52Z" }, - { url = "https://files.pythonhosted.org/packages/e9/49/547b93b7c0428ede7b3f309bc965986874759f7d89e4e04aeddbc9699acb/greenlet-3.2.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:58b97143c9cc7b86fc458f215bd0932f1757ce649e05b640fea2e79b54cedb31", size = 635417, upload-time = "2025-08-07T13:18:25.189Z" }, - { url = "https://files.pythonhosted.org/packages/7f/91/ae2eb6b7979e2f9b035a9f612cf70f1bf54aad4e1d125129bef1eae96f19/greenlet-3.2.4-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c2ca18a03a8cfb5b25bc1cbe20f3d9a4c80d8c3b13ba3df49ac3961af0b1018d", size = 584358, upload-time = "2025-08-07T13:18:23.708Z" }, - { url = "https://files.pythonhosted.org/packages/f7/85/433de0c9c0252b22b16d413c9407e6cb3b41df7389afc366ca204dbc1393/greenlet-3.2.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9fe0a28a7b952a21e2c062cd5756d34354117796c6d9215a87f55e38d15402c5", size = 1113550, upload-time = "2025-08-07T13:42:37.467Z" }, - { url = "https://files.pythonhosted.org/packages/a1/8d/88f3ebd2bc96bf7747093696f4335a0a8a4c5acfcf1b757717c0d2474ba3/greenlet-3.2.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8854167e06950ca75b898b104b63cc646573aa5fef1353d4508ecdd1ee76254f", size = 1137126, upload-time = "2025-08-07T13:18:20.239Z" }, - { url = "https://files.pythonhosted.org/packages/f1/29/74242b7d72385e29bcc5563fba67dad94943d7cd03552bac320d597f29b2/greenlet-3.2.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f47617f698838ba98f4ff4189aef02e7343952df3a615f847bb575c3feb177a7", size = 1544904, upload-time = "2025-11-04T12:42:04.763Z" }, - { url = "https://files.pythonhosted.org/packages/c8/e2/1572b8eeab0f77df5f6729d6ab6b141e4a84ee8eb9bc8c1e7918f94eda6d/greenlet-3.2.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:af41be48a4f60429d5cad9d22175217805098a9ef7c40bfef44f7669fb9d74d8", size = 1611228, upload-time = "2025-11-04T12:42:08.423Z" }, - { url = "https://files.pythonhosted.org/packages/d6/6f/b60b0291d9623c496638c582297ead61f43c4b72eef5e9c926ef4565ec13/greenlet-3.2.4-cp310-cp310-win_amd64.whl", hash = "sha256:73f49b5368b5359d04e18d15828eecc1806033db5233397748f4ca813ff1056c", size = 298654, upload-time = "2025-08-07T13:50:00.469Z" }, { url = "https://files.pythonhosted.org/packages/a4/de/f28ced0a67749cac23fecb02b694f6473f47686dff6afaa211d186e2ef9c/greenlet-3.2.4-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:96378df1de302bc38e99c3a9aa311967b7dc80ced1dcc6f171e99842987882a2", size = 272305, upload-time = "2025-08-07T13:15:41.288Z" }, { url = "https://files.pythonhosted.org/packages/09/16/2c3792cba130000bf2a31c5272999113f4764fd9d874fb257ff588ac779a/greenlet-3.2.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1ee8fae0519a337f2329cb78bd7a8e128ec0f881073d43f023c7b8d4831d5246", size = 632472, upload-time = "2025-08-07T13:42:55.044Z" }, { url = "https://files.pythonhosted.org/packages/ae/8f/95d48d7e3d433e6dae5b1682e4292242a53f22df82e6d3dda81b1701a960/greenlet-3.2.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:94abf90142c2a18151632371140b3dba4dee031633fe614cb592dbb6c9e17bc3", size = 644646, upload-time = "2025-08-07T13:45:26.523Z" }, @@ -1070,8 +908,7 @@ dependencies = [ { name = "appnope", marker = "sys_platform == 'darwin'" }, { name = "comm" }, { name = "debugpy" }, - { name = "ipython", version = "8.37.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "ipython", version = "9.6.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "ipython" }, { name = "jupyter-client" }, { name = "jupyter-core" }, { name = "matplotlib-inline" }, @@ -1087,40 +924,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fc/c7/b445faca8deb954fe536abebff4ece5b097b923de482b26e78448c89d1dd/ipykernel-6.30.1-py3-none-any.whl", hash = "sha256:aa6b9fb93dca949069d8b85b6c79b2518e32ac583ae9c7d37c51d119e18b3fb4", size = 117484, upload-time = "2025-08-04T15:47:32.622Z" }, ] -[[package]] -name = "ipython" -version = "8.37.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.11'", -] -dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "decorator" }, - { name = "exceptiongroup" }, - { name = "jedi" }, - { name = "matplotlib-inline" }, - { name = "pexpect", marker = "sys_platform != 'emscripten' and sys_platform != 'win32'" }, - { name = "prompt-toolkit" }, - { name = "pygments" }, - { name = "stack-data" }, - { name = "traitlets" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/85/31/10ac88f3357fc276dc8a64e8880c82e80e7459326ae1d0a211b40abf6665/ipython-8.37.0.tar.gz", hash = "sha256:ca815841e1a41a1e6b73a0b08f3038af9b2252564d01fc405356d34033012216", size = 5606088, upload-time = "2025-05-31T16:39:09.613Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/91/d0/274fbf7b0b12643cbbc001ce13e6a5b1607ac4929d1b11c72460152c9fc3/ipython-8.37.0-py3-none-any.whl", hash = "sha256:ed87326596b878932dbcb171e3e698845434d8c61b8d8cd474bf663041a9dcf2", size = 831864, upload-time = "2025-05-31T16:39:06.38Z" }, -] - [[package]] name = "ipython" version = "9.6.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.12' and python_full_version < '3.14'", - "python_full_version == '3.11.*'", -] dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, { name = "decorator" }, @@ -1224,8 +1031,7 @@ dependencies = [ { name = "myst-parser" }, { name = "pyyaml" }, { name = "sphinx" }, - { name = "sphinx-book-theme", version = "1.1.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "sphinx-book-theme", version = "1.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "sphinx-book-theme" }, { name = "sphinx-comments" }, { name = "sphinx-copybutton" }, { name = "sphinx-design" }, @@ -1305,19 +1111,6 @@ version = "1.4.9" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/5c/3c/85844f1b0feb11ee581ac23fe5fce65cd049a200c1446708cc1b7f922875/kiwisolver-1.4.9.tar.gz", hash = "sha256:c3b22c26c6fd6811b0ae8363b95ca8ce4ea3c202d3d0975b2914310ceb1bcc4d", size = 97564, upload-time = "2025-08-10T21:27:49.279Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c6/5d/8ce64e36d4e3aac5ca96996457dcf33e34e6051492399a3f1fec5657f30b/kiwisolver-1.4.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b4b4d74bda2b8ebf4da5bd42af11d02d04428b2c32846e4c2c93219df8a7987b", size = 124159, upload-time = "2025-08-10T21:25:35.472Z" }, - { url = "https://files.pythonhosted.org/packages/96/1e/22f63ec454874378175a5f435d6ea1363dd33fb2af832c6643e4ccea0dc8/kiwisolver-1.4.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fb3b8132019ea572f4611d770991000d7f58127560c4889729248eb5852a102f", size = 66578, upload-time = "2025-08-10T21:25:36.73Z" }, - { url = "https://files.pythonhosted.org/packages/41/4c/1925dcfff47a02d465121967b95151c82d11027d5ec5242771e580e731bd/kiwisolver-1.4.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:84fd60810829c27ae375114cd379da1fa65e6918e1da405f356a775d49a62bcf", size = 65312, upload-time = "2025-08-10T21:25:37.658Z" }, - { url = "https://files.pythonhosted.org/packages/d4/42/0f333164e6307a0687d1eb9ad256215aae2f4bd5d28f4653d6cd319a3ba3/kiwisolver-1.4.9-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b78efa4c6e804ecdf727e580dbb9cba85624d2e1c6b5cb059c66290063bd99a9", size = 1628458, upload-time = "2025-08-10T21:25:39.067Z" }, - { url = "https://files.pythonhosted.org/packages/86/b6/2dccb977d651943995a90bfe3495c2ab2ba5cd77093d9f2318a20c9a6f59/kiwisolver-1.4.9-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d4efec7bcf21671db6a3294ff301d2fc861c31faa3c8740d1a94689234d1b415", size = 1225640, upload-time = "2025-08-10T21:25:40.489Z" }, - { url = "https://files.pythonhosted.org/packages/50/2b/362ebd3eec46c850ccf2bfe3e30f2fc4c008750011f38a850f088c56a1c6/kiwisolver-1.4.9-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:90f47e70293fc3688b71271100a1a5453aa9944a81d27ff779c108372cf5567b", size = 1244074, upload-time = "2025-08-10T21:25:42.221Z" }, - { url = "https://files.pythonhosted.org/packages/6f/bb/f09a1e66dab8984773d13184a10a29fe67125337649d26bdef547024ed6b/kiwisolver-1.4.9-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8fdca1def57a2e88ef339de1737a1449d6dbf5fab184c54a1fca01d541317154", size = 1293036, upload-time = "2025-08-10T21:25:43.801Z" }, - { url = "https://files.pythonhosted.org/packages/ea/01/11ecf892f201cafda0f68fa59212edaea93e96c37884b747c181303fccd1/kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9cf554f21be770f5111a1690d42313e140355e687e05cf82cb23d0a721a64a48", size = 2175310, upload-time = "2025-08-10T21:25:45.045Z" }, - { url = "https://files.pythonhosted.org/packages/7f/5f/bfe11d5b934f500cc004314819ea92427e6e5462706a498c1d4fc052e08f/kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fc1795ac5cd0510207482c3d1d3ed781143383b8cfd36f5c645f3897ce066220", size = 2270943, upload-time = "2025-08-10T21:25:46.393Z" }, - { url = "https://files.pythonhosted.org/packages/3d/de/259f786bf71f1e03e73d87e2db1a9a3bcab64d7b4fd780167123161630ad/kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:ccd09f20ccdbbd341b21a67ab50a119b64a403b09288c27481575105283c1586", size = 2440488, upload-time = "2025-08-10T21:25:48.074Z" }, - { url = "https://files.pythonhosted.org/packages/1b/76/c989c278faf037c4d3421ec07a5c452cd3e09545d6dae7f87c15f54e4edf/kiwisolver-1.4.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:540c7c72324d864406a009d72f5d6856f49693db95d1fbb46cf86febef873634", size = 2246787, upload-time = "2025-08-10T21:25:49.442Z" }, - { url = "https://files.pythonhosted.org/packages/a2/55/c2898d84ca440852e560ca9f2a0d28e6e931ac0849b896d77231929900e7/kiwisolver-1.4.9-cp310-cp310-win_amd64.whl", hash = "sha256:ede8c6d533bc6601a47ad4046080d36b8fc99f81e6f1c17b0ac3c2dc91ac7611", size = 73730, upload-time = "2025-08-10T21:25:51.102Z" }, - { url = "https://files.pythonhosted.org/packages/e8/09/486d6ac523dd33b80b368247f238125d027964cfacb45c654841e88fb2ae/kiwisolver-1.4.9-cp310-cp310-win_arm64.whl", hash = "sha256:7b4da0d01ac866a57dd61ac258c5607b4cd677f63abaec7b148354d2b2cdd536", size = 65036, upload-time = "2025-08-10T21:25:52.063Z" }, { url = "https://files.pythonhosted.org/packages/6f/ab/c80b0d5a9d8a1a65f4f815f2afff9798b12c3b9f31f1d304dd233dd920e2/kiwisolver-1.4.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:eb14a5da6dc7642b0f3a18f13654847cd8b7a2550e2645a5bda677862b03ba16", size = 124167, upload-time = "2025-08-10T21:25:53.403Z" }, { url = "https://files.pythonhosted.org/packages/a0/c0/27fe1a68a39cf62472a300e2879ffc13c0538546c359b86f149cc19f6ac3/kiwisolver-1.4.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:39a219e1c81ae3b103643d2aedb90f1ef22650deb266ff12a19e7773f3e5f089", size = 66579, upload-time = "2025-08-10T21:25:54.79Z" }, { url = "https://files.pythonhosted.org/packages/31/a2/a12a503ac1fd4943c50f9822678e8015a790a13b5490354c68afb8489814/kiwisolver-1.4.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2405a7d98604b87f3fc28b1716783534b1b4b8510d8142adca34ee0bc3c87543", size = 65309, upload-time = "2025-08-10T21:25:55.76Z" }, @@ -1395,11 +1188,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/99/dd/841e9a66c4715477ea0abc78da039832fbb09dac5c35c58dc4c41a407b8a/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:aedff62918805fb62d43a4aa2ecd4482c380dc76cd31bd7c8878588a61bd0369", size = 2391835, upload-time = "2025-08-10T21:27:34.23Z" }, { url = "https://files.pythonhosted.org/packages/0c/28/4b2e5c47a0da96896fdfdb006340ade064afa1e63675d01ea5ac222b6d52/kiwisolver-1.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:1fa333e8b2ce4d9660f2cda9c0e1b6bafcfb2457a9d259faa82289e73ec24891", size = 79988, upload-time = "2025-08-10T21:27:35.587Z" }, { url = "https://files.pythonhosted.org/packages/80/be/3578e8afd18c88cdf9cb4cffde75a96d2be38c5a903f1ed0ceec061bd09e/kiwisolver-1.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:4a48a2ce79d65d363597ef7b567ce3d14d68783d2b2263d98db3d9477805ba32", size = 70260, upload-time = "2025-08-10T21:27:36.606Z" }, - { url = "https://files.pythonhosted.org/packages/a2/63/fde392691690f55b38d5dd7b3710f5353bf7a8e52de93a22968801ab8978/kiwisolver-1.4.9-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4d1d9e582ad4d63062d34077a9a1e9f3c34088a2ec5135b1f7190c07cf366527", size = 60183, upload-time = "2025-08-10T21:27:37.669Z" }, - { url = "https://files.pythonhosted.org/packages/27/b1/6aad34edfdb7cced27f371866f211332bba215bfd918ad3322a58f480d8b/kiwisolver-1.4.9-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:deed0c7258ceb4c44ad5ec7d9918f9f14fd05b2be86378d86cf50e63d1e7b771", size = 58675, upload-time = "2025-08-10T21:27:39.031Z" }, - { url = "https://files.pythonhosted.org/packages/9d/1a/23d855a702bb35a76faed5ae2ba3de57d323f48b1f6b17ee2176c4849463/kiwisolver-1.4.9-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0a590506f303f512dff6b7f75fd2fd18e16943efee932008fe7140e5fa91d80e", size = 80277, upload-time = "2025-08-10T21:27:40.129Z" }, - { url = "https://files.pythonhosted.org/packages/5a/5b/5239e3c2b8fb5afa1e8508f721bb77325f740ab6994d963e61b2b7abcc1e/kiwisolver-1.4.9-pp310-pypy310_pp73-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e09c2279a4d01f099f52d5c4b3d9e208e91edcbd1a175c9662a8b16e000fece9", size = 77994, upload-time = "2025-08-10T21:27:41.181Z" }, - { url = "https://files.pythonhosted.org/packages/f9/1c/5d4d468fb16f8410e596ed0eac02d2c68752aa7dc92997fe9d60a7147665/kiwisolver-1.4.9-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c9e7cdf45d594ee04d5be1b24dd9d49f3d1590959b2271fb30b5ca2b262c00fb", size = 73744, upload-time = "2025-08-10T21:27:42.254Z" }, { url = "https://files.pythonhosted.org/packages/a3/0f/36d89194b5a32c054ce93e586d4049b6c2c22887b0eb229c61c68afd3078/kiwisolver-1.4.9-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:720e05574713db64c356e86732c0f3c5252818d05f9df320f0ad8380641acea5", size = 60104, upload-time = "2025-08-10T21:27:43.287Z" }, { url = "https://files.pythonhosted.org/packages/52/ba/4ed75f59e4658fd21fe7dde1fee0ac397c678ec3befba3fe6482d987af87/kiwisolver-1.4.9-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:17680d737d5335b552994a2008fab4c851bcd7de33094a82067ef3a576ff02fa", size = 58592, upload-time = "2025-08-10T21:27:44.314Z" }, { url = "https://files.pythonhosted.org/packages/33/01/a8ea7c5ea32a9b45ceeaee051a04c8ed4320f5add3c51bfa20879b765b70/kiwisolver-1.4.9-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:85b5352f94e490c028926ea567fc569c52ec79ce131dadb968d3853e809518c2", size = 80281, upload-time = "2025-08-10T21:27:45.369Z" }, @@ -1434,10 +1222,6 @@ version = "0.46.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/74/cd/08ae687ba099c7e3d21fe2ea536500563ef1943c5105bf6ab4ee3829f68e/llvmlite-0.46.0.tar.gz", hash = "sha256:227c9fd6d09dce2783c18b754b7cd9d9b3b3515210c46acc2d3c5badd9870ceb", size = 193456, upload-time = "2025-12-08T18:15:36.295Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3d/a4/3959e1c61c5ca9db7921e5fd115b344c29b9d57a5dadd87bef97963ca1a5/llvmlite-0.46.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4323177e936d61ae0f73e653e2e614284d97d14d5dd12579adc92b6c2b0597b0", size = 37232766, upload-time = "2025-12-08T18:14:34.765Z" }, - { url = "https://files.pythonhosted.org/packages/c2/a5/a4d916f1015106e1da876028606a8e87fd5d5c840f98c87bc2d5153b6a2f/llvmlite-0.46.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0a2d461cb89537b7c20feb04c46c32e12d5ad4f0896c9dfc0f60336219ff248e", size = 56275176, upload-time = "2025-12-08T18:14:37.944Z" }, - { url = "https://files.pythonhosted.org/packages/79/7f/a7f2028805dac8c1a6fae7bda4e739b7ebbcd45b29e15bf6d21556fcd3d5/llvmlite-0.46.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b1f6595a35b7b39c3518b85a28bf18f45e075264e4b2dce3f0c2a4f232b4a910", size = 55128629, upload-time = "2025-12-08T18:14:41.674Z" }, - { url = "https://files.pythonhosted.org/packages/b2/bc/4689e1ba0c073c196b594471eb21be0aa51d9e64b911728aa13cd85ef0ae/llvmlite-0.46.0-cp310-cp310-win_amd64.whl", hash = "sha256:e7a34d4aa6f9a97ee006b504be6d2b8cb7f755b80ab2f344dda1ef992f828559", size = 38138651, upload-time = "2025-12-08T18:14:45.845Z" }, { url = "https://files.pythonhosted.org/packages/7a/a1/2ad4b2367915faeebe8447f0a057861f646dbf5fbbb3561db42c65659cf3/llvmlite-0.46.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:82f3d39b16f19aa1a56d5fe625883a6ab600d5cc9ea8906cca70ce94cabba067", size = 37232766, upload-time = "2025-12-08T18:14:48.836Z" }, { url = "https://files.pythonhosted.org/packages/12/b5/99cf8772fdd846c07da4fd70f07812a3c8fd17ea2409522c946bb0f2b277/llvmlite-0.46.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a3df43900119803bbc52720e758c76f316a9a0f34612a886862dfe0a5591a17e", size = 56275175, upload-time = "2025-12-08T18:14:51.604Z" }, { url = "https://files.pythonhosted.org/packages/38/f2/ed806f9c003563732da156139c45d970ee435bd0bfa5ed8de87ba972b452/llvmlite-0.46.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de183fefc8022d21b0aa37fc3e90410bc3524aed8617f0ff76732fc6c3af5361", size = 55128630, upload-time = "2025-12-08T18:14:55.107Z" }, @@ -1471,22 +1255,6 @@ version = "6.1.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/28/30/9abc9e34c657c33834eaf6cd02124c61bdf5944d802aa48e69be8da3585d/lxml-6.1.0.tar.gz", hash = "sha256:bfd57d8008c4965709a919c3e9a98f76c2c7cb319086b3d26858250620023b13", size = 4197006, upload-time = "2026-04-18T04:32:51.613Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/02/6e/ee8fc0e01202eb3dd2b9e1ea4f0910d72425d35c66187c63931d7a3ea73f/lxml-6.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:41dcc4c7b10484257cbd6c37b83ddb26df2b0e5aff5ac00d095689015af868ec", size = 8540733, upload-time = "2026-04-18T04:27:33.185Z" }, - { url = "https://files.pythonhosted.org/packages/54/e8/325fe9b942824c773dffe1baf0c35b046a763851fdff4393af4450bceeb7/lxml-6.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a31286dbb5e74c8e9a5344465b77ab4c5bd511a253b355b5ca2fae7e579fafec", size = 4602805, upload-time = "2026-04-18T04:27:36.097Z" }, - { url = "https://files.pythonhosted.org/packages/2d/81/221aa3ea4a40370bb0358fa454cbe7e5a837e522f7630c24dfef3f9a73b0/lxml-6.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1bc4cc83fb7f66ffb16f74d6dd0162e144333fc36ebcce32246f80c8735b2551", size = 5002652, upload-time = "2026-04-18T04:27:30.603Z" }, - { url = "https://files.pythonhosted.org/packages/c6/e1/fdbfb9019542f1875c093576df7f37adc2983c8ba7ecf17e5f14490bc107/lxml-6.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:20cf4d0651987c906a2f5cba4e3a8d6ba4bfdf973cfe2a96c0d6053888ea2ecd", size = 5155332, upload-time = "2026-04-18T04:27:33.507Z" }, - { url = "https://files.pythonhosted.org/packages/56/b1/4087c782fff397cd03abf9c551069be59bb04a7e548c50fb7b9c4cdaca28/lxml-6.1.0-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ffb34ea45a82dd637c2c97ae1bbb920850c1e59bcae79ce1c15af531d83e7215", size = 5057226, upload-time = "2026-04-18T04:27:37.567Z" }, - { url = "https://files.pythonhosted.org/packages/5d/66/516c79dec8417f3a972327330254c0b5fac93d5c3ecfd8a5b43650a5a4d9/lxml-6.1.0-cp310-cp310-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a1d9b99e5b2597e4f5aed2484fef835256fa1b68a19e4265c97628ef4bf8bcf4", size = 5287588, upload-time = "2026-04-18T04:27:41.4Z" }, - { url = "https://files.pythonhosted.org/packages/94/1d/e578f4cbeb42b9df9f29b0d44a45a7cdfa3a5ae300dd59ec68e3602d29bb/lxml-6.1.0-cp310-cp310-manylinux_2_28_i686.whl", hash = "sha256:d43aa26dcda363f21e79afa0668f5029ed7394b3bb8c92a6927a3d34e8b610ea", size = 5412438, upload-time = "2026-04-18T04:27:45.589Z" }, - { url = "https://files.pythonhosted.org/packages/47/5b/2aa68307d6d15959e84d4882f9c04f2da63127eac463e1594166f681ef77/lxml-6.1.0-cp310-cp310-manylinux_2_31_armv7l.whl", hash = "sha256:6262b87f9e5c1e5fe501d6c153247289af42eb44ad7660b9b3de17baaf92d6f6", size = 4770997, upload-time = "2026-04-18T04:27:49.853Z" }, - { url = "https://files.pythonhosted.org/packages/ae/c9/3e51fc1228310a836b4eb32595ae00154ab12197fca944676a3ab3b163ea/lxml-6.1.0-cp310-cp310-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d1392c569c032f78a11a25d1de1c43fff13294c793b39e19d84fade3045cbbc3", size = 5359678, upload-time = "2026-04-18T04:31:56.184Z" }, - { url = "https://files.pythonhosted.org/packages/b5/91/ab8bc834f977fbbd310e697b120787c153db026f9151e02a88d2645d4e5b/lxml-6.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:045e387d1f4f42a418380930fa3f45c73c9b392faf67e495e58902e68e8f44a7", size = 5107890, upload-time = "2026-04-18T04:32:00.387Z" }, - { url = "https://files.pythonhosted.org/packages/bb/10/8a143cfa3ac99cb5b0523ff6d0429a9c9dddf25ffeae09caa3866c7964d9/lxml-6.1.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:9f93d5b8b07f73e8c77e3c6556a3db269918390c804b5e5fcdd4858232cc8f16", size = 4803977, upload-time = "2026-04-18T04:32:05.099Z" }, - { url = "https://files.pythonhosted.org/packages/45/fd/ee02faf52fa39c2fe32f824628958b9aa86dff21343dc3161f0e3c6ccd15/lxml-6.1.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:de550d129f18d8ab819651ffe4f38b1b713c7e116707de3c0c6400d0ef34fbc1", size = 5350277, upload-time = "2026-04-18T04:32:09.176Z" }, - { url = "https://files.pythonhosted.org/packages/85/8c/b3481364b8554b5d36d540189a87fc71e94b0b01c24f8f152bd662dd2e45/lxml-6.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c08da09dc003c9e8c70e06b53a11db6fb3b250c21c4236b03c7d7b443c318e7a", size = 5309717, upload-time = "2026-04-18T04:32:13.303Z" }, - { url = "https://files.pythonhosted.org/packages/74/e8/a6b21927077a9127afa17473b6576b322616f34ac50ee4f577e763b75ec0/lxml-6.1.0-cp310-cp310-win32.whl", hash = "sha256:37448bf9c7d7adfc5254763901e2bbd6bb876228dfc1fc7f66e58c06368a7544", size = 3598491, upload-time = "2026-04-18T04:27:24.288Z" }, - { url = "https://files.pythonhosted.org/packages/ea/82/14dea800d041274d96c07d49ff9191f011d1427450850de19bf541e2cc12/lxml-6.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:2593a0a6621545b9095b71ad74ed4226eba438a7d9fc3712a99bdb15508cf93a", size = 4020906, upload-time = "2026-04-18T04:27:27.53Z" }, - { url = "https://files.pythonhosted.org/packages/f2/ba/d3539aaf4d9d21456b9a7b902816623227d05d63e7c5aafd8834c4b9bed6/lxml-6.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:e80807d72f96b96ad5588cb85c75616e4f2795a7737d4630784c51497beb7776", size = 3667787, upload-time = "2026-04-18T04:27:29.407Z" }, { url = "https://files.pythonhosted.org/packages/5e/5d/3bccad330292946f97962df9d5f2d3ae129cce6e212732a781e856b91e07/lxml-6.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cec05be8c876f92a5aa07b01d60bbb4d11cfbdd654cad0561c0d7b5c043a61b9", size = 8526232, upload-time = "2026-04-18T04:27:40.389Z" }, { url = "https://files.pythonhosted.org/packages/a7/51/adc8826570a112f83bb4ddb3a2ab510bbc2ccd62c1b9fe1f34fae2d90b57/lxml-6.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9c03e048b6ce8e77b09c734e931584894ecd58d08296804ca2d0b184c933ce50", size = 4595448, upload-time = "2026-04-18T04:27:44.208Z" }, { url = "https://files.pythonhosted.org/packages/54/84/5a9ec07cbe1d2334a6465f863b949a520d2699a755738986dcd3b6b89e3f/lxml-6.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:942454ff253da14218f972b23dc72fa4edf6c943f37edd19cd697618b626fac5", size = 4923771, upload-time = "2026-04-18T04:32:17.402Z" }, @@ -1601,17 +1369,6 @@ version = "3.0.3" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e8/4b/3541d44f3937ba468b75da9eebcae497dcf67adb65caa16760b0a6807ebb/markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559", size = 11631, upload-time = "2025-09-27T18:36:05.558Z" }, - { url = "https://files.pythonhosted.org/packages/98/1b/fbd8eed11021cabd9226c37342fa6ca4e8a98d8188a8d9b66740494960e4/markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419", size = 12057, upload-time = "2025-09-27T18:36:07.165Z" }, - { url = "https://files.pythonhosted.org/packages/40/01/e560d658dc0bb8ab762670ece35281dec7b6c1b33f5fbc09ebb57a185519/markupsafe-3.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ba88449deb3de88bd40044603fafffb7bc2b055d626a330323a9ed736661695", size = 22050, upload-time = "2025-09-27T18:36:08.005Z" }, - { url = "https://files.pythonhosted.org/packages/af/cd/ce6e848bbf2c32314c9b237839119c5a564a59725b53157c856e90937b7a/markupsafe-3.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f42d0984e947b8adf7dd6dde396e720934d12c506ce84eea8476409563607591", size = 20681, upload-time = "2025-09-27T18:36:08.881Z" }, - { url = "https://files.pythonhosted.org/packages/c9/2a/b5c12c809f1c3045c4d580b035a743d12fcde53cf685dbc44660826308da/markupsafe-3.0.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c0c0b3ade1c0b13b936d7970b1d37a57acde9199dc2aecc4c336773e1d86049c", size = 20705, upload-time = "2025-09-27T18:36:10.131Z" }, - { url = "https://files.pythonhosted.org/packages/cf/e3/9427a68c82728d0a88c50f890d0fc072a1484de2f3ac1ad0bfc1a7214fd5/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0303439a41979d9e74d18ff5e2dd8c43ed6c6001fd40e5bf2e43f7bd9bbc523f", size = 21524, upload-time = "2025-09-27T18:36:11.324Z" }, - { url = "https://files.pythonhosted.org/packages/bc/36/23578f29e9e582a4d0278e009b38081dbe363c5e7165113fad546918a232/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:d2ee202e79d8ed691ceebae8e0486bd9a2cd4794cec4824e1c99b6f5009502f6", size = 20282, upload-time = "2025-09-27T18:36:12.573Z" }, - { url = "https://files.pythonhosted.org/packages/56/21/dca11354e756ebd03e036bd8ad58d6d7168c80ce1fe5e75218e4945cbab7/markupsafe-3.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:177b5253b2834fe3678cb4a5f0059808258584c559193998be2601324fdeafb1", size = 20745, upload-time = "2025-09-27T18:36:13.504Z" }, - { url = "https://files.pythonhosted.org/packages/87/99/faba9369a7ad6e4d10b6a5fbf71fa2a188fe4a593b15f0963b73859a1bbd/markupsafe-3.0.3-cp310-cp310-win32.whl", hash = "sha256:2a15a08b17dd94c53a1da0438822d70ebcd13f8c3a95abe3a9ef9f11a94830aa", size = 14571, upload-time = "2025-09-27T18:36:14.779Z" }, - { url = "https://files.pythonhosted.org/packages/d6/25/55dc3ab959917602c96985cb1253efaa4ff42f71194bddeb61eb7278b8be/markupsafe-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:c4ffb7ebf07cfe8931028e3e4c85f0357459a3f9f9490886198848f4fa002ec8", size = 15056, upload-time = "2025-09-27T18:36:16.125Z" }, - { url = "https://files.pythonhosted.org/packages/d0/9e/0a02226640c255d1da0b8d12e24ac2aa6734da68bff14c05dd53b94a0fc3/markupsafe-3.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:e2103a929dfa2fcaf9bb4e7c091983a49c9ac3b19c9061b6d5427dd7d14d81a1", size = 13932, upload-time = "2025-09-27T18:36:17.311Z" }, { url = "https://files.pythonhosted.org/packages/08/db/fefacb2136439fc8dd20e797950e749aa1f4997ed584c62cfb8ef7c2be0e/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", size = 11631, upload-time = "2025-09-27T18:36:18.185Z" }, { url = "https://files.pythonhosted.org/packages/e1/2e/5898933336b61975ce9dc04decbc0a7f2fee78c30353c5efba7f2d6ff27a/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", size = 12058, upload-time = "2025-09-27T18:36:19.444Z" }, { url = "https://files.pythonhosted.org/packages/1d/09/adf2df3699d87d1d8184038df46a9c80d78c0148492323f4693df54e17bb/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", size = 24287, upload-time = "2025-09-27T18:36:20.768Z" }, @@ -1685,13 +1442,11 @@ name = "matplotlib" version = "3.10.6" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "contourpy", version = "1.3.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "contourpy", version = "1.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "contourpy" }, { name = "cycler" }, { name = "fonttools" }, { name = "kiwisolver" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "numpy" }, { name = "packaging" }, { name = "pillow" }, { name = "pyparsing" }, @@ -1699,12 +1454,6 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/a0/59/c3e6453a9676ffba145309a73c462bb407f4400de7de3f2b41af70720a3c/matplotlib-3.10.6.tar.gz", hash = "sha256:ec01b645840dd1996df21ee37f208cd8ba57644779fa20464010638013d3203c", size = 34804264, upload-time = "2025-08-30T00:14:25.137Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/da/dc/ab89f7a5efd0cbaaebf2c3cf1881f4cba20c8925bb43f64511059df76895/matplotlib-3.10.6-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:bc7316c306d97463a9866b89d5cc217824e799fa0de346c8f68f4f3d27c8693d", size = 8247159, upload-time = "2025-08-30T00:12:30.507Z" }, - { url = "https://files.pythonhosted.org/packages/30/a5/ddaee1a383ab28174093644fff7438eddb87bf8dbd58f7b85f5cdd6b2485/matplotlib-3.10.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d00932b0d160ef03f59f9c0e16d1e3ac89646f7785165ce6ad40c842db16cc2e", size = 8108011, upload-time = "2025-08-30T00:12:32.771Z" }, - { url = "https://files.pythonhosted.org/packages/75/5b/a53f69bb0522db352b1135bb57cd9fe00fd7252072409392d991d3a755d0/matplotlib-3.10.6-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8fa4c43d6bfdbfec09c733bca8667de11bfa4970e8324c471f3a3632a0301c15", size = 8680518, upload-time = "2025-08-30T00:12:34.387Z" }, - { url = "https://files.pythonhosted.org/packages/5f/31/e059ddce95f68819b005a2d6820b2d6ed0307827a04598891f00649bed2d/matplotlib-3.10.6-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ea117a9c1627acaa04dbf36265691921b999cbf515a015298e54e1a12c3af837", size = 9514997, upload-time = "2025-08-30T00:12:36.272Z" }, - { url = "https://files.pythonhosted.org/packages/66/d5/28b408a7c0f07b41577ee27e4454fe329e78ca21fe46ae7a27d279165fb5/matplotlib-3.10.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:08fc803293b4e1694ee325896030de97f74c141ccff0be886bb5915269247676", size = 9566440, upload-time = "2025-08-30T00:12:41.675Z" }, - { url = "https://files.pythonhosted.org/packages/2d/99/8325b3386b479b1d182ab1a7fd588fd393ff00a99dc04b7cf7d06668cf0f/matplotlib-3.10.6-cp310-cp310-win_amd64.whl", hash = "sha256:2adf92d9b7527fbfb8818e050260f0ebaa460f79d61546374ce73506c9421d09", size = 8108186, upload-time = "2025-08-30T00:12:43.621Z" }, { url = "https://files.pythonhosted.org/packages/80/d6/5d3665aa44c49005aaacaa68ddea6fcb27345961cd538a98bb0177934ede/matplotlib-3.10.6-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:905b60d1cb0ee604ce65b297b61cf8be9f4e6cfecf95a3fe1c388b5266bc8f4f", size = 8257527, upload-time = "2025-08-30T00:12:45.31Z" }, { url = "https://files.pythonhosted.org/packages/8c/af/30ddefe19ca67eebd70047dabf50f899eaff6f3c5e6a1a7edaecaf63f794/matplotlib-3.10.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7bac38d816637343e53d7185d0c66677ff30ffb131044a81898b5792c956ba76", size = 8119583, upload-time = "2025-08-30T00:12:47.236Z" }, { url = "https://files.pythonhosted.org/packages/d3/29/4a8650a3dcae97fa4f375d46efcb25920d67b512186f8a6788b896062a81/matplotlib-3.10.6-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:942a8de2b5bfff1de31d95722f702e2966b8a7e31f4e68f7cd963c7cd8861cf6", size = 8692682, upload-time = "2025-08-30T00:12:48.781Z" }, @@ -1747,9 +1496,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c7/b0/40fb2b3a1ab9381bb39a952e8390357c8be3bdadcf6d5055d9c31e1b35ae/matplotlib-3.10.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:83847b47f6524c34b4f2d3ce726bb0541c48c8e7692729865c3df75bfa0f495a", size = 9594077, upload-time = "2025-08-30T00:14:07.012Z" }, { url = "https://files.pythonhosted.org/packages/76/34/c4b71b69edf5b06e635eee1ed10bfc73cf8df058b66e63e30e6a55e231d5/matplotlib-3.10.6-cp314-cp314t-win_amd64.whl", hash = "sha256:c7e0518e0d223683532a07f4b512e2e0729b62674f1b3a1a69869f98e6b1c7e3", size = 8342822, upload-time = "2025-08-30T00:14:09.041Z" }, { url = "https://files.pythonhosted.org/packages/e8/62/aeabeef1a842b6226a30d49dd13e8a7a1e81e9ec98212c0b5169f0a12d83/matplotlib-3.10.6-cp314-cp314t-win_arm64.whl", hash = "sha256:4dd83e029f5b4801eeb87c64efd80e732452781c16a9cf7415b7b63ec8f374d7", size = 8172588, upload-time = "2025-08-30T00:14:11.166Z" }, - { url = "https://files.pythonhosted.org/packages/17/6f/2551e45bea2938e0363ccdd54fa08dae7605ce782d4332497d31a7b97672/matplotlib-3.10.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:13fcd07ccf17e354398358e0307a1f53f5325dca22982556ddb9c52837b5af41", size = 8241220, upload-time = "2025-08-30T00:14:12.888Z" }, - { url = "https://files.pythonhosted.org/packages/54/7e/0f4c6e8b98105fdb162a4efde011af204ca47d7c05d735aff480ebfead1b/matplotlib-3.10.6-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:470fc846d59d1406e34fa4c32ba371039cd12c2fe86801159a965956f2575bd1", size = 8104624, upload-time = "2025-08-30T00:14:14.511Z" }, - { url = "https://files.pythonhosted.org/packages/27/27/c29696702b9317a6ade1ba6f8861e02d7423f18501729203d7a80b686f23/matplotlib-3.10.6-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f7173f8551b88f4ef810a94adae3128c2530e0d07529f7141be7f8d8c365f051", size = 8682271, upload-time = "2025-08-30T00:14:17.273Z" }, { url = "https://files.pythonhosted.org/packages/12/bb/02c35a51484aae5f49bd29f091286e7af5f3f677a9736c58a92b3c78baeb/matplotlib-3.10.6-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f2d684c3204fa62421bbf770ddfebc6b50130f9cad65531eeba19236d73bb488", size = 8252296, upload-time = "2025-08-30T00:14:19.49Z" }, { url = "https://files.pythonhosted.org/packages/7d/85/41701e3092005aee9a2445f5ee3904d9dbd4a7df7a45905ffef29b7ef098/matplotlib-3.10.6-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:6f4a69196e663a41d12a728fab8751177215357906436804217d6d9cf0d4d6cf", size = 8116749, upload-time = "2025-08-30T00:14:21.344Z" }, { url = "https://files.pythonhosted.org/packages/16/53/8d8fa0ea32a8c8239e04d022f6c059ee5e1b77517769feccd50f1df43d6d/matplotlib-3.10.6-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d6ca6ef03dfd269f4ead566ec6f3fb9becf8dab146fb999022ed85ee9f6b3eb", size = 8693933, upload-time = "2025-08-30T00:14:22.942Z" }, @@ -1792,9 +1538,6 @@ wheels = [ name = "mistune" version = "3.3.3" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, -] sdist = { url = "https://files.pythonhosted.org/packages/7b/a5/2dab368d6950e6808904dec98f54c7e726ee7be4a0c6afe00e6e011bd52d/mistune-3.3.3.tar.gz", hash = "sha256:c4c6c0c840b8637a2e9b8b6d607eb7c8f00888bf14c754409bcd339e848c2477", size = 115363, upload-time = "2026-07-09T06:18:05.268Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/89/70/b1e4737b84163db5bb1dfde6f216dbfbf32783330a9989c965e121172830/mistune-3.3.3-py3-none-any.whl", hash = "sha256:99de1585e42dcbd826faa9e11a202727a5e202e4e4722a4c69ac1ff615793dd7", size = 63569, upload-time = "2026-07-09T06:18:03.839Z" }, @@ -1807,8 +1550,7 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "importlib-metadata" }, { name = "ipykernel" }, - { name = "ipython", version = "8.37.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "ipython", version = "9.6.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "ipython" }, { name = "jupyter-cache" }, { name = "myst-parser" }, { name = "nbclient" }, @@ -1951,15 +1693,10 @@ version = "0.63.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "llvmlite" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "numpy" }, ] sdist = { url = "https://files.pythonhosted.org/packages/dc/60/0145d479b2209bd8fdae5f44201eceb8ce5a23e0ed54c71f57db24618665/numba-0.63.1.tar.gz", hash = "sha256:b320aa675d0e3b17b40364935ea52a7b1c670c9037c39cf92c49502a75902f4b", size = 2761666, upload-time = "2025-12-10T02:57:39.002Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/5e/ce/5283d4ffa568f795bb0fd61ee1f0efc0c6094b94209259167fc8d4276bde/numba-0.63.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c6d6bf5bf00f7db629305caaec82a2ffb8abe2bf45eaad0d0738dc7de4113779", size = 2680810, upload-time = "2025-12-10T02:56:55.269Z" }, - { url = "https://files.pythonhosted.org/packages/0f/72/a8bda517e26d912633b32626333339b7c769ea73a5c688365ea5f88fd07e/numba-0.63.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:08653d0dfc9cc9c4c9a8fba29ceb1f2d5340c3b86c4a7e5e07e42b643bc6a2f4", size = 3739735, upload-time = "2025-12-10T02:56:57.922Z" }, - { url = "https://files.pythonhosted.org/packages/ca/17/1913b7c1173b2db30fb7a9696892a7c4c59aeee777a9af6859e9e01bac51/numba-0.63.1-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f09eebf5650246ce2a4e9a8d38270e2d4b0b0ae978103bafb38ed7adc5ea906e", size = 3446707, upload-time = "2025-12-10T02:56:59.837Z" }, - { url = "https://files.pythonhosted.org/packages/b4/77/703db56c3061e9fdad5e79c91452947fdeb2ec0bdfe4affe9b144e7025e0/numba-0.63.1-cp310-cp310-win_amd64.whl", hash = "sha256:f8bba17421d865d8c0f7be2142754ebce53e009daba41c44cf6909207d1a8d7d", size = 2747374, upload-time = "2025-12-10T02:57:07.908Z" }, { url = "https://files.pythonhosted.org/packages/70/90/5f8614c165d2e256fbc6c57028519db6f32e4982475a372bbe550ea0454c/numba-0.63.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b33db00f18ccc790ee9911ce03fcdfe9d5124637d1ecc266f5ae0df06e02fec3", size = 2680501, upload-time = "2025-12-10T02:57:09.797Z" }, { url = "https://files.pythonhosted.org/packages/dc/9d/d0afc4cf915edd8eadd9b2ab5b696242886ee4f97720d9322650d66a88c6/numba-0.63.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7d31ea186a78a7c0f6b1b2a3fe68057fdb291b045c52d86232b5383b6cf4fc25", size = 3744945, upload-time = "2025-12-10T02:57:11.697Z" }, { url = "https://files.pythonhosted.org/packages/05/a9/d82f38f2ab73f3be6f838a826b545b80339762ee8969c16a8bf1d39395a8/numba-0.63.1-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ed3bb2fbdb651d6aac394388130a7001aab6f4541837123a4b4ab8b02716530c", size = 3450827, upload-time = "2025-12-10T02:57:13.709Z" }, @@ -1978,80 +1715,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0d/5f/4d0c9e756732577a52211f31da13a3d943d185f7fb90723f56d79c696caa/numba-0.63.1-cp314-cp314-win_amd64.whl", hash = "sha256:8d6d5ce85f572ed4e1a135dbb8c0114538f9dd0e3657eeb0bb64ab204cbe2a8f", size = 2752161, upload-time = "2025-12-10T02:57:37.12Z" }, ] -[[package]] -name = "numpy" -version = "2.2.6" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.11'", -] -sdist = { url = "https://files.pythonhosted.org/packages/76/21/7d2a95e4bba9dc13d043ee156a356c0a8f0c6309dff6b21b4d71a073b8a8/numpy-2.2.6.tar.gz", hash = "sha256:e29554e2bef54a90aa5cc07da6ce955accb83f21ab5de01a62c8478897b264fd", size = 20276440, upload-time = "2025-05-17T22:38:04.611Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9a/3e/ed6db5be21ce87955c0cbd3009f2803f59fa08df21b5df06862e2d8e2bdd/numpy-2.2.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b412caa66f72040e6d268491a59f2c43bf03eb6c96dd8f0307829feb7fa2b6fb", size = 21165245, upload-time = "2025-05-17T21:27:58.555Z" }, - { url = "https://files.pythonhosted.org/packages/22/c2/4b9221495b2a132cc9d2eb862e21d42a009f5a60e45fc44b00118c174bff/numpy-2.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8e41fd67c52b86603a91c1a505ebaef50b3314de0213461c7a6e99c9a3beff90", size = 14360048, upload-time = "2025-05-17T21:28:21.406Z" }, - { url = "https://files.pythonhosted.org/packages/fd/77/dc2fcfc66943c6410e2bf598062f5959372735ffda175b39906d54f02349/numpy-2.2.6-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:37e990a01ae6ec7fe7fa1c26c55ecb672dd98b19c3d0e1d1f326fa13cb38d163", size = 5340542, upload-time = "2025-05-17T21:28:30.931Z" }, - { url = "https://files.pythonhosted.org/packages/7a/4f/1cb5fdc353a5f5cc7feb692db9b8ec2c3d6405453f982435efc52561df58/numpy-2.2.6-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:5a6429d4be8ca66d889b7cf70f536a397dc45ba6faeb5f8c5427935d9592e9cf", size = 6878301, upload-time = "2025-05-17T21:28:41.613Z" }, - { url = "https://files.pythonhosted.org/packages/eb/17/96a3acd228cec142fcb8723bd3cc39c2a474f7dcf0a5d16731980bcafa95/numpy-2.2.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efd28d4e9cd7d7a8d39074a4d44c63eda73401580c5c76acda2ce969e0a38e83", size = 14297320, upload-time = "2025-05-17T21:29:02.78Z" }, - { url = "https://files.pythonhosted.org/packages/b4/63/3de6a34ad7ad6646ac7d2f55ebc6ad439dbbf9c4370017c50cf403fb19b5/numpy-2.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc7b73d02efb0e18c000e9ad8b83480dfcd5dfd11065997ed4c6747470ae8915", size = 16801050, upload-time = "2025-05-17T21:29:27.675Z" }, - { url = "https://files.pythonhosted.org/packages/07/b6/89d837eddef52b3d0cec5c6ba0456c1bf1b9ef6a6672fc2b7873c3ec4e2e/numpy-2.2.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:74d4531beb257d2c3f4b261bfb0fc09e0f9ebb8842d82a7b4209415896adc680", size = 15807034, upload-time = "2025-05-17T21:29:51.102Z" }, - { url = "https://files.pythonhosted.org/packages/01/c8/dc6ae86e3c61cfec1f178e5c9f7858584049b6093f843bca541f94120920/numpy-2.2.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8fc377d995680230e83241d8a96def29f204b5782f371c532579b4f20607a289", size = 18614185, upload-time = "2025-05-17T21:30:18.703Z" }, - { url = "https://files.pythonhosted.org/packages/5b/c5/0064b1b7e7c89137b471ccec1fd2282fceaae0ab3a9550f2568782d80357/numpy-2.2.6-cp310-cp310-win32.whl", hash = "sha256:b093dd74e50a8cba3e873868d9e93a85b78e0daf2e98c6797566ad8044e8363d", size = 6527149, upload-time = "2025-05-17T21:30:29.788Z" }, - { url = "https://files.pythonhosted.org/packages/a3/dd/4b822569d6b96c39d1215dbae0582fd99954dcbcf0c1a13c61783feaca3f/numpy-2.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:f0fd6321b839904e15c46e0d257fdd101dd7f530fe03fd6359c1ea63738703f3", size = 12904620, upload-time = "2025-05-17T21:30:48.994Z" }, - { url = "https://files.pythonhosted.org/packages/da/a8/4f83e2aa666a9fbf56d6118faaaf5f1974d456b1823fda0a176eff722839/numpy-2.2.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f9f1adb22318e121c5c69a09142811a201ef17ab257a1e66ca3025065b7f53ae", size = 21176963, upload-time = "2025-05-17T21:31:19.36Z" }, - { url = "https://files.pythonhosted.org/packages/b3/2b/64e1affc7972decb74c9e29e5649fac940514910960ba25cd9af4488b66c/numpy-2.2.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c820a93b0255bc360f53eca31a0e676fd1101f673dda8da93454a12e23fc5f7a", size = 14406743, upload-time = "2025-05-17T21:31:41.087Z" }, - { url = "https://files.pythonhosted.org/packages/4a/9f/0121e375000b5e50ffdd8b25bf78d8e1a5aa4cca3f185d41265198c7b834/numpy-2.2.6-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3d70692235e759f260c3d837193090014aebdf026dfd167834bcba43e30c2a42", size = 5352616, upload-time = "2025-05-17T21:31:50.072Z" }, - { url = "https://files.pythonhosted.org/packages/31/0d/b48c405c91693635fbe2dcd7bc84a33a602add5f63286e024d3b6741411c/numpy-2.2.6-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:481b49095335f8eed42e39e8041327c05b0f6f4780488f61286ed3c01368d491", size = 6889579, upload-time = "2025-05-17T21:32:01.712Z" }, - { url = "https://files.pythonhosted.org/packages/52/b8/7f0554d49b565d0171eab6e99001846882000883998e7b7d9f0d98b1f934/numpy-2.2.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b64d8d4d17135e00c8e346e0a738deb17e754230d7e0810ac5012750bbd85a5a", size = 14312005, upload-time = "2025-05-17T21:32:23.332Z" }, - { url = "https://files.pythonhosted.org/packages/b3/dd/2238b898e51bd6d389b7389ffb20d7f4c10066d80351187ec8e303a5a475/numpy-2.2.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba10f8411898fc418a521833e014a77d3ca01c15b0c6cdcce6a0d2897e6dbbdf", size = 16821570, upload-time = "2025-05-17T21:32:47.991Z" }, - { url = "https://files.pythonhosted.org/packages/83/6c/44d0325722cf644f191042bf47eedad61c1e6df2432ed65cbe28509d404e/numpy-2.2.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bd48227a919f1bafbdda0583705e547892342c26fb127219d60a5c36882609d1", size = 15818548, upload-time = "2025-05-17T21:33:11.728Z" }, - { url = "https://files.pythonhosted.org/packages/ae/9d/81e8216030ce66be25279098789b665d49ff19eef08bfa8cb96d4957f422/numpy-2.2.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9551a499bf125c1d4f9e250377c1ee2eddd02e01eac6644c080162c0c51778ab", size = 18620521, upload-time = "2025-05-17T21:33:39.139Z" }, - { url = "https://files.pythonhosted.org/packages/6a/fd/e19617b9530b031db51b0926eed5345ce8ddc669bb3bc0044b23e275ebe8/numpy-2.2.6-cp311-cp311-win32.whl", hash = "sha256:0678000bb9ac1475cd454c6b8c799206af8107e310843532b04d49649c717a47", size = 6525866, upload-time = "2025-05-17T21:33:50.273Z" }, - { url = "https://files.pythonhosted.org/packages/31/0a/f354fb7176b81747d870f7991dc763e157a934c717b67b58456bc63da3df/numpy-2.2.6-cp311-cp311-win_amd64.whl", hash = "sha256:e8213002e427c69c45a52bbd94163084025f533a55a59d6f9c5b820774ef3303", size = 12907455, upload-time = "2025-05-17T21:34:09.135Z" }, - { url = "https://files.pythonhosted.org/packages/82/5d/c00588b6cf18e1da539b45d3598d3557084990dcc4331960c15ee776ee41/numpy-2.2.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:41c5a21f4a04fa86436124d388f6ed60a9343a6f767fced1a8a71c3fbca038ff", size = 20875348, upload-time = "2025-05-17T21:34:39.648Z" }, - { url = "https://files.pythonhosted.org/packages/66/ee/560deadcdde6c2f90200450d5938f63a34b37e27ebff162810f716f6a230/numpy-2.2.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:de749064336d37e340f640b05f24e9e3dd678c57318c7289d222a8a2f543e90c", size = 14119362, upload-time = "2025-05-17T21:35:01.241Z" }, - { url = "https://files.pythonhosted.org/packages/3c/65/4baa99f1c53b30adf0acd9a5519078871ddde8d2339dc5a7fde80d9d87da/numpy-2.2.6-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:894b3a42502226a1cac872f840030665f33326fc3dac8e57c607905773cdcde3", size = 5084103, upload-time = "2025-05-17T21:35:10.622Z" }, - { url = "https://files.pythonhosted.org/packages/cc/89/e5a34c071a0570cc40c9a54eb472d113eea6d002e9ae12bb3a8407fb912e/numpy-2.2.6-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:71594f7c51a18e728451bb50cc60a3ce4e6538822731b2933209a1f3614e9282", size = 6625382, upload-time = "2025-05-17T21:35:21.414Z" }, - { url = "https://files.pythonhosted.org/packages/f8/35/8c80729f1ff76b3921d5c9487c7ac3de9b2a103b1cd05e905b3090513510/numpy-2.2.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2618db89be1b4e05f7a1a847a9c1c0abd63e63a1607d892dd54668dd92faf87", size = 14018462, upload-time = "2025-05-17T21:35:42.174Z" }, - { url = "https://files.pythonhosted.org/packages/8c/3d/1e1db36cfd41f895d266b103df00ca5b3cbe965184df824dec5c08c6b803/numpy-2.2.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd83c01228a688733f1ded5201c678f0c53ecc1006ffbc404db9f7a899ac6249", size = 16527618, upload-time = "2025-05-17T21:36:06.711Z" }, - { url = "https://files.pythonhosted.org/packages/61/c6/03ed30992602c85aa3cd95b9070a514f8b3c33e31124694438d88809ae36/numpy-2.2.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:37c0ca431f82cd5fa716eca9506aefcabc247fb27ba69c5062a6d3ade8cf8f49", size = 15505511, upload-time = "2025-05-17T21:36:29.965Z" }, - { url = "https://files.pythonhosted.org/packages/b7/25/5761d832a81df431e260719ec45de696414266613c9ee268394dd5ad8236/numpy-2.2.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fe27749d33bb772c80dcd84ae7e8df2adc920ae8297400dabec45f0dedb3f6de", size = 18313783, upload-time = "2025-05-17T21:36:56.883Z" }, - { url = "https://files.pythonhosted.org/packages/57/0a/72d5a3527c5ebffcd47bde9162c39fae1f90138c961e5296491ce778e682/numpy-2.2.6-cp312-cp312-win32.whl", hash = "sha256:4eeaae00d789f66c7a25ac5f34b71a7035bb474e679f410e5e1a94deb24cf2d4", size = 6246506, upload-time = "2025-05-17T21:37:07.368Z" }, - { url = "https://files.pythonhosted.org/packages/36/fa/8c9210162ca1b88529ab76b41ba02d433fd54fecaf6feb70ef9f124683f1/numpy-2.2.6-cp312-cp312-win_amd64.whl", hash = "sha256:c1f9540be57940698ed329904db803cf7a402f3fc200bfe599334c9bd84a40b2", size = 12614190, upload-time = "2025-05-17T21:37:26.213Z" }, - { url = "https://files.pythonhosted.org/packages/f9/5c/6657823f4f594f72b5471f1db1ab12e26e890bb2e41897522d134d2a3e81/numpy-2.2.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0811bb762109d9708cca4d0b13c4f67146e3c3b7cf8d34018c722adb2d957c84", size = 20867828, upload-time = "2025-05-17T21:37:56.699Z" }, - { url = "https://files.pythonhosted.org/packages/dc/9e/14520dc3dadf3c803473bd07e9b2bd1b69bc583cb2497b47000fed2fa92f/numpy-2.2.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:287cc3162b6f01463ccd86be154f284d0893d2b3ed7292439ea97eafa8170e0b", size = 14143006, upload-time = "2025-05-17T21:38:18.291Z" }, - { url = "https://files.pythonhosted.org/packages/4f/06/7e96c57d90bebdce9918412087fc22ca9851cceaf5567a45c1f404480e9e/numpy-2.2.6-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:f1372f041402e37e5e633e586f62aa53de2eac8d98cbfb822806ce4bbefcb74d", size = 5076765, upload-time = "2025-05-17T21:38:27.319Z" }, - { url = "https://files.pythonhosted.org/packages/73/ed/63d920c23b4289fdac96ddbdd6132e9427790977d5457cd132f18e76eae0/numpy-2.2.6-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:55a4d33fa519660d69614a9fad433be87e5252f4b03850642f88993f7b2ca566", size = 6617736, upload-time = "2025-05-17T21:38:38.141Z" }, - { url = "https://files.pythonhosted.org/packages/85/c5/e19c8f99d83fd377ec8c7e0cf627a8049746da54afc24ef0a0cb73d5dfb5/numpy-2.2.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f92729c95468a2f4f15e9bb94c432a9229d0d50de67304399627a943201baa2f", size = 14010719, upload-time = "2025-05-17T21:38:58.433Z" }, - { url = "https://files.pythonhosted.org/packages/19/49/4df9123aafa7b539317bf6d342cb6d227e49f7a35b99c287a6109b13dd93/numpy-2.2.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bc23a79bfabc5d056d106f9befb8d50c31ced2fbc70eedb8155aec74a45798f", size = 16526072, upload-time = "2025-05-17T21:39:22.638Z" }, - { url = "https://files.pythonhosted.org/packages/b2/6c/04b5f47f4f32f7c2b0e7260442a8cbcf8168b0e1a41ff1495da42f42a14f/numpy-2.2.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e3143e4451880bed956e706a3220b4e5cf6172ef05fcc397f6f36a550b1dd868", size = 15503213, upload-time = "2025-05-17T21:39:45.865Z" }, - { url = "https://files.pythonhosted.org/packages/17/0a/5cd92e352c1307640d5b6fec1b2ffb06cd0dabe7d7b8227f97933d378422/numpy-2.2.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b4f13750ce79751586ae2eb824ba7e1e8dba64784086c98cdbbcc6a42112ce0d", size = 18316632, upload-time = "2025-05-17T21:40:13.331Z" }, - { url = "https://files.pythonhosted.org/packages/f0/3b/5cba2b1d88760ef86596ad0f3d484b1cbff7c115ae2429678465057c5155/numpy-2.2.6-cp313-cp313-win32.whl", hash = "sha256:5beb72339d9d4fa36522fc63802f469b13cdbe4fdab4a288f0c441b74272ebfd", size = 6244532, upload-time = "2025-05-17T21:43:46.099Z" }, - { url = "https://files.pythonhosted.org/packages/cb/3b/d58c12eafcb298d4e6d0d40216866ab15f59e55d148a5658bb3132311fcf/numpy-2.2.6-cp313-cp313-win_amd64.whl", hash = "sha256:b0544343a702fa80c95ad5d3d608ea3599dd54d4632df855e4c8d24eb6ecfa1c", size = 12610885, upload-time = "2025-05-17T21:44:05.145Z" }, - { url = "https://files.pythonhosted.org/packages/6b/9e/4bf918b818e516322db999ac25d00c75788ddfd2d2ade4fa66f1f38097e1/numpy-2.2.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0bca768cd85ae743b2affdc762d617eddf3bcf8724435498a1e80132d04879e6", size = 20963467, upload-time = "2025-05-17T21:40:44Z" }, - { url = "https://files.pythonhosted.org/packages/61/66/d2de6b291507517ff2e438e13ff7b1e2cdbdb7cb40b3ed475377aece69f9/numpy-2.2.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:fc0c5673685c508a142ca65209b4e79ed6740a4ed6b2267dbba90f34b0b3cfda", size = 14225144, upload-time = "2025-05-17T21:41:05.695Z" }, - { url = "https://files.pythonhosted.org/packages/e4/25/480387655407ead912e28ba3a820bc69af9adf13bcbe40b299d454ec011f/numpy-2.2.6-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:5bd4fc3ac8926b3819797a7c0e2631eb889b4118a9898c84f585a54d475b7e40", size = 5200217, upload-time = "2025-05-17T21:41:15.903Z" }, - { url = "https://files.pythonhosted.org/packages/aa/4a/6e313b5108f53dcbf3aca0c0f3e9c92f4c10ce57a0a721851f9785872895/numpy-2.2.6-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:fee4236c876c4e8369388054d02d0e9bb84821feb1a64dd59e137e6511a551f8", size = 6712014, upload-time = "2025-05-17T21:41:27.321Z" }, - { url = "https://files.pythonhosted.org/packages/b7/30/172c2d5c4be71fdf476e9de553443cf8e25feddbe185e0bd88b096915bcc/numpy-2.2.6-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1dda9c7e08dc141e0247a5b8f49cf05984955246a327d4c48bda16821947b2f", size = 14077935, upload-time = "2025-05-17T21:41:49.738Z" }, - { url = "https://files.pythonhosted.org/packages/12/fb/9e743f8d4e4d3c710902cf87af3512082ae3d43b945d5d16563f26ec251d/numpy-2.2.6-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f447e6acb680fd307f40d3da4852208af94afdfab89cf850986c3ca00562f4fa", size = 16600122, upload-time = "2025-05-17T21:42:14.046Z" }, - { url = "https://files.pythonhosted.org/packages/12/75/ee20da0e58d3a66f204f38916757e01e33a9737d0b22373b3eb5a27358f9/numpy-2.2.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:389d771b1623ec92636b0786bc4ae56abafad4a4c513d36a55dce14bd9ce8571", size = 15586143, upload-time = "2025-05-17T21:42:37.464Z" }, - { url = "https://files.pythonhosted.org/packages/76/95/bef5b37f29fc5e739947e9ce5179ad402875633308504a52d188302319c8/numpy-2.2.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8e9ace4a37db23421249ed236fdcdd457d671e25146786dfc96835cd951aa7c1", size = 18385260, upload-time = "2025-05-17T21:43:05.189Z" }, - { url = "https://files.pythonhosted.org/packages/09/04/f2f83279d287407cf36a7a8053a5abe7be3622a4363337338f2585e4afda/numpy-2.2.6-cp313-cp313t-win32.whl", hash = "sha256:038613e9fb8c72b0a41f025a7e4c3f0b7a1b5d768ece4796b674c8f3fe13efff", size = 6377225, upload-time = "2025-05-17T21:43:16.254Z" }, - { url = "https://files.pythonhosted.org/packages/67/0e/35082d13c09c02c011cf21570543d202ad929d961c02a147493cb0c2bdf5/numpy-2.2.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6031dd6dfecc0cf9f668681a37648373bddd6421fff6c66ec1624eed0180ee06", size = 12771374, upload-time = "2025-05-17T21:43:35.479Z" }, - { url = "https://files.pythonhosted.org/packages/9e/3b/d94a75f4dbf1ef5d321523ecac21ef23a3cd2ac8b78ae2aac40873590229/numpy-2.2.6-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0b605b275d7bd0c640cad4e5d30fa701a8d59302e127e5f79138ad62762c3e3d", size = 21040391, upload-time = "2025-05-17T21:44:35.948Z" }, - { url = "https://files.pythonhosted.org/packages/17/f4/09b2fa1b58f0fb4f7c7963a1649c64c4d315752240377ed74d9cd878f7b5/numpy-2.2.6-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:7befc596a7dc9da8a337f79802ee8adb30a552a94f792b9c9d18c840055907db", size = 6786754, upload-time = "2025-05-17T21:44:47.446Z" }, - { url = "https://files.pythonhosted.org/packages/af/30/feba75f143bdc868a1cc3f44ccfa6c4b9ec522b36458e738cd00f67b573f/numpy-2.2.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce47521a4754c8f4593837384bd3424880629f718d87c5d44f8ed763edd63543", size = 16643476, upload-time = "2025-05-17T21:45:11.871Z" }, - { url = "https://files.pythonhosted.org/packages/37/48/ac2a9584402fb6c0cd5b5d1a91dcf176b15760130dd386bbafdbfe3640bf/numpy-2.2.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d042d24c90c41b54fd506da306759e06e568864df8ec17ccc17e9e884634fd00", size = 12812666, upload-time = "2025-05-17T21:45:31.426Z" }, -] - [[package]] name = "numpy" version = "2.3.3" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.12' and python_full_version < '3.14'", - "python_full_version == '3.11.*'", -] sdist = { url = "https://files.pythonhosted.org/packages/d0/19/95b3d357407220ed24c139018d2518fab0a61a948e68286a25f1a4d049ff/numpy-2.3.3.tar.gz", hash = "sha256:ddc7c39727ba62b80dfdbedf400d1c10ddfa8eefbd7ec8dcb118be8b56d31029", size = 20576648, upload-time = "2025-09-09T16:54:12.543Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/7a/45/e80d203ef6b267aa29b22714fb558930b27960a0c5ce3c19c999232bb3eb/numpy-2.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0ffc4f5caba7dfcbe944ed674b7eef683c7e94874046454bb79ed7ee0236f59d", size = 21259253, upload-time = "2025-09-09T15:56:02.094Z" }, @@ -2135,7 +1802,6 @@ version = "1.9.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "sphinx" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/2f/19/7721093e25804cc82c7c1cdab0cce6b9343451828fc2ce249cee10646db5/numpydoc-1.9.0.tar.gz", hash = "sha256:5fec64908fe041acc4b3afc2a32c49aab1540cf581876f5563d68bb129e27c5b", size = 91451, upload-time = "2025-06-24T12:22:55.283Z" } wheels = [ @@ -2156,21 +1822,13 @@ name = "pandas" version = "2.3.3" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "numpy" }, { name = "python-dateutil" }, { name = "pytz" }, { name = "tzdata" }, ] sdist = { url = "https://files.pythonhosted.org/packages/33/01/d40b85317f86cf08d853a4f495195c73815fdf205eef3993821720274518/pandas-2.3.3.tar.gz", hash = "sha256:e05e1af93b977f7eafa636d043f9f94c7ee3ac81af99c13508215942e64c993b", size = 4495223, upload-time = "2025-09-29T23:34:51.853Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3d/f7/f425a00df4fcc22b292c6895c6831c0c8ae1d9fac1e024d16f98a9ce8749/pandas-2.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:376c6446ae31770764215a6c937f72d917f214b43560603cd60da6408f183b6c", size = 11555763, upload-time = "2025-09-29T23:16:53.287Z" }, - { url = "https://files.pythonhosted.org/packages/13/4f/66d99628ff8ce7857aca52fed8f0066ce209f96be2fede6cef9f84e8d04f/pandas-2.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e19d192383eab2f4ceb30b412b22ea30690c9e618f78870357ae1d682912015a", size = 10801217, upload-time = "2025-09-29T23:17:04.522Z" }, - { url = "https://files.pythonhosted.org/packages/1d/03/3fc4a529a7710f890a239cc496fc6d50ad4a0995657dccc1d64695adb9f4/pandas-2.3.3-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5caf26f64126b6c7aec964f74266f435afef1c1b13da3b0636c7518a1fa3e2b1", size = 12148791, upload-time = "2025-09-29T23:17:18.444Z" }, - { url = "https://files.pythonhosted.org/packages/40/a8/4dac1f8f8235e5d25b9955d02ff6f29396191d4e665d71122c3722ca83c5/pandas-2.3.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd7478f1463441ae4ca7308a70e90b33470fa593429f9d4c578dd00d1fa78838", size = 12769373, upload-time = "2025-09-29T23:17:35.846Z" }, - { url = "https://files.pythonhosted.org/packages/df/91/82cc5169b6b25440a7fc0ef3a694582418d875c8e3ebf796a6d6470aa578/pandas-2.3.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:4793891684806ae50d1288c9bae9330293ab4e083ccd1c5e383c34549c6e4250", size = 13200444, upload-time = "2025-09-29T23:17:49.341Z" }, - { url = "https://files.pythonhosted.org/packages/10/ae/89b3283800ab58f7af2952704078555fa60c807fff764395bb57ea0b0dbd/pandas-2.3.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:28083c648d9a99a5dd035ec125d42439c6c1c525098c58af0fc38dd1a7a1b3d4", size = 13858459, upload-time = "2025-09-29T23:18:03.722Z" }, - { url = "https://files.pythonhosted.org/packages/85/72/530900610650f54a35a19476eca5104f38555afccda1aa11a92ee14cb21d/pandas-2.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:503cf027cf9940d2ceaa1a93cfb5f8c8c7e6e90720a2850378f0b3f3b1e06826", size = 11346086, upload-time = "2025-09-29T23:18:18.505Z" }, { url = "https://files.pythonhosted.org/packages/c1/fa/7ac648108144a095b4fb6aa3de1954689f7af60a14cf25583f4960ecb878/pandas-2.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:602b8615ebcc4a0c1751e71840428ddebeb142ec02c786e8ad6b1ce3c8dec523", size = 11578790, upload-time = "2025-09-29T23:18:30.065Z" }, { url = "https://files.pythonhosted.org/packages/9b/35/74442388c6cf008882d4d4bdfc4109be87e9b8b7ccd097ad1e7f006e2e95/pandas-2.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8fe25fc7b623b0ef6b5009149627e34d2a4657e880948ec3c840e9402e5c1b45", size = 10833831, upload-time = "2025-09-29T23:38:56.071Z" }, { url = "https://files.pythonhosted.org/packages/fe/e4/de154cbfeee13383ad58d23017da99390b91d73f8c11856f2095e813201b/pandas-2.3.3-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b468d3dad6ff947df92dcb32ede5b7bd41a9b3cceef0a30ed925f6d01fb8fa66", size = 12199267, upload-time = "2025-09-29T23:18:41.627Z" }, @@ -2249,8 +1907,7 @@ name = "patsy" version = "1.0.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "numpy" }, ] sdist = { url = "https://files.pythonhosted.org/packages/be/44/ed13eccdd0519eff265f44b670d46fbb0ec813e2274932dc1c0e48520f7d/patsy-1.0.2.tar.gz", hash = "sha256:cdc995455f6233e90e22de72c37fcadb344e7586fb83f06696f54d92f8ce74c0", size = 399942, upload-time = "2025-10-20T16:17:37.535Z" } wheels = [ @@ -2275,15 +1932,6 @@ version = "12.3.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/1c/3d/bb7fca845737cf9d7dbde16ed1843984665ff2e0a518f5db43e77ec540b9/pillow-12.3.0.tar.gz", hash = "sha256:3b8182a766685eaa002637e28b4ec8d6b18819a0c71f579bf0dbaa5830297cce", size = 47025035, upload-time = "2026-07-01T11:56:38.965Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/25/c2/669d88644cddb1485bd9534e63e8cf476c8e51cb3c3a1297677023505c0e/pillow-12.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:6c0016e7b354317c4e9e525b937ac8596c38d2d232b419529b9cd7a1cd46e39a", size = 5392418, upload-time = "2026-07-01T11:53:27.808Z" }, - { url = "https://files.pythonhosted.org/packages/6b/ba/3762f376a2948e3036488d773a146e0ae6ecc2ca03ac20e2615bd0b2ba02/pillow-12.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bcc33feacfaefce60c12fd500a277533bdc02b10a19f7f6d348763d8140bbba7", size = 4785287, upload-time = "2026-07-01T11:53:29.761Z" }, - { url = "https://files.pythonhosted.org/packages/07/50/b5d688cc9c52d4482f3d5bcab6ce20bc2a74a85d2343841c907444a3be2c/pillow-12.3.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5594fc43d548a7ed94949d139aa1341b270f1863f11cfd37f5a6c8b778a6b67f", size = 6253754, upload-time = "2026-07-01T11:53:32.298Z" }, - { url = "https://files.pythonhosted.org/packages/4e/89/36f4cd76cf4baf05c50ababb976249153f18c959171c7f6ba09a6f217260/pillow-12.3.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f0606c8bf2cdefea14a43530f7657cbbb7ecf1c4222512492ef4a4434a9501ec", size = 6925605, upload-time = "2026-07-01T11:53:34.487Z" }, - { url = "https://files.pythonhosted.org/packages/eb/c0/4de58cf6633b9e3a6061ef4be6fb91fc3c90b812ece886f531e3c523d777/pillow-12.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:85f998ea1848bc6757289e739cfbdda3a04adfd58b02fc018ce54d754a5ce468", size = 6327788, upload-time = "2026-07-01T11:53:36.433Z" }, - { url = "https://files.pythonhosted.org/packages/87/3c/14d53682a19550dbbaf3b598f807d5457646c510805a44c7d7891cd1cd1a/pillow-12.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:25b9b82bb22e6e2b3cd07b39c68b7b862001226cb3dff7130d1cb914121b39ed", size = 7036288, upload-time = "2026-07-01T11:53:38.712Z" }, - { url = "https://files.pythonhosted.org/packages/38/1d/36279e3c77efe034e4cc2b0393ee74ffdb5a62391dacbf9b916154f5f0b8/pillow-12.3.0-cp310-cp310-win32.whl", hash = "sha256:37dc8f7bbb66efe481bb60defacef820c950c24713fb44962ed6aa2a50966de1", size = 6472396, upload-time = "2026-07-01T11:53:40.781Z" }, - { url = "https://files.pythonhosted.org/packages/48/7c/8fa0039574c476d7c6fa57dd7c32a130436877c6ec1e5ce1cc8ec44878c1/pillow-12.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:300557495eb45ebb8aec96c2da9c4be642fbf7cd937278b4013ba894ea8eb0eb", size = 7226887, upload-time = "2026-07-01T11:53:42.764Z" }, - { url = "https://files.pythonhosted.org/packages/fa/17/e324be141d173c1c919428066c3259f21c1b8982e564e01a4a81e96dbdcf/pillow-12.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:514435a37670e3e5e08f3945b68718b6ed329bb84367777e16f9f4dfe1e61a0f", size = 2568039, upload-time = "2026-07-01T11:53:45.372Z" }, { url = "https://files.pythonhosted.org/packages/fb/c8/0a78b0e02d7ac54bc03e5321c9220da52f0c2ea83b21f7c40e7f3169c502/pillow-12.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:00808c5e14ef63ac5161091d242999076604ff74b883423a11e5d7bbb38bf756", size = 5392415, upload-time = "2026-07-01T11:53:47.162Z" }, { url = "https://files.pythonhosted.org/packages/b2/5b/a02d30018abd97ced9f5a6c63d28597694a00d066516b9c1c6de45859fc9/pillow-12.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37d6d0a00072fd2948eb22bce7e1475f34569d90c87c59f7a2ec59541b77f7a6", size = 4785266, upload-time = "2026-07-01T11:53:49.079Z" }, { url = "https://files.pythonhosted.org/packages/c8/98/766667a4be768150a202836acd9fad19c06824ca86c4286d3cf6b274964e/pillow-12.3.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bcb46e2f9feff8d06323983bd83ed00c201fdcab3d74973e7072a889b3979fcd", size = 6263814, upload-time = "2026-07-01T11:53:51.32Z" }, @@ -2475,13 +2123,6 @@ version = "25.0.0" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/27/f3/95428098d1fa7d04432fb750eed06b41304c2f6a5d3319985e64db2d9d41/pyarrow-25.0.0.tar.gz", hash = "sha256:d2d697008b5ec06d75952ef260c2e9a8a0f6ccfce24266c04c9c8ade927cb3b4", size = 1199181, upload-time = "2026-07-10T08:29:50.116Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/2a/eaa70e6d6ed430c2e90c0599e2831a41a50251879e44788ccdbc73115af1/pyarrow-25.0.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:ce0ca222802087b9a8cb031a6468442cb6b67c290a45a601cac64753d34954d3", size = 35945551, upload-time = "2026-07-10T08:25:23.153Z" }, - { url = "https://files.pythonhosted.org/packages/df/e0/917086af6b246143012cdc8a7c886b018b53204f3d69fc5f9be5857a8b80/pyarrow-25.0.0-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:7d6da02ffc7a3a9bda3b7ded4cc2a27ff73969ab37153f3afd46bbbc1ba4f0f7", size = 37636698, upload-time = "2026-07-10T08:25:28.031Z" }, - { url = "https://files.pythonhosted.org/packages/68/6a/c87829f92503f84993721791c942f3d9aa81044de51a8cfb1da5810e5345/pyarrow-25.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:dbf9fa5d4bde73b1cc16377dcaaa010f971e6fa7f5083f5d44f34b50bc1d74af", size = 46858364, upload-time = "2026-07-10T08:25:34.527Z" }, - { url = "https://files.pythonhosted.org/packages/cc/ba/2030d454c2747e26cce23e4a0338067ee0830a155b7894da04caa96783a5/pyarrow-25.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b72d943ff4e10fec8d48aedb23322d8f6ea8bc2d698b81db37e73730f69e4862", size = 50056398, upload-time = "2026-07-10T08:25:40.785Z" }, - { url = "https://files.pythonhosted.org/packages/78/ce/ba7a5ce7bf0cfc372ec48203a34ece42f73aa2f3231706f61c55e105ecd0/pyarrow-25.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5fb2d837960f1df7f679ff9f1a55065e306347d379e0768cebf14781254d6194", size = 49958146, upload-time = "2026-07-10T08:25:46.98Z" }, - { url = "https://files.pythonhosted.org/packages/75/eb/c34a29fb7a70dca2f903c7d85a928928ef55af20cd56e99de6b4c0d897bc/pyarrow-25.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:add690feafa0953c443cdba9e9e87f5eaa198f1ea2e43a3b146ea83f202262d0", size = 53096264, upload-time = "2026-07-10T08:25:53.925Z" }, - { url = "https://files.pythonhosted.org/packages/36/f9/35b1f83a0727d84951588e4034aca2feb76dfb45b0725918c0037b0a48f7/pyarrow-25.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:d293e9959b29a24c82d936d04ab2b7fd8b8d334030de2e56a99aba94f008ad7a", size = 27840572, upload-time = "2026-07-10T08:25:58.966Z" }, { url = "https://files.pythonhosted.org/packages/a7/98/ae2b5acf9876dbeffa6f320776242c52caab062df55c8ac5501ed2679e74/pyarrow-25.0.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:2e3b6544e26e393fe2cd530f523e36c1c8d3c345bbbb60cca3fd866be8322517", size = 35939080, upload-time = "2026-07-10T08:26:04.53Z" }, { url = "https://files.pythonhosted.org/packages/80/09/3de2a968edbd496c86cb8b932cdbee2d4b08c4a28e9884a15e5c705a646b/pyarrow-25.0.0-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:b724d127783b4c19f088fcdfc844cbc318809246a30307bcabd5ed02045e890e", size = 37633420, upload-time = "2026-07-10T08:26:10.354Z" }, { url = "https://files.pythonhosted.org/packages/19/86/8399243a4ce080426ec37db18d5e29148b7ec960a8a8c7f9059a7bf6ef0a/pyarrow-25.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:244f98a595f70fa4fd35faa7508c4ae67e14a173397a4b3b49d2b3c360fb0062", size = 46861050, upload-time = "2026-07-10T08:26:16.397Z" }, @@ -2554,37 +2195,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934", size = 118140, upload-time = "2025-09-09T13:23:46.651Z" }, ] -[[package]] -name = "pydata-sphinx-theme" -version = "0.15.4" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.11'", -] -dependencies = [ - { name = "accessible-pygments" }, - { name = "babel" }, - { name = "beautifulsoup4" }, - { name = "docutils" }, - { name = "packaging" }, - { name = "pygments" }, - { name = "sphinx" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/67/ea/3ab478cccacc2e8ef69892c42c44ae547bae089f356c4b47caf61730958d/pydata_sphinx_theme-0.15.4.tar.gz", hash = "sha256:7762ec0ac59df3acecf49fd2f889e1b4565dbce8b88b2e29ee06fdd90645a06d", size = 2400673, upload-time = "2024-06-25T19:28:45.041Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/d3/c622950d87a2ffd1654208733b5bd1c5645930014abed8f4c0d74863988b/pydata_sphinx_theme-0.15.4-py3-none-any.whl", hash = "sha256:2136ad0e9500d0949f96167e63f3e298620040aea8f9c74621959eda5d4cf8e6", size = 4640157, upload-time = "2024-06-25T19:28:42.383Z" }, -] - [[package]] name = "pydata-sphinx-theme" version = "0.16.1" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.12' and python_full_version < '3.14'", - "python_full_version == '3.11.*'", -] dependencies = [ { name = "accessible-pygments" }, { name = "babel" }, @@ -2636,12 +2250,10 @@ version = "9.0.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, { name = "iniconfig" }, { name = "packaging" }, { name = "pluggy" }, { name = "pygments" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" } wheels = [ @@ -2713,9 +2325,6 @@ name = "pywin32" version = "311" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7b/40/44efbb0dfbd33aca6a6483191dae0716070ed99e2ecb0c53683f400a0b4f/pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3", size = 8760432, upload-time = "2025-07-14T20:13:05.9Z" }, - { url = "https://files.pythonhosted.org/packages/5e/bf/360243b1e953bd254a82f12653974be395ba880e7ec23e3731d9f73921cc/pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b", size = 9590103, upload-time = "2025-07-14T20:13:07.698Z" }, - { url = "https://files.pythonhosted.org/packages/57/38/d290720e6f138086fb3d5ffe0b6caa019a791dd57866940c82e4eeaf2012/pywin32-311-cp310-cp310-win_arm64.whl", hash = "sha256:0502d1facf1fed4839a9a51ccbcc63d952cf318f78ffc00a7e78528ac27d7a2b", size = 8778557, upload-time = "2025-07-14T20:13:11.11Z" }, { url = "https://files.pythonhosted.org/packages/7c/af/449a6a91e5d6db51420875c54f6aff7c97a86a3b13a0b4f1a5c13b988de3/pywin32-311-cp311-cp311-win32.whl", hash = "sha256:184eb5e436dea364dcd3d2316d577d625c0351bf237c4e9a5fabbcfa5a58b151", size = 8697031, upload-time = "2025-07-14T20:13:13.266Z" }, { url = "https://files.pythonhosted.org/packages/51/8f/9bb81dd5bb77d22243d33c8397f09377056d5c687aa6d4042bea7fbf8364/pywin32-311-cp311-cp311-win_amd64.whl", hash = "sha256:3ce80b34b22b17ccbd937a6e78e7225d80c52f5ab9940fe0506a1a16f3dab503", size = 9508308, upload-time = "2025-07-14T20:13:15.147Z" }, { url = "https://files.pythonhosted.org/packages/44/7b/9c2ab54f74a138c491aba1b1cd0795ba61f144c711daea84a88b63dc0f6c/pywin32-311-cp311-cp311-win_arm64.whl", hash = "sha256:a733f1388e1a842abb67ffa8e7aad0e70ac519e09b0f6a784e65a136ec7cefd2", size = 8703930, upload-time = "2025-07-14T20:13:16.945Z" }, @@ -2736,15 +2345,6 @@ version = "6.0.3" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, - { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, - { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, - { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, - { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, - { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, - { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, - { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, - { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, { url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z" }, { url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z" }, { url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z" }, @@ -2803,16 +2403,6 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/04/0b/3c9baedbdf613ecaa7aa07027780b8867f57b6293b6ee50de316c9f3222b/pyzmq-27.1.0.tar.gz", hash = "sha256:ac0765e3d44455adb6ddbf4417dcce460fc40a05978c08efdf2948072f6db540", size = 281750, upload-time = "2025-09-08T23:10:18.157Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/67/b9/52aa9ec2867528b54f1e60846728d8b4d84726630874fee3a91e66c7df81/pyzmq-27.1.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:508e23ec9bc44c0005c4946ea013d9317ae00ac67778bd47519fdf5a0e930ff4", size = 1329850, upload-time = "2025-09-08T23:07:26.274Z" }, - { url = "https://files.pythonhosted.org/packages/99/64/5653e7b7425b169f994835a2b2abf9486264401fdef18df91ddae47ce2cc/pyzmq-27.1.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:507b6f430bdcf0ee48c0d30e734ea89ce5567fd7b8a0f0044a369c176aa44556", size = 906380, upload-time = "2025-09-08T23:07:29.78Z" }, - { url = "https://files.pythonhosted.org/packages/73/78/7d713284dbe022f6440e391bd1f3c48d9185673878034cfb3939cdf333b2/pyzmq-27.1.0-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf7b38f9fd7b81cb6d9391b2946382c8237fd814075c6aa9c3b746d53076023b", size = 666421, upload-time = "2025-09-08T23:07:31.263Z" }, - { url = "https://files.pythonhosted.org/packages/30/76/8f099f9d6482450428b17c4d6b241281af7ce6a9de8149ca8c1c649f6792/pyzmq-27.1.0-cp310-cp310-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03ff0b279b40d687691a6217c12242ee71f0fba28bf8626ff50e3ef0f4410e1e", size = 854149, upload-time = "2025-09-08T23:07:33.17Z" }, - { url = "https://files.pythonhosted.org/packages/59/f0/37fbfff06c68016019043897e4c969ceab18bde46cd2aca89821fcf4fb2e/pyzmq-27.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:677e744fee605753eac48198b15a2124016c009a11056f93807000ab11ce6526", size = 1655070, upload-time = "2025-09-08T23:07:35.205Z" }, - { url = "https://files.pythonhosted.org/packages/47/14/7254be73f7a8edc3587609554fcaa7bfd30649bf89cd260e4487ca70fdaa/pyzmq-27.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dd2fec2b13137416a1c5648b7009499bcc8fea78154cd888855fa32514f3dad1", size = 2033441, upload-time = "2025-09-08T23:07:37.432Z" }, - { url = "https://files.pythonhosted.org/packages/22/dc/49f2be26c6f86f347e796a4d99b19167fc94503f0af3fd010ad262158822/pyzmq-27.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:08e90bb4b57603b84eab1d0ca05b3bbb10f60c1839dc471fc1c9e1507bef3386", size = 1891529, upload-time = "2025-09-08T23:07:39.047Z" }, - { url = "https://files.pythonhosted.org/packages/a3/3e/154fb963ae25be70c0064ce97776c937ecc7d8b0259f22858154a9999769/pyzmq-27.1.0-cp310-cp310-win32.whl", hash = "sha256:a5b42d7a0658b515319148875fcb782bbf118dd41c671b62dae33666c2213bda", size = 567276, upload-time = "2025-09-08T23:07:40.695Z" }, - { url = "https://files.pythonhosted.org/packages/62/b2/f4ab56c8c595abcb26b2be5fd9fa9e6899c1e5ad54964e93ae8bb35482be/pyzmq-27.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:c0bb87227430ee3aefcc0ade2088100e528d5d3298a0a715a64f3d04c60ba02f", size = 632208, upload-time = "2025-09-08T23:07:42.298Z" }, - { url = "https://files.pythonhosted.org/packages/3b/e3/be2cc7ab8332bdac0522fdb64c17b1b6241a795bee02e0196636ec5beb79/pyzmq-27.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:9a916f76c2ab8d045b19f2286851a38e9ac94ea91faf65bd64735924522a8b32", size = 559766, upload-time = "2025-09-08T23:07:43.869Z" }, { url = "https://files.pythonhosted.org/packages/06/5d/305323ba86b284e6fcb0d842d6adaa2999035f70f8c38a9b6d21ad28c3d4/pyzmq-27.1.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:226b091818d461a3bef763805e75685e478ac17e9008f49fce2d3e52b3d58b86", size = 1333328, upload-time = "2025-09-08T23:07:45.946Z" }, { url = "https://files.pythonhosted.org/packages/bd/a0/fc7e78a23748ad5443ac3275943457e8452da67fda347e05260261108cbc/pyzmq-27.1.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:0790a0161c281ca9723f804871b4027f2e8b5a528d357c8952d08cd1a9c15581", size = 908803, upload-time = "2025-09-08T23:07:47.551Z" }, { url = "https://files.pythonhosted.org/packages/7e/22/37d15eb05f3bdfa4abea6f6d96eb3bb58585fbd3e4e0ded4e743bc650c97/pyzmq-27.1.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c895a6f35476b0c3a54e3eb6ccf41bf3018de937016e6e18748317f25d4e925f", size = 668836, upload-time = "2025-09-08T23:07:49.436Z" }, @@ -2855,11 +2445,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c4/59/a5f38970f9bf07cee96128de79590bb354917914a9be11272cfc7ff26af0/pyzmq-27.1.0-cp314-cp314t-win32.whl", hash = "sha256:1f0b2a577fd770aa6f053211a55d1c47901f4d537389a034c690291485e5fe92", size = 587472, upload-time = "2025-09-08T23:08:58.18Z" }, { url = "https://files.pythonhosted.org/packages/70/d8/78b1bad170f93fcf5e3536e70e8fadac55030002275c9a29e8f5719185de/pyzmq-27.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:19c9468ae0437f8074af379e986c5d3d7d7bfe033506af442e8c879732bedbe0", size = 661401, upload-time = "2025-09-08T23:08:59.802Z" }, { url = "https://files.pythonhosted.org/packages/81/d6/4bfbb40c9a0b42fc53c7cf442f6385db70b40f74a783130c5d0a5aa62228/pyzmq-27.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dc5dbf68a7857b59473f7df42650c621d7e8923fb03fa74a526890f4d33cc4d7", size = 575170, upload-time = "2025-09-08T23:09:01.418Z" }, - { url = "https://files.pythonhosted.org/packages/f3/81/a65e71c1552f74dec9dff91d95bafb6e0d33338a8dfefbc88aa562a20c92/pyzmq-27.1.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c17e03cbc9312bee223864f1a2b13a99522e0dc9f7c5df0177cd45210ac286e6", size = 836266, upload-time = "2025-09-08T23:09:40.048Z" }, - { url = "https://files.pythonhosted.org/packages/58/ed/0202ca350f4f2b69faa95c6d931e3c05c3a397c184cacb84cb4f8f42f287/pyzmq-27.1.0-pp310-pypy310_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:f328d01128373cb6763823b2b4e7f73bdf767834268c565151eacb3b7a392f90", size = 800206, upload-time = "2025-09-08T23:09:41.902Z" }, - { url = "https://files.pythonhosted.org/packages/47/42/1ff831fa87fe8f0a840ddb399054ca0009605d820e2b44ea43114f5459f4/pyzmq-27.1.0-pp310-pypy310_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c1790386614232e1b3a40a958454bdd42c6d1811837b15ddbb052a032a43f62", size = 567747, upload-time = "2025-09-08T23:09:43.741Z" }, - { url = "https://files.pythonhosted.org/packages/d1/db/5c4d6807434751e3f21231bee98109aa57b9b9b55e058e450d0aef59b70f/pyzmq-27.1.0-pp310-pypy310_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:448f9cb54eb0cee4732b46584f2710c8bc178b0e5371d9e4fc8125201e413a74", size = 747371, upload-time = "2025-09-08T23:09:45.575Z" }, - { url = "https://files.pythonhosted.org/packages/26/af/78ce193dbf03567eb8c0dc30e3df2b9e56f12a670bf7eb20f9fb532c7e8a/pyzmq-27.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:05b12f2d32112bf8c95ef2e74ec4f1d4beb01f8b5e703b38537f8849f92cb9ba", size = 544862, upload-time = "2025-09-08T23:09:47.448Z" }, { url = "https://files.pythonhosted.org/packages/4c/c6/c4dcdecdbaa70969ee1fdced6d7b8f60cfabe64d25361f27ac4665a70620/pyzmq-27.1.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:18770c8d3563715387139060d37859c02ce40718d1faf299abddcdcc6a649066", size = 836265, upload-time = "2025-09-08T23:09:49.376Z" }, { url = "https://files.pythonhosted.org/packages/3e/79/f38c92eeaeb03a2ccc2ba9866f0439593bb08c5e3b714ac1d553e5c96e25/pyzmq-27.1.0-pp311-pypy311_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:ac25465d42f92e990f8d8b0546b01c391ad431c3bf447683fdc40565941d0604", size = 800208, upload-time = "2025-09-08T23:09:51.073Z" }, { url = "https://files.pythonhosted.org/packages/49/0e/3f0d0d335c6b3abb9b7b723776d0b21fa7f3a6c819a0db6097059aada160/pyzmq-27.1.0-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53b40f8ae006f2734ee7608d59ed661419f087521edbfc2149c3932e9c14808c", size = 567747, upload-time = "2025-09-08T23:09:52.698Z" }, @@ -2902,20 +2487,6 @@ version = "0.27.1" source = { registry = "https://pypi.org/simple" } sdist = { url = "https://files.pythonhosted.org/packages/e9/dd/2c0cbe774744272b0ae725f44032c77bdcab6e8bcf544bffa3b6e70c8dba/rpds_py-0.27.1.tar.gz", hash = "sha256:26a1c73171d10b7acccbded82bf6a586ab8203601e565badc74bbbf8bc5a10f8", size = 27479, upload-time = "2025-08-27T12:16:36.024Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a5/ed/3aef893e2dd30e77e35d20d4ddb45ca459db59cead748cad9796ad479411/rpds_py-0.27.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:68afeec26d42ab3b47e541b272166a0b4400313946871cba3ed3a4fc0cab1cef", size = 371606, upload-time = "2025-08-27T12:12:25.189Z" }, - { url = "https://files.pythonhosted.org/packages/6d/82/9818b443e5d3eb4c83c3994561387f116aae9833b35c484474769c4a8faf/rpds_py-0.27.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74e5b2f7bb6fa38b1b10546d27acbacf2a022a8b5543efb06cfebc72a59c85be", size = 353452, upload-time = "2025-08-27T12:12:27.433Z" }, - { url = "https://files.pythonhosted.org/packages/99/c7/d2a110ffaaa397fc6793a83c7bd3545d9ab22658b7cdff05a24a4535cc45/rpds_py-0.27.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9024de74731df54546fab0bfbcdb49fae19159ecaecfc8f37c18d2c7e2c0bd61", size = 381519, upload-time = "2025-08-27T12:12:28.719Z" }, - { url = "https://files.pythonhosted.org/packages/5a/bc/e89581d1f9d1be7d0247eaef602566869fdc0d084008ba139e27e775366c/rpds_py-0.27.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:31d3ebadefcd73b73928ed0b2fd696f7fefda8629229f81929ac9c1854d0cffb", size = 394424, upload-time = "2025-08-27T12:12:30.207Z" }, - { url = "https://files.pythonhosted.org/packages/ac/2e/36a6861f797530e74bb6ed53495f8741f1ef95939eed01d761e73d559067/rpds_py-0.27.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2e7f8f169d775dd9092a1743768d771f1d1300453ddfe6325ae3ab5332b4657", size = 523467, upload-time = "2025-08-27T12:12:31.808Z" }, - { url = "https://files.pythonhosted.org/packages/c4/59/c1bc2be32564fa499f988f0a5c6505c2f4746ef96e58e4d7de5cf923d77e/rpds_py-0.27.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d905d16f77eb6ab2e324e09bfa277b4c8e5e6b8a78a3e7ff8f3cdf773b4c013", size = 402660, upload-time = "2025-08-27T12:12:33.444Z" }, - { url = "https://files.pythonhosted.org/packages/0a/ec/ef8bf895f0628dd0a59e54d81caed6891663cb9c54a0f4bb7da918cb88cf/rpds_py-0.27.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50c946f048209e6362e22576baea09193809f87687a95a8db24e5fbdb307b93a", size = 384062, upload-time = "2025-08-27T12:12:34.857Z" }, - { url = "https://files.pythonhosted.org/packages/69/f7/f47ff154be8d9a5e691c083a920bba89cef88d5247c241c10b9898f595a1/rpds_py-0.27.1-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:3deab27804d65cd8289eb814c2c0e807c4b9d9916c9225e363cb0cf875eb67c1", size = 401289, upload-time = "2025-08-27T12:12:36.085Z" }, - { url = "https://files.pythonhosted.org/packages/3b/d9/ca410363efd0615814ae579f6829cafb39225cd63e5ea5ed1404cb345293/rpds_py-0.27.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8b61097f7488de4be8244c89915da8ed212832ccf1e7c7753a25a394bf9b1f10", size = 417718, upload-time = "2025-08-27T12:12:37.401Z" }, - { url = "https://files.pythonhosted.org/packages/e3/a0/8cb5c2ff38340f221cc067cc093d1270e10658ba4e8d263df923daa18e86/rpds_py-0.27.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8a3f29aba6e2d7d90528d3c792555a93497fe6538aa65eb675b44505be747808", size = 558333, upload-time = "2025-08-27T12:12:38.672Z" }, - { url = "https://files.pythonhosted.org/packages/6f/8c/1b0de79177c5d5103843774ce12b84caa7164dfc6cd66378768d37db11bf/rpds_py-0.27.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dd6cd0485b7d347304067153a6dc1d73f7d4fd995a396ef32a24d24b8ac63ac8", size = 589127, upload-time = "2025-08-27T12:12:41.48Z" }, - { url = "https://files.pythonhosted.org/packages/c8/5e/26abb098d5e01266b0f3a2488d299d19ccc26849735d9d2b95c39397e945/rpds_py-0.27.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6f4461bf931108c9fa226ffb0e257c1b18dc2d44cd72b125bec50ee0ab1248a9", size = 554899, upload-time = "2025-08-27T12:12:42.925Z" }, - { url = "https://files.pythonhosted.org/packages/de/41/905cc90ced13550db017f8f20c6d8e8470066c5738ba480d7ba63e3d136b/rpds_py-0.27.1-cp310-cp310-win32.whl", hash = "sha256:ee5422d7fb21f6a00c1901bf6559c49fee13a5159d0288320737bbf6585bd3e4", size = 217450, upload-time = "2025-08-27T12:12:44.813Z" }, - { url = "https://files.pythonhosted.org/packages/75/3d/6bef47b0e253616ccdf67c283e25f2d16e18ccddd38f92af81d5a3420206/rpds_py-0.27.1-cp310-cp310-win_amd64.whl", hash = "sha256:3e039aabf6d5f83c745d5f9a0a381d031e9ed871967c0a5c38d201aca41f3ba1", size = 228447, upload-time = "2025-08-27T12:12:46.204Z" }, { url = "https://files.pythonhosted.org/packages/b5/c1/7907329fbef97cbd49db6f7303893bd1dd5a4a3eae415839ffdfb0762cae/rpds_py-0.27.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:be898f271f851f68b318872ce6ebebbc62f303b654e43bf72683dbdc25b7c881", size = 371063, upload-time = "2025-08-27T12:12:47.856Z" }, { url = "https://files.pythonhosted.org/packages/11/94/2aab4bc86228bcf7c48760990273653a4900de89c7537ffe1b0d6097ed39/rpds_py-0.27.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:62ac3d4e3e07b58ee0ddecd71d6ce3b1637de2d373501412df395a0ec5f9beb5", size = 353210, upload-time = "2025-08-27T12:12:49.187Z" }, { url = "https://files.pythonhosted.org/packages/3a/57/f5eb3ecf434342f4f1a46009530e93fd201a0b5b83379034ebdb1d7c1a58/rpds_py-0.27.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4708c5c0ceb2d034f9991623631d3d23cb16e65c83736ea020cdbe28d57c0a0e", size = 381636, upload-time = "2025-08-27T12:12:50.492Z" }, @@ -3004,19 +2575,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/dd/10/6b283707780a81919f71625351182b4f98932ac89a09023cb61865136244/rpds_py-0.27.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f39f58a27cc6e59f432b568ed8429c7e1641324fbe38131de852cd77b2d534b0", size = 555813, upload-time = "2025-08-27T12:15:00.334Z" }, { url = "https://files.pythonhosted.org/packages/04/2e/30b5ea18c01379da6272a92825dd7e53dc9d15c88a19e97932d35d430ef7/rpds_py-0.27.1-cp314-cp314t-win32.whl", hash = "sha256:d5fa0ee122dc09e23607a28e6d7b150da16c662e66409bbe85230e4c85bb528a", size = 217385, upload-time = "2025-08-27T12:15:01.937Z" }, { url = "https://files.pythonhosted.org/packages/32/7d/97119da51cb1dd3f2f3c0805f155a3aa4a95fa44fe7d78ae15e69edf4f34/rpds_py-0.27.1-cp314-cp314t-win_amd64.whl", hash = "sha256:6567d2bb951e21232c2f660c24cf3470bb96de56cdcb3f071a83feeaff8a2772", size = 230097, upload-time = "2025-08-27T12:15:03.961Z" }, - { url = "https://files.pythonhosted.org/packages/d5/63/b7cc415c345625d5e62f694ea356c58fb964861409008118f1245f8c3347/rpds_py-0.27.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7ba22cb9693df986033b91ae1d7a979bc399237d45fccf875b76f62bb9e52ddf", size = 371360, upload-time = "2025-08-27T12:15:29.218Z" }, - { url = "https://files.pythonhosted.org/packages/e5/8c/12e1b24b560cf378b8ffbdb9dc73abd529e1adcfcf82727dfd29c4a7b88d/rpds_py-0.27.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5b640501be9288c77738b5492b3fd3abc4ba95c50c2e41273c8a1459f08298d3", size = 353933, upload-time = "2025-08-27T12:15:30.837Z" }, - { url = "https://files.pythonhosted.org/packages/9b/85/1bb2210c1f7a1b99e91fea486b9f0f894aa5da3a5ec7097cbad7dec6d40f/rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb08b65b93e0c6dd70aac7f7890a9c0938d5ec71d5cb32d45cf844fb8ae47636", size = 382962, upload-time = "2025-08-27T12:15:32.348Z" }, - { url = "https://files.pythonhosted.org/packages/cc/c9/a839b9f219cf80ed65f27a7f5ddbb2809c1b85c966020ae2dff490e0b18e/rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d7ff07d696a7a38152ebdb8212ca9e5baab56656749f3d6004b34ab726b550b8", size = 394412, upload-time = "2025-08-27T12:15:33.839Z" }, - { url = "https://files.pythonhosted.org/packages/02/2d/b1d7f928b0b1f4fc2e0133e8051d199b01d7384875adc63b6ddadf3de7e5/rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fb7c72262deae25366e3b6c0c0ba46007967aea15d1eea746e44ddba8ec58dcc", size = 523972, upload-time = "2025-08-27T12:15:35.377Z" }, - { url = "https://files.pythonhosted.org/packages/a9/af/2cbf56edd2d07716df1aec8a726b3159deb47cb5c27e1e42b71d705a7c2f/rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7b002cab05d6339716b03a4a3a2ce26737f6231d7b523f339fa061d53368c9d8", size = 403273, upload-time = "2025-08-27T12:15:37.051Z" }, - { url = "https://files.pythonhosted.org/packages/c0/93/425e32200158d44ff01da5d9612c3b6711fe69f606f06e3895511f17473b/rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23f6b69d1c26c4704fec01311963a41d7de3ee0570a84ebde4d544e5a1859ffc", size = 385278, upload-time = "2025-08-27T12:15:38.571Z" }, - { url = "https://files.pythonhosted.org/packages/eb/1a/1a04a915ecd0551bfa9e77b7672d1937b4b72a0fc204a17deef76001cfb2/rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:530064db9146b247351f2a0250b8f00b289accea4596a033e94be2389977de71", size = 402084, upload-time = "2025-08-27T12:15:40.529Z" }, - { url = "https://files.pythonhosted.org/packages/51/f7/66585c0fe5714368b62951d2513b684e5215beaceab2c6629549ddb15036/rpds_py-0.27.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7b90b0496570bd6b0321724a330d8b545827c4df2034b6ddfc5f5275f55da2ad", size = 419041, upload-time = "2025-08-27T12:15:42.191Z" }, - { url = "https://files.pythonhosted.org/packages/8e/7e/83a508f6b8e219bba2d4af077c35ba0e0cdd35a751a3be6a7cba5a55ad71/rpds_py-0.27.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:879b0e14a2da6a1102a3fc8af580fc1ead37e6d6692a781bd8c83da37429b5ab", size = 560084, upload-time = "2025-08-27T12:15:43.839Z" }, - { url = "https://files.pythonhosted.org/packages/66/66/bb945683b958a1b19eb0fe715594630d0f36396ebdef4d9b89c2fa09aa56/rpds_py-0.27.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:0d807710df3b5faa66c731afa162ea29717ab3be17bdc15f90f2d9f183da4059", size = 590115, upload-time = "2025-08-27T12:15:46.647Z" }, - { url = "https://files.pythonhosted.org/packages/12/00/ccfaafaf7db7e7adace915e5c2f2c2410e16402561801e9c7f96683002d3/rpds_py-0.27.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:3adc388fc3afb6540aec081fa59e6e0d3908722771aa1e37ffe22b220a436f0b", size = 556561, upload-time = "2025-08-27T12:15:48.219Z" }, - { url = "https://files.pythonhosted.org/packages/e1/b7/92b6ed9aad103bfe1c45df98453dfae40969eef2cb6c6239c58d7e96f1b3/rpds_py-0.27.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c796c0c1cc68cb08b0284db4229f5af76168172670c74908fdbd4b7d7f515819", size = 229125, upload-time = "2025-08-27T12:15:49.956Z" }, { url = "https://files.pythonhosted.org/packages/0c/ed/e1fba02de17f4f76318b834425257c8ea297e415e12c68b4361f63e8ae92/rpds_py-0.27.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cdfe4bb2f9fe7458b7453ad3c33e726d6d1c7c0a72960bcc23800d77384e42df", size = 371402, upload-time = "2025-08-27T12:15:51.561Z" }, { url = "https://files.pythonhosted.org/packages/af/7c/e16b959b316048b55585a697e94add55a4ae0d984434d279ea83442e460d/rpds_py-0.27.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:8fabb8fd848a5f75a2324e4a84501ee3a5e3c78d8603f83475441866e60b94a3", size = 354084, upload-time = "2025-08-27T12:15:53.219Z" }, { url = "https://files.pythonhosted.org/packages/de/c1/ade645f55de76799fdd08682d51ae6724cb46f318573f18be49b1e040428/rpds_py-0.27.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eda8719d598f2f7f3e0f885cba8646644b55a187762bec091fa14a2b819746a9", size = 383090, upload-time = "2025-08-27T12:15:55.158Z" }, @@ -3062,19 +2620,12 @@ version = "1.7.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "joblib" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, - { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "scipy", version = "1.16.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "numpy" }, + { name = "scipy" }, { name = "threadpoolctl" }, ] sdist = { url = "https://files.pythonhosted.org/packages/98/c2/a7855e41c9d285dfe86dc50b250978105dce513d6e459ea66a6aeb0e1e0c/scikit_learn-1.7.2.tar.gz", hash = "sha256:20e9e49ecd130598f1ca38a1d85090e1a600147b9c02fa6f15d69cb53d968fda", size = 7193136, upload-time = "2025-09-09T08:21:29.075Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ba/3e/daed796fd69cce768b8788401cc464ea90b306fb196ae1ffed0b98182859/scikit_learn-1.7.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b33579c10a3081d076ab403df4a4190da4f4432d443521674637677dc91e61f", size = 9336221, upload-time = "2025-09-09T08:20:19.328Z" }, - { url = "https://files.pythonhosted.org/packages/1c/ce/af9d99533b24c55ff4e18d9b7b4d9919bbc6cd8f22fe7a7be01519a347d5/scikit_learn-1.7.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:36749fb62b3d961b1ce4fedf08fa57a1986cd409eff2d783bca5d4b9b5fce51c", size = 8653834, upload-time = "2025-09-09T08:20:22.073Z" }, - { url = "https://files.pythonhosted.org/packages/58/0e/8c2a03d518fb6bd0b6b0d4b114c63d5f1db01ff0f9925d8eb10960d01c01/scikit_learn-1.7.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7a58814265dfc52b3295b1900cfb5701589d30a8bb026c7540f1e9d3499d5ec8", size = 9660938, upload-time = "2025-09-09T08:20:24.327Z" }, - { url = "https://files.pythonhosted.org/packages/2b/75/4311605069b5d220e7cf5adabb38535bd96f0079313cdbb04b291479b22a/scikit_learn-1.7.2-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a847fea807e278f821a0406ca01e387f97653e284ecbd9750e3ee7c90347f18", size = 9477818, upload-time = "2025-09-09T08:20:26.845Z" }, - { url = "https://files.pythonhosted.org/packages/7f/9b/87961813c34adbca21a6b3f6b2bea344c43b30217a6d24cc437c6147f3e8/scikit_learn-1.7.2-cp310-cp310-win_amd64.whl", hash = "sha256:ca250e6836d10e6f402436d6463d6c0e4d8e0234cfb6a9a47835bd392b852ce5", size = 8886969, upload-time = "2025-09-09T08:20:29.329Z" }, { url = "https://files.pythonhosted.org/packages/43/83/564e141eef908a5863a54da8ca342a137f45a0bfb71d1d79704c9894c9d1/scikit_learn-1.7.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7509693451651cd7361d30ce4e86a1347493554f172b1c72a39300fa2aea79e", size = 9331967, upload-time = "2025-09-09T08:20:32.421Z" }, { url = "https://files.pythonhosted.org/packages/18/d6/ba863a4171ac9d7314c4d3fc251f015704a2caeee41ced89f321c049ed83/scikit_learn-1.7.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:0486c8f827c2e7b64837c731c8feff72c0bd2b998067a8a9cbc10643c31f0fe1", size = 8648645, upload-time = "2025-09-09T08:20:34.436Z" }, { url = "https://files.pythonhosted.org/packages/ef/0e/97dbca66347b8cf0ea8b529e6bb9367e337ba2e8be0ef5c1a545232abfde/scikit_learn-1.7.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:89877e19a80c7b11a2891a27c21c4894fb18e2c2e077815bcade10d34287b20d", size = 9715424, upload-time = "2025-09-09T08:20:36.776Z" }, @@ -3102,76 +2653,12 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8e/87/24f541b6d62b1794939ae6422f8023703bbf6900378b2b34e0b4384dfefd/scikit_learn-1.7.2-cp314-cp314-win_amd64.whl", hash = "sha256:bb24510ed3f9f61476181e4db51ce801e2ba37541def12dc9333b946fc7a9cf8", size = 8820007, upload-time = "2025-09-09T08:21:26.713Z" }, ] -[[package]] -name = "scipy" -version = "1.15.3" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.11'", -] -dependencies = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" } }, -] -sdist = { url = "https://files.pythonhosted.org/packages/0f/37/6964b830433e654ec7485e45a00fc9a27cf868d622838f6b6d9c5ec0d532/scipy-1.15.3.tar.gz", hash = "sha256:eae3cf522bc7df64b42cad3925c876e1b0b6c35c1337c93e12c0f366f55b0eaf", size = 59419214, upload-time = "2025-05-08T16:13:05.955Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/78/2f/4966032c5f8cc7e6a60f1b2e0ad686293b9474b65246b0c642e3ef3badd0/scipy-1.15.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:a345928c86d535060c9c2b25e71e87c39ab2f22fc96e9636bd74d1dbf9de448c", size = 38702770, upload-time = "2025-05-08T16:04:20.849Z" }, - { url = "https://files.pythonhosted.org/packages/a0/6e/0c3bf90fae0e910c274db43304ebe25a6b391327f3f10b5dcc638c090795/scipy-1.15.3-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:ad3432cb0f9ed87477a8d97f03b763fd1d57709f1bbde3c9369b1dff5503b253", size = 30094511, upload-time = "2025-05-08T16:04:27.103Z" }, - { url = "https://files.pythonhosted.org/packages/ea/b1/4deb37252311c1acff7f101f6453f0440794f51b6eacb1aad4459a134081/scipy-1.15.3-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:aef683a9ae6eb00728a542b796f52a5477b78252edede72b8327a886ab63293f", size = 22368151, upload-time = "2025-05-08T16:04:31.731Z" }, - { url = "https://files.pythonhosted.org/packages/38/7d/f457626e3cd3c29b3a49ca115a304cebb8cc6f31b04678f03b216899d3c6/scipy-1.15.3-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:1c832e1bd78dea67d5c16f786681b28dd695a8cb1fb90af2e27580d3d0967e92", size = 25121732, upload-time = "2025-05-08T16:04:36.596Z" }, - { url = "https://files.pythonhosted.org/packages/db/0a/92b1de4a7adc7a15dcf5bddc6e191f6f29ee663b30511ce20467ef9b82e4/scipy-1.15.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:263961f658ce2165bbd7b99fa5135195c3a12d9bef045345016b8b50c315cb82", size = 35547617, upload-time = "2025-05-08T16:04:43.546Z" }, - { url = "https://files.pythonhosted.org/packages/8e/6d/41991e503e51fc1134502694c5fa7a1671501a17ffa12716a4a9151af3df/scipy-1.15.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e2abc762b0811e09a0d3258abee2d98e0c703eee49464ce0069590846f31d40", size = 37662964, upload-time = "2025-05-08T16:04:49.431Z" }, - { url = "https://files.pythonhosted.org/packages/25/e1/3df8f83cb15f3500478c889be8fb18700813b95e9e087328230b98d547ff/scipy-1.15.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ed7284b21a7a0c8f1b6e5977ac05396c0d008b89e05498c8b7e8f4a1423bba0e", size = 37238749, upload-time = "2025-05-08T16:04:55.215Z" }, - { url = "https://files.pythonhosted.org/packages/93/3e/b3257cf446f2a3533ed7809757039016b74cd6f38271de91682aa844cfc5/scipy-1.15.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5380741e53df2c566f4d234b100a484b420af85deb39ea35a1cc1be84ff53a5c", size = 40022383, upload-time = "2025-05-08T16:05:01.914Z" }, - { url = "https://files.pythonhosted.org/packages/d1/84/55bc4881973d3f79b479a5a2e2df61c8c9a04fcb986a213ac9c02cfb659b/scipy-1.15.3-cp310-cp310-win_amd64.whl", hash = "sha256:9d61e97b186a57350f6d6fd72640f9e99d5a4a2b8fbf4b9ee9a841eab327dc13", size = 41259201, upload-time = "2025-05-08T16:05:08.166Z" }, - { url = "https://files.pythonhosted.org/packages/96/ab/5cc9f80f28f6a7dff646c5756e559823614a42b1939d86dd0ed550470210/scipy-1.15.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:993439ce220d25e3696d1b23b233dd010169b62f6456488567e830654ee37a6b", size = 38714255, upload-time = "2025-05-08T16:05:14.596Z" }, - { url = "https://files.pythonhosted.org/packages/4a/4a/66ba30abe5ad1a3ad15bfb0b59d22174012e8056ff448cb1644deccbfed2/scipy-1.15.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:34716e281f181a02341ddeaad584205bd2fd3c242063bd3423d61ac259ca7eba", size = 30111035, upload-time = "2025-05-08T16:05:20.152Z" }, - { url = "https://files.pythonhosted.org/packages/4b/fa/a7e5b95afd80d24313307f03624acc65801846fa75599034f8ceb9e2cbf6/scipy-1.15.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3b0334816afb8b91dab859281b1b9786934392aa3d527cd847e41bb6f45bee65", size = 22384499, upload-time = "2025-05-08T16:05:24.494Z" }, - { url = "https://files.pythonhosted.org/packages/17/99/f3aaddccf3588bb4aea70ba35328c204cadd89517a1612ecfda5b2dd9d7a/scipy-1.15.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:6db907c7368e3092e24919b5e31c76998b0ce1684d51a90943cb0ed1b4ffd6c1", size = 25152602, upload-time = "2025-05-08T16:05:29.313Z" }, - { url = "https://files.pythonhosted.org/packages/56/c5/1032cdb565f146109212153339f9cb8b993701e9fe56b1c97699eee12586/scipy-1.15.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:721d6b4ef5dc82ca8968c25b111e307083d7ca9091bc38163fb89243e85e3889", size = 35503415, upload-time = "2025-05-08T16:05:34.699Z" }, - { url = "https://files.pythonhosted.org/packages/bd/37/89f19c8c05505d0601ed5650156e50eb881ae3918786c8fd7262b4ee66d3/scipy-1.15.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39cb9c62e471b1bb3750066ecc3a3f3052b37751c7c3dfd0fd7e48900ed52982", size = 37652622, upload-time = "2025-05-08T16:05:40.762Z" }, - { url = "https://files.pythonhosted.org/packages/7e/31/be59513aa9695519b18e1851bb9e487de66f2d31f835201f1b42f5d4d475/scipy-1.15.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:795c46999bae845966368a3c013e0e00947932d68e235702b5c3f6ea799aa8c9", size = 37244796, upload-time = "2025-05-08T16:05:48.119Z" }, - { url = "https://files.pythonhosted.org/packages/10/c0/4f5f3eeccc235632aab79b27a74a9130c6c35df358129f7ac8b29f562ac7/scipy-1.15.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:18aaacb735ab38b38db42cb01f6b92a2d0d4b6aabefeb07f02849e47f8fb3594", size = 40047684, upload-time = "2025-05-08T16:05:54.22Z" }, - { url = "https://files.pythonhosted.org/packages/ab/a7/0ddaf514ce8a8714f6ed243a2b391b41dbb65251affe21ee3077ec45ea9a/scipy-1.15.3-cp311-cp311-win_amd64.whl", hash = "sha256:ae48a786a28412d744c62fd7816a4118ef97e5be0bee968ce8f0a2fba7acf3bb", size = 41246504, upload-time = "2025-05-08T16:06:00.437Z" }, - { url = "https://files.pythonhosted.org/packages/37/4b/683aa044c4162e10ed7a7ea30527f2cbd92e6999c10a8ed8edb253836e9c/scipy-1.15.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6ac6310fdbfb7aa6612408bd2f07295bcbd3fda00d2d702178434751fe48e019", size = 38766735, upload-time = "2025-05-08T16:06:06.471Z" }, - { url = "https://files.pythonhosted.org/packages/7b/7e/f30be3d03de07f25dc0ec926d1681fed5c732d759ac8f51079708c79e680/scipy-1.15.3-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:185cd3d6d05ca4b44a8f1595af87f9c372bb6acf9c808e99aa3e9aa03bd98cf6", size = 30173284, upload-time = "2025-05-08T16:06:11.686Z" }, - { url = "https://files.pythonhosted.org/packages/07/9c/0ddb0d0abdabe0d181c1793db51f02cd59e4901da6f9f7848e1f96759f0d/scipy-1.15.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:05dc6abcd105e1a29f95eada46d4a3f251743cfd7d3ae8ddb4088047f24ea477", size = 22446958, upload-time = "2025-05-08T16:06:15.97Z" }, - { url = "https://files.pythonhosted.org/packages/af/43/0bce905a965f36c58ff80d8bea33f1f9351b05fad4beaad4eae34699b7a1/scipy-1.15.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:06efcba926324df1696931a57a176c80848ccd67ce6ad020c810736bfd58eb1c", size = 25242454, upload-time = "2025-05-08T16:06:20.394Z" }, - { url = "https://files.pythonhosted.org/packages/56/30/a6f08f84ee5b7b28b4c597aca4cbe545535c39fe911845a96414700b64ba/scipy-1.15.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c05045d8b9bfd807ee1b9f38761993297b10b245f012b11b13b91ba8945f7e45", size = 35210199, upload-time = "2025-05-08T16:06:26.159Z" }, - { url = "https://files.pythonhosted.org/packages/0b/1f/03f52c282437a168ee2c7c14a1a0d0781a9a4a8962d84ac05c06b4c5b555/scipy-1.15.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:271e3713e645149ea5ea3e97b57fdab61ce61333f97cfae392c28ba786f9bb49", size = 37309455, upload-time = "2025-05-08T16:06:32.778Z" }, - { url = "https://files.pythonhosted.org/packages/89/b1/fbb53137f42c4bf630b1ffdfc2151a62d1d1b903b249f030d2b1c0280af8/scipy-1.15.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6cfd56fc1a8e53f6e89ba3a7a7251f7396412d655bca2aa5611c8ec9a6784a1e", size = 36885140, upload-time = "2025-05-08T16:06:39.249Z" }, - { url = "https://files.pythonhosted.org/packages/2e/2e/025e39e339f5090df1ff266d021892694dbb7e63568edcfe43f892fa381d/scipy-1.15.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0ff17c0bb1cb32952c09217d8d1eed9b53d1463e5f1dd6052c7857f83127d539", size = 39710549, upload-time = "2025-05-08T16:06:45.729Z" }, - { url = "https://files.pythonhosted.org/packages/e6/eb/3bf6ea8ab7f1503dca3a10df2e4b9c3f6b3316df07f6c0ded94b281c7101/scipy-1.15.3-cp312-cp312-win_amd64.whl", hash = "sha256:52092bc0472cfd17df49ff17e70624345efece4e1a12b23783a1ac59a1b728ed", size = 40966184, upload-time = "2025-05-08T16:06:52.623Z" }, - { url = "https://files.pythonhosted.org/packages/73/18/ec27848c9baae6e0d6573eda6e01a602e5649ee72c27c3a8aad673ebecfd/scipy-1.15.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2c620736bcc334782e24d173c0fdbb7590a0a436d2fdf39310a8902505008759", size = 38728256, upload-time = "2025-05-08T16:06:58.696Z" }, - { url = "https://files.pythonhosted.org/packages/74/cd/1aef2184948728b4b6e21267d53b3339762c285a46a274ebb7863c9e4742/scipy-1.15.3-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:7e11270a000969409d37ed399585ee530b9ef6aa99d50c019de4cb01e8e54e62", size = 30109540, upload-time = "2025-05-08T16:07:04.209Z" }, - { url = "https://files.pythonhosted.org/packages/5b/d8/59e452c0a255ec352bd0a833537a3bc1bfb679944c4938ab375b0a6b3a3e/scipy-1.15.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:8c9ed3ba2c8a2ce098163a9bdb26f891746d02136995df25227a20e71c396ebb", size = 22383115, upload-time = "2025-05-08T16:07:08.998Z" }, - { url = "https://files.pythonhosted.org/packages/08/f5/456f56bbbfccf696263b47095291040655e3cbaf05d063bdc7c7517f32ac/scipy-1.15.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:0bdd905264c0c9cfa74a4772cdb2070171790381a5c4d312c973382fc6eaf730", size = 25163884, upload-time = "2025-05-08T16:07:14.091Z" }, - { url = "https://files.pythonhosted.org/packages/a2/66/a9618b6a435a0f0c0b8a6d0a2efb32d4ec5a85f023c2b79d39512040355b/scipy-1.15.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79167bba085c31f38603e11a267d862957cbb3ce018d8b38f79ac043bc92d825", size = 35174018, upload-time = "2025-05-08T16:07:19.427Z" }, - { url = "https://files.pythonhosted.org/packages/b5/09/c5b6734a50ad4882432b6bb7c02baf757f5b2f256041da5df242e2d7e6b6/scipy-1.15.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9deabd6d547aee2c9a81dee6cc96c6d7e9a9b1953f74850c179f91fdc729cb7", size = 37269716, upload-time = "2025-05-08T16:07:25.712Z" }, - { url = "https://files.pythonhosted.org/packages/77/0a/eac00ff741f23bcabd352731ed9b8995a0a60ef57f5fd788d611d43d69a1/scipy-1.15.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dde4fc32993071ac0c7dd2d82569e544f0bdaff66269cb475e0f369adad13f11", size = 36872342, upload-time = "2025-05-08T16:07:31.468Z" }, - { url = "https://files.pythonhosted.org/packages/fe/54/4379be86dd74b6ad81551689107360d9a3e18f24d20767a2d5b9253a3f0a/scipy-1.15.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f77f853d584e72e874d87357ad70f44b437331507d1c311457bed8ed2b956126", size = 39670869, upload-time = "2025-05-08T16:07:38.002Z" }, - { url = "https://files.pythonhosted.org/packages/87/2e/892ad2862ba54f084ffe8cc4a22667eaf9c2bcec6d2bff1d15713c6c0703/scipy-1.15.3-cp313-cp313-win_amd64.whl", hash = "sha256:b90ab29d0c37ec9bf55424c064312930ca5f4bde15ee8619ee44e69319aab163", size = 40988851, upload-time = "2025-05-08T16:08:33.671Z" }, - { url = "https://files.pythonhosted.org/packages/1b/e9/7a879c137f7e55b30d75d90ce3eb468197646bc7b443ac036ae3fe109055/scipy-1.15.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3ac07623267feb3ae308487c260ac684b32ea35fd81e12845039952f558047b8", size = 38863011, upload-time = "2025-05-08T16:07:44.039Z" }, - { url = "https://files.pythonhosted.org/packages/51/d1/226a806bbd69f62ce5ef5f3ffadc35286e9fbc802f606a07eb83bf2359de/scipy-1.15.3-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:6487aa99c2a3d509a5227d9a5e889ff05830a06b2ce08ec30df6d79db5fcd5c5", size = 30266407, upload-time = "2025-05-08T16:07:49.891Z" }, - { url = "https://files.pythonhosted.org/packages/e5/9b/f32d1d6093ab9eeabbd839b0f7619c62e46cc4b7b6dbf05b6e615bbd4400/scipy-1.15.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:50f9e62461c95d933d5c5ef4a1f2ebf9a2b4e83b0db374cb3f1de104d935922e", size = 22540030, upload-time = "2025-05-08T16:07:54.121Z" }, - { url = "https://files.pythonhosted.org/packages/e7/29/c278f699b095c1a884f29fda126340fcc201461ee8bfea5c8bdb1c7c958b/scipy-1.15.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:14ed70039d182f411ffc74789a16df3835e05dc469b898233a245cdfd7f162cb", size = 25218709, upload-time = "2025-05-08T16:07:58.506Z" }, - { url = "https://files.pythonhosted.org/packages/24/18/9e5374b617aba742a990581373cd6b68a2945d65cc588482749ef2e64467/scipy-1.15.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a769105537aa07a69468a0eefcd121be52006db61cdd8cac8a0e68980bbb723", size = 34809045, upload-time = "2025-05-08T16:08:03.929Z" }, - { url = "https://files.pythonhosted.org/packages/e1/fe/9c4361e7ba2927074360856db6135ef4904d505e9b3afbbcb073c4008328/scipy-1.15.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9db984639887e3dffb3928d118145ffe40eff2fa40cb241a306ec57c219ebbbb", size = 36703062, upload-time = "2025-05-08T16:08:09.558Z" }, - { url = "https://files.pythonhosted.org/packages/b7/8e/038ccfe29d272b30086b25a4960f757f97122cb2ec42e62b460d02fe98e9/scipy-1.15.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:40e54d5c7e7ebf1aa596c374c49fa3135f04648a0caabcb66c52884b943f02b4", size = 36393132, upload-time = "2025-05-08T16:08:15.34Z" }, - { url = "https://files.pythonhosted.org/packages/10/7e/5c12285452970be5bdbe8352c619250b97ebf7917d7a9a9e96b8a8140f17/scipy-1.15.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5e721fed53187e71d0ccf382b6bf977644c533e506c4d33c3fb24de89f5c3ed5", size = 38979503, upload-time = "2025-05-08T16:08:21.513Z" }, - { url = "https://files.pythonhosted.org/packages/81/06/0a5e5349474e1cbc5757975b21bd4fad0e72ebf138c5592f191646154e06/scipy-1.15.3-cp313-cp313t-win_amd64.whl", hash = "sha256:76ad1fb5f8752eabf0fa02e4cc0336b4e8f021e2d5f061ed37d6d264db35e3ca", size = 40308097, upload-time = "2025-05-08T16:08:27.627Z" }, -] - [[package]] name = "scipy" version = "1.16.2" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.12' and python_full_version < '3.14'", - "python_full_version == '3.11.*'", -] dependencies = [ - { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" } }, + { name = "numpy" }, ] sdist = { url = "https://files.pythonhosted.org/packages/4c/3b/546a6f0bfe791bbb7f8d591613454d15097e53f906308ec6f7c1ce588e8e/scipy-1.16.2.tar.gz", hash = "sha256:af029b153d243a80afb6eabe40b0a07f8e35c9adc269c019f364ad747f826a6b", size = 30580599, upload-time = "2025-09-11T17:48:08.271Z" } wheels = [ @@ -3275,16 +2762,15 @@ wheels = [ [[package]] name = "sparse" -version = "0.17.0" +version = "0.19.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numba" }, - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "numpy" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/63/74/5c674277fc3d61bd1863d233a8e1f7ddf35cb1adeeaf9973888629e7a9b1/sparse-0.17.0.tar.gz", hash = "sha256:6b1ad51a810c5be40b6f95e28513ec810fe1c785923bd83b2e4839a751df4bf7", size = 642387, upload-time = "2025-05-20T08:17:03.256Z" } +sdist = { url = "https://files.pythonhosted.org/packages/86/9f/2cd5f071ce00083f74af90ae2c083393ef3e91ecd78f0f24887871473dd4/sparse-0.19.2.tar.gz", hash = "sha256:0d41a7c3f477cb4265d7193bcf12b0146674d6533ff328afa1e1d0f2b8480f00", size = 814045, upload-time = "2026-08-14T09:37:27.288Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8d/fd/42a1720542199ae6ff0f9c37bbd55dd3033ddd7bbe00d68cde09d6824887/sparse-0.17.0-py2.py3-none-any.whl", hash = "sha256:1922d1d97f692b1061c4f03a1dd6ee21850aedc88e171aa845715f5069952f18", size = 259370, upload-time = "2025-05-20T08:17:00.874Z" }, + { url = "https://files.pythonhosted.org/packages/09/4e/23e0009b6d5d415c223ea38fcf1e38dc9b0fc6d3ff15b5c5090dcc1f6d88/sparse-0.19.2-py2.py3-none-any.whl", hash = "sha256:2fcad7b83dacb5c70123a7de76db3626cbdaf567fcf12bdbf637aca6c4ee1bbe", size = 155257, upload-time = "2026-08-14T09:37:25.64Z" }, ] [[package]] @@ -3308,40 +2794,18 @@ dependencies = [ { name = "sphinxcontrib-jsmath" }, { name = "sphinxcontrib-qthelp" }, { name = "sphinxcontrib-serializinghtml" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/5b/be/50e50cb4f2eff47df05673d361095cafd95521d2a22521b920c67a372dcb/sphinx-7.4.7.tar.gz", hash = "sha256:242f92a7ea7e6c5b406fdc2615413890ba9f699114a9c09192d7dfead2ee9cfe", size = 8067911, upload-time = "2024-07-20T14:46:56.059Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/0d/ef/153f6803c5d5f8917dbb7f7fcf6d34a871ede3296fa89c2c703f5f8a6c8e/sphinx-7.4.7-py3-none-any.whl", hash = "sha256:c2419e2135d11f1951cd994d6eb18a1835bd8fdd8429f9ca375dc1f3281bd239", size = 3401624, upload-time = "2024-07-20T14:46:52.142Z" }, ] -[[package]] -name = "sphinx-book-theme" -version = "1.1.4" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.11'", -] -dependencies = [ - { name = "pydata-sphinx-theme", version = "0.15.4", source = { registry = "https://pypi.org/simple" } }, - { name = "sphinx" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/45/19/d002ed96bdc7738c15847c730e1e88282d738263deac705d5713b4d8fa94/sphinx_book_theme-1.1.4.tar.gz", hash = "sha256:73efe28af871d0a89bd05856d300e61edce0d5b2fbb7984e84454be0fedfe9ed", size = 439188, upload-time = "2025-02-20T16:32:32.581Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/51/9e/c41d68be04eef5b6202b468e0f90faf0c469f3a03353f2a218fd78279710/sphinx_book_theme-1.1.4-py3-none-any.whl", hash = "sha256:843b3f5c8684640f4a2d01abd298beb66452d1b2394cd9ef5be5ebd5640ea0e1", size = 433952, upload-time = "2025-02-20T16:32:31.009Z" }, -] - [[package]] name = "sphinx-book-theme" version = "1.2.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version >= '3.12' and python_full_version < '3.14'", - "python_full_version == '3.11.*'", -] dependencies = [ - { name = "pydata-sphinx-theme", version = "0.16.1", source = { registry = "https://pypi.org/simple" } }, + { name = "pydata-sphinx-theme" }, { name = "sphinx" }, ] sdist = { url = "https://files.pythonhosted.org/packages/eb/f7/154786f3cfb7692cd7acc24b6dfe4dcd1146b66f376b17df9e47125555e9/sphinx_book_theme-1.2.0.tar.gz", hash = "sha256:4a7ebfc7da4395309ac942ddfc38fbec5c5254c3be22195e99ad12586fbda9e3", size = 443962, upload-time = "2026-03-09T23:20:30.442Z" } @@ -3556,14 +3020,6 @@ dependencies = [ ] sdist = { url = "https://files.pythonhosted.org/packages/d7/bc/d59b5d97d27229b0e009bd9098cd81af71c2fa5549c580a0a67b9bed0496/sqlalchemy-2.0.43.tar.gz", hash = "sha256:788bfcef6787a7764169cfe9859fe425bf44559619e1d9f56f5bddf2ebf6f417", size = 9762949, upload-time = "2025-08-11T14:24:58.438Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8f/4e/985f7da36f09592c5ade99321c72c15101d23c0bb7eecfd1daaca5714422/sqlalchemy-2.0.43-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:70322986c0c699dca241418fcf18e637a4369e0ec50540a2b907b184c8bca069", size = 2133162, upload-time = "2025-08-11T15:52:17.854Z" }, - { url = "https://files.pythonhosted.org/packages/37/34/798af8db3cae069461e3bc0898a1610dc469386a97048471d364dc8aae1c/sqlalchemy-2.0.43-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:87accdbba88f33efa7b592dc2e8b2a9c2cdbca73db2f9d5c510790428c09c154", size = 2123082, upload-time = "2025-08-11T15:52:19.181Z" }, - { url = "https://files.pythonhosted.org/packages/fb/0f/79cf4d9dad42f61ec5af1e022c92f66c2d110b93bb1dc9b033892971abfa/sqlalchemy-2.0.43-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c00e7845d2f692ebfc7d5e4ec1a3fd87698e4337d09e58d6749a16aedfdf8612", size = 3208871, upload-time = "2025-08-11T15:50:30.656Z" }, - { url = "https://files.pythonhosted.org/packages/56/b3/59befa58fb0e1a9802c87df02344548e6d007e77e87e6084e2131c29e033/sqlalchemy-2.0.43-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:022e436a1cb39b13756cf93b48ecce7aa95382b9cfacceb80a7d263129dfd019", size = 3209583, upload-time = "2025-08-11T15:57:47.697Z" }, - { url = "https://files.pythonhosted.org/packages/29/d2/124b50c0eb8146e8f0fe16d01026c1a073844f0b454436d8544fe9b33bd7/sqlalchemy-2.0.43-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c5e73ba0d76eefc82ec0219d2301cb33bfe5205ed7a2602523111e2e56ccbd20", size = 3148177, upload-time = "2025-08-11T15:50:32.078Z" }, - { url = "https://files.pythonhosted.org/packages/83/f5/e369cd46aa84278107624617034a5825fedfc5c958b2836310ced4d2eadf/sqlalchemy-2.0.43-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9c2e02f06c68092b875d5cbe4824238ab93a7fa35d9c38052c033f7ca45daa18", size = 3172276, upload-time = "2025-08-11T15:57:49.477Z" }, - { url = "https://files.pythonhosted.org/packages/de/2b/4602bf4c3477fa4c837c9774e6dd22e0389fc52310c4c4dfb7e7ba05e90d/sqlalchemy-2.0.43-cp310-cp310-win32.whl", hash = "sha256:e7a903b5b45b0d9fa03ac6a331e1c1d6b7e0ab41c63b6217b3d10357b83c8b00", size = 2101491, upload-time = "2025-08-11T15:54:59.191Z" }, - { url = "https://files.pythonhosted.org/packages/38/2d/bfc6b6143adef553a08295490ddc52607ee435b9c751c714620c1b3dd44d/sqlalchemy-2.0.43-cp310-cp310-win_amd64.whl", hash = "sha256:4bf0edb24c128b7be0c61cd17eef432e4bef507013292415f3fb7023f02b7d4b", size = 2125148, upload-time = "2025-08-11T15:55:00.593Z" }, { url = "https://files.pythonhosted.org/packages/9d/77/fa7189fe44114658002566c6fe443d3ed0ec1fa782feb72af6ef7fbe98e7/sqlalchemy-2.0.43-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:52d9b73b8fb3e9da34c2b31e6d99d60f5f99fd8c1225c9dad24aeb74a91e1d29", size = 2136472, upload-time = "2025-08-11T15:52:21.789Z" }, { url = "https://files.pythonhosted.org/packages/99/ea/92ac27f2fbc2e6c1766bb807084ca455265707e041ba027c09c17d697867/sqlalchemy-2.0.43-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f42f23e152e4545157fa367b2435a1ace7571cab016ca26038867eb7df2c3631", size = 2126535, upload-time = "2025-08-11T15:52:23.109Z" }, { url = "https://files.pythonhosted.org/packages/94/12/536ede80163e295dc57fff69724caf68f91bb40578b6ac6583a293534849/sqlalchemy-2.0.43-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4fb1a8c5438e0c5ea51afe9c6564f951525795cf432bed0c028c1cb081276685", size = 3297521, upload-time = "2025-08-11T15:50:33.536Z" }, @@ -3610,22 +3066,14 @@ name = "statsmodels" version = "0.14.6" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "numpy", version = "2.2.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "numpy", version = "2.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "numpy" }, { name = "packaging" }, { name = "pandas" }, { name = "patsy" }, - { name = "scipy", version = "1.15.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, - { name = "scipy", version = "1.16.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "scipy" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0d/81/e8d74b34f85285f7335d30c5e3c2d7c0346997af9f3debf9a0a9a63de184/statsmodels-0.14.6.tar.gz", hash = "sha256:4d17873d3e607d398b85126cd4ed7aad89e4e9d89fc744cdab1af3189a996c2a", size = 20689085, upload-time = "2025-12-05T23:08:39.522Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b5/6d/9ec309a175956f88eb8420ac564297f37cf9b1f73f89db74da861052dc29/statsmodels-0.14.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f4ff0649a2df674c7ffb6fa1a06bffdb82a6adf09a48e90e000a15a6aaa734b0", size = 10142419, upload-time = "2025-12-05T19:27:35.625Z" }, - { url = "https://files.pythonhosted.org/packages/86/8f/338c5568315ec5bf3ac7cd4b71e34b98cb3b0f834919c0c04a0762f878a1/statsmodels-0.14.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:109012088b3e370080846ab053c76d125268631410142daad2f8c10770e8e8d9", size = 10022819, upload-time = "2025-12-05T19:27:49.385Z" }, - { url = "https://files.pythonhosted.org/packages/b0/77/5fc4cbc2d608f9b483b0675f82704a8bcd672962c379fe4d82100d388dbf/statsmodels-0.14.6-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e93bd5d220f3cb6fc5fc1bffd5b094966cab8ee99f6c57c02e95710513d6ac3f", size = 10118927, upload-time = "2025-12-05T23:07:51.256Z" }, - { url = "https://files.pythonhosted.org/packages/94/55/b86c861c32186403fe121d9ab27bc16d05839b170d92a978beb33abb995e/statsmodels-0.14.6-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:06eec42d682fdb09fe5d70a05930857efb141754ec5a5056a03304c1b5e32fd9", size = 10413015, upload-time = "2025-12-05T23:08:53.95Z" }, - { url = "https://files.pythonhosted.org/packages/f9/be/daf0dba729ccdc4176605f4a0fd5cfe71cdda671749dca10e74a732b8b1c/statsmodels-0.14.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0444e88557df735eda7db330806fe09d51c9f888bb1f5906cb3a61fb1a3ed4a8", size = 10441248, upload-time = "2025-12-05T23:09:09.353Z" }, - { url = "https://files.pythonhosted.org/packages/9a/1c/2e10b7c7cc44fa418272996bf0427b8016718fd62f995d9c1f7ab37adf35/statsmodels-0.14.6-cp310-cp310-win_amd64.whl", hash = "sha256:e83a9abe653835da3b37fb6ae04b45480c1de11b3134bd40b09717192a1456ea", size = 9583410, upload-time = "2025-12-05T19:28:02.086Z" }, { url = "https://files.pythonhosted.org/packages/a9/4d/df4dd089b406accfc3bb5ee53ba29bb3bdf5ae61643f86f8f604baa57656/statsmodels-0.14.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6ad5c2810fc6c684254a7792bf1cbaf1606cdee2a253f8bd259c43135d87cfb4", size = 10121514, upload-time = "2025-12-05T19:28:16.521Z" }, { url = "https://files.pythonhosted.org/packages/82/af/ec48daa7f861f993b91a0dcc791d66e1cf56510a235c5cbd2ab991a31d5c/statsmodels-0.14.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:341fa68a7403e10a95c7b6e41134b0da3a7b835ecff1eb266294408535a06eb6", size = 10003346, upload-time = "2025-12-05T19:28:29.568Z" }, { url = "https://files.pythonhosted.org/packages/a9/2c/c8f7aa24cd729970728f3f98822fb45149adc216f445a9301e441f7ac760/statsmodels-0.14.6-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bdf1dfe2a3ca56f5529118baf33a13efed2783c528f4a36409b46bbd2d9d48eb", size = 10129872, upload-time = "2025-12-05T23:09:25.724Z" }, @@ -3801,7 +3249,6 @@ dependencies = [ { name = "filelock" }, { name = "platformdirs" }, { name = "python-discovery" }, - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ea/fa/18004e5cb15541ad2a68ff219c755233b012b12d4ec8663d06a258082bec/virtualenv-21.7.1.tar.gz", hash = "sha256:d0dbfaa5483487baea28d7210ef8d24c9d1bd0f10f449eeb215568825a9b334e", size = 5525237, upload-time = "2026-07-30T15:40:36.36Z" } wheels = [ From 2dda08391d3d73b2fb16218595fafcb6ff25427a Mon Sep 17 00:00:00 2001 From: Gene Dan Date: Sat, 19 Sep 2026 16:10:55 -0500 Subject: [PATCH 19/20] [DOCS] Move precision example to tutorial. --- chainladder/core/style.py | 25 +--- chainladder/core/tests/test_style.py | 15 +++ docs/user_guide/style.ipynb | 169 +++++++++++++++++++++++++++ 3 files changed, 188 insertions(+), 21 deletions(-) diff --git a/chainladder/core/style.py b/chainladder/core/style.py index 473838cc9..e0cd60782 100644 --- a/chainladder/core/style.py +++ b/chainladder/core/style.py @@ -59,7 +59,7 @@ class Styler(_PandasStyler): If ``triangle`` is anything other than a Triangle. ValueError If ``triangle`` is multidimensional, i.e. holds more than a single index - and column. + and column, or if it is empty, i.e. holds no values to style. Examples -------- @@ -67,23 +67,9 @@ class Styler(_PandasStyler): .. testcode:: import chainladder as cl - from chainladder.core.style import Styler raa = cl.load_sample("raa") - print(Styler(raa.link_ratio).format(precision=1).to_string(), end="") - - .. testoutput:: - - 12-24 24-36 36-48 48-60 60-72 72-84 84-96 96-108 108-120 - 1981 1.6 1.3 1.1 1.1 1.2 1.1 1.0 1.0 1.0 - 1982 40.4 1.3 2.0 1.3 1.1 1.0 1.0 1.0 nan - 1983 2.6 1.5 1.2 1.2 1.2 1.0 1.0 nan nan - 1984 2.0 1.4 1.3 1.1 1.1 1.0 nan nan nan - 1985 8.8 1.7 1.4 1.2 1.0 nan nan nan nan - 1986 4.3 1.8 1.1 1.2 nan nan nan nan nan - 1987 7.2 2.7 1.1 nan nan nan nan nan nan - 1988 5.1 1.9 nan nan nan nan nan nan nan - 1989 1.7 nan nan nan nan nan nan nan nan + raa.link_ratio.style.format(precision=1) """ def __init__( @@ -104,11 +90,8 @@ def __init__( "Styler must be created from a Triangle, not a " f"{type(triangle).__name__}.{hint}" ) - if triangle._dimensionality == "multi": - raise ValueError( - "Styler only supports a single Triangle. Select one " - "index and column first, e.g. triangle.iloc[0, 0]." - ) + if triangle._dimensionality in ["multi", "empty"]: + raise ValueError("Styler only supports a single Triangle.") data = triangle._repr_format(origin_as_datetime=False) super().__init__(data, *args, **kwargs) self._triangle = triangle diff --git a/chainladder/core/tests/test_style.py b/chainladder/core/tests/test_style.py index f96d406fb..0d624aa35 100644 --- a/chainladder/core/tests/test_style.py +++ b/chainladder/core/tests/test_style.py @@ -429,6 +429,21 @@ def test_style_rejects_multidimensional_triangle(clrd) -> None: _ = clrd.style +def test_style_rejects_empty_triangle() -> None: + """ + Check that styling an empty Triangle raises an error. + + Returns + ------- + None + + """ + empty = cl.Triangle() + assert empty._dimensionality == "empty" + with pytest.raises(ValueError, match="only supports a single"): + _ = empty.style + + def test_style_accepts_single_triangle_selected_from_multidimensional(clrd) -> None: """ Check that the error the multidimensional case raises is escapable by diff --git a/docs/user_guide/style.ipynb b/docs/user_guide/style.ipynb index d79d57a7d..020e2c2b7 100644 --- a/docs/user_guide/style.ipynb +++ b/docs/user_guide/style.ipynb @@ -438,6 +438,175 @@ ], "execution_count": 2 }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## Numeric Formatting\n", + "\n", + "The `Styler` allows you to control the numeric format of a `Triangle`'s values. Let's change the precision of the link ratios to have 3 decimal places." + ], + "id": "74e8ab5639dea59a" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-09-19T21:16:44.122097802Z", + "start_time": "2026-09-19T21:16:44.093538132Z" + } + }, + "cell_type": "code", + "source": [ + "raa.link_ratio.style.format(\n", + " precision=3,\n", + " na_rep=\"\",\n", + ")" + ], + "id": "273e4d8cdd19d064", + "outputs": [ + { + "data": { + "text/plain": [ + "" + ], + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
 12-2424-3636-4848-6060-7272-8484-9696-108108-120
19811.6501.3191.0821.1471.1951.1131.0331.0031.009
198240.4251.2591.9771.2921.1320.9931.0431.033
19832.6371.5431.1631.1611.1861.0291.026
19842.0431.3641.3491.1021.1131.038
19858.7591.6561.4001.1711.009
19864.2601.8161.1051.226
19877.2172.7231.125
19885.1421.887
19891.722
\n" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "execution_count": 6 + }, { "metadata": {}, "cell_type": "markdown", From 3c9f69433bf8ad5c7dfb6dacece26f6d9e25f651 Mon Sep 17 00:00:00 2001 From: Gene Dan Date: Sun, 20 Sep 2026 23:01:32 -0500 Subject: [PATCH 20/20] [FIX] Address review feedback - disable lower diagonal highlighting on valuation triangles. --- chainladder/core/style.py | 46 +- chainladder/core/tests/test_style.py | 70 ++- docs/user_guide/style.ipynb | 876 +-------------------------- 3 files changed, 105 insertions(+), 887 deletions(-) diff --git a/chainladder/core/style.py b/chainladder/core/style.py index e0cd60782..e46e1487c 100644 --- a/chainladder/core/style.py +++ b/chainladder/core/style.py @@ -15,6 +15,7 @@ import pandas as pd from pandas.io.formats.style import Styler as _PandasStyler +from chainladder import options from chainladder.core.triangle import Triangle from datetime import ( @@ -61,6 +62,10 @@ class Styler(_PandasStyler): If ``triangle`` is multidimensional, i.e. holds more than a single index and column, or if it is empty, i.e. holds no values to style. + See Also + -------- + Triangle.style : Returns a Styler for the Triangle. + Examples -------- @@ -70,6 +75,9 @@ class Styler(_PandasStyler): raa = cl.load_sample("raa") raa.link_ratio.style.format(precision=1) + + Please see: :doc:`Triangle Visualization ` for more + examples. """ def __init__( @@ -172,9 +180,9 @@ def _mask_style( def highlight_lower_triangle( self, color: str = "blue", + text_color: str | None = None, props: str | None = None, valuation_date: ValuationDateLike | None = None, - text_color: str | None = None, ) -> Styler: """ Highlight the lower triangle -- the cells beyond the Triangle's @@ -190,9 +198,9 @@ def highlight_lower_triangle( ``text_color``, e.g. ``"background-color: blue; opacity: 60%;"``. Optional. valuation_date: ValuationDateLike | None - The "as of" date used to determine which cells fall beyond the - latest diagonal, i.e. the lower triangle. If ``None``, defaults to the - wrapped Triangle's own ``valuation_date``. + The "as of" date used to determine the diagonal beyond which the + cells are highlighted. If ``None``, defaults to the + lastest diagonal. text_color: str | None Text color applied to lower-triangle cells. Ignored if ``props`` is given. Left unstyled (i.e. inherited) if not given. @@ -201,6 +209,11 @@ def highlight_lower_triangle( ------- Styler + Raises + ------ + ValueError + If the wrapped Triangle is a valuation Triangle. + Examples -------- @@ -218,32 +231,33 @@ def highlight_lower_triangle( color="#BDD7EE", text_color="#1F4E78" ) - Highlighting a fully-predicted Triangle requires a - valuation date, since its cells are no longer ``NaN``. + A fully-predicted Triangle needs no valuation date, even though its + cells are no longer ``NaN``. .. code-block:: python raa = cl.load_sample("raa") full = cl.Chainladder().fit(raa).full_triangle_ - full.style.highlight_lower_triangle( - color="lightgray", - valuation_date=raa.valuation_date, + full.style.highlight_lower_triangle(color="lightgray") + """ + if self._triangle.is_val_tri: + raise ValueError( + "highlight_lower_triangle does not support a valuation Triangle." ) - Please see: :doc:`Triangle Visualization ` for more - examples. - """ # Find which cells are beyond the valuation date. Does this by filling # a triangle's cells with their valuation dates and then comparing them to # the triangle's overall valuation date. - if valuation_date is None: - cutoff = self._triangle.valuation_date - else: - cutoff = pd.Timestamp(valuation_date) val_array = np.array(self._triangle.valuation).reshape( self._triangle.shape[-2:], order="F", ) + if valuation_date is not None: + cutoff = pd.Timestamp(valuation_date) + elif self._triangle.valuation_date >= pd.Timestamp(options.ULT_VAL): + cutoff = pd.Timestamp(val_array[-1, 0]) + else: + cutoff = self._triangle.valuation_date mask = val_array > cutoff if mask.shape != self.data.shape: raise ValueError( diff --git a/chainladder/core/tests/test_style.py b/chainladder/core/tests/test_style.py index 0d624aa35..5d9bf95c5 100644 --- a/chainladder/core/tests/test_style.py +++ b/chainladder/core/tests/test_style.py @@ -344,14 +344,15 @@ def test_highlight_lower_triangle_returns_styler(raa) -> None: assert isinstance(raa.style.highlight_lower_triangle(), Styler) -def test_highlight_lower_triangle_predicted_cells_not_highlighted_by_default( +def test_highlight_lower_triangle_predicted_cells_highlighted_by_default( raa, ) -> None: """ - A fully-predicted Triangle (e.g. full_triangle_) has no NaN cells left, - and once it carries an ultimate column its own nan_triangle collapses to - all-observed -- so without an explicit valuation_date, nothing gets - highlighted. + A fully-predicted Triangle (e.g. full_triangle_) has no NaN cells left and + carries the ultimate sentinel as its valuation_date, which would select no + cells. Its latest diagonal is taken from the last origin period instead, so + the predicted cells are highlighted without an explicit valuation_date, and + identically to passing the source Triangle's own valuation date. Parameters ---------- @@ -364,9 +365,17 @@ def test_highlight_lower_triangle_predicted_cells_not_highlighted_by_default( """ full = cl.Chainladder().fit(raa).full_triangle_ - styler = full.style.highlight_lower_triangle(color="lightgray") - styler._compute() - assert not any(styler.ctx.values()) + + inferred = full.style.highlight_lower_triangle(color="lightgray") + inferred._compute() + assert any(inferred.ctx.values()) + + explicit = full.style.highlight_lower_triangle( + color="lightgray", + valuation_date=raa.valuation_date, + ) + explicit._compute() + assert inferred.ctx == explicit.ctx def test_highlight_lower_triangle_with_valuation_date_highlights_predicted_cells( @@ -462,3 +471,48 @@ def test_style_accepts_single_triangle_selected_from_multidimensional(clrd) -> N single = clrd.iloc[0, 0] assert single._dimensionality == "single" assert isinstance(single.style, Styler) + + +def test_highlight_lower_triangle_rejects_valuation_triangle(raa) -> None: + """ + Check that a valuation Triangle is refused outright. It is indexed by + calendar date, so it holds nothing beyond its own valuation date and has no + lower triangle to highlight -- its empty corner is the lower left, the + origin periods that had not begun yet. + + Parameters + ---------- + raa: Triangle + The raa sample data set. + + Returns + ------- + None + + """ + with pytest.raises(ValueError, match="does not support a valuation Triangle"): + raa.dev_to_val().style.highlight_lower_triangle() + + +def test_highlight_lower_triangle_rejects_fully_developed_valuation_triangle( + raa, +) -> None: + """ + Check that a fully developed Triangle in valuation mode is refused too. It + carries the ultimate sentinel as its valuation_date, so it reaches the + branch that infers a cutoff from the last origin period -- an inference that + does not hold once the axes are calendar dates. + + Parameters + ---------- + raa: Triangle + The raa sample data set. + + Returns + ------- + None + + """ + full = cl.Chainladder().fit(raa).full_triangle_ + with pytest.raises(ValueError, match="does not support a valuation Triangle"): + full.dev_to_val().style.highlight_lower_triangle() diff --git a/docs/user_guide/style.ipynb b/docs/user_guide/style.ipynb index 020e2c2b7..9650dcc79 100644 --- a/docs/user_guide/style.ipynb +++ b/docs/user_guide/style.ipynb @@ -33,10 +33,6 @@ "iopub.status.busy": "2026-09-11T21:41:17.506923Z", "iopub.status.idle": "2026-09-11T21:41:17.514890Z", "shell.execute_reply": "2026-09-11T21:41:17.514455Z" - }, - "ExecuteTime": { - "end_time": "2026-09-19T20:40:48.142036845Z", - "start_time": "2026-09-19T20:40:47.300243472Z" } }, "source": [ @@ -46,175 +42,8 @@ "\n", "raa.style.highlight_lower_triangle(color=\"blue\")" ], - "outputs": [ - { - "data": { - "text/plain": [ - "" - ], - "text/html": [ - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
 1224364860728496108120
19815,0128,26910,90711,80513,53916,18118,00918,60818,66218,834
19821064,2855,39610,66613,78215,59915,49616,16916,704
19833,4108,99213,87316,14118,73522,21422,86323,466
19845,65511,55515,76621,26623,42526,08327,067
19851,0929,56515,83622,16925,95526,180
19861,5136,44511,70212,93515,852
19875574,02010,94612,314
19881,3516,94713,112
19893,1335,395
19902,063
\n" - ] - }, - "execution_count": 1, - "metadata": {}, - "output_type": "execute_result" - } - ], - "execution_count": 1 + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -229,10 +58,6 @@ "iopub.status.busy": "2026-09-11T21:41:17.516335Z", "iopub.status.idle": "2026-09-11T21:41:17.559733Z", "shell.execute_reply": "2026-09-11T21:41:17.559161Z" - }, - "ExecuteTime": { - "end_time": "2026-09-19T20:40:48.218230125Z", - "start_time": "2026-09-19T20:40:48.146899319Z" } }, "cell_type": "code", @@ -241,202 +66,11 @@ "full.style.highlight_lower_triangle(\n", " color=\"#2F61AD\",\n", " text_color=\"#FFFFFF\",\n", - " valuation_date=raa.valuation_date,\n", ")" ], "id": "0089690f", - "outputs": [ - { - "data": { - "text/plain": [ - "" - ], - "text/html": [ - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
 12243648607284961081201329999
19815,0128,26910,90711,80513,53916,18118,00918,60818,66218,83418,83418,834
19821064,2855,39610,66613,78215,59915,49616,16916,70416,85816,85816,858
19833,4108,99213,87316,14118,73522,21422,86323,46623,86324,08324,08324,083
19845,65511,55515,76621,26623,42526,08327,06727,96728,44128,70328,70328,703
19851,0929,56515,83622,16925,95526,18027,27828,18528,66328,92728,92728,927
19861,5136,44511,70212,93515,85217,64918,38919,00119,32319,50119,50119,501
19875574,02010,94612,31414,42816,06416,73817,29417,58717,74917,74917,749
19881,3516,94713,11216,66419,52521,73822,65023,40323,80024,01924,01924,019
19893,1335,3958,75911,13213,04314,52115,13015,63415,89816,04516,04516,045
19902,0636,18810,04612,76714,95916,65517,35317,93118,23418,40218,40218,402
\n" - ] - }, - "execution_count": 2, - "metadata": {}, - "output_type": "execute_result" - } - ], - "execution_count": 2 + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -449,12 +83,7 @@ "id": "74e8ab5639dea59a" }, { - "metadata": { - "ExecuteTime": { - "end_time": "2026-09-19T21:16:44.122097802Z", - "start_time": "2026-09-19T21:16:44.093538132Z" - } - }, + "metadata": {}, "cell_type": "code", "source": [ "raa.link_ratio.style.format(\n", @@ -463,149 +92,8 @@ ")" ], "id": "273e4d8cdd19d064", - "outputs": [ - { - "data": { - "text/plain": [ - "" - ], - "text/html": [ - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
 12-2424-3636-4848-6060-7272-8484-9696-108108-120
19811.6501.3191.0821.1471.1951.1131.0331.0031.009
198240.4251.2591.9771.2921.1320.9931.0431.033
19832.6371.5431.1631.1611.1861.0291.026
19842.0431.3641.3491.1021.1131.038
19858.7591.6561.4001.1711.009
19864.2601.8161.1051.226
19877.2172.7231.125
19885.1421.887
19891.722
\n" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "execution_count": 6 + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -618,12 +106,7 @@ "id": "c0003c7573b19f76" }, { - "metadata": { - "ExecuteTime": { - "end_time": "2026-09-19T20:40:48.288141793Z", - "start_time": "2026-09-19T20:40:48.241398739Z" - } - }, + "metadata": {}, "cell_type": "code", "source": [ "genins = cl.load_sample(\"genins\")\n", @@ -635,172 +118,8 @@ ")" ], "id": "8bd149db1ac700f3", - "outputs": [ - { - "data": { - "text/plain": [ - "" - ], - "text/html": [ - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
 1224364860728496108120
2001357'8481'124'7881'735'3302'218'2702'745'5963'319'9943'466'3363'606'2863'833'5153'901'463
2002352'1181'236'1392'170'0333'353'3223'799'0674'120'0634'647'8674'914'0395'339'085
2003290'5071'292'3062'218'5253'235'1793'985'9954'132'9184'628'9104'909'315
2004310'6081'418'8582'195'0473'757'4474'029'9294'381'9824'588'268
2005443'1601'136'3502'128'3332'897'8213'402'6723'873'311
2006396'1321'333'2172'180'7152'985'7523'691'712
2007440'8321'288'4632'419'8613'483'130
2008359'4801'421'1282'864'498
2009376'6861'363'294
2010344'014
\n" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "execution_count": 3 + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -813,12 +132,7 @@ "id": "39b84ce4ca3395e0" }, { - "metadata": { - "ExecuteTime": { - "end_time": "2026-09-19T20:40:48.342975643Z", - "start_time": "2026-09-19T20:40:48.291637687Z" - } - }, + "metadata": {}, "cell_type": "code", "source": [ "from babel.numbers import format_decimal\n", @@ -830,172 +144,8 @@ ")" ], "id": "28d799df4037a6c7", - "outputs": [ - { - "data": { - "text/plain": [ - "" - ], - "text/html": [ - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
 1224364860728496108120
20013,57,84811,24,78817,35,33022,18,27027,45,59633,19,99434,66,33636,06,28638,33,51539,01,463
20023,52,11812,36,13921,70,03333,53,32237,99,06741,20,06346,47,86749,14,03953,39,085
20032,90,50712,92,30622,18,52532,35,17939,85,99541,32,91846,28,91049,09,315
20043,10,60814,18,85821,95,04737,57,44740,29,92943,81,98245,88,268
20054,43,16011,36,35021,28,33328,97,82134,02,67238,73,311
20063,96,13213,33,21721,80,71529,85,75236,91,712
20074,40,83212,88,46324,19,86134,83,130
20083,59,48014,21,12828,64,498
20093,76,68613,63,294
20103,44,014
\n" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "execution_count": 4 + "outputs": [], + "execution_count": null } ], "metadata": {