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.
Files changed (53) hide show
  1. {fastwarc-1.0.2 → fastwarc-1.0.4}/FastWARC.egg-info/PKG-INFO +3 -2
  2. {fastwarc-1.0.2 → fastwarc-1.0.4}/FastWARC.egg-info/requires.txt +3 -0
  3. {fastwarc-1.0.2 → fastwarc-1.0.4}/PKG-INFO +3 -2
  4. {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/cli.py +31 -116
  5. {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/_shims.py +21 -12
  6. {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/stream_io.pyi +8 -7
  7. {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/warc.pyi +17 -10
  8. {fastwarc-1.0.2 → fastwarc-1.0.4}/pyproject.toml +4 -3
  9. {fastwarc-1.0.2 → fastwarc-1.0.4}/FastWARC.egg-info/SOURCES.txt +0 -0
  10. {fastwarc-1.0.2 → fastwarc-1.0.4}/FastWARC.egg-info/dependency_links.txt +0 -0
  11. {fastwarc-1.0.2 → fastwarc-1.0.4}/FastWARC.egg-info/entry_points.txt +0 -0
  12. {fastwarc-1.0.2 → fastwarc-1.0.4}/FastWARC.egg-info/top_level.txt +0 -0
  13. {fastwarc-1.0.2 → fastwarc-1.0.4}/MANIFEST.in +0 -0
  14. {fastwarc-1.0.2 → fastwarc-1.0.4}/README.md +0 -0
  15. {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/__init__.py +0 -0
  16. {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/__init__.pyi +0 -0
  17. {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/__init__.pxd +0 -0
  18. {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/__init__.py +0 -0
  19. {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/__init__.pyi +0 -0
  20. {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/stream_io.pxd +0 -0
  21. {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/stream_io.pyi +0 -0
  22. {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/stream_io.pyx +0 -0
  23. {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/tools.pyi +0 -0
  24. {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/tools.pyx +0 -0
  25. {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/warc.pxd +0 -0
  26. {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/warc.pyi +0 -0
  27. {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/legacy/warc.pyx +0 -0
  28. {fastwarc-1.0.2 → fastwarc-1.0.4}/fastwarc/py.typed +0 -0
  29. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_common/__init__.pxd +0 -0
  30. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_common/string_util.pxd +0 -0
  31. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/__init__.pxd +0 -0
  32. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/algorithm.pxd +0 -0
  33. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/atomic.pxd +0 -0
  34. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/boost_regex.pxd +0 -0
  35. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/cctype.pxd +0 -0
  36. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/cstdlib.pxd +0 -0
  37. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/cstring.pxd +0 -0
  38. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/dlfcn.pxd +0 -0
  39. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/errno.pxd +0 -0
  40. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/lexbor.pxd +0 -0
  41. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/lz4frame.pxd +0 -0
  42. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/lz4hc.pxd +0 -0
  43. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/pthread.pxd +0 -0
  44. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/re2.pxd +0 -0
  45. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/stdio.pxd +0 -0
  46. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/string_view.pxd +0 -0
  47. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/time.pxd +0 -0
  48. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/uchardet.pxd +0 -0
  49. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/unistd.pxd +0 -0
  50. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/utility.pxd +0 -0
  51. {fastwarc-1.0.2 → fastwarc-1.0.4}/resiliparse_inc/zlib.pxd +0 -0
  52. {fastwarc-1.0.2 → fastwarc-1.0.4}/setup.cfg +0 -0
  53. {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.2
4
- Summary: A high-performance WARC parsing library written in Rust with bindings for Python.
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
@@ -2,6 +2,9 @@ brotli
2
2
  click
3
3
  tqdm
4
4
 
5
+ [:python_version < "3.13"]
6
+ typing_extensions>=4.5
7
+
5
8
  [all]
6
9
  fastwarc[fsspec]
7
10
 
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: FastWARC
3
- Version: 1.0.2
4
- Summary: A high-performance WARC parsing library written in Rust with bindings for Python.
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, verify_digests
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 == OSError:
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(['uncompressed', 'gzip', 'zstd', 'lz4', 'auto']),
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(['uncompressed', 'gzip', 'zstd', 'lz4', 'auto']),
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, not compressed
161
- properly at the record-level, or if you want to recompress a Gzip WARC as Zstd or LZ4 or vice versa.
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.upper())
165
- decompress_alg = getattr(CompressionAlg, decompress_alg.upper())
77
+ compress_alg = getattr(CompressionAlg, compress_alg)
78
+ decompress_alg = getattr(CompressionAlg, decompress_alg)
166
79
 
167
- infile = get_decompressor(infile, decompress_alg if decompress_alg != CompressionAlg.AUTO else None)
168
- outfile_name = outfile
169
- outfile = get_compressor(outfile, compress_alg, compress_level)
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.monotonic()
89
+ start = time.time()
173
90
  try:
174
- with outfile as out:
175
- for r in tqdm(ArchiveIterator(infile),
176
- desc='Recompressing WARC file', unit=' record(s)', leave=False,
177
- disable=quiet, mininterval=0.3):
178
- num += 1
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
- if not quiet:
184
- click.echo('Recompression completed.')
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(os.stat(outfile_name).st_size)}')
193
- click.echo(f' - Completed in: {time.monotonic() - start:.02f} seconds')
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
- import warnings
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
- StreamError = OSError
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 = 4096, zlib: bool = False, fsspec_args=None) -> Self: ...
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 = 4096, fsspec_args=None,
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 = 4096, fsspec_args=None) -> Self: ...
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 = 4096, fsspec_args=None) -> Self: ...
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 = 1024, fsspec_args=None) -> Self: ...
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 = 512, fsspec_args=None) -> Self: ...
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
- @final
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
- # deprecated
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
- # deprecated
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
- # Legacy name
202
- WarcHeaderMap = HeaderMap
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.2"
8
- description = "A high-performance WARC parsing library written in Rust with bindings for Python."
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