Coverage Report

Created: 2025-11-24 06:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Include/cpython/dictobject.h
Line
Count
Source
1
#ifndef Py_CPYTHON_DICTOBJECT_H
2
#  error "this header file must not be included directly"
3
#endif
4
5
typedef struct _dictkeysobject PyDictKeysObject;
6
typedef struct _dictvalues PyDictValues;
7
8
/* The ma_values pointer is NULL for a combined table
9
 * or points to an array of PyObject* for a split table
10
 */
11
typedef struct {
12
    PyObject_HEAD
13
14
    /* Number of items in the dictionary */
15
    Py_ssize_t ma_used;
16
17
    /* This is a private field for CPython's internal use.
18
     * Bits 0-7 are for dict watchers.
19
     * Bits 8-11 are for the watched mutation counter (used by tier2 optimization)
20
     * Bits 12-31 are currently unused
21
     * Bits 32-63 are a unique id in the free threading build (used for per-thread refcounting)
22
     */
23
    uint64_t _ma_watcher_tag;
24
25
    PyDictKeysObject *ma_keys;
26
27
    /* If ma_values is NULL, the table is "combined": keys and values
28
       are stored in ma_keys.
29
30
       If ma_values is not NULL, the table is split:
31
       keys are stored in ma_keys and values are stored in ma_values */
32
    PyDictValues *ma_values;
33
} PyDictObject;
34
35
PyAPI_FUNC(PyObject *) _PyDict_GetItem_KnownHash(PyObject *mp, PyObject *key,
36
                                                 Py_hash_t hash);
37
// PyDict_GetItemStringRef() can be used instead
38
Py_DEPRECATED(3.14) PyAPI_FUNC(PyObject *) _PyDict_GetItemStringWithError(PyObject *, const char *);
39
PyAPI_FUNC(PyObject *) PyDict_SetDefault(
40
    PyObject *mp, PyObject *key, PyObject *defaultobj);
41
42
/* Get the number of items of a dictionary. */
43
43.8M
static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
44
43.8M
    PyDictObject *mp;
45
43.8M
    assert(PyDict_Check(op));
46
43.8M
    mp = _Py_CAST(PyDictObject*, op);
47
#ifdef Py_GIL_DISABLED
48
    return _Py_atomic_load_ssize_relaxed(&mp->ma_used);
49
#else
50
43.8M
    return mp->ma_used;
51
43.8M
#endif
52
43.8M
}
Unexecuted instantiation: bytesobject.c:PyDict_GET_SIZE
call.c:PyDict_GET_SIZE
Line
Count
Source
43
23.7M
static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
44
23.7M
    PyDictObject *mp;
45
23.7M
    assert(PyDict_Check(op));
46
23.7M
    mp = _Py_CAST(PyDictObject*, op);
47
#ifdef Py_GIL_DISABLED
48
    return _Py_atomic_load_ssize_relaxed(&mp->ma_used);
49
#else
50
23.7M
    return mp->ma_used;
51
23.7M
#endif
52
23.7M
}
Unexecuted instantiation: exceptions.c:PyDict_GET_SIZE
Unexecuted instantiation: genericaliasobject.c:PyDict_GET_SIZE
Unexecuted instantiation: floatobject.c:PyDict_GET_SIZE
listobject.c:PyDict_GET_SIZE
Line
Count
Source
43
511k
static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
44
511k
    PyDictObject *mp;
45
511k
    assert(PyDict_Check(op));
46
511k
    mp = _Py_CAST(PyDictObject*, op);
47
#ifdef Py_GIL_DISABLED
48
    return _Py_atomic_load_ssize_relaxed(&mp->ma_used);
49
#else
50
511k
    return mp->ma_used;
51
511k
#endif
52
511k
}
Unexecuted instantiation: longobject.c:PyDict_GET_SIZE
Unexecuted instantiation: dictobject.c:PyDict_GET_SIZE
Unexecuted instantiation: memoryobject.c:PyDict_GET_SIZE
Unexecuted instantiation: moduleobject.c:PyDict_GET_SIZE
Unexecuted instantiation: object.c:PyDict_GET_SIZE
Unexecuted instantiation: obmalloc.c:PyDict_GET_SIZE
Unexecuted instantiation: picklebufobject.c:PyDict_GET_SIZE
Unexecuted instantiation: rangeobject.c:PyDict_GET_SIZE
setobject.c:PyDict_GET_SIZE
Line
Count
Source
43
180
static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
44
180
    PyDictObject *mp;
