FastWARC 1.0.1__tar.gz → 1.0.2__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 (56) hide show
  1. fastwarc-1.0.2/FastWARC.egg-info/PKG-INFO +110 -0
  2. {fastwarc-1.0.1 → fastwarc-1.0.2}/FastWARC.egg-info/SOURCES.txt +1 -0
  3. {fastwarc-1.0.1 → fastwarc-1.0.2}/FastWARC.egg-info/requires.txt +1 -1
  4. fastwarc-1.0.2/PKG-INFO +110 -0
  5. fastwarc-1.0.2/README.md +86 -0
  6. {fastwarc-1.0.1 → fastwarc-1.0.2}/fastwarc/cli.py +115 -29
  7. fastwarc-1.0.2/fastwarc/legacy/__init__.pyi +19 -0
  8. {fastwarc-1.0.1 → fastwarc-1.0.2}/fastwarc/stream_io.pyi +12 -11
  9. {fastwarc-1.0.1 → fastwarc-1.0.2}/fastwarc/warc.pyi +10 -0
  10. {fastwarc-1.0.1 → fastwarc-1.0.2}/pyproject.toml +6 -6
  11. fastwarc-1.0.1/FastWARC.egg-info/PKG-INFO +0 -97
  12. fastwarc-1.0.1/PKG-INFO +0 -97
  13. fastwarc-1.0.1/README.md +0 -73
  14. {fastwarc-1.0.1 → fastwarc-1.0.2}/FastWARC.egg-info/dependency_links.txt +0 -0
  15. {fastwarc-1.0.1 → fastwarc-1.0.2}/FastWARC.egg-info/entry_points.txt +0 -0
  16. {fastwarc-1.0.1 → fastwarc-1.0.2}/FastWARC.egg-info/top_level.txt +0 -0
  17. {fastwarc-1.0.1 → fastwarc-1.0.2}/MANIFEST.in +0 -0
  18. {fastwarc-1.0.1 → fastwarc-1.0.2}/fastwarc/__init__.py +0 -0
  19. {fastwarc-1.0.1 → fastwarc-1.0.2}/fastwarc/__init__.pyi +0 -0
  20. {fastwarc-1.0.1 → fastwarc-1.0.2}/fastwarc/legacy/__init__.pxd +0 -0
  21. {fastwarc-1.0.1 → fastwarc-1.0.2}/fastwarc/legacy/__init__.py +0 -0
  22. {fastwarc-1.0.1 → fastwarc-1.0.2}/fastwarc/legacy/_shims.py +0 -0
  23. {fastwarc-1.0.1 → fastwarc-1.0.2}/fastwarc/legacy/stream_io.pxd +0 -0
  24. {fastwarc-1.0.1 → fastwarc-1.0.2}/fastwarc/legacy/stream_io.pyi +0 -0
  25. {fastwarc-1.0.1 → fastwarc-1.0.2}/fastwarc/legacy/stream_io.pyx +0 -0
  26. {fastwarc-1.0.1 → fastwarc-1.0.2}/fastwarc/legacy/tools.pyi +0 -0
  27. {fastwarc-1.0.1 → fastwarc-1.0.2}/fastwarc/legacy/tools.pyx +0 -0
  28. {fastwarc-1.0.1 → fastwarc-1.0.2}/fastwarc/legacy/warc.pxd +0 -0
  29. {fastwarc-1.0.1 → fastwarc-1.0.2}/fastwarc/legacy/warc.pyi +0 -0
  30. {fastwarc-1.0.1 → fastwarc-1.0.2}/fastwarc/legacy/warc.pyx +0 -0
  31. {fastwarc-1.0.1 → fastwarc-1.0.2}/fastwarc/py.typed +0 -0
  32. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_common/__init__.pxd +0 -0
  33. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_common/string_util.pxd +0 -0
  34. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_inc/__init__.pxd +0 -0
  35. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_inc/algorithm.pxd +0 -0
  36. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_inc/atomic.pxd +0 -0
  37. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_inc/boost_regex.pxd +0 -0
  38. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_inc/cctype.pxd +0 -0
  39. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_inc/cstdlib.pxd +0 -0
  40. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_inc/cstring.pxd +0 -0
  41. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_inc/dlfcn.pxd +0 -0
  42. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_inc/errno.pxd +0 -0
  43. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_inc/lexbor.pxd +0 -0
  44. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_inc/lz4frame.pxd +0 -0
  45. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_inc/lz4hc.pxd +0 -0
  46. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_inc/pthread.pxd +0 -0
  47. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_inc/re2.pxd +0 -0
  48. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_inc/stdio.pxd +0 -0
  49. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_inc/string_view.pxd +0 -0
  50. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_inc/time.pxd +0 -0
  51. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_inc/uchardet.pxd +0 -0
  52. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_inc/unistd.pxd +0 -0
  53. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_inc/utility.pxd +0 -0
  54. {fastwarc-1.0.1 → fastwarc-1.0.2}/resiliparse_inc/zlib.pxd +0 -0
  55. {fastwarc-1.0.1 → fastwarc-1.0.2}/setup.cfg +0 -0
  56. {fastwarc-1.0.1 → fastwarc-1.0.2}/setup.py +0 -0
@@ -0,0 +1,110 @@
1
+ Metadata-Version: 2.4
2
+ Name: FastWARC
3
+ Version: 1.0.2
4
+ Summary: A high-performance WARC parsing library written in Rust with bindings for Python.
5
+ Author: Janek Bevendorff
6
+ License-Expression: Apache-2.0
7
+ Project-URL: repository, https://github.com/chatnoir-eu/chatnoir-resiliparse
8
+ Project-URL: homepage, https://resiliparse.chatnoir.eu
9
+ Project-URL: documentation, https://resiliparse.chatnoir.eu
10
+ Requires-Python: >=3.10
11
+ Description-Content-Type: text/markdown
12
+ Requires-Dist: brotli
13
+ Requires-Dist: click
14
+ Requires-Dist: tqdm
15
+ Provides-Extra: all
16
+ Requires-Dist: fastwarc[fsspec]; extra == "all"
17
+ Provides-Extra: fsspec
18
+ Requires-Dist: fsspec; extra == "fsspec"
19
+ Requires-Dist: s3fs; extra == "fsspec"
20
+ Provides-Extra: test
21
+ Requires-Dist: fastwarc[all]; extra == "test"
22
+ Requires-Dist: pytest>=7.2.2; extra == "test"
23
+ Requires-Dist: pytest-cov>=4.0.0; extra == "test"
24
+
25
+ # FastWARC (Python)
26
+
27
+ FastWARC is a high-performance WARC parsing library written in Rust with bindings for Python.
28
+ FastWARC supports compressed and uncompressed WARC/1.0 and WARC/1.1 streams. Supported compression algorithms are Gzip,
29
+ Zstd, and LZ4.
30
+
31
+ This package contains the Python bindings for FastWARC.
32
+
33
+ FastWARC belongs to the [ChatNoir Resiliparse toolkit](https://github.com/chatnoir-eu/chatnoir-resiliparse/) for fast
34
+ and robust web data processing.
35
+
36
+ ## Installing FastWARC
37
+
38
+ Pre-built FastWARC binaries for Python can be installed from [PyPi](https://pypi.org/project/FastWARC/):
39
+
40
+ ```bash
41
+ pip install fastwarc
42
+ ```
43
+
44
+ ## Building Python Bindings From Source
45
+
46
+ To be able to build FastWARC, you need the Rust toolchain installed (see above). Then to build directly from the GitHub
47
+ repository, follow these steps:
48
+
49
+ ```bash
50
+ # Clone repository
51
+
52
+ git clone https://github.com/chatnoir-eu/chatnoir-resiliparse.git
53
+ cd chatnoir-resiliparse
54
+
55
+ # Install Rust toolchain (if not already installed)
56
+
57
+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
58
+
59
+ # Create a fresh venv first (recommended)
60
+
61
+ python3 -m venv venv && source venv/bin/activate
62
+
63
+ # Option 1: Build and install in editable mode (best for development)
64
+
65
+ python3 -m pip install -e ./fastwarc-py
66
+
67
+ # Option 2 (alternative): Build and install wheels in separate steps (best for redistribution)
68
+
69
+ python3 -m pip wheel -w build ./fastwarc-py
70
+ ls ./build/*.whl | xargs python3 -m pip install
71
+ ```
72
+
73
+ ## Usage Instructions
74
+
75
+ For detailed usage instructions, please consult
76
+ the [FastWARC User Manual](https://resiliparse.chatnoir.eu/en/latest/man/fastwarc.html).
77
+
78
+ ## Cite Us
79
+
80
+ If you use FastWARC, please consider citing our [OSSYM 2021 abstract paper](https://arxiv.org/abs/2112.03103):
81
+
82
+ ```bibtex
83
+ @InProceedings{bevendorff:2021,
84
+ author = {Janek Bevendorff and Martin Potthast and Benno Stein},
85
+ booktitle = {3rd International Symposium on Open Search Technology (OSSYM 2021)},
86
+ editor = {Andreas Wagner and Christian Guetl and Michael Granitzer and Stefan Voigt},
87
+ month = oct,
88
+ publisher = {International Open Search Symposium},
89
+ site = {CERN, Geneva, Switzerland},
90
+ title = {{FastWARC: Optimizing Large-Scale Web Archive Analytics}},
91
+ year = 2021
92
+ }
93
+ ```
94
+
95
+ You can also cite our [ECIR 2018 demo paper](https://webis.de/downloads/publications/papers/bevendorff_2018.pdf):
96
+
97
+ ```bibtex
98
+ @InProceedings{bevendorff:2018,
99
+ address = {Berlin Heidelberg New York},
100
+ author = {Janek Bevendorff and Benno Stein and Matthias Hagen and Martin Potthast},
101
+ booktitle = {Advances in Information Retrieval. 40th European Conference on IR Research (ECIR 2018)},
102
+ editor = {Leif Azzopardi and Allan Hanbury and Gabriella Pasi and Benjamin Piwowarski},
103
+ month = mar,
104
+ publisher = {Springer},
105
+ series = {Lecture Notes in Computer Science},
106
+ site = {Grenoble, France},
107
+ title = {{Elastic ChatNoir: Search Engine for the ClueWeb and the Common Crawl}},
108
+ year = 2018
109
+ }
110
+ ```
@@ -16,6 +16,7 @@ fastwarc/stream_io.pyi
16
16
  fastwarc/warc.pyi
17
17
  fastwarc/legacy/__init__.pxd
18
18
  fastwarc/legacy/__init__.py
19
+ fastwarc/legacy/__init__.pyi
19
20
  fastwarc/legacy/_shims.py
20
21
  fastwarc/legacy/stream_io.pxd
21
22
  fastwarc/legacy/stream_io.pyi
@@ -7,9 +7,9 @@ fastwarc[fsspec]
7
7
 
8
8
  [fsspec]
9
9
  fsspec
10
+ s3fs
10
11
 
11
12
  [test]
12
13
  fastwarc[all]
13
14
  pytest>=7.2.2
14
15
  pytest-cov>=4.0.0
15
- lz4
@@ -0,0 +1,110 @@
1
+ Metadata-Version: 2.4
2
+ Name: FastWARC
3
+ Version: 1.0.2
4
+ Summary: A high-performance WARC parsing library written in Rust with bindings for Python.
5
+ Author: Janek Bevendorff
6
+ License-Expression: Apache-2.0
7
+ Project-URL: repository, https://github.com/chatnoir-eu/chatnoir-resiliparse
8
+ Project-URL: homepage, https://resiliparse.chatnoir.eu
9
+ Project-URL: documentation, https://resiliparse.chatnoir.eu
10
+ Requires-Python: >=3.10
11
+ Description-Content-Type: text/markdown
12
+ Requires-Dist: brotli
13
+ Requires-Dist: click
14
+ Requires-Dist: tqdm
15
+ Provides-Extra: all
16
+ Requires-Dist: fastwarc[fsspec]; extra == "all"
17
+ Provides-Extra: fsspec
18
+ Requires-Dist: fsspec; extra == "fsspec"
19
+ Requires-Dist: s3fs; extra == "fsspec"
20
+ Provides-Extra: test
21
+ Requires-Dist: fastwarc[all]; extra == "test"
22
+ Requires-Dist: pytest>=7.2.2; extra == "test"
23
+ Requires-Dist: pytest-cov>=4.0.0; extra == "test"
24
+
25
+ # FastWARC (Python)
26
+
27
+ FastWARC is a high-performance WARC parsing library written in Rust with bindings for Python.
28
+ FastWARC supports compressed and uncompressed WARC/1.0 and WARC/1.1 streams. Supported compression algorithms are Gzip,
29
+ Zstd, and LZ4.
30
+
31
+ This package contains the Python bindings for FastWARC.
32
+
33
+ FastWARC belongs to the [ChatNoir Resiliparse toolkit](https://github.com/chatnoir-eu/chatnoir-resiliparse/) for fast
34
+ and robust web data processing.
35
+
36
+ ## Installing FastWARC
37
+
38
+ Pre-built FastWARC binaries for Python can be installed from [PyPi](https://pypi.org/project/FastWARC/):
39
+
40
+ ```bash
41
+ pip install fastwarc
42
+ ```
43
+
44
+ ## Building Python Bindings From Source
45
+
46
+ To be able to build FastWARC, you need the Rust toolchain installed (see above). Then to build directly from the GitHub
47
+ repository, follow these steps:
48
+
49
+ ```bash
50
+ # Clone repository
51
+
52
+ git clone https://github.com/chatnoir-eu/chatnoir-resiliparse.git
53
+ cd chatnoir-resiliparse
54
+
55
+ # Install Rust toolchain (if not already installed)
56
+
57
+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
58
+
59
+ # Create a fresh venv first (recommended)
60
+
61
+ python3 -m venv venv && source venv/bin/activate
62
+
63
+ # Option 1: Build and install in editable mode (best for development)
64
+
65
+ python3 -m pip install -e ./fastwarc-py
66
+
67
+ # Option 2 (alternative): Build and install wheels in separate steps (best for redistribution)
68
+
69
+ python3 -m pip wheel -w build ./fastwarc-py
70
+ ls ./build/*.whl | xargs python3 -m pip install
71
+ ```
72
+
73
+ ## Usage Instructions
74
+
75
+ For detailed usage instructions, please consult
76
+ the [FastWARC User Manual](https://resiliparse.chatnoir.eu/en/latest/man/fastwarc.html).
77
+
78
+ ## Cite Us
79
+
80
+ If you use FastWARC, please consider citing our [OSSYM 2021 abstract paper](https://arxiv.org/abs/2112.03103):
81
+
82
+ ```bibtex
83
+ @InProceedings{bevendorff:2021,
84
+ author = {Janek Bevendorff and Martin Potthast and Benno Stein},
85
+ booktitle = {3rd International Symposium on Open Search Technology (OSSYM 2021)},
86
+ editor = {Andreas Wagner and Christian Guetl and Michael Granitzer and Stefan Voigt},
87
+ month = oct,
88
+ publisher = {International Open Search Symposium},
89
+ site = {CERN, Geneva, Switzerland},
90
+ title = {{FastWARC: Optimizing Large-Scale Web Archive Analytics}},
91
+ year = 2021
92
+ }
93
+ ```
94
+
95
+ You can also cite our [ECIR 2018 demo paper](https://webis.de/downloads/publications/papers/bevendorff_2018.pdf):
96
+
97
+ ```bibtex
98
+ @InProceedings{bevendorff:2018,
99
+ address = {Berlin Heidelberg New York},
100
+ author = {Janek Bevendorff and Benno Stein and Matthias Hagen and Martin Potthast},
101
+ booktitle = {Advances in Information Retrieval. 40th European Conference on IR Research (ECIR 2018)},
102
+ editor = {Leif Azzopardi and Allan Hanbury and Gabriella Pasi and Benjamin Piwowarski},
103
+ month = mar,
104
+ publisher = {Springer},
105
+ series = {Lecture Notes in Computer Science},
106
+ site = {Grenoble, France},
107
+ title = {{Elastic ChatNoir: Search Engine for the ClueWeb and the Common Crawl}},
108
+ year = 2018
109
+ }
110
+ ```
@@ -0,0 +1,86 @@
1
+ # FastWARC (Python)
2
+
3
+ FastWARC is a high-performance WARC parsing library written in Rust with bindings for Python.
4
+ FastWARC supports compressed and uncompressed WARC/1.0 and WARC/1.1 streams. Supported compression algorithms are Gzip,
5
+ Zstd, and LZ4.
6
+
7
+ This package contains the Python bindings for FastWARC.
8
+
9
+ FastWARC belongs to the [ChatNoir Resiliparse toolkit](https://github.com/chatnoir-eu/chatnoir-resiliparse/) for fast
10
+ and robust web data processing.
11
+
12
+ ## Installing FastWARC
13
+
14
+ Pre-built FastWARC binaries for Python can be installed from [PyPi](https://pypi.org/project/FastWARC/):
15
+
16
+ ```bash
17
+ pip install fastwarc
18
+ ```
19
+
20
+ ## Building Python Bindings From Source
21
+
22
+ To be able to build FastWARC, you need the Rust toolchain installed (see above). Then to build directly from the GitHub
23
+ repository, follow these steps:
24
+
25
+ ```bash
26
+ # Clone repository
27
+
28
+ git clone https://github.com/chatnoir-eu/chatnoir-resiliparse.git
29
+ cd chatnoir-resiliparse
30
+
31
+ # Install Rust toolchain (if not already installed)
32
+
33
+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
34
+
35
+ # Create a fresh venv first (recommended)
36
+
37
+ python3 -m venv venv && source venv/bin/activate
38
+
39
+ # Option 1: Build and install in editable mode (best for development)
40
+
41
+ python3 -m pip install -e ./fastwarc-py
42
+
43
+ # Option 2 (alternative): Build and install wheels in separate steps (best for redistribution)
44
+
45
+ python3 -m pip wheel -w build ./fastwarc-py
46
+ ls ./build/*.whl | xargs python3 -m pip install
47
+ ```
48
+
49
+ ## Usage Instructions
50
+
51
+ For detailed usage instructions, please consult
52
+ the [FastWARC User Manual](https://resiliparse.chatnoir.eu/en/latest/man/fastwarc.html).
53
+
54
+ ## Cite Us
55
+
56
+ If you use FastWARC, please consider citing our [OSSYM 2021 abstract paper](https://arxiv.org/abs/2112.03103):
57
+
58
+ ```bibtex
59
+ @InProceedings{bevendorff:2021,
60
+ author = {Janek Bevendorff and Martin Potthast and Benno Stein},
61
+ booktitle = {3rd International Symposium on Open Search Technology (OSSYM 2021)},
62
+ editor = {Andreas Wagner and Christian Guetl and Michael Granitzer and Stefan Voigt},
63
+ month = oct,
64
+ publisher = {International Open Search Symposium},
65
+ site = {CERN, Geneva, Switzerland},
66
+ title = {{FastWARC: Optimizing Large-Scale Web Archive Analytics}},
67
+ year = 2021
68
+ }
69
+ ```
70
+
71
+ You can also cite our [ECIR 2018 demo paper](https://webis.de/downloads/publications/papers/bevendorff_2018.pdf):
72
+
73
+ ```bibtex
74
+ @InProceedings{bevendorff:2018,
75
+ address = {Berlin Heidelberg New York},
76
+ author = {Janek Bevendorff and Benno Stein and Matthias Hagen and Martin Potthast},
77
+ booktitle = {Advances in Information Retrieval. 40th European Conference on IR Research (ECIR 2018)},
78
+ editor = {Leif Azzopardi and Allan Hanbury and Gabriella Pasi and Benjamin Piwowarski},
79
+ month = mar,
80
+ publisher = {Springer},
81
+ series = {Lecture Notes in Computer Science},
82
+ site = {Grenoble, France},
83
+ title = {{Elastic ChatNoir: Search Engine for the ClueWeb and the Common Crawl}},
84
+ year = 2018
85
+ }
86
+ ```
@@ -14,6 +14,7 @@
14
14
 
15
15
  import getpass
16
16
  import importlib
17
+ from enum import IntFlag
17
18
  from itertools import chain
18
19
  import json
19
20
  import os
@@ -24,14 +25,13 @@ import urllib.request
24
25
  import click
25
26
  from tqdm import tqdm
26
27
 
27
- from fastwarc.legacy.stream_io import FileStream, StreamError, FastWARCError, PythonIOStreamAdapter
28
- from fastwarc.legacy.warc import ArchiveIterator, WarcRecordType
29
- from fastwarc.legacy.tools import CompressionAlg, detect_compression_algorithm, wrap_warc_stream, \
30
- recompress_warc_interactive, verify_digests
28
+ from fastwarc.stream_io import *
29
+ from fastwarc.warc import ArchiveIterator, WarcRecordType
30
+ from fastwarc.legacy.tools import CompressionAlg, detect_compression_algorithm, wrap_warc_stream, verify_digests
31
31
 
32
32
 
33
33
  def exception_handler(exctype, value, _):
34
- if exctype == FastWARCError:
34
+ if exctype == OSError:
35
35
  click.echo(str(value), err=True)
36
36
  sys.exit(1)
37
37
 
@@ -56,46 +56,132 @@ 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
+
59
146
  @main.command()
60
147
  @click.argument('infile', type=click.Path(dir_okay=False, exists=True))
61
148
  @click.argument('outfile', type=click.Path(dir_okay=False, exists=False))
62
- @click.option('-c', '--compress-alg', type=click.Choice(['gzip', 'lz4', 'uncompressed', 'auto']),
149
+ @click.option('-c', '--compress-alg', type=click.Choice(['uncompressed', 'gzip', 'zstd', 'lz4', 'auto']),
63
150
  default='auto', show_default=True, help='Compression algorithm to use for output file')
64
- @click.option('-d', '--decompress-alg', type=click.Choice(['gzip', 'lz4', 'uncompressed', 'auto']),
151
+ @click.option('-d', '--decompress-alg', type=click.Choice(['uncompressed', 'gzip', 'zstd', 'lz4', 'auto']),
65
152
  default='auto', show_default=True,
66
153
  help='Decompression algorithm for decoding input file (auto tries to detect based on file extension)')
67
- @click.option('-l', '--compress-level', type=int, default=None, help='Compression level (defaults to max)')
154
+ @click.option('-l', '--compress-level', type=int, default=None, help='Compression level')
68
155
  @click.option('-q', '--quiet', is_flag=True, help='Do not print progress information')
69
156
  def recompress(infile, outfile, compress_alg, decompress_alg, compress_level, quiet):
70
157
  """
71
158
  Recompress a WARC file.
72
159
 
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.
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.
75
162
  """
76
163
 
77
- compress_alg = getattr(CompressionAlg, compress_alg)
78
- decompress_alg = getattr(CompressionAlg, decompress_alg)
164
+ compress_alg = getattr(CompressionAlg, compress_alg.upper())
165
+ decompress_alg = getattr(CompressionAlg, decompress_alg.upper())
79
166
 
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
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)
86
170
 
87
- bytes_written = 0
88
171
  num = 0
89
- start = time.time()
172
+ start = time.monotonic()
90
173
  try:
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
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()
96
182
 
97
- if not quiet:
98
- click.echo('Recompression completed.')
183
+ if not quiet:
184
+ click.echo('Recompression completed.')
99
185
  except KeyboardInterrupt:
100
186
  if not quiet:
101
187
  click.echo('Recompression aborted.')
@@ -103,8 +189,8 @@ def recompress(infile, outfile, compress_alg, decompress_alg, compress_level, qu
103
189
  finally:
104
190
  if not quiet and num > 0:
105
191
  click.echo(f' - Records recompressed: {num}')
106
- click.echo(f' - Bytes written: {_human_readable_bytes(bytes_written)}')
107
- click.echo(f' - Completed in: {time.time() - start:.02f} seconds')
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')
108
194
 
109
195
 
110
196
  @main.command()
@@ -0,0 +1,19 @@
1
+ from .stream_io import (
2
+ FileStream,
3
+ GZipStream,
4
+ LZ4Stream,
5
+ FastWARCError,
6
+ StreamError,
7
+ )
8
+ from .warc import ArchiveIterator, WarcRecord, WarcRecordType
9
+
10
+ __all__ = [
11
+ "FileStream",
12
+ "GZipStream",
13
+ "LZ4Stream",
14
+ "FastWARCError",
15
+ "StreamError",
16
+ "ArchiveIterator",
17
+ "WarcRecord",
18
+ "WarcRecordType",
19
+ ]
@@ -128,54 +128,55 @@ _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=4096, zlib=False, fsspec_args=None) -> Self: ...
131
+ def __new__(cls, inner: _ReaderInput, buffer_size: int = 4096, zlib: bool = False, fsspec_args=None) -> Self: ...
132
132
 
133
133
 
134
134
  @disjoint_base
135
135
  class GzipWriter(WarcWriter):
136
- def __new__(cls, inner: _WriterInput, compression_level=9, buffer_size=8192, zlib=False,
136
+ def __new__(cls, inner: _WriterInput, compression_level: int = 9, buffer_size=8192, zlib=False,
137
137
  fsspec_args=None) -> Self: ...
138
138
 
139
139
 
140
140
  @disjoint_base
141
141
  class ZstdReader(WarcReader):
142
- def __new__(cls, inner: _ReaderInput, buffer_size=4096, fsspec_args=None, dictionary=None) -> Self: ...
142
+ def __new__(cls, inner: _ReaderInput, buffer_size: int = 4096, fsspec_args=None,
143
+ dictionary: bytes | None = None) -> Self: ...
143
144
 
144
145
 
145
146
  @disjoint_base
146
147
  class ZstdWriter(WarcWriter):
147
- def __new__(cls, inner: _WriterInput, buffer_size=8192, fsspec_args=None, dictionary=None,
148
- compress_dictionary_frame=False) -> Self: ...
148
+ def __new__(cls, inner: _WriterInput, buffer_size: int = 8192, compression_level: int = 3, fsspec_args=None,
149
+ dictionary: bytes | None = None, compress_dictionary_frame=False) -> Self: ...
149
150
 
150
151
 
151
152
  @disjoint_base
152
153
  class Lz4Reader(WarcReader):
153
- def __new__(cls, inner: _ReaderInput, buffer_size=4096, fsspec_args=None) -> Self: ...
154
+ def __new__(cls, inner: _ReaderInput, buffer_size: int = 4096, fsspec_args=None) -> Self: ...
154
155
 
155
156
 
156
157
  @disjoint_base
157
158
  class Lz4Writer(WarcWriter):
158
- def __new__(cls, inner: _WriterInput, buffer_size=8192, fsspec_args=None) -> Self: ...
159
+ def __new__(cls, inner: _WriterInput, buffer_size: int = 8192, fsspec_args=None) -> Self: ...
159
160
 
160
161
 
161
162
  @disjoint_base
162
163
  class BrotliReader(WarcReader):
163
- def __new__(cls, inner: _ReaderInput, buffer_size=4096, fsspec_args=None) -> Self: ...
164
+ def __new__(cls, inner: _ReaderInput, buffer_size: int = 4096, fsspec_args=None) -> Self: ...
164
165
 
165
166
 
166
167
  @disjoint_base
167
168
  class BrotliWriter(WarcWriter):
168
- def __new__(cls, inner: _WriterInput, buffer_size=8192, fsspec_args=None) -> Self: ...
169
+ def __new__(cls, inner: _WriterInput, buffer_size: int = 8192, fsspec_args=None) -> Self: ...
169
170
 
170
171
 
171
172
  @disjoint_base
172
173
  class ChunkedReader(WarcReader):
173
- def __new__(cls, inner: _ReaderInput, buffer_size=1024, fsspec_args=None) -> Self: ...
174
+ def __new__(cls, inner: _ReaderInput, buffer_size: int = 1024, fsspec_args=None) -> Self: ...
174
175
 
175
176
 
176
177
  @disjoint_base
177
178
  class ChunkedWriter(WarcWriter):
178
- def __new__(cls, inner: _WriterInput, min_chunk_size=512, fsspec_args=None) -> Self: ...
179
+ def __new__(cls, inner: _WriterInput, min_chunk_size: int = 512, fsspec_args=None) -> Self: ...
179
180
 
180
181
 
181
182
  def zstd_train_dictionary_from_continuous(sample_data: bytes, sample_sizes: list[int], max_size: int) -> bytes: ...
@@ -213,6 +213,12 @@ class WarcRecordPayloadReader(WarcReader):
213
213
  class WarcRecord:
214
214
  def __new__(cls) -> Self: ...
215
215
 
216
+ @classmethod
217
+ def from_bytes(cls, payload: bytes) -> Self: ...
218
+
219
+ @classmethod
220
+ def from_reader(cls, reader: _ReaderInput, quirks_mode: bool = False) -> Self: ...
221
+
216
222
  @property
217
223
  def record_id(self) -> str | None: ...
218
224
 
@@ -298,6 +304,10 @@ class WarcRecord:
298
304
  chunk_size: int = 16384
299
305
  ) -> int: ...
300
306
 
307
+ def __eq__(self, other, /) -> bool: ...
308
+
309
+ def __ne__(self, other, /) -> bool: ...
310
+
301
311
  def __str__(self) -> str: ...
302
312
 
303
313
  def __repr__(self) -> str: ...
@@ -4,14 +4,14 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "FastWARC"
7
- version = "1.0.1"
8
- description = "A high-performance WARC parsing library for Python written in C++/Cython."
7
+ version = "1.0.2"
8
+ description = "A high-performance WARC parsing library written in Rust with bindings for Python."
9
9
  authors = [
10
10
  { name = "Janek Bevendorff" }
11
11
  ]
12
12
  license = "Apache-2.0"
13
13
  readme = "README.md"
14
- requires-python = ">=3.8"
14
+ requires-python = ">=3.10"
15
15
  dependencies = [
16
16
  "brotli",
17
17
  "click",
@@ -28,20 +28,20 @@ all = [
28
28
  "fastwarc[fsspec]"
29
29
  ]
30
30
  fsspec = [
31
- "fsspec"
31
+ "fsspec",
32
+ "s3fs",
32
33
  ]
33
34
  test = [
34
35
  "fastwarc[all]",
35
36
  "pytest>=7.2.2",
36
37
  "pytest-cov>=4.0.0",
37
- "lz4",
38
38
  ]
39
39
 
40
40
  [project.scripts]
41
41
  fastwarc = "fastwarc.cli:main"
42
42
 
43
43
  [tool.setuptools.packages.find]
44
- include = ["fastwarc*"]
44
+ include = ["fastwarc", "fastwarc.legacy"]
45
45
 
46
46
  [tool.setuptools.package-data]
47
47
  "*" = ["*.pyi"]
@@ -1,97 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: FastWARC
3
- Version: 1.0.1
4
- Summary: A high-performance WARC parsing library for Python written in C++/Cython.
5
- Author: Janek Bevendorff
6
- License-Expression: Apache-2.0
7
- Project-URL: repository, https://github.com/chatnoir-eu/chatnoir-resiliparse
8
- Project-URL: homepage, https://resiliparse.chatnoir.eu
9
- Project-URL: documentation, https://resiliparse.chatnoir.eu
10
- Requires-Python: >=3.8
11
- Description-Content-Type: text/markdown
12
- Requires-Dist: brotli
13
- Requires-Dist: click
14
- Requires-Dist: tqdm
15
- Provides-Extra: all
16
- Requires-Dist: fastwarc[fsspec]; extra == "all"
17
- Provides-Extra: fsspec
18
- Requires-Dist: fsspec; extra == "fsspec"
19
- Provides-Extra: test
20
- Requires-Dist: fastwarc[all]; extra == "test"
21
- Requires-Dist: pytest>=7.2.2; extra == "test"
22
- Requires-Dist: pytest-cov>=4.0.0; extra == "test"
23
- Requires-Dist: lz4; extra == "test"
24
-
25
- # FastWARC (Python)
26
-
27
- FastWARC is a high-performance WARC parsing library for Python written in Rust with Python bindings. FastWARC supports
28
- compressed and uncompressed WARC/1.0 and WARC/1.1 streams. Supported compression algorithms are Gzip and LZ4.
29
-
30
- This crate contains the Python bindings for FastWARC.
31
-
32
- FastWARC belongs to the [ChatNoir Resiliparse toolkit](https://github.com/chatnoir-eu/chatnoir-resiliparse/) for fast
33
- and robust web data processing.
34
-
35
- ## Installing FastWARC
36
-
37
- Pre-built FastWARC binaries for most Linux platforms can be installed from PyPi:
38
-
39
- ```bash
40
- pip install fastwarc
41
- ```
42
-
43
- **However:** the Linux binaries are provided *solely for your convenience*. Since they are built on the very old
44
- `manylinux` base system for better compatibility, their performance isn't optimal (though still better than WARCIO). For
45
- best performance, see the next section on how to build FastWARC yourself.
46
-
47
- ## Building FastWARC From Source
48
-
49
- You can compile FastWARC either from the PyPi source package or directly from this repository, though in any case, you
50
- need to install all required build-time dependencies first. On Ubuntu, this is done as follows:
51
-
52
- ```bash
53
- sudo apt install build-essential python3-dev zlib1g-dev liblz4-dev
54
- ```
55
-
56
- To build and install FastWARC from PyPi, run
57
-
58
- ```bash
59
- pip install --no-binary fastwarc fastwarc
60
- ```
61
-
62
- That's it. If you prefer to build and install directly from this repository instead, run:
63
-
64
- ```bash
65
- pip install -e fastwarc
66
- ```
67
-
68
- To build the wheels without installing them, run:
69
-
70
- ```bash
71
- pip wheel -e fastwarc
72
-
73
- # Or:
74
- pip install build && python -m build --wheel fastwarc
75
- ```
76
-
77
- ## Usage Instructions
78
-
79
- For detailed usage instructions, please consult
80
- the [FastWARC User Manual](https://resiliparse.chatnoir.eu/en/latest/man/fastwarc.html).
81
-
82
- ## Cite Us
83
-
84
- If you use FastWARC, please consider citing our [OSSYM 2021 abstract paper](https://arxiv.org/abs/2112.03103):
85
-
86
- ```bibtex
87
- @InProceedings{bevendorff:2021,
88
- author = {Janek Bevendorff and Martin Potthast and Benno Stein},
89
- booktitle = {3rd International Symposium on Open Search Technology (OSSYM 2021)},
90
- editor = {Andreas Wagner and Christian Guetl and Michael Granitzer and Stefan Voigt},
91
- month = oct,
92
- publisher = {International Open Search Symposium},
93
- site = {CERN, Geneva, Switzerland},
94
- title = {{FastWARC: Optimizing Large-Scale Web Archive Analytics}},
95
- year = 2021
96
- }
97
- ```
fastwarc-1.0.1/PKG-INFO DELETED
@@ -1,97 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: FastWARC
3
- Version: 1.0.1
4
- Summary: A high-performance WARC parsing library for Python written in C++/Cython.
5
- Author: Janek Bevendorff
6
- License-Expression: Apache-2.0
7
- Project-URL: repository, https://github.com/chatnoir-eu/chatnoir-resiliparse
8
- Project-URL: homepage, https://resiliparse.chatnoir.eu
9
- Project-URL: documentation, https://resiliparse.chatnoir.eu
10
- Requires-Python: >=3.8
11
- Description-Content-Type: text/markdown
12
- Requires-Dist: brotli
13
- Requires-Dist: click
14
- Requires-Dist: tqdm
15
- Provides-Extra: all
16
- Requires-Dist: fastwarc[fsspec]; extra == "all"
17
- Provides-Extra: fsspec
18
- Requires-Dist: fsspec; extra == "fsspec"
19
- Provides-Extra: test
20
- Requires-Dist: fastwarc[all]; extra == "test"
21
- Requires-Dist: pytest>=7.2.2; extra == "test"
22
- Requires-Dist: pytest-cov>=4.0.0; extra == "test"
23
- Requires-Dist: lz4; extra == "test"
24
-
25
- # FastWARC (Python)
26
-
27
- FastWARC is a high-performance WARC parsing library for Python written in Rust with Python bindings. FastWARC supports
28
- compressed and uncompressed WARC/1.0 and WARC/1.1 streams. Supported compression algorithms are Gzip and LZ4.
29
-
30
- This crate contains the Python bindings for FastWARC.
31
-
32
- FastWARC belongs to the [ChatNoir Resiliparse toolkit](https://github.com/chatnoir-eu/chatnoir-resiliparse/) for fast
33
- and robust web data processing.
34
-
35
- ## Installing FastWARC
36
-
37
- Pre-built FastWARC binaries for most Linux platforms can be installed from PyPi:
38
-
39
- ```bash
40
- pip install fastwarc
41
- ```
42
-
43
- **However:** the Linux binaries are provided *solely for your convenience*. Since they are built on the very old
44
- `manylinux` base system for better compatibility, their performance isn't optimal (though still better than WARCIO). For
45
- best performance, see the next section on how to build FastWARC yourself.
46
-
47
- ## Building FastWARC From Source
48
-
49
- You can compile FastWARC either from the PyPi source package or directly from this repository, though in any case, you
50
- need to install all required build-time dependencies first. On Ubuntu, this is done as follows:
51
-
52
- ```bash
53
- sudo apt install build-essential python3-dev zlib1g-dev liblz4-dev
54
- ```
55
-
56
- To build and install FastWARC from PyPi, run
57
-
58
- ```bash
59
- pip install --no-binary fastwarc fastwarc
60
- ```
61
-
62
- That's it. If you prefer to build and install directly from this repository instead, run:
63
-
64
- ```bash
65
- pip install -e fastwarc
66
- ```
67
-
68
- To build the wheels without installing them, run:
69
-
70
- ```bash
71
- pip wheel -e fastwarc
72
-
73
- # Or:
74
- pip install build && python -m build --wheel fastwarc
75
- ```
76
-
77
- ## Usage Instructions
78
-
79
- For detailed usage instructions, please consult
80
- the [FastWARC User Manual](https://resiliparse.chatnoir.eu/en/latest/man/fastwarc.html).
81
-
82
- ## Cite Us
83
-
84
- If you use FastWARC, please consider citing our [OSSYM 2021 abstract paper](https://arxiv.org/abs/2112.03103):
85
-
86
- ```bibtex
87
- @InProceedings{bevendorff:2021,
88
- author = {Janek Bevendorff and Martin Potthast and Benno Stein},
89
- booktitle = {3rd International Symposium on Open Search Technology (OSSYM 2021)},
90
- editor = {Andreas Wagner and Christian Guetl and Michael Granitzer and Stefan Voigt},
91
- month = oct,
92
- publisher = {International Open Search Symposium},
93
- site = {CERN, Geneva, Switzerland},
94
- title = {{FastWARC: Optimizing Large-Scale Web Archive Analytics}},
95
- year = 2021
96
- }
97
- ```
fastwarc-1.0.1/README.md DELETED
@@ -1,73 +0,0 @@
1
- # FastWARC (Python)
2
-
3
- FastWARC is a high-performance WARC parsing library for Python written in Rust with Python bindings. FastWARC supports
4
- compressed and uncompressed WARC/1.0 and WARC/1.1 streams. Supported compression algorithms are Gzip and LZ4.
5
-
6
- This crate contains the Python bindings for FastWARC.
7
-
8
- FastWARC belongs to the [ChatNoir Resiliparse toolkit](https://github.com/chatnoir-eu/chatnoir-resiliparse/) for fast
9
- and robust web data processing.
10
-
11
- ## Installing FastWARC
12
-
13
- Pre-built FastWARC binaries for most Linux platforms can be installed from PyPi:
14
-
15
- ```bash
16
- pip install fastwarc
17
- ```
18
-
19
- **However:** the Linux binaries are provided *solely for your convenience*. Since they are built on the very old
20
- `manylinux` base system for better compatibility, their performance isn't optimal (though still better than WARCIO). For
21
- best performance, see the next section on how to build FastWARC yourself.
22
-
23
- ## Building FastWARC From Source
24
-
25
- You can compile FastWARC either from the PyPi source package or directly from this repository, though in any case, you
26
- need to install all required build-time dependencies first. On Ubuntu, this is done as follows:
27
-
28
- ```bash
29
- sudo apt install build-essential python3-dev zlib1g-dev liblz4-dev
30
- ```
31
-
32
- To build and install FastWARC from PyPi, run
33
-
34
- ```bash
35
- pip install --no-binary fastwarc fastwarc
36
- ```
37
-
38
- That's it. If you prefer to build and install directly from this repository instead, run:
39
-
40
- ```bash
41
- pip install -e fastwarc
42
- ```
43
-
44
- To build the wheels without installing them, run:
45
-
46
- ```bash
47
- pip wheel -e fastwarc
48
-
49
- # Or:
50
- pip install build && python -m build --wheel fastwarc
51
- ```
52
-
53
- ## Usage Instructions
54
-
55
- For detailed usage instructions, please consult
56
- the [FastWARC User Manual](https://resiliparse.chatnoir.eu/en/latest/man/fastwarc.html).
57
-
58
- ## Cite Us
59
-
60
- If you use FastWARC, please consider citing our [OSSYM 2021 abstract paper](https://arxiv.org/abs/2112.03103):
61
-
62
- ```bibtex
63
- @InProceedings{bevendorff:2021,
64
- author = {Janek Bevendorff and Martin Potthast and Benno Stein},
65
- booktitle = {3rd International Symposium on Open Search Technology (OSSYM 2021)},
66
- editor = {Andreas Wagner and Christian Guetl and Michael Granitzer and Stefan Voigt},
67
- month = oct,
68
- publisher = {International Open Search Symposium},
69
- site = {CERN, Geneva, Switzerland},
70
- title = {{FastWARC: Optimizing Large-Scale Web Archive Analytics}},
71
- year = 2021
72
- }
73
- ```
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes