[Jython-checkins] jython: Make bytearray acceptable to f.readinto(b) and f.write(b)
jeff.allen
jython-checkins at python.org
Wed Aug 1 10:12:30 CEST 2012
http://hg.python.org/jython/rev/5018fda4fc52
changeset: 6818:5018fda4fc52
user: Jeff Allen <ja...py at farowl.co.uk>
date: Sun Jul 29 21:56:01 2012 +0100
summary:
Make bytearray acceptable to f.readinto(b) and f.write(b)
This fixes a test failure in test.test_bytes, but I'm not at all sure it finishes the job as far as bytearray and the io module go. There is much about the design that remains a puzzle to me.
files:
src/org/python/core/PyFile.java | 19 ++++
src/org/python/core/io/TextIOBase.java | 56 ++++++++++----
2 files changed, 59 insertions(+), 16 deletions(-)
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
@@ -22,6 +22,7 @@
import org.python.core.io.TextIOBase;
import org.python.core.io.TextIOWrapper;
import org.python.core.io.UniversalIOWrapper;
+import org.python.core.util.StringUtil;
import org.python.expose.ExposedDelete;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
@@ -379,10 +380,28 @@
* Return a String for writing to the underlying file from obj.
*/
private String asWritable(PyObject obj, String message) {
+
if (obj instanceof PyUnicode) {
return ((PyUnicode)obj).encode();
+
} else if (obj instanceof PyString) {
return ((PyString) obj).getString();
+
+ } else if (obj instanceof BufferProtocol) {
+ // Try to get a simple byte-oriented buffer
+ PyBuffer buf = null;
+ try {
+ buf = ((BufferProtocol)obj).getBuffer(PyBUF.SIMPLE);
+ return StringUtil.fromBytes(buf);
+ } catch (Exception e) {
+ // Wrong kind of buffer: generic error message will do
+ } finally {
+ // If we got a buffer, we should release it
+ if (buf != null) {
+ buf.release();
+ }
+ }
+
} else if (binary && obj instanceof PyArray) {
return ((PyArray)obj).tostring();
}
diff --git a/src/org/python/core/io/TextIOBase.java b/src/org/python/core/io/TextIOBase.java
--- a/src/org/python/core/io/TextIOBase.java
+++ b/src/org/python/core/io/TextIOBase.java
@@ -5,10 +5,15 @@
import java.io.OutputStream;
import java.nio.ByteBuffer;
+import org.python.core.BufferPointer;
+import org.python.core.BufferProtocol;
import org.python.core.Py;
import org.python.core.PyArray;
+import org.python.core.PyBUF;
+import org.python.core.PyBuffer;
import org.python.core.PyObject;
import org.python.core.PyString;
+import org.python.core.util.StringUtil;
/**
* Base class for text I/O.
@@ -91,29 +96,48 @@
}
/**
- * Read into the given PyObject that implements the read-write
- * buffer interface (currently just a PyArray).
- *
- * @param buf a PyObject implementing the read-write buffer interface
+ * Read into the given PyObject that implements the Jython buffer API (with write access) or is
+ * a PyArray.
+ *
+ * @param buf a PyObject compatible with the buffer API
* @return the amount of data read as an int
*/
public int readinto(PyObject buf) {
// This is an inefficient version of readinto: but readinto is
// not recommended for use in Python 2.x anyway
- if (!(buf instanceof PyArray)) {
- // emulate PyArg_ParseTuple
- if (buf instanceof PyString) {
- throw Py.TypeError("Cannot use string as modifiable buffer");
+ if (buf instanceof BufferProtocol) {
+ PyBuffer view = ((BufferProtocol)buf).getBuffer(PyBUF.SIMPLE);
+ if (view.isReadonly()) {
+ // More helpful than falling through to CPython message
+ throw Py.TypeError("cannot read into read-only "
+ + buf.getType().fastGetName());
+ } else {
+ try {
+ // Inefficiently, we have to go via a String
+ String read = read(view.getLen());
+ int n = read.length();
+ for (int i = 0; i < n; i++) {
+ view.storeAt((byte)read.charAt(i), i);
+ }
+ return read.length();
+ } finally {
+ // We should release the buffer explicitly
+ view.release();
+ }
}
- throw Py.TypeError("argument 1 must be read-write buffer, not "
- + buf.getType().fastGetName());
+
+ } else if (buf instanceof PyArray) {
+ PyArray array = (PyArray)buf;
+ String read = read(array.__len__());
+ for (int i = 0; i < read.length(); i++) {
+ array.set(i, new PyString(read.charAt(i)));
+ }
+ return read.length();
}
- PyArray array = (PyArray)buf;
- String read = read(array.__len__());
- for (int i = 0; i < read.length(); i++) {
- array.set(i, new PyString(read.charAt(i)));
- }
- return read.length();
+
+ // No valid alternative worked
+ throw Py.TypeError("argument 1 must be read-write buffer, not "
+ + buf.getType().fastGetName());
}
/**
--
Repository URL: http://hg.python.org/jython
More information about the Jython-checkins
mailing list