Merge with ongoing work in 3.5 branch.

This commit is contained in:
Larry Hastings 2015-07-05 10:31:09 -07:00
commit ab30353adb
6 changed files with 50 additions and 14 deletions

View File

@ -937,6 +937,20 @@ class DictTest(unittest.TestCase):
d.popitem()
self.check_reentrant_insertion(mutate)
def test_merge_and_mutate(self):
class X:
def __hash__(self):
return 0
def __eq__(self, o):
other.clear()
return False
l = [(i,0) for i in range(1, 1337)]
other = dict(l)
other[X()] = 0
d = {X(): 0, 1: 1}
self.assertRaises(RuntimeError, d.update, other)
from test import mapping_tests

View File

@ -128,6 +128,9 @@ Dict display element unpacking
... for i in range(1000)) + "}"))
1000
>>> {0:1, **{0:2}, 0:3, 0:4}
{0: 4}
List comprehension element unpacking
>>> a, b, c = [0, 1, 2], 3, 4

View File

@ -10,6 +10,10 @@ Release date: 2015-07-26
Core and Builtins
-----------------
- Issue #24569: Make PEP 448 dictionary evaluation more consistent.
- Issue #24407: Fix crash when dict is mutated while being updated.
Library
-------

View File

@ -2039,20 +2039,32 @@ PyDict_Merge(PyObject *a, PyObject *b, int override)
if (dictresize(mp, (mp->ma_used + other->ma_used)*2) != 0)
return -1;
for (i = 0, n = DK_SIZE(other->ma_keys); i < n; i++) {
PyObject *value;
PyObject *key, *value;
Py_hash_t hash;
entry = &other->ma_keys->dk_entries[i];
key = entry->me_key;
hash = entry->me_hash;
if (other->ma_values)
value = other->ma_values[i];
else
value = entry->me_value;
if (value != NULL &&
(override ||
PyDict_GetItem(a, entry->me_key) == NULL)) {
if (insertdict(mp, entry->me_key,
entry->me_hash,
value) != 0)
if (value != NULL) {
int err = 0;
Py_INCREF(key);
Py_INCREF(value);
if (override || PyDict_GetItem(a, key) == NULL)
err = insertdict(mp, key, hash, value);
Py_DECREF(value);
Py_DECREF(key);
if (err != 0)
return -1;
if (n != DK_SIZE(other->ma_keys)) {
PyErr_SetString(PyExc_RuntimeError,
"dict mutated during update");
return -1;
}
}
}
}

View File

@ -2561,22 +2561,25 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
}
TARGET(BUILD_MAP) {
int i;
PyObject *map = _PyDict_NewPresized((Py_ssize_t)oparg);
if (map == NULL)
goto error;
while (--oparg >= 0) {
for (i = oparg; i > 0; i--) {
int err;
PyObject *value = TOP();
PyObject *key = SECOND();
STACKADJ(-2);
PyObject *key = PEEK(2*i);
PyObject *value = PEEK(2*i - 1);
err = PyDict_SetItem(map, key, value);
Py_DECREF(value);
Py_DECREF(key);
if (err != 0) {
Py_DECREF(map);
goto error;
}
}
while (oparg--) {
Py_DECREF(POP());
Py_DECREF(POP());
}
PUSH(map);
DISPATCH();
}

View File

@ -24,7 +24,7 @@
</ItemGroup>
</Target>
<Target Name="_TransformWxlTemplates" AfterTargets="PrepareForBuild">
<Target Name="_TransformWxlTemplates" AfterTargets="PrepareForBuild" Inputs="@(WxlTemplate);$(PySourcePath)include\patchlevel.h" Outputs="$(IntermediateOutputPath)%(Filename).wxl">
<PropertyGroup>
<_Content>$([System.IO.File]::ReadAllText(%(WxlTemplate.FullPath)).Replace(`{{ShortVersion}}`, `$(MajorVersionNumber).$(MinorVersionNumber)`).Replace(`{{LongVersion}}`, `$(PythonVersion)`).Replace(`{{Bitness}}`, `$(Bitness)`))</_Content>
<_ExistingContent Condition="Exists('$(IntermediateOutputPath)%(WxlTemplate.Filename).wxl')">$([System.IO.File]::ReadAllText($(IntermediateOutputPath)%(WxlTemplate.Filename).wxl))</_ExistingContent>