From ef498bbb48004847cfb38605ec775a194fa9d9e8 Mon Sep 17 00:00:00 2001 From: uttam12331 Date: Sun, 2 Aug 2026 23:17:21 +0530 Subject: [PATCH 1/2] Fix argument order in scale_size_datetime.__post_init__ scale_size_datetime is a dataclass subclass of scale_datetime, so the generated __init__ passes the InitVars to __post_init__ positionally in field order: (date_breaks, date_labels, date_minor_breaks, range). But __post_init__ declared them as (range, date_breaks, date_labels, date_minor_breaks), so every value landed in the wrong parameter. As a result scale_size_datetime(range=...) misrouted range and raised "object of too small depth for desired array" when mapping data, and a supplied date_breaks was silently ignored. The sibling datetime scales (scale_alpha_datetime, scale_color_datetime, scale_fill_datetime) all declare these InitVars in the correct order. Reorder the parameters to match the field order; the body was already correct. Adds a regression test. --- doc/changelog.qmd | 4 ++++ plotnine/scales/scale_size.py | 2 +- tests/test_scale_internals.py | 12 ++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/doc/changelog.qmd b/doc/changelog.qmd index 0afaea656..66d424f5b 100644 --- a/doc/changelog.qmd +++ b/doc/changelog.qmd @@ -112,6 +112,10 @@ title: Changelog ### Bug Fixes +- [](:class:`~plotnine.scale_size_datetime`) no longer raises an error (or + silently ignores `date_breaks`); its `__post_init__` parameters were + declared in the wrong order, misrouting the `range` argument. + - In a non-linear coordinate system (e.g. [](:class:`~plotnine.coord_trans`)), the closing edge of a polygon is now curved along with the rest of its boundary instead of being drawn as a straight chord. diff --git a/plotnine/scales/scale_size.py b/plotnine/scales/scale_size.py index 0ecfcc3da..693ae203e 100644 --- a/plotnine/scales/scale_size.py +++ b/plotnine/scales/scale_size.py @@ -141,7 +141,7 @@ class scale_size_datetime(scale_datetime): guide: OptionalLegend = "legend" def __post_init__( - self, range, date_breaks, date_labels, date_minor_breaks + self, date_breaks, date_labels, date_minor_breaks, range ): from mizani.palettes import area_pal diff --git a/tests/test_scale_internals.py b/tests/test_scale_internals.py index aff976fcd..bc5252a49 100644 --- a/tests/test_scale_internals.py +++ b/tests/test_scale_internals.py @@ -45,6 +45,7 @@ from plotnine.scales.scale_size import ( scale_size_area, scale_size_continuous, + scale_size_datetime, scale_size_discrete, scale_size_radius, ) @@ -250,6 +251,17 @@ def test_size_palette(): s.palette(frac**2) +def test_size_datetime_palette(): + # The `range` argument must reach the area palette. Regression: the + # __post_init__ InitVars were declared in the wrong order, so `range` + # was misrouted and the palette crashed / ignored it. + s = scale_size_datetime(range=(2, 10)) + npt.assert_allclose(s.palette([0.0, 1.0]), [2.0, 10.0]) + + s = scale_size_datetime() + npt.assert_allclose(s.palette([0.0, 1.0]), [1.0, 6.0]) + + def test_scale_identity(): def is_identity_scale(name): return name.startswith("scale_") and name.endswith("_identity") From f4ff8725626047daa67170b1a77f98b4c43a3460 Mon Sep 17 00:00:00 2001 From: Hassan Kibirige Date: Tue, 11 Aug 2026 17:33:45 +0300 Subject: [PATCH 2/2] test(scales): cover every scale_size_datetime argument The regression test pinned only `range`. Check the date arguments as well, so that any reordering of the initialisation-only arguments fails the test rather than only the one combination that was reported. Annotate the argument types to match the other datetime scales, and state the changelog entries in terms of the arguments that were ignored. --- doc/changelog.qmd | 9 ++++++--- plotnine/scales/scale_size.py | 6 +++++- tests/test_scale_internals.py | 21 ++++++++++++++++----- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/doc/changelog.qmd b/doc/changelog.qmd index 66d424f5b..cc75c84f2 100644 --- a/doc/changelog.qmd +++ b/doc/changelog.qmd @@ -112,9 +112,12 @@ title: Changelog ### Bug Fixes -- [](:class:`~plotnine.scale_size_datetime`) no longer raises an error (or - silently ignores `date_breaks`); its `__post_init__` parameters were - declared in the wrong order, misrouting the `range` argument. +- [](:class:`~plotnine.scale_size_datetime`) now honours its `range` + argument. Previously it was ignored and mapping data raised an error. + +- [](:class:`~plotnine.scale_size_datetime`) now honours its `date_breaks`, + `date_labels` and `date_minor_breaks` arguments, which it previously + ignored. - In a non-linear coordinate system (e.g. [](:class:`~plotnine.coord_trans`)), the closing edge of a polygon is now curved along with the rest of its diff --git a/plotnine/scales/scale_size.py b/plotnine/scales/scale_size.py index 693ae203e..cab969bbe 100644 --- a/plotnine/scales/scale_size.py +++ b/plotnine/scales/scale_size.py @@ -141,7 +141,11 @@ class scale_size_datetime(scale_datetime): guide: OptionalLegend = "legend" def __post_init__( - self, date_breaks, date_labels, date_minor_breaks, range + self, + date_breaks: str | None, + date_labels: str | None, + date_minor_breaks: str | None, + range: tuple[float, float], ): from mizani.palettes import area_pal diff --git a/tests/test_scale_internals.py b/tests/test_scale_internals.py index bc5252a49..b9c4d7c77 100644 --- a/tests/test_scale_internals.py +++ b/tests/test_scale_internals.py @@ -251,15 +251,26 @@ def test_size_palette(): s.palette(frac**2) -def test_size_datetime_palette(): - # The `range` argument must reach the area palette. Regression: the - # __post_init__ InitVars were declared in the wrong order, so `range` - # was misrouted and the palette crashed / ignored it. - s = scale_size_datetime(range=(2, 10)) +def test_size_datetime_arguments(): + # Every initialisation-only argument is checked, not just `range`. They + # reach the scale by position, so one of them landing in the wrong + # parameter leaves the others correct and the mistake invisible. + s = scale_size_datetime( + date_breaks="1 year", + date_labels="%Y", + date_minor_breaks="1 month", + range=(2, 10), + ) npt.assert_allclose(s.palette([0.0, 1.0]), [2.0, 10.0]) + assert callable(s.breaks) + assert callable(s.labels) + assert callable(s.minor_breaks) s = scale_size_datetime() npt.assert_allclose(s.palette([0.0, 1.0]), [1.0, 6.0]) + assert s.breaks is True + assert s.labels is True + assert s.minor_breaks is True def test_scale_identity():