[Jython-checkins] jython: Make attributes closed, mode readonly in _io.FileIO.

jeff.allen jython-checkins at python.org
Sun Dec 16 01:20:11 CET 2012


http://hg.python.org/jython/rev/9968367fa217
changeset:   6904:9968367fa217
user:        Jeff Allen <ja...py at farowl.co.uk>
date:        Sat Dec 15 23:59:45 2012 +0000
summary:
  Make attributes closed, mode readonly in _io.FileIO.
Removed some skps and other suppression of Jython test failures in test_fileio.
test_io scores unchanged at fail/error/skip = 12/15/99, test_fileio down at
0/1/1, but with concessions to Jython ValueError issue still in place.

files:
  Lib/test/test_fileio.py                     |  22 ++++---
  src/org/python/modules/_io/OpenMode.java    |  17 +++++-
  src/org/python/modules/_io/PyFileIO.java    |   5 +
  src/org/python/modules/_io/PyIOBase.java    |  28 +++++++--
  src/org/python/modules/_io/PyRawIOBase.java |  22 ++++++-
  5 files changed, 74 insertions(+), 20 deletions(-)


diff --git a/Lib/test/test_fileio.py b/Lib/test/test_fileio.py
--- a/Lib/test/test_fileio.py
+++ b/Lib/test/test_fileio.py
@@ -66,10 +66,9 @@
         self.assertEqual(f.closed, False)
 
         # verify the attributes are readonly
-        #XXX: not read only in Jython?
-        ###for attr in 'mode', 'closed':
-        ###    self.assertRaises((AttributeError, TypeError),
-        ###                      setattr, f, attr, 'oops')
+        for attr in 'mode', 'closed':
+            self.assertRaises((AttributeError, TypeError),
+                              setattr, f, attr, 'oops')
 
     def testReadinto(self):
         # verify readinto
@@ -112,9 +111,9 @@
         f.close()
         self.assertTrue(f.closed)
 
-    def testMethods(self):
-        methods = ['fileno', 'isatty', 'read', 'readinto',
-                   'seek', 'tell', 'truncate', 'write', 'seekable',
+        # These methods all accept a call with 0 arguments
+        methods = ['fileno', 'isatty', 'read', 
+                   'tell', 'truncate', 'seekable',
                    'readable', 'writable']
         if sys.platform.startswith('atheos'):
             methods.remove('truncate')
@@ -127,6 +126,13 @@
             # should raise on closed file
             self.assertRaises(ValueError, method)
 
+        # These other methods should be tested using a specific call
+        # in case the test for number of arguments comes first.
+        b = bytearray()
+        self.assertRaises(ValueError, self.f.readinto, b )
+        self.assertRaises(ValueError, self.f.seek, 0)
+        self.assertRaises(ValueError, self.f.write, b )
+
     def testOpendir(self):
         # Issue 3703: opening a directory should fill the errno
         # Windows always returns "[Errno 13]: Permission denied
@@ -188,7 +194,6 @@
 
         return wrapper
 
-    @unittest.skipIf(is_jython, "FIXME: not working in Jython")
     @ClosedFDRaises
     def testErrnoOnClose(self, f):
         f.close()
@@ -307,7 +312,6 @@
                     self.assertEqual(f.seekable(), False)
                 self.assertEqual(f.isatty(), True)
 
-    @unittest.skipIf(is_jython, "FIXME: not working in Jython")
     def testModeStrings(self):
         # check invalid mode strings
         for mode in ("", "aU", "wU+", "rw", "rt"):
diff --git a/src/org/python/modules/_io/OpenMode.java b/src/org/python/modules/_io/OpenMode.java
--- a/src/org/python/modules/_io/OpenMode.java
+++ b/src/org/python/modules/_io/OpenMode.java
@@ -140,8 +140,21 @@
                 message = "can't use U and writing mode at once";
             } else if (text && binary) {
                 message = "can't have text and binary mode at once";
-            } else if (reading && writing || appending && (reading || writing)) {
-                message = "must have exactly one of read/write/append mode";
+            } else {
+                // How many of r/U, w and a were given?
+                int rwa = 0;
+                if (reading) {
+                    rwa += 1;
+                }
+                if (writing) {
+                    rwa += 1;
+                }
+                if (appending) {
+                    rwa += 1;
+                }
+                if (rwa != 1) {
+                    message = "must have exactly one of read/write/append mode";
+                }
             }
             invalid |= (message != null);
         }
diff --git a/src/org/python/modules/_io/PyFileIO.java b/src/org/python/modules/_io/PyFileIO.java
--- a/src/org/python/modules/_io/PyFileIO.java
+++ b/src/org/python/modules/_io/PyFileIO.java
@@ -22,6 +22,7 @@
 import org.python.expose.ExposedGet;
 import org.python.expose.ExposedMethod;
 import org.python.expose.ExposedNew;
+import org.python.expose.ExposedSet;
 import org.python.expose.ExposedType;
 
 import com.kenai.constantine.platform.Errno;
@@ -60,6 +61,10 @@
     /** The mode as a PyString based on readable and writable */
     @ExposedGet(doc = "String giving the file mode: 'rb', 'rb+', or 'wb'")
     public final PyString mode;
+    @ExposedSet(name="mode")
+    public final void mode_readonly(PyString value) {
+        readonlyAttributeError("mode");
+    }
 
     private static final PyString defaultMode = new PyString("r");
 
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
@@ -20,6 +20,7 @@
 import org.python.expose.ExposedGet;
 import org.python.expose.ExposedMethod;
 import org.python.expose.ExposedNew;
+import org.python.expose.ExposedSet;
 import org.python.expose.ExposedType;
 
 /**
@@ -197,6 +198,10 @@
      */
     @ExposedGet(name = "closed", doc = closed_doc)
     protected boolean __closed;
+    @ExposedSet(name="closed")
+    public final void closed_readonly(boolean value) {
+        readonlyAttributeError("closed");
+    }
 
     /**
      * Close the stream. If closed already, this is a no-op.
@@ -481,7 +486,7 @@
         } else if (limit.isIndex()) {
             return _readline(limit.asInt());
         } else {
-            throw Py.TypeError("limit must be an integer");
+            throw tailoredTypeError("integer limit", limit);
         }
     }
 
@@ -653,7 +658,7 @@
             return new PyList(this);
 
         } else if (!hint.isIndex()) {
-            throw Py.TypeError("integer or None expected");
+            throw tailoredTypeError("integer or None", hint);
 
         } else if ((h = hint.asIndex()) <= 0) {
             return new PyList(this);
@@ -739,8 +744,7 @@
                 s = ((PyArray)obj).tostring();
             } else {
                 // None of the above: complain
-                String fmt = "object must be string or buffer, not %.100s";
-                throw Py.TypeError(String.format(fmt, obj.getType().fastGetName()));
+                throw tailoredTypeError("read-write buffer", obj);
             }
             return new SimpleStringBuffer(PyBUF.SIMPLE, s);
         }
@@ -769,11 +773,23 @@
             }
         } else {
             // Can't be a buffer: complain
-            String fmt = "object must be read-write buffer, not %.100s";
-            throw Py.TypeError(String.format(fmt, obj.getType().fastGetName()));
+            throw tailoredTypeError("read-write buffer", obj);
         }
     }
 
+    /**
+     * Convenience method providing the exception when an argument is not the expected type.
+     * The format is "<b>type</b> argument expected, got <code>type(arg)</code>."
+     *
+     * @param type of thing expected (or could any text)
+     * @param arg argument provided from which actual type will be reported
+     * @return TypeError to throw
+     */
+    protected static PyException tailoredTypeError(String type, PyObject arg){
+        return Py.TypeError(String.format("%s argument expected, got %.100s.",
+                type, arg.getType().fastGetName()));
+    }
+
     /*
      * Documentation strings: public where they might be useful to a subclass.
      */
diff --git a/src/org/python/modules/_io/PyRawIOBase.java b/src/org/python/modules/_io/PyRawIOBase.java
--- a/src/org/python/modules/_io/PyRawIOBase.java
+++ b/src/org/python/modules/_io/PyRawIOBase.java
@@ -54,7 +54,7 @@
      *         is not ready with further data)
      */
     public PyObject read(int n) {
-        return _RawIOBase_read(n);
+        return _read(n);
     }
 
     /*
@@ -62,8 +62,24 @@
      * terms of read(), in case the latter is a more suitable primitive operation, but that would
      * lead to nasty recursion in case a subclass doesn't implement either.)
      */
-    @ExposedMethod(defaults = "-1", doc = read_doc)
-    final PyObject _RawIOBase_read(int n) {
+    @ExposedMethod(defaults = "null", doc = read_doc)
+    final PyObject _RawIOBase_read(PyObject n) {
+        if (n == null || n == Py.None) {
+            return _read(-1);
+        } else if (n.isIndex()) {
+            return _read(n.asInt());
+        } else {
+            throw tailoredTypeError("integer", n);
+        }
+    }
+
+    /**
+     * Implementation of the read() method once the argument has been reduced to an int.
+     * @param n number of bytes to read (if possible)
+     * @return a PyString holding the bytes read or <code>Py.None</code> (when a non-blocking source
+     *         is not ready with further data)
+     */
+    private PyObject _read(int n) {
 
         if (n < 0) {
             // This is really a request to read the whole stream

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


More information about the Jython-checkins mailing list