Alex Gaynor avatar Alex Gaynor committed eb35134

Fixes for io.StringIO.{tell,seek}.

Comments (0)

Files changed (3)

pypy/module/_io/interp_stringio.py

 from pypy.module._io.interp_textio import W_TextIOBase
 from pypy.module._io.interp_iobase import convert_size
 
+
 class W_StringIO(W_TextIOBase):
     def __init__(self, space):
         W_TextIOBase.__init__(self, space)
         self.pos = end
         return space.wrap(u''.join(self.buf[start:end]))
 
-    @unwrap_spec('self', ObjSpace, int)
-    def seek_w(self, space, pos):
-        if pos < 0:
+    @unwrap_spec('self', ObjSpace, int, int)
+    def seek_w(self, space, pos, mode=0):
+        self._check_closed(space)
+
+        if not 0 <= mode <= 2:
+            raise operationerrfmt(space.w_ValueError,
+                "Invalid whence (%d, should be 0, 1 or 2)", mode
+            )
+        elif mode == 0 and pos < 0:
             raise operationerrfmt(space.w_ValueError,
                 "negative seek position: %d", pos
             )
+        elif mode != 0 and pos != 0:
+            raise OperationError(space.w_IOError,
+                space.wrap("Can't do nonzero cur-relative seeks")
+            )
+
+        # XXX: this makes almost no sense, but its how CPython does it.
+        if mode == 1:
+            pos = self.pos
+        elif mode == 2:
+            pos = len(self.buf)
         self.pos = pos
+        return space.wrap(pos)
 
     @unwrap_spec('self', ObjSpace)
     def getvalue_w(self, space):

pypy/module/_io/interp_textio.py

     setstate = interp2app(W_IncrementalNewlineDecoder.setstate_w),
 
     newlines = GetSetProperty(W_IncrementalNewlineDecoder.newlines_get_w),
-    )
+)
 
 class W_TextIOBase(W_IOBase):
     w_encoding = None

pypy/module/_io/test/test_stringio.py

         exc_info = raises(ValueError, sio.seek, -3)
         assert exc_info.value.args[0] == "negative seek position: -3"
 
+        raises(ValueError, sio.seek, 3, -1)
+        raises(ValueError, sio.seek, 3, -3)
+
+        sio.close()
+        raises(ValueError, sio.seek, 0)
+
+    def test_tell(self):
+        import io
+
+        s = u"1234567890"
+        sio = io.StringIO(s)
+
+        assert sio.tell() == 0
+        sio.seek(5)
+        assert sio.tell() == 5
+        sio.seek(10000)
+        assert sio.tell() == 10000
+
+        sio.close()
+        raises(ValueError, sio.tell)
+
     def test_write_error(self):
         import io
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.