Archived
refactor: HTTP 垫片异常层次收敛到 core.http_errors 单一来源
为什么:core/aiohttp_compat.py 与 core/sync_http.py 各自定义了一份 RequestException / HTTPError,是**两个不同的类**。调用方在同步段捕获 core.sync_http.HTTPError、异步段抛的却是 core.aiohttp_compat.HTTPError, 两者无继承关系——异常会穿透所有 except 分支,属于隐藏的跨层 bug。 改法:新建 core/http_errors.py 作为唯一定义处(RequestException 基类 + HTTPError / Timeout / ConnectionError),两个垫片改为从它导入并再导出。 刻意保留 requests 的命名约定(Timeout / ConnectionError 与内置同名, 调用方需带模块前缀引用),已在 docstring 写明,避免后来者误改。 注意:sync_http 补了 __all__ 显式再导出——models._RetryFromScratch 继承它、 tests/test_aria2.py 直接导入它,符号必须保持可导入。
This commit is contained in:
1 parent
2b4704183c
commit
d7d3cfce69
3 files changed
+46
-34
No files matched your search
+2
-22
@@ -21,31 +21,11 @@ from typing import Any
|
||||
|
||||
import aiohttp
|
||||
|
||||
from core.http_errors import ConnectionError, HTTPError, RequestException, Timeout
|
||||
|
||||
DEFAULT_TIMEOUT = 30
|
||||
DEFAULT_MAX_BYTES = 8 * 1024 * 1024
|
||||
|
||||
# ---------- 异常层次(对齐 requests 命名,便于原样 except) ----------
|
||||
|
||||
|
||||
class RequestException(Exception):
|
||||
"""请求异常基类(网络/协议层)。"""
|
||||
|
||||
|
||||
class HTTPError(RequestException):
|
||||
"""raise_for_status() 抛出的 HTTP 状态异常。"""
|
||||
|
||||
def __init__(self, message: str, response: 'Response | None' = None):
|
||||
super().__init__(message)
|
||||
self.response = response
|
||||
|
||||
|
||||
class Timeout(RequestException):
|
||||
"""请求超时。"""
|
||||
|
||||
|
||||
class ConnectionError(RequestException):
|
||||
"""连接错误。"""
|
||||
|
||||
|
||||
class Response:
|
||||
"""requests.Response 的异步子集:body 已读全,属性同步访问。"""
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""requests 同形异常层次(同步 / 异步两个 HTTP 垫片共用)。
|
||||
|
||||
`core.aiohttp_compat`(异步)与 `core.sync_http`(同步)此前各自定义了一份
|
||||
`RequestException` / `HTTPError`——两份定义互不相干,于是同一条调用链上
|
||||
「同步段抛的异常捕获不到异步段的同类失败」,调用方被迫记住自己走的是哪条垫片。
|
||||
|
||||
此处收敛为唯一来源;命名沿用 requests(`Timeout` / `ConnectionError` 与内置
|
||||
异常同名,这是 requests 自身的约定——调用方应带模块前缀引用,例如
|
||||
`requests.ConnectionError`,裸 `ConnectionError` 会命中内置的那个)。
|
||||
|
||||
层次:
|
||||
RequestException 网络 / 协议层失败(可捕获的总入口)
|
||||
├── HTTPError raise_for_status() 抛出的状态异常(携带 response)
|
||||
├── Timeout 请求超时
|
||||
└── ConnectionError 连接错误
|
||||
"""
|
||||
from typing import Any
|
||||
|
||||
|
||||
class RequestException(Exception):
|
||||
"""请求异常基类(网络/协议层)。"""
|
||||
|
||||
|
||||
class HTTPError(RequestException):
|
||||
"""raise_for_status() 抛出的 HTTP 状态异常。"""
|
||||
|
||||
def __init__(self, message: str, response: Any = None):
|
||||
super().__init__(message)
|
||||
self.response = response
|
||||
|
||||
|
||||
class Timeout(RequestException):
|
||||
"""请求超时。"""
|
||||
|
||||
|
||||
class ConnectionError(RequestException):
|
||||
"""连接错误。"""
|
||||
+6
-12
@@ -16,22 +16,16 @@ from typing import Any
|
||||
|
||||
from core import async_bridge
|
||||
from core.http_client import client as _client
|
||||
from core.http_errors import HTTPError, RequestException
|
||||
|
||||
# 异常层次与异步垫片(core.aiohttp_compat)共用同一份定义——调用方可用同一组
|
||||
# 类型捕获两条通道的失败。RequestException 在此再导出:music_downloader.models
|
||||
# 的 _RetryFromScratch 继承它,既有 except 与测试也直接导入它。
|
||||
__all__ = ['HTTPError', 'RequestException', 'Session', 'SyncResponse', 'get', 'post']
|
||||
|
||||
_DEFAULT_TIMEOUT = 30
|
||||
|
||||
|
||||
class RequestException(Exception):
|
||||
"""请求异常基类(对齐 requests 命名,便于迁移)。"""
|
||||
|
||||
|
||||
class HTTPError(RequestException):
|
||||
"""raise_for_status() 抛出的 HTTP 状态异常。"""
|
||||
|
||||
def __init__(self, message: str, response: 'SyncResponse | None' = None):
|
||||
super().__init__(message)
|
||||
self.response = response
|
||||
|
||||
|
||||
class SyncResponse:
|
||||
"""requests.Response 的同步子集(底层 aiohttp)。"""
|
||||
|
||||
|
||||
Reference in new issue
Block a user