|
12 | 12 | - **转换约定**:MultiProtocolAuthProvider 在调用方做转换,不扩展协议方法: |
13 | 13 | - 取回时:_get_credentials() 调用 storage.get_tokens(),若得到 OAuthToken 则经 |
14 | 14 | _oauth_token_to_credentials 转为 OAuthCredentials。 |
15 | | - - 写入时:401 流程得到 AuthCredentials 后经 _credentials_to_storage 转为 |
16 | | - OAuthToken(仅 OAuthCredentials 转 OAuthToken,其他凭证原样),再调用 storage.set_tokens(to_store)。 |
| 15 | + - 写入时:_discover_and_authenticate 得到 AuthCredentials 后经 _credentials_to_storage |
| 16 | + 转为 OAuthToken(仅 OAuthCredentials 转 OAuthToken,其他凭证原样),再调用 |
| 17 | + storage.set_tokens(to_store)。 |
17 | 18 | - 因此仅实现 get_tokens/set_tokens(OAuthToken) 的旧存储可直接用于 MultiProtocolAuthProvider, |
18 | 19 | 无需改存储实现。可选使用 OAuthTokenStorageAdapter 将此类存储包装为满足 multi_protocol 契约。 |
19 | 20 | """ |
|
60 | 61 |
|
61 | 62 |
|
62 | 63 | class TokenStorage(Protocol): |
63 | | - """凭证存储协议(兼容 OAuthToken 与 AuthCredentials)。""" |
| 64 | + """ |
| 65 | + 凭证存储协议(multi_protocol 契约)。 |
| 66 | +
|
| 67 | + 本协议接受 get_tokens() -> AuthCredentials | OAuthToken | None 与 |
| 68 | + set_tokens(AuthCredentials | OAuthToken)。仅支持 OAuthToken 的旧存储亦可使用: |
| 69 | + MultiProtocolAuthProvider 在 _get_credentials/_discover_and_authenticate 内做 |
| 70 | + OAuthToken <-> OAuthCredentials 转换;或使用 OAuthTokenStorageAdapter 包装。 |
| 71 | + """ |
64 | 72 |
|
65 | 73 | async def get_tokens(self) -> AuthCredentials | OAuthToken | None: |
66 | 74 | """获取已存储的凭证。""" |
@@ -109,6 +117,44 @@ def _credentials_to_storage(credentials: AuthCredentials) -> AuthCredentials | O |
109 | 117 | return credentials |
110 | 118 |
|
111 | 119 |
|
| 120 | +class _OAuthTokenOnlyStorage(Protocol): |
| 121 | + """仅支持 OAuthToken 的存储契约(供 OAuthTokenStorageAdapter 包装)。""" |
| 122 | + |
| 123 | + async def get_tokens(self) -> OAuthToken | None: |
| 124 | + ... |
| 125 | + |
| 126 | + async def set_tokens(self, tokens: OAuthToken) -> None: |
| 127 | + ... |
| 128 | + |
| 129 | + |
| 130 | +class OAuthTokenStorageAdapter: |
| 131 | + """ |
| 132 | + 将仅支持 OAuthToken 的 storage 包装为满足 multi_protocol TokenStorage。 |
| 133 | +
|
| 134 | + 取回时把 OAuthToken 转为 OAuthCredentials;写入时把 OAuthCredentials 转为 OAuthToken |
| 135 | + 再调用底层 set_tokens。仅 OAuth 凭证会写入底层存储,非 OAuth 凭证(如 APIKeyCredentials) |
| 136 | + 不写入。 |
| 137 | + """ |
| 138 | + |
| 139 | + def __init__(self, wrapped: _OAuthTokenOnlyStorage) -> None: |
| 140 | + self._wrapped = wrapped |
| 141 | + |
| 142 | + async def get_tokens(self) -> AuthCredentials | OAuthToken | None: |
| 143 | + raw = await self._wrapped.get_tokens() |
| 144 | + if raw is None: |
| 145 | + return None |
| 146 | + return _oauth_token_to_credentials(raw) |
| 147 | + |
| 148 | + async def set_tokens(self, tokens: AuthCredentials | OAuthToken) -> None: |
| 149 | + to_store = ( |
| 150 | + _credentials_to_storage(tokens) |
| 151 | + if isinstance(tokens, AuthCredentials) |
| 152 | + else tokens |
| 153 | + ) |
| 154 | + if isinstance(to_store, OAuthToken): |
| 155 | + await self._wrapped.set_tokens(to_store) |
| 156 | + |
| 157 | + |
112 | 158 | class MultiProtocolAuthProvider(httpx.Auth): |
113 | 159 | """ |
114 | 160 | 多协议认证提供者。 |
|
0 commit comments