Author: Amaury Forgeot d'Arc <[email protected]>
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
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit