11import hashlib
22import logging
3- from pathlib import Path
43from typing import Any
54
65import aiofiles
76import httpx
87import libconf
98import semver
9+ from anyio import AsyncFile , Path , open_file
1010
1111logger = logging .getLogger (__name__ )
1212
@@ -41,7 +41,7 @@ def parse_descriptor(swdesc: libconf.AttrDict[Any, Any | None]):
4141
4242
4343async def parse_file (file : Path ):
44- async with aiofiles . open (file , "r+b" ) as f :
44+ async with await open_file (file , "r+b" ) as f :
4545 # get file size
4646 size = int ((await f .read (110 ))[54 :62 ], 16 )
4747 filename = b""
@@ -59,8 +59,9 @@ async def parse_file(file: Path):
5959 swdesc = libconf .loads ((await f .read (size )).decode ("utf-8" ))
6060
6161 swdesc_attrs = parse_descriptor (swdesc )
62- swdesc_attrs ["size" ] = file .stat ().st_size
63- swdesc_attrs ["hash" ] = _sha1_hash_file (file )
62+ stat = await file .stat ()
63+ swdesc_attrs ["size" ] = stat .st_size
64+ swdesc_attrs ["hash" ] = await _sha1_hash_file (f )
6465 return swdesc_attrs
6566
6667
@@ -72,7 +73,17 @@ async def parse_remote(url: str):
7273 return await parse_file (Path (str (f .name )))
7374
7475
75- def _sha1_hash_file (file_path : Path ):
76- with file_path .open ("rb" ) as f :
77- sha1_hash = hashlib .file_digest (f , "sha1" )
76+ async def _sha1_hash_file (fileobj : AsyncFile ):
77+ last = await fileobj .tell ()
78+ await fileobj .seek (0 )
79+ sha1_hash = hashlib .sha1 ()
80+ buf = bytearray (2 ** 18 )
81+ view = memoryview (buf )
82+ while True :
83+ size = await fileobj .readinto (buf )
84+ if size == 0 :
85+ break
86+ sha1_hash .update (view [:size ])
87+
88+ await fileobj .seek (last )
7889 return sha1_hash .hexdigest ()
0 commit comments