python-gitlab 4.4.0__py3-none-any.whl → 4.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. gitlab/_backends/protocol.py +2 -4
  2. gitlab/_version.py +1 -1
  3. gitlab/cli.py +33 -5
  4. gitlab/client.py +2 -3
  5. gitlab/mixins.py +22 -14
  6. gitlab/utils.py +3 -3
  7. gitlab/v4/cli.py +32 -11
  8. gitlab/v4/objects/__init__.py +1 -0
  9. gitlab/v4/objects/artifacts.py +7 -3
  10. gitlab/v4/objects/audit_events.py +1 -0
  11. gitlab/v4/objects/branches.py +10 -3
  12. gitlab/v4/objects/ci_lint.py +4 -4
  13. gitlab/v4/objects/commits.py +6 -6
  14. gitlab/v4/objects/container_registry.py +2 -2
  15. gitlab/v4/objects/deploy_keys.py +3 -1
  16. gitlab/v4/objects/deployments.py +3 -2
  17. gitlab/v4/objects/environments.py +1 -1
  18. gitlab/v4/objects/features.py +1 -0
  19. gitlab/v4/objects/files.py +15 -7
  20. gitlab/v4/objects/geo_nodes.py +4 -4
  21. gitlab/v4/objects/groups.py +13 -7
  22. gitlab/v4/objects/integrations.py +3 -1
  23. gitlab/v4/objects/issues.py +6 -4
  24. gitlab/v4/objects/iterations.py +29 -2
  25. gitlab/v4/objects/job_token_scope.py +48 -0
  26. gitlab/v4/objects/jobs.py +15 -15
  27. gitlab/v4/objects/merge_request_approvals.py +12 -59
  28. gitlab/v4/objects/merge_requests.py +14 -12
  29. gitlab/v4/objects/milestones.py +4 -4
  30. gitlab/v4/objects/namespaces.py +3 -1
  31. gitlab/v4/objects/packages.py +4 -4
  32. gitlab/v4/objects/pipelines.py +6 -5
  33. gitlab/v4/objects/projects.py +22 -18
  34. gitlab/v4/objects/repositories.py +14 -9
  35. gitlab/v4/objects/runners.py +2 -2
  36. gitlab/v4/objects/secure_files.py +2 -1
  37. gitlab/v4/objects/service_accounts.py +18 -0
  38. gitlab/v4/objects/sidekiq.py +4 -4
  39. gitlab/v4/objects/snippets.py +3 -3
  40. gitlab/v4/objects/todos.py +2 -2
  41. gitlab/v4/objects/topics.py +2 -2
  42. gitlab/v4/objects/users.py +11 -10
  43. gitlab/v4/objects/variables.py +1 -0
  44. {python_gitlab-4.4.0.dist-info → python_gitlab-4.6.0.dist-info}/METADATA +20 -3
  45. {python_gitlab-4.4.0.dist-info → python_gitlab-4.6.0.dist-info}/RECORD +50 -49
  46. {python_gitlab-4.4.0.dist-info → python_gitlab-4.6.0.dist-info}/WHEEL +1 -1
  47. {python_gitlab-4.4.0.dist-info → python_gitlab-4.6.0.dist-info}/AUTHORS +0 -0
  48. {python_gitlab-4.4.0.dist-info → python_gitlab-4.6.0.dist-info}/COPYING +0 -0
  49. {python_gitlab-4.4.0.dist-info → python_gitlab-4.6.0.dist-info}/entry_points.txt +0 -0
  50. {python_gitlab-4.4.0.dist-info → python_gitlab-4.6.0.dist-info}/top_level.txt +0 -0
@@ -3,6 +3,7 @@ GitLab API:
3
3
  https://docs.gitlab.com/ee/api/merge_requests.html
4
4
  https://docs.gitlab.com/ee/api/merge_request_approvals.html
5
5
  """
6
+
6
7
  from typing import Any, cast, Dict, Optional, TYPE_CHECKING, Union
7
8
 
8
9
  import requests
@@ -167,7 +168,7 @@ class ProjectMergeRequest(
167
168
  resourcestateevents: ProjectMergeRequestResourceStateEventManager
168
169
  reviewer_details: ProjectMergeRequestReviewerDetailManager
169
170
 
170
- @cli.register_custom_action("ProjectMergeRequest")
171
+ @cli.register_custom_action(cls_names="ProjectMergeRequest")
171
172
  @exc.on_http_error(exc.GitlabMROnBuildSuccessError)
172
173
  def cancel_merge_when_pipeline_succeeds(self, **kwargs: Any) -> Dict[str, str]:
173
174
  """Cancel merge when the pipeline succeeds.
@@ -196,7 +197,7 @@ class ProjectMergeRequest(
196
197
  assert isinstance(server_data, dict)
197
198
  return server_data
198
199
 
199
- @cli.register_custom_action("ProjectMergeRequest")
200
+ @cli.register_custom_action(cls_names="ProjectMergeRequest")
200
201
  @exc.on_http_error(exc.GitlabListError)
201
202
  def closes_issues(self, **kwargs: Any) -> RESTObjectList:
202
203
  """List issues that will close on merge."
@@ -221,7 +222,7 @@ class ProjectMergeRequest(
221
222
  manager = ProjectIssueManager(self.manager.gitlab, parent=self.manager._parent)
222
223
  return RESTObjectList(manager, ProjectIssue, data_list)
223
224
 
224
- @cli.register_custom_action("ProjectMergeRequest")
225
+ @cli.register_custom_action(cls_names="ProjectMergeRequest")
225
226
  @exc.on_http_error(exc.GitlabListError)
226
227
  def commits(self, **kwargs: Any) -> RESTObjectList:
227
228
  """List the merge request commits.
@@ -247,7 +248,9 @@ class ProjectMergeRequest(
247
248
  manager = ProjectCommitManager(self.manager.gitlab, parent=self.manager._parent)
248
249
  return RESTObjectList(manager, ProjectCommit, data_list)
249
250
 
250
- @cli.register_custom_action("ProjectMergeRequest", optional=("access_raw_diffs",))
251
+ @cli.register_custom_action(
252
+ cls_names="ProjectMergeRequest", optional=("access_raw_diffs",)
253
+ )
251
254
  @exc.on_http_error(exc.GitlabListError)
252
255
  def changes(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]:
253
256
  """List the merge request changes.
@@ -265,7 +268,7 @@ class ProjectMergeRequest(
265
268
  path = f"{self.manager.path}/{self.encoded_id}/changes"
266
269
  return self.manager.gitlab.http_get(path, **kwargs)
267
270
 
268
- @cli.register_custom_action("ProjectMergeRequest", (), ("sha",))
271
+ @cli.register_custom_action(cls_names="ProjectMergeRequest", optional=("sha",))
269
272
  @exc.on_http_error(exc.GitlabMRApprovalError)
270
273
  def approve(self, sha: Optional[str] = None, **kwargs: Any) -> Dict[str, Any]:
271
274
  """Approve the merge request.
@@ -294,7 +297,7 @@ class ProjectMergeRequest(
294
297
  self._update_attrs(server_data)
295
298
  return server_data
296
299
 
297
- @cli.register_custom_action("ProjectMergeRequest")
300
+ @cli.register_custom_action(cls_names="ProjectMergeRequest")
298
301
  @exc.on_http_error(exc.GitlabMRApprovalError)
299
302
  def unapprove(self, **kwargs: Any) -> None:
300
303
  """Unapprove the merge request.
@@ -316,7 +319,7 @@ class ProjectMergeRequest(
316
319
  assert isinstance(server_data, dict)
317
320
  self._update_attrs(server_data)
318
321
 
319
- @cli.register_custom_action("ProjectMergeRequest")
322
+ @cli.register_custom_action(cls_names="ProjectMergeRequest")
320
323
  @exc.on_http_error(exc.GitlabMRRebaseError)
321
324
  def rebase(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]:
322
325
  """Attempt to rebase the source branch onto the target branch
@@ -332,7 +335,7 @@ class ProjectMergeRequest(
332
335
  data: Dict[str, Any] = {}
333
336
  return self.manager.gitlab.http_put(path, post_data=data, **kwargs)
334
337
 
335
- @cli.register_custom_action("ProjectMergeRequest")
338
+ @cli.register_custom_action(cls_names="ProjectMergeRequest")
336
339
  @exc.on_http_error(exc.GitlabMRResetApprovalError)
337
340
  def reset_approvals(
338
341
  self, **kwargs: Any
@@ -350,7 +353,7 @@ class ProjectMergeRequest(
350
353
  data: Dict[str, Any] = {}
351
354
  return self.manager.gitlab.http_put(path, post_data=data, **kwargs)
352
355
 
353
- @cli.register_custom_action("ProjectMergeRequest")
356
+ @cli.register_custom_action(cls_names="ProjectMergeRequest")
354
357
  @exc.on_http_error(exc.GitlabGetError)
355
358
  def merge_ref(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]:
356
359
  """Attempt to merge changes between source and target branches into
@@ -366,9 +369,8 @@ class ProjectMergeRequest(
366
369
  return self.manager.gitlab.http_get(path, **kwargs)
367
370
 
368
371
  @cli.register_custom_action(
369
- "ProjectMergeRequest",
370
- (),
371
- (
372
+ cls_names="ProjectMergeRequest",
373
+ optional=(
372
374
  "merge_commit_message",
373
375
  "should_remove_source_branch",
374
376
  "merge_when_pipeline_succeeds",
@@ -31,7 +31,7 @@ __all__ = [
31
31
  class GroupMilestone(SaveMixin, ObjectDeleteMixin, RESTObject):
32
32
  _repr_attr = "title"
33
33
 
34
- @cli.register_custom_action("GroupMilestone")
34
+ @cli.register_custom_action(cls_names="GroupMilestone")
35
35
  @exc.on_http_error(exc.GitlabListError)
36
36
  def issues(self, **kwargs: Any) -> RESTObjectList:
37
37
  """List issues related to this milestone.
@@ -58,7 +58,7 @@ class GroupMilestone(SaveMixin, ObjectDeleteMixin, RESTObject):
58
58
  # FIXME(gpocentek): the computed manager path is not correct
59
59
  return RESTObjectList(manager, GroupIssue, data_list)
60
60
 
61
- @cli.register_custom_action("GroupMilestone")
61
+ @cli.register_custom_action(cls_names="GroupMilestone")
62
62
  @exc.on_http_error(exc.GitlabListError)
63
63
  def merge_requests(self, **kwargs: Any) -> RESTObjectList:
64
64
  """List the merge requests related to this milestone.
@@ -108,7 +108,7 @@ class ProjectMilestone(PromoteMixin, SaveMixin, ObjectDeleteMixin, RESTObject):
108
108
  _repr_attr = "title"
109
109
  _update_method = UpdateMethod.POST
110
110
 
111
- @cli.register_custom_action("ProjectMilestone")
111
+ @cli.register_custom_action(cls_names="ProjectMilestone")
112
112
  @exc.on_http_error(exc.GitlabListError)
113
113
  def issues(self, **kwargs: Any) -> RESTObjectList:
114
114
  """List issues related to this milestone.
@@ -135,7 +135,7 @@ class ProjectMilestone(PromoteMixin, SaveMixin, ObjectDeleteMixin, RESTObject):
135
135
  # FIXME(gpocentek): the computed manager path is not correct
136
136
  return RESTObjectList(manager, ProjectIssue, data_list)
137
137
 
138
- @cli.register_custom_action("ProjectMilestone")
138
+ @cli.register_custom_action(cls_names="ProjectMilestone")
139
139
  @exc.on_http_error(exc.GitlabListError)
140
140
  def merge_requests(self, **kwargs: Any) -> RESTObjectList:
141
141
  """List the merge requests related to this milestone.
@@ -24,7 +24,9 @@ class NamespaceManager(RetrieveMixin, RESTManager):
24
24
  def get(self, id: Union[str, int], lazy: bool = False, **kwargs: Any) -> Namespace:
25
25
  return cast(Namespace, super().get(id=id, lazy=lazy, **kwargs))
26
26
 
27
- @cli.register_custom_action("NamespaceManager", ("namespace", "parent_id"))
27
+ @cli.register_custom_action(
28
+ cls_names="NamespaceManager", required=("namespace", "parent_id")
29
+ )
28
30
  @exc.on_http_error(exc.GitlabGetError)
29
31
  def exists(self, namespace: str, **kwargs: Any) -> Namespace:
30
32
  """Get existence of a namespace by path.
@@ -48,8 +48,8 @@ class GenericPackageManager(RESTManager):
48
48
  _from_parent_attrs = {"project_id": "id"}
49
49
 
50
50
  @cli.register_custom_action(
51
- "GenericPackageManager",
52
- ("package_name", "package_version", "file_name", "path"),
51
+ cls_names="GenericPackageManager",
52
+ required=("package_name", "package_version", "file_name", "path"),
53
53
  )
54
54
  @exc.on_http_error(exc.GitlabUploadError)
55
55
  def upload(
@@ -123,8 +123,8 @@ class GenericPackageManager(RESTManager):
123
123
  return self._obj_cls(self, attrs=attrs)
124
124
 
125
125
  @cli.register_custom_action(
126
- "GenericPackageManager",
127
- ("package_name", "package_version", "file_name"),
126
+ cls_names="GenericPackageManager",
127
+ required=("package_name", "package_version", "file_name"),
128
128
  )
129
129
  @exc.on_http_error(exc.GitlabGetError)
130
130
  def download(
@@ -17,7 +17,7 @@ from gitlab.mixins import (
17
17
  SaveMixin,
18
18
  UpdateMixin,
19
19
  )
20
- from gitlab.types import RequiredOptional
20
+ from gitlab.types import ArrayAttribute, RequiredOptional
21
21
 
22
22
  __all__ = [
23
23
  "ProjectMergeRequestPipeline",
@@ -60,7 +60,7 @@ class ProjectPipeline(RefreshMixin, ObjectDeleteMixin, RESTObject):
60
60
  test_report_summary: "ProjectPipelineTestReportSummaryManager"
61
61
  variables: "ProjectPipelineVariableManager"
62
62
 
63
- @cli.register_custom_action("ProjectPipeline")
63
+ @cli.register_custom_action(cls_names="ProjectPipeline")
64
64
  @exc.on_http_error(exc.GitlabPipelineCancelError)
65
65
  def cancel(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]:
66
66
  """Cancel the job.
@@ -75,7 +75,7 @@ class ProjectPipeline(RefreshMixin, ObjectDeleteMixin, RESTObject):
75
75
  path = f"{self.manager.path}/{self.encoded_id}/cancel"
76
76
  return self.manager.gitlab.http_post(path, **kwargs)
77
77
 
78
- @cli.register_custom_action("ProjectPipeline")
78
+ @cli.register_custom_action(cls_names="ProjectPipeline")
79
79
  @exc.on_http_error(exc.GitlabPipelineRetryError)
80
80
  def retry(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]:
81
81
  """Retry the job.
@@ -149,6 +149,7 @@ class ProjectPipelineJobManager(ListMixin, RESTManager):
149
149
  _obj_cls = ProjectPipelineJob
150
150
  _from_parent_attrs = {"project_id": "project_id", "pipeline_id": "id"}
151
151
  _list_filters = ("scope", "include_retried")
152
+ _types = {"scope": ArrayAttribute}
152
153
 
153
154
 
154
155
  class ProjectPipelineBridge(RESTObject):
@@ -200,7 +201,7 @@ class ProjectPipelineSchedule(SaveMixin, ObjectDeleteMixin, RESTObject):
200
201
  variables: ProjectPipelineScheduleVariableManager
201
202
  pipelines: ProjectPipelineSchedulePipelineManager
202
203
 
203
- @cli.register_custom_action("ProjectPipelineSchedule")
204
+ @cli.register_custom_action(cls_names="ProjectPipelineSchedule")
204
205
  @exc.on_http_error(exc.GitlabOwnershipError)
205
206
  def take_ownership(self, **kwargs: Any) -> None:
206
207
  """Update the owner of a pipeline schedule.
@@ -218,7 +219,7 @@ class ProjectPipelineSchedule(SaveMixin, ObjectDeleteMixin, RESTObject):
218
219
  assert isinstance(server_data, dict)
219
220
  self._update_attrs(server_data)
220
221
 
221
- @cli.register_custom_action("ProjectPipelineSchedule")
222
+ @cli.register_custom_action(cls_names="ProjectPipelineSchedule")
222
223
  @exc.on_http_error(exc.GitlabPipelinePlayError)
223
224
  def play(self, **kwargs: Any) -> Dict[str, Any]:
224
225
  """Trigger a new scheduled pipeline, which runs immediately.
@@ -2,6 +2,8 @@
2
2
  GitLab API:
3
3
  https://docs.gitlab.com/ee/api/projects.html
4
4
  """
5
+
6
+ import io
5
7
  from typing import (
6
8
  Any,
7
9
  Callable,
@@ -229,7 +231,7 @@ class Project(
229
231
  variables: ProjectVariableManager
230
232
  wikis: ProjectWikiManager
231
233
 
232
- @cli.register_custom_action("Project", ("forked_from_id",))
234
+ @cli.register_custom_action(cls_names="Project", required=("forked_from_id",))
233
235
  @exc.on_http_error(exc.GitlabCreateError)
234
236
  def create_fork_relation(self, forked_from_id: int, **kwargs: Any) -> None:
235
237
  """Create a forked from/to relation between existing projects.
@@ -245,7 +247,7 @@ class Project(
245
247
  path = f"/projects/{self.encoded_id}/fork/{forked_from_id}"
246
248
  self.manager.gitlab.http_post(path, **kwargs)
247
249
 
248
- @cli.register_custom_action("Project")
250
+ @cli.register_custom_action(cls_names="Project")
249
251
  @exc.on_http_error(exc.GitlabDeleteError)
250
252
  def delete_fork_relation(self, **kwargs: Any) -> None:
251
253
  """Delete a forked relation between existing projects.
@@ -260,7 +262,7 @@ class Project(
260
262
  path = f"/projects/{self.encoded_id}/fork"
261
263
  self.manager.gitlab.http_delete(path, **kwargs)
262
264
 
263
- @cli.register_custom_action("Project")
265
+ @cli.register_custom_action(cls_names="Project")
264
266
  @exc.on_http_error(exc.GitlabGetError)
265
267
  def languages(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]:
266
268
  """Get languages used in the project with percentage value.
@@ -275,7 +277,7 @@ class Project(
275
277
  path = f"/projects/{self.encoded_id}/languages"
276
278
  return self.manager.gitlab.http_get(path, **kwargs)
277
279
 
278
- @cli.register_custom_action("Project")
280
+ @cli.register_custom_action(cls_names="Project")
279
281
  @exc.on_http_error(exc.GitlabCreateError)
280
282
  def star(self, **kwargs: Any) -> None:
281
283
  """Star a project.
@@ -293,7 +295,7 @@ class Project(
293
295
  assert isinstance(server_data, dict)
294
296
  self._update_attrs(server_data)
295
297
 
296
- @cli.register_custom_action("Project")
298
+ @cli.register_custom_action(cls_names="Project")
297
299
  @exc.on_http_error(exc.GitlabDeleteError)
298
300
  def unstar(self, **kwargs: Any) -> None:
299
301
  """Unstar a project.
@@ -311,7 +313,7 @@ class Project(
311
313
  assert isinstance(server_data, dict)
312
314
  self._update_attrs(server_data)
313
315
 
314
- @cli.register_custom_action("Project")
316
+ @cli.register_custom_action(cls_names="Project")
315
317
  @exc.on_http_error(exc.GitlabCreateError)
316
318
  def archive(self, **kwargs: Any) -> None:
317
319
  """Archive a project.
@@ -329,7 +331,7 @@ class Project(
329
331
  assert isinstance(server_data, dict)
330
332
  self._update_attrs(server_data)
331
333
 
332
- @cli.register_custom_action("Project")
334
+ @cli.register_custom_action(cls_names="Project")
333
335
  @exc.on_http_error(exc.GitlabDeleteError)
334
336
  def unarchive(self, **kwargs: Any) -> None:
335
337
  """Unarchive a project.
@@ -348,7 +350,9 @@ class Project(
348
350
  self._update_attrs(server_data)
349
351
 
350
352
  @cli.register_custom_action(
351
- "Project", ("group_id", "group_access"), ("expires_at",)
353
+ cls_names="Project",
354
+ required=("group_id", "group_access"),
355
+ optional=("expires_at",),
352
356
  )
353
357
  @exc.on_http_error(exc.GitlabCreateError)
354
358
  def share(
@@ -377,7 +381,7 @@ class Project(
377
381
  }
378
382
  self.manager.gitlab.http_post(path, post_data=data, **kwargs)
379
383
 
380
- @cli.register_custom_action("Project", ("group_id",))
384
+ @cli.register_custom_action(cls_names="Project", required=("group_id",))
381
385
  @exc.on_http_error(exc.GitlabDeleteError)
382
386
  def unshare(self, group_id: int, **kwargs: Any) -> None:
383
387
  """Delete a shared project link within a group.
@@ -394,7 +398,7 @@ class Project(
394
398
  self.manager.gitlab.http_delete(path, **kwargs)
395
399
 
396
400
  # variables not supported in CLI
397
- @cli.register_custom_action("Project", ("ref", "token"))
401
+ @cli.register_custom_action(cls_names="Project", required=("ref", "token"))
398
402
  @exc.on_http_error(exc.GitlabCreateError)
399
403
  def trigger_pipeline(
400
404
  self,
@@ -425,7 +429,7 @@ class Project(
425
429
  assert isinstance(attrs, dict)
426
430
  return ProjectPipeline(self.pipelines, attrs)
427
431
 
428
- @cli.register_custom_action("Project")
432
+ @cli.register_custom_action(cls_names="Project")
429
433
  @exc.on_http_error(exc.GitlabHousekeepingError)
430
434
  def housekeeping(self, **kwargs: Any) -> None:
431
435
  """Start the housekeeping task.
@@ -441,7 +445,7 @@ class Project(
441
445
  path = f"/projects/{self.encoded_id}/housekeeping"
442
446
  self.manager.gitlab.http_post(path, **kwargs)
443
447
 
444
- @cli.register_custom_action("Project")
448
+ @cli.register_custom_action(cls_names="Project")
445
449
  @exc.on_http_error(exc.GitlabRestoreError)
446
450
  def restore(self, **kwargs: Any) -> None:
447
451
  """Restore a project marked for deletion.
@@ -456,7 +460,7 @@ class Project(
456
460
  path = f"/projects/{self.encoded_id}/restore"
457
461
  self.manager.gitlab.http_post(path, **kwargs)
458
462
 
459
- @cli.register_custom_action("Project", optional=("wiki",))
463
+ @cli.register_custom_action(cls_names="Project", optional=("wiki",))
460
464
  @exc.on_http_error(exc.GitlabGetError)
461
465
  def snapshot(
462
466
  self,
@@ -499,7 +503,7 @@ class Project(
499
503
  result, streamed, action, chunk_size, iterator=iterator
500
504
  )
501
505
 
502
- @cli.register_custom_action("Project", ("scope", "search"))
506
+ @cli.register_custom_action(cls_names="Project", required=("scope", "search"))
503
507
  @exc.on_http_error(exc.GitlabSearchError)
504
508
  def search(
505
509
  self, scope: str, search: str, **kwargs: Any
@@ -522,7 +526,7 @@ class Project(
522
526
  path = f"/projects/{self.encoded_id}/search"
523
527
  return self.manager.gitlab.http_list(path, query_data=data, **kwargs)
524
528
 
525
- @cli.register_custom_action("Project")
529
+ @cli.register_custom_action(cls_names="Project")
526
530
  @exc.on_http_error(exc.GitlabCreateError)
527
531
  def mirror_pull(self, **kwargs: Any) -> None:
528
532
  """Start the pull mirroring process for the project.
@@ -537,7 +541,7 @@ class Project(
537
541
  path = f"/projects/{self.encoded_id}/mirror/pull"
538
542
  self.manager.gitlab.http_post(path, **kwargs)
539
543
 
540
- @cli.register_custom_action("Project")
544
+ @cli.register_custom_action(cls_names="Project")
541
545
  @exc.on_http_error(exc.GitlabGetError)
542
546
  def mirror_pull_details(self, **kwargs: Any) -> Dict[str, Any]:
543
547
  """Get a project's pull mirror details.
@@ -560,7 +564,7 @@ class Project(
560
564
  assert isinstance(result, dict)
561
565
  return result
562
566
 
563
- @cli.register_custom_action("Project", ("to_namespace",))
567
+ @cli.register_custom_action(cls_names="Project", required=("to_namespace",))
564
568
  @exc.on_http_error(exc.GitlabTransferProjectError)
565
569
  def transfer(self, to_namespace: Union[int, str], **kwargs: Any) -> None:
566
570
  """Transfer a project to the given namespace ID
@@ -785,7 +789,7 @@ class ProjectManager(CRUDMixin, RESTManager):
785
789
  @exc.on_http_error(exc.GitlabImportError)
786
790
  def import_project(
787
791
  self,
788
- file: str,
792
+ file: io.BufferedReader,
789
793
  path: str,
790
794
  name: Optional[str] = None,
791
795
  namespace: Optional[str] = None,
@@ -3,6 +3,7 @@ GitLab API: https://docs.gitlab.com/ee/api/repositories.html
3
3
 
4
4
  Currently this module only contains repository-related methods for projects.
5
5
  """
6
+
6
7
  from typing import Any, Callable, Dict, Iterator, List, Optional, TYPE_CHECKING, Union
7
8
 
8
9
  import requests
@@ -20,7 +21,9 @@ else:
20
21
 
21
22
 
22
23
  class RepositoryMixin(_RestObjectBase):
23
- @cli.register_custom_action("Project", ("submodule", "branch", "commit_sha"))
24
+ @cli.register_custom_action(
25
+ cls_names="Project", required=("submodule", "branch", "commit_sha")
26
+ )
24
27
  @exc.on_http_error(exc.GitlabUpdateError)
25
28
  def update_submodule(
26
29
  self, submodule: str, branch: str, commit_sha: str, **kwargs: Any
@@ -46,7 +49,9 @@ class RepositoryMixin(_RestObjectBase):
46
49
  data["commit_message"] = kwargs["commit_message"]
47
50
  return self.manager.gitlab.http_put(path, post_data=data)
48
51
 
49
- @cli.register_custom_action("Project", (), ("path", "ref", "recursive"))
52
+ @cli.register_custom_action(
53
+ cls_names="Project", optional=("path", "ref", "recursive")
54
+ )
50
55
  @exc.on_http_error(exc.GitlabGetError)
51
56
  def repository_tree(
52
57
  self, path: str = "", ref: str = "", recursive: bool = False, **kwargs: Any
@@ -79,7 +84,7 @@ class RepositoryMixin(_RestObjectBase):
79
84
  query_data["ref"] = ref
80
85
  return self.manager.gitlab.http_list(gl_path, query_data=query_data, **kwargs)
81
86
 
82
- @cli.register_custom_action("Project", ("sha",))
87
+ @cli.register_custom_action(cls_names="Project", required=("sha",))
83
88
  @exc.on_http_error(exc.GitlabGetError)
84
89
  def repository_blob(
85
90
  self, sha: str, **kwargs: Any
@@ -101,7 +106,7 @@ class RepositoryMixin(_RestObjectBase):
101
106
  path = f"/projects/{self.encoded_id}/repository/blobs/{sha}"
102
107
  return self.manager.gitlab.http_get(path, **kwargs)
103
108
 
104
- @cli.register_custom_action("Project", ("sha",))
109
+ @cli.register_custom_action(cls_names="Project", required=("sha",))
105
110
  @exc.on_http_error(exc.GitlabGetError)
106
111
  def repository_raw_blob(
107
112
  self,
@@ -144,7 +149,7 @@ class RepositoryMixin(_RestObjectBase):
144
149
  result, streamed, action, chunk_size, iterator=iterator
145
150
  )
146
151
 
147
- @cli.register_custom_action("Project", ("from_", "to"))
152
+ @cli.register_custom_action(cls_names="Project", required=("from_", "to"))
148
153
  @exc.on_http_error(exc.GitlabGetError)
149
154
  def repository_compare(
150
155
  self, from_: str, to: str, **kwargs: Any
@@ -167,7 +172,7 @@ class RepositoryMixin(_RestObjectBase):
167
172
  query_data = {"from": from_, "to": to}
168
173
  return self.manager.gitlab.http_get(path, query_data=query_data, **kwargs)
169
174
 
170
- @cli.register_custom_action("Project")
175
+ @cli.register_custom_action(cls_names="Project")
171
176
  @exc.on_http_error(exc.GitlabGetError)
172
177
  def repository_contributors(
173
178
  self, **kwargs: Any
@@ -192,7 +197,7 @@ class RepositoryMixin(_RestObjectBase):
192
197
  path = f"/projects/{self.encoded_id}/repository/contributors"
193
198
  return self.manager.gitlab.http_list(path, **kwargs)
194
199
 
195
- @cli.register_custom_action("Project", (), ("sha", "format"))
200
+ @cli.register_custom_action(cls_names="Project", optional=("sha", "format"))
196
201
  @exc.on_http_error(exc.GitlabListError)
197
202
  def repository_archive(
198
203
  self,
@@ -246,7 +251,7 @@ class RepositoryMixin(_RestObjectBase):
246
251
  result, streamed, action, chunk_size, iterator=iterator
247
252
  )
248
253
 
249
- @cli.register_custom_action("Project", ("refs",))
254
+ @cli.register_custom_action(cls_names="Project", required=("refs",))
250
255
  @exc.on_http_error(exc.GitlabGetError)
251
256
  def repository_merge_base(
252
257
  self, refs: List[str], **kwargs: Any
@@ -272,7 +277,7 @@ class RepositoryMixin(_RestObjectBase):
272
277
  )
273
278
  return self.manager.gitlab.http_get(path, query_data=query_data, **kwargs)
274
279
 
275
- @cli.register_custom_action("Project")
280
+ @cli.register_custom_action(cls_names="Project")
276
281
  @exc.on_http_error(exc.GitlabDeleteError)
277
282
  def delete_merged_branches(self, **kwargs: Any) -> None:
278
283
  """Delete merged branches.
@@ -74,7 +74,7 @@ class RunnerManager(CRUDMixin, RESTManager):
74
74
  _list_filters = ("scope", "type", "status", "paused", "tag_list")
75
75
  _types = {"tag_list": types.CommaSeparatedListAttribute}
76
76
 
77
- @cli.register_custom_action("RunnerManager", (), ("scope",))
77
+ @cli.register_custom_action(cls_names="RunnerManager", optional=("scope",))
78
78
  @exc.on_http_error(exc.GitlabListError)
79
79
  def all(self, scope: Optional[str] = None, **kwargs: Any) -> List[Runner]:
80
80
  """List all the runners.
@@ -103,7 +103,7 @@ class RunnerManager(CRUDMixin, RESTManager):
103
103
  obj = self.gitlab.http_list(path, query_data, **kwargs)
104
104
  return [self._obj_cls(self, item) for item in obj]
105
105
 
106
- @cli.register_custom_action("RunnerManager", ("token",))
106
+ @cli.register_custom_action(cls_names="RunnerManager", required=("token",))
107
107
  @exc.on_http_error(exc.GitlabVerifyError)
108
108
  def verify(self, token: str, **kwargs: Any) -> None:
109
109
  """Validates authentication credentials for a registered Runner.
@@ -2,6 +2,7 @@
2
2
  GitLab API:
3
3
  https://docs.gitlab.com/ee/api/secure_files.html
4
4
  """
5
+
5
6
  from typing import Any, Callable, cast, Iterator, Optional, TYPE_CHECKING, Union
6
7
 
7
8
  import requests
@@ -17,7 +18,7 @@ __all__ = ["ProjectSecureFile", "ProjectSecureFileManager"]
17
18
 
18
19
 
19
20
  class ProjectSecureFile(ObjectDeleteMixin, RESTObject):
20
- @cli.register_custom_action("ProjectSecureFile")
21
+ @cli.register_custom_action(cls_names="ProjectSecureFile")
21
22
  @exc.on_http_error(exc.GitlabGetError)
22
23
  def download(
23
24
  self,
@@ -0,0 +1,18 @@
1
+ from gitlab.base import RESTManager, RESTObject
2
+ from gitlab.mixins import CreateMixin
3
+ from gitlab.types import RequiredOptional
4
+
5
+ __all__ = ["GroupServiceAccount", "GroupServiceAccountManager"]
6
+
7
+
8
+ class GroupServiceAccount(RESTObject):
9
+ pass
10
+
11
+
12
+ class GroupServiceAccountManager(CreateMixin, RESTManager):
13
+ _path = "/groups/{group_id}/service_accounts"
14
+ _obj_cls = GroupServiceAccount
15
+ _from_parent_attrs = {"group_id": "id"}
16
+ _create_attrs = RequiredOptional(
17
+ optional=("name", "username"),
18
+ )
@@ -18,7 +18,7 @@ class SidekiqManager(RESTManager):
18
18
  for the sidekiq metrics API.
19
19
  """
20
20
 
21
- @cli.register_custom_action("SidekiqManager")
21
+ @cli.register_custom_action(cls_names="SidekiqManager")
22
22
  @exc.on_http_error(exc.GitlabGetError)
23
23
  def queue_metrics(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]:
24
24
  """Return the registered queues information.
@@ -35,7 +35,7 @@ class SidekiqManager(RESTManager):
35
35
  """
36
36
  return self.gitlab.http_get("/sidekiq/queue_metrics", **kwargs)
37
37
 
38
- @cli.register_custom_action("SidekiqManager")
38
+ @cli.register_custom_action(cls_names="SidekiqManager")
39
39
  @exc.on_http_error(exc.GitlabGetError)
40
40
  def process_metrics(
41
41
  self, **kwargs: Any
@@ -54,7 +54,7 @@ class SidekiqManager(RESTManager):
54
54
  """
55
55
  return self.gitlab.http_get("/sidekiq/process_metrics", **kwargs)
56
56
 
57
- @cli.register_custom_action("SidekiqManager")
57
+ @cli.register_custom_action(cls_names="SidekiqManager")
58
58
  @exc.on_http_error(exc.GitlabGetError)
59
59
  def job_stats(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]:
60
60
  """Return statistics about the jobs performed.
@@ -71,7 +71,7 @@ class SidekiqManager(RESTManager):
71
71
  """
72
72
  return self.gitlab.http_get("/sidekiq/job_stats", **kwargs)
73
73
 
74
- @cli.register_custom_action("SidekiqManager")
74
+ @cli.register_custom_action(cls_names="SidekiqManager")
75
75
  @exc.on_http_error(exc.GitlabGetError)
76
76
  def compound_metrics(
77
77
  self, **kwargs: Any
@@ -24,7 +24,7 @@ __all__ = [
24
24
  class Snippet(UserAgentDetailMixin, SaveMixin, ObjectDeleteMixin, RESTObject):
25
25
  _repr_attr = "title"
26
26
 
27
- @cli.register_custom_action("Snippet")
27
+ @cli.register_custom_action(cls_names="Snippet")
28
28
  @exc.on_http_error(exc.GitlabGetError)
29
29
  def content(
30
30
  self,
@@ -89,7 +89,7 @@ class SnippetManager(CRUDMixin, RESTManager):
89
89
  ),
90
90
  )
91
91
 
92
- @cli.register_custom_action("SnippetManager")
92
+ @cli.register_custom_action(cls_names="SnippetManager")
93
93
  def public(self, **kwargs: Any) -> Union[RESTObjectList, List[RESTObject]]:
94
94
  """List all the public snippets.
95
95
 
@@ -117,7 +117,7 @@ class ProjectSnippet(UserAgentDetailMixin, SaveMixin, ObjectDeleteMixin, RESTObj
117
117
  discussions: ProjectSnippetDiscussionManager
118
118
  notes: ProjectSnippetNoteManager
119
119
 
120
- @cli.register_custom_action("ProjectSnippet")
120
+ @cli.register_custom_action(cls_names="ProjectSnippet")
121
121
  @exc.on_http_error(exc.GitlabGetError)
122
122
  def content(
123
123
  self,
@@ -12,7 +12,7 @@ __all__ = [
12
12
 
13
13
 
14
14
  class Todo(ObjectDeleteMixin, RESTObject):
15
- @cli.register_custom_action("Todo")
15
+ @cli.register_custom_action(cls_names="Todo")
16
16
  @exc.on_http_error(exc.GitlabTodoError)
17
17
  def mark_as_done(self, **kwargs: Any) -> Dict[str, Any]:
18
18
  """Mark the todo as done.
@@ -40,7 +40,7 @@ class TodoManager(ListMixin, DeleteMixin, RESTManager):
40
40
  _obj_cls = Todo
41
41
  _list_filters = ("action", "author_id", "project_id", "state", "type")
42
42
 
43
- @cli.register_custom_action("TodoManager")
43
+ @cli.register_custom_action(cls_names="TodoManager")
44
44
  @exc.on_http_error(exc.GitlabTodoError)
45
45
  def mark_all_as_done(self, **kwargs: Any) -> None:
46
46
  """Mark all the todos as done.
@@ -33,8 +33,8 @@ class TopicManager(CRUDMixin, RESTManager):
33
33
  return cast(Topic, super().get(id=id, lazy=lazy, **kwargs))
34
34
 
35
35
  @cli.register_custom_action(
36
- "TopicManager",
37
- mandatory=("source_topic_id", "target_topic_id"),
36
+ cls_names="TopicManager",
37
+ required=("source_topic_id", "target_topic_id"),
38
38
  )
39
39
  @exc.on_http_error(exc.GitlabMRClosedError)
40
40
  def merge(