45
180
    assert(PyDict_Check(op));
46
180
    mp = _Py_CAST(PyDictObject*, op);
47
#ifdef Py_GIL_DISABLED
48
    return _Py_atomic_load_ssize_relaxed(&mp->ma_used);
49
#else
50
180
    return mp->ma_used;
51
180
#endif
52
180
}
Unexecuted instantiation: sliceobject.c:PyDict_GET_SIZE
Unexecuted instantiation: structseq.c:PyDict_GET_SIZE
Unexecuted instantiation: templateobject.c:PyDict_GET_SIZE
Unexecuted instantiation: tupleobject.c:PyDict_GET_SIZE
typeobject.c:PyDict_GET_SIZE
Line
Count
Source
43
7.69M
static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
44
7.69M
    PyDictObject *mp;
45
7.69M
    assert(PyDict_Check(op));
46
7.69M
    mp = _Py_CAST(PyDictObject*, op);
47
#ifdef Py_GIL_DISABLED
48
    return _Py_atomic_load_ssize_relaxed(&mp->ma_used);
49
#else
50
7.69M
    return mp->ma_used;
51
7.69M
#endif
52
7.69M
}
typevarobject.c:PyDict_GET_SIZE
Line
Count
Source
43
20
static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
44
20
    PyDictObject *mp;
45
20
    assert(PyDict_Check(op));
46
20
    mp = _Py_CAST(PyDictObject*, op);
47
#ifdef Py_GIL_DISABLED
48
    return _Py_atomic_load_ssize_relaxed(&mp->ma_used);
49
#else
50
20
    return mp->ma_used;
51
20
#endif
52
20
}
Unexecuted instantiation: unicode_format.c:PyDict_GET_SIZE
Unexecuted instantiation: unicode_formatter.c:PyDict_GET_SIZE
Unexecuted instantiation: unicode_writer.c:PyDict_GET_SIZE
Unexecuted instantiation: unicodectype.c:PyDict_GET_SIZE
Unexecuted instantiation: unicodeobject.c:PyDict_GET_SIZE
Unexecuted instantiation: unionobject.c:PyDict_GET_SIZE
Unexecuted instantiation: weakrefobject.c:PyDict_GET_SIZE
Unexecuted instantiation: _warnings.c:PyDict_GET_SIZE
Unexecuted instantiation: bltinmodule.c:PyDict_GET_SIZE
ceval.c:PyDict_GET_SIZE
Line
Count
Source
43
78.2k
static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
44
78.2k
    PyDictObject *mp;
45
78.2k
    assert(PyDict_Check(op));
46
78.2k
    mp = _Py_CAST(PyDictObject*, op);
47
#ifdef Py_GIL_DISABLED
48
    return _Py_atomic_load_ssize_relaxed(&mp->ma_used);
49
#else
50
78.2k
    return mp->ma_used;
51
78.2k
#endif
52
78.2k
}
Unexecuted instantiation: codecs.c:PyDict_GET_SIZE
Unexecuted instantiation: codegen.c:PyDict_GET_SIZE
compile.c:PyDict_GET_SIZE
Line
Count
Source
43
154k
static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
44
154k
    PyDictObject *mp;
45
154k
    assert(PyDict_Check(op));
46
154k
    mp = _Py_CAST(PyDictObject*, op);
47
#ifdef Py_GIL_DISABLED
48
    return _Py_atomic_load_ssize_relaxed(&mp->ma_used);
49
#else
50
154k
    return mp->ma_used;
51
154k
#endif
52
154k
}
Unexecuted instantiation: context.c:PyDict_GET_SIZE
Unexecuted instantiation: errors.c:PyDict_GET_SIZE
flowgraph.c:PyDict_GET_SIZE
Line
Count
Source
43
86.1k
static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
44
86.1k
    PyDictObject *mp;
45
86.1k
    assert(PyDict_Check(op));
46
86.1k
    mp = _Py_CAST(PyDictObject*, op);
47
#ifdef Py_GIL_DISABLED
48
    return _Py_atomic_load_ssize_relaxed(&mp->ma_used);
49
#else
50
86.1k
    return mp->ma_used;
51
86.1k
#endif
52
86.1k
}
Unexecuted instantiation: frame.c:PyDict_GET_SIZE
Unexecuted instantiation: future.c:PyDict_GET_SIZE
Unexecuted instantiation: gc.c:PyDict_GET_SIZE
Unexecuted instantiation: gc_gil.c:PyDict_GET_SIZE
getargs.c:PyDict_GET_SIZE
Line
Count
Source
43
11.4M
static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
44
11.4M
    PyDictObject *mp;
45
11.4M
    assert(PyDict_Check(op));
46
11.4M
    mp = _Py_CAST(PyDictObject*, op);
47
#ifdef Py_GIL_DISABLED
48
    return _Py_atomic_load_ssize_relaxed(&mp->ma_used);
49
#else
50
11.4M
    return mp->ma_used;
51
11.4M
#endif
52
11.4M
}
Unexecuted instantiation: ceval_gil.c:PyDict_GET_SIZE
Unexecuted instantiation: hamt.c:PyDict_GET_SIZE
Unexecuted instantiation: hashtable.c:PyDict_GET_SIZE
Unexecuted instantiation: import.c:PyDict_GET_SIZE
Unexecuted instantiation: importdl.c:PyDict_GET_SIZE
Unexecuted instantiation: initconfig.c:PyDict_GET_SIZE
Unexecuted instantiation: instrumentation.c:PyDict_GET_SIZE
Unexecuted instantiation: instruction_sequence.c:PyDict_GET_SIZE
Unexecuted instantiation: intrinsics.c:PyDict_GET_SIZE
Unexecuted instantiation: legacy_tracing.c:PyDict_GET_SIZE
Unexecuted instantiation: lock.c:PyDict_GET_SIZE
Unexecuted instantiation: marshal.c:PyDict_GET_SIZE
Unexecuted instantiation: modsupport.c:PyDict_GET_SIZE
Unexecuted instantiation: mysnprintf.c:PyDict_GET_SIZE
Unexecuted instantiation: parking_lot.c:PyDict_GET_SIZE
Unexecuted instantiation: preconfig.c:PyDict_GET_SIZE
Unexecuted instantiation: pyarena.c:PyDict_GET_SIZE
Unexecuted instantiation: pyctype.c:PyDict_GET_SIZE
Unexecuted instantiation: pyhash.c:PyDict_GET_SIZE
Unexecuted instantiation: pylifecycle.c:PyDict_GET_SIZE
Unexecuted instantiation: pymath.c:PyDict_GET_SIZE
Unexecuted instantiation: pystate.c:PyDict_GET_SIZE
Unexecuted instantiation: pythonrun.c:PyDict_GET_SIZE
Unexecuted instantiation: pytime.c:PyDict_GET_SIZE
Unexecuted instantiation: qsbr.c:PyDict_GET_SIZE
Unexecuted instantiation: bootstrap_hash.c:PyDict_GET_SIZE
Unexecuted instantiation: specialize.c:PyDict_GET_SIZE
Unexecuted instantiation: symtable.c:PyDict_GET_SIZE
Unexecuted instantiation: sysmodule.c:PyDict_GET_SIZE
Unexecuted instantiation: thread.c:PyDict_GET_SIZE
Unexecuted instantiation: traceback.c:PyDict_GET_SIZE
Unexecuted instantiation: tracemalloc.c:PyDict_GET_SIZE
Unexecuted instantiation: getopt.c:PyDict_GET_SIZE
Unexecuted instantiation: pystrcmp.c:PyDict_GET_SIZE
Unexecuted instantiation: pystrtod.c:PyDict_GET_SIZE
Unexecuted instantiation: pystrhex.c:PyDict_GET_SIZE
Unexecuted instantiation: dtoa.c:PyDict_GET_SIZE
Unexecuted instantiation: fileutils.c:PyDict_GET_SIZE
Unexecuted instantiation: suggestions.c:PyDict_GET_SIZE
Unexecuted instantiation: perf_trampoline.c:PyDict_GET_SIZE
Unexecuted instantiation: perf_jit_trampoline.c:PyDict_GET_SIZE
Unexecuted instantiation: remote_debugging.c:PyDict_GET_SIZE
Unexecuted instantiation: dynload_shlib.c:PyDict_GET_SIZE
Unexecuted instantiation: config.c:PyDict_GET_SIZE
Unexecuted instantiation: gcmodule.c:PyDict_GET_SIZE
Unexecuted instantiation: _asynciomodule.c:PyDict_GET_SIZE
Unexecuted instantiation: atexitmodule.c:PyDict_GET_SIZE
Unexecuted instantiation: faulthandler.c:PyDict_GET_SIZE
Unexecuted instantiation: posixmodule.c:PyDict_GET_SIZE
Unexecuted instantiation: signalmodule.c:PyDict_GET_SIZE
Unexecuted instantiation: _tracemalloc.c:PyDict_GET_SIZE
Unexecuted instantiation: _suggestions.c:PyDict_GET_SIZE
_datetimemodule.c:PyDict_GET_SIZE
Line
Count
Source
43
3
static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
44
3
    PyDictObject *mp;
45
3
    assert(PyDict_Check(op));
46
3
    mp = _Py_CAST(PyDictObject*, op);
47
#ifdef Py_GIL_DISABLED
48
    return _Py_atomic_load_ssize_relaxed(&mp->ma_used);
49
#else
50
3
    return mp->ma_used;
51
3
#endif
52
3
}
Unexecuted instantiation: _codecsmodule.c:PyDict_GET_SIZE
Unexecuted instantiation: _collectionsmodule.c:PyDict_GET_SIZE
Unexecuted instantiation: _iomodule.c:PyDict_GET_SIZE
Unexecuted instantiation: iobase.c:PyDict_GET_SIZE
Unexecuted instantiation: fileio.c:PyDict_GET_SIZE
Unexecuted instantiation: bytesio.c:PyDict_GET_SIZE
Unexecuted instantiation: bufferedio.c:PyDict_GET_SIZE
Unexecuted instantiation: textio.c:PyDict_GET_SIZE
stringio.c:PyDict_GET_SIZE
Line
Count
Source
43
16.4k
static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
44
16.4k
    PyDictObject *mp;
45
16.4k
    assert(PyDict_Check(op));
46
16.4k
    mp = _Py_CAST(PyDictObject*, op);
47
#ifdef Py_GIL_DISABLED
48
    return _Py_atomic_load_ssize_relaxed(&mp->ma_used);
49
#else
50
16.4k
    return mp->ma_used;
51
16.4k
#endif
52
16.4k
}
Unexecuted instantiation: itertoolsmodule.c:PyDict_GET_SIZE
sre.c:PyDict_GET_SIZE
Line
Count
Source
43
2.36k
static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
44
2.36k
    PyDictObject *mp;
45
2.36k
    assert(PyDict_Check(op));
46
2.36k
    mp = _Py_CAST(PyDictObject*, op);
47
#ifdef Py_GIL_DISABLED
48
    return _Py_atomic_load_ssize_relaxed(&mp->ma_used);
49
#else
50
2.36k
    return mp->ma_used;
51
2.36k
#endif
52
2.36k
}
Unexecuted instantiation: _sysconfig.c:PyDict_GET_SIZE
Unexecuted instantiation: _threadmodule.c:PyDict_GET_SIZE
Unexecuted instantiation: timemodule.c:PyDict_GET_SIZE
Unexecuted instantiation: _typesmodule.c:PyDict_GET_SIZE
Unexecuted instantiation: _typingmodule.c:PyDict_GET_SIZE
Unexecuted instantiation: _weakref.c:PyDict_GET_SIZE
Unexecuted instantiation: _abc.c:PyDict_GET_SIZE
_functoolsmodule.c:PyDict_GET_SIZE
Line
Count
Source
43
46.7k
static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
44
46.7k
    PyDictObject *mp;
45
46.7k
    assert(PyDict_Check(op));
46
46.7k
    mp = _Py_CAST(PyDictObject*, op);
47
#ifdef Py_GIL_DISABLED
48
    return _Py_atomic_load_ssize_relaxed(&mp->ma_used);
49
#else
50
46.7k
    return mp->ma_used;
51
46.7k
#endif
52
46.7k
}
Unexecuted instantiation: _localemodule.c:PyDict_GET_SIZE
Unexecuted instantiation: _opcode.c:PyDict_GET_SIZE
Unexecuted instantiation: _operator.c:PyDict_GET_SIZE
Unexecuted instantiation: symtablemodule.c:PyDict_GET_SIZE
Unexecuted instantiation: pwdmodule.c:PyDict_GET_SIZE
Unexecuted instantiation: getpath.c:PyDict_GET_SIZE
Unexecuted instantiation: frozen.c:PyDict_GET_SIZE
Unexecuted instantiation: getbuildinfo.c:PyDict_GET_SIZE
Unexecuted instantiation: peg_api.c:PyDict_GET_SIZE
Unexecuted instantiation: file_tokenizer.c:PyDict_GET_SIZE
Unexecuted instantiation: helpers.c:PyDict_GET_SIZE
Unexecuted instantiation: myreadline.c:PyDict_GET_SIZE
Unexecuted instantiation: abstract.c:PyDict_GET_SIZE
Unexecuted instantiation: boolobject.c:PyDict_GET_SIZE
Unexecuted instantiation: bytes_methods.c:PyDict_GET_SIZE
Unexecuted instantiation: bytearrayobject.c:PyDict_GET_SIZE
Unexecuted instantiation: capsule.c:PyDict_GET_SIZE
Unexecuted instantiation: cellobject.c:PyDict_GET_SIZE
Unexecuted instantiation: classobject.c:PyDict_GET_SIZE
Unexecuted instantiation: codeobject.c:PyDict_GET_SIZE
Unexecuted instantiation: complexobject.c:PyDict_GET_SIZE
Unexecuted instantiation: descrobject.c:PyDict_GET_SIZE
Unexecuted instantiation: enumobject.c:PyDict_GET_SIZE
Unexecuted instantiation: genobject.c:PyDict_GET_SIZE
Unexecuted instantiation: fileobject.c:PyDict_GET_SIZE
Unexecuted instantiation: frameobject.c:PyDict_GET_SIZE
funcobject.c:PyDict_GET_SIZE
Line
Count
Source
43
8
static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
44
8
    PyDictObject *mp;
45
8
    assert(PyDict_Check(op));
46
8
    mp = _Py_CAST(PyDictObject*, op);
47
#ifdef Py_GIL_DISABLED
48
    return _Py_atomic_load_ssize_relaxed(&mp->ma_used);
49
#else
50
8
    return mp->ma_used;
51
8
#endif
52
8
}
Unexecuted instantiation: interpolationobject.c:PyDict_GET_SIZE
Unexecuted instantiation: iterobject.c:PyDict_GET_SIZE
odictobject.c:PyDict_GET_SIZE
Line
Count
Source
43
192
static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
44
192
    PyDictObject *mp;
45
192
    assert(PyDict_Check(op));
46
192
    mp = _Py_CAST(PyDictObject*, op);
47
#ifdef Py_GIL_DISABLED
48
    return _Py_atomic_load_ssize_relaxed(&mp->ma_used);
49
#else
50
192
    return mp->ma_used;
51
192
#endif
52
192
}
Unexecuted instantiation: methodobject.c:PyDict_GET_SIZE
Unexecuted instantiation: namespaceobject.c:PyDict_GET_SIZE
Unexecuted instantiation: _contextvars.c:PyDict_GET_SIZE
Unexecuted instantiation: Python-ast.c:PyDict_GET_SIZE
Unexecuted instantiation: Python-tokenize.c:PyDict_GET_SIZE
Unexecuted instantiation: asdl.c:PyDict_GET_SIZE
assemble.c:PyDict_GET_SIZE
Line
Count
Source
43
17.0k
static inline Py_ssize_t PyDict_GET_SIZE(PyObject *op) {
44
17.0k
    PyDictObject *mp;
45
17.0k
    assert(PyDict_Check(op));
46
17.0k
    mp = _Py_CAST(PyDictObject*, op);
47
#ifdef Py_GIL_DISABLED
48
    return _Py_atomic_load_ssize_relaxed(&mp->ma_used);
49
#else
50
17.0k
    return mp->ma_used;
51
17.0k
#endif
52
17.0k
}
Unexecuted instantiation: ast.c:PyDict_GET_SIZE
Unexecuted instantiation: ast_preprocess.c:PyDict_GET_SIZE
Unexecuted instantiation: ast_unparse.c:PyDict_GET_SIZE
Unexecuted instantiation: critical_section.c:PyDict_GET_SIZE
Unexecuted instantiation: crossinterp.c:PyDict_GET_SIZE
Unexecuted instantiation: getcopyright.c:PyDict_GET_SIZE
Unexecuted instantiation: getplatform.c:PyDict_GET_SIZE
Unexecuted instantiation: getversion.c:PyDict_GET_SIZE
Unexecuted instantiation: optimizer.c:PyDict_GET_SIZE
Unexecuted instantiation: pathconfig.c:PyDict_GET_SIZE
Unexecuted instantiation: structmember.c:PyDict_GET_SIZE
Unexecuted instantiation: pegen.c:PyDict_GET_SIZE
Unexecuted instantiation: pegen_errors.c:PyDict_GET_SIZE
Unexecuted instantiation: parser.c:PyDict_GET_SIZE
Unexecuted instantiation: buffer.c:PyDict_GET_SIZE
Unexecuted instantiation: lexer.c:PyDict_GET_SIZE
Unexecuted instantiation: state.c:PyDict_GET_SIZE
Unexecuted instantiation: readline_tokenizer.c:PyDict_GET_SIZE
Unexecuted instantiation: string_tokenizer.c:PyDict_GET_SIZE
Unexecuted instantiation: utf8_tokenizer.c:PyDict_GET_SIZE
Unexecuted instantiation: getcompiler.c:PyDict_GET_SIZE
Unexecuted instantiation: mystrtoul.c:PyDict_GET_SIZE
Unexecuted instantiation: token.c:PyDict_GET_SIZE
Unexecuted instantiation: action_helpers.c:PyDict_GET_SIZE
Unexecuted instantiation: string_parser.c:PyDict_GET_SIZE
53
44.5M
#define PyDict_GET_SIZE(op) PyDict_GET_SIZE(_PyObject_CAST(op))
54
55
PyAPI_FUNC(int) PyDict_ContainsString(PyObject *mp, const char *key);
56
57
PyAPI_FUNC(PyObject *) _PyDict_NewPresized(Py_ssize_t minused);
58
59
PyAPI_FUNC(int) PyDict_Pop(PyObject *dict, PyObject *key, PyObject **result);
60
PyAPI_FUNC(int) PyDict_PopString(PyObject *dict, const char *key, PyObject **result);
61
62
// Use PyDict_Pop() instead
63
Py_DEPRECATED(3.14) PyAPI_FUNC(PyObject *) _PyDict_Pop(
64
    PyObject *dict,
65
    PyObject *key,
66
    PyObject *default_value);
67
68
/* Dictionary watchers */
69
70
#define PY_FOREACH_DICT_EVENT(V) \
71
0
    V(ADDED)                     \
72
0
    V(MODIFIED)                  \
73
0
    V(DELETED)                   \
74
0
    V(CLONED)                    \
75
0
    V(CLEARED)                   \
76
0
    V(DEALLOCATED)
77
78
typedef enum {
79
    #define PY_DEF_EVENT(EVENT) PyDict_EVENT_##EVENT,
80
    PY_FOREACH_DICT_EVENT(PY_DEF_EVENT)
81
    #undef PY_DEF_EVENT
82
} PyDict_WatchEvent;
83
84
// Callback to be invoked when a watched dict is cleared, dealloced, or modified.
85
// In clear/dealloc case, key and new_value will be NULL. Otherwise, new_value will be the
86
// new value for key, NULL if key is being deleted.
87
typedef int(*PyDict_WatchCallback)(PyDict_WatchEvent event, PyObject* dict, PyObject* key, PyObject* new_value);
88
89
// Register/unregister a dict-watcher callback
90
PyAPI_FUNC(int) PyDict_AddWatcher(PyDict_WatchCallback callback);
91
PyAPI_FUNC(int) PyDict_ClearWatcher(int watcher_id);
92
93
// Mark given dictionary as "watched" (callback will be called if it is modified)
94
PyAPI_FUNC(int) PyDict_Watch(int watcher_id, PyObject* dict);
95
PyAPI_FUNC(int) PyDict_Unwatch(int watcher_id, PyObject* dict);