Skip to content

Commit 28348d6

Browse files
chore: update SDK to v0.8.1
1 parent 2728411 commit 28348d6

File tree

85 files changed

+34139
-18113
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+34139
-18113
lines changed

conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
project = "X API SDK"
2222
copyright = "2024, X Developer Platform"
2323
author = "X Developer Platform"
24-
release = "0.5.0"
25-
version = "0.5.0"
24+
release = "0.8.1"
25+
version = "0.8.1"
2626

2727
# -- General configuration ----------------------------------------------------
2828

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ build-backend = "hatchling.build"
1414

1515
[project]
1616
name = "xdk"
17-
version = "0.5.0"
17+
version = "0.8.1"
1818
description = "Python SDK for the X API"
1919
authors = [
2020
{name = "X Developer Platform", email = "[email protected]"},

tests/account_activity/test_contracts.py

Lines changed: 524 additions & 320 deletions
Large diffs are not rendered by default.

tests/account_activity/test_structure.py

Lines changed: 76 additions & 76 deletions
Large diffs are not rendered by default.

tests/activity/test_contracts.py

Lines changed: 525 additions & 299 deletions
Large diffs are not rendered by default.

tests/activity/test_pagination.py

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
# AUTO-GENERATED FILE - DO NOT EDIT
2+
# This file was automatically generated by the XDK build tool.
3+
# Any manual changes will be overwritten on the next generation.
4+
"""
5+
Auto-generated pagination tests for {"class_name": "Activity", "display_name": "activity", "import_name": "activity", "original": ["activity"], "property_name": "activity"} client.
6+
7+
This module contains tests that validate pagination functionality
8+
using the Cursor class for methods that support pagination. Tests verify
9+
proper handling of pagination tokens, page limits, and item iteration.
10+
11+
Generated automatically - do not edit manually.
12+
"""
13+
14+
import pytest
15+
from unittest.mock import Mock, patch
16+
from xdk.activity.client import ActivityClient
17+
from xdk import Client, Cursor, cursor, PaginationError
18+
19+
20+
class TestActivityPagination:
21+
"""Test pagination functionality for ActivityClient."""
22+
23+
24+
def setup_class(self):
25+
"""Set up test fixtures."""
26+
# Provide all authentication types for comprehensive test coverage
27+
# Tests mock the session, so actual HTTP requests won't be made
28+
from xdk.oauth1_auth import OAuth1
29+
oauth1 = OAuth1(
30+
api_key="test_api_key",
31+
api_secret="test_api_secret",
32+
callback="http://localhost:8080/callback",
33+
access_token="test_access_token",
34+
access_token_secret="test_access_token_secret",
35+
)
36+
self.client = Client(
37+
base_url="https://api.example.com",
38+
bearer_token="test_bearer_token",
39+
access_token="test_access_token",
40+
auth=oauth1,
41+
)
42+
self.activity_client = getattr(self.client, "activity")
43+
44+
45+
def test_get_subscriptions_cursor_creation(self):
46+
"""Test that get_subscriptions can be used with Cursor."""
47+
method = getattr(self.activity_client, "get_subscriptions")
48+
# Should be able to create cursor without error
49+
try:
50+
test_cursor = cursor(method, max_results=10)
51+
assert test_cursor is not None
52+
assert isinstance(test_cursor, Cursor)
53+
except PaginationError:
54+
pytest.fail(f"Method get_subscriptions should support pagination")
55+
56+
57+
def test_get_subscriptions_cursor_pages(self):
58+
"""Test pagination with pages() for get_subscriptions."""
59+
with patch.object(self.client, "session") as mock_session:
60+
# Mock first page response
61+
first_page_response = Mock()
62+
first_page_response.status_code = 200
63+
first_page_response.json.return_value = {
64+
"data": [{"id": "1", "name": "Item 1"}, {"id": "2", "name": "Item 2"}],
65+
"meta": {"next_token": "next_page_token", "result_count": 2},
66+
}
67+
first_page_response.raise_for_status.return_value = None
68+
# Mock second page response (no next token = end of pagination)
69+
second_page_response = Mock()
70+
second_page_response.status_code = 200
71+
second_page_response.json.return_value = {
72+
"data": [{"id": "3", "name": "Item 3"}],
73+
"meta": {"result_count": 1},
74+
}
75+
second_page_response.raise_for_status.return_value = None
76+
# Return different responses for consecutive calls
77+
mock_session.get.side_effect = [first_page_response, second_page_response]
78+
# Test pagination
79+
method = getattr(self.activity_client, "get_subscriptions")
80+
test_cursor = cursor(method, max_results=2)
81+
pages = list(test_cursor.pages(2)) # Limit to 2 pages
82+
assert len(pages) == 2, f"Should get 2 pages, got {len(pages)}"
83+
# Verify first page
84+
first_page = pages[0]
85+
assert hasattr(first_page, "data")
86+
first_data = getattr(first_page, "data")
87+
assert len(first_data) == 2, "First page should have 2 items"
88+
# Verify second page
89+
second_page = pages[1]
90+
assert hasattr(second_page, "data")
91+
second_data = getattr(second_page, "data")
92+
assert len(second_data) == 1, "Second page should have 1 item"
93+
94+
95+
def test_get_subscriptions_cursor_items(self):
96+
"""Test pagination with items() for get_subscriptions."""
97+
with patch.object(self.client, "session") as mock_session:
98+
# Mock response with paginated data
99+
mock_response = Mock()
100+
mock_response.status_code = 200
101+
mock_response.json.return_value = {
102+
"data": [
103+
{"id": "1", "name": "Item 1"},
104+
{"id": "2", "name": "Item 2"},
105+
{"id": "3", "name": "Item 3"},
106+
],
107+
"meta": {
108+
"result_count": 3
109+
# No next_token = single page
110+
},
111+
}
112+
mock_response.raise_for_status.return_value = None
113+
mock_session.get.return_value = mock_response
114+
# Test item iteration
115+
method = getattr(self.activity_client, "get_subscriptions")
116+
test_cursor = cursor(method, max_results=10)
117+
items = list(test_cursor.items(5)) # Limit to 5 items
118+
assert len(items) == 3, f"Should get 3 items, got {len(items)}"
119+
# Verify items have expected structure
120+
for item in items:
121+
assert "id" in item or hasattr(
122+
item, "id"
123+
), "Items should have 'id' field"
124+
125+
126+
def test_get_subscriptions_pagination_parameters(self):
127+
"""Test that pagination parameters are handled correctly for get_subscriptions."""
128+
with patch.object(self.client, "session") as mock_session:
129+
mock_response = Mock()
130+
mock_response.status_code = 200
131+
mock_response.json.return_value = {"data": [], "meta": {"result_count": 0}}
132+
mock_response.raise_for_status.return_value = None
133+
mock_session.get.return_value = mock_response
134+
method = getattr(self.activity_client, "get_subscriptions")
135+
# Test with max_results parameter
136+
test_cursor = cursor(method, max_results=5)
137+
list(test_cursor.pages(1)) # Trigger one request
138+
# Verify max_results was passed in request
139+
call_args = mock_session.get.call_args
140+
if call_args and "params" in call_args[1]:
141+
params = call_args[1]["params"]
142+
assert (
143+
"max_results" in params
144+
), "max_results should be in request parameters"
145+
# Test with pagination token (simulate second page request)
146+
mock_session.reset_mock()
147+
mock_response_with_token = Mock()
148+
mock_response_with_token.status_code = 200
149+
mock_response_with_token.json.return_value = {
150+
"data": [{"id": "1"}],
151+
"meta": {"next_token": "next_token_value", "result_count": 1},
152+
}
153+
mock_response_with_token.raise_for_status.return_value = None
154+
second_page_response = Mock()
155+
second_page_response.status_code = 200
156+
second_page_response.json.return_value = {
157+
"data": [],
158+
"meta": {"result_count": 0},
159+
}
160+
second_page_response.raise_for_status.return_value = None
161+
mock_session.get.side_effect = [
162+
mock_response_with_token,
163+
second_page_response,
164+
]
165+
test_cursor = cursor(method, max_results=1)
166+
pages = list(test_cursor.pages(2))
167+
# Should have made 2 requests
168+
assert (
169+
mock_session.get.call_count == 2
170+
), "Should make 2 requests for 2 pages"
171+
# Second request should include pagination token
172+
second_call_args = mock_session.get.call_args_list[1]
173+
if (
174+
second_call_args
175+
and len(second_call_args) > 1
176+
and "params" in second_call_args[1]
177+
):
178+
second_params = second_call_args[1]["params"]
179+
assert (
180+
"pagination_token" in second_params
181+
), "Second request should include pagination_token"
182+
assert (
183+
second_params["pagination_token"] == "next_token_value"
184+
), "Pagination token should be passed correctly"
185+
186+
187+
def test_pagination_edge_cases(self):
188+
"""Test pagination edge cases."""
189+
with patch.object(self.client, "session") as mock_session:
190+
# Test empty response
191+
empty_response = Mock()
192+
empty_response.status_code = 200
193+
empty_response.json.return_value = {"data": [], "meta": {"result_count": 0}}
194+
empty_response.raise_for_status.return_value = None
195+
mock_session.get.return_value = empty_response
196+
# Pick first paginatable method for testing
197+
method = getattr(self.activity_client, "get_subscriptions")
198+
test_cursor = cursor(method, max_results=10)
199+
# Should handle empty responses gracefully
200+
pages = list(test_cursor.pages(1))
201+
assert len(pages) == 1, "Should get one page even if empty"
202+
items = list(test_cursor.items(10))
203+
assert len(items) == 0, "Should get no items from empty response"
204+
205+
206+
def test_non_paginatable_method_raises_error(self):
207+
"""Test that non-paginatable methods raise PaginationError."""
208+
# Create a mock method that doesn't support pagination
209+
def non_paginatable_method(id: str) -> dict:
210+
return {"id": id}
211+
with pytest.raises(PaginationError):
212+
cursor(non_paginatable_method)
213+
214+
215+
def non_paginatable_method(id: str) -> dict:
216+
return {"id": id}
217+
218+
with pytest.raises(PaginationError):
219+
cursor(non_paginatable_method)
220+
221+
222+
def test_cursor_class_functionality(self):
223+
"""Test basic Cursor class functionality."""
224+
# Test that Cursor can be imported and instantiated
225+
from xdk.paginator import Cursor
226+
assert Cursor is not None
227+
# Test cursor factory function
228+
from xdk.paginator import cursor as cursor_factory
229+
assert cursor_factory is not None

0 commit comments

Comments
 (0)