mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Make C helper function more closely match the pure python version, and add tests.
This commit is contained in:
parent
23eaa70057
commit
426e052a4f
2 changed files with 63 additions and 23 deletions
|
@ -3,7 +3,7 @@
|
||||||
import unittest, doctest, operator
|
import unittest, doctest, operator
|
||||||
import inspect
|
import inspect
|
||||||
from test import support
|
from test import support
|
||||||
from collections import namedtuple, Counter, OrderedDict
|
from collections import namedtuple, Counter, OrderedDict, _count_elements
|
||||||
from test import mapping_tests
|
from test import mapping_tests
|
||||||
import pickle, copy
|
import pickle, copy
|
||||||
from random import randrange, shuffle
|
from random import randrange, shuffle
|
||||||
|
@ -775,6 +775,19 @@ class TestCounter(unittest.TestCase):
|
||||||
c.subtract('aaaabbcce')
|
c.subtract('aaaabbcce')
|
||||||
self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
|
self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1))
|
||||||
|
|
||||||
|
def test_helper_function(self):
|
||||||
|
# two paths, one for real dicts and one for other mappings
|
||||||
|
elems = list('abracadabra')
|
||||||
|
|
||||||
|
d = dict()
|
||||||
|
_count_elements(d, elems)
|
||||||
|
self.assertEqual(d, {'a': 5, 'r': 2, 'b': 2, 'c': 1, 'd': 1})
|
||||||
|
|
||||||
|
m = OrderedDict()
|
||||||
|
_count_elements(m, elems)
|
||||||
|
self.assertEqual(m,
|
||||||
|
OrderedDict([('a', 5), ('b', 2), ('r', 2), ('c', 1), ('d', 1)]))
|
||||||
|
|
||||||
class TestOrderedDict(unittest.TestCase):
|
class TestOrderedDict(unittest.TestCase):
|
||||||
|
|
||||||
def test_init(self):
|
def test_init(self):
|
||||||
|
|
|
@ -1536,41 +1536,68 @@ _count_elements(PyObject *self, PyObject *args)
|
||||||
if (!PyArg_UnpackTuple(args, "_count_elements", 2, 2, &mapping, &iterable))
|
if (!PyArg_UnpackTuple(args, "_count_elements", 2, 2, &mapping, &iterable))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!PyDict_Check(mapping)) {
|
|
||||||
PyErr_SetString(PyExc_TypeError,
|
|
||||||
"Expected mapping argument to be a dictionary");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
it = PyObject_GetIter(iterable);
|
it = PyObject_GetIter(iterable);
|
||||||
if (it == NULL)
|
if (it == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
one = PyLong_FromLong(1);
|
one = PyLong_FromLong(1);
|
||||||
if (one == NULL) {
|
if (one == NULL) {
|
||||||
Py_DECREF(it);
|
Py_DECREF(it);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
while (1) {
|
|
||||||
key = PyIter_Next(it);
|
if (PyDict_CheckExact(mapping)) {
|
||||||
if (key == NULL) {
|
while (1) {
|
||||||
if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_StopIteration))
|
key = PyIter_Next(it);
|
||||||
PyErr_Clear();
|
if (key == NULL) {
|
||||||
break;
|
if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_StopIteration))
|
||||||
|
PyErr_Clear();
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
oldval = PyDict_GetItem(mapping, key);
|
||||||
|
if (oldval == NULL) {
|
||||||
|
if (PyDict_SetItem(mapping, key, one) == -1)
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
newval = PyNumber_Add(oldval, one);
|
||||||
|
if (newval == NULL)
|
||||||
|
break;
|
||||||
|
if (PyDict_SetItem(mapping, key, newval) == -1)
|
||||||
|
break;
|
||||||
|
Py_CLEAR(newval);
|
||||||
|
}
|
||||||
|
Py_DECREF(key);
|
||||||
}
|
}
|
||||||
oldval = PyDict_GetItem(mapping, key);
|
} else {
|
||||||
if (oldval == NULL) {
|
while (1) {
|
||||||
if (PyDict_SetItem(mapping, key, one) == -1)
|
key = PyIter_Next(it);
|
||||||
break;
|
if (key == NULL) {
|
||||||
} else {
|
if (PyErr_Occurred() && PyErr_ExceptionMatches(PyExc_StopIteration))
|
||||||
newval = PyNumber_Add(oldval, one);
|
PyErr_Clear();
|
||||||
if (newval == NULL)
|
else
|
||||||
break;
|
break;
|
||||||
if (PyDict_SetItem(mapping, key, newval) == -1)
|
}
|
||||||
|
oldval = PyObject_GetItem(mapping, key);
|
||||||
|
if (oldval == NULL) {
|
||||||
|
if (!PyErr_Occurred() || !PyErr_ExceptionMatches(PyExc_KeyError))
|
||||||
|
break;
|
||||||
|
PyErr_Clear();
|
||||||
|
Py_INCREF(one);
|
||||||
|
newval = one;
|
||||||
|
} else {
|
||||||
|
newval = PyNumber_Add(oldval, one);
|
||||||
|
Py_DECREF(oldval);
|
||||||
|
if (newval == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (PyObject_SetItem(mapping, key, newval) == -1)
|
||||||
break;
|
break;
|
||||||
Py_CLEAR(newval);
|
Py_CLEAR(newval);
|
||||||
|
Py_DECREF(key);
|
||||||
}
|
}
|
||||||
Py_DECREF(key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_DECREF(it);
|
Py_DECREF(it);
|
||||||
Py_XDECREF(key);
|
Py_XDECREF(key);
|
||||||
Py_XDECREF(newval);
|
Py_XDECREF(newval);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue