[pypy-svn] pypy default: _io.open translates, and fixed the first set of segfaults.

alex_gaynor commits-noreply at bitbucket.org
Mon Jan 31 01:00:11 CET 2011


Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch: 
Changeset: r41477:74343e919325
Date: 2011-01-30 18:32 -0500
http://bitbucket.org/pypy/pypy/changeset/74343e919325/

Log:	_io.open translates, and fixed the first set of segfaults.

diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py
--- a/pypy/module/_io/interp_textio.py
+++ b/pypy/module/_io/interp_textio.py
@@ -260,6 +260,7 @@
     def __init__(self, space):
         W_TextIOBase.__init__(self, space)
         self.state = STATE_ZERO
+        self.w_encoder = None
         self.w_decoder = None
 
         self.decoded_chars = None   # buffer for text returned from decoder
@@ -744,7 +745,7 @@
             space.call_method(self.w_decoder, "reset")
             self.encoding_start_of_stream = True
         else:
-            space.call_method(self.w_encoder, "setstate",
+            space.call_method(self.w_decoder, "setstate",
                               space.newtuple([space.wrap(""),
                                               space.wrap(cookie.dec_flags)]))
 

diff --git a/pypy/module/_io/interp_io.py b/pypy/module/_io/interp_io.py
--- a/pypy/module/_io/interp_io.py
+++ b/pypy/module/_io/interp_io.py
@@ -1,9 +1,13 @@
 from pypy.interpreter.baseobjspace import ObjSpace, W_Root
+from pypy.interpreter.error import operationerrfmt, OperationError
+from pypy.interpreter.gateway import interp2app, Arguments, unwrap_spec
 from pypy.interpreter.typedef import (
     TypeDef, interp_attrproperty, generic_new_descr)
-from pypy.interpreter.gateway import interp2app, Arguments, unwrap_spec
 from pypy.module.exceptions.interp_exceptions import W_IOError
+from pypy.module._io.interp_fileio import W_FileIO
 from pypy.module._io.interp_iobase import W_IOBase
+from pypy.module._io.interp_textio import W_TextIOWrapper
+
 
 class W_BlockingIOError(W_IOError):
     def __init__(self, space):
@@ -24,11 +28,144 @@
     characters_written = interp_attrproperty('written', W_BlockingIOError),
     )
 
- at unwrap_spec(ObjSpace, Arguments)
-def open(space, __args__):
-    # XXX cheat!
-    w_pyio = space.call_method(space.builtin, '__import__',
-                             space.wrap("_pyio"))
-    w_func = space.getattr(w_pyio, space.wrap("open"))
-    return space.call_args(w_func, __args__)
+DEFAULT_BUFFER_SIZE = 8 * 1024
 
+ at unwrap_spec(ObjSpace, W_Root, str, int, "str_or_None", "str_or_None", "str_or_None", bool)
+def open(space, w_file, mode="r", buffering=-1, encoding=None, errors=None,
+    newline=None, closefd=True):
+    from pypy.module._io.interp_bufferedio import (W_BufferedRandom,
+        W_BufferedWriter, W_BufferedReader)
+
+    if not (space.isinstance_w(w_file, space.w_basestring) or
+        space.isinstance_w(w_file, space.w_int) or
+        space.isinstance_w(w_file, space.w_long)):
+        raise operationerrfmt(space.w_TypeError,
+            "invalid file: %s", space.str_w(space.repr(w_file))
+        )
+
+    reading = writing = appending = updating = text = binary = universal = False
+
+    uniq_mode = {}
+    for flag in mode:
+        uniq_mode[flag] = None
+    if len(uniq_mode) != len(mode):
+        raise operationerrfmt(space.w_ValueError,
+            "invalid mode: %s", mode
+        )
+    for flag in mode:
+        if flag == "r":
+            reading = True
+        elif flag == "w":
+            writing = True
+        elif flag == "a":
+            appending = True
+        elif flag == "+":
+            updating = True
+        elif flag == "t":
+            text = True
+        elif flag == "b":
+            binary = True
+        elif flag == "U":
+            universal = True
+            reading = True
+        else:
+            raise operationerrfmt(space.w_ValueError,
+                "invalid mode: %s", mode
+            )
+
+    rawmode = ""
+    if reading:
+        rawmode += "r"
+    if writing:
+        rawmode += "w"
+    if appending:
+        rawmode += "a"
+    if updating:
+        rawmode += "+"
+
+    if universal and (writing or appending):
+        raise OperationError(space.w_ValueError,
+            space.wrap("can't use U and writing mode at once")
+        )
+    if text and binary:
+        raise OperationError(space.w_ValueError,
+            space.wrap("can't have text and binary mode at once")
+        )
+    if reading + writing + appending > 1:
+        raise OperationError(space.w_ValueError,
+            space.wrap("must have exactly one of read/write/append mode")
+        )
+    if binary and encoding is not None:
+        raise OperationError(space.w_ValueError,
+            space.wrap("binary mode doesn't take an errors argument")
+        )
+    if binary and newline is not None:
+        raise OperationError(space.w_ValueError,
+            space.wrap("binary mode doesn't take a newline argument")
+        )
+    w_raw = space.call_function(
+        space.gettypefor(W_FileIO), w_file, space.wrap(rawmode), space.wrap(closefd)
+    )
+
+    isatty = space.is_true(space.call_method(w_raw, "isatty"))
+    line_buffering = buffering == 1 or (buffering < 0 and isatty)
+    if line_buffering:
+        buffering = -1
+
+    if buffering < 0:
+        buffering = DEFAULT_BUFFER_SIZE
+        """
+        XXX: implement me!
+        #ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
+            {
+                struct stat st;
+                long fileno;
+                PyObject *res = PyObject_CallMethod(raw, "fileno", NULL);
+                if (res == NULL)
+                    goto error;
+
+                fileno = PyInt_AsLong(res);
+                Py_DECREF(res);
+                if (fileno == -1 && PyErr_Occurred())
+                    goto error;
+
+                if (fstat(fileno, &st) >= 0)
+                    buffering = st.st_blksize;
+            }
+        #endif
+        """
+    if buffering < 0:
+        raise OperationError(space.w_ValueError,
+            space.wrap("invalid buffering size")
+        )
+
+    if buffering == 0:
+        if not binary:
+            raise OperationError(space.w_ValueError,
+                space.wrap("can't have unbuffered text I/O")
+            )
+        return w_raw
+
+    if updating:
+        buffer_cls = W_BufferedRandom
+    elif writing or appending:
+        buffer_cls = W_BufferedWriter
+    elif reading:
+        buffer_cls = W_BufferedReader
+    else:
+        raise operationerrfmt(space.w_ValueError, "unknown mode: '%s'", mode)
+    w_buffer = space.call_function(
+        space.gettypefor(buffer_cls), w_raw, space.wrap(buffering)
+    )
+    if binary:
+        return w_buffer
+
+    w_wrapper = space.call_function(space.gettypefor(W_TextIOWrapper),
+        w_buffer,
+        space.wrap(encoding),
+        space.wrap(errors),
+        space.wrap(newline),
+        space.wrap(line_buffering)
+    )
+    space.setattr(w_wrapper, space.wrap("mode"), space.wrap(mode))
+    return w_wrapper

diff --git a/pypy/module/_io/test/test_io.py b/pypy/module/_io/test/test_io.py
--- a/pypy/module/_io/test/test_io.py
+++ b/pypy/module/_io/test/test_io.py
@@ -1,6 +1,9 @@
+from __future__ import with_statement
+
 from pypy.conftest import gettestobjspace
 from pypy.tool.udir import udir
 
+
 class AppTestIoModule:
     def setup_class(cls):
         cls.space = gettestobjspace(usemodules=['_io'])
@@ -148,11 +151,21 @@
         assert f.mode == 'rb'
         f.close()
 
+        with io.open(self.tmpfile, "rt") as f:
+            assert f.mode == "rt"
+
     def test_open_writable(self):
         import io
         f = io.open(self.tmpfile, "w+b")
         f.close()
 
+    def test_valid_mode(self):
+        import io
+
+        raises(ValueError, io.open, self.tmpfile, "ww")
+        raises(ValueError, io.open, self.tmpfile, "rwa")
+        raises(ValueError, io.open, self.tmpfile, "b", newline="\n")
+
     def test_array_write(self):
         import _io, array
         a = array.array(b'i', range(10))
@@ -160,3 +173,26 @@
         with _io.open(self.tmpfile, "wb", 0) as f:
             assert f.write(a) == n
 
+
+    def test_seek_and_tell(self):
+        import _io
+
+        with _io.open(self.tmpfile, "wb") as f:
+            f.write("abcd")
+
+        with _io.open(self.tmpfile) as f:
+            decoded = f.read()
+
+        # seek positions
+        for i in xrange(len(decoded) + 1):
+            # read lenghts
+            for j in [1, 5, len(decoded) - i]:
+                with _io.open(self.tmpfile) as f:
+                    res = f.read(i)
+                    assert res == decoded[:i]
+                    cookie = f.tell()
+                    res = f.read(j)
+                    assert res == decoded[i:i + j]
+                    f.seek(cookie)
+                    res = f.read()
+                    assert res == decoded[i:]


More information about the Pypy-commit mailing list