py-wisharetec 0.1.0__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.
- py_wisharetec-0.1.0/LICENSE +21 -0
- py_wisharetec-0.1.0/PKG-INFO +227 -0
- py_wisharetec-0.1.0/README.md +172 -0
- py_wisharetec-0.1.0/pyproject.toml +47 -0
- py_wisharetec-0.1.0/setup.cfg +4 -0
- py_wisharetec-0.1.0/src/py_wisharetec/__init__.py +2 -0
- py_wisharetec-0.1.0/src/py_wisharetec/saas/__init__.py +374 -0
- py_wisharetec-0.1.0/src/py_wisharetec/saas/utils.py +39 -0
- py_wisharetec-0.1.0/src/py_wisharetec.egg-info/PKG-INFO +227 -0
- py_wisharetec-0.1.0/src/py_wisharetec.egg-info/SOURCES.txt +11 -0
- py_wisharetec-0.1.0/src/py_wisharetec.egg-info/dependency_links.txt +1 -0
- py_wisharetec-0.1.0/src/py_wisharetec.egg-info/requires.txt +12 -0
- py_wisharetec-0.1.0/src/py_wisharetec.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 郭磊
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: py-wisharetec
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Wisharetec SaaS 系统的 Python 客户端库,提供同步和异步接口调用能力。
|
|
5
|
+
Author-email: Guolei <174000902@qq.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 郭磊
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://gitee.com/guolei19850528/py_wisharetec
|
|
29
|
+
Project-URL: Repository, https://gitee.com/guolei19850528/py_wisharetec.git
|
|
30
|
+
Keywords: wisharetec,python,client,api,wisharetec saas,saas
|
|
31
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
32
|
+
Classifier: Development Status :: 4 - Beta
|
|
33
|
+
Classifier: Intended Audience :: Developers
|
|
34
|
+
Classifier: Programming Language :: Python :: 3
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
39
|
+
Classifier: Operating System :: OS Independent
|
|
40
|
+
Requires-Python: >=3.10
|
|
41
|
+
Description-Content-Type: text/markdown
|
|
42
|
+
License-File: LICENSE
|
|
43
|
+
Requires-Dist: httpx>=0.27.0
|
|
44
|
+
Requires-Dist: pydantic>=2.0
|
|
45
|
+
Requires-Dist: jsonpath-ng>=1.5.3
|
|
46
|
+
Requires-Dist: jsonschema>=4.21.0
|
|
47
|
+
Requires-Dist: diskcache>=5.6.3
|
|
48
|
+
Requires-Dist: redis>=4.6.0
|
|
49
|
+
Provides-Extra: dev
|
|
50
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
51
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
52
|
+
Requires-Dist: setuptools>=61.0; extra == "dev"
|
|
53
|
+
Requires-Dist: twine>=4.0; extra == "dev"
|
|
54
|
+
Dynamic: license-file
|
|
55
|
+
|
|
56
|
+
# py_wisharetec
|
|
57
|
+
|
|
58
|
+
Wisharetec SaaS 系统的 Python 客户端库,提供同步和异步接口调用能力。
|
|
59
|
+
|
|
60
|
+
## 功能特性
|
|
61
|
+
|
|
62
|
+
- 同步/异步 HTTP 客户端支持
|
|
63
|
+
- 登录认证与令牌管理
|
|
64
|
+
- 令牌缓存机制(支持 diskcache 和 Redis)
|
|
65
|
+
- 请求封装与响应处理
|
|
66
|
+
- JSON 数据校验与查询工具
|
|
67
|
+
|
|
68
|
+
## 安装
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pip install py_wisharetec
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## 快速开始
|
|
75
|
+
|
|
76
|
+
### 同步模式
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from py_wisharetec.saas import Saas
|
|
80
|
+
|
|
81
|
+
# 初始化客户端
|
|
82
|
+
saas = Saas(
|
|
83
|
+
base_url="https://saas.wisharetec.com/",
|
|
84
|
+
account="your_account",
|
|
85
|
+
password="your_password"
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
# 登录并刷新令牌
|
|
89
|
+
saas.refresh_token()
|
|
90
|
+
|
|
91
|
+
# 发起请求
|
|
92
|
+
response = saas.request(
|
|
93
|
+
method="GET",
|
|
94
|
+
url="/api/your-endpoint"
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
print(response.json())
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### 异步模式
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
import asyncio
|
|
104
|
+
from py_wisharetec.saas import Saas
|
|
105
|
+
|
|
106
|
+
async def main():
|
|
107
|
+
# 初始化客户端
|
|
108
|
+
saas = Saas(
|
|
109
|
+
base_url="https://saas.wisharetec.com/",
|
|
110
|
+
account="your_account",
|
|
111
|
+
password="your_password"
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
# 异步登录并刷新令牌
|
|
115
|
+
await saas.async_refresh_token()
|
|
116
|
+
|
|
117
|
+
# 发起异步请求
|
|
118
|
+
response = await saas.async_request(
|
|
119
|
+
method="GET",
|
|
120
|
+
url="/api/your-endpoint"
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
print(response.json())
|
|
124
|
+
|
|
125
|
+
asyncio.run(main())
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## 配置选项
|
|
129
|
+
|
|
130
|
+
### 初始化参数
|
|
131
|
+
|
|
132
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
133
|
+
|------|------|--------|------|
|
|
134
|
+
| base_url | str | https://saas.wisharetec.com/ | SaaS 服务基础 URL |
|
|
135
|
+
| account | str | None | 账号 |
|
|
136
|
+
| password | str | None | 密码 |
|
|
137
|
+
| cache_config | dict | {} | 缓存配置 |
|
|
138
|
+
| client_kwargs | dict | {} | HTTP 客户端额外参数 |
|
|
139
|
+
|
|
140
|
+
### 缓存配置
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
cache_config = {
|
|
144
|
+
"instance": None, # diskcache.Cache 或 redis.Redis 实例
|
|
145
|
+
"key": "py_wisharetec_saas_{account}", # 缓存键名
|
|
146
|
+
"expire": 7100 # 过期时间(秒)
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 客户端配置
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
client_kwargs = {
|
|
154
|
+
"timeout": 60, # 请求超时时间
|
|
155
|
+
"verify": False, # 是否验证 SSL 证书
|
|
156
|
+
"headers": {
|
|
157
|
+
"client": "co-pc"
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## API 参考
|
|
163
|
+
|
|
164
|
+
### Saas 类
|
|
165
|
+
|
|
166
|
+
#### 同步方法
|
|
167
|
+
|
|
168
|
+
- `client()` - 创建同步 HTTP 客户端
|
|
169
|
+
- `login(**kwargs)` - 登录系统
|
|
170
|
+
- `refresh_token(**kwargs)` - 刷新令牌
|
|
171
|
+
- `request(**kwargs)` - 发起请求
|
|
172
|
+
- `query_space_manage_tree(**kwargs)` - 查询空间管理树
|
|
173
|
+
|
|
174
|
+
#### 异步方法
|
|
175
|
+
|
|
176
|
+
- `async_client()` - 创建异步 HTTP 客户端
|
|
177
|
+
- `async_login(**kwargs)` - 异步登录系统
|
|
178
|
+
- `async_refresh_token(**kwargs)` - 异步刷新令牌
|
|
179
|
+
- `async_request(**kwargs)` - 发起异步请求
|
|
180
|
+
- `async_query_space_manage_tree(**kwargs)` - 异步查询空间管理树
|
|
181
|
+
|
|
182
|
+
### 工具函数
|
|
183
|
+
|
|
184
|
+
- `json_find_first(expression, data)` - 使用 JSONPath 查找第一个匹配项
|
|
185
|
+
- `json_is_valid(schema, data)` - 校验 JSON 数据是否符合 Schema
|
|
186
|
+
|
|
187
|
+
## 示例
|
|
188
|
+
|
|
189
|
+
### 使用缓存
|
|
190
|
+
|
|
191
|
+
```python
|
|
192
|
+
import diskcache
|
|
193
|
+
from py_wisharetec.saas import Saas
|
|
194
|
+
|
|
195
|
+
# 创建缓存实例
|
|
196
|
+
cache = diskcache.Cache("./cache")
|
|
197
|
+
|
|
198
|
+
# 初始化客户端(带缓存)
|
|
199
|
+
saas = Saas(
|
|
200
|
+
account="your_account",
|
|
201
|
+
password="your_password",
|
|
202
|
+
cache_config={
|
|
203
|
+
"instance": cache,
|
|
204
|
+
"expire": 7200
|
|
205
|
+
}
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
# 登录(自动使用缓存)
|
|
209
|
+
saas.refresh_token()
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## 依赖
|
|
213
|
+
|
|
214
|
+
- httpx >= 0.27.0
|
|
215
|
+
- pydantic >= 2.0.0
|
|
216
|
+
- diskcache >= 5.0.0 (可选)
|
|
217
|
+
- redis >= 5.0.0 (可选)
|
|
218
|
+
- jsonpath-ng >= 1.6.0
|
|
219
|
+
- jsonschema >= 4.0.0
|
|
220
|
+
|
|
221
|
+
## 主页
|
|
222
|
+
|
|
223
|
+
[https://gitee.com/guolei19850528/py_wisharetec](https://gitee.com/guolei19850528/py_wisharetec)
|
|
224
|
+
|
|
225
|
+
## 许可证
|
|
226
|
+
|
|
227
|
+
MIT License
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# py_wisharetec
|
|
2
|
+
|
|
3
|
+
Wisharetec SaaS 系统的 Python 客户端库,提供同步和异步接口调用能力。
|
|
4
|
+
|
|
5
|
+
## 功能特性
|
|
6
|
+
|
|
7
|
+
- 同步/异步 HTTP 客户端支持
|
|
8
|
+
- 登录认证与令牌管理
|
|
9
|
+
- 令牌缓存机制(支持 diskcache 和 Redis)
|
|
10
|
+
- 请求封装与响应处理
|
|
11
|
+
- JSON 数据校验与查询工具
|
|
12
|
+
|
|
13
|
+
## 安装
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install py_wisharetec
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## 快速开始
|
|
20
|
+
|
|
21
|
+
### 同步模式
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
from py_wisharetec.saas import Saas
|
|
25
|
+
|
|
26
|
+
# 初始化客户端
|
|
27
|
+
saas = Saas(
|
|
28
|
+
base_url="https://saas.wisharetec.com/",
|
|
29
|
+
account="your_account",
|
|
30
|
+
password="your_password"
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
# 登录并刷新令牌
|
|
34
|
+
saas.refresh_token()
|
|
35
|
+
|
|
36
|
+
# 发起请求
|
|
37
|
+
response = saas.request(
|
|
38
|
+
method="GET",
|
|
39
|
+
url="/api/your-endpoint"
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
print(response.json())
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 异步模式
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
import asyncio
|
|
49
|
+
from py_wisharetec.saas import Saas
|
|
50
|
+
|
|
51
|
+
async def main():
|
|
52
|
+
# 初始化客户端
|
|
53
|
+
saas = Saas(
|
|
54
|
+
base_url="https://saas.wisharetec.com/",
|
|
55
|
+
account="your_account",
|
|
56
|
+
password="your_password"
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# 异步登录并刷新令牌
|
|
60
|
+
await saas.async_refresh_token()
|
|
61
|
+
|
|
62
|
+
# 发起异步请求
|
|
63
|
+
response = await saas.async_request(
|
|
64
|
+
method="GET",
|
|
65
|
+
url="/api/your-endpoint"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
print(response.json())
|
|
69
|
+
|
|
70
|
+
asyncio.run(main())
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## 配置选项
|
|
74
|
+
|
|
75
|
+
### 初始化参数
|
|
76
|
+
|
|
77
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
78
|
+
|------|------|--------|------|
|
|
79
|
+
| base_url | str | https://saas.wisharetec.com/ | SaaS 服务基础 URL |
|
|
80
|
+
| account | str | None | 账号 |
|
|
81
|
+
| password | str | None | 密码 |
|
|
82
|
+
| cache_config | dict | {} | 缓存配置 |
|
|
83
|
+
| client_kwargs | dict | {} | HTTP 客户端额外参数 |
|
|
84
|
+
|
|
85
|
+
### 缓存配置
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
cache_config = {
|
|
89
|
+
"instance": None, # diskcache.Cache 或 redis.Redis 实例
|
|
90
|
+
"key": "py_wisharetec_saas_{account}", # 缓存键名
|
|
91
|
+
"expire": 7100 # 过期时间(秒)
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 客户端配置
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
client_kwargs = {
|
|
99
|
+
"timeout": 60, # 请求超时时间
|
|
100
|
+
"verify": False, # 是否验证 SSL 证书
|
|
101
|
+
"headers": {
|
|
102
|
+
"client": "co-pc"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## API 参考
|
|
108
|
+
|
|
109
|
+
### Saas 类
|
|
110
|
+
|
|
111
|
+
#### 同步方法
|
|
112
|
+
|
|
113
|
+
- `client()` - 创建同步 HTTP 客户端
|
|
114
|
+
- `login(**kwargs)` - 登录系统
|
|
115
|
+
- `refresh_token(**kwargs)` - 刷新令牌
|
|
116
|
+
- `request(**kwargs)` - 发起请求
|
|
117
|
+
- `query_space_manage_tree(**kwargs)` - 查询空间管理树
|
|
118
|
+
|
|
119
|
+
#### 异步方法
|
|
120
|
+
|
|
121
|
+
- `async_client()` - 创建异步 HTTP 客户端
|
|
122
|
+
- `async_login(**kwargs)` - 异步登录系统
|
|
123
|
+
- `async_refresh_token(**kwargs)` - 异步刷新令牌
|
|
124
|
+
- `async_request(**kwargs)` - 发起异步请求
|
|
125
|
+
- `async_query_space_manage_tree(**kwargs)` - 异步查询空间管理树
|
|
126
|
+
|
|
127
|
+
### 工具函数
|
|
128
|
+
|
|
129
|
+
- `json_find_first(expression, data)` - 使用 JSONPath 查找第一个匹配项
|
|
130
|
+
- `json_is_valid(schema, data)` - 校验 JSON 数据是否符合 Schema
|
|
131
|
+
|
|
132
|
+
## 示例
|
|
133
|
+
|
|
134
|
+
### 使用缓存
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
import diskcache
|
|
138
|
+
from py_wisharetec.saas import Saas
|
|
139
|
+
|
|
140
|
+
# 创建缓存实例
|
|
141
|
+
cache = diskcache.Cache("./cache")
|
|
142
|
+
|
|
143
|
+
# 初始化客户端(带缓存)
|
|
144
|
+
saas = Saas(
|
|
145
|
+
account="your_account",
|
|
146
|
+
password="your_password",
|
|
147
|
+
cache_config={
|
|
148
|
+
"instance": cache,
|
|
149
|
+
"expire": 7200
|
|
150
|
+
}
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
# 登录(自动使用缓存)
|
|
154
|
+
saas.refresh_token()
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## 依赖
|
|
158
|
+
|
|
159
|
+
- httpx >= 0.27.0
|
|
160
|
+
- pydantic >= 2.0.0
|
|
161
|
+
- diskcache >= 5.0.0 (可选)
|
|
162
|
+
- redis >= 5.0.0 (可选)
|
|
163
|
+
- jsonpath-ng >= 1.6.0
|
|
164
|
+
- jsonschema >= 4.0.0
|
|
165
|
+
|
|
166
|
+
## 主页
|
|
167
|
+
|
|
168
|
+
[https://gitee.com/guolei19850528/py_wisharetec](https://gitee.com/guolei19850528/py_wisharetec)
|
|
169
|
+
|
|
170
|
+
## 许可证
|
|
171
|
+
|
|
172
|
+
MIT License
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
[project]
|
|
5
|
+
name = "py-wisharetec"
|
|
6
|
+
version = "0.1.0"
|
|
7
|
+
requires-python = ">=3.10"
|
|
8
|
+
authors = [
|
|
9
|
+
{ name = "Guolei", email = "174000902@qq.com" }
|
|
10
|
+
]
|
|
11
|
+
description = "Wisharetec SaaS 系统的 Python 客户端库,提供同步和异步接口调用能力。"
|
|
12
|
+
keywords = ["wisharetec", "python", "client", "api", "wisharetec saas", "saas"]
|
|
13
|
+
license = { file = "LICENSE" }
|
|
14
|
+
readme = "README.md"
|
|
15
|
+
classifiers = [
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.10",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Programming Language :: Python :: 3.13",
|
|
24
|
+
"Operating System :: OS Independent",
|
|
25
|
+
]
|
|
26
|
+
dependencies = [
|
|
27
|
+
"httpx>=0.27.0",
|
|
28
|
+
"pydantic>=2.0",
|
|
29
|
+
"jsonpath-ng>=1.5.3",
|
|
30
|
+
"jsonschema>=4.21.0",
|
|
31
|
+
"diskcache>=5.6.3",
|
|
32
|
+
"redis>=4.6.0",
|
|
33
|
+
]
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
dev = [
|
|
36
|
+
"pytest>=7.0",
|
|
37
|
+
"pytest-cov>=4.0",
|
|
38
|
+
"setuptools>=61.0",
|
|
39
|
+
"twine>=4.0",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[project.urls]
|
|
43
|
+
"Homepage" = "https://gitee.com/guolei19850528/py_wisharetec"
|
|
44
|
+
"Repository" = "https://gitee.com/guolei19850528/py_wisharetec.git"
|
|
45
|
+
|
|
46
|
+
[tool.setuptools.packages.find]
|
|
47
|
+
where = ["src"]
|
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: UTF-8 -*-
|
|
3
|
+
import hashlib
|
|
4
|
+
from typing import Optional, Union
|
|
5
|
+
|
|
6
|
+
import diskcache
|
|
7
|
+
import httpx
|
|
8
|
+
import redis
|
|
9
|
+
from pydantic import HttpUrl
|
|
10
|
+
|
|
11
|
+
from py_wisharetec.saas.utils import json_is_valid
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Saas:
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
base_url: Optional[HttpUrl] = "https://saas.wisharetec.com/",
|
|
18
|
+
account: Optional[str] = None,
|
|
19
|
+
password: Optional[str] = None,
|
|
20
|
+
cache_config: Optional[dict] = None,
|
|
21
|
+
client_kwargs: Optional[dict] = None
|
|
22
|
+
):
|
|
23
|
+
self.base_url = base_url or "https://saas.wisharetec.com/"
|
|
24
|
+
self.base_url = self.base_url[:-1] if self.base_url.endswith("/") else self.base_url
|
|
25
|
+
|
|
26
|
+
# 处理账号密码
|
|
27
|
+
self.account = account or ""
|
|
28
|
+
self.password = password or ""
|
|
29
|
+
self.cache_config = cache_config or {}
|
|
30
|
+
self.cache_config = {
|
|
31
|
+
**{
|
|
32
|
+
"instance": None,
|
|
33
|
+
"key": f"py_wisharetec_saas_{self.account}",
|
|
34
|
+
"expire": 7100,
|
|
35
|
+
},
|
|
36
|
+
**self.cache_config,
|
|
37
|
+
}
|
|
38
|
+
self.client_kwargs = client_kwargs or {}
|
|
39
|
+
self.client_kwargs = {
|
|
40
|
+
**{
|
|
41
|
+
"base_url": self.base_url,
|
|
42
|
+
"timeout": 60,
|
|
43
|
+
"verify": False,
|
|
44
|
+
"headers": {
|
|
45
|
+
"client": "co-pc"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
**self.client_kwargs,
|
|
49
|
+
}
|
|
50
|
+
self.token = ""
|
|
51
|
+
|
|
52
|
+
def client(self) -> httpx.Client:
|
|
53
|
+
"""
|
|
54
|
+
创建并返回同步HTTP客户端
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
httpx.Client: 配置好的同步HTTP客户端实例
|
|
58
|
+
"""
|
|
59
|
+
return httpx.Client(**self.client_kwargs)
|
|
60
|
+
|
|
61
|
+
def async_client(self) -> httpx.AsyncClient:
|
|
62
|
+
"""
|
|
63
|
+
创建并返回异步HTTP客户端
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
httpx.AsyncClient: 配置好的异步HTTP客户端实例
|
|
67
|
+
"""
|
|
68
|
+
return httpx.AsyncClient(**self.client_kwargs)
|
|
69
|
+
|
|
70
|
+
def query_space_manage_tree(self, client: Optional[httpx.Client] = None, **kwargs) -> httpx.Response:
|
|
71
|
+
"""
|
|
72
|
+
查询空间管理树
|
|
73
|
+
|
|
74
|
+
:param client: 可选的同步客户端实例
|
|
75
|
+
:param **kwargs: 传递给request的额外参数
|
|
76
|
+
:return: httpx.Response - HTTP响应对象
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
kwargs = kwargs or {}
|
|
80
|
+
kwargs = {
|
|
81
|
+
**{
|
|
82
|
+
"method": "GET",
|
|
83
|
+
"url": "/api/space/space/manageTree",
|
|
84
|
+
"headers": {
|
|
85
|
+
"client": "co-pc",
|
|
86
|
+
"authorization": self.token,
|
|
87
|
+
},
|
|
88
|
+
"json": {
|
|
89
|
+
"account": self.account,
|
|
90
|
+
"password": hashlib.md5(self.password.encode("utf-8")).hexdigest(),
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
**kwargs,
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
# 发送请求
|
|
97
|
+
if isinstance(client, httpx.Client):
|
|
98
|
+
response = client.request(**kwargs)
|
|
99
|
+
else:
|
|
100
|
+
with self.client() as _client:
|
|
101
|
+
response = _client.request(**kwargs)
|
|
102
|
+
return response
|
|
103
|
+
|
|
104
|
+
def login(self, client: Optional[httpx.Client] = None, **kwargs) -> httpx.Response:
|
|
105
|
+
"""
|
|
106
|
+
登录 SaaS 系统
|
|
107
|
+
|
|
108
|
+
:param client: 可选的同步客户端实例
|
|
109
|
+
:param kwargs: 传递给request的额外参数
|
|
110
|
+
:return: httpx.Response - HTTP响应对象
|
|
111
|
+
"""
|
|
112
|
+
kwargs = kwargs or {}
|
|
113
|
+
kwargs = {
|
|
114
|
+
**{
|
|
115
|
+
"method": "POST",
|
|
116
|
+
"url": "/api/user/loginInteractive",
|
|
117
|
+
"headers": {
|
|
118
|
+
"client": "co-pc"
|
|
119
|
+
},
|
|
120
|
+
"json": {
|
|
121
|
+
"account": self.account,
|
|
122
|
+
"password": hashlib.md5(self.password.encode("utf-8")).hexdigest(),
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
**kwargs,
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
# 发送请求
|
|
129
|
+
if isinstance(client, httpx.Client):
|
|
130
|
+
response = client.request(**kwargs)
|
|
131
|
+
else:
|
|
132
|
+
with self.client() as _client:
|
|
133
|
+
response = _client.request(**kwargs)
|
|
134
|
+
|
|
135
|
+
if response.is_success:
|
|
136
|
+
if json_is_valid(
|
|
137
|
+
schema={
|
|
138
|
+
"type": "object",
|
|
139
|
+
"properties": {
|
|
140
|
+
# "tenantSimpleInfoVList": {"type": "array", "minItems": 1},
|
|
141
|
+
"userLoginV": {
|
|
142
|
+
"type": "object",
|
|
143
|
+
"properties": {
|
|
144
|
+
"userInfoV": {
|
|
145
|
+
"type": "object",
|
|
146
|
+
"properties": {
|
|
147
|
+
"id": {"type": "string", "minLength": 1}
|
|
148
|
+
},
|
|
149
|
+
"required": ["id"]
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
"required": ["userInfoV"]
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
"required": ["userLoginV"],
|
|
156
|
+
},
|
|
157
|
+
data=response.json(),
|
|
158
|
+
):
|
|
159
|
+
self.token = response.headers.get("authorization", "")
|
|
160
|
+
else:
|
|
161
|
+
self.token = ""
|
|
162
|
+
|
|
163
|
+
return response
|
|
164
|
+
|
|
165
|
+
def refresh_token(
|
|
166
|
+
self,
|
|
167
|
+
login_func_kwargs: Optional[dict] = None,
|
|
168
|
+
query_space_manage_tree_func_kwargs: Optional[dict] = None,
|
|
169
|
+
) -> "Saas":
|
|
170
|
+
login_func_kwargs = login_func_kwargs or {}
|
|
171
|
+
query_space_manage_tree_func_kwargs = query_space_manage_tree_func_kwargs or {}
|
|
172
|
+
cache_key = self.cache_config.get("key", f"py_wisharetec_saas_{self.account}")
|
|
173
|
+
cache_expire = self.cache_config.get("expire", 7100)
|
|
174
|
+
cache_instance = self.cache_config.get("instance", None)
|
|
175
|
+
if not isinstance(cache_instance, Union[diskcache.Cache, redis.Redis]):
|
|
176
|
+
self.login(**login_func_kwargs)
|
|
177
|
+
else:
|
|
178
|
+
self.token = cache_instance.get(cache_key)
|
|
179
|
+
if not isinstance(self.token, str) or not len(self.token):
|
|
180
|
+
self.login(**login_func_kwargs)
|
|
181
|
+
response_json = self.query_space_manage_tree(**query_space_manage_tree_func_kwargs).json()
|
|
182
|
+
if not json_is_valid(
|
|
183
|
+
schema={
|
|
184
|
+
"type": "array",
|
|
185
|
+
"minItems": 1,
|
|
186
|
+
},
|
|
187
|
+
data=response_json,
|
|
188
|
+
):
|
|
189
|
+
self.login(**login_func_kwargs)
|
|
190
|
+
if json_is_valid(
|
|
191
|
+
schema={
|
|
192
|
+
"type": "array",
|
|
193
|
+
"minItems": 1,
|
|
194
|
+
},
|
|
195
|
+
data=response_json,
|
|
196
|
+
):
|
|
197
|
+
if isinstance(cache_instance, diskcache.Cache):
|
|
198
|
+
cache_instance.set(cache_key, self.token, expire=cache_expire)
|
|
199
|
+
elif isinstance(cache_instance, redis.Redis):
|
|
200
|
+
cache_instance.set(cache_key, self.token, ex=cache_expire)
|
|
201
|
+
return self
|
|
202
|
+
|
|
203
|
+
def request(self, client: Optional[httpx.Client] = None, **kwargs) -> httpx.Response:
|
|
204
|
+
kwargs = kwargs or {}
|
|
205
|
+
kwargs = {
|
|
206
|
+
"headers": {
|
|
207
|
+
"client": "co-pc",
|
|
208
|
+
"authorization": self.token,
|
|
209
|
+
},
|
|
210
|
+
**kwargs,
|
|
211
|
+
}
|
|
212
|
+
if isinstance(client, httpx.Client):
|
|
213
|
+
response = client.request(**kwargs)
|
|
214
|
+
else:
|
|
215
|
+
with self.client() as _client:
|
|
216
|
+
response = _client.request(**kwargs)
|
|
217
|
+
return response
|
|
218
|
+
|
|
219
|
+
async def async_query_space_manage_tree(self, client: Optional[httpx.AsyncClient] = None,
|
|
220
|
+
**kwargs) -> httpx.Response:
|
|
221
|
+
"""
|
|
222
|
+
查询空间管理树
|
|
223
|
+
|
|
224
|
+
:param client: 可选的同步客户端实例
|
|
225
|
+
:param **kwargs: 传递给request的额外参数
|
|
226
|
+
:return: httpx.Response - HTTP响应对象
|
|
227
|
+
"""
|
|
228
|
+
|
|
229
|
+
kwargs = kwargs or {}
|
|
230
|
+
kwargs = {
|
|
231
|
+
**{
|
|
232
|
+
"method": "GET",
|
|
233
|
+
"url": "/api/space/space/manageTree",
|
|
234
|
+
"headers": {
|
|
235
|
+
"client": "co-pc",
|
|
236
|
+
"authorization": self.token,
|
|
237
|
+
},
|
|
238
|
+
"json": {
|
|
239
|
+
"account": self.account,
|
|
240
|
+
"password": hashlib.md5(self.password.encode("utf-8")).hexdigest(),
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
**kwargs,
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
# 发送请求
|
|
247
|
+
if isinstance(client, httpx.AsyncClient):
|
|
248
|
+
response = await client.request(**kwargs)
|
|
249
|
+
else:
|
|
250
|
+
async with self.async_client() as _client:
|
|
251
|
+
response = await _client.request(**kwargs)
|
|
252
|
+
return response
|
|
253
|
+
|
|
254
|
+
async def async_login(self, client: Optional[httpx.AsyncClient] = None, **kwargs) -> httpx.Response:
|
|
255
|
+
"""
|
|
256
|
+
登录 SaaS 系统
|
|
257
|
+
|
|
258
|
+
:param client: 可选的异步客户端实例
|
|
259
|
+
:param kwargs: 传递给request的额外参数
|
|
260
|
+
:return: httpx.Response - HTTP响应对象
|
|
261
|
+
"""
|
|
262
|
+
kwargs = kwargs or {}
|
|
263
|
+
kwargs = {
|
|
264
|
+
**{
|
|
265
|
+
"method": "POST",
|
|
266
|
+
"url": "/api/user/loginInteractive",
|
|
267
|
+
"headers": {
|
|
268
|
+
"client": "co-pc"
|
|
269
|
+
},
|
|
270
|
+
"json": {
|
|
271
|
+
"account": self.account,
|
|
272
|
+
"password": hashlib.md5(self.password.encode("utf-8")).hexdigest(),
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
**kwargs,
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
# 发送请求
|
|
279
|
+
if isinstance(client, httpx.AsyncClient):
|
|
280
|
+
response = await client.request(**kwargs)
|
|
281
|
+
else:
|
|
282
|
+
async with self.async_client() as _client:
|
|
283
|
+
response = await _client.request(**kwargs)
|
|
284
|
+
|
|
285
|
+
if response.is_success:
|
|
286
|
+
if json_is_valid(
|
|
287
|
+
schema={
|
|
288
|
+
"type": "object",
|
|
289
|
+
"properties": {
|
|
290
|
+
# "tenantSimpleInfoVList": {"type": "array", "minItems": 1},
|
|
291
|
+
"userLoginV": {
|
|
292
|
+
"type": "object",
|
|
293
|
+
"properties": {
|
|
294
|
+
"userInfoV": {
|
|
295
|
+
"type": "object",
|
|
296
|
+
"properties": {
|
|
297
|
+
"id": {"type": "string", "minLength": 1}
|
|
298
|
+
},
|
|
299
|
+
"required": ["id"]
|
|
300
|
+
},
|
|
301
|
+
},
|
|
302
|
+
"required": ["userInfoV"]
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
"required": ["userLoginV"],
|
|
306
|
+
},
|
|
307
|
+
data=response.json(),
|
|
308
|
+
):
|
|
309
|
+
self.token = response.headers.get("authorization", "")
|
|
310
|
+
else:
|
|
311
|
+
self.token = ""
|
|
312
|
+
|
|
313
|
+
return response
|
|
314
|
+
|
|
315
|
+
async def async_refresh_token(
|
|
316
|
+
self,
|
|
317
|
+
login_func_kwargs: Optional[dict] = None,
|
|
318
|
+
query_space_manage_tree_func_kwargs: Optional[dict] = None,
|
|
319
|
+
) -> "Saas":
|
|
320
|
+
login_func_kwargs = login_func_kwargs or {}
|
|
321
|
+
query_space_manage_tree_func_kwargs = query_space_manage_tree_func_kwargs or {}
|
|
322
|
+
cache_key = self.cache_config.get("key", f"py_wisharetec_saas_{self.account}")
|
|
323
|
+
cache_expire = self.cache_config.get("expire", 7100)
|
|
324
|
+
cache_instance = self.cache_config.get("instance", None)
|
|
325
|
+
if not isinstance(cache_instance, Union[diskcache.Cache, redis.Redis]):
|
|
326
|
+
await self.async_login(**login_func_kwargs)
|
|
327
|
+
else:
|
|
328
|
+
self.token = cache_instance.get(cache_key)
|
|
329
|
+
if not isinstance(self.token, str) or not len(self.token):
|
|
330
|
+
await self.async_login(**login_func_kwargs)
|
|
331
|
+
response = await self.async_query_space_manage_tree(**query_space_manage_tree_func_kwargs)
|
|
332
|
+
if not json_is_valid(
|
|
333
|
+
schema={
|
|
334
|
+
"type": "object",
|
|
335
|
+
"properties": {
|
|
336
|
+
"children": {"type": "array", "minItems": 1},
|
|
337
|
+
},
|
|
338
|
+
"required": ["children"],
|
|
339
|
+
},
|
|
340
|
+
data=response.json(),
|
|
341
|
+
):
|
|
342
|
+
await self.async_login(**login_func_kwargs)
|
|
343
|
+
response = await self.async_query_space_manage_tree(**query_space_manage_tree_func_kwargs)
|
|
344
|
+
if json_is_valid(
|
|
345
|
+
schema={
|
|
346
|
+
"type": "object",
|
|
347
|
+
"properties": {
|
|
348
|
+
"children": {"type": "array", "minItems": 1},
|
|
349
|
+
},
|
|
350
|
+
"required": ["children"],
|
|
351
|
+
},
|
|
352
|
+
data=response.json(),
|
|
353
|
+
):
|
|
354
|
+
if isinstance(cache_instance, diskcache.Cache):
|
|
355
|
+
cache_instance.set(cache_key, self.token, expire=cache_expire)
|
|
356
|
+
elif isinstance(cache_instance, redis.Redis):
|
|
357
|
+
cache_instance.set(cache_key, self.token, ex=cache_expire)
|
|
358
|
+
return self
|
|
359
|
+
|
|
360
|
+
async def async_request(self, client: Optional[httpx.AsyncClient] = None, **kwargs) -> httpx.Response:
|
|
361
|
+
kwargs = kwargs or {}
|
|
362
|
+
kwargs = {
|
|
363
|
+
"headers": {
|
|
364
|
+
"client": "co-pc",
|
|
365
|
+
"authorization": self.token,
|
|
366
|
+
},
|
|
367
|
+
**kwargs,
|
|
368
|
+
}
|
|
369
|
+
if isinstance(client, httpx.AsyncClient):
|
|
370
|
+
response = await client.request(**kwargs)
|
|
371
|
+
else:
|
|
372
|
+
async with self.async_client() as _client:
|
|
373
|
+
response = await _client.request(**kwargs)
|
|
374
|
+
return response
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: UTF-8 -*-
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from typing import Any, Optional, Union
|
|
5
|
+
|
|
6
|
+
import httpx
|
|
7
|
+
from jsonpath_ng import parse
|
|
8
|
+
from jsonschema.validators import Draft202012Validator
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def json_find_first(expression: str, data: Any) -> Any:
|
|
12
|
+
"""
|
|
13
|
+
使用 JSONPath 表达式从数据中查找第一个匹配项
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
expression: JSONPath 表达式,用于指定要查找的数据路径
|
|
17
|
+
data: 待查询的 JSON 数据
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
Any: 第一个匹配的值,如果没有匹配项则返回 None
|
|
21
|
+
"""
|
|
22
|
+
results = [i.value for i in parse(expression).find(data)]
|
|
23
|
+
if isinstance(results, list) and len(results) > 0:
|
|
24
|
+
return results[0]
|
|
25
|
+
return None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def json_is_valid(schema: Optional[dict], data: Any) -> bool:
|
|
29
|
+
"""
|
|
30
|
+
校验 JSON 数据是否符合指定的 JSON Schema
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
schema: JSON Schema 字典
|
|
34
|
+
data: 待校验的 JSON 数据
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
bool: 校验是否成功
|
|
38
|
+
"""
|
|
39
|
+
return Draft202012Validator(schema).is_valid(data)
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: py-wisharetec
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Wisharetec SaaS 系统的 Python 客户端库,提供同步和异步接口调用能力。
|
|
5
|
+
Author-email: Guolei <174000902@qq.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 郭磊
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://gitee.com/guolei19850528/py_wisharetec
|
|
29
|
+
Project-URL: Repository, https://gitee.com/guolei19850528/py_wisharetec.git
|
|
30
|
+
Keywords: wisharetec,python,client,api,wisharetec saas,saas
|
|
31
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
32
|
+
Classifier: Development Status :: 4 - Beta
|
|
33
|
+
Classifier: Intended Audience :: Developers
|
|
34
|
+
Classifier: Programming Language :: Python :: 3
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
39
|
+
Classifier: Operating System :: OS Independent
|
|
40
|
+
Requires-Python: >=3.10
|
|
41
|
+
Description-Content-Type: text/markdown
|
|
42
|
+
License-File: LICENSE
|
|
43
|
+
Requires-Dist: httpx>=0.27.0
|
|
44
|
+
Requires-Dist: pydantic>=2.0
|
|
45
|
+
Requires-Dist: jsonpath-ng>=1.5.3
|
|
46
|
+
Requires-Dist: jsonschema>=4.21.0
|
|
47
|
+
Requires-Dist: diskcache>=5.6.3
|
|
48
|
+
Requires-Dist: redis>=4.6.0
|
|
49
|
+
Provides-Extra: dev
|
|
50
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
51
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
52
|
+
Requires-Dist: setuptools>=61.0; extra == "dev"
|
|
53
|
+
Requires-Dist: twine>=4.0; extra == "dev"
|
|
54
|
+
Dynamic: license-file
|
|
55
|
+
|
|
56
|
+
# py_wisharetec
|
|
57
|
+
|
|
58
|
+
Wisharetec SaaS 系统的 Python 客户端库,提供同步和异步接口调用能力。
|
|
59
|
+
|
|
60
|
+
## 功能特性
|
|
61
|
+
|
|
62
|
+
- 同步/异步 HTTP 客户端支持
|
|
63
|
+
- 登录认证与令牌管理
|
|
64
|
+
- 令牌缓存机制(支持 diskcache 和 Redis)
|
|
65
|
+
- 请求封装与响应处理
|
|
66
|
+
- JSON 数据校验与查询工具
|
|
67
|
+
|
|
68
|
+
## 安装
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pip install py_wisharetec
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## 快速开始
|
|
75
|
+
|
|
76
|
+
### 同步模式
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from py_wisharetec.saas import Saas
|
|
80
|
+
|
|
81
|
+
# 初始化客户端
|
|
82
|
+
saas = Saas(
|
|
83
|
+
base_url="https://saas.wisharetec.com/",
|
|
84
|
+
account="your_account",
|
|
85
|
+
password="your_password"
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
# 登录并刷新令牌
|
|
89
|
+
saas.refresh_token()
|
|
90
|
+
|
|
91
|
+
# 发起请求
|
|
92
|
+
response = saas.request(
|
|
93
|
+
method="GET",
|
|
94
|
+
url="/api/your-endpoint"
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
print(response.json())
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### 异步模式
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
import asyncio
|
|
104
|
+
from py_wisharetec.saas import Saas
|
|
105
|
+
|
|
106
|
+
async def main():
|
|
107
|
+
# 初始化客户端
|
|
108
|
+
saas = Saas(
|
|
109
|
+
base_url="https://saas.wisharetec.com/",
|
|
110
|
+
account="your_account",
|
|
111
|
+
password="your_password"
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
# 异步登录并刷新令牌
|
|
115
|
+
await saas.async_refresh_token()
|
|
116
|
+
|
|
117
|
+
# 发起异步请求
|
|
118
|
+
response = await saas.async_request(
|
|
119
|
+
method="GET",
|
|
120
|
+
url="/api/your-endpoint"
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
print(response.json())
|
|
124
|
+
|
|
125
|
+
asyncio.run(main())
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## 配置选项
|
|
129
|
+
|
|
130
|
+
### 初始化参数
|
|
131
|
+
|
|
132
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
133
|
+
|------|------|--------|------|
|
|
134
|
+
| base_url | str | https://saas.wisharetec.com/ | SaaS 服务基础 URL |
|
|
135
|
+
| account | str | None | 账号 |
|
|
136
|
+
| password | str | None | 密码 |
|
|
137
|
+
| cache_config | dict | {} | 缓存配置 |
|
|
138
|
+
| client_kwargs | dict | {} | HTTP 客户端额外参数 |
|
|
139
|
+
|
|
140
|
+
### 缓存配置
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
cache_config = {
|
|
144
|
+
"instance": None, # diskcache.Cache 或 redis.Redis 实例
|
|
145
|
+
"key": "py_wisharetec_saas_{account}", # 缓存键名
|
|
146
|
+
"expire": 7100 # 过期时间(秒)
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 客户端配置
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
client_kwargs = {
|
|
154
|
+
"timeout": 60, # 请求超时时间
|
|
155
|
+
"verify": False, # 是否验证 SSL 证书
|
|
156
|
+
"headers": {
|
|
157
|
+
"client": "co-pc"
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## API 参考
|
|
163
|
+
|
|
164
|
+
### Saas 类
|
|
165
|
+
|
|
166
|
+
#### 同步方法
|
|
167
|
+
|
|
168
|
+
- `client()` - 创建同步 HTTP 客户端
|
|
169
|
+
- `login(**kwargs)` - 登录系统
|
|
170
|
+
- `refresh_token(**kwargs)` - 刷新令牌
|
|
171
|
+
- `request(**kwargs)` - 发起请求
|
|
172
|
+
- `query_space_manage_tree(**kwargs)` - 查询空间管理树
|
|
173
|
+
|
|
174
|
+
#### 异步方法
|
|
175
|
+
|
|
176
|
+
- `async_client()` - 创建异步 HTTP 客户端
|
|
177
|
+
- `async_login(**kwargs)` - 异步登录系统
|
|
178
|
+
- `async_refresh_token(**kwargs)` - 异步刷新令牌
|
|
179
|
+
- `async_request(**kwargs)` - 发起异步请求
|
|
180
|
+
- `async_query_space_manage_tree(**kwargs)` - 异步查询空间管理树
|
|
181
|
+
|
|
182
|
+
### 工具函数
|
|
183
|
+
|
|
184
|
+
- `json_find_first(expression, data)` - 使用 JSONPath 查找第一个匹配项
|
|
185
|
+
- `json_is_valid(schema, data)` - 校验 JSON 数据是否符合 Schema
|
|
186
|
+
|
|
187
|
+
## 示例
|
|
188
|
+
|
|
189
|
+
### 使用缓存
|
|
190
|
+
|
|
191
|
+
```python
|
|
192
|
+
import diskcache
|
|
193
|
+
from py_wisharetec.saas import Saas
|
|
194
|
+
|
|
195
|
+
# 创建缓存实例
|
|
196
|
+
cache = diskcache.Cache("./cache")
|
|
197
|
+
|
|
198
|
+
# 初始化客户端(带缓存)
|
|
199
|
+
saas = Saas(
|
|
200
|
+
account="your_account",
|
|
201
|
+
password="your_password",
|
|
202
|
+
cache_config={
|
|
203
|
+
"instance": cache,
|
|
204
|
+
"expire": 7200
|
|
205
|
+
}
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
# 登录(自动使用缓存)
|
|
209
|
+
saas.refresh_token()
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## 依赖
|
|
213
|
+
|
|
214
|
+
- httpx >= 0.27.0
|
|
215
|
+
- pydantic >= 2.0.0
|
|
216
|
+
- diskcache >= 5.0.0 (可选)
|
|
217
|
+
- redis >= 5.0.0 (可选)
|
|
218
|
+
- jsonpath-ng >= 1.6.0
|
|
219
|
+
- jsonschema >= 4.0.0
|
|
220
|
+
|
|
221
|
+
## 主页
|
|
222
|
+
|
|
223
|
+
[https://gitee.com/guolei19850528/py_wisharetec](https://gitee.com/guolei19850528/py_wisharetec)
|
|
224
|
+
|
|
225
|
+
## 许可证
|
|
226
|
+
|
|
227
|
+
MIT License
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/py_wisharetec/__init__.py
|
|
5
|
+
src/py_wisharetec.egg-info/PKG-INFO
|
|
6
|
+
src/py_wisharetec.egg-info/SOURCES.txt
|
|
7
|
+
src/py_wisharetec.egg-info/dependency_links.txt
|
|
8
|
+
src/py_wisharetec.egg-info/requires.txt
|
|
9
|
+
src/py_wisharetec.egg-info/top_level.txt
|
|
10
|
+
src/py_wisharetec/saas/__init__.py
|
|
11
|
+
src/py_wisharetec/saas/utils.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
py_wisharetec
|