justoneapi 3.0.81__tar.gz → 3.0.82__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 (69) hide show
  1. {justoneapi-3.0.81/justoneapi.egg-info → justoneapi-3.0.82}/PKG-INFO +1 -1
  2. justoneapi-3.0.82/justoneapi/_version.py +1 -0
  3. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/xiaohongshu.py +23 -0
  4. {justoneapi-3.0.81 → justoneapi-3.0.82/justoneapi.egg-info}/PKG-INFO +1 -1
  5. {justoneapi-3.0.81 → justoneapi-3.0.82}/tests/test_codegen.py +111 -0
  6. justoneapi-3.0.81/justoneapi/_version.py +0 -1
  7. {justoneapi-3.0.81 → justoneapi-3.0.82}/LICENSE +0 -0
  8. {justoneapi-3.0.81 → justoneapi-3.0.82}/MANIFEST.in +0 -0
  9. {justoneapi-3.0.81 → justoneapi-3.0.82}/README.md +0 -0
  10. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/__init__.py +0 -0
  11. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/_exceptions.py +0 -0
  12. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/_resource.py +0 -0
  13. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/_response.py +0 -0
  14. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/_transport.py +0 -0
  15. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/client.py +0 -0
  16. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/config.py +0 -0
  17. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/__init__.py +0 -0
  18. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/models.py +0 -0
  19. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/__init__.py +0 -0
  20. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/aliexpress.py +0 -0
  21. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/amazon.py +0 -0
  22. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/beike.py +0 -0
  23. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/bilibili.py +0 -0
  24. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/dewu.py +0 -0
  25. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/douban.py +0 -0
  26. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/douyin.py +0 -0
  27. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/douyin_ec.py +0 -0
  28. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/douyin_xingtu.py +0 -0
  29. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/facebook.py +0 -0
  30. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/field_1688.py +0 -0
  31. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/imdb.py +0 -0
  32. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/instagram.py +0 -0
  33. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/jd.py +0 -0
  34. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/kuaishou.py +0 -0
  35. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/linkedin.py +0 -0
  36. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/llm.py +0 -0
  37. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/pixabay.py +0 -0
  38. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/qq_huxuan.py +0 -0
  39. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/reddit.py +0 -0
  40. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/search.py +0 -0
  41. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/shopee.py +0 -0
  42. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/taobao.py +0 -0
  43. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/temu.py +0 -0
  44. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/tiktok.py +0 -0
  45. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/tiktok_shop.py +0 -0
  46. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/toutiao.py +0 -0
  47. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/twitter.py +0 -0
  48. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/vcg.py +0 -0
  49. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/weibo.py +0 -0
  50. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/weixin.py +0 -0
  51. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/weixin_channels.py +0 -0
  52. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/xianyu.py +0 -0
  53. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/xiaohongshu_ec.py +0 -0
  54. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/xiaohongshu_pgy.py +0 -0
  55. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/youku.py +0 -0
  56. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/youtube.py +0 -0
  57. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/zcool.py +0 -0
  58. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/generated/resources/zhihu.py +0 -0
  59. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi/log.py +0 -0
  60. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi.egg-info/SOURCES.txt +0 -0
  61. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi.egg-info/dependency_links.txt +0 -0
  62. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi.egg-info/requires.txt +0 -0
  63. {justoneapi-3.0.81 → justoneapi-3.0.82}/justoneapi.egg-info/top_level.txt +0 -0
  64. {justoneapi-3.0.81 → justoneapi-3.0.82}/pyproject.toml +0 -0
  65. {justoneapi-3.0.81 → justoneapi-3.0.82}/setup.cfg +0 -0
  66. {justoneapi-3.0.81 → justoneapi-3.0.82}/tests/test_bump_version.py +0 -0
  67. {justoneapi-3.0.81 → justoneapi-3.0.82}/tests/test_generated_surface.py +0 -0
  68. {justoneapi-3.0.81 → justoneapi-3.0.82}/tests/test_integration_smoke.py +0 -0
  69. {justoneapi-3.0.81 → justoneapi-3.0.82}/tests/test_runtime.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: justoneapi
3
- Version: 3.0.81
3
+ Version: 3.0.82
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
@@ -0,0 +1 @@
1
+ __version__ = "3.0.82"
@@ -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.81
3
+ Version: 3.0.82
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
@@ -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"
File without changes
File without changes
File without changes
File without changes
File without changes