https://github.com/python/cpython/commit/c0d0b286bc0b24512b56c9087a4bcf8ffca50ab6 commit: c0d0b286bc0b24512b56c9087a4bcf8ffca50ab6 branch: main author: Serhiy Storchaka <[email protected]> committer: serhiy-storchaka <[email protected]> date: 2026-08-13T13:06:17+03:00 summary:
gh-155044: Support copy.replace() for optparse.Values (GH-155050) Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> files: A Misc/NEWS.d/next/Library/2026-08-01-19-05-00.gh-issue-155044.Op1Val.rst M Doc/library/optparse.rst M Lib/optparse.py M Lib/test/test_optparse.py diff --git a/Doc/library/optparse.rst b/Doc/library/optparse.rst index 905212965bd70f..09416f12ad45c2 100644 --- a/Doc/library/optparse.rst +++ b/Doc/library/optparse.rst @@ -1073,6 +1073,12 @@ As you can see, most actions involve storing or updating a value somewhere. and can be overridden by a custom subclass passed to the *values* argument of :meth:`OptionParser.parse_args` (as described in :ref:`optparse-parsing-arguments`). + :class:`!Values` objects support :func:`copy.replace`, + which returns a copy of the object with the specified attributes replaced. + + .. versionchanged:: next + Added support for :func:`copy.replace`. + Option arguments (and various other values) are stored as attributes of this object, according to the :attr:`~Option.dest` (destination) option attribute. diff --git a/Lib/optparse.py b/Lib/optparse.py index de1082442ef7f2..ae6737a3d13942 100644 --- a/Lib/optparse.py +++ b/Lib/optparse.py @@ -830,6 +830,12 @@ def __eq__(self, other): else: return NotImplemented + def __replace__(self, /, **changes): + new = self.__class__() + new.__dict__.update(self.__dict__) + new.__dict__.update(changes) + return new + def _update_careful(self, dict): """ Update the option values from an arbitrary dictionary, but only diff --git a/Lib/test/test_optparse.py b/Lib/test/test_optparse.py index fc8ef9520b3c0f..9fca2dafd5c99e 100644 --- a/Lib/test/test_optparse.py +++ b/Lib/test/test_optparse.py @@ -434,6 +434,13 @@ def test_basics(self): self.assertNotEqual(values, "") self.assertNotEqual(values, []) + def test_replace(self): + values = Values(defaults={"foo": "bar", "baz": 42}) + new = copy.replace(values, baz=43, spam="eggs") + self.assertIsInstance(new, Values) + self.assertEqual(vars(new), {"foo": "bar", "baz": 43, "spam": "eggs"}) + self.assertEqual(vars(values), {"foo": "bar", "baz": 42}) + class TestTypeAliases(BaseTest): def setUp(self): diff --git a/Misc/NEWS.d/next/Library/2026-08-01-19-05-00.gh-issue-155044.Op1Val.rst b/Misc/NEWS.d/next/Library/2026-08-01-19-05-00.gh-issue-155044.Op1Val.rst new file mode 100644 index 00000000000000..10665f913ef5e6 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-08-01-19-05-00.gh-issue-155044.Op1Val.rst @@ -0,0 +1 @@ +:class:`optparse.Values` objects now support :func:`copy.replace`. _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]
