glpi-python-client 0.2.1__py3-none-any.whl → 0.3.0__py3-none-any.whl

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 (58) hide show
  1. glpi_python_client/__init__.py +15 -5
  2. glpi_python_client/clients/__init__.py +13 -6
  3. glpi_python_client/clients/api/__init__.py +21 -21
  4. glpi_python_client/clients/api/administration/__init__.py +6 -5
  5. glpi_python_client/clients/api/administration/_entity.py +15 -17
  6. glpi_python_client/clients/api/administration/_user.py +16 -16
  7. glpi_python_client/clients/api/assistance/__init__.py +4 -4
  8. glpi_python_client/clients/api/assistance/_team.py +11 -13
  9. glpi_python_client/clients/api/assistance/_ticket.py +15 -17
  10. glpi_python_client/clients/api/assistance/timeline/__init__.py +9 -9
  11. glpi_python_client/clients/api/assistance/timeline/_document.py +16 -16
  12. glpi_python_client/clients/api/assistance/timeline/_followup.py +16 -18
  13. glpi_python_client/clients/api/assistance/timeline/_solution.py +16 -18
  14. glpi_python_client/clients/api/assistance/timeline/_task.py +16 -18
  15. glpi_python_client/clients/api/dropdowns/__init__.py +3 -3
  16. glpi_python_client/clients/api/dropdowns/_location.py +15 -17
  17. glpi_python_client/clients/api/management/__init__.py +3 -3
  18. glpi_python_client/clients/api/management/_document.py +25 -28
  19. glpi_python_client/clients/async_client.py +241 -0
  20. glpi_python_client/clients/commons/_async_bridge.py +118 -0
  21. glpi_python_client/clients/commons/_config.py +2 -1
  22. glpi_python_client/clients/commons/_transport.py +89 -61
  23. glpi_python_client/clients/commons/tests/test_transport.py +136 -0
  24. glpi_python_client/clients/custom/__init__.py +20 -3
  25. glpi_python_client/clients/custom/_statistics.py +11 -14
  26. glpi_python_client/clients/custom/_statistics_async.py +69 -0
  27. glpi_python_client/clients/custom/_ticket_context.py +17 -16
  28. glpi_python_client/clients/custom/_ticket_context_async.py +73 -0
  29. glpi_python_client/clients/custom/tests/test_statistics.py +14 -16
  30. glpi_python_client/clients/custom/tests/test_ticket_context.py +57 -0
  31. glpi_python_client/clients/{glpi_client.py → sync_client.py} +55 -54
  32. glpi_python_client/clients/tests/test_api_coverage.py +87 -87
  33. glpi_python_client/clients/tests/test_async_branches.py +137 -0
  34. glpi_python_client/clients/tests/test_async_smoke.py +150 -0
  35. glpi_python_client/clients/tests/test_glpi_client.py +14 -14
  36. glpi_python_client/clients/tests/test_parity.py +64 -0
  37. glpi_python_client/clients/tests/test_smoke.py +28 -28
  38. glpi_python_client/models/__init__.py +5 -1
  39. glpi_python_client/models/api_schema/administration/_entity.py +44 -4
  40. glpi_python_client/models/api_schema/administration/_user.py +237 -12
  41. glpi_python_client/models/api_schema/administration/tests/test_administration_schemas.py +31 -0
  42. glpi_python_client/models/api_schema/assistance/_team.py +36 -11
  43. glpi_python_client/models/api_schema/assistance/_ticket.py +199 -10
  44. glpi_python_client/models/api_schema/assistance/timeline/_document.py +46 -4
  45. glpi_python_client/models/api_schema/assistance/timeline/_followup.py +92 -4
  46. glpi_python_client/models/api_schema/assistance/timeline/_solution.py +84 -4
  47. glpi_python_client/models/api_schema/assistance/timeline/_task.py +117 -4
  48. glpi_python_client/models/api_schema/dropdowns/_location.py +111 -4
  49. glpi_python_client/models/api_schema/management/_document.py +67 -4
  50. glpi_python_client/models/custom_schema/__init__.py +2 -1
  51. glpi_python_client/models/custom_schema/_ticket_context.py +143 -39
  52. glpi_python_client/models/custom_schema/tests/test_ticket_context.py +189 -1
  53. glpi_python_client/testing/fixtures.py +1 -1
  54. glpi_python_client/testing/utils.py +15 -2
  55. {glpi_python_client-0.2.1.dist-info → glpi_python_client-0.3.0.dist-info}/METADATA +58 -36
  56. {glpi_python_client-0.2.1.dist-info → glpi_python_client-0.3.0.dist-info}/RECORD +58 -49
  57. {glpi_python_client-0.2.1.dist-info → glpi_python_client-0.3.0.dist-info}/WHEEL +0 -0
  58. {glpi_python_client-0.2.1.dist-info → glpi_python_client-0.3.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,13 +1,20 @@
1
1
  """Public import surface for the GLPI Python client package.
2
2
 
3
- The package re-exports the asynchronous :class:`GlpiClient` and the
4
- ``api_schema`` and ``custom_schema`` Pydantic models so downstream users
5
- can import them from a single stable package root.
3
+ The package re-exports two client classes:
4
+
5
+ * :class:`GlpiClient` — synchronous, blocking client (single source of
6
+ truth for endpoint behaviour).
7
+ * :class:`AsyncGlpiClient` — asynchronous facade that wraps each
8
+ synchronous method into a coroutine.
9
+
10
+ The ``api_schema`` and ``custom_schema`` Pydantic models are also
11
+ re-exported so downstream users can import them from a single stable
12
+ package root.
6
13
  """
7
14
 
8
15
  from __future__ import annotations
9
16
 
10
- from glpi_python_client.clients import GlpiClient
17
+ from glpi_python_client.clients import AsyncGlpiClient, GlpiClient
11
18
  from glpi_python_client.models import (
12
19
  DeleteDocument,
13
20
  DeleteEntity,
@@ -62,11 +69,13 @@ from glpi_python_client.models import (
62
69
  PostTicketTask,
63
70
  PostTimelineDocument,
64
71
  PostUser,
72
+ TicketMarkdownOptions,
65
73
  )
66
74
 
67
- __version__ = "0.2.1"
75
+ __version__ = "0.3.0"
68
76
 
69
77
  __all__ = [
78
+ "AsyncGlpiClient",
70
79
  "DeleteDocument",
71
80
  "DeleteEntity",
72
81
  "DeleteFollowup",
@@ -121,5 +130,6 @@ __all__ = [
121
130
  "PostTicketTask",
122
131
  "PostTimelineDocument",
123
132
  "PostUser",
133
+ "TicketMarkdownOptions",
124
134
  "__version__",
125
135
  ]
@@ -1,13 +1,20 @@
1
1
  """Public client exports for the GLPI Python package.
2
2
 
3
- Only one client class is supported: the asynchronous
4
- :class:`glpi_python_client.clients.glpi_client.GlpiClient`. The legacy
5
- synchronous and dual-stack clients have been removed in favour of the
6
- async-only design described in ``update.md``.
3
+ The package exposes two client classes:
4
+
5
+ * :class:`GlpiClient` — synchronous, blocking client. The single source
6
+ of truth for endpoint behaviour.
7
+ * :class:`AsyncGlpiClient` — asynchronous facade that wraps every
8
+ synchronous method into a coroutine via
9
+ :class:`~glpi_python_client.clients.commons._async_bridge.AsyncBridge`.
10
+
11
+ Both classes share the same endpoint surface; pick the one matching
12
+ your runtime model.
7
13
  """
8
14
 
9
15
  from __future__ import annotations
10
16
 
11
- from glpi_python_client.clients.glpi_client import GlpiClient
17
+ from glpi_python_client.clients.async_client import AsyncGlpiClient
18
+ from glpi_python_client.clients.sync_client import GlpiClient
12
19
 
13
- __all__ = ["GlpiClient"]
20
+ __all__ = ["AsyncGlpiClient", "GlpiClient"]
@@ -1,7 +1,7 @@
1
1
  """Per-endpoint API mixins backed by the ``api_schema`` Pydantic models.
2
2
 
3
3
  The mixins under this package mirror the endpoints documented in
4
- ``docs/glpi_api_contract.json`` one for one. They wrap the asynchronous
4
+ ``docs/glpi_api_contract.json`` one for one. They wrap the Synchronous
5
5
  transport helpers from :mod:`glpi_python_client.clients.commons` and exchange
6
6
  typed ``Get<Name>``, ``Post<Name>``, ``Patch<Name>``, and ``Delete<Name>``
7
7
  models with the GLPI API.
@@ -10,31 +10,31 @@ models with the GLPI API.
10
10
  from __future__ import annotations
11
11
 
12
12
  from glpi_python_client.clients.api.administration import (
13
- AsyncEntityMixin,
14
- AsyncUserMixin,
13
+ EntityMixin,
14
+ UserMixin,
15
15
  )
16
16
  from glpi_python_client.clients.api.assistance import (
17
- AsyncTeamMemberMixin,
18
- AsyncTicketMixin,
17
+ TeamMemberMixin,
18
+ TicketMixin,
19
19
  )
20
20
  from glpi_python_client.clients.api.assistance.timeline import (
21
- AsyncFollowupMixin,
22
- AsyncSolutionMixin,
23
- AsyncTicketTaskMixin,
24
- AsyncTimelineDocumentMixin,
21
+ FollowupMixin,
22
+ SolutionMixin,
23
+ TicketTaskMixin,
24
+ TimelineDocumentMixin,
25
25
  )
26
- from glpi_python_client.clients.api.dropdowns import AsyncLocationMixin
27
- from glpi_python_client.clients.api.management import AsyncDocumentMixin
26
+ from glpi_python_client.clients.api.dropdowns import LocationMixin
27
+ from glpi_python_client.clients.api.management import DocumentMixin
28
28
 
29
29
  __all__ = [
30
- "AsyncDocumentMixin",
31
- "AsyncEntityMixin",
32
- "AsyncFollowupMixin",
33
- "AsyncLocationMixin",
34
- "AsyncSolutionMixin",
35
- "AsyncTeamMemberMixin",
36
- "AsyncTicketMixin",
37
- "AsyncTicketTaskMixin",
38
- "AsyncTimelineDocumentMixin",
39
- "AsyncUserMixin",
30
+ "DocumentMixin",
31
+ "EntityMixin",
32
+ "FollowupMixin",
33
+ "LocationMixin",
34
+ "SolutionMixin",
35
+ "TeamMemberMixin",
36
+ "TicketMixin",
37
+ "TicketTaskMixin",
38
+ "TimelineDocumentMixin",
39
+ "UserMixin",
40
40
  ]
@@ -1,12 +1,13 @@
1
- """GLPI ``/Administration`` mixins for the asynchronous client.
1
+ """GLPI ``/Administration`` mixins for the Synchronous client.
2
2
 
3
3
  The submodules expose the user and entity mixins used by
4
- :class:`glpi_python_client.clients.glpi_client.GlpiClient`.
4
+ :class:`glpi_python_client.clients.sync_client.GlpiClient` and
5
+ :class:`glpi_python_client.clients.async_client.AsyncGlpiClient`.
5
6
  """
6
7
 
7
8
  from __future__ import annotations
8
9
 
9
- from glpi_python_client.clients.api.administration._entity import AsyncEntityMixin
10
- from glpi_python_client.clients.api.administration._user import AsyncUserMixin
10
+ from glpi_python_client.clients.api.administration._entity import EntityMixin
11
+ from glpi_python_client.clients.api.administration._user import UserMixin
11
12
 
12
- __all__ = ["AsyncEntityMixin", "AsyncUserMixin"]
13
+ __all__ = ["EntityMixin", "UserMixin"]
@@ -1,4 +1,4 @@
1
- """Asynchronous GLPI ``/Administration/Entity`` mixin.
1
+ """Synchronous GLPI ``/Administration/Entity`` mixin.
2
2
 
3
3
  The mixin exposes the search, fetch, create, update, and delete helpers
4
4
  for the GLPI entity resource. Entity calls intentionally bypass the
@@ -8,7 +8,7 @@ client's ``GLPI-Entity`` header so cross-entity lookups remain possible.
8
8
  from __future__ import annotations
9
9
 
10
10
  from glpi_python_client.clients.commons._constants import ENTITY_ENDPOINT, GlpiId
11
- from glpi_python_client.clients.commons._transport import AsyncTransportMixin
11
+ from glpi_python_client.clients.commons._transport import TransportMixin
12
12
  from glpi_python_client.models.api_schema.administration._entity import (
13
13
  DeleteEntity,
14
14
  GetEntity,
@@ -17,10 +17,10 @@ from glpi_python_client.models.api_schema.administration._entity import (
17
17
  )
18
18
 
19
19
 
20
- class AsyncEntityMixin(AsyncTransportMixin):
21
- """Asynchronous CRUD helpers for ``/Administration/Entity``."""
20
+ class EntityMixin(TransportMixin):
21
+ """Synchronous CRUD helpers for ``/Administration/Entity``."""
22
22
 
23
- async def search_entities(
23
+ def search_entities(
24
24
  self,
25
25
  rsql_filter: str = "",
26
26
  *,
@@ -50,11 +50,11 @@ class AsyncEntityMixin(AsyncTransportMixin):
50
50
  params["limit"] = limit
51
51
  if rsql_filter:
52
52
  params["filter"] = rsql_filter
53
- return await self._resource_list(
53
+ return self._resource_list(
54
54
  ENTITY_ENDPOINT, GetEntity, params=params, skip_entity=True
55
55
  )
56
56
 
57
- async def get_entity(self, entity_id: GlpiId) -> GetEntity:
57
+ def get_entity(self, entity_id: GlpiId) -> GetEntity:
58
58
  """Fetch one GLPI entity by identifier.
59
59
 
60
60
  Parameters
@@ -73,14 +73,14 @@ class AsyncEntityMixin(AsyncTransportMixin):
73
73
  If the GLPI server returns a non-success HTTP status.
74
74
  """
75
75
 
76
- return await self._resource_get(
76
+ return self._resource_get(
77
77
  f"{ENTITY_ENDPOINT}/{entity_id}",
78
78
  GetEntity,
79
79
  failure_message=f"Failed to get entity {entity_id}",
80
80
  skip_entity=True,
81
81
  )
82
82
 
83
- async def create_entity(self, entity: PostEntity) -> int:
83
+ def create_entity(self, entity: PostEntity) -> int:
84
84
  """Create one GLPI entity.
85
85
 
86
86
  Parameters
@@ -100,7 +100,7 @@ class AsyncEntityMixin(AsyncTransportMixin):
100
100
  non-success HTTP status.
101
101
  """
102
102
 
103
- return await self._resource_create(
103
+ return self._resource_create(
104
104
  ENTITY_ENDPOINT,
105
105
  entity,
106
106
  failure_message="Failed to create entity",
@@ -109,7 +109,7 @@ class AsyncEntityMixin(AsyncTransportMixin):
109
109
  skip_entity=True,
110
110
  )
111
111
 
112
- async def update_entity(self, entity_id: GlpiId, entity: PatchEntity) -> None:
112
+ def update_entity(self, entity_id: GlpiId, entity: PatchEntity) -> None:
113
113
  """Update one GLPI entity with a partial body.
114
114
 
115
115
  Parameters
@@ -129,16 +129,14 @@ class AsyncEntityMixin(AsyncTransportMixin):
129
129
  If the GLPI server returns a non-success HTTP status.
130
130
  """
131
131
 
132
- await self._resource_update(
132
+ self._resource_update(
133
133
  f"{ENTITY_ENDPOINT}/{entity_id}",
134
134
  entity,
135
135
  failure_message=f"Failed to update entity {entity_id}",
136
136
  log_message=f"GLPI API updated entity {entity_id}",
137
137
  )
138
138
 
139
- async def delete_entity(
140
- self, entity_id: GlpiId, *, force: bool | None = None
141
- ) -> None:
139
+ def delete_entity(self, entity_id: GlpiId, *, force: bool | None = None) -> None:
142
140
  """Delete one GLPI entity by identifier.
143
141
 
144
142
  Parameters
@@ -159,7 +157,7 @@ class AsyncEntityMixin(AsyncTransportMixin):
159
157
  If the GLPI server returns a non-success HTTP status.
160
158
  """
161
159
 
162
- await self._resource_delete(
160
+ self._resource_delete(
163
161
  f"{ENTITY_ENDPOINT}/{entity_id}",
164
162
  failure_message=f"Failed to delete entity {entity_id}",
165
163
  log_message=f"GLPI API deleted entity {entity_id}",
@@ -169,4 +167,4 @@ class AsyncEntityMixin(AsyncTransportMixin):
169
167
  )
170
168
 
171
169
 
172
- __all__ = ["AsyncEntityMixin"]
170
+ __all__ = ["EntityMixin"]
@@ -1,15 +1,15 @@
1
- """Asynchronous GLPI ``/Administration/User`` mixin.
1
+ """Synchronous GLPI ``/Administration/User`` mixin.
2
2
 
3
3
  The mixin exposes search, fetch, create, update, and delete helpers for the
4
4
  GLPI user resource. All operations exchange the
5
5
  :mod:`glpi_python_client.models.api_schema.administration` models and rely on
6
- the asynchronous transport mixin for HTTP dispatch.
6
+ the Synchronous transport mixin for HTTP dispatch.
7
7
  """
8
8
 
9
9
  from __future__ import annotations
10
10
 
11
11
  from glpi_python_client.clients.commons._constants import USER_ENDPOINT, GlpiId
12
- from glpi_python_client.clients.commons._transport import AsyncTransportMixin
12
+ from glpi_python_client.clients.commons._transport import TransportMixin
13
13
  from glpi_python_client.models.api_schema.administration._user import (
14
14
  DeleteUser,
15
15
  GetUser,
@@ -18,15 +18,15 @@ from glpi_python_client.models.api_schema.administration._user import (
18
18
  )
19
19
 
20
20
 
21
- class AsyncUserMixin(AsyncTransportMixin):
22
- """Asynchronous CRUD helpers for ``/Administration/User``.
21
+ class UserMixin(TransportMixin):
22
+ """Synchronous CRUD helpers for ``/Administration/User``.
23
23
 
24
24
  The helpers follow the contract-first naming convention and forward all
25
25
  server-side validation to the GLPI API instead of duplicating checks on
26
26
  the client side.
27
27
  """
28
28
 
29
- async def search_users(
29
+ def search_users(
30
30
  self,
31
31
  rsql_filter: str = "",
32
32
  *,
@@ -59,11 +59,11 @@ class AsyncUserMixin(AsyncTransportMixin):
59
59
  params: dict[str, object] = {"limit": limit, "start": start}
60
60
  if rsql_filter:
61
61
  params["filter"] = rsql_filter
62
- return await self._resource_list(
62
+ return self._resource_list(
63
63
  USER_ENDPOINT, GetUser, params=params, skip_entity=skip_entity
64
64
  )
65
65
 
66
- async def get_user(self, user_id: GlpiId) -> GetUser:
66
+ def get_user(self, user_id: GlpiId) -> GetUser:
67
67
  """Fetch one GLPI user by identifier.
68
68
 
69
69
  Parameters
@@ -82,13 +82,13 @@ class AsyncUserMixin(AsyncTransportMixin):
82
82
  If the GLPI server returns a non-success HTTP status.
83
83
  """
84
84
 
85
- return await self._resource_get(
85
+ return self._resource_get(
86
86
  f"{USER_ENDPOINT}/{user_id}",
87
87
  GetUser,
88
88
  failure_message=f"Failed to get user {user_id}",
89
89
  )
90
90
 
91
- async def create_user(self, user: PostUser) -> int:
91
+ def create_user(self, user: PostUser) -> int:
92
92
  """Create one GLPI user.
93
93
 
94
94
  Parameters
@@ -108,7 +108,7 @@ class AsyncUserMixin(AsyncTransportMixin):
108
108
  non-success HTTP status.
109
109
  """
110
110
 
111
- return await self._resource_create(
111
+ return self._resource_create(
112
112
  USER_ENDPOINT,
113
113
  user,
114
114
  failure_message="Failed to create user",
@@ -116,7 +116,7 @@ class AsyncUserMixin(AsyncTransportMixin):
116
116
  log_message_factory=lambda new_id: f"GLPI API created user {new_id}",
117
117
  )
118
118
 
119
- async def update_user(self, user_id: GlpiId, user: PatchUser) -> None:
119
+ def update_user(self, user_id: GlpiId, user: PatchUser) -> None:
120
120
  """Update one GLPI user with a partial body.
121
121
 
122
122
  Parameters
@@ -136,14 +136,14 @@ class AsyncUserMixin(AsyncTransportMixin):
136
136
  If the GLPI server returns a non-success HTTP status.
137
137
  """
138
138
 
139
- await self._resource_update(
139
+ self._resource_update(
140
140
  f"{USER_ENDPOINT}/{user_id}",
141
141
  user,
142
142
  failure_message=f"Failed to update user {user_id}",
143
143
  log_message=f"GLPI API updated user {user_id}",
144
144
  )
145
145
 
146
- async def delete_user(self, user_id: GlpiId, *, force: bool | None = None) -> None:
146
+ def delete_user(self, user_id: GlpiId, *, force: bool | None = None) -> None:
147
147
  """Delete one GLPI user by identifier.
148
148
 
149
149
  Parameters
@@ -164,7 +164,7 @@ class AsyncUserMixin(AsyncTransportMixin):
164
164
  If the GLPI server returns a non-success HTTP status.
165
165
  """
166
166
 
167
- await self._resource_delete(
167
+ self._resource_delete(
168
168
  f"{USER_ENDPOINT}/{user_id}",
169
169
  failure_message=f"Failed to delete user {user_id}",
170
170
  log_message=f"GLPI API deleted user {user_id}",
@@ -173,4 +173,4 @@ class AsyncUserMixin(AsyncTransportMixin):
173
173
  )
174
174
 
175
175
 
176
- __all__ = ["AsyncUserMixin"]
176
+ __all__ = ["UserMixin"]
@@ -1,8 +1,8 @@
1
- """GLPI ``/Assistance`` mixins for the asynchronous client."""
1
+ """GLPI ``/Assistance`` mixins for the Synchronous client."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from glpi_python_client.clients.api.assistance._team import AsyncTeamMemberMixin
6
- from glpi_python_client.clients.api.assistance._ticket import AsyncTicketMixin
5
+ from glpi_python_client.clients.api.assistance._team import TeamMemberMixin
6
+ from glpi_python_client.clients.api.assistance._ticket import TicketMixin
7
7
 
8
- __all__ = ["AsyncTeamMemberMixin", "AsyncTicketMixin"]
8
+ __all__ = ["TeamMemberMixin", "TicketMixin"]
@@ -1,4 +1,4 @@
1
- """Asynchronous GLPI ``/Assistance/Ticket/{id}/TeamMember`` mixin.
1
+ """Synchronous GLPI ``/Assistance/Ticket/{id}/TeamMember`` mixin.
2
2
 
3
3
  The team-member endpoint exposes list, add, and remove operations on a
4
4
  ticket. The mixin uses the ``api_schema`` ``TeamMember`` models and lets
@@ -16,7 +16,7 @@ from glpi_python_client.clients.commons._constants import (
16
16
  )
17
17
  from glpi_python_client.clients.commons._http import ensure_response_status
18
18
  from glpi_python_client.clients.commons._payloads import model_to_payload
19
- from glpi_python_client.clients.commons._transport import AsyncTransportMixin
19
+ from glpi_python_client.clients.commons._transport import TransportMixin
20
20
  from glpi_python_client.models.api_schema.assistance._team import (
21
21
  GetTeamMember,
22
22
  PostTeamMember,
@@ -25,10 +25,10 @@ from glpi_python_client.models.api_schema.assistance._team import (
25
25
  logger = logging.getLogger(__name__)
26
26
 
27
27
 
28
- class AsyncTeamMemberMixin(AsyncTransportMixin):
29
- """Asynchronous helpers for the ticket team-member endpoint."""
28
+ class TeamMemberMixin(TransportMixin):
29
+ """Synchronous helpers for the ticket team-member endpoint."""
30
30
 
31
- async def list_ticket_team_members(self, ticket_id: GlpiId) -> list[GetTeamMember]:
31
+ def list_ticket_team_members(self, ticket_id: GlpiId) -> list[GetTeamMember]:
32
32
  """List the team members currently linked to one ticket.
33
33
 
34
34
  Parameters
@@ -47,15 +47,13 @@ class AsyncTeamMemberMixin(AsyncTransportMixin):
47
47
  If the GLPI server returns a non-success HTTP status.
48
48
  """
49
49
 
50
- return await self._resource_list(
50
+ return self._resource_list(
51
51
  f"{TICKET_ENDPOINT}/{ticket_id}/{TEAM_MEMBER_SUFFIX}",
52
52
  GetTeamMember,
53
53
  failure_message=f"Failed to list ticket team members for {ticket_id}",
54
54
  )
55
55
 
56
- async def add_ticket_team_member(
57
- self, ticket_id: GlpiId, member: PostTeamMember
58
- ) -> None:
56
+ def add_ticket_team_member(self, ticket_id: GlpiId, member: PostTeamMember) -> None:
59
57
  """Add one team member to a ticket.
60
58
 
61
59
  Parameters
@@ -79,7 +77,7 @@ class AsyncTeamMemberMixin(AsyncTransportMixin):
79
77
  """
80
78
 
81
79
  endpoint = f"{TICKET_ENDPOINT}/{ticket_id}/{TEAM_MEMBER_SUFFIX}"
82
- response = await self._post_request(endpoint, model_to_payload(member))
80
+ response = self._post_request(endpoint, model_to_payload(member))
83
81
  ensure_response_status(
84
82
  response,
85
83
  success_statuses=(200, 201),
@@ -87,7 +85,7 @@ class AsyncTeamMemberMixin(AsyncTransportMixin):
87
85
  )
88
86
  logger.info("GLPI API added team member on ticket %s", ticket_id)
89
87
 
90
- async def remove_ticket_team_member(
88
+ def remove_ticket_team_member(
91
89
  self, ticket_id: GlpiId, member: PostTeamMember
92
90
  ) -> None:
93
91
  """Remove one team member from a ticket.
@@ -110,7 +108,7 @@ class AsyncTeamMemberMixin(AsyncTransportMixin):
110
108
  If the GLPI server returns a non-success HTTP status.
111
109
  """
112
110
 
113
- await self._resource_delete(
111
+ self._resource_delete(
114
112
  f"{TICKET_ENDPOINT}/{ticket_id}/{TEAM_MEMBER_SUFFIX}",
115
113
  failure_message=f"Failed to remove team member on ticket {ticket_id}",
116
114
  log_message=f"GLPI API removed team member on ticket {ticket_id}",
@@ -118,4 +116,4 @@ class AsyncTeamMemberMixin(AsyncTransportMixin):
118
116
  )
119
117
 
120
118
 
121
- __all__ = ["AsyncTeamMemberMixin"]
119
+ __all__ = ["TeamMemberMixin"]
@@ -1,4 +1,4 @@
1
- """Asynchronous GLPI ``/Assistance/Ticket`` mixin.
1
+ """Synchronous GLPI ``/Assistance/Ticket`` mixin.
2
2
 
3
3
  The mixin exposes search, fetch, create, update, and delete helpers for the
4
4
  GLPI ticket resource using the ``api_schema`` Pydantic models.
@@ -7,7 +7,7 @@ GLPI ticket resource using the ``api_schema`` Pydantic models.
7
7
  from __future__ import annotations
8
8
 
9
9
  from glpi_python_client.clients.commons._constants import TICKET_ENDPOINT, GlpiId
10
- from glpi_python_client.clients.commons._transport import AsyncTransportMixin
10
+ from glpi_python_client.clients.commons._transport import TransportMixin
11
11
  from glpi_python_client.models.api_schema.assistance._ticket import (
12
12
  DeleteTicket,
13
13
  GetTicket,
@@ -16,15 +16,15 @@ from glpi_python_client.models.api_schema.assistance._ticket import (
16
16
  )
17
17
 
18
18
 
19
- class AsyncTicketMixin(AsyncTransportMixin):
20
- """Asynchronous CRUD helpers for ``/Assistance/Ticket``.
19
+ class TicketMixin(TransportMixin):
20
+ """Synchronous CRUD helpers for ``/Assistance/Ticket``.
21
21
 
22
22
  The helpers exchange the contract-aligned ``GetTicket``, ``PostTicket``,
23
23
  ``PatchTicket``, and ``DeleteTicket`` models with the GLPI API and let the
24
24
  server perform all field-level validation.
25
25
  """
26
26
 
27
- async def search_tickets(
27
+ def search_tickets(
28
28
  self,
29
29
  rsql_filter: str = "",
30
30
  *,
@@ -66,9 +66,9 @@ class AsyncTicketMixin(AsyncTransportMixin):
66
66
  params["sort"] = sort
67
67
  if fields:
68
68
  params["fields"] = ",".join(fields)
69
- return await self._resource_list(TICKET_ENDPOINT, GetTicket, params=params)
69
+ return self._resource_list(TICKET_ENDPOINT, GetTicket, params=params)
70
70
 
71
- async def get_ticket(self, ticket_id: GlpiId) -> GetTicket:
71
+ def get_ticket(self, ticket_id: GlpiId) -> GetTicket:
72
72
  """Fetch one GLPI ticket by identifier.
73
73
 
74
74
  Parameters
@@ -87,13 +87,13 @@ class AsyncTicketMixin(AsyncTransportMixin):
87
87
  If the GLPI server returns a non-success HTTP status.
88
88
  """
89
89
 
90
- return await self._resource_get(
90
+ return self._resource_get(
91
91
  f"{TICKET_ENDPOINT}/{ticket_id}",
92
92
  GetTicket,
93
93
  failure_message=f"Failed to get ticket {ticket_id}",
94
94
  )
95
95
 
96
- async def create_ticket(self, ticket: PostTicket) -> int:
96
+ def create_ticket(self, ticket: PostTicket) -> int:
97
97
  """Create one GLPI ticket.
98
98
 
99
99
  Parameters
@@ -114,7 +114,7 @@ class AsyncTicketMixin(AsyncTransportMixin):
114
114
  HTTP status is not success.
115
115
  """
116
116
 
117
- return await self._resource_create(
117
+ return self._resource_create(
118
118
  TICKET_ENDPOINT,
119
119
  ticket,
120
120
  failure_message="Failed to create ticket",
@@ -122,7 +122,7 @@ class AsyncTicketMixin(AsyncTransportMixin):
122
122
  log_message_factory=lambda new_id: f"GLPI API created ticket {new_id}",
123
123
  )
124
124
 
125
- async def update_ticket(self, ticket_id: GlpiId, ticket: PatchTicket) -> None:
125
+ def update_ticket(self, ticket_id: GlpiId, ticket: PatchTicket) -> None:
126
126
  """Update one GLPI ticket with a partial body.
127
127
 
128
128
  Parameters
@@ -142,16 +142,14 @@ class AsyncTicketMixin(AsyncTransportMixin):
142
142
  If the GLPI server returns a non-success HTTP status.
143
143
  """
144
144
 
145
- await self._resource_update(
145
+ self._resource_update(
146
146
  f"{TICKET_ENDPOINT}/{ticket_id}",
147
147
  ticket,
148
148
  failure_message=f"Failed to update ticket {ticket_id}",
149
149
  log_message=f"GLPI API updated ticket {ticket_id}",
150
150
  )
151
151
 
152
- async def delete_ticket(
153
- self, ticket_id: GlpiId, *, force: bool | None = None
154
- ) -> None:
152
+ def delete_ticket(self, ticket_id: GlpiId, *, force: bool | None = None) -> None:
155
153
  """Delete one GLPI ticket by identifier.
156
154
 
157
155
  Parameters
@@ -173,7 +171,7 @@ class AsyncTicketMixin(AsyncTransportMixin):
173
171
  If the GLPI server returns a non-success HTTP status.
174
172
  """
175
173
 
176
- await self._resource_delete(
174
+ self._resource_delete(
177
175
  f"{TICKET_ENDPOINT}/{ticket_id}",
178
176
  failure_message=f"Failed to delete ticket {ticket_id}",
179
177
  log_message=f"GLPI API deleted ticket {ticket_id}",
@@ -182,4 +180,4 @@ class AsyncTicketMixin(AsyncTransportMixin):
182
180
  )
183
181
 
184
182
 
185
- __all__ = ["AsyncTicketMixin"]
183
+ __all__ = ["TicketMixin"]
@@ -1,23 +1,23 @@
1
- """GLPI ticket-timeline mixins for the asynchronous client."""
1
+ """GLPI ticket-timeline mixins for the Synchronous client."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
5
  from glpi_python_client.clients.api.assistance.timeline._document import (
6
- AsyncTimelineDocumentMixin,
6
+ TimelineDocumentMixin,
7
7
  )
8
8
  from glpi_python_client.clients.api.assistance.timeline._followup import (
9
- AsyncFollowupMixin,
9
+ FollowupMixin,
10
10
  )
11
11
  from glpi_python_client.clients.api.assistance.timeline._solution import (
12
- AsyncSolutionMixin,
12
+ SolutionMixin,
13
13
  )
14
14
  from glpi_python_client.clients.api.assistance.timeline._task import (
15
- AsyncTicketTaskMixin,
15
+ TicketTaskMixin,
16
16
  )
17
17
 
18
18
  __all__ = [
19
- "AsyncFollowupMixin",
20
- "AsyncSolutionMixin",
21
- "AsyncTicketTaskMixin",
22
- "AsyncTimelineDocumentMixin",
19
+ "FollowupMixin",
20
+ "SolutionMixin",
21
+ "TicketTaskMixin",
22
+ "TimelineDocumentMixin",
23
23
  ]