[Jython-checkins] jython: Support corner case in bytearray b[x:y:z]=b''

jeff.allen jython-checkins at python.org
Sat Jul 21 00:35:13 CEST 2012


http://hg.python.org/jython/rev/95bc782dc561
changeset:   6808:95bc782dc561
user:        Jeff Allen <ja...py at farowl.co.uk>
date:        Fri Jul 20 23:01:33 2012 +0100
summary:
  Support corner case in bytearray b[x:y:z]=b''
Unlike list, CPython bytearray accepts assignment of empty list to extended slice as deletion.
Now down to 3 failures in test.test_bytes

files:
  src/org/python/core/BaseBytes.java  |  44 +++++++++++++++-
  src/org/python/core/PySequence.java |  33 ++++++++++++-
  2 files changed, 72 insertions(+), 5 deletions(-)


diff --git a/src/org/python/core/BaseBytes.java b/src/org/python/core/BaseBytes.java
--- a/src/org/python/core/BaseBytes.java
+++ b/src/org/python/core/BaseBytes.java
@@ -41,7 +41,8 @@
      * @param type explicit Jython type
      */
     public BaseBytes(PyType type) {
-        super(type);            // implicit setStorage( emptyStorage );
+        super(type, null);
+        delegator = new IndexDelegate();
         setStorage(emptyStorage);
     }
 
@@ -52,7 +53,8 @@
      * @param type explicit Jython type
      */
     public BaseBytes(PyType type, int size) {
-        super(type);
+        super(type, null);
+        delegator = new IndexDelegate();
         newStorage(size);
     }
 
@@ -63,7 +65,8 @@
      * @param value source of values (and size)
      */
     public BaseBytes(PyType type, int[] value) {
-        super(type);
+        super(type, null);
+        delegator = new IndexDelegate();
         int n = value.length;
         newStorage(n);
         for (int i = offset, j = 0; j < n; i++, j++) {
@@ -80,7 +83,8 @@
      * @throws PyException if any value[i] > 255
      */
     protected BaseBytes(PyType type, String value) throws PyException {
-        super(type);
+        super(type, null);
+        delegator = new IndexDelegate();
         int n = value.length();
         newStorage(n);
         for (int i = offset, j = 0; j < n; j++) {
@@ -1127,6 +1131,38 @@
         return getslice(start, stop, 1);
     }
 
+    /**
+     * Class defining the behaviour of bytearray with respect to slice assignment, etc., which
+     * differs from the default (list) behaviour in small ways.
+     */
+    private class IndexDelegate extends PySequence.DefaultIndexDelegate {
+
+        /*
+         * bytearray treats assignment of a zero-length object to a slice as equivalent to deletion,
+         * unlike list, even for an extended slice.
+         */
+        // >>> a = range(10)
+        // >>> b = bytearray(a)
+        // >>> a[1:6:2] = []
+        // Traceback (most recent call last):
+        // File "<stdin>", line 1, in <module>
+        // ValueError: attempt to assign sequence of size 0 to extended slice of size 3
+        // >>> b[1:6:2] = []
+        // >>> b
+        // bytearray(b'\x00\x02\x04\x06\x07\x08\t')
+        //
+        @Override
+        public void checkIdxAndSetSlice(PySlice slice, PyObject value) {
+            if (value.__len__() != 0) {
+                // Proceed as default
+                super.checkIdxAndSetSlice(slice, value);
+            } else {
+                // Treat as deletion
+                super.checkIdxAndDelItem(slice);
+            }
+        }
+    };
+
     /*
      * ============================================================================================
      * Support for Python API common to mutable and immutable subclasses
diff --git a/src/org/python/core/PySequence.java b/src/org/python/core/PySequence.java
--- a/src/org/python/core/PySequence.java
+++ b/src/org/python/core/PySequence.java
@@ -14,8 +14,35 @@
  */
 public abstract class PySequence extends PyObject {
 
+    /**
+     * A delegate that handles index checking and manipulation for get, set and del operations on
+     * this sequence in the form of a "pluggable behaviour". Because different types of sequence
+     * exhibit subtly different behaviour, there is scope for subclasses to customise the behaviour
+     * with their own extension of <code>SequenceIndexDelegate</code>.
+     */
+    protected SequenceIndexDelegate delegator;
+
+    /**
+     * Construct a PySequence for the given sub-type with the default index behaviour.
+     * 
+     * @param type actual (Python) type of sub-class
+     */
     protected PySequence(PyType type) {
         super(type);
+        delegator = new DefaultIndexDelegate();
+    }
+
+    /**
+     * Construct a PySequence for the given sub-type with custom index behaviour. In practice,
+     * restrictions on the construction of inner classes will mean null has to be passed and the
+     * actual delegator assigned later.
+     * 
+     * @param type actual (Python) type of sub-class
+     * @param behaviour specific index behaviour (or null)
+     */
+    protected PySequence(PyType type, SequenceIndexDelegate behaviour) {
+        super(type);
+        delegator = behaviour;
     }
 
     // These methods must be defined for any sequence
@@ -451,7 +478,11 @@
         return true;
     }
 
-    protected final SequenceIndexDelegate delegator = new SequenceIndexDelegate() {
+    /**
+     * Class defining the default behaviour of sequences with respect to slice assignment, etc.,
+     * which is the one correct for <code>list</code>.
+     */
+    protected class DefaultIndexDelegate extends SequenceIndexDelegate {
 
         @Override
         public String getTypeName() {

-- 
Repository URL: http://hg.python.org/jython


More information about the Jython-checkins mailing list