[Jython-checkins] jython: Re-work PyFile.parseMode to accept 'Ub', curing test_file2k failure.
jeff.allen
jython-checkins at python.org
Sat Nov 30 17:52:48 CET 2013
http://hg.python.org/jython/rev/4c2a46a387ec
changeset: 7158:4c2a46a387ec
user: Jeff Allen <ja.py at farowl.co.uk>
date: Sat Nov 23 08:37:33 2013 +0000
summary:
Re-work PyFile.parseMode to accept 'Ub', curing test_file2k failure.
Re-used the logic from _io.OpenMode rather than emulate the string-mangling from
CPython. Removes a skip.
files:
Lib/test/test_file2k.py | 4 +-
src/org/python/core/PyFile.java | 108 +++++++++++++++----
2 files changed, 86 insertions(+), 26 deletions(-)
diff --git a/Lib/test/test_file2k.py b/Lib/test/test_file2k.py
--- a/Lib/test/test_file2k.py
+++ b/Lib/test/test_file2k.py
@@ -155,8 +155,10 @@
yield str(i)
self.assertRaises(ValueError, self.f.writelines, nasty())
- @unittest.skipIf(test_support.is_jython, "FIXME: Not working on Jython")
def testIssue5677(self):
+ # We don't use the already-open file.
+ self.f.close()
+
# Remark: Do not perform more than one test per open file,
# since that does NOT catch the readline error on Windows.
data = 'xxx'
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,7 +22,6 @@
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;
@@ -199,41 +198,100 @@
}
/**
- * Parse and validate the python file mode, returning a cleaned
- * file mode suitable for FileIO.
+ * Parse and validate the python file mode, returning a cleaned file mode suitable for FileIO.
*
* @param mode a python file mode String
* @return a RandomAccessFile mode String
*/
private String parseMode(String mode) {
- if (mode.length() == 0) {
- throw Py.ValueError("empty mode string");
+
+ String message = null;
+ boolean duplicate = false, invalid = false;
+ int n = mode.length();
+
+ // Convert the letters to booleans, noticing duplicates
+ for (int i = 0; i < n; i++) {
+ char c = mode.charAt(i);
+
+ switch (c) {
+ case 'r':
+ duplicate = reading;
+ reading = true;
+ break;
+ case 'w':
+ duplicate = writing;
+ writing = true;
+ break;
+ case 'a':
+ duplicate = appending;
+ appending = true;
+ break;
+ case '+':
+ duplicate = updating;
+ updating = true;
+ break;
+ case 'b':
+ duplicate = binary;
+ binary = true;
+ break;
+ case 'U':
+ duplicate = universal;
+ universal = true;
+ break;
+ default:
+ invalid = true;
+ }
+
+ // duplicate is set iff c was encountered previously */
+ if (duplicate) {
+ invalid = true;
+ break;
+ }
}
- String origMode = mode;
- if (mode.contains("U")) {
- universal = true;
- mode = mode.replace("U", "");
- if (mode.length() == 0) {
- mode = "r";
- } else if ("wa+".indexOf(mode.charAt(0)) > -1) {
- throw Py.ValueError("universal newline mode can only be used with modes starting "
- + "with 'r'");
+ // Implications
+ reading |= universal;
+ binary |= universal;
+
+ // Standard tests and the mode for FileIO
+ StringBuilder fileioMode = new StringBuilder();
+ if (!invalid) {
+ if (universal && (writing || appending)) {
+ // Not quite true, consider 'Ub', but it's what CPython says:
+ message = "universal newline mode can only be used with modes starting with 'r'";
+ } else {
+ // Build the FileIO mode string
+ if (reading) {
+ fileioMode.append('r');
+ }
+ if (writing) {
+ fileioMode.append('w');
+ }
+ if (appending) {
+ fileioMode.append('a');
+ }
+ if (fileioMode.length() != 1) {
+ // We should only have added one of the above
+ message = "mode string must begin with one of 'r', 'w', 'a' or 'U', not '" //
+ + mode + "'";
+ }
+ if (updating) {
+ fileioMode.append('+');
+ }
}
- }
- if ("rwa".indexOf(mode.charAt(0)) == -1) {
- throw Py.ValueError("mode string must begin with one of 'r', 'w', 'a' or 'U', not '"
- + origMode + "'");
+ invalid |= (message != null);
}
- binary = mode.contains("b");
- reading = mode.contains("r");
- writing = mode.contains("w");
- appending = mode.contains("a");
- updating = mode.contains("+");
+ // Finally, if invalid, report this as an error
+ if (invalid) {
+ if (message == null) {
+ // Duplicates discovered or invalid symbols
+ message = String.format("invalid mode: '%.20s'", mode);
+ }
+ throw Py.ValueError(message);
+ }
- return (reading ? "r" : "") + (writing ? "w" : "") + (appending ? "a" : "")
- + (updating ? "+" : "");
+ return fileioMode.toString();
}
@ExposedMethod(defaults = {"-1"}, doc = BuiltinDocs.file_read_doc)
--
Repository URL: http://hg.python.org/jython
More information about the Jython-checkins
mailing list