## The Python Imaging Library.# $Id$## a class to read from a container file## History:# 1995-06-18 fl Created# 1995-09-07 fl Added readline(), readlines()## Copyright (c) 1997-2001 by Secret Labs AB# Copyright (c) 1995 by Fredrik Lundh## See the README file for information on usage and redistribution.#from__future__importannotationsimportiofromcollections.abcimportIterablefromtypingimportIO,AnyStr,NoReturn
[docs]classContainerIO(IO[AnyStr]):""" A file object that provides read access to a part of an existing file (for example a TAR file). """def__init__(self,file:IO[AnyStr],offset:int,length:int)->None:""" Create file object. :param file: Existing file. :param offset: Start of region, in bytes. :param length: Size of region, in bytes. """self.fh:IO[AnyStr]=fileself.pos=0self.offset=offsetself.length=lengthself.fh.seek(offset)### Always false.
[docs]defseek(self,offset:int,mode:int=io.SEEK_SET)->int:""" Move file pointer. :param offset: Offset in bytes. :param mode: Starting position. Use 0 for beginning of region, 1 for current offset, and 2 for end of region. You cannot move the pointer outside the defined region. :returns: Offset from start of region, in bytes. """ifmode==1:self.pos=self.pos+offsetelifmode==2:self.pos=self.length+offsetelse:self.pos=offset# clampself.pos=max(0,min(self.pos,self.length))self.fh.seek(self.offset+self.pos)returnself.pos
[docs]deftell(self)->int:""" Get current file pointer. :returns: Offset from start of region, in bytes. """returnself.pos
[docs]defread(self,n:int=-1)->AnyStr:""" Read data. :param n: Number of bytes to read. If omitted, zero or negative, read until end of region. :returns: An 8-bit string. """ifn>0:n=min(n,self.length-self.pos)else:n=self.length-self.posifn<=0:# EOFreturnb""if"b"inself.fh.modeelse""# type: ignore[return-value]self.pos=self.pos+nreturnself.fh.read(n)
[docs]defreadline(self,n:int=-1)->AnyStr:""" Read a line of text. :param n: Number of bytes to read. If omitted, zero or negative, read until end of line. :returns: An 8-bit string. """s:AnyStr=b""if"b"inself.fh.modeelse""# type: ignore[assignment]newline_character=b"\n"if"b"inself.fh.modeelse"\n"whileTrue:c=self.read(1)ifnotc:breaks=s+cifc==newline_characterorlen(s)==n:breakreturns
[docs]defreadlines(self,n:int|None=-1)->list[AnyStr]:""" Read multiple lines of text. :param n: Number of lines to read. If omitted, zero, negative or None, read until end of region. :returns: A list of 8-bit strings. """lines=[]whileTrue:s=self.readline()ifnots:breaklines.append(s)iflen(lines)==n:breakreturnlines
def__enter__(self)->ContainerIO[AnyStr]:returnselfdef__exit__(self,*args:object)->None:self.close()def__iter__(self)->ContainerIO[AnyStr]:returnselfdef__next__(self)->AnyStr:line=self.readline()ifnotline:msg="end of region"raiseStopIteration(msg)returnline