Commits

Anonymous committed 4c44912

Implement _io._IOBase in Java
There is now an implementation in org.python.modules._io.PyIOBase.java. Score in test_io.py is slightly up again at fail/error/skip = 12/58/99, but this will come down in later rounds when PyFileIO finally joins the new class hierarchy.

Comments (0)

Files changed (9)

CoreExposed.includes

 org/python/modules/_csv/PyDialect.class
 org/python/modules/_csv/PyReader.class
 org/python/modules/_csv/PyWriter.class
+org/python/modules/_io/PyIOBase.class
 org/python/modules/_io/PyFileIO.class
 org/python/modules/_functools/PyPartial.class
 org/python/modules/_hashlib$Hash.class
         self.characters_written = characters_written
 
 
-from _io import (open, UnsupportedOperation)
-
-
-class _IOBase:
-    __metaclass__ = abc.ABCMeta
-
-    """The abstract base class for all I/O classes, acting on streams of
-    bytes. There is no public constructor.
-
-    This class provides dummy implementations for many methods that
-    derived classes can override selectively; the default implementations
-    represent a file that cannot be read, written or seeked.
-
-    Even though _IOBase does not declare read, readinto, or write because
-    their signatures will vary, implementations and clients should
-    consider those methods part of the interface. Also, implementations
-    may raise a IOError when operations they do not support are called.
-
-    The basic type used for binary data read from or written to a file is
-    bytes. bytearrays are accepted too, and in some cases (such as
-    readinto) needed. Text I/O classes work with str data.
-
-    Note that calling any method (even inquiries) on a closed stream is
-    undefined. Implementations may raise IOError in this case.
-
-    _IOBase (and its subclasses) support the iterator protocol, meaning
-    that an _IOBase object can be iterated over yielding the lines in a
-    stream.
-
-    _IOBase also supports the :keyword:`with` statement. In this example,
-    fp is closed after the suite of the with statement is complete:
-
-    with open('spam.txt', 'r') as fp:
-        fp.write('Spam and eggs!')
-    """
-
-    ### Internal ###
-
-    def _unsupported(self, name):
-        """Internal: raise an exception for unsupported operations."""
-        raise UnsupportedOperation("%s.%s() not supported" %
-                                   (self.__class__.__name__, name))
-
-    ### Positioning ###
-
-    def seek(self, pos, whence=0):
-        """Change stream position.
-
-        Change the stream position to byte offset offset. offset is
-        interpreted relative to the position indicated by whence.  Values
-        for whence are:
-
-        * 0 -- start of stream (the default); offset should be zero or positive
-        * 1 -- current stream position; offset may be negative
-        * 2 -- end of stream; offset is usually negative
-
-        Return the new absolute position.
-        """
-        self._unsupported("seek")
-
-    def tell(self):
-        """Return current stream position."""
-        return self.seek(0, 1)
-
-    def truncate(self, pos=None):
-        """Truncate file to size bytes.
-
-        Size defaults to the current IO position as reported by tell().  Return
-        the new size.
-        """
-        self._unsupported("truncate")
-
-    ### Flush and close ###
-
-    def flush(self):
-        """Flush write buffers, if applicable.
-
-        This is not implemented for read-only and non-blocking streams.
-        """
-        self._checkClosed()
-        # XXX Should this return the number of bytes written???
-
-    __closed = False
-
-    def close(self):
-        """Flush and close the IO object.
-
-        This method has no effect if the file is already closed.
-        """
-        if not self.__closed:
-            self.flush()
-            self.__closed = True
-
-    def __del__(self):
-        """Destructor.  Calls close()."""
-        # The try/except block is in case this is called at program
-        # exit time, when it's possible that globals have already been
-        # deleted, and then the close() call might fail.  Since
-        # there's nothing we can do about such failures and they annoy
-        # the end users, we suppress the traceback.
-        try:
-            self.close()
-        except:
-            pass
-
-    ### Inquiries ###
-
-    def seekable(self):
-        """Return whether object supports random access.
-
-        If False, seek(), tell() and truncate() will raise IOError.
-        This method may need to do a test seek().
-        """
-        return False
-
-    def _checkSeekable(self, msg=None):
-        """Internal: raise an IOError if file is not seekable
-        """
-        if not self.seekable():
-            raise IOError("File or stream is not seekable."
-                          if msg is None else msg)
-
-
-    def readable(self):
-        """Return whether object was opened for reading.
-
-        If False, read() will raise IOError.
-        """
-        return False
-
-    def _checkReadable(self, msg=None):
-        """Internal: raise an IOError if file is not readable
-        """
-        if not self.readable():
-            raise IOError("File or stream is not readable."
-                          if msg is None else msg)
-
-    def writable(self):
-        """Return whether object was opened for writing.
-
-        If False, write() and truncate() will raise IOError.
-        """
-        return False
-
-    def _checkWritable(self, msg=None):
-        """Internal: raise an IOError if file is not writable
-        """
-        if not self.writable():
-            raise IOError("File or stream is not writable."
-                          if msg is None else msg)
-
-    @property
-    def closed(self):
-        """closed: bool.  True iff the file has been closed.
-
-        For backwards compatibility, this is a property, not a predicate.
-        """
-        return self.__closed
-
-    def _checkClosed(self, msg=None):
-        """Internal: raise an ValueError if file is closed
-        """
-        if self.closed:
-            raise ValueError("I/O operation on closed file."
-                             if msg is None else msg)
-
-    ### Context manager ###
-
-    def __enter__(self):
-        """Context management protocol.  Returns self."""
-        self._checkClosed()
-        return self
-
-    def __exit__(self, *args):
-        """Context management protocol.  Calls close()"""
-        self.close()
-
-    ### Lower-level APIs ###
-
-    # XXX Should these be present even if unimplemented?
-
-    def fileno(self):
-        """Returns underlying file descriptor if one exists.
-
-        An IOError is raised if the IO object does not use a file descriptor.
-        """
-        self._unsupported("fileno")
-
-    def isatty(self):
-        """Return whether this is an 'interactive' stream.
-
-        Return False if it can't be determined.
-        """
-        self._checkClosed()
-        return False
-
-    ### Readline[s] and writelines ###
-
-    def readline(self, limit=-1):
-        r"""Read and return a line from the stream.
-
-        If limit is specified, at most limit bytes will be read.
-
-        The line terminator is always b'\n' for binary files; for text
-        files, the newlines argument to open can be used to select the line
-        terminator(s) recognized.
-        """
-        # For backwards compatibility, a (slowish) readline().
-        if hasattr(self, "peek"):
-            def nreadahead():
-                readahead = self.peek(1)
-                if not readahead:
-                    return 1
-                n = (readahead.find(b"\n") + 1) or len(readahead)
-                if limit >= 0:
-                    n = min(n, limit)
-                return n
-        else:
-            def nreadahead():
-                return 1
-        if limit is None:
-            limit = -1
-        elif not isinstance(limit, (int, long)):
-            raise TypeError("limit must be an integer")
-        res = bytearray()
-        while limit < 0 or len(res) < limit:
-            b = self.read(nreadahead())
-            if not b:
-                break
-            res += b
-            if res.endswith(b"\n"):
-                break
-        return bytes(res)
-
-    def __iter__(self):
-        self._checkClosed()
-        return self
-
-    def next(self):
-        line = self.readline()
-        if not line:
-            raise StopIteration
-        return line
-
-    def readlines(self, hint=None):
-        """Return a list of lines from the stream.
-
-        hint can be specified to control the number of lines read: no more
-        lines will be read if the total size (in bytes/characters) of all
-        lines so far exceeds hint.
-        """
-        if hint is not None and not isinstance(hint, (int, long)):
-            raise TypeError("integer or None expected")
-        if hint is None or hint <= 0:
-            return list(self)
-        n = 0
-        lines = []
-        for line in self:
-            lines.append(line)
-            n += len(line)
-            if n >= hint:
-                break
-        return lines
-
-    def writelines(self, lines):
-        self._checkClosed()
-        for line in lines:
-            self.write(line)
+from _io import (open, UnsupportedOperation, _IOBase)
 
 
 class _RawIOBase(_IOBase):
         try:
             name = self.name
         except AttributeError:
-            return "<_pyio.{0}>".format(clsname)
+            return "<_jyio.{0}>".format(clsname)
         else:
-            return "<_pyio.{0} name={1!r}>".format(clsname, name)
+            return "<_jyio.{0} name={1!r}>".format(clsname, name)
 
     ### Lower-level APIs ###
 
         try:
             name = self.name
         except AttributeError:
-            return "<_pyio.TextIOWrapper encoding='{0}'>".format(self.encoding)
+            return "<_jyio.TextIOWrapper encoding='{0}'>".format(self.encoding)
         else:
-            return "<_pyio.TextIOWrapper name={0!r} encoding='{1}'>".format(
+            return "<_jyio.TextIOWrapper name={0!r} encoding='{1}'>".format(
                 name, self.encoding)
 
     @property
 
     def close(self):
         if self.buffer is not None and not self.closed:
-            self.flush()
+            # Jython difference: flush and close via super.
+            # Sets __closed for quick _checkClosed().
+            super(TextIOWrapper, self).close()
             self.buffer.close()
 
-    @property
-    def closed(self):
-        return self.buffer.closed
+    # Jython difference: @property closed(self) inherited from _IOBase.__closed
 
     @property
     def name(self):

Lib/test/test_io.py

 from test import test_support as support
 
 import codecs
-import io  # C implementation of io
-import _pyio as pyio # Python implementation of io
+import io               # subject of test
+import _io              # compiled implementation of io
+import _pyio as pyio    # Python implementation of io
 try:
     import threading
 except ImportError:

src/org/python/modules/_io/Closer.java

+/* Copyright (c)2012 Jython Developers */
+package org.python.modules._io;
+
+import java.lang.ref.WeakReference;
+import java.util.concurrent.Callable;
+
+import org.python.core.PyObject;
+import org.python.core.PySystemState;
+
+/**
+ * A class to take responsibility for closing a stream on JVM shutdown. On creation a Closer adds
+ * itself to a list that will be run by PySystemState on shutdown and it maintains a reference to
+ * its client PyIOBase. The client (assuming it kept a reference to the Closer) may dismiss the
+ * closer at any time: normally this will be when the client stream is closed directly, or
+ * implicitly through {@link PyIOBase#__exit__(PyObject, PyObject, PyObject)}. A possibility is that
+ * the JVM exits before an <code>close()</code> is called. In that case, {@link Closer#call()} will
+ * be called, and the <code>Closer</code> will call the client's close operation.
+ * <p>
+ * In case the close operation is overridden so that it does not dismiss the closer, it is useful to
+ * have the client's finalize dismiss the closer. If not, the Closer will remain registered and this
+ * will keep the <code>PyIOBase</code> object alive in the JVM, which is mostly harmless.
+ */
+/*
+ * Adapted from PyFile, but significantly different to call the overridden close operation of the
+ * client itself, rather than just the underlying file.
+ */
+class Closer<C extends PyIOBase> implements Callable<Void> {
+
+    /** The client in need of closing. */
+    private final WeakReference<C> client;
+
+    /** Interpreter state that will call {@link #call()} on shutdown. */
+    private PySystemState sys;
+
+    public Closer(C toClose, PySystemState sys) {
+        this.client = new WeakReference<C>(toClose);
+        this.sys = sys;
+        sys.registerCloser(this);
+    }
+
+    /**
+     * Tell the Closer that its services are no longer required. This unhooks it from the shutdown
+     * list. Repeated calls are allowed but only the first has any effect.
+     */
+    public synchronized void dismiss() {
+        if (sys != null) {
+            sys.unregisterCloser(this);
+            sys = null;
+        }
+    }
+
+    /**
+     * Called as part of a shutdown process. If the client is still (weakly) reachable, invoke its
+     * "close" method.
+     */
+    @Override
+    public synchronized Void call() {
+        // This will prevent a call to dismiss() manipulating the caller's list of closers
+        sys = null;
+        // Call close on the client (if it still exists)
+        C toClose = client.get();
+        if (toClose != null) {
+            toClose.invoke("close");
+        }
+        return null;
+    }
+}

src/org/python/modules/_io/PyIOBase.java

+/* Copyright (c)2012 Jython Developers */
+package org.python.modules._io;
+
+import org.python.core.BufferProtocol;
+import org.python.core.Py;
+import org.python.core.PyArray;
+import org.python.core.PyBUF;
+import org.python.core.PyBuffer;
+import org.python.core.PyByteArray;
+import org.python.core.PyException;
+import org.python.core.PyList;
+import org.python.core.PyNewWrapper;
+import org.python.core.PyObject;
+import org.python.core.PyString;
+import org.python.core.PyStringMap;
+import org.python.core.PyType;
+import org.python.core.PyUnicode;
+import org.python.core.buffer.SimpleStringBuffer;
+import org.python.core.io.FileIO;
+import org.python.expose.ExposedGet;
+import org.python.expose.ExposedMethod;
+import org.python.expose.ExposedNew;
+import org.python.expose.ExposedType;
+
+/**
+ * The Python module <code>_io._IOBase</code>, on which the <code>io</code> module depends directly.
+ * <p>
+ * <b>Implementation note:</b> The code is based heavily on the Jython 2.6-ish
+ * <code>_fileio.PyFileIO</code>, the purely Java-accessible {@link org.python.core.io.IOBase} (both
+ * Philip Jenvey's work), and the Python implementation in <code>Lib/_pyio</code>. We do not simply
+ * delegate to the implementation in {@link org.python.core.io} because of the need to override
+ * parts of the implementation in Python subclasses. A call to {@link #close()}, for example, is
+ * required to call {@link #flush()}, but if delegated to the pure Java implementation would not
+ * call the version of <code>flush()</code> overridden in a Python sub-class of
+ * <code>_io._IOBase</code>. Equally, the use made by <code>PyRawIOBase.read(int)</code> of
+ * <code>readinto(bytearray)</code> would not pick up the version of <code>readinto</code> defined
+ * in Python.
+ */
+@ExposedType(name = "_io._IOBase", doc = PyIOBase.doc)
+public class PyIOBase extends PyObject {
+
+    public static final PyType TYPE = PyType.fromClass(PyIOBase.class);
+
+    /** The ioDelegate's closer object; ensures the stream is closed at shutdown */
+    private Closer<PyIOBase> closer;
+
+    protected PyIOBase() {
+        this(TYPE);
+    }
+
+    protected PyIOBase(PyType subtype) {
+        super(subtype);
+        closer = new Closer<PyIOBase>(this, Py.getSystemState());
+    }
+
+    /**
+     * Provide a dictionary in the object, mainly so that methods can be overridden at instance
+     * level, mainly, in fact, so that the test <code>test_flush_error_on_close</code> passes.
+     */
+    @ExposedGet
+    protected PyObject __dict__ = new PyStringMap();
+
+    @Override
+    public PyObject fastGetDict() {
+        return __dict__;
+    }
+
+    @ExposedNew
+    static PyObject _IOBase___new__(PyNewWrapper new_, boolean init, PyType subtype,
+            PyObject[] args, String[] keywords) {
+        if (new_.for_type == subtype) {
+            // We only want an _io._IOBase, so the constructor does it all
+            return new PyIOBase();
+        } else {
+            // We want some sub-class of it (in which __init__ will be called by the caller)
+            return new PyIOBaseDerived(subtype);
+        }
+    }
+
+    /**
+     * Convenience method returning a PyException(_io.UnsupportedOperation), ripe for throwing, and
+     * naming the unsupported operation. Like many similar methods, this does not actually throw
+     * (raise) the exception: it should be thrown from the place where the problem is.
+     *
+     * @param op name of operation
+     * @return the exception for throwing
+     */
+    protected PyException unsupported(String op) {
+        String fmt = "%s.%s() not supported";
+        String msg = String.format(fmt, getType().fastGetName(), op);
+        return _io.UnsupportedOperation(msg);
+    }
+
+    @ExposedMethod(doc = "Internal: raise an exception for unsupported operations.")
+    final void _IOBase__unsupported(String name) {
+        throw unsupported(name);
+    }
+
+    /**
+     * Position the read or write pointer at a given byte offset <code>pos</code> relative to a
+     * position indicated by <code>whence</code>.
+     * <ul>
+     * <li>If <code>whence</code>=0, the position will be set to <code>pos</code> bytes.</li>
+     * <li>If <code>whence</code>=1 the position will be set to the current position plus
+     * <code>pos</code>.</li>
+     * <li>If <code>whence</code>=2 the position will be set to the stream size plus
+     * <code>pos</code> (and usually <code>pos</code>&lt;=0).</li>
+     * </ul>
+     *
+     * @param pos relative to the specified point
+     * @param whence 0=from start, 1=from here, 2=from end
+     * @return the new current position
+     */
+    public long seek(long pos, int whence) {
+        return _IOBase_seek(pos, whence);
+    }
+
+    public final long seek(long pos) {
+        return seek(pos, 0);
+    }
+
+    @ExposedMethod(defaults = "0", doc = seek_doc)
+    final long _IOBase_seek(long pos, int whence) {
+        throw unsupported("seek");
+    }
+
+    /**
+     * Get the current stream position.
+     *
+     * @return stream position
+     */
+    public long tell() {
+        return _IOBase_tell();
+    }
+
+    @ExposedMethod(doc = tell_doc)
+    final long _IOBase_tell() {
+        return seek(0, 1);
+    }
+
+    /**
+     * Truncate file to <code>size</code> bytes.
+     *
+     * @param size requested for stream
+     * @return the new size
+     */
+    public long truncate(long size) {
+        return _IOBase_truncate(null); // Just raises an exception anyway
+    }
+
+    /**
+     * Truncate file to <code>size</code> bytes to the current position (as reported by
+     * <code>tell()</code>).
+     *
+     * @param size requested for stream (or null for default)
+     * @return the new size
+     */
+    public long truncate() {
+        return _IOBase_truncate(null);
+    }
+
+    @ExposedMethod(defaults = "null", doc = truncate_doc)
+    final long _IOBase_truncate(PyObject size) {
+        throw unsupported("truncate");
+    }
+
+    /**
+     * Flush write buffers, or no-op for read-only and non-blocking streams. Irrespective of the
+     * concrete type of the i/o object, locally-buffered write data is written downstream. Whether
+     * the downstream in object is also flushed depends upon the specific type of this object.
+     */
+    public void flush() {
+        _IOBase_flush();
+    }
+
+    @ExposedMethod(doc = flush_doc)
+    final void _IOBase_flush() {}
+
+    /**
+     * True if the object is closed to further <b>client</b> operations. It is the state accessed by
+     * <code>closed</code> and checked by {@link #_checkClosed()}. It may be set without making it
+     * an error (for this object and its subclasses) to access some downstream object, notably in
+     * the implementation of <code>close()</code>.
+     */
+    /*
+     * This is the analogue of the IS_CLOSED(self) macro and iobase_closed_get() in CPython
+     * modules/_io/iobase.c. That function checks for the *existence* of an attribute
+     * __IOBase_closed. You can find this exposed in CPython. _pyio.IOBase exposes _IOBase__closed
+     * (aka "__closed") for a similar purpose (note different name).
+     */
+    @ExposedGet(name = "closed", doc = closed_doc)
+    protected boolean __closed;
+
+    /**
+     * Close the stream. If closed already, this is a no-op.
+     */
+    public void close() {
+        _IOBase_close();
+    }
+
+    @ExposedMethod(doc = close_doc)
+    final void _IOBase_close() {
+        if (!__closed) {
+            // Cancel the wake-up call
+            closer.dismiss();
+            // Close should invoke (possibly overridden) flush here.
+            invoke("flush");
+            // Prevent further access from upstream
+            __closed = true;
+        }
+    }
+
+    /**
+     * Is the stream capable of positioning the read/write pointer?
+     *
+     * @return <code>True</code> if may be positioned
+     */
+    public boolean seekable() {
+        return _IOBase_seekable();
+    }
+
+    @ExposedMethod(doc = seekable_doc)
+    final boolean _IOBase_seekable() {
+        return false;
+    }
+
+    /**
+     * Raise an error if the pointer of underlying IO stream <b>is not</b> capable of being
+     * positioned.
+     *
+     * @param msg optional custom message
+     */
+    public void _checkSeekable(String msg) {
+        _IOBase__checkSeekable(msg);
+    }
+
+    /**
+     * Raise an error if the pointer of underlying IO stream <b>is not</b> capable of being
+     * positioned.
+     */
+    public final void _checkSeekable() {
+        _checkSeekable(null);
+    }
+
+    @ExposedMethod(defaults = "null")
+    final void _IOBase__checkSeekable(String msg) {
+        if (!invoke("seekable").__nonzero__()) {
+            throw tailoredIOError(msg, "seek");
+        }
+    }
+
+    /**
+     * Is the stream readable?
+     *
+     * @return <code>true</code> if readable
+     */
+    public boolean readable() {
+        return _IOBase_readable();
+    }
+
+    @ExposedMethod(doc = readable_doc)
+    final boolean _IOBase_readable() {
+        return false;
+    }
+
+    /**
+     * Raise an error if the underlying IO stream <b>is not</b> readable.
+     *
+     * @param msg optional custom message
+     */
+    public void _checkReadable(String msg) {
+        _IOBase__checkReadable(msg);
+    }
+
+    /**
+     * Raise an error if the underlying IO stream <b>is not</b> readable.
+     */
+    public final void _checkReadable() {
+        _checkReadable(null);
+    }
+
+    @ExposedMethod(defaults = "null")
+    final void _IOBase__checkReadable(String msg) {
+        if (!invoke("readable").__nonzero__()) {
+            throw tailoredIOError(msg, "read");
+        }
+    }
+
+    /**
+     * Is the stream writable?
+     *
+     * @return <code>true</code> if writable
+     */
+    public boolean writable() {
+        return _IOBase_writable();
+    }
+
+    @ExposedMethod(doc = writable_doc)
+    final boolean _IOBase_writable() {
+        return false;
+    }
+
+    /**
+     * Raise an error if the underlying IO stream <b>is not</b> writable.
+     *
+     * @param msg optional custom message
+     */
+    public void _checkWritable(String msg) {
+        _IOBase__checkWritable(msg);
+    }
+
+    /**
+     * Raise an error if the underlying IO stream <b>is not</b> writable.
+     */
+    public final void _checkWritable() {
+        _checkWritable(null);
+    }
+
+    @ExposedMethod(defaults = "null")
+    final void _IOBase__checkWritable(String msg) {
+        if (!invoke("writable").__nonzero__()) {
+            throw tailoredIOError(msg, "writ");
+        }
+    }
+
+    /**
+     * Is the stream closed against further client operations?
+     *
+     * @return <code>true</code> if closed
+     */
+    public final boolean closed() {
+        return __closed;
+    }
+
+    /**
+     * Raise an error if the underlying IO stream <b>is</b> closed. (Note opposite sense from
+     * {@link #_checkSeekable}, etc..
+     *
+     * @param msg optional custom message
+     */
+    public void _checkClosed(String msg) {
+        _IOBase__checkClosed(msg);
+    }
+
+    public final void _checkClosed() {
+        _checkClosed(null);
+    }
+
+    @ExposedMethod(defaults = "null")
+    final void _IOBase__checkClosed(String msg) {
+        if (closed()) {
+            throw Py.ValueError(msg != null ? msg : "I/O operation on closed file");
+        }
+    }
+
+    /**
+     * Called at the start of a context-managed suite (supporting the <code>with</code> clause).
+     *
+     * @return this object
+     */
+    public PyObject __enter__() {
+        return _IOBase___enter__();
+    }
+
+    @ExposedMethod(names = {"__enter__", "__iter__"})
+    final PyObject _IOBase___enter__() {
+        _checkClosed();
+        return this;
+    }
+
+    /**
+     * Called at the end of a context-managed suite (supporting the <code>with</code> clause), and
+     * will normally close the stream.
+     *
+     * @return false
+     */
+    public boolean __exit__(PyObject type, PyObject value, PyObject traceback) {
+        return _IOBase___exit__(type, value, traceback);
+    }
+
+    @ExposedMethod
+    final boolean _IOBase___exit__(PyObject type, PyObject value, PyObject traceback) {
+        invoke("close");
+        return false;
+    }
+
+    /**
+     * Return a file descriptor for the stream. A CPython file descriptor is an int, but this is not
+     * the natural choice in Jython, since Java has no such convention of using integers. File
+     * descriptors should be passed around opaquely, so their actual type is irrelevant, as long as
+     * (say) {@link _io#open(PyObject[], String[])} accepts the type that {@link FileIO#fileno()}
+     * returns.
+     *
+     * @return a file descriptor (as opaque object)
+     */
+    public PyObject fileno() {
+        return _IOBase_fileno();
+    }
+
+    @ExposedMethod(doc = fileno_doc)
+    final PyObject _IOBase_fileno() {
+        throw unsupported("fileno");
+    }
+
+    /**
+     * Is the stream known to be an interactive console? This relies on the ability of the
+     * underlying stream to know, which is not always possible.
+     *
+     * @return <code>true</code> if a console: <code>false</code> if not or we can't tell
+     */
+    public boolean isatty() {
+        return _IOBase_isatty();
+    }
+
+    @ExposedMethod(doc = isatty_doc)
+    final boolean _IOBase_isatty() {
+        _checkClosed();
+        return false;
+    }
+
+    /**
+     * Return one line of text (bytes terminates by <code>'\n'</code>), or the specified number of
+     * bytes, or the whole stream, whichever is shortest.
+     *
+     * @param limit maximum number of bytes (<0 means no limit)
+     * @return the line (or fragment)
+     */
+    public PyObject readline(int limit) {
+        return _readline(limit);
+    }
+
+    /**
+     * Return one line of text (bytes terminates by <code>'\n'</code>), or the whole stream,
+     * whichever is shorter.
+     *
+     * @return the line (or fragment)
+     */
+    public PyObject readline() {
+        return _readline(-1);
+    }
+
+    @ExposedMethod(defaults = "null", doc = readline_doc)
+    final PyObject _IOBase_readline(PyObject limit) {
+        if (limit == null || limit==Py.None) {
+            return _readline(-1);
+        } else if (limit.isIndex()) {
+            return _readline(limit.asInt());
+        } else {
+            throw Py.TypeError("limit must be an integer");
+        }
+    }
+
+    private PyObject _readline(int limit) {
+
+        // Either null, or a thing we can __call__()
+        PyObject peekMethod = __findattr__("peek");
+        // Either an error, or a thing we can __call__()
+        PyObject readMethod = __getattr__("read");
+
+        // We'll count down from the provided limit here
+        int remainingLimit = (limit) >= 0 ? limit : Integer.MAX_VALUE;
+
+        /*
+         * We have two almost independent versions of the implementation, depending on whether we
+         * have a peek() method available.
+         */
+        if (peekMethod != null) {
+            /*
+             * This type/object has some kind of read-ahead buffer that we can scan for end of line,
+             * and refill as required. We are prepared to make a list of the fragments and join them
+             * at the end, but often there is only one.
+             */
+            PyList list = null;
+            PyObject curr = Py.EmptyString;
+
+            while (remainingLimit > 0) {
+
+                // We hope to get away with just one pass of the loop, but if not ...
+                if (curr.__nonzero__()) {
+                    // We have some previous bytes that must be added to the list
+                    if (list == null) {
+                        // ... be first we need a list to add them to.
+                        list = new PyList();
+                    }
+                    list.add(curr);
+                }
+
+                /*
+                 * peek() returns a str of bytes from the buffer (if any), doing at most one read to
+                 * refill, all without advancing the pointer, or it returns None (in vacuous
+                 * non-blocking read).
+                 */
+                PyObject peekResult = peekMethod.__call__(Py.One);
+                if (peekResult.__nonzero__()) {
+
+                    // Get a look at the bytes themselves
+                    PyBuffer peekBuffer = readablePyBuffer(peekResult);
+
+                    try {
+                        /*
+                         * Scan forwards in the peek buffer to see if there is an end-of-line. Most
+                         * frequently this succeeds. The number of bytes to scan is limited to the
+                         * (remaining) limit value and the peek-buffer length.
+                         */
+                        int p = 0, nr = peekBuffer.getLen();
+                        if (nr > remainingLimit) {
+                            nr = remainingLimit;
+                        }
+
+                        while (p < nr) {
+                            if (peekBuffer.byteAt(p++) == '\n') {
+                                remainingLimit = p; // Engineer an exit from the outer loop
+                                break;
+                            }
+                        }
+
+                        /*
+                         * The the next p bytes should be added to the line we are building, and the
+                         * pointer advanced: that's a read().
+                         */
+                        curr = readMethod.__call__(Py.newInteger(p));
+                        remainingLimit -= p;
+
+                    } finally {
+                        // We must let go of the buffer we were given
+                        peekBuffer.release();
+                    }
+
+                } else {
+                    // peekResult was vacuous: we must be finished
+                    curr = Py.EmptyString;
+                    remainingLimit = 0;
+                }
+            }
+
+            if (list == null) {
+                // We went through the loop at most once and the entire answer is in curr
+                return curr;
+
+            } else {
+                // Previous reads are in the list: return them all stitched together
+                if (curr.__nonzero__()) {
+                    list.add(curr);
+                }
+                return Py.EmptyString.join(list);
+            }
+
+        } else {
+            /*
+             * We don't have a peek method, so we'll be reading one byte at a time.
+             */
+            PyByteArray res = new PyByteArray();
+
+            while (remainingLimit > 0) {
+
+                /*
+                 * peek() returns a str of bytes from the buffer (if any), doing at most one read to
+                 * refill, all without advancing the pointer, or it returns None (in vacuous
+                 * non-blocking read).
+                 */
+                PyObject curr = readMethod.__call__(Py.One);
+
+                if (curr.__nonzero__()) {
+                    if (curr instanceof PyString) {
+                        // Should be one-character string holding a byte
+                        char c = ((PyString)curr).getString().charAt(0);
+                        if (c == '\n') {
+                            remainingLimit = 0; // Engineer an exit from the outer loop
+                        }
+                        res.append((byte)c);
+                    } else {
+                        String fmt = "read() should have returned a bytes object, not '%.200s'";
+                        throw Py.IOError(String.format(fmt, curr.getType().fastGetName()));
+                    }
+                } else {
+                    remainingLimit = 0; // Exit the outer loop
+                }
+
+            }
+
+            return res.__str__();
+        }
+
+    }
+
+    @Override
+    public PyObject __iter__() {
+        _checkClosed();
+        // Not like this, in spite of what base comment says, because file *is* an iterator
+        //        return new PySequenceIter(this);
+        return this;
+    }
+
+    // _IOBase___iter__ = _IOBase___enter__
+
+    @Override
+    public PyObject __iternext__() {
+        PyObject line = invoke("readline");
+        return (!line.__nonzero__()) ? null : line;
+    }
+
+    /**
+     * Read a stream as a sequence of lines.
+     *
+     * @param hint stop reading lines after this many bytes (if not EOF first)
+     * @return list containing the lines read
+     */
+    public PyObject readlines(PyObject hint) {
+        return _IOBase_readlines(hint);
+    }
+
+    @ExposedMethod(defaults = "null", doc = readlines_doc)
+    final PyObject _IOBase_readlines(PyObject hint) {
+
+        int h = 0;
+
+        if (hint==null || hint == Py.None) {
+            return new PyList(this);
+
+        } else if (!hint.isIndex()) {
+            throw Py.TypeError("integer or None expected");
+
+        } else if ((h = hint.asIndex()) <= 0) {
+            return new PyList(this);
+
+        } else {
+            int n = 0;
+            PyList lines = new PyList();
+
+            for (PyObject line : this.asIterable()) {
+                lines.append(line);
+                n += line.__len__();
+                if (n >= h) {
+                    break;
+                }
+            }
+            return lines;
+        }
+    }
+
+    /**
+     * Write an iterable sequence of strings to the stream.
+     *
+     * @param lines
+     */
+    public void writelines(PyObject lines) {
+        _IOBase_writelines(lines);
+    }
+
+    @ExposedMethod(doc = writelines_doc)
+    final void _IOBase_writelines(PyObject lines) {
+        _checkClosed();
+        // Either an error, or a thing we can __call__()
+        PyObject writeMethod = __getattr__("write");
+
+        for (PyObject line : lines.asIterable()) {
+            writeMethod.__call__(line);
+        }
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        closer.dismiss();
+        invoke("close");
+        super.finalize();
+    }
+
+    /** Convenience method providing the exception in the _checkWhatever() methods. */
+    private static PyException tailoredIOError(String msg, String oper) {
+        if (msg == null) {
+            return Py.IOError("File or stream is not " + oper + "able.");
+        } else {
+            return Py.IOError(msg);
+        }
+    }
+
+    /**
+     * Construct a PyBuffer on a given object suitable for writing to the underlying stream. The
+     * buffer returned will be navigable as a 1D contiguous sequence of bytes.
+     *
+     * @param obj to be wrapped and presented as a buffer
+     * @return a 1D contiguous PyBuffer of bytes
+     * @throws PyException (BufferError) if object has buffer API, but is not 1D contiguous bytes
+     * @throws PyException (TypeError) if object not convertible to a byte array
+     */
+    protected static PyBuffer readablePyBuffer(PyObject obj) throws PyException {
+        if (obj instanceof BufferProtocol) {
+            return ((BufferProtocol)obj).getBuffer(PyBUF.SIMPLE);
+        } else {
+            // Something else we can view as a String?
+            String s;
+            if (obj instanceof PyUnicode) {
+                s = ((PyUnicode)obj).encode();
+            } else if (obj instanceof PyArray) {
+                s = ((PyArray)obj).tostring();
+            } else {
+                // None of the above: complain
+                String fmt = "object must be string or buffer, not %.100s";
+                throw Py.TypeError(String.format(fmt, obj.getType().fastGetName()));
+            }
+            return new SimpleStringBuffer(PyBUF.SIMPLE, s);
+        }
+    }
+
+    /**
+     * Construct a PyBuffer on a given object suitable for reading into from the underlying stream.
+     * The buffer returned will be navigable as a 1D contiguous writable sequence of bytes.
+     *
+     * @param obj to be wrapped and presented as a buffer
+     * @return a 1D contiguous PyBuffer of bytes
+     * @throws PyException (BufferError) if object has buffer API, but is not 1D contiguous bytes
+     * @throws PyException (TypeError) if object not convertible to a byte array
+     */
+    protected static PyBuffer writablePyBuffer(PyObject obj) throws PyException {
+        if (obj instanceof BufferProtocol) {
+            return ((BufferProtocol)obj).getBuffer(PyBUF.WRITABLE);
+        } else {
+            // Can't be a buffer: complain
+            String fmt = "object must be read-write buffer, not %.100s";
+            throw Py.TypeError(String.format(fmt, obj.getType().fastGetName()));
+        }
+    }
+
+    /*
+     * Documentation strings: public where they might be useful to a subclass.
+     */
+    public static final String seek_doc = "Change stream position.\n" + "\n"
+            + "Change the stream position to byte offset offset. offset is\n"
+            + "interpreted relative to the position indicated by whence.  Values\n"
+            + "for whence are:\n" + "\n"
+            + "* 0 -- start of stream (the default); offset should be zero or positive\n"
+            + "* 1 -- current stream position; offset may be negative\n"
+            + "* 2 -- end of stream; offset is usually negative\n" + "\n"
+            + "Return the new absolute position.";
+
+    public static final String tell_doc = "Return current stream position.";
+
+    public static final String truncate_doc = "Truncate file to size bytes.\n" + "\n"
+            + "File pointer is left unchanged.  Size defaults to the current IO\n"
+            + "position as reported by tell().  Returns the new size.";
+
+    public static final String flush_doc = "Flush write buffers, if applicable.\n" + "\n"
+            + "This is not implemented for read-only and non-blocking streams.";
+
+    // public static final String _flush_self_doc =
+    // "Flush write buffers (if any) into the downstream object\n"
+    // + "without flushing that object. The base implementations of\n"
+    // + "flush() and close() will call this method to move any\n"
+    // + "buffered write-data down to the next i/o object in the\n"
+    // + "stack before flushing or closing that downstream object.\n"
+    // + "A sub-class may override this method if it defines buffered\n"
+    // + "state. Generally sub-classes and clients should not call\n"
+    // + "this method directly.";
+
+    public static final String close_doc = "Flush and close the IO object.\n" + "\n"
+            + "This method has no effect if the file is already closed.";
+
+    public static final String closed_doc = "True if the stream is closed.\n";
+
+    public static final String seekable_doc = "Return whether object supports random access.\n"
+            + "\n" + "If False, seek(), tell() and truncate() will raise IOError.\n"
+            + "This method may need to do a test seek().";
+
+    public static final String readable_doc = "Return whether object was opened for reading.\n"
+            + "\n" + "If False, read() will raise IOError.";
+
+    public static final String writable_doc = "Return whether object was opened for writing.\n"
+            + "\n" + "If False, read() will raise IOError.";
+
+    public static final String fileno_doc = "Returns underlying file descriptor if one exists.\n"
+            + "\n" + "An IOError is raised if the IO object does not use a file descriptor.\n";
+
+    public static final String isatty_doc = "Return whether this is an 'interactive' stream.\n"
+            + "\n" + "Return False if it can't be determined.\n";
+
+    public static final String readline_doc = "Read and return a line from the stream.\n" + "\n"
+            + "If limit is specified, at most limit bytes will be read.\n" + "\n"
+            + "The line terminator is always b'\n' for binary files; for text\n"
+            + "files, the newlines argument to open can be used to select the line\n"
+            + "terminator(s) recognized.\n";
+
+    public static final String readlines_doc = "Return a list of lines from the stream.\n" + "\n"
+            + "hint can be specified to control the number of lines read: no more\n"
+            + "lines will be read if the total size (in bytes/characters) of all\n"
+            + "lines so far exceeds hint.";
+
+    public static final String writelines_doc =
+            "Write a list of lines to the stream. Line separators are not added,\n"
+                    + "so it is usual for each of the lines provided to have a line separator\n"
+                    + "at the end.";
+
+    static final String doc = "The abstract base class for all I/O classes, acting on streams of\n"
+            + "bytes. There is no public constructor.\n" + "\n"
+            + "This class provides dummy implementations for many methods that\n"
+            + "derived classes can override selectively; the default implementations\n"
+            + "represent a file that cannot be read, written or seeked.\n" + "\n"
+            + "Even though IOBase does not declare read, readinto, or write because\n"
+            + "their signatures will vary, implementations and clients should\n"
+            + "consider those methods part of the interface. Also, implementations\n"
+            + "may raise a IOError when operations they do not support are called.\n" + "\n"
+            + "The basic type used for binary data read from or written to a file is\n"
+            + "bytes. bytearrays are accepted too, and in some cases (such as\n"
+            + "readinto) needed. Text I/O classes work with str data.\n" + "\n"
+            + "Note that calling any method (even inquiries) on a closed stream is\n"
+            + "undefined. Implementations may raise IOError in this case.\n" + "\n"
+            + "IOBase (and its subclasses) support the iterator protocol, meaning\n"
+            + "that an IOBase object can be iterated over yielding the lines in a\n" + "stream.\n"
+            + "\n" + "IOBase also supports the :keyword:`with` statement. In this example,\n"
+            + "fp is closed after the suite of the with statement is complete:\n" + "\n"
+            + "with open('spam.txt', 'r') as fp:\n" + "    fp.write('Spam and eggs!')\n";
+
+}

src/org/python/modules/_io/PyIOBaseDerived.java

+/* Generated file, do not modify. See jython/src/templates/gderived.py. */
+package org.python.modules._io;
+
+import java.io.Serializable;
+
+import org.python.core.Deriveds;
+import org.python.core.Py;
+import org.python.core.PyBoolean;
+import org.python.core.PyComplex;
+import org.python.core.PyException;
+import org.python.core.PyFloat;
+import org.python.core.PyInteger;
+import org.python.core.PyLong;
+import org.python.core.PyObject;
+import org.python.core.PySequenceIter;
+import org.python.core.PySlice;
+import org.python.core.PyString;
+import org.python.core.PyTuple;
+import org.python.core.PyType;
+import org.python.core.PyUnicode;
+import org.python.core.Slotted;
+import org.python.core.ThreadState;
+
+public class PyIOBaseDerived extends PyIOBase implements Slotted {
+
+    @Override
+    public PyObject getSlot(int index) {
+        return slots[index];
+    }
+
+    @Override
+    public void setSlot(int index, PyObject value) {
+        slots[index] = value;
+    }
+
+    private PyObject[] slots;
+
+    public PyIOBaseDerived(PyType subtype) {
+        super(subtype);
+        slots = new PyObject[subtype.getNumSlots()];
+    }
+
+    @Override
+    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__();
+    }
+
+    @Override
+    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__();
+    }
+
+    @Override
+    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__();
+    }
+
+    @Override
+    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__();
+    }
+
+    @Override
+    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__();
+    }
+
+    @Override
+    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__();
+    }
+
+    @Override
+    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__();
+    }
+
+    @Override
+    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__();
+    }
+
+    @Override
+    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__();
+    }
+
+    @Override
+    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__();
+    }
+
+    @Override
+    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__();
+    }
+
+    @Override
+    public PyObject __dir__() {
+        PyType self_type = getType();
+        PyObject impl = self_type.lookup("__dir__");
+        if (impl != null) {
+            return impl.__get__(this, self_type).__call__();
+        }
+        return super.__dir__();
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    public PyObject __format__(PyObject other) {
+        PyType self_type = getType();
+        PyObject impl = self_type.lookup("__format__");
+        if (impl != null) {
+            PyObject res = impl.__get__(this, self_type).__call__(other);
+            if (res == Py.NotImplemented) {
+                return null;
+            }
+            return res;
+        }
+        return super.__format__(other);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    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);
+    }
+
+    @Override
+    public PyObject __ipow__(PyObject other) {
+        PyType self_type = getType();
+        PyObject impl = self_type.lookup("__ipow__");