+------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+
| :c:member:`~PyTypeObject.tp_vectorcall` | :c:type:`vectorcallfunc` | | | | | |
+------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+
- | [:c:member:`~PyTypeObject.tp_watched`] | char | | | | | |
+ | [:c:member:`~PyTypeObject.tp_watched`] | unsigned char | | | | | |
+------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+
.. [#slots]
.. versionadded:: 3.9 (the field exists since 3.8 but it's only used since 3.9)
-.. c:member:: char PyTypeObject.tp_watched
+.. c:member:: unsigned char PyTypeObject.tp_watched
Internal. Do not use.
vectorcallfunc tp_vectorcall;
/* bitset of which type-watchers care about this type */
- char tp_watched;
+ unsigned char tp_watched;
} PyTypeObject;
vectorcallfunc tp_vectorcall;
/* bitset of which type-watchers care about this type */
- char tp_watched;
+ unsigned char tp_watched;
};
/* This struct is used by the specializer
C2.hmm = "baz"
self.assert_events([C1, [C2]])
+ def test_all_watchers(self):
+ class C: pass
+ with ExitStack() as stack:
+ last_wid = -1
+ # don't make assumptions about how many watchers are already
+ # registered, just go until we reach the max ID
+ while last_wid < self.TYPE_MAX_WATCHERS - 1:
+ last_wid = stack.enter_context(self.watcher())
+ self.watch(last_wid, C)
+ C.foo = "bar"
+ self.assert_events([C])
+
def test_watch_non_type(self):
with self.watcher() as wid:
with self.assertRaisesRegex(ValueError, r"Cannot watch non-type"):
--- /dev/null
+Fix abort / segfault when using all eight type watcher slots, on platforms
+where ``char`` is signed by default.