wop-python-sdk 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,39 @@
1
+ # -*- coding: utf-8 -*-
2
+ """可插拔 HTTP 适配层(Q1 定稿):协议核心零网络 IO,传输以独立模块交付。
3
+
4
+ - ``Transport``:协议接口,商户自带栈时可直接实现或消费 RequestDraft;
5
+ - ``send_draft``:RequestDraft → Transport(URL 拼接归此,适配器只面对完整请求);
6
+ - stdlib urllib 适配器随主包;httpx / requests 适配器为 peer 依赖(extras)。
7
+ """
8
+ from dataclasses import dataclass
9
+ from typing import Dict, Optional, Protocol, runtime_checkable
10
+
11
+ from ..client import RequestDraft
12
+
13
+ __all__ = ["HttpResponse", "Transport", "UrllibTransport", "send_draft"]
14
+
15
+
16
+ @dataclass
17
+ class HttpResponse:
18
+ """传输层归一响应:headers 键统一小写。"""
19
+
20
+ status: int
21
+ headers: Dict[str, str]
22
+ body: bytes
23
+
24
+
25
+ @runtime_checkable
26
+ class Transport(Protocol):
27
+ def send(
28
+ self, method: str, url: str, headers: Dict[str, str], body: Optional[bytes]
29
+ ) -> HttpResponse:
30
+ ... # pragma: no cover —— Protocol 声明
31
+
32
+
33
+ def send_draft(transport: Transport, base_url: str, draft: RequestDraft) -> HttpResponse:
34
+ """把 RequestDraft 交给 Transport:URL = base_url + path。"""
35
+ url = base_url.rstrip("/") + draft.path
36
+ return transport.send(draft.method, url, draft.headers, draft.wire_body)
37
+
38
+
39
+ from .urllib_transport import UrllibTransport # noqa: E402 (置于 __all__ 定义后避免循环)
@@ -0,0 +1,37 @@
1
+ # -*- coding: utf-8 -*-
2
+ """httpx peer 适配器(extras:``pip install 'wop-sdk[httpx]'``)。"""
3
+ from typing import Dict, Optional
4
+
5
+ from . import HttpResponse
6
+
7
+
8
+ class HttpxTransport:
9
+ """httpx.Client 适配器;惰性导入,未安装时给出安装指引。"""
10
+
11
+ def __init__(self, client=None):
12
+ try:
13
+ import httpx
14
+ except ImportError as exc: # pragma: no cover —— 视环境而定
15
+ raise ImportError(
16
+ "httpx 未安装;peer 适配器请执行 pip install 'wop-sdk[httpx]'"
17
+ ) from exc
18
+ self._client = client if client is not None else httpx.Client()
19
+
20
+ def send(
21
+ self, method: str, url: str, headers: Dict[str, str], body: Optional[bytes]
22
+ ) -> HttpResponse:
23
+ resp = self._client.request(method, url, headers=headers, content=body)
24
+ return HttpResponse(
25
+ resp.status_code,
26
+ {k.lower(): v for k, v in resp.headers.items()},
27
+ resp.content,
28
+ )
29
+
30
+ def close(self) -> None:
31
+ self._client.close()
32
+
33
+ def __enter__(self) -> "HttpxTransport":
34
+ return self
35
+
36
+ def __exit__(self, *exc_info) -> None:
37
+ self.close()
@@ -0,0 +1,37 @@
1
+ # -*- coding: utf-8 -*-
2
+ """requests peer 适配器(extras:``pip install 'wop-sdk[requests]'``)。"""
3
+ from typing import Dict, Optional
4
+
5
+ from . import HttpResponse
6
+
7
+
8
+ class RequestsTransport:
9
+ """requests 适配器;惰性导入,未安装时给出安装指引。"""
10
+
11
+ def __init__(self, session=None):
12
+ try:
13
+ import requests
14
+ except ImportError as exc: # pragma: no cover —— 视环境而定
15
+ raise ImportError(
16
+ "requests 未安装;peer 适配器请执行 pip install 'wop-sdk[requests]'"
17
+ ) from exc
18
+ self._session = session if session is not None else requests.Session()
19
+
20
+ def send(
21
+ self, method: str, url: str, headers: Dict[str, str], body: Optional[bytes]
22
+ ) -> HttpResponse:
23
+ resp = self._session.request(method, url, headers=headers, data=body)
24
+ return HttpResponse(
25
+ resp.status_code,
26
+ {k.lower(): v for k, v in resp.headers.items()},
27
+ resp.content,
28
+ )
29
+
30
+ def close(self) -> None:
31
+ self._session.close()
32
+
33
+ def __enter__(self) -> "RequestsTransport":
34
+ return self
35
+
36
+ def __exit__(self, *exc_info) -> None:
37
+ self.close()
@@ -0,0 +1,29 @@
1
+ # -*- coding: utf-8 -*-
2
+ """stdlib urllib 适配器(零依赖,随主包交付)。"""
3
+ import urllib.error
4
+ import urllib.request
5
+ from typing import Dict, Optional
6
+
7
+ from . import HttpResponse
8
+
9
+
10
+ class UrllibTransport:
11
+ """urllib.request 适配器;4xx/5xx 返回响应体而非抛异常(协议错误也在 body 里)。"""
12
+
13
+ def send(
14
+ self, method: str, url: str, headers: Dict[str, str], body: Optional[bytes]
15
+ ) -> HttpResponse:
16
+ req = urllib.request.Request(url, data=body, method=method)
17
+ for name, value in headers.items():
18
+ req.add_header(name, value)
19
+ try:
20
+ with urllib.request.urlopen(req) as resp:
21
+ return HttpResponse(
22
+ resp.status,
23
+ {k.lower(): v for k, v in resp.headers.items()},
24
+ resp.read(),
25
+ )
26
+ except urllib.error.HTTPError as exc:
27
+ return HttpResponse(
28
+ exc.code, {k.lower(): v for k, v in exc.headers.items()}, exc.read()
29
+ )