kmoe-manga-downloader 1.2.6__tar.gz → 1.2.8a0__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.
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/PKG-INFO +1 -1
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/_version.py +3 -3
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/core/utils.py +16 -2
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/downloader/ReferViaDownloader.py +5 -1
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/downloader/download_utils.py +91 -22
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmoe_manga_downloader.egg-info/PKG-INFO +1 -1
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/.github/workflows/release-package.yml +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/.github/workflows/unit-test.yml +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/.gitignore +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/LICENSE +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/README.md +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/assets/kmdr-demo.gif +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/assets/kmdr-log-demo.gif +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/mirror/mirrors.json +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/pyproject.toml +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/setup.cfg +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/__init__.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/core/__init__.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/core/bases.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/core/console.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/core/constants.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/core/context.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/core/defaults.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/core/error.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/core/protocol.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/core/registry.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/core/session.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/core/structure.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/main.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/__init__.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/authenticator/CookieAuthenticator.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/authenticator/LoginAuthenticator.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/authenticator/__init__.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/authenticator/utils.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/configurer/BaseUrlUpdator.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/configurer/ConfigClearer.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/configurer/ConfigUnsetter.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/configurer/OptionLister.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/configurer/OptionSetter.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/configurer/__init__.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/configurer/option_validate.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/downloader/DirectDownloader.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/downloader/__init__.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/downloader/misc.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/lister/BookUrlLister.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/lister/FollowedBookLister.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/lister/__init__.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/lister/utils.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/picker/ArgsFilterPicker.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/picker/DefaultVolPicker.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/picker/__init__.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/picker/utils.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmoe_manga_downloader.egg-info/SOURCES.txt +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmoe_manga_downloader.egg-info/dependency_links.txt +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmoe_manga_downloader.egg-info/entry_points.txt +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmoe_manga_downloader.egg-info/requires.txt +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmoe_manga_downloader.egg-info/top_level.txt +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/tests/__init__.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/tests/test_async_retry_decorator.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/tests/test_kmdr_config_option.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/tests/test_kmdr_download.py +0 -0
- {kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/tests/test_utils_resolve_volme.py +0 -0
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '1.2.
|
|
32
|
-
__version_tuple__ = version_tuple = (1, 2,
|
|
31
|
+
__version__ = version = '1.2.8a0'
|
|
32
|
+
__version_tuple__ = version_tuple = (1, 2, 8, 'a0')
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'g32d79b016'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import functools
|
|
2
|
-
from typing import Optional, Callable, TypeVar, Hashable, Generic
|
|
2
|
+
from typing import Optional, Callable, TypeVar, Hashable, Generic, Mapping, Any
|
|
3
3
|
import asyncio
|
|
4
4
|
from asyncio.proactor_events import _ProactorBasePipeTransport
|
|
5
5
|
|
|
@@ -146,4 +146,18 @@ def _silence_event_loop_closed(func):
|
|
|
146
146
|
|
|
147
147
|
return wrapper
|
|
148
148
|
|
|
149
|
-
_ProactorBasePipeTransport.__del__ = _silence_event_loop_closed(_ProactorBasePipeTransport.__del__)
|
|
149
|
+
_ProactorBasePipeTransport.__del__ = _silence_event_loop_closed(_ProactorBasePipeTransport.__del__)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
SENSITIVE_KEYS = {'cookie', 'authorization', 'proxy-authorization', 'set-cookie'}
|
|
154
|
+
"""定义需要脱敏的字段(全部小写以便不区分大小写匹配)"""
|
|
155
|
+
|
|
156
|
+
def sanitize_headers(headers: Mapping[str, Any]) -> dict:
|
|
157
|
+
"""
|
|
158
|
+
清洗 HTTP 头信息,隐藏敏感字段(如 Cookie, Authorization)。
|
|
159
|
+
"""
|
|
160
|
+
return {
|
|
161
|
+
k: '******' if k.lower() in SENSITIVE_KEYS else v
|
|
162
|
+
for k, v in headers.items()
|
|
163
|
+
}
|
|
@@ -38,7 +38,11 @@ class ReferViaDownloader(Downloader):
|
|
|
38
38
|
)
|
|
39
39
|
|
|
40
40
|
@alru_cache(maxsize=128)
|
|
41
|
-
@async_retry(
|
|
41
|
+
@async_retry(
|
|
42
|
+
delay=3,
|
|
43
|
+
backoff=1.5,
|
|
44
|
+
retry_on_status={500, 502, 503, 504, 429, 408, 403} # 这里加入 403 重试
|
|
45
|
+
)
|
|
42
46
|
async def fetch_download_url(self, book_id: str, volume_id: str) -> str:
|
|
43
47
|
|
|
44
48
|
async with self._session.get(
|
|
@@ -3,6 +3,7 @@ import os
|
|
|
3
3
|
import re
|
|
4
4
|
import math
|
|
5
5
|
from typing import Callable, Optional, Union, Awaitable
|
|
6
|
+
import shutil
|
|
6
7
|
|
|
7
8
|
from typing_extensions import deprecated
|
|
8
9
|
|
|
@@ -14,7 +15,7 @@ from aiohttp.client_exceptions import ClientPayloadError
|
|
|
14
15
|
|
|
15
16
|
from kmdr.core.console import info, log, debug
|
|
16
17
|
from kmdr.core.error import ResponseError
|
|
17
|
-
from kmdr.core.utils import async_retry
|
|
18
|
+
from kmdr.core.utils import async_retry, sanitize_headers
|
|
18
19
|
|
|
19
20
|
from .misc import STATUS, StateManager
|
|
20
21
|
|
|
@@ -182,14 +183,13 @@ async def download_file_multipart(
|
|
|
182
183
|
|
|
183
184
|
state_manager: Optional[StateManager] = None
|
|
184
185
|
try:
|
|
185
|
-
current_url = await fetch_url(url)
|
|
186
|
-
|
|
187
186
|
async with _get_head_request_semaphore():
|
|
188
187
|
# 获取文件信息,请求以获取文件大小
|
|
189
188
|
# 控制并发,避免过多并发请求触发服务器限流
|
|
189
|
+
current_url = await fetch_url(url)
|
|
190
190
|
total_size = await _fetch_content_length(session, current_url, headers=headers)
|
|
191
191
|
|
|
192
|
-
chunk_size = chunk_size_mb
|
|
192
|
+
chunk_size = determine_chunk_size(file_size=total_size, base_chunk_mb=chunk_size_mb)
|
|
193
193
|
num_chunks = math.ceil(total_size / chunk_size)
|
|
194
194
|
|
|
195
195
|
tasks = []
|
|
@@ -224,10 +224,13 @@ async def download_file_multipart(
|
|
|
224
224
|
await asyncio.gather(*tasks)
|
|
225
225
|
|
|
226
226
|
assert len(part_paths) == len(part_expected_sizes)
|
|
227
|
-
results = await asyncio.gather(*[
|
|
227
|
+
results = await asyncio.gather(*[
|
|
228
|
+
asyncio.to_thread(_sync_validate_part, part_paths[i], part_expected_sizes[i])
|
|
229
|
+
for i in range(num_chunks)
|
|
230
|
+
])
|
|
228
231
|
if all(results):
|
|
229
232
|
await state_manager.request_status_update(part_id=StateManager.PARENT_ID, status=STATUS.MERGING)
|
|
230
|
-
await
|
|
233
|
+
await asyncio.to_thread(_sync_merge_parts, part_paths, filename_downloading)
|
|
231
234
|
await aio_os.rename(filename_downloading, file_path)
|
|
232
235
|
else:
|
|
233
236
|
# 如果有任何一个分片校验失败,则视为下载失败
|
|
@@ -316,6 +319,9 @@ async def _download_part(
|
|
|
316
319
|
debug("开始下载分片:", os.path.basename(part_path), "范围:", current_start, "-", end)
|
|
317
320
|
async with session.get(url, headers=local_headers) as response:
|
|
318
321
|
response.raise_for_status()
|
|
322
|
+
debug("分片", os.path.basename(part_path), "状态码:", response.status)
|
|
323
|
+
debug("分片", os.path.basename(part_path), "请求头:", sanitize_headers(response.request_info.headers))
|
|
324
|
+
debug("分片", os.path.basename(part_path), "响应头:", sanitize_headers(response.headers))
|
|
319
325
|
|
|
320
326
|
await state_manager.request_status_update(part_id=start, status=STATUS.DOWNLOADING)
|
|
321
327
|
|
|
@@ -343,28 +349,91 @@ async def _download_part(
|
|
|
343
349
|
debug("分片", os.path.basename(part_path), "下载失败:", e)
|
|
344
350
|
await state_manager.request_status_update(part_id=start, status=STATUS.PARTIALLY_FAILED)
|
|
345
351
|
|
|
346
|
-
|
|
347
|
-
|
|
352
|
+
def _sync_validate_part(part_path: str, expected_size: int) -> bool:
|
|
353
|
+
"""
|
|
354
|
+
使用同步的 IO 来验证分片文件的完整性。
|
|
355
|
+
|
|
356
|
+
:param part_path: 分片文件路径
|
|
357
|
+
:param expected_size: 预期的文件大小
|
|
358
|
+
:return: 如果文件大小匹配则返回 True,否则返回 False
|
|
359
|
+
:note: 这个函数应该在线程池中运行。
|
|
360
|
+
:usage: await asyncio.to_thread(_sync_validate_part, part_path, expected_size)
|
|
361
|
+
"""
|
|
362
|
+
if not os.path.exists(part_path):
|
|
348
363
|
return False
|
|
349
|
-
actual_size =
|
|
364
|
+
actual_size = os.path.getsize(part_path)
|
|
350
365
|
return actual_size == expected_size
|
|
351
366
|
|
|
352
|
-
|
|
367
|
+
def _sync_merge_parts(part_paths: list[str], final_path: str):
|
|
368
|
+
"""
|
|
369
|
+
使用同步的 IO 来合并文件。
|
|
370
|
+
|
|
371
|
+
:param part_paths: 分片文件路径列表
|
|
372
|
+
:param final_path: 最终合并后的文件路径
|
|
373
|
+
:note: 这个函数应该在线程池中运行。
|
|
374
|
+
:usage: await asyncio.to_thread(_sync_merge_parts, part_paths, final_path)
|
|
375
|
+
"""
|
|
353
376
|
debug("合并分片到最终文件:", final_path)
|
|
354
|
-
|
|
355
|
-
|
|
377
|
+
try:
|
|
378
|
+
with open(final_path, 'wb') as final_file:
|
|
356
379
|
for part_path in part_paths:
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
if aio_os.path.exists(final_path):
|
|
365
|
-
await aio_os.remove(final_path)
|
|
366
|
-
raise e
|
|
380
|
+
with open(part_path, 'rb') as part_file:
|
|
381
|
+
shutil.copyfileobj(part_file, final_file)
|
|
382
|
+
except Exception as e:
|
|
383
|
+
if os.path.exists(final_path):
|
|
384
|
+
os.remove(final_path)
|
|
385
|
+
raise e
|
|
386
|
+
|
|
367
387
|
|
|
388
|
+
def determine_chunk_size(
|
|
389
|
+
file_size: int,
|
|
390
|
+
base_chunk_mb: int = 10,
|
|
391
|
+
max_chunks_limit: int = 100,
|
|
392
|
+
min_chunk_threshold_factor: float = 0.2
|
|
393
|
+
) -> int:
|
|
394
|
+
"""
|
|
395
|
+
计算合适的分片大小以优化下载性能。
|
|
396
|
+
|
|
397
|
+
TODO: 这个算法可以进一步优化,例如考虑网络状况、服务器限制等因素。10 这个魔法数字也许可以调整。
|
|
398
|
+
需要收集更多的信息:
|
|
399
|
+
- 文件大小的分布
|
|
400
|
+
- 用户的下载速度分布
|
|
401
|
+
- 连接开销的大致值
|
|
402
|
+
|
|
403
|
+
:param file_size: 文件总大小(字节)
|
|
404
|
+
:param base_chunk_mb: 基础分片大小 (MB)
|
|
405
|
+
:param max_chunks_limit: 限制的最大分片数
|
|
406
|
+
:param min_chunk_threshold_factor: 最小分片的体积因子
|
|
407
|
+
:return: 最佳的每个分片的大小(字节)
|
|
408
|
+
"""
|
|
409
|
+
base_chunk = int(base_chunk_mb * 1024 * 1024)
|
|
410
|
+
|
|
411
|
+
if not isinstance(file_size, int) or file_size <= 0:
|
|
412
|
+
# 如果文件大小不正常,返回基础分片大小
|
|
413
|
+
return base_chunk
|
|
414
|
+
|
|
415
|
+
if file_size <= base_chunk * (1 + min_chunk_threshold_factor):
|
|
416
|
+
# 如果文件较小,直接使用单分片下载,避免无谓的分片开销
|
|
417
|
+
# 例如 10.2MB 会被视为单分片下载
|
|
418
|
+
return file_size
|
|
419
|
+
|
|
420
|
+
num_chunks = math.ceil(file_size / base_chunk)
|
|
421
|
+
|
|
422
|
+
if num_chunks > max_chunks_limit:
|
|
423
|
+
# 如果文件太大导致分片数量过多 (2GB -> 200 块)
|
|
424
|
+
# 增加分片大小,将分片数限制在 100
|
|
425
|
+
return int(math.ceil(file_size / max_chunks_limit))
|
|
426
|
+
|
|
427
|
+
# 计算最后一个分片的大小,如果过小则调整分片大小
|
|
428
|
+
# 例如 250.2MB - (10MB * (26 - 1)) = 0.2MB
|
|
429
|
+
last_chunk_size = file_size - (base_chunk * (num_chunks - 1))
|
|
430
|
+
|
|
431
|
+
if last_chunk_size < base_chunk * min_chunk_threshold_factor:
|
|
432
|
+
# 如果最后一个分片过小,则均摊到前面的分片中
|
|
433
|
+
# 例如 250.2 / 25 = 10.008MB
|
|
434
|
+
return int(math.ceil(file_size / (num_chunks - 1)))
|
|
435
|
+
else:
|
|
436
|
+
return base_chunk
|
|
368
437
|
|
|
369
438
|
CHAR_MAPPING = {
|
|
370
439
|
'\\': '\',
|
{kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/.github/ISSUE_TEMPLATE/bug_report.yml
RENAMED
|
File without changes
|
|
File without changes
|
{kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/.github/workflows/release-package.yml
RENAMED
|
File without changes
|
{kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/.github/workflows/unit-test.yml
RENAMED
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/authenticator/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/configurer/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/downloader/__init__.py
RENAMED
|
File without changes
|
{kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/downloader/misc.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/lister/__init__.py
RENAMED
|
File without changes
|
{kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/lister/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/picker/__init__.py
RENAMED
|
File without changes
|
{kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/src/kmdr/module/picker/utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/tests/test_async_retry_decorator.py
RENAMED
|
File without changes
|
{kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/tests/test_kmdr_config_option.py
RENAMED
|
File without changes
|
|
File without changes
|
{kmoe_manga_downloader-1.2.6 → kmoe_manga_downloader-1.2.8a0}/tests/test_utils_resolve_volme.py
RENAMED
|
File without changes
|