2020import weakref
2121from test import support
2222from test .support import MISSING_C_DOCSTRINGS
23+ from test .support import catch_unraisable_exception
2324from test .support import import_helper
2425from test .support import threading_helper
2526from test .support import warnings_helper
@@ -1421,6 +1422,9 @@ def assert_events(self, expected):
14211422 def watch (self , wid , d ):
14221423 _testcapi .watch_dict (wid , d )
14231424
1425+ def unwatch (self , wid , d ):
1426+ _testcapi .unwatch_dict (wid , d )
1427+
14241428 def test_set_new_item (self ):
14251429 d = {}
14261430 with self .watcher () as wid :
@@ -1477,27 +1481,24 @@ def test_dealloc(self):
14771481 del d
14781482 self .assert_events (["dealloc" ])
14791483
1484+ def test_unwatch (self ):
1485+ d = {}
1486+ with self .watcher () as wid :
1487+ self .watch (wid , d )
1488+ d ["foo" ] = "bar"
1489+ self .unwatch (wid , d )
1490+ d ["hmm" ] = "baz"
1491+ self .assert_events (["new:foo:bar" ])
1492+
14801493 def test_error (self ):
14811494 d = {}
1482- unraisables = []
1483- def unraisable_hook (unraisable ):
1484- unraisables .append (unraisable )
14851495 with self .watcher (kind = self .ERROR ) as wid :
14861496 self .watch (wid , d )
1487- orig_unraisable_hook = sys .unraisablehook
1488- sys .unraisablehook = unraisable_hook
1489- try :
1497+ with catch_unraisable_exception () as cm :
14901498 d ["foo" ] = "bar"
1491- finally :
1492- sys . unraisablehook = orig_unraisable_hook
1499+ self . assertIs ( cm . unraisable . object , d )
1500+ self . assertEqual ( str ( cm . unraisable . exc_value ), "boom!" )
14931501 self .assert_events ([])
1494- self .assertEqual (len (unraisables ), 1 )
1495- unraisable = unraisables [0 ]
1496- self .assertIs (unraisable .object , d )
1497- self .assertEqual (str (unraisable .exc_value ), "boom!" )
1498- # avoid leaking reference cycles
1499- del unraisable
1500- del unraisables
15011502
15021503 def test_two_watchers (self ):
15031504 d1 = {}
@@ -1522,11 +1523,38 @@ def test_watch_out_of_range_watcher_id(self):
15221523 with self .assertRaisesRegex (ValueError , r"Invalid dict watcher ID 8" ):
15231524 self .watch (8 , d ) # DICT_MAX_WATCHERS = 8
15241525
1525- def test_unassigned_watcher_id (self ):
1526+ def test_watch_unassigned_watcher_id (self ):
15261527 d = {}
15271528 with self .assertRaisesRegex (ValueError , r"No dict watcher set for ID 1" ):
15281529 self .watch (1 , d )
15291530
1531+ def test_unwatch_non_dict (self ):
1532+ with self .watcher () as wid :
1533+ with self .assertRaisesRegex (ValueError , r"Cannot watch non-dictionary" ):
1534+ self .unwatch (wid , 1 )
1535+
1536+ def test_unwatch_out_of_range_watcher_id (self ):
1537+ d = {}
1538+ with self .assertRaisesRegex (ValueError , r"Invalid dict watcher ID -1" ):
1539+ self .unwatch (- 1 , d )
1540+ with self .assertRaisesRegex (ValueError , r"Invalid dict watcher ID 8" ):
1541+ self .unwatch (8 , d ) # DICT_MAX_WATCHERS = 8
1542+
1543+ def test_unwatch_unassigned_watcher_id (self ):
1544+ d = {}
1545+ with self .assertRaisesRegex (ValueError , r"No dict watcher set for ID 1" ):
1546+ self .unwatch (1 , d )
1547+
1548+ def test_clear_out_of_range_watcher_id (self ):
1549+ with self .assertRaisesRegex (ValueError , r"Invalid dict watcher ID -1" ):
1550+ self .clear_watcher (- 1 )
1551+ with self .assertRaisesRegex (ValueError , r"Invalid dict watcher ID 8" ):
1552+ self .clear_watcher (8 ) # DICT_MAX_WATCHERS = 8
1553+
1554+ def test_clear_unassigned_watcher_id (self ):
1555+ with self .assertRaisesRegex (ValueError , r"No dict watcher set for ID 1" ):
1556+ self .clear_watcher (1 )
1557+
15301558
15311559if __name__ == "__main__" :
15321560 unittest .main ()
0 commit comments