From 20c7ecb9ff9f07eb078c034c288a84cff9f96fee Mon Sep 17 00:00:00 2001 From: htjworld <116538001+htjworld@users.noreply.github.com> Date: Sat, 2 May 2026 11:32:55 +0900 Subject: [PATCH] gh-149259: Fix median_grouped() exception chaining and error messages Split the single try/except block into two, add `from exc` chaining so the original ValueError is visible in tracebacks, and improve the error messages to identify whether `interval` or the data value failed the float conversion. --- Lib/statistics.py | 11 +++++++++-- Lib/test/test_statistics.py | 19 +++++++++++++++++++ ...-05-02-11-32-35.gh-issue-149259.rJ6MXk.rst | 3 +++ 3 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2026-05-02-11-32-35.gh-issue-149259.rJ6MXk.rst diff --git a/Lib/statistics.py b/Lib/statistics.py index 32fcf2313a815a..0e5f4aee93ccc8 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -453,9 +453,16 @@ def median_grouped(data, interval=1.0): # Coerce to floats, raising a TypeError if not possible try: interval = float(interval) + except ValueError as exc: + raise TypeError( + f'interval must be a real number, got {interval!r}' + ) from exc + try: x = float(x) - except ValueError: - raise TypeError(f'Value cannot be converted to a float') + except ValueError as exc: + raise TypeError( + f'data sequence must contain real numbers, found {x!r}' + ) from exc # Interpolate the median using the formula found at: # https://www.cuemath.com/data/median-of-grouped-data/ diff --git a/Lib/test/test_statistics.py b/Lib/test/test_statistics.py index 677a87b51b9192..9c92a6093bfd31 100644 --- a/Lib/test/test_statistics.py +++ b/Lib/test/test_statistics.py @@ -1799,6 +1799,25 @@ def test_data_type_error(self): interval = b"" self.assertRaises(TypeError, self.func, data, interval) + def test_exception_chaining_and_messages(self): + # TypeError raised for bad interval should chain the original ValueError + # and identify the problematic parameter. + data = [1, 2, 3] + with self.assertRaises(TypeError) as cm: + self.func(data, interval="bad") + exc = cm.exception + self.assertIsInstance(exc.__cause__, ValueError) + self.assertIn("interval", str(exc)) + + # TypeError raised for non-numeric data should chain the original ValueError + # and identify that the data is the problem. + data = ["a", "b", "c"] + with self.assertRaises(TypeError) as cm: + self.func(data) + exc = cm.exception + self.assertIsInstance(exc.__cause__, ValueError) + self.assertIn("data", str(exc)) + class TestMode(NumericTestCase, AverageMixin, UnivariateTypeMixin): # Test cases for the discrete version of mode. diff --git a/Misc/NEWS.d/next/Library/2026-05-02-11-32-35.gh-issue-149259.rJ6MXk.rst b/Misc/NEWS.d/next/Library/2026-05-02-11-32-35.gh-issue-149259.rJ6MXk.rst new file mode 100644 index 00000000000000..80e643eeb1d121 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-05-02-11-32-35.gh-issue-149259.rJ6MXk.rst @@ -0,0 +1,3 @@ +Fix :func:`statistics.median_grouped` to chain the original :exc:`ValueError` +when coercing *interval* or the median data value to ``float`` fails, and +improve the error message to identify which parameter caused the failure.