|
7 | 7 | MEGABYTE = 1048576 |
8 | 8 |
|
9 | 9 |
|
10 | | -class Basicdown: |
| 10 | +class BaseDownloader: |
11 | 11 | """Base downloader class.""" |
12 | 12 |
|
13 | 13 | def __init__(self, session: ClientSession, speed_limit: float) -> None: |
14 | 14 | self.session = session |
15 | | - self.speed_limit = speed_limit * MEGABYTE |
| 15 | + self.speed_limit = max(0, speed_limit * MEGABYTE) |
16 | 16 | self.curr = 0 |
17 | 17 |
|
18 | 18 | async def download(self, url: str, path: str, mode: str, **kwargs) -> None: |
19 | 19 | """Download data in chunks.""" |
20 | | - speedlimit_time = time.time() |
21 | | - speedlimit_size = 0 |
| 20 | + start_time = time.monotonic() |
22 | 21 | async with self.session.get(url, **kwargs) as response: |
23 | 22 | async with aiofiles.open(path, mode) as file: |
24 | 23 | async for chunk in response.content.iter_chunked(MEGABYTE): |
25 | | - if self.speed_limit > 0: |
26 | | - now = time.time() |
27 | | - time_passed = now - speedlimit_time |
28 | | - if time_passed > 0.1: |
29 | | - curr_download = self.curr - speedlimit_size |
30 | | - if curr_download / time_passed >= self.speed_limit: |
31 | | - await asyncio.sleep(curr_download / self.speed_limit) |
32 | | - else: |
33 | | - speedlimit_time = now |
34 | | - speedlimit_size = self.curr |
35 | | - |
36 | 24 | await file.write(chunk) |
37 | 25 | self.curr += len(chunk) |
38 | 26 |
|
| 27 | + if self.speed_limit > 0: |
| 28 | + expected_time = self.curr / self.speed_limit |
| 29 | + current_time = time.monotonic() - start_time |
| 30 | + sleep_time = expected_time - current_time |
| 31 | + if sleep_time > 0: |
| 32 | + await asyncio.sleep(sleep_time) |
| 33 | + |
39 | 34 |
|
40 | | -class Singledown(Basicdown): |
| 35 | +class SingleSegmentDownloader(BaseDownloader): |
41 | 36 | """Class for downloading the whole file in a single segment.""" |
42 | 37 |
|
43 | 38 | async def worker(self, url: str, file_path: str, **kwargs) -> None: |
44 | 39 | await self.download(url, file_path, "wb", **kwargs) |
45 | 40 |
|
46 | 41 |
|
47 | | -class Multidown(Basicdown): |
| 42 | +class SegmentDownloader(BaseDownloader): |
48 | 43 | """Class for downloading a specific segment of the file.""" |
49 | 44 |
|
50 | 45 | async def worker(self, segment_table: dict, id: int, **kwargs) -> None: |
|
0 commit comments