From c4607aeedd19fad5e5fe1a6a72a0c79d014ee4e1 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 29 Jul 2011 18:19:43 -0500 Subject: [PATCH 1/2] make the types of None and Ellipsis callable --- Lib/test/test_builtin.py | 7 +++++++ Misc/NEWS | 3 +++ Objects/object.c | 34 ++++++++++++++++++++++++++++++++++ Objects/sliceobject.c | 29 +++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index aa9b4e2ed8d..145ae69237f 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -1343,6 +1343,13 @@ class BuiltinTest(unittest.TestCase): self.assertRaises(ValueError, x.translate, b"1", 1) self.assertRaises(TypeError, x.translate, b"1"*256, 1) + def test_construct_singletons(self): + for const in None, Ellipsis: + tp = type(const) + self.assertIs(tp(), const) + self.assertRaises(TypeError, tp, 1, 2) + self.assertRaises(TypeError, tp, a=1, b=2) + class TestSorted(unittest.TestCase): def test_basic(self): diff --git a/Misc/NEWS b/Misc/NEWS index 0b205ad9a8b..d1d13a5d6f8 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ What's New in Python 3.3 Alpha 1? Core and Builtins ----------------- +- Make type(None) and type(Ellipsis) callable. They return the respective + singleton instances. + - Forbid summing bytes in sum(). - Verify the types of AST strings and identifiers provided by the user before diff --git a/Objects/object.c b/Objects/object.c index 27d7089dcf8..f2f4363d6a6 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1277,6 +1277,16 @@ none_dealloc(PyObject* ignore) Py_FatalError("deallocating None"); } +static PyObject * +none_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_Size(kwargs))) { + PyErr_SetString(PyExc_TypeError, "NoneType takes no arguments"); + return NULL; + } + Py_RETURN_NONE; +} + static int none_bool(PyObject *v) { @@ -1335,6 +1345,30 @@ static PyTypeObject PyNone_Type = { 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ + 0, /*tp_call */ + 0, /*tp_str */ + 0, /*tp_getattro */ + 0, /*tp_setattro */ + 0, /*tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /*tp_flags */ + 0, /*tp_doc */ + 0, /*tp_traverse */ + 0, /*tp_clear */ + 0, /*tp_richcompare */ + 0, /*tp_weaklistoffset */ + 0, /*tp_iter */ + 0, /*tp_iternext */ + 0, /*tp_methods */ + 0, /*tp_members */ + 0, /*tp_getset */ + 0, /*tp_base */ + 0, /*tp_dict */ + 0, /*tp_descr_get */ + 0, /*tp_descr_set */ + 0, /*tp_dictoffset */ + 0, /*tp_init */ + 0, /*tp_alloc */ + none_new, /*tp_new */ }; PyObject _Py_NoneStruct = { diff --git a/Objects/sliceobject.c b/Objects/sliceobject.c index 51c53a8a11c..53cc951a735 100644 --- a/Objects/sliceobject.c +++ b/Objects/sliceobject.c @@ -16,6 +16,17 @@ this type and there is exactly one in existence. #include "Python.h" #include "structmember.h" +static PyObject * +ellipsis_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_Size(kwargs))) { + PyErr_SetString(PyExc_TypeError, "EllipsisType takes no arguments"); + return NULL; + } + Py_INCREF(Py_Ellipsis); + return Py_Ellipsis; +} + static PyObject * ellipsis_repr(PyObject *op) { @@ -43,6 +54,24 @@ PyTypeObject PyEllipsis_Type = { 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, /* tp_flags */ + 0, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + ellipsis_new, /* tp_new */ }; PyObject _Py_EllipsisObject = { From 18d7d7a2176e169942d5764516eee6f952610884 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 29 Jul 2011 18:27:44 -0500 Subject: [PATCH 2/2] also make NotImplementedType callable --- Lib/test/test_builtin.py | 2 +- Misc/NEWS | 4 ++-- Objects/object.c | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 145ae69237f..4e33c234096 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -1344,7 +1344,7 @@ class BuiltinTest(unittest.TestCase): self.assertRaises(TypeError, x.translate, b"1"*256, 1) def test_construct_singletons(self): - for const in None, Ellipsis: + for const in None, Ellipsis, NotImplemented: tp = type(const) self.assertIs(tp(), const) self.assertRaises(TypeError, tp, 1, 2) diff --git a/Misc/NEWS b/Misc/NEWS index d0f203a8ca3..cdbb09b845d 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,8 +10,8 @@ What's New in Python 3.3 Alpha 1? Core and Builtins ----------------- -- Make type(None) and type(Ellipsis) callable. They return the respective - singleton instances. +- Make type(None), type(Ellipsis), and type(NotImplemented) callable. They + return the respective singleton instances. - Forbid summing bytes in sum(). diff --git a/Objects/object.c b/Objects/object.c index f2f4363d6a6..cf10f3cb1b2 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -1385,6 +1385,17 @@ NotImplemented_repr(PyObject *op) return PyUnicode_FromString("NotImplemented"); } +static PyObject * +notimplemented_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) +{ + if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_Size(kwargs))) { + PyErr_SetString(PyExc_TypeError, "NotImplementedType takes no arguments"); + return NULL; + } + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; +} + static PyTypeObject PyNotImplemented_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "NotImplementedType", @@ -1400,6 +1411,30 @@ static PyTypeObject PyNotImplemented_Type = { 0, /*tp_as_sequence*/ 0, /*tp_as_mapping*/ 0, /*tp_hash */ + 0, /*tp_call */ + 0, /*tp_str */ + 0, /*tp_getattro */ + 0, /*tp_setattro */ + 0, /*tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /*tp_flags */ + 0, /*tp_doc */ + 0, /*tp_traverse */ + 0, /*tp_clear */ + 0, /*tp_richcompare */ + 0, /*tp_weaklistoffset */ + 0, /*tp_iter */ + 0, /*tp_iternext */ + 0, /*tp_methods */ + 0, /*tp_members */ + 0, /*tp_getset */ + 0, /*tp_base */ + 0, /*tp_dict */ + 0, /*tp_descr_get */ + 0, /*tp_descr_set */ + 0, /*tp_dictoffset */ + 0, /*tp_init */ + 0, /*tp_alloc */ + notimplemented_new, /*tp_new */ }; PyObject _Py_NotImplementedStruct = {