Commit ab30353a authored by Larry Hastings's avatar Larry Hastings

Merge with ongoing work in 3.5 branch.

parents b34db6ad 95f9dd5e
...@@ -937,6 +937,20 @@ class DictTest(unittest.TestCase): ...@@ -937,6 +937,20 @@ class DictTest(unittest.TestCase):
d.popitem() d.popitem()
self.check_reentrant_insertion(mutate) 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 from test import mapping_tests
......
...@@ -128,6 +128,9 @@ Dict display element unpacking ...@@ -128,6 +128,9 @@ Dict display element unpacking
... for i in range(1000)) + "}")) ... for i in range(1000)) + "}"))
1000 1000
>>> {0:1, **{0:2}, 0:3, 0:4}
{0: 4}
List comprehension element unpacking List comprehension element unpacking
>>> a, b, c = [0, 1, 2], 3, 4 >>> a, b, c = [0, 1, 2], 3, 4
......
...@@ -10,6 +10,10 @@ Release date: 2015-07-26 ...@@ -10,6 +10,10 @@ Release date: 2015-07-26
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #24569: Make PEP 448 dictionary evaluation more consistent.
- Issue #24407: Fix crash when dict is mutated while being updated.
Library Library
------- -------
......
...@@ -2039,23 +2039,35 @@ PyDict_Merge(PyObject *a, PyObject *b, int override) ...@@ -2039,23 +2039,35 @@ PyDict_Merge(PyObject *a, PyObject *b, int override)
if (dictresize(mp, (mp->ma_used + other->ma_used)*2) != 0) if (dictresize(mp, (mp->ma_used + other->ma_used)*2) != 0)
return -1; return -1;
for (i = 0, n = DK_SIZE(other->ma_keys); i < n; i++) { 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]; entry = &other->ma_keys->dk_entries[i];
key = entry->me_key;
hash = entry->me_hash;
if (other->ma_values) if (other->ma_values)
value = other->ma_values[i]; value = other->ma_values[i];
else else
value = entry->me_value; value = entry->me_value;
if (value != NULL && if (value != NULL) {
(override || int err = 0;
PyDict_GetItem(a, entry->me_key) == NULL)) { Py_INCREF(key);
if (insertdict(mp, entry->me_key, Py_INCREF(value);
entry->me_hash, if (override || PyDict_GetItem(a, key) == NULL)
value) != 0) 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; return -1;
} }
} }
} }
}
else { else {
/* Do it the generic, slower way */ /* Do it the generic, slower way */
PyObject *keys = PyMapping_Keys(b); PyObject *keys = PyMapping_Keys(b);
......
...@@ -2561,22 +2561,25 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) ...@@ -2561,22 +2561,25 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
} }
TARGET(BUILD_MAP) { TARGET(BUILD_MAP) {
int i;
PyObject *map = _PyDict_NewPresized((Py_ssize_t)oparg); PyObject *map = _PyDict_NewPresized((Py_ssize_t)oparg);
if (map == NULL) if (map == NULL)
goto error; goto error;
while (--oparg >= 0) { for (i = oparg; i > 0; i--) {
int err; int err;
PyObject *value = TOP(); PyObject *key = PEEK(2*i);
PyObject *key = SECOND(); PyObject *value = PEEK(2*i - 1);
STACKADJ(-2);
err = PyDict_SetItem(map, key, value); err = PyDict_SetItem(map, key, value);
Py_DECREF(value);
Py_DECREF(key);
if (err != 0) { if (err != 0) {
Py_DECREF(map); Py_DECREF(map);
goto error; goto error;
} }
} }
while (oparg--) {
Py_DECREF(POP());
Py_DECREF(POP());
}
PUSH(map); PUSH(map);
DISPATCH(); DISPATCH();
} }
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
</ItemGroup> </ItemGroup>
</Target> </Target>
<Target Name="_TransformWxlTemplates" AfterTargets="PrepareForBuild"> <Target Name="_TransformWxlTemplates" AfterTargets="PrepareForBuild" Inputs="@(WxlTemplate);$(PySourcePath)include\patchlevel.h" Outputs="$(IntermediateOutputPath)%(Filename).wxl">
<PropertyGroup> <PropertyGroup>
<_Content>$([System.IO.File]::ReadAllText(%(WxlTemplate.FullPath)).Replace(`{{ShortVersion}}`, `$(MajorVersionNumber).$(MinorVersionNumber)`).Replace(`{{LongVersion}}`, `$(PythonVersion)`).Replace(`{{Bitness}}`, `$(Bitness)`))</_Content> <_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> <_ExistingContent Condition="Exists('$(IntermediateOutputPath)%(WxlTemplate.Filename).wxl')">$([System.IO.File]::ReadAllText($(IntermediateOutputPath)%(WxlTemplate.Filename).wxl))</_ExistingContent>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment