mirror of
https://github.com/python/cpython.git
synced 2025-11-13 15:40:05 +00:00
Make dictionary() a real constructor. Accepts at most one argument, "a
mapping object", in the same sense dict.update(x) requires of x (that x
has a keys() method and a getitem).
Questionable: The other type constructors accept a keyword argument, so I
did that here too (e.g., dictionary(mapping={1:2}) works). But type_call
doesn't pass the keyword args to the tp_new slot (it passes NULL), it only
passes them to the tp_init slot, so getting at them required adding a
tp_init slot to dicts. Looks like that makes the normal case (i.e., no
args at all) a little slower (the time it takes to call dict.tp_init and
have it figure out there's nothing to do).
This commit is contained in:
parent
1b8ca0d87a
commit
25786c0851
2 changed files with 80 additions and 3 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
# Test descriptor-related enhancements
|
# Test descriptor-related enhancements
|
||||||
|
|
||||||
from test_support import verify, verbose
|
from test_support import verify, verbose, TestFailed
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
|
||||||
def testunop(a, res, expr="len(a)", meth="__len__"):
|
def testunop(a, res, expr="len(a)", meth="__len__"):
|
||||||
|
|
@ -123,6 +123,55 @@ def dicts():
|
||||||
verify(eval(d.__repr__(), {}) == d)
|
verify(eval(d.__repr__(), {}) == d)
|
||||||
testset2op({1:2,3:4}, 2, 3, {1:2,2:3,3:4}, "a[b]=c", "__setitem__")
|
testset2op({1:2,3:4}, 2, 3, {1:2,2:3,3:4}, "a[b]=c", "__setitem__")
|
||||||
|
|
||||||
|
def dict_constructor():
|
||||||
|
if verbose:
|
||||||
|
print "Testing dictionary constructor ..."
|
||||||
|
d = dictionary()
|
||||||
|
verify(d == {})
|
||||||
|
d = dictionary({})
|
||||||
|
verify(d == {})
|
||||||
|
d = dictionary(mapping={})
|
||||||
|
verify(d == {})
|
||||||
|
d = dictionary({1: 2, 'a': 'b'})
|
||||||
|
verify(d == {1: 2, 'a': 'b'})
|
||||||
|
for badarg in 0, 0L, 0j, "0", [0], (0,):
|
||||||
|
try:
|
||||||
|
dictionary(badarg)
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise TestFailed("no TypeError from dictionary(%r)" % badarg)
|
||||||
|
try:
|
||||||
|
dictionary(senseless={})
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise TestFailed("no TypeError from dictionary(senseless={}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
dictionary({}, {})
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise TestFailed("no TypeError from dictionary({}, {})")
|
||||||
|
|
||||||
|
class Mapping:
|
||||||
|
dict = {1:2, 3:4, 'a':1j}
|
||||||
|
|
||||||
|
def __getitem__(self, i):
|
||||||
|
return self.dict[i]
|
||||||
|
|
||||||
|
try:
|
||||||
|
dictionary(Mapping())
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise TestFailed("no TypeError from dictionary(incomplete mapping)")
|
||||||
|
|
||||||
|
Mapping.keys = lambda self: self.dict.keys()
|
||||||
|
d = dictionary(mapping=Mapping())
|
||||||
|
verify(d == Mapping.dict)
|
||||||
|
|
||||||
binops = {
|
binops = {
|
||||||
'add': '+',
|
'add': '+',
|
||||||
'sub': '-',
|
'sub': '-',
|
||||||
|
|
@ -1299,6 +1348,7 @@ def inherits():
|
||||||
def all():
|
def all():
|
||||||
lists()
|
lists()
|
||||||
dicts()
|
dicts()
|
||||||
|
dict_constructor()
|
||||||
ints()
|
ints()
|
||||||
longs()
|
longs()
|
||||||
floats()
|
floats()
|
||||||
|
|
|
||||||
|
|
@ -1692,12 +1692,39 @@ dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
dict_init(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
|
{
|
||||||
|
PyObject *arg = NULL;
|
||||||
|
static char *kwlist[] = {"mapping", 0};
|
||||||
|
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:dictionary",
|
||||||
|
kwlist, &arg))
|
||||||
|
return -1;
|
||||||
|
if (arg != NULL) {
|
||||||
|
if (PyDict_Merge(self, arg, 1) < 0) {
|
||||||
|
/* An error like "AttibuteError: keys" is too
|
||||||
|
cryptic in this context. */
|
||||||
|
if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"argument must be of a mapping type");
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
dict_iter(dictobject *dict)
|
dict_iter(dictobject *dict)
|
||||||
{
|
{
|
||||||
return dictiter_new(dict, select_key);
|
return dictiter_new(dict, select_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char dictionary_doc[] =
|
||||||
|
"dictionary() -> new empty dictionary\n"
|
||||||
|
"dictionary(mapping) -> new dict initialized from mapping's key+value pairs";
|
||||||
|
|
||||||
PyTypeObject PyDict_Type = {
|
PyTypeObject PyDict_Type = {
|
||||||
PyObject_HEAD_INIT(&PyType_Type)
|
PyObject_HEAD_INIT(&PyType_Type)
|
||||||
0,
|
0,
|
||||||
|
|
@ -1721,7 +1748,7 @@ PyTypeObject PyDict_Type = {
|
||||||
0, /* tp_as_buffer */
|
0, /* tp_as_buffer */
|
||||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
|
||||||
Py_TPFLAGS_BASETYPE, /* tp_flags */
|
Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||||
"dictionary type", /* tp_doc */
|
dictionary_doc, /* tp_doc */
|
||||||
(traverseproc)dict_traverse, /* tp_traverse */
|
(traverseproc)dict_traverse, /* tp_traverse */
|
||||||
(inquiry)dict_tp_clear, /* tp_clear */
|
(inquiry)dict_tp_clear, /* tp_clear */
|
||||||
dict_richcompare, /* tp_richcompare */
|
dict_richcompare, /* tp_richcompare */
|
||||||
|
|
@ -1736,7 +1763,7 @@ PyTypeObject PyDict_Type = {
|
||||||
0, /* tp_descr_get */
|
0, /* tp_descr_get */
|
||||||
0, /* tp_descr_set */
|
0, /* tp_descr_set */
|
||||||
0, /* tp_dictoffset */
|
0, /* tp_dictoffset */
|
||||||
0, /* tp_init */
|
(initproc)dict_init, /* tp_init */
|
||||||
PyType_GenericAlloc, /* tp_alloc */
|
PyType_GenericAlloc, /* tp_alloc */
|
||||||
dict_new, /* tp_new */
|
dict_new, /* tp_new */
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue