@@ -208,6 +208,7 @@ class TestTypeWatchers(unittest.TestCase):
208208 TYPES = 0 # appends modified types to global event list
209209 ERROR = 1 # unconditionally sets and signals a RuntimeException
210210 WRAP = 2 # appends modified type wrapped in list to global event list
211+ NAME = 3 # appends type name (string) to global event list
211212
212213 # duplicating the C constant
213214 TYPE_MAX_WATCHERS = 8
@@ -377,6 +378,27 @@ def test_clear_unassigned_watcher_id(self):
377378 with self .assertRaisesRegex (ValueError , r"No type watcher set for ID 1" ):
378379 self .clear_watcher (1 )
379380
381+ def test_watch_type_dealloc (self ):
382+ # Use the NAME watcher (kind=3) which records the type's name as a
383+ # string, avoiding any reference to the type object itself during
384+ # deallocation.
385+ with self .watcher (kind = self .NAME ) as wid :
386+ class MyTestType : pass
387+ self .watch (wid , MyTestType )
388+ del MyTestType
389+ gc_collect ()
390+ events = _testcapi .get_type_modified_events ()
391+ self .assertIn ("MyTestType" , events )
392+
393+ def test_watch_type_dealloc_error (self ):
394+ with self .watcher (kind = self .ERROR ) as wid :
395+ class MyTestType2 : pass
396+ self .watch (wid , MyTestType2 )
397+ with catch_unraisable_exception () as cm :
398+ del MyTestType2
399+ gc_collect ()
400+ self .assertEqual (str (cm .unraisable .exc_value ), "boom!" )
401+
380402 def test_no_more_ids_available (self ):
381403 with self .assertRaisesRegex (RuntimeError , r"no more type watcher IDs" ):
382404 with ExitStack () as stack :
0 commit comments