[pypy-commit] pypy py3k: Fix BZ2File by importing the applevel version from CPython 3.3.

amauryfa noreply at buildbot.pypy.org
Sat Dec 17 23:01:13 CET 2011


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3k
Changeset: r50645:8d890adadd94
Date: 2011-12-17 22:59 +0100
http://bitbucket.org/pypy/pypy/changeset/8d890adadd94/

Log:	Fix BZ2File by importing the applevel version from CPython 3.3.

diff --git a/pypy/module/bz2/__init__.py b/pypy/module/bz2/__init__.py
--- a/pypy/module/bz2/__init__.py
+++ b/pypy/module/bz2/__init__.py
@@ -12,8 +12,8 @@
         'BZ2Decompressor': 'interp_bz2.W_BZ2Decompressor',
         'compress': 'interp_bz2.compress',
         'decompress': 'interp_bz2.decompress',
-        'BZ2File': 'interp_bz2.W_BZ2File',
     }
 
     appleveldefs = {
+        'BZ2File': 'app_bz2file.BZ2File',
     }
diff --git a/pypy/module/bz2/app_bz2file.py b/pypy/module/bz2/app_bz2file.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/bz2/app_bz2file.py
@@ -0,0 +1,370 @@
+"""Interface to the libbzip2 compression library.
+
+This file is an almost exact copy of CPython3.3 Lib/bz2.py.
+"""
+
+import io
+import threading
+
+from bz2 import BZ2Compressor, BZ2Decompressor
+
+
+_MODE_CLOSED   = 0
+_MODE_READ     = 1
+_MODE_READ_EOF = 2
+_MODE_WRITE    = 3
+
+_BUFFER_SIZE = 8192
+
+
+class BZ2File(io.BufferedIOBase):
+
+    """A file object providing transparent bzip2 (de)compression.
+
+    A BZ2File can act as a wrapper for an existing file object, or refer
+    directly to a named file on disk.
+
+    Note that BZ2File provides a *binary* file interface - data read is
+    returned as bytes, and data to be written should be given as bytes.
+    """
+
+    def __init__(self, filename=None, mode="r", buffering=None,
+                 compresslevel=9, fileobj=None):
+        """Open a bzip2-compressed file.
+
+        If filename is given, open the named file. Otherwise, operate on
+        the file object given by fileobj. Exactly one of these two
+        parameters should be provided.
+
+        mode can be 'r' for reading (default), or 'w' for writing.
+
+        buffering is ignored. Its use is deprecated.
+
+        If mode is 'w', compresslevel can be a number between 1 and 9
+        specifying the level of compression: 1 produces the least
+        compression, and 9 (default) produces the most compression.
+        """
+        # This lock must be recursive, so that BufferedIOBase's
+        # readline(), readlines() and writelines() don't deadlock.
+        self._lock = threading.RLock()
+        self._fp = None
+        self._closefp = False
+        self._mode = _MODE_CLOSED
+        self._pos = 0
+        self._size = -1
+
+        if not (1 <= compresslevel <= 9):
+            raise ValueError("compresslevel must be between 1 and 9")
+
+        if mode in ("", "r", "rb"):
+            mode = "rb"
+            mode_code = _MODE_READ
+            self._decompressor = BZ2Decompressor()
+            self._buffer = None
+        elif mode in ("w", "wb"):
+            mode = "wb"
+            mode_code = _MODE_WRITE
+            self._compressor = BZ2Compressor(compresslevel)
+        elif mode in ("a", "ab"):
+            mode = "ab"
+            mode_code = _MODE_WRITE
+            self._compressor = BZ2Compressor(compresslevel)
+        else:
+            raise ValueError("Invalid mode: {!r}".format(mode))
+
+        if filename is not None and fileobj is None:
+            self._fp = open(filename, mode)
+            self._closefp = True
+            self._mode = mode_code
+        elif fileobj is not None and filename is None:
+            self._fp = fileobj
+            self._mode = mode_code
+        else:
+            raise ValueError("Must give exactly one of filename and fileobj")
+
+    def close(self):
+        """Flush and close the file.
+
+        May be called more than once without error. Once the file is
+        closed, any other operation on it will raise a ValueError.
+        """
+        with self._lock:
+            if self._mode == _MODE_CLOSED:
+                return
+            try:
+                if self._mode in (_MODE_READ, _MODE_READ_EOF):
+                    self._decompressor = None
+                elif self._mode == _MODE_WRITE:
+                    self._fp.write(self._compressor.flush())
+                    self._compressor = None
+            finally:
+                try:
+                    if self._closefp:
+                        self._fp.close()
+                finally:
+                    self._fp = None
+                    self._closefp = False
+                    self._mode = _MODE_CLOSED
+                    self._buffer = None
+
+    @property
+    def closed(self):
+        """True if this file is closed."""
+        return self._mode == _MODE_CLOSED
+
+    def fileno(self):
+        """Return the file descriptor for the underlying file."""
+        self._check_not_closed()
+        return self._fp.fileno()
+
+    def seekable(self):
+        """Return whether the file supports seeking."""
+        return self.readable()
+
+    def readable(self):
+        """Return whether the file was opened for reading."""
+        self._check_not_closed()
+        return self._mode in (_MODE_READ, _MODE_READ_EOF)
+
+    def writable(self):
+        """Return whether the file was opened for writing."""
+        self._check_not_closed()
+        return self._mode == _MODE_WRITE
+
+    # Mode-checking helper functions.
+
+    def _check_not_closed(self):
+        if self.closed:
+            raise ValueError("I/O operation on closed file")
+
+    def _check_can_read(self):
+        if not self.readable():
+            raise io.UnsupportedOperation("File not open for reading")
+
+    def _check_can_write(self):
+        if not self.writable():
+            raise io.UnsupportedOperation("File not open for writing")
+
+    def _check_can_seek(self):
+        if not self.seekable():
+            raise io.UnsupportedOperation("Seeking is only supported "
+                                          "on files open for reading")
+
+    # Fill the readahead buffer if it is empty. Returns False on EOF.
+    def _fill_buffer(self):
+        if self._buffer:
+            return True
+
+        if self._decompressor.unused_data:
+            rawblock = self._decompressor.unused_data
+        else:
+            rawblock = self._fp.read(_BUFFER_SIZE)
+
+        if not rawblock:
+            if self._decompressor.eof:
+                self._mode = _MODE_READ_EOF
+                self._size = self._pos
+                return False
+            else:
+                raise EOFError("Compressed file ended before the "
+                               "end-of-stream marker was reached")
+
+        # Continue to next stream.
+        if self._decompressor.eof:
+            self._decompressor = BZ2Decompressor()
+
+        self._buffer = self._decompressor.decompress(rawblock)
+        return True
+
+    # Read data until EOF.
+    # If return_data is false, consume the data without returning it.
+    def _read_all(self, return_data=True):
+        blocks = []
+        while self._fill_buffer():
+            if return_data:
+                blocks.append(self._buffer)
+            self._pos += len(self._buffer)
+            self._buffer = None
+        if return_data:
+            return b"".join(blocks)
+
+    # Read a block of up to n bytes.
+    # If return_data is false, consume the data without returning it.
+    def _read_block(self, n, return_data=True):
+        blocks = []
+        while n > 0 and self._fill_buffer():
+            if n < len(self._buffer):
+                data = self._buffer[:n]
+                self._buffer = self._buffer[n:]
+            else:
+                data = self._buffer
+                self._buffer = None
+            if return_data:
+                blocks.append(data)
+            self._pos += len(data)
+            n -= len(data)
+        if return_data:
+            return b"".join(blocks)
+
+    def peek(self, n=0):
+        """Return buffered data without advancing the file position.
+
+        Always returns at least one byte of data, unless at EOF.
+        The exact number of bytes returned is unspecified.
+        """
+        with self._lock:
+            self._check_can_read()
+            if self._mode == _MODE_READ_EOF or not self._fill_buffer():
+                return b""
+            return self._buffer
+
+    def read(self, size=-1):
+        """Read up to size uncompressed bytes from the file.
+
+        If size is negative or omitted, read until EOF is reached.
+        Returns b'' if the file is already at EOF.
+        """
+        with self._lock:
+            self._check_can_read()
+            if self._mode == _MODE_READ_EOF or size == 0:
+                return b""
+            elif size < 0:
+                return self._read_all()
+            else:
+                return self._read_block(size)
+
+    def read1(self, size=-1):
+        """Read up to size uncompressed bytes with at most one read
+        from the underlying stream.
+
+        Returns b'' if the file is at EOF.
+        """
+        with self._lock:
+            self._check_can_read()
+            if (size == 0 or self._mode == _MODE_READ_EOF or
+                not self._fill_buffer()):
+                return b""
+            if 0 < size < len(self._buffer):
+                data = self._buffer[:size]
+                self._buffer = self._buffer[size:]
+            else:
+                data = self._buffer
+                self._buffer = None
+            self._pos += len(data)
+            return data
+
+    def readinto(self, b):
+        """Read up to len(b) bytes into b.
+
+        Returns the number of bytes read (0 for EOF).
+        """
+        with self._lock:
+            return io.BufferedIOBase.readinto(self, b)
+
+    def readline(self, size=-1):
+        """Read a line of uncompressed bytes from the file.
+
+        The terminating newline (if present) is retained. If size is
+        non-negative, no more than size bytes will be read (in which
+        case the line may be incomplete). Returns b'' if already at EOF.
+        """
+        if not hasattr(size, "__index__"):
+            raise TypeError("Integer argument expected")
+        size = size.__index__()
+        with self._lock:
+            return io.BufferedIOBase.readline(self, size)
+
+    def readlines(self, size=-1):
+        """Read a list of lines of uncompressed bytes from the file.
+
+        size can be specified to control the number of lines read: no
+        further lines will be read once the total size of the lines read
+        so far equals or exceeds size.
+        """
+        if not hasattr(size, "__index__"):
+            raise TypeError("Integer argument expected")
+        size = size.__index__()
+        with self._lock:
+            return io.BufferedIOBase.readlines(self, size)
+
+    def write(self, data):
+        """Write a byte string to the file.
+
+        Returns the number of uncompressed bytes written, which is
+        always len(data). Note that due to buffering, the file on disk
+        may not reflect the data written until close() is called.
+        """
+        with self._lock:
+            self._check_can_write()
+            compressed = self._compressor.compress(data)
+            self._fp.write(compressed)
+            self._pos += len(data)
+            return len(data)
+
+    def writelines(self, seq):
+        """Write a sequence of byte strings to the file.
+
+        Returns the number of uncompressed bytes written.
+        seq can be any iterable yielding byte strings.
+
+        Line separators are not added between the written byte strings.
+        """
+        with self._lock:
+            return io.BufferedIOBase.writelines(self, seq)
+
+    # Rewind the file to the beginning of the data stream.
+    def _rewind(self):
+        self._fp.seek(0, 0)
+        self._mode = _MODE_READ
+        self._pos = 0
+        self._decompressor = BZ2Decompressor()
+        self._buffer = None
+
+    def seek(self, offset, whence=0):
+        """Change the file position.
+
+        The new position is specified by offset, relative to the
+        position indicated by whence. Values for whence are:
+
+            0: start of stream (default); offset must not be negative
+            1: current stream position
+            2: end of stream; offset must not be positive
+
+        Returns the new file position.
+
+        Note that seeking is emulated, so depending on the parameters,
+        this operation may be extremely slow.
+        """
+        with self._lock:
+            self._check_can_seek()
+
+            # Recalculate offset as an absolute file position.
+            if whence == 0:
+                pass
+            elif whence == 1:
+                offset = self._pos + offset
+            elif whence == 2:
+                # Seeking relative to EOF - we need to know the file's size.
+                if self._size < 0:
+                    self._read_all(return_data=False)
+                offset = self._size + offset
+            else:
+                raise ValueError("Invalid value for whence: {}".format(whence))
+
+            # Make it so that offset is the number of bytes to skip forward.
+            if offset < self._pos:
+                self._rewind()
+            else:
+                offset -= self._pos
+
+            # Read and discard data until we reach the desired position.
+            if self._mode != _MODE_READ_EOF:
+                self._read_block(offset, return_data=False)
+
+            return self._pos
+
+    def tell(self):
+        """Return the current file position."""
+        with self._lock:
+            self._check_not_closed()
+            return self._pos
diff --git a/pypy/module/bz2/interp_bz2.py b/pypy/module/bz2/interp_bz2.py
--- a/pypy/module/bz2/interp_bz2.py
+++ b/pypy/module/bz2/interp_bz2.py
@@ -2,11 +2,11 @@
 from pypy.rpython.tool import rffi_platform as platform
 from pypy.rpython.lltypesystem import rffi
 from pypy.rpython.lltypesystem import lltype
-from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.interpreter.error import OperationError
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.typedef import TypeDef, interp_attrproperty_bytes
+from pypy.interpreter.typedef import GetSetProperty
 from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.rlib.streamio import Stream
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.translator.platform import platform as compiler
 from pypy.rlib.rarithmetic import intmask, r_longlong
@@ -232,275 +232,6 @@
     def __exit__(self, *args):
         self.free()
 
-# ____________________________________________________________
-#
-# Make the BZ2File type by internally inheriting from W_File.
-# XXX this depends on internal details of W_File to work properly.
-
-from pypy.module._file.interp_file import W_File
-
-class W_BZ2File(W_File):
-
-    def check_mode_ok(self, mode):
-        if (not mode or mode[0] not in ['r', 'w', 'a', 'U']):
-            space = self.space
-            raise operationerrfmt(space.w_ValueError,
-                                  "invalid mode: '%s'", mode)
-
-    @unwrap_spec(mode=str, buffering=int, compresslevel=int)
-    def direct_bz2__init__(self, w_name, mode='r', buffering=-1,
-                           compresslevel=9):
-        self.direct_close()
-        # the stream should always be opened in binary mode
-        if "b" not in mode:
-            mode = mode + "b"
-        self.check_mode_ok(mode)
-        stream = open_bz2file_as_stream(self.space, w_name, mode,
-                                        buffering, compresslevel)
-        fd = stream.try_to_find_file_descriptor()
-        self.fdopenstream(stream, fd, mode, w_name)
-
-    _exposed_method_names = []
-    W_File._decl.im_func(locals(), "bz2__init__",
-                         """Opens a BZ2-compressed file.""")
-    # XXX ^^^ hacking hacking... can't just use the name "__init__" again
-    # because the RTyper is confused about the two direct__init__() with
-    # a different signature, confusion caused by the fact that
-    # W_File.file__init__() would appear to contain an indirect call to
-    # one of the two versions of direct__init__().
-
-    def file_bz2__repr__(self):
-        if self.stream is None:
-            head = "closed"
-        else:
-            head = "open"
-        w_name = self.w_name
-        if w_name is None:
-            w_name = self.space.wrap('?')
-        info = "%s bz2.BZ2File %s, mode '%s'" % (head, self.getdisplayname(),
-                                                 self.mode)
-        return self.getrepr(self.space, info)
-
-def descr_bz2file__new__(space, w_subtype, __args__):
-    bz2file = space.allocate_instance(W_BZ2File, w_subtype)
-    W_BZ2File.__init__(bz2file, space)
-    return space.wrap(bz2file)
-
-same_attributes_as_in_file = list(W_File._exposed_method_names)
-same_attributes_as_in_file.remove('__init__')
-same_attributes_as_in_file.extend([
-    'name', 'mode', 'encoding', 'closed', 'newlines', 'softspace',
-    'writelines', '__exit__', '__weakref__'])
-
-W_BZ2File.typedef = TypeDef(
-    "BZ2File",
-    __doc__ = """\
-BZ2File(name [, mode='r', buffering=-1, compresslevel=9]) -> file object
-
-Open a bz2 file. The mode can be 'r' or 'w', for reading (default) or
-writing. When opened for writing, the file will be created if it doesn't
-exist, and truncated otherwise. If the buffering argument is given, 0 means
-unbuffered, and larger numbers specify the buffer size. If compresslevel
-is given, must be a number between 1 and 9.
-
-Add a 'U' to mode to open the file for input with universal newline
-support. Any line ending in the input file will be seen as a '\\n' in
-Python. Also, a file so opened gains the attribute 'newlines'; the value
-for this attribute is one of None (no newline read yet), '\\r', '\\n',
-'\\r\\n' or a tuple containing all the newline types seen. Universal
-newlines are available only when reading.""",
-    __new__  = interp2app(descr_bz2file__new__),
-    __init__ = interp2app(W_BZ2File.file_bz2__init__),
-    __repr__ = interp2app(W_BZ2File.file_bz2__repr__),
-    **dict([(name, W_File.typedef.rawdict[name])
-            for name in same_attributes_as_in_file]))
-
-# ____________________________________________________________
-
-def open_bz2file_as_stream(space, w_path, mode="r", buffering=-1,
-                           compresslevel=9):
-    from pypy.rlib.streamio import decode_mode, open_path_helper
-    from pypy.rlib.streamio import construct_stream_tower
-    os_flags, universal, reading, writing, basemode, binary = decode_mode(mode)
-    if reading and writing:
-        raise OperationError(space.w_ValueError,
-                             space.wrap("cannot open in read-write mode"))
-    if basemode == "a":
-        raise OperationError(space.w_ValueError,
-                             space.wrap("cannot append to bz2 file"))
-    stream = open_path_helper(space.str_w(w_path), os_flags, False)
-    if reading:
-        bz2stream = ReadBZ2Filter(space, stream, buffering)
-        buffering = 0     # by construction, the ReadBZ2Filter acts like
-                          # a read buffer too - no need for another one
-    else:
-        assert writing
-        bz2stream = WriteBZ2Filter(space, stream, compresslevel)
-    stream = construct_stream_tower(bz2stream, buffering, universal, reading,
-                                    writing, binary)
-    return stream
-
-
-class ReadBZ2Filter(Stream):
-
-    """Standard I/O stream filter that decompresses the stream with bz2."""
-
-    def __init__(self, space, stream, buffering):
-        self.space = space
-        self.stream = stream
-        self.decompressor = W_BZ2Decompressor(space)
-        self.readlength = r_longlong(0)
-        self.buffer = ""
-        self.pos = 0
-        self.finished = False
-        if buffering < 1024:
-            buffering = 1024   # minimum amount of compressed data read at once
-        self.buffering = buffering
-
-    def close(self):
-        self.stream.close()
-
-    def tell(self):
-        return self.readlength
-
-    def seek(self, offset, whence):
-        READMAX = 2**18   # 256KB
-
-        # Make offset relative to the start of the file
-        if whence == 2:
-            # Read everything to arrive at the end
-            while len(self.read(READMAX)) > 0:
-                pass
-            offset += self.readlength
-        elif whence == 1:
-            offset += self.readlength
-        elif whence == 0:
-            pass
-        else:
-            raise operationerrfmt(self.space.w_ValueError,
-                                  "Invalid value for whence: %d", whence)
-
-        # Make offset relative to the current pos
-        # Rewind iff necessary
-        if offset < self.readlength:
-            self.stream.seek(0, 0)
-            self.decompressor = W_BZ2Decompressor(self.space)
-            self.readlength = r_longlong(0)
-            self.pos = 0
-            self.buffer = ""
-            self.finished = False
-        else:
-            offset -= self.readlength
-
-        # Seek
-        read = r_longlong(0)
-        while read < offset:
-            count = offset - read
-            if count < READMAX:
-                count = intmask(count)
-            else:
-                count = READMAX
-            length = len(self.read(count))
-            if not length:
-                break
-            read += length
-
-    def readall(self):
-        w_result = self.decompressor.decompress(self.stream.readall())
-        if self.decompressor.running:
-            raise OperationError(self.space.w_EOFError,
-                                 self.space.wrap("compressed file ended before the logical end-of-the-stream was detected"))
-        result = self.space.bytes_w(w_result)
-        self.readlength += len(result)
-        if len(self.buffer) != self.pos:
-            pos = self.pos
-            assert pos >= 0
-            result = self.buffer[pos:] + result
-        self.buffer = ''
-        self.pos = 0
-        return result
-
-    def read(self, n):
-        # XXX not nice
-        if n <= 0:
-            return ''
-        while self.pos == len(self.buffer):
-            if self.finished:
-                return ""
-            moredata = self.stream.read(max(self.buffering, n))
-            if not moredata:
-                self.finished = True
-                return ""
-            try:
-                w_read = self.decompressor.decompress(moredata)
-            except OperationError, e:
-                if e.match(self.space, self.space.w_EOFError):
-                    self.finished = True
-                    return ""
-                raise
-            self.buffer = self.space.bytes_w(w_read)
-            self.pos = 0
-        if len(self.buffer) - self.pos >= n:
-            pos = self.pos
-            assert pos >= 0
-            result = self.buffer[pos:pos + n]
-            self.pos += n
-        else:
-            pos = self.pos
-            assert pos >= 0
-            result = self.buffer[pos:]
-            self.pos = 0
-            self.buffer = ""
-        self.readlength += len(result)
-        return result
-
-    def peek(self):
-        pos = self.pos
-        assert pos >= 0
-        return self.buffer[pos:]
-
-    def try_to_find_file_descriptor(self):
-        return self.stream.try_to_find_file_descriptor()
-
-    def write(self, s):
-        raise OperationError(self.space.w_IOError,
-                             self.space.wrap("file is not ready for writing"))
-
-class WriteBZ2Filter(Stream):
-    """Standard I/O stream filter that compresses the stream with bz2."""
-
-    def __init__(self, space, stream, compresslevel):
-        self.stream = stream
-        self.space = space
-        self.compressor = W_BZ2Compressor(space, compresslevel)
-        self.writtenlength = 0
-
-    def close(self):
-        self.stream.write(self.space.bytes_w(self.compressor.flush()))
-        self.stream.close()
-
-    def write(self, data):
-        self.stream.write(self.space.bytes_w(self.compressor.compress(data)))
-        self.writtenlength += len(data)
-
-    def tell(self):
-        return self.writtenlength
-
-    def seek(self, offset, whence):
-        raise OperationError(self.space.w_IOError,
-                             self.space.wrap("seek works only while reading"))
-
-    def read(self, n):
-        raise OperationError(self.space.w_IOError,
-                             self.space.wrap("file is not ready for reading"))
-
-    def readall(self):
-        raise OperationError(self.space.w_IOError,
-                             self.space.wrap("file is not ready for reading"))
-
-    def try_to_find_file_descriptor(self):
-        return self.stream.try_to_find_file_descriptor()
-
 @unwrap_spec(compresslevel=int)
 def descr_compressor__new__(space, w_subtype, compresslevel=9):
     x = space.allocate_instance(W_BZ2Compressor, w_subtype)
@@ -639,6 +370,12 @@
         BZ2_bzDecompressEnd(self.bzs)
         lltype.free(self.bzs, flavor='raw')
 
+    def eof_w(self, space):
+        if self.running:
+            return space.w_False
+        else:
+            return space.w_True
+
     @unwrap_spec(data='bufferstr')
     def decompress(self, data):
         """decompress(data) -> string
@@ -691,6 +428,7 @@
     __doc__ = W_BZ2Decompressor.__doc__,
     __new__ = interp2app(descr_decompressor__new__),
     unused_data = interp_attrproperty_bytes("unused_data", W_BZ2Decompressor),
+    eof = GetSetProperty(W_BZ2Decompressor.eof_w),
     decompress = interp2app(W_BZ2Decompressor.decompress),
 )
 
diff --git a/pypy/module/bz2/test/test_bz2_file.py b/pypy/module/bz2/test/test_bz2_file.py
--- a/pypy/module/bz2/test/test_bz2_file.py
+++ b/pypy/module/bz2/test/test_bz2_file.py
@@ -50,7 +50,7 @@
     # XXX for unknown reasons, we cannot do allocation checks, as sth is
     # keeping those objects alive (BZ2File objects)
     def setup_class(cls):
-        space = gettestobjspace(usemodules=('bz2',))
+        space = gettestobjspace(usemodules=('bz2', 'thread'))
         cls.space = space
         cls.w_TEXT = space.wrapbytes(TEXT)
         cls.w_DATA = space.wrapbytes(DATA)
@@ -67,10 +67,6 @@
         from bz2 import BZ2File
         
         bz2f = BZ2File(self.temppath, mode="w")
-        assert bz2f.name == self.temppath
-        assert bz2f.newlines == None
-        assert bz2f.mode == "wb"
-        assert bz2f.softspace == False
         assert bz2f.closed == False
         bz2f.close()
         assert bz2f.closed == True
@@ -83,7 +79,7 @@
         # XXX the following is fine, currently:
         #raises(ValueError, BZ2File, self.temppath, mode='ww')
         
-        BZ2File(self.temppath, mode='wU', buffering=0, compresslevel=8)
+        BZ2File(self.temppath, mode='w', buffering=0, compresslevel=8)
         BZ2File(self.temppath, mode='wb')
         # a large buf size
         BZ2File(self.temppath, mode='w', buffering=4096)
@@ -118,7 +114,7 @@
         
         # hack to create a foo file
         open(self.temppath, "w").close()
-        
+
         # cannot seek if close
         bz2f = BZ2File(self.temppath, mode='r')
         bz2f.close()
@@ -132,10 +128,11 @@
         bz2f = BZ2File(self.temppath, mode='r')
         raises(TypeError, bz2f.seek)
         raises(TypeError, bz2f.seek, "foo")
-        raises(TypeError, bz2f.seek, 0, "foo")
-        
+        raises((TypeError, ValueError), bz2f.seek, 0, "foo")
+
         bz2f.seek(0)
         assert bz2f.tell() == 0
+        bz2f.close()
         del bz2f   # delete from this frame, which is captured in the traceback
 
     def test_open_close_del(self):
@@ -151,19 +148,6 @@
         from bz2 import BZ2File
         raises(IOError, BZ2File, "/non/existent/path")
     
-    def test_open_mode_U(self):
-        # bug #1194181: bz2.BZ2File opened for write with mode "U"
-        from bz2 import BZ2File
-        self.create_temp_file()
-        
-        bz2f = BZ2File(self.temppath, "U")
-        bz2f.close()
-        f = open(self.temppath)
-        f.seek(0, 2)
-        f.read()
-        assert f.tell() == len(self.DATA)
-        f.close()
-    
     def test_seek_forward(self):
         from bz2 import BZ2File
         self.create_temp_file()
@@ -201,7 +185,7 @@
         bz2f = BZ2File(self.temppath)
         bz2f.seek(150000)
         assert bz2f.tell() == len(self.TEXT)
-        assert bz2f.read() == ""
+        assert bz2f.read() == b""
         bz2f.close()
     
     def test_seek_post_end_twice(self):
@@ -212,7 +196,7 @@
         bz2f.seek(150000)
         bz2f.seek(150000)
         assert bz2f.tell() == len(self.TEXT)
-        assert bz2f.read() == ""
+        assert bz2f.read() == b""
         bz2f.close()
 
     def test_seek_pre_start(self):
@@ -261,7 +245,7 @@
         self.create_broken_temp_file()
         bz2f = BZ2File(self.temppath)
         raises(EOFError, bz2f.read)
-        del bz2f   # delete from this frame, which is captured in the traceback
+        bz2f.close()
 
     def test_subsequent_read_broken_file(self):
         from bz2 import BZ2File
@@ -275,19 +259,19 @@
                 raise Exception("should generate EOFError earlier")
         except EOFError:
             pass
-        del bz2f   # delete from this frame, which is captured in the traceback
+        bz2f.close()
 
     def test_read_chunk9(self):
         from bz2 import BZ2File
         self.create_temp_file()
         
         bz2f = BZ2File(self.temppath)
-        text_read = ""
+        text_read = b""
         while True:
             data = bz2f.read(9) # 9 doesn't divide evenly into data length
             if not data:
                 break
-            text_read = "%s%s" % (text_read, data)
+            text_read += data
         assert text_read == self.TEXT
         bz2f.close()
 
@@ -299,25 +283,6 @@
         assert bz2f.read(100) == self.TEXT[:100]
         bz2f.close()
 
-    def test_universal_newlines_lf(self):
-        from bz2 import BZ2File
-        self.create_temp_file()
-        
-        bz2f = BZ2File(self.temppath, "rU")
-        assert bz2f.read() == self.TEXT
-        assert bz2f.newlines == "\n"
-        bz2f.close()
-
-    def test_universal_newlines_crlf(self):
-        from bz2 import BZ2File
-        self.create_temp_file(crlf=True)
-        
-        bz2f = BZ2File(self.temppath, "rU")
-        data = bz2f.read()
-        assert data == self.TEXT
-        assert bz2f.newlines == "\r\n"
-        bz2f.close()
-
     def test_readlines(self):
         from bz2 import BZ2File
         from io import BytesIO
@@ -340,35 +305,6 @@
         assert list(iter(bz2f)) == sio.readlines()
         bz2f.close()
         
-    def test_xreadlines(self):
-        from bz2 import BZ2File
-        from io import BytesIO
-        self.create_temp_file()
-        
-        bz2f = BZ2File(self.temppath)
-        sio = BytesIO(self.TEXT)
-        assert list(bz2f.xreadlines()) == sio.readlines()
-        bz2f.close()
-
-    def test_readlines_bug_1191043(self):
-        # readlines()/xreadlines() for files containing no newline
-        from bz2 import BZ2File
-        
-        DATA = b'BZh91AY&SY\xd9b\x89]\x00\x00\x00\x03\x80\x04\x00\x02\x00\x0c\x00 \x00!\x9ah3M\x13<]\xc9\x14\xe1BCe\x8a%t'
-        f = open(self.temppath, "wb")
-        f.write(DATA)
-        f.close()
-        
-        bz2f = BZ2File(self.temppath)
-        lines = bz2f.readlines()
-        bz2f.close()
-        assert lines == ['Test']
-
-        bz2f = BZ2File(self.temppath)
-        xlines = list(bz2f.xreadlines())
-        bz2f.close()
-        assert xlines == ['Test']
-    
     def test_write(self):
         from bz2 import BZ2File
 


More information about the pypy-commit mailing list