modelscope-api 0.0.4__tar.gz → 0.0.5__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.
Files changed (48) hide show
  1. {modelscope_api-0.0.4/src/modelscope_api.egg-info → modelscope_api-0.0.5}/PKG-INFO +1 -1
  2. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/pyproject.toml +1 -1
  3. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/models/modelscope_client.py +19 -1
  4. {modelscope_api-0.0.4 → modelscope_api-0.0.5/src/modelscope_api.egg-info}/PKG-INFO +1 -1
  5. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api.egg-info/SOURCES.txt +2 -1
  6. modelscope_api-0.0.5/tests/test_stream.py +125 -0
  7. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/LICENSE +0 -0
  8. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/README.md +0 -0
  9. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/setup.cfg +0 -0
  10. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/__init__.py +0 -0
  11. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/config.py +0 -0
  12. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/data_models/__init__.py +0 -0
  13. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/data_models/base.py +0 -0
  14. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/data_models/collection/__init__.py +0 -0
  15. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/data_models/collection/collection.py +0 -0
  16. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/data_models/collection/collection_item.py +0 -0
  17. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/data_models/magicube/__init__.py +0 -0
  18. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/data_models/magicube/magicube_blance.py +0 -0
  19. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/data_models/studio/__init__.py +0 -0
  20. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/data_models/studio/base_image.py +0 -0
  21. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/data_models/studio/environment_variable.py +0 -0
  22. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/data_models/studio/hardware.py +0 -0
  23. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/data_models/studio/logs.py +0 -0
  24. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/data_models/studio/sdk.py +0 -0
  25. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/data_models/studio/studio.py +0 -0
  26. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/data_models/user/__init__.py +0 -0
  27. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/data_models/user/user.py +0 -0
  28. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/exceptions.py +0 -0
  29. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/models/__init__.py +0 -0
  30. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/models/_sub_client.py +0 -0
  31. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/models/collection/__init__.py +0 -0
  32. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/models/collection/collection.py +0 -0
  33. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/models/collection/collection_client.py +0 -0
  34. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/models/collection/collection_item.py +0 -0
  35. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/models/collection/collection_item_client.py +0 -0
  36. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/models/magicube/__init__.py +0 -0
  37. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/models/magicube/magicube_client.py +0 -0
  38. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/models/studio/__init__.py +0 -0
  39. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/models/studio/environment_variable_client.py +0 -0
  40. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/models/studio/studio.py +0 -0
  41. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/models/studio/studio_client.py +0 -0
  42. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/models/user/__init__.py +0 -0
  43. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/models/user/user_client.py +0 -0
  44. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/utils/regex.py +0 -0
  45. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api/utils/typing.py +0 -0
  46. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api.egg-info/dependency_links.txt +0 -0
  47. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api.egg-info/requires.txt +0 -0
  48. {modelscope_api-0.0.4 → modelscope_api-0.0.5}/src/modelscope_api.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modelscope-api
3
- Version: 0.0.4
3
+ Version: 0.0.5
4
4
  Summary: A Python async SDK that wraps the ModelScope API into a clean, type-safe interface.
5
5
  Author-email: Jerry <wujr24@m.fudan.edu.cn>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "modelscope-api" # 包名,保持与项目仓库名一致
7
- version = "0.0.4" # 当前版本
7
+ version = "0.0.5" # 当前版本
8
8
  description = "A Python async SDK that wraps the ModelScope API into a clean, type-safe interface." # 简短描述
9
9
  readme = "README.md" # 自述文件,PyPI 会将其渲染为项目首页
10
10
  authors = [{name = "Jerry", email = "wujr24@m.fudan.edu.cn"}] # 作者信息
@@ -3,7 +3,7 @@
3
3
  """
4
4
 
5
5
  import json
6
- from typing import Any, Dict, List, Optional, Union
6
+ from typing import Any, AsyncContextManager, Dict, List, Optional, Union
7
7
 
8
8
  from fake_useragent import UserAgent
9
9
  import httpx
@@ -201,6 +201,24 @@ class ModelScopeClient:
201
201
  return response
202
202
 
203
203
 
204
+ def stream(self, **kwargs) -> AsyncContextManager[httpx.Response]:
205
+ """
206
+ 用该客户端发送流式请求。
207
+
208
+ 用法与 `httpx.AsyncClient.stream` 完全一致,区别在于发送前会通过
209
+ `self._get_kwargs` 合并本客户端初始化时的 `self._kwargs`(以及 API Token)。
210
+
211
+ 用法:
212
+ async with client.stream(method="GET", url=url) as response:
213
+ async for chunk in response.aiter_bytes():
214
+ ...
215
+
216
+ 注意:该方法不是协程,直接返回异步上下文管理器,使用时无需 `await`。
217
+ """
218
+ kwargs = self._get_kwargs(kwargs)
219
+ return self._http_client.stream(**kwargs)
220
+
221
+
204
222
  async def request_data(
205
223
  self,
206
224
  *,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modelscope-api
3
- Version: 0.0.4
3
+ Version: 0.0.5
4
4
  Summary: A Python async SDK that wraps the ModelScope API into a clean, type-safe interface.
5
5
  Author-email: Jerry <wujr24@m.fudan.edu.cn>
6
6
  License: MIT
@@ -42,4 +42,5 @@ src/modelscope_api/models/studio/studio_client.py
42
42
  src/modelscope_api/models/user/__init__.py
43
43
  src/modelscope_api/models/user/user_client.py
44
44
  src/modelscope_api/utils/regex.py
45
- src/modelscope_api/utils/typing.py
45
+ src/modelscope_api/utils/typing.py
46
+ tests/test_stream.py
@@ -0,0 +1,125 @@
1
+ """
2
+ `ModelScopeClient.stream` 的测试用例。
3
+
4
+ 通过 `httpx.MockTransport` 伪造网络请求,无需真实网络与 API Token。
5
+ """
6
+
7
+ import asyncio
8
+
9
+ import httpx
10
+
11
+ from modelscope_api import ModelScopeClient
12
+
13
+
14
+ def _run(coro):
15
+ return asyncio.run(coro)
16
+
17
+
18
+ def test_stream_merges_init_kwargs():
19
+ """
20
+ 初始化客户端时传入的 kwargs 应被合并进流式请求。
21
+ """
22
+ async def main():
23
+ received = {}
24
+
25
+ def handler(request: httpx.Request) -> httpx.Response:
26
+ received["headers"] = dict(request.headers)
27
+ received["url"] = str(request.url)
28
+ return httpx.Response(200, content=b"hello world")
29
+
30
+ transport = httpx.MockTransport(handler)
31
+ http_client = httpx.AsyncClient(transport=transport)
32
+
33
+ client = ModelScopeClient(
34
+ api_key="", # 避免读取环境变量中的 Token
35
+ http_client=http_client,
36
+ headers={
37
+ "user-agent": "test-agent", # 避免动态生成 UA
38
+ "X-Injected": "from-init",
39
+ },
40
+ )
41
+
42
+ async with client.stream(method="GET", url="https://example.com/echo") as response:
43
+ assert response.status_code == 200
44
+ chunks = [chunk async for chunk in response.aiter_bytes()]
45
+
46
+ assert b"".join(chunks) == b"hello world"
47
+ assert received["url"] == "https://example.com/echo"
48
+ assert received["headers"]["x-injected"] == "from-init"
49
+ assert received["headers"]["user-agent"] == "test-agent"
50
+
51
+ await http_client.aclose()
52
+
53
+ _run(main())
54
+
55
+
56
+ def test_stream_call_kwargs_override_init_kwargs():
57
+ """
58
+ 调用 stream 时传入的 kwargs 应覆盖初始化时的 kwargs。
59
+ """
60
+ async def main():
61
+ received = {}
62
+
63
+ def handler(request: httpx.Request) -> httpx.Response:
64
+ received["headers"] = dict(request.headers)
65
+ return httpx.Response(200, content=b"ok")
66
+
67
+ transport = httpx.MockTransport(handler)
68
+ http_client = httpx.AsyncClient(transport=transport)
69
+
70
+ client = ModelScopeClient(
71
+ api_key="",
72
+ http_client=http_client,
73
+ headers={"user-agent": "test-agent", "X-Test": "init"},
74
+ )
75
+
76
+ async with client.stream(
77
+ method="POST",
78
+ url="https://example.com/echo",
79
+ headers={"X-Test": "call"},
80
+ content=b"body",
81
+ ) as response:
82
+ await response.aread()
83
+
84
+ assert received["headers"]["x-test"] == "call"
85
+
86
+ await http_client.aclose()
87
+
88
+ _run(main())
89
+
90
+
91
+ def test_stream_injects_api_key():
92
+ """
93
+ 流式请求应携带 API Token 的 Authorization 头。
94
+ """
95
+ async def main():
96
+ received = {}
97
+
98
+ def handler(request: httpx.Request) -> httpx.Response:
99
+ received["headers"] = dict(request.headers)
100
+ return httpx.Response(200, content=b"ok")
101
+
102
+ transport = httpx.MockTransport(handler)
103
+ http_client = httpx.AsyncClient(transport=transport)
104
+
105
+ client = ModelScopeClient(
106
+ api_key="test-key",
107
+ http_client=http_client,
108
+ headers={"user-agent": "test-agent"},
109
+ )
110
+
111
+ async with client.stream(method="GET", url="https://example.com/echo") as response:
112
+ await response.aread()
113
+
114
+ assert received["headers"]["authorization"] == "Bearer test-key"
115
+
116
+ await http_client.aclose()
117
+
118
+ _run(main())
119
+
120
+
121
+ if __name__ == "__main__":
122
+ test_stream_merges_init_kwargs()
123
+ test_stream_call_kwargs_override_init_kwargs()
124
+ test_stream_injects_api_key()
125
+ print("All stream tests passed.")
File without changes
File without changes
File without changes