diff options
-rw-r--r-- | Lib/test/test_descr.py | 52 | ||||
-rw-r--r-- | Objects/dictobject.c | 31 |
2 files changed, 80 insertions, 3 deletions
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index f495a37..f6b9e1b 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -1,6 +1,6 @@ # Test descriptor-related enhancements -from test_support import verify, verbose +from test_support import verify, verbose, TestFailed from copy import deepcopy def testunop(a, res, expr="len(a)", meth="__len__"): @@ -123,6 +123,55 @@ def dicts(): verify(eval(d.__repr__(), {}) == d) 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 = { 'add': '+', 'sub': '-', @@ -1299,6 +1348,7 @@ def inherits(): def all(): lists() dicts() + dict_constructor() ints() longs() floats() diff --git a/Objects/dictobject.c b/Objects/dictobject.c index e8a564e..91d2c53 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -1692,12 +1692,39 @@ dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds) 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 * dict_iter(dictobject *dict) { 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 = { PyObject_HEAD_INIT(&PyType_Type) 0, @@ -1721,7 +1748,7 @@ PyTypeObject PyDict_Type = { 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /* tp_flags */ - "dictionary type", /* tp_doc */ + dictionary_doc, /* tp_doc */ (traverseproc)dict_traverse, /* tp_traverse */ (inquiry)dict_tp_clear, /* tp_clear */ dict_richcompare, /* tp_richcompare */ @@ -1736,7 +1763,7 @@ PyTypeObject PyDict_Type = { 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ - 0, /* tp_init */ + (initproc)dict_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ dict_new, /* tp_new */ }; |