FastWARC 1.0.2__tar.gz → 1.0.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fastwarc-1.0.2 → fastwarc-1.0.4}/FastWARC.egg-info/PKG-INFO +3 -2
- {fastwarc-1.0.2 → fastwarc-1.0.4}/FastWARC.egg-info/requires.txt +3 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/PKG-INFO +3 -2
- {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/cli.py +31 -116
- {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/_shims.py +21 -12
- {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/stream_io.pyi +8 -7
- {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/warc.pyi +17 -10
- {fastwarc-1.0.2 → fastwarc-1.0.4}/pyproject.toml +4 -3
- {fastwarc-1.0.2 → fastwarc-1.0.4}/FastWARC.egg-info/SOURCES.txt +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/FastWARC.egg-info/dependency_links.txt +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/FastWARC.egg-info/entry_points.txt +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/FastWARC.egg-info/top_level.txt +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/MANIFEST.in +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/README.md +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/__init__.py +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/__init__.pyi +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/__init__.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/__init__.py +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/__init__.pyi +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/stream_io.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/stream_io.pyi +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/stream_io.pyx +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/tools.pyi +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/tools.pyx +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/warc.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/warc.pyi +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/warc.pyx +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/py.typed +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_common/__init__.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_common/string_util.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/__init__.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/algorithm.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/atomic.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/boost_regex.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/cctype.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/cstdlib.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/cstring.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/dlfcn.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/errno.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/lexbor.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/lz4frame.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/lz4hc.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/pthread.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/re2.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/stdio.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/string_view.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/time.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/uchardet.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/unistd.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/utility.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/zlib.pxd +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/setup.cfg +0 -0
- {fastwarc-1.0.2 → fastwarc-1.0.4}/setup.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: FastWARC
|
|
3
|
-
Version: 1.0.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 1.0.4
|
|
4
|
+
Summary: The world's fastest WARC parsing library written in Rust with bindings for Python.
|
|
5
5
|
Author: Janek Bevendorff
|
|
6
6
|
License-Expression: Apache-2.0
|
|
7
7
|
Project-URL: repository, https://github.com/chatnoir-eu/chatnoir-resiliparse
|
|
@@ -12,6 +12,7 @@ Description-Content-Type: text/markdown
|
|
|
12
12
|
Requires-Dist: brotli
|
|
13
13
|
Requires-Dist: click
|
|
14
14
|
Requires-Dist: tqdm
|
|
15
|
+
Requires-Dist: typing_extensions>=4.5; python_version < "3.13"
|
|
15
16
|
Provides-Extra: all
|
|
16
17
|
Requires-Dist: fastwarc[fsspec]; extra == "all"
|
|
17
18
|
Provides-Extra: fsspec
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: FastWARC
|
|
3
|
-
Version: 1.0.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 1.0.4
|
|
4
|
+
Summary: The world's fastest WARC parsing library written in Rust with bindings for Python.
|
|
5
5
|
Author: Janek Bevendorff
|
|
6
6
|
License-Expression: Apache-2.0
|
|
7
7
|
Project-URL: repository, https://github.com/chatnoir-eu/chatnoir-resiliparse
|
|
@@ -12,6 +12,7 @@ Description-Content-Type: text/markdown
|
|
|
12
12
|
Requires-Dist: brotli
|
|
13
13
|
Requires-Dist: click
|
|
14
14
|
Requires-Dist: tqdm
|
|
15
|
+
Requires-Dist: typing_extensions>=4.5; python_version < "3.13"
|
|
15
16
|
Provides-Extra: all
|
|
16
17
|
Requires-Dist: fastwarc[fsspec]; extra == "all"
|
|
17
18
|
Provides-Extra: fsspec
|
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
|
|
15
15
|
import getpass
|
|
16
16
|
import importlib
|
|
17
|
-
from enum import IntFlag
|
|
18
17
|
from itertools import chain
|
|
19
18
|
import json
|
|
20
19
|
import os
|
|
@@ -25,13 +24,14 @@ import urllib.request
|
|
|
25
24
|
import click
|
|
26
25
|
from tqdm import tqdm
|
|
27
26
|
|
|
28
|
-
from fastwarc.stream_io import
|
|
27
|
+
from fastwarc.stream_io import FileStream, StreamError, FastWARCError, PythonIOStreamAdapter
|
|
29
28
|
from fastwarc.warc import ArchiveIterator, WarcRecordType
|
|
30
|
-
from fastwarc.legacy.tools import CompressionAlg, detect_compression_algorithm, wrap_warc_stream,
|
|
29
|
+
from fastwarc.legacy.tools import CompressionAlg, detect_compression_algorithm, wrap_warc_stream, \
|
|
30
|
+
recompress_warc_interactive, verify_digests
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
def exception_handler(exctype, value, _):
|
|
34
|
-
if exctype ==
|
|
34
|
+
if exctype == FastWARCError:
|
|
35
35
|
click.echo(str(value), err=True)
|
|
36
36
|
sys.exit(1)
|
|
37
37
|
|
|
@@ -56,132 +56,46 @@ def _human_readable_bytes(byte_num):
|
|
|
56
56
|
byte_num /= 1024
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
class CompressionAlg(IntFlag):
|
|
60
|
-
UNCOMPRESSED = 0
|
|
61
|
-
GZIP = 1
|
|
62
|
-
ZSTD = 2
|
|
63
|
-
LZ4 = 3
|
|
64
|
-
AUTO = 65535
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def detect_compression_algorithm(infile):
|
|
68
|
-
"""
|
|
69
|
-
Try to detect the used compression algorithm from the given filename.
|
|
70
|
-
|
|
71
|
-
:param infile: filename or file object
|
|
72
|
-
:return: compression algorithm
|
|
73
|
-
"""
|
|
74
|
-
|
|
75
|
-
if os.fspath(infile):
|
|
76
|
-
infile = str(infile)
|
|
77
|
-
elif hasattr(infile, 'name'):
|
|
78
|
-
infile = infile.name
|
|
79
|
-
else:
|
|
80
|
-
raise ValueError('Invalid infile type.')
|
|
81
|
-
|
|
82
|
-
if type(infile) is str:
|
|
83
|
-
if infile.endswith('.gz'):
|
|
84
|
-
return CompressionAlg.GZIP
|
|
85
|
-
if infile.endswith('.zst'):
|
|
86
|
-
return CompressionAlg.ZSTD
|
|
87
|
-
if infile.endswith('.lz4'):
|
|
88
|
-
return CompressionAlg.LZ4
|
|
89
|
-
if infile.endswith('.warc'):
|
|
90
|
-
return CompressionAlg.UNCOMPRESSED
|
|
91
|
-
|
|
92
|
-
if not os.path.isfile(infile):
|
|
93
|
-
raise click.UsageError('Could not determine compression algorithm.')
|
|
94
|
-
|
|
95
|
-
with open(infile, 'rb') as infile:
|
|
96
|
-
magic_bytes = infile.read(5)
|
|
97
|
-
|
|
98
|
-
if magic_bytes[:3] == b'\x1F\x8B\x08':
|
|
99
|
-
return CompressionAlg.GZIP
|
|
100
|
-
elif magic_bytes[:4] == b'\x28\xB5\x2F\xFD' or magic_bytes[:4] == b'\x5D\x2A\x4D\x18':
|
|
101
|
-
return CompressionAlg.ZSTD
|
|
102
|
-
elif magic_bytes[:4] == b'\x04\x22\x4D\x18':
|
|
103
|
-
return CompressionAlg.LZ4
|
|
104
|
-
elif magic_bytes == b'WARC/':
|
|
105
|
-
return CompressionAlg.UNCOMPRESSED
|
|
106
|
-
|
|
107
|
-
raise click.FileError('No compression algorithm detected.')
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
def get_compressor(filename, alg, level):
|
|
111
|
-
if alg == CompressionAlg.AUTO:
|
|
112
|
-
alg = detect_compression_algorithm(filename)
|
|
113
|
-
if alg == CompressionAlg.UNCOMPRESSED:
|
|
114
|
-
return open(filename, 'wb')
|
|
115
|
-
elif alg == CompressionAlg.GZIP:
|
|
116
|
-
return GzipWriter(filename, compression_level=level or 9)
|
|
117
|
-
elif alg == CompressionAlg.ZSTD:
|
|
118
|
-
return ZstdWriter(filename, compression_level=level or 3)
|
|
119
|
-
elif alg == CompressionAlg.LZ4:
|
|
120
|
-
return Lz4Writer(filename) # compression_level currently unsupported
|
|
121
|
-
else:
|
|
122
|
-
raise ValueError(f'Unknown compression algorithm: {alg}')
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
def get_decompressor(filename, decompress_alg):
|
|
126
|
-
if os.fspath(filename) and not decompress_alg:
|
|
127
|
-
# Use plain filename to avoid Python IO stack
|
|
128
|
-
return str(filename)
|
|
129
|
-
|
|
130
|
-
if decompress_alg:
|
|
131
|
-
alg = decompress_alg
|
|
132
|
-
else:
|
|
133
|
-
alg = detect_compression_algorithm(filename)
|
|
134
|
-
if alg == CompressionAlg.UNCOMPRESSED:
|
|
135
|
-
return open(filename, 'rb')
|
|
136
|
-
if alg == CompressionAlg.GZIP:
|
|
137
|
-
return GzipReader(filename)
|
|
138
|
-
if alg == CompressionAlg.ZSTD:
|
|
139
|
-
return ZstdReader(filename)
|
|
140
|
-
if alg == CompressionAlg.LZ4:
|
|
141
|
-
return Lz4Reader(filename) # compression_level currently unsupported
|
|
142
|
-
|
|
143
|
-
raise ValueError(f'Unknown compression algorithm: {alg}')
|
|
144
|
-
|
|
145
|
-
|
|
146
59
|
@main.command()
|
|
147
60
|
@click.argument('infile', type=click.Path(dir_okay=False, exists=True))
|
|
148
61
|
@click.argument('outfile', type=click.Path(dir_okay=False, exists=False))
|
|
149
|
-
@click.option('-c', '--compress-alg', type=click.Choice(['
|
|
62
|
+
@click.option('-c', '--compress-alg', type=click.Choice(['gzip', 'lz4', 'uncompressed', 'auto']),
|
|
150
63
|
default='auto', show_default=True, help='Compression algorithm to use for output file')
|
|
151
|
-
@click.option('-d', '--decompress-alg', type=click.Choice(['
|
|
64
|
+
@click.option('-d', '--decompress-alg', type=click.Choice(['gzip', 'lz4', 'uncompressed', 'auto']),
|
|
152
65
|
default='auto', show_default=True,
|
|
153
66
|
help='Decompression algorithm for decoding input file (auto tries to detect based on file extension)')
|
|
154
|
-
@click.option('-l', '--compress-level', type=int, default=None, help='Compression level')
|
|
67
|
+
@click.option('-l', '--compress-level', type=int, default=None, help='Compression level (defaults to max)')
|
|
155
68
|
@click.option('-q', '--quiet', is_flag=True, help='Do not print progress information')
|
|
156
69
|
def recompress(infile, outfile, compress_alg, decompress_alg, compress_level, quiet):
|
|
157
70
|
"""
|
|
158
71
|
Recompress a WARC file.
|
|
159
72
|
|
|
160
|
-
This command allows you to recompress a WARC file if it is uncompressed
|
|
161
|
-
properly at the record-level
|
|
73
|
+
This command allows you to recompress a WARC file if it is uncompressed or not compressed
|
|
74
|
+
properly at the record-level if or you want to recompress a GZip WARC as LZ4 or vice versa.
|
|
162
75
|
"""
|
|
163
76
|
|
|
164
|
-
compress_alg = getattr(CompressionAlg, compress_alg
|
|
165
|
-
decompress_alg = getattr(CompressionAlg, decompress_alg
|
|
77
|
+
compress_alg = getattr(CompressionAlg, compress_alg)
|
|
78
|
+
decompress_alg = getattr(CompressionAlg, decompress_alg)
|
|
166
79
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
80
|
+
comp_args = {}
|
|
81
|
+
if compress_level is None:
|
|
82
|
+
if compress_alg == CompressionAlg.gzip:
|
|
83
|
+
comp_args['compression_level'] = 9
|
|
84
|
+
elif compress_alg == CompressionAlg.lz4:
|
|
85
|
+
comp_args['compression_level'] = 12
|
|
170
86
|
|
|
87
|
+
bytes_written = 0
|
|
171
88
|
num = 0
|
|
172
|
-
start = time.
|
|
89
|
+
start = time.time()
|
|
173
90
|
try:
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
r.write(out)
|
|
180
|
-
if compress_alg != CompressionAlg.UNCOMPRESSED:
|
|
181
|
-
out.finish()
|
|
91
|
+
for _, b in tqdm(recompress_warc_interactive(infile, outfile, decompress_alg, compress_alg, **comp_args),
|
|
92
|
+
desc='Recompressing WARC file', unit=' record(s)', leave=False,
|
|
93
|
+
disable=quiet, mininterval=0.2):
|
|
94
|
+
num += 1
|
|
95
|
+
bytes_written += b
|
|
182
96
|
|
|
183
|
-
|
|
184
|
-
|
|
97
|
+
if not quiet:
|
|
98
|
+
click.echo('Recompression completed.')
|
|
185
99
|
except KeyboardInterrupt:
|
|
186
100
|
if not quiet:
|
|
187
101
|
click.echo('Recompression aborted.')
|
|
@@ -189,8 +103,8 @@ def recompress(infile, outfile, compress_alg, decompress_alg, compress_level, qu
|
|
|
189
103
|
finally:
|
|
190
104
|
if not quiet and num > 0:
|
|
191
105
|
click.echo(f' - Records recompressed: {num}')
|
|
192
|
-
click.echo(f' - Bytes written: {_human_readable_bytes(
|
|
193
|
-
click.echo(f' - Completed in: {time.
|
|
106
|
+
click.echo(f' - Bytes written: {_human_readable_bytes(bytes_written)}')
|
|
107
|
+
click.echo(f' - Completed in: {time.time() - start:.02f} seconds')
|
|
194
108
|
|
|
195
109
|
|
|
196
110
|
@main.command()
|
|
@@ -525,8 +439,9 @@ def benchmark(input_url, decompress_alg, endpoint_url, aws_access_key, aws_secre
|
|
|
525
439
|
return num, time.monotonic() - start, interrupted
|
|
526
440
|
|
|
527
441
|
def _fastwarc_iterator(f):
|
|
528
|
-
s = _get_raw_stream_from_url(f, use_python_stream)
|
|
529
|
-
s = wrap_warc_stream(s, 'rb', decompress_alg)
|
|
442
|
+
# s = _get_raw_stream_from_url(f, use_python_stream)
|
|
443
|
+
# s = wrap_warc_stream(s, 'rb', decompress_alg)
|
|
444
|
+
s = '/home/roce3528/code-in-progress/code-research/web-search/chatnoir/chatnoir-resiliparse/tmpfs/CC-MAIN-20231005012006-20231005042006-00899.warc'
|
|
530
445
|
return ArchiveIterator(s, rec_type_filter, parse_http=parse_http, verify_digests=verify_digests)
|
|
531
446
|
|
|
532
447
|
n, t_fastwarc, interrupted = _bench(input_url, _fastwarc_iterator, 'FastWARC')
|
|
@@ -14,7 +14,10 @@
|
|
|
14
14
|
|
|
15
15
|
# Legacy shims for making the new Rust extension work with the old type names
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
try:
|
|
18
|
+
from warnings import deprecated
|
|
19
|
+
except ImportError:
|
|
20
|
+
from typing_extensions import deprecated
|
|
18
21
|
|
|
19
22
|
__all__ = [
|
|
20
23
|
'wrap_stream',
|
|
@@ -32,19 +35,21 @@ __all__ = [
|
|
|
32
35
|
'ReaderStaleError',
|
|
33
36
|
]
|
|
34
37
|
|
|
35
|
-
FastWARCError = OSError
|
|
36
38
|
|
|
37
|
-
|
|
39
|
+
@deprecated("Use OSError instead.", category=FutureWarning)
|
|
40
|
+
class FastWARCError(OSError): ...
|
|
38
41
|
|
|
39
|
-
ReaderStaleError = OSError
|
|
40
42
|
|
|
43
|
+
@deprecated("Use OSError instead.", category=FutureWarning)
|
|
44
|
+
class StreamError(OSError): ...
|
|
41
45
|
|
|
42
|
-
def _warn_deprecated(msg):
|
|
43
|
-
warnings.warn(msg, FutureWarning, 3)
|
|
44
46
|
|
|
47
|
+
@deprecated("Use OSError instead.", category=FutureWarning)
|
|
48
|
+
class ReaderStaleError(OSError): ...
|
|
45
49
|
|
|
50
|
+
|
|
51
|
+
@deprecated("wrap_stream is deprecated and will be removed in a future version.", category=FutureWarning)
|
|
46
52
|
def wrap_stream(raw_stream, mode='rb', fsspec_args=None):
|
|
47
|
-
_warn_deprecated("wrap_stream is deprecated and will be removed in a future version.")
|
|
48
53
|
if isinstance(raw_stream, str):
|
|
49
54
|
if fsspec_args is not False and '://' in raw_stream:
|
|
50
55
|
try:
|
|
@@ -57,9 +62,9 @@ def wrap_stream(raw_stream, mode='rb', fsspec_args=None):
|
|
|
57
62
|
return raw_stream
|
|
58
63
|
|
|
59
64
|
|
|
65
|
+
@deprecated("BufferedReader is deprecated and will be removed in a future version.", category=FutureWarning)
|
|
60
66
|
class BufferedReader:
|
|
61
67
|
def __init__(self, stream, *args, **kwargs):
|
|
62
|
-
_warn_deprecated("BufferedReader is deprecated and will be removed in a future version.")
|
|
63
68
|
self._stream = stream
|
|
64
69
|
|
|
65
70
|
def close(self):
|
|
@@ -78,12 +83,9 @@ class BufferedReader:
|
|
|
78
83
|
return self._stream.tell()
|
|
79
84
|
|
|
80
85
|
|
|
86
|
+
@deprecated("Use the new Reader and Writer classes from stream_io instead.", category=FutureWarning)
|
|
81
87
|
class IOStream:
|
|
82
88
|
def __init__(self, *_, _reader_factory=None, _writer_factory=None, **__):
|
|
83
|
-
_warn_deprecated(
|
|
84
|
-
f"{self.__class__.__name__} is deprecated and will be removed in a future version. "
|
|
85
|
-
"Use the new Reader and Writer classes from stream_io instead.")
|
|
86
|
-
|
|
87
89
|
self._reader_factory = _reader_factory
|
|
88
90
|
self._writer_factory = _writer_factory
|
|
89
91
|
self._reader = None
|
|
@@ -140,6 +142,7 @@ class IOStream:
|
|
|
140
142
|
s.close()
|
|
141
143
|
|
|
142
144
|
|
|
145
|
+
@deprecated("Use the new Reader and Writer classes from stream_io instead.", category=FutureWarning)
|
|
143
146
|
class CompressingStream(IOStream):
|
|
144
147
|
def begin_member(self):
|
|
145
148
|
pass
|
|
@@ -149,12 +152,14 @@ class CompressingStream(IOStream):
|
|
|
149
152
|
self._writer = None
|
|
150
153
|
|
|
151
154
|
|
|
155
|
+
@deprecated("Use the plain Python stream object without any wrapper.", category=FutureWarning)
|
|
152
156
|
class PythonIOStreamAdapter:
|
|
153
157
|
def __new__(cls, py_stream):
|
|
154
158
|
return IOStream(_reader_factory=lambda: py_stream,
|
|
155
159
|
_writer_factory=lambda: py_stream)
|
|
156
160
|
|
|
157
161
|
|
|
162
|
+
@deprecated("Use plain file paths instead.", category=FutureWarning)
|
|
158
163
|
class FileStream:
|
|
159
164
|
def __new__(cls, filename: str, mode: str = 'rb'):
|
|
160
165
|
if 'b' not in mode:
|
|
@@ -163,6 +168,7 @@ class FileStream:
|
|
|
163
168
|
return IOStream(_reader_factory=lambda: f, _writer_factory=lambda: f)
|
|
164
169
|
|
|
165
170
|
|
|
171
|
+
@deprecated("Use io.BytesIO instead.", category=FutureWarning)
|
|
166
172
|
class BytesIOStream:
|
|
167
173
|
def __new__(cls, initial_data=None):
|
|
168
174
|
import io
|
|
@@ -170,6 +176,7 @@ class BytesIOStream:
|
|
|
170
176
|
return IOStream(_reader_factory=lambda: bio, _writer_factory=lambda: bio)
|
|
171
177
|
|
|
172
178
|
|
|
179
|
+
@deprecated("Use the new GzipReader and GzipWriter classes from stream_io instead.", category=FutureWarning)
|
|
173
180
|
class GZipStream:
|
|
174
181
|
def __new__(cls, raw_stream, compression_level=9, zlib=False, fsspec_args=None):
|
|
175
182
|
from ..stream_io import GzipReader, GzipWriter
|
|
@@ -181,6 +188,7 @@ class GZipStream:
|
|
|
181
188
|
return stream
|
|
182
189
|
|
|
183
190
|
|
|
191
|
+
@deprecated("Use the new Lz4Reader and Lz4Writer classes from stream_io instead.", category=FutureWarning)
|
|
184
192
|
class LZ4Stream:
|
|
185
193
|
def __new__(cls, raw_stream, mode='r', compression_level=12,
|
|
186
194
|
favor_dec_speed=True, fsspec_args=None):
|
|
@@ -192,6 +200,7 @@ class LZ4Stream:
|
|
|
192
200
|
return stream
|
|
193
201
|
|
|
194
202
|
|
|
203
|
+
@deprecated("Use the new BrotliReader and BrotliWriter classes from stream_io instead.", category=FutureWarning)
|
|
195
204
|
class BrotliStream:
|
|
196
205
|
def __new__(cls, raw_stream, quality=11, lgwin=22, lgblock=0, fsspec_args=None):
|
|
197
206
|
from ..stream_io import BrotliReader, BrotliWriter
|
|
@@ -128,18 +128,19 @@ _WriterInput = WarcWriter | BinaryIO | _GenericWriter | PathLike[str] | str
|
|
|
128
128
|
|
|
129
129
|
@disjoint_base
|
|
130
130
|
class GzipReader(WarcReader):
|
|
131
|
-
def __new__(cls, inner: _ReaderInput, buffer_size: int =
|
|
131
|
+
def __new__(cls, inner: _ReaderInput, buffer_size: int = 64 << 10, zlib: bool = False,
|
|
132
|
+
fsspec_args=None) -> Self: ...
|
|
132
133
|
|
|
133
134
|
|
|
134
135
|
@disjoint_base
|
|
135
136
|
class GzipWriter(WarcWriter):
|
|
136
|
-
def __new__(cls, inner: _WriterInput, compression_level: int = 9, buffer_size=8192, zlib=False,
|
|
137
|
+
def __new__(cls, inner: _WriterInput, compression_level: int = 9, buffer_size: int = 8192, zlib=False,
|
|
137
138
|
fsspec_args=None) -> Self: ...
|
|
138
139
|
|
|
139
140
|
|
|
140
141
|
@disjoint_base
|
|
141
142
|
class ZstdReader(WarcReader):
|
|
142
|
-
def __new__(cls, inner: _ReaderInput, buffer_size: int =
|
|
143
|
+
def __new__(cls, inner: _ReaderInput, buffer_size: int = 64 << 10, fsspec_args=None,
|
|
143
144
|
dictionary: bytes | None = None) -> Self: ...
|
|
144
145
|
|
|
145
146
|
|
|
@@ -151,7 +152,7 @@ class ZstdWriter(WarcWriter):
|
|
|
151
152
|
|
|
152
153
|
@disjoint_base
|
|
153
154
|
class Lz4Reader(WarcReader):
|
|
154
|
-
def __new__(cls, inner: _ReaderInput, buffer_size: int =
|
|
155
|
+
def __new__(cls, inner: _ReaderInput, buffer_size: int = 64 << 10, fsspec_args=None) -> Self: ...
|
|
155
156
|
|
|
156
157
|
|
|
157
158
|
@disjoint_base
|
|
@@ -161,7 +162,7 @@ class Lz4Writer(WarcWriter):
|
|
|
161
162
|
|
|
162
163
|
@disjoint_base
|
|
163
164
|
class BrotliReader(WarcReader):
|
|
164
|
-
def __new__(cls, inner: _ReaderInput, buffer_size: int =
|
|
165
|
+
def __new__(cls, inner: _ReaderInput, buffer_size: int = 64 << 10, fsspec_args=None) -> Self: ...
|
|
165
166
|
|
|
166
167
|
|
|
167
168
|
@disjoint_base
|
|
@@ -171,12 +172,12 @@ class BrotliWriter(WarcWriter):
|
|
|
171
172
|
|
|
172
173
|
@disjoint_base
|
|
173
174
|
class ChunkedReader(WarcReader):
|
|
174
|
-
def __new__(cls, inner: _ReaderInput, buffer_size: int =
|
|
175
|
+
def __new__(cls, inner: _ReaderInput, buffer_size: int = 4096, fsspec_args=None) -> Self: ...
|
|
175
176
|
|
|
176
177
|
|
|
177
178
|
@disjoint_base
|
|
178
179
|
class ChunkedWriter(WarcWriter):
|
|
179
|
-
def __new__(cls, inner: _WriterInput, min_chunk_size: int =
|
|
180
|
+
def __new__(cls, inner: _WriterInput, min_chunk_size: int = 1024, fsspec_args=None) -> Self: ...
|
|
180
181
|
|
|
181
182
|
|
|
182
183
|
def zstd_train_dictionary_from_continuous(sample_data: bytes, sample_sizes: list[int], max_size: int) -> bytes: ...
|
|
@@ -16,7 +16,7 @@ from datetime import datetime
|
|
|
16
16
|
from collections.abc import Callable, Iterable, Iterator
|
|
17
17
|
from enum import IntFlag
|
|
18
18
|
from typing import BinaryIO, final, Literal, Self
|
|
19
|
-
from typing_extensions import disjoint_base
|
|
19
|
+
from typing_extensions import deprecated, disjoint_base
|
|
20
20
|
|
|
21
21
|
from .stream_io import _GenericReader, _GenericWriter, _ReaderInput, WarcReader, WarcWriter
|
|
22
22
|
|
|
@@ -95,8 +95,7 @@ no_type = WarcRecordType.no_type
|
|
|
95
95
|
any_type = WarcRecordType.any_type
|
|
96
96
|
|
|
97
97
|
|
|
98
|
-
|
|
99
|
-
class HeaderMap:
|
|
98
|
+
class _HeaderMap:
|
|
100
99
|
def __new__(cls, encoding: str = "utf-8") -> Self: ...
|
|
101
100
|
|
|
102
101
|
@property
|
|
@@ -127,12 +126,12 @@ class HeaderMap:
|
|
|
127
126
|
|
|
128
127
|
def to_dict(self) -> dict[str, str]: ...
|
|
129
128
|
|
|
130
|
-
|
|
129
|
+
@deprecated("Use to_dict() instead.")
|
|
131
130
|
def asdict(self) -> dict[str, str]: ...
|
|
132
131
|
|
|
133
132
|
def to_tuples(self) -> tuple[tuple[str, str], ...]: ...
|
|
134
133
|
|
|
135
|
-
|
|
134
|
+
@deprecated("Use to_tuples() instead.")
|
|
136
135
|
def astuples(self) -> tuple[tuple[str, str], ...]: ...
|
|
137
136
|
|
|
138
137
|
def is_empty(self) -> bool: ...
|
|
@@ -198,8 +197,13 @@ class HeaderMap:
|
|
|
198
197
|
def __setstate__(self, state: tuple[bytes, bool]): ...
|
|
199
198
|
|
|
200
199
|
|
|
201
|
-
|
|
202
|
-
|
|
200
|
+
@final
|
|
201
|
+
class HeaderMap(_HeaderMap): ...
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
@deprecated("Use HeaderMap instead.")
|
|
205
|
+
@final
|
|
206
|
+
class WarcHeaderMap(_HeaderMap): ...
|
|
203
207
|
|
|
204
208
|
|
|
205
209
|
@final
|
|
@@ -287,10 +291,10 @@ class WarcRecord:
|
|
|
287
291
|
|
|
288
292
|
def consume(self, n: int | None = None) -> int: ...
|
|
289
293
|
|
|
290
|
-
def parse_warc_headers(self, quirks_mode: bool = False) -> int: ...
|
|
294
|
+
def parse_warc_headers(self, quirks_mode: bool = False, max_header_len: int = 32 << 10) -> int: ...
|
|
291
295
|
|
|
292
|
-
def parse_http(self, auto_decode: Literal['none', 'content', 'transfer', 'all'] = 'none',
|
|
293
|
-
strict_mode: bool = True): ...
|
|
296
|
+
def parse_http(self, auto_decode: Literal['none', 'content', 'transfer', 'all'] = 'none',
|
|
297
|
+
max_header_len: int = 32 << 10, quirks_mode: bool = False, *, strict_mode: bool = True): ...
|
|
294
298
|
|
|
295
299
|
def verify_block_digest(self, consume: bool = False) -> bool: ...
|
|
296
300
|
|
|
@@ -332,7 +336,10 @@ class ArchiveIterator(Iterable[WarcRecord]):
|
|
|
332
336
|
verify_digests: bool = False,
|
|
333
337
|
quirks_mode: bool = False,
|
|
334
338
|
auto_decode: Literal['none', 'content', 'transfer', 'all'] = 'none',
|
|
339
|
+
max_header_len: int = 32 << 10,
|
|
335
340
|
stream_detect: bool = True,
|
|
341
|
+
buffer_size: int = 64 << 10,
|
|
342
|
+
inplace: bool = False,
|
|
336
343
|
fsspec_args=None,
|
|
337
344
|
*,
|
|
338
345
|
strict_mode: bool = True
|
|
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "FastWARC"
|
|
7
|
-
version = "1.0.
|
|
8
|
-
description = "
|
|
7
|
+
version = "1.0.4"
|
|
8
|
+
description = "The world's fastest WARC parsing library written in Rust with bindings for Python."
|
|
9
9
|
authors = [
|
|
10
10
|
{ name = "Janek Bevendorff" }
|
|
11
11
|
]
|
|
@@ -15,7 +15,8 @@ requires-python = ">=3.10"
|
|
|
15
15
|
dependencies = [
|
|
16
16
|
"brotli",
|
|
17
17
|
"click",
|
|
18
|
-
"tqdm"
|
|
18
|
+
"tqdm",
|
|
19
|
+
"typing_extensions>=4.5; python_version < '3.13'",
|
|
19
20
|
]
|
|
20
21
|
|
|
21
22
|
[project.urls]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|