]> granicus.if.org Git - python/commitdiff
Two fixes for extended call syntax:
authorJeremy Hylton <jeremy@alum.mit.edu>
Thu, 30 Mar 2000 23:55:31 +0000 (23:55 +0000)
committerJeremy Hylton <jeremy@alum.mit.edu>
Thu, 30 Mar 2000 23:55:31 +0000 (23:55 +0000)
If a non-tuple sequence is passed as the *arg, convert it to a tuple
before checking its length.
If named keyword arguments are used in combination with **kwargs, make
a copy of kwargs before inserting the new keys.

Lib/test/output/test_extcall
Lib/test/test_extcall.py
Python/ceval.c

index f4369b5dad44dbf01d48a79d6f26acdde8dfd2f1..209ded7f347cad7c78067a0dc771a8444dc36031 100644 (file)
@@ -16,6 +16,10 @@ TypeError: not enough arguments; expected 1, got 0
 1 (2,) {}
 1 (2, 3) {}
 1 (2, 3, 4, 5) {}
+0 (1, 2) {}
+1 () {'d': 4, 'b': 2, 'c': 3, 'a': 1}
+{'b': 2, 'c': 3, 'a': 1}
+{'b': 2, 'c': 3, 'a': 1}
 keyword parameter redefined: x
 keyword parameter redefined: b
 keywords must be strings
index 9b5994d3c9c03d2feff2fb6fe6d4b03ecc64cf31..74d9ef2aca99eca823a50d6110ad4876dd889f81 100644 (file)
@@ -46,6 +46,50 @@ g(1)
 g(1, 2)
 g(1, 2, 3)
 g(1, 2, 3, *(4, 5))
+class Nothing: pass
+try:
+    g(*Nothing())
+except AttributeError, attr:
+    assert attr[0] == '__len__'
+else:
+    print "should raise AttributeError: __len__"
+
+class Nothing:
+    def __len__(self):
+        return 5
+try:
+    g(*Nothing())
+except AttributeError, attr:
+    assert attr[0] == '__getitem__'
+else:
+    print "should raise AttributeError: __getitem__"
+    
+class Nothing:
+    def __len__(self):
+        return 5
+    def __getitem__(self, i):
+        if i < 3:
+            return i
+        else:
+            raise IndexError, i
+g(*Nothing())
+
+# make sure the function call doesn't stomp on the dictionary?
+d = {'a': 1, 'b': 2, 'c': 3}
+d2 = d.copy()
+assert d == d2
+g(1, d=4, **d)
+print d
+print d2
+assert d == d2, "function call modified dictionary"
+
+# what about willful misconduct?
+def saboteur(**kw):
+    kw['x'] = locals()
+d = {}
+saboteur(a=1, **d)
+assert d == {}
+        
 try:
     g(1, 2, 3, **{'x':4, 'y':5})
 except TypeError, err:
index d7171c8de3aaffaa957a6636883f46c881eacae2..6b3b25748573ed50ca338aa5149d2136c0c0e93b 100644 (file)
@@ -1635,7 +1635,18 @@ eval_code2(co, globals, locals,
                                x = NULL;
                                break;
                            }
-                           nstar = PySequence_Length(stararg);
+                           /* Convert abstract sequence to concrete tuple */
+                           if (!PyTuple_Check(stararg)) {
+                               PyObject *t = NULL;
+                               t = PySequence_Tuple(stararg);
+                               if (t == NULL) {
+                                   x = NULL;
+                                   break;
+                               }
+                               Py_DECREF(stararg);
+                               stararg = t;
+                           }
+                           nstar = PyTuple_GET_SIZE(stararg);
                            if (nstar < 0) {
                                x = NULL;
                                break;
@@ -1649,6 +1660,15 @@ eval_code2(co, globals, locals,
                                    break;
                                }
                            }
+                           else {
+                                   PyObject *d = PyDict_Copy(kwdict);
+                                   if (d == NULL) {
+                                           x = NULL;
+                                           break;
+                                   }
+                                   Py_DECREF(kwdict);
+                                   kwdict = d;
+                           }
                            err = 0;
                            while (--nk >= 0) {
                                PyObject *value = POP();
@@ -1678,18 +1698,7 @@ eval_code2(co, globals, locals,
                            break;
                        }
                        if (stararg) {
-                           PyObject *t = NULL;
                            int i;
-                           if (!PyTuple_Check(stararg)) {
-                               /* must be sequence to pass earlier test */
-                               t = PySequence_Tuple(stararg);
-                               if (t == NULL) {
-                                   x = NULL;
-                                   break;
-                               }
-                               Py_DECREF(stararg);
-                               stararg = t;
-                           }
                            for (i = 0; i < nstar; i++) {
                                PyObject *a = PyTuple_GET_ITEM(stararg, i);
                                Py_INCREF(a);