From: <pj...@us...> - 2008-08-06 02:48:50
|
Revision: 5090 http://jython.svn.sourceforge.net/jython/?rev=5090&view=rev Author: pjenvey Date: 2008-08-06 02:48:46 +0000 (Wed, 06 Aug 2008) Log Message: ----------- PEP 305 (csv module) patches from Paul Drummond, Dave Kuhlman (thanks!) fixes #1650802 Modified Paths: -------------- branches/asm/CPythonLib.includes branches/asm/CoreExposed.includes branches/asm/src/org/python/modules/Setup.java branches/asm/src/templates/mappings Added Paths: ----------- branches/asm/src/org/python/modules/_csv/ branches/asm/src/org/python/modules/_csv/PyDialect.java branches/asm/src/org/python/modules/_csv/PyDialectDerived.java branches/asm/src/org/python/modules/_csv/PyReader.java branches/asm/src/org/python/modules/_csv/PyWriter.java branches/asm/src/org/python/modules/_csv/QuoteStyle.java branches/asm/src/org/python/modules/_csv/_csv.java branches/asm/src/templates/dialect.derived Modified: branches/asm/CPythonLib.includes =================================================================== --- branches/asm/CPythonLib.includes 2008-08-06 02:27:45 UTC (rev 5089) +++ branches/asm/CPythonLib.includes 2008-08-06 02:48:46 UTC (rev 5090) @@ -43,6 +43,7 @@ copy.py copy_reg.py Cookie.py +csv.py difflib.py dircache.py dircmp.py Modified: branches/asm/CoreExposed.includes =================================================================== --- branches/asm/CoreExposed.includes 2008-08-06 02:27:45 UTC (rev 5089) +++ branches/asm/CoreExposed.includes 2008-08-06 02:48:46 UTC (rev 5090) @@ -36,6 +36,9 @@ org/python/core/PyUnicode.class org/python/core/PyXRange.class org/python/modules/_codecs$EncodingMap.class +org/python/modules/_csv/PyDialect.class +org/python/modules/_csv/PyReader.class +org/python/modules/_csv/PyWriter.class org/python/modules/_functools/PyPartial.class org/python/modules/_weakref/CallableProxyType.class org/python/modules/_weakref/ReferenceType.class Modified: branches/asm/src/org/python/modules/Setup.java =================================================================== --- branches/asm/src/org/python/modules/Setup.java 2008-08-06 02:27:45 UTC (rev 5089) +++ branches/asm/src/org/python/modules/Setup.java 2008-08-06 02:48:46 UTC (rev 5090) @@ -53,6 +53,7 @@ "collections:org.python.modules.collections.Collections", "gc", "_hashlib", - "_functools:org.python.modules._functools._functools" + "_functools:org.python.modules._functools._functools", + "_csv:org.python.modules._csv._csv" }; } Added: branches/asm/src/org/python/modules/_csv/PyDialect.java =================================================================== --- branches/asm/src/org/python/modules/_csv/PyDialect.java (rev 0) +++ branches/asm/src/org/python/modules/_csv/PyDialect.java 2008-08-06 02:48:46 UTC (rev 5090) @@ -0,0 +1,217 @@ +/* Copyright (c) Jython Developers */ +package org.python.modules._csv; + +import org.python.core.ArgParser; +import org.python.core.Py; +import org.python.core.PyBaseString; +import org.python.core.PyInteger; +import org.python.core.PyNewWrapper; +import org.python.core.PyObject; +import org.python.core.PyString; +import org.python.core.PyType; +import org.python.expose.ExposedDelete; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedNew; +import org.python.expose.ExposedSet; +import org.python.expose.ExposedType; + +/** + * The Python CSV Dialect type. + */ +@ExposedType(name = "_csv.Dialect") +public class PyDialect extends PyObject { + + public static final PyType TYPE = PyType.fromClass(PyDialect.class); + + public PyString __doc__ = Py.newString( + "CSV dialect\n" + + "\n" + + "The Dialect type records CSV parsing and generation options.\n"); + + /** Whether " is represented by "". */ + @ExposedGet + public boolean doublequote; + + /** Field separator. */ + @ExposedGet + public char delimiter; + + /** Quote character. */ + public char quotechar; + + /** Escape character. */ + public char escapechar; + + /** Ignore spaces following delimiter? */ + @ExposedGet + public boolean skipinitialspace; + + /** String to write between records. */ + @ExposedGet + public String lineterminator; + + /** Style of quoting to write. */ + public QuoteStyle quoting; + + /** Whether an exception is raised on bad CSV. */ + @ExposedGet + public boolean strict; + + public PyDialect() { + super(TYPE); + } + + public PyDialect(PyType subType) { + super(subType); + } + + @ExposedNew + final static PyObject Dialect___new__(PyNewWrapper new_, boolean init, PyType subtype, + PyObject[] args, String[] keywords) { + ArgParser ap = new ArgParser("__new__", args, keywords, + new String[] {"dialect", "delimiter", "doublequote", + "escapechar", "lineterminator", "quotechar", + "quoting", "skipinitialspace", "strict"}); + PyObject dialect = ap.getPyObject(0, null); + PyObject delimiter = ap.getPyObject(1, null); + PyObject doublequote = ap.getPyObject(2, null); + PyObject escapechar = ap.getPyObject(3, null); + PyObject lineterminator = ap.getPyObject(4, null); + PyObject quotechar = ap.getPyObject(5, null); + PyObject quoting = ap.getPyObject(6, null); + PyObject skipinitialspace = ap.getPyObject(7, null); + PyObject strict = ap.getPyObject(8, null); + + if (dialect instanceof PyString) { + dialect = _csv.get_dialect_from_registry(dialect); + } + + // Can we reuse this instance? + if (dialect instanceof PyDialect && delimiter == null && doublequote == null + && escapechar == null && lineterminator == null && quotechar == null && quoting == null + && skipinitialspace == null && strict == null) { + return dialect; + } + + if (dialect != null) { + delimiter = delimiter != null ? delimiter : dialect.__findattr__("delimiter"); + doublequote = doublequote != null + ? doublequote : dialect.__findattr__("doublequote"); + escapechar = escapechar != null ? escapechar : dialect.__findattr__("escapechar"); + lineterminator = lineterminator != null + ? lineterminator : dialect.__findattr__("lineterminator"); + quotechar = quotechar != null ? quotechar : dialect.__findattr__("quotechar"); + quoting = quoting != null ? quoting : dialect.__findattr__("quoting"); + skipinitialspace = skipinitialspace != null + ? skipinitialspace : dialect.__findattr__("skipinitialspace"); + strict = strict != null ? strict : dialect.__findattr__("strict"); + } + + PyDialect self; + if (new_.for_type == subtype) { + self = new PyDialect(); + } else { + self = new PyDialectDerived(subtype); + } + + // check types and convert to Java values + int quotingOrdinal; + self.delimiter = toChar("delimiter", delimiter, ','); + self.doublequote = toBool("doublequote", doublequote, true); + self.escapechar = toChar("escapechar", escapechar, '\0'); + self.lineterminator = toStr("lineterminator", lineterminator, "\r\n"); + self.quotechar = toChar("quotechar", quotechar, '"'); + quotingOrdinal = toInt("quoting", quoting, QuoteStyle.QUOTE_MINIMAL.ordinal()); + self.skipinitialspace = toBool("skipinitialspace", skipinitialspace, false); + self.strict = toBool("strict", strict, false); + + // validate options + self.quoting = QuoteStyle.fromOrdinal(quotingOrdinal); + if (self.quoting == null) { + throw Py.TypeError("bad \"quoting\" value"); + } + if (self.delimiter == '\0') { + throw Py.TypeError("delimiter must be set"); + } + if (quotechar == Py.None && quoting == null) { + self.quoting = QuoteStyle.QUOTE_NONE; + } + if (self.quoting != QuoteStyle.QUOTE_NONE && self.quotechar == '\0') { + throw Py.TypeError("quotechar must be set if quoting enabled"); + } + if (self.lineterminator == null) { + throw Py.TypeError("lineterminator must be set"); + } + + return self; + } + + private static boolean toBool(String name, PyObject src, boolean dflt) { + return src == null ? dflt : src.__nonzero__(); + } + + private static char toChar(String name, PyObject src, char dflt) { + if (src == null) { + return dflt; + } + boolean isStr = Py.isInstance(src, PyString.TYPE); + if (src == Py.None || isStr && src.__len__() == 0) { + return '\0'; + } else if (!isStr || src.__len__() != 1) { + throw Py.TypeError(String.format("\"%s\" must be an 1-character string", name)); + } + return src.toString().charAt(0); + } + + private static int toInt(String name, PyObject src, int dflt) { + if (src == null) { + return dflt; + } + if (!(src instanceof PyInteger)) { + throw Py.TypeError(String.format("\"%s\" must be an integer", name)); + } + return src.asInt(); + } + + private static String toStr(String name, PyObject src, String dflt) { + if (src == null) { + return dflt; + } + if (src == Py.None) { + return null; + } + if (!(src instanceof PyBaseString)) { + throw Py.TypeError(String.format("\"%s\" must be an string", name)); + } + return src.toString(); + } + + @ExposedGet(name = "escapechar") + public PyObject getEscapechar() { + return escapechar == '\0' ? Py.None : Py.newString(escapechar); + } + + @ExposedGet(name = "quotechar") + public PyObject getQuotechar() { + return quotechar == '\0' ? Py.None : Py.newString(quotechar); + } + + @ExposedGet(name = "quoting") + public PyObject getQuoting() { + return Py.newInteger(quoting.ordinal()); + } + + // XXX: setQuoting and delQuoting are to make test_csv pass (currently we incorrectly + // throw TypeErrors for get/set AttributeError failures) + @ExposedSet(name = "quoting") + public void setQuoting(PyObject obj) { + throw Py.AttributeError(String.format("attribute '%s' of '%s' objects is not writable", + "quoting", getType().fastGetName())); + } + + @ExposedDelete(name = "quoting") + public void delQuoting() { + throw Py.AttributeError(String.format("attribute '%s' of '%s' objects is not writable", + "quoting", getType().fastGetName())); + } +} Added: branches/asm/src/org/python/modules/_csv/PyDialectDerived.java =================================================================== --- branches/asm/src/org/python/modules/_csv/PyDialectDerived.java (rev 0) +++ branches/asm/src/org/python/modules/_csv/PyDialectDerived.java 2008-08-06 02:48:46 UTC (rev 5090) @@ -0,0 +1,1104 @@ +/* Generated file, do not modify. See jython/src/templates/gderived.py. */ +package org.python.modules._csv; + +import org.python.core.*; + +public class PyDialectDerived extends PyDialect implements Slotted { + + public PyObject getSlot(int index) { + return slots[index]; + } + + public void setSlot(int index,PyObject value) { + slots[index]=value; + } + + private PyObject[]slots; + + public PyDialectDerived(PyType subtype) { + super(subtype); + slots=new PyObject[subtype.getNumSlots()]; + } + + public PyString __str__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__str__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__str__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__str__(); + } + + public PyString __repr__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__repr__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__repr__(); + } + + public PyString __hex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__hex__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__hex__(); + } + + public PyString __oct__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__oct__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyString) + return(PyString)res; + throw Py.TypeError("__oct__"+" returned non-"+"string"+" (type "+res.getType().fastGetName()+")"); + } + return super.__oct__(); + } + + public PyFloat __float__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__float__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyFloat) + return(PyFloat)res; + throw Py.TypeError("__float__"+" returned non-"+"float"+" (type "+res.getType().fastGetName()+")"); + } + return super.__float__(); + } + + public PyComplex __complex__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__complex__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyComplex) + return(PyComplex)res; + throw Py.TypeError("__complex__"+" returned non-"+"complex"+" (type "+res.getType().fastGetName()+")"); + } + return super.__complex__(); + } + + public PyObject __pos__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pos__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__pos__(); + } + + public PyObject __neg__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__neg__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__neg__(); + } + + public PyObject __abs__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__abs__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__abs__(); + } + + public PyObject __invert__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__invert__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__invert__(); + } + + public PyObject __reduce__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__reduce__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + return super.__reduce__(); + } + + public PyObject __add__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__add__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__add__(other); + } + + public PyObject __radd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__radd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__radd__(other); + } + + public PyObject __sub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__sub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__sub__(other); + } + + public PyObject __rsub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rsub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rsub__(other); + } + + public PyObject __mul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mul__(other); + } + + public PyObject __rmul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmul__(other); + } + + public PyObject __div__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__div__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__div__(other); + } + + public PyObject __rdiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdiv__(other); + } + + public PyObject __floordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__floordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__floordiv__(other); + } + + public PyObject __rfloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rfloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rfloordiv__(other); + } + + public PyObject __truediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__truediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__truediv__(other); + } + + public PyObject __rtruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rtruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rtruediv__(other); + } + + public PyObject __mod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__mod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__mod__(other); + } + + public PyObject __rmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rmod__(other); + } + + public PyObject __divmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__divmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__divmod__(other); + } + + public PyObject __rdivmod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rdivmod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rdivmod__(other); + } + + public PyObject __rpow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rpow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rpow__(other); + } + + public PyObject __lshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lshift__(other); + } + + public PyObject __rlshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rlshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rlshift__(other); + } + + public PyObject __rshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rshift__(other); + } + + public PyObject __rrshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rrshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rrshift__(other); + } + + public PyObject __and__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__and__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__and__(other); + } + + public PyObject __rand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rand__(other); + } + + public PyObject __or__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__or__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__or__(other); + } + + public PyObject __ror__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ror__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ror__(other); + } + + public PyObject __xor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__xor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__xor__(other); + } + + public PyObject __rxor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__rxor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__rxor__(other); + } + + public PyObject __lt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__lt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__lt__(other); + } + + public PyObject __le__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__le__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__le__(other); + } + + public PyObject __gt__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__gt__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__gt__(other); + } + + public PyObject __ge__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ge__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ge__(other); + } + + public PyObject __eq__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__eq__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__eq__(other); + } + + public PyObject __ne__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ne__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ne__(other); + } + + public PyObject __iadd__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iadd__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iadd__(other); + } + + public PyObject __isub__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__isub__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__isub__(other); + } + + public PyObject __imul__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imul__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imul__(other); + } + + public PyObject __idiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__idiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__idiv__(other); + } + + public PyObject __ifloordiv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ifloordiv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ifloordiv__(other); + } + + public PyObject __itruediv__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__itruediv__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__itruediv__(other); + } + + public PyObject __imod__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__imod__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__imod__(other); + } + + public PyObject __ipow__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ipow__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ipow__(other); + } + + public PyObject __ilshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ilshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ilshift__(other); + } + + public PyObject __irshift__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__irshift__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__irshift__(other); + } + + public PyObject __iand__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iand__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__iand__(other); + } + + public PyObject __ior__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ior__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ior__(other); + } + + public PyObject __ixor__(PyObject other) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__ixor__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__ixor__(other); + } + + public PyObject __int__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__int__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) + return(PyObject)res; + throw Py.TypeError("__int__"+" should return an integer"); + } + return super.__int__(); + } + + public PyObject __long__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__long__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyLong||res instanceof PyInteger) + return res; + throw Py.TypeError("__long__"+" returned non-"+"long"+" (type "+res.getType().fastGetName()+")"); + } + return super.__long__(); + } + + public int hashCode() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__hash__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) { + return((PyInteger)res).getValue(); + } else + if (res instanceof PyLong) { + return((PyLong)res).getValue().intValue(); + } + throw Py.TypeError("__hash__ should return a int"); + } + if (self_type.lookup("__eq__")!=null||self_type.lookup("__cmp__")!=null) { + throw Py.TypeError("unhashable type"); + } + return super.hashCode(); + } + + public PyUnicode __unicode__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__unicode__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyUnicode) + return(PyUnicode)res; + if (res instanceof PyString) + return new PyUnicode((PyString)res); + throw Py.TypeError("__unicode__"+" should return a "+"unicode"); + } + return super.__unicode__(); + } + + public int __cmp__(PyObject other) { + PyType self_type=getType(); + PyType[]where_type=new PyType[1]; + PyObject impl=self_type.lookup_where("__cmp__",where_type); + // Full Compatibility with CPython __cmp__: + // If the derived type don't override __cmp__, the + // *internal* super().__cmp__ should be called, not the + // exposed one. The difference is that the exposed __cmp__ + // throws a TypeError if the argument is an instance of the same type. + if (impl==null||where_type[0]==TYPE||Py.isSubClass(TYPE,where_type[0])) { + return super.__cmp__(other); + } + PyObject res=impl.__get__(this,self_type).__call__(other); + if (res instanceof PyInteger) { + int v=((PyInteger)res).getValue(); + return v<0?-1:v>0?1:0; + } + throw Py.TypeError("__cmp__ should return a int"); + } + + public boolean __nonzero__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__nonzero__"); + if (impl==null) { + impl=self_type.lookup("__len__"); + if (impl==null) + return super.__nonzero__(); + } + return impl.__get__(this,self_type).__call__().__nonzero__(); + } + + public boolean __contains__(PyObject o) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__contains__"); + if (impl==null) + return super.__contains__(o); + return impl.__get__(this,self_type).__call__(o).__nonzero__(); + } + + public int __len__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__len__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger) + return((PyInteger)res).getValue(); + throw Py.TypeError("__len__ should return a int"); + } + return super.__len__(); + } + + public PyObject __iter__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__iter__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(); + impl=self_type.lookup("__getitem__"); + if (impl==null) + return super.__iter__(); + return new PySequenceIter(this); + } + + public PyObject __iternext__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("next"); + if (impl!=null) { + try { + return impl.__get__(this,self_type).__call__(); + } catch (PyException exc) { + if (Py.matchException(exc,Py.StopIteration)) + return null; + throw exc; + } + } + return super.__iternext__(); // ??? + } + + public PyObject __finditem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(key); + } catch (PyException exc) { + if (Py.matchException(exc,Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __finditem__(int key) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + try { + return impl.__get__(this,self_type).__call__(new PyInteger(key)); + } catch (PyException exc) { + if (Py.matchException(exc,Py.LookupError)) + return null; + throw exc; + } + return super.__finditem__(key); + } + + public PyObject __getitem__(PyObject key) { + // Same as __finditem__, without swallowing LookupErrors. This allows + // __getitem__ implementations written in Python to raise custom + // exceptions (such as subclasses of KeyError). + // + // We are forced to duplicate the code, instead of defining __finditem__ + // in terms of __getitem__. That's because PyObject defines __getitem__ + // in terms of __finditem__. Therefore, we would end with an infinite + // loop when self_type.lookup("__getitem__") returns null: + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> __getitem__ + // + // By duplicating the (short) lookup and call code, we are safe, because + // the call chains will be: + // + // __finditem__ -> super.__finditem__ + // + // __getitem__ -> super.__getitem__ -> __finditem__ -> super.__finditem__ + + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getitem__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(key); + return super.__getitem__(key); + } + + public void __setitem__(PyObject key,PyObject value) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key,value); + return; + } + super.__setitem__(key,value); + } + + public PyObject __getslice__(PyObject start,PyObject stop,PyObject step) { // ??? + if (step!=null) { + return __getitem__(new PySlice(start,stop,step)); + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__getslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + return impl.__get__(this,self_type).__call__(indices[0],indices[1]); + } + return super.__getslice__(start,stop,step); + } + + public void __setslice__(PyObject start,PyObject stop,PyObject step,PyObject value) { + if (step!=null) { + __setitem__(new PySlice(start,stop,step),value); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1],value); + return; + } + super.__setslice__(start,stop,step,value); + } + + public void __delslice__(PyObject start,PyObject stop,PyObject step) { + if (step!=null) { + __delitem__(new PySlice(start,stop,step)); + return; + } + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delslice__"); + if (impl!=null) { + PyObject[]indices=PySlice.indices2(this,start,stop); + impl.__get__(this,self_type).__call__(indices[0],indices[1]); + return; + } + super.__delslice__(start,stop,step); + } + + public void __delitem__(PyObject key) { // ??? + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delitem__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(key); + return; + } + super.__delitem__(key); + } + + public PyObject __call__(PyObject args[],String keywords[]) { + ThreadState ts=Py.getThreadState(); + if (ts.recursion_depth++>ts.systemState.getrecursionlimit()) + throw Py.RuntimeError("maximum __call__ recursion depth exceeded"); + try { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__call__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(args,keywords); + return super.__call__(args,keywords); + } finally { + --ts.recursion_depth; + } + } + + public PyObject __findattr__(String name) { + PyType self_type=getType(); + PyObject getattribute=self_type.lookup("__getattribute__"); + PyString py_name=null; + try { + if (getattribute!=null) { + return getattribute.__get__(this,self_type).__call__(py_name=PyString.fromInterned(name)); + } else { + return super.__findattr__(name); + } + } catch (PyException e) { + if (Py.matchException(e,Py.AttributeError)) { + PyObject getattr=self_type.lookup("__getattr__"); + if (getattr!=null) + try { + return getattr.__get__(this,self_type).__call__(py_name!=null?py_name:PyString.fromInterned(name)); + } catch (PyException e1) { + if (!Py.matchException(e1,Py.AttributeError)) + throw e1; + } + return null; + } + throw e; + } + } + + public void __setattr__(String name,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__setattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name),value); + return; + } + super.__setattr__(name,value); + } + + public void __delattr__(String name) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delattr__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(PyString.fromInterned(name)); + return; + } + super.__delattr__(name); + } + + public PyObject __get__(PyObject obj,PyObject type) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__get__"); + if (impl!=null) { + if (obj==null) + obj=Py.None; + if (type==null) + type=Py.None; + return impl.__get__(this,self_type).__call__(obj,type); + } + return super.__get__(obj,type); + } + + public void __set__(PyObject obj,PyObject value) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__set__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj,value); + return; + } + super.__set__(obj,value); + } + + public void __delete__(PyObject obj) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__delete__"); + if (impl!=null) { + impl.__get__(this,self_type).__call__(obj); + return; + } + super.__delete__(obj); + } + + public PyObject __pow__(PyObject other,PyObject modulo) { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__pow__"); + if (impl!=null) { + PyObject res; + if (modulo==null) { + res=impl.__get__(this,self_type).__call__(other); + } else { + res=impl.__get__(this,self_type).__call__(other,modulo); + } + if (res==Py.NotImplemented) + return null; + return res; + } + return super.__pow__(other,modulo); + } + + public void dispatch__init__(PyType type,PyObject[]args,String[]keywords) { + PyType self_type=getType(); + if (self_type.isSubType(type)) { + PyObject impl=self_type.lookup("__init__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(args,keywords); + if (res!=Py.None) { + throw Py.TypeError(String.format("__init__() should return None, not '%.200s'",res.getType().fastGetName())); + } + } + } + } + + public PyObject __index__() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__index__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (res instanceof PyInteger||res instanceof PyLong) { + return res; + } + throw Py.TypeError(String.format("__index__ returned non-(int,long) (type %s)",res.getType().fastGetName())); + } + return super.__index__(); + } + + public Object __tojava__(Class c) { + // If we are not being asked by the "default" conversion to java, then + // we can provide this as the result, as long as it is a instance of the + // specified class. Without this, derived.__tojava__(PyObject.class) + // would broke. (And that's not pure speculation: PyReflectedFunction's + // ReflectedArgs asks for things like that). + if ((c!=Object.class)&&(c.isInstance(this))) { + return this; + } + // Otherwise, we call the derived __tojava__, if it exists: + PyType self_type=getType(); + PyObject impl=self_type.lookup("__tojava__"); + if (impl!=null) + return impl.__get__(this,self_type).__call__(Py.java2py(c)).__tojava__(Object.class); + return super.__tojava__(c); + } + + public String toString() { + PyType self_type=getType(); + PyObject impl=self_type.lookup("__repr__"); + if (impl!=null) { + PyObject res=impl.__get__(this,self_type).__call__(); + if (!(res instanceof PyString)) + throw Py.TypeError("__repr__ returned non-string (type "+res.getType().fastGetName()+")"); + return((PyString)res).toString(); + } + return super.toString(); + } + +} Added: branches/asm/src/org/python/modules/_csv/PyReader.java =================================================================== --- branches/asm/src/org/python/modules/_csv/PyReader.java (rev 0) +++ branches/asm/src/org/python/modules/_csv/PyReader.java 2008-08-06 02:48:46 UTC (rev 5090) @@ -0,0 +1,271 @@ +/* Copyright (c) Jython Developers */ +package org.python.modules._csv; + +import org.python.core.Py; +import org.python.core.PyIterator; +import org.python.core.PyList; +import org.python.core.PyObject; +import org.python.core.PyString; +import org.python.core.PyType; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedType; + +/** + * CSV file reader. + * + * Analogous to CPython's _csv.c::ReaderObj struct. + */ +@ExposedType(name = "_csv.reader") +public class PyReader extends PyIterator { + + public static final PyType TYPE = PyType.fromClass(PyReader.class); + + public PyString __doc__ = Py.newString( + "CSV reader\n" + + "\n" + + "Reader objects are responsible for reading and parsing tabular data\n" + + "in CSV format.\n"); + + /** Parsing Dialect. */ + @ExposedGet + public PyDialect dialect; + + /** The current line number. */ + @ExposedGet + public int line_num = 0; + + /** The underlying input iterator. */ + private PyObject input_iter; + + /** Current CSV parse state. */ + private ParserState state = ParserState.START_RECORD; + + /** Field list for current record. */ + private PyList fields = new PyList(); + + /** Current field builder in here. */ + private StringBuffer field = new StringBuffer(INITIAL_BUILDER_CAPACITY); + + /** Whether the field should be treated as numeric. */ + private boolean numeric_field = false; + + /** Initial capacity of the field StringBuilder. */ + private static final int INITIAL_BUILDER_CAPACITY = 4096; + + public PyReader(PyObject input_iter, PyDialect dialect) { + this.input_iter = input_iter; + this.dialect = dialect; + } + + public PyObject __iternext__() { + PyObject lineobj; + PyObject fields; + String line; + char c; + int linelen; + + parse_reset(); + do { + lineobj = input_iter.__iternext__(); + if (lineobj == null) { + // End of input OR exception + if (field.length() != 0) { + throw _csv.Error("newline inside string"); + } else { + return null; + } + } + + line_num++; + line = lineobj.toString(); + linelen = line.length(); + + for (int i = 0; i < linelen; i++) { + c = line.charAt(i); + if (c == '\0') { + throw _csv.Error("line contains NULL byte"); + } + parse_process_char(c); + } + parse_process_char('\0'); + } while (state != ParserState.START_RECORD); + + fields = this.fields; + this.fields = new PyList(); + + return fields; + } + + private void parse_process_char(char c) { + switch (state) { + case START_RECORD: + // start of record + if (c == '\0') { + // empty line - return [] + break; + } else if (c == '\n' || c == '\r') { + state = ParserState.EAT_CRNL; + break; + } + // normal character - handle as START_FIELD + state = ParserState.START_FIELD; + // *** fallthru *** + case START_FIELD: + // expecting field + if (c == '\n' || c == '\r' || c == '\0') { + // save empty field - return [fields] + parse_save_field(); + state = c == '\0' ? ParserState.START_RECORD : ParserState.EAT_CRNL; + } else if (c == dialect.quotechar && dialect.quoting != QuoteStyle.QUOTE_NONE) { + // start quoted field + state = ParserState.IN_QUOTED_FIELD; + } else if (c == dialect.escapechar) { + // possible escaped character + state = ParserState.ESCAPED_CHAR; + } else if (c == ' ' && dialect.skipinitialspace) { + // ignore space at start of field + ; + } else if (c == dialect.delimiter) { + // save empty field + parse_save_field(); + } else { + // begin new unquoted field + if (dialect.quoting == QuoteStyle.QUOTE_NONNUMERIC) { + numeric_field = true; + } + parse_add_char(c); + state = ParserState.IN_FIELD; + } + break; + + case ESCAPED_CHAR: + if (c == '\0') { + c = '\n'; + } + parse_add_char(c); + state = ParserState.IN_FIELD; + break; + + case IN_FIELD: + // in unquoted field + if (c == '\n' || c == '\r' || c == '\0') { + // end of line - return [fields] + parse_save_field(); + state = c == '\0' ? ParserState.START_RECORD : ParserState.EAT_CRNL; + } else if (c == dialect.escapechar) { + // possible escaped character + state = ParserState.ESCAPED_CHAR; + } else if (c == dialect.delimiter) { + // save field - wait for new field + parse_save_field(); + state = ParserState.START_FIELD; + } else { + // normal character - save in field + parse_add_char(c); + } + break; + + case IN_QUOTED_FIELD: + // in quoted field + if (c == '\0') { + ; + } else if (c == dialect.escapechar) { + // Possible escape character + state = ParserState.ESCAPE_IN_QUOTED_FIELD; + } else if (c == dialect.quotechar && dialect.quoting != QuoteStyle.QUOTE_NONE) { + if (dialect.doublequote) { + // doublequote; " represented by "" + state = ParserState.QUOTE_IN_QUOTED_FIELD; + } else { + // end of quote part of field + state = ParserState.IN_FIELD; + } + } else { + // normal character - save in field + parse_add_char(c); + } + break; + + case ESCAPE_IN_QUOTED_FIELD: + if (c == '\0') { + c = '\n'; + } + parse_add_char(c); + state = ParserState.IN_QUOTED_FIELD; + break; + + case QUOTE_IN_QUOTED_FIELD: + // doublequote - seen a quote in an quoted field + if (dialect.quoting != QuoteStyle.QUOTE_NONE && c == dialect.quotechar) { + // save "" as " + parse_add_char(c); + state = ParserState.IN_QUOTED_FIELD; + } else if (c == dialect.delimiter) { + // save field - wait for new field + parse_save_field(); + state = ParserState.START_FIELD; + } else if (c == '\n' || c == '\r' || c == '\0') { + // end of line - return [fields] + parse_save_field(); + state = c == '\0' ? ParserState.START_RECORD : ParserState.EAT_CRNL; + } else if (!dialect.strict) { + parse_add_char(c); + state = ParserState.IN_FIELD; + } else { + // illegal + throw _csv.Error(String.format("'%c' expected after '%c'", + dialect.delimiter, dialect.quotechar)); + } + break; + + case EAT_CRNL: + if (c == '\n' || c == '\r') { + ; + } else if (c == '\0') { + state = ParserState.START_RECORD; + } else { + String err = "new-line character seen in unquoted field - do you need to " + + "open the file in universal-newline mode?"; + throw _csv.Error(err); + } + break; + } + } + + private void parse_reset() { + fields = new PyList(); + state = ParserState.START_RECORD; + numeric_field = false; + } + + private void parse_save_field() { + PyObject field; + + field = new PyString(this.field.toString()); + if (numeric_field) { + numeric_field = false; + field = field.__float__(); + } + fields.append(field); + + // XXX: fastest way to clear StringBuffer? + this.field = new StringBuffer(INITIAL_BUILDER_CAPACITY); + } + + private void parse_add_char(char c) { + int field_len = field.length(); + if (field_len >= _csv.field_limit) { + throw _csv.Error(String.format("field larger than field limit (%d)", + _csv.field_limit)); + } + field.append(c); + } + + /** + * State of the CSV reader. + */ + private enum ParserState { + START_RECORD, START_FIELD, ESCAPED_CHAR, IN_FIELD, IN_QUOTED_FIELD, ESCAPE_IN_QUOTED_FIELD, + QUOTE_IN_QUOTED_FIELD, EAT_CRNL; + } +} Added: branches/asm/src/org/python/modules/_csv/PyWriter.java =================================================================== --- branches/asm/src/org/python/modules/_csv/PyWriter.java (rev 0) +++ branches/asm/src/org/python/modules/_csv/PyWriter.java 2008-08-06 02:48:46 UTC (rev 5090) @@ -0,0 +1,267 @@ +/* Copyright (c) Jython Developers */ +package org.python.modules._csv; + +import org.python.core.Py; +import org.python.core.PyException; +import org.python.core.PyObject; +import org.python.core.PyString; +import org.python.core.PyType; +import org.python.expose.ExposedType; +import org.python.expose.ExposedMethod; +import org.python.expose.ExposedGet; + +/** + * CSV file writer. + * + * Analogous to CPython's _csv.c::WriterObj str... [truncated message content] |