mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	Bug #1486663: don't reject keyword arguments for subclasses of builtin
types.
This commit is contained in:
		
							parent
							
								
									aef4c6bc00
								
							
						
					
					
						commit
						b84c13792d
					
				
					 9 changed files with 62 additions and 16 deletions
				
			
		|  | @ -12,6 +12,10 @@ | ||||||
| class ArraySubclass(array.array): | class ArraySubclass(array.array): | ||||||
|     pass |     pass | ||||||
| 
 | 
 | ||||||
|  | class ArraySubclassWithKwargs(array.array): | ||||||
|  |     def __init__(self, typecode, newarg=None): | ||||||
|  |         array.array.__init__(typecode) | ||||||
|  | 
 | ||||||
| tests = [] # list to accumulate all tests | tests = [] # list to accumulate all tests | ||||||
| typecodes = "cubBhHiIlLfd" | typecodes = "cubBhHiIlLfd" | ||||||
| 
 | 
 | ||||||
|  | @ -683,6 +687,9 @@ def test_bug_782369(self): | ||||||
|                 b = array.array('B', range(64)) |                 b = array.array('B', range(64)) | ||||||
|             self.assertEqual(rc, sys.getrefcount(10)) |             self.assertEqual(rc, sys.getrefcount(10)) | ||||||
| 
 | 
 | ||||||
|  |     def test_subclass_with_kwargs(self): | ||||||
|  |         # SF bug #1486663 -- this used to erroneously raise a TypeError | ||||||
|  |         ArraySubclassWithKwargs('b', newarg=1) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class StringTest(BaseTest): | class StringTest(BaseTest): | ||||||
|  |  | ||||||
|  | @ -486,6 +486,16 @@ def __iter__(self): | ||||||
|         d1 == d2   # not clear if this is supposed to be True or False, |         d1 == d2   # not clear if this is supposed to be True or False, | ||||||
|                    # but it used to give a SystemError |                    # but it used to give a SystemError | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | class SubclassWithKwargs(deque): | ||||||
|  |     def __init__(self, newarg=1): | ||||||
|  |         deque.__init__(self) | ||||||
|  | 
 | ||||||
|  | class TestSubclassWithKwargs(unittest.TestCase): | ||||||
|  |     def test_subclass_with_kwargs(self): | ||||||
|  |         # SF bug #1486663 -- this used to erroneously raise a TypeError | ||||||
|  |         SubclassWithKwargs(newarg=1) | ||||||
|  | 
 | ||||||
| #============================================================================== | #============================================================================== | ||||||
| 
 | 
 | ||||||
| libreftest = """ | libreftest = """ | ||||||
|  | @ -599,6 +609,7 @@ def test_main(verbose=None): | ||||||
|         TestBasic, |         TestBasic, | ||||||
|         TestVariousIteratorArgs, |         TestVariousIteratorArgs, | ||||||
|         TestSubclass, |         TestSubclass, | ||||||
|  |         TestSubclassWithKwargs, | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     test_support.run_unittest(*test_classes) |     test_support.run_unittest(*test_classes) | ||||||
|  |  | ||||||
|  | @ -740,6 +740,21 @@ def gen2(x): | ||||||
|         self.assertRaises(AssertionError, list, cycle(gen1())) |         self.assertRaises(AssertionError, list, cycle(gen1())) | ||||||
|         self.assertEqual(hist, [0,1]) |         self.assertEqual(hist, [0,1]) | ||||||
| 
 | 
 | ||||||
|  | class SubclassWithKwargsTest(unittest.TestCase): | ||||||
|  |     def test_keywords_in_subclass(self): | ||||||
|  |         # count is not subclassable... | ||||||
|  |         for cls in (repeat, izip, ifilter, ifilterfalse, chain, imap, | ||||||
|  |                     starmap, islice, takewhile, dropwhile, cycle): | ||||||
|  |             class Subclass(cls): | ||||||
|  |                 def __init__(self, newarg=None, *args): | ||||||
|  |                     cls.__init__(self, *args) | ||||||
|  |             try: | ||||||
|  |                 Subclass(newarg=1) | ||||||
|  |             except TypeError, err: | ||||||
|  |                 # we expect type errors because of wrong argument count | ||||||
|  |                 self.failIf("does not take keyword arguments" in err.args[0]) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| libreftest = """ Doctest for examples in the library reference: libitertools.tex | libreftest = """ Doctest for examples in the library reference: libitertools.tex | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -934,7 +949,8 @@ def gen2(x): | ||||||
| 
 | 
 | ||||||
| def test_main(verbose=None): | def test_main(verbose=None): | ||||||
|     test_classes = (TestBasicOps, TestVariousIteratorArgs, TestGC, |     test_classes = (TestBasicOps, TestVariousIteratorArgs, TestGC, | ||||||
|                     RegressionTests, LengthTransparency) |                     RegressionTests, LengthTransparency, | ||||||
|  |                     SubclassWithKwargsTest) | ||||||
|     test_support.run_unittest(*test_classes) |     test_support.run_unittest(*test_classes) | ||||||
| 
 | 
 | ||||||
|     # verify reference counting |     # verify reference counting | ||||||
|  |  | ||||||
|  | @ -515,6 +515,14 @@ def test__all__(self): | ||||||
|         # tests validity but not completeness of the __all__ list |         # tests validity but not completeness of the __all__ list | ||||||
|         self.failUnless(set(random.__all__) <= set(dir(random))) |         self.failUnless(set(random.__all__) <= set(dir(random))) | ||||||
| 
 | 
 | ||||||
|  |     def test_random_subclass_with_kwargs(self): | ||||||
|  |         # SF bug #1486663 -- this used to erroneously raise a TypeError | ||||||
|  |         class Subclass(random.Random): | ||||||
|  |             def __init__(self, newarg=None): | ||||||
|  |                 random.Random.__init__(self) | ||||||
|  |         Subclass(newarg=1) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| def test_main(verbose=None): | def test_main(verbose=None): | ||||||
|     testclasses =    [WichmannHill_TestBasicOps, |     testclasses =    [WichmannHill_TestBasicOps, | ||||||
|                       MersenneTwister_TestBasicOps, |                       MersenneTwister_TestBasicOps, | ||||||
|  |  | ||||||
|  | @ -313,6 +313,9 @@ Library | ||||||
| Extension Modules | Extension Modules | ||||||
| ----------------- | ----------------- | ||||||
| 
 | 
 | ||||||
|  | - Bug #1486663: don't reject keyword arguments for subclasses of builtin | ||||||
|  |   types. | ||||||
|  | 
 | ||||||
| - Patch #1610575: The struct module now supports the 't' code, for | - Patch #1610575: The struct module now supports the 't' code, for | ||||||
|   C99 _Bool. |   C99 _Bool. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -481,7 +481,7 @@ random_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | ||||||
| 	RandomObject *self; | 	RandomObject *self; | ||||||
| 	PyObject *tmp; | 	PyObject *tmp; | ||||||
| 
 | 
 | ||||||
| 	if (!_PyArg_NoKeywords("Random()", kwds)) | 	if (type == &Random_Type && !_PyArg_NoKeywords("Random()", kwds)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
| 	self = (RandomObject *)type->tp_alloc(type, 0); | 	self = (RandomObject *)type->tp_alloc(type, 0); | ||||||
|  |  | ||||||
|  | @ -1797,7 +1797,7 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | ||||||
| 	PyObject *initial = NULL, *it = NULL; | 	PyObject *initial = NULL, *it = NULL; | ||||||
| 	struct arraydescr *descr; | 	struct arraydescr *descr; | ||||||
| 	 | 	 | ||||||
| 	if (!_PyArg_NoKeywords("array.array()", kwds)) | 	if (type == &Arraytype && !_PyArg_NoKeywords("array.array()", kwds)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
| 	if (!PyArg_ParseTuple(args, "c|O:array", &c, &initial)) | 	if (!PyArg_ParseTuple(args, "c|O:array", &c, &initial)) | ||||||
|  |  | ||||||
|  | @ -95,7 +95,7 @@ deque_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | ||||||
| 	dequeobject *deque; | 	dequeobject *deque; | ||||||
| 	block *b; | 	block *b; | ||||||
| 
 | 
 | ||||||
| 	if (!_PyArg_NoKeywords("deque()", kwds)) | 	if (type == &deque_type && !_PyArg_NoKeywords("deque()", kwds)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
| 	/* create dequeobject structure */ | 	/* create dequeobject structure */ | ||||||
|  |  | ||||||
|  | @ -681,7 +681,7 @@ cycle_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | ||||||
| 	PyObject *saved; | 	PyObject *saved; | ||||||
| 	cycleobject *lz; | 	cycleobject *lz; | ||||||
| 
 | 
 | ||||||
| 	if (!_PyArg_NoKeywords("cycle()", kwds)) | 	if (type == &cycle_type && !_PyArg_NoKeywords("cycle()", kwds)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
| 	if (!PyArg_UnpackTuple(args, "cycle", 1, 1, &iterable)) | 	if (!PyArg_UnpackTuple(args, "cycle", 1, 1, &iterable)) | ||||||
|  | @ -831,7 +831,7 @@ dropwhile_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | ||||||
| 	PyObject *it; | 	PyObject *it; | ||||||
| 	dropwhileobject *lz; | 	dropwhileobject *lz; | ||||||
| 
 | 
 | ||||||
| 	if (!_PyArg_NoKeywords("dropwhile()", kwds)) | 	if (type == &dropwhile_type && !_PyArg_NoKeywords("dropwhile()", kwds)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
| 	if (!PyArg_UnpackTuple(args, "dropwhile", 2, 2, &func, &seq)) | 	if (!PyArg_UnpackTuple(args, "dropwhile", 2, 2, &func, &seq)) | ||||||
|  | @ -975,7 +975,7 @@ takewhile_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | ||||||
| 	PyObject *it; | 	PyObject *it; | ||||||
| 	takewhileobject *lz; | 	takewhileobject *lz; | ||||||
| 
 | 
 | ||||||
| 	if (!_PyArg_NoKeywords("takewhile()", kwds)) | 	if (type == &takewhile_type && !_PyArg_NoKeywords("takewhile()", kwds)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
| 	if (!PyArg_UnpackTuple(args, "takewhile", 2, 2, &func, &seq)) | 	if (!PyArg_UnpackTuple(args, "takewhile", 2, 2, &func, &seq)) | ||||||
|  | @ -1120,7 +1120,7 @@ islice_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | ||||||
| 	Py_ssize_t numargs; | 	Py_ssize_t numargs; | ||||||
| 	isliceobject *lz; | 	isliceobject *lz; | ||||||
| 
 | 
 | ||||||
| 	if (!_PyArg_NoKeywords("islice()", kwds)) | 	if (type == &islice_type && !_PyArg_NoKeywords("islice()", kwds)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
| 	if (!PyArg_UnpackTuple(args, "islice", 2, 4, &seq, &a1, &a2, &a3)) | 	if (!PyArg_UnpackTuple(args, "islice", 2, 4, &seq, &a1, &a2, &a3)) | ||||||
|  | @ -1311,7 +1311,7 @@ starmap_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | ||||||
| 	PyObject *it; | 	PyObject *it; | ||||||
| 	starmapobject *lz; | 	starmapobject *lz; | ||||||
| 
 | 
 | ||||||
| 	if (!_PyArg_NoKeywords("starmap()", kwds)) | 	if (type == &starmap_type && !_PyArg_NoKeywords("starmap()", kwds)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
| 	if (!PyArg_UnpackTuple(args, "starmap", 2, 2, &func, &seq)) | 	if (!PyArg_UnpackTuple(args, "starmap", 2, 2, &func, &seq)) | ||||||
|  | @ -1443,7 +1443,7 @@ imap_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | ||||||
| 	imapobject *lz; | 	imapobject *lz; | ||||||
| 	Py_ssize_t numargs, i; | 	Py_ssize_t numargs, i; | ||||||
| 
 | 
 | ||||||
| 	if (!_PyArg_NoKeywords("imap()", kwds)) | 	if (type == &imap_type && !_PyArg_NoKeywords("imap()", kwds)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
| 	numargs = PyTuple_Size(args); | 	numargs = PyTuple_Size(args); | ||||||
|  | @ -1625,7 +1625,7 @@ chain_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | ||||||
| 	Py_ssize_t i; | 	Py_ssize_t i; | ||||||
| 	PyObject *ittuple; | 	PyObject *ittuple; | ||||||
| 
 | 
 | ||||||
| 	if (!_PyArg_NoKeywords("chain()", kwds)) | 	if (type == &chain_type && !_PyArg_NoKeywords("chain()", kwds)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
| 	/* obtain iterators */ | 	/* obtain iterators */ | ||||||
|  | @ -1768,7 +1768,7 @@ ifilter_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | ||||||
| 	PyObject *it; | 	PyObject *it; | ||||||
| 	ifilterobject *lz; | 	ifilterobject *lz; | ||||||
| 
 | 
 | ||||||
| 	if (!_PyArg_NoKeywords("ifilter()", kwds)) | 	if (type == &ifilter_type && !_PyArg_NoKeywords("ifilter()", kwds)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
| 	if (!PyArg_UnpackTuple(args, "ifilter", 2, 2, &func, &seq)) | 	if (!PyArg_UnpackTuple(args, "ifilter", 2, 2, &func, &seq)) | ||||||
|  | @ -1912,7 +1912,8 @@ ifilterfalse_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | ||||||
| 	PyObject *it; | 	PyObject *it; | ||||||
| 	ifilterfalseobject *lz; | 	ifilterfalseobject *lz; | ||||||
| 
 | 
 | ||||||
| 	if (!_PyArg_NoKeywords("ifilterfalse()", kwds)) | 	if (type == &ifilterfalse_type && | ||||||
|  | 	    !_PyArg_NoKeywords("ifilterfalse()", kwds)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
| 	if (!PyArg_UnpackTuple(args, "ifilterfalse", 2, 2, &func, &seq)) | 	if (!PyArg_UnpackTuple(args, "ifilterfalse", 2, 2, &func, &seq)) | ||||||
|  | @ -2054,7 +2055,7 @@ count_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | ||||||
| 	countobject *lz; | 	countobject *lz; | ||||||
| 	Py_ssize_t cnt = 0; | 	Py_ssize_t cnt = 0; | ||||||
| 
 | 
 | ||||||
| 	if (!_PyArg_NoKeywords("count()", kwds)) | 	if (type == &count_type && !_PyArg_NoKeywords("count()", kwds)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
| 	if (!PyArg_ParseTuple(args, "|n:count", &cnt)) | 	if (!PyArg_ParseTuple(args, "|n:count", &cnt)) | ||||||
|  | @ -2153,7 +2154,7 @@ izip_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | ||||||
| 	PyObject *result; | 	PyObject *result; | ||||||
| 	Py_ssize_t tuplesize = PySequence_Length(args); | 	Py_ssize_t tuplesize = PySequence_Length(args); | ||||||
| 
 | 
 | ||||||
| 	if (!_PyArg_NoKeywords("izip()", kwds)) | 	if (type == &izip_type && !_PyArg_NoKeywords("izip()", kwds)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
| 	/* args must be a tuple */ | 	/* args must be a tuple */ | ||||||
|  | @ -2336,7 +2337,7 @@ repeat_new(PyTypeObject *type, PyObject *args, PyObject *kwds) | ||||||
| 	PyObject *element; | 	PyObject *element; | ||||||
| 	Py_ssize_t cnt = -1; | 	Py_ssize_t cnt = -1; | ||||||
| 
 | 
 | ||||||
| 	if (!_PyArg_NoKeywords("repeat()", kwds)) | 	if (type == &repeat_type && !_PyArg_NoKeywords("repeat()", kwds)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
| 	if (!PyArg_ParseTuple(args, "O|n:repeat", &element, &cnt)) | 	if (!PyArg_ParseTuple(args, "O|n:repeat", &element, &cnt)) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Georg Brandl
						Georg Brandl