[Jython-checkins] jython: Add read-only buffer API to array.array for all type codes.

jeff.allen jython-checkins at python.org
Fri Nov 15 00:01:39 CET 2013


http://hg.python.org/jython/rev/0d5f6b1e0a04
changeset:   7151:0d5f6b1e0a04
user:        Jeff Allen <ja.py at farowl.co.uk>
date:        Thu Nov 14 21:29:18 2013 +0000
summary:
  Add read-only buffer API to array.array for all type codes.
Fixes a regression in test_re where arrays of arbitrary type are required
to be arguments to PatternObject.match(), which accepts buffer
API objects.

files:
  Lib/test/test_array.py                        |  101 ++++-----
  src/org/python/core/PyArray.java              |   11 +-
  src/org/python/core/PyFile.java               |   25 +-
  src/org/python/modules/sre/PatternObject.java |   22 +-
  4 files changed, 70 insertions(+), 89 deletions(-)


diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py
--- a/Lib/test/test_array.py
+++ b/Lib/test/test_array.py
@@ -832,11 +832,10 @@
         gc.collect()
 
     def test_buffer(self):
-        if self.typecode == 'b':    # FIXME: Jython supports only the byte buffer
-            a = array.array(self.typecode, self.example)
-            with test_support.check_py3k_warnings():
-                b = buffer(a)
-            self.assertEqual(b[0], a.tostring()[0])
+        a = array.array(self.typecode, self.example)
+        with test_support.check_py3k_warnings():
+            b = buffer(a)
+        self.assertEqual(b[0], a.tostring()[0])
 
     def test_weakref(self):
         s = array.array(self.typecode, self.example)
@@ -869,58 +868,57 @@
         # if it wouldn't reallocate the underlying array.
         # Furthermore, no destructive changes to the buffer may be applied
         # before raising the error.
-        if self.typecode == 'b':    # Jython supports only the byte buffer
-            a = array.array(self.typecode, self.example)
-            def resize(n):
-                "n = -1 -> Smaller, 0 -> the same, or 1 -> larger."
-                a[1:-1] = array.array(self.typecode, self.example[1-n:-1])
+        a = array.array(self.typecode, self.example)
+        def resize(n):
+            "n = -1 -> Smaller, 0 -> the same, or 1 -> larger."
+            a[1:-1] = array.array(self.typecode, self.example[1-n:-1])
 
-            v = memoryview(a)
-            orig = a[:]
+        v = memoryview(a)
+        orig = a[:]
 
-            self.assertRaises(BufferError, resize, -1)
-            self.assertEqual(a, orig)
-            #self.assertRaises(BufferError, resize, 0)
-            #self.assertEqual(a, orig)
-            self.assertRaises(BufferError, resize, 1)
-            self.assertEqual(a, orig)
+        self.assertRaises(BufferError, resize, -1)
+        self.assertEqual(a, orig)
+        #self.assertRaises(BufferError, resize, 0)
+        #self.assertEqual(a, orig)
+        self.assertRaises(BufferError, resize, 1)
+        self.assertEqual(a, orig)
 
-            # Other operations implying resize
-            self.assertRaises(BufferError, a.pop, 0)
-            self.assertEqual(a, orig)
-            self.assertRaises(BufferError, a.remove, a[1])
-            self.assertEqual(a, orig)
-            self.assertRaises(BufferError, a.append, self.outside)
-            self.assertEqual(a, orig)
-            self.assertRaises(BufferError, a.insert, 1, self.outside)
-            self.assertEqual(a, orig)
-            self.assertRaises(BufferError, a.extend, self.example)
-            self.assertEqual(a, orig)
+        # Other operations implying resize
+        self.assertRaises(BufferError, a.pop, 0)
+        self.assertEqual(a, orig)
+        self.assertRaises(BufferError, a.remove, a[1])
+        self.assertEqual(a, orig)
+        self.assertRaises(BufferError, a.append, self.outside)
+        self.assertEqual(a, orig)
+        self.assertRaises(BufferError, a.insert, 1, self.outside)
+        self.assertEqual(a, orig)
+        self.assertRaises(BufferError, a.extend, self.example)
+        self.assertEqual(a, orig)
 
-            def iadd(x):
-                x += array.array(self.typecode, self.biggerexample)
-            self.assertRaises(BufferError, iadd, a)
-            self.assertEqual(a, orig)
+        def iadd(x):
+            x += array.array(self.typecode, self.biggerexample)
+        self.assertRaises(BufferError, iadd, a)
+        self.assertEqual(a, orig)
 
-            def imul(x):
-                x *= 3
-            self.assertRaises(BufferError, imul, a)
-            self.assertEqual(a, orig)
+        def imul(x):
+            x *= 3
+        self.assertRaises(BufferError, imul, a)
+        self.assertEqual(a, orig)
 
-            def delitem():
-                del a[1]
-            self.assertRaises(BufferError, delitem)
-            self.assertEqual(a, orig)
+        def delitem():
+            del a[1]
+        self.assertRaises(BufferError, delitem)
+        self.assertEqual(a, orig)
 
-            # deleting a non-contiguous slice
-            def delslice():
-                del a[1:-1:2]
-            self.assertRaises(BufferError, delslice)
-            self.assertEqual(a, orig)
+        # deleting a non-contiguous slice
+        def delslice():
+            del a[1:-1:2]
+        self.assertRaises(BufferError, delslice)
+        self.assertEqual(a, orig)
 
-            # Show that releasing v releases the array for size change
-            v.release()
-            a.pop()
+        # Show that releasing v releases the array for size change
+        v.release()
+        a.pop()
 
 
 class StringTest(BaseTest):
@@ -1033,9 +1031,8 @@
         self.assertEqual(a, array.array(self.typecode, [1,2,3,4,5,6,7,8,9]))
         # test issue7788
         a = array.array(self.typecode, range(10))
-        # FIXME #1860: not working on Jython yet.
-        if not test_support.is_jython:
-            del a[9::1<<333]
+        del a[9::1<<333]
+        self.assertEqual(a, array.array(self.typecode, range(9)))
 
     def test_assignment(self):
         a = array.array(self.typecode, range(10))
diff --git a/src/org/python/core/PyArray.java b/src/org/python/core/PyArray.java
--- a/src/org/python/core/PyArray.java
+++ b/src/org/python/core/PyArray.java
@@ -13,6 +13,7 @@
 import java.lang.reflect.Array;
 
 import org.python.core.buffer.BaseBuffer;
+import org.python.core.buffer.SimpleStringBuffer;
 import org.python.core.buffer.SimpleWritableBuffer;
 import org.python.core.util.ByteSwapper;
 import org.python.core.util.StringUtil;
@@ -2058,13 +2059,15 @@
                 byte[] storage = (byte[])data;
                 int size = delegate.getSize();
                 pybuf = new SimpleWritableBuffer(flags, storage, 0, size);
-                // Hold a reference for possible re-use
-                export = new WeakReference<BaseBuffer>(pybuf);
-
+            } else if ((flags & PyBUF.WRITABLE) == 0) {
+                // As the client only intends to read, fake the answer with a String
+                pybuf = new SimpleStringBuffer(flags, tostring());
             } else {
                 // For the time being ...
-                throw Py.NotImplementedError("only array('b') can export a buffer");
+                throw Py.NotImplementedError("only array('b') can export a writable buffer");
             }
+            // Hold a reference for possible re-use
+            export = new WeakReference<BaseBuffer>(pybuf);
         }
 
         return pybuf;
diff --git a/src/org/python/core/PyFile.java b/src/org/python/core/PyFile.java
--- a/src/org/python/core/PyFile.java
+++ b/src/org/python/core/PyFile.java
@@ -394,27 +394,18 @@
             // Take a short cut
             return ((PyString)obj).getString();
 
-        } else if (obj instanceof PyArray) {
-            if (binary) {
-                // PyArray has the buffer interface but it only works for bytes at present
-                return ((PyArray)obj).tostring();
-            } else {
-                // Fall through to TypeError
-            }
+        } else if (obj instanceof PyArray && !binary) {
+            // Fall through to TypeError. (If binary, BufferProtocol takes care of PyArray.)
 
         } else if (obj instanceof BufferProtocol) {
-            // Try to get a simple byte-oriented buffer
-            PyBuffer buf = null;
+            // Try to get a byte-oriented buffer
+            PyBuffer buf = ((BufferProtocol)obj).getBuffer(PyBUF.FULL_RO);
             try {
-                buf = ((BufferProtocol)obj).getBuffer(PyBUF.SIMPLE);
-                return StringUtil.fromBytes(buf);
-            } catch (Exception e) {
-                // Wrong kind of buffer: generic/supplied error message will do
+                // ... and treat those bytes as a String
+                return buf.toString();
             } finally {
-                // If we got a buffer, we should release it
-                if (buf != null) {
-                    buf.release();
-                }
+                // We should release the buffer
+                buf.release();
             }
         }
 
diff --git a/src/org/python/modules/sre/PatternObject.java b/src/org/python/modules/sre/PatternObject.java
--- a/src/org/python/modules/sre/PatternObject.java
+++ b/src/org/python/modules/sre/PatternObject.java
@@ -372,28 +372,18 @@
             return (PyString)obj;
 
         } else if (obj instanceof BufferProtocol) {
-            // Try to get a simple byte-oriented buffer
-            PyBuffer buf = null;
+            // Try to get a byte-oriented buffer
+            PyBuffer buf = ((BufferProtocol)obj).getBuffer(PyBUF.FULL_RO);
             try {
-                buf = ((BufferProtocol)obj).getBuffer(PyBUF.SIMPLE);
                 // ... and treat those bytes as a PyString
-                String s = StringUtil.fromBytes(buf);
-                return new PyString(s);
-            } catch (Exception e) {
-                // Wrong kind of buffer: generic error message will do
+                return new PyString(buf.toString());
             } finally {
-                // If we got a buffer, we should release it
-                if (buf != null) {
-                    buf.release();
-                }
+                // We should release the buffer
+                buf.release();
             }
-
-        } else if (obj instanceof PyArray) {
-            // PyArray can do something similar
-            return new PyString(obj.toString());
         }
 
-        // None of those things worked
+        // Neither of those things worked
         throw Py.TypeError("expected string or buffer, but got " + obj.getType());
     }
 }

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


More information about the Jython-checkins mailing list