Mercurial > hg > cc > cirrus_work
annotate lib/python/cc/warc.py @ 344:279793350225 trim
decompOneBlock working with gzip
| author | Henry S. Thompson <ht@inf.ed.ac.uk> |
|---|---|
| date | Wed, 11 Mar 2026 13:24:48 +0000 |
| parents | 9ecf193718c1 |
| children | 8c9e7578ed30 |
| rev | line source |
|---|---|
| 39 | 1 #!/usr/bin/env python3 |
|
46
44d3a4f4ea51
support on-board unzipping, reduce buffer size to 2MB
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
43
diff
changeset
|
2 '''Stream a warc format file, unzipping if necessary, invoking a |
|
44d3a4f4ea51
support on-board unzipping, reduce buffer size to 2MB
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
43
diff
changeset
|
3 callback on each record. Callback can be limited by WARC-Type, record |
|
44d3a4f4ea51
support on-board unzipping, reduce buffer size to 2MB
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
43
diff
changeset
|
4 part''' |
| 39 | 5 |
|
164
4315a36b1672
refactor to provide for buffer overflow fix
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
120
diff
changeset
|
6 import sys, io |
|
42
689a0e311cd2
make warc.py a library, separate out testing
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
39
diff
changeset
|
7 from isal import igzip |
| 289 | 8 import cython, typing, gzip |
| 39 | 9 |
|
287
fe78af4ea7c5
in the midst of trying to rethink the refill logic
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
283
diff
changeset
|
10 # see warc.pxd for function signatures |
|
283
6739e08d19ff
type decls, cythonize works
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
164
diff
changeset
|
11 |
| 289 | 12 INFO: int = 0 |
| 13 RESP: int = 1 | |
| 14 REQ: int = 2 | |
| 15 META: int = 3 | |
|
293
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
16 REVISIT: int = 4 |
|
62
11cbaee8bbc8
Test 2 works with parts=1,2,3.
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
61
diff
changeset
|
17 |
| 289 | 18 BUFSIZE: int = 16 * 1024 * 1024 |
|
308
d52602a64e09
double buffer size to deal with massive header cases
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
293
diff
changeset
|
19 BUFMIN: int = 3 * 1024 * 1024 # 1.5MiB, will need to be increased |
|
288
d3fc7b5c73d0
park that, try fixed large buffer and large-enough min to ensure we always have a whole record in view
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
287
diff
changeset
|
20 # to 5.5MiB for CC-MAIN-2025-13 (Mar) and thereafter |
|
287
fe78af4ea7c5
in the midst of trying to rethink the refill logic
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
283
diff
changeset
|
21 |
|
288
d3fc7b5c73d0
park that, try fixed large buffer and large-enough min to ensure we always have a whole record in view
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
287
diff
changeset
|
22 HDRMAX: int = 0 # will grow |
| 290 | 23 RECORDMAX: int = 0 # will grow |
|
164
4315a36b1672
refactor to provide for buffer overflow fix
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
120
diff
changeset
|
24 |
|
287
fe78af4ea7c5
in the midst of trying to rethink the refill logic
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
283
diff
changeset
|
25 def warc(filename: str, |
|
fe78af4ea7c5
in the midst of trying to rethink the refill logic
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
283
diff
changeset
|
26 callback: typing.Callable[[bytes, typing.ByteString, int], typing.BinaryIO], |
| 289 | 27 types: typing.List[int] = [RESP], whole: bool = False, parts: int = 7, |
|
287
fe78af4ea7c5
in the midst of trying to rethink the refill logic
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
283
diff
changeset
|
28 debug: bool = False): |
| 61 | 29 '''parts is a bit-mask: |
| 30 1 for warc header; | |
| 31 2 for req/resp HTTP header, warcinfo/metadata features; | |
| 32 4 for req/resp body''' | |
|
288
d3fc7b5c73d0
park that, try fixed large buffer and large-enough min to ensure we always have a whole record in view
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
287
diff
changeset
|
33 # Not currently trying to depend on this, but I believe that |
| 289 | 34 # warcinfo: record-headers+1bl+crawl-headers+2bl |
| 35 # request: record-headers+1bl+HTTP-headers+3bl | |
| 36 # response: record-headers+1bl+HTTP-headers+[1bl or 2bl]+HTTP-body+1bl | |
| 37 # metadata: record-headers+1bl+metadata-headers+3bl | |
| 38 global BUFSIZE, HDRMAX, BUFMIN, RECORDMAX | |
| 39 _out: typing.BinaryIO | |
|
62
11cbaee8bbc8
Test 2 works with parts=1,2,3.
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
61
diff
changeset
|
40 # should do some sanity checking wrt parts and types |
| 289 | 41 stream: typing.BinaryIO |
| 42 with gzip.open(filename, 'r') as fh: | |
| 43 try: | |
| 44 fh.read(1) | |
| 45 except gzip.BadGzipFile: | |
| 46 stream = open(filename,'rb',0) | |
| 47 else: | |
| 48 stream = igzip.IGzipFile(filename=filename) | |
|
287
fe78af4ea7c5
in the midst of trying to rethink the refill logic
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
283
diff
changeset
|
49 buf: char[::1] = bytearray(BUFSIZE) |
| 289 | 50 bufView: char[::1] = memoryview(buf) |
| 290 | 51 fpos: int = 0 |
| 52 bp: int = 0 | |
| 53 bl: int = stream.readinto(buf) | |
| 54 n: int = 0 | |
| 289 | 55 done: bool = bl < BUFSIZE |
| 290 | 56 while buf.startswith(b'\r\n',bp): |
| 57 bp+=2 | |
|
293
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
58 while not (done and bp >= bl): |
| 290 | 59 start_1: int = bp |
|
48
d0d2fd9830d6
starting on conversion to direct-querying of buffer
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
46
diff
changeset
|
60 if not buf.startswith(b'WARC/1.0\r\n',bp): |
|
292
a3d55cc7da18
fix another long-tail bug
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
291
diff
changeset
|
61 breakpoint() |
|
67
b8d4a5ede7a3
fix eof bug, expand error messages
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
66
diff
changeset
|
62 raise ValueError("Not a WARC file? In %s at %s of %s (%s): %s[%s]"%(filename, |
|
b8d4a5ede7a3
fix eof bug, expand error messages
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
66
diff
changeset
|
63 bp,bl,fpos, |
|
b8d4a5ede7a3
fix eof bug, expand error messages
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
66
diff
changeset
|
64 (buf[bp:min(bl,bp+20)] if bp<bl else buf[bl-20:bl]).decode('latin-1'), |
|
b8d4a5ede7a3
fix eof bug, expand error messages
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
66
diff
changeset
|
65 bl-bp)) |
| 290 | 66 bp += 10 |
| 67 n += 1 | |
| 68 wtype: int = -1 | |
|
287
fe78af4ea7c5
in the midst of trying to rethink the refill logic
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
283
diff
changeset
|
69 length: int = 0 |
|
288
d3fc7b5c73d0
park that, try fixed large buffer and large-enough min to ensure we always have a whole record in view
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
287
diff
changeset
|
70 tr: bytes = b'' # Was this record truncated? |
|
48
d0d2fd9830d6
starting on conversion to direct-querying of buffer
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
46
diff
changeset
|
71 while not buf.startswith(b'\r\n',bp): |
|
56
f8c8f79b2532
rework completely to refill as much as possible only when necessary,
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
54
diff
changeset
|
72 # there should always be enough in the buffer to complete this loop, |
| 289 | 73 # because of the buffer update logic at the end |
|
287
fe78af4ea7c5
in the midst of trying to rethink the refill logic
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
283
diff
changeset
|
74 eol = buf.index(b'\r\n', bp) |
| 289 | 75 if buf.startswith(b"Content-Length: ",bp): |
| 290 | 76 length=wl=int(bufView[bp+16:eol]) |
|
287
fe78af4ea7c5
in the midst of trying to rethink the refill logic
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
283
diff
changeset
|
77 if buf.startswith(b"WARC-Truncated: ",bp): |
|
59
5d40d7511374
avoid slicing buf by using memoryview to save copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
58
diff
changeset
|
78 if bp+16==eol-2: |
|
287
fe78af4ea7c5
in the midst of trying to rethink the refill logic
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
283
diff
changeset
|
79 tr = b"EMPTY" |
|
59
5d40d7511374
avoid slicing buf by using memoryview to save copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
58
diff
changeset
|
80 else: |
|
287
fe78af4ea7c5
in the midst of trying to rethink the refill logic
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
283
diff
changeset
|
81 tr = bytes(bufView[bp+16:eol-2]) |
|
48
d0d2fd9830d6
starting on conversion to direct-querying of buffer
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
46
diff
changeset
|
82 elif buf.startswith(b'WARC-Type: ',bp): |
|
59
5d40d7511374
avoid slicing buf by using memoryview to save copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
58
diff
changeset
|
83 if buf.startswith(b's',bp+13): |
|
62
11cbaee8bbc8
Test 2 works with parts=1,2,3.
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
61
diff
changeset
|
84 wtype = RESP |
|
59
5d40d7511374
avoid slicing buf by using memoryview to save copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
58
diff
changeset
|
85 elif buf.startswith(b'q',bp+13): |
|
62
11cbaee8bbc8
Test 2 works with parts=1,2,3.
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
61
diff
changeset
|
86 wtype = REQ |
|
59
5d40d7511374
avoid slicing buf by using memoryview to save copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
58
diff
changeset
|
87 elif buf.startswith(b'm',bp+11): |
|
62
11cbaee8bbc8
Test 2 works with parts=1,2,3.
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
61
diff
changeset
|
88 wtype = META |
|
59
5d40d7511374
avoid slicing buf by using memoryview to save copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
58
diff
changeset
|
89 elif buf.startswith(b'w',bp+11): |
|
62
11cbaee8bbc8
Test 2 works with parts=1,2,3.
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
61
diff
changeset
|
90 wtype = INFO |
|
293
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
91 elif buf.startswith(b'v',bp+13): |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
92 wtype = REVISIT |
|
59
5d40d7511374
avoid slicing buf by using memoryview to save copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
58
diff
changeset
|
93 else: |
|
67
b8d4a5ede7a3
fix eof bug, expand error messages
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
66
diff
changeset
|
94 raise ValueError("Unknown WARC-Type: %s in %s at %s"%( |
|
b8d4a5ede7a3
fix eof bug, expand error messages
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
66
diff
changeset
|
95 bytes(bufView[bp+11:eol-2]),filename, |
|
59
5d40d7511374
avoid slicing buf by using memoryview to save copying
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
58
diff
changeset
|
96 fpos-(bl-bp))) |
| 290 | 97 bp=eol+2 |
| 289 | 98 # record header done |
|
288
d3fc7b5c73d0
park that, try fixed large buffer and large-enough min to ensure we always have a whole record in view
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
287
diff
changeset
|
99 if (hl:=(bp - start_1)) > HDRMAX: |
|
d3fc7b5c73d0
park that, try fixed large buffer and large-enough min to ensure we always have a whole record in view
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
287
diff
changeset
|
100 HDRMAX = hl |
| 289 | 101 #if done: |
| 102 # if (bp+length)>bl: | |
| 103 # raise ValueError("Done but need more! %s + %s > %s in %s"%(bp, | |
| 104 # length,bl,filename)) | |
| 39 | 105 if (wtype in types): |
|
62
11cbaee8bbc8
Test 2 works with parts=1,2,3.
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
61
diff
changeset
|
106 # Output whole or part 1 as required |
| 39 | 107 if whole: |
|
293
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
108 _out=callback(wtype,bufView[start_1:bp+length],7) |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
109 else: |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
110 if (parts & 1): |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
111 bp = eol+2 |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
112 _out=callback(wtype,bufView[start_1:bp],1) |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
113 if parts!=1: |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
114 while buf.startswith(b'\r\n',bp): |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
115 bp+=2 |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
116 start_2=bp |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
117 eob=bp+length |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
118 while buf.startswith(b'\r\n',eob-2): |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
119 eob-=2 |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
120 # Only output parts (2 = HTTP header, 4 = body) that are wanted |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
121 if parts & 2: |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
122 if wtype == RESP or wtype == REQ : |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
123 # request and response have http headers |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
124 eo2=buf.index(b'\r\n\r\n',start_2) |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
125 _out=callback(wtype,bufView[start_2:eo2+2],2) |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
126 else: |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
127 # rest of the part |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
128 _out=callback(wtype,bufView[start_2:eob],2) |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
129 if parts & 4: |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
130 raise ValueError("Not implemented: body part (4): %s"%parts) |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
131 #bp += length |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
132 #if buf[bp] != 13: |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
133 # # Why does this sometimes happen, e.g. when doing |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
134 # python3 ~/lib/python/cc/test_warc.py 4 /beegfs/common_crawl/CC-MAIN-2019-35/1566027313501.0/orig/crawldiagnostics/CC-MAIN-20190817222907-20190818004907-00000.warc.gz |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
135 # at a point where bp+length is 11018, looking at >\n\r\n |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
136 # bp += 1 [doesn't work] |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
137 bp = buf.index(b'\r\n',bp+length) |
|
12d13a1d387f
extend, then fix, to get it working for crawldiagnostics warc files
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
292
diff
changeset
|
138 # check if refill needed |
| 289 | 139 rl: int |
| 140 if (rl := (bp - start_1)) > RECORDMAX: | |
| 141 RECORDMAX = rl | |
| 142 keepLen: int | |
| 143 if (not done) and (keepLen := bl - bp) < BUFMIN: | |
| 144 # we need to shift and read more | |
| 145 buf[0:keepLen]=bufView[bp:bl] | |
| 146 with memoryview(buf)[keepLen:BUFSIZE] as xBuf: | |
| 147 nb=stream.readinto(xBuf) | |
| 148 bl = keepLen+nb | |
| 149 done = bl < BUFSIZE | |
| 150 bp = 0 | |
| 290 | 151 while buf.startswith(b'\r\n',bp): |
| 152 bp+=2 | |
| 61 | 153 #print('end of loop',wtype,start_1,bp,eol,length,bl,file=sys.stderr) |
| 290 | 154 print('%d records, max record: %d, max header: %d'%(n, RECORDMAX, HDRMAX), |
| 155 file=sys.stderr) | |
|
343
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
156 |
|
344
279793350225
decompOneBlock working with gzip
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
343
diff
changeset
|
157 import zlib, gzip, struct |
|
279793350225
decompOneBlock working with gzip
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
343
diff
changeset
|
158 |
|
343
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
159 def decompOneBlock(fp: io.BytesIO): |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
160 """Decompress one block of a gzip compressed stream in one shot. |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
161 Return the decompressed string and the stream repositioned |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
162 at the start of the next block. |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
163 """ |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
164 data = fp.getbuffer() |
|
344
279793350225
decompOneBlock working with gzip
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
343
diff
changeset
|
165 if gzip._read_gzip_header(fp) is None: |
|
343
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
166 return b"" |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
167 # Use a zlib raw deflate compressor |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
168 do = zlib.decompressobj(wbits=-zlib.MAX_WBITS) |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
169 # Read all the data except the header |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
170 decompressed = do.decompress(data[fp.tell():]) |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
171 if not do.eof or len(do.unused_data) < 8: |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
172 raise EOFError("Compressed file ended before the end-of-stream " |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
173 "marker was reached") |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
174 crc, length = struct.unpack("<II", do.unused_data[:8]) |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
175 if crc != zlib.crc32(decompressed): |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
176 raise BadGzipFile("CRC check failed") |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
177 if length != (len(decompressed) & 0xffffffff): |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
178 raise BadGzipFile("Incorrect length of data produced") |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
179 eob = 8 |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
180 unused = len(do.unused_data) - 8 |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
181 while unused > 0 and do.unused_data[eob] == 0: |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
182 eob += 1 |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
183 unused -= 1 |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
184 if unused > 0: |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
185 fp.seek(-unused, 2) |
|
9ecf193718c1
process exactly one block at a time, maybe?
Henry S. Thompson <ht@inf.ed.ac.uk>
parents:
308
diff
changeset
|
186 return decompressed |
