summaryrefslogtreecommitdiffstats
path: root/Objects/dictobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/dictobject.c')
-rw-r--r--Objects/dictobject.c424
1 files changed, 250 insertions, 174 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index 953484c..a494d6b 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -69,6 +69,11 @@ to the combined-table form.
#include "Python.h"
#include "stringlib/eq.h"
+/*[clinic input]
+class dict "PyDictObject *" "&PyDict_Type"
+[clinic start generated code]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f157a5a0ce9589d6]*/
+
typedef struct {
/* Cached hash code of me_key. */
Py_hash_t me_hash;
@@ -95,20 +100,6 @@ To avoid slowing down lookups on a near-full table, we resize the table when
it's USABLE_FRACTION (currently two-thirds) full.
*/
-/* Set a key error with the specified argument, wrapping it in a
- * tuple automatically so that tuple keys are not unpacked as the
- * exception arguments. */
-static void
-set_key_error(PyObject *arg)
-{
- PyObject *tup;
- tup = PyTuple_Pack(1, arg);
- if (!tup)
- return; /* caller will expect error to be set anyway */
- PyErr_SetObject(PyExc_KeyError, tup);
- Py_DECREF(tup);
-}
-
#define PERTURB_SHIFT 5
/*
@@ -305,9 +296,9 @@ PyDict_Fini(void)
* #define USABLE_FRACTION(n) (((n) >> 1) + ((n) >> 2) - ((n) >> 3))
*/
-/* GROWTH_RATE. Growth rate upon hitting maximum load.
- * Currently set to used*2 + capacity/2.
- * This means that dicts double in size when growing without deletions,
+/* GROWTH_RATE. Growth rate upon hitting maximum load.
+ * Currently set to used*2 + capacity/2.
+ * This means that dicts double in size when growing without deletions,
* but have more head room when the number of deletions is on a par with the
* number of insertions.
* Raising this to used*4 doubles memory consumption depending on the size of
@@ -389,6 +380,7 @@ static PyObject *
new_dict(PyDictKeysObject *keys, PyObject **values)
{
PyDictObject *mp;
+ assert(keys != NULL);
if (numfree) {
mp = free_list[--numfree];
assert (mp != NULL);
@@ -431,7 +423,10 @@ new_dict_with_shared_keys(PyDictKeysObject *keys)
PyObject *
PyDict_New(void)
{
- return new_dict(new_keys_object(PyDict_MINSIZE_COMBINED), NULL);
+ PyDictKeysObject *keys = new_keys_object(PyDict_MINSIZE_COMBINED);
+ if (keys == NULL)
+ return NULL;
+ return new_dict(keys, NULL);
}
/*
@@ -463,13 +458,13 @@ static PyDictKeyEntry *
lookdict(PyDictObject *mp, PyObject *key,
Py_hash_t hash, PyObject ***value_addr)
{
- register size_t i;
- register size_t perturb;
- register PyDictKeyEntry *freeslot;
- register size_t mask;
+ size_t i;
+ size_t perturb;
+ PyDictKeyEntry *freeslot;
+ size_t mask;
PyDictKeyEntry *ep0;
- register PyDictKeyEntry *ep;
- register int cmp;
+ PyDictKeyEntry *ep;
+ int cmp;
PyObject *startkey;
top:
@@ -555,12 +550,12 @@ static PyDictKeyEntry *
lookdict_unicode(PyDictObject *mp, PyObject *key,
Py_hash_t hash, PyObject ***value_addr)
{
- register size_t i;
- register size_t perturb;
- register PyDictKeyEntry *freeslot;
- register size_t mask = DK_MASK(mp->ma_keys);
+ size_t i;
+ size_t perturb;
+ PyDictKeyEntry *freeslot;
+ size_t mask = DK_MASK(mp->ma_keys);
PyDictKeyEntry *ep0 = &mp->ma_keys->dk_entries[0];
- register PyDictKeyEntry *ep;
+ PyDictKeyEntry *ep;
/* Make sure this function doesn't have to handle non-unicode keys,
including subclasses of str; e.g., one reason to subclass
@@ -620,11 +615,11 @@ static PyDictKeyEntry *
lookdict_unicode_nodummy(PyDictObject *mp, PyObject *key,
Py_hash_t hash, PyObject ***value_addr)
{
- register size_t i;
- register size_t perturb;
- register size_t mask = DK_MASK(mp->ma_keys);
+ size_t i;
+ size_t perturb;
+ size_t mask = DK_MASK(mp->ma_keys);
PyDictKeyEntry *ep0 = &mp->ma_keys->dk_entries[0];
- register PyDictKeyEntry *ep;
+ PyDictKeyEntry *ep;
/* Make sure this function doesn't have to handle non-unicode keys,
including subclasses of str; e.g., one reason to subclass
@@ -665,11 +660,11 @@ static PyDictKeyEntry *
lookdict_split(PyDictObject *mp, PyObject *key,
Py_hash_t hash, PyObject ***value_addr)
{
- register size_t i;
- register size_t perturb;
- register size_t mask = DK_MASK(mp->ma_keys);
+ size_t i;
+ size_t perturb;
+ size_t mask = DK_MASK(mp->ma_keys);
PyDictKeyEntry *ep0 = &mp->ma_keys->dk_entries[0];
- register PyDictKeyEntry *ep;
+ PyDictKeyEntry *ep;
if (!PyUnicode_CheckExact(key)) {
ep = lookdict(mp, key, hash, value_addr);
@@ -819,13 +814,14 @@ insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value)
if (ep == NULL) {
return -1;
}
+ assert(PyUnicode_CheckExact(key) || mp->ma_keys->dk_lookup == lookdict);
Py_INCREF(value);
MAINTAIN_TRACKING(mp, key, value);
old_value = *value_addr;
if (old_value != NULL) {
assert(ep->me_key != NULL && ep->me_key != dummy);
*value_addr = value;
- Py_DECREF(old_value); /* which **CAN** re-enter */
+ Py_DECREF(old_value); /* which **CAN** re-enter (see issue #22653) */
}
else {
if (ep->me_key == NULL) {
@@ -856,9 +852,8 @@ insertdict(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject *value)
}
mp->ma_used++;
*value_addr = value;
+ assert(ep->me_key != NULL && ep->me_key != dummy);
}
- assert(ep->me_key != NULL && ep->me_key != dummy);
- assert(PyUnicode_CheckExact(key) || mp->ma_keys->dk_lookup == lookdict);
return 0;
}
@@ -1237,7 +1232,7 @@ PyDict_DelItem(PyObject *op, PyObject *key)
if (ep == NULL)
return -1;
if (*value_addr == NULL) {
- set_key_error(key);
+ _PyErr_SetKeyError(key);
return -1;
}
old_value = *value_addr;
@@ -1391,7 +1386,7 @@ dict_dealloc(PyDictObject *mp)
}
DK_DECREF(keys);
}
- else {
+ else if (keys != NULL) {
assert(keys->dk_refcnt == 1);
DK_DECREF(keys);
}
@@ -1407,9 +1402,9 @@ static PyObject *
dict_repr(PyDictObject *mp)
{
Py_ssize_t i;
- PyObject *s, *temp, *colon = NULL;
- PyObject *pieces = NULL, *result = NULL;
- PyObject *key, *value;
+ PyObject *key = NULL, *value = NULL;
+ _PyUnicodeWriter writer;
+ int first;
i = Py_ReprEnter((PyObject *)mp);
if (i != 0) {
@@ -1417,71 +1412,73 @@ dict_repr(PyDictObject *mp)
}
if (mp->ma_used == 0) {
- result = PyUnicode_FromString("{}");
- goto Done;
+ Py_ReprLeave((PyObject *)mp);
+ return PyUnicode_FromString("{}");
}
- pieces = PyList_New(0);
- if (pieces == NULL)
- goto Done;
+ _PyUnicodeWriter_Init(&writer);
+ writer.overallocate = 1;
+ /* "{" + "1: 2" + ", 3: 4" * (len - 1) + "}" */
+ writer.min_length = 1 + 4 + (2 + 4) * (mp->ma_used - 1) + 1;
- colon = PyUnicode_FromString(": ");
- if (colon == NULL)
- goto Done;
+ if (_PyUnicodeWriter_WriteChar(&writer, '{') < 0)
+ goto error;
/* Do repr() on each key+value pair, and insert ": " between them.
Note that repr may mutate the dict. */
i = 0;
+ first = 1;
while (PyDict_Next((PyObject *)mp, &i, &key, &value)) {
- int status;
+ PyObject *s;
+ int res;
+
/* Prevent repr from deleting key or value during key format. */
Py_INCREF(key);
Py_INCREF(value);
+
+ if (!first) {
+ if (_PyUnicodeWriter_WriteASCIIString(&writer, ", ", 2) < 0)
+ goto error;
+ }
+ first = 0;
+
s = PyObject_Repr(key);
- PyUnicode_Append(&s, colon);
- PyUnicode_AppendAndDel(&s, PyObject_Repr(value));
- Py_DECREF(key);
- Py_DECREF(value);
if (s == NULL)
- goto Done;
- status = PyList_Append(pieces, s);
- Py_DECREF(s); /* append created a new ref */
- if (status < 0)
- goto Done;
- }
-
- /* Add "{}" decorations to the first and last items. */
- assert(PyList_GET_SIZE(pieces) > 0);
- s = PyUnicode_FromString("{");
- if (s == NULL)
- goto Done;
- temp = PyList_GET_ITEM(pieces, 0);
- PyUnicode_AppendAndDel(&s, temp);
- PyList_SET_ITEM(pieces, 0, s);
- if (s == NULL)
- goto Done;
-
- s = PyUnicode_FromString("}");
- if (s == NULL)
- goto Done;
- temp = PyList_GET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1);
- PyUnicode_AppendAndDel(&temp, s);
- PyList_SET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1, temp);
- if (temp == NULL)
- goto Done;
-
- /* Paste them all together with ", " between. */
- s = PyUnicode_FromString(", ");
- if (s == NULL)
- goto Done;
- result = PyUnicode_Join(s, pieces);
- Py_DECREF(s);
-
-Done:
- Py_XDECREF(pieces);
- Py_XDECREF(colon);
+ goto error;
+ res = _PyUnicodeWriter_WriteStr(&writer, s);
+ Py_DECREF(s);
+ if (res < 0)
+ goto error;
+
+ if (_PyUnicodeWriter_WriteASCIIString(&writer, ": ", 2) < 0)
+ goto error;
+
+ s = PyObject_Repr(value);
+ if (s == NULL)
+ goto error;
+ res = _PyUnicodeWriter_WriteStr(&writer, s);
+ Py_DECREF(s);
+ if (res < 0)
+ goto error;
+
+ Py_CLEAR(key);
+ Py_CLEAR(value);
+ }
+
+ writer.overallocate = 0;
+ if (_PyUnicodeWriter_WriteChar(&writer, '}') < 0)
+ goto error;
+
Py_ReprLeave((PyObject *)mp);
- return result;
+
+ return _PyUnicodeWriter_Finish(&writer);
+
+error:
+ Py_ReprLeave((PyObject *)mp);
+ _PyUnicodeWriter_Dealloc(&writer);
+ Py_XDECREF(key);
+ Py_XDECREF(value);
+ return NULL;
}
static Py_ssize_t
@@ -1491,7 +1488,7 @@ dict_length(PyDictObject *mp)
}
static PyObject *
-dict_subscript(PyDictObject *mp, register PyObject *key)
+dict_subscript(PyDictObject *mp, PyObject *key)
{
PyObject *v;
Py_hash_t hash;
@@ -1523,7 +1520,7 @@ dict_subscript(PyDictObject *mp, register PyObject *key)
else if (PyErr_Occurred())
return NULL;
}
- set_key_error(key);
+ _PyErr_SetKeyError(key);
return NULL;
}
else
@@ -1547,10 +1544,10 @@ static PyMappingMethods dict_as_mapping = {
};
static PyObject *
-dict_keys(register PyDictObject *mp)
+dict_keys(PyDictObject *mp)
{
- register PyObject *v;
- register Py_ssize_t i, j;
+ PyObject *v;
+ Py_ssize_t i, j;
PyDictKeyEntry *ep;
Py_ssize_t size, n, offset;
PyObject **value_ptr;
@@ -1591,10 +1588,10 @@ dict_keys(register PyDictObject *mp)
}
static PyObject *
-dict_values(register PyDictObject *mp)
+dict_values(PyDictObject *mp)
{
- register PyObject *v;
- register Py_ssize_t i, j;
+ PyObject *v;
+ Py_ssize_t i, j;
Py_ssize_t size, n, offset;
PyObject **value_ptr;
@@ -1633,10 +1630,10 @@ dict_values(register PyDictObject *mp)
}
static PyObject *
-dict_items(register PyDictObject *mp)
+dict_items(PyDictObject *mp)
{
- register PyObject *v;
- register Py_ssize_t i, j, n;
+ PyObject *v;
+ Py_ssize_t i, j, n;
Py_ssize_t size, offset;
PyObject *item, *key;
PyDictKeyEntry *ep;
@@ -1694,37 +1691,72 @@ dict_items(register PyDictObject *mp)
return v;
}
+/*[clinic input]
+@classmethod
+dict.fromkeys
+ iterable: object
+ value: object=None
+ /
+
+Returns a new dict with keys from iterable and values equal to value.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(dict_fromkeys__doc__,
+"fromkeys($type, iterable, value=None, /)\n"
+"--\n"
+"\n"
+"Returns a new dict with keys from iterable and values equal to value.");
+
+#define DICT_FROMKEYS_METHODDEF \
+ {"fromkeys", (PyCFunction)dict_fromkeys, METH_VARARGS|METH_CLASS, dict_fromkeys__doc__},
+
static PyObject *
-dict_fromkeys(PyObject *cls, PyObject *args)
+dict_fromkeys_impl(PyTypeObject *type, PyObject *iterable, PyObject *value);
+
+static PyObject *
+dict_fromkeys(PyTypeObject *type, PyObject *args)
{
- PyObject *seq;
+ PyObject *return_value = NULL;
+ PyObject *iterable;
PyObject *value = Py_None;
+
+ if (!PyArg_UnpackTuple(args, "fromkeys",
+ 1, 2,
+ &iterable, &value))
+ goto exit;
+ return_value = dict_fromkeys_impl(type, iterable, value);
+
+exit:
+ return return_value;
+}
+
+static PyObject *
+dict_fromkeys_impl(PyTypeObject *type, PyObject *iterable, PyObject *value)
+/*[clinic end generated code: output=55f8dc0ffa87406f input=b85a667f9bf4669d]*/
+{
PyObject *it; /* iter(seq) */
PyObject *key;
PyObject *d;
int status;
- if (!PyArg_UnpackTuple(args, "fromkeys", 1, 2, &seq, &value))
- return NULL;
-
- d = PyObject_CallObject(cls, NULL);
+ d = PyObject_CallObject((PyObject *)type, NULL);
if (d == NULL)
return NULL;
if (PyDict_CheckExact(d) && ((PyDictObject *)d)->ma_used == 0) {
- if (PyDict_CheckExact(seq)) {
+ if (PyDict_CheckExact(iterable)) {
PyDictObject *mp = (PyDictObject *)d;
PyObject *oldvalue;
Py_ssize_t pos = 0;
PyObject *key;
Py_hash_t hash;
- if (dictresize(mp, Py_SIZE(seq))) {
+ if (dictresize(mp, Py_SIZE(iterable))) {
Py_DECREF(d);
return NULL;
}
- while (_PyDict_Next(seq, &pos, &key, &oldvalue, &hash)) {
+ while (_PyDict_Next(iterable, &pos, &key, &oldvalue, &hash)) {
if (insertdict(mp, key, hash, value)) {
Py_DECREF(d);
return NULL;
@@ -1732,18 +1764,18 @@ dict_fromkeys(PyObject *cls, PyObject *args)
}
return d;
}
- if (PyAnySet_CheckExact(seq)) {
+ if (PyAnySet_CheckExact(iterable)) {
PyDictObject *mp = (PyDictObject *)d;
Py_ssize_t pos = 0;
PyObject *key;
Py_hash_t hash;
- if (dictresize(mp, PySet_GET_SIZE(seq))) {
+ if (dictresize(mp, PySet_GET_SIZE(iterable))) {
Py_DECREF(d);
return NULL;
}
- while (_PySet_NextEntry(seq, &pos, &key, &hash)) {
+ while (_PySet_NextEntry(iterable, &pos, &key, &hash)) {
if (insertdict(mp, key, hash, value)) {
Py_DECREF(d);
return NULL;
@@ -1753,7 +1785,7 @@ dict_fromkeys(PyObject *cls, PyObject *args)
}
}
- it = PyObject_GetIter(seq);
+ it = PyObject_GetIter(iterable);
if (it == NULL){
Py_DECREF(d);
return NULL;
@@ -1908,8 +1940,8 @@ PyDict_Update(PyObject *a, PyObject *b)
int
PyDict_Merge(PyObject *a, PyObject *b, int override)
{
- register PyDictObject *mp, *other;
- register Py_ssize_t i, n;
+ PyDictObject *mp, *other;
+ Py_ssize_t i, n;
PyDictKeyEntry *entry;
/* We accept for the argument either a concrete dictionary object,
@@ -2018,7 +2050,7 @@ PyDict_Merge(PyObject *a, PyObject *b, int override)
}
static PyObject *
-dict_copy(register PyDictObject *mp)
+dict_copy(PyDictObject *mp)
{
return PyDict_Copy((PyObject*)mp);
}
@@ -2130,13 +2162,18 @@ dict_equal(PyDictObject *a, PyDictObject *b)
if (aval != NULL) {
int cmp;
PyObject *bval;
+ PyObject **vaddr;
PyObject *key = ep->me_key;
/* temporarily bump aval's refcount to ensure it stays
alive until we're done with it */
Py_INCREF(aval);
/* ditto for key */
Py_INCREF(key);
- bval = PyDict_GetItemWithError((PyObject *)b, key);
+ /* reuse the known hash value */
+ if ((b->ma_keys->dk_lookup)(b, key, ep->me_hash, &vaddr) == NULL)
+ bval = NULL;
+ else
+ bval = *vaddr;
Py_DECREF(key);
if (bval == NULL) {
Py_DECREF(aval);
@@ -2174,9 +2211,31 @@ dict_richcompare(PyObject *v, PyObject *w, int op)
return res;
}
+/*[clinic input]
+
+@coexist
+dict.__contains__
+
+ key: object
+ /
+
+True if D has a key k, else False.
+[clinic start generated code]*/
+
+PyDoc_STRVAR(dict___contains____doc__,
+"__contains__($self, key, /)\n"
+"--\n"
+"\n"
+"True if D has a key k, else False.");
+
+#define DICT___CONTAINS___METHODDEF \
+ {"__contains__", (PyCFunction)dict___contains__, METH_O|METH_COEXIST, dict___contains____doc__},
+
static PyObject *
-dict_contains(register PyDictObject *mp, PyObject *key)
+dict___contains__(PyDictObject *self, PyObject *key)
+/*[clinic end generated code: output=3cf3f8aaf2cc5cc3 input=b852b2a19b51ab24]*/
{
+ register PyDictObject *mp = self;
Py_hash_t hash;
PyDictKeyEntry *ep;
PyObject **value_addr;
@@ -2194,7 +2253,7 @@ dict_contains(register PyDictObject *mp, PyObject *key)
}
static PyObject *
-dict_get(register PyDictObject *mp, PyObject *args)
+dict_get(PyDictObject *mp, PyObject *args)
{
PyObject *key;
PyObject *failobj = Py_None;
@@ -2222,19 +2281,19 @@ dict_get(register PyDictObject *mp, PyObject *args)
return val;
}
-static PyObject *
-dict_setdefault(register PyDictObject *mp, PyObject *args)
+PyObject *
+PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)
{
- PyObject *key;
- PyObject *failobj = Py_None;
+ PyDictObject *mp = (PyDictObject *)d;
PyObject *val = NULL;
Py_hash_t hash;
PyDictKeyEntry *ep;
PyObject **value_addr;
- if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &failobj))
+ if (!PyDict_Check(d)) {
+ PyErr_BadInternalCall();
return NULL;
-
+ }
if (!PyUnicode_CheckExact(key) ||
(hash = ((PyASCIIObject *) key)->hash) == -1) {
hash = PyObject_Hash(key);
@@ -2252,23 +2311,35 @@ dict_setdefault(register PyDictObject *mp, PyObject *args)
return NULL;
ep = find_empty_slot(mp, key, hash, &value_addr);
}
- Py_INCREF(failobj);
+ Py_INCREF(defaultobj);
Py_INCREF(key);
- MAINTAIN_TRACKING(mp, key, failobj);
+ MAINTAIN_TRACKING(mp, key, defaultobj);
ep->me_key = key;
ep->me_hash = hash;
- *value_addr = failobj;
- val = failobj;
+ *value_addr = defaultobj;
+ val = defaultobj;
mp->ma_keys->dk_usable--;
mp->ma_used++;
}
- Py_INCREF(val);
return val;
}
+static PyObject *
+dict_setdefault(PyDictObject *mp, PyObject *args)
+{
+ PyObject *key, *val;
+ PyObject *defaultobj = Py_None;
+
+ if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &defaultobj))
+ return NULL;
+
+ val = PyDict_SetDefault((PyObject *)mp, key, defaultobj);
+ Py_XINCREF(val);
+ return val;
+}
static PyObject *
-dict_clear(register PyDictObject *mp)
+dict_clear(PyDictObject *mp)
{
PyDict_Clear((PyObject *)mp);
Py_RETURN_NONE;
@@ -2290,7 +2361,7 @@ dict_pop(PyDictObject *mp, PyObject *args)
Py_INCREF(deflt);
return deflt;
}
- set_key_error(key);
+ _PyErr_SetKeyError(key);
return NULL;
}
if (!PyUnicode_CheckExact(key) ||
@@ -2308,7 +2379,7 @@ dict_pop(PyDictObject *mp, PyObject *args)
Py_INCREF(deflt);
return deflt;
}
- set_key_error(key);
+ _PyErr_SetKeyError(key);
return NULL;
}
*value_addr = NULL;
@@ -2449,9 +2520,6 @@ _PyDict_KeysSize(PyDictKeysObject *keys)
return sizeof(PyDictKeysObject) + (DK_SIZE(keys)-1) * sizeof(PyDictKeyEntry);
}
-PyDoc_STRVAR(contains__doc__,
-"D.__contains__(k) -> True if D has a key k, else False");
-
PyDoc_STRVAR(getitem__doc__, "x.__getitem__(y) <==> x[y]");
PyDoc_STRVAR(sizeof__doc__,
@@ -2472,14 +2540,10 @@ PyDoc_STRVAR(popitem__doc__,
2-tuple; but raise KeyError if D is empty.");
PyDoc_STRVAR(update__doc__,
-"D.update([E, ]**F) -> None. Update D from dict/iterable E and F.\n"
-"If E present and has a .keys() method, does: for k in E: D[k] = E[k]\n\
-If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v\n\
-In either case, this is followed by: for k in F: D[k] = F[k]");
-
-PyDoc_STRVAR(fromkeys__doc__,
-"dict.fromkeys(S[,v]) -> New dict with keys from S and values equal to v.\n\
-v defaults to None.");
+"D.update([E, ]**F) -> None. Update D from dict/iterable E and F.\n\
+If E is present and has a .keys() method, then does: for k in E: D[k] = E[k]\n\
+If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v\n\
+In either case, this is followed by: for k in F: D[k] = F[k]");
PyDoc_STRVAR(clear__doc__,
"D.clear() -> None. Remove all items from D.");
@@ -2500,8 +2564,7 @@ PyDoc_STRVAR(values__doc__,
"D.values() -> an object providing a view on D's values");
static PyMethodDef mapp_methods[] = {
- {"__contains__",(PyCFunction)dict_contains, METH_O | METH_COEXIST,
- contains__doc__},
+ DICT___CONTAINS___METHODDEF
{"__getitem__", (PyCFunction)dict_subscript, METH_O | METH_COEXIST,
getitem__doc__},
{"__sizeof__", (PyCFunction)dict_sizeof, METH_NOARGS,
@@ -2522,8 +2585,7 @@ static PyMethodDef mapp_methods[] = {
values__doc__},
{"update", (PyCFunction)dict_update, METH_VARARGS | METH_KEYWORDS,
update__doc__},
- {"fromkeys", (PyCFunction)dict_fromkeys, METH_VARARGS | METH_CLASS,
- fromkeys__doc__},
+ DICT_FROMKEYS_METHODDEF
{"clear", (PyCFunction)dict_clear, METH_NOARGS,
clear__doc__},
{"copy", (PyCFunction)dict_copy, METH_NOARGS,
@@ -2580,22 +2642,23 @@ static PyObject *
dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *self;
+ PyDictObject *d;
assert(type != NULL && type->tp_alloc != NULL);
self = type->tp_alloc(type, 0);
- if (self != NULL) {
- PyDictObject *d = (PyDictObject *)self;
- d->ma_keys = new_keys_object(PyDict_MINSIZE_COMBINED);
- /* XXX - Should we raise a no-memory error? */
- if (d->ma_keys == NULL) {
- DK_INCREF(Py_EMPTY_KEYS);
- d->ma_keys = Py_EMPTY_KEYS;
- d->ma_values = empty_values;
- }
- d->ma_used = 0;
- /* The object has been implicitly tracked by tp_alloc */
- if (type == &PyDict_Type)
- _PyObject_GC_UNTRACK(d);
+ if (self == NULL)
+ return NULL;
+ d = (PyDictObject *)self;
+
+ /* The object has been implicitly tracked by tp_alloc */
+ if (type == &PyDict_Type)
+ _PyObject_GC_UNTRACK(d);
+
+ d->ma_used = 0;
+ d->ma_keys = new_keys_object(PyDict_MINSIZE_COMBINED);
+ if (d->ma_keys == NULL) {
+ Py_DECREF(self);
+ return NULL;
}
return self;
}
@@ -2671,8 +2734,10 @@ _PyDict_GetItemId(PyObject *dp, struct _Py_Identifier *key)
{
PyObject *kv;
kv = _PyUnicode_FromId(key); /* borrowed */
- if (kv == NULL)
+ if (kv == NULL) {
+ PyErr_Clear();
return NULL;
+ }
return PyDict_GetItem(dp, kv);
}
@@ -2683,8 +2748,10 @@ PyDict_GetItemString(PyObject *v, const char *key)
{
PyObject *kv, *rv;
kv = PyUnicode_FromString(key);
- if (kv == NULL)
+ if (kv == NULL) {
+ PyErr_Clear();
return NULL;
+ }
rv = PyDict_GetItem(v, kv);
Py_DECREF(kv);
return rv;
@@ -2715,6 +2782,15 @@ PyDict_SetItemString(PyObject *v, const char *key, PyObject *item)
}
int
+_PyDict_DelItemId(PyObject *v, _Py_Identifier *key)
+{
+ PyObject *kv = _PyUnicode_FromId(key); /* borrowed */
+ if (kv == NULL)
+ return -1;
+ return PyDict_DelItem(v, kv);
+}
+
+int
PyDict_DelItemString(PyObject *v, const char *key)
{
PyObject *kv;
@@ -2807,8 +2883,8 @@ static PyMethodDef dictiter_methods[] = {
static PyObject *dictiter_iternextkey(dictiterobject *di)
{
PyObject *key;
- register Py_ssize_t i, mask, offset;
- register PyDictKeysObject *k;
+ Py_ssize_t i, mask, offset;
+ PyDictKeysObject *k;
PyDictObject *d = di->di_dict;
PyObject **value_ptr;
@@ -2890,7 +2966,7 @@ PyTypeObject PyDictIterKey_Type = {
static PyObject *dictiter_iternextvalue(dictiterobject *di)
{
PyObject *value;
- register Py_ssize_t i, mask, offset;
+ Py_ssize_t i, mask, offset;
PyDictObject *d = di->di_dict;
PyObject **value_ptr;
@@ -2971,7 +3047,7 @@ PyTypeObject PyDictIterValue_Type = {
static PyObject *dictiter_iternextitem(dictiterobject *di)
{
PyObject *key, *value, *result = di->di_result;
- register Py_ssize_t i, mask, offset;
+ Py_ssize_t i, mask, offset;
PyDictObject *d = di->di_dict;
PyObject **value_ptr;