python-gitlab 5.5.0__py3-none-any.whl → 6.0.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.
- gitlab/__init__.py +0 -1
- gitlab/_backends/protocol.py +9 -13
- gitlab/_backends/requests_backend.py +12 -12
- gitlab/_version.py +1 -1
- gitlab/base.py +48 -48
- gitlab/cli.py +14 -24
- gitlab/client.py +114 -140
- gitlab/config.py +16 -17
- gitlab/exceptions.py +7 -5
- gitlab/mixins.py +154 -238
- gitlab/types.py +13 -14
- gitlab/utils.py +32 -43
- gitlab/v4/cli.py +50 -53
- gitlab/v4/objects/__init__.py +1 -0
- gitlab/v4/objects/access_requests.py +11 -3
- gitlab/v4/objects/appearance.py +12 -14
- gitlab/v4/objects/applications.py +5 -6
- gitlab/v4/objects/artifacts.py +10 -17
- gitlab/v4/objects/audit_events.py +4 -19
- gitlab/v4/objects/award_emojis.py +13 -57
- gitlab/v4/objects/badges.py +4 -19
- gitlab/v4/objects/boards.py +7 -27
- gitlab/v4/objects/branches.py +3 -15
- gitlab/v4/objects/broadcast_messages.py +3 -13
- gitlab/v4/objects/bulk_imports.py +6 -14
- gitlab/v4/objects/ci_lint.py +7 -13
- gitlab/v4/objects/cluster_agents.py +3 -13
- gitlab/v4/objects/clusters.py +13 -23
- gitlab/v4/objects/commits.py +23 -28
- gitlab/v4/objects/container_registry.py +13 -19
- gitlab/v4/objects/custom_attributes.py +16 -21
- gitlab/v4/objects/deploy_keys.py +22 -19
- gitlab/v4/objects/deploy_tokens.py +14 -32
- gitlab/v4/objects/deployments.py +13 -15
- gitlab/v4/objects/discussions.py +13 -29
- gitlab/v4/objects/draft_notes.py +4 -14
- gitlab/v4/objects/environments.py +13 -21
- gitlab/v4/objects/epics.py +14 -17
- gitlab/v4/objects/events.py +27 -79
- gitlab/v4/objects/export_import.py +7 -19
- gitlab/v4/objects/features.py +11 -12
- gitlab/v4/objects/files.py +23 -38
- gitlab/v4/objects/geo_nodes.py +7 -11
- gitlab/v4/objects/group_access_tokens.py +6 -13
- gitlab/v4/objects/groups.py +42 -37
- gitlab/v4/objects/hooks.py +4 -17
- gitlab/v4/objects/integrations.py +7 -18
- gitlab/v4/objects/invitations.py +12 -23
- gitlab/v4/objects/issues.py +21 -27
- gitlab/v4/objects/iterations.py +4 -8
- gitlab/v4/objects/job_token_scope.py +18 -14
- gitlab/v4/objects/jobs.py +17 -32
- gitlab/v4/objects/keys.py +8 -11
- gitlab/v4/objects/labels.py +19 -30
- gitlab/v4/objects/ldap.py +25 -9
- gitlab/v4/objects/member_roles.py +102 -0
- gitlab/v4/objects/members.py +11 -29
- gitlab/v4/objects/merge_request_approvals.py +47 -38
- gitlab/v4/objects/merge_requests.py +30 -40
- gitlab/v4/objects/merge_trains.py +3 -6
- gitlab/v4/objects/milestones.py +23 -29
- gitlab/v4/objects/namespaces.py +4 -10
- gitlab/v4/objects/notes.py +26 -69
- gitlab/v4/objects/notification_settings.py +5 -14
- gitlab/v4/objects/package_protection_rules.py +8 -8
- gitlab/v4/objects/packages.py +22 -37
- gitlab/v4/objects/pages.py +8 -14
- gitlab/v4/objects/personal_access_tokens.py +7 -10
- gitlab/v4/objects/pipelines.py +38 -47
- gitlab/v4/objects/project_access_tokens.py +6 -13
- gitlab/v4/objects/projects.py +54 -76
- gitlab/v4/objects/push_rules.py +13 -15
- gitlab/v4/objects/registry_protection_repository_rules.py +6 -7
- gitlab/v4/objects/registry_protection_rules.py +7 -11
- gitlab/v4/objects/releases.py +6 -20
- gitlab/v4/objects/repositories.py +25 -34
- gitlab/v4/objects/resource_groups.py +10 -15
- gitlab/v4/objects/reviewers.py +4 -2
- gitlab/v4/objects/runners.py +14 -13
- gitlab/v4/objects/secure_files.py +8 -21
- gitlab/v4/objects/service_accounts.py +7 -5
- gitlab/v4/objects/settings.py +13 -14
- gitlab/v4/objects/sidekiq.py +17 -18
- gitlab/v4/objects/snippets.py +78 -66
- gitlab/v4/objects/statistics.py +8 -23
- gitlab/v4/objects/status_checks.py +6 -3
- gitlab/v4/objects/tags.py +3 -13
- gitlab/v4/objects/templates.py +11 -59
- gitlab/v4/objects/todos.py +3 -6
- gitlab/v4/objects/topics.py +10 -21
- gitlab/v4/objects/triggers.py +3 -13
- gitlab/v4/objects/users.py +87 -93
- gitlab/v4/objects/variables.py +4 -19
- gitlab/v4/objects/wikis.py +4 -19
- {python_gitlab-5.5.0.dist-info → python_gitlab-6.0.0.dist-info}/METADATA +3 -2
- python_gitlab-6.0.0.dist-info/RECORD +107 -0
- {python_gitlab-5.5.0.dist-info → python_gitlab-6.0.0.dist-info}/WHEEL +1 -1
- python_gitlab-5.5.0.dist-info/RECORD +0 -106
- {python_gitlab-5.5.0.dist-info → python_gitlab-6.0.0.dist-info}/entry_points.txt +0 -0
- {python_gitlab-5.5.0.dist-info → python_gitlab-6.0.0.dist-info/licenses}/AUTHORS +0 -0
- {python_gitlab-5.5.0.dist-info → python_gitlab-6.0.0.dist-info/licenses}/COPYING +0 -0
- {python_gitlab-5.5.0.dist-info → python_gitlab-6.0.0.dist-info}/top_level.txt +0 -0
gitlab/mixins.py
CHANGED
@@ -1,19 +1,9 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
1
3
|
import enum
|
4
|
+
from collections.abc import Iterator
|
2
5
|
from types import ModuleType
|
3
|
-
from typing import
|
4
|
-
Any,
|
5
|
-
Callable,
|
6
|
-
Dict,
|
7
|
-
Iterator,
|
8
|
-
List,
|
9
|
-
Literal,
|
10
|
-
Optional,
|
11
|
-
overload,
|
12
|
-
Tuple,
|
13
|
-
Type,
|
14
|
-
TYPE_CHECKING,
|
15
|
-
Union,
|
16
|
-
)
|
6
|
+
from typing import Any, Callable, Literal, overload, TYPE_CHECKING
|
17
7
|
|
18
8
|
import requests
|
19
9
|
|
@@ -48,18 +38,16 @@ __all__ = [
|
|
48
38
|
|
49
39
|
if TYPE_CHECKING:
|
50
40
|
# When running mypy we use these as the base classes
|
51
|
-
_RestManagerBase = base.RESTManager
|
52
41
|
_RestObjectBase = base.RESTObject
|
53
42
|
else:
|
54
|
-
_RestManagerBase = object
|
55
43
|
_RestObjectBase = object
|
56
44
|
|
57
45
|
|
58
|
-
class HeadMixin(
|
46
|
+
class HeadMixin(base.RESTManager[base.TObjCls]):
|
59
47
|
@exc.on_http_error(exc.GitlabHeadError)
|
60
48
|
def head(
|
61
|
-
self, id:
|
62
|
-
) ->
|
49
|
+
self, id: str | int | None = None, **kwargs: Any
|
50
|
+
) -> requests.structures.CaseInsensitiveDict[Any]:
|
63
51
|
"""Retrieve headers from an endpoint.
|
64
52
|
|
65
53
|
Args:
|
@@ -73,9 +61,6 @@ class HeadMixin(_RestManagerBase):
|
|
73
61
|
GitlabAuthenticationError: If authentication is not correct
|
74
62
|
GitlabHeadError: If the server cannot perform the request
|
75
63
|
"""
|
76
|
-
if TYPE_CHECKING:
|
77
|
-
assert self.path is not None
|
78
|
-
|
79
64
|
path = self.path
|
80
65
|
if id is not None:
|
81
66
|
path = f"{path}/{utils.EncodedId(id)}"
|
@@ -83,20 +68,11 @@ class HeadMixin(_RestManagerBase):
|
|
83
68
|
return self.gitlab.http_head(path, **kwargs)
|
84
69
|
|
85
70
|
|
86
|
-
class GetMixin(HeadMixin
|
87
|
-
|
88
|
-
_from_parent_attrs: Dict[str, Any]
|
89
|
-
_obj_cls: Optional[Type[base.RESTObject]]
|
90
|
-
_optional_get_attrs: Tuple[str, ...] = ()
|
91
|
-
_parent: Optional[base.RESTObject]
|
92
|
-
_parent_attrs: Dict[str, Any]
|
93
|
-
_path: Optional[str]
|
94
|
-
gitlab: gitlab.Gitlab
|
71
|
+
class GetMixin(HeadMixin[base.TObjCls]):
|
72
|
+
_optional_get_attrs: tuple[str, ...] = ()
|
95
73
|
|
96
74
|
@exc.on_http_error(exc.GitlabGetError)
|
97
|
-
def get(
|
98
|
-
self, id: Union[str, int], lazy: bool = False, **kwargs: Any
|
99
|
-
) -> base.RESTObject:
|
75
|
+
def get(self, id: str | int, lazy: bool = False, **kwargs: Any) -> base.TObjCls:
|
100
76
|
"""Retrieve a single object.
|
101
77
|
|
102
78
|
Args:
|
@@ -116,8 +92,6 @@ class GetMixin(HeadMixin, _RestManagerBase):
|
|
116
92
|
if isinstance(id, str):
|
117
93
|
id = utils.EncodedId(id)
|
118
94
|
path = f"{self.path}/{id}"
|
119
|
-
if TYPE_CHECKING:
|
120
|
-
assert self._obj_cls is not None
|
121
95
|
if lazy is True:
|
122
96
|
if TYPE_CHECKING:
|
123
97
|
assert self._obj_cls._id_attr is not None
|
@@ -128,18 +102,11 @@ class GetMixin(HeadMixin, _RestManagerBase):
|
|
128
102
|
return self._obj_cls(self, server_data, lazy=lazy)
|
129
103
|
|
130
104
|
|
131
|
-
class GetWithoutIdMixin(HeadMixin
|
132
|
-
|
133
|
-
_from_parent_attrs: Dict[str, Any]
|
134
|
-
_obj_cls: Optional[Type[base.RESTObject]]
|
135
|
-
_optional_get_attrs: Tuple[str, ...] = ()
|
136
|
-
_parent: Optional[base.RESTObject]
|
137
|
-
_parent_attrs: Dict[str, Any]
|
138
|
-
_path: Optional[str]
|
139
|
-
gitlab: gitlab.Gitlab
|
105
|
+
class GetWithoutIdMixin(HeadMixin[base.TObjCls]):
|
106
|
+
_optional_get_attrs: tuple[str, ...] = ()
|
140
107
|
|
141
108
|
@exc.on_http_error(exc.GitlabGetError)
|
142
|
-
def get(self, **kwargs: Any) -> base.
|
109
|
+
def get(self, **kwargs: Any) -> base.TObjCls:
|
143
110
|
"""Retrieve a single object.
|
144
111
|
|
145
112
|
Args:
|
@@ -152,22 +119,19 @@ class GetWithoutIdMixin(HeadMixin, _RestManagerBase):
|
|
152
119
|
GitlabAuthenticationError: If authentication is not correct
|
153
120
|
GitlabGetError: If the server cannot perform the request
|
154
121
|
"""
|
155
|
-
if TYPE_CHECKING:
|
156
|
-
assert self.path is not None
|
157
122
|
server_data = self.gitlab.http_get(self.path, **kwargs)
|
158
123
|
if TYPE_CHECKING:
|
159
124
|
assert not isinstance(server_data, requests.Response)
|
160
|
-
assert self._obj_cls is not None
|
161
125
|
return self._obj_cls(self, server_data)
|
162
126
|
|
163
127
|
|
164
128
|
class RefreshMixin(_RestObjectBase):
|
165
|
-
_id_attr:
|
166
|
-
_attrs:
|
129
|
+
_id_attr: str | None
|
130
|
+
_attrs: dict[str, Any]
|
167
131
|
_module: ModuleType
|
168
|
-
_parent_attrs:
|
169
|
-
_updated_attrs:
|
170
|
-
manager: base.RESTManager
|
132
|
+
_parent_attrs: dict[str, Any]
|
133
|
+
_updated_attrs: dict[str, Any]
|
134
|
+
manager: base.RESTManager[Any]
|
171
135
|
|
172
136
|
@exc.on_http_error(exc.GitlabGetError)
|
173
137
|
def refresh(self, **kwargs: Any) -> None:
|
@@ -194,22 +158,32 @@ class RefreshMixin(_RestObjectBase):
|
|
194
158
|
self._update_attrs(server_data)
|
195
159
|
|
196
160
|
|
197
|
-
class ListMixin(HeadMixin
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
161
|
+
class ListMixin(HeadMixin[base.TObjCls]):
|
162
|
+
_list_filters: tuple[str, ...] = ()
|
163
|
+
|
164
|
+
@overload
|
165
|
+
def list(
|
166
|
+
self, *, iterator: Literal[False] = False, **kwargs: Any
|
167
|
+
) -> list[base.TObjCls]: ...
|
168
|
+
|
169
|
+
@overload
|
170
|
+
def list(
|
171
|
+
self, *, iterator: Literal[True] = True, **kwargs: Any
|
172
|
+
) -> base.RESTObjectList[base.TObjCls]: ...
|
173
|
+
|
174
|
+
@overload
|
175
|
+
def list(
|
176
|
+
self, *, iterator: bool = False, **kwargs: Any
|
177
|
+
) -> base.RESTObjectList[base.TObjCls] | list[base.TObjCls]: ...
|
206
178
|
|
207
179
|
@exc.on_http_error(exc.GitlabListError)
|
208
|
-
def list(
|
180
|
+
def list(
|
181
|
+
self, *, iterator: bool = False, **kwargs: Any
|
182
|
+
) -> base.RESTObjectList[base.TObjCls] | list[base.TObjCls]:
|
209
183
|
"""Retrieve a list of objects.
|
210
184
|
|
211
185
|
Args:
|
212
|
-
|
186
|
+
get_all: If True, return all the items, without pagination
|
213
187
|
per_page: Number of items to retrieve per request
|
214
188
|
page: ID of the page to return (starts with page 1)
|
215
189
|
iterator: If set to True and no pagination option is
|
@@ -244,37 +218,18 @@ class ListMixin(HeadMixin, _RestManagerBase):
|
|
244
218
|
# Allow to overwrite the path, handy for custom listings
|
245
219
|
path = data.pop("path", self.path)
|
246
220
|
|
247
|
-
|
248
|
-
assert self._obj_cls is not None
|
249
|
-
obj = self.gitlab.http_list(path, **data)
|
221
|
+
obj = self.gitlab.http_list(path, iterator=iterator, **data)
|
250
222
|
if isinstance(obj, list):
|
251
223
|
return [self._obj_cls(self, item, created_from_list=True) for item in obj]
|
252
224
|
return base.RESTObjectList(self, self._obj_cls, obj)
|
253
225
|
|
254
226
|
|
255
|
-
class RetrieveMixin(ListMixin, GetMixin):
|
256
|
-
_computed_path: Optional[str]
|
257
|
-
_from_parent_attrs: Dict[str, Any]
|
258
|
-
_obj_cls: Optional[Type[base.RESTObject]]
|
259
|
-
_parent: Optional[base.RESTObject]
|
260
|
-
_parent_attrs: Dict[str, Any]
|
261
|
-
_path: Optional[str]
|
262
|
-
gitlab: gitlab.Gitlab
|
263
|
-
|
227
|
+
class RetrieveMixin(ListMixin[base.TObjCls], GetMixin[base.TObjCls]): ...
|
264
228
|
|
265
|
-
class CreateMixin(_RestManagerBase):
|
266
|
-
_computed_path: Optional[str]
|
267
|
-
_from_parent_attrs: Dict[str, Any]
|
268
|
-
_obj_cls: Optional[Type[base.RESTObject]]
|
269
|
-
_parent: Optional[base.RESTObject]
|
270
|
-
_parent_attrs: Dict[str, Any]
|
271
|
-
_path: Optional[str]
|
272
|
-
gitlab: gitlab.Gitlab
|
273
229
|
|
230
|
+
class CreateMixin(base.RESTManager[base.TObjCls]):
|
274
231
|
@exc.on_http_error(exc.GitlabCreateError)
|
275
|
-
def create(
|
276
|
-
self, data: Optional[Dict[str, Any]] = None, **kwargs: Any
|
277
|
-
) -> base.RESTObject:
|
232
|
+
def create(self, data: dict[str, Any] | None = None, **kwargs: Any) -> base.TObjCls:
|
278
233
|
"""Create a new object.
|
279
234
|
|
280
235
|
Args:
|
@@ -303,7 +258,6 @@ class CreateMixin(_RestManagerBase):
|
|
303
258
|
server_data = self.gitlab.http_post(path, post_data=data, files=files, **kwargs)
|
304
259
|
if TYPE_CHECKING:
|
305
260
|
assert not isinstance(server_data, requests.Response)
|
306
|
-
assert self._obj_cls is not None
|
307
261
|
return self._obj_cls(self, server_data)
|
308
262
|
|
309
263
|
|
@@ -314,19 +268,11 @@ class UpdateMethod(enum.IntEnum):
|
|
314
268
|
PATCH = 3
|
315
269
|
|
316
270
|
|
317
|
-
class UpdateMixin(
|
318
|
-
|
319
|
-
_from_parent_attrs: Dict[str, Any]
|
320
|
-
_obj_cls: Optional[Type[base.RESTObject]]
|
321
|
-
_parent: Optional[base.RESTObject]
|
322
|
-
_parent_attrs: Dict[str, Any]
|
323
|
-
_path: Optional[str]
|
271
|
+
class UpdateMixin(base.RESTManager[base.TObjCls]):
|
272
|
+
# Update mixins attrs for easier implementation
|
324
273
|
_update_method: UpdateMethod = UpdateMethod.PUT
|
325
|
-
gitlab: gitlab.Gitlab
|
326
274
|
|
327
|
-
def _get_update_method(
|
328
|
-
self,
|
329
|
-
) -> Callable[..., Union[Dict[str, Any], requests.Response]]:
|
275
|
+
def _get_update_method(self) -> Callable[..., dict[str, Any] | requests.Response]:
|
330
276
|
"""Return the HTTP method to use.
|
331
277
|
|
332
278
|
Returns:
|
@@ -344,10 +290,10 @@ class UpdateMixin(_RestManagerBase):
|
|
344
290
|
@exc.on_http_error(exc.GitlabUpdateError)
|
345
291
|
def update(
|
346
292
|
self,
|
347
|
-
id:
|
348
|
-
new_data:
|
293
|
+
id: str | int | None = None,
|
294
|
+
new_data: dict[str, Any] | None = None,
|
349
295
|
**kwargs: Any,
|
350
|
-
) ->
|
296
|
+
) -> dict[str, Any]:
|
351
297
|
"""Update an object on the server.
|
352
298
|
|
353
299
|
Args:
|
@@ -384,17 +330,9 @@ class UpdateMixin(_RestManagerBase):
|
|
384
330
|
return result
|
385
331
|
|
386
332
|
|
387
|
-
class SetMixin(
|
388
|
-
_computed_path: Optional[str]
|
389
|
-
_from_parent_attrs: Dict[str, Any]
|
390
|
-
_obj_cls: Optional[Type[base.RESTObject]]
|
391
|
-
_parent: Optional[base.RESTObject]
|
392
|
-
_parent_attrs: Dict[str, Any]
|
393
|
-
_path: Optional[str]
|
394
|
-
gitlab: gitlab.Gitlab
|
395
|
-
|
333
|
+
class SetMixin(base.RESTManager[base.TObjCls]):
|
396
334
|
@exc.on_http_error(exc.GitlabSetError)
|
397
|
-
def set(self, key: str, value: str, **kwargs: Any) -> base.
|
335
|
+
def set(self, key: str, value: str, **kwargs: Any) -> base.TObjCls:
|
398
336
|
"""Create or update the object.
|
399
337
|
|
400
338
|
Args:
|
@@ -414,21 +352,12 @@ class SetMixin(_RestManagerBase):
|
|
414
352
|
server_data = self.gitlab.http_put(path, post_data=data, **kwargs)
|
415
353
|
if TYPE_CHECKING:
|
416
354
|
assert not isinstance(server_data, requests.Response)
|
417
|
-
assert self._obj_cls is not None
|
418
355
|
return self._obj_cls(self, server_data)
|
419
356
|
|
420
357
|
|
421
|
-
class DeleteMixin(
|
422
|
-
_computed_path: Optional[str]
|
423
|
-
_from_parent_attrs: Dict[str, Any]
|
424
|
-
_obj_cls: Optional[Type[base.RESTObject]]
|
425
|
-
_parent: Optional[base.RESTObject]
|
426
|
-
_parent_attrs: Dict[str, Any]
|
427
|
-
_path: Optional[str]
|
428
|
-
gitlab: gitlab.Gitlab
|
429
|
-
|
358
|
+
class DeleteMixin(base.RESTManager[base.TObjCls]):
|
430
359
|
@exc.on_http_error(exc.GitlabDeleteError)
|
431
|
-
def delete(self, id:
|
360
|
+
def delete(self, id: str | int | None = None, **kwargs: Any) -> None:
|
432
361
|
"""Delete an object on the server.
|
433
362
|
|
434
363
|
Args:
|
@@ -444,42 +373,37 @@ class DeleteMixin(_RestManagerBase):
|
|
444
373
|
else:
|
445
374
|
path = f"{self.path}/{utils.EncodedId(id)}"
|
446
375
|
|
447
|
-
if TYPE_CHECKING:
|
448
|
-
assert path is not None
|
449
376
|
self.gitlab.http_delete(path, **kwargs)
|
450
377
|
|
451
378
|
|
452
|
-
class CRUDMixin(
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
gitlab: gitlab.Gitlab
|
379
|
+
class CRUDMixin(
|
380
|
+
GetMixin[base.TObjCls],
|
381
|
+
ListMixin[base.TObjCls],
|
382
|
+
CreateMixin[base.TObjCls],
|
383
|
+
UpdateMixin[base.TObjCls],
|
384
|
+
DeleteMixin[base.TObjCls],
|
385
|
+
): ...
|
460
386
|
|
461
387
|
|
462
|
-
class NoUpdateMixin(
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
_path: Optional[str]
|
469
|
-
gitlab: gitlab.Gitlab
|
388
|
+
class NoUpdateMixin(
|
389
|
+
GetMixin[base.TObjCls],
|
390
|
+
ListMixin[base.TObjCls],
|
391
|
+
CreateMixin[base.TObjCls],
|
392
|
+
DeleteMixin[base.TObjCls],
|
393
|
+
): ...
|
470
394
|
|
471
395
|
|
472
396
|
class SaveMixin(_RestObjectBase):
|
473
397
|
"""Mixin for RESTObject's that can be updated."""
|
474
398
|
|
475
|
-
_id_attr:
|
476
|
-
_attrs:
|
399
|
+
_id_attr: str | None
|
400
|
+
_attrs: dict[str, Any]
|
477
401
|
_module: ModuleType
|
478
|
-
_parent_attrs:
|
479
|
-
_updated_attrs:
|
480
|
-
manager: base.RESTManager
|
402
|
+
_parent_attrs: dict[str, Any]
|
403
|
+
_updated_attrs: dict[str, Any]
|
404
|
+
manager: base.RESTManager[Any]
|
481
405
|
|
482
|
-
def _get_updated_data(self) ->
|
406
|
+
def _get_updated_data(self) -> dict[str, Any]:
|
483
407
|
updated_data = {}
|
484
408
|
for attr in self.manager._update_attrs.required:
|
485
409
|
# Get everything required, no matter if it's been updated
|
@@ -489,7 +413,7 @@ class SaveMixin(_RestObjectBase):
|
|
489
413
|
|
490
414
|
return updated_data
|
491
415
|
|
492
|
-
def save(self, **kwargs: Any) ->
|
416
|
+
def save(self, **kwargs: Any) -> dict[str, Any] | None:
|
493
417
|
"""Save the changes made to the object to the server.
|
494
418
|
|
495
419
|
The object is updated to match what the server returns.
|
@@ -521,12 +445,12 @@ class SaveMixin(_RestObjectBase):
|
|
521
445
|
class ObjectDeleteMixin(_RestObjectBase):
|
522
446
|
"""Mixin for RESTObject's that can be deleted."""
|
523
447
|
|
524
|
-
_id_attr:
|
525
|
-
_attrs:
|
448
|
+
_id_attr: str | None
|
449
|
+
_attrs: dict[str, Any]
|
526
450
|
_module: ModuleType
|
527
|
-
_parent_attrs:
|
528
|
-
_updated_attrs:
|
529
|
-
manager: base.RESTManager
|
451
|
+
_parent_attrs: dict[str, Any]
|
452
|
+
_updated_attrs: dict[str, Any]
|
453
|
+
manager: base.RESTManager[Any]
|
530
454
|
|
531
455
|
def delete(self, **kwargs: Any) -> None:
|
532
456
|
"""Delete the object from the server.
|
@@ -545,16 +469,16 @@ class ObjectDeleteMixin(_RestObjectBase):
|
|
545
469
|
|
546
470
|
|
547
471
|
class UserAgentDetailMixin(_RestObjectBase):
|
548
|
-
_id_attr:
|
549
|
-
_attrs:
|
472
|
+
_id_attr: str | None
|
473
|
+
_attrs: dict[str, Any]
|
550
474
|
_module: ModuleType
|
551
|
-
_parent_attrs:
|
552
|
-
_updated_attrs:
|
553
|
-
manager: base.RESTManager
|
475
|
+
_parent_attrs: dict[str, Any]
|
476
|
+
_updated_attrs: dict[str, Any]
|
477
|
+
manager: base.RESTManager[Any]
|
554
478
|
|
555
479
|
@cli.register_custom_action(cls_names=("Snippet", "ProjectSnippet", "ProjectIssue"))
|
556
480
|
@exc.on_http_error(exc.GitlabGetError)
|
557
|
-
def user_agent_detail(self, **kwargs: Any) ->
|
481
|
+
def user_agent_detail(self, **kwargs: Any) -> dict[str, Any]:
|
558
482
|
"""Get the user agent detail.
|
559
483
|
|
560
484
|
Args:
|
@@ -572,12 +496,12 @@ class UserAgentDetailMixin(_RestObjectBase):
|
|
572
496
|
|
573
497
|
|
574
498
|
class AccessRequestMixin(_RestObjectBase):
|
575
|
-
_id_attr:
|
576
|
-
_attrs:
|
499
|
+
_id_attr: str | None
|
500
|
+
_attrs: dict[str, Any]
|
577
501
|
_module: ModuleType
|
578
|
-
_parent_attrs:
|
579
|
-
_updated_attrs:
|
580
|
-
manager: base.RESTManager
|
502
|
+
_parent_attrs: dict[str, Any]
|
503
|
+
_updated_attrs: dict[str, Any]
|
504
|
+
manager: base.RESTManager[Any]
|
581
505
|
|
582
506
|
@cli.register_custom_action(
|
583
507
|
cls_names=("ProjectAccessRequest", "GroupAccessRequest"),
|
@@ -607,12 +531,12 @@ class AccessRequestMixin(_RestObjectBase):
|
|
607
531
|
|
608
532
|
|
609
533
|
class DownloadMixin(_RestObjectBase):
|
610
|
-
_id_attr:
|
611
|
-
_attrs:
|
534
|
+
_id_attr: str | None
|
535
|
+
_attrs: dict[str, Any]
|
612
536
|
_module: ModuleType
|
613
|
-
_parent_attrs:
|
614
|
-
_updated_attrs:
|
615
|
-
manager: base.RESTManager
|
537
|
+
_parent_attrs: dict[str, Any]
|
538
|
+
_updated_attrs: dict[str, Any]
|
539
|
+
manager: base.RESTManager[Any]
|
616
540
|
|
617
541
|
@overload
|
618
542
|
def download(
|
@@ -640,7 +564,7 @@ class DownloadMixin(_RestObjectBase):
|
|
640
564
|
def download(
|
641
565
|
self,
|
642
566
|
streamed: Literal[True] = True,
|
643
|
-
action:
|
567
|
+
action: Callable[[bytes], Any] | None = None,
|
644
568
|
chunk_size: int = 1024,
|
645
569
|
*,
|
646
570
|
iterator: Literal[False] = False,
|
@@ -652,12 +576,12 @@ class DownloadMixin(_RestObjectBase):
|
|
652
576
|
def download(
|
653
577
|
self,
|
654
578
|
streamed: bool = False,
|
655
|
-
action:
|
579
|
+
action: Callable[[bytes], Any] | None = None,
|
656
580
|
chunk_size: int = 1024,
|
657
581
|
*,
|
658
582
|
iterator: bool = False,
|
659
583
|
**kwargs: Any,
|
660
|
-
) ->
|
584
|
+
) -> bytes | Iterator[Any] | None:
|
661
585
|
"""Download the archive of a resource export.
|
662
586
|
|
663
587
|
Args:
|
@@ -689,15 +613,7 @@ class DownloadMixin(_RestObjectBase):
|
|
689
613
|
)
|
690
614
|
|
691
615
|
|
692
|
-
class RotateMixin(
|
693
|
-
_computed_path: Optional[str]
|
694
|
-
_from_parent_attrs: Dict[str, Any]
|
695
|
-
_obj_cls: Optional[Type[base.RESTObject]]
|
696
|
-
_parent: Optional[base.RESTObject]
|
697
|
-
_parent_attrs: Dict[str, Any]
|
698
|
-
_path: Optional[str]
|
699
|
-
gitlab: gitlab.Gitlab
|
700
|
-
|
616
|
+
class RotateMixin(base.RESTManager[base.TObjCls]):
|
701
617
|
@cli.register_custom_action(
|
702
618
|
cls_names=(
|
703
619
|
"PersonalAccessTokenManager",
|
@@ -708,8 +624,8 @@ class RotateMixin(_RestManagerBase):
|
|
708
624
|
)
|
709
625
|
@exc.on_http_error(exc.GitlabRotateError)
|
710
626
|
def rotate(
|
711
|
-
self, id:
|
712
|
-
) ->
|
627
|
+
self, id: str | int, expires_at: str | None = None, **kwargs: Any
|
628
|
+
) -> dict[str, Any]:
|
713
629
|
"""Rotate an access token.
|
714
630
|
|
715
631
|
Args:
|
@@ -721,7 +637,7 @@ class RotateMixin(_RestManagerBase):
|
|
721
637
|
GitlabRotateError: If the server cannot perform the request
|
722
638
|
"""
|
723
639
|
path = f"{self.path}/{utils.EncodedId(id)}/rotate"
|
724
|
-
data:
|
640
|
+
data: dict[str, Any] = {}
|
725
641
|
if expires_at is not None:
|
726
642
|
data = {"expires_at": expires_at}
|
727
643
|
|
@@ -732,22 +648,23 @@ class RotateMixin(_RestManagerBase):
|
|
732
648
|
|
733
649
|
|
734
650
|
class ObjectRotateMixin(_RestObjectBase):
|
735
|
-
_id_attr:
|
736
|
-
_attrs:
|
651
|
+
_id_attr: str | None
|
652
|
+
_attrs: dict[str, Any]
|
737
653
|
_module: ModuleType
|
738
|
-
_parent_attrs:
|
739
|
-
_updated_attrs:
|
740
|
-
manager: base.RESTManager
|
654
|
+
_parent_attrs: dict[str, Any]
|
655
|
+
_updated_attrs: dict[str, Any]
|
656
|
+
manager: base.RESTManager[Any]
|
741
657
|
|
742
658
|
@cli.register_custom_action(
|
743
659
|
cls_names=("PersonalAccessToken", "GroupAccessToken", "ProjectAccessToken"),
|
744
660
|
optional=("expires_at",),
|
745
661
|
)
|
746
662
|
@exc.on_http_error(exc.GitlabRotateError)
|
747
|
-
def rotate(self, **kwargs: Any) ->
|
663
|
+
def rotate(self, *, self_rotate: bool = False, **kwargs: Any) -> dict[str, Any]:
|
748
664
|
"""Rotate the current access token object.
|
749
665
|
|
750
666
|
Args:
|
667
|
+
self_rotate: If True, the current access token object will be rotated.
|
751
668
|
**kwargs: Extra options to send to the server (e.g. sudo)
|
752
669
|
|
753
670
|
Raises:
|
@@ -757,18 +674,19 @@ class ObjectRotateMixin(_RestObjectBase):
|
|
757
674
|
if TYPE_CHECKING:
|
758
675
|
assert isinstance(self.manager, RotateMixin)
|
759
676
|
assert self.encoded_id is not None
|
760
|
-
|
677
|
+
token_id = "self" if self_rotate else self.encoded_id
|
678
|
+
server_data = self.manager.rotate(token_id, **kwargs)
|
761
679
|
self._update_attrs(server_data)
|
762
680
|
return server_data
|
763
681
|
|
764
682
|
|
765
683
|
class SubscribableMixin(_RestObjectBase):
|
766
|
-
_id_attr:
|
767
|
-
_attrs:
|
684
|
+
_id_attr: str | None
|
685
|
+
_attrs: dict[str, Any]
|
768
686
|
_module: ModuleType
|
769
|
-
_parent_attrs:
|
770
|
-
_updated_attrs:
|
771
|
-
manager: base.RESTManager
|
687
|
+
_parent_attrs: dict[str, Any]
|
688
|
+
_updated_attrs: dict[str, Any]
|
689
|
+
manager: base.RESTManager[Any]
|
772
690
|
|
773
691
|
@cli.register_custom_action(
|
774
692
|
cls_names=("ProjectIssue", "ProjectMergeRequest", "ProjectLabel", "GroupLabel")
|
@@ -812,12 +730,12 @@ class SubscribableMixin(_RestObjectBase):
|
|
812
730
|
|
813
731
|
|
814
732
|
class TodoMixin(_RestObjectBase):
|
815
|
-
_id_attr:
|
816
|
-
_attrs:
|
733
|
+
_id_attr: str | None
|
734
|
+
_attrs: dict[str, Any]
|
817
735
|
_module: ModuleType
|
818
|
-
_parent_attrs:
|
819
|
-
_updated_attrs:
|
820
|
-
manager: base.RESTManager
|
736
|
+
_parent_attrs: dict[str, Any]
|
737
|
+
_updated_attrs: dict[str, Any]
|
738
|
+
manager: base.RESTManager[Any]
|
821
739
|
|
822
740
|
@cli.register_custom_action(cls_names=("ProjectIssue", "ProjectMergeRequest"))
|
823
741
|
@exc.on_http_error(exc.GitlabTodoError)
|
@@ -836,16 +754,16 @@ class TodoMixin(_RestObjectBase):
|
|
836
754
|
|
837
755
|
|
838
756
|
class TimeTrackingMixin(_RestObjectBase):
|
839
|
-
_id_attr:
|
840
|
-
_attrs:
|
757
|
+
_id_attr: str | None
|
758
|
+
_attrs: dict[str, Any]
|
841
759
|
_module: ModuleType
|
842
|
-
_parent_attrs:
|
843
|
-
_updated_attrs:
|
844
|
-
manager: base.RESTManager
|
760
|
+
_parent_attrs: dict[str, Any]
|
761
|
+
_updated_attrs: dict[str, Any]
|
762
|
+
manager: base.RESTManager[Any]
|
845
763
|
|
846
764
|
@cli.register_custom_action(cls_names=("ProjectIssue", "ProjectMergeRequest"))
|
847
765
|
@exc.on_http_error(exc.GitlabTimeTrackingError)
|
848
|
-
def time_stats(self, **kwargs: Any) ->
|
766
|
+
def time_stats(self, **kwargs: Any) -> dict[str, Any]:
|
849
767
|
"""Get time stats for the object.
|
850
768
|
|
851
769
|
Args:
|
@@ -873,7 +791,7 @@ class TimeTrackingMixin(_RestObjectBase):
|
|
873
791
|
cls_names=("ProjectIssue", "ProjectMergeRequest"), required=("duration",)
|
874
792
|
)
|
875
793
|
@exc.on_http_error(exc.GitlabTimeTrackingError)
|
876
|
-
def time_estimate(self, duration: str, **kwargs: Any) ->
|
794
|
+
def time_estimate(self, duration: str, **kwargs: Any) -> dict[str, Any]:
|
877
795
|
"""Set an estimated time of work for the object.
|
878
796
|
|
879
797
|
Args:
|
@@ -893,7 +811,7 @@ class TimeTrackingMixin(_RestObjectBase):
|
|
893
811
|
|
894
812
|
@cli.register_custom_action(cls_names=("ProjectIssue", "ProjectMergeRequest"))
|
895
813
|
@exc.on_http_error(exc.GitlabTimeTrackingError)
|
896
|
-
def reset_time_estimate(self, **kwargs: Any) ->
|
814
|
+
def reset_time_estimate(self, **kwargs: Any) -> dict[str, Any]:
|
897
815
|
"""Resets estimated time for the object to 0 seconds.
|
898
816
|
|
899
817
|
Args:
|
@@ -913,7 +831,7 @@ class TimeTrackingMixin(_RestObjectBase):
|
|
913
831
|
cls_names=("ProjectIssue", "ProjectMergeRequest"), required=("duration",)
|
914
832
|
)
|
915
833
|
@exc.on_http_error(exc.GitlabTimeTrackingError)
|
916
|
-
def add_spent_time(self, duration: str, **kwargs: Any) ->
|
834
|
+
def add_spent_time(self, duration: str, **kwargs: Any) -> dict[str, Any]:
|
917
835
|
"""Add time spent working on the object.
|
918
836
|
|
919
837
|
Args:
|
@@ -933,7 +851,7 @@ class TimeTrackingMixin(_RestObjectBase):
|
|
933
851
|
|
934
852
|
@cli.register_custom_action(cls_names=("ProjectIssue", "ProjectMergeRequest"))
|
935
853
|
@exc.on_http_error(exc.GitlabTimeTrackingError)
|
936
|
-
def reset_spent_time(self, **kwargs: Any) ->
|
854
|
+
def reset_spent_time(self, **kwargs: Any) -> dict[str, Any]:
|
937
855
|
"""Resets the time spent working on the object.
|
938
856
|
|
939
857
|
Args:
|
@@ -951,22 +869,22 @@ class TimeTrackingMixin(_RestObjectBase):
|
|
951
869
|
|
952
870
|
|
953
871
|
class ParticipantsMixin(_RestObjectBase):
|
954
|
-
_id_attr:
|
955
|
-
_attrs:
|
872
|
+
_id_attr: str | None
|
873
|
+
_attrs: dict[str, Any]
|
956
874
|
_module: ModuleType
|
957
|
-
_parent_attrs:
|
958
|
-
_updated_attrs:
|
959
|
-
manager: base.RESTManager
|
875
|
+
_parent_attrs: dict[str, Any]
|
876
|
+
_updated_attrs: dict[str, Any]
|
877
|
+
manager: base.RESTManager[Any]
|
960
878
|
|
961
879
|
@cli.register_custom_action(cls_names=("ProjectMergeRequest", "ProjectIssue"))
|
962
880
|
@exc.on_http_error(exc.GitlabListError)
|
963
881
|
def participants(
|
964
882
|
self, **kwargs: Any
|
965
|
-
) ->
|
883
|
+
) -> gitlab.client.GitlabList | list[dict[str, Any]]:
|
966
884
|
"""List the participants.
|
967
885
|
|
968
886
|
Args:
|
969
|
-
|
887
|
+
get_all: If True, return all the items, without pagination
|
970
888
|
per_page: Number of items to retrieve per request
|
971
889
|
page: ID of the page to return (starts with page 1)
|
972
890
|
**kwargs: Extra options to send to the server (e.g. sudo)
|
@@ -986,13 +904,13 @@ class ParticipantsMixin(_RestObjectBase):
|
|
986
904
|
return result
|
987
905
|
|
988
906
|
|
989
|
-
class BadgeRenderMixin(
|
907
|
+
class BadgeRenderMixin(base.RESTManager[base.TObjCls]):
|
990
908
|
@cli.register_custom_action(
|
991
909
|
cls_names=("GroupBadgeManager", "ProjectBadgeManager"),
|
992
910
|
required=("link_url", "image_url"),
|
993
911
|
)
|
994
912
|
@exc.on_http_error(exc.GitlabRenderError)
|
995
|
-
def render(self, link_url: str, image_url: str, **kwargs: Any) ->
|
913
|
+
def render(self, link_url: str, image_url: str, **kwargs: Any) -> dict[str, Any]:
|
996
914
|
"""Preview link_url and image_url after interpolation.
|
997
915
|
|
998
916
|
Args:
|
@@ -1016,17 +934,15 @@ class BadgeRenderMixin(_RestManagerBase):
|
|
1016
934
|
|
1017
935
|
|
1018
936
|
class PromoteMixin(_RestObjectBase):
|
1019
|
-
_id_attr:
|
1020
|
-
_attrs:
|
937
|
+
_id_attr: str | None
|
938
|
+
_attrs: dict[str, Any]
|
1021
939
|
_module: ModuleType
|
1022
|
-
_parent_attrs:
|
1023
|
-
_updated_attrs:
|
940
|
+
_parent_attrs: dict[str, Any]
|
941
|
+
_updated_attrs: dict[str, Any]
|
1024
942
|
_update_method: UpdateMethod = UpdateMethod.PUT
|
1025
|
-
manager: base.RESTManager
|
943
|
+
manager: base.RESTManager[Any]
|
1026
944
|
|
1027
|
-
def _get_update_method(
|
1028
|
-
self,
|
1029
|
-
) -> Callable[..., Union[Dict[str, Any], requests.Response]]:
|
945
|
+
def _get_update_method(self) -> Callable[..., dict[str, Any] | requests.Response]:
|
1030
946
|
"""Return the HTTP method to use.
|
1031
947
|
|
1032
948
|
Returns:
|
@@ -1039,7 +955,7 @@ class PromoteMixin(_RestObjectBase):
|
|
1039
955
|
return http_method
|
1040
956
|
|
1041
957
|
@exc.on_http_error(exc.GitlabPromoteError)
|
1042
|
-
def promote(self, **kwargs: Any) ->
|
958
|
+
def promote(self, **kwargs: Any) -> dict[str, Any]:
|
1043
959
|
"""Promote the item.
|
1044
960
|
|
1045
961
|
Args:
|
@@ -1063,13 +979,13 @@ class PromoteMixin(_RestObjectBase):
|
|
1063
979
|
|
1064
980
|
|
1065
981
|
class UploadMixin(_RestObjectBase):
|
1066
|
-
_id_attr:
|
1067
|
-
_attrs:
|
982
|
+
_id_attr: str | None
|
983
|
+
_attrs: dict[str, Any]
|
1068
984
|
_module: ModuleType
|
1069
|
-
_parent_attrs:
|
1070
|
-
_updated_attrs:
|
985
|
+
_parent_attrs: dict[str, Any]
|
986
|
+
_updated_attrs: dict[str, Any]
|
1071
987
|
_upload_path: str
|
1072
|
-
manager: base.RESTManager
|
988
|
+
manager: base.RESTManager[Any]
|
1073
989
|
|
1074
990
|
def _get_upload_path(self) -> str:
|
1075
991
|
"""Formats _upload_path with object attributes.
|
@@ -1089,10 +1005,10 @@ class UploadMixin(_RestObjectBase):
|
|
1089
1005
|
def upload(
|
1090
1006
|
self,
|
1091
1007
|
filename: str,
|
1092
|
-
filedata:
|
1093
|
-
filepath:
|
1008
|
+
filedata: bytes | None = None,
|
1009
|
+
filepath: str | None = None,
|
1094
1010
|
**kwargs: Any,
|
1095
|
-
) ->
|
1011
|
+
) -> dict[str, Any]:
|
1096
1012
|
"""Upload the specified file.
|
1097
1013
|
|
1098
1014
|
.. note::
|