@@ -45,7 +45,7 @@ Dictionary objects
4545 The first argument can be a :class: `dict `, a :class: `frozendict `, or a
4646 mapping.
4747
48- .. versionchanged :: next
48+ .. versionchanged :: 3.15
4949 Also accept :class: `frozendict `.
5050
5151
@@ -76,7 +76,12 @@ Dictionary objects
7676
7777 The first argument can be a :class: `dict ` or a :class: `frozendict `.
7878
79- .. versionchanged :: next
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+
84+ .. versionchanged :: 3.15
8085 Also accept :class: `frozendict `.
8186
8287
@@ -90,7 +95,7 @@ Dictionary objects
9095
9196 .. versionadded :: 3.13
9297
93- .. versionchanged :: next
98+ .. versionchanged :: 3.15
9499 Also accept :class: `frozendict `.
95100
96101
@@ -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,9 +155,14 @@ 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
145- .. versionchanged :: next
165+ .. versionchanged :: 3.15
146166 Also accept :class: `frozendict `.
147167
148168 See also the :c:func: `PyObject_GetItem ` function.
@@ -162,11 +182,18 @@ 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.
168195
169- .. versionchanged :: next
196+ .. versionchanged :: 3.15
170197 Also accept :class: `frozendict `.
171198
172199
@@ -177,7 +204,14 @@ Dictionary objects
177204 occurred. Return ``NULL `` **without ** an exception set if the key
178205 wasn't present.
179206
180- .. versionchanged :: next
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+
214+ .. versionchanged :: 3.15
181215 Also accept :class: `frozendict `.
182216
183217
@@ -195,7 +229,14 @@ Dictionary objects
195229 Prefer using the :c:func: `PyDict_GetItemWithError ` function with your own
196230 :c:func: `PyUnicode_FromString ` *key * instead.
197231
198- .. versionchanged :: next
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+
239+ .. versionchanged :: 3.15
199240 Also accept :class: `frozendict `.
200241
201242
@@ -207,7 +248,7 @@ Dictionary objects
207248
208249 .. versionadded :: 3.13
209250
210- .. versionchanged :: next
251+ .. versionchanged :: 3.15
211252 Also accept :class: `frozendict `.
212253
213254
@@ -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
@@ -275,7 +334,7 @@ Dictionary objects
275334
276335 The first argument can be a :class: `dict ` or a :class: `frozendict `.
277336
278- .. versionchanged :: next
337+ .. versionchanged :: 3.15
279338 Also accept :class: `frozendict `.
280339
281340
@@ -285,7 +344,7 @@ Dictionary objects
285344
286345 The first argument can be a :class: `dict ` or a :class: `frozendict `.
287346
288- .. versionchanged :: next
347+ .. versionchanged :: 3.15
289348 Also accept :class: `frozendict `.
290349
291350
@@ -296,7 +355,7 @@ Dictionary objects
296355
297356 The first argument can be a :class: `dict ` or a :class: `frozendict `.
298357
299- .. versionchanged :: next
358+ .. versionchanged :: 3.15
300359 Also accept :class: `frozendict `.
301360
302361
@@ -309,15 +368,15 @@ Dictionary objects
309368
310369 The argument can be a :class: `dict ` or a :class: `frozendict `.
311370
312- .. versionchanged :: next
371+ .. versionchanged :: 3.15
313372 Also accept :class: `frozendict `.
314373
315374
316375.. c :function :: Py_ssize_t PyDict_GET_SIZE (PyObject *p)
317376
318377 Similar to :c:func: `PyDict_Size `, but without error checking.
319378
320- .. versionchanged :: next
379+ .. versionchanged :: 3.15
321380 Also accept :class: `frozendict `.
322381
323382
@@ -391,7 +450,7 @@ Dictionary objects
391450 :term: `strong reference <strong reference> ` (for example, using
392451 :c:func: `Py_NewRef `).
393452
394- .. versionchanged:: next
453+ .. versionchanged:: 3.15
395454 Also accept :class:`frozendict`.
396455
397456.. c:function:: int PyDict_Merge(PyObject *a, PyObject *b, int override)
@@ -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