[Python-checkins] r51486 - in python/branches/p3yk-noslice: Include/opcode.h Lib/UserList.py Lib/UserString.py Lib/sre_parse.py Lib/test/list_tests.py Lib/test/output/test_class Lib/test/seq_tests.py Lib/test/string_tests.py Lib/test/test_descr.py Lib/test/test_index.py Lib/test/test_support.py Lib/test/test_userlist.py Objects/bufferobject.c Objects/bytesobject.c Objects/structseq.c Python/ceval.c Python/compile.c

thomas.wouters python-checkins at python.org
Tue Aug 22 21:54:36 CEST 2006


Author: thomas.wouters
Date: Tue Aug 22 21:54:34 2006
New Revision: 51486

Modified:
   python/branches/p3yk-noslice/Include/opcode.h
   python/branches/p3yk-noslice/Lib/UserList.py
   python/branches/p3yk-noslice/Lib/UserString.py
   python/branches/p3yk-noslice/Lib/sre_parse.py
   python/branches/p3yk-noslice/Lib/test/list_tests.py
   python/branches/p3yk-noslice/Lib/test/output/test_class
   python/branches/p3yk-noslice/Lib/test/seq_tests.py
   python/branches/p3yk-noslice/Lib/test/string_tests.py
   python/branches/p3yk-noslice/Lib/test/test_descr.py
   python/branches/p3yk-noslice/Lib/test/test_index.py
   python/branches/p3yk-noslice/Lib/test/test_support.py
   python/branches/p3yk-noslice/Lib/test/test_userlist.py
   python/branches/p3yk-noslice/Objects/bufferobject.c
   python/branches/p3yk-noslice/Objects/bytesobject.c
   python/branches/p3yk-noslice/Objects/structseq.c
   python/branches/p3yk-noslice/Python/ceval.c
   python/branches/p3yk-noslice/Python/compile.c
Log:

Checkpoint current status of removing-slice work:
 - Add 'extended' (now really just 'normal') slicing support to buffer,
   bytes and structseq, including non-default step sizes.
 - Fix proxying in UserList, UserString
 - Adjust sre_parse to cope with slice objects
 (Those three items could be forward-ported to 2.6)

 - Remove all 12 SLICE opcodes, freeing up an otherwise unused register vrbl
   in ceval.c's PyEval_EvalFrameEx
 - Fix tests to not look at __getslice__ (possibly by removing tests too
   rigorously)

TODO:
 - Fix mmap to support slice objects (test currently fails)
 - Fix ctypes to support slice objects (test currently fails)
 - Remove PySequenceMethod hooks and rework various API's to index using
   slice objects instead
 - Remove PySequence_Check and PyMapping_Check (or think of a new way of
   spelling them)
 - Check removed tests to see if they should be readded



Modified: python/branches/p3yk-noslice/Include/opcode.h
==============================================================================
--- python/branches/p3yk-noslice/Include/opcode.h	(original)
+++ python/branches/p3yk-noslice/Include/opcode.h	Tue Aug 22 21:54:34 2006
@@ -36,15 +36,6 @@
 #define INPLACE_FLOOR_DIVIDE 28
 #define INPLACE_TRUE_DIVIDE 29
 
-#define SLICE		30
-/* Also uses 31-33 */
-
-#define STORE_SLICE	40
-/* Also uses 41-43 */
-
-#define DELETE_SLICE	50
-/* Also uses 51-53 */
-
 #define INPLACE_ADD	55
 #define INPLACE_SUBTRACT	56
 #define INPLACE_MULTIPLY	57

Modified: python/branches/p3yk-noslice/Lib/UserList.py
==============================================================================
--- python/branches/p3yk-noslice/Lib/UserList.py	(original)
+++ python/branches/p3yk-noslice/Lib/UserList.py	Tue Aug 22 21:54:34 2006
@@ -28,20 +28,6 @@
     def __getitem__(self, i): return self.data[i]
     def __setitem__(self, i, item): self.data[i] = item
     def __delitem__(self, i): del self.data[i]
-    def __getslice__(self, i, j):
-        i = max(i, 0); j = max(j, 0)
-        return self.__class__(self.data[i:j])
-    def __setslice__(self, i, j, other):
-        i = max(i, 0); j = max(j, 0)
-        if isinstance(other, UserList):
-            self.data[i:j] = other.data
-        elif isinstance(other, type(self.data)):
-            self.data[i:j] = other
-        else:
-            self.data[i:j] = list(other)
-    def __delslice__(self, i, j):
-        i = max(i, 0); j = max(j, 0)
-        del self.data[i:j]
     def __add__(self, other):
         if isinstance(other, UserList):
             return self.__class__(self.data + other.data)

Modified: python/branches/p3yk-noslice/Lib/UserString.py
==============================================================================
--- python/branches/p3yk-noslice/Lib/UserString.py	(original)
+++ python/branches/p3yk-noslice/Lib/UserString.py	Tue Aug 22 21:54:34 2006
@@ -35,9 +35,6 @@
 
     def __len__(self): return len(self.data)
     def __getitem__(self, index): return self.__class__(self.data[index])
-    def __getslice__(self, start, end):
-        start = max(start, 0); end = max(end, 0)
-        return self.__class__(self.data[start:end])
 
     def __add__(self, other):
         if isinstance(other, UserString):
@@ -149,26 +146,31 @@
     def __hash__(self):
         raise TypeError, "unhashable type (it is mutable)"
     def __setitem__(self, index, sub):
-        if index < 0:
-            index += len(self.data)
-        if index < 0 or index >= len(self.data): raise IndexError
-        self.data = self.data[:index] + sub + self.data[index+1:]
+        if isinstance(index, slice):
+            if isinstance(sub, UserString):
+               sub = sub.data
+            elif not isinstance(sub, basestring):
+               sub = str(sub)
+            start, stop, step = index.indices(len(self.data))
+            if step != 1:
+                raise TypeError, "invalid step in slicing assignment"
+            self.data = self.data[:start] + sub + self.data[stop:]
+        else:
+            if index < 0:
+                index += len(self.data)
+            if index < 0 or index >= len(self.data): raise IndexError
+            self.data = self.data[:index] + sub + self.data[index+1:]
     def __delitem__(self, index):
