FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

gh-141510: Return frozendict unmodified in PyDict_Copy() by vstinner · Pull Request #145505 · python/cpython · GitHub

/ cpython Public
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .c  (2) .h  (1) .py  (1) All 3 file types selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
2 changes: 2 additions & 0 deletions Include/internal/pycore_dict.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ extern void _PyDict_Clear_LockHeld(PyObject *op);
PyAPI_FUNC(void) _PyDict_EnsureSharedOnRead(PyDictObject *mp);
#endif

extern PyObject* _PyDict_CopyAsDict(PyObject *op);

#define DKIX_EMPTY (-1)
#define DKIX_DUMMY (-2) /* Used internally */
#define DKIX_ERROR (-3)
Expand Down
16 changes: 10 additions & 6 deletions Lib/test/test_capi/test_dict.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,18 @@ def test_dict_copy(self):
# Test PyDict_Copy()
copy = _testlimitedcapi.dict_copy
for dict_type in ANYDICT_TYPES:
if issubclass(dict_type, frozendict):
expected_type = frozendict
else:
expected_type = dict
dct = dict_type({1: 2})
dct_copy = copy(dct)
self.assertIs(type(dct_copy), expected_type)
self.assertEqual(dct_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)

for test_type in NOT_ANYDICT_TYPES + OTHER_TYPES:
self.assertRaises(SystemError, copy, test_type())
Expand Down
50 changes: 35 additions & 15 deletions Objects/dictobject.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -4235,9 +4235,6 @@ static PyObject *
dict_copy_impl(PyDictObject *self)
/*[clinic end generated code: output=ffb782cf970a5c39 input=73935f042b639de4]*/
{
if (PyFrozenDict_CheckExact(self)) {
return Py_NewRef(self);
}
return PyDict_Copy((PyObject *)self);
}

Expand All @@ -4263,18 +4260,17 @@ copy_values(PyDictValues *values)
}

static PyObject *
copy_lock_held(PyObject *o)
copy_lock_held(PyObject *o, int as_frozendict)
{
PyObject *copy;
PyDictObject *mp;
int frozendict = PyFrozenDict_Check(o);

ASSERT_DICT_LOCKED(o);

mp = (PyDictObject *)o;
if (mp->ma_used == 0) {
/* The dict is empty; just return a new dict. */
if (frozendict) {
if (as_frozendict) {
return PyFrozenDict_New(NULL);
}
else {
Expand All @@ -4288,7 +4284,7 @@ copy_lock_held(PyObject *o)
if (newvalues == NULL) {
return PyErr_NoMemory();
}
if (frozendict) {
if (as_frozendict) {
split_copy = (PyDictObject *)PyObject_GC_New(PyFrozenDictObject,
&PyFrozenDict_Type);
}
Expand All @@ -4307,7 +4303,7 @@ copy_lock_held(PyObject *o)
split_copy->ma_used = mp->ma_used;
split_copy->_ma_watcher_tag = 0;
dictkeys_incref(mp->ma_keys);
if (frozendict) {
if (as_frozendict) {
PyFrozenDictObject *frozen = (PyFrozenDictObject *)split_copy;
frozen->ma_hash = -1;
}
Expand All @@ -4318,7 +4314,7 @@ copy_lock_held(PyObject *o)
if (Py_TYPE(mp)->tp_iter == dict_iter &&
mp->ma_values == NULL &&
(mp->ma_used >= (mp->ma_keys->dk_nentries * 2) / 3) &&
!frozendict)
!as_frozendict)
{
/* Use fast-copy if:

Expand Down Expand Up @@ -4350,7 +4346,7 @@ copy_lock_held(PyObject *o)
return (PyObject *)new;
}

if (frozendict) {
if (as_frozendict) {
copy = PyFrozenDict_New(NULL);
}
else {
Expand All @@ -4364,6 +4360,19 @@ copy_lock_held(PyObject *o)
return NULL;
}

// Similar to PyDict_Copy(), but copy also frozendict.
static PyObject *
_PyDict_Copy(PyObject *o)
{
assert(PyAnyDict_Check(o));

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

PyObject *
PyDict_Copy(PyObject *o)
{
Expand All @@ -4372,11 +4381,22 @@ PyDict_Copy(PyObject *o)
return NULL;
}

PyObject *res;
Py_BEGIN_CRITICAL_SECTION(o);
if (PyFrozenDict_CheckExact(o)) {
return Py_NewRef(o);
}

return _PyDict_Copy(o);
}

res = copy_lock_held(o);
// Similar to PyDict_Copy(), but return a dict if the argument is a frozendict.
PyObject*
_PyDict_CopyAsDict(PyObject *o)
{
assert(PyAnyDict_Check(o));

PyObject *res;
Py_BEGIN_CRITICAL_SECTION(o);
res = copy_lock_held(o, 0);
Py_END_CRITICAL_SECTION();
return res;
}
Expand Down Expand Up @@ -4925,7 +4945,7 @@ dict_or(PyObject *self, PyObject *other)
if (!PyAnyDict_Check(self) || !PyAnyDict_Check(other)) {
Py_RETURN_NOTIMPLEMENTED;
}
PyObject *new = PyDict_Copy(self);
PyObject *new = _PyDict_Copy(self);
if (new == NULL) {
return NULL;
}
Expand Down Expand Up @@ -6479,7 +6499,7 @@ dictitems_xor_lock_held(PyObject *d1, PyObject *d2)
ASSERT_DICT_LOCKED(d1);
ASSERT_DICT_LOCKED(d2);

PyObject *temp_dict = copy_lock_held(d1);
PyObject *temp_dict = copy_lock_held(d1, PyFrozenDict_Check(d1));
if (temp_dict == NULL) {
return NULL;
}
Expand Down
18 changes: 3 additions & 15 deletions Objects/typeobject.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -4872,21 +4872,9 @@ type_new_get_slots(type_new_ctx *ctx, PyObject *dict)
static PyTypeObject*
type_new_init(type_new_ctx *ctx)
{
PyObject *dict;
if (PyFrozenDict_Check(ctx->orig_dict)) {
dict = PyDict_New();
if (dict == NULL) {
goto error;
}
if (PyDict_Merge(dict, ctx->orig_dict, 1) < 0) {
goto error;
}
}
else {
dict = PyDict_Copy(ctx->orig_dict);
if (dict == NULL) {
goto error;
}
PyObject *dict = _PyDict_CopyAsDict(ctx->orig_dict);
if (dict == NULL) {
goto error;
}

if (type_new_get_slots(ctx, dict) < 0) {
Expand Down
Loading

Back | FazBrowse Home | New Git URL