@@ -14,7 +14,13 @@ def hash_file(filename, algo="sha256"):
1414 :param filename: name of the file to be hashed
1515 :return: ALGO(file)
1616 """
17- h = hashlib .new (algo )
17+ try :
18+ h = hashlib .new (algo )
19+ except ValueError : # unsupported hash type
20+ try :
21+ h = hashlib .__dict__ [algo ]()
22+ except KeyError :
23+ raise ValueError (f"unsupported hash type { algo } " )
1824 with open (filename , 'rb' ) as f :
1925 while True :
2026 data = f .read (h .block_size )
@@ -25,18 +31,66 @@ def hash_file(filename, algo="sha256"):
2531hashlib .hash_file = hash_file
2632
2733
34+ def mmh3_32 (data : bytes = b"" , seed : int = 0 ):
35+ """ 32-bit MurmurHash3 """
36+ from mmh3 import mmh3_32 as _mmh3_32
37+ class mmh3_32 :
38+ __module__ = "builtins"
39+ _h : _mmh3_32
40+ def __init__ (self , data : bytes = b"" , seed : int = 0 ) -> None : self ._h = _mmh3_32 (data , seed )
41+ def copy (self ) -> "mmh3_32" :
42+ cls = self .__class__ .__new__ (self .__class__ )
43+ cls ._h = self ._h .copy ()
44+ return cls
45+ def digest (self ) -> bytes : return self ._h .digest ()
46+ def hexdigest (self ) -> str : return self ._h .digest ().hex ()
47+ def sintdigest (self ) -> int : return self ._h .sintdigest ()
48+ def uintdigest (self ) -> int : return self ._h .uintdigest ()
49+ def update (self , data : bytes ) -> None : self ._h .update (data )
50+ block_size = property (lambda self : self ._h .block_size )
51+ digest_size = property (lambda self : self ._h .digest_size )
52+ name = property (lambda self : self ._h .name )
53+ return mmh3_32 (data , seed )
54+ hashlib .mmh3_32 = mmh3_32
55+ hashlib .algorithms_available .add ("mmh3_32" )
56+
57+
58+ def mmh3_128 (data : bytes = b"" , seed : int = 0 ):
59+ """ 128-bit MurmurHash3 """
60+ from mmh3 import mmh3_x64_128 as _mmh3_x64_128
61+ class mmh3_128 :
62+ __module__ = "builtins"
63+ _h : _mmh3_x64_128
64+ def __init__ (self , data : bytes = b"" , seed : int = 0 ) -> None : self ._h = _mmh3_x64_128 (data , seed )
65+ def copy (self ) -> "mmh3_128" :
66+ cls = self .__class__ .__new__ (self .__class__ )
67+ cls ._h = self ._h .copy ()
68+ return cls
69+ def digest (self ) -> bytes : return self ._h .digest ()
70+ def hexdigest (self ) -> str : return self ._h .digest ().hex ()
71+ def sintdigest (self ) -> int : return self ._h .sintdigest ()
72+ def uintdigest (self ) -> int : return self ._h .uintdigest ()
73+ def update (self , data : bytes ) -> None : self ._h .update (data )
74+ block_size = property (lambda self : self ._h .block_size )
75+ digest_size = property (lambda self : self ._h .digest_size )
76+ name = property (lambda self : self ._h .name )
77+ return mmh3_128 (data , seed )
78+ hashlib .mmh3_128 = mmh3_128
79+ hashlib .algorithms_available .add ("mmh3_128" )
80+
81+
2882# this binds new file hashing functions to the hashlib for each existing hash algorithm
29- for algo in [ x for x in hashlib .__dict__ . keys ()] :
83+ for algo in hashlib .algorithms_available :
3084 try :
3185 h = hashlib .new (algo )
32- h .update (b"" )
33- def _hash_file (a ):
34- def _wrapper (f ):
35- return hash_file (f , a )
36- return _wrapper
37- setattr (hashlib , "{}_file" .format (algo ), _hash_file (algo ))
3886 except ValueError : # unsupported hash type
39- pass
87+ h = hashlib .__dict__ [algo ]()
88+ h .update (b"" )
89+ def _hash_file (a ):
90+ def _wrapper (f ):
91+ return hash_file (f , a )
92+ return _wrapper
93+ setattr (hashlib , f"{ algo } _file" , _hash_file (algo ))
4094
4195
4296class LookupTable (dict ):
0 commit comments