justoneapi 3.0.81__tar.gz → 3.0.83__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.
- {justoneapi-3.0.81/justoneapi.egg-info → justoneapi-3.0.83}/PKG-INFO +2 -1
- {justoneapi-3.0.81 → justoneapi-3.0.83}/README.md +1 -0
- justoneapi-3.0.83/justoneapi/_version.py +1 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/__init__.py +0 -6
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/xiaohongshu.py +23 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83/justoneapi.egg-info}/PKG-INFO +2 -1
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi.egg-info/SOURCES.txt +0 -2
- {justoneapi-3.0.81 → justoneapi-3.0.83}/tests/test_codegen.py +111 -0
- justoneapi-3.0.81/justoneapi/_version.py +0 -1
- justoneapi-3.0.81/justoneapi/generated/resources/pixabay.py +0 -39
- justoneapi-3.0.81/justoneapi/generated/resources/vcg.py +0 -48
- {justoneapi-3.0.81 → justoneapi-3.0.83}/LICENSE +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/MANIFEST.in +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/__init__.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/_exceptions.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/_resource.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/_response.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/_transport.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/client.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/config.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/__init__.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/models.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/aliexpress.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/amazon.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/beike.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/bilibili.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/dewu.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/douban.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/douyin.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/douyin_ec.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/douyin_xingtu.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/facebook.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/field_1688.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/imdb.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/instagram.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/jd.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/kuaishou.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/linkedin.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/llm.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/qq_huxuan.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/reddit.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/search.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/shopee.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/taobao.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/temu.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/tiktok.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/tiktok_shop.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/toutiao.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/twitter.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/weibo.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/weixin.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/weixin_channels.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/xianyu.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/xiaohongshu_ec.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/xiaohongshu_pgy.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/youku.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/youtube.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/zcool.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/generated/resources/zhihu.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi/log.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi.egg-info/dependency_links.txt +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi.egg-info/requires.txt +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/justoneapi.egg-info/top_level.txt +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/pyproject.toml +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/setup.cfg +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/tests/test_bump_version.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/tests/test_generated_surface.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/tests/test_integration_smoke.py +0 -0
- {justoneapi-3.0.81 → justoneapi-3.0.83}/tests/test_runtime.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: justoneapi
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.83
|
|
4
4
|
Summary: OpenAPI-driven Python SDK for Just One API
|
|
5
5
|
Author-email: Just One API <support@justoneapi.com>
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -175,6 +175,7 @@ except BusinessError as exc:
|
|
|
175
175
|
- [用户发布笔记 (V2)](https://docs.justoneapi.com/zh/api/xiaohongshu-rednote/user-published-notes-v2?utm_source=github.com&utm_medium=referral&utm_campaign=justoneapi_justoneapi_python&utm_content=repo_readme_api_list) <!-- api-operation:GET /api/xiaohongshu/get-user-note-list/v2 -->
|
|
176
176
|
- [用户发布笔记 (V3)](https://docs.justoneapi.com/zh/api/xiaohongshu-rednote/user-published-notes-v3?utm_source=github.com&utm_medium=referral&utm_campaign=justoneapi_justoneapi_python&utm_content=repo_readme_api_list) <!-- api-operation:GET /api/xiaohongshu/get-user-note-list/v3 -->
|
|
177
177
|
- [用户笔记 (V4)](https://docs.justoneapi.com/zh/api/xiaohongshu-rednote/user-notes-v4?utm_source=github.com&utm_medium=referral&utm_campaign=justoneapi_justoneapi_python&utm_content=repo_readme_api_list) <!-- api-operation:GET /api/xiaohongshu/get-user-note-list/v4 --> <sub>[JSON](https://github.com/justoneapi-official/justoneapi-python/blob/main/docs/api-examples/getApiXiaohongshuGetUserNoteListV4.json)</sub>
|
|
178
|
+
- [用户收藏的笔记 (V1)](https://docs.justoneapi.com/zh/api/xiaohongshu-rednote/user-favorited-notes-v1?utm_source=github.com&utm_medium=referral&utm_campaign=justoneapi_justoneapi_python&utm_content=repo_readme_api_list) <!-- api-operation:GET /api/xiaohongshu/get-user-faved-note-list/v1 -->
|
|
178
179
|
- [笔记详情 (V1)](https://docs.justoneapi.com/zh/api/xiaohongshu-rednote/note-details-v1?utm_source=github.com&utm_medium=referral&utm_campaign=justoneapi_justoneapi_python&utm_content=repo_readme_api_list) <!-- api-operation:GET /api/xiaohongshu/get-note-detail/v1 --> <sub>[JSON](https://github.com/justoneapi-official/justoneapi-python/blob/main/docs/api-examples/getApiXiaohongshuGetNoteDetailV1.json)</sub>
|
|
179
180
|
- [笔记详情 (V2)](https://docs.justoneapi.com/zh/api/xiaohongshu-rednote/note-details-v2?utm_source=github.com&utm_medium=referral&utm_campaign=justoneapi_justoneapi_python&utm_content=repo_readme_api_list) <!-- api-operation:GET /api/xiaohongshu/get-note-detail/v2 -->
|
|
180
181
|
- [笔记详情 (V3)](https://docs.justoneapi.com/zh/api/xiaohongshu-rednote/note-details-v3?utm_source=github.com&utm_medium=referral&utm_campaign=justoneapi_justoneapi_python&utm_content=repo_readme_api_list) <!-- api-operation:GET /api/xiaohongshu/get-note-detail/v3 -->
|
|
@@ -159,6 +159,7 @@ except BusinessError as exc:
|
|
|
159
159
|
- [用户发布笔记 (V2)](https://docs.justoneapi.com/zh/api/xiaohongshu-rednote/user-published-notes-v2?utm_source=github.com&utm_medium=referral&utm_campaign=justoneapi_justoneapi_python&utm_content=repo_readme_api_list) <!-- api-operation:GET /api/xiaohongshu/get-user-note-list/v2 -->
|
|
160
160
|
- [用户发布笔记 (V3)](https://docs.justoneapi.com/zh/api/xiaohongshu-rednote/user-published-notes-v3?utm_source=github.com&utm_medium=referral&utm_campaign=justoneapi_justoneapi_python&utm_content=repo_readme_api_list) <!-- api-operation:GET /api/xiaohongshu/get-user-note-list/v3 -->
|
|
161
161
|
- [用户笔记 (V4)](https://docs.justoneapi.com/zh/api/xiaohongshu-rednote/user-notes-v4?utm_source=github.com&utm_medium=referral&utm_campaign=justoneapi_justoneapi_python&utm_content=repo_readme_api_list) <!-- api-operation:GET /api/xiaohongshu/get-user-note-list/v4 --> <sub>[JSON](https://github.com/justoneapi-official/justoneapi-python/blob/main/docs/api-examples/getApiXiaohongshuGetUserNoteListV4.json)</sub>
|
|
162
|
+
- [用户收藏的笔记 (V1)](https://docs.justoneapi.com/zh/api/xiaohongshu-rednote/user-favorited-notes-v1?utm_source=github.com&utm_medium=referral&utm_campaign=justoneapi_justoneapi_python&utm_content=repo_readme_api_list) <!-- api-operation:GET /api/xiaohongshu/get-user-faved-note-list/v1 -->
|
|
162
163
|
- [笔记详情 (V1)](https://docs.justoneapi.com/zh/api/xiaohongshu-rednote/note-details-v1?utm_source=github.com&utm_medium=referral&utm_campaign=justoneapi_justoneapi_python&utm_content=repo_readme_api_list) <!-- api-operation:GET /api/xiaohongshu/get-note-detail/v1 --> <sub>[JSON](https://github.com/justoneapi-official/justoneapi-python/blob/main/docs/api-examples/getApiXiaohongshuGetNoteDetailV1.json)</sub>
|
|
163
164
|
- [笔记详情 (V2)](https://docs.justoneapi.com/zh/api/xiaohongshu-rednote/note-details-v2?utm_source=github.com&utm_medium=referral&utm_campaign=justoneapi_justoneapi_python&utm_content=repo_readme_api_list) <!-- api-operation:GET /api/xiaohongshu/get-note-detail/v2 -->
|
|
164
165
|
- [笔记详情 (V3)](https://docs.justoneapi.com/zh/api/xiaohongshu-rednote/note-details-v3?utm_source=github.com&utm_medium=referral&utm_campaign=justoneapi_justoneapi_python&utm_content=repo_readme_api_list) <!-- api-operation:GET /api/xiaohongshu/get-note-detail/v3 -->
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "3.0.83"
|
|
@@ -17,7 +17,6 @@ from justoneapi.generated.resources.jd import JdResource
|
|
|
17
17
|
from justoneapi.generated.resources.kuaishou import KuaishouResource
|
|
18
18
|
from justoneapi.generated.resources.linkedin import LinkedinResource
|
|
19
19
|
from justoneapi.generated.resources.llm import LlmResource
|
|
20
|
-
from justoneapi.generated.resources.pixabay import PixabayResource
|
|
21
20
|
from justoneapi.generated.resources.qq_huxuan import QqHuxuanResource
|
|
22
21
|
from justoneapi.generated.resources.reddit import RedditResource
|
|
23
22
|
from justoneapi.generated.resources.search import SearchResource
|
|
@@ -28,7 +27,6 @@ from justoneapi.generated.resources.tiktok import TiktokResource
|
|
|
28
27
|
from justoneapi.generated.resources.tiktok_shop import TiktokShopResource
|
|
29
28
|
from justoneapi.generated.resources.toutiao import ToutiaoResource
|
|
30
29
|
from justoneapi.generated.resources.twitter import TwitterResource
|
|
31
|
-
from justoneapi.generated.resources.vcg import VcgResource
|
|
32
30
|
from justoneapi.generated.resources.weibo import WeiboResource
|
|
33
31
|
from justoneapi.generated.resources.weixin import WeixinResource
|
|
34
32
|
from justoneapi.generated.resources.weixin_channels import WeixinChannelsResource
|
|
@@ -59,7 +57,6 @@ RESOURCE_CLASSES = {
|
|
|
59
57
|
"kuaishou": KuaishouResource,
|
|
60
58
|
"linkedin": LinkedinResource,
|
|
61
59
|
"llm": LlmResource,
|
|
62
|
-
"pixabay": PixabayResource,
|
|
63
60
|
"qq_huxuan": QqHuxuanResource,
|
|
64
61
|
"reddit": RedditResource,
|
|
65
62
|
"search": SearchResource,
|
|
@@ -70,7 +67,6 @@ RESOURCE_CLASSES = {
|
|
|
70
67
|
"tiktok_shop": TiktokShopResource,
|
|
71
68
|
"toutiao": ToutiaoResource,
|
|
72
69
|
"twitter": TwitterResource,
|
|
73
|
-
"vcg": VcgResource,
|
|
74
70
|
"weibo": WeiboResource,
|
|
75
71
|
"weixin": WeixinResource,
|
|
76
72
|
"weixin_channels": WeixinChannelsResource,
|
|
@@ -102,7 +98,6 @@ __all__ = [
|
|
|
102
98
|
"KuaishouResource",
|
|
103
99
|
"LinkedinResource",
|
|
104
100
|
"LlmResource",
|
|
105
|
-
"PixabayResource",
|
|
106
101
|
"QqHuxuanResource",
|
|
107
102
|
"RedditResource",
|
|
108
103
|
"SearchResource",
|
|
@@ -113,7 +108,6 @@ __all__ = [
|
|
|
113
108
|
"TiktokShopResource",
|
|
114
109
|
"ToutiaoResource",
|
|
115
110
|
"TwitterResource",
|
|
116
|
-
"VcgResource",
|
|
117
111
|
"WeiboResource",
|
|
118
112
|
"WeixinResource",
|
|
119
113
|
"WeixinChannelsResource",
|
|
@@ -337,6 +337,29 @@ class XiaohongshuResource(BaseResource):
|
|
|
337
337
|
},
|
|
338
338
|
)
|
|
339
339
|
|
|
340
|
+
def get_user_faved_note_list_v1(
|
|
341
|
+
self,
|
|
342
|
+
*,
|
|
343
|
+
user_id: str,
|
|
344
|
+
last_cursor: str | None = "",
|
|
345
|
+
) -> ApiResponse[Any]:
|
|
346
|
+
"""
|
|
347
|
+
User Favorited Notes
|
|
348
|
+
|
|
349
|
+
Retrieves a Xiaohongshu (RedNote) user's favorited notes by user ID with cursor pagination. Use it to review a user's saved content and research content interests.
|
|
350
|
+
|
|
351
|
+
Args:
|
|
352
|
+
user_id: Unique user identifier on Xiaohongshu.
|
|
353
|
+
last_cursor: For the next page, pass the cursor from the previous response. Omit or pass an empty value for the first page.
|
|
354
|
+
"""
|
|
355
|
+
return self._get(
|
|
356
|
+
"/api/xiaohongshu/get-user-faved-note-list/v1",
|
|
357
|
+
{
|
|
358
|
+
"userId": user_id,
|
|
359
|
+
"lastCursor": last_cursor,
|
|
360
|
+
},
|
|
361
|
+
)
|
|
362
|
+
|
|
340
363
|
def get_note_detail_v1(
|
|
341
364
|
self,
|
|
342
365
|
*,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: justoneapi
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.83
|
|
4
4
|
Summary: OpenAPI-driven Python SDK for Just One API
|
|
5
5
|
Author-email: Just One API <support@justoneapi.com>
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -175,6 +175,7 @@ except BusinessError as exc:
|
|
|
175
175
|
- [用户发布笔记 (V2)](https://docs.justoneapi.com/zh/api/xiaohongshu-rednote/user-published-notes-v2?utm_source=github.com&utm_medium=referral&utm_campaign=justoneapi_justoneapi_python&utm_content=repo_readme_api_list) <!-- api-operation:GET /api/xiaohongshu/get-user-note-list/v2 -->
|
|
176
176
|
- [用户发布笔记 (V3)](https://docs.justoneapi.com/zh/api/xiaohongshu-rednote/user-published-notes-v3?utm_source=github.com&utm_medium=referral&utm_campaign=justoneapi_justoneapi_python&utm_content=repo_readme_api_list) <!-- api-operation:GET /api/xiaohongshu/get-user-note-list/v3 -->
|
|
177
177
|
- [用户笔记 (V4)](https://docs.justoneapi.com/zh/api/xiaohongshu-rednote/user-notes-v4?utm_source=github.com&utm_medium=referral&utm_campaign=justoneapi_justoneapi_python&utm_content=repo_readme_api_list) <!-- api-operation:GET /api/xiaohongshu/get-user-note-list/v4 --> <sub>[JSON](https://github.com/justoneapi-official/justoneapi-python/blob/main/docs/api-examples/getApiXiaohongshuGetUserNoteListV4.json)</sub>
|
|
178
|
+
- [用户收藏的笔记 (V1)](https://docs.justoneapi.com/zh/api/xiaohongshu-rednote/user-favorited-notes-v1?utm_source=github.com&utm_medium=referral&utm_campaign=justoneapi_justoneapi_python&utm_content=repo_readme_api_list) <!-- api-operation:GET /api/xiaohongshu/get-user-faved-note-list/v1 -->
|
|
178
179
|
- [笔记详情 (V1)](https://docs.justoneapi.com/zh/api/xiaohongshu-rednote/note-details-v1?utm_source=github.com&utm_medium=referral&utm_campaign=justoneapi_justoneapi_python&utm_content=repo_readme_api_list) <!-- api-operation:GET /api/xiaohongshu/get-note-detail/v1 --> <sub>[JSON](https://github.com/justoneapi-official/justoneapi-python/blob/main/docs/api-examples/getApiXiaohongshuGetNoteDetailV1.json)</sub>
|
|
179
180
|
- [笔记详情 (V2)](https://docs.justoneapi.com/zh/api/xiaohongshu-rednote/note-details-v2?utm_source=github.com&utm_medium=referral&utm_campaign=justoneapi_justoneapi_python&utm_content=repo_readme_api_list) <!-- api-operation:GET /api/xiaohongshu/get-note-detail/v2 -->
|
|
180
181
|
- [笔记详情 (V3)](https://docs.justoneapi.com/zh/api/xiaohongshu-rednote/note-details-v3?utm_source=github.com&utm_medium=referral&utm_campaign=justoneapi_justoneapi_python&utm_content=repo_readme_api_list) <!-- api-operation:GET /api/xiaohongshu/get-note-detail/v3 -->
|
|
@@ -36,7 +36,6 @@ justoneapi/generated/resources/jd.py
|
|
|
36
36
|
justoneapi/generated/resources/kuaishou.py
|
|
37
37
|
justoneapi/generated/resources/linkedin.py
|
|
38
38
|
justoneapi/generated/resources/llm.py
|
|
39
|
-
justoneapi/generated/resources/pixabay.py
|
|
40
39
|
justoneapi/generated/resources/qq_huxuan.py
|
|
41
40
|
justoneapi/generated/resources/reddit.py
|
|
42
41
|
justoneapi/generated/resources/search.py
|
|
@@ -47,7 +46,6 @@ justoneapi/generated/resources/tiktok.py
|
|
|
47
46
|
justoneapi/generated/resources/tiktok_shop.py
|
|
48
47
|
justoneapi/generated/resources/toutiao.py
|
|
49
48
|
justoneapi/generated/resources/twitter.py
|
|
50
|
-
justoneapi/generated/resources/vcg.py
|
|
51
49
|
justoneapi/generated/resources/weibo.py
|
|
52
50
|
justoneapi/generated/resources/weixin.py
|
|
53
51
|
justoneapi/generated/resources/weixin_channels.py
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import json
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
|
|
6
|
+
import httpx
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
from tools import sdk_codegen
|
|
5
10
|
from tools.sdk_codegen import (
|
|
6
11
|
build_diff_summary,
|
|
7
12
|
collect_resources,
|
|
13
|
+
fetch_openapi,
|
|
8
14
|
load_json,
|
|
9
15
|
load_overrides,
|
|
10
16
|
normalize_spec,
|
|
@@ -14,6 +20,111 @@ RAW_SPEC_PATH = Path("openapi/public-api.json")
|
|
|
14
20
|
OVERRIDES_PATH = Path("openapi/sdk_overrides.yaml")
|
|
15
21
|
|
|
16
22
|
|
|
23
|
+
@pytest.fixture
|
|
24
|
+
def mock_openapi_fetch(monkeypatch):
|
|
25
|
+
outcomes = []
|
|
26
|
+
requests = []
|
|
27
|
+
delays = []
|
|
28
|
+
|
|
29
|
+
def handle(request):
|
|
30
|
+
requests.append(request)
|
|
31
|
+
outcome = outcomes.pop(0)
|
|
32
|
+
if isinstance(outcome, Exception):
|
|
33
|
+
raise outcome
|
|
34
|
+
return outcome
|
|
35
|
+
|
|
36
|
+
client_type = httpx.Client
|
|
37
|
+
monkeypatch.setattr(
|
|
38
|
+
sdk_codegen.httpx,
|
|
39
|
+
"Client",
|
|
40
|
+
lambda **kwargs: client_type(transport=httpx.MockTransport(handle), **kwargs),
|
|
41
|
+
)
|
|
42
|
+
monkeypatch.setattr(sdk_codegen.time, "sleep", delays.append)
|
|
43
|
+
return outcomes, requests, delays
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@pytest.mark.parametrize("timeout_type", [httpx.ConnectTimeout, httpx.ReadTimeout])
|
|
47
|
+
@pytest.mark.parametrize("timeouts_before_success", [0, 1, 2])
|
|
48
|
+
def test_fetch_openapi_recovers_from_temporary_timeouts(
|
|
49
|
+
mock_openapi_fetch, timeout_type, timeouts_before_success
|
|
50
|
+
):
|
|
51
|
+
outcomes, requests, delays = mock_openapi_fetch
|
|
52
|
+
spec = {"openapi": "3.0.3", "paths": {}}
|
|
53
|
+
outcomes.extend(
|
|
54
|
+
timeout_type("Temporary timeout") for _ in range(timeouts_before_success)
|
|
55
|
+
)
|
|
56
|
+
outcomes.append(httpx.Response(200, json=spec))
|
|
57
|
+
|
|
58
|
+
assert (
|
|
59
|
+
fetch_openapi("https://example.test/openapi", "test-user", "test-pass") == spec
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
assert len(requests) == timeouts_before_success + 1
|
|
63
|
+
assert delays == [2, 4][:timeouts_before_success]
|
|
64
|
+
assert all(request.method == "GET" for request in requests)
|
|
65
|
+
assert all(
|
|
66
|
+
request.headers["authorization"] == requests[0].headers["authorization"]
|
|
67
|
+
for request in requests
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@pytest.mark.parametrize("timeout_type", [httpx.ConnectTimeout, httpx.ReadTimeout])
|
|
72
|
+
def test_fetch_openapi_raises_after_three_timeouts(mock_openapi_fetch, timeout_type):
|
|
73
|
+
outcomes, requests, delays = mock_openapi_fetch
|
|
74
|
+
last_error = timeout_type("Still unavailable")
|
|
75
|
+
outcomes.extend(
|
|
76
|
+
[
|
|
77
|
+
timeout_type("Temporary timeout"),
|
|
78
|
+
timeout_type("Temporary timeout"),
|
|
79
|
+
last_error,
|
|
80
|
+
]
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
with pytest.raises(timeout_type) as caught:
|
|
84
|
+
fetch_openapi("https://example.test/openapi", "test-user", "test-pass")
|
|
85
|
+
|
|
86
|
+
assert caught.value is last_error
|
|
87
|
+
assert len(requests) == 3
|
|
88
|
+
assert delays == [2, 4]
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@pytest.mark.parametrize("status_code", [401, 503])
|
|
92
|
+
def test_fetch_openapi_does_not_retry_http_errors(mock_openapi_fetch, status_code):
|
|
93
|
+
outcomes, requests, delays = mock_openapi_fetch
|
|
94
|
+
outcomes.append(httpx.Response(status_code))
|
|
95
|
+
|
|
96
|
+
with pytest.raises(httpx.HTTPStatusError):
|
|
97
|
+
fetch_openapi("https://example.test/openapi", "test-user", "test-pass")
|
|
98
|
+
|
|
99
|
+
assert len(requests) == 1
|
|
100
|
+
assert delays == []
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def test_fetch_openapi_does_not_retry_invalid_json(mock_openapi_fetch):
|
|
104
|
+
outcomes, requests, delays = mock_openapi_fetch
|
|
105
|
+
outcomes.append(httpx.Response(200, text="not JSON"))
|
|
106
|
+
|
|
107
|
+
with pytest.raises(json.JSONDecodeError):
|
|
108
|
+
fetch_openapi("https://example.test/openapi", "test-user", "test-pass")
|
|
109
|
+
|
|
110
|
+
assert len(requests) == 1
|
|
111
|
+
assert delays == []
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@pytest.mark.parametrize("error_type", [httpx.ConnectError, httpx.WriteTimeout])
|
|
115
|
+
def test_fetch_openapi_does_not_retry_other_transport_errors(
|
|
116
|
+
mock_openapi_fetch, error_type
|
|
117
|
+
):
|
|
118
|
+
outcomes, requests, delays = mock_openapi_fetch
|
|
119
|
+
outcomes.append(error_type("Non-retryable transport failure"))
|
|
120
|
+
|
|
121
|
+
with pytest.raises(error_type):
|
|
122
|
+
fetch_openapi("https://example.test/openapi", "test-user", "test-pass")
|
|
123
|
+
|
|
124
|
+
assert len(requests) == 1
|
|
125
|
+
assert delays == []
|
|
126
|
+
|
|
127
|
+
|
|
17
128
|
def count_operations(spec: dict) -> int:
|
|
18
129
|
return sum(
|
|
19
130
|
1
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "3.0.81"
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import Any
|
|
4
|
-
|
|
5
|
-
from justoneapi._resource import BaseResource
|
|
6
|
-
from justoneapi._response import ApiResponse
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class PixabayResource(BaseResource):
|
|
10
|
-
"""Generated resource for Pixabay."""
|
|
11
|
-
|
|
12
|
-
def search_image_v1(
|
|
13
|
-
self,
|
|
14
|
-
*,
|
|
15
|
-
keyword: str,
|
|
16
|
-
limit: str | None = None,
|
|
17
|
-
start_page: str | None = None,
|
|
18
|
-
max_pages: str | None = None,
|
|
19
|
-
) -> ApiResponse[Any]:
|
|
20
|
-
"""
|
|
21
|
-
Photo Search
|
|
22
|
-
|
|
23
|
-
Searches public Pixabay photo result pages by keyword with a requested image count and page controls. Each result includes its Pixabay photo page, public contributor information when shown, and a source-provided image URL.
|
|
24
|
-
|
|
25
|
-
Args:
|
|
26
|
-
keyword: Photo search keyword, up to 100 characters without control characters.
|
|
27
|
-
limit: Maximum number of unique photos to return.
|
|
28
|
-
start_page: First result page to search, starting from 1.
|
|
29
|
-
max_pages: Maximum number of pages to visit in this request. The last page must not exceed 10000.
|
|
30
|
-
"""
|
|
31
|
-
return self._get(
|
|
32
|
-
"/api/pixabay/search-image/v1",
|
|
33
|
-
{
|
|
34
|
-
"keyword": keyword,
|
|
35
|
-
"limit": limit,
|
|
36
|
-
"startPage": start_page,
|
|
37
|
-
"maxPages": max_pages,
|
|
38
|
-
},
|
|
39
|
-
)
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import Any
|
|
4
|
-
|
|
5
|
-
from justoneapi._resource import BaseResource
|
|
6
|
-
from justoneapi._response import ApiResponse
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class VcgResource(BaseResource):
|
|
10
|
-
"""Generated resource for VCG."""
|
|
11
|
-
|
|
12
|
-
def search_image_v1(
|
|
13
|
-
self,
|
|
14
|
-
*,
|
|
15
|
-
keyword: str,
|
|
16
|
-
limit: str | None = None,
|
|
17
|
-
start_page: str | None = None,
|
|
18
|
-
max_pages: str | None = None,
|
|
19
|
-
exclude_resource_ids: list[Any] | None = None,
|
|
20
|
-
content_filter: str | None = "all",
|
|
21
|
-
result_mode: str | None = "full",
|
|
22
|
-
) -> ApiResponse[Any]:
|
|
23
|
-
"""
|
|
24
|
-
Image Search
|
|
25
|
-
|
|
26
|
-
Searches VCG images by keyword with page controls, resource ID exclusions, and an optional 500px Select/Prime filter excluding AIGC. Use full image details for collection or candidate_ids for single-page ID inspection.
|
|
27
|
-
|
|
28
|
-
Args:
|
|
29
|
-
keyword: Image search keyword, up to 200 characters without control characters.
|
|
30
|
-
limit: Maximum number of unique images to return, excluding the supplied resource IDs.
|
|
31
|
-
start_page: First page to search, starting from 1. For continuation, use the next page returned by the previous request.
|
|
32
|
-
max_pages: Maximum number of pages to visit in this request. The last requested page must not exceed 10000.
|
|
33
|
-
exclude_resource_ids: Previously collected VCG resource IDs to exclude when continuing a search. Supply comma-separated IDs or repeat this query parameter.
|
|
34
|
-
content_filter: Optional brand and AIGC search restriction. Keep this value unchanged across pagination and continuation. Available Values: - `all`: Keep the default search without additional brand or AIGC filters. - `selected_500px_no_aigc`: Select only 500px Select and 500px Prime, exclude AIGC using the site's filter, and retain best ordering. Do not expand to other brands when results run out.
|
|
35
|
-
result_mode: Result mode: full returns normal image details; candidate_ids only inspects one page of resource IDs and requires limit 10000, maxPages 1, and no excluded resource IDs. A candidate inspection does not complete or advance an image search. Available Values: - `full`: Return the normal image search result with complete image details. - `candidate_ids`: Inspect resource IDs from one validated search page without image details. Requires limit 10000, maxPages 1, and no excluded resource IDs; this is not an image result or a completion receipt.
|
|
36
|
-
"""
|
|
37
|
-
return self._get(
|
|
38
|
-
"/api/vcg/search-image/v1",
|
|
39
|
-
{
|
|
40
|
-
"keyword": keyword,
|
|
41
|
-
"limit": limit,
|
|
42
|
-
"startPage": start_page,
|
|
43
|
-
"maxPages": max_pages,
|
|
44
|
-
"excludeResourceIds": exclude_resource_ids,
|
|
45
|
-
"contentFilter": content_filter,
|
|
46
|
-
"resultMode": result_mode,
|
|
47
|
-
},
|
|
48
|
-
)
|
|
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
|
|
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
|
|
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
|