From f95eee07a2a7e2db56bcfe5310cf68f7703eb479 Mon Sep 17 00:00:00 2001 From: Stefan Zetzsche Date: Sun, 22 Feb 2026 14:54:51 +0000 Subject: [PATCH 1/5] gh-XXXXX: Fix optparse._check_callback TypeError for tuple callback_kwargs %r % tuple unpacks the tuple as multiple format args, raising TypeError instead of OptionError. Wrap in a 1-tuple: % (value,). --- Lib/optparse.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/optparse.py b/Lib/optparse.py index 5ff7f74754f9c1..839330454d2a2c 100644 --- a/Lib/optparse.py +++ b/Lib/optparse.py @@ -704,7 +704,7 @@ def _check_callback(self): not isinstance(self.callback_kwargs, dict)): raise OptionError( "callback_kwargs, if supplied, must be a dict: not %r" - % self.callback_kwargs, self) + % (self.callback_kwargs,), self) else: if self.callback is not None: raise OptionError( From e757e271cdaea5752b2a7df3a369aad6c54de5f7 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Wed, 11 Mar 2026 14:14:28 +0000 Subject: [PATCH 2/5] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Library/2026-03-11-14-14-27.gh-issue-145821.xWSIjR.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-03-11-14-14-27.gh-issue-145821.xWSIjR.rst diff --git a/Misc/NEWS.d/next/Library/2026-03-11-14-14-27.gh-issue-145821.xWSIjR.rst b/Misc/NEWS.d/next/Library/2026-03-11-14-14-27.gh-issue-145821.xWSIjR.rst new file mode 100644 index 00000000000000..55e12181be6862 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-03-11-14-14-27.gh-issue-145821.xWSIjR.rst @@ -0,0 +1,3 @@ +Fix :exc:`TypeError` in :mod:`optparse` when ``callback_kwargs`` is a +non-dict (e.g. a tuple). The validation in ``Option._check_callback`` now +correctly raises :exc:`~optparse.OptionError`. From 578a3b6d9bd43e0a573c57ddc92ad1c3b161b65f Mon Sep 17 00:00:00 2001 From: Stefan Zetzsche <120379523+stefanzetzsche@users.noreply.github.com> Date: Wed, 11 Mar 2026 17:29:23 +0000 Subject: [PATCH 3/5] Update Misc/NEWS.d/next/Library/2026-03-11-14-14-27.gh-issue-145821.xWSIjR.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com> --- .../Library/2026-03-11-14-14-27.gh-issue-145821.xWSIjR.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2026-03-11-14-14-27.gh-issue-145821.xWSIjR.rst b/Misc/NEWS.d/next/Library/2026-03-11-14-14-27.gh-issue-145821.xWSIjR.rst index 55e12181be6862..654ea8ae6a7277 100644 --- a/Misc/NEWS.d/next/Library/2026-03-11-14-14-27.gh-issue-145821.xWSIjR.rst +++ b/Misc/NEWS.d/next/Library/2026-03-11-14-14-27.gh-issue-145821.xWSIjR.rst @@ -1,3 +1,2 @@ -Fix :exc:`TypeError` in :mod:`optparse` when ``callback_kwargs`` is a -non-dict (e.g. a tuple). The validation in ``Option._check_callback`` now -correctly raises :exc:`~optparse.OptionError`. +:mod:`optparse`: raise :exc:`~optparse.OptionError` instead of :exc:`TypeError` +when ``callback_kwargs`` is not a dictionary. From a27f627c7d57cce990c2b75b2b6c7e56c96ef404 Mon Sep 17 00:00:00 2001 From: Stefan Zetzsche Date: Wed, 11 Mar 2026 17:48:34 +0000 Subject: [PATCH 4/5] test(optparse): add regression test for tuple callback_kwargs raising OptionError A tuple callback_kwargs should raise OptionError with the repr of the tuple, not TypeError from string formatting unpacking the tuple. --- Lib/test/test_optparse.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Lib/test/test_optparse.py b/Lib/test/test_optparse.py index fc8ef9520b3c0f..c4d47e6c5669fc 100644 --- a/Lib/test/test_optparse.py +++ b/Lib/test/test_optparse.py @@ -301,6 +301,16 @@ def test_callback_kwargs_no_dict(self): 'callback': self.dummy, 'callback_kwargs': 'foo'}) + def test_callback_kwargs_tuple_not_dict(self): + # A tuple callback_kwargs should raise OptionError, not TypeError + # from string formatting unpacking the tuple. + self.assertOptionError( + "option -b: callback_kwargs, if supplied, " + "must be a dict: not (1, 2)", + ["-b"], {'action': 'callback', + 'callback': self.dummy, + 'callback_kwargs': (1, 2)}) + def test_no_callback_for_action(self): self.assertOptionError( "option -b: callback supplied ('foo') for non-callback option", From 5cea36d07e8f0fc34a4a6f9ea7bcd86223c52305 Mon Sep 17 00:00:00 2001 From: Stefan Zetzsche Date: Thu, 12 Mar 2026 14:23:38 +0000 Subject: [PATCH 5/5] Remove unnecessary comments from test case --- Lib/test/test_optparse.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/Lib/test/test_optparse.py b/Lib/test/test_optparse.py index c4d47e6c5669fc..dd05e3e4e438a7 100644 --- a/Lib/test/test_optparse.py +++ b/Lib/test/test_optparse.py @@ -302,8 +302,6 @@ def test_callback_kwargs_no_dict(self): 'callback_kwargs': 'foo'}) def test_callback_kwargs_tuple_not_dict(self): - # A tuple callback_kwargs should raise OptionError, not TypeError - # from string formatting unpacking the tuple. self.assertOptionError( "option -b: callback_kwargs, if supplied, " "must be a dict: not (1, 2)",