[pypy-svn] r49538 - pypy/branch/pypy-interp-file/module/bz2
arigo at codespeak.net
arigo at codespeak.net
Fri Dec 7 21:16:59 CET 2007
Author: arigo
Date: Fri Dec 7 21:16:58 2007
New Revision: 49538
Removed:
pypy/branch/pypy-interp-file/module/bz2/app_bz2.py
Modified:
pypy/branch/pypy-interp-file/module/bz2/__init__.py
pypy/branch/pypy-interp-file/module/bz2/interp_bz2.py
Log:
Trying to fix the bz2 module:
* port BZ2File to interp-level. This is not as nice as it could be.
* fix various bugs in ReadBZ2Filter that for some reason were not
apparent before (probably differences in what stream methods get
called in answer to what file-level operation).
Modified: pypy/branch/pypy-interp-file/module/bz2/__init__.py
==============================================================================
--- pypy/branch/pypy-interp-file/module/bz2/__init__.py (original)
+++ pypy/branch/pypy-interp-file/module/bz2/__init__.py Fri Dec 7 21:16:58 2007
@@ -2,15 +2,18 @@
from pypy.interpreter.mixedmodule import MixedModule
class Module(MixedModule):
+ """The python bz2 module provides a comprehensive interface for
+the bz2 compression library. It implements a complete file
+interface, one shot (de)compression functions, and types for
+sequential (de)compression."""
+
interpleveldefs = {
'BZ2Compressor': 'interp_bz2.W_BZ2Compressor',
'BZ2Decompressor': 'interp_bz2.W_BZ2Decompressor',
'compress': 'interp_bz2.compress',
'decompress': 'interp_bz2.decompress',
- '_open_file_as_stream': 'interp_bz2.open_file_as_stream'
+ 'BZ2File': 'interp_bz2.W_BZ2File',
}
appleveldefs = {
- '__doc__': 'app_bz2.__doc__',
- 'BZ2File': 'app_bz2.BZ2File',
}
Modified: pypy/branch/pypy-interp-file/module/bz2/interp_bz2.py
==============================================================================
--- pypy/branch/pypy-interp-file/module/bz2/interp_bz2.py (original)
+++ pypy/branch/pypy-interp-file/module/bz2/interp_bz2.py Fri Dec 7 21:16:58 2007
@@ -5,7 +5,7 @@
from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.typedef import TypeDef, GetSetProperty
from pypy.interpreter.typedef import interp_attrproperty
-from pypy.interpreter.gateway import ObjSpace, W_Root, NoneNotWrapped, interp2app
+from pypy.interpreter.gateway import ObjSpace, W_Root, NoneNotWrapped, interp2app, Arguments
from pypy.rlib.streamio import Stream
from pypy.translator.tool.cbuild import ExternalCompilationInfo
import sys
@@ -161,12 +161,83 @@
return current_size + BIGCHUNK
return current_size + SMALLCHUNK
-def open_file_as_stream(space, path, mode="r", buffering=-1, compresslevel=9):
+# ____________________________________________________________
+#
+# 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 direct___init__(self, name, mode='r', buffering=0, 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, name, mode,
+ buffering, compresslevel)
+ fd = stream.try_to_find_file_descriptor()
+ self.fdopenstream(stream, fd, mode, name)
+
+ _exposed_method_names = []
+ W_File._decl.im_func(locals(), "__init__", ['self', str, str, int, int],
+ """Opens a BZ2-compressed file.""")
+
+ def bz2file__repr__(self):
+ if self.stream is None:
+ head = "closed"
+ else:
+ head = "open"
+ info = "%s bz2.BZ2File '%s', mode '%s'" % (head, self.name, self.mode)
+ return self.getrepr(self.space, info)
+ bz2file__repr__.unwrap_spec = ['self']
+
+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)
+descr_bz2file__new__.unwrap_spec = [ObjSpace, W_Root, Arguments]
+
+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',
+ '__weakref__'])
+
+extra_attrs = dict([(name, interp2app(getattr(W_BZ2File, 'file_' + name)))
+ for name in W_BZ2File._exposed_method_names])
+extra_attrs.update(dict([(name, W_File.typedef.rawdict[name])
+ for name in same_attributes_as_in_file]))
+
+W_BZ2File.typedef = TypeDef(
+ "BZ2File",
+ __doc__ = """\
+BZ2File(name [, mode='r', buffering=0, 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__),
+ __repr__ = interp2app(W_BZ2File.bz2file__repr__),
+ **extra_attrs)
+
+# ____________________________________________________________
+
+def open_bz2file_as_stream(space, 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
- from pypy.module._file.interp_file import wrap_oserror_as_ioerror, W_Stream
- from pypy.module._file.interp_file import is_mode_ok
- is_mode_ok(space, mode)
os_flags, universal, reading, writing, basemode = decode_mode(mode)
if reading and writing:
raise OperationError(space.w_ValueError,
@@ -174,10 +245,7 @@
if basemode == "a":
raise OperationError(space.w_ValueError,
space.wrap("cannot append to bz2 file"))
- try:
- stream = open_path_helper(path, os_flags, False)
- except OSError, exc:
- raise wrap_oserror_as_ioerror(space, exc)
+ stream = open_path_helper(path, os_flags, False)
if reading:
bz2stream = ReadBZ2Filter(space, stream, compresslevel)
else:
@@ -185,8 +253,7 @@
bz2stream = WriteBZ2Filter(space, stream, compresslevel)
stream = construct_stream_tower(bz2stream, buffering, universal, reading,
writing)
- return space.wrap(W_Stream(space, stream))
-open_file_as_stream.unwrap_spec = [ObjSpace, str, str, int, int]
+ return stream
class ReadBZ2Filter(Stream):
@@ -229,12 +296,18 @@
if not length:
break
else:
- raise NotImplementedError
+ # first measure the length by reading everything left
+ while len(self.read(65536)) > 0:
+ pass
+ pos = self.readlength + offset
+ self.seek(pos, 0)
def readall(self):
w_result = self.decompressor.decompress(self.stream.readall())
result = self.space.str_w(w_result)
self.readlength += len(result)
+ result = self.buffer + result
+ self.buffer = ''
return result
def read(self, n):
@@ -244,8 +317,12 @@
while not self.buffer:
if self.finished:
return ""
+ moredata = self.stream.read(n)
+ if not moredata:
+ self.finished = True
+ return ""
try:
- w_read = self.decompressor.decompress(self.stream.read(n))
+ w_read = self.decompressor.decompress(moredata)
except OperationError, e:
if e.match(self.space, self.space.w_EOFError):
self.finished = True
@@ -507,7 +584,9 @@
after the end of stream is found, EOFError will be raised. If any data
was found after the end of stream, it'll be ignored and saved in
unused_data attribute."""
-
+
+ if data == '':
+ return self.space.wrap('')
if not self.running:
raise OperationError(self.space.w_EOFError,
self.space.wrap("end of stream was already found"))
More information about the Pypy-commit
mailing list