fiuai-sdk-python 0.8.5__tar.gz → 0.8.7__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.8.5 → fiuai_sdk_python-0.8.7}/PKG-INFO +1 -1
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/pyproject.toml +1 -1
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/client.py +22 -2
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/profile.py +117 -3
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/.gitignore +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/CHANGELOG.md +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/LICENSE +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/README.md +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/__init__.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/auth/__init__.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/auth/context_mgr.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/auth/header.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/auth/helper.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/auth/type.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/bank.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/company.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/config.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/const.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/context.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/datatype.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/doctype.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/error.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/examples/fastapi_integration.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/http/__init__.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/http/client.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/item.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/perm.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/pkg/cache/__init__.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/pkg/cache/cache_client.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/pkg/cache/circuit_breaker.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/pkg/cache/decorator.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/pkg/cache/redis_manager.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/pkg/cache/types.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/resp.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/setup.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/type.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/util.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/utils/__init__.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/utils/ids.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/utils/logger.py +0 -0
- {fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/utils/text.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fiuai_sdk_python
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.7
|
|
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
|
|
@@ -2,7 +2,7 @@ import httpx
|
|
|
2
2
|
from tenacity import retry, stop_after_attempt, wait_exponential
|
|
3
3
|
import json
|
|
4
4
|
from urllib.parse import quote
|
|
5
|
-
from typing import Any, Literal,
|
|
5
|
+
from typing import Any, Dict, List, Literal, Optional
|
|
6
6
|
|
|
7
7
|
from .util import get_client_config, is_initialized
|
|
8
8
|
from .error import FiuaiGeneralError, FiuaiAuthError
|
|
@@ -12,7 +12,6 @@ from .profile import UserProfileInfo
|
|
|
12
12
|
from .auth import AuthHeader
|
|
13
13
|
from .resp import parse_response, ApiResponse
|
|
14
14
|
from .context import get_current_headers
|
|
15
|
-
from typing import Dict, Any, Optional
|
|
16
15
|
|
|
17
16
|
|
|
18
17
|
logger = getLogger(__name__)
|
|
@@ -298,6 +297,27 @@ class FiuaiSDK(object):
|
|
|
298
297
|
res = self.client.get(self.url + '/api/v2/internal/doctype/get', params=d, headers=headers)
|
|
299
298
|
return self.post_process(res)
|
|
300
299
|
|
|
300
|
+
def get_decrypted_password(
|
|
301
|
+
self,
|
|
302
|
+
doctype: str,
|
|
303
|
+
name: str,
|
|
304
|
+
fieldname: str = "password",
|
|
305
|
+
extra_headers: Optional[Dict[str, Any]] = None,
|
|
306
|
+
) -> Optional[str]:
|
|
307
|
+
"""从 Frappe __Auth 读取 Password 类型字段明文 (internal get_password)."""
|
|
308
|
+
params = {"doctype": doctype, "name": name, "fieldname": fieldname}
|
|
309
|
+
headers = self._get_merged_headers(extra_headers)
|
|
310
|
+
res = self.client.get(
|
|
311
|
+
self.url + "/api/v2/internal/doctype/get_password",
|
|
312
|
+
params=params,
|
|
313
|
+
headers=headers,
|
|
314
|
+
)
|
|
315
|
+
resp = self.post_process(res)
|
|
316
|
+
if resp.is_success() and resp.data and isinstance(resp.data, dict):
|
|
317
|
+
pw = resp.data.get("password")
|
|
318
|
+
return pw if isinstance(pw, str) else None
|
|
319
|
+
return None
|
|
320
|
+
|
|
301
321
|
def internal_get_list(self, doctype, filters=None, fields=None, limit_start=0, limit_page_length=20, order_by=None,
|
|
302
322
|
extra_headers: Optional[Dict[str, Any]] = None) -> ApiResponse:
|
|
303
323
|
d = {
|
|
@@ -14,9 +14,70 @@
|
|
|
14
14
|
# Copyright (c) 2025 FiuAI
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
from pydantic import BaseModel, Field
|
|
18
|
-
from typing import List, Literal
|
|
17
|
+
from pydantic import BaseModel, Field, field_validator, model_validator
|
|
18
|
+
from typing import List, Literal, Optional, Self
|
|
19
19
|
from .utils.text import safe_string_name
|
|
20
|
+
from enum import StrEnum
|
|
21
|
+
|
|
22
|
+
class TaxPayerType(StrEnum):
|
|
23
|
+
GeneralTaxPayer = "general_tax_payer"
|
|
24
|
+
SmallTaxPayer = "small_tax_payer"
|
|
25
|
+
OtherTaxPayer = "other_tax_payer"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
PROVINCE_CODE = {
|
|
29
|
+
"China": [
|
|
30
|
+
["1100", "北京市"],
|
|
31
|
+
["1200", "天津市"],
|
|
32
|
+
["1300", "河北省"],
|
|
33
|
+
["1400", "山西省"],
|
|
34
|
+
["1500", "内蒙古自治区"],
|
|
35
|
+
["2100", "辽宁省"],
|
|
36
|
+
["2200", "吉林省"],
|
|
37
|
+
["2300", "黑龙江省"],
|
|
38
|
+
["3100", "上海市"],
|
|
39
|
+
["3200", "江苏省"],
|
|
40
|
+
["3300", "浙江省"],
|
|
41
|
+
["3400", "安徽省"],
|
|
42
|
+
["3500", "福建省"],
|
|
43
|
+
["3600", "江西省"],
|
|
44
|
+
["3700", "山东省"],
|
|
45
|
+
["4100", "河南省"],
|
|
46
|
+
["4200", "湖北省"],
|
|
47
|
+
["4300", "湖南省"],
|
|
48
|
+
["4400", "广东省"],
|
|
49
|
+
["4500", "广西壮族自治区"],
|
|
50
|
+
["4600", "海南省"],
|
|
51
|
+
["5000", "重庆市"],
|
|
52
|
+
["5100", "四川省"],
|
|
53
|
+
["5200", "贵州省"],
|
|
54
|
+
["5300", "云南省"],
|
|
55
|
+
["5400", "西藏自治区"],
|
|
56
|
+
["6100", "陕西省"],
|
|
57
|
+
["6200", "甘肃省"],
|
|
58
|
+
["6300", "青海省"],
|
|
59
|
+
["6400", "宁夏回族自治区"],
|
|
60
|
+
["6500", "新疆维吾尔自治区"],
|
|
61
|
+
["7100", "台湾省"],
|
|
62
|
+
["8100", "香港特别行政区"],
|
|
63
|
+
["8200", "澳门特别行政区"],
|
|
64
|
+
],
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
_CHINA_PROVINCE_CODES: frozenset[str] = frozenset(
|
|
68
|
+
row[0] for row in PROVINCE_CODE["China"]
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _is_china_country_region(region: str) -> bool:
|
|
73
|
+
r = region.strip()
|
|
74
|
+
if not r:
|
|
75
|
+
return False
|
|
76
|
+
else:
|
|
77
|
+
if r.casefold() == "china":
|
|
78
|
+
return True
|
|
79
|
+
else:
|
|
80
|
+
return False
|
|
20
81
|
|
|
21
82
|
|
|
22
83
|
class UserCompanyInfo(BaseModel):
|
|
@@ -85,8 +146,59 @@ class UserCurrentCompanyInfo(BaseModel):
|
|
|
85
146
|
default_currency: str = Field(description="货币")
|
|
86
147
|
company_size: str = Field(description="公司规模")
|
|
87
148
|
entity_type: Literal["Enterprise", "Individual", "Other"] = Field(description="公司类型")
|
|
149
|
+
tax_payer_type: Optional[TaxPayerType] = Field(default=None, description="纳税人类型,一般纳税人,小规模纳税人,其他")
|
|
150
|
+
tax_source_location: Optional[str] = Field(default=None, description="税务登记地,中国特有配置,按省级行政区划分,比如江苏是3200")
|
|
88
151
|
company_profile: str = Field(description="公司业务特点提示词", default="")
|
|
89
|
-
|
|
152
|
+
|
|
153
|
+
@field_validator("tax_payer_type", mode="before")
|
|
154
|
+
@classmethod
|
|
155
|
+
def validate_tax_payer_type_when_present(cls, value: object) -> TaxPayerType | None:
|
|
156
|
+
if value is None or value == "":
|
|
157
|
+
return None
|
|
158
|
+
if isinstance(value, TaxPayerType):
|
|
159
|
+
return value
|
|
160
|
+
if isinstance(value, str):
|
|
161
|
+
try:
|
|
162
|
+
return TaxPayerType(value)
|
|
163
|
+
except ValueError:
|
|
164
|
+
allowed = ", ".join(repr(m.value) for m in TaxPayerType)
|
|
165
|
+
raise ValueError(
|
|
166
|
+
f"tax_payer_type must be one of [{allowed}], got {value!r}"
|
|
167
|
+
) from None
|
|
168
|
+
raise TypeError(
|
|
169
|
+
f"tax_payer_type must be str, TaxPayerType or None, got {type(value).__name__}"
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
@field_validator("tax_source_location", mode="before")
|
|
173
|
+
@classmethod
|
|
174
|
+
def normalize_tax_source_location(cls, value: object) -> str | None:
|
|
175
|
+
if value is None:
|
|
176
|
+
return None
|
|
177
|
+
if not isinstance(value, str):
|
|
178
|
+
raise TypeError(
|
|
179
|
+
"tax_source_location must be str or None, "
|
|
180
|
+
f"got {type(value).__name__}"
|
|
181
|
+
)
|
|
182
|
+
stripped = value.strip()
|
|
183
|
+
return None if stripped == "" else stripped
|
|
184
|
+
|
|
185
|
+
@model_validator(mode="after")
|
|
186
|
+
def validate_tax_source_location_against_china_provinces(self) -> Self:
|
|
187
|
+
loc = self.tax_source_location
|
|
188
|
+
china = _is_china_country_region(self.country_region)
|
|
189
|
+
|
|
190
|
+
if loc is not None and not china:
|
|
191
|
+
raise ValueError(
|
|
192
|
+
"tax_source_location is only applicable when country_region is China, CN or 中国"
|
|
193
|
+
)
|
|
194
|
+
if loc is not None and china and loc not in _CHINA_PROVINCE_CODES:
|
|
195
|
+
raise ValueError(
|
|
196
|
+
"tax_source_location must be a valid China province admin code "
|
|
197
|
+
f"(e.g. 3200 for Jiangsu), got {loc!r}"
|
|
198
|
+
)
|
|
199
|
+
return self
|
|
200
|
+
|
|
201
|
+
|
|
90
202
|
class UserProfileInfo(BaseModel):
|
|
91
203
|
user_base_info: UserBaseInfo = Field(description="用户基础信息")
|
|
92
204
|
user_permissions: UserPermissionInfo = Field(description="用户权限")
|
|
@@ -123,6 +235,8 @@ class UserProfileInfo(BaseModel):
|
|
|
123
235
|
default_currency=self.user_current_company_info.default_currency,
|
|
124
236
|
company_size=self.user_current_company_info.company_size,
|
|
125
237
|
entity_type=self.user_current_company_info.entity_type,
|
|
238
|
+
tax_payer_type=self.user_current_company_info.tax_payer_type,
|
|
239
|
+
tax_source_location=self.user_current_company_info.tax_source_location,
|
|
126
240
|
company_profile=self.user_current_company_info.company_profile,
|
|
127
241
|
),
|
|
128
242
|
)
|
|
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
|
{fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/pkg/cache/__init__.py
RENAMED
|
File without changes
|
{fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/pkg/cache/cache_client.py
RENAMED
|
File without changes
|
{fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/pkg/cache/circuit_breaker.py
RENAMED
|
File without changes
|
{fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/pkg/cache/decorator.py
RENAMED
|
File without changes
|
{fiuai_sdk_python-0.8.5 → fiuai_sdk_python-0.8.7}/src/fiuai_sdk_python/pkg/cache/redis_manager.py
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
|