From b84961a460d288ac80f0404afc2d0088c4811d32 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 5 Mar 2026 11:51:56 +0100 Subject: [PATCH] gh-141510: Don't accept frozendict in PyDict_Watch() Don't accept frozendict in PyDict_Watch() and PyDict_Unwatch(). A frozendict cannot be modified, so it's not useful to watch for modifications. --- Lib/test/test_capi/test_watchers.py | 5 +++-- Objects/dictobject.c | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_capi/test_watchers.py b/Lib/test/test_capi/test_watchers.py index bef72032513da5..67595e3550b0ff 100644 --- a/Lib/test/test_capi/test_watchers.py +++ b/Lib/test/test_capi/test_watchers.py @@ -176,8 +176,9 @@ def test_watch_unassigned_watcher_id(self): def test_unwatch_non_dict(self): with self.watcher() as wid: - with self.assertRaisesRegex(ValueError, r"Cannot watch non-dictionary"): - self.unwatch(wid, 1) + for wrong_type in (frozendict(), 5, [123], object()): + with self.assertRaisesRegex(ValueError, r"Cannot watch non-dictionary"): + self.unwatch(wid, wrong_type) def test_unwatch_out_of_range_watcher_id(self): d = {} diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 2552216152f98d..e0127f04249f6b 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -7912,7 +7912,7 @@ validate_watcher_id(PyInterpreterState *interp, int watcher_id) int PyDict_Watch(int watcher_id, PyObject* dict) { - if (!PyAnyDict_Check(dict)) { + if (!PyDict_Check(dict)) { PyErr_SetString(PyExc_ValueError, "Cannot watch non-dictionary"); return -1; } @@ -7927,7 +7927,7 @@ PyDict_Watch(int watcher_id, PyObject* dict) int PyDict_Unwatch(int watcher_id, PyObject* dict) { - if (!PyAnyDict_Check(dict)) { + if (!PyDict_Check(dict)) { PyErr_SetString(PyExc_ValueError, "Cannot watch non-dictionary"); return -1; }