-        if index < 0:
-            index += len(self.data)
-        if index < 0 or index >= len(self.data): raise IndexError
-        self.data = self.data[:index] + self.data[index+1:]
-    def __setslice__(self, start, end, sub):
-        start = max(start, 0); end = max(end, 0)
-        if isinstance(sub, UserString):
-            self.data = self.data[:start]+sub.data+self.data[end:]
-        elif isinstance(sub, basestring):
-            self.data = self.data[:start]+sub+self.data[end:]
-        else:
-            self.data =  self.data[:start]+str(sub)+self.data[end:]
-    def __delslice__(self, start, end):
-        start = max(start, 0); end = max(end, 0)
-        self.data = self.data[:start] + self.data[end:]
+        if isinstance(index, slice):
+            start, stop, step = index.indices(len(self.data))
+            if step != 1:
+                raise TypeError, "invalid step in slicing assignment"
+            self.data = self.data[:start] + self.data[stop:]
+        else:
+            if index < 0:
+                index += len(self.data)
+            if index < 0 or index >= len(self.data): raise IndexError
+            self.data = self.data[:index] + self.data[index+1:]
     def immutable(self):
         return UserString(self.data)
     def __iadd__(self, other):

Modified: python/branches/p3yk-noslice/Lib/sre_parse.py
==============================================================================
--- python/branches/p3yk-noslice/Lib/sre_parse.py	(original)
+++ python/branches/p3yk-noslice/Lib/sre_parse.py	Tue Aug 22 21:54:34 2006
@@ -134,11 +134,11 @@
     def __delitem__(self, index):
         del self.data[index]
     def __getitem__(self, index):
+        if isinstance(index, slice):
+            return SubPattern(self.pattern, self.data[index])
         return self.data[index]
     def __setitem__(self, index, code):
         self.data[index] = code
-    def __getslice__(self, start, stop):
-        return SubPattern(self.pattern, self.data[start:stop])
     def insert(self, index, code):
         self.data.insert(index, code)
     def append(self, code):

Modified: python/branches/p3yk-noslice/Lib/test/list_tests.py
==============================================================================
--- python/branches/p3yk-noslice/Lib/test/list_tests.py	(original)
+++ python/branches/p3yk-noslice/Lib/test/list_tests.py	Tue Aug 22 21:54:34 2006
@@ -178,9 +178,9 @@
         a[:] = tuple(range(10))
         self.assertEqual(a, self.type2test(range(10)))
 
-        self.assertRaises(TypeError, a.__setslice__, 0, 1, 5)
+        self.assertRaises(TypeError, a.__setitem__, slice(0, 1, 5))
 
-        self.assertRaises(TypeError, a.__setslice__)
+        self.assertRaises(TypeError, a.__setitem__)
 
     def test_delslice(self):
         a = self.type2test([0, 1])

Modified: python/branches/p3yk-noslice/Lib/test/output/test_class
==============================================================================
--- python/branches/p3yk-noslice/Lib/test/output/test_class	(original)
+++ python/branches/p3yk-noslice/Lib/test/output/test_class	Tue Aug 22 21:54:34 2006
@@ -28,9 +28,9 @@
 __getitem__: (1,)
 __setitem__: (1, 1)
 __delitem__: (1,)
-__getslice__: (0, 42)
-__setslice__: (0, 42, 'The Answer')
-__delslice__: (0, 42)
+__getitem__: (slice(None, 42, None),)
+__setitem__: (slice(None, 42, None), 'The Answer')
+__delitem__: (slice(None, 42, None),)
 __getitem__: (slice(2, 1024, 10),)
 __setitem__: (slice(2, 1024, 10), 'A lot')
 __delitem__: (slice(2, 1024, 10),)

Modified: python/branches/p3yk-noslice/Lib/test/seq_tests.py
==============================================================================
--- python/branches/p3yk-noslice/Lib/test/seq_tests.py	(original)
+++ python/branches/p3yk-noslice/Lib/test/seq_tests.py	Tue Aug 22 21:54:34 2006
@@ -196,8 +196,6 @@
         self.assertEqual(a[ -pow(2,128L): 3 ], self.type2test([0,1,2]))
         self.assertEqual(a[ 3: pow(2,145L) ], self.type2test([3,4]))
 
-        self.assertRaises(TypeError, u.__getslice__)
-
     def test_contains(self):
         u = self.type2test([0, 1, 2])
         for i in u:

Modified: python/branches/p3yk-noslice/Lib/test/string_tests.py
==============================================================================
--- python/branches/p3yk-noslice/Lib/test/string_tests.py	(original)
+++ python/branches/p3yk-noslice/Lib/test/string_tests.py	Tue Aug 22 21:54:34 2006
@@ -911,20 +911,6 @@
 
         self.checkraises(TypeError, 'abc', '__getitem__', 'def')
 
-    def test_slice(self):
-        self.checkequal('abc', 'abc', '__getslice__', 0, 1000)
-        self.checkequal('abc', 'abc', '__getslice__', 0, 3)
-        self.checkequal('ab', 'abc', '__getslice__', 0, 2)
-        self.checkequal('bc', 'abc', '__getslice__', 1, 3)
-        self.checkequal('b', 'abc', '__getslice__', 1, 2)
-        self.checkequal('', 'abc', '__getslice__', 2, 2)
-        self.checkequal('', 'abc', '__getslice__', 1000, 1000)
-        self.checkequal('', 'abc', '__getslice__', 2000, 1000)
-        self.checkequal('', 'abc', '__getslice__', 2, 1)
-        # FIXME What about negative indizes? This is handled differently by [] and __getslice__
-
-        self.checkraises(TypeError, 'abc', '__getslice__', 'def')
-
     def test_mul(self):
         self.checkequal('', 'abc', '__mul__', -1)
         self.checkequal('', 'abc', '__mul__', 0)

Modified: python/branches/p3yk-noslice/Lib/test/test_descr.py
==============================================================================
--- python/branches/p3yk-noslice/Lib/test/test_descr.py	(original)
+++ python/branches/p3yk-noslice/Lib/test/test_descr.py	Tue Aug 22 21:54:34 2006
@@ -39,7 +39,7 @@
     bm = getattr(a, meth)
     vereq(bm(b), res)
 
-def testternop(a, b, c, res, expr="a[b:c]", meth="__getslice__"):
+def testternop(a, b, c, res, expr="a[b:c]", meth="__getitem__"):
     if verbose: print "checking", expr
     dict = {'a': a, 'b': b, 'c': c}
     vereq(eval(expr, dict), res)
@@ -48,9 +48,9 @@
     while meth not in t.__dict__:
         t = t.__bases__[0]
     vereq(m, t.__dict__[meth])
-    vereq(m(a, b, c), res)
+    vereq(m(a, slice(b, c, None)), res)
     bm = getattr(a, meth)
-    vereq(bm(b, c), res)
+    vereq(bm(slice(b, c, None)), res)
 
 def testsetop(a, b, res, stmt="a+=b", meth="__iadd__"):
     if verbose: print "checking", stmt
@@ -88,7 +88,7 @@
     bm(b, c)
     vereq(dict['a'], res)
 
-def testset3op(a, b, c, d, res, stmt="a[b:c]=d", meth="__setslice__"):
+def testset3op(a, b, c, d, res, stmt="a[b:c]=d", meth="__setitem__"):
     if verbose: print "checking", stmt
     dict = {'a': deepcopy(a), 'b': b, 'c': c, 'd': d}
     exec stmt in dict
@@ -99,11 +99,11 @@
     m = getattr(t, meth)
     vereq(m, t.__dict__[meth])
     dict['a'] = deepcopy(a)
-    m(dict['a'], b, c, d)
+    m(dict['a'], slice(b, c, None), d)
     vereq(dict['a'], res)
     dict['a'] = deepcopy(a)
     bm = getattr(dict['a'], meth)
-    bm(b, c, d)
+    bm(slice(b, c, None), d)
     vereq(dict['a'], res)
 
 def class_docstrings():
@@ -140,14 +140,14 @@
     testbinop([1,2,3], 2, 1, "b in a", "__contains__")
     testbinop([1,2,3], 4, 0, "b in a", "__contains__")
     testbinop([1,2,3], 1, 2, "a[b]", "__getitem__")
-    testternop([1,2,3], 0, 2, [1,2], "a[b:c]", "__getslice__")
+    testternop([1,2,3], 0, 2, [1,2], "a[b:c]", "__getitem__")
     testsetop([1], [2], [1,2], "a+=b", "__iadd__")
     testsetop([1,2], 3, [1,2,1,2,1,2], "a*=b", "__imul__")
     testunop([1,2,3], 3, "len(a)", "__len__")
     testbinop([1,2], 3, [1,2,1,2,1,2], "a*b", "__mul__")
     testbinop([1,2], 3, [1,2,1,2,1,2], "b*a", "__rmul__")
     testset2op([1,2], 1, 3, [1,3], "a[b]=c", "__setitem__")
-    testset3op([1,2,3,4], 1, 3, [5,6], [1,5,6,4], "a[b:c]=d", "__setslice__")
+    testset3op([1,2,3,4], 1, 3, [5,6], [1,5,6,4], "a[b:c]=d", "__setitem__")
 
 def dicts():
     if verbose: print "Testing dict operations..."
@@ -490,7 +490,7 @@
     testbinop(spamlist([1,2,3]), 4, 0, "b in a", "__contains__")
     testbinop(spamlist([1,2,3]), 1, 2, "a[b]", "__getitem__")
     testternop(spamlist([1,2,3]), 0, 2, spamlist([1,2]),
-               "a[b:c]", "__getslice__")
+               "a[b:c]", "__getitem__")
     testsetop(spamlist([1]), spamlist([2]), spamlist([1,2]),
               "a+=b", "__iadd__")
     testsetop(spamlist([1,2]), 3, spamlist([1,2,1,2,1,2]), "a*=b", "__imul__")
@@ -499,7 +499,7 @@
     testbinop(spamlist([1,2]), 3, spamlist([1,2,1,2,1,2]), "b*a", "__rmul__")
     testset2op(spamlist([1,2]), 1, 3, spamlist([1,3]), "a[b]=c", "__setitem__")
     testset3op(spamlist([1,2,3,4]), 1, 3, spamlist([5,6]),
-               spamlist([1,5,6,4]), "a[b:c]=d", "__setslice__")
+               spamlist([1,5,6,4]), "a[b:c]=d", "__setitem__")
     # Test subclassing
     class C(spam.spamlist):
         def foo(self): return 1
@@ -613,9 +613,9 @@
     if verbose: print "Testing Python subclass of list..."
     class C(list):
         def __getitem__(self, i):
+            if isinstance(i, slice):
+                return i.start, i.stop
             return list.__getitem__(self, i) + 100
-        def __getslice__(self, i, j):
-            return (i, j)
     a = C()
     a.extend([0,1,2])
     vereq(a[0], 100)
@@ -1580,13 +1580,6 @@
         def __delitem__(self, key):
             self.delitem = key
 
-        def __getslice__(self, i, j):
-            return ("getslice", i, j)
-        def __setslice__(self, i, j, value):
-            self.setslice = (i, j, value)
-        def __delslice__(self, i, j):
-            self.delslice = (i, j)
-
     a = C()
     vereq(a.foo, ("getattr", "foo"))
     a.foo = 12
@@ -1600,11 +1593,11 @@
     del a[12]
     vereq(a.delitem, 12)
 
-    vereq(a[0:10], ("getslice", 0, 10))
+    vereq(a[0:10], ("getitem", slice(0, 10, None)))
     a[0:10] = "foo"
-    vereq(a.setslice, (0, 10, "foo"))
+    vereq(a.setitem, (slice(0, 10, None), "foo"))
     del a[0:10]
-    vereq(a.delslice, (0, 10))
+    vereq(a.delitem, slice(0, 10, None))
 
 def methods():
     if verbose: print "Testing methods..."

Modified: python/branches/p3yk-noslice/Lib/test/test_index.py
==============================================================================
--- python/branches/p3yk-noslice/Lib/test/test_index.py	(original)
+++ python/branches/p3yk-noslice/Lib/test/test_index.py	Tue Aug 22 21:54:34 2006
@@ -188,12 +188,10 @@
                 return maxint
             def __getitem__(self, key):
                 return key
-            def __getslice__(self, i, j):
-                return i, j
         x = GetItem()
         self.assertEqual(x[self.pos], self.pos)
         self.assertEqual(x[self.neg], self.neg)
-        self.assertEqual(x[self.neg:self.pos], (-1, maxint))
+        self.assertEqual(x[self.neg:self.pos], slice(self.neg, self.pos, None))
         self.assertEqual(x[self.neg:self.pos:1].indices(maxint), (0, maxint, 1))
 
     def test_getitem(self):

Modified: python/branches/p3yk-noslice/Lib/test/test_support.py
==============================================================================
--- python/branches/p3yk-noslice/Lib/test/test_support.py	(original)
+++ python/branches/p3yk-noslice/Lib/test/test_support.py	Tue Aug 22 21:54:34 2006
@@ -314,10 +314,7 @@
 _2G = 2 * _1G
 
 # Hack to get at the maximum value an internal index can take.
-class _Dummy:
-    def __getslice__(self, i, j):
-        return j
-MAX_Py_ssize_t = _Dummy()[:]
+MAX_Py_ssize_t = 1<<63
 
 def set_memlimit(limit):
     import re

Modified: python/branches/p3yk-noslice/Lib/test/test_userlist.py
==============================================================================
--- python/branches/p3yk-noslice/Lib/test/test_userlist.py	(original)
+++ python/branches/p3yk-noslice/Lib/test/test_userlist.py	Tue Aug 22 21:54:34 2006
@@ -7,16 +7,6 @@
 class UserListTest(list_tests.CommonTest):
     type2test = UserList
 
-    def test_getslice(self):
-        super(UserListTest, self).test_getslice()
-        l = [0, 1, 2, 3, 4]
-        u = self.type2test(l)
-        for i in range(-3, 6):
-            self.assertEqual(u[:i], l[:i])
-            self.assertEqual(u[i:], l[i:])
-            for j in xrange(-3, 6):
-                self.assertEqual(u[i:j], l[i:j])
-
     def test_add_specials(self):
         u = UserList("spam")
         u2 = u + "eggs"

Modified: python/branches/p3yk-noslice/Objects/bufferobject.c
==============================================================================
--- python/branches/p3yk-noslice/Objects/bufferobject.c	(original)
+++ python/branches/p3yk-noslice/Objects/bufferobject.c	Tue Aug 22 21:54:34 2006
@@ -466,6 +466,62 @@
 					  right - left);
 }
 
+static PyObject *
+buffer_subscript(PyBufferObject *self, PyObject *item)
+{
+	void *p;
+	Py_ssize_t size;
+	
+	if (!get_buf(self, &p, &size, ANY_BUFFER))
+		return NULL;
+	if (PyIndex_Check(item)) {
+		Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
+		if (i == -1 && PyErr_Occurred())
+			return NULL;
+		if (i < 0)
+			i += size;
+		return buffer_item(self, i);
+	}
+	else if (PySlice_Check(item)) {
+		Py_ssize_t start, stop, step, slicelength, cur, i;
+
+		if (PySlice_GetIndicesEx((PySliceObject*)item, size,
+				 &start, &stop, &step, &slicelength) < 0) {
+			return NULL;
+		}
+
+		if (slicelength <= 0)
+			return PyString_FromStringAndSize("", 0);
+		else if (step == 1)
+			return PyString_FromStringAndSize((char *)p + start,
+							  stop - start);
+		else {
+			PyObject *result;
+			char *source_buf = (char *)p;
+			char *result_buf = (char *)PyMem_Malloc(slicelength);
+
+			if (result_buf == NULL)
+				return PyErr_NoMemory();
+
+			for (cur = start, i = 0; i < slicelength;
+			     cur += step, i++) {
+				result_buf[i] = source_buf[cur];
+			}
+
+			result = PyString_FromStringAndSize(result_buf,
+							    slicelength);
+			PyMem_Free(result_buf);
+			return result;
+		}
+	}
+	else {
+		PyErr_SetString(PyExc_TypeError,
+				"string indices must be integers");
+		return NULL;
+	}
+}
+		
+
 static int
 buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
 {
@@ -575,6 +631,101 @@
 	return 0;
 }
 
+static int
+buffer_ass_subscript(PyBufferObject *self, PyObject *item, PyObject *value)
+{
+	PyBufferProcs *pb;
+	void *ptr1, *ptr2;
+	Py_ssize_t selfsize;
+	Py_ssize_t othersize;
+	Py_ssize_t start, stop, step, slicelength;
+
+	if ( self->b_readonly ) {
+		PyErr_SetString(PyExc_TypeError,
+				"buffer is read-only");
+		return -1;
+	}
+
+	pb = value ? value->ob_type->tp_as_buffer : NULL;
+	if ( pb == NULL ||
+	     pb->bf_getreadbuffer == NULL ||
+	     pb->bf_getsegcount == NULL )
+	{
+		PyErr_BadArgument();
+		return -1;
+	}
+	if ( (*pb->bf_getsegcount)(value, NULL) != 1 )
+	{
+		/* ### use a different exception type/message? */
+		PyErr_SetString(PyExc_TypeError,
+				"single-segment buffer object expected");
+		return -1;
+	}
+	if (!get_buf(self, &ptr1, &selfsize, ANY_BUFFER))
+		return -1;
+	if (PyIndex_Check(item)) {
+		Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
+		if (i == -1 && PyErr_Occurred())
+			return -1;
+		if (i < 0)
+			i += selfsize;
+		return buffer_ass_item(self, i, value);
+	}
+	else if (PySlice_Check(item)) {
+		Py_ssize_t start, stop, step, slicelength;
+		
+		if (PySlice_GetIndicesEx((PySliceObject *)item, selfsize,
+				&start, &stop, &step, &slicelength) < 0)
+			return -1;
+
+		pb = value ? value->ob_type->tp_as_buffer : NULL;
+		if (pb == NULL ||
+		    pb->bf_getreadbuffer == NULL ||
+		    pb->bf_getsegcount == NULL) {
+			PyErr_BadArgument();
+			return -1;
+		}
+		if ((*pb->bf_getsegcount)(value, NULL) != 1) {
+			/* ### use a different exception type/message? */
+			PyErr_SetString(PyExc_TypeError,
+					"single-segment buffer object expected");
+			return -1;
+		}
+		if ((othersize = (*pb->bf_getreadbuffer)(value, 0, &ptr2)) < 0)
+			return -1;
+
+		if (othersize != slicelength) {
+			PyErr_SetString(
+				PyExc_TypeError,
+				"right operand length must match slice length");
+			return -1;
+		}
+
+		if (slicelength == 0)
+			return 0;
+		else if (step == 1) {
+			memcpy((char *)ptr1 + start, ptr2, slicelength);
+			return 0;
+		}
+		else {
+			Py_ssize_t cur, i;
+			char *resultbuf = (char *)ptr1;
+			char *sourcebuf = (char *)ptr2;
+			
+			for (cur = start, i = 0; i < slicelength;
+			     cur += step, i++) {
+				((char *)ptr1)[cur] = ((char *)ptr2)[i];
+			}
+
+			return 0;
+		}
+	} else {
+		PyErr_SetString(PyExc_TypeError,
+				"buffer indices must be integers");
+		return -1;
+	}
+}
+
 /* Buffer methods */
 
 static Py_ssize_t
@@ -650,6 +801,12 @@
 	(ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
 };
 
+static PyMappingMethods buffer_as_mapping = {
+	(lenfunc)buffer_length,
+	(binaryfunc)buffer_subscript,
+	(objobjargproc)buffer_ass_subscript,
+};
+
 static PyBufferProcs buffer_as_buffer = {
 	(readbufferproc)buffer_getreadbuf,
 	(writebufferproc)buffer_getwritebuf,
@@ -671,7 +828,7 @@
 	(reprfunc)buffer_repr,			/* tp_repr */
 	0,					/* tp_as_number */
 	&buffer_as_sequence,			/* tp_as_sequence */
-	0,					/* tp_as_mapping */
+	&buffer_as_mapping,			/* tp_as_mapping */
 	(hashfunc)buffer_hash,			/* tp_hash */
 	0,					/* tp_call */
 	(reprfunc)buffer_str,			/* tp_str */

Modified: python/branches/p3yk-noslice/Objects/bytesobject.c
==============================================================================
--- python/branches/p3yk-noslice/Objects/bytesobject.c	(original)
+++ python/branches/p3yk-noslice/Objects/bytesobject.c	Tue Aug 22 21:54:34 2006
@@ -280,6 +280,61 @@
     return PyBytes_FromStringAndSize(self->ob_bytes + lo, hi - lo);
 }
 
+static PyObject *
+bytes_subscript(PyBytesObject *self, PyObject *item)
+{
+    if (PyIndex_Check(item)) {
+        Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
+
+        if (i == -1 && PyErr_Occurred())
+            return NULL;
+
+        if (i < 0)
+            i += PyBytes_GET_SIZE(self);
+
+        if (i < 0 || i >= self->ob_size) {
+            PyErr_SetString(PyExc_IndexError, "bytes index out of range");
+            return NULL;
+        }
+        return PyInt_FromLong((unsigned char)(self->ob_bytes[i]));
+    }
+    else if (PySlice_Check(item)) {
+        Py_ssize_t start, stop, step, slicelength, cur, i;
+        if (PySlice_GetIndicesEx((PySliceObject *)item,
+                                 PyBytes_GET_SIZE(self),
+                                 &start, &stop, &step, &slicelength) < 0) {
+            return NULL;
+        }
+        
+        if (slicelength <= 0)
+            return PyBytes_FromStringAndSize("", 0);
+        else if (step == 1) {
+            return PyBytes_FromStringAndSize(self->ob_bytes + start,
+                                             slicelength);
+        }
+        else {
+            char *source_buf = PyBytes_AS_STRING(self);
+            char *result_buf = (char *)PyMem_Malloc(slicelength);
+            PyObject *result;
+            
+            if (result_buf == NULL)
+                return PyErr_NoMemory();
+            
+            for (cur = start, i = 0; i < slicelength;
+                 cur += step, i++) {
+                     result_buf[i] = source_buf[cur];
+            }
+            result = PyBytes_FromStringAndSize(result_buf, slicelength);
+            PyMem_Free(result_buf);
+            return result;
+        }
+    }
+    else {
+        PyErr_SetString(PyExc_TypeError, "bytes indices must be integers");
+        return NULL;
+    }
+}
+ 
 static int
 bytes_setslice(PyBytesObject *self, Py_ssize_t lo, Py_ssize_t hi, 
                PyObject *values)
@@ -379,6 +434,158 @@
 }
 
 static int
+bytes_ass_subscript(PyBytesObject *self, PyObject *item, PyObject *values)
+{
+    Py_ssize_t start, stop, step, slicelen, needed;
+    char *bytes;
+    
+    if (PyIndex_Check(item)) {
+        Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
+
+        if (i == -1 && PyErr_Occurred())
+            return -1;
+
+        if (i < 0)
+            i += PyBytes_GET_SIZE(self);
+
+        if (i < 0 || i >= self->ob_size) {
+            PyErr_SetString(PyExc_IndexError, "bytes index out of range");
+            return -1;
+        }
+        
+        if (values == NULL) {
+            /* Fall through to slice assignment */
+            start = i;
+            stop = i + 1;
+            step = 1;
+            slicelen = 1;
+        } else {
+            Py_ssize_t ival = PyNumber_AsSsize_t(values, PyExc_ValueError);
+            if (ival == -1 && PyErr_Occurred())
+                return -1;
+            if (ival < 0 || ival >= 256) {
+                PyErr_SetString(PyExc_ValueError,
+                                "byte must be in range(0, 256)");
+                return -1;
+            }
+            self->ob_bytes[i] = (char)ival;
+            return 0;
+        }
+    }
+    else if (PySlice_Check(item)) {
+        if (PySlice_GetIndicesEx((PySliceObject *)item,
+                                 PyBytes_GET_SIZE(self),
+                                 &start, &stop, &step, &slicelen) < 0) {
+            return -1;
+        }
+    }
+    else {
+        PyErr_SetString(PyExc_TypeError, "bytes indices must be integer");
+        return -1;
+    }
+
+    if (values == NULL) {
+        bytes = NULL;
+        needed = 0;
+    }
+    else if (values == (PyObject *)self || !PyBytes_Check(values)) {
+        /* Make a copy an call this function recursively */
+        int err;
+        values = PyBytes_FromObject(values);
+        if (values == NULL)
+            return -1;
+        err = bytes_ass_subscript(self, item, values);
+        Py_DECREF(values);
+        return err;
+    }
+    else {
+        assert(PyBytes_Check(values));
+        bytes = ((PyBytesObject *)values)->ob_bytes;
+        needed = ((PyBytesObject *)values)->ob_size;
+    }
+
+    if (step == 1) {
+        if (slicelen != needed) {
+            if (slicelen > needed) {
+                /*
+                  0   start           stop              old_size
+                  |   |<---slicelen--->|<-----tomove------>|
+                  |   |<-needed->|<-----tomove------>|
+                  0   lo      new_hi              new_size
+                */
+                memmove(self->ob_bytes + start + needed, self->ob_bytes + stop,
+                        self->ob_size - stop);
+            }
+            if (PyBytes_Resize((PyObject *)self, 
+                               self->ob_size + needed - slicelen) < 0)
+                return -1;
+            if (slicelen < needed) {
+                /*
+                  0   lo        hi               old_size
+                  |   |<-avail->|<-----tomove------>|
+                  |   |<----needed---->|<-----tomove------>|
+                  0   lo            new_hi              new_size
+                 */
+                memmove(self->ob_bytes + start + needed, self->ob_bytes + stop,
+                        self->ob_size - start - needed);
+            }
+        }
+
+        if (needed > 0)
+            memcpy(self->ob_bytes + start, bytes, needed);
+
+        return 0;
+    }
+    else {
+        if (needed == 0) {
+            /* Delete slice */
+            Py_ssize_t cur, i;
+            
+            if (step < 0) {
+                stop = start + 1;
+                start = stop + step * (slicelen - 1) - 1;
+                step = -step;
+            }
+            for (cur = start, i = 0;
+                 i < slicelen; cur += step, i++) {
+                Py_ssize_t lim = step;
+
+                if (cur + step >= PyBytes_GET_SIZE(self))
+                    lim = PyBytes_GET_SIZE(self) - cur - 1;
+                
+                memmove(self->ob_bytes + cur - i,
+                        self->ob_bytes + cur + 1, lim);
+            }
+            /* Move the tail of the bytes, in one chunk */
+            cur = start + slicelen*step + 1;
+            memmove(self->ob_bytes + cur - slicelen,
+                    self->ob_bytes + cur,
+                    PyBytes_GET_SIZE(self) - cur);
+            if (PyBytes_Resize((PyObject *)self, 
+                               PyBytes_GET_SIZE(self) - slicelen) < 0)
+                return -1;
+
+            return 0;
+        }
+        else {
+            /* Assign slice */
+            Py_ssize_t cur, i;
+            
+            if (needed != slicelen) {
+                PyErr_Format(PyExc_ValueError,
+                             "attempt to assign bytes of size %zd "
+                             "to extended slice of size %zd",
+                             needed, slicelen);
+                return -1;
+            }
+            for (cur = start, i = 0; i < slicelen; cur += step, i++)
+                self->ob_bytes[cur] = bytes[i];
+            return 0;
+        }
+    }
+}
+
+static int
 bytes_init(PyBytesObject *self, PyObject *args, PyObject *kwds)
 {
     static char *kwlist[] = {"source", "encoding", "errors", 0};
@@ -784,8 +991,8 @@
 
 static PyMappingMethods bytes_as_mapping = {
     (lenfunc)bytes_length,
-    (binaryfunc)0,
-    0,
+    (binaryfunc)bytes_subscript,
+    (objobjargproc)bytes_ass_subscript,
 };
 
 static PyBufferProcs bytes_as_buffer = {

Modified: python/branches/p3yk-noslice/Objects/structseq.c
==============================================================================
--- python/branches/p3yk-noslice/Objects/structseq.c	(original)
+++ python/branches/p3yk-noslice/Objects/structseq.c	Tue Aug 22 21:54:34 2006
@@ -90,6 +90,54 @@
 }
 
 static PyObject *
+structseq_subscript(PyStructSequence *self, PyObject *item)
+{
+	if (PyIndex_Check(item)) {
+		Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
+		if (i == -1 && PyErr_Occurred())
+			return NULL;
+
+		if (i < 0)
+			i += VISIBLE_SIZE(self);
+
+		if (i < 0 || i >= VISIBLE_SIZE(self)) {
+			PyErr_SetString(PyExc_IndexError,
+				"tuple index out of range");
+			return NULL;
+		}
+		Py_INCREF(self->ob_item[i]);
+		return self->ob_item[i];
+	}
+	else if (PySlice_Check(item)) {
+		Py_ssize_t start, stop, step, slicelen, cur, i;
+		PyObject *result;
+		
+		if (PySlice_GetIndicesEx((PySliceObject *)item,
+					 VISIBLE_SIZE(self), &start, &stop,
+					 &step, &slicelen) < 0) {
+			return NULL;
+		}
+		if (slicelen <= 0)
+			return PyTuple_New(0);
+		result = PyTuple_New(slicelen);
+		if (result == NULL)
+			return NULL;
+		for (cur = start, i = 0; i < slicelen;
+		     cur += step, i++) {
+			PyObject *v = self->ob_item[cur];
+			Py_INCREF(v);
+			PyTuple_SET_ITEM(result, i, v);
+		}
+		return result;
+	}
+	else {
+		PyErr_SetString(PyExc_TypeError,
+				"structseq indices must be integers");
+		return NULL;
+	}
+}
+
+static PyObject *
 structseq_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
 	PyObject *arg = NULL;
@@ -298,6 +346,11 @@
 	(objobjproc)structseq_contains,	        /* sq_contains */
 };
 
+static PyMappingMethods structseq_as_mapping = {
+	(lenfunc)structseq_length,
+	(binaryfunc)structseq_subscript,
+};
+
 static PyMethodDef structseq_methods[] = {
 	{"__reduce__", (PyCFunction)structseq_reduce, 
 	 METH_NOARGS, NULL},
@@ -318,7 +371,7 @@
 	(reprfunc)structseq_repr,             	/* tp_repr */
 	0,					/* tp_as_number */
 	&structseq_as_sequence,			/* tp_as_sequence */
-	0,					/* tp_as_mapping */
+	&structseq_as_mapping,			/* tp_as_mapping */
 	structseq_hash,				/* tp_hash */
 	0,              			/* tp_call */
 	0,					/* tp_str */

Modified: python/branches/p3yk-noslice/Python/ceval.c
==============================================================================
--- python/branches/p3yk-noslice/Python/ceval.c	(original)
+++ python/branches/p3yk-noslice/Python/ceval.c	Tue Aug 22 21:54:34 2006
@@ -111,9 +111,6 @@
 static int maybe_call_line_trace(Py_tracefunc, PyObject *,
 				  PyFrameObject *, int *, int *, int *);
 
-static PyObject * apply_slice(PyObject *, PyObject *, PyObject *);
-static int assign_slice(PyObject *, PyObject *,
-			PyObject *, PyObject *);
 static PyObject * cmp_outcome(int, PyObject *, PyObject *);
 static PyObject * import_from(PyObject *, PyObject *);
 static int import_all_from(PyObject *, PyObject *);
@@ -525,7 +522,6 @@
 	register PyObject *v;	/* Temporary objects popped off stack */
 	register PyObject *w;
 	register PyObject *u;
-	register PyObject *t;
 	register PyObject *stream = NULL;    /* for PRINT opcodes */
 	register PyObject **fastlocals, **freevars;
 	PyObject *retval = NULL;	/* Return value */
@@ -1398,70 +1394,6 @@
 			if (x != NULL) continue;
 			break;
 
-		case SLICE+0:
-		case SLICE+1:
-		case SLICE+2:
-		case SLICE+3:
-			if ((opcode-SLICE) & 2)
-				w = POP();
-			else
-				w = NULL;
-			if ((opcode-SLICE) & 1)
-				v = POP();
-			else
-				v = NULL;
-			u = TOP();
-			x = apply_slice(u, v, w);
-			Py_DECREF(u);
-			Py_XDECREF(v);
-			Py_XDECREF(w);
-			SET_TOP(x);
-			if (x != NULL) continue;
-			break;
-
-		case STORE_SLICE+0:
-		case STORE_SLICE+1:
-		case STORE_SLICE+2:
-		case STORE_SLICE+3:
-			if ((opcode-STORE_SLICE) & 2)
-				w = POP();
-			else
-				w = NULL;
-			if ((opcode-STORE_SLICE) & 1)
-				v = POP();
-			else
-				v = NULL;
-			u = POP();
-			t = POP();
-			err = assign_slice(u, v, w, t); /* u[v:w] = t */
-			Py_DECREF(t);
-			Py_DECREF(u);
-			Py_XDECREF(v);
-			Py_XDECREF(w);
-			if (err == 0) continue;
-			break;
-
-		case DELETE_SLICE+0:
-		case DELETE_SLICE+1:
-		case DELETE_SLICE+2:
-		case DELETE_SLICE+3:
-			if ((opcode-DELETE_SLICE) & 2)
-				w = POP();
-			else
-				w = NULL;
-			if ((opcode-DELETE_SLICE) & 1)
-				v = POP();
-			else
-				v = NULL;
-			u = POP();
-			err = assign_slice(u, v, w, (PyObject *)NULL);
-							/* del u[v:w] */
-			Py_DECREF(u);
-			Py_XDECREF(v);
-			Py_XDECREF(w);
-			if (err == 0) continue;
-			break;
-
 		case STORE_SUBSCR:
 			w = TOP();
 			v = SECOND();
@@ -3842,70 +3774,6 @@
 	return 1;
 }
 
-#undef ISINDEX
-#define ISINDEX(x) ((x) == NULL || \
-		    PyInt_Check(x) || PyLong_Check(x) || PyIndex_Check(x))
-
-static PyObject *
-apply_slice(PyObject *u, PyObject *v, PyObject *w) /* return u[v:w] */
-{
-	PyTypeObject *tp = u->ob_type;
-	PySequenceMethods *sq = tp->tp_as_sequence;
-
-	if (sq && sq->sq_slice && ISINDEX(v) && ISINDEX(w)) {
-		Py_ssize_t ilow = 0, ihigh = PY_SSIZE_T_MAX;
-		if (!_PyEval_SliceIndex(v, &ilow))
-			return NULL;
-		if (!_PyEval_SliceIndex(w, &ihigh))
-			return NULL;
-		return PySequence_GetSlice(u, ilow, ihigh);
-	}
-	else {
-		PyObject *slice = PySlice_New(v, w, NULL);
-		if (slice != NULL) {
-			PyObject *res = PyObject_GetItem(u, slice);
-			Py_DECREF(slice);
-			return res;
-		}
-		else
-			return NULL;
-	}
-}
-
-static int
-assign_slice(PyObject *u, PyObject *v, PyObject *w, PyObject *x)
-	/* u[v:w] = x */
-{
-	PyTypeObject *tp = u->ob_type;
-	PySequenceMethods *sq = tp->tp_as_sequence;
-
-	if (sq && sq->sq_slice && ISINDEX(v) && ISINDEX(w)) {
-		Py_ssize_t ilow = 0, ihigh = PY_SSIZE_T_MAX;
-		if (!_PyEval_SliceIndex(v, &ilow))
-			return -1;
-		if (!_PyEval_SliceIndex(w, &ihigh))
-			return -1;
-		if (x == NULL)
-			return PySequence_DelSlice(u, ilow, ihigh);
-		else
-			return PySequence_SetSlice(u, ilow, ihigh, x);
-	}
-	else {
-		PyObject *slice = PySlice_New(v, w, NULL);
-		if (slice != NULL) {
-			int res;
-			if (x != NULL)
-				res = PyObject_SetItem(u, slice, x);
-			else
-				res = PyObject_DelItem(u, slice);
-			Py_DECREF(slice);
-			return res;
-		}
-		else
-			return -1;
-	}
-}
-
 static PyObject *
 cmp_outcome(int op, register PyObject *v, register PyObject *w)
 {

Modified: python/branches/p3yk-noslice/Python/compile.c
==============================================================================
--- python/branches/p3yk-noslice/Python/compile.c	(original)
+++ python/branches/p3yk-noslice/Python/compile.c	Tue Aug 22 21:54:34 2006
@@ -741,33 +741,6 @@
 		case INPLACE_TRUE_DIVIDE:
 			return -1;
 
-		case SLICE+0:
-			return 1;
-		case SLICE+1:
-			return 0;
-		case SLICE+2:
-			return 0;
-		case SLICE+3:
-			return -1;
-
-		case STORE_SLICE+0:
-			return -2;
-		case STORE_SLICE+1:
-			return -3;
-		case STORE_SLICE+2:
-			return -3;
-		case STORE_SLICE+3:
-			return -4;
-
-		case DELETE_SLICE+0:
-			return -1;
-		case DELETE_SLICE+1:
-			return -2;
-		case DELETE_SLICE+2:
-			return -2;
-		case DELETE_SLICE+3:
-			return -3;
-
 		case INPLACE_ADD:
 		case INPLACE_SUBTRACT:
 		case INPLACE_MULTIPLY:
@@ -3214,57 +3187,6 @@
 }
 
 static int
-compiler_simple_slice(struct compiler *c, slice_ty s, expr_context_ty ctx)
-{
-	int op = 0, slice_offset = 0, stack_count = 0;
-
-	assert(s->v.Slice.step == NULL);
-	if (s->v.Slice.lower) {
-		slice_offset++;
-		stack_count++;
-		if (ctx != AugStore) 
-			VISIT(c, expr, s->v.Slice.lower);
-	}
-	if (s->v.Slice.upper) {
-		slice_offset += 2;
-		stack_count++;
-		if (ctx != AugStore) 
-			VISIT(c, expr, s->v.Slice.upper);
-	}
-
-	if (ctx == AugLoad) {
-		switch (stack_count) {
-		case 0: ADDOP(c, DUP_TOP); break;
-		case 1: ADDOP_I(c, DUP_TOPX, 2); break;
-		case 2: ADDOP_I(c, DUP_TOPX, 3); break;
-		}
-	}
-	else if (ctx == AugStore) {
-		switch (stack_count) {
-		case 0: ADDOP(c, ROT_TWO); break;
-		case 1: ADDOP(c, ROT_THREE); break;
-		case 2: ADDOP(c, ROT_FOUR); break;
-		}
-	}
-
-	switch (ctx) {
-	case AugLoad: /* fall through to Load */
-	case Load: op = SLICE; break;
-	case AugStore:/* fall through to Store */
-	case Store: op = STORE_SLICE; break;
-	case Del: op = DELETE_SLICE; break;
-	case Param:
-	default:
-		PyErr_SetString(PyExc_SystemError,
-				"param invalid in simple slice");
-		return 0;
-	}
-
-	ADDOP(c, op + slice_offset);
-	return 1;
-}
-
-static int
 compiler_visit_nested_slice(struct compiler *c, slice_ty s, 
 			    expr_context_ty ctx)
 {
@@ -3306,8 +3228,6 @@
 		break;
 	case Slice_kind:
 		kindname = "slice";
-		if (!s->v.Slice.step) 
-			return compiler_simple_slice(c, s, ctx);
 		if (ctx != AugStore) {
 			if (!compiler_slice(c, s, ctx))
 				return 0;


More information about the Python-checkins mailing list