# 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())
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);
}
}
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 {
if (newvalues == NULL) {
return PyErr_NoMemory();
}
- if (frozendict) {
+ if (as_frozendict) {
split_copy = (PyDictObject *)PyObject_GC_New(PyFrozenDictObject,
&PyFrozenDict_Type);
}
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;
}
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:
return (PyObject *)new;
}
- if (frozendict) {
+ if (as_frozendict) {
copy = PyFrozenDict_New(NULL);
}
else {
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)
{
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;
}
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;
}
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;
}