Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions 4 Doc/c-api/dict.rst
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,6 @@ Dictionary objects

Return a new dictionary that contains the same key-value pairs as *p*.

.. versionchanged:: next
If *p* is a subclass of :class:`frozendict`, the result will be a
:class:`frozendict` instance instead of a :class:`dict` instance.

.. c:function:: int PyDict_SetItem(PyObject *p, PyObject *key, PyObject *val)

Insert *val* into the dictionary *p* with a key of *key*. *key* must be
Expand Down
16 changes: 4 additions & 12 deletions 16 Lib/test/test_capi/test_dict.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,21 +97,13 @@ def test_dictproxy_new(self):
def test_dict_copy(self):
# Test PyDict_Copy()
copy = _testlimitedcapi.dict_copy
for dict_type in ANYDICT_TYPES:
for dict_type in DICT_TYPES:
dct = dict_type({1: 2})
dct_copy = copy(dct)
if dict_type == frozendict:
expected_type = frozendict
self.assertIs(dct_copy, dct)
else:
if issubclass(dict_type, frozendict):
expected_type = frozendict
else:
expected_type = dict
self.assertIs(type(dct_copy), expected_type)
self.assertEqual(dct_copy, dct)
self.assertIs(type(dct_copy), dict)
self.assertEqual(dct_copy, dct)

for test_type in NOT_ANYDICT_TYPES + OTHER_TYPES:
for test_type in NOT_DICT_TYPES + OTHER_TYPES:
self.assertRaises(SystemError, copy, test_type())
self.assertRaises(SystemError, copy, NULL)

Expand Down
20 changes: 19 additions & 1 deletion 20 Objects/clinic/dictobject.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

64 changes: 43 additions & 21 deletions 64 Objects/dictobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,9 @@ static int dict_merge_from_seq2(PyObject *d, PyObject *seq2, int override);

/*[clinic input]
class dict "PyDictObject *" "&PyDict_Type"
class frozendict "PyFrozenDictObject *" "&PyFrozenDict_Type"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f157a5a0ce9589d6]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=5dfa93bac68e7c54]*/


/*
Expand Down Expand Up @@ -2406,7 +2407,7 @@ dict_unhashable_type(PyObject *op, PyObject *key)
}

const char *errmsg;
if (PyObject_IsInstance(op, (PyObject*)&PyFrozenDict_Type)) {
if (PyFrozenDict_Check(op)) {
errmsg = "cannot use '%T' as a frozendict key (%S)";
}
else {
Expand Down Expand Up @@ -4384,35 +4385,37 @@ copy_lock_held(PyObject *o, int as_frozendict)
return NULL;
}

// Similar to PyDict_Copy(), but copy also frozendict.
static PyObject *
_PyDict_Copy(PyObject *o)
PyObject *
PyDict_Copy(PyObject *o)
{
assert(PyAnyDict_Check(o));
if (o == NULL || !PyDict_Check(o)) {
PyErr_BadInternalCall();
return NULL;
}

PyObject *res;
Py_BEGIN_CRITICAL_SECTION(o);
res = copy_lock_held(o, PyFrozenDict_Check(o));
res = copy_lock_held(o, 0);
Py_END_CRITICAL_SECTION();
return res;
}

PyObject *
PyDict_Copy(PyObject *o)
// Similar to PyDict_Copy(), but return a frozendict if the argument
// is a frozendict.
static PyObject *
anydict_copy(PyObject *o)
{
if (o == NULL || !PyAnyDict_Check(o)) {
PyErr_BadInternalCall();
return NULL;
}

if (PyFrozenDict_CheckExact(o)) {
return Py_NewRef(o);
}
assert(PyAnyDict_Check(o));

return _PyDict_Copy(o);
PyObject *res;
Py_BEGIN_CRITICAL_SECTION(o);
res = copy_lock_held(o, PyFrozenDict_Check(o));
Py_END_CRITICAL_SECTION();
return res;
}

// Similar to PyDict_Copy(), but return a dict if the argument is a frozendict.
// Similar to PyDict_Copy(), but accept also frozendict:
// convert frozendict to a new dict.
PyObject*
_PyDict_CopyAsDict(PyObject *o)
{
Expand Down Expand Up @@ -4969,7 +4972,7 @@ dict_or(PyObject *self, PyObject *other)
if (!PyAnyDict_Check(self) || !PyAnyDict_Check(other)) {
Py_RETURN_NOTIMPLEMENTED;
}
PyObject *new = _PyDict_Copy(self);
PyObject *new = anydict_copy(self);
if (new == NULL) {
return NULL;
}
Expand Down Expand Up @@ -8057,7 +8060,7 @@ static PyMethodDef frozendict_methods[] = {
DICT_ITEMS_METHODDEF
DICT_VALUES_METHODDEF
DICT_FROMKEYS_METHODDEF
DICT_COPY_METHODDEF
FROZENDICT_COPY_METHODDEF
DICT___REVERSED___METHODDEF
{"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
{"__getnewargs__", frozendict_getnewargs, METH_NOARGS},
Expand Down Expand Up @@ -8182,6 +8185,25 @@ PyFrozenDict_New(PyObject *iterable)
}
}

/*[clinic input]
frozendict.copy

Return a shallow copy of the frozendict.
[clinic start generated code]*/

static PyObject *
frozendict_copy_impl(PyFrozenDictObject *self)
/*[clinic end generated code: output=e580fd91d9fc2cf7 input=35f6abeaa08fd4bc]*/
{
assert(PyFrozenDict_Check(self));

if (PyFrozenDict_CheckExact(self)) {
return Py_NewRef(self);
}

return anydict_copy((PyObject*)self);
}


PyTypeObject PyFrozenDict_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
Expand Down
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.