fiuai-sdk-python 0.4.0__tar.gz → 0.4.2__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.
- {fiuai_sdk_python-0.4.0 → fiuai_sdk_python-0.4.2}/PKG-INFO +1 -1
- {fiuai_sdk_python-0.4.0 → fiuai_sdk_python-0.4.2}/pyproject.toml +1 -1
- fiuai_sdk_python-0.4.2/src/fiuai_sdk_python/__init__.py +24 -0
- fiuai_sdk_python-0.4.2/src/fiuai_sdk_python/client.py +387 -0
- fiuai_sdk_python-0.4.2/src/fiuai_sdk_python/context.py +288 -0
- fiuai_sdk_python-0.4.0/src/fiuai_sdk_python/__init__.py +0 -16
- fiuai_sdk_python-0.4.0/src/fiuai_sdk_python/auth/test_auth.py +0 -273
- fiuai_sdk_python-0.4.0/src/fiuai_sdk_python/client.py +0 -280
- fiuai_sdk_python-0.4.0/src/fiuai_sdk_python/context.py +0 -236
- fiuai_sdk_python-0.4.0/src/fiuai_sdk_python/test_all.py +0 -73
- {fiuai_sdk_python-0.4.0 → fiuai_sdk_python-0.4.2}/.gitignore +0 -0
- {fiuai_sdk_python-0.4.0 → fiuai_sdk_python-0.4.2}/CHANGELOG.md +0 -0
- {fiuai_sdk_python-0.4.0 → fiuai_sdk_python-0.4.2}/LICENSE +0 -0
- {fiuai_sdk_python-0.4.0 → fiuai_sdk_python-0.4.2}/README.md +0 -0
- {fiuai_sdk_python-0.4.0 → fiuai_sdk_python-0.4.2}/src/fiuai_sdk_python/auth/__init__.py +0 -0
- {fiuai_sdk_python-0.4.0 → fiuai_sdk_python-0.4.2}/src/fiuai_sdk_python/auth/header.py +0 -0
- {fiuai_sdk_python-0.4.0 → fiuai_sdk_python-0.4.2}/src/fiuai_sdk_python/auth/helper.py +0 -0
- {fiuai_sdk_python-0.4.0 → fiuai_sdk_python-0.4.2}/src/fiuai_sdk_python/auth/type.py +0 -0
- {fiuai_sdk_python-0.4.0 → fiuai_sdk_python-0.4.2}/src/fiuai_sdk_python/bank.py +0 -0
- {fiuai_sdk_python-0.4.0 → fiuai_sdk_python-0.4.2}/src/fiuai_sdk_python/company.py +0 -0
- {fiuai_sdk_python-0.4.0 → fiuai_sdk_python-0.4.2}/src/fiuai_sdk_python/const.py +0 -0
- {fiuai_sdk_python-0.4.0 → fiuai_sdk_python-0.4.2}/src/fiuai_sdk_python/error.py +0 -0
- {fiuai_sdk_python-0.4.0 → fiuai_sdk_python-0.4.2}/src/fiuai_sdk_python/examples/fastapi_integration.py +0 -0
- {fiuai_sdk_python-0.4.0 → fiuai_sdk_python-0.4.2}/src/fiuai_sdk_python/item.py +0 -0
- {fiuai_sdk_python-0.4.0 → fiuai_sdk_python-0.4.2}/src/fiuai_sdk_python/perm.py +0 -0
- {fiuai_sdk_python-0.4.0 → fiuai_sdk_python-0.4.2}/src/fiuai_sdk_python/profile.py +0 -0
- {fiuai_sdk_python-0.4.0 → fiuai_sdk_python-0.4.2}/src/fiuai_sdk_python/resp.py +0 -0
- {fiuai_sdk_python-0.4.0 → fiuai_sdk_python-0.4.2}/src/fiuai_sdk_python/setup.py +0 -0
- {fiuai_sdk_python-0.4.0 → fiuai_sdk_python-0.4.2}/src/fiuai_sdk_python/type.py +0 -0
- {fiuai_sdk_python-0.4.0 → fiuai_sdk_python-0.4.2}/src/fiuai_sdk_python/util.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fiuai_sdk_python
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: FiuAI Python SDK - 企业级AI服务集成开发工具包
|
|
5
5
|
Project-URL: Homepage, https://github.com/fiuai/fiuai-sdk-python
|
|
6
6
|
Project-URL: Documentation, https://github.com/fiuai/fiuai-sdk-python#readme
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from .client import FiuaiSDK, get_client
|
|
2
|
+
from .util import init_fiuai
|
|
3
|
+
from .profile import UserProfileInfo
|
|
4
|
+
from .type import UserProfile
|
|
5
|
+
from .context import (
|
|
6
|
+
RequestContext,
|
|
7
|
+
get_current_headers,
|
|
8
|
+
validate_current_context,
|
|
9
|
+
get_current_missing_fields,
|
|
10
|
+
is_current_context_valid
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
'FiuaiSDK',
|
|
15
|
+
'init_fiuai',
|
|
16
|
+
'get_client',
|
|
17
|
+
'UserProfileInfo',
|
|
18
|
+
'UserProfile',
|
|
19
|
+
'RequestContext',
|
|
20
|
+
'get_current_headers',
|
|
21
|
+
'validate_current_context',
|
|
22
|
+
'get_current_missing_fields',
|
|
23
|
+
'is_current_context_valid'
|
|
24
|
+
]
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
from tenacity import retry, stop_after_attempt, wait_exponential
|
|
3
|
+
import json
|
|
4
|
+
from urllib.parse import quote
|
|
5
|
+
from typing import Any, Literal
|
|
6
|
+
|
|
7
|
+
from .util import get_client_config, is_initialized
|
|
8
|
+
from .error import FiuaiGeneralError, FiuaiAuthError
|
|
9
|
+
from logging import getLogger
|
|
10
|
+
from .type import UserProfile
|
|
11
|
+
from .profile import UserProfileInfo
|
|
12
|
+
from .auth import AuthHeader
|
|
13
|
+
from .resp import parse_response, ApiResponse
|
|
14
|
+
from .context import get_current_headers
|
|
15
|
+
from typing import Dict, Any, Optional
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
logger = getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
class NotUploadableException(FiuaiGeneralError):
|
|
21
|
+
def __init__(self, doctype):
|
|
22
|
+
self.message = "The doctype `{1}` is not uploadable, so you can't download the template".format(doctype)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class FiuaiSDK(object):
|
|
28
|
+
def __init__(self,
|
|
29
|
+
url: str,
|
|
30
|
+
username: str = None,
|
|
31
|
+
auth_tenant_id: str = None,
|
|
32
|
+
current_company: str = None,
|
|
33
|
+
company_unique_no: str = None,
|
|
34
|
+
# auth_type: Literal["internal", "password"]="password",
|
|
35
|
+
max_api_retry: int=3,
|
|
36
|
+
timeout: int=5,
|
|
37
|
+
verify: bool=False
|
|
38
|
+
):
|
|
39
|
+
self.username = username
|
|
40
|
+
self.auth_tenant_id = auth_tenant_id
|
|
41
|
+
self.current_company = current_company
|
|
42
|
+
self.company_unique_no = company_unique_no
|
|
43
|
+
self.verify = verify
|
|
44
|
+
self.url = url
|
|
45
|
+
self.max_api_retry = max_api_retry
|
|
46
|
+
|
|
47
|
+
self.client = httpx.Client(
|
|
48
|
+
verify=self.verify,
|
|
49
|
+
timeout=timeout,
|
|
50
|
+
follow_redirects=True,
|
|
51
|
+
proxy=None
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# 默认的 AuthHeader,优先使用传入的参数,否则从上下文获取
|
|
55
|
+
self.headers = AuthHeader(
|
|
56
|
+
x_fiuai_user=username or "",
|
|
57
|
+
x_fiuai_auth_tenant_id=auth_tenant_id or "",
|
|
58
|
+
x_fiuai_current_company=current_company or "",
|
|
59
|
+
x_fiuai_impersonation="",
|
|
60
|
+
x_fiuai_unique_no=company_unique_no or current_company or "", # 优先使用 company_unique_no
|
|
61
|
+
x_fiuai_trace_id="",
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# 临时 headers 存储,用于 set_temp_header 方法
|
|
65
|
+
self._temp_headers = {}
|
|
66
|
+
|
|
67
|
+
def _get_merged_headers(self, extra_headers: Optional[Dict[str, Any]] = None) -> Dict[str, str]:
|
|
68
|
+
"""
|
|
69
|
+
获取合并后的请求头,自动注入 AuthData 中除了 sid 以外的所有字段
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
extra_headers: 额外的请求头,会覆盖默认值
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
Dict[str, str]: 合并后的请求头字典
|
|
76
|
+
"""
|
|
77
|
+
# 获取当前上下文的 headers
|
|
78
|
+
context_headers = get_current_headers()
|
|
79
|
+
|
|
80
|
+
# 从上下文构建 AuthData 相关的 headers
|
|
81
|
+
auth_headers = {}
|
|
82
|
+
if context_headers:
|
|
83
|
+
# 映射 AuthData 字段到 HTTP headers,优先使用初始化参数
|
|
84
|
+
current_company_value = self.current_company or context_headers.get("x-fiuai-current-company", self.headers.x_fiuai_current_company)
|
|
85
|
+
company_unique_no_value = self.company_unique_no or context_headers.get("x-fiuai-unique-no", self.headers.x_fiuai_unique_no)
|
|
86
|
+
# 如果 company_unique_no 没有值,使用 current_company 的值
|
|
87
|
+
if not company_unique_no_value:
|
|
88
|
+
company_unique_no_value = current_company_value
|
|
89
|
+
|
|
90
|
+
auth_headers.update({
|
|
91
|
+
"x-fiuai-user": self.username or context_headers.get("x-fiuai-user", self.headers.x_fiuai_user),
|
|
92
|
+
"x-fiuai-auth-tenant-id": self.auth_tenant_id or context_headers.get("x-fiuai-auth-tenant-id", self.headers.x_fiuai_auth_tenant_id),
|
|
93
|
+
"x-fiuai-current-company": current_company_value,
|
|
94
|
+
"x-fiuai-impersonation": context_headers.get("x-fiuai-impersonation", self.headers.x_fiuai_impersonation),
|
|
95
|
+
"x-fiuai-unique-no": company_unique_no_value,
|
|
96
|
+
"x-fiuai-trace-id": context_headers.get("x-fiuai-trace-id", self.headers.x_fiuai_trace_id),
|
|
97
|
+
"x-fiuai-lang": context_headers.get("x-fiuai-lang", self.headers.x_fiuai_lang),
|
|
98
|
+
"accept-language": context_headers.get("accept-language", self.headers.accept_language),
|
|
99
|
+
})
|
|
100
|
+
else:
|
|
101
|
+
# 如果没有上下文,使用初始化参数或默认的 headers
|
|
102
|
+
current_company_value = self.current_company or self.headers.x_fiuai_current_company
|
|
103
|
+
company_unique_no_value = self.company_unique_no or self.headers.x_fiuai_unique_no
|
|
104
|
+
# 如果 company_unique_no 没有值,使用 current_company 的值
|
|
105
|
+
if not company_unique_no_value:
|
|
106
|
+
company_unique_no_value = current_company_value
|
|
107
|
+
|
|
108
|
+
auth_headers = {
|
|
109
|
+
"x-fiuai-user": self.username or self.headers.x_fiuai_user,
|
|
110
|
+
"x-fiuai-auth-tenant-id": self.auth_tenant_id or self.headers.x_fiuai_auth_tenant_id,
|
|
111
|
+
"x-fiuai-current-company": current_company_value,
|
|
112
|
+
"x-fiuai-impersonation": self.headers.x_fiuai_impersonation,
|
|
113
|
+
"x-fiuai-unique-no": company_unique_no_value,
|
|
114
|
+
"x-fiuai-trace-id": self.headers.x_fiuai_trace_id,
|
|
115
|
+
"x-fiuai-lang": self.headers.x_fiuai_lang,
|
|
116
|
+
"accept-language": self.headers.accept_language,
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
# 应用临时 headers(优先级高于上下文,低于 extra_headers)
|
|
120
|
+
if self._temp_headers:
|
|
121
|
+
auth_headers.update(self._temp_headers)
|
|
122
|
+
|
|
123
|
+
# 合并 extra_headers(优先级最高)
|
|
124
|
+
if extra_headers:
|
|
125
|
+
auth_headers.update(extra_headers)
|
|
126
|
+
|
|
127
|
+
return auth_headers
|
|
128
|
+
|
|
129
|
+
def set_temp_header(self,
|
|
130
|
+
auth_tenant_id: Optional[str] = None,
|
|
131
|
+
auth_company_id: Optional[str] = None,
|
|
132
|
+
user_id: Optional[str] = None,
|
|
133
|
+
company_unique_no: Optional[str] = None) -> None:
|
|
134
|
+
"""
|
|
135
|
+
设置临时请求头,这些值会在本地请求中替换对应的header,但不覆盖context中的值
|
|
136
|
+
|
|
137
|
+
Args:
|
|
138
|
+
auth_tenant_id: 临时租户ID
|
|
139
|
+
auth_company_id: 临时公司ID(会自动设置 company_unique_no = auth_company_id)
|
|
140
|
+
user_id: 临时用户ID
|
|
141
|
+
company_unique_no: 临时公司唯一编号
|
|
142
|
+
"""
|
|
143
|
+
if auth_tenant_id is not None:
|
|
144
|
+
self._temp_headers["x-fiuai-auth-tenant-id"] = auth_tenant_id
|
|
145
|
+
|
|
146
|
+
if auth_company_id is not None:
|
|
147
|
+
self._temp_headers["x-fiuai-current-company"] = auth_company_id
|
|
148
|
+
# 实现 company_unique_no = auth_company_id
|
|
149
|
+
self._temp_headers["x-fiuai-unique-no"] = auth_company_id
|
|
150
|
+
|
|
151
|
+
if user_id is not None:
|
|
152
|
+
self._temp_headers["x-fiuai-user"] = user_id
|
|
153
|
+
|
|
154
|
+
if company_unique_no is not None:
|
|
155
|
+
if auth_company_id:
|
|
156
|
+
self._temp_headers["x-fiuai-unique-no"] = auth_company_id
|
|
157
|
+
else:
|
|
158
|
+
self._temp_headers["x-fiuai-unique-no"] = company_unique_no
|
|
159
|
+
|
|
160
|
+
def clear_temp_headers(self) -> None:
|
|
161
|
+
"""清除所有临时请求头"""
|
|
162
|
+
self._temp_headers.clear()
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
# def _login(self, username: str, password: str):
|
|
166
|
+
# r = self.client.post(self.url, data={
|
|
167
|
+
# 'cmd': 'login',
|
|
168
|
+
# 'usr': username,
|
|
169
|
+
# 'pwd': password
|
|
170
|
+
# }, headers=self.headers)
|
|
171
|
+
|
|
172
|
+
# if r.json().get('message') == "Logged In":
|
|
173
|
+
# self.can_download = []
|
|
174
|
+
# logger.info(f"Login to {self.url} success")
|
|
175
|
+
|
|
176
|
+
# ### 获取cookie
|
|
177
|
+
# self.headers["Fiuai-Internal-Company"] = r.cookies.get("current_company")
|
|
178
|
+
# self.headers["Fiuai-Internal-Tenant"] = r.cookies.get("tenant")
|
|
179
|
+
# return r.json()
|
|
180
|
+
# else:
|
|
181
|
+
# raise FiuaiAuthError(f"Login failed: {r.json().get('message')}")
|
|
182
|
+
|
|
183
|
+
# def _logout(self):
|
|
184
|
+
# logger.info(f"Logout from {self.url}")
|
|
185
|
+
# if self.auth_type == "password":
|
|
186
|
+
# # internal login 不需要logout
|
|
187
|
+
# self.client.get(self.url, params={"cmd": "logout"}, headers=self.headers)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def __enter__(self):
|
|
191
|
+
return self
|
|
192
|
+
|
|
193
|
+
def __exit__(self, *args, **kwargs):
|
|
194
|
+
# self._logout()
|
|
195
|
+
self.client.close()
|
|
196
|
+
# self.logout()
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def get_avaliable_company(self, page: int=1, page_size: int=20, extra_headers: Optional[Dict[str, Any]] = None) -> ApiResponse:
|
|
200
|
+
headers = self._get_merged_headers(extra_headers)
|
|
201
|
+
r = self.client.get(self.url + "/api/method/fiuai.network.doctype.company.company.get_available_companies",
|
|
202
|
+
params={"page": page, "page_size": page_size},
|
|
203
|
+
headers=headers)
|
|
204
|
+
|
|
205
|
+
return self.post_process(r)
|
|
206
|
+
|
|
207
|
+
def swith_company(self, tenant: str = "", company: str = "") -> ApiResponse:
|
|
208
|
+
|
|
209
|
+
self.headers.x_fiuai_auth_tenant_id = tenant
|
|
210
|
+
self.headers.x_fiuai_current_company = company
|
|
211
|
+
|
|
212
|
+
if company == "":
|
|
213
|
+
raise FiuaiAuthError("Company is required when using password auth")
|
|
214
|
+
|
|
215
|
+
if tenant == "":
|
|
216
|
+
raise FiuaiAuthError("Tenant is required when using internal auth")
|
|
217
|
+
|
|
218
|
+
# else:
|
|
219
|
+
# r = self.client.post(self.url + "/api/method/frappe.sessions.change_current_company",
|
|
220
|
+
# data={"auth_company_id": company})
|
|
221
|
+
# if r.status_code != 200:
|
|
222
|
+
# logger.error(f"Switch company failed: {r.json().get('message')}")
|
|
223
|
+
# # raise FiuaiAuthError(f"Switch company failed: {r.json().get('message')}")
|
|
224
|
+
# return False
|
|
225
|
+
# else:
|
|
226
|
+
# return True
|
|
227
|
+
|
|
228
|
+
def get_tenant(self) -> ApiResponse:
|
|
229
|
+
return self.headers.x_fiuai_auth_tenant_id
|
|
230
|
+
|
|
231
|
+
def get_company(self) -> ApiResponse:
|
|
232
|
+
return self.headers.x_fiuai_current_company
|
|
233
|
+
|
|
234
|
+
# def get_v2_api(self, uri, params={}):
|
|
235
|
+
|
|
236
|
+
# print(f"22222, ", self.headers.model_dump())
|
|
237
|
+
# res = self.client.get(self.url + '/api/v2/' + uri.lstrip('/'), params=params, headers=self.headers.model_dump())
|
|
238
|
+
# return self.post_process(res)
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def get_user_profile_info(self, user_id: str=None, extra_headers: Optional[Dict[str, Any]] = None) -> ApiResponse:
|
|
242
|
+
"""获取详细的用户信息"""
|
|
243
|
+
if not user_id:
|
|
244
|
+
user_id = self.headers.x_fiuai_user
|
|
245
|
+
|
|
246
|
+
headers = self._get_merged_headers(extra_headers)
|
|
247
|
+
res = self.client.get(self.url + f"/api/v2/internal/user/profile/{user_id}", headers=headers)
|
|
248
|
+
|
|
249
|
+
profile_response = self.post_process(res)
|
|
250
|
+
|
|
251
|
+
if profile_response.is_success():
|
|
252
|
+
try:
|
|
253
|
+
profile_response.data = UserProfileInfo.model_validate(profile_response.data)
|
|
254
|
+
except Exception as e:
|
|
255
|
+
profile_response.error = str(e)
|
|
256
|
+
profile_response.error_code = "PROFILE_FORMAT_ERROR"
|
|
257
|
+
return profile_response
|
|
258
|
+
return profile_response
|
|
259
|
+
else:
|
|
260
|
+
return profile_response
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def internal_post_req(self, uri, postdata={}, extra_headers: Optional[Dict[str, Any]] = None) -> ApiResponse:
|
|
265
|
+
headers = self._get_merged_headers(extra_headers)
|
|
266
|
+
res = self.client.post(self.url + '/api/v2/internal/' + uri.lstrip('/'), data=postdata, headers=headers)
|
|
267
|
+
return self.post_process(res)
|
|
268
|
+
|
|
269
|
+
def internal_get_req(self, uri, params={}, extra_headers: Optional[Dict[str, Any]] = None) -> ApiResponse:
|
|
270
|
+
headers = self._get_merged_headers(extra_headers)
|
|
271
|
+
res = self.client.get(self.url + '/api/v2/internal/' + uri.lstrip('/'), params=params, headers=headers)
|
|
272
|
+
return self.post_process(res)
|
|
273
|
+
|
|
274
|
+
def internal_create(self, data={}, extra_headers: Optional[Dict[str, Any]] = None) -> ApiResponse:
|
|
275
|
+
headers = self._get_merged_headers(extra_headers)
|
|
276
|
+
res = self.client.post(self.url + '/api/v2/internal/doctype/create', data={"data":json.dumps(data, ensure_ascii=False)}, headers=headers)
|
|
277
|
+
return self.post_process(res)
|
|
278
|
+
|
|
279
|
+
def internal_get(self, doctype, name, fields=None, filters=None, extra_headers: Optional[Dict[str, Any]] = None) -> ApiResponse:
|
|
280
|
+
d = {
|
|
281
|
+
"doctype": doctype,
|
|
282
|
+
"name": name,
|
|
283
|
+
}
|
|
284
|
+
if fields:
|
|
285
|
+
d["fields"] = json.dumps(fields)
|
|
286
|
+
if filters:
|
|
287
|
+
d["filters"] = json.dumps(filters)
|
|
288
|
+
headers = self._get_merged_headers(extra_headers)
|
|
289
|
+
res = self.client.get(self.url + '/api/v2/internal/doctype/get', params=d, headers=headers)
|
|
290
|
+
return self.post_process(res)
|
|
291
|
+
|
|
292
|
+
def internal_get_list(self, doctype, filters=None, fields=None, limit_start=0, limit_page_length=20, order_by=None,
|
|
293
|
+
extra_headers: Optional[Dict[str, Any]] = None) -> ApiResponse:
|
|
294
|
+
d = {
|
|
295
|
+
"doctype": doctype,
|
|
296
|
+
"limit_start":limit_start,
|
|
297
|
+
"limit_page_length":limit_page_length,
|
|
298
|
+
}
|
|
299
|
+
if filters:
|
|
300
|
+
d["filters"] = json.dumps(filters)
|
|
301
|
+
if fields:
|
|
302
|
+
d["fields"] = json.dumps(fields)
|
|
303
|
+
if order_by:
|
|
304
|
+
d["order_by"] = order_by
|
|
305
|
+
headers = self._get_merged_headers(extra_headers)
|
|
306
|
+
res = self.client.get(
|
|
307
|
+
self.url + '/api/v2/internal/doctype/get_list',
|
|
308
|
+
params=d,
|
|
309
|
+
headers=headers)
|
|
310
|
+
return self.post_process(res)
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
def internal_update(self, data={}, extra_headers: Optional[Dict[str, Any]] = None) -> ApiResponse:
|
|
314
|
+
headers = self._get_merged_headers(extra_headers)
|
|
315
|
+
res = self.client.post(self.url + '/api/v2/internal/doctype/update', data={"data":json.dumps(data, ensure_ascii=False)}, headers=headers)
|
|
316
|
+
return self.post_process(res)
|
|
317
|
+
|
|
318
|
+
def internal_delete(self, doctype, name, extra_headers: Optional[Dict[str, Any]] = None) -> ApiResponse:
|
|
319
|
+
headers = self._get_merged_headers(extra_headers)
|
|
320
|
+
res = self.client.post(self.url + '/api/v2/internal/doctype/delete', data={"doctype": doctype, "name":name}, headers=headers)
|
|
321
|
+
return self.post_process(res)
|
|
322
|
+
|
|
323
|
+
def internal_submit(self, doctype, name, extra_headers: Optional[Dict[str, Any]] = None) -> ApiResponse:
|
|
324
|
+
headers = self._get_merged_headers(extra_headers)
|
|
325
|
+
res = self.client.post(self.url + '/api/v2/internal/doctype/submit', data={"doctype": doctype, "name":name}, headers=headers)
|
|
326
|
+
return self.post_process(res)
|
|
327
|
+
|
|
328
|
+
def internal_cancel(self, doctype, name, extra_headers: Optional[Dict[str, Any]] = None) -> ApiResponse:
|
|
329
|
+
headers = self._get_merged_headers(extra_headers)
|
|
330
|
+
res = self.client.post(self.url + '/api/v2/internal/doctype/cancel', data={"doctype": doctype, "name":name}, headers=headers)
|
|
331
|
+
return self.post_process(res)
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
def get_meta(self, doctype: str, extra_headers: Optional[Dict[str, Any]] = None) -> ApiResponse:
|
|
335
|
+
headers = self._get_merged_headers(extra_headers)
|
|
336
|
+
res = self.client.get(self.url + '/api/v2/internal/doctype/meta/' + doctype, headers=headers)
|
|
337
|
+
|
|
338
|
+
return self.post_process(res)
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
def post_process(self, response) -> ApiResponse:
|
|
342
|
+
"""
|
|
343
|
+
处理API响应,使用结构化的错误处理系统
|
|
344
|
+
|
|
345
|
+
Args:
|
|
346
|
+
response: httpx响应对象
|
|
347
|
+
|
|
348
|
+
Returns:
|
|
349
|
+
Any: 成功时返回数据,失败时抛出异常
|
|
350
|
+
|
|
351
|
+
Raises:
|
|
352
|
+
FiuaiGeneralError: 当API返回错误时
|
|
353
|
+
FiuaiAuthError: 当认证相关错误时
|
|
354
|
+
"""
|
|
355
|
+
# 使用resp.py中的统一解析函数
|
|
356
|
+
api_response = parse_response(response)
|
|
357
|
+
|
|
358
|
+
return api_response
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
def get_client(username: str = None, auth_tenant_id: str = None, current_company: str = None, company_unique_no: str = None) -> FiuaiSDK:
|
|
362
|
+
"""
|
|
363
|
+
获取FiuaiSDK客户端, 需要提取调用init_fiuai()初始化
|
|
364
|
+
|
|
365
|
+
Args:
|
|
366
|
+
username: 用户名(如果提供,优先使用此值而不是上下文)
|
|
367
|
+
auth_tenant_id: 租户ID(如果提供,优先使用此值而不是上下文)
|
|
368
|
+
current_company: 当前公司(如果提供,优先使用此值而不是上下文)
|
|
369
|
+
company_unique_no: 公司唯一编号(如果提供,优先使用此值而不是上下文)
|
|
370
|
+
"""
|
|
371
|
+
# 检查是否已初始化
|
|
372
|
+
if not is_initialized():
|
|
373
|
+
raise ValueError("FiuaiSDK not initialized. Please call init_fiuai() first.")
|
|
374
|
+
|
|
375
|
+
client_config = get_client_config()
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
return FiuaiSDK(
|
|
379
|
+
url=client_config.url,
|
|
380
|
+
username=username,
|
|
381
|
+
auth_tenant_id=auth_tenant_id,
|
|
382
|
+
current_company=current_company,
|
|
383
|
+
company_unique_no=company_unique_no,
|
|
384
|
+
max_api_retry=client_config.max_api_retry,
|
|
385
|
+
timeout=client_config.timeout,
|
|
386
|
+
verify=client_config.verify,
|
|
387
|
+
)
|