Staging
v0.8.1
https://github.com/python/cpython
Revision 958980190cd04b819d592dd6654df72cd1df3edd authored by Georg Brandl on 05 April 2009, 21:23:27 UTC, committed by Georg Brandl on 05 April 2009, 21:23:27 UTC
........
  r70869 | georg.brandl | 2009-03-31 21:14:42 +0200 (Di, 31 Mär 2009) | 1 line

  Fix-up unwanted change.
........
  r70883 | georg.brandl | 2009-03-31 22:41:08 +0200 (Di, 31 Mär 2009) | 1 line

  #1674032: return value of flag from Event.wait(). OKed by Guido.
........
  r70901 | georg.brandl | 2009-03-31 23:40:24 +0200 (Di, 31 Mär 2009) | 2 lines

  Remove warning about pending Win9x support removal.
........
  r70903 | georg.brandl | 2009-03-31 23:45:18 +0200 (Di, 31 Mär 2009) | 1 line

  #1676135: remove trailing slashes from --prefix argument.
........
  r70951 | georg.brandl | 2009-04-01 16:02:27 +0200 (Mi, 01 Apr 2009) | 1 line

  Add Maksim, who worked on several issues at the sprint.
........
  r70992 | georg.brandl | 2009-04-01 23:00:55 +0200 (Mi, 01 Apr 2009) | 1 line

  #4572: add SEEK_* values as constants in io.py.
........
  r70993 | georg.brandl | 2009-04-01 23:05:44 +0200 (Mi, 01 Apr 2009) | 1 line

  Add NEWS item.
........
  r70994 | georg.brandl | 2009-04-01 23:06:30 +0200 (Mi, 01 Apr 2009) | 1 line

  Revert accidental checkin.
........
  r71006 | georg.brandl | 2009-04-02 01:32:17 +0200 (Do, 02 Apr 2009) | 1 line

  Cache the f_locals dict of the current frame, since every access to frame.f_locals overrides its contents with the real locals which undoes modifications made by the debugging user.
........
  r71019 | georg.brandl | 2009-04-02 04:00:01 +0200 (Do, 02 Apr 2009) | 1 line

  Fix test_doctest, missed two assignments to curframe.
........
  r71024 | georg.brandl | 2009-04-02 04:47:44 +0200 (Do, 02 Apr 2009) | 4 lines

  In PyErr_GivenExceptionMatches, temporarily bump the recursion
  limit, so that in the most common case PyObject_IsSubclass will
  not raise a recursion error we have to ignore anyway.
........
1 parent 9b08e05
Raw File
Tip revision: 958980190cd04b819d592dd6654df72cd1df3edd authored by Georg Brandl on 05 April 2009, 21:23:27 UTC
Blocked revisions 70869,70883,70901,70903,70951,70992-70994,71006,71019,71024 via svnmerge
Tip revision: 9589801
chunk.py
"""Simple class to read IFF chunks.

An IFF chunk (used in formats such as AIFF, TIFF, RMFF (RealMedia File
Format)) has the following structure:

+----------------+
| ID (4 bytes)   |
+----------------+
| size (4 bytes) |
+----------------+
| data           |
| ...            |
+----------------+

The ID is a 4-byte string which identifies the type of chunk.

The size field (a 32-bit value, encoded using big-endian byte order)
gives the size of the whole chunk, including the 8-byte header.

Usually an IFF-type file consists of one or more chunks.  The proposed
usage of the Chunk class defined here is to instantiate an instance at
the start of each chunk and read from the instance until it reaches
the end, after which a new instance can be instantiated.  At the end
of the file, creating a new instance will fail with a EOFError
exception.

Usage:
while True:
    try:
        chunk = Chunk(file)
    except EOFError:
        break
    chunktype = chunk.getname()
    while True:
        data = chunk.read(nbytes)
        if not data:
            pass
        # do something with data

The interface is file-like.  The implemented methods are:
read, close, seek, tell, isatty.
Extra methods are: skip() (called by close, skips to the end of the chunk),
getname() (returns the name (ID) of the chunk)

The __init__ method has one required argument, a file-like object
(including a chunk instance), and one optional argument, a flag which
specifies whether or not chunks are aligned on 2-byte boundaries.  The
default is 1, i.e. aligned.
"""

class Chunk:
    def __init__(self, file, align=True, bigendian=True, inclheader=False):
        import struct
        self.closed = False
        self.align = align      # whether to align to word (2-byte) boundaries
        if bigendian:
            strflag = '>'
        else:
            strflag = '<'
        self.file = file
        self.chunkname = file.read(4)
        if len(self.chunkname) < 4:
            raise EOFError
        try:
            self.chunksize = struct.unpack(strflag+'L', file.read(4))[0]
        except struct.error:
            raise EOFError
        if inclheader:
            self.chunksize = self.chunksize - 8 # subtract header
        self.size_read = 0
        try:
            self.offset = self.file.tell()
        except (AttributeError, IOError):
            self.seekable = False
        else:
            self.seekable = True

    def getname(self):
        """Return the name (ID) of the current chunk."""
        return self.chunkname

    def getsize(self):
        """Return the size of the current chunk."""
        return self.chunksize

    def close(self):
        if not self.closed:
            self.skip()
            self.closed = True

    def isatty(self):
        if self.closed:
            raise ValueError, "I/O operation on closed file"
        return False

    def seek(self, pos, whence=0):
        """Seek to specified position into the chunk.
        Default position is 0 (start of chunk).
        If the file is not seekable, this will result in an error.
        """

        if self.closed:
            raise ValueError, "I/O operation on closed file"
        if not self.seekable:
            raise IOError, "cannot seek"
        if whence == 1:
            pos = pos + self.size_read
        elif whence == 2:
            pos = pos + self.chunksize
        if pos < 0 or pos > self.chunksize:
            raise RuntimeError
        self.file.seek(self.offset + pos, 0)
        self.size_read = pos

    def tell(self):
        if self.closed:
            raise ValueError, "I/O operation on closed file"
        return self.size_read

    def read(self, size=-1):
        """Read at most size bytes from the chunk.
        If size is omitted or negative, read until the end
        of the chunk.
        """

        if self.closed:
            raise ValueError, "I/O operation on closed file"
        if self.size_read >= self.chunksize:
            return ''
        if size < 0:
            size = self.chunksize - self.size_read
        if size > self.chunksize - self.size_read:
            size = self.chunksize - self.size_read
        data = self.file.read(size)
        self.size_read = self.size_read + len(data)
        if self.size_read == self.chunksize and \
           self.align and \
           (self.chunksize & 1):
            dummy = self.file.read(1)
            self.size_read = self.size_read + len(dummy)
        return data

    def skip(self):
        """Skip the rest of the chunk.
        If you are not interested in the contents of the chunk,
        this method should be called so that the file points to
        the start of the next chunk.
        """

        if self.closed:
            raise ValueError, "I/O operation on closed file"
        if self.seekable:
            try:
                n = self.chunksize - self.size_read
                # maybe fix alignment
                if self.align and (self.chunksize & 1):
                    n = n + 1
                self.file.seek(n, 1)
                self.size_read = self.size_read + n
                return
            except IOError:
                pass
        while self.size_read < self.chunksize:
            n = min(8192, self.chunksize - self.size_read)
            dummy = self.read(n)
            if not dummy:
                raise EOFError
back to top