@@ -76,6 +76,11 @@ Dictionary objects
7676
7777 The first argument can be a :class: `dict ` or a :class: `frozendict `.
7878
79+ .. note ::
80+
81+ The operation is atomic on :term: `free threading <free-threaded build> `
82+ when *key * is :class: `str `, :class: `int `, :class: `float `, :class: `bool ` or :class: `bytes `.
83+
7984 .. versionchanged :: 3.15
8085 Also accept :class: `frozendict `.
8186
@@ -105,6 +110,11 @@ Dictionary objects
105110 ``0 `` on success or ``-1 `` on failure. This function *does not * steal a
106111 reference to *val *.
107112
113+ .. note ::
114+
115+ The operation is atomic on :term: `free threading <free-threaded build> `
116+ when *key * is :class: `str `, :class: `int `, :class: `float `, :class: `bool ` or :class: `bytes `.
117+
108118
109119.. c :function :: int PyDict_SetItemString (PyObject *p, const char *key, PyObject *val)
110120
@@ -120,6 +130,11 @@ Dictionary objects
120130 If *key * is not in the dictionary, :exc: `KeyError ` is raised.
121131 Return ``0 `` on success or ``-1 `` on failure.
122132
133+ .. note ::
134+
135+ The operation is atomic on :term: `free threading <free-threaded build> `
136+ when *key * is :class: `str `, :class: `int `, :class: `float `, :class: `bool ` or :class: `bytes `.
137+
123138
124139.. c :function :: int PyDict_DelItemString (PyObject *p, const char *key)
125140
@@ -140,6 +155,11 @@ Dictionary objects
140155
141156 The first argument can be a :class: `dict ` or a :class: `frozendict `.
142157
158+ .. note ::
159+
160+ The operation is atomic on :term: `free threading <free-threaded build> `
161+ when *key * is :class: `str `, :class: `int `, :class: `float `, :class: `bool ` or :class: `bytes `.
162+
143163 .. versionadded :: 3.13
144164
145165 .. versionchanged :: 3.15
@@ -162,6 +182,13 @@ Dictionary objects
162182 :meth: `~object.__eq__ ` methods are silently ignored.
163183 Prefer the :c:func: `PyDict_GetItemWithError ` function instead.
164184
185+ .. note ::
186+
187+ In the :term: `free-threaded build `, the returned
188+ :term: `borrowed reference ` may become invalid if another thread modifies
189+ the dictionary concurrently. Prefer :c:func: `PyDict_GetItemRef `, which
190+ returns a :term: `strong reference `.
191+
165192 .. versionchanged :: 3.10
166193 Calling this API without an :term: `attached thread state ` had been allowed for historical
167194 reason. It is no longer allowed.
@@ -177,6 +204,13 @@ Dictionary objects
177204 occurred. Return ``NULL `` **without ** an exception set if the key
178205 wasn't present.
179206
207+ .. note ::
208+
209+ In the :term: `free-threaded build `, the returned
210+ :term: `borrowed reference ` may become invalid if another thread modifies
211+ the dictionary concurrently. Prefer :c:func: `PyDict_GetItemRef `, which
212+ returns a :term: `strong reference `.
213+
180214 .. versionchanged :: 3.15
181215 Also accept :class: `frozendict `.
182216
@@ -195,6 +229,13 @@ Dictionary objects
195229 Prefer using the :c:func: `PyDict_GetItemWithError ` function with your own
196230 :c:func: `PyUnicode_FromString ` *key * instead.
197231
232+ .. note ::
233+
234+ In the :term: `free-threaded build `, the returned
235+ :term: `borrowed reference ` may become invalid if another thread modifies
236+ the dictionary concurrently. Prefer :c:func: `PyDict_GetItemStringRef `,
237+ which returns a :term: `strong reference `.
238+
198239 .. versionchanged :: 3.15
199240 Also accept :class: `frozendict `.
200241
@@ -221,6 +262,14 @@ Dictionary objects
221262
222263 .. versionadded :: 3.4
223264
265+ .. note ::
266+
267+ In the :term: `free-threaded build `, the returned
268+ :term: `borrowed reference ` may become invalid if another thread modifies
269+ the dictionary concurrently. Prefer :c:func: `PyDict_SetDefaultRef `,
270+ which returns a :term: `strong reference `.
271+
272+
224273
225274.. c :function :: int PyDict_SetDefaultRef (PyObject *p, PyObject *key, PyObject *default_value, PyObject **result)
226275
@@ -240,6 +289,11 @@ Dictionary objects
240289 These may refer to the same object: in that case you hold two separate
241290 references to it.
242291
292+ .. note::
293+
294+ The operation is atomic on :term:`free threading <free-threaded build>`
295+ when *key* is :class:`str`, :class:`int`, :class:`float`, :class:`bool` or :class:`bytes`.
296+
243297 .. versionadded:: 3.13
244298
245299
@@ -257,6 +311,11 @@ Dictionary objects
257311 Similar to :meth: `dict.pop `, but without the default value and
258312 not raising :exc: `KeyError ` if the key is missing.
259313
314+ .. note ::
315+
316+ The operation is atomic on :term: `free threading <free-threaded build> `
317+ when *key * is :class: `str `, :class: `int `, :class: `float `, :class: `bool ` or :class: `bytes `.
318+
260319 .. versionadded :: 3.13
261320
262321
@@ -403,6 +462,13 @@ Dictionary objects
403462 only be added if there is not a matching key in *a *. Return ``0 `` on
404463 success or ``-1 `` if an exception was raised.
405464
465+ .. note ::
466+
467+ In the :term: `free-threaded build `, when *b * is a
468+ :class: `dict ` (with the standard iterator), both *a* and *b* are locked
469+ for the duration of the operation. When *b* is a non-dict mapping, only
470+ *a* is locked; *b* may be concurrently modified by another thread.
471+
406472
407473 .. c :function :: int PyDict_Update (PyObject *a, PyObject *b)
408474
@@ -412,6 +478,13 @@ Dictionary objects
412478 argument has no "keys" attribute. Return ``0 `` on success or ``-1 `` if an
413479 exception was raised.
414480
481+ .. note ::
482+
483+ In the :term: `free-threaded build `, when *b * is a
484+ :class: `dict ` (with the standard iterator), both *a* and *b* are locked
485+ for the duration of the operation. When *b* is a non-dict mapping, only
486+ *a* is locked; *b* may be concurrently modified by another thread.
487+
415488
416489 .. c :function :: int PyDict_MergeFromSeq2 (PyObject *a, PyObject *seq2, int override)
417490
@@ -427,13 +500,27 @@ Dictionary objects
427500 if override or key not in a:
428501 a[key] = value
429502
503+ .. note ::
504+
505+ In the :term: `free-threaded <free threading> ` build, only *a * is locked.
506+ The iteration over *seq2 * is not synchronized; *seq2 * may be concurrently
507+ modified by another thread.
508+
509+
430510.. c :function :: int PyDict_AddWatcher (PyDict_WatchCallback callback)
431511
432512 Register *callback* as a dictionary watcher. Return a non-negative integer
433513 id which must be passed to future calls to :c:func:`PyDict_Watch`. In case
434514 of error (e.g. no more watcher IDs available), return ``-1`` and set an
435515 exception.
436516
517+ .. note::
518+
519+ This function is not internally synchronized. In the
520+ :term:`free-threaded <free threading>` build, callers should ensure no
521+ concurrent calls to :c:func:`PyDict_AddWatcher` or
522+ :c:func:`PyDict_ClearWatcher` are in progress.
523+
437524 .. versionadded:: 3.12
438525
439526.. c:function:: int PyDict_ClearWatcher(int watcher_id)
@@ -442,6 +529,13 @@ Dictionary objects
442529 :c:func:`PyDict_AddWatcher`. Return ``0`` on success, ``-1`` on error (e.g.
443530 if the given *watcher_id * was never registered.)
444531
532+ .. note::
533+
534+ This function is not internally synchronized. In the
535+ :term:`free-threaded <free threading>` build, callers should ensure no
536+ concurrent calls to :c:func:`PyDict_AddWatcher` or
537+ :c:func:`PyDict_ClearWatcher` are in progress.
538+
445539 .. versionadded:: 3.12
446540
447541.. c:function:: int PyDict_Watch(int watcher_id, PyObject *dict)
0 commit comments