o b%@sdZddlZddlZddlZddlZGdddejZGdddZGdddeZ Gd d d eZ d Z d d Z ddZ dddZdS)z An incremental approach to unzipping files. This allows you to unzip a little bit of a file at a time, which means you can report progress as a file unzips. Nc@seZdZdZddZdS)ChunkingZipFilez~ A L{zipfile.ZipFile} object which, with L{readfile}, also gives you access to a file-like object for each entry. cCs"|jdvr td|jstd||}|j|jd|jtj}|ddtj kr2t dt tj |}|j|tj}|tjrP|j|tj|jd@r[|d}n|d }||jkrot d |j|f|jtjkr{t||jS|jtjkrt||jSt d |j|f) z3 Return file-like object for name. )razread() requires mode "r" or "a"z3Attempt to read ZIP archive that was already closedrz Bad magic number for file headerizutf-8cp437z3File name in directory "%s" and header "%s" differ.z-Unsupported compression method %d for file %s)mode RuntimeErrorfpgetinfoseek header_offsetreadzipfilesizeFileHeaderstringFileHeader BadZipfilestructunpackstructFileHeader_FH_FILENAME_LENGTH_FH_EXTRA_FIELD_LENGTH flag_bitsdecode orig_filename compress_type ZIP_STORED ZipFileEntry compress_size ZIP_DEFLATEDDeflatedZipFileEntry)selfnamezinfofheaderfname fname_strr&:/usr/lib/python3/dist-packages/twisted/python/zipstream.pyreadfiles>            zChunkingZipFile.readfileN)__name__ __module__ __qualname____doc__r(r&r&r&r'rs rc@sdeZdZdZddZddZddZdd Zd d ZeZ d d Z ddZ ddZ ddZ ddZdS) _FileEntrya! Abstract superclass of both compressed and uncompressed variants of file-like objects within a zip archive. @ivar chunkingZipFile: a chunking zip file. @type chunkingZipFile: L{ChunkingZipFile} @ivar length: The number of bytes within the zip file that represent this file. (This is the size on disk, not the number of decompressed bytes which will result from reading it.) @ivar fp: the underlying file object (that contains pkzip data). Do not touch this, please. It will quite likely move or go away. @ivar closed: File-like 'closed' attribute; True before this file has been closed, False after. @type closed: L{bool} @ivar finished: An older, broken synonym for 'closed'. Do not touch this, please. @type finished: L{int} cCs&||_|jj|_||_d|_d|_dS)zC Create a L{_FileEntry} from a L{ChunkingZipFile}. rFN)chunkingZipFiler lengthfinishedclosedr r.r/r&r&r'__init__[s   z_FileEntry.__init__cCsdS)zD Returns false because zip files should not be ttys Fr&r r&r&r'isattyez_FileEntry.isattycCsd|_d|_|`dS)z/ Close self (file-like object) TN)r1r0r r4r&r&r'closeksz_FileEntry.closecs6d}tfdddD] }||7}|dkr|Sq |S)z Read a line. cs dS)Nr7)r r&r4r&r'xs z%_FileEntry.readline.. )iter)r linebyter&r4r'readlinessz_FileEntry.readlinecCs|}|r|St)zi Implement next as file does (like readline, except raises StopIteration at EOF) )r? StopIteration)r nextliner&r&r'__next__~sz_FileEntry.__next__cCst|S)z1 Returns a list of all the lines )listr4r&r&r' readlinessz_FileEntry.readlinescC|Sz/ Returns an iterator (so self) r&r4r&r&r' xreadlinesr6z_FileEntry.xreadlinescCrErFr&r4r&r&r'__iter__r6z_FileEntry.__iter__cCrENr&r4r&r&r' __enter__sz_FileEntry.__enter__cCs |dSrI)r8)r exc_type exc_value tracebackr&r&r'__exit__s z_FileEntry.__exit__N)r)r*r+r,r3r5r8r?rBnextrDrGrHrJrNr&r&r&r'r-Cs    r-c@*eZdZdZddZddZd ddZdS) rzJ File-like object used to read an uncompressed entry in a ZipFile cCst|||d|_dS)Nr)r-r3 readBytesr2r&r&r'r3s zZipFileEntry.__init__cC|jSrI)rQr4r&r&r'tellzZipFileEntry.tellNcCsv|dur |j|j}|dks|jrdS|jjt||j|j}|jt|7_|j|jks6t||kr9d|_|S)Nrr9r7)r/rQr0r.r r minlen)r ndatar&r&r'r s zZipFileEntry.readrIr)r*r+r,r3rSr r&r&r&r'rs rc@rP) rzE File-like object used to read a deflated entry in a ZipFile cCs0t|||d|_d|_td|_d|_dS)Nrir9)r-r3 returnedBytesrQzlib decompressobjdecompbufferr2r&r&r'r3s   zDeflatedZipFileEntry.__init__cCrRrI)rZr4r&r&r'rSrTzDeflatedZipFileEntry.tellNcCsd|jrdS|durF|jg}||j|jj|j|j ||jd||j d|_d|_d |}|j t |7_ |St |j|kr|jjt|d|j|j }|j t |7_ |s|j|jd|j }d|_d|_|j t |7_ |S|j|j|7_t |j|ksM|jd|}|j|d|_|j t |7_ |S)Nr9Zr7i)r0r^appendr] decompressr.r r r/rQflushjoinrZrVrU)r rWresultrXr&r&r'r sF zDeflatedZipFileEntry.readrIrYr&r&r&r'rs rcCs,d}t|}|D] }|t||7}q |S)zr Predict the number of chunks that will be extracted from the entire zipfile, given chunksize blocks. r)rinfolistcountFileChunks)filename chunksize totalchunkszfinfor&r&r'countZipFileChunkss  rmcCs(t|j|\}}|dkr|d7}|pdS)a9 Count the number of chunks that will result from the given C{ZipInfo}. @param zipinfo: a C{zipfile.ZipInfo} instance describing an entry in a zip archive to be counted. @return: the number of chunks present in the zip file. (Even an empty file counts as one chunk.) @rtype: L{int} rr7)divmod file_size)zipinforicountextrar&r&r'rgs rg.c cslt|d}tj|st|t||}|}|}t||D]\}} | j t @} tj ||} | rHtj| s@t| |d8}|Vq#tj | d} tj| s[t| |sctj| s| |} | jdkrt|d8}|Vt| d'}| | jkr| |}|||d8}|V| | jksWdn1swYq#|t| |8}|Vq#dS)z Return a generator for the zipfile. This implementation will yield after every chunksize uncompressed bytes, or at the end of a file, whichever comes first. The value it yields is the number of chunks left to unzip. rr7rwbN)rospathexistsmakedirsrmnamelistrfzip external_attrDIR_BITrcsplitr(roopenrSr writerg)rh directory overwritericzf remainingnamesinfosentryrlisdirffdirr outfilehunkr&r&r'unzipIterChunkysH              r)rsrrt)r,os.pathrvrrr[ZipFilerr-rrr}rmrgrr&r&r&r's3a8