[Jython-checkins] jython: Add to PyBuffer a reference to the exporting object.

jeff.allen jython-checkins at python.org
Sat Aug 27 09:12:25 EDT 2016


https://hg.python.org/jython/rev/59e3bae3c519
changeset:   7948:59e3bae3c519
user:        Jeff Allen <ja.py at farowl.co.uk>
date:        Mon Jul 11 13:33:02 2016 +0100
summary:
  Add to PyBuffer a reference to the exporting object.

A getObj() method is added to the interface (emulating the CPython obj
member), and is added to constructors for concrete implementations
provided in the org.python.core.buffer package.

files:
  src/org/python/core/PyArray.java                        |   9 +-
  src/org/python/core/PyBuffer.java                       |   8 ++
  src/org/python/core/PyByteArray.java                    |   2 +-
  src/org/python/core/PyMemoryView.java                   |  17 +++-
  src/org/python/core/PyString.java                       |   2 +-
  src/org/python/core/buffer/BaseBuffer.java              |  11 +++
  src/org/python/core/buffer/BaseNIOBuffer.java           |   2 -
  src/org/python/core/buffer/SimpleBuffer.java            |  29 +++++---
  src/org/python/core/buffer/SimpleNIOBuffer.java         |  29 +++++---
  src/org/python/core/buffer/SimpleStringBuffer.java      |  10 +-
  src/org/python/core/buffer/SimpleWritableBuffer.java    |  16 ++-
  src/org/python/core/buffer/Strided1DBuffer.java         |  12 ++-
  src/org/python/core/buffer/Strided1DNIOBuffer.java      |  17 +++-
  src/org/python/core/buffer/Strided1DWritableBuffer.java |  11 ++-
  src/org/python/core/buffer/ZeroByteBuffer.java          |   8 +-
  src/org/python/modules/_io/PyIOBase.java                |   9 +-
  tests/java/org/python/core/BaseBytesTest.java           |   7 +-
  tests/java/org/python/core/PyBufferNIOTest.java         |  22 +++--
  tests/java/org/python/core/PyBufferTest.java            |  34 ++++++---
  19 files changed, 163 insertions(+), 92 deletions(-)


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
@@ -2081,10 +2081,10 @@
                 // This is byte data, so we are within the state of the art
                 byte[] storage = (byte[])data;
                 int size = delegate.getSize();
-                pybuf = new SimpleWritableBuffer(flags, storage, 0, size);
+                pybuf = new SimpleWritableBuffer(flags, this, storage, 0, size);
             } else if ((flags & PyBUF.WRITABLE) == 0) {
                 // As the client only intends to read, fake the answer with a String
-                pybuf = new SimpleStringBuffer(flags, tostring());
+                pybuf = new SimpleStringBuffer(flags, this, tostring());
             } else {
                 // For the time being ...
                 throw Py.NotImplementedError("only array('b') can export a writable buffer");
@@ -2163,7 +2163,6 @@
             return buf.remaining();
         }
 
-
         @Override
         public int read() {
             return buf.hasRemaining() ? buf.get() & 0xff : -1;
@@ -2187,7 +2186,6 @@
         }
     }
 
-
     /* Traverseproc implementation */
     @Override
     public int traverse(Visitproc visit, Object arg) {
@@ -2198,8 +2196,7 @@
     }
 
     @Override
-    public boolean refersDirectlyTo(PyObject ob)
-            throws UnsupportedOperationException {
+    public boolean refersDirectlyTo(PyObject ob) throws UnsupportedOperationException {
         if (data == null || !gc.canLinkToPyObject(data.getClass(), true)) {
             return false;
         }
diff --git a/src/org/python/core/PyBuffer.java b/src/org/python/core/PyBuffer.java
--- a/src/org/python/core/PyBuffer.java
+++ b/src/org/python/core/PyBuffer.java
@@ -30,6 +30,14 @@
     // int getLen();
 
     /**
+     * Return the underlying exporting object (or <code>null</code> if no object implementing the
+     * {@link BufferProtocol} is in that role). This will often be a <code>PyObject</code>.
+     *
+     * @return exporting object (or <code>null</code>)
+     */
+    BufferProtocol getObj();
+
+    /**
      * Return the byte indexed from a one-dimensional buffer with item size one. This is part of the
      * fully-encapsulated API: the buffer implementation exported takes care of navigating the
      * structure of the buffer. Results are undefined where the number of dimensions is not one or
diff --git a/src/org/python/core/PyByteArray.java b/src/org/python/core/PyByteArray.java
--- a/src/org/python/core/PyByteArray.java
+++ b/src/org/python/core/PyByteArray.java
@@ -228,7 +228,7 @@
 
         if (pybuf == null) {
             // No existing export we can re-use: create a new one
-            pybuf = new SimpleWritableBuffer(flags, storage, offset, size);
+            pybuf = new SimpleWritableBuffer(flags, this, storage, offset, size);
             // Hold a reference for possible re-use
             export = new WeakReference<BaseBuffer>(pybuf);
         }
diff --git a/src/org/python/core/PyMemoryView.java b/src/org/python/core/PyMemoryView.java
--- a/src/org/python/core/PyMemoryView.java
+++ b/src/org/python/core/PyMemoryView.java
@@ -75,6 +75,13 @@
         }
     }
 
+    // @ExposedGet(doc = obj_doc) // Not exposed in Python 2.7
+    public PyObject obj() {
+        checkNotReleased();
+        BufferProtocol obj = backing.getObj();
+        return (obj instanceof PyObject) ? (PyObject)obj : Py.None;
+    }
+
     @ExposedGet(doc = format_doc)
     public String format() {
         checkNotReleased();
@@ -843,19 +850,18 @@
         }
     }
 
-
     /* Traverseproc implementation */
     @Override
     public int traverse(Visitproc visit, Object arg) {
         int retVal;
         if (backing != null) {
             if (backing instanceof PyObject) {
-                retVal = visit.visit((PyObject) backing, arg);
+                retVal = visit.visit((PyObject)backing, arg);
                 if (retVal != 0) {
                     return retVal;
                 }
             } else if (backing instanceof Traverseproc) {
-                retVal = ((Traverseproc) backing).traverse(visit, arg);
+                retVal = ((Traverseproc)backing).traverse(visit, arg);
                 if (retVal != 0) {
                     return retVal;
                 }
@@ -878,11 +884,10 @@
 
     @Override
     public boolean refersDirectlyTo(PyObject ob) {
-        if (ob != null && (ob == backing || ob == shape || ob == strides
-            || ob == suboffsets)) {
+        if (ob != null && (ob == backing || ob == shape || ob == strides || ob == suboffsets)) {
             return true;
         } else if (suboffsets instanceof Traverseproc) {
-            return ((Traverseproc) suboffsets).refersDirectlyTo(ob);
+            return ((Traverseproc)suboffsets).refersDirectlyTo(ob);
         } else {
             return false;
         }
diff --git a/src/org/python/core/PyString.java b/src/org/python/core/PyString.java
--- a/src/org/python/core/PyString.java
+++ b/src/org/python/core/PyString.java
@@ -204,7 +204,7 @@
              * No existing export we can re-use. Return a buffer, but specialised to defer
              * construction of the buf object, and cache a soft reference to it.
              */
-            pybuf = new SimpleStringBuffer(flags, getString());
+            pybuf = new SimpleStringBuffer(flags, this, getString());
             export = new SoftReference<BaseBuffer>(pybuf);
         }
         return pybuf;
diff --git a/src/org/python/core/buffer/BaseBuffer.java b/src/org/python/core/buffer/BaseBuffer.java
--- a/src/org/python/core/buffer/BaseBuffer.java
+++ b/src/org/python/core/buffer/BaseBuffer.java
@@ -45,6 +45,12 @@
 public abstract class BaseBuffer implements PyBuffer {
 
     /**
+     * The object that exported this buffer (or <code>null</code> if the subclass or exporter
+     * chooses not to supply a reference).
+     */
+    protected BufferProtocol obj;
+
+    /**
      * The dimensions of the array represented by the buffer. The length of the <code>shape</code>
      * array is the number of dimensions. The <code>shape</code> array should always be created and
      * filled (difference from CPython). This value is returned by {@link #getShape()}.
@@ -255,6 +261,11 @@
         return len;
     }
 
+    @Override
+    public final BufferProtocol getObj() {
+        return obj;
+    }
+
     /**
      * Retrieve the byte at the given index in the underlying storage treated as a flat sequence of
      * bytes. This byte-index will have been computed from the item index (which may have been
diff --git a/src/org/python/core/buffer/BaseNIOBuffer.java b/src/org/python/core/buffer/BaseNIOBuffer.java
--- a/src/org/python/core/buffer/BaseNIOBuffer.java
+++ b/src/org/python/core/buffer/BaseNIOBuffer.java
@@ -5,7 +5,6 @@
 import java.nio.ReadOnlyBufferException;
 
 import org.python.core.PyBUF;
-import org.python.core.PyBuffer;
 import org.python.core.PyException;
 
 /**
@@ -50,7 +49,6 @@
      * @param size number of elements in the view
      * @param stride byte-index step between successive elements
      */
-
     protected BaseNIOBuffer(ByteBuffer storage, int featureFlags, int index0, int size, int stride) {
         super(featureFlags & ~(WRITABLE | AS_ARRAY), index0, size, stride);
         this.storage = storage;
diff --git a/src/org/python/core/buffer/SimpleBuffer.java b/src/org/python/core/buffer/SimpleBuffer.java
--- a/src/org/python/core/buffer/SimpleBuffer.java
+++ b/src/org/python/core/buffer/SimpleBuffer.java
@@ -1,5 +1,6 @@
 package org.python.core.buffer;
 
+import org.python.core.BufferProtocol;
 import org.python.core.PyBuffer;
 import org.python.core.PyException;
 import org.python.core.util.StringUtil;
@@ -22,14 +23,16 @@
      * checkRequestFlags(flags);        // Check request is compatible with type
      * </pre>
      *
+     * @param obj exporting object (or <code>null</code>)
      * @param storage the array of bytes storing the implementation of the exporting object
      * @param index0 offset where the data starts in that array (item[0])
      * @param size the number of bytes occupied
      * @throws NullPointerException if <code>storage</code> is null
      */
-    protected SimpleBuffer(byte[] storage, int index0, int size) throws PyException,
-            ArrayIndexOutOfBoundsException {
+    protected SimpleBuffer(BufferProtocol obj, byte[] storage, int index0, int size)
+            throws PyException, ArrayIndexOutOfBoundsException {
         super(storage, CONTIGUITY | SIMPLE, index0, size, 1);
+        this.obj = obj;
     }
 
     /**
@@ -38,6 +41,7 @@
      * against the capabilities of the buffer type.
      *
      * @param flags consumer requirements
+     * @param obj exporting object (or <code>null</code>)
      * @param storage the array of bytes storing the implementation of the exporting object
      * @param index0 offset where the data starts in that array (item[0])
      * @param size the number of bytes occupied
@@ -46,10 +50,10 @@
      *             inconsistent with <code>storage.length</code>
      * @throws PyException (BufferError) when expectations do not correspond with the type
      */
-    public SimpleBuffer(int flags, byte[] storage, int index0, int size) throws PyException,
-            ArrayIndexOutOfBoundsException, NullPointerException {
-        this(storage, index0, size);    // Construct checked SimpleBuffer
-        checkRequestFlags(flags);       // Check request is compatible with type
+    public SimpleBuffer(int flags, BufferProtocol obj, byte[] storage, int index0, int size)
+            throws PyException, ArrayIndexOutOfBoundsException, NullPointerException {
+        this(obj, storage, index0, size);   // Construct checked SimpleBuffer
+        checkRequestFlags(flags);           // Check request is compatible with type
         // Check arguments using the "all non-negative" trick
         if ((index0 | size | storage.length - (index0 + size)) < 0) {
             throw new ArrayIndexOutOfBoundsException();
@@ -62,11 +66,12 @@
      * {@link #index0}), and the navigation ({@link #shape} array) will be initialised from the
      * array argument.
      *
+     * @param obj exporting object (or <code>null</code>)
      * @param storage the array of bytes storing the implementation of the exporting object
      * @throws NullPointerException if <code>storage</code> is null
      */
-    protected SimpleBuffer(byte[] storage) throws NullPointerException {
-        this(storage, 0, storage.length);
+    protected SimpleBuffer(BufferProtocol obj, byte[] storage) throws NullPointerException {
+        this(obj, storage, 0, storage.length);
     }
 
     /**
@@ -75,12 +80,14 @@
      * against the capabilities of the buffer type.
      *
      * @param flags consumer requirements
+     * @param obj exporting object (or <code>null</code>)
      * @param storage the array of bytes storing the implementation of the exporting object
      * @throws NullPointerException if <code>storage</code> is null
      * @throws PyException (BufferError) when expectations do not correspond with the type
      */
-    public SimpleBuffer(int flags, byte[] storage) throws PyException, NullPointerException {
-        this(storage);                  // Construct SimpleBuffer on whole array
+    public SimpleBuffer(int flags, BufferProtocol obj, byte[] storage) throws PyException,
+            NullPointerException {
+        this(obj, storage);             // Construct SimpleBuffer on whole array
         checkRequestFlags(flags);       // Check request is compatible with type
     }
 
@@ -189,7 +196,7 @@
          */
         public SimpleView(PyBuffer root, int flags, byte[] storage, int offset, int size) {
             // Create a new SimpleBuffer on the buffer passed in (part of the root)
-            super(flags, storage, offset, size);
+            super(flags, root.getObj(), storage, offset, size);
             // Get a lease on the root PyBuffer
             this.root = root.getBuffer(FULL_RO);
         }
diff --git a/src/org/python/core/buffer/SimpleNIOBuffer.java b/src/org/python/core/buffer/SimpleNIOBuffer.java
--- a/src/org/python/core/buffer/SimpleNIOBuffer.java
+++ b/src/org/python/core/buffer/SimpleNIOBuffer.java
@@ -2,6 +2,7 @@
 
 import java.nio.ByteBuffer;
 
+import org.python.core.BufferProtocol;
 import org.python.core.PyBuffer;
 import org.python.core.PyException;
 
@@ -29,6 +30,7 @@
      * checkRequestFlags(flags);        // Check request is compatible with type
      * </pre>
      *
+     * @param obj exporting object (or <code>null</code>)
      * @param storage the <code>ByteBuffer</code> wrapping the exported object state. NOTE: this
      *            <code>PyBuffer</code> keeps a reference and may manipulate the position, mark and
      *            limit hereafter. Use {@link ByteBuffer#duplicate()} to give it an isolated copy.
@@ -38,9 +40,10 @@
      * @throws ArrayIndexOutOfBoundsException if <code>index0</code> and <code>size</code> are
      *             inconsistent with <code>storage.capacity()</code>
      */
-    protected SimpleNIOBuffer(ByteBuffer storage, int index0, int size) throws PyException,
-            ArrayIndexOutOfBoundsException {
+    protected SimpleNIOBuffer(BufferProtocol obj, ByteBuffer storage, int index0, int size)
+            throws PyException, ArrayIndexOutOfBoundsException {
         super(storage, CONTIGUITY | SIMPLE, index0, size, 1);
+        this.obj = obj;
         // Check arguments using the "all non-negative" trick
         if ((index0 | size | storage.capacity() - (index0 + size)) < 0) {
             throw new ArrayIndexOutOfBoundsException();
@@ -54,6 +57,7 @@
      * <code>ByteBuffer</code> passed in. (It is duplicated.)
      *
      * @param flags consumer requirements
+     * @param obj exporting object (or <code>null</code>)
      * @param storage the <code>ByteBuffer</code> wrapping the exported object state
      * @param index0 offset where the data starts in that buffer (item[0])
      * @param size the number of bytes occupied
@@ -62,10 +66,10 @@
      *             inconsistent with <code>storage.length</code>
      * @throws PyException (BufferError) when expectations do not correspond with the type
      */
-    public SimpleNIOBuffer(int flags, ByteBuffer storage, int index0, int size) throws PyException,
-            ArrayIndexOutOfBoundsException, NullPointerException {
-        this(storage.duplicate(), index0, size);    // Construct checked SimpleNIOBuffer
-        checkRequestFlags(flags);                   // Check request is compatible with type
+    public SimpleNIOBuffer(int flags, BufferProtocol obj, ByteBuffer storage, int index0, int size)
+            throws PyException, ArrayIndexOutOfBoundsException, NullPointerException {
+        this(obj, storage.duplicate(), index0, size);   // Construct checked SimpleNIOBuffer
+        checkRequestFlags(flags);                       // Check request is compatible with type
     }
 
     /**
@@ -74,13 +78,14 @@
      * {@link #index0}), and the navigation ({@link #shape} array) will be initialised from the
      * argument.
      *
+     * @param obj exporting object (or <code>null</code>)
      * @param storage the <code>ByteBuffer</code> wrapping the exported object state. NOTE: this
      *            <code>PyBuffer</code> keeps a reference and may manipulate the position, mark and
      *            limit hereafter. Use {@link ByteBuffer#duplicate()} to give it an isolated copy.
      * @throws NullPointerException if <code>storage</code> is null
      */
-    protected SimpleNIOBuffer(ByteBuffer storage) throws NullPointerException {
-        this(storage, 0, storage.capacity());
+    protected SimpleNIOBuffer(BufferProtocol obj, ByteBuffer storage) throws NullPointerException {
+        this(obj, storage, 0, storage.capacity());
     }
 
     /**
@@ -90,12 +95,14 @@
      * <code>ByteBuffer</code> passed in. (It is duplicated.)
      *
      * @param flags consumer requirements
+     * @param obj exporting object (or <code>null</code>)
      * @param storage the <code>ByteBuffer</code> wrapping the exported object state
      * @throws NullPointerException if <code>storage</code> is null
      * @throws PyException (BufferError) when expectations do not correspond with the type
      */
-    public SimpleNIOBuffer(int flags, ByteBuffer storage) throws PyException, NullPointerException {
-        this(storage.duplicate());      // Construct SimpleNIOBuffer on whole ByteBuffer
+    public SimpleNIOBuffer(int flags, BufferProtocol obj, ByteBuffer storage) throws PyException,
+            NullPointerException {
+        this(obj, storage.duplicate()); // Construct SimpleNIOBuffer on whole ByteBuffer
         checkRequestFlags(flags);       // Check request is compatible with type
     }
 
@@ -176,7 +183,7 @@
          */
         public SimpleView(PyBuffer root, int flags, ByteBuffer storage, int offset, int count) {
             // Create a new SimpleNIOBuffer on the buffer passed in (part of the root)
-            super(flags, storage, offset, count);
+            super(flags, root.getObj(), storage, offset, count);
             // Get a lease on the root PyBuffer
             this.root = root.getBuffer(FULL_RO);
         }
diff --git a/src/org/python/core/buffer/SimpleStringBuffer.java b/src/org/python/core/buffer/SimpleStringBuffer.java
--- a/src/org/python/core/buffer/SimpleStringBuffer.java
+++ b/src/org/python/core/buffer/SimpleStringBuffer.java
@@ -2,6 +2,7 @@
 
 import java.nio.ByteBuffer;
 
+import org.python.core.BufferProtocol;
 import org.python.core.PyBuffer;
 import org.python.core.util.StringUtil;
 
@@ -26,15 +27,16 @@
      * Provide an instance of SimpleStringBuffer meeting the consumer's expectations as expressed in
      * the flags argument.
      *
+     * @param flags consumer requirements
+     * @param obj exporting object (or <code>null</code>)
      * @param bufString storing the implementation of the object
-     * @param flags consumer requirements
      */
-    public SimpleStringBuffer(int flags, String bufString) {
+    public SimpleStringBuffer(int flags, BufferProtocol obj, String bufString) {
         /*
          * Leaving storage=null is ok because we carefully override every method that uses it,
          * deferring creation of the storage byte array until we absolutely must have one.
          */
-        super(null, 0, bufString.length());
+        super(obj, null, 0, bufString.length());
         // Save the backing string
         this.bufString = bufString;
         // Check request is compatible with type
@@ -205,7 +207,7 @@
          */
         public SimpleStringView(PyBuffer root, int flags, String bufString) {
             // Create a new SimpleStringBuffer on the string passed in
-            super(flags, bufString);
+            super(flags, root.getObj(), bufString);
             // Get a lease on the root PyBuffer
             this.root = root.getBuffer(FULL_RO);
         }
diff --git a/src/org/python/core/buffer/SimpleWritableBuffer.java b/src/org/python/core/buffer/SimpleWritableBuffer.java
--- a/src/org/python/core/buffer/SimpleWritableBuffer.java
+++ b/src/org/python/core/buffer/SimpleWritableBuffer.java
@@ -1,5 +1,6 @@
 package org.python.core.buffer;
 
+import org.python.core.BufferProtocol;
 import org.python.core.PyBuffer;
 import org.python.core.PyException;
 
@@ -14,16 +15,17 @@
      * against the capabilities of the buffer type.
      *
      * @param flags consumer requirements
+     * @param obj exporting object (or <code>null</code>)
      * @param storage the array of bytes storing the implementation of the exporting object
      * @param index0 offset where the data starts in that array (item[0])
      * @param size the number of bytes occupied
      * @throws PyException (BufferError) when expectations do not correspond with the type
      */
-    public SimpleWritableBuffer(int flags, byte[] storage, int index0, int size)
+    public SimpleWritableBuffer(int flags, BufferProtocol obj, byte[] storage, int index0, int size)
             throws PyException, NullPointerException {
-        super(storage, index0, size);   // Construct checked SimpleBuffer
+        super(obj, storage, index0, size);      // Construct checked SimpleBuffer
         addFeatureFlags(WRITABLE);
-        checkRequestFlags(flags);       // Check request is compatible with type
+        checkRequestFlags(flags);               // Check request is compatible with type
     }
 
     /**
@@ -32,11 +34,13 @@
      * checked against the capabilities of the buffer type.
      *
      * @param flags consumer requirements
+     * @param obj exporting object (or <code>null</code>)
      * @param storage the array of bytes storing the implementation of the exporting object
      * @throws PyException (BufferError) when expectations do not correspond with the type
      */
-    public SimpleWritableBuffer(int flags, byte[] storage) throws PyException, NullPointerException {
-        this(flags, storage, 0, storage.length);
+    public SimpleWritableBuffer(int flags, BufferProtocol obj, byte[] storage) throws PyException,
+            NullPointerException {
+        this(flags, obj, storage, 0, storage.length);
     }
 
     /**
@@ -121,7 +125,7 @@
          */
         public SimpleView(PyBuffer root, int flags, byte[] storage, int index0, int size) {
             // Create a new SimpleBuffer on the buffer passed in (part of the root)
-            super(flags, storage, index0, size);
+            super(flags, root.getObj(), storage, index0, size);
             // Get a lease on the root PyBuffer
             this.root = root.getBuffer(FULL_RO);
         }
diff --git a/src/org/python/core/buffer/Strided1DBuffer.java b/src/org/python/core/buffer/Strided1DBuffer.java
--- a/src/org/python/core/buffer/Strided1DBuffer.java
+++ b/src/org/python/core/buffer/Strided1DBuffer.java
@@ -1,5 +1,6 @@
 package org.python.core.buffer;
 
+import org.python.core.BufferProtocol;
 import org.python.core.PyBuffer;
 import org.python.core.PyException;
 
@@ -48,6 +49,7 @@
      * {@link Strided1DWritableBuffer#Strided1DWritableBuffer(int, byte[], int, int, int)} for an
      * example of this use.)
      *
+     * @param obj exporting object (or <code>null</code>)
      * @param storage raw byte array containing exported data
      * @param index0 index into storage of item[0]
      * @param count number of items in the slice
@@ -56,9 +58,10 @@
      * @throws ArrayIndexOutOfBoundsException if <code>index0</code>, <code>count</code> and
      *             <code>stride</code> are inconsistent with <code>storage.length</code>
      */
-    protected Strided1DBuffer(byte[] storage, int index0, int count, int stride)
+    protected Strided1DBuffer(BufferProtocol obj, byte[] storage, int index0, int count, int stride)
             throws ArrayIndexOutOfBoundsException, NullPointerException {
         super(storage, STRIDES, index0, count, stride);
+        this.obj = obj;
         this.stride = stride;           // Between items
 
         if (count == 0) {
@@ -107,6 +110,7 @@
      * <code>storage</code> array (unless <code>count=0</code>).
      *
      * @param flags consumer requirements
+     * @param obj exporting object (or <code>null</code>)
      * @param storage raw byte array containing exported data
      * @param index0 index into storage of item[0]
      * @param count number of items in the slice
@@ -116,9 +120,9 @@
      *             <code>stride</code> are inconsistent with <code>storage.length</code>
      * @throws PyException (BufferError) when expectations do not correspond with the type
      */
-    public Strided1DBuffer(int flags, byte[] storage, int index0, int count, int stride)
+    public Strided1DBuffer(int flags, BufferProtocol obj, byte[] storage, int index0, int count, int stride)
             throws ArrayIndexOutOfBoundsException, NullPointerException, PyException {
-        this(storage, index0, count, stride);
+        this(obj, storage, index0, count, stride);
         checkRequestFlags(flags);   // Check request is compatible with type
 
     }
@@ -199,7 +203,7 @@
         public SlicedView(PyBuffer root, int flags, byte[] storage, int index0, int count,
                 int stride) throws PyException {
             // Create a new on the buffer passed in (part of the root)
-            super(flags, storage, index0, count, stride);
+            super(flags, root.getObj(), storage, index0, count, stride);
             // Get a lease on the root PyBuffer (read-only)
             this.root = root.getBuffer(FULL_RO);
         }
diff --git a/src/org/python/core/buffer/Strided1DNIOBuffer.java b/src/org/python/core/buffer/Strided1DNIOBuffer.java
--- a/src/org/python/core/buffer/Strided1DNIOBuffer.java
+++ b/src/org/python/core/buffer/Strided1DNIOBuffer.java
@@ -2,6 +2,7 @@
 
 import java.nio.ByteBuffer;
 
+import org.python.core.BufferProtocol;
 import org.python.core.PyBuffer;
 import org.python.core.PyException;
 
@@ -50,6 +51,7 @@
      * {@link Strided1DWritableBuffer#Strided1DWritableBuffer(int, ByteBuffer, int, int, int)} for
      * an example of this use.)
      *
+     * @param obj exporting object (or <code>null</code>)
      * @param storage the <code>ByteBuffer</code> wrapping the exported object state. NOTE: this
      *            <code>PyBuffer</code> keeps a reference and may manipulate the position, mark and
      *            limit hereafter. Use {@link ByteBuffer#duplicate()} to give it an isolated copy.
@@ -60,9 +62,10 @@
      * @throws ArrayIndexOutOfBoundsException if <code>index0</code>, <code>count</code> and
      *             <code>stride</code> are inconsistent with <code>storage.length</code>
      */
-    protected Strided1DNIOBuffer(ByteBuffer storage, int index0, int count, int stride)
-            throws ArrayIndexOutOfBoundsException, NullPointerException {
+    protected Strided1DNIOBuffer(BufferProtocol obj, ByteBuffer storage, int index0, int count,
+            int stride) throws ArrayIndexOutOfBoundsException, NullPointerException {
         super(storage, STRIDES, index0, count, stride);
+        this.obj = obj;
         this.stride = stride;           // Between items
 
         if (count == 0) {
@@ -121,6 +124,7 @@
      * <code>storage</code> array (unless <code>count=0</code>).
      *
      * @param flags consumer requirements
+     * @param obj exporting object (or <code>null</code>)
      * @param storage <code>ByteBuffer</code> wrapping exported data
      * @param index0 index into storage of item[0]
      * @param count number of items in the slice
@@ -130,9 +134,10 @@
      *             <code>stride</code> are inconsistent with <code>storage.length</code>
      * @throws PyException (BufferError) when expectations do not correspond with the type
      */
-    public Strided1DNIOBuffer(int flags, ByteBuffer storage, int index0, int count, int stride)
-            throws ArrayIndexOutOfBoundsException, NullPointerException, PyException {
-        this(storage.duplicate(), index0, count, stride);
+    public Strided1DNIOBuffer(int flags, BufferProtocol obj, ByteBuffer storage, int index0,
+            int count, int stride) throws ArrayIndexOutOfBoundsException, NullPointerException,
+            PyException {
+        this(obj, storage.duplicate(), index0, count, stride);
         checkRequestFlags(flags);   // Check request is compatible with type
 
     }
@@ -191,7 +196,7 @@
         public SlicedView(PyBuffer root, int flags, ByteBuffer storage, int index0, int count,
                 int stride) throws PyException {
             // Create a new slice on the buffer passed in (part of the root)
-            super(flags, storage, index0, count, stride);
+            super(flags, root.getObj(), storage, index0, count, stride);
             // Get a lease on the root PyBuffer (read-only)
             this.root = root.getBuffer(FULL_RO);
         }
diff --git a/src/org/python/core/buffer/Strided1DWritableBuffer.java b/src/org/python/core/buffer/Strided1DWritableBuffer.java
--- a/src/org/python/core/buffer/Strided1DWritableBuffer.java
+++ b/src/org/python/core/buffer/Strided1DWritableBuffer.java
@@ -1,5 +1,6 @@
 package org.python.core.buffer;
 
+import org.python.core.BufferProtocol;
 import org.python.core.PyBuffer;
 import org.python.core.PyException;
 
@@ -25,6 +26,7 @@
      * the sub-range the caller is allowed to use.
      *
      * @param flags consumer requirements
+     * @param obj exporting object (or <code>null</code>)
      * @param storage raw byte array containing exported data
      * @param index0 index into storage of item[0]
      * @param count number of items in the slice
@@ -34,9 +36,10 @@
      *             <code>stride</code> are inconsistent with <code>storage.length</code>
      * @throws PyException (BufferError) when expectations do not correspond with the type
      */
-    public Strided1DWritableBuffer(int flags, byte[] storage, int index0, int count, int stride)
-            throws ArrayIndexOutOfBoundsException, NullPointerException, PyException {
-        super(storage, index0, count, stride);
+    public Strided1DWritableBuffer(int flags, BufferProtocol obj, byte[] storage, int index0,
+            int count, int stride) throws ArrayIndexOutOfBoundsException, NullPointerException,
+            PyException {
+        super(obj, storage, index0, count, stride);
         addFeatureFlags(WRITABLE);
         checkRequestFlags(flags);   // Check request is compatible with type
     }
@@ -107,7 +110,7 @@
         public SlicedView(PyBuffer root, int flags, byte[] storage, int index0, int count,
                 int stride) throws PyException {
             // Create a new on the buffer passed in (part of the root)
-            super(flags, storage, index0, count, stride);
+            super(flags, root.getObj(), storage, index0, count, stride);
             // Get a lease on the root PyBuffer (writable)
             this.root = root.getBuffer(FULL);
         }
diff --git a/src/org/python/core/buffer/ZeroByteBuffer.java b/src/org/python/core/buffer/ZeroByteBuffer.java
--- a/src/org/python/core/buffer/ZeroByteBuffer.java
+++ b/src/org/python/core/buffer/ZeroByteBuffer.java
@@ -1,5 +1,6 @@
 package org.python.core.buffer;
 
+import org.python.core.BufferProtocol;
 import org.python.core.PyBuffer;
 import org.python.core.PyException;
 
@@ -25,12 +26,15 @@
      * client code that may ask, if the results are customary for the exporting object.
      *
      * @param flags consumer requirements
+     * @param obj exporting object (or <code>null</code>)
      * @param readonly set true if not to be considered writable
      * @param hasArray set true if to be considered as backed by an array
      * @throws PyException (BufferError) when client expectations do not correspond with the type
      */
-    public ZeroByteBuffer(int flags, boolean readonly, boolean hasArray) throws PyException {
+    public ZeroByteBuffer(int flags, BufferProtocol obj, boolean readonly, boolean hasArray)
+            throws PyException {
         super(EMPTY, CONTIGUITY | (readonly ? 0 : WRITABLE), 0, 0, 1);
+        this.obj = obj;
         if (!hasArray) {
             // super() knows we have an array, but this truth is inconvenient here.
             removeFeatureFlags(AS_ARRAY);
@@ -175,7 +179,7 @@
          */
         public View(PyBuffer root, int flags) {
             // Create a new ZeroByteBuffer on who-cares-what byte array
-            super(flags, root.isReadonly(), root.hasArray());
+            super(flags, root.getObj(), root.isReadonly(), root.hasArray());
             // But we still have to get a lease on the root PyBuffer
             this.root = root.getBuffer(FULL_RO);
         }
diff --git a/src/org/python/modules/_io/PyIOBase.java b/src/org/python/modules/_io/PyIOBase.java
--- a/src/org/python/modules/_io/PyIOBase.java
+++ b/src/org/python/modules/_io/PyIOBase.java
@@ -778,7 +778,7 @@
                 // None of the above: complain
                 throw tailoredTypeError("read-write buffer", obj);
             }
-            return new SimpleStringBuffer(PyBUF.SIMPLE, s);
+            return new SimpleStringBuffer(PyBUF.SIMPLE, null, s);
         }
     }
 
@@ -910,18 +910,17 @@
             + "fp is closed after the suite of the with statement is complete:\n" + "\n"
             + "with open('spam.txt', 'r') as fp:\n" + "    fp.write('Spam and eggs!')\n";
 
-
     /* Traverseproc implementation */
     @Override
     public int traverse(Visitproc visit, Object arg) {
-    	//closer cannot be null
+        // closer cannot be null
         if (closer.sys != null) {
-        	int retVal = visit.visit(closer.sys, arg);
+            int retVal = visit.visit(closer.sys, arg);
             if (retVal != 0) {
                 return retVal;
             }
         }
-        //__dict__ cannot be null
+        // __dict__ cannot be null
         return visit.visit(__dict__, arg);
     }
 
diff --git a/tests/java/org/python/core/BaseBytesTest.java b/tests/java/org/python/core/BaseBytesTest.java
--- a/tests/java/org/python/core/BaseBytesTest.java
+++ b/tests/java/org/python/core/BaseBytesTest.java
@@ -203,6 +203,7 @@
      *
      * @see junit.framework.TestCase#setUp()
      */
+    @Override
     protected void setUp() throws Exception {
         super.setUp();
         random = new Random(20120310L);
@@ -595,7 +596,7 @@
          */
         public MyBytes(BufferProtocol value) {
             super(TYPE);
-            init((BufferProtocol)value.getBuffer(PyBUF.SIMPLE));
+            init(value.getBuffer(PyBUF.SIMPLE));
         }
 
         /**
@@ -787,7 +788,7 @@
 
         @Override
         public PyBuffer getBuffer(int flags) {
-            return new SimpleBuffer(flags, store);
+            return new SimpleBuffer(flags, this, store);
         }
 
     }
@@ -824,7 +825,7 @@
                 return;
             }
             for (int i = 0; i < n; i++) {
-                int c = 0xff & ((int)s[pos + i]);
+                int c = 0xff & (s[pos + i]);
                 if (c == 0) {
                     c = '.';
                 } else if (Character.isISOControl(c)) {
diff --git a/tests/java/org/python/core/PyBufferNIOTest.java b/tests/java/org/python/core/PyBufferNIOTest.java
--- a/tests/java/org/python/core/PyBufferNIOTest.java
+++ b/tests/java/org/python/core/PyBufferNIOTest.java
@@ -119,7 +119,7 @@
             BaseBuffer pybuf = getExistingBuffer(flags);
             if (pybuf == null) {
                 // No existing export we can re-use
-                pybuf = new SimpleNIOBuffer(flags, storage) {
+                pybuf = new SimpleNIOBuffer(flags, this, storage) {
 
                     @Override
                     protected void releaseAction() {
@@ -200,7 +200,7 @@
             BaseBuffer pybuf = getExistingBuffer(flags);
             if (pybuf == null) {
                 // No existing export we can re-use
-                pybuf = new RollYourOwnNIOBuffer(flags, storage);
+                pybuf = new RollYourOwnNIOBuffer(flags, this, storage);
                 // Hold a reference for possible re-use
                 export = new WeakReference<BaseBuffer>(pybuf);
             }
@@ -227,26 +227,28 @@
          * contiguous sequence of bytes from the position to the limit.
          *
          * @param flags consumer requirements
+         * @param obj exporting object (or <code>null</code>)
          * @param storage buffer exported (from the position to the limit)
          */
-        public RollYourOwnNIOBuffer(int flags, ByteBuffer storage) {
-            this(null /* =this */, flags, storage, storage.position(), storage.remaining(), 1);
+        public RollYourOwnNIOBuffer(int flags, BufferProtocol obj, ByteBuffer storage) {
+            this(flags, null /* =this */, obj, storage, storage.position(), storage.remaining(), 1);
         }
 
         /**
          * Construct a slice of a one-dimensional byte buffer.
          *
+         * @param flags consumer requirements
+         * @param obj exporting object (or <code>null</code>)
          * @param root on which release must be called when this is released
-         * @param flags consumer requirements
          * @param storage buffer containing exported data
          * @param index0 index into storage of item[0]
          * @param count number of items in the slice
          * @param stride in between successive elements of the new PyBuffer
          * @throws PyException (BufferError) when expectations do not correspond with the type
          */
-        public RollYourOwnNIOBuffer(PyBuffer root, int flags, ByteBuffer storage, int index0,
-                int count, int stride) throws IndexOutOfBoundsException, NullPointerException,
-                PyException {
+        public RollYourOwnNIOBuffer(int flags, PyBuffer root, BufferProtocol obj,
+                ByteBuffer storage, int index0, int count, int stride)
+                throws IndexOutOfBoundsException, NullPointerException, PyException {
             // Client will need to navigate using shape and strides if this is a slice
             super(FEATURES | ((index0 == 0 && stride == 1) ? 0 : STRIDES), //
                     index0, new int[] {count}, new int[] {stride});
@@ -265,8 +267,10 @@
             // Get a lease on the root PyBuffer (read-only). Last in case a check above fails.
             if (root == null) {
                 this.root = this;
+                this.obj = obj;
             } else {
                 this.root = root.getBuffer(FULL_RO);
+                this.obj = root.getObj();
             }
         }
 
@@ -279,7 +283,7 @@
         public PyBuffer getBufferSlice(int flags, int start, int count, int stride) {
             int newStart = index0 + start * strides[0];
             int newStride = strides[0] * stride;
-            return new RollYourOwnNIOBuffer(root, flags, storage, newStart, count, newStride);
+            return new RollYourOwnNIOBuffer(flags, root, null, storage, newStart, count, newStride);
         }
 
         @Override
diff --git a/tests/java/org/python/core/PyBufferTest.java b/tests/java/org/python/core/PyBufferTest.java
--- a/tests/java/org/python/core/PyBufferTest.java
+++ b/tests/java/org/python/core/PyBufferTest.java
@@ -273,6 +273,13 @@
         assertEquals("unexpected length", ref.length, view.getLen());
     }
 
+    /** Test method for {@link org.python.core.PyBUF#getObj()}. */
+    @Test
+    public void testGetObj() {
+        announce("getObj");
+        assertEquals("unexpected exporting object", obj, view.getObj());
+    }
+
     /** Test method for {@link org.python.core.PyBuffer#byteAt(int)}. */
     @Test
     public void testByteAt() {
@@ -1279,7 +1286,7 @@
 
         @Override
         public PyBuffer getBuffer(int flags) {
-            return new SimpleBuffer(flags, storage);
+            return new SimpleBuffer(flags, this, storage);
         }
 
     }
@@ -1368,7 +1375,7 @@
             BaseBuffer pybuf = getExistingBuffer(flags);
             if (pybuf == null) {
                 // No existing export we can re-use
-                pybuf = new SimpleStringBuffer(flags, storage);
+                pybuf = new SimpleStringBuffer(flags, this, storage);
                 // Hold a reference for possible re-use
                 export = new SoftReference<BaseBuffer>(pybuf);
             }
@@ -1404,7 +1411,7 @@
             BaseBuffer pybuf = getExistingBuffer(flags);
             if (pybuf == null) {
                 // No existing export we can re-use
-                pybuf = new SimpleWritableBuffer(flags, storage) {
+                pybuf = new SimpleWritableBuffer(flags, this, storage) {
 
                     @Override
                     protected void releaseAction() {
@@ -1435,7 +1442,7 @@
             BaseBuffer pybuf = getExistingBuffer(flags);
             if (pybuf == null) {
                 // No existing export we can re-use
-                pybuf = new RollYourOwnArrayBuffer(flags, storage);
+                pybuf = new RollYourOwnArrayBuffer(flags, this, storage);
                 // Hold a reference for possible re-use
                 export = new WeakReference<BaseBuffer>(pybuf);
             }
@@ -1461,26 +1468,28 @@
          * Create a buffer view of the entire array.
          *
          * @param flags consumer requirements
+         * @param obj exporting object (or <code>null</code>)
          * @param storage byte array exported in its entirety
          */
-        public RollYourOwnArrayBuffer(int flags, byte[] storage) {
-            this(null /* =this */, flags, storage, 0, storage.length, 1);
+        public RollYourOwnArrayBuffer(int flags, BufferProtocol obj, byte[] storage) {
+            this(flags, null /* =this */, obj, storage, 0, storage.length, 1);
         }
 
         /**
          * Construct a slice of a one-dimensional byte array.
          *
+         * @param flags consumer requirements
          * @param root on which release must be called when this is released
-         * @param flags consumer requirements
+         * @param obj exporting object (or <code>null</code>)
          * @param storage raw byte array containing exported data
          * @param index0 index into storage of item[0]
          * @param count number of items in the slice
          * @param stride in between successive elements of the new PyBuffer
          * @throws PyException (BufferError) when expectations do not correspond with the type
          */
-        public RollYourOwnArrayBuffer(PyBuffer root, int flags, byte[] storage, int index0,
-                int count, int stride) throws IndexOutOfBoundsException, NullPointerException,
-                PyException {
+        public RollYourOwnArrayBuffer(int flags, PyBuffer root, BufferProtocol obj, byte[] storage,
+                int index0, int count, int stride) throws IndexOutOfBoundsException,
+                NullPointerException, PyException {
             // Client will need to navigate using shape and strides if this is a slice
             super(FEATURES | ((index0 == 0 && stride == 1) ? 0 : STRIDES), //
                     index0, new int[] {count}, new int[] {stride});
@@ -1498,8 +1507,10 @@
             // Get a lease on the root PyBuffer (read-only). Last in case a check above fails.
             if (root == null) {
                 this.root = this;
+                this.obj = obj;
             } else {
                 this.root = root.getBuffer(FULL_RO);
+                this.obj = root.getObj();
             }
         }
 
@@ -1512,7 +1523,8 @@
         public PyBuffer getBufferSlice(int flags, int start, int length, int stride) {
             int newStart = index0 + start * strides[0];
             int newStride = strides[0] * stride;
-            return new RollYourOwnArrayBuffer(root, flags, storage, newStart, length, newStride);
+            return new RollYourOwnArrayBuffer(flags, root, null, storage, newStart, length,
+                    newStride);
         }
 
         @Override

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


More information about the Jython-checkins mailing list