python-zendesk-sdk 0.11.0__tar.gz → 0.12.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.
Files changed (60) hide show
  1. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/PKG-INFO +12 -1
  2. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/README.md +11 -0
  3. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/examples/groups.py +20 -0
  4. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/pyproject.toml +1 -1
  5. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/__init__.py +3 -1
  6. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/clients/groups.py +66 -1
  7. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/models/__init__.py +2 -0
  8. python_zendesk_sdk-0.12.0/src/zendesk_sdk/models/group_membership.py +31 -0
  9. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/pagination.py +27 -1
  10. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/tests/test_package_import.py +1 -1
  11. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/.flake8 +0 -0
  12. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/.github/workflows/publish.yml +0 -0
  13. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/.gitignore +0 -0
  14. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/.python-version +0 -0
  15. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/LICENSE +0 -0
  16. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/context7.json +0 -0
  17. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/examples/basic_usage.py +0 -0
  18. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/examples/caching.py +0 -0
  19. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/examples/enriched_tickets.py +0 -0
  20. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/examples/error_handling.py +0 -0
  21. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/examples/help_center.py +0 -0
  22. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/examples/organizations.py +0 -0
  23. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/examples/pagination_example.py +0 -0
  24. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/examples/search.py +0 -0
  25. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/examples/users.py +0 -0
  26. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/client.py +0 -0
  27. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/clients/__init__.py +0 -0
  28. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/clients/attachments.py +0 -0
  29. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/clients/base.py +0 -0
  30. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/clients/help_center/__init__.py +0 -0
  31. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/clients/help_center/articles.py +0 -0
  32. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/clients/help_center/categories.py +0 -0
  33. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/clients/help_center/sections.py +0 -0
  34. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/clients/organizations.py +0 -0
  35. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/clients/search.py +0 -0
  36. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/clients/ticket_fields.py +0 -0
  37. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/clients/tickets.py +0 -0
  38. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/clients/users.py +0 -0
  39. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/config.py +0 -0
  40. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/exceptions.py +0 -0
  41. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/http_client.py +0 -0
  42. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/models/base.py +0 -0
  43. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/models/comment.py +0 -0
  44. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/models/enriched_ticket.py +0 -0
  45. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/models/group.py +0 -0
  46. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/models/help_center.py +0 -0
  47. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/models/organization.py +0 -0
  48. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/models/search.py +0 -0
  49. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/models/ticket.py +0 -0
  50. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/src/zendesk_sdk/models/user.py +0 -0
  51. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/tests/__init__.py +0 -0
  52. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/tests/test_client.py +0 -0
  53. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/tests/test_clients.py +0 -0
  54. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/tests/test_config.py +0 -0
  55. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/tests/test_exceptions.py +0 -0
  56. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/tests/test_help_center_client.py +0 -0
  57. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/tests/test_http_client.py +0 -0
  58. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/tests/test_models.py +0 -0
  59. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.0}/tests/test_pagination.py +0 -0
  60. {python_zendesk_sdk-0.11.0 → python_zendesk_sdk-0.12.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.11.0
3
+ Version: 0.12.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
@@ -266,6 +266,17 @@ count = await client.groups.count() # Get total number of groups
266
266
  paginator = client.groups.list() # List all groups (paginator)
267
267
  paginator = client.groups.list_assignable() # List assignable groups (paginator)
268
268
 
269
+ # Memberships — find which agents belong to a group
270
+ paginator = client.groups.list_memberships() # All memberships (paginator)
271
+ paginator = client.groups.list_group_members(group_id) # Members of specific group (paginator)
272
+ membership = await client.groups.get_membership(membership_id) # Get specific membership
273
+
274
+ # Example: get all agents in a group
275
+ members = await client.groups.list_group_members(group_id).collect()
276
+ for m in members:
277
+ user = await client.users.get(m.user_id)
278
+ print(f" {user.name} (default={m.default})")
279
+
269
280
  # Create
270
281
  group = await client.groups.create(
271
282
  name="Support Team",
@@ -228,6 +228,17 @@ count = await client.groups.count() # Get total number of groups
228
228
  paginator = client.groups.list() # List all groups (paginator)
229
229
  paginator = client.groups.list_assignable() # List assignable groups (paginator)
230
230
 
231
+ # Memberships — find which agents belong to a group
232
+ paginator = client.groups.list_memberships() # All memberships (paginator)
233
+ paginator = client.groups.list_group_members(group_id) # Members of specific group (paginator)
234
+ membership = await client.groups.get_membership(membership_id) # Get specific membership
235
+
236
+ # Example: get all agents in a group
237
+ members = await client.groups.list_group_members(group_id).collect()
238
+ for m in members:
239
+ user = await client.users.get(m.user_id)
240
+ print(f" {user.name} (default={m.default})")
241
+
231
242
  # Create
232
243
  group = await client.groups.create(
233
244
  name="Support Team",
@@ -6,6 +6,7 @@ This example demonstrates:
6
6
  - Updating groups
7
7
  - Deleting groups
8
8
  - Listing assignable groups
9
+ - Group memberships (list members of a group)
9
10
  """
10
11
 
11
12
  import asyncio
@@ -97,6 +98,25 @@ async def main() -> None:
97
98
  await client.groups.delete(detailed_group.id)
98
99
  print(f"Deleted group: {detailed_group.id}")
99
100
 
101
+ # ==================== Membership Operations ====================
102
+
103
+ print("\n=== Membership Operations ===")
104
+
105
+ # List all memberships across all groups
106
+ print("All memberships:")
107
+ async for membership in client.groups.list_memberships(limit=10):
108
+ print(f" User {membership.user_id} -> Group {membership.group_id} (default={membership.default})")
109
+
110
+ # List members of a specific group
111
+ print("\nMembers of first group:")
112
+ first_group = groups[0] if groups else None
113
+ if first_group:
114
+ members = await client.groups.list_group_members(first_group.id).collect()
115
+ for m in members:
116
+ user = await client.users.get(m.user_id)
117
+ default_str = " [DEFAULT]" if m.default else ""
118
+ print(f" {user.name}{default_str}")
119
+
100
120
  # ==================== Caching Example ====================
101
121
 
102
122
  print("\n=== Caching Example ===")
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "python-zendesk-sdk"
3
- version = "0.11.0"
3
+ version = "0.12.0"
4
4
  description = "Modern Python SDK for Zendesk API"
5
5
  authors = [
6
6
  {name = "bormog"}
@@ -5,7 +5,7 @@ This package provides a clean, async-first interface to the Zendesk API
5
5
  with full type safety and comprehensive error handling.
6
6
  """
7
7
 
8
- __version__ = "0.11.0"
8
+ __version__ = "0.12.0"
9
9
 
10
10
  from .client import ZendeskClient
11
11
  from .clients import (
@@ -38,6 +38,7 @@ from .models import (
38
38
  Category,
39
39
  EnrichedTicket,
40
40
  Group,
41
+ GroupMembership,
41
42
  PasswordRequirements,
42
43
  SearchQueryConfig,
43
44
  SearchType,
@@ -76,6 +77,7 @@ __all__ = [
76
77
  "ArticlesClient",
77
78
  # Models
78
79
  "Group",
80
+ "GroupMembership",
79
81
  "EnrichedTicket",
80
82
  "TicketField",
81
83
  "Category",
@@ -2,7 +2,7 @@
2
2
 
3
3
  from typing import TYPE_CHECKING, Any, Callable, Dict, Optional
4
4
 
5
- from ..models import Group
5
+ from ..models import Group, GroupMembership
6
6
  from ..pagination import ZendeskPaginator
7
7
  from .base import BaseClient
8
8
 
@@ -300,3 +300,68 @@ class GroupsClient(BaseClient):
300
300
  """
301
301
  await self._delete(f"groups/{group_id}.json")
302
302
  return True
303
+
304
+ # ==================== Membership Operations ====================
305
+
306
+ def list_memberships(self, per_page: int = 100, limit: Optional[int] = None) -> "Paginator[GroupMembership]":
307
+ """Get paginated list of all group memberships.
308
+
309
+ Returns all group membership records across the entire account.
310
+
311
+ Args:
312
+ per_page: Number of memberships per API request (max 100).
313
+ limit: Maximum total memberships to return. None for no limit.
314
+
315
+ Returns:
316
+ Paginator[GroupMembership] for iterating through all memberships
317
+
318
+ Example:
319
+ async for membership in client.groups.list_memberships():
320
+ print(f"User {membership.user_id} in Group {membership.group_id}")
321
+ """
322
+ return ZendeskPaginator.create_group_memberships_paginator(self._http, per_page=per_page, limit=limit)
323
+
324
+ def list_group_members(
325
+ self, group_id: int, per_page: int = 100, limit: Optional[int] = None
326
+ ) -> "Paginator[GroupMembership]":
327
+ """Get paginated list of memberships for a specific group.
328
+
329
+ Returns membership records for agents in the given group.
330
+ Use this to find out which agents belong to a group.
331
+
332
+ Args:
333
+ group_id: The group's ID
334
+ per_page: Number of memberships per API request (max 100).
335
+ limit: Maximum total memberships to return. None for no limit.
336
+
337
+ Returns:
338
+ Paginator[GroupMembership] for iterating through group's memberships
339
+
340
+ Example:
341
+ # List all agents in a group
342
+ async for membership in client.groups.list_group_members(12345):
343
+ print(f"Agent {membership.user_id}, default={membership.default}")
344
+
345
+ # Collect all members
346
+ members = await client.groups.list_group_members(12345).collect()
347
+ user_ids = [m.user_id for m in members]
348
+ """
349
+ return ZendeskPaginator.create_group_memberships_by_group_paginator(
350
+ self._http, group_id, per_page=per_page, limit=limit
351
+ )
352
+
353
+ async def get_membership(self, membership_id: int) -> GroupMembership:
354
+ """Get a specific group membership by ID.
355
+
356
+ Args:
357
+ membership_id: The membership's ID
358
+
359
+ Returns:
360
+ GroupMembership object
361
+
362
+ Example:
363
+ membership = await client.groups.get_membership(99999)
364
+ print(f"User {membership.user_id} in Group {membership.group_id}")
365
+ """
366
+ response = await self._get(f"group_memberships/{membership_id}.json")
367
+ return GroupMembership(**response["group_membership"])
@@ -4,6 +4,7 @@ from .base import ZendeskModel
4
4
  from .comment import Comment, CommentAttachment, CommentMetadata, CommentVia
5
5
  from .enriched_ticket import EnrichedTicket
6
6
  from .group import Group
7
+ from .group_membership import GroupMembership
7
8
  from .help_center import Article, Category, Section
8
9
  from .organization import Organization, OrganizationField, OrganizationSubscription
9
10
  from .search import (
@@ -43,6 +44,7 @@ __all__ = [
43
44
  "PasswordRequirements",
44
45
  # Group models
45
46
  "Group",
47
+ "GroupMembership",
46
48
  # Organization models
47
49
  "Organization",
48
50
  "OrganizationField",
@@ -0,0 +1,31 @@
1
+ """Group Membership model for Zendesk API."""
2
+
3
+ from datetime import datetime
4
+ from typing import Optional
5
+
6
+ from pydantic import Field
7
+
8
+ from .base import ZendeskModel
9
+
10
+
11
+ class GroupMembership(ZendeskModel):
12
+ """Zendesk Group Membership model.
13
+
14
+ Represents the association between a user (agent) and a group.
15
+ Agents can be members of multiple groups, and one group is marked
16
+ as their default group for ticket assignment.
17
+ """
18
+
19
+ # Read-only fields
20
+ id: Optional[int] = Field(None, description="Automatically assigned when creating memberships")
21
+ url: Optional[str] = Field(None, description="The API url of the membership")
22
+ user_id: int = Field(..., description="The ID of the agent")
23
+ group_id: int = Field(..., description="The ID of the group")
24
+ default: Optional[bool] = Field(None, description="If true, tickets assigned directly to the agent use this group")
25
+ created_at: Optional[datetime] = Field(None, description="The time the membership was created")
26
+ updated_at: Optional[datetime] = Field(None, description="The time of the last update")
27
+
28
+ def __str__(self) -> str:
29
+ """Human-readable string representation."""
30
+ default_str = " (default)" if self.default else ""
31
+ return f"User {self.user_id} -> Group {self.group_id}{default_str} (id={self.id})"
@@ -5,7 +5,7 @@ from abc import ABC, abstractmethod
5
5
  from typing import Any, AsyncIterator, Dict, Generic, List, Optional, TypeVar
6
6
 
7
7
  from .exceptions import ZendeskPaginationException
8
- from .models import Article, Category, Comment, Group, Organization, Section, Ticket, TicketField, User
8
+ from .models import Article, Category, Comment, Group, GroupMembership, Organization, Section, Ticket, TicketField, User
9
9
 
10
10
  logger = logging.getLogger(__name__)
11
11
 
@@ -557,6 +557,32 @@ class ZendeskPaginator:
557
557
 
558
558
  return AssignableGroupsPaginator(http_client, "groups/assignable.json", per_page=per_page, limit=limit)
559
559
 
560
+ @staticmethod
561
+ def create_group_memberships_paginator(
562
+ http_client: Any, per_page: int = 100, limit: Optional[int] = None
563
+ ) -> OffsetPaginator[GroupMembership]:
564
+ """Create paginator for all group memberships endpoint."""
565
+
566
+ class GroupMembershipsPaginator(OffsetPaginator[GroupMembership]):
567
+ def _extract_items(self, response: Dict[str, Any]) -> List[GroupMembership]:
568
+ return [GroupMembership(**m) for m in response.get("group_memberships", [])]
569
+
570
+ return GroupMembershipsPaginator(http_client, "group_memberships.json", per_page=per_page, limit=limit)
571
+
572
+ @staticmethod
573
+ def create_group_memberships_by_group_paginator(
574
+ http_client: Any, group_id: int, per_page: int = 100, limit: Optional[int] = None
575
+ ) -> OffsetPaginator[GroupMembership]:
576
+ """Create paginator for memberships of a specific group."""
577
+
578
+ class GroupMembershipsByGroupPaginator(OffsetPaginator[GroupMembership]):
579
+ def _extract_items(self, response: Dict[str, Any]) -> List[GroupMembership]:
580
+ return [GroupMembership(**m) for m in response.get("group_memberships", [])]
581
+
582
+ return GroupMembershipsByGroupPaginator(
583
+ http_client, f"groups/{group_id}/memberships.json", per_page=per_page, limit=limit
584
+ )
585
+
560
586
  @staticmethod
561
587
  def create_ticket_fields_paginator(
562
588
  http_client: Any, per_page: int = 100, limit: Optional[int] = None
@@ -9,7 +9,7 @@ class TestPackageImport:
9
9
  import zendesk_sdk
10
10
 
11
11
  assert hasattr(zendesk_sdk, "__version__")
12
- assert zendesk_sdk.__version__ == "0.11.0"
12
+ assert zendesk_sdk.__version__ == "0.12.0"
13
13
 
14
14
  def test_client_import(self):
15
15
  """Test importing ZendeskClient."""