bpo-45150: Add hashlib.file_digest() for efficient file hashing (GH-3… · python/cpython@4f97d64 (original) (raw)
`@@ -10,6 +10,7 @@
`
10
10
`from binascii import unhexlify
`
11
11
`import hashlib
`
12
12
`import importlib
`
``
13
`+
import io
`
13
14
`import itertools
`
14
15
`import os
`
15
16
`import sys
`
`@@ -20,6 +21,7 @@
`
20
21
`from test import support
`
21
22
`from test.support import _4G, bigmemtest
`
22
23
`from test.support.import_helper import import_fresh_module
`
``
24
`+
from test.support import os_helper
`
23
25
`from test.support import threading_helper
`
24
26
`from test.support import warnings_helper
`
25
27
`from http.client import HTTPException
`
`@@ -371,6 +373,31 @@ def check(self, name, data, hexdigest, shake=False, **kwargs):
`
371
373
`if not shake:
`
372
374
`self.assertEqual(len(digest), m.digest_size)
`
373
375
``
``
376
`+
if not shake and kwargs.get("key") is None:
`
``
377
`+
skip shake and blake2 extended parameter tests
`
``
378
`+
self.check_file_digest(name, data, hexdigest)
`
``
379
+
``
380
`+
def check_file_digest(self, name, data, hexdigest):
`
``
381
`+
hexdigest = hexdigest.lower()
`
``
382
`+
digests = [name]
`
``
383
`+
digests.extend(self.constructors_to_test[name])
`
``
384
+
``
385
`+
with open(os_helper.TESTFN, "wb") as f:
`
``
386
`+
f.write(data)
`
``
387
+
``
388
`+
try:
`
``
389
`+
for digest in digests:
`
``
390
`+
buf = io.BytesIO(data)
`
``
391
`+
buf.seek(0)
`
``
392
`+
self.assertEqual(
`
``
393
`+
hashlib.file_digest(buf, digest).hexdigest(), hexdigest
`
``
394
`+
)
`
``
395
`+
with open(os_helper.TESTFN, "rb") as f:
`
``
396
`+
digestobj = hashlib.file_digest(f, digest)
`
``
397
`+
self.assertEqual(digestobj.hexdigest(), hexdigest)
`
``
398
`+
finally:
`
``
399
`+
os.unlink(os_helper.TESTFN)
`
``
400
+
374
401
`def check_no_unicode(self, algorithm_name):
`
375
402
`# Unicode objects are not allowed as input.
`
376
403
`constructors = self.constructors_to_test[algorithm_name]
`
`@@ -1117,6 +1144,33 @@ def test_normalized_name(self):
`
1117
1144
`self.assertNotIn("blake2b512", hashlib.algorithms_available)
`
1118
1145
`self.assertNotIn("sha3-512", hashlib.algorithms_available)
`
1119
1146
``
``
1147
`+
def test_file_digest(self):
`
``
1148
`+
data = b'a' * 65536
`
``
1149
`+
d1 = hashlib.sha256()
`
``
1150
`+
self.addCleanup(os.unlink, os_helper.TESTFN)
`
``
1151
`+
with open(os_helper.TESTFN, "wb") as f:
`
``
1152
`+
for _ in range(10):
`
``
1153
`+
d1.update(data)
`
``
1154
`+
f.write(data)
`
``
1155
+
``
1156
`+
with open(os_helper.TESTFN, "rb") as f:
`
``
1157
`+
d2 = hashlib.file_digest(f, hashlib.sha256)
`
``
1158
+
``
1159
`+
self.assertEqual(d1.hexdigest(), d2.hexdigest())
`
``
1160
`+
self.assertEqual(d1.name, d2.name)
`
``
1161
`+
self.assertIs(type(d1), type(d2))
`
``
1162
+
``
1163
`+
with self.assertRaises(ValueError):
`
``
1164
`+
hashlib.file_digest(None, "sha256")
`
``
1165
+
``
1166
`+
with self.assertRaises(ValueError):
`
``
1167
`+
with open(os_helper.TESTFN, "r") as f:
`
``
1168
`+
hashlib.file_digest(f, "sha256")
`
``
1169
+
``
1170
`+
with self.assertRaises(ValueError):
`
``
1171
`+
with open(os_helper.TESTFN, "wb") as f:
`
``
1172
`+
hashlib.file_digest(f, "sha256")
`
``
1173
+
1120
1174
``
1121
1175
`if name == "main":
`
1122
1176
`unittest.main()
`