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.
- glpi_python_client/__init__.py +15 -5
- glpi_python_client/clients/__init__.py +13 -6
- glpi_python_client/clients/api/__init__.py +21 -21
- glpi_python_client/clients/api/administration/__init__.py +6 -5
- glpi_python_client/clients/api/administration/_entity.py +15 -17
- glpi_python_client/clients/api/administration/_user.py +16 -16
- glpi_python_client/clients/api/assistance/__init__.py +4 -4
- glpi_python_client/clients/api/assistance/_team.py +11 -13
- glpi_python_client/clients/api/assistance/_ticket.py +15 -17
- glpi_python_client/clients/api/assistance/timeline/__init__.py +9 -9
- glpi_python_client/clients/api/assistance/timeline/_document.py +16 -16
- glpi_python_client/clients/api/assistance/timeline/_followup.py +16 -18
- glpi_python_client/clients/api/assistance/timeline/_solution.py +16 -18
- glpi_python_client/clients/api/assistance/timeline/_task.py +16 -18
- glpi_python_client/clients/api/dropdowns/__init__.py +3 -3
- glpi_python_client/clients/api/dropdowns/_location.py +15 -17
- glpi_python_client/clients/api/management/__init__.py +3 -3
- glpi_python_client/clients/api/management/_document.py +25 -28
- glpi_python_client/clients/async_client.py +241 -0
- glpi_python_client/clients/commons/_async_bridge.py +118 -0
- glpi_python_client/clients/commons/_config.py +2 -1
- glpi_python_client/clients/commons/_transport.py +89 -61
- glpi_python_client/clients/commons/tests/test_transport.py +136 -0
- glpi_python_client/clients/custom/__init__.py +20 -3
- glpi_python_client/clients/custom/_statistics.py +11 -14
- glpi_python_client/clients/custom/_statistics_async.py +69 -0
- glpi_python_client/clients/custom/_ticket_context.py +17 -16
- glpi_python_client/clients/custom/_ticket_context_async.py +73 -0
- glpi_python_client/clients/custom/tests/test_statistics.py +14 -16
- glpi_python_client/clients/custom/tests/test_ticket_context.py +57 -0
- glpi_python_client/clients/{glpi_client.py → sync_client.py} +55 -54
- glpi_python_client/clients/tests/test_api_coverage.py +87 -87
- glpi_python_client/clients/tests/test_async_branches.py +137 -0
- glpi_python_client/clients/tests/test_async_smoke.py +150 -0
- glpi_python_client/clients/tests/test_glpi_client.py +14 -14
- glpi_python_client/clients/tests/test_parity.py +64 -0
- glpi_python_client/clients/tests/test_smoke.py +28 -28
- glpi_python_client/models/__init__.py +5 -1
- glpi_python_client/models/api_schema/administration/_entity.py +44 -4
- glpi_python_client/models/api_schema/administration/_user.py +237 -12
- glpi_python_client/models/api_schema/administration/tests/test_administration_schemas.py +31 -0
- glpi_python_client/models/api_schema/assistance/_team.py +36 -11
- glpi_python_client/models/api_schema/assistance/_ticket.py +199 -10
- glpi_python_client/models/api_schema/assistance/timeline/_document.py +46 -4
- glpi_python_client/models/api_schema/assistance/timeline/_followup.py +92 -4
- glpi_python_client/models/api_schema/assistance/timeline/_solution.py +84 -4
- glpi_python_client/models/api_schema/assistance/timeline/_task.py +117 -4
- glpi_python_client/models/api_schema/dropdowns/_location.py +111 -4
- glpi_python_client/models/api_schema/management/_document.py +67 -4
- glpi_python_client/models/custom_schema/__init__.py +2 -1
- glpi_python_client/models/custom_schema/_ticket_context.py +143 -39
- glpi_python_client/models/custom_schema/tests/test_ticket_context.py +189 -1
- glpi_python_client/testing/fixtures.py +1 -1
- glpi_python_client/testing/utils.py +15 -2
- {glpi_python_client-0.2.1.dist-info → glpi_python_client-0.3.0.dist-info}/METADATA +58 -36
- {glpi_python_client-0.2.1.dist-info → glpi_python_client-0.3.0.dist-info}/RECORD +58 -49
- {glpi_python_client-0.2.1.dist-info → glpi_python_client-0.3.0.dist-info}/WHEEL +0 -0
- {glpi_python_client-0.2.1.dist-info → glpi_python_client-0.3.0.dist-info}/licenses/LICENSE +0 -0
glpi_python_client/__init__.py
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
"""Public import surface for the GLPI Python client package.
|
|
2
2
|
|
|
3
|
-
The package re-exports
|
|
4
|
-
|
|
5
|
-
|
|
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.
|
|
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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
14
|
-
|
|
13
|
+
EntityMixin,
|
|
14
|
+
UserMixin,
|
|
15
15
|
)
|
|
16
16
|
from glpi_python_client.clients.api.assistance import (
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
TeamMemberMixin,
|
|
18
|
+
TicketMixin,
|
|
19
19
|
)
|
|
20
20
|
from glpi_python_client.clients.api.assistance.timeline import (
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
FollowupMixin,
|
|
22
|
+
SolutionMixin,
|
|
23
|
+
TicketTaskMixin,
|
|
24
|
+
TimelineDocumentMixin,
|
|
25
25
|
)
|
|
26
|
-
from glpi_python_client.clients.api.dropdowns import
|
|
27
|
-
from glpi_python_client.clients.api.management import
|
|
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
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
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
|
|
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.
|
|
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
|
|
10
|
-
from glpi_python_client.clients.api.administration._user import
|
|
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__ = ["
|
|
13
|
+
__all__ = ["EntityMixin", "UserMixin"]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
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
|
|
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
|
|
21
|
-
"""
|
|
20
|
+
class EntityMixin(TransportMixin):
|
|
21
|
+
"""Synchronous CRUD helpers for ``/Administration/Entity``."""
|
|
22
22
|
|
|
23
|
-
|
|
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
|
|
53
|
+
return self._resource_list(
|
|
54
54
|
ENTITY_ENDPOINT, GetEntity, params=params, skip_entity=True
|
|
55
55
|
)
|
|
56
56
|
|
|
57
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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__ = ["
|
|
170
|
+
__all__ = ["EntityMixin"]
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
"""
|
|
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
|
|
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
|
|
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
|
|
22
|
-
"""
|
|
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
|
-
|
|
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
|
|
62
|
+
return self._resource_list(
|
|
63
63
|
USER_ENDPOINT, GetUser, params=params, skip_entity=skip_entity
|
|
64
64
|
)
|
|
65
65
|
|
|
66
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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__ = ["
|
|
176
|
+
__all__ = ["UserMixin"]
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
"""GLPI ``/Assistance`` mixins for the
|
|
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
|
|
6
|
-
from glpi_python_client.clients.api.assistance._ticket import
|
|
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__ = ["
|
|
8
|
+
__all__ = ["TeamMemberMixin", "TicketMixin"]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
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
|
|
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
|
|
29
|
-
"""
|
|
28
|
+
class TeamMemberMixin(TransportMixin):
|
|
29
|
+
"""Synchronous helpers for the ticket team-member endpoint."""
|
|
30
30
|
|
|
31
|
-
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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__ = ["
|
|
119
|
+
__all__ = ["TeamMemberMixin"]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
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
|
|
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
|
|
20
|
-
"""
|
|
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
|
-
|
|
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
|
|
69
|
+
return self._resource_list(TICKET_ENDPOINT, GetTicket, params=params)
|
|
70
70
|
|
|
71
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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__ = ["
|
|
183
|
+
__all__ = ["TicketMixin"]
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
"""GLPI ticket-timeline mixins for the
|
|
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
|
-
|
|
6
|
+
TimelineDocumentMixin,
|
|
7
7
|
)
|
|
8
8
|
from glpi_python_client.clients.api.assistance.timeline._followup import (
|
|
9
|
-
|
|
9
|
+
FollowupMixin,
|
|
10
10
|
)
|
|
11
11
|
from glpi_python_client.clients.api.assistance.timeline._solution import (
|
|
12
|
-
|
|
12
|
+
SolutionMixin,
|
|
13
13
|
)
|
|
14
14
|
from glpi_python_client.clients.api.assistance.timeline._task import (
|
|
15
|
-
|
|
15
|
+
TicketTaskMixin,
|
|
16
16
|
)
|
|
17
17
|
|
|
18
18
|
__all__ = [
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
19
|
+
"FollowupMixin",
|
|
20
|
+
"SolutionMixin",
|
|
21
|
+
"TicketTaskMixin",
|
|
22
|
+
"TimelineDocumentMixin",
|
|
23
23
|
]
|