diff -r 2cb7e7b8f4a8 .project --- a/.project Sat Sep 13 18:50:40 2008 -0400 +++ b/.project Sun Sep 21 13:05:09 2008 -0400 @@ -5,6 +5,11 @@ + + org.python.pydev.PyDevBuilder + + + org.eclipse.jdt.core.javabuilder @@ -23,5 +28,6 @@ org.eclipse.jdt.core.javanature + org.python.pydev.pythonNature diff -r 2cb7e7b8f4a8 Lib/javapath.py --- a/Lib/javapath.py Sat Sep 13 18:50:40 2008 -0400 +++ b/Lib/javapath.py Sun Sep 21 13:05:09 2008 -0400 @@ -20,6 +20,8 @@ from java.lang import System import os +from org.python.core.util.StringUtil import asPyString + def _tostr(s, method): if isinstance(s, basestring): @@ -36,11 +38,11 @@ type_name = '%s.' % obj_type.__module__ type_name += obj_type.__name__ return type_name - + def dirname(path): """Return the directory component of a pathname""" path = _tostr(path, "dirname") - result = File(path).getParent() + result = asPyString(File(path).getParent()) if not result: if isabs(path): result = path # Must be root @@ -51,7 +53,7 @@ def basename(path): """Return the final component of a pathname""" path = _tostr(path, "basename") - return File(path).getName() + return asPyString(File(path).getName()) def split(path): """Split a pathname. @@ -81,7 +83,7 @@ return (path[:n], path[n:]) def splitdrive(path): - """Split a pathname into drive and path specifiers. + """Split a pathname into drive and path specifiers. Returns a 2-tuple "(drive,path)"; either part may be empty. """ @@ -128,7 +130,7 @@ if a == "": a = os.sep f = File(f, a) - return f.getPath() + return asPyString(f.getPath()) def normcase(path): """Normalize case of pathname. @@ -137,7 +139,7 @@ """ path = _tostr(path, "normcase") - return File(path).getPath() + return asPyString(File(path).getPath()) def commonprefix(m): "Given a list of pathnames, return the longest common leading component" @@ -197,7 +199,7 @@ if not c: return gethome() if c == os.sep: - return File(gethome(), path[2:]).getPath() + return asPyString(File(gethome(), path[2:]).getPath()) return path def getuser(): @@ -252,16 +254,16 @@ def _abspath(path): # Must use normpath separately because getAbsolutePath doesn't normalize # and getCanonicalPath would eliminate symlinks. - return normpath(File(sys.getPath(path)).getAbsolutePath()) + return normpath(asPyString(File(sys.getPath(path)).getAbsolutePath())) def realpath(path): """Return an absolute path normalized and symbolic links eliminated""" path = _tostr(path, "realpath") return _realpath(path) - + def _realpath(path): try: - return File(sys.getPath(path)).getCanonicalPath() + return asPyString(File(sys.getPath(path)).getCanonicalPath()) except java.io.IOException: return _abspath(path) diff -r 2cb7e7b8f4a8 Lib/os.py --- a/Lib/os.py Sat Sep 13 18:50:40 2008 -0400 +++ b/Lib/os.py Sun Sep 21 13:05:09 2008 -0400 @@ -48,6 +48,7 @@ from java.io import File from org.python.core import PyFile from org.python.core.io import FileDescriptors, FileIO, IOBase +from org.python.core.util.StringUtil import asPyString # Mapping of: os._name: [name list, shell command list] _os_map = dict(nt=[ @@ -205,15 +206,15 @@ if i < 0 or i > 9: raise IndexError(i) return getattr(self, stat_result._stat_members[i][0]) - + def __setitem__(self, x, value): raise TypeError("object doesn't support item assignment") - + def __setattr__(self, name, value): if name in [x[0] for x in stat_result._stat_members]: raise TypeError(name) raise AttributeError("readonly attribute") - + def __len__(self): return 10 @@ -264,7 +265,7 @@ l = File(sys.getPath(path)).list() if l is None: raise OSError(0, 'No such directory', path) - return list(l) + return [asPyString(entry) for entry in l] def chmod(path, mode): """chmod(path, mode) @@ -303,14 +304,14 @@ # if making a /x/y/z/., java.io.File#mkdirs inexplicably fails. So we need # to force it - + # need to use _path instead of path, because param is hiding # os.path module in namespace! head, tail = _path.split(sys_path) if tail == curdir: if File(_path.join(head)).mkdirs(): return - + raise OSError(0, "couldn't make directories", path) def remove(path): @@ -392,7 +393,7 @@ def strerror(code): """strerror(code) -> string - + Translate an error code to a message string. """ if not isinstance(code, (int, long)): @@ -404,7 +405,7 @@ def access(path, mode): """access(path, mode) -> True if granted, False otherwise - + Use the real uid/gid to test for access to a path. Note that most operations will use the effective uid/gid, therefore this routine can be used in a suid/sgid environment to test if the invoking user has the @@ -458,7 +459,7 @@ def lstat(path): """lstat(path) -> stat result - + Like stat(path), but do not follow symbolic links. """ abs_path = sys.getPath(path) @@ -545,7 +546,7 @@ """ftruncate(fd, length) Truncate a file to a specified length. - """ + """ rawio = FileDescriptors.get(fd) try: rawio.truncate(length) @@ -624,7 +625,7 @@ from org.python.core.util import StringUtil rawio = FileDescriptors.get(fd) buf = _handle_oserror(rawio.read, buffersize) - return str(StringUtil.fromBytes(buf)) + return asPyString(StringUtil.fromBytes(buf)) def write(fd, string): """write(fd, string) -> byteswritten @@ -647,7 +648,7 @@ if _name == 'posix' and _native_posix: def link(src, dst): """link(src, dst) - + Create a hard link to a file. """ _posix.link(sys.getPath(src), sys.getPath(dst)) @@ -661,7 +662,7 @@ def readlink(path): """readlink(path) -> path - + Return a string representing the path to which the symbolic link points. """ @@ -863,7 +864,7 @@ def putenv(key, value): """putenv(key, value) - + Change or add an environment variable. """ environ[key] = value diff -r 2cb7e7b8f4a8 Lib/zlib.py --- a/Lib/zlib.py Sat Sep 13 18:50:40 2008 -0400 +++ b/Lib/zlib.py Sun Sep 21 13:05:09 2008 -0400 @@ -1,7 +1,9 @@ import jarray, binascii from java.util.zip import Adler32, Deflater, Inflater -from java.lang import Long, String, StringBuffer +from java.lang import Long, String + +from cStringIO import StringIO class error(Exception): pass @@ -28,7 +30,7 @@ _valid_flush_modes = (Z_FINISH,) def adler32(s, value=1): - if value != 1: + if value != 1: raise ValueError, "adler32 only support start value of 1" checksum = Adler32() checksum.update(String.getBytes(s, 'iso-8859-1')) @@ -50,7 +52,7 @@ inflater = Inflater(wbits < 0) inflater.setInput(string) return _get_inflate_data(inflater) - + class compressobj: # all jython uses wbits for is deciding whether to skip the header if it's negative @@ -69,7 +71,7 @@ raise error("compressobj may not be used after flush(Z_FINISH)") self.deflater.setInput(string, 0, len(string)) return _get_deflate_data(self.deflater) - + def flush(self, mode=Z_FINISH): if self._ended: raise error("compressobj may not be used after flush(Z_FINISH)") @@ -94,7 +96,7 @@ def decompress(self, string, max_length=0): if self._ended: raise error("decompressobj may not be used after flush()") - + # unused_data is always "" until inflation is finished; then it is # the unused bytes of the input; # unconsumed_tail is whatever input was not used because max_length @@ -115,7 +117,7 @@ self.unconsumed_tail = string[-r:] else: self.unused_data = string[-r:] - + return inflated def flush(self, length=None): @@ -132,18 +134,19 @@ def _get_deflate_data(deflater): buf = jarray.zeros(1024, 'b') - sb = StringBuffer() + s = StringIO() while not deflater.finished(): l = deflater.deflate(buf) if l == 0: break - sb.append(String(buf, 0, 0, l)) - return sb.toString() + s.write(String(buf, 0, 0, l)) + s.seek(0) + return s.read() - + def _get_inflate_data(inflater, max_length=0): buf = jarray.zeros(1024, 'b') - sb = StringBuffer() + s = StringIO() total = 0 while not inflater.finished(): if max_length: @@ -154,7 +157,8 @@ break total += l - sb.append(String(buf, 0, 0, l)) + s.write(String(buf, 0, 0, l)) if max_length and total == max_length: break - return sb.toString() + s.seek(0) + return s.read() diff -r 2cb7e7b8f4a8 src/com/ziclix/python/sql/DataHandler.java --- a/src/com/ziclix/python/sql/DataHandler.java Sat Sep 13 18:50:40 2008 -0400 +++ b/src/com/ziclix/python/sql/DataHandler.java Sun Sep 21 13:05:09 2008 -0400 @@ -177,7 +177,7 @@ case Types.LONGVARCHAR: if (object instanceof PyFile) { - object = new PyString(((PyFile) object).read()); + object = ((PyFile) object).read(); } String varchar = (String) object.__tojava__(String.class); @@ -192,7 +192,7 @@ default : if (object instanceof PyFile) { - object = new PyString(((PyFile) object).read()); + object = ((PyFile) object).read(); } stmt.setObject(index, object.__tojava__(Object.class), type); diff -r 2cb7e7b8f4a8 src/com/ziclix/python/sql/JDBC20DataHandler.java --- a/src/com/ziclix/python/sql/JDBC20DataHandler.java Sat Sep 13 18:50:40 2008 -0400 +++ b/src/com/ziclix/python/sql/JDBC20DataHandler.java Sun Sep 21 13:05:09 2008 -0400 @@ -62,7 +62,7 @@ case Types.CLOB: if (object instanceof PyFile) { - object = new PyString(((PyFile) object).read()); + object = ((PyFile) object).read(); } String clob = (String) object.__tojava__(String.class); diff -r 2cb7e7b8f4a8 src/com/ziclix/python/sql/Jython22DataHandler.java --- a/src/com/ziclix/python/sql/Jython22DataHandler.java Sat Sep 13 18:50:40 2008 -0400 +++ b/src/com/ziclix/python/sql/Jython22DataHandler.java Sun Sep 21 13:05:09 2008 -0400 @@ -163,7 +163,7 @@ case Types.LONGVARCHAR: if (object instanceof PyFile) { - object = new PyString(((PyFile) object).read()); + object = ((PyFile) object).read(); } String varchar = (String) object.__tojava__(String.class); @@ -178,7 +178,7 @@ default : if (object instanceof PyFile) { - object = new PyString(((PyFile) object).read()); + object = ((PyFile) object).read(); } stmt.setObject(index, object.__tojava__(Object.class), type); diff -r 2cb7e7b8f4a8 src/com/ziclix/python/sql/handler/MySQLDataHandler.java --- a/src/com/ziclix/python/sql/handler/MySQLDataHandler.java Sat Sep 13 18:50:40 2008 -0400 +++ b/src/com/ziclix/python/sql/handler/MySQLDataHandler.java Sun Sep 21 13:05:09 2008 -0400 @@ -54,22 +54,24 @@ switch (type) { case Types.LONGVARCHAR: - String varchar; - if (object instanceof PyFile) { - varchar = ((PyFile) object).read(); - } else { - varchar = (String) object.__tojava__(String.class); - } - InputStream stream = new ByteArrayInputStream(StringUtil.toBytes(varchar)); + // XXX: Only works with ASCII data! + byte[] bytes; + if (object instanceof PyFile) { + bytes = ((PyFile) object).read().toBytes(); + } else { + String varchar = (String) object.__tojava__(String.class); + bytes = StringUtil.toBytes(varchar); + } + InputStream stream = new ByteArrayInputStream(bytes); - stream = new BufferedInputStream(stream); + stream = new BufferedInputStream(stream); - stmt.setAsciiStream(index, stream, varchar.length()); - break; + stmt.setAsciiStream(index, stream, bytes.length); + break; default : - super.setJDBCObject(stmt, index, object, type); - break; + super.setJDBCObject(stmt, index, object, type); + break; } } } diff -r 2cb7e7b8f4a8 src/com/ziclix/python/sql/handler/PostgresqlDataHandler.java --- a/src/com/ziclix/python/sql/handler/PostgresqlDataHandler.java Sat Sep 13 18:50:40 2008 -0400 +++ b/src/com/ziclix/python/sql/handler/PostgresqlDataHandler.java Sun Sep 21 13:05:09 2008 -0400 @@ -111,11 +111,11 @@ String varchar; // Postgresql driver can't handle the setCharacterStream() method so use setObject() instead if (object instanceof PyFile) { - varchar = ((PyFile) object).read(); + varchar = ((PyFile) object).read().asString(); } else { varchar = (String) object.__tojava__(String.class); } - + stmt.setObject(index, varchar, type); break; diff -r 2cb7e7b8f4a8 src/org/python/core/PyFile.java --- a/src/org/python/core/PyFile.java Sat Sep 13 18:50:40 2008 -0400 +++ b/src/org/python/core/PyFile.java Sun Sep 21 13:05:09 2008 -0400 @@ -35,7 +35,7 @@ public class PyFile extends PyObject { public static final PyType TYPE = PyType.fromClass(PyFile.class); - + /** The filename */ @ExposedGet public PyObject name; @@ -286,16 +286,16 @@ } @ExposedMethod(defaults = {"-1"}) - final synchronized String file_read(int n) { + final synchronized PyString file_read(int n) { checkClosed(); - return file.read(n); + return new PyString(file.read(n)); } - public String read(int n) { + public PyString read(int n) { return file_read(n); } - public String read() { + public PyString read() { return file_read(-1); } @@ -310,16 +310,16 @@ } @ExposedMethod(defaults = {"-1"}) - final synchronized String file_readline(int max) { + final synchronized PyString file_readline(int max) { checkClosed(); - return file.readline(max); + return new PyString(file.readline(max)); } - public String readline(int max) { + public PyString readline(int max) { return file_readline(max); } - public String readline() { + public PyString readline() { return file_readline(-1); } diff -r 2cb7e7b8f4a8 src/org/python/core/PyFunction.java --- a/src/org/python/core/PyFunction.java Sat Sep 13 18:50:40 2008 -0400 +++ b/src/org/python/core/PyFunction.java Sun Sep 21 13:05:09 2008 -0400 @@ -143,13 +143,13 @@ } @ExposedGet(name = "func_name") - public String getFuncName() { - return __name__; + public PyString getFuncName() { + return new PyString(__name__); } @ExposedSet(name = "func_name") - public void setFuncName(String func_name) { - __name__ = func_name; + public void setFuncName(PyString func_name) { + __name__ = func_name.asString(); } @ExposedGet(name = "func_doc") diff -r 2cb7e7b8f4a8 src/org/python/core/PyString.java --- a/src/org/python/core/PyString.java Sat Sep 13 18:50:40 2008 -0400 +++ b/src/org/python/core/PyString.java Sun Sep 21 13:05:10 2008 -0400 @@ -46,7 +46,7 @@ PyString(StringBuilder buffer) { this(TYPE, new String(buffer)); } - + /** * Creates a PyString from an already interned String. Just means it won't * be reinterned if used in a place that requires interned Strings. @@ -83,11 +83,11 @@ } return codePoints; } - + public String substring(int start, int end) { return string.substring(start, end); } - + public PyString __str__() { return str___str__(); } @@ -126,7 +126,7 @@ final String str_toString() { return toString(); } - + public String internedString() { if (interned) return string; @@ -223,7 +223,7 @@ private static ucnhashAPI pucnHash = null; - + public static String decode_UnicodeEscape(String str, int start, int end, @@ -479,7 +479,7 @@ } return ret; } - + @ExposedMethod(defaults = "null") final PyObject str___getslice__(PyObject start, PyObject stop, PyObject step) { return seq___getslice__(start, stop, step); @@ -521,7 +521,7 @@ return null; return string.equals(s) ? Py.False : Py.True; } - + public PyObject __lt__(PyObject other) { return str___lt__(other); } @@ -645,8 +645,8 @@ protected PyString createInstance(String str, boolean isBasic) { // ignore isBasic, doesn't apply to PyString, just PyUnicode return new PyString(str); - } - + } + public boolean __contains__(PyObject o) { return str___contains__(o); } @@ -690,7 +690,7 @@ } return repeat(o.asIndex(Py.OverflowError)); } - + @Override public PyObject __rmul__(PyObject o) { return str___rmul__(o); @@ -707,7 +707,7 @@ public PyObject __add__(PyObject generic_other) { return str___add__(generic_other); } - + @ExposedMethod(type = MethodType.BINARY) final PyObject str___add__(PyObject generic_other) { if (generic_other instanceof PyString) { @@ -733,7 +733,7 @@ public PyObject __mod__(PyObject other) { return str___mod__(other); } - + @ExposedMethod public PyObject str___mod__(PyObject other){ StringFormatter fmt = new StringFormatter(string, false); @@ -844,7 +844,7 @@ int end = endDouble(string, s); z = Double.valueOf(string.substring(s, end)).doubleValue(); if (z == Double.POSITIVE_INFINITY) { - throw Py.ValueError(String.format("float() out of range: %.150s", string)); + throw Py.ValueError(String.format("float() out of range: %.150s", string)); } s=end; @@ -904,7 +904,7 @@ public String lower() { return str_lower(); } - + @ExposedMethod final String str_lower() { return string.toLowerCase(); @@ -1005,7 +1005,7 @@ public String lstrip() { return str_lstrip(null); } - + public String lstrip(String sep) { return str_lstrip(sep); } @@ -1028,7 +1028,7 @@ public String rstrip(String sep) { return str_rstrip(sep); } - + @ExposedMethod(defaults = "null") final String str_rstrip(String sep) { char[] chars = string.toCharArray(); @@ -1427,7 +1427,7 @@ public int count(String sub, int start, int end) { return str_count(sub, start, Py.newInteger(end)); } - + @ExposedMethod(defaults = {"0", "null"}) final int str_count(String sub, int start, PyObject end) { int[] indices = translateIndices(start, end); @@ -1518,7 +1518,7 @@ if (lowSval.equals("nan")) return Double.NaN; else if (lowSval.equals("inf")) return Double.POSITIVE_INFINITY; else if (lowSval.equals("-inf")) return Double.NEGATIVE_INFINITY; - + if (lowSval.endsWith("d") || lowSval.endsWith("f")) { throw new NumberFormatException("format specifiers not allowed"); } @@ -1640,10 +1640,10 @@ // if the base >= 22, then an 'l' or 'L' is a digit! if (base < 22 && e > b && (str.charAt(e-1) == 'L' || str.charAt(e-1) == 'l')) e--; - + if (b > 0 || e < str.length()) str = str.substring(b, e); - + try { java.math.BigInteger bi = null; if (sign == '-') @@ -1682,7 +1682,7 @@ } return fillchar.charAt(0); } - + public String ljust(int width) { return str_ljust(width, null); } @@ -1690,7 +1690,7 @@ public String ljust(int width, String padding) { return str_ljust(width, padding); } - + @ExposedMethod(defaults="null") final String str_ljust(int width, String fillchar) { char pad = parse_fillchar("ljust", fillchar); @@ -1726,7 +1726,7 @@ int half = n/2; if (n%2 > 0 && width%2 > 0) half += 1; - + return padding(half, pad)+string+padding(n-half, pad); } @@ -1815,7 +1815,7 @@ return replace((PyString)oldPiece, (PyString)newPiece, maxsplit == null ? -1 : maxsplit.asInt()); } - + protected PyString replace(PyString oldPiece, PyString newPiece, int maxsplit) { int len = string.length(); int old_len = oldPiece.string.length(); @@ -1825,7 +1825,7 @@ } return createInstance(string, true); } - + if (old_len == 0 && newPiece.string.length() != 0 && maxsplit !=0) { // old="" and new != "", interleave new piece with each char in original, taking in effect maxsplit StringBuilder buffer = new StringBuilder(); @@ -1838,7 +1838,7 @@ buffer.append(string.substring(i)); return createInstance(buffer.toString(), true); } - + if(maxsplit == -1) { if(old_len == 0) { maxsplit = len + 1; @@ -1846,7 +1846,7 @@ maxsplit = len; } } - + return newPiece.str_join(splitfields(oldPiece.string, maxsplit)); } @@ -1923,30 +1923,30 @@ @ExposedMethod(defaults = {"0", "null"}) final boolean str_startswith(PyObject prefix, int start, PyObject end) { int[] indices = translateIndices(start, end); - + if (prefix instanceof PyString) { - String strPrefix = ((PyString)prefix).string; + String strPrefix = ((PyString)prefix).string; if (indices[1] - indices[0] < strPrefix.length()) return false; - - return string.startsWith(strPrefix, indices[0]); + + return string.startsWith(strPrefix, indices[0]); } else if (prefix instanceof PyTuple) { - PyObject[] prefixes = ((PyTuple)prefix).getArray(); - - for (int i = 0 ; i < prefixes.length ; i++) { - if (!(prefixes[i] instanceof PyString)) - throw Py.TypeError("expected a character buffer object"); + PyObject[] prefixes = ((PyTuple)prefix).getArray(); - String strPrefix = ((PyString)prefixes[i]).string; + for (int i = 0 ; i < prefixes.length ; i++) { + if (!(prefixes[i] instanceof PyString)) + throw Py.TypeError("expected a character buffer object"); + + String strPrefix = ((PyString)prefixes[i]).string; if (indices[1] - indices[0] < strPrefix.length()) - continue; - - if (string.startsWith(strPrefix, indices[0])) - return true; - } - return false; + continue; + + if (string.startsWith(strPrefix, indices[0])) + return true; + } + return false; } else { - throw Py.TypeError("expected a character buffer object or tuple"); + throw Py.TypeError("expected a character buffer object or tuple"); } } @@ -1968,31 +1968,31 @@ String substr = string.substring(indices[0], indices[1]); if (suffix instanceof PyString) { - return substr.endsWith(((PyString)suffix).string); + return substr.endsWith(((PyString)suffix).string); } else if (suffix instanceof PyTuple) { - PyObject[] suffixes = ((PyTuple)suffix).getArray(); - - for (int i = 0 ; i < suffixes.length ; i++) { - if (!(suffixes[i] instanceof PyString)) - throw Py.TypeError("expected a character buffer object"); + PyObject[] suffixes = ((PyTuple)suffix).getArray(); - if (substr.endsWith(((PyString)suffixes[i]).string)) - return true; - } - return false; + for (int i = 0 ; i < suffixes.length ; i++) { + if (!(suffixes[i] instanceof PyString)) + throw Py.TypeError("expected a character buffer object"); + + if (substr.endsWith(((PyString)suffixes[i]).string)) + return true; + } + return false; } else { - throw Py.TypeError("expected a character buffer object or tuple"); + throw Py.TypeError("expected a character buffer object or tuple"); } - } + } /** * Turns the possibly negative Python slice start and end into valid indices * into this string. - * + * * @return a 2 element array of indices into this string describing a * substring from [0] to [1]. [0] <= [1], [0] >= 0 and [1] <= * string.length() - * + * */ protected int[] translateIndices(int start, PyObject end) { int iEnd; @@ -2501,7 +2501,7 @@ // A magic number. Larger than in CPython. throw Py.OverflowError("formatted " + type + " is too long (precision too long?)"); } - + } private String formatLong(PyObject arg, char type, boolean altFlag) { @@ -2886,7 +2886,7 @@ string = formatFloatExponential(arg, c, false); break; case 'f': - case 'F': + case 'F': string = formatFloatDecimal(arg, false); // if (altFlag && string.indexOf('.') == -1) // string += '.'; diff -r 2cb7e7b8f4a8 src/org/python/core/PyStringMap.java --- a/src/org/python/core/PyStringMap.java Sat Sep 13 18:50:40 2008 -0400 +++ b/src/org/python/core/PyStringMap.java Sun Sep 21 13:05:10 2008 -0400 @@ -141,7 +141,9 @@ for (Entry entry : table.entrySet()) { Object key = entry.getKey(); if (key instanceof String) { - buf.append(Py.java2py(key).__repr__().toString()); + // This is a bit complicated, but prevents us to duplicate + // PyString#__repr__ logic here. + buf.append(new PyString((String)key).__repr__().toString()); } else { buf.append(((PyObject)key).__repr__().toString()); } @@ -211,7 +213,7 @@ /** * Return this[key] if the key exists in the mapping, default_object is returned otherwise. - * + * * @param key * the key to lookup in the mapping. * @param default_object @@ -228,7 +230,7 @@ /** * Return this[key] if the key exists in the mapping, None is returned otherwise. - * + * * @param key * the key to lookup in the mapping. */ @@ -261,7 +263,7 @@ } for (int i = 0; i < keywords.length; i++) { __setitem__(keywords[i], args[nargs + i]); - } + } } /** @@ -323,7 +325,7 @@ /** * Return this[key] if the key exist, otherwise insert key with a None value and return None. - * + * * @param key * the key to lookup in the mapping. */ @@ -334,7 +336,7 @@ /** * Return this[key] if the key exist, otherwise insert key with the value of failobj and return * failobj - * + * * @param key * the key to lookup in the mapping. * @param failobj diff -r 2cb7e7b8f4a8 src/org/python/core/PySystemState.java --- a/src/org/python/core/PySystemState.java Sat Sep 13 18:50:40 2008 -0400 +++ b/src/org/python/core/PySystemState.java Sun Sep 21 13:05:10 2008 -0400 @@ -35,13 +35,13 @@ public static final String PYTHON_CACHEDIR = "python.cachedir"; public static final String PYTHON_CACHEDIR_SKIP = "python.cachedir.skip"; protected static final String CACHEDIR_DEFAULT_NAME = "cachedir"; - + public static final String JYTHON_JAR = "jython.jar"; private static final String JAR_URL_PREFIX = "jar:file:"; private static final String JAR_SEPARATOR = "!"; - public static String version = Version.getVersion(); + public static PyString version = new PyString(Version.getVersion()); public static int hexversion = ((Version.PY_MAJOR_VERSION << 24) | (Version.PY_MINOR_VERSION << 16) | (Version.PY_MICRO_VERSION << 8) | @@ -79,7 +79,7 @@ public static PackageManager packageManager; public static File cachedir; - + private static PyList defaultPath; private static PyList defaultArgv; private static PyObject defaultExecutable; @@ -89,7 +89,7 @@ public static String exec_prefix=""; private static boolean initialized = false; - + /** The arguments passed to this program on the command line. */ public PyList argv = new PyList(); @@ -101,8 +101,8 @@ public PyList path_hooks; public PyObject path_importer_cache; - public static String platform = "java"; - public static String byteorder = "big"; + public static PyString platform = new PyString("java"); + public static PyString byteorder = new PyString("big"); public PyObject ps1 = new PyString(">>> "); public PyObject ps2 = new PyString("... "); @@ -130,7 +130,7 @@ public PyObject last_traceback = Py.None; public PyObject __name__ = new PyString("sys"); - + public PyObject __dict__; private int recursionlimit = 1000; @@ -182,7 +182,7 @@ __dict__.__setitem__("displayhook", __displayhook__); __dict__.__setitem__("excepthook", __excepthook__); } - + void reload() throws PyIgnoreMethodTag { __dict__.invoke("update", getType().fastGetDict()); } @@ -213,10 +213,10 @@ PyObject ret = super.__findattr_ex__(name); if (ret != null) { if (ret instanceof PyMethod) { - if (__dict__.__finditem__(name) instanceof PyReflectedFunction) - return ret; // xxx depends on nonstandard __dict__ + if (__dict__.__finditem__(name) instanceof PyReflectedFunction) + return ret; // xxx depends on nonstandard __dict__ } else if (ret == PyAttributeDeleted.INSTANCE) { - return null; + return null; } else return ret; } @@ -245,7 +245,7 @@ __dict__.__delitem__(name); } catch (PyException pye) { // KeyError if (ret == null) { - throw Py.AttributeError(name); + throw Py.AttributeError(name); } } } @@ -288,8 +288,8 @@ } } - public String getdefaultencoding() { - return codecs.getDefaultEncoding(); + public PyString getdefaultencoding() { + return new PyString(codecs.getDefaultEncoding()); } public void setdefaultencoding(String encoding) { @@ -431,10 +431,10 @@ if (version.equals("12")) { version = "1.2"; } - platform = "java" + version; + platform = new PyString("java" + version); } - private static void initRegistry(Properties preProperties, Properties postProperties, + private static void initRegistry(Properties preProperties, Properties postProperties, boolean standalone, String jarFileName) { if (registry != null) { @@ -712,7 +712,7 @@ addBuiltin(tok.nextToken()); int n = builtinNames.size(); - PyObject [] built_mod = new PyObject[n]; + PyObject [] built_mod = new PyObject[n]; Enumeration keys = builtinNames.keys(); for (int i=0; itrue if we have a standalone .jar file, false otherwise. */ private static boolean isStandalone(String jarFileName) { diff -r 2cb7e7b8f4a8 src/org/python/core/PyTraceback.java --- a/src/org/python/core/PyTraceback.java Sat Sep 13 18:50:40 2008 -0400 +++ b/src/org/python/core/PyTraceback.java Sun Sep 21 13:05:10 2008 -0400 @@ -62,11 +62,12 @@ return null; } + String line = null; int i = 0; try { for (i = 0; i < tb_lineno; i++) { - line = pyFile.readline(); + line = pyFile.readline().asString(); if (line.equals("")) { break; } diff -r 2cb7e7b8f4a8 src/org/python/core/__builtin__.java --- a/src/org/python/core/__builtin__.java Sat Sep 13 18:50:40 2008 -0400 +++ b/src/org/python/core/__builtin__.java Sun Sep 21 13:05:10 2008 -0400 @@ -234,7 +234,7 @@ /** * @param intern - should the resulting string be interned - * @return arg as a String, or throws TypeError with message if asString throws a ConversionException. + * @return arg as a String, or throws TypeError with message if asString throws a ConversionException. */ private String asString(PyObject arg, String message, boolean intern) { @@ -278,7 +278,7 @@ } if (args[0] instanceof PyUnicode) { - flags += PyTableCode.PyCF_SOURCE_IS_UTF8; + flags += PyTableCode.PyCF_SOURCE_IS_UTF8; } return __builtin__.compile(args[0].toString(), args[1].toString(), args[2].toString(), flags, dont_inherit); case 29: @@ -387,7 +387,7 @@ dict.__setitem__("__import__", new ImportFunction()); dict.__setitem__("sorted", new SortedFunction()); dict.__setitem__("all", new AllFunction()); - dict.__setitem__("any", new AnyFunction()); + dict.__setitem__("any", new AnyFunction()); } public static PyObject abs(PyObject o) { @@ -395,9 +395,9 @@ } public static PyObject apply(PyObject o) { - return o.__call__(); + return o.__call__(); } - + public static PyObject apply(PyObject o, PyObject args) { return o.__call__(Py.make_array(args)); } @@ -463,7 +463,7 @@ public static PyObject compile(modType node, String filename, String kind) { return Py.compile_flags(node, filename, kind, Py.getCompilerFlags()); } - + public static PyObject compile(String data, String filename, String kind, int flags, boolean dont_inherit) { if ((flags & ~PyTableCode.CO_ALL_FEATURES) != 0) { throw Py.ValueError("compile(): unrecognised flags"); @@ -516,16 +516,16 @@ (o.__findattr__("__getitem__") != null && (!rw || o.__findattr__("__setitem__") != null)); } - + private static void verify_mappings(PyObject globals, PyObject locals, boolean rw) { if (!PyMapping_check(globals, rw)) { throw Py.TypeError("globals must be a mapping"); - } + } if (!PyMapping_check(locals, rw)) { throw Py.TypeError("locals must be a mapping"); } } - + public static PyObject eval(PyObject o, PyObject globals, PyObject locals) { verify_mappings(globals, locals, false); PyCode code; @@ -898,7 +898,7 @@ throw Py.TypeError("ord() expected a character, but string of length " + length + " found"); } - + public static PyObject pow(PyObject x, PyObject y) { return x._pow(y); } @@ -1026,7 +1026,7 @@ private static PyString readline(PyObject file) { if (file instanceof PyFile) { - return new PyString(((PyFile) file).readline()); + return ((PyFile) file).readline(); } else { PyObject ret = file.invoke("readline"); if (!(ret instanceof PyString)) { @@ -1035,7 +1035,7 @@ return (PyString) ret; } } - + public static String raw_input(PyObject prompt, PyObject file) { PyObject stdout = Py.getSystemState().stdout; if (stdout instanceof PyAttributeDeleted) { @@ -1095,7 +1095,7 @@ } public static PyObject reload(PySystemState o) { - // reinitialize methods + // reinitialize methods o.reload(); return o; } @@ -1155,7 +1155,7 @@ public static PyObject zip() { return new PyList(); } - + public static PyObject zip(PyObject[] argstar) { int itemsize = argstar.length; @@ -1228,7 +1228,7 @@ } class ImportFunction extends PyObject { - + @ExposedGet(name = "__doc__") public PyObject getDoc() { return new PyString("__import__(name, globals={}, locals={}, fromlist=[], level=-1) -> module\n\n" + @@ -1236,7 +1236,7 @@ "they are not modified. The locals are currently unused. The fromlist\n" + "should be a list of names to emulate ``from name import ...'', or an\n" + "empty list to emulate ``import name''.\n" + - "When importing a module from a package, note that __import__('A.B', ...)\n" + + "When importing a module from a package, note that __import__('A.B', ...)\n" + "returns package A when fromlist is empty, but its submodule B when\n" + "fromlist is not empty. Level is used to determine whether to perform \n" + "absolute or relative imports. -1 is the original strategy of attempting\n" + @@ -1272,8 +1272,8 @@ public String toString() { return ""; } - - + + } class SortedFunction extends PyObject { @@ -1283,7 +1283,7 @@ public PyObject getDoc() { return new PyString("sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list"); } - + @Override public PyObject __call__(PyObject args[], String kwds[]) { if (args.length == 0) { @@ -1341,7 +1341,7 @@ } return Py.True; } - + @Override public String toString() { return ""; @@ -1370,9 +1370,9 @@ return Py.True; } } - return Py.False; + return Py.False; } - + @Override public String toString() { return ""; @@ -1388,7 +1388,7 @@ public PyObject getDoc() { return new PyString( "max(iterable[, key=func]) -> value\nmax(a, b, c, ...[, key=func]) -> value\n\n" + - "With a single iterable argument, return its largest item.\n" + + "With a single iterable argument, return its largest item.\n" + "With two or more arguments, return the largest argument."); } @@ -1396,7 +1396,7 @@ public PyObject __call__(PyObject args[], String kwds[]) { int argslen = args.length; PyObject key = null; - + if (args.length - kwds.length == 0) { throw Py.TypeError(" max() expected 1 arguments, got 0"); } @@ -1411,7 +1411,7 @@ throw Py.TypeError(" max() got an unexpected keyword argument"); } } - + if (args.length > 1) { return max(new PyTuple(args), key); } @@ -1419,12 +1419,12 @@ return max(args[0], key); } } - + @Override public String toString() { return ""; } - + private static PyObject max(PyObject o, PyObject key) { PyObject max = null; PyObject maxKey = null; @@ -1463,7 +1463,7 @@ public PyObject __call__(PyObject args[], String kwds[]) { int argslen = args.length; PyObject key = null; - + if (args.length - kwds.length == 0) { throw Py.TypeError(" min() expected 1 arguments, got 0"); } @@ -1478,7 +1478,7 @@ throw Py.TypeError(" min() got an unexpected keyword argument"); } } - + if (args.length > 1) { return min(new PyTuple(args), key); } @@ -1486,12 +1486,12 @@ return min(args[0], key); } } - + @Override public String toString() { return ""; } - + private static PyObject min(PyObject o, PyObject key) { PyObject min = null; PyObject minKey = null; @@ -1534,7 +1534,7 @@ int ndigits = ap.getInt(1, 0); return round(Py.py2double(number), ndigits); } - + private static PyFloat round(double f, int digits) { boolean neg = f < 0; double multiple = Math.pow(10., digits); diff -r 2cb7e7b8f4a8 src/org/python/core/adapter/ClassicPyObjectAdapter.java --- a/src/org/python/core/adapter/ClassicPyObjectAdapter.java Sat Sep 13 18:50:40 2008 -0400 +++ b/src/org/python/core/adapter/ClassicPyObjectAdapter.java Sun Sep 21 13:05:10 2008 -0400 @@ -9,146 +9,146 @@ import org.python.core.PyLong; import org.python.core.PyObject; import org.python.core.PyProxy; -import org.python.core.PyString; import org.python.core.PyType; +import org.python.core.PyUnicode; /** * Implements the algorithm originally used in {@link Py#java2py} to adapt objects. - * + * * Pre-class adapters are added to handle instances of PyObject, PyProxy and * null values. Class adapters are added to handle builtin Java classes: String, * Integer, Float, Double, Byte, Long, Short, Character, Class and Boolean. An * adapter is added to the post-class adapters to handle wrapping arrays * properly. Finally, if all of the added adapters can handle an object, it's * wrapped in a PyJavaInstance. - * + * */ public class ClassicPyObjectAdapter extends ExtensiblePyObjectAdapter { - public ClassicPyObjectAdapter() { - addPreClass(new PyObjectAdapter() { + public ClassicPyObjectAdapter() { + addPreClass(new PyObjectAdapter() { - public PyObject adapt(Object o) { - return (PyObject) o; - } + public PyObject adapt(Object o) { + return (PyObject) o; + } - public boolean canAdapt(Object o) { - return o instanceof PyObject; - } - }); - addPreClass(new PyObjectAdapter() { + public boolean canAdapt(Object o) { + return o instanceof PyObject; + } + }); + addPreClass(new PyObjectAdapter() { - public PyObject adapt(Object o) { - return ((PyProxy) o)._getPyInstance(); - } + public PyObject adapt(Object o) { + return ((PyProxy) o)._getPyInstance(); + } - public boolean canAdapt(Object o) { - return o instanceof PyProxy; - } - }); - addPreClass(new PyObjectAdapter() { + public boolean canAdapt(Object o) { + return o instanceof PyProxy; + } + }); + addPreClass(new PyObjectAdapter() { - public boolean canAdapt(Object o) { - return o == null; - } + public boolean canAdapt(Object o) { + return o == null; + } - public PyObject adapt(Object o) { - return Py.None; - } - }); + public PyObject adapt(Object o) { + return Py.None; + } + }); - add(new ClassAdapter(String.class) { + add(new ClassAdapter(String.class) { - public PyObject adapt(Object o) { - return new PyString((String) o); - } + public PyObject adapt(Object o) { + return new PyUnicode((String) o); + } - }); - add(new ClassAdapter(Character.class) { + }); + add(new ClassAdapter(Character.class) { - public PyObject adapt(Object o) { - return Py.makeCharacter((Character) o); - } + public PyObject adapt(Object o) { + return Py.makeCharacter((Character) o); + } - }); - add(new ClassAdapter(Class.class) { + }); + add(new ClassAdapter(Class.class) { - public PyObject adapt(Object o) { - Class cls = (Class) o; - if (PyObject.class.isAssignableFrom(cls)) { - return PyType.fromClass(cls); - } - return PyJavaClass.lookup(cls); - } + public PyObject adapt(Object o) { + Class cls = (Class) o; + if (PyObject.class.isAssignableFrom(cls)) { + return PyType.fromClass(cls); + } + return PyJavaClass.lookup(cls); + } - }); - add(new NumberToPyFloat(Double.class)); - add(new NumberToPyFloat(Float.class)); - add(new NumberToPyInteger(Integer.class)); - add(new NumberToPyInteger(Byte.class)); - add(new NumberToPyInteger(Short.class)); - add(new ClassAdapter(Long.class) { + }); + add(new NumberToPyFloat(Double.class)); + add(new NumberToPyFloat(Float.class)); + add(new NumberToPyInteger(Integer.class)); + add(new NumberToPyInteger(Byte.class)); + add(new NumberToPyInteger(Short.class)); + add(new ClassAdapter(Long.class) { - public PyObject adapt(Object o) { - return new PyLong(((Number) o).longValue()); - } + public PyObject adapt(Object o) { + return new PyLong(((Number) o).longValue()); + } - }); - add(new ClassAdapter(Boolean.class) { + }); + add(new ClassAdapter(Boolean.class) { - public PyObject adapt(Object o) { - return ((Boolean) o).booleanValue() ? Py.True : Py.False; - } + public PyObject adapt(Object o) { + return ((Boolean) o).booleanValue() ? Py.True : Py.False; + } - }); - addPostClass(new PyObjectAdapter() { + }); + addPostClass(new PyObjectAdapter() { - public PyObject adapt(Object o) { - return new PyArray(o.getClass().getComponentType(), o); - } + public PyObject adapt(Object o) { + return new PyArray(o.getClass().getComponentType(), o); + } - public boolean canAdapt(Object o) { - return o.getClass().isArray(); - } - }); - } + public boolean canAdapt(Object o) { + return o.getClass().isArray(); + } + }); + } - /** - * Always returns true as we just return new PyJavaInstance(o) if the - * adapters added to the superclass can't handle o. - */ - public boolean canAdapt(Object o) { - return true; - } + /** + * Always returns true as we just return new PyJavaInstance(o) if the + * adapters added to the superclass can't handle o. + */ + public boolean canAdapt(Object o) { + return true; + } - public PyObject adapt(Object o) { - PyObject result = super.adapt(o); - if (result != null) { - return result; - } - return new PyJavaInstance(o); - } + public PyObject adapt(Object o) { + PyObject result = super.adapt(o); + if (result != null) { + return result; + } + return new PyJavaInstance(o); + } - private static class NumberToPyInteger extends ClassAdapter { + private static class NumberToPyInteger extends ClassAdapter { - public NumberToPyInteger(Class c) { - super(c); - } + public NumberToPyInteger(Class c) { + super(c); + } - public PyObject adapt(Object o) { - return new PyInteger(((Number) o).intValue()); - } + public PyObject adapt(Object o) { + return new PyInteger(((Number) o).intValue()); + } - } + } - private static class NumberToPyFloat extends ClassAdapter { - public NumberToPyFloat(Class c) { - super(c); - } + private static class NumberToPyFloat extends ClassAdapter { + public NumberToPyFloat(Class c) { + super(c); + } - public PyObject adapt(Object o) { - return new PyFloat(((Number) o).doubleValue()); - } + public PyObject adapt(Object o) { + return new PyFloat(((Number) o).doubleValue()); + } - } + } } diff -r 2cb7e7b8f4a8 src/org/python/core/util/StringUtil.java --- a/src/org/python/core/util/StringUtil.java Sat Sep 13 18:50:40 2008 -0400 +++ b/src/org/python/core/util/StringUtil.java Sun Sep 21 13:05:10 2008 -0400 @@ -5,6 +5,7 @@ import java.nio.ByteBuffer; import org.python.core.Py; +import org.python.core.PyString; /** * String Utility methods. @@ -83,4 +84,8 @@ chars[0] = Character.toLowerCase(c0); return new String(chars); } + + public static PyString asPyString(String string) { + return new PyString(string); + } } diff -r 2cb7e7b8f4a8 src/org/python/modules/binascii.java --- a/src/org/python/modules/binascii.java Sat Sep 13 18:50:40 2008 -0400 +++ b/src/org/python/modules/binascii.java Sun Sep 21 13:05:10 2008 -0400 @@ -272,13 +272,13 @@ * binary data. Lines normally contain 45 (binary) bytes, except for the * last line. Line data may be followed by whitespace. */ - public static String a2b_uu(String ascii_data) { + public static PyString a2b_uu(String ascii_data) { int leftbits = 0; int leftchar = 0; if (ascii_data.length() == 0) - return ""; - + return new PyString(""); + StringBuffer bin_data = new StringBuffer(); char this_ch; @@ -315,7 +315,7 @@ bin_len--; } } - + // Finally, check that if there's anything left on the line // that it's whitespace only. while (ascii_len-- > 0) { @@ -326,12 +326,12 @@ throw new PyException(Error, "Trailing garbage"); } } - + // finally, if we haven't decoded enough stuff, fill it up with zeros for (; idata should be at most 45. */ - public static String b2a_uu(String bin_data) { + public static PyString b2a_uu(String bin_data) { int leftbits = 0; char this_ch; int leftchar = 0; @@ -379,7 +379,7 @@ } ascii_data.append('\n'); // Append a courtesy newline - return ascii_data.toString(); + return new PyString(ascii_data.toString()); } @@ -417,7 +417,7 @@ * Convert a block of base64 data back to binary and return the * binary data. More than one line may be passed at a time. */ - public static String a2b_base64(String ascii_data) { + public static PyString a2b_base64(String ascii_data) { int leftbits = 0; char this_ch; int leftchar = 0; @@ -468,7 +468,7 @@ if (leftbits != 0) { throw new PyException(Error, "Incorrect padding"); } - return bin_data.toString(); + return new PyString(bin_data.toString()); } @@ -482,7 +482,7 @@ * Convert binary data to a line of ASCII characters in base64 coding. * The return value is the converted line, including a newline char. */ - public static String b2a_base64(String bin_data) { + public static PyString b2a_base64(String bin_data) { int leftbits = 0; char this_ch; int leftchar = 0; @@ -516,7 +516,7 @@ } ascii_data.append('\n'); // Append a courtesy newline - return ascii_data.toString(); + return new PyString(ascii_data.toString()); } @@ -625,7 +625,7 @@ * resulting string. The argument should already be RLE-coded, and have a * length divisible by 3 (except possibly the last fragment). */ - public static String b2a_hqx(String bin_data) { + public static PyString b2a_hqx(String bin_data) { int leftbits = 0; char this_ch; int leftchar = 0; @@ -649,7 +649,7 @@ leftchar <<= (6-leftbits); ascii_data.append((char) table_b2a_hqx[leftchar & 0x3f]); } - return ascii_data.toString(); + return new PyString(ascii_data.toString()); } @@ -834,7 +834,7 @@ "This function is also available as \"hexlify()\"." ); - public static String b2a_hex(String argbuf) { + public static PyString b2a_hex(String argbuf) { int arglen = argbuf.length(); StringBuffer retbuf = new StringBuffer(arglen*2); @@ -845,12 +845,12 @@ retbuf.append(hexdigit[(ch >>> 4) & 0xF]); retbuf.append(hexdigit[ch & 0xF]); } - return retbuf.toString(); + return new PyString(retbuf.toString()); } - public static String hexlify(String argbuf) { + public static PyString hexlify(String argbuf) { return b2a_hex(argbuf); } @@ -864,7 +864,7 @@ ); - public static String a2b_hex(String argbuf) { + public static PyString a2b_hex(String argbuf) { int arglen = argbuf.length(); /* XXX What should we do about strings with an odd length? Should @@ -883,19 +883,19 @@ throw Py.TypeError("Non-hexadecimal digit found"); retbuf.append((char) ((top << 4) + bot)); } - return retbuf.toString(); + return new PyString(retbuf.toString()); } - public static String unhexlify(String argbuf) { + public static PyString unhexlify(String argbuf) { return a2b_hex(argbuf); } final private static char[] upper_hexdigit = "0123456789ABCDEF".toCharArray(); - + private static StringBuffer qpEscape(StringBuffer sb, char c) { - sb.append('='); + sb.append('='); sb.append(upper_hexdigit[(c >>> 4) & 0xF]); sb.append(upper_hexdigit[c & 0xF]); return sb; @@ -908,16 +908,16 @@ public static boolean getIntFlagAsBool(ArgParser ap, int index, int dflt, String errMsg) { boolean val; try { - val = ap.getInt(index, dflt) != 0; + val = ap.getInt(index, dflt) != 0; } catch (PyException e) { - if (Py.matchException(e, Py.AttributeError) || Py.matchException(e, Py.ValueError)) - throw Py.TypeError(errMsg); - throw e; + if (Py.matchException(e, Py.AttributeError) || Py.matchException(e, Py.ValueError)) + throw Py.TypeError(errMsg); + throw e; } return val; } - public static String a2b_qp(PyObject[] arg, String[] kws) + public static PyString a2b_qp(PyObject[] arg, String[] kws) { ArgParser ap = new ArgParser("a2b_qp", arg, kws, new String[] {"s", "header"}); String s = ap.getString(0); @@ -925,46 +925,45 @@ boolean header = getIntFlagAsBool(ap, 1, 0, "an integer is required"); if (header) - s = UNDERSCORE.matcher(s).replaceAll(" "); - + s = UNDERSCORE.matcher(s).replaceAll(" "); + for (int i=0, m=s.length(); i= '0' && c <= '9' || c >= 'A' && c <= 'F') && i < m) { + char nc = s.charAt(i++); + if ((nc >= '0' && nc <= '9' || nc >= 'A' && nc <= 'F')) { + sb.append((char)(Character.digit(c, 16) << 4 | Character.digit(nc, 16))); + } else { + sb.append('=').append(c).append(nc); + } + } else if (c != '\n') { + sb.append('=').append(c); + } + } + } else { + sb.append(c); + } } - - return sb.toString(); + return new PyString(sb.toString()); } final private static Pattern RN_TO_N = Pattern.compile("\r\n"); final private static Pattern N_TO_RN = Pattern.compile("(? s;\n" - + "Encode a string using quoted-printable encoding.\n\n" - + "On encoding, when istext is set, newlines are not encoded, and white\n" - + "space at end of lines is. When istext is not set, \r and \n (CR/LF) are\n" - + "both encoded. When quotetabs is set, space and tabs are encoded."); + + "Encode a string using quoted-printable encoding.\n\n" + + "On encoding, when istext is set, newlines are not encoded, and white\n" + + "space at end of lines is. When istext is not set, \r and \n (CR/LF) are\n" + + "both encoded. When quotetabs is set, space and tabs are encoded."); - public static String b2a_qp(PyObject[] arg, String[] kws) { + public static PyString b2a_qp(PyObject[] arg, String[] kws) { ArgParser ap = new ArgParser("b2a_qp", arg, kws, new String[] {"s", "quotetabs", "istext", "header"}); String s = ap.getString(0); boolean quotetabs = getIntFlagAsBool(ap, 1, 0, "an integer is required"); @@ -974,54 +973,54 @@ String lineEnd; int pos = s.indexOf('\n'); if (pos > 0 && s.charAt(pos-1) == '\r') { - lineEnd = "\r\n"; - s = N_TO_RN.matcher(s).replaceAll("\r\n"); + lineEnd = "\r\n"; + s = N_TO_RN.matcher(s).replaceAll("\r\n"); } else { - lineEnd = "\n"; - s = RN_TO_N.matcher(s).replaceAll("\n"); + lineEnd = "\n"; + s = RN_TO_N.matcher(s).replaceAll("\n"); } StringBuffer sb = new StringBuffer(); int count = 0; for (int i=0, m=s.length(); i' <= c && c <= '^') - || ('`' <= c && c <= '~') - || (c == '_' && !header) - || (c == '\n' || c == '\r' && istext)) { - if (count == 75) { - sb.append("=").append(lineEnd); - count = 0; - } - sb.append(c); - count++; - } - else if (!quotetabs && (c == '\t' || c == ' ')) { - if (count >= 72) { - sb.append("=").append(lineEnd); - count = 0; - } - - if (count >= 71) { - count += 3; - qpEscape(sb, c); - } else { - if (c == ' ' && header) - sb.append('_'); - else - sb.append(c); - count += 1; - } - } else { - if (count >= 72) { - sb.append("=").append(lineEnd); - count = 0; - } - count += 3; - qpEscape(sb, c); - } + char c = s.charAt(i); + if (('!' <= c && c <= '<') + || ('>' <= c && c <= '^') + || ('`' <= c && c <= '~') + || (c == '_' && !header) + || (c == '\n' || c == '\r' && istext)) { + if (count == 75) { + sb.append("=").append(lineEnd); + count = 0; + } + sb.append(c); + count++; + } + else if (!quotetabs && (c == '\t' || c == ' ')) { + if (count >= 72) { + sb.append("=").append(lineEnd); + count = 0; + } + + if (count >= 71) { + count += 3; + qpEscape(sb, c); + } else { + if (c == ' ' && header) + sb.append('_'); + else + sb.append(c); + count += 1; + } + } else { + if (count >= 72) { + sb.append("=").append(lineEnd); + count = 0; + } + count += 3; + qpEscape(sb, c); + } } - return sb.toString(); + return new PyString(sb.toString()); } /* diff -r 2cb7e7b8f4a8 src/org/python/modules/cPickle.java --- a/src/org/python/modules/cPickle.java Sat Sep 13 18:50:40 2008 -0400 +++ b/src/org/python/modules/cPickle.java Sun Sep 21 13:05:10 2008 -0400 @@ -614,7 +614,7 @@ * @param object a data object which should be pickled. * @returns a string representing the pickled object. */ - public static String dumps(PyObject object) { + public static PyString dumps(PyObject object) { return dumps(object, 0); } @@ -625,7 +625,7 @@ * @param protocol pickle protocol version (0 - text, 1 - pre-2.3 binary, 2 - 2.3) * @returns a string representing the pickled object. */ - public static String dumps(PyObject object, int protocol) { + public static PyString dumps(PyObject object, int protocol) { cStringIO.StringIO file = cStringIO.StringIO(); dump(object, file, protocol); return file.getvalue(); @@ -705,11 +705,11 @@ public void flush() {} public String read(int len) { - return file.read(len); + return file.read(len).asString(); } public String readlineNoNl() { - return file.readlineNoNl(); + return file.readlineNoNl().asString(); } } @@ -2298,7 +2298,7 @@ value = temp.__getitem__(0); slotstate = temp.__getitem__(1); } - + PyObject dict; if(inst instanceof PyInstance) { dict = ((PyInstance)inst).__dict__; diff -r 2cb7e7b8f4a8 src/org/python/modules/cStringIO.java --- a/src/org/python/modules/cStringIO.java Sat Sep 13 18:50:40 2008 -0400 +++ b/src/org/python/modules/cStringIO.java Sun Sep 21 13:05:10 2008 -0400 @@ -30,7 +30,7 @@ * Create an empty StringIO object * @return a new StringIO object. */ - + // would be nicer if we directly imported from os, but crazy to do so // since in python code itself private class os { @@ -41,7 +41,7 @@ public static PyType InputType = PyType.fromClass(StringIO.class); public static PyType OutputType = PyType.fromClass(StringIO.class); - + public static StringIO StringIO() { return new StringIO(); } @@ -81,7 +81,7 @@ if (closed) throw Py.ValueError("I/O operation on closed file"); } - + private int _convert_to_int(long val) { if (val > Integer.MAX_VALUE) { throw Py.OverflowError("long int too large to convert to int"); @@ -99,10 +99,10 @@ public PyObject __iternext__() { _complain_ifclosed(); - String r = readline(); - if(r.equals("")) + PyString r = readline(); + if (r.__len__() == 0) return null; - return new PyString(r); + return r; } /** @@ -176,7 +176,7 @@ * An empty string is returned when EOF is encountered immediately. * @returns A string containing the data. */ - public String read() { + public PyString read() { return read(-1); } @@ -189,8 +189,8 @@ * @param size the number of characters to read. * @returns A string containing the data read. */ - - public synchronized String read(long size) { + + public synchronized PyString read(long size) { _complain_ifclosed(); int size_int = _convert_to_int(size); int len = buf.length(); @@ -204,9 +204,8 @@ substr = buf.substring(pos, newpos); pos = newpos; } - return substr; + return new PyString(substr); } - /** * Read one entire line from the file. A trailing newline character @@ -215,7 +214,7 @@ * An empty string is returned when EOF is hit immediately. * @returns data from the file up to and including the newline. */ - public String readline() { + public PyString readline() { return readline(-1); } @@ -229,12 +228,12 @@ * returned. * @returns data from the file up to and including the newline. */ - public synchronized String readline(long size) { + public synchronized PyString readline(long size) { _complain_ifclosed(); int size_int = _convert_to_int(size); int len = buf.length(); if (pos == len) { - return ""; + return new PyString(""); } int i = buf.indexOf("\n", pos); int newpos = (i < 0) ? len : i + 1; @@ -243,7 +242,7 @@ } String r = buf.substring(pos, newpos); pos = newpos; - return r; + return new PyString(r); } @@ -251,7 +250,7 @@ * Read and return a line without the trailing newline. * Usind by cPickle as an optimization. */ - public synchronized String readlineNoNl() { + public synchronized PyString readlineNoNl() { _complain_ifclosed(); int len = buf.length(); int i = buf.indexOf("\n", pos); @@ -260,7 +259,7 @@ pos = newpos; if (pos < len) // Skip the newline pos++; - return r; + return new PyString(r); } @@ -286,10 +285,10 @@ int sizehint_int = (int)sizehint; int total = 0; PyList lines = new PyList(); - String line = readline(); - while (line.length() > 0) { - lines.append(new PyString(line)); - total += line.length(); + PyString line = readline(); + while (line.__len__() > 0) { + lines.append(line); + total += line.__len__(); if (0 < sizehint_int && sizehint_int <= total) break; line = readline(); @@ -367,12 +366,12 @@ * before the StringIO object's close() method is called. * @return the contents of the StringIO. */ - public synchronized String getvalue() { - return buf.toString(); + public synchronized PyString getvalue() { + return new PyString(buf.toString()); } } - + private static String[] strings = new String[256]; static String getString(char ch) { if (ch > 255) { diff -r 2cb7e7b8f4a8 src/org/python/modules/struct.java --- a/src/org/python/modules/struct.java Sat Sep 13 18:50:40 2008 -0400 +++ b/src/org/python/modules/struct.java Sun Sep 21 13:05:10 2008 -0400 @@ -965,7 +965,7 @@ * to the given format. The arguments must match the * values required by the format exactly. */ - static public String pack(PyObject[] args) { + static public PyString pack(PyObject[] args) { if (args.length < 1) Py.TypeError("illegal argument type for built-in operation"); @@ -1005,7 +1005,7 @@ if (i < args.length) throw StructError("too many arguments for pack format"); - return res.toString(); + return new PyString(res.toString()); } diff -r 2cb7e7b8f4a8 src/org/python/modules/time/Time.java --- a/src/org/python/modules/time/Time.java Sat Sep 13 18:50:40 2008 -0400 +++ b/src/org/python/modules/time/Time.java Sun Sep 21 13:05:10 2008 -0400 @@ -308,11 +308,11 @@ return _timefields(parseTimeDoubleArg(arg), TimeZone.getTimeZone("GMT")); } - public static String ctime() { + public static PyString ctime() { return ctime(Py.None); } - public static String ctime(PyObject secs) { + public static PyString ctime(PyObject secs) { return asctime(localtime(secs)); } @@ -405,11 +405,11 @@ return yearstr.substring(yearstr.length()-2, yearstr.length()); } - public static String asctime() { + public static PyString asctime() { return asctime(localtime()); } - public static String asctime(PyTuple tup) { + public static PyString asctime(PyTuple tup) { StringBuffer buf = new StringBuffer(25); buf.append(enshortdays[item(tup, 6)]).append(' '); buf.append(enshortmonths[item(tup, 1)]).append(' '); @@ -421,7 +421,7 @@ buf.append(_twodigit(item(tup, 3))).append(':'); buf.append(_twodigit(item(tup, 4))).append(':'); buf.append(_twodigit(item(tup, 5))).append(' '); - return buf.append(item(tup, 0)).toString(); + return new PyString(buf.append(item(tup, 0)).toString()); } public static String locale_asctime(PyTuple tup) { @@ -454,11 +454,11 @@ // writable but ignore its value? public static final int accept2dyear = 0; - public static String strftime(String format) { + public static PyString strftime(String format) { return strftime(format, localtime()); } - public static String strftime(String format, PyTuple tup) { + public static PyString strftime(String format, PyTuple tup) { checkLocale(); // Immediately validate the tuple @@ -651,7 +651,20 @@ lastc = i+1; i++; } - return s; + // FIXME: This have problems with localized data: + // $ LANG=es_ES.UTF-8 jythont -c "import time; print time.strftime('%A')" + // s?bado + // + // On the other hand, returning unicode would break some doctests + // and will give problems when the return value of strftime is + // mixed with other strings and then the final result is stored + // on places which only support str and not unicode (such as + // os.environ) + // + // TODO: Check how CPython deals with this problem. On Linux it doesn't + // seem to localize the names of the days, but on other platforms + // I think it does. + return new PyString(s); }