Skip to content
4 changes: 4 additions & 0 deletions Include/cpython/dictobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,7 @@ typedef struct {

PyAPI_FUNC(PyObject *) _PyDictView_New(PyObject *, PyTypeObject *);
PyAPI_FUNC(PyObject *) _PyDictView_Intersect(PyObject* self, PyObject *other);

/* Gets a version number unique to the current state of the keys of dict, if possible.
* Returns the version number, or zero if it was not possible to get a version number. */
uint32_t _PyDictKeys_GetVersionForCurrentState(PyDictObject *dict);
2 changes: 1 addition & 1 deletion Lib/test/test_ordered_dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,7 @@ def test_sizeof_exact(self):
check = self.check_sizeof

basicsize = size('nQ2P' + '3PnPn2P')
keysize = calcsize('2nP2n')
keysize = calcsize('n2BI2n')

entrysize = calcsize('n2P')
p = calcsize('P')
Expand Down
9 changes: 5 additions & 4 deletions Lib/test/test_sys.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
# strings to intern in test_intern()
INTERN_NUMRUNS = 0

DICT_KEY_STRUCT_FORMAT = 'n2BI2n'

class DisplayHookTest(unittest.TestCase):

Expand Down Expand Up @@ -1229,9 +1230,9 @@ def inner():
# empty dict
check({}, size('nQ2P'))
# dict
check({"a": 1}, size('nQ2P') + calcsize('2nP2n') + 8 + (8*2//3)*calcsize('n2P'))
check({"a": 1}, size('nQ2P') + calcsize(DICT_KEY_STRUCT_FORMAT) + 8 + (8*2//3)*calcsize('n2P'))
longdict = {1:1, 2:2, 3:3, 4:4, 5:5, 6:6, 7:7, 8:8}
check(longdict, size('nQ2P') + calcsize('2nP2n') + 16 + (16*2//3)*calcsize('n2P'))
check(longdict, size('nQ2P') + calcsize(DICT_KEY_STRUCT_FORMAT) + 16 + (16*2//3)*calcsize('n2P'))
# dictionary-keyview
check({}.keys(), size('P'))
# dictionary-valueview
Expand Down Expand Up @@ -1385,13 +1386,13 @@ def delx(self): del self.__x
'5P')
class newstyleclass(object): pass
# Separate block for PyDictKeysObject with 8 keys and 5 entries
check(newstyleclass, s + calcsize("2nP2n0P") + 8 + 5*calcsize("n2P"))
check(newstyleclass, s + calcsize(DICT_KEY_STRUCT_FORMAT) + 8 + 5*calcsize("n2P"))
# dict with shared keys
check(newstyleclass().__dict__, size('nQ2P') + 5*self.P)
o = newstyleclass()
o.a = o.b = o.c = o.d = o.e = o.f = o.g = o.h = 1
# Separate block for PyDictKeysObject with 16 keys and 10 entries
check(newstyleclass, s + calcsize("2nP2n0P") + 16 + 10*calcsize("n2P"))
check(newstyleclass, s + calcsize(DICT_KEY_STRUCT_FORMAT) + 16 + 10*calcsize("n2P"))
# dict with shared keys
check(newstyleclass().__dict__, size('nQ2P') + 10*self.P)
# unicode
Expand Down
31 changes: 14 additions & 17 deletions Objects/dict-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,34 @@ typedef struct {
PyObject *me_value; /* This field is only meaningful for combined tables */
} PyDictKeyEntry;

/* dict_lookup_func() returns index of entry which can be used like DK_ENTRIES(dk)[index].
/* _Py_dict_lookup() returns index of entry which can be used like DK_ENTRIES(dk)[index].
* -1 when no entry found, -3 when compare raises error.
*/
typedef Py_ssize_t (*dict_lookup_func)
(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr);
Py_ssize_t _Py_dict_lookup(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject **value_addr);


#define DKIX_EMPTY (-1)
#define DKIX_DUMMY (-2) /* Used internally */
#define DKIX_ERROR (-3)

typedef enum {
DICT_KEYS_GENERAL = 0,
DICT_KEYS_UNICODE = 1,
DICT_KEYS_SPLIT = 2
} DictKeysKind;

/* See dictobject.c for actual layout of DictKeysObject */
struct _dictkeysobject {
Py_ssize_t dk_refcnt;

/* Size of the hash table (dk_indices). It must be a power of 2. */
Py_ssize_t dk_size;

/* Function to lookup in the hash table (dk_indices):

- lookdict(): general-purpose, and may return DKIX_ERROR if (and
only if) a comparison raises an exception.

- lookdict_unicode(): specialized to Unicode string keys, comparison of
which can never raise an exception; that function can never return
DKIX_ERROR.
uint8_t dk_log2_size;

- lookdict_unicode_nodummy(): similar to lookdict_unicode() but further
specialized for Unicode string keys that cannot be the <dummy> value.
/* Kind of keys */
uint8_t dk_kind;

- lookdict_split(): Version of lookdict() for split tables. */
dict_lookup_func dk_lookup;
/* Version number -- Reset to 0 by any modification to keys */
uint32_t dk_version;

/* Number of usable entries in dk_entries. */
Py_ssize_t dk_usable;
Expand Down
Loading