pywaybackup 4.2.2__tar.gz → 4.2.3__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.
- {pywaybackup-4.2.2/pywaybackup.egg-info → pywaybackup-4.2.3}/PKG-INFO +1 -1
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/pyproject.toml +1 -1
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/pywaybackup/archive_download.py +24 -12
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/pywaybackup/helper.py +23 -2
- {pywaybackup-4.2.2 → pywaybackup-4.2.3/pywaybackup.egg-info}/PKG-INFO +1 -1
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/LICENSE +0 -0
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/README.md +0 -0
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/pywaybackup/Exception.py +0 -0
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/pywaybackup/PyWayBackup.py +0 -0
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/pywaybackup/Snapshot.py +0 -0
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/pywaybackup/SnapshotCollection.py +0 -0
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/pywaybackup/Verbosity.py +0 -0
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/pywaybackup/Worker.py +0 -0
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/pywaybackup/__init__.py +0 -0
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/pywaybackup/archive_save.py +0 -0
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/pywaybackup/arguments.py +0 -0
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/pywaybackup/db.py +0 -0
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/pywaybackup/files.py +0 -0
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/pywaybackup/interactive.py +0 -0
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/pywaybackup/main.py +0 -0
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/pywaybackup.egg-info/SOURCES.txt +0 -0
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/pywaybackup.egg-info/dependency_links.txt +0 -0
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/pywaybackup.egg-info/entry_points.txt +0 -0
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/pywaybackup.egg-info/requires.txt +0 -0
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/pywaybackup.egg-info/top_level.txt +0 -0
- {pywaybackup-4.2.2 → pywaybackup-4.2.3}/setup.cfg +0 -0
|
@@ -16,7 +16,7 @@ dependencies = [
|
|
|
16
16
|
"python-magic-standalone==0.4.28",
|
|
17
17
|
]
|
|
18
18
|
name = "pywaybackup"
|
|
19
|
-
version = "4.2.
|
|
19
|
+
version = "4.2.3"
|
|
20
20
|
description = "Query and download archive.org as simple as possible."
|
|
21
21
|
authors = [{ name = "bitdruid", email = "bitdruid@outlook.com" }]
|
|
22
22
|
license = { file = "LICENSE" }
|
|
@@ -11,7 +11,7 @@ from socket import timeout
|
|
|
11
11
|
from urllib.parse import urljoin
|
|
12
12
|
|
|
13
13
|
from pywaybackup.Exception import Exception as ex
|
|
14
|
-
from pywaybackup.helper import check_nt, move_index, url_get_timestamp
|
|
14
|
+
from pywaybackup.helper import add_html_extension, check_nt, move_index, url_get_timestamp
|
|
15
15
|
from pywaybackup.SnapshotCollection import SnapshotCollection
|
|
16
16
|
from pywaybackup.Verbosity import Verbosity as vb
|
|
17
17
|
from pywaybackup.Worker import Worker
|
|
@@ -81,7 +81,17 @@ class DownloadArchive:
|
|
|
81
81
|
sc (SnapshotCollection): The snapshot collection being processed.
|
|
82
82
|
"""
|
|
83
83
|
|
|
84
|
-
def __init__(
|
|
84
|
+
def __init__(
|
|
85
|
+
self,
|
|
86
|
+
mode: str,
|
|
87
|
+
output: str,
|
|
88
|
+
retry: int,
|
|
89
|
+
no_redirect: bool,
|
|
90
|
+
delay: int,
|
|
91
|
+
wait: int,
|
|
92
|
+
workers: int,
|
|
93
|
+
merge_www: bool = True,
|
|
94
|
+
):
|
|
85
95
|
"""
|
|
86
96
|
Initialize the download manager with configuration options.
|
|
87
97
|
|
|
@@ -270,7 +280,7 @@ class DownloadArchive:
|
|
|
270
280
|
except Exception as e:
|
|
271
281
|
ex.exception(f"\nWorker: {worker.id} - Exception", e)
|
|
272
282
|
finally:
|
|
273
|
-
worker.close()
|
|
283
|
+
worker.close()
|
|
274
284
|
|
|
275
285
|
def _download(self, worker: Worker):
|
|
276
286
|
"""
|
|
@@ -291,6 +301,7 @@ class DownloadArchive:
|
|
|
291
301
|
|
|
292
302
|
if context.response_status == 200:
|
|
293
303
|
context.output_file = worker.snapshot.create_output()
|
|
304
|
+
context.output_file = add_html_extension(context.output_file, context.response_data)
|
|
294
305
|
context.output_path = os.path.dirname(context.output_file)
|
|
295
306
|
|
|
296
307
|
# if output_file is too long for windows, skip download
|
|
@@ -305,15 +316,6 @@ class DownloadArchive:
|
|
|
305
316
|
# download file if not existing
|
|
306
317
|
if not os.path.isfile(context.output_file):
|
|
307
318
|
with open(context.output_file, "wb") as file:
|
|
308
|
-
if context.response.getheader("Content-Encoding") == "gzip":
|
|
309
|
-
try:
|
|
310
|
-
context.response_data = gzip.decompress(context.response_data)
|
|
311
|
-
except BadGzipFile:
|
|
312
|
-
vb.write(
|
|
313
|
-
verbose=None,
|
|
314
|
-
content=f"Worker: {worker.id} - GZIP DECOMPRESS SKIPPED - {context.snapshot_url}",
|
|
315
|
-
)
|
|
316
|
-
pass
|
|
317
319
|
file.write(context.response_data)
|
|
318
320
|
|
|
319
321
|
# check if file is downloaded
|
|
@@ -428,3 +430,13 @@ class DownloadArchive:
|
|
|
428
430
|
context.response = worker.connection.getresponse()
|
|
429
431
|
context.response_data = context.response.read()
|
|
430
432
|
context.response_status = context.response.status
|
|
433
|
+
|
|
434
|
+
# decompress before sniff
|
|
435
|
+
if context.response.getheader("Content-Encoding") == "gzip":
|
|
436
|
+
try:
|
|
437
|
+
context.response_data = gzip.decompress(context.response_data)
|
|
438
|
+
except BadGzipFile:
|
|
439
|
+
vb.write(
|
|
440
|
+
verbose=None,
|
|
441
|
+
content=f"Worker: {worker.id} - GZIP DECOMPRESS SKIPPED - {context.snapshot_url}",
|
|
442
|
+
)
|
|
@@ -2,6 +2,12 @@ import os
|
|
|
2
2
|
import shutil
|
|
3
3
|
import magic
|
|
4
4
|
|
|
5
|
+
# one instance for the run to keep resource usage low
|
|
6
|
+
_mime = magic.Magic(mime=True)
|
|
7
|
+
|
|
8
|
+
# only keep the header for libmagic
|
|
9
|
+
_MIME_SNIFF_BYTES = 2048
|
|
10
|
+
|
|
5
11
|
|
|
6
12
|
def check_nt():
|
|
7
13
|
"""
|
|
@@ -128,8 +134,23 @@ def move_index(existpath: str = None, existfile: str = None, filebuffer: bytes =
|
|
|
128
134
|
|
|
129
135
|
|
|
130
136
|
def check_index_mime(filebuffer: bytes) -> bool:
|
|
131
|
-
|
|
132
|
-
mime_type = mime.from_buffer(filebuffer)
|
|
137
|
+
mime_type = _mime.from_buffer(filebuffer[:_MIME_SNIFF_BYTES])
|
|
133
138
|
if mime_type != "text/html":
|
|
134
139
|
return False
|
|
135
140
|
return True
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def add_html_extension(filepath: str, filebuffer: bytes) -> str:
|
|
144
|
+
"""
|
|
145
|
+
Append `.html` to a file without extension if its content is html.
|
|
146
|
+
|
|
147
|
+
Urls like `/about` or `/docs/guide` carry no extension, so the snapshot is
|
|
148
|
+
written as an extensionless file that no browser or file manager opens.
|
|
149
|
+
The content type is sniffed from the buffer instead of the cdx mimetype
|
|
150
|
+
column, which is often `warc/revisit` or `unk` rather than a real type.
|
|
151
|
+
"""
|
|
152
|
+
if os.path.splitext(filepath)[1]:
|
|
153
|
+
return filepath
|
|
154
|
+
if not check_index_mime(filebuffer):
|
|
155
|
+
return filepath
|
|
156
|
+
return filepath + ".html"
|
|
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
|