glpi-python-client 0.6.4__py3-none-any.whl → 0.6.6__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 +9 -1
- glpi_python_client/_async/clients/api/__init__.py +2 -0
- glpi_python_client/_async/clients/api/administration/__init__.py +3 -2
- glpi_python_client/_async/clients/api/administration/_group.py +218 -0
- glpi_python_client/_async/clients/client.py +2 -0
- glpi_python_client/_async/clients/commons/_constants.py +2 -0
- glpi_python_client/_sync/clients/api/__init__.py +2 -0
- glpi_python_client/_sync/clients/api/administration/__init__.py +3 -2
- glpi_python_client/_sync/clients/api/administration/_group.py +218 -0
- glpi_python_client/_sync/clients/client.py +2 -0
- glpi_python_client/_sync/clients/commons/_constants.py +2 -0
- glpi_python_client/content/conversion.py +59 -0
- glpi_python_client/models/__init__.py +8 -0
- glpi_python_client/models/api_schema/administration/__init__.py +13 -2
- glpi_python_client/models/api_schema/administration/_group.py +150 -0
- glpi_python_client/models/api_schema/management/_document.py +14 -0
- {glpi_python_client-0.6.4.dist-info → glpi_python_client-0.6.6.dist-info}/METADATA +1 -1
- {glpi_python_client-0.6.4.dist-info → glpi_python_client-0.6.6.dist-info}/RECORD +20 -17
- {glpi_python_client-0.6.4.dist-info → glpi_python_client-0.6.6.dist-info}/WHEEL +1 -1
- {glpi_python_client-0.6.4.dist-info → glpi_python_client-0.6.6.dist-info}/licenses/LICENSE +0 -0
glpi_python_client/__init__.py
CHANGED
|
@@ -40,6 +40,7 @@ from glpi_python_client.models import (
|
|
|
40
40
|
DeleteDocument,
|
|
41
41
|
DeleteEntity,
|
|
42
42
|
DeleteFollowup,
|
|
43
|
+
DeleteGroup,
|
|
43
44
|
DeleteKBArticle,
|
|
44
45
|
DeleteKBArticleComment,
|
|
45
46
|
DeleteKBCategory,
|
|
@@ -60,6 +61,7 @@ from glpi_python_client.models import (
|
|
|
60
61
|
GetDocumentItem,
|
|
61
62
|
GetEntity,
|
|
62
63
|
GetFollowup,
|
|
64
|
+
GetGroup,
|
|
63
65
|
GetKBArticle,
|
|
64
66
|
GetKBArticleComment,
|
|
65
67
|
GetKBArticleRevision,
|
|
@@ -96,6 +98,7 @@ from glpi_python_client.models import (
|
|
|
96
98
|
PatchDocument,
|
|
97
99
|
PatchEntity,
|
|
98
100
|
PatchFollowup,
|
|
101
|
+
PatchGroup,
|
|
99
102
|
PatchKBArticle,
|
|
100
103
|
PatchKBArticleComment,
|
|
101
104
|
PatchKBCategory,
|
|
@@ -114,6 +117,7 @@ from glpi_python_client.models import (
|
|
|
114
117
|
PostDocument,
|
|
115
118
|
PostEntity,
|
|
116
119
|
PostFollowup,
|
|
120
|
+
PostGroup,
|
|
117
121
|
PostKBArticle,
|
|
118
122
|
PostKBArticleComment,
|
|
119
123
|
PostKBCategory,
|
|
@@ -133,7 +137,7 @@ from glpi_python_client.rsql import (
|
|
|
133
137
|
date_window,
|
|
134
138
|
)
|
|
135
139
|
|
|
136
|
-
__version__ = "0.6.
|
|
140
|
+
__version__ = "0.6.6"
|
|
137
141
|
|
|
138
142
|
__all__ = [
|
|
139
143
|
"AsyncGlpiClient",
|
|
@@ -145,6 +149,7 @@ __all__ = [
|
|
|
145
149
|
"DeleteDocument",
|
|
146
150
|
"DeleteEntity",
|
|
147
151
|
"DeleteFollowup",
|
|
152
|
+
"DeleteGroup",
|
|
148
153
|
"DeleteKBArticle",
|
|
149
154
|
"DeleteKBArticleComment",
|
|
150
155
|
"DeleteKBCategory",
|
|
@@ -165,6 +170,7 @@ __all__ = [
|
|
|
165
170
|
"GetDocumentItem",
|
|
166
171
|
"GetEntity",
|
|
167
172
|
"GetFollowup",
|
|
173
|
+
"GetGroup",
|
|
168
174
|
"GetKBArticle",
|
|
169
175
|
"GetKBArticleComment",
|
|
170
176
|
"GetKBArticleRevision",
|
|
@@ -212,6 +218,7 @@ __all__ = [
|
|
|
212
218
|
"PatchDocument",
|
|
213
219
|
"PatchEntity",
|
|
214
220
|
"PatchFollowup",
|
|
221
|
+
"PatchGroup",
|
|
215
222
|
"PatchKBArticle",
|
|
216
223
|
"PatchKBArticleComment",
|
|
217
224
|
"PatchKBCategory",
|
|
@@ -230,6 +237,7 @@ __all__ = [
|
|
|
230
237
|
"PostDocument",
|
|
231
238
|
"PostEntity",
|
|
232
239
|
"PostFollowup",
|
|
240
|
+
"PostGroup",
|
|
233
241
|
"PostKBArticle",
|
|
234
242
|
"PostKBArticleComment",
|
|
235
243
|
"PostKBCategory",
|
|
@@ -11,6 +11,7 @@ from __future__ import annotations
|
|
|
11
11
|
|
|
12
12
|
from glpi_python_client._async.clients.api.administration import (
|
|
13
13
|
EntityMixin,
|
|
14
|
+
GroupMixin,
|
|
14
15
|
UserMixin,
|
|
15
16
|
)
|
|
16
17
|
from glpi_python_client._async.clients.api.assets import ComputerMixin
|
|
@@ -49,6 +50,7 @@ __all__ = [
|
|
|
49
50
|
"DocumentMixin",
|
|
50
51
|
"EntityMixin",
|
|
51
52
|
"FollowupMixin",
|
|
53
|
+
"GroupMixin",
|
|
52
54
|
"KBArticleCommentMixin",
|
|
53
55
|
"KBArticleMixin",
|
|
54
56
|
"KBArticleRevisionMixin",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""GLPI ``/Administration`` mixins for the GLPI client.
|
|
2
2
|
|
|
3
|
-
The submodules expose the user and
|
|
3
|
+
The submodules expose the user, entity and group mixins used by this tree's
|
|
4
4
|
client -- :class:`glpi_python_client.AsyncGlpiClient` on the async
|
|
5
5
|
surface, :class:`glpi_python_client.GlpiClient` on the generated one.
|
|
6
6
|
"""
|
|
@@ -8,6 +8,7 @@ surface, :class:`glpi_python_client.GlpiClient` on the generated one.
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
10
|
from glpi_python_client._async.clients.api.administration._entity import EntityMixin
|
|
11
|
+
from glpi_python_client._async.clients.api.administration._group import GroupMixin
|
|
11
12
|
from glpi_python_client._async.clients.api.administration._user import UserMixin
|
|
12
13
|
|
|
13
|
-
__all__ = ["EntityMixin", "UserMixin"]
|
|
14
|
+
__all__ = ["EntityMixin", "GroupMixin", "UserMixin"]
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"""GLPI ``/Administration/Group`` mixin.
|
|
2
|
+
|
|
3
|
+
The mixin exposes search, fetch, create, update, and delete helpers for the
|
|
4
|
+
GLPI group resource. Every call sends the client's ``GLPI-Entity`` header
|
|
5
|
+
(and the profile and recursion headers that travel with it) except where a
|
|
6
|
+
search is told to skip it with ``skip_entity=True``.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from collections.abc import AsyncIterator
|
|
12
|
+
|
|
13
|
+
from glpi_python_client._async.clients.commons._constants import GROUP_ENDPOINT, GlpiId
|
|
14
|
+
from glpi_python_client._async.clients.commons._transport import TransportMixin
|
|
15
|
+
from glpi_python_client.models.api_schema.administration._group import (
|
|
16
|
+
DeleteGroup,
|
|
17
|
+
GetGroup,
|
|
18
|
+
PatchGroup,
|
|
19
|
+
PostGroup,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class GroupMixin(TransportMixin):
|
|
24
|
+
"""CRUD helpers for ``/Administration/Group``."""
|
|
25
|
+
|
|
26
|
+
async def search_groups(
|
|
27
|
+
self,
|
|
28
|
+
rsql_filter: str = "",
|
|
29
|
+
*,
|
|
30
|
+
limit: int = 50,
|
|
31
|
+
start: int = 0,
|
|
32
|
+
skip_entity: bool = False,
|
|
33
|
+
) -> list[GetGroup]:
|
|
34
|
+
"""Search GLPI groups with an optional RSQL filter.
|
|
35
|
+
|
|
36
|
+
Parameters
|
|
37
|
+
----------
|
|
38
|
+
rsql_filter : str, optional
|
|
39
|
+
Raw RSQL filter forwarded as the ``filter`` query parameter,
|
|
40
|
+
for example ``"name==Support"``. Empty by default.
|
|
41
|
+
limit : int, optional
|
|
42
|
+
Maximum number of records returned by the GLPI server.
|
|
43
|
+
start : int, optional
|
|
44
|
+
Zero-based offset of the first record returned.
|
|
45
|
+
skip_entity : bool, optional
|
|
46
|
+
When ``True`` the ``GLPI-Entity`` header is omitted so the
|
|
47
|
+
search spans every entity the caller has access to.
|
|
48
|
+
|
|
49
|
+
Returns
|
|
50
|
+
-------
|
|
51
|
+
list[GetGroup]
|
|
52
|
+
Groups matching the filter.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
params: dict[str, object] = {"limit": limit, "start": start}
|
|
56
|
+
if rsql_filter:
|
|
57
|
+
params["filter"] = rsql_filter
|
|
58
|
+
return await self._resource_list(
|
|
59
|
+
GROUP_ENDPOINT, GetGroup, params=params, skip_entity=skip_entity
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
async def iter_search_groups(
|
|
63
|
+
self,
|
|
64
|
+
rsql_filter: str = "",
|
|
65
|
+
*,
|
|
66
|
+
batch_size: int = 50,
|
|
67
|
+
skip_entity: bool = False,
|
|
68
|
+
) -> AsyncIterator[list[GetGroup]]:
|
|
69
|
+
"""Yield successive pages of GLPI groups until exhausted.
|
|
70
|
+
|
|
71
|
+
Pagination advances the ``start`` offset after each batch and stops
|
|
72
|
+
when the server returns fewer items than ``batch_size``.
|
|
73
|
+
|
|
74
|
+
Parameters
|
|
75
|
+
----------
|
|
76
|
+
rsql_filter : str, optional
|
|
77
|
+
Raw RSQL filter forwarded as the ``filter`` query parameter.
|
|
78
|
+
batch_size : int, optional
|
|
79
|
+
Number of records requested per page (default 50).
|
|
80
|
+
skip_entity : bool, optional
|
|
81
|
+
When ``True`` the ``GLPI-Entity`` header is omitted so the
|
|
82
|
+
search spans every entity the caller has access to.
|
|
83
|
+
|
|
84
|
+
Yields
|
|
85
|
+
------
|
|
86
|
+
list[GetGroup]
|
|
87
|
+
One page of groups per iteration. The last yielded batch may
|
|
88
|
+
be shorter than ``batch_size``.
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
start = 0
|
|
92
|
+
while True:
|
|
93
|
+
batch = await self.search_groups(
|
|
94
|
+
rsql_filter,
|
|
95
|
+
limit=batch_size,
|
|
96
|
+
start=start,
|
|
97
|
+
skip_entity=skip_entity,
|
|
98
|
+
)
|
|
99
|
+
if batch:
|
|
100
|
+
yield batch
|
|
101
|
+
if len(batch) < batch_size:
|
|
102
|
+
break
|
|
103
|
+
start += batch_size
|
|
104
|
+
|
|
105
|
+
async def get_group(self, group_id: GlpiId) -> GetGroup:
|
|
106
|
+
"""Fetch one GLPI group by identifier.
|
|
107
|
+
|
|
108
|
+
Parameters
|
|
109
|
+
----------
|
|
110
|
+
group_id : GlpiId
|
|
111
|
+
Numeric identifier of the group to retrieve.
|
|
112
|
+
|
|
113
|
+
Returns
|
|
114
|
+
-------
|
|
115
|
+
GetGroup
|
|
116
|
+
Validated group payload.
|
|
117
|
+
|
|
118
|
+
Raises
|
|
119
|
+
------
|
|
120
|
+
GlpiStatusError
|
|
121
|
+
If the GLPI server returns a non-success HTTP status.
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
return await self._resource_get(
|
|
125
|
+
f"{GROUP_ENDPOINT}/{group_id}",
|
|
126
|
+
GetGroup,
|
|
127
|
+
failure_message=f"Failed to get group {group_id}",
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
async def create_group(self, group: PostGroup) -> int:
|
|
131
|
+
"""Create one GLPI group.
|
|
132
|
+
|
|
133
|
+
Parameters
|
|
134
|
+
----------
|
|
135
|
+
group : PostGroup
|
|
136
|
+
Request body describing the group to create.
|
|
137
|
+
|
|
138
|
+
Returns
|
|
139
|
+
-------
|
|
140
|
+
int
|
|
141
|
+
Identifier assigned by the GLPI server.
|
|
142
|
+
|
|
143
|
+
Raises
|
|
144
|
+
------
|
|
145
|
+
GlpiStatusError
|
|
146
|
+
If the GLPI server returns a non-success HTTP status.
|
|
147
|
+
GlpiProtocolError
|
|
148
|
+
If the create response is missing the ``id`` field.
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
return await self._resource_create(
|
|
152
|
+
GROUP_ENDPOINT,
|
|
153
|
+
group,
|
|
154
|
+
failure_message="Failed to create group",
|
|
155
|
+
missing_message="GLPI group create response did not include an ID",
|
|
156
|
+
log_message_factory=lambda new_id: f"GLPI API created group {new_id}",
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
async def update_group(self, group_id: GlpiId, group: PatchGroup) -> None:
|
|
160
|
+
"""Update one GLPI group with a partial body.
|
|
161
|
+
|
|
162
|
+
Parameters
|
|
163
|
+
----------
|
|
164
|
+
group_id : GlpiId
|
|
165
|
+
Numeric identifier of the group to update.
|
|
166
|
+
group : PatchGroup
|
|
167
|
+
Partial request body.
|
|
168
|
+
|
|
169
|
+
Returns
|
|
170
|
+
-------
|
|
171
|
+
None
|
|
172
|
+
|
|
173
|
+
Raises
|
|
174
|
+
------
|
|
175
|
+
GlpiStatusError
|
|
176
|
+
If the GLPI server returns a non-success HTTP status.
|
|
177
|
+
"""
|
|
178
|
+
|
|
179
|
+
await self._resource_update(
|
|
180
|
+
f"{GROUP_ENDPOINT}/{group_id}",
|
|
181
|
+
group,
|
|
182
|
+
failure_message=f"Failed to update group {group_id}",
|
|
183
|
+
log_message=f"GLPI API updated group {group_id}",
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
async def delete_group(
|
|
187
|
+
self, group_id: GlpiId, *, force: bool | None = None
|
|
188
|
+
) -> None:
|
|
189
|
+
"""Delete one GLPI group by identifier.
|
|
190
|
+
|
|
191
|
+
Parameters
|
|
192
|
+
----------
|
|
193
|
+
group_id : GlpiId
|
|
194
|
+
Numeric identifier of the group to delete.
|
|
195
|
+
force : bool | None, optional
|
|
196
|
+
When ``True`` the group is permanently deleted instead of
|
|
197
|
+
being moved to the trash.
|
|
198
|
+
|
|
199
|
+
Returns
|
|
200
|
+
-------
|
|
201
|
+
None
|
|
202
|
+
|
|
203
|
+
Raises
|
|
204
|
+
------
|
|
205
|
+
GlpiStatusError
|
|
206
|
+
If the GLPI server returns a non-success HTTP status.
|
|
207
|
+
"""
|
|
208
|
+
|
|
209
|
+
await self._resource_delete(
|
|
210
|
+
f"{GROUP_ENDPOINT}/{group_id}",
|
|
211
|
+
failure_message=f"Failed to delete group {group_id}",
|
|
212
|
+
log_message=f"GLPI API deleted group {group_id}",
|
|
213
|
+
force=force,
|
|
214
|
+
delete_model_cls=DeleteGroup,
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
__all__ = ["GroupMixin"]
|
|
@@ -25,6 +25,7 @@ from glpi_python_client._async.clients.api import (
|
|
|
25
25
|
DocumentMixin,
|
|
26
26
|
EntityMixin,
|
|
27
27
|
FollowupMixin,
|
|
28
|
+
GroupMixin,
|
|
28
29
|
KBArticleCommentMixin,
|
|
29
30
|
KBArticleMixin,
|
|
30
31
|
KBArticleRevisionMixin,
|
|
@@ -59,6 +60,7 @@ class AsyncGlpiClient(
|
|
|
59
60
|
ComputerMixin,
|
|
60
61
|
UserMixin,
|
|
61
62
|
EntityMixin,
|
|
63
|
+
GroupMixin,
|
|
62
64
|
LocationMixin,
|
|
63
65
|
ContractTypeMixin,
|
|
64
66
|
KBCategoryMixin,
|
|
@@ -19,6 +19,7 @@ COMPUTER_ENDPOINT = "Assets/Computer"
|
|
|
19
19
|
# administration/
|
|
20
20
|
USER_ENDPOINT = "Administration/User"
|
|
21
21
|
ENTITY_ENDPOINT = "Administration/Entity"
|
|
22
|
+
GROUP_ENDPOINT = "Administration/Group"
|
|
22
23
|
|
|
23
24
|
# dropdowns/
|
|
24
25
|
CONTRACT_TYPE_ENDPOINT = "Dropdowns/ContractType"
|
|
@@ -52,6 +53,7 @@ __all__ = [
|
|
|
52
53
|
"DOCUMENT_ENDPOINT",
|
|
53
54
|
"ENTITY_ENDPOINT",
|
|
54
55
|
"FOLLOWUP_SUFFIX",
|
|
56
|
+
"GROUP_ENDPOINT",
|
|
55
57
|
"KB_ARTICLE_ENDPOINT",
|
|
56
58
|
"KB_CATEGORY_ENDPOINT",
|
|
57
59
|
"KB_COMMENT_SUFFIX",
|
|
@@ -11,6 +11,7 @@ from __future__ import annotations
|
|
|
11
11
|
|
|
12
12
|
from glpi_python_client._sync.clients.api.administration import (
|
|
13
13
|
EntityMixin,
|
|
14
|
+
GroupMixin,
|
|
14
15
|
UserMixin,
|
|
15
16
|
)
|
|
16
17
|
from glpi_python_client._sync.clients.api.assets import ComputerMixin
|
|
@@ -49,6 +50,7 @@ __all__ = [
|
|
|
49
50
|
"DocumentMixin",
|
|
50
51
|
"EntityMixin",
|
|
51
52
|
"FollowupMixin",
|
|
53
|
+
"GroupMixin",
|
|
52
54
|
"KBArticleCommentMixin",
|
|
53
55
|
"KBArticleMixin",
|
|
54
56
|
"KBArticleRevisionMixin",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""GLPI ``/Administration`` mixins for the GLPI client.
|
|
2
2
|
|
|
3
|
-
The submodules expose the user and
|
|
3
|
+
The submodules expose the user, entity and group mixins used by this tree's
|
|
4
4
|
client -- :class:`glpi_python_client.AsyncGlpiClient` on the async
|
|
5
5
|
surface, :class:`glpi_python_client.GlpiClient` on the generated one.
|
|
6
6
|
"""
|
|
@@ -8,6 +8,7 @@ surface, :class:`glpi_python_client.GlpiClient` on the generated one.
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
10
|
from glpi_python_client._sync.clients.api.administration._entity import EntityMixin
|
|
11
|
+
from glpi_python_client._sync.clients.api.administration._group import GroupMixin
|
|
11
12
|
from glpi_python_client._sync.clients.api.administration._user import UserMixin
|
|
12
13
|
|
|
13
|
-
__all__ = ["EntityMixin", "UserMixin"]
|
|
14
|
+
__all__ = ["EntityMixin", "GroupMixin", "UserMixin"]
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
"""GLPI ``/Administration/Group`` mixin.
|
|
2
|
+
|
|
3
|
+
The mixin exposes search, fetch, create, update, and delete helpers for the
|
|
4
|
+
GLPI group resource. Every call sends the client's ``GLPI-Entity`` header
|
|
5
|
+
(and the profile and recursion headers that travel with it) except where a
|
|
6
|
+
search is told to skip it with ``skip_entity=True``.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from collections.abc import Iterator
|
|
12
|
+
|
|
13
|
+
from glpi_python_client._sync.clients.commons._constants import GROUP_ENDPOINT, GlpiId
|
|
14
|
+
from glpi_python_client._sync.clients.commons._transport import TransportMixin
|
|
15
|
+
from glpi_python_client.models.api_schema.administration._group import (
|
|
16
|
+
DeleteGroup,
|
|
17
|
+
GetGroup,
|
|
18
|
+
PatchGroup,
|
|
19
|
+
PostGroup,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class GroupMixin(TransportMixin):
|
|
24
|
+
"""CRUD helpers for ``/Administration/Group``."""
|
|
25
|
+
|
|
26
|
+
def search_groups(
|
|
27
|
+
self,
|
|
28
|
+
rsql_filter: str = "",
|
|
29
|
+
*,
|
|
30
|
+
limit: int = 50,
|
|
31
|
+
start: int = 0,
|
|
32
|
+
skip_entity: bool = False,
|
|
33
|
+
) -> list[GetGroup]:
|
|
34
|
+
"""Search GLPI groups with an optional RSQL filter.
|
|
35
|
+
|
|
36
|
+
Parameters
|
|
37
|
+
----------
|
|
38
|
+
rsql_filter : str, optional
|
|
39
|
+
Raw RSQL filter forwarded as the ``filter`` query parameter,
|
|
40
|
+
for example ``"name==Support"``. Empty by default.
|
|
41
|
+
limit : int, optional
|
|
42
|
+
Maximum number of records returned by the GLPI server.
|
|
43
|
+
start : int, optional
|
|
44
|
+
Zero-based offset of the first record returned.
|
|
45
|
+
skip_entity : bool, optional
|
|
46
|
+
When ``True`` the ``GLPI-Entity`` header is omitted so the
|
|
47
|
+
search spans every entity the caller has access to.
|
|
48
|
+
|
|
49
|
+
Returns
|
|
50
|
+
-------
|
|
51
|
+
list[GetGroup]
|
|
52
|
+
Groups matching the filter.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
params: dict[str, object] = {"limit": limit, "start": start}
|
|
56
|
+
if rsql_filter:
|
|
57
|
+
params["filter"] = rsql_filter
|
|
58
|
+
return self._resource_list(
|
|
59
|
+
GROUP_ENDPOINT, GetGroup, params=params, skip_entity=skip_entity
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
def iter_search_groups(
|
|
63
|
+
self,
|
|
64
|
+
rsql_filter: str = "",
|
|
65
|
+
*,
|
|
66
|
+
batch_size: int = 50,
|
|
67
|
+
skip_entity: bool = False,
|
|
68
|
+
) -> Iterator[list[GetGroup]]:
|
|
69
|
+
"""Yield successive pages of GLPI groups until exhausted.
|
|
70
|
+
|
|
71
|
+
Pagination advances the ``start`` offset after each batch and stops
|
|
72
|
+
when the server returns fewer items than ``batch_size``.
|
|
73
|
+
|
|
74
|
+
Parameters
|
|
75
|
+
----------
|
|
76
|
+
rsql_filter : str, optional
|
|
77
|
+
Raw RSQL filter forwarded as the ``filter`` query parameter.
|
|
78
|
+
batch_size : int, optional
|
|
79
|
+
Number of records requested per page (default 50).
|
|
80
|
+
skip_entity : bool, optional
|
|
81
|
+
When ``True`` the ``GLPI-Entity`` header is omitted so the
|
|
82
|
+
search spans every entity the caller has access to.
|
|
83
|
+
|
|
84
|
+
Yields
|
|
85
|
+
------
|
|
86
|
+
list[GetGroup]
|
|
87
|
+
One page of groups per iteration. The last yielded batch may
|
|
88
|
+
be shorter than ``batch_size``.
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
start = 0
|
|
92
|
+
while True:
|
|
93
|
+
batch = self.search_groups(
|
|
94
|
+
rsql_filter,
|
|
95
|
+
limit=batch_size,
|
|
96
|
+
start=start,
|
|
97
|
+
skip_entity=skip_entity,
|
|
98
|
+
)
|
|
99
|
+
if batch:
|
|
100
|
+
yield batch
|
|
101
|
+
if len(batch) < batch_size:
|
|
102
|
+
break
|
|
103
|
+
start += batch_size
|
|
104
|
+
|
|
105
|
+
def get_group(self, group_id: GlpiId) -> GetGroup:
|
|
106
|
+
"""Fetch one GLPI group by identifier.
|
|
107
|
+
|
|
108
|
+
Parameters
|
|
109
|
+
----------
|
|
110
|
+
group_id : GlpiId
|
|
111
|
+
Numeric identifier of the group to retrieve.
|
|
112
|
+
|
|
113
|
+
Returns
|
|
114
|
+
-------
|
|
115
|
+
GetGroup
|
|
116
|
+
Validated group payload.
|
|
117
|
+
|
|
118
|
+
Raises
|
|
119
|
+
------
|
|
120
|
+
GlpiStatusError
|
|
121
|
+
If the GLPI server returns a non-success HTTP status.
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
return self._resource_get(
|
|
125
|
+
f"{GROUP_ENDPOINT}/{group_id}",
|
|
126
|
+
GetGroup,
|
|
127
|
+
failure_message=f"Failed to get group {group_id}",
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
def create_group(self, group: PostGroup) -> int:
|
|
131
|
+
"""Create one GLPI group.
|
|
132
|
+
|
|
133
|
+
Parameters
|
|
134
|
+
----------
|
|
135
|
+
group : PostGroup
|
|
136
|
+
Request body describing the group to create.
|
|
137
|
+
|
|
138
|
+
Returns
|
|
139
|
+
-------
|
|
140
|
+
int
|
|
141
|
+
Identifier assigned by the GLPI server.
|
|
142
|
+
|
|
143
|
+
Raises
|
|
144
|
+
------
|
|
145
|
+
GlpiStatusError
|
|
146
|
+
If the GLPI server returns a non-success HTTP status.
|
|
147
|
+
GlpiProtocolError
|
|
148
|
+
If the create response is missing the ``id`` field.
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
return self._resource_create(
|
|
152
|
+
GROUP_ENDPOINT,
|
|
153
|
+
group,
|
|
154
|
+
failure_message="Failed to create group",
|
|
155
|
+
missing_message="GLPI group create response did not include an ID",
|
|
156
|
+
log_message_factory=lambda new_id: f"GLPI API created group {new_id}",
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
def update_group(self, group_id: GlpiId, group: PatchGroup) -> None:
|
|
160
|
+
"""Update one GLPI group with a partial body.
|
|
161
|
+
|
|
162
|
+
Parameters
|
|
163
|
+
----------
|
|
164
|
+
group_id : GlpiId
|
|
165
|
+
Numeric identifier of the group to update.
|
|
166
|
+
group : PatchGroup
|
|
167
|
+
Partial request body.
|
|
168
|
+
|
|
169
|
+
Returns
|
|
170
|
+
-------
|
|
171
|
+
None
|
|
172
|
+
|
|
173
|
+
Raises
|
|
174
|
+
------
|
|
175
|
+
GlpiStatusError
|
|
176
|
+
If the GLPI server returns a non-success HTTP status.
|
|
177
|
+
"""
|
|
178
|
+
|
|
179
|
+
self._resource_update(
|
|
180
|
+
f"{GROUP_ENDPOINT}/{group_id}",
|
|
181
|
+
group,
|
|
182
|
+
failure_message=f"Failed to update group {group_id}",
|
|
183
|
+
log_message=f"GLPI API updated group {group_id}",
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
def delete_group(
|
|
187
|
+
self, group_id: GlpiId, *, force: bool | None = None
|
|
188
|
+
) -> None:
|
|
189
|
+
"""Delete one GLPI group by identifier.
|
|
190
|
+
|
|
191
|
+
Parameters
|
|
192
|
+
----------
|
|
193
|
+
group_id : GlpiId
|
|
194
|
+
Numeric identifier of the group to delete.
|
|
195
|
+
force : bool | None, optional
|
|
196
|
+
When ``True`` the group is permanently deleted instead of
|
|
197
|
+
being moved to the trash.
|
|
198
|
+
|
|
199
|
+
Returns
|
|
200
|
+
-------
|
|
201
|
+
None
|
|
202
|
+
|
|
203
|
+
Raises
|
|
204
|
+
------
|
|
205
|
+
GlpiStatusError
|
|
206
|
+
If the GLPI server returns a non-success HTTP status.
|
|
207
|
+
"""
|
|
208
|
+
|
|
209
|
+
self._resource_delete(
|
|
210
|
+
f"{GROUP_ENDPOINT}/{group_id}",
|
|
211
|
+
failure_message=f"Failed to delete group {group_id}",
|
|
212
|
+
log_message=f"GLPI API deleted group {group_id}",
|
|
213
|
+
force=force,
|
|
214
|
+
delete_model_cls=DeleteGroup,
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
__all__ = ["GroupMixin"]
|
|
@@ -25,6 +25,7 @@ from glpi_python_client._sync.clients.api import (
|
|
|
25
25
|
DocumentMixin,
|
|
26
26
|
EntityMixin,
|
|
27
27
|
FollowupMixin,
|
|
28
|
+
GroupMixin,
|
|
28
29
|
KBArticleCommentMixin,
|
|
29
30
|
KBArticleMixin,
|
|
30
31
|
KBArticleRevisionMixin,
|
|
@@ -59,6 +60,7 @@ class GlpiClient(
|
|
|
59
60
|
ComputerMixin,
|
|
60
61
|
UserMixin,
|
|
61
62
|
EntityMixin,
|
|
63
|
+
GroupMixin,
|
|
62
64
|
LocationMixin,
|
|
63
65
|
ContractTypeMixin,
|
|
64
66
|
KBCategoryMixin,
|
|
@@ -19,6 +19,7 @@ COMPUTER_ENDPOINT = "Assets/Computer"
|
|
|
19
19
|
# administration/
|
|
20
20
|
USER_ENDPOINT = "Administration/User"
|
|
21
21
|
ENTITY_ENDPOINT = "Administration/Entity"
|
|
22
|
+
GROUP_ENDPOINT = "Administration/Group"
|
|
22
23
|
|
|
23
24
|
# dropdowns/
|
|
24
25
|
CONTRACT_TYPE_ENDPOINT = "Dropdowns/ContractType"
|
|
@@ -52,6 +53,7 @@ __all__ = [
|
|
|
52
53
|
"DOCUMENT_ENDPOINT",
|
|
53
54
|
"ENTITY_ENDPOINT",
|
|
54
55
|
"FOLLOWUP_SUFFIX",
|
|
56
|
+
"GROUP_ENDPOINT",
|
|
55
57
|
"KB_ARTICLE_ENDPOINT",
|
|
56
58
|
"KB_CATEGORY_ENDPOINT",
|
|
57
59
|
"KB_COMMENT_SUFFIX",
|
|
@@ -179,6 +179,30 @@ def _plain_text_html(text: str) -> str:
|
|
|
179
179
|
return "<p>" + "<br>".join(lines) + "</p>"
|
|
180
180
|
|
|
181
181
|
|
|
182
|
+
#: What a browser strips from the front of a URL, and drops from inside one.
|
|
183
|
+
_URL_LEADING = "".join(chr(c) for c in range(0x21))
|
|
184
|
+
_URL_INNER = str.maketrans("", "", "\t\r\n")
|
|
185
|
+
|
|
186
|
+
#: The elements inside which the reader writes no image, so offers none.
|
|
187
|
+
_UNFORMATTED = ("pre", "code", "kbd", "samp")
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def _is_data_uri(src: str) -> bool:
|
|
191
|
+
"""Whether a browser reads ``src`` as a ``data:`` URI.
|
|
192
|
+
|
|
193
|
+
The scheme is case-insensitive, leading C0 controls and spaces are
|
|
194
|
+
stripped, and tabs and line breaks are dropped wherever they are.
|
|
195
|
+
"""
|
|
196
|
+
|
|
197
|
+
return src.lstrip(_URL_LEADING).translate(_URL_INNER).casefold().startswith("data:")
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def _image_id(el: Tag) -> str | None:
|
|
201
|
+
"""The trimmed ``id`` of an element, or ``None`` when it has none."""
|
|
202
|
+
|
|
203
|
+
return str(el.get("id") or "").strip() or None
|
|
204
|
+
|
|
205
|
+
|
|
182
206
|
def _soup(html: str) -> BeautifulSoup:
|
|
183
207
|
"""Parse ``html`` and drop what a browser does not display."""
|
|
184
208
|
|
|
@@ -402,6 +426,12 @@ class Link:
|
|
|
402
426
|
enclosing_href : str or None
|
|
403
427
|
For an ``<img>`` inside a link, that link's ``href``; ``None``
|
|
404
428
|
otherwise. The image is read before the link around it.
|
|
429
|
+
image_id : str or None
|
|
430
|
+
For an ``<img>``, the value of its ``id`` attribute, trimmed, or
|
|
431
|
+
``None`` when it has none or the element is a link. GLPI sets it to
|
|
432
|
+
the tag of the Document it created for an image it has not rewritten
|
|
433
|
+
into a document link, and that Document carries the same value as its
|
|
434
|
+
tag, so a caller can find it.
|
|
405
435
|
"""
|
|
406
436
|
|
|
407
437
|
href: str
|
|
@@ -410,6 +440,7 @@ class Link:
|
|
|
410
440
|
image: bool = False
|
|
411
441
|
document_id: int | None = None
|
|
412
442
|
enclosing_href: str | None = None
|
|
443
|
+
image_id: str | None = None
|
|
413
444
|
|
|
414
445
|
|
|
415
446
|
#: A ``rewrite_link`` callback: called with each link and image a read meets,
|
|
@@ -664,6 +695,7 @@ class _Converter(MarkdownConverter):
|
|
|
664
695
|
enclosing_href=(
|
|
665
696
|
None if around is None else str(around.get("href") or "")
|
|
666
697
|
),
|
|
698
|
+
image_id=_image_id(el),
|
|
667
699
|
)
|
|
668
700
|
)
|
|
669
701
|
if isinstance(answer, str):
|
|
@@ -1021,6 +1053,33 @@ class GlpiContentConverter:
|
|
|
1021
1053
|
document_id = int(values[0])
|
|
1022
1054
|
return document_id if document_id > 0 else None
|
|
1023
1055
|
|
|
1056
|
+
@staticmethod
|
|
1057
|
+
def data_image_ids(html: str) -> tuple[str, ...]:
|
|
1058
|
+
"""Return the ``id`` of every image a body keeps as a ``data:`` URI.
|
|
1059
|
+
|
|
1060
|
+
Each ``<img>`` whose ``src`` a browser reads as a ``data:`` URI and
|
|
1061
|
+
that has a non-empty ``id`` contributes it, in document order and
|
|
1062
|
+
without repeats. The base64 is not decoded. An image inside ``<pre>``,
|
|
1063
|
+
``<code>``, ``<kbd>`` or ``<samp>`` is left out: the reader shows it
|
|
1064
|
+
as no image, so it never offers it to ``rewrite_link`` either.
|
|
1065
|
+
|
|
1066
|
+
GLPI sets a tag on the Documents it creates from an upload or an
|
|
1067
|
+
editor paste, images or not. For an image it has not rewritten into a
|
|
1068
|
+
document link, that tag is the ``id`` of the ``<img>``
|
|
1069
|
+
(:attr:`Link.image_id`, :attr:`GetDocument.tag`). A caller calls this
|
|
1070
|
+
first, to decide whether it needs to read any Document at all.
|
|
1071
|
+
"""
|
|
1072
|
+
|
|
1073
|
+
if "<" not in html:
|
|
1074
|
+
return ()
|
|
1075
|
+
ids = (
|
|
1076
|
+
_image_id(img)
|
|
1077
|
+
for img in _soup(html).find_all("img")
|
|
1078
|
+
if _is_data_uri(str(img.get("src") or ""))
|
|
1079
|
+
and img.find_parent(_UNFORMATTED) is None
|
|
1080
|
+
)
|
|
1081
|
+
return tuple(dict.fromkeys(i for i in ids if i is not None))
|
|
1082
|
+
|
|
1024
1083
|
@staticmethod
|
|
1025
1084
|
def document_image(
|
|
1026
1085
|
document_id: int,
|
|
@@ -22,12 +22,16 @@ from glpi_python_client.models.api_schema._common import (
|
|
|
22
22
|
)
|
|
23
23
|
from glpi_python_client.models.api_schema.administration import (
|
|
24
24
|
DeleteEntity,
|
|
25
|
+
DeleteGroup,
|
|
25
26
|
DeleteUser,
|
|
26
27
|
GetEntity,
|
|
28
|
+
GetGroup,
|
|
27
29
|
GetUser,
|
|
28
30
|
PatchEntity,
|
|
31
|
+
PatchGroup,
|
|
29
32
|
PatchUser,
|
|
30
33
|
PostEntity,
|
|
34
|
+
PostGroup,
|
|
31
35
|
PostUser,
|
|
32
36
|
)
|
|
33
37
|
from glpi_python_client.models.api_schema.assets import (
|
|
@@ -141,6 +145,7 @@ __all__ = [
|
|
|
141
145
|
"DeleteDocument",
|
|
142
146
|
"DeleteEntity",
|
|
143
147
|
"DeleteFollowup",
|
|
148
|
+
"DeleteGroup",
|
|
144
149
|
"DeleteKBArticle",
|
|
145
150
|
"DeleteKBArticleComment",
|
|
146
151
|
"DeleteKBCategory",
|
|
@@ -161,6 +166,7 @@ __all__ = [
|
|
|
161
166
|
"GetDocumentItem",
|
|
162
167
|
"GetEntity",
|
|
163
168
|
"GetFollowup",
|
|
169
|
+
"GetGroup",
|
|
164
170
|
"GetKBArticle",
|
|
165
171
|
"GetKBArticleComment",
|
|
166
172
|
"GetKBArticleRevision",
|
|
@@ -197,6 +203,7 @@ __all__ = [
|
|
|
197
203
|
"PatchDocument",
|
|
198
204
|
"PatchEntity",
|
|
199
205
|
"PatchFollowup",
|
|
206
|
+
"PatchGroup",
|
|
200
207
|
"PatchKBArticle",
|
|
201
208
|
"PatchKBArticleComment",
|
|
202
209
|
"PatchKBCategory",
|
|
@@ -215,6 +222,7 @@ __all__ = [
|
|
|
215
222
|
"PostDocument",
|
|
216
223
|
"PostEntity",
|
|
217
224
|
"PostFollowup",
|
|
225
|
+
"PostGroup",
|
|
218
226
|
"PostKBArticle",
|
|
219
227
|
"PostKBArticleComment",
|
|
220
228
|
"PostKBCategory",
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"""Administration entity schemas mirroring the ``/Administration`` endpoints.
|
|
2
2
|
|
|
3
|
-
This subpackage exposes the per-verb Pydantic models for ``User
|
|
4
|
-
``Entity``. Each module follows the same
|
|
3
|
+
This subpackage exposes the per-verb Pydantic models for ``User``,
|
|
4
|
+
``Entity`` and ``Group``. Each module follows the same
|
|
5
|
+
``Get<Name>``/``Post<Name>``/
|
|
5
6
|
``Patch<Name>``/``Delete<Name>`` naming convention.
|
|
6
7
|
"""
|
|
7
8
|
|
|
@@ -11,6 +12,12 @@ from glpi_python_client.models.api_schema.administration._entity import (
|
|
|
11
12
|
PatchEntity,
|
|
12
13
|
PostEntity,
|
|
13
14
|
)
|
|
15
|
+
from glpi_python_client.models.api_schema.administration._group import (
|
|
16
|
+
DeleteGroup,
|
|
17
|
+
GetGroup,
|
|
18
|
+
PatchGroup,
|
|
19
|
+
PostGroup,
|
|
20
|
+
)
|
|
14
21
|
from glpi_python_client.models.api_schema.administration._user import (
|
|
15
22
|
DeleteUser,
|
|
16
23
|
GetUser,
|
|
@@ -20,11 +27,15 @@ from glpi_python_client.models.api_schema.administration._user import (
|
|
|
20
27
|
|
|
21
28
|
__all__ = [
|
|
22
29
|
"DeleteEntity",
|
|
30
|
+
"DeleteGroup",
|
|
23
31
|
"DeleteUser",
|
|
24
32
|
"GetEntity",
|
|
33
|
+
"GetGroup",
|
|
25
34
|
"GetUser",
|
|
26
35
|
"PatchEntity",
|
|
36
|
+
"PatchGroup",
|
|
27
37
|
"PatchUser",
|
|
28
38
|
"PostEntity",
|
|
39
|
+
"PostGroup",
|
|
29
40
|
"PostUser",
|
|
30
41
|
]
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"""GLPI ``Group`` schemas for the ``/Administration/Group`` endpoints.
|
|
2
|
+
|
|
3
|
+
The field layout mirrors ``components.schemas.Group`` from the GLPI OpenAPI
|
|
4
|
+
contract. Read-only contract fields are not declared on the request models;
|
|
5
|
+
a caller that supplies one anyway sends it through ``extra_payload`` and the
|
|
6
|
+
server decides.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from datetime import datetime
|
|
12
|
+
|
|
13
|
+
from glpi_python_client.models._base import GlpiModel
|
|
14
|
+
from glpi_python_client.models.api_schema._common import IdNameRef
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class GetGroup(GlpiModel):
|
|
18
|
+
"""Response shape returned by ``GET /Administration/Group`` endpoints.
|
|
19
|
+
|
|
20
|
+
Mirrors ``components.schemas.Group``. All fields are optional because
|
|
21
|
+
the contract does not advertise a ``required`` array.
|
|
22
|
+
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
id : int | None, optional
|
|
26
|
+
Native GLPI identifier (``readOnly``).
|
|
27
|
+
name : str | None, optional
|
|
28
|
+
Name of the group.
|
|
29
|
+
comment : str | None, optional
|
|
30
|
+
Free-form comment.
|
|
31
|
+
completename : str | None, optional
|
|
32
|
+
Full hierarchical path of the group (``readOnly``).
|
|
33
|
+
parent : IdNameRef | None, optional
|
|
34
|
+
Parent group in the hierarchy.
|
|
35
|
+
level : int | None, optional
|
|
36
|
+
Depth of the group in the hierarchy tree (``readOnly``).
|
|
37
|
+
entity : IdNameRef | None, optional
|
|
38
|
+
Entity the group belongs to.
|
|
39
|
+
code : str | None, optional
|
|
40
|
+
Group code (at most 255 characters).
|
|
41
|
+
ldap_field : str | None, optional
|
|
42
|
+
LDAP user attribute that may contain this group (memberof).
|
|
43
|
+
ldap_value : str | None, optional
|
|
44
|
+
LDAP attribute value to match for membership, usually the DN.
|
|
45
|
+
ldap_group_dn : str | None, optional
|
|
46
|
+
DN of the group in LDAP; only populated in certain cases.
|
|
47
|
+
maybe_requester : bool | None, optional
|
|
48
|
+
Can be a requester.
|
|
49
|
+
maybe_observer : bool | None, optional
|
|
50
|
+
Can be an observer.
|
|
51
|
+
maybe_assigned : bool | None, optional
|
|
52
|
+
Can be assigned (to tickets).
|
|
53
|
+
maybe_assigned_task : bool | None, optional
|
|
54
|
+
Can be assigned to tasks.
|
|
55
|
+
maybe_notified : bool | None, optional
|
|
56
|
+
Can be notified.
|
|
57
|
+
may_contain_items : bool | None, optional
|
|
58
|
+
Can contain items.
|
|
59
|
+
may_contain_users : bool | None, optional
|
|
60
|
+
Can contain users.
|
|
61
|
+
maybe_manager : bool | None, optional
|
|
62
|
+
Can be manager.
|
|
63
|
+
recursive_membership : bool | None, optional
|
|
64
|
+
Whether users of this group are implied members of all child
|
|
65
|
+
groups. Unrelated to entity recursion.
|
|
66
|
+
mfa_enforced : bool | None, optional
|
|
67
|
+
Whether two-factor authentication is enforced for members.
|
|
68
|
+
date_creation : datetime | None, optional
|
|
69
|
+
Creation timestamp.
|
|
70
|
+
date_mod : datetime | None, optional
|
|
71
|
+
Last modification timestamp.
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
id: int | None = None
|
|
75
|
+
name: str | None = None
|
|
76
|
+
comment: str | None = None
|
|
77
|
+
completename: str | None = None
|
|
78
|
+
parent: IdNameRef | None = None
|
|
79
|
+
level: int | None = None
|
|
80
|
+
entity: IdNameRef | None = None
|
|
81
|
+
code: str | None = None
|
|
82
|
+
ldap_field: str | None = None
|
|
83
|
+
ldap_value: str | None = None
|
|
84
|
+
ldap_group_dn: str | None = None
|
|
85
|
+
maybe_requester: bool | None = None
|
|
86
|
+
maybe_observer: bool | None = None
|
|
87
|
+
maybe_assigned: bool | None = None
|
|
88
|
+
maybe_assigned_task: bool | None = None
|
|
89
|
+
maybe_notified: bool | None = None
|
|
90
|
+
may_contain_items: bool | None = None
|
|
91
|
+
may_contain_users: bool | None = None
|
|
92
|
+
maybe_manager: bool | None = None
|
|
93
|
+
recursive_membership: bool | None = None
|
|
94
|
+
mfa_enforced: bool | None = None
|
|
95
|
+
date_creation: datetime | None = None
|
|
96
|
+
date_mod: datetime | None = None
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class PostGroup(GlpiModel):
|
|
100
|
+
"""Request body for ``POST /Administration/Group``.
|
|
101
|
+
|
|
102
|
+
Read-only contract fields (``id``, ``completename``, ``level``) and the
|
|
103
|
+
server-set timestamps are not declared; see :class:`GetGroup` for the
|
|
104
|
+
meaning of each field.
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
name: str | None = None
|
|
108
|
+
comment: str | None = None
|
|
109
|
+
parent: IdNameRef | None = None
|
|
110
|
+
entity: IdNameRef | None = None
|
|
111
|
+
code: str | None = None
|
|
112
|
+
ldap_field: str | None = None
|
|
113
|
+
ldap_value: str | None = None
|
|
114
|
+
ldap_group_dn: str | None = None
|
|
115
|
+
maybe_requester: bool | None = None
|
|
116
|
+
maybe_observer: bool | None = None
|
|
117
|
+
maybe_assigned: bool | None = None
|
|
118
|
+
maybe_assigned_task: bool | None = None
|
|
119
|
+
maybe_notified: bool | None = None
|
|
120
|
+
may_contain_items: bool | None = None
|
|
121
|
+
may_contain_users: bool | None = None
|
|
122
|
+
maybe_manager: bool | None = None
|
|
123
|
+
recursive_membership: bool | None = None
|
|
124
|
+
mfa_enforced: bool | None = None
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class PatchGroup(PostGroup):
|
|
128
|
+
"""Request body for ``PATCH /Administration/Group/{id}``.
|
|
129
|
+
|
|
130
|
+
The contract uses the same ``Group`` schema for create and
|
|
131
|
+
partial-update bodies; ``PatchGroup`` is kept distinct so client
|
|
132
|
+
mixins can express the intent of the operation explicitly.
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class DeleteGroup(GlpiModel):
|
|
137
|
+
"""Query parameters for ``DELETE /Administration/Group/{id}``.
|
|
138
|
+
|
|
139
|
+
Parameters
|
|
140
|
+
----------
|
|
141
|
+
force : bool | None, optional
|
|
142
|
+
When ``True``, permanently delete the group instead of moving the
|
|
143
|
+
record to the GLPI trash. When ``False`` or :data:`None`, the
|
|
144
|
+
server applies its default soft-delete behaviour.
|
|
145
|
+
"""
|
|
146
|
+
|
|
147
|
+
force: bool | None = None
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
__all__ = ["DeleteGroup", "GetGroup", "PatchGroup", "PostGroup"]
|
|
@@ -61,6 +61,20 @@ class GetDocument(GlpiModel):
|
|
|
61
61
|
mime: str | None = None
|
|
62
62
|
sha1sum: str | None = None
|
|
63
63
|
|
|
64
|
+
@property
|
|
65
|
+
def tag(self) -> str | None:
|
|
66
|
+
"""The tag GLPI gave the Document, or ``None``.
|
|
67
|
+
|
|
68
|
+
GLPI sets a tag on the Documents it creates from an upload or an
|
|
69
|
+
editor paste, images or not. For an image it has not rewritten into
|
|
70
|
+
a document link, it is the ``id`` of the ``<img>`` left in the body
|
|
71
|
+
(see ``GlpiContentConverter.data_image_ids``). Read from
|
|
72
|
+
``extra_payload``; ``None`` when absent, empty or not a string.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
value = self.extra_payload.get("tag")
|
|
76
|
+
return value if isinstance(value, str) and value else None
|
|
77
|
+
|
|
64
78
|
|
|
65
79
|
class PostDocument(GlpiModel):
|
|
66
80
|
"""Request body for ``POST /Management/Document``.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: glpi-python-client
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.6
|
|
4
4
|
Summary: A typed Python client for GLPI ITSM APIs.
|
|
5
5
|
Project-URL: Homepage, https://github.com/baraline/glpi_python_client
|
|
6
6
|
Project-URL: Documentation, https://glpi-python-client.readthedocs.io/en/latest/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
glpi_python_client/__init__.py,sha256=
|
|
1
|
+
glpi_python_client/__init__.py,sha256=PxyLPvdfRqFJPkX1RhaRjOJruLSmLJgW7M6_d2M634A,5762
|
|
2
2
|
glpi_python_client/_errors.py,sha256=Bc9UvlxulbdcGvzZIKXnJCTL78sW78R6EFg50P-1dpY,7151
|
|
3
3
|
glpi_python_client/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
glpi_python_client/rsql.py,sha256=3u3lH3_-F1bvHbVzxALXTDPoHyoMATP1f4QPTar_sEU,8974
|
|
@@ -10,10 +10,11 @@ glpi_python_client/_async/auth/_v1_session.py,sha256=3t1OammbfUm9E-ANynrBFryxjx5
|
|
|
10
10
|
glpi_python_client/_async/auth/auth.py,sha256=1vGG5uBNG8lMjcm20-mgcsH2e0GWKGujQo4k6vck1lE,14694
|
|
11
11
|
glpi_python_client/_async/clients/__init__.py,sha256=LCjaQ_tjb4icz04PvPQdmtfP6PgtymBKhnhA7PuW52I,637
|
|
12
12
|
glpi_python_client/_async/clients/_base_client.py,sha256=Yq_Stx2BqZjNbvysrEMLYyOrfSYjzihN6alfQpy7pWA,7553
|
|
13
|
-
glpi_python_client/_async/clients/client.py,sha256=
|
|
14
|
-
glpi_python_client/_async/clients/api/__init__.py,sha256=
|
|
15
|
-
glpi_python_client/_async/clients/api/administration/__init__.py,sha256=
|
|
13
|
+
glpi_python_client/_async/clients/client.py,sha256=4lZbd4wHNRqI2xbzjsff3iy8e4FnMgF-1Ezi0KyBtHM,3879
|
|
14
|
+
glpi_python_client/_async/clients/api/__init__.py,sha256=keInRT6ogmkeWETnNQC6VliBjZZk4ur2hRcIyWSv1_k,1776
|
|
15
|
+
glpi_python_client/_async/clients/api/administration/__init__.py,sha256=raqpFI2U8WDfeSRzN8-PcqhzD3sKP0oTamgj77-Nhxk,614
|
|
16
16
|
glpi_python_client/_async/clients/api/administration/_entity.py,sha256=qG1SBMwOCZWHjHV4KfswY6bTaTQP9I83mQvOd-Xo70w,6453
|
|
17
|
+
glpi_python_client/_async/clients/api/administration/_group.py,sha256=uqx4Qqt7bWCYZlQayDIL5l_wW8kUg50ngxz3ktD771w,6511
|
|
17
18
|
glpi_python_client/_async/clients/api/administration/_user.py,sha256=SQ_CM353cFD0BW0GQSQp__HZQlmJsAUuAiOgs-1NoNg,10085
|
|
18
19
|
glpi_python_client/_async/clients/api/assets/__init__.py,sha256=WFWG5zcRf0kFtz35it3W83xOlqXJ77IcYI51KRSiL08,198
|
|
19
20
|
glpi_python_client/_async/clients/api/assets/_computer.py,sha256=U-dDeYmY3MaS0BTqJAQThKtKTbvDS7BvshbXheD64rM,13634
|
|
@@ -40,7 +41,7 @@ glpi_python_client/_async/clients/api/plugins/__init__.py,sha256=mmY6HngIzna2AG3
|
|
|
40
41
|
glpi_python_client/_async/clients/api/plugins/_fields.py,sha256=mGpPutvN8JUDUszdvLEE2kkQnz28rktshHdFhs9A1X4,15485
|
|
41
42
|
glpi_python_client/_async/clients/commons/__init__.py,sha256=1-V_LgNwIYDyXdpLP2nijCTeGgajTcY-wt0C4aeRE3k,406
|
|
42
43
|
glpi_python_client/_async/clients/commons/_config.py,sha256=JlUZy_oPQj0ldSbBVWcytMlvROyeCW0JldOpPrBmFMs,13080
|
|
43
|
-
glpi_python_client/_async/clients/commons/_constants.py,sha256=
|
|
44
|
+
glpi_python_client/_async/clients/commons/_constants.py,sha256=Y2uQ0zE_7m0DLSKLg41JEbW4ww23Mk9g-hDbjNZjaZQ,1834
|
|
44
45
|
glpi_python_client/_async/clients/commons/_filters.py,sha256=eQdrc06RhEuGHtvAqBJy1VrOVHVjeiFh82pvX-HxGw8,4695
|
|
45
46
|
glpi_python_client/_async/clients/commons/_http.py,sha256=8x9H9eHw-neOYoQ2MAP2JmbVqcpno42pZlzfuhizpmk,15240
|
|
46
47
|
glpi_python_client/_async/clients/commons/_payloads.py,sha256=7LEzk72WwLcLqxWXQ_rHcjAnpo3WIuq97X768-Zkvt8,3707
|
|
@@ -56,10 +57,11 @@ glpi_python_client/_sync/auth/_v1_session.py,sha256=dlnYA2yi_aWI6wTpfnRD3nzRvnw1
|
|
|
56
57
|
glpi_python_client/_sync/auth/auth.py,sha256=azWE3bqDswxU-PtO-m_aKb-luSVPRrRXDVuq2aFRz18,14608
|
|
57
58
|
glpi_python_client/_sync/clients/__init__.py,sha256=DWKGlB1KAgTQvmc_Dycz7rynNo0y_fr5Z4LcTxzn4iQ,623
|
|
58
59
|
glpi_python_client/_sync/clients/_base_client.py,sha256=-59b4F383zVhcnt_KV8VY3f9nMr0SlRG9tm_d3yKRKU,7551
|
|
59
|
-
glpi_python_client/_sync/clients/client.py,sha256=
|
|
60
|
-
glpi_python_client/_sync/clients/api/__init__.py,sha256=
|
|
61
|
-
glpi_python_client/_sync/clients/api/administration/__init__.py,sha256=
|
|
60
|
+
glpi_python_client/_sync/clients/client.py,sha256=WTqrTs_0xSUSR8ez__JjHPgDBhsBUtyUFBhgZANNZqo,3821
|
|
61
|
+
glpi_python_client/_sync/clients/api/__init__.py,sha256=_nlTpSQyldJrTVvlifp__DQGF6_vqCl_YPWp6FCa-mM,1767
|
|
62
|
+
glpi_python_client/_sync/clients/api/administration/__init__.py,sha256=3s3Nfawu1FI97Q-WIlz5OgLZL7TszItF6l_JzQHVzaM,611
|
|
62
63
|
glpi_python_client/_sync/clients/api/administration/_entity.py,sha256=jYvIl1hXcPQuAABa0I0TCKBG6FMHtO8xl55xhG5CRS8,6369
|
|
64
|
+
glpi_python_client/_sync/clients/api/administration/_group.py,sha256=84J78kE35pBhokqrRTMDj2H7yyU8UWvPfdbCcDLR8hY,6427
|
|
63
65
|
glpi_python_client/_sync/clients/api/administration/_user.py,sha256=8QuL9G_6donw0UNtpQEyxh1gHpjfymnDcGy-7AW7IcA,9989
|
|
64
66
|
glpi_python_client/_sync/clients/api/assets/__init__.py,sha256=_4-S2nkXQNuFXzZzXoLR3DnykaKTzata9ZPN74ASO8s,197
|
|
65
67
|
glpi_python_client/_sync/clients/api/assets/_computer.py,sha256=jILfoo7L2FJwL7Q_uFXkpfDBCuPczCAJ_TbAoyiGrj0,13490
|
|
@@ -86,7 +88,7 @@ glpi_python_client/_sync/clients/api/plugins/__init__.py,sha256=x9RwOUD34H1bPsJJ
|
|
|
86
88
|
glpi_python_client/_sync/clients/api/plugins/_fields.py,sha256=jkGTF0T7eQHzOPcKSqaEmwJx-EgETcgncXyke69HJeg,15368
|
|
87
89
|
glpi_python_client/_sync/clients/commons/__init__.py,sha256=Ur1hbt0_A9TlRqYi97PmlfsXYS_EMGk0lVjkHx_cyBE,404
|
|
88
90
|
glpi_python_client/_sync/clients/commons/_config.py,sha256=f2wVtUUdh6rxaf-s84X8Fhfn0zxn0OPJg445dKeCSVw,13056
|
|
89
|
-
glpi_python_client/_sync/clients/commons/_constants.py,sha256=
|
|
91
|
+
glpi_python_client/_sync/clients/commons/_constants.py,sha256=Y2uQ0zE_7m0DLSKLg41JEbW4ww23Mk9g-hDbjNZjaZQ,1834
|
|
90
92
|
glpi_python_client/_sync/clients/commons/_filters.py,sha256=eQdrc06RhEuGHtvAqBJy1VrOVHVjeiFh82pvX-HxGw8,4695
|
|
91
93
|
glpi_python_client/_sync/clients/commons/_http.py,sha256=5p8S1J1usIB0WQg5u3h6zovr14an-NoIGNfwAHEOSS4,15239
|
|
92
94
|
glpi_python_client/_sync/clients/commons/_payloads.py,sha256=7LEzk72WwLcLqxWXQ_rHcjAnpo3WIuq97X768-Zkvt8,3707
|
|
@@ -95,15 +97,16 @@ glpi_python_client/_sync/clients/custom/__init__.py,sha256=sxfGlHVulucP7bacWhUMi
|
|
|
95
97
|
glpi_python_client/_sync/clients/custom/_statistics.py,sha256=xrD5C99ieROJx60iUomBHacQ_49HpgQL4XjnfREUQvs,38616
|
|
96
98
|
glpi_python_client/_sync/clients/custom/_ticket_context.py,sha256=LDUvKNr8VpZonF5bDo8QYYwMEsWmayVU28Ra3GonNmE,3004
|
|
97
99
|
glpi_python_client/content/__init__.py,sha256=TaZPo8WSvVj4U-hSnxhUcqU8JnCKNZYpfQf4pH45aN4,424
|
|
98
|
-
glpi_python_client/content/conversion.py,sha256=
|
|
99
|
-
glpi_python_client/models/__init__.py,sha256=
|
|
100
|
+
glpi_python_client/content/conversion.py,sha256=0dxQW0ojSo1KC8zcTFa476KQa1i3sLWzQ8gTEEVslys,45341
|
|
101
|
+
glpi_python_client/models/__init__.py,sha256=7OxYvXSQc4QdK1VAQb_1BGvgwGc6211gKnSdLWy-qhY,5586
|
|
100
102
|
glpi_python_client/models/_base.py,sha256=pYg69KHuR5TDED5utr4Knr7HncBnLTxXHJZYf6vEUKA,12183
|
|
101
103
|
glpi_python_client/models/api_schema/__init__.py,sha256=yTxUYih1Xy7NUogzD7UKp2b8HyE4wdeC_FCKS6ZRVVM,1176
|
|
102
104
|
glpi_python_client/models/api_schema/_common.py,sha256=wVtaIkUM9iS3jyDb0bpFopEkP_3vP1ax7D8rwHe9QkI,2004
|
|
103
105
|
glpi_python_client/models/api_schema/_content.py,sha256=DlsEmlXIK_0jyXh3j5PgU6vkwch2o0I8UpUkLq2fqYw,12826
|
|
104
106
|
glpi_python_client/models/api_schema/enums.py,sha256=bHNCuumOXIZm80n5RqIhCzFqizII-3er41mn2aktF5s,5071
|
|
105
|
-
glpi_python_client/models/api_schema/administration/__init__.py,sha256=
|
|
107
|
+
glpi_python_client/models/api_schema/administration/__init__.py,sha256=CFZ36OIk1PPBzkXkCtOo2C6s7JfaKSp63Nw4-b_coxc,924
|
|
106
108
|
glpi_python_client/models/api_schema/administration/_entity.py,sha256=KdbxMyPXumGZKmmabDIciF3nFS61pLRp5SBOTFa8slk,3297
|
|
109
|
+
glpi_python_client/models/api_schema/administration/_group.py,sha256=8aWnDupTT9lxGtzMC_dAG8yDLO_NKtFz-OCNHOYESi0,5298
|
|
107
110
|
glpi_python_client/models/api_schema/administration/_user.py,sha256=MQ6cHKdni98sjm-Whf0GKdGpNjPgGGJpUBgVjlGa19Q,15872
|
|
108
111
|
glpi_python_client/models/api_schema/assets/__init__.py,sha256=QikGfQwwhjKt3vUd5FYC1F-BeClP5ByK1hahRRumdsA,562
|
|
109
112
|
glpi_python_client/models/api_schema/assets/_computer.py,sha256=me3px9rkaN_ZataDVLjOer9wsZw_fRoRikxkLzXopsE,10304
|
|
@@ -127,7 +130,7 @@ glpi_python_client/models/api_schema/knowledgebase/_revision.py,sha256=KuTb_F85m
|
|
|
127
130
|
glpi_python_client/models/api_schema/management/__init__.py,sha256=z5ntUAXiXXhZCEIsTVaTgJdXbg0ZW24TZctarfAqjr0,987
|
|
128
131
|
glpi_python_client/models/api_schema/management/_contract.py,sha256=m6g__AKWvDQ09xKyUe8RhRS8xE1d1pOBjqOOG-8u6Ck,14045
|
|
129
132
|
glpi_python_client/models/api_schema/management/_contract_cost.py,sha256=Bp2B3bA5u8CE_oBYY70QIUot8jFLCrX_icXZ4kpYqSE,4966
|
|
130
|
-
glpi_python_client/models/api_schema/management/_document.py,sha256=
|
|
133
|
+
glpi_python_client/models/api_schema/management/_document.py,sha256=kiEkTnOydGHjOyAwTbo020Kei4ffkBDj-9m775gLyfw,5200
|
|
131
134
|
glpi_python_client/models/api_schema/management/_document_item.py,sha256=Bu9c9YdhSs5hGZ8dRfRxqS4g7VZ1A3EJtNbDLulKpWA,3113
|
|
132
135
|
glpi_python_client/models/api_schema/plugins/__init__.py,sha256=GA0pr0PeoPOqwjUilrBujh0OqjUfZhzPWgIlgDJcZog,544
|
|
133
136
|
glpi_python_client/models/api_schema/plugins/_fields.py,sha256=Se-12ZDqk_-on_37YF_hRD5S0e0H6zyha3SXI9xb_9Y,6576
|
|
@@ -136,7 +139,7 @@ glpi_python_client/models/custom_schema/_ticket_context.py,sha256=jnlfgho-aDbmA9
|
|
|
136
139
|
glpi_python_client/testing/__init__.py,sha256=iLtUyJjyv3fEhy3PN25NxNTbtqDl3SoHLbNium0Z80U,568
|
|
137
140
|
glpi_python_client/testing/fixtures.py,sha256=HKt6MXHgcmLn4L98pSwp-oGlc9C--_vrABNe5G_iBeg,1286
|
|
138
141
|
glpi_python_client/testing/utils.py,sha256=JyO3w2d-0kYdtC1hEZ2Tu_YjnCz8nUQ_Ck05-1EhsX4,4404
|
|
139
|
-
glpi_python_client-0.6.
|
|
140
|
-
glpi_python_client-0.6.
|
|
141
|
-
glpi_python_client-0.6.
|
|
142
|
-
glpi_python_client-0.6.
|
|
142
|
+
glpi_python_client-0.6.6.dist-info/METADATA,sha256=RiSWOUSsejQZVqs8hWndBh8TB9DPm07vq56KpoluRZo,8234
|
|
143
|
+
glpi_python_client-0.6.6.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
|
|
144
|
+
glpi_python_client-0.6.6.dist-info/licenses/LICENSE,sha256=nL8re-TIKkxCoL7OkSBja6EB4NsQR1HoOJgxv_MEhtc,1088
|
|
145
|
+
glpi_python_client-0.6.6.dist-info/RECORD,,
|
|
File without changes
|