python-zendesk-sdk 0.3.1__tar.gz → 0.4.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.
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/PKG-INFO +41 -27
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/README.md +40 -26
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/examples/basic_usage.py +7 -6
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/examples/caching.py +3 -3
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/examples/enriched_tickets.py +13 -19
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/examples/error_handling.py +4 -3
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/examples/help_center.py +22 -20
- python_zendesk_sdk-0.4.0/examples/pagination_example.py +106 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/examples/search.py +44 -9
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/pyproject.toml +1 -1
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/__init__.py +1 -1
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/clients/attachments.py +1 -2
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/clients/help_center/articles.py +30 -8
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/clients/help_center/categories.py +12 -4
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/clients/help_center/sections.py +20 -8
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/clients/organizations.py +12 -6
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/clients/search.py +121 -138
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/clients/tickets.py +62 -92
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/clients/users.py +12 -6
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/models/ticket.py +14 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/pagination.py +224 -47
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/tests/test_clients.py +35 -41
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/tests/test_package_import.py +1 -1
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/tests/test_pagination.py +23 -6
- python_zendesk_sdk-0.3.1/examples/pagination_example.py +0 -66
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/.flake8 +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/.github/workflows/publish.yml +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/.gitignore +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/.python-version +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/LICENSE +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/client.py +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/clients/__init__.py +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/clients/base.py +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/clients/help_center/__init__.py +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/config.py +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/exceptions.py +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/http_client.py +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/models/__init__.py +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/models/base.py +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/models/comment.py +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/models/enriched_ticket.py +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/models/help_center.py +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/models/organization.py +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/models/search.py +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/src/zendesk_sdk/models/user.py +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/tests/__init__.py +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/tests/test_client.py +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/tests/test_config.py +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/tests/test_exceptions.py +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/tests/test_help_center_client.py +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/tests/test_http_client.py +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/tests/test_models.py +0 -0
- {python_zendesk_sdk-0.3.1 → python_zendesk_sdk-0.4.0}/tests/test_search_query_config.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-zendesk-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Modern Python SDK for Zendesk API
|
|
5
5
|
Project-URL: Homepage, https://github.com/bormog/python-zendesk-sdk
|
|
6
6
|
Project-URL: Repository, https://github.com/bormog/python-zendesk-sdk
|
|
@@ -40,7 +40,7 @@ Description-Content-Type: text/markdown
|
|
|
40
40
|
|
|
41
41
|
[](https://pypi.org/project/python-zendesk-sdk/)
|
|
42
42
|
[](https://pypi.org/project/python-zendesk-sdk/)
|
|
43
|
-
[](https://pepy.tech/projects/python-zendesk-sdk)
|
|
44
44
|
[](https://github.com/bormog/python-zendesk-sdk/blob/main/LICENSE)
|
|
45
45
|
[](https://github.com/psf/black)
|
|
46
46
|
[](https://docs.pydantic.dev/)
|
|
@@ -122,18 +122,15 @@ async def main():
|
|
|
122
122
|
)
|
|
123
123
|
|
|
124
124
|
async with ZendeskClient(config) as client:
|
|
125
|
-
# Get
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
for user in users:
|
|
130
|
-
print(f"User: {user['name']} ({user['email']})")
|
|
125
|
+
# Get a single user
|
|
126
|
+
user = await client.users.get(12345)
|
|
127
|
+
print(f"User: {user.name} ({user.email})")
|
|
131
128
|
|
|
132
129
|
# Get specific ticket
|
|
133
130
|
ticket = await client.tickets.get(12345)
|
|
134
131
|
print(f"Ticket: {ticket.subject}")
|
|
135
132
|
|
|
136
|
-
# Search tickets
|
|
133
|
+
# Search tickets with pagination
|
|
137
134
|
async for ticket in client.search.tickets("status:open priority:high", limit=10):
|
|
138
135
|
print(f"High priority: {ticket.subject}")
|
|
139
136
|
|
|
@@ -164,31 +161,48 @@ config = ZendeskConfig() # Will load from environment
|
|
|
164
161
|
|
|
165
162
|
## API Methods
|
|
166
163
|
|
|
164
|
+
### Pagination
|
|
165
|
+
|
|
166
|
+
All list methods return **Paginator** objects. Three ways to work with them:
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
# 1. Get specific page
|
|
170
|
+
paginator = client.users.list(per_page=20)
|
|
171
|
+
users = await paginator.get_page(2) # Get page 2
|
|
172
|
+
|
|
173
|
+
# 2. Iterate through all items
|
|
174
|
+
async for user in client.users.list():
|
|
175
|
+
print(user.name)
|
|
176
|
+
|
|
177
|
+
# 3. Collect to list
|
|
178
|
+
users = await client.users.list(limit=50).collect()
|
|
179
|
+
```
|
|
180
|
+
|
|
167
181
|
### Users
|
|
168
182
|
```python
|
|
169
183
|
user = await client.users.get(user_id) # Get user by ID
|
|
170
|
-
paginator = await client.users.list() # List users with pagination
|
|
171
184
|
user = await client.users.by_email(email) # Get user by email
|
|
172
185
|
users = await client.users.get_many([id1, id2]) # Get multiple users
|
|
186
|
+
paginator = client.users.list() # List users (paginator)
|
|
173
187
|
```
|
|
174
188
|
|
|
175
189
|
### Organizations
|
|
176
190
|
```python
|
|
177
191
|
org = await client.organizations.get(org_id) # Get organization by ID
|
|
178
|
-
paginator =
|
|
192
|
+
paginator = client.organizations.list() # List organizations (paginator)
|
|
179
193
|
```
|
|
180
194
|
|
|
181
195
|
### Tickets
|
|
182
196
|
```python
|
|
183
197
|
ticket = await client.tickets.get(ticket_id) # Get ticket by ID
|
|
184
|
-
paginator =
|
|
185
|
-
|
|
186
|
-
|
|
198
|
+
paginator = client.tickets.list() # List tickets (paginator)
|
|
199
|
+
paginator = client.tickets.for_user(user_id) # User's tickets (paginator)
|
|
200
|
+
paginator = client.tickets.for_organization(org_id) # Org's tickets (paginator)
|
|
187
201
|
```
|
|
188
202
|
|
|
189
203
|
### Comments (nested under tickets)
|
|
190
204
|
```python
|
|
191
|
-
|
|
205
|
+
paginator = client.tickets.comments.list(ticket_id) # List comments (paginator)
|
|
192
206
|
ticket = await client.tickets.comments.add(ticket_id, body, public=False)
|
|
193
207
|
await client.tickets.comments.make_private(ticket_id, comment_id)
|
|
194
208
|
comment = await client.tickets.comments.redact(ticket_id, comment_id, text)
|
|
@@ -243,14 +257,14 @@ await client.tickets.comments.add(ticket_id, "See attached", uploads=[token])
|
|
|
243
257
|
|
|
244
258
|
### Search
|
|
245
259
|
|
|
246
|
-
All search methods return **
|
|
260
|
+
All search methods return **Paginator** objects with the same interface as list methods.
|
|
247
261
|
|
|
248
262
|
#### Raw Queries (Zendesk syntax)
|
|
249
263
|
|
|
250
264
|
Use the same query syntax as in Zendesk UI — it just works:
|
|
251
265
|
|
|
252
266
|
```python
|
|
253
|
-
# Tickets
|
|
267
|
+
# Tickets - iterate through results
|
|
254
268
|
async for ticket in client.search.tickets("status:open priority:high"):
|
|
255
269
|
print(ticket.subject)
|
|
256
270
|
|
|
@@ -262,8 +276,8 @@ async for user in client.search.users("role:admin"):
|
|
|
262
276
|
async for org in client.search.organizations("tags:enterprise"):
|
|
263
277
|
print(org.name)
|
|
264
278
|
|
|
265
|
-
# Collect to list
|
|
266
|
-
|
|
279
|
+
# Collect to list with limit
|
|
280
|
+
tickets = await client.search.tickets("status:pending", limit=100).collect()
|
|
267
281
|
|
|
268
282
|
# Search with enrichment (loads comments + users)
|
|
269
283
|
async for item in client.tickets.search_enriched("status:open", limit=10):
|
|
@@ -363,7 +377,7 @@ Access Help Center (Guide) via `client.help_center` namespace:
|
|
|
363
377
|
#### Categories
|
|
364
378
|
```python
|
|
365
379
|
cat = await client.help_center.categories.get(category_id)
|
|
366
|
-
paginator =
|
|
380
|
+
paginator = client.help_center.categories.list() # Paginator
|
|
367
381
|
cat = await client.help_center.categories.create(name, description)
|
|
368
382
|
cat = await client.help_center.categories.update(category_id, name=new_name)
|
|
369
383
|
await client.help_center.categories.delete(category_id, force=True)
|
|
@@ -372,8 +386,8 @@ await client.help_center.categories.delete(category_id, force=True)
|
|
|
372
386
|
#### Sections
|
|
373
387
|
```python
|
|
374
388
|
sec = await client.help_center.sections.get(section_id)
|
|
375
|
-
paginator =
|
|
376
|
-
paginator =
|
|
389
|
+
paginator = client.help_center.sections.list() # Paginator
|
|
390
|
+
paginator = client.help_center.sections.for_category(category_id)
|
|
377
391
|
sec = await client.help_center.sections.create(category_id, name, description)
|
|
378
392
|
sec = await client.help_center.sections.update(section_id, name=new_name)
|
|
379
393
|
await client.help_center.sections.delete(section_id, force=True)
|
|
@@ -382,9 +396,9 @@ await client.help_center.sections.delete(section_id, force=True)
|
|
|
382
396
|
#### Articles
|
|
383
397
|
```python
|
|
384
398
|
art = await client.help_center.articles.get(article_id)
|
|
385
|
-
paginator =
|
|
386
|
-
paginator =
|
|
387
|
-
paginator =
|
|
399
|
+
paginator = client.help_center.articles.list() # Paginator
|
|
400
|
+
paginator = client.help_center.articles.for_section(section_id)
|
|
401
|
+
paginator = client.help_center.articles.for_category(category_id)
|
|
388
402
|
results = await client.help_center.articles.search(query)
|
|
389
403
|
art = await client.help_center.articles.create(section_id, title, body=html)
|
|
390
404
|
art = await client.help_center.articles.update(article_id, title=new_title)
|
|
@@ -397,8 +411,8 @@ async with ZendeskClient(config) as client:
|
|
|
397
411
|
hc = client.help_center
|
|
398
412
|
|
|
399
413
|
# Get permission_group_id from existing article (required for article creation)
|
|
400
|
-
existing = await
|
|
401
|
-
article_details = await hc.articles.get(existing[0]
|
|
414
|
+
existing = await hc.articles.list(per_page=1).get_page()
|
|
415
|
+
article_details = await hc.articles.get(existing[0].id)
|
|
402
416
|
permission_group_id = article_details.permission_group_id
|
|
403
417
|
|
|
404
418
|
# Create category -> section -> article hierarchy
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://pypi.org/project/python-zendesk-sdk/)
|
|
4
4
|
[](https://pypi.org/project/python-zendesk-sdk/)
|
|
5
|
-
[](https://pepy.tech/projects/python-zendesk-sdk)
|
|
6
6
|
[](https://github.com/bormog/python-zendesk-sdk/blob/main/LICENSE)
|
|
7
7
|
[](https://github.com/psf/black)
|
|
8
8
|
[](https://docs.pydantic.dev/)
|
|
@@ -84,18 +84,15 @@ async def main():
|
|
|
84
84
|
)
|
|
85
85
|
|
|
86
86
|
async with ZendeskClient(config) as client:
|
|
87
|
-
# Get
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
for user in users:
|
|
92
|
-
print(f"User: {user['name']} ({user['email']})")
|
|
87
|
+
# Get a single user
|
|
88
|
+
user = await client.users.get(12345)
|
|
89
|
+
print(f"User: {user.name} ({user.email})")
|
|
93
90
|
|
|
94
91
|
# Get specific ticket
|
|
95
92
|
ticket = await client.tickets.get(12345)
|
|
96
93
|
print(f"Ticket: {ticket.subject}")
|
|
97
94
|
|
|
98
|
-
# Search tickets
|
|
95
|
+
# Search tickets with pagination
|
|
99
96
|
async for ticket in client.search.tickets("status:open priority:high", limit=10):
|
|
100
97
|
print(f"High priority: {ticket.subject}")
|
|
101
98
|
|
|
@@ -126,31 +123,48 @@ config = ZendeskConfig() # Will load from environment
|
|
|
126
123
|
|
|
127
124
|
## API Methods
|
|
128
125
|
|
|
126
|
+
### Pagination
|
|
127
|
+
|
|
128
|
+
All list methods return **Paginator** objects. Three ways to work with them:
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
# 1. Get specific page
|
|
132
|
+
paginator = client.users.list(per_page=20)
|
|
133
|
+
users = await paginator.get_page(2) # Get page 2
|
|
134
|
+
|
|
135
|
+
# 2. Iterate through all items
|
|
136
|
+
async for user in client.users.list():
|
|
137
|
+
print(user.name)
|
|
138
|
+
|
|
139
|
+
# 3. Collect to list
|
|
140
|
+
users = await client.users.list(limit=50).collect()
|
|
141
|
+
```
|
|
142
|
+
|
|
129
143
|
### Users
|
|
130
144
|
```python
|
|
131
145
|
user = await client.users.get(user_id) # Get user by ID
|
|
132
|
-
paginator = await client.users.list() # List users with pagination
|
|
133
146
|
user = await client.users.by_email(email) # Get user by email
|
|
134
147
|
users = await client.users.get_many([id1, id2]) # Get multiple users
|
|
148
|
+
paginator = client.users.list() # List users (paginator)
|
|
135
149
|
```
|
|
136
150
|
|
|
137
151
|
### Organizations
|
|
138
152
|
```python
|
|
139
153
|
org = await client.organizations.get(org_id) # Get organization by ID
|
|
140
|
-
paginator =
|
|
154
|
+
paginator = client.organizations.list() # List organizations (paginator)
|
|
141
155
|
```
|
|
142
156
|
|
|
143
157
|
### Tickets
|
|
144
158
|
```python
|
|
145
159
|
ticket = await client.tickets.get(ticket_id) # Get ticket by ID
|
|
146
|
-
paginator =
|
|
147
|
-
|
|
148
|
-
|
|
160
|
+
paginator = client.tickets.list() # List tickets (paginator)
|
|
161
|
+
paginator = client.tickets.for_user(user_id) # User's tickets (paginator)
|
|
162
|
+
paginator = client.tickets.for_organization(org_id) # Org's tickets (paginator)
|
|
149
163
|
```
|
|
150
164
|
|
|
151
165
|
### Comments (nested under tickets)
|
|
152
166
|
```python
|
|
153
|
-
|
|
167
|
+
paginator = client.tickets.comments.list(ticket_id) # List comments (paginator)
|
|
154
168
|
ticket = await client.tickets.comments.add(ticket_id, body, public=False)
|
|
155
169
|
await client.tickets.comments.make_private(ticket_id, comment_id)
|
|
156
170
|
comment = await client.tickets.comments.redact(ticket_id, comment_id, text)
|
|
@@ -205,14 +219,14 @@ await client.tickets.comments.add(ticket_id, "See attached", uploads=[token])
|
|
|
205
219
|
|
|
206
220
|
### Search
|
|
207
221
|
|
|
208
|
-
All search methods return **
|
|
222
|
+
All search methods return **Paginator** objects with the same interface as list methods.
|
|
209
223
|
|
|
210
224
|
#### Raw Queries (Zendesk syntax)
|
|
211
225
|
|
|
212
226
|
Use the same query syntax as in Zendesk UI — it just works:
|
|
213
227
|
|
|
214
228
|
```python
|
|
215
|
-
# Tickets
|
|
229
|
+
# Tickets - iterate through results
|
|
216
230
|
async for ticket in client.search.tickets("status:open priority:high"):
|
|
217
231
|
print(ticket.subject)
|
|
218
232
|
|
|
@@ -224,8 +238,8 @@ async for user in client.search.users("role:admin"):
|
|
|
224
238
|
async for org in client.search.organizations("tags:enterprise"):
|
|
225
239
|
print(org.name)
|
|
226
240
|
|
|
227
|
-
# Collect to list
|
|
228
|
-
|
|
241
|
+
# Collect to list with limit
|
|
242
|
+
tickets = await client.search.tickets("status:pending", limit=100).collect()
|
|
229
243
|
|
|
230
244
|
# Search with enrichment (loads comments + users)
|
|
231
245
|
async for item in client.tickets.search_enriched("status:open", limit=10):
|
|
@@ -325,7 +339,7 @@ Access Help Center (Guide) via `client.help_center` namespace:
|
|
|
325
339
|
#### Categories
|
|
326
340
|
```python
|
|
327
341
|
cat = await client.help_center.categories.get(category_id)
|
|
328
|
-
paginator =
|
|
342
|
+
paginator = client.help_center.categories.list() # Paginator
|
|
329
343
|
cat = await client.help_center.categories.create(name, description)
|
|
330
344
|
cat = await client.help_center.categories.update(category_id, name=new_name)
|
|
331
345
|
await client.help_center.categories.delete(category_id, force=True)
|
|
@@ -334,8 +348,8 @@ await client.help_center.categories.delete(category_id, force=True)
|
|
|
334
348
|
#### Sections
|
|
335
349
|
```python
|
|
336
350
|
sec = await client.help_center.sections.get(section_id)
|
|
337
|
-
paginator =
|
|
338
|
-
paginator =
|
|
351
|
+
paginator = client.help_center.sections.list() # Paginator
|
|
352
|
+
paginator = client.help_center.sections.for_category(category_id)
|
|
339
353
|
sec = await client.help_center.sections.create(category_id, name, description)
|
|
340
354
|
sec = await client.help_center.sections.update(section_id, name=new_name)
|
|
341
355
|
await client.help_center.sections.delete(section_id, force=True)
|
|
@@ -344,9 +358,9 @@ await client.help_center.sections.delete(section_id, force=True)
|
|
|
344
358
|
#### Articles
|
|
345
359
|
```python
|
|
346
360
|
art = await client.help_center.articles.get(article_id)
|
|
347
|
-
paginator =
|
|
348
|
-
paginator =
|
|
349
|
-
paginator =
|
|
361
|
+
paginator = client.help_center.articles.list() # Paginator
|
|
362
|
+
paginator = client.help_center.articles.for_section(section_id)
|
|
363
|
+
paginator = client.help_center.articles.for_category(category_id)
|
|
350
364
|
results = await client.help_center.articles.search(query)
|
|
351
365
|
art = await client.help_center.articles.create(section_id, title, body=html)
|
|
352
366
|
art = await client.help_center.articles.update(article_id, title=new_title)
|
|
@@ -359,8 +373,8 @@ async with ZendeskClient(config) as client:
|
|
|
359
373
|
hc = client.help_center
|
|
360
374
|
|
|
361
375
|
# Get permission_group_id from existing article (required for article creation)
|
|
362
|
-
existing = await
|
|
363
|
-
article_details = await hc.articles.get(existing[0]
|
|
376
|
+
existing = await hc.articles.list(per_page=1).get_page()
|
|
377
|
+
article_details = await hc.articles.get(existing[0].id)
|
|
364
378
|
permission_group_id = article_details.permission_group_id
|
|
365
379
|
|
|
366
380
|
# Create category -> section -> article hierarchy
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
This example demonstrates:
|
|
4
4
|
- Configuration setup
|
|
5
5
|
- Basic API operations (get users, tickets, organizations)
|
|
6
|
+
- Pagination basics
|
|
6
7
|
- Search functionality
|
|
7
8
|
"""
|
|
8
9
|
|
|
@@ -41,23 +42,23 @@ async def main() -> None:
|
|
|
41
42
|
ticket = await client.tickets.get(12345)
|
|
42
43
|
print(f"Ticket: {ticket.subject} (status: {ticket.status})")
|
|
43
44
|
|
|
44
|
-
# Get ticket comments
|
|
45
|
-
comments = await client.tickets.comments.list(12345)
|
|
46
|
-
print(f"Ticket has {len(comments)} comments")
|
|
45
|
+
# Get ticket comments (returns paginator)
|
|
46
|
+
comments = await client.tickets.comments.list(12345, limit=10).collect()
|
|
47
|
+
print(f"Ticket has {len(comments)} comments (limited to 10)")
|
|
47
48
|
|
|
48
49
|
# Get organization
|
|
49
50
|
org = await client.organizations.get(123)
|
|
50
51
|
print(f"Organization: {org.name}")
|
|
51
52
|
|
|
52
|
-
# Search for tickets (
|
|
53
|
+
# Search for tickets (paginator with async iteration)
|
|
53
54
|
count = 0
|
|
54
55
|
async for ticket in client.search.tickets("status:open", limit=10):
|
|
55
56
|
count += 1
|
|
56
57
|
print(f" Open ticket: {ticket.subject}")
|
|
57
58
|
print(f"Found {count} open tickets (limited to 10)")
|
|
58
59
|
|
|
59
|
-
#
|
|
60
|
-
admins =
|
|
60
|
+
# Collect search results to list
|
|
61
|
+
admins = await client.search.users("role:admin", limit=5).collect()
|
|
61
62
|
print(f"Found {len(admins)} admin users (limited to 5)")
|
|
62
63
|
|
|
63
64
|
|
|
@@ -85,9 +85,9 @@ async def demo_disabled_cache() -> None:
|
|
|
85
85
|
print(f"Cache enabled: {config.cache.enabled}")
|
|
86
86
|
|
|
87
87
|
# Both calls hit the API
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
print(
|
|
88
|
+
_ = await client.users.get(12345)
|
|
89
|
+
_ = await client.users.get(12345)
|
|
90
|
+
print("Both calls hit API - no caching")
|
|
91
91
|
|
|
92
92
|
# cache_info not available when caching is disabled
|
|
93
93
|
has_cache_info = hasattr(client.users.get, "cache_info")
|
|
@@ -19,6 +19,8 @@ async def main() -> None:
|
|
|
19
19
|
)
|
|
20
20
|
|
|
21
21
|
async with ZendeskClient(config) as client:
|
|
22
|
+
# ==================== Single enriched ticket ====================
|
|
23
|
+
|
|
22
24
|
# Get a single ticket with all related data
|
|
23
25
|
# This makes 2 API calls: ticket + comments (with sideloaded users)
|
|
24
26
|
enriched = await client.tickets.get_enriched(12345)
|
|
@@ -48,6 +50,8 @@ async def main() -> None:
|
|
|
48
50
|
else:
|
|
49
51
|
print(f" - Unknown: {body_preview}")
|
|
50
52
|
|
|
53
|
+
# ==================== Search with enrichment ====================
|
|
54
|
+
|
|
51
55
|
# Search for tickets and load all related data
|
|
52
56
|
# This efficiently batch-loads users using show_many endpoint
|
|
53
57
|
print("\n--- Searching tickets with enriched data ---")
|
|
@@ -57,25 +61,15 @@ async def main() -> None:
|
|
|
57
61
|
print(f" Assignee: {item.assignee.name if item.assignee else 'Unassigned'}")
|
|
58
62
|
print(f" Comments: {len(item.comments)}")
|
|
59
63
|
|
|
60
|
-
#
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
for item in
|
|
68
|
-
print(f"
|
|
69
|
-
|
|
70
|
-
# Get user's tickets with all related data
|
|
71
|
-
print("\n--- User tickets ---")
|
|
72
|
-
user_tickets = await client.tickets.for_user_enriched(
|
|
73
|
-
user_id=456,
|
|
74
|
-
per_page=10,
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
for item in user_tickets:
|
|
78
|
-
print(f"Ticket #{item.ticket.id}: {item.ticket.subject}")
|
|
64
|
+
# ==================== Collect enriched tickets ====================
|
|
65
|
+
|
|
66
|
+
# You can also collect enriched tickets to a list
|
|
67
|
+
print("\n--- Collecting enriched tickets ---")
|
|
68
|
+
enriched_tickets = [item async for item in client.tickets.search_enriched("status:pending", limit=5)]
|
|
69
|
+
print(f"Collected {len(enriched_tickets)} enriched tickets")
|
|
70
|
+
|
|
71
|
+
for item in enriched_tickets:
|
|
72
|
+
print(f" #{item.ticket.id}: {item.ticket.subject}")
|
|
79
73
|
|
|
80
74
|
|
|
81
75
|
if __name__ == "__main__":
|
|
@@ -69,7 +69,7 @@ async def main() -> None:
|
|
|
69
69
|
|
|
70
70
|
# Example: Handling specific HTTP status codes
|
|
71
71
|
try:
|
|
72
|
-
|
|
72
|
+
_ = await client.tickets.get(123)
|
|
73
73
|
except ZendeskHTTPException as e:
|
|
74
74
|
if e.status_code == 404:
|
|
75
75
|
print("Ticket not found")
|
|
@@ -92,8 +92,9 @@ async def retry_with_backoff() -> None:
|
|
|
92
92
|
max_attempts = 5
|
|
93
93
|
for attempt in range(max_attempts):
|
|
94
94
|
try:
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
# Search returns paginator - iterate to get results
|
|
96
|
+
tickets = await client.search.tickets("status:open", limit=10).collect()
|
|
97
|
+
print(f"Found {len(tickets)} tickets")
|
|
97
98
|
break
|
|
98
99
|
except ZendeskRateLimitException as e:
|
|
99
100
|
if attempt < max_attempts - 1:
|
|
@@ -26,34 +26,31 @@ async def main() -> None:
|
|
|
26
26
|
|
|
27
27
|
# ==================== Reading Content ====================
|
|
28
28
|
|
|
29
|
-
# List categories with pagination
|
|
29
|
+
# List categories with pagination (no await for list())
|
|
30
30
|
print("--- Categories ---")
|
|
31
|
-
|
|
32
|
-
categories = await categories_paginator.get_page()
|
|
31
|
+
categories = await hc.categories.list(per_page=10).get_page()
|
|
33
32
|
for cat in categories[:5]:
|
|
34
|
-
print(f"Category: {cat
|
|
33
|
+
print(f"Category: {cat.name} (ID: {cat.id})")
|
|
35
34
|
|
|
36
35
|
# Get specific category
|
|
37
36
|
if categories:
|
|
38
|
-
category = await hc.categories.get(categories[0]
|
|
37
|
+
category = await hc.categories.get(categories[0].id)
|
|
39
38
|
print(f"\nCategory details: {category.name}")
|
|
40
39
|
print(f"Description: {category.description}")
|
|
41
40
|
|
|
42
41
|
# List sections (all or by category)
|
|
43
42
|
print("\n--- Sections ---")
|
|
44
|
-
|
|
45
|
-
sections = await sections_paginator.get_page()
|
|
43
|
+
sections = await hc.sections.list(per_page=10).get_page()
|
|
46
44
|
for sec in sections[:5]:
|
|
47
|
-
print(f"Section: {sec
|
|
45
|
+
print(f"Section: {sec.name} (Category: {sec.category_id})")
|
|
48
46
|
|
|
49
47
|
# List articles in a section
|
|
50
48
|
if sections:
|
|
51
|
-
section_id = sections[0]
|
|
52
|
-
|
|
53
|
-
articles = await articles_paginator.get_page()
|
|
49
|
+
section_id = sections[0].id
|
|
50
|
+
articles = await hc.articles.for_section(section_id, per_page=10).get_page()
|
|
54
51
|
print(f"\nArticles in section {section_id}:")
|
|
55
52
|
for art in articles[:5]:
|
|
56
|
-
print(f" - {art
|
|
53
|
+
print(f" - {art.title}")
|
|
57
54
|
|
|
58
55
|
# ==================== Search ====================
|
|
59
56
|
|
|
@@ -84,11 +81,11 @@ async def main() -> None:
|
|
|
84
81
|
print(f"Created section: {new_section.name} (ID: {new_section.id})")
|
|
85
82
|
|
|
86
83
|
# Get permission_group_id from an existing article (required for creation)
|
|
87
|
-
existing_articles = await
|
|
84
|
+
existing_articles = await hc.articles.list(per_page=1).get_page()
|
|
88
85
|
if not existing_articles:
|
|
89
86
|
print("No existing articles to get permission_group_id from")
|
|
90
87
|
return
|
|
91
|
-
existing = await hc.articles.get(existing_articles[0]
|
|
88
|
+
existing = await hc.articles.get(existing_articles[0].id)
|
|
92
89
|
permission_group_id = existing.permission_group_id
|
|
93
90
|
|
|
94
91
|
# Create an article in the section
|
|
@@ -129,20 +126,25 @@ async def main() -> None:
|
|
|
129
126
|
await hc.categories.delete(new_category.id, force=True)
|
|
130
127
|
print("Deleted category (cascade deleted section and article)")
|
|
131
128
|
|
|
132
|
-
# ==================== Pagination ====================
|
|
129
|
+
# ==================== Pagination Examples ====================
|
|
133
130
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
131
|
+
print("\n--- Pagination Examples ---")
|
|
132
|
+
|
|
133
|
+
# Iterate through all articles
|
|
137
134
|
count = 0
|
|
138
|
-
async for
|
|
135
|
+
async for article in hc.articles.list(per_page=10):
|
|
139
136
|
count += 1
|
|
140
137
|
if count <= 3:
|
|
141
|
-
|
|
138
|
+
title = article.title[:40] if article.title else "Untitled"
|
|
139
|
+
print(f"Article {count}: {title}...")
|
|
142
140
|
if count >= 10:
|
|
143
141
|
print(f"... and more (stopped at {count})")
|
|
144
142
|
break
|
|
145
143
|
|
|
144
|
+
# Collect articles to list
|
|
145
|
+
all_articles = await hc.articles.list(limit=50).collect()
|
|
146
|
+
print(f"Collected {len(all_articles)} articles")
|
|
147
|
+
|
|
146
148
|
|
|
147
149
|
if __name__ == "__main__":
|
|
148
150
|
asyncio.run(main())
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""Pagination example for Zendesk SDK.
|
|
2
|
+
|
|
3
|
+
This example demonstrates three ways to work with paginators:
|
|
4
|
+
1. Get specific page
|
|
5
|
+
2. Iterate through all items
|
|
6
|
+
3. Collect to list
|
|
7
|
+
|
|
8
|
+
All list() and search() methods return Paginator objects.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import asyncio
|
|
12
|
+
|
|
13
|
+
from zendesk_sdk import ZendeskClient, ZendeskConfig
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
async def main() -> None:
|
|
17
|
+
config = ZendeskConfig(
|
|
18
|
+
subdomain="your-subdomain",
|
|
19
|
+
email="your-email@example.com",
|
|
20
|
+
token="your-api-token",
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
async with ZendeskClient(config) as client:
|
|
24
|
+
# ==================== Method 1: Get specific page ====================
|
|
25
|
+
|
|
26
|
+
print("=== Method 1: Get specific page ===")
|
|
27
|
+
|
|
28
|
+
# Create paginator (no await needed)
|
|
29
|
+
paginator = client.users.list(per_page=20)
|
|
30
|
+
|
|
31
|
+
# Get first page
|
|
32
|
+
first_page = await paginator.get_page()
|
|
33
|
+
print(f"First page: {len(first_page)} users")
|
|
34
|
+
|
|
35
|
+
# Get specific page by number
|
|
36
|
+
second_page = await paginator.get_page(page=2)
|
|
37
|
+
print(f"Second page: {len(second_page)} users")
|
|
38
|
+
|
|
39
|
+
# Check pagination info after fetching
|
|
40
|
+
if paginator.pagination_info:
|
|
41
|
+
print(f"Total count: {paginator.pagination_info.count}")
|
|
42
|
+
print(f"Has more: {paginator.pagination_info.has_more}")
|
|
43
|
+
|
|
44
|
+
# ==================== Method 2: Iterate through all ====================
|
|
45
|
+
|
|
46
|
+
print("\n=== Method 2: Iterate through all items ===")
|
|
47
|
+
|
|
48
|
+
# Iterate through all users (handles pagination automatically)
|
|
49
|
+
count = 0
|
|
50
|
+
async for user in client.users.list(per_page=100):
|
|
51
|
+
count += 1
|
|
52
|
+
if count <= 3:
|
|
53
|
+
print(f" User: {user.name}")
|
|
54
|
+
if count >= 100:
|
|
55
|
+
print(f" ... stopping at {count} users")
|
|
56
|
+
break
|
|
57
|
+
|
|
58
|
+
print(f"Iterated through {count} users")
|
|
59
|
+
|
|
60
|
+
# ==================== Method 3: Collect to list ====================
|
|
61
|
+
|
|
62
|
+
print("\n=== Method 3: Collect to list ===")
|
|
63
|
+
|
|
64
|
+
# Collect with limit
|
|
65
|
+
users = await client.users.list(limit=50).collect()
|
|
66
|
+
print(f"Collected {len(users)} users (limit=50)")
|
|
67
|
+
|
|
68
|
+
# Collect all (be careful with large datasets!)
|
|
69
|
+
# all_users = await client.users.list().collect()
|
|
70
|
+
|
|
71
|
+
# ==================== Pagination with search ====================
|
|
72
|
+
|
|
73
|
+
print("\n=== Pagination with search ===")
|
|
74
|
+
|
|
75
|
+
# Search also returns paginator
|
|
76
|
+
paginator = client.search.tickets("status:open", per_page=50)
|
|
77
|
+
|
|
78
|
+
# Get first page
|
|
79
|
+
open_tickets = await paginator.get_page()
|
|
80
|
+
print(f"Found {len(open_tickets)} open tickets on first page")
|
|
81
|
+
|
|
82
|
+
# Or iterate
|
|
83
|
+
async for ticket in client.search.tickets("priority:high", limit=10):
|
|
84
|
+
print(f" High priority: {ticket.subject}")
|
|
85
|
+
|
|
86
|
+
# Or collect
|
|
87
|
+
urgent = await client.search.tickets("priority:urgent", limit=20).collect()
|
|
88
|
+
print(f"Collected {len(urgent)} urgent tickets")
|
|
89
|
+
|
|
90
|
+
# ==================== Pagination info ====================
|
|
91
|
+
|
|
92
|
+
print("\n=== Pagination info ===")
|
|
93
|
+
|
|
94
|
+
paginator = client.tickets.list(per_page=10)
|
|
95
|
+
await paginator.get_page()
|
|
96
|
+
|
|
97
|
+
info = paginator.pagination_info
|
|
98
|
+
if info:
|
|
99
|
+
print(f"Page: {info.page}")
|
|
100
|
+
print(f"Per page: {info.per_page}")
|
|
101
|
+
print(f"Total count: {info.count}")
|
|
102
|
+
print(f"Has more: {info.has_more}")
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
if __name__ == "__main__":
|
|
106
|
+
asyncio.run(main())
|