Coverage Report

Created: 2026-04-12 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Objects/odictobject.c
Line
Count
Source
1
/* Ordered Dictionary object implementation.
2
3
This implementation is necessarily explicitly equivalent to the pure Python
4
OrderedDict class in Lib/collections/__init__.py.  The strategy there
5
involves using a doubly-linked-list to capture the order.  We keep to that
6
strategy, using a lower-level linked-list.
7
8
About the Linked-List
9
=====================
10
11
For the linked list we use a basic doubly-linked-list.  Using a circularly-
12
linked-list does have some benefits, but they don't apply so much here
13
since OrderedDict is focused on the ends of the list (for the most part).
14
Furthermore, there are some features of generic linked-lists that we simply
15
don't need for OrderedDict.  Thus a simple custom implementation meets our
16
needs.  Alternatives to our simple approach include the QCIRCLE_*
17
macros from BSD's queue.h, and the linux's list.h.
18
19
Getting O(1) Node Lookup
20
------------------------
21
22
One invariant of Python's OrderedDict is that it preserves time complexity
23
of dict's methods, particularly the O(1) operations.  Simply adding a
24
linked-list on top of dict is not sufficient here; operations for nodes in
25
the middle of the linked-list implicitly require finding the node first.
26
With a simple linked-list like we're using, that is an O(n) operation.
27
Consequently, methods like __delitem__() would change from O(1) to O(n),
28
which is unacceptable.
29
30
In order to preserve O(1) performance for node removal (finding nodes), we
31
must do better than just looping through the linked-list.  Here are options
32
we've considered:
33
34
1. use a second dict to map keys to nodes (a la the pure Python version).
35
2. keep a simple hash table mirroring the order of dict's, mapping each key
36
   to the corresponding node in the linked-list.
37
3. use a version of shared keys (split dict) that allows non-unicode keys.
38
4. have the value stored for each key be a (value, node) pair, and adjust
39
   __getitem__(), get(), etc. accordingly.
40
41
The approach with the least performance impact (time and space) is #2,
42
mirroring the key order of dict's dk_entries with an array of node pointers.
43
While _Py_dict_lookup() does not give us the index into the array,
44
we make use of pointer arithmetic to get that index.  An alternative would
45
be to refactor _Py_dict_lookup() to provide the index, explicitly exposing
46
the implementation detail.  We could even just use a custom lookup function
47
for OrderedDict that facilitates our need.  However, both approaches are
48
significantly more complicated than just using pointer arithmetic.
49
50
The catch with mirroring the hash table ordering is that we have to keep
51
the ordering in sync through any dict resizes.  However, that order only
52
matters during node lookup.  We can simply defer any potential resizing
53
until we need to do a lookup.
54
55
Linked-List Nodes
56
-----------------
57
58
The current implementation stores a pointer to the associated key only.
59
One alternative would be to store a pointer to the PyDictKeyEntry instead.
60
This would save one pointer de-reference per item, which is nice during
61
calls to values() and items().  However, it adds unnecessary overhead
62
otherwise, so we stick with just the key.
63
64
Linked-List API
65
---------------
66
67
As noted, the linked-list implemented here does not have all the bells and
68
whistles.  However, we recognize that the implementation may need to
69
change to accommodate performance improvements or extra functionality.  To
70
that end, we use a simple API to interact with the linked-list.  Here's a
71
summary of the methods/macros:
72
73
Node info:
74
75
* _odictnode_KEY(node)
76
* _odictnode_VALUE(od, node)
77
* _odictnode_PREV(node)
78
* _odictnode_NEXT(node)
79
80
Linked-List info:
81
82
* _odict_FIRST(od)
83
* _odict_LAST(od)
84
* _odict_EMPTY(od)
85
* _odict_FOREACH(od, node) - used in place of `for (node=...)`
86
87
For adding nodes:
88
89
* _odict_add_head(od, node)
90
* _odict_add_tail(od, node)
91
* _odict_add_new_node(od, key, hash)
92
93
For removing nodes:
94
95
* _odict_clear_node(od, node, key, hash)
96
* _odict_clear_nodes(od, clear_each)
97
98
Others:
99
100
* _odict_find_node_hash(od, key, hash)
101
* _odict_find_node(od, key)
102
* _odict_keys_equal(od1, od2)
103
104
And here's a look at how the linked-list relates to the OrderedDict API:
105
106
============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===
107
method       key val prev next mem  1st last empty iter find add rmv  clr keq
108
============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===
109
__del__                                      ~                        X
110
__delitem__                    free                     ~        node
111
__eq__       ~                                                            X
112
__iter__     X            X
113
__new__                             X   X
114
__reduce__   X   ~                                 X
115
__repr__     X   X                                 X
116
__reversed__ X       X
117
__setitem__                                                  key
118
__sizeof__                     size          X
119
clear                          ~             ~                        X
120
copy         X   X                                 X
121
items        X   X        X
122
keys         X            X
123
move_to_end  X                      X   X               ~    h/t key
124
pop                            free                              key
125
popitem      X   X             free X   X                        node
126
setdefault       ~                                      ?    ~
127
values           X        X
128
============ === === ==== ==== ==== === ==== ===== ==== ==== === ==== === ===
129
130
__delitem__ is the only method that directly relies on finding an arbitrary
131
node in the linked-list.  Everything else is iteration or relates to the
132
ends of the linked-list.
133
134
Situation that Endangers Consistency
135
------------------------------------
136
Using a raw linked-list for OrderedDict exposes a key situation that can
137
cause problems.  If a node is stored in a variable, there is a chance that
138
the node may have been deallocated before the variable gets used, thus
139
potentially leading to a segmentation fault.  A key place where this shows
140
up is during iteration through the linked list (via _odict_FOREACH or
141
otherwise).
142
143
A number of solutions are available to resolve this situation:
144
145
* defer looking up the node until as late as possible and certainly after
146
  any code that could possibly result in a deletion;
147
* if the node is needed both before and after a point where the node might
148
  be removed, do a check before using the node at the "after" location to
149
  see if the node is still valid;
150
* like the last one, but simply pull the node again to ensure it's right;
151
* keep the key in the variable instead of the node and then look up the
152
  node using the key at the point where the node is needed (this is what
153
  we do for the iterators).
154
155
Another related problem, preserving consistent ordering during iteration,
156
is described below.  That one is not exclusive to using linked-lists.
157
158
159
Challenges from Subclassing dict
160
================================
161
162
OrderedDict subclasses dict, which is an unusual relationship between two
163
builtin types (other than the base object type).  Doing so results in
164
some complication and deserves further explanation.  There are two things
165
to consider here.  First, in what circumstances or with what adjustments
166
can OrderedDict be used as a drop-in replacement for dict (at the C level)?
167
Second, how can the OrderedDict implementation leverage the dict
168
implementation effectively without introducing unnecessary coupling or
169
inefficiencies?
170
171
This second point is reflected here and in the implementation, so the
172
further focus is on the first point.  It is worth noting that for
173
overridden methods, the dict implementation is deferred to as much as
174
possible.  Furthermore, coupling is limited to as little as is reasonable.
175
176
Concrete API Compatibility
177
--------------------------
178
179
Use of the concrete C-API for dict (PyDict_*) with OrderedDict is
180
problematic.  (See http://bugs.python.org/issue10977.)  The concrete API
181
has a number of hard-coded assumptions tied to the dict implementation.
182
This is, in part, due to performance reasons, which is understandable
183
given the part dict plays in Python.
184
185
Any attempt to replace dict with OrderedDict for any role in the
186
interpreter (e.g. **kwds) faces a challenge.  Such any effort must
187
recognize that the instances in affected locations currently interact with
188
the concrete API.
189
190
Here are some ways to address this challenge:
191
192
1. Change the relevant usage of the concrete API in CPython and add
193
   PyDict_CheckExact() calls to each of the concrete API functions.
194
2. Adjust the relevant concrete API functions to explicitly accommodate
195
   OrderedDict.
196
3. As with #1, add the checks, but improve the abstract API with smart fast
197
   paths for dict and OrderedDict, and refactor CPython to use the abstract
198
   API.  Improvements to the abstract API would be valuable regardless.
199
200
Adding the checks to the concrete API would help make any interpreter
201
switch to OrderedDict less painful for extension modules.  However, this
202
won't work.  The equivalent C API call to `dict.__setitem__(obj, k, v)`
203
is `PyDict_SetItem(obj, k, v)`.  This illustrates how subclasses in C call
204
the base class's methods, since there is no equivalent of super() in the
205
C API.  Calling into Python for parent class API would work, but some
206
extension modules already rely on this feature of the concrete API.
207
208
For reference, here is a breakdown of some of the dict concrete API:
209
210
========================== ============= =======================
211
concrete API               uses          abstract API
212
========================== ============= =======================
213
PyDict_Check                             PyMapping_Check
214
(PyDict_CheckExact)                      -
215
(PyDict_New)                             -
216
(PyDictProxy_New)                        -
217
PyDict_Clear                             -
218
PyDict_Contains                          PySequence_Contains
219
PyDict_Copy                              -
220
PyDict_SetItem                           PyObject_SetItem
221
PyDict_SetItemString                     PyMapping_SetItemString
222
PyDict_DelItem                           PyMapping_DelItem
223
PyDict_DelItemString                     PyMapping_DelItemString
224
PyDict_GetItem                           -
225
PyDict_GetItemWithError                  PyObject_GetItem
226
PyDict_GetItemString                     PyMapping_GetItemString
227
PyDict_Items                             PyMapping_Items
228
PyDict_Keys                              PyMapping_Keys
229
PyDict_Values                            PyMapping_Values
230
PyDict_Size                              PyMapping_Size
231
                                         PyMapping_Length
232
PyDict_Next                              PyIter_Next
233
_PyDict_Next                             -
234
PyDict_Merge                             -
235
PyDict_Update                            -
236
PyDict_MergeFromSeq2                     -
237
PyDict_ClearFreeList                     -
238
-                                        PyMapping_HasKeyString
239
-                                        PyMapping_HasKey
240
========================== ============= =======================
241
242
243
The dict Interface Relative to OrderedDict
244
==========================================
245
246
Since OrderedDict subclasses dict, understanding the various methods and
247
attributes of dict is important for implementing OrderedDict.
248
249
Relevant Type Slots
250
-------------------
251
252
================= ================ =================== ================
253
slot              attribute        object              dict
254
================= ================ =================== ================
255
tp_dealloc        -                object_dealloc      dict_dealloc
256
tp_repr           __repr__         object_repr         dict_repr
257
sq_contains       __contains__     -                   dict_contains
258
mp_length         __len__          -                   dict_length
259
mp_subscript      __getitem__      -                   dict_subscript
260
mp_ass_subscript  __setitem__      -                   dict_ass_sub
261
                  __delitem__
262
tp_hash           __hash__         Py_HashPointer      ..._HashNotImpl
263
tp_str            __str__          object_str          -
264
tp_getattro       __getattribute__ ..._GenericGetAttr  (repeated)
265
                  __getattr__
266
tp_setattro       __setattr__      ..._GenericSetAttr  (disabled)
267
tp_doc            __doc__          (literal)           dictionary_doc
268
tp_traverse       -                -                   dict_traverse
269
tp_clear          -                -                   dict_tp_clear
270
tp_richcompare    __eq__           object_richcompare  dict_richcompare
271
                  __ne__
272
tp_weaklistoffset (__weakref__)    -                   -
273
tp_iter           __iter__         -                   dict_iter
274
tp_dictoffset     (__dict__)       -                   -
275
tp_init           __init__         object_init         dict_init
276
tp_alloc          -                PyType_GenericAlloc (repeated)
277
tp_new            __new__          object_new          dict_new
278
tp_free           -                PyObject_Free       PyObject_GC_Del
279
================= ================ =================== ================
280
281
Relevant Methods
282
----------------
283
284
================ =================== ===============
285
method           object              dict
286
================ =================== ===============
287
__reduce__       object_reduce       -
288
__sizeof__       object_sizeof       dict_sizeof
289
clear            -                   dict_clear
290
copy             -                   dict_copy
291
fromkeys         -                   dict_fromkeys
292
get              -                   dict_get
293
items            -                   dictitems_new
294
keys             -                   dictkeys_new
295
pop              -                   dict_pop
296
popitem          -                   dict_popitem
297
setdefault       -                   dict_setdefault
298
update           -                   dict_update
299
values           -                   dictvalues_new
300
================ =================== ===============
301
302
303
Pure Python OrderedDict
304
=======================
305
306
As already noted, compatibility with the pure Python OrderedDict
307
implementation is a key goal of this C implementation.  To further that
308
goal, here's a summary of how OrderedDict-specific methods are implemented
309
in collections/__init__.py.  Also provided is an indication of which
310
methods directly mutate or iterate the object, as well as any relationship
311
with the underlying linked-list.
312
313
============= ============== == ================ === === ====
314
method        impl used      ll uses             inq mut iter
315
============= ============== == ================ === === ====
316
__contains__  dict           -  -                X
317
__delitem__   OrderedDict    Y  dict.__delitem__     X
318
__eq__        OrderedDict    N  OrderedDict      ~
319
                                dict.__eq__
320
                                __iter__
321
__getitem__   dict           -  -                X
322
__iter__      OrderedDict    Y  -                        X
323
__init__      OrderedDict    N  update
324
__len__       dict           -  -                X
325
__ne__        MutableMapping -  __eq__           ~
326
__reduce__    OrderedDict    N  OrderedDict      ~
327
                                __iter__
328
                                __getitem__
329
__repr__      OrderedDict    N  __class__        ~
330
                                items
331
__reversed__  OrderedDict    Y  -                        X
332
__setitem__   OrderedDict    Y  __contains__         X
333
                                dict.__setitem__
334
__sizeof__    OrderedDict    Y  __len__          ~
335
                                __dict__
336
clear         OrderedDict    Y  dict.clear           X
337
copy          OrderedDict    N  __class__
338
                                __init__
339
fromkeys      OrderedDict    N  __setitem__
340
get           dict           -  -                ~
341
items         MutableMapping -  ItemsView                X
342
keys          MutableMapping -  KeysView                 X
343
move_to_end   OrderedDict    Y  -                    X
344
pop           OrderedDict    N  __contains__         X
345
                                __getitem__
346
                                __delitem__
347
popitem       OrderedDict    Y  dict.pop             X
348
setdefault    OrderedDict    N  __contains__         ~
349
                                __getitem__
350
                                __setitem__
351
update        MutableMapping -  __setitem__          ~
352
values        MutableMapping -  ValuesView               X
353
============= ============== == ================ === === ====
354
355
__reversed__ and move_to_end are both exclusive to OrderedDict.
356
357
358
C OrderedDict Implementation
359
============================
360
361
================= ================
362
slot              impl
363
================= ================
364
tp_dealloc        odict_dealloc
365
tp_repr           odict_repr
366
mp_ass_subscript  odict_ass_sub
367
tp_doc            odict_doc
368
tp_traverse       odict_traverse
369
tp_clear          odict_tp_clear
370
tp_richcompare    odict_richcompare
371
tp_weaklistoffset (offset)
372
tp_iter           odict_iter
373
tp_dictoffset     (offset)
374
tp_init           odict_init
375
tp_alloc          (repeated)
376
================= ================
377
378
================= ================
379
method            impl
380
================= ================
381
__reduce__        odict_reduce
382
__sizeof__        odict_sizeof
383
clear             odict_clear
384
copy              odict_copy
385
fromkeys          odict_fromkeys
386
items             odictitems_new
387
keys              odictkeys_new
388
pop               odict_pop
389
popitem           odict_popitem
390
setdefault        odict_setdefault
391
update            odict_update
392
values            odictvalues_new
393
================= ================
394
395
Inherited unchanged from object/dict:
396
397
================ ==========================
398
method           type field
399
================ ==========================
400
-                tp_free
401
__contains__     tp_as_sequence.sq_contains
402
__getattr__      tp_getattro
403
__getattribute__ tp_getattro
404
__getitem__      tp_as_mapping.mp_subscript
405
__hash__         tp_hash
406
__len__          tp_as_mapping.mp_length
407
__setattr__      tp_setattro
408
__str__          tp_str
409
get              -
410
================ ==========================
411
412
413
Other Challenges
414
================
415
416
Preserving Ordering During Iteration
417
------------------------------------
418
During iteration through an OrderedDict, it is possible that items could
419
get added, removed, or reordered.  For a linked-list implementation, as
420
with some other implementations, that situation may lead to undefined
421
behavior.  The documentation for dict mentions this in the `iter()` section
422
of http://docs.python.org/3.4/library/stdtypes.html#dictionary-view-objects.
423
In this implementation we follow dict's lead (as does the pure Python
424
implementation) for __iter__(), keys(), values(), and items().
425
426
For internal iteration (using _odict_FOREACH or not), there is still the
427
risk that not all nodes that we expect to be seen in the loop actually get
428
seen.  Thus, we are careful in each of those places to ensure that they
429
are.  This comes, of course, at a small price at each location.  The
430
solutions are much the same as those detailed in the `Situation that
431
Endangers Consistency` section above.
432
433
434
Potential Optimizations
435
=======================
436
437
* Allocate the nodes as a block via od_fast_nodes instead of individually.
438
  - Set node->key to NULL to indicate the node is not-in-use.
439
  - Add _odict_EXISTS()?
440
  - How to maintain consistency across resizes?  Existing node pointers
441
    would be invalidated after a resize, which is particularly problematic
442
    for the iterators.
443
* Use a more stream-lined implementation of update() and, likely indirectly,
444
  __init__().
445
446
*/
447
448
/* TODO
449
450
sooner:
451
- reentrancy (make sure everything is at a thread-safe state when calling
452
  into Python).  I've already checked this multiple times, but want to
453
  make one more pass.
454
- add unit tests for reentrancy?
455
456
later:
457
- make the dict views support the full set API (the pure Python impl does)
458
- implement a fuller MutableMapping API in C?
459
- move the MutableMapping implementation to abstract.c?
460
- optimize mutablemapping_update
461
- use PyObject_Malloc (small object allocator) for odict nodes?
462
- support subclasses better (e.g. in odict_richcompare)
463
464
*/
465
466
#include "Python.h"
467
#include "pycore_call.h"             // _PyObject_CallNoArgs()
468
#include "pycore_ceval.h"            // _PyEval_GetBuiltin()
469
#include "pycore_critical_section.h" //_Py_BEGIN_CRITICAL_SECTION
470
#include "pycore_dict.h"             // _Py_dict_lookup()
471
#include "pycore_object.h"           // _PyObject_GC_UNTRACK()
472
#include "pycore_pyerrors.h"         // _PyErr_ChainExceptions1()
473
#include "pycore_tuple.h"            // _PyTuple_Recycle()
474
#include <stddef.h>                  // offsetof()
475
#include "pycore_weakref.h"          // FT_CLEAR_WEAKREFS()
476
477
#include "clinic/odictobject.c.h"
478
479
/*[clinic input]
480
class OrderedDict "PyODictObject *" "&PyODict_Type"
481
[clinic start generated code]*/
482
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ca0641cf6143d4af]*/
483
484
485
typedef struct _odictnode _ODictNode;
486
487
/* PyODictObject */
488
struct _odictobject {
489
    PyDictObject od_dict;        /* the underlying dict */
490
    _ODictNode *od_first;        /* first node in the linked list, if any */
491
    _ODictNode *od_last;         /* last node in the linked list, if any */
492
    /* od_fast_nodes, od_fast_nodes_size and od_resize_sentinel are managed
493
     * by _odict_resize().
494
     * Note that we rely on implementation details of dict for both. */
495
    _ODictNode **od_fast_nodes;  /* hash table that mirrors the dict table */
496
    Py_ssize_t od_fast_nodes_size;
497
    void *od_resize_sentinel;    /* changes if odict should be resized */
498
499
    size_t od_state;             /* incremented whenever the LL changes */
500
    PyObject *od_inst_dict;      /* OrderedDict().__dict__ */
501
    PyObject *od_weakreflist;    /* holds weakrefs to the odict */
502
};
503
504
13.6M
#define _PyODictObject_CAST(op) _Py_CAST(PyODictObject*, (op))
505
506
507
/* ----------------------------------------------
508
 * odict keys (a simple doubly-linked list)
509
 */
510
511
struct _odictnode {
512
    PyObject *key;
513
    Py_hash_t hash;
514
    _ODictNode *next;
515
    _ODictNode *prev;
516
};
517
518
#define _odictnode_KEY(node) \
519
2.94M
    (node->key)
520
#define _odictnode_HASH(node) \
521
35.0k
    (node->hash)
522
/* borrowed reference */
523
#define _odictnode_VALUE(node, od) \
524
0
    PyODict_GetItemWithError((PyObject *)od, _odictnode_KEY(node))
525
1.48M
#define _odictnode_PREV(node) (node->prev)
526
2.03M
#define _odictnode_NEXT(node) (node->next)
527
528
9.42M
#define _odict_FIRST(od) (_PyODictObject_CAST(od)->od_first)
529
7.11M
#define _odict_LAST(od) (_PyODictObject_CAST(od)->od_last)
530
5.92M
#define _odict_EMPTY(od) (_odict_FIRST(od) == NULL)
531
#define _odict_FOREACH(od, node) \
532
26.4k
    for (node = _odict_FIRST(od); node != NULL; node = _odictnode_NEXT(node))
533
534
/* Return the index into the hash table, regardless of a valid node. */
535
static Py_ssize_t
536
_odict_get_index_raw(PyODictObject *od, PyObject *key, Py_hash_t hash)
537
3.05M
{
538
3.05M
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
539
3.05M
    PyObject *value = NULL;
540
3.05M
    PyDictKeysObject *keys = ((PyDictObject *)od)->ma_keys;
541
3.05M
    Py_ssize_t ix;
542
#ifdef Py_GIL_DISABLED
543
    ix = _Py_dict_lookup_threadsafe((PyDictObject *)od, key, hash, &value);
544
    Py_XDECREF(value);
545
#else
546
3.05M
    ix = _Py_dict_lookup((PyDictObject *)od, key, hash, &value);
547
3.05M
#endif
548
3.05M
    if (ix == DKIX_EMPTY) {
549
0
        return keys->dk_nentries;  /* index of new entry */
550
0
    }
551
3.05M
    if (ix < 0)
552
0
        return -1;
553
    /* We use pointer arithmetic to get the entry's index into the table. */
554
3.05M
    return ix;
555
3.05M
}
556
557
3.05M
#define ONE ((Py_ssize_t)1)
558
559
/* Replace od->od_fast_nodes with a new table matching the size of dict's. */
560
static int
561
_odict_resize(PyODictObject *od)
562
23.3k
{
563
23.3k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
564
23.3k
    Py_ssize_t size, i;
565
23.3k
    _ODictNode **fast_nodes, *node;
566
567
    /* Initialize a new "fast nodes" table. */
568
23.3k
    size = ONE << (((PyDictObject *)od)->ma_keys->dk_log2_size);
569
23.3k
    fast_nodes = PyMem_NEW(_ODictNode *, size);
570
23.3k
    if (fast_nodes == NULL) {
571
0
        PyErr_NoMemory();
572
0
        return -1;
573
0
    }
574
213k
    for (i = 0; i < size; i++)
575
190k
        fast_nodes[i] = NULL;
576
577
    /* Copy the current nodes into the table. */
578
23.3k
    _odict_FOREACH(od, node) {
579
1.77k
        i = _odict_get_index_raw(od, _odictnode_KEY(node),
580
1.77k
                                 _odictnode_HASH(node));
581
1.77k
        if (i < 0) {
582
0
            PyMem_Free(fast_nodes);
583
0
            return -1;
584
0
        }
585
1.77k
        fast_nodes[i] = node;
586
1.77k
    }
587
588
    /* Replace the old fast nodes table. */
589
23.3k
    PyMem_Free(od->od_fast_nodes);
590
23.3k
    od->od_fast_nodes = fast_nodes;
591
23.3k
    od->od_fast_nodes_size = size;
592
23.3k
    od->od_resize_sentinel = ((PyDictObject *)od)->ma_keys;
593
23.3k
    return 0;
594
23.3k
}
595
596
/* Return the index into the hash table, regardless of a valid node. */
597
static Py_ssize_t
598
_odict_get_index(PyODictObject *od, PyObject *key, Py_hash_t hash)
599
3.05M
{
600
3.05M
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
601
3.05M
    PyDictKeysObject *keys;
602
603
3.05M
    assert(key != NULL);
604
3.05M
    keys = ((PyDictObject *)od)->ma_keys;
605
606
    /* Ensure od_fast_nodes and dk_entries are in sync. */
607
3.05M
    if (od->od_resize_sentinel != keys ||
608
3.02M
        od->od_fast_nodes_size != (ONE << (keys->dk_log2_size))) {
609
23.3k
        int resize_res = _odict_resize(od);
610
23.3k
        if (resize_res < 0)
611
0
            return -1;
612
23.3k
    }
613
614
3.05M
    return _odict_get_index_raw(od, key, hash);
615
3.05M
}
616
617
/* Returns NULL if there was some error or the key was not found. */
618
static _ODictNode *
619
_odict_find_node_hash(PyODictObject *od, PyObject *key, Py_hash_t hash)
620
4
{
621
4
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
622
4
    Py_ssize_t index;
623
624
4
    if (_odict_EMPTY(od))
625
0
        return NULL;
626
4
    index = _odict_get_index(od, key, hash);
627
4
    if (index < 0)
628
0
        return NULL;
629
4
    assert(od->od_fast_nodes != NULL);
630
4
    return od->od_fast_nodes[index];
631
4
}
632
633
static _ODictNode *
634
_odict_find_node(PyODictObject *od, PyObject *key)
635
3.01M
{
636
3.01M
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
637
3.01M
    Py_ssize_t index;
638
3.01M
    Py_hash_t hash;
639
640
3.01M
    if (_odict_EMPTY(od))
641
0
        return NULL;
642
3.01M
    hash = PyObject_Hash(key);
643
3.01M
    if (hash == -1)
644
0
        return NULL;
645
3.01M
    index = _odict_get_index(od, key, hash);
646
3.01M
    if (index < 0)
647
0
        return NULL;
648
3.01M
    assert(od->od_fast_nodes != NULL);
649
3.01M
    return od->od_fast_nodes[index];
650
3.01M
}
651
652
static void
653
_odict_add_head(PyODictObject *od, _ODictNode *node)
654
0
{
655
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
656
0
    _odictnode_PREV(node) = NULL;
657
0
    _odictnode_NEXT(node) = _odict_FIRST(od);
658
0
    if (_odict_FIRST(od) == NULL)
659
0
        _odict_LAST(od) = node;
660
0
    else
661
0
        _odictnode_PREV(_odict_FIRST(od)) = node;
662
0
    _odict_FIRST(od) = node;
663
0
    od->od_state++;
664
0
}
665
666
static void
667
_odict_add_tail(PyODictObject *od, _ODictNode *node)
668
324k
{
669
324k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
670
324k
    _odictnode_PREV(node) = _odict_LAST(od);
671
324k
    _odictnode_NEXT(node) = NULL;
672
324k
    if (_odict_LAST(od) == NULL)
673
23.1k
        _odict_FIRST(od) = node;
674
301k
    else
675
301k
        _odictnode_NEXT(_odict_LAST(od)) = node;
676
324k
    _odict_LAST(od) = node;
677
324k
    od->od_state++;
678
324k
}
679
680
/* adds the node to the end of the list */
681
static int
682
_odict_add_new_node(PyODictObject *od, PyObject *key, Py_hash_t hash)
683
33.2k
{
684
33.2k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
685
33.2k
    Py_ssize_t i;
686
33.2k
    _ODictNode *node;
687
688
33.2k
    Py_INCREF(key);
689
33.2k
    i = _odict_get_index(od, key, hash);
690
33.2k
    if (i < 0) {
691
0
        if (!PyErr_Occurred())
692
0
            PyErr_SetObject(PyExc_KeyError, key);
693
0
        Py_DECREF(key);
694
0
        return -1;
695
0
    }
696
33.2k
    assert(od->od_fast_nodes != NULL);
697
33.2k
    if (od->od_fast_nodes[i] != NULL) {
698
        /* We already have a node for the key so there's no need to add one. */
699
0
        Py_DECREF(key);
700
0
        return 0;
701
0
    }
702
703
    /* must not be added yet */
704
33.2k
    node = (_ODictNode *)PyMem_Malloc(sizeof(_ODictNode));
705
33.2k
    if (node == NULL) {
706
0
        Py_DECREF(key);
707
0
        PyErr_NoMemory();
708
0
        return -1;
709
0
    }
710
711
33.2k
    _odictnode_KEY(node) = key;
712
33.2k
    _odictnode_HASH(node) = hash;
713
33.2k
    _odict_add_tail(od, node);
714
33.2k
    od->od_fast_nodes[i] = node;
715
33.2k
    return 0;
716
33.2k
}
717
718
/* Putting the decref after the free causes problems. */
719
#define _odictnode_DEALLOC(node) \
720
33.1k
    do { \
721
33.1k
        Py_DECREF(_odictnode_KEY(node)); \
722
33.1k
        PyMem_Free((void *)node); \
723
33.1k
    } while (0)
724
725
/* Repeated calls on the same node are no-ops. */
726
static void
727
_odict_remove_node(PyODictObject *od, _ODictNode *node)
728
291k
{
729
291k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
730
291k
    if (_odict_FIRST(od) == node)
731
74
        _odict_FIRST(od) = _odictnode_NEXT(node);
732
291k
    else if (_odictnode_PREV(node) != NULL)
733
291k
        _odictnode_NEXT(_odictnode_PREV(node)) = _odictnode_NEXT(node);
734
735
291k
    if (_odict_LAST(od) == node)
736
0
        _odict_LAST(od) = _odictnode_PREV(node);
737
291k
    else if (_odictnode_NEXT(node) != NULL)
738
291k
        _odictnode_PREV(_odictnode_NEXT(node)) = _odictnode_PREV(node);
739
740
291k
    _odictnode_PREV(node) = NULL;
741
291k
    _odictnode_NEXT(node) = NULL;
742
291k
    od->od_state++;
743
291k
}
744
745
/* If someone calls PyDict_DelItem() directly on an OrderedDict, we'll
746
   get all sorts of problems here.  In PyODict_DelItem we make sure to
747
   call _odict_clear_node first.
748
749
   This matters in the case of colliding keys.  Suppose we add 3 keys:
750
   [A, B, C], where the hash of C collides with A and the next possible
751
   index in the hash table is occupied by B.  If we remove B then for C
752
   the dict's looknode func will give us the old index of B instead of
753
   the index we got before deleting B.  However, the node for C in
754
   od_fast_nodes is still at the old dict index of C.  Thus to be sure
755
   things don't get out of sync, we clear the node in od_fast_nodes
756
   *before* calling PyDict_DelItem.
757
758
   The same must be done for any other OrderedDict operations where
759
   we modify od_fast_nodes.
760
*/
761
static int
762
_odict_clear_node(PyODictObject *od, _ODictNode *node, PyObject *key,
763
                  Py_hash_t hash)
764
4
{
765
4
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
766
4
    Py_ssize_t i;
767
768
4
    assert(key != NULL);
769
4
    if (_odict_EMPTY(od)) {
770
        /* Let later code decide if this is a KeyError. */
771
0
        return 0;
772
0
    }
773
774
4
    i = _odict_get_index(od, key, hash);
775
4
    if (i < 0)
776
0
        return PyErr_Occurred() ? -1 : 0;
777
778
4
    assert(od->od_fast_nodes != NULL);
779
4
    if (node == NULL)
780
0
        node = od->od_fast_nodes[i];
781
4
    assert(node == od->od_fast_nodes[i]);
782
4
    if (node == NULL) {
783
        /* Let later code decide if this is a KeyError. */
784
0
        return 0;
785
0
    }
786
787
    // Now clear the node.
788
4
    od->od_fast_nodes[i] = NULL;
789
4
    _odict_remove_node(od, node);
790
4
    _odictnode_DEALLOC(node);
791
4
    return 0;
792
4
}
793
794
static void
795
_odict_clear_nodes(PyODictObject *od)
796
23.1k
{
797
23.1k
    _ODictNode *node, *next;
798
799
23.1k
    PyMem_Free(od->od_fast_nodes);
800
23.1k
    od->od_fast_nodes = NULL;
801
23.1k
    od->od_fast_nodes_size = 0;
802
23.1k
    od->od_resize_sentinel = NULL;
803
804
23.1k
    node = _odict_FIRST(od);
805
23.1k
    _odict_FIRST(od) = NULL;
806
23.1k
    _odict_LAST(od) = NULL;
807
56.2k
    while (node != NULL) {
808
33.1k
        next = _odictnode_NEXT(node);
809
33.1k
        _odictnode_DEALLOC(node);
810
33.1k
        node = next;
811
33.1k
    }
812
23.1k
    od->od_state++;
813
23.1k
}
814
815
/* There isn't any memory management of nodes past this point. */
816
#undef _odictnode_DEALLOC
817
818
static int
819
_odict_keys_equal(PyODictObject *a, PyODictObject *b)
820
0
{
821
0
    _ODictNode *node_a, *node_b;
822
823
    // keep operands' state to detect undesired mutations
824
0
    const size_t state_a = a->od_state;
825
0
    const size_t state_b = b->od_state;
826
827
0
    node_a = _odict_FIRST(a);
828
0
    node_b = _odict_FIRST(b);
829
0
    while (1) {
830
0
        if (node_a == NULL && node_b == NULL) {
831
            /* success: hit the end of each at the same time */
832
0
            return 1;
833
0
        }
834
0
        else if (node_a == NULL || node_b == NULL) {
835
            /* unequal length */
836
0
            return 0;
837
0
        }
838
0
        else {
839
0
            PyObject *key_a = Py_NewRef(_odictnode_KEY(node_a));
840
0
            PyObject *key_b = Py_NewRef(_odictnode_KEY(node_b));
841
0
            int res = PyObject_RichCompareBool(key_a, key_b, Py_EQ);
842
0
            Py_DECREF(key_a);
843
0
            Py_DECREF(key_b);
844
0
            if (res < 0) {
845
0
                return res;
846
0
            }
847
0
            else if (a->od_state != state_a || b->od_state != state_b) {
848
0
                PyErr_SetString(PyExc_RuntimeError,
849
0
                                "OrderedDict mutated during iteration");
850
0
                return -1;
851
0
            }
852
0
            else if (res == 0) {
853
                // This check comes after the check on the state
854
                // in order for the exception to be set correctly.
855
0
                return 0;
856
0
            }
857
858
            /* otherwise it must match, so move on to the next one */
859
0
            node_a = _odictnode_NEXT(node_a);
860
0
            node_b = _odictnode_NEXT(node_b);
861
0
        }
862
0
    }
863
0
}
864
865
866
/* ----------------------------------------------
867
 * OrderedDict mapping methods
868
 */
869
870
/* mp_ass_subscript: __setitem__() and __delitem__() */
871
872
static int
873
odict_mp_ass_sub(PyObject *od, PyObject *v, PyObject *w)
874
33.2k
{
875
33.2k
    if (w == NULL)
876
0
        return PyODict_DelItem(od, v);
877
33.2k
    else
878
33.2k
        return PyODict_SetItem(od, v, w);
879
33.2k
}
880
881
/* tp_as_mapping */
882
883
static PyMappingMethods odict_as_mapping = {
884
    0,                                  /*mp_length*/
885
    0,                                  /*mp_subscript*/
886
    odict_mp_ass_sub,                   /*mp_ass_subscript*/
887
};
888
889
890
/* ----------------------------------------------
891
 * OrderedDict number methods
892
 */
893
894
static int mutablemapping_update_arg(PyObject*, PyObject*);
895
896
static PyObject *
897
odict_or(PyObject *left, PyObject *right)
898
0
{
899
0
    PyTypeObject *type;
900
0
    PyObject *other;
901
0
    if (PyODict_Check(left)) {
902
0
        type = Py_TYPE(left);
903
0
        other = right;
904
0
    }
905
0
    else {
906
0
        type = Py_TYPE(right);
907
0
        other = left;
908
0
    }
909
0
    if (!PyAnyDict_Check(other)) {
910
0
        Py_RETURN_NOTIMPLEMENTED;
911
0
    }
912
0
    PyObject *new = PyObject_CallOneArg((PyObject*)type, left);
913
0
    if (!new) {
914
0
        return NULL;
915
0
    }
916
0
    if (mutablemapping_update_arg(new, right) < 0) {
917
0
        Py_DECREF(new);
918
0
        return NULL;
919
0
    }
920
0
    return new;
921
0
}
922
923
static PyObject *
924
odict_inplace_or(PyObject *self, PyObject *other)
925
0
{
926
0
    if (mutablemapping_update_arg(self, other) < 0) {
927
0
        return NULL;
928
0
    }
929
0
    return Py_NewRef(self);
930
0
}
931
932
/* tp_as_number */
933
934
static PyNumberMethods odict_as_number = {
935
    .nb_or = odict_or,
936
    .nb_inplace_or = odict_inplace_or,
937
};
938
939
940
/* ----------------------------------------------
941
 * OrderedDict methods
942
 */
943
944
/* fromkeys() */
945
946
/*[clinic input]
947
@permit_long_summary
948
@classmethod
949
OrderedDict.fromkeys
950
951
    iterable as seq: object
952
    value: object = None
953
954
Create a new ordered dictionary with keys from iterable and values set to value.
955
[clinic start generated code]*/
956
957
static PyObject *
958
OrderedDict_fromkeys_impl(PyTypeObject *type, PyObject *seq, PyObject *value)
959
/*[clinic end generated code: output=c10390d452d78d6d input=1277ae0769083848]*/
960
0
{
961
0
    return _PyDict_FromKeys((PyObject *)type, seq, value);
962
0
}
963
964
/*[clinic input]
965
@critical_section
966
OrderedDict.__sizeof__ -> Py_ssize_t
967
[clinic start generated code]*/
968
969
static Py_ssize_t
970
OrderedDict___sizeof___impl(PyODictObject *self)
971
/*[clinic end generated code: output=1a8560db8cf83ac5 input=655e989ae24daa6a]*/
972
0
{
973
0
    Py_ssize_t res = _PyDict_SizeOf_LockHeld((PyDictObject *)self);
974
0
    res += sizeof(_ODictNode *) * self->od_fast_nodes_size;  /* od_fast_nodes */
975
0
    if (!_odict_EMPTY(self)) {
976
0
        res += sizeof(_ODictNode) * PyODict_SIZE(self);  /* linked-list */
977
0
    }
978
0
    return res;
979
0
}
980
981
/*[clinic input]
982
OrderedDict.__reduce__
983
    self as od: self(type="PyODictObject *")
984
985
Return state information for pickling
986
[clinic start generated code]*/
987
988
static PyObject *
989
OrderedDict___reduce___impl(PyODictObject *od)
990
/*[clinic end generated code: output=71eeb81f760a6a8e input=b0467c7ec400fe5e]*/
991
0
{
992
0
    PyObject *state, *result = NULL;
993
0
    PyObject *items_iter, *items, *args = NULL;
994
995
    /* capture any instance state */
996
0
    state = _PyObject_GetState((PyObject *)od);
997
0
    if (state == NULL)
998
0
        goto Done;
999
1000
    /* build the result */
1001
0
    args = PyTuple_New(0);
1002
0
    if (args == NULL)
1003
0
        goto Done;
1004
1005
0
    items = PyObject_CallMethodNoArgs((PyObject *)od, &_Py_ID(items));
1006
0
    if (items == NULL)
1007
0
        goto Done;
1008
1009
0
    items_iter = PyObject_GetIter(items);
1010
0
    Py_DECREF(items);
1011
0
    if (items_iter == NULL)
1012
0
        goto Done;
1013
1014
0
    result = PyTuple_Pack(5, Py_TYPE(od), args, state, Py_None, items_iter);
1015
0
    Py_DECREF(items_iter);
1016
1017
0
Done:
1018
0
    Py_XDECREF(state);
1019
0
    Py_XDECREF(args);
1020
1021
0
    return result;
1022
0
}
1023
1024
/* setdefault(): Skips __missing__() calls. */
1025
1026
static int PyODict_SetItem_LockHeld(PyObject *self, PyObject *key, PyObject *value);
1027
1028
/*[clinic input]
1029
@critical_section
1030
OrderedDict.setdefault
1031
1032
    key: object
1033
    default: object = None
1034
1035
Insert key with a value of default if key is not in the dictionary.
1036
1037
Return the value for key if key is in the dictionary, else default.
1038
[clinic start generated code]*/
1039
1040
static PyObject *
1041
OrderedDict_setdefault_impl(PyODictObject *self, PyObject *key,
1042
                            PyObject *default_value)
1043
/*[clinic end generated code: output=97537cb7c28464b6 input=d7b93e92734f99b5]*/
1044
0
{
1045
0
    PyObject *result = NULL;
1046
1047
0
    if (PyODict_CheckExact(self)) {
1048
0
        result = PyODict_GetItemWithError(self, key);  /* borrowed */
1049
0
        if (result == NULL) {
1050
0
            if (PyErr_Occurred())
1051
0
                return NULL;
1052
0
            assert(_odict_find_node(self, key) == NULL);
1053
0
            if (PyODict_SetItem_LockHeld((PyObject *)self, key, default_value) >= 0) {
1054
0
                result = Py_NewRef(default_value);
1055
0
            }
1056
0
        }
1057
0
        else {
1058
0
            Py_INCREF(result);
1059
0
        }
1060
0
    }
1061
0
    else {
1062
0
        int exists = PySequence_Contains((PyObject *)self, key);
1063
0
        if (exists < 0) {
1064
0
            return NULL;
1065
0
        }
1066
0
        else if (exists) {
1067
0
            result = PyObject_GetItem((PyObject *)self, key);
1068
0
        }
1069
0
        else if (PyObject_SetItem((PyObject *)self, key, default_value) >= 0) {
1070
0
            result = Py_NewRef(default_value);
1071
0
        }
1072
0
    }
1073
1074
0
    return result;
1075
0
}
1076
1077
/* pop() */
1078
1079
static PyObject *
1080
_odict_popkey_hash(PyObject *od, PyObject *key, PyObject *failobj,
1081
                   Py_hash_t hash)
1082
4
{
1083
4
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
1084
1085
4
    PyObject *value = NULL;
1086
4
    _ODictNode *node = _odict_find_node_hash(_PyODictObject_CAST(od), key, hash);
1087
4
    if (node != NULL) {
1088
        /* Pop the node first to avoid a possible dict resize (due to
1089
           eval loop reentrancy) and complications due to hash collision
1090
           resolution. */
1091
4
        int res = _odict_clear_node(_PyODictObject_CAST(od), node, key, hash);
1092
4
        if (res < 0) {
1093
0
            goto done;
1094
0
        }
1095
        /* Now delete the value from the dict. */
1096
4
        if (_PyDict_Pop_KnownHash((PyDictObject *)od, key, hash,
1097
4
                                  &value) == 0) {
1098
0
            value = Py_NewRef(failobj);
1099
0
        }
1100
4
    }
1101
0
    else if (value == NULL && !PyErr_Occurred()) {
1102
        /* Apply the fallback value, if necessary. */
1103
0
        if (failobj) {
1104
0
            value = Py_NewRef(failobj);
1105
0
        }
1106
0
        else {
1107
0
            PyErr_SetObject(PyExc_KeyError, key);
1108
0
        }
1109
0
    }
1110
4
done:
1111
1112
4
    return value;
1113
4
}
1114
1115
/* Skips __missing__() calls. */
1116
/*[clinic input]
1117
@critical_section
1118
@permit_long_summary
1119
OrderedDict.pop
1120
1121
    key: object
1122
    default: object = NULL
1123
1124
od.pop(key[,default]) -> v, remove specified key and return the corresponding value.
1125
1126
If the key is not found, return the default if given; otherwise,
1127
raise a KeyError.
1128
[clinic start generated code]*/
1129
1130
static PyObject *
1131
OrderedDict_pop_impl(PyODictObject *self, PyObject *key,
1132
                     PyObject *default_value)
1133
/*[clinic end generated code: output=7a6447d104e7494b input=0742e3c9bf076a72]*/
1134
4
{
1135
4
    Py_hash_t hash = PyObject_Hash(key);
1136
4
    if (hash == -1)
1137
0
        return NULL;
1138
4
    return _odict_popkey_hash((PyObject *)self, key, default_value, hash);
1139
4
}
1140
1141
1142
/* popitem() */
1143
1144
/*[clinic input]
1145
@critical_section
1146
OrderedDict.popitem
1147
1148
    last: bool = True
1149
1150
Remove and return a (key, value) pair from the dictionary.
1151
1152
Pairs are returned in LIFO order if last is true or FIFO order if false.
1153
[clinic start generated code]*/
1154
1155
static PyObject *
1156
OrderedDict_popitem_impl(PyODictObject *self, int last)
1157
/*[clinic end generated code: output=98e7d986690d49eb input=8aafc7433e0a40e7]*/
1158
0
{
1159
0
    PyObject *key, *value;
1160
0
    _ODictNode *node;
1161
1162
    /* pull the item */
1163
1164
0
    if (_odict_EMPTY(self)) {
1165
0
        PyErr_SetString(PyExc_KeyError, "dictionary is empty");
1166
0
        return NULL;
1167
0
    }
1168
1169
0
    node = last ? _odict_LAST(self) : _odict_FIRST(self);
1170
0
    key = Py_NewRef(_odictnode_KEY(node));
1171
0
    value = _odict_popkey_hash((PyObject *)self, key, NULL, _odictnode_HASH(node));
1172
0
    if (value == NULL) {
1173
0
        Py_DECREF(key);
1174
0
        return NULL;
1175
0
    }
1176
0
    return _PyTuple_FromPairSteal(key, value);
1177
0
}
1178
1179
/* keys() */
1180
1181
/* MutableMapping.keys() does not have a docstring. */
1182
PyDoc_STRVAR(odict_keys__doc__, "");
1183
1184
static PyObject * odictkeys_new(PyObject *od, PyObject *Py_UNUSED(ignored));  /* forward */
1185
static int
1186
_PyODict_SetItem_KnownHash_LockHeld(PyObject *od, PyObject *key, PyObject *value,
1187
                                    Py_hash_t hash); /* forward */
1188
1189
/* values() */
1190
1191
/* MutableMapping.values() does not have a docstring. */
1192
PyDoc_STRVAR(odict_values__doc__, "");
1193
1194
static PyObject * odictvalues_new(PyObject *od, PyObject *Py_UNUSED(ignored));  /* forward */
1195
1196
/* items() */
1197
1198
/* MutableMapping.items() does not have a docstring. */
1199
PyDoc_STRVAR(odict_items__doc__, "");
1200
1201
static PyObject * odictitems_new(PyObject *od, PyObject *Py_UNUSED(ignored));  /* forward */
1202
1203
/* update() */
1204
1205
/* MutableMapping.update() does not have a docstring. */
1206
PyDoc_STRVAR(odict_update__doc__, "");
1207
1208
/* forward */
1209
static PyObject * mutablemapping_update(PyObject *, PyObject *, PyObject *);
1210
1211
23.2k
#define odict_update mutablemapping_update
1212
1213
/*[clinic input]
1214
@critical_section
1215
OrderedDict.clear
1216
1217
Remove all items from ordered dict.
1218
[clinic start generated code]*/
1219
1220
static PyObject *
1221
OrderedDict_clear_impl(PyODictObject *self)
1222
/*[clinic end generated code: output=a1a76d1322f556c5 input=08b12322e74c535c]*/
1223
0
{
1224
0
    _PyDict_Clear_LockHeld((PyObject *)self);
1225
0
    _odict_clear_nodes(self);
1226
0
    Py_RETURN_NONE;
1227
0
}
1228
1229
/* copy() */
1230
1231
/*[clinic input]
1232
@critical_section
1233
OrderedDict.copy
1234
    self as od: self
1235
1236
A shallow copy of ordered dict.
1237
[clinic start generated code]*/
1238
1239
static PyObject *
1240
OrderedDict_copy_impl(PyObject *od)
1241
/*[clinic end generated code: output=9cdbe7394aecc576 input=e329951ae617ed48]*/
1242
0
{
1243
0
    _ODictNode *node;
1244
0
    PyObject *od_copy;
1245
1246
0
    if (PyODict_CheckExact(od))
1247
0
        od_copy = PyODict_New();
1248
0
    else
1249
0
        od_copy = _PyObject_CallNoArgs((PyObject *)Py_TYPE(od));
1250
0
    if (od_copy == NULL)
1251
0
        return NULL;
1252
1253
0
    if (PyODict_CheckExact(od)) {
1254
0
        _odict_FOREACH(od, node) {
1255
0
            PyObject *key = _odictnode_KEY(node);
1256
0
            PyObject *value = _odictnode_VALUE(node, od);
1257
0
            if (value == NULL) {
1258
0
                if (!PyErr_Occurred())
1259
0
                    PyErr_SetObject(PyExc_KeyError, key);
1260
0
                goto fail;
1261
0
            }
1262
0
            if (_PyODict_SetItem_KnownHash_LockHeld((PyObject *)od_copy, key, value,
1263
0
                                                    _odictnode_HASH(node)) != 0)
1264
0
                goto fail;
1265
0
        }
1266
0
    }
1267
0
    else {
1268
0
        _odict_FOREACH(od, node) {
1269
0
            int res;
1270
0
            PyObject *value = PyObject_GetItem((PyObject *)od,
1271
0
                                               _odictnode_KEY(node));
1272
0
            if (value == NULL)
1273
0
                goto fail;
1274
0
            res = PyObject_SetItem((PyObject *)od_copy,
1275
0
                                   _odictnode_KEY(node), value);
1276
0
            Py_DECREF(value);
1277
0
            if (res != 0)
1278
0
                goto fail;
1279
0
        }
1280
0
    }
1281
0
    return od_copy;
1282
1283
0
fail:
1284
0
    Py_DECREF(od_copy);
1285
0
    return NULL;
1286
0
}
1287
1288
/* __reversed__() */
1289
1290
PyDoc_STRVAR(odict_reversed__doc__, "od.__reversed__() <==> reversed(od)");
1291
1292
297k
#define _odict_ITER_REVERSED 1
1293
503k
#define _odict_ITER_KEYS 2
1294
588k
#define _odict_ITER_VALUES 4
1295
398k
#define _odict_ITER_ITEMS (_odict_ITER_KEYS|_odict_ITER_VALUES)
1296
1297
/* forward */
1298
static PyObject * odictiter_new(PyODictObject *, int);
1299
1300
static PyObject *
1301
odict_reversed(PyObject *op, PyObject *Py_UNUSED(ignored))
1302
0
{
1303
0
    PyODictObject *od = _PyODictObject_CAST(op);
1304
0
    return odictiter_new(od, _odict_ITER_KEYS|_odict_ITER_REVERSED);
1305
0
}
1306
1307
1308
/* move_to_end() */
1309
1310
/*[clinic input]
1311
@critical_section
1312
OrderedDict.move_to_end
1313
1314
    key: object
1315
    last: bool = True
1316
1317
Move an existing element to the end (or beginning if last is false).
1318
1319
Raise KeyError if the element does not exist.
1320
[clinic start generated code]*/
1321
1322
static PyObject *
1323
OrderedDict_move_to_end_impl(PyODictObject *self, PyObject *key, int last)
1324
/*[clinic end generated code: output=fafa4c5cc9b92f20 input=09f8bc7053c0f6d4]*/
1325
2.91M
{
1326
2.91M
    _ODictNode *node;
1327
1328
2.91M
    if (_odict_EMPTY(self)) {
1329
0
        PyErr_SetObject(PyExc_KeyError, key);
1330
0
        return NULL;
1331
0
    }
1332
2.91M
    node = last ? _odict_LAST(self) : _odict_FIRST(self);
1333
2.91M
    if (key != _odictnode_KEY(node)) {
1334
2.91M
        node = _odict_find_node(self, key);
1335
2.91M
        if (node == NULL) {
1336
0
            if (!PyErr_Occurred())
1337
0
                PyErr_SetObject(PyExc_KeyError, key);
1338
0
            return NULL;
1339
0
        }
1340
2.91M
        if (last) {
1341
            /* Only move if not already the last one. */
1342
2.91M
            if (node != _odict_LAST(self)) {
1343
291k
                _odict_remove_node(self, node);
1344
291k
                _odict_add_tail(self, node);
1345
291k
            }
1346
2.91M
        }
1347
0
        else {
1348
            /* Only move if not already the first one. */
1349
0
            if (node != _odict_FIRST(self)) {
1350
0
                _odict_remove_node(self, node);
1351
0
                _odict_add_head(self, node);
1352
0
            }
1353
0
        }
1354
2.91M
    }
1355
2.91M
    Py_RETURN_NONE;
1356
2.91M
}
1357
1358
1359
/* tp_methods */
1360
1361
static PyMethodDef odict_methods[] = {
1362
1363
    /* overridden dict methods */
1364
    ORDEREDDICT_FROMKEYS_METHODDEF
1365
    ORDEREDDICT___SIZEOF___METHODDEF
1366
    ORDEREDDICT___REDUCE___METHODDEF
1367
    ORDEREDDICT_SETDEFAULT_METHODDEF
1368
    ORDEREDDICT_POP_METHODDEF
1369
    ORDEREDDICT_POPITEM_METHODDEF
1370
    {"keys",            odictkeys_new,                  METH_NOARGS,
1371
     odict_keys__doc__},
1372
    {"values",          odictvalues_new,                METH_NOARGS,
1373
     odict_values__doc__},
1374
    {"items",           odictitems_new,                 METH_NOARGS,
1375
     odict_items__doc__},
1376
    {"update",          _PyCFunction_CAST(odict_update), METH_VARARGS | METH_KEYWORDS,
1377
     odict_update__doc__},
1378
     ORDEREDDICT_CLEAR_METHODDEF
1379
     ORDEREDDICT_COPY_METHODDEF
1380
    /* new methods */
1381
    {"__reversed__",    odict_reversed,    METH_NOARGS,
1382
     odict_reversed__doc__},
1383
    ORDEREDDICT_MOVE_TO_END_METHODDEF
1384
1385
    {NULL,              NULL}   /* sentinel */
1386
};
1387
1388
1389
/* ----------------------------------------------
1390
 * OrderedDict members
1391
 */
1392
1393
/* tp_getset */
1394
1395
static PyGetSetDef odict_getset[] = {
1396
    {"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict},
1397
    {NULL}
1398
};
1399
1400
/* ----------------------------------------------
1401
 * OrderedDict type slot methods
1402
 */
1403
1404
/* tp_dealloc */
1405
1406
static void
1407
odict_dealloc(PyObject *op)
1408
23.1k
{
1409
23.1k
    PyODictObject *self = _PyODictObject_CAST(op);
1410
23.1k
    PyObject_GC_UnTrack(self);
1411
1412
23.1k
    Py_XDECREF(self->od_inst_dict);
1413
23.1k
    FT_CLEAR_WEAKREFS(op, self->od_weakreflist);
1414
1415
23.1k
    _odict_clear_nodes(self);
1416
23.1k
    PyDict_Type.tp_dealloc((PyObject *)self);
1417
23.1k
}
1418
1419
/* tp_repr */
1420
1421
static PyObject *
1422
odict_repr(PyObject *op)
1423
0
{
1424
0
    PyODictObject *self = _PyODictObject_CAST(op);
1425
0
    int i;
1426
0
    PyObject *result = NULL, *dcopy = NULL;
1427
1428
0
    if (PyODict_SIZE(self) == 0)
1429
0
        return PyUnicode_FromFormat("%s()", _PyType_Name(Py_TYPE(self)));
1430
1431
0
    i = Py_ReprEnter((PyObject *)self);
1432
0
    if (i != 0) {
1433
0
        return i > 0 ? PyUnicode_FromString("...") : NULL;
1434
0
    }
1435
1436
0
    dcopy = PyDict_Copy((PyObject *)self);
1437
0
    if (dcopy == NULL) {
1438
0
        goto Done;
1439
0
    }
1440
1441
0
    result = PyUnicode_FromFormat("%s(%R)",
1442
0
                                  _PyType_Name(Py_TYPE(self)),
1443
0
                                  dcopy);
1444
0
    Py_DECREF(dcopy);
1445
1446
0
Done:
1447
0
    Py_ReprLeave((PyObject *)self);
1448
0
    return result;
1449
0
}
1450
1451
/* tp_doc */
1452
1453
PyDoc_STRVAR(odict_doc,
1454
        "Dictionary that remembers insertion order");
1455
1456
/* tp_traverse */
1457
1458
static int
1459
odict_traverse(PyObject *op, visitproc visit, void *arg)
1460
346
{
1461
346
    PyODictObject *od = _PyODictObject_CAST(op);
1462
346
    _ODictNode *node;
1463
1464
346
    Py_VISIT(od->od_inst_dict);
1465
990
    _odict_FOREACH(od, node) {
1466
990
        Py_VISIT(_odictnode_KEY(node));
1467
990
    }
1468
346
    return PyDict_Type.tp_traverse((PyObject *)od, visit, arg);
1469
346
}
1470
1471
/* tp_clear */
1472
1473
static int
1474
odict_tp_clear(PyObject *op)
1475
0
{
1476
0
    PyODictObject *od = _PyODictObject_CAST(op);
1477
0
    Py_CLEAR(od->od_inst_dict);
1478
    // cannot use lock held variant as critical section is not held here
1479
0
    PyDict_Clear(op);
1480
0
    _odict_clear_nodes(od);
1481
0
    return 0;
1482
0
}
1483
1484
/* tp_richcompare */
1485
1486
static PyObject *
1487
odict_richcompare_lock_held(PyObject *v, PyObject *w, int op)
1488
0
{
1489
0
    if (!PyODict_Check(v) || !PyDict_Check(w)) {
1490
0
        Py_RETURN_NOTIMPLEMENTED;
1491
0
    }
1492
1493
0
    if (op == Py_EQ || op == Py_NE) {
1494
0
        PyObject *res, *cmp;
1495
0
        int eq;
1496
1497
0
        cmp = PyDict_Type.tp_richcompare(v, w, op);
1498
0
        if (cmp == NULL)
1499
0
            return NULL;
1500
0
        if (!PyODict_Check(w))
1501
0
            return cmp;
1502
0
        if (op == Py_EQ && cmp == Py_False)
1503
0
            return cmp;
1504
0
        if (op == Py_NE && cmp == Py_True)
1505
0
            return cmp;
1506
0
        Py_DECREF(cmp);
1507
1508
        /* Try comparing odict keys. */
1509
0
        eq = _odict_keys_equal(_PyODictObject_CAST(v), _PyODictObject_CAST(w));
1510
0
        if (eq < 0)
1511
0
            return NULL;
1512
1513
0
        res = (eq == (op == Py_EQ)) ? Py_True : Py_False;
1514
0
        return Py_NewRef(res);
1515
0
    } else {
1516
0
        Py_RETURN_NOTIMPLEMENTED;
1517
0
    }
1518
0
}
1519
1520
static PyObject *
1521
odict_richcompare(PyObject *v, PyObject *w, int op)
1522
0
{
1523
0
    PyObject *res;
1524
0
    Py_BEGIN_CRITICAL_SECTION2(v, w);
1525
0
    res = odict_richcompare_lock_held(v, w, op);
1526
0
    Py_END_CRITICAL_SECTION2();
1527
0
    return res;
1528
0
}
1529
1530
/* tp_iter */
1531
1532
static PyObject *
1533
odict_iter(PyObject *op)
1534
15.2k
{
1535
15.2k
    return odictiter_new(_PyODictObject_CAST(op), _odict_ITER_KEYS);
1536
15.2k
}
1537
1538
/* tp_init */
1539
1540
static int
1541
odict_init(PyObject *self, PyObject *args, PyObject *kwds)
1542
23.2k
{
1543
23.2k
    PyObject *res;
1544
23.2k
    Py_ssize_t len = PyObject_Length(args);
1545
1546
23.2k
    if (len == -1)
1547
0
        return -1;
1548
23.2k
    if (len > 1) {
1549
0
        const char *msg = "expected at most 1 argument, got %zd";
1550
0
        PyErr_Format(PyExc_TypeError, msg, len);
1551
0
        return -1;
1552
0
    }
1553
1554
    /* __init__() triggering update() is just the way things are! */
1555
23.2k
    res = odict_update(self, args, kwds);
1556
23.2k
    if (res == NULL) {
1557
0
        return -1;
1558
23.2k
    } else {
1559
23.2k
        Py_DECREF(res);
1560
23.2k
        return 0;
1561
23.2k
    }
1562
23.2k
}
1563
1564
/* PyODict_Type */
1565
1566
PyTypeObject PyODict_Type = {
1567
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
1568
    "collections.OrderedDict",                  /* tp_name */
1569
    sizeof(PyODictObject),                      /* tp_basicsize */
1570
    0,                                          /* tp_itemsize */
1571
    odict_dealloc,                              /* tp_dealloc */
1572
    0,                                          /* tp_vectorcall_offset */
1573
    0,                                          /* tp_getattr */
1574
    0,                                          /* tp_setattr */
1575
    0,                                          /* tp_as_async */
1576
    odict_repr,                                 /* tp_repr */
1577
    &odict_as_number,                           /* tp_as_number */
1578
    0,                                          /* tp_as_sequence */
1579
    &odict_as_mapping,                          /* tp_as_mapping */
1580
    0,                                          /* tp_hash */
1581
    0,                                          /* tp_call */
1582
    0,                                          /* tp_str */
1583
    0,                                          /* tp_getattro */
1584
    0,                                          /* tp_setattro */
1585
    0,                                          /* tp_as_buffer */
1586
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,/* tp_flags */
1587
    odict_doc,                                  /* tp_doc */
1588
    odict_traverse,                             /* tp_traverse */
1589
    odict_tp_clear,                             /* tp_clear */
1590
    odict_richcompare,                          /* tp_richcompare */
1591
    offsetof(PyODictObject, od_weakreflist),    /* tp_weaklistoffset */
1592
    odict_iter,                                 /* tp_iter */
1593
    0,                                          /* tp_iternext */
1594
    odict_methods,                              /* tp_methods */
1595
    0,                                          /* tp_members */
1596
    odict_getset,                               /* tp_getset */
1597
    &PyDict_Type,                               /* tp_base */
1598
    0,                                          /* tp_dict */
1599
    0,                                          /* tp_descr_get */
1600
    0,                                          /* tp_descr_set */
1601
    offsetof(PyODictObject, od_inst_dict),      /* tp_dictoffset */
1602
    odict_init,                                 /* tp_init */
1603
    PyType_GenericAlloc,                        /* tp_alloc */
1604
    0,                                          /* tp_new */
1605
    0,                                          /* tp_free */
1606
};
1607
1608
1609
/* ----------------------------------------------
1610
 * the public OrderedDict API
1611
 */
1612
1613
PyObject *
1614
PyODict_New(void)
1615
0
{
1616
0
    return PyDict_Type.tp_new(&PyODict_Type, NULL, NULL);
1617
0
}
1618
1619
static int
1620
_PyODict_SetItem_KnownHash_LockHeld(PyObject *od, PyObject *key, PyObject *value,
1621
                                    Py_hash_t hash)
1622
33.2k
{
1623
33.2k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
1624
33.2k
    int res = _PyDict_SetItem_KnownHash_LockHeld((PyDictObject *)od, key, value, hash);
1625
33.2k
    if (res == 0) {
1626
33.2k
        res = _odict_add_new_node(_PyODictObject_CAST(od), key, hash);
1627
33.2k
        if (res < 0) {
1628
            /* Revert setting the value on the dict */
1629
0
            PyObject *exc = PyErr_GetRaisedException();
1630
0
            (void) _PyDict_DelItem_KnownHash(od, key, hash);
1631
0
            _PyErr_ChainExceptions1(exc);
1632
0
        }
1633
33.2k
    }
1634
33.2k
    return res;
1635
33.2k
}
1636
1637
1638
static int
1639
PyODict_SetItem_LockHeld(PyObject *od, PyObject *key, PyObject *value)
1640
33.2k
{
1641
33.2k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
1642
33.2k
    Py_hash_t hash = PyObject_Hash(key);
1643
33.2k
    if (hash == -1) {
1644
0
        return -1;
1645
0
    }
1646
33.2k
    return _PyODict_SetItem_KnownHash_LockHeld(od, key, value, hash);
1647
33.2k
}
1648
1649
int
1650
PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value)
1651
33.2k
{
1652
33.2k
    int res;
1653
33.2k
    Py_BEGIN_CRITICAL_SECTION(od);
1654
33.2k
    res = PyODict_SetItem_LockHeld(od, key, value);
1655
33.2k
    Py_END_CRITICAL_SECTION();
1656
33.2k
    return res;
1657
33.2k
}
1658
1659
int
1660
PyODict_DelItem_LockHeld(PyObject *od, PyObject *key)
1661
0
{
1662
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(od);
1663
0
    int res;
1664
0
    Py_hash_t hash = PyObject_Hash(key);
1665
0
    if (hash == -1)
1666
0
        return -1;
1667
0
    res = _odict_clear_node(_PyODictObject_CAST(od), NULL, key, hash);
1668
0
    if (res < 0)
1669
0
        return -1;
1670
0
    return _PyDict_DelItem_KnownHash_LockHeld(od, key, hash);
1671
0
}
1672
1673
int
1674
PyODict_DelItem(PyObject *od, PyObject *key)
1675
0
{
1676
0
    int res;
1677
0
    Py_BEGIN_CRITICAL_SECTION(od);
1678
0
    res = PyODict_DelItem_LockHeld(od, key);
1679
0
    Py_END_CRITICAL_SECTION();
1680
0
    return res;
1681
0
}
1682
1683
/* -------------------------------------------
1684
 * The OrderedDict views (keys/values/items)
1685
 */
1686
1687
typedef struct {
1688
    PyObject_HEAD
1689
    int kind;
1690
    PyODictObject *di_odict;
1691
    Py_ssize_t di_size;
1692
    size_t di_state;
1693
    PyObject *di_current;
1694
    PyObject *di_result; /* reusable result tuple for iteritems */
1695
} odictiterobject;
1696
1697
static void
1698
odictiter_dealloc(PyObject *op)
1699
99.5k
{
1700
99.5k
    odictiterobject *di = (odictiterobject*)op;
1701
99.5k
    _PyObject_GC_UNTRACK(di);
1702
99.5k
    Py_XDECREF(di->di_odict);
1703
99.5k
    Py_XDECREF(di->di_current);
1704
99.5k
    if ((di->kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) {
1705
8
        Py_DECREF(di->di_result);
1706
8
    }
1707
99.5k
    PyObject_GC_Del(di);
1708
99.5k
}
1709
1710
static int
1711
odictiter_traverse(PyObject *op, visitproc visit, void *arg)
1712
0
{
1713
0
    odictiterobject *di = (odictiterobject*)op;
1714
0
    Py_VISIT(di->di_odict);
1715
0
    Py_VISIT(di->di_current);  /* A key could be any type, not just str. */
1716
0
    Py_VISIT(di->di_result);
1717
0
    return 0;
1718
0
}
1719
1720
/* In order to protect against modifications during iteration, we track
1721
 * the current key instead of the current node. */
1722
static PyObject *
1723
odictiter_nextkey_lock_held(odictiterobject *di)
1724
198k
{
1725
198k
    assert(di->di_odict != NULL);
1726
198k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(di->di_odict);
1727
198k
    PyObject *key = NULL;
1728
198k
    _ODictNode *node;
1729
198k
    int reversed = di->kind & _odict_ITER_REVERSED;
1730
1731
198k
    if (di->di_current == NULL)
1732
91.9k
        goto done;  /* We're already done. */
1733
1734
    /* Check for unsupported changes. */
1735
106k
    if (di->di_odict->od_state != di->di_state) {
1736
0
        PyErr_SetString(PyExc_RuntimeError,
1737
0
                        "OrderedDict mutated during iteration");
1738
0
        goto done;
1739
0
    }
1740
106k
    if (di->di_size != PyODict_SIZE(di->di_odict)) {
1741
0
        PyErr_SetString(PyExc_RuntimeError,
1742
0
                        "OrderedDict changed size during iteration");
1743
0
        di->di_size = -1; /* Make this state sticky */
1744
0
        return NULL;
1745
0
    }
1746
1747
    /* Get the key. */
1748
106k
    node = _odict_find_node(di->di_odict, di->di_current);
1749
106k
    if (node == NULL) {
1750
0
        if (!PyErr_Occurred())
1751
0
            PyErr_SetObject(PyExc_KeyError, di->di_current);
1752
        /* Must have been deleted. */
1753
0
        Py_CLEAR(di->di_current);
1754
0
        return NULL;
1755
0
    }
1756
106k
    key = di->di_current;
1757
1758
    /* Advance to the next key. */
1759
106k
    node = reversed ? _odictnode_PREV(node) : _odictnode_NEXT(node);
1760
106k
    if (node == NULL) {
1761
        /* Reached the end. */
1762
91.4k
        di->di_current = NULL;
1763
91.4k
    }
1764
14.7k
    else {
1765
14.7k
        di->di_current = Py_NewRef(_odictnode_KEY(node));
1766
14.7k
    }
1767
1768
106k
    return key;
1769
1770
91.9k
done:
1771
91.9k
    Py_CLEAR(di->di_odict);
1772
91.9k
    return key;
1773
106k
}
1774
1775
1776
static PyObject *
1777
odictiter_nextkey(odictiterobject *di)
1778
198k
{
1779
198k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(di);
1780
198k
    if (di->di_odict == NULL) {
1781
8
        return NULL;
1782
8
    }
1783
198k
    PyObject *res;
1784
198k
    Py_BEGIN_CRITICAL_SECTION(di->di_odict);
1785
198k
    res = odictiter_nextkey_lock_held(di);
1786
198k
    Py_END_CRITICAL_SECTION();
1787
198k
    return res;
1788
198k
}
1789
1790
static PyObject *
1791
odictiter_iternext_lock_held(PyObject *op)
1792
198k
{
1793
198k
    odictiterobject *di = (odictiterobject*)op;
1794
198k
    PyObject *result, *value;
1795
198k
    PyObject *key = odictiter_nextkey(di);  /* new reference */
1796
1797
198k
    if (key == NULL)
1798
91.9k
        return NULL;
1799
1800
    /* Handle the keys case. */
1801
106k
    if (! (di->kind & _odict_ITER_VALUES)) {
1802
16.1k
        return key;
1803
16.1k
    }
1804
1805
90.0k
    if (PyDict_GetItemRef((PyObject *)di->di_odict, key, &value) != 1) {
1806
0
        if (!PyErr_Occurred())
1807
0
            PyErr_SetObject(PyExc_KeyError, key);
1808
0
        Py_DECREF(key);
1809
0
        goto error;
1810
0
    }
1811
1812
    /* Handle the values case. */
1813
90.0k
    if (!(di->kind & _odict_ITER_KEYS)) {
1814
90.0k
        Py_DECREF(key);
1815
90.0k
        return value;
1816
90.0k
    }
1817
1818
    /* Handle the items case. */
1819
24
    result = di->di_result;
1820
1821
24
    if (_PyObject_IsUniquelyReferenced(result)) {
1822
        /* not in use so we can reuse it
1823
         * (the common case during iteration) */
1824
24
        Py_INCREF(result);
1825
24
        Py_DECREF(PyTuple_GET_ITEM(result, 0));  /* borrowed */
1826
24
        Py_DECREF(PyTuple_GET_ITEM(result, 1));  /* borrowed */
1827
        // bpo-42536: The GC may have untracked this result tuple. Since we're
1828
        // recycling it, make sure it's tracked again:
1829
24
        _PyTuple_Recycle(result);
1830
24
        PyTuple_SET_ITEM(result, 0, key);  /* steals reference */
1831
24
        PyTuple_SET_ITEM(result, 1, value);  /* steals reference */
1832
24
    }
1833
0
    else {
1834
0
        result = _PyTuple_FromPairSteal(key, value);
1835
0
        if (result == NULL) {
1836
0
            goto error;
1837
0
        }
1838
0
    }
1839
1840
24
    return result;
1841
1842
0
error:
1843
0
    Py_CLEAR(di->di_current);
1844
0
    Py_CLEAR(di->di_odict);
1845
0
    return NULL;
1846
24
}
1847
1848
static PyObject *
1849
odictiter_iternext(PyObject *op)
1850
198k
{
1851
198k
    PyObject *res;
1852
198k
    Py_BEGIN_CRITICAL_SECTION(op);
1853
198k
    res = odictiter_iternext_lock_held(op);
1854
198k
    Py_END_CRITICAL_SECTION();
1855
198k
    return res;
1856
198k
}
1857
1858
1859
/* No need for tp_clear because odictiterobject is not mutable. */
1860
1861
PyDoc_STRVAR(reduce_doc, "Return state information for pickling");
1862
1863
static PyObject *
1864
odictiter_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
1865
0
{
1866
0
    odictiterobject *di = (odictiterobject*)op;
1867
1868
    /* copy the iterator state */
1869
0
    odictiterobject tmp = *di;
1870
0
    Py_XINCREF(tmp.di_odict);
1871
0
    Py_XINCREF(tmp.di_current);
1872
1873
    /* iterate the temporary into a list */
1874
0
    PyObject *list = PySequence_List((PyObject*)&tmp);
1875
0
    Py_XDECREF(tmp.di_odict);
1876
0
    Py_XDECREF(tmp.di_current);
1877
0
    if (list == NULL) {
1878
0
        return NULL;
1879
0
    }
1880
0
    return Py_BuildValue("N(N)", _PyEval_GetBuiltin(&_Py_ID(iter)), list);
1881
0
}
1882
1883
static PyMethodDef odictiter_methods[] = {
1884
    {"__reduce__", odictiter_reduce, METH_NOARGS, reduce_doc},
1885
    {NULL,              NULL}           /* sentinel */
1886
};
1887
1888
PyTypeObject PyODictIter_Type = {
1889
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
1890
    "odict_iterator",                         /* tp_name */
1891
    sizeof(odictiterobject),                  /* tp_basicsize */
1892
    0,                                        /* tp_itemsize */
1893
    /* methods */
1894
    odictiter_dealloc,                        /* tp_dealloc */
1895
    0,                                        /* tp_vectorcall_offset */
1896
    0,                                        /* tp_getattr */
1897
    0,                                        /* tp_setattr */
1898
    0,                                        /* tp_as_async */
1899
    0,                                        /* tp_repr */
1900
    0,                                        /* tp_as_number */
1901
    0,                                        /* tp_as_sequence */
1902
    0,                                        /* tp_as_mapping */
1903
    0,                                        /* tp_hash */
1904
    0,                                        /* tp_call */
1905
    0,                                        /* tp_str */
1906
    PyObject_GenericGetAttr,                  /* tp_getattro */
1907
    0,                                        /* tp_setattro */
1908
    0,                                        /* tp_as_buffer */
1909
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,  /* tp_flags */
1910
    0,                                        /* tp_doc */
1911
    odictiter_traverse,                       /* tp_traverse */
1912
    0,                                        /* tp_clear */
1913
    0,                                        /* tp_richcompare */
1914
    0,                                        /* tp_weaklistoffset */
1915
    PyObject_SelfIter,                        /* tp_iter */
1916
    odictiter_iternext,                       /* tp_iternext */
1917
    odictiter_methods,                        /* tp_methods */
1918
    0,
1919
};
1920
1921
static PyObject *
1922
odictiter_new(PyODictObject *od, int kind)
1923
99.5k
{
1924
99.5k
    odictiterobject *di;
1925
99.5k
    _ODictNode *node;
1926
99.5k
    int reversed = kind & _odict_ITER_REVERSED;
1927
1928
99.5k
    di = PyObject_GC_New(odictiterobject, &PyODictIter_Type);
1929
99.5k
    if (di == NULL)
1930
0
        return NULL;
1931
1932
99.5k
    if ((kind & _odict_ITER_ITEMS) == _odict_ITER_ITEMS) {
1933
8
        di->di_result = _PyTuple_FromPairSteal(Py_None, Py_None);
1934
8
        if (di->di_result == NULL) {
1935
0
            Py_DECREF(di);
1936
0
            return NULL;
1937
0
        }
1938
8
    }
1939
99.5k
    else {
1940
99.5k
        di->di_result = NULL;
1941
99.5k
    }
1942
1943
99.5k
    di->kind = kind;
1944
99.5k
    node = reversed ? _odict_LAST(od) : _odict_FIRST(od);
1945
99.5k
    di->di_current = node ? Py_NewRef(_odictnode_KEY(node)) : NULL;
1946
99.5k
    di->di_size = PyODict_SIZE(od);
1947
99.5k
    di->di_state = od->od_state;
1948
99.5k
    di->di_odict = (PyODictObject*)Py_NewRef(od);
1949
1950
99.5k
    _PyObject_GC_TRACK(di);
1951
99.5k
    return (PyObject *)di;
1952
99.5k
}
1953
1954
/* keys() */
1955
1956
static PyObject *
1957
odictkeys_iter(PyObject *op)
1958
0
{
1959
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
1960
0
    if (dv->dv_dict == NULL) {
1961
0
        Py_RETURN_NONE;
1962
0
    }
1963
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
1964
0
            _odict_ITER_KEYS);
1965
0
}
1966
1967
static PyObject *
1968
odictkeys_reversed(PyObject *op, PyObject *Py_UNUSED(ignored))
1969
0
{
1970
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
1971
0
    if (dv->dv_dict == NULL) {
1972
0
        Py_RETURN_NONE;
1973
0
    }
1974
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
1975
0
            _odict_ITER_KEYS|_odict_ITER_REVERSED);
1976
0
}
1977
1978
static PyMethodDef odictkeys_methods[] = {
1979
    {"__reversed__", odictkeys_reversed, METH_NOARGS, NULL},
1980
    {NULL,          NULL}           /* sentinel */
1981
};
1982
1983
PyTypeObject PyODictKeys_Type = {
1984
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
1985
    "odict_keys",                             /* tp_name */
1986
    0,                                        /* tp_basicsize */
1987
    0,                                        /* tp_itemsize */
1988
    0,                                        /* tp_dealloc */
1989
    0,                                        /* tp_vectorcall_offset */
1990
    0,                                        /* tp_getattr */
1991
    0,                                        /* tp_setattr */
1992
    0,                                        /* tp_as_async */
1993
    0,                                        /* tp_repr */
1994
    0,                                        /* tp_as_number */
1995
    0,                                        /* tp_as_sequence */
1996
    0,                                        /* tp_as_mapping */
1997
    0,                                        /* tp_hash */
1998
    0,                                        /* tp_call */
1999
    0,                                        /* tp_str */
2000
    0,                                        /* tp_getattro */
2001
    0,                                        /* tp_setattro */
2002
    0,                                        /* tp_as_buffer */
2003
    0,                                        /* tp_flags */
2004
    0,                                        /* tp_doc */
2005
    0,                                        /* tp_traverse */
2006
    0,                                        /* tp_clear */
2007
    0,                                        /* tp_richcompare */
2008
    0,                                        /* tp_weaklistoffset */
2009
    odictkeys_iter,                           /* tp_iter */
2010
    0,                                        /* tp_iternext */
2011
    odictkeys_methods,                        /* tp_methods */
2012
    0,                                        /* tp_members */
2013
    0,                                        /* tp_getset */
2014
    &PyDictKeys_Type,                         /* tp_base */
2015
};
2016
2017
static PyObject *
2018
odictkeys_new(PyObject *od, PyObject *Py_UNUSED(ignored))
2019
0
{
2020
0
    return _PyDictView_New(od, &PyODictKeys_Type);
2021
0
}
2022
2023
/* items() */
2024
2025
static PyObject *
2026
odictitems_iter(PyObject *op)
2027
8
{
2028
8
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
2029
8
    if (dv->dv_dict == NULL) {
2030
0
        Py_RETURN_NONE;
2031
0
    }
2032
8
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
2033
8
            _odict_ITER_KEYS|_odict_ITER_VALUES);
2034
8
}
2035
2036
static PyObject *
2037
odictitems_reversed(PyObject *op, PyObject *Py_UNUSED(ignored))
2038
0
{
2039
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
2040
0
    if (dv->dv_dict == NULL) {
2041
0
        Py_RETURN_NONE;
2042
0
    }
2043
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
2044
0
            _odict_ITER_KEYS|_odict_ITER_VALUES|_odict_ITER_REVERSED);
2045
0
}
2046
2047
static PyMethodDef odictitems_methods[] = {
2048
    {"__reversed__", odictitems_reversed, METH_NOARGS, NULL},
2049
    {NULL,          NULL}           /* sentinel */
2050
};
2051
2052
PyTypeObject PyODictItems_Type = {
2053
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2054
    "odict_items",                            /* tp_name */
2055
    0,                                        /* tp_basicsize */
2056
    0,                                        /* tp_itemsize */
2057
    0,                                        /* tp_dealloc */
2058
    0,                                        /* tp_vectorcall_offset */
2059
    0,                                        /* tp_getattr */
2060
    0,                                        /* tp_setattr */
2061
    0,                                        /* tp_as_async */
2062
    0,                                        /* tp_repr */
2063
    0,                                        /* tp_as_number */
2064
    0,                                        /* tp_as_sequence */
2065
    0,                                        /* tp_as_mapping */
2066
    0,                                        /* tp_hash */
2067
    0,                                        /* tp_call */
2068
    0,                                        /* tp_str */
2069
    0,                                        /* tp_getattro */
2070
    0,                                        /* tp_setattro */
2071
    0,                                        /* tp_as_buffer */
2072
    0,                                        /* tp_flags */
2073
    0,                                        /* tp_doc */
2074
    0,                                        /* tp_traverse */
2075
    0,                                        /* tp_clear */
2076
    0,                                        /* tp_richcompare */
2077
    0,                                        /* tp_weaklistoffset */
2078
    odictitems_iter,                          /* tp_iter */
2079
    0,                                        /* tp_iternext */
2080
    odictitems_methods,                       /* tp_methods */
2081
    0,                                        /* tp_members */
2082
    0,                                        /* tp_getset */
2083
    &PyDictItems_Type,                        /* tp_base */
2084
};
2085
2086
static PyObject *
2087
odictitems_new(PyObject *od, PyObject *Py_UNUSED(ignored))
2088
8
{
2089
8
    return _PyDictView_New(od, &PyODictItems_Type);
2090
8
}
2091
2092
/* values() */
2093
2094
static PyObject *
2095
odictvalues_iter(PyObject *op)
2096
84.2k
{
2097
84.2k
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
2098
84.2k
    if (dv->dv_dict == NULL) {
2099
0
        Py_RETURN_NONE;
2100
0
    }
2101
84.2k
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
2102
84.2k
            _odict_ITER_VALUES);
2103
84.2k
}
2104
2105
static PyObject *
2106
odictvalues_reversed(PyObject *op, PyObject *Py_UNUSED(ignored))
2107
0
{
2108
0
    _PyDictViewObject *dv = (_PyDictViewObject*)op;
2109
0
    if (dv->dv_dict == NULL) {
2110
0
        Py_RETURN_NONE;
2111
0
    }
2112
0
    return odictiter_new(_PyODictObject_CAST(dv->dv_dict),
2113
0
            _odict_ITER_VALUES|_odict_ITER_REVERSED);
2114
0
}
2115
2116
static PyMethodDef odictvalues_methods[] = {
2117
    {"__reversed__", odictvalues_reversed, METH_NOARGS, NULL},
2118
    {NULL,          NULL}           /* sentinel */
2119
};
2120
2121
PyTypeObject PyODictValues_Type = {
2122
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2123
    "odict_values",                           /* tp_name */
2124
    0,                                        /* tp_basicsize */
2125
    0,                                        /* tp_itemsize */
2126
    0,                                        /* tp_dealloc */
2127
    0,                                        /* tp_vectorcall_offset */
2128
    0,                                        /* tp_getattr */
2129
    0,                                        /* tp_setattr */
2130
    0,                                        /* tp_as_async */
2131
    0,                                        /* tp_repr */
2132
    0,                                        /* tp_as_number */
2133
    0,                                        /* tp_as_sequence */
2134
    0,                                        /* tp_as_mapping */
2135
    0,                                        /* tp_hash */
2136
    0,                                        /* tp_call */
2137
    0,                                        /* tp_str */
2138
    0,                                        /* tp_getattro */
2139
    0,                                        /* tp_setattro */
2140
    0,                                        /* tp_as_buffer */
2141
    0,                                        /* tp_flags */
2142
    0,                                        /* tp_doc */
2143
    0,                                        /* tp_traverse */
2144
    0,                                        /* tp_clear */
2145
    0,                                        /* tp_richcompare */
2146
    0,                                        /* tp_weaklistoffset */
2147
    odictvalues_iter,                         /* tp_iter */
2148
    0,                                        /* tp_iternext */
2149
    odictvalues_methods,                      /* tp_methods */
2150
    0,                                        /* tp_members */
2151
    0,                                        /* tp_getset */
2152
    &PyDictValues_Type,                       /* tp_base */
2153
};
2154
2155
static PyObject *
2156
odictvalues_new(PyObject *od, PyObject *Py_UNUSED(ignored))
2157
84.2k
{
2158
84.2k
    return _PyDictView_New(od, &PyODictValues_Type);
2159
84.2k
}
2160
2161
2162
/* ----------------------------------------------
2163
   MutableMapping implementations
2164
2165
Mapping:
2166
2167
============ ===========
2168
method       uses
2169
============ ===========
2170
__contains__ __getitem__
2171
__eq__       items
2172
__getitem__  +
2173
__iter__     +
2174
__len__      +
2175
__ne__       __eq__
2176
get          __getitem__
2177
items        ItemsView
2178
keys         KeysView
2179
values       ValuesView
2180
============ ===========
2181
2182
ItemsView uses __len__, __iter__, and __getitem__.
2183
KeysView uses __len__, __iter__, and __contains__.
2184
ValuesView uses __len__, __iter__, and __getitem__.
2185
2186
MutableMapping:
2187
2188
============ ===========
2189
method       uses
2190
============ ===========
2191
__delitem__  +
2192
__setitem__  +
2193
clear        popitem
2194
pop          __getitem__
2195
             __delitem__
2196
popitem      __iter__
2197
             _getitem__
2198
             __delitem__
2199
setdefault   __getitem__
2200
             __setitem__
2201
update       __setitem__
2202
============ ===========
2203
*/
2204
2205
static int
2206
mutablemapping_add_pairs(PyObject *self, PyObject *pairs)
2207
15.4k
{
2208
15.4k
    PyObject *pair, *iterator, *unexpected;
2209
15.4k
    int res = 0;
2210
2211
15.4k
    iterator = PyObject_GetIter(pairs);
2212
15.4k
    if (iterator == NULL)
2213
0
        return -1;
2214
15.4k
    PyErr_Clear();
2215
2216
39.7k
    while ((pair = PyIter_Next(iterator)) != NULL) {
2217
        /* could be more efficient (see UNPACK_SEQUENCE in ceval.c) */
2218
24.3k
        PyObject *key = NULL, *value = NULL;
2219
24.3k
        PyObject *pair_iterator = PyObject_GetIter(pair);
2220
24.3k
        if (pair_iterator == NULL)
2221
0
            goto Done;
2222
2223
24.3k
        key = PyIter_Next(pair_iterator);
2224
24.3k
        if (key == NULL) {
2225
0
            if (!PyErr_Occurred())
2226
0
                PyErr_SetString(PyExc_ValueError,
2227
0
                                "need more than 0 values to unpack");
2228
0
            goto Done;
2229
0
        }
2230
2231
24.3k
        value = PyIter_Next(pair_iterator);
2232
24.3k
        if (value == NULL) {
2233
0
            if (!PyErr_Occurred())
2234
0
                PyErr_SetString(PyExc_ValueError,
2235
0
                                "need more than 1 value to unpack");
2236
0
            goto Done;
2237
0
        }
2238
2239
24.3k
        unexpected = PyIter_Next(pair_iterator);
2240
24.3k
        if (unexpected != NULL) {
2241
0
            Py_DECREF(unexpected);
2242
0
            PyErr_SetString(PyExc_ValueError,
2243
0
                            "too many values to unpack (expected 2)");
2244
0
            goto Done;
2245
0
        }
2246
24.3k
        else if (PyErr_Occurred())
2247
0
            goto Done;
2248
2249
24.3k
        res = PyObject_SetItem(self, key, value);
2250
2251
24.3k
Done:
2252
24.3k
        Py_DECREF(pair);
2253
24.3k
        Py_XDECREF(pair_iterator);
2254
24.3k
        Py_XDECREF(key);
2255
24.3k
        Py_XDECREF(value);
2256
24.3k
        if (PyErr_Occurred())
2257
0
            break;
2258
24.3k
    }
2259
15.4k
    Py_DECREF(iterator);
2260
2261
15.4k
    if (res < 0 || PyErr_Occurred() != NULL)
2262
0
        return -1;
2263
15.4k
    else
2264
15.4k
        return 0;
2265
15.4k
}
2266
2267
static int
2268
mutablemapping_update_arg(PyObject *self, PyObject *arg)
2269
15.4k
{
2270
15.4k
    int res = 0;
2271
15.4k
    if (PyAnyDict_CheckExact(arg)) {
2272
0
        PyObject *items = PyDict_Items(arg);
2273
0
        if (items == NULL) {
2274
0
            return -1;
2275
0
        }
2276
0
        res = mutablemapping_add_pairs(self, items);
2277
0
        Py_DECREF(items);
2278
0
        return res;
2279
0
    }
2280
15.4k
    PyObject *func;
2281
15.4k
    if (PyObject_GetOptionalAttr(arg, &_Py_ID(keys), &func) < 0) {
2282
0
        return -1;
2283
0
    }
2284
15.4k
    if (func != NULL) {
2285
0
        PyObject *keys = _PyObject_CallNoArgs(func);
2286
0
        Py_DECREF(func);
2287
0
        if (keys == NULL) {
2288
0
            return -1;
2289
0
        }
2290
0
        PyObject *iterator = PyObject_GetIter(keys);
2291
0
        Py_DECREF(keys);
2292
0
        if (iterator == NULL) {
2293
0
            return -1;
2294
0
        }
2295
0
        PyObject *key;
2296
0
        while (res == 0 && (key = PyIter_Next(iterator))) {
2297
0
            PyObject *value = PyObject_GetItem(arg, key);
2298
0
            if (value != NULL) {
2299
0
                res = PyObject_SetItem(self, key, value);
2300
0
                Py_DECREF(value);
2301
0
            }
2302
0
            else {
2303
0
                res = -1;
2304
0
            }
2305
0
            Py_DECREF(key);
2306
0
        }
2307
0
        Py_DECREF(iterator);
2308
0
        if (res != 0 || PyErr_Occurred()) {
2309
0
            return -1;
2310
0
        }
2311
0
        return 0;
2312
0
    }
2313
15.4k
    if (PyObject_GetOptionalAttr(arg, &_Py_ID(items), &func) < 0) {
2314
0
        return -1;
2315
0
    }
2316
15.4k
    if (func != NULL) {
2317
0
        PyObject *items = _PyObject_CallNoArgs(func);
2318
0
        Py_DECREF(func);
2319
0
        if (items == NULL) {
2320
0
            return -1;
2321
0
        }
2322
0
        res = mutablemapping_add_pairs(self, items);
2323
0
        Py_DECREF(items);
2324
0
        return res;
2325
0
    }
2326
15.4k
    res = mutablemapping_add_pairs(self, arg);
2327
15.4k
    return res;
2328
15.4k
}
2329
2330
static PyObject *
2331
mutablemapping_update(PyObject *self, PyObject *args, PyObject *kwargs)
2332
23.2k
{
2333
23.2k
    int res;
2334
    /* first handle args, if any */
2335
23.2k
    assert(args == NULL || PyTuple_Check(args));
2336
23.2k
    Py_ssize_t len = (args != NULL) ? PyTuple_GET_SIZE(args) : 0;
2337
23.2k
    if (len > 1) {
2338
0
        const char *msg = "update() takes at most 1 positional argument (%zd given)";
2339
0
        PyErr_Format(PyExc_TypeError, msg, len);
2340
0
        return NULL;
2341
0
    }
2342
2343
23.2k
    if (len) {
2344
15.4k
        PyObject *other = PyTuple_GET_ITEM(args, 0);  /* borrowed reference */
2345
15.4k
        assert(other != NULL);
2346
15.4k
        Py_INCREF(other);
2347
15.4k
        res = mutablemapping_update_arg(self, other);
2348
15.4k
        Py_DECREF(other);
2349
15.4k
        if (res < 0) {
2350
0
            return NULL;
2351
0
        }
2352
15.4k
    }
2353
2354
    /* now handle kwargs */
2355
23.2k
    assert(kwargs == NULL || PyDict_Check(kwargs));
2356
23.2k
    if (kwargs != NULL && PyDict_GET_SIZE(kwargs)) {
2357
0
        PyObject *items = PyDict_Items(kwargs);
2358
0
        if (items == NULL)
2359
0
            return NULL;
2360
0
        res = mutablemapping_add_pairs(self, items);
2361
0
        Py_DECREF(items);
2362
0
        if (res == -1)
2363
0
            return NULL;
2364
0
    }
2365
2366
23.2k
    Py_RETURN_NONE;
2367
23.2k
}