python-gitlab 5.6.0__py3-none-any.whl → 6.1.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 (103) hide show
  1. gitlab/__init__.py +0 -1
  2. gitlab/_backends/protocol.py +9 -13
  3. gitlab/_backends/requests_backend.py +12 -12
  4. gitlab/_version.py +1 -1
  5. gitlab/base.py +48 -48
  6. gitlab/cli.py +15 -25
  7. gitlab/client.py +114 -140
  8. gitlab/config.py +16 -17
  9. gitlab/const.py +2 -0
  10. gitlab/exceptions.py +7 -5
  11. gitlab/mixins.py +154 -238
  12. gitlab/types.py +13 -14
  13. gitlab/utils.py +32 -43
  14. gitlab/v4/cli.py +51 -54
  15. gitlab/v4/objects/__init__.py +1 -0
  16. gitlab/v4/objects/access_requests.py +11 -3
  17. gitlab/v4/objects/appearance.py +12 -14
  18. gitlab/v4/objects/applications.py +5 -6
  19. gitlab/v4/objects/artifacts.py +10 -17
  20. gitlab/v4/objects/audit_events.py +4 -19
  21. gitlab/v4/objects/award_emojis.py +13 -57
  22. gitlab/v4/objects/badges.py +4 -19
  23. gitlab/v4/objects/boards.py +7 -27
  24. gitlab/v4/objects/branches.py +26 -14
  25. gitlab/v4/objects/broadcast_messages.py +3 -13
  26. gitlab/v4/objects/bulk_imports.py +6 -14
  27. gitlab/v4/objects/ci_lint.py +7 -13
  28. gitlab/v4/objects/cluster_agents.py +3 -13
  29. gitlab/v4/objects/clusters.py +13 -23
  30. gitlab/v4/objects/commits.py +23 -28
  31. gitlab/v4/objects/container_registry.py +13 -19
  32. gitlab/v4/objects/custom_attributes.py +16 -21
  33. gitlab/v4/objects/deploy_keys.py +22 -19
  34. gitlab/v4/objects/deploy_tokens.py +14 -32
  35. gitlab/v4/objects/deployments.py +13 -15
  36. gitlab/v4/objects/discussions.py +13 -29
  37. gitlab/v4/objects/draft_notes.py +4 -14
  38. gitlab/v4/objects/environments.py +13 -21
  39. gitlab/v4/objects/epics.py +14 -17
  40. gitlab/v4/objects/events.py +27 -79
  41. gitlab/v4/objects/export_import.py +7 -19
  42. gitlab/v4/objects/features.py +11 -12
  43. gitlab/v4/objects/files.py +23 -38
  44. gitlab/v4/objects/geo_nodes.py +7 -11
  45. gitlab/v4/objects/group_access_tokens.py +6 -13
  46. gitlab/v4/objects/groups.py +42 -37
  47. gitlab/v4/objects/hooks.py +4 -17
  48. gitlab/v4/objects/integrations.py +7 -18
  49. gitlab/v4/objects/invitations.py +12 -23
  50. gitlab/v4/objects/issues.py +21 -27
  51. gitlab/v4/objects/iterations.py +4 -8
  52. gitlab/v4/objects/job_token_scope.py +18 -14
  53. gitlab/v4/objects/jobs.py +17 -32
  54. gitlab/v4/objects/keys.py +8 -11
  55. gitlab/v4/objects/labels.py +19 -30
  56. gitlab/v4/objects/ldap.py +25 -9
  57. gitlab/v4/objects/member_roles.py +102 -0
  58. gitlab/v4/objects/members.py +11 -29
  59. gitlab/v4/objects/merge_request_approvals.py +31 -44
  60. gitlab/v4/objects/merge_requests.py +30 -40
  61. gitlab/v4/objects/merge_trains.py +3 -6
  62. gitlab/v4/objects/milestones.py +23 -29
  63. gitlab/v4/objects/namespaces.py +4 -10
  64. gitlab/v4/objects/notes.py +26 -69
  65. gitlab/v4/objects/notification_settings.py +5 -14
  66. gitlab/v4/objects/package_protection_rules.py +8 -8
  67. gitlab/v4/objects/packages.py +22 -37
  68. gitlab/v4/objects/pages.py +8 -14
  69. gitlab/v4/objects/personal_access_tokens.py +7 -10
  70. gitlab/v4/objects/pipelines.py +38 -47
  71. gitlab/v4/objects/project_access_tokens.py +6 -13
  72. gitlab/v4/objects/projects.py +63 -77
  73. gitlab/v4/objects/push_rules.py +13 -15
  74. gitlab/v4/objects/registry_protection_repository_rules.py +6 -7
  75. gitlab/v4/objects/registry_protection_rules.py +7 -11
  76. gitlab/v4/objects/releases.py +6 -20
  77. gitlab/v4/objects/repositories.py +25 -34
  78. gitlab/v4/objects/resource_groups.py +10 -15
  79. gitlab/v4/objects/reviewers.py +4 -2
  80. gitlab/v4/objects/runners.py +14 -13
  81. gitlab/v4/objects/secure_files.py +8 -21
  82. gitlab/v4/objects/service_accounts.py +7 -5
  83. gitlab/v4/objects/settings.py +13 -14
  84. gitlab/v4/objects/sidekiq.py +17 -18
  85. gitlab/v4/objects/snippets.py +78 -66
  86. gitlab/v4/objects/statistics.py +8 -23
  87. gitlab/v4/objects/status_checks.py +6 -3
  88. gitlab/v4/objects/tags.py +4 -13
  89. gitlab/v4/objects/templates.py +11 -59
  90. gitlab/v4/objects/todos.py +3 -6
  91. gitlab/v4/objects/topics.py +10 -21
  92. gitlab/v4/objects/triggers.py +3 -13
  93. gitlab/v4/objects/users.py +101 -93
  94. gitlab/v4/objects/variables.py +4 -19
  95. gitlab/v4/objects/wikis.py +4 -19
  96. {python_gitlab-5.6.0.dist-info → python_gitlab-6.1.0.dist-info}/METADATA +3 -2
  97. python_gitlab-6.1.0.dist-info/RECORD +107 -0
  98. {python_gitlab-5.6.0.dist-info → python_gitlab-6.1.0.dist-info}/WHEEL +1 -1
  99. python_gitlab-5.6.0.dist-info/RECORD +0 -106
  100. {python_gitlab-5.6.0.dist-info → python_gitlab-6.1.0.dist-info}/entry_points.txt +0 -0
  101. {python_gitlab-5.6.0.dist-info → python_gitlab-6.1.0.dist-info/licenses}/AUTHORS +0 -0
  102. {python_gitlab-5.6.0.dist-info → python_gitlab-6.1.0.dist-info/licenses}/COPYING +0 -0
  103. {python_gitlab-5.6.0.dist-info → python_gitlab-6.1.0.dist-info}/top_level.txt +0 -0
@@ -4,14 +4,16 @@ https://docs.gitlab.com/ee/api/users.html
4
4
  https://docs.gitlab.com/ee/api/projects.html#list-projects-starred-by-a-user
5
5
  """
6
6
 
7
- from typing import Any, cast, Dict, List, Optional, Union
7
+ from __future__ import annotations
8
+
9
+ from typing import Any, cast, Literal, Optional, overload
8
10
 
9
11
  import requests
10
12
 
11
13
  from gitlab import cli
12
14
  from gitlab import exceptions as exc
13
15
  from gitlab import types
14
- from gitlab.base import RESTManager, RESTObject, RESTObjectList
16
+ from gitlab.base import RESTObject, RESTObjectList
15
17
  from gitlab.mixins import (
16
18
  CreateMixin,
17
19
  CRUDMixin,
@@ -66,6 +68,8 @@ __all__ = [
66
68
  "UserMembershipManager",
67
69
  "UserProject",
68
70
  "UserProjectManager",
71
+ "UserContributedProject",
72
+ "UserContributedProjectManager",
69
73
  ]
70
74
 
71
75
 
@@ -73,52 +77,49 @@ class CurrentUserEmail(ObjectDeleteMixin, RESTObject):
73
77
  _repr_attr = "email"
74
78
 
75
79
 
76
- class CurrentUserEmailManager(RetrieveMixin, CreateMixin, DeleteMixin, RESTManager):
80
+ class CurrentUserEmailManager(
81
+ RetrieveMixin[CurrentUserEmail],
82
+ CreateMixin[CurrentUserEmail],
83
+ DeleteMixin[CurrentUserEmail],
84
+ ):
77
85
  _path = "/user/emails"
78
86
  _obj_cls = CurrentUserEmail
79
87
  _create_attrs = RequiredOptional(required=("email",))
80
88
 
81
- def get(
82
- self, id: Union[str, int], lazy: bool = False, **kwargs: Any
83
- ) -> CurrentUserEmail:
84
- return cast(CurrentUserEmail, super().get(id=id, lazy=lazy, **kwargs))
85
-
86
89
 
87
90
  class CurrentUserGPGKey(ObjectDeleteMixin, RESTObject):
88
91
  pass
89
92
 
90
93
 
91
- class CurrentUserGPGKeyManager(RetrieveMixin, CreateMixin, DeleteMixin, RESTManager):
94
+ class CurrentUserGPGKeyManager(
95
+ RetrieveMixin[CurrentUserGPGKey],
96
+ CreateMixin[CurrentUserGPGKey],
97
+ DeleteMixin[CurrentUserGPGKey],
98
+ ):
92
99
  _path = "/user/gpg_keys"
93
100
  _obj_cls = CurrentUserGPGKey
94
101
  _create_attrs = RequiredOptional(required=("key",))
95
102
 
96
- def get(
97
- self, id: Union[str, int], lazy: bool = False, **kwargs: Any
98
- ) -> CurrentUserGPGKey:
99
- return cast(CurrentUserGPGKey, super().get(id=id, lazy=lazy, **kwargs))
100
-
101
103
 
102
104
  class CurrentUserKey(ObjectDeleteMixin, RESTObject):
103
105
  _repr_attr = "title"
104
106
 
105
107
 
106
- class CurrentUserKeyManager(RetrieveMixin, CreateMixin, DeleteMixin, RESTManager):
108
+ class CurrentUserKeyManager(
109
+ RetrieveMixin[CurrentUserKey],
110
+ CreateMixin[CurrentUserKey],
111
+ DeleteMixin[CurrentUserKey],
112
+ ):
107
113
  _path = "/user/keys"
108
114
  _obj_cls = CurrentUserKey
109
115
  _create_attrs = RequiredOptional(required=("title", "key"))
110
116
 
111
- def get(
112
- self, id: Union[str, int], lazy: bool = False, **kwargs: Any
113
- ) -> CurrentUserKey:
114
- return cast(CurrentUserKey, super().get(id=id, lazy=lazy, **kwargs))
115
-
116
117
 
117
118
  class CurrentUserRunner(RESTObject):
118
119
  pass
119
120
 
120
121
 
121
- class CurrentUserRunnerManager(CreateMixin, RESTManager):
122
+ class CurrentUserRunnerManager(CreateMixin[CurrentUserRunner]):
122
123
  _path = "/user/runners"
123
124
  _obj_cls = CurrentUserRunner
124
125
  _types = {"tag_list": types.CommaSeparatedListAttribute}
@@ -144,14 +145,13 @@ class CurrentUserStatus(SaveMixin, RESTObject):
144
145
  _repr_attr = "message"
145
146
 
146
147
 
147
- class CurrentUserStatusManager(GetWithoutIdMixin, UpdateMixin, RESTManager):
148
+ class CurrentUserStatusManager(
149
+ GetWithoutIdMixin[CurrentUserStatus], UpdateMixin[CurrentUserStatus]
150
+ ):
148
151
  _path = "/user/status"
149
152
  _obj_cls = CurrentUserStatus
150
153
  _update_attrs = RequiredOptional(optional=("emoji", "message"))
151
154
 
152
- def get(self, **kwargs: Any) -> CurrentUserStatus:
153
- return cast(CurrentUserStatus, super().get(**kwargs))
154
-
155
155
 
156
156
  class CurrentUser(RESTObject):
157
157
  _id_attr = None
@@ -164,35 +164,33 @@ class CurrentUser(RESTObject):
164
164
  status: CurrentUserStatusManager
165
165
 
166
166
 
167
- class CurrentUserManager(GetWithoutIdMixin, RESTManager):
167
+ class CurrentUserManager(GetWithoutIdMixin[CurrentUser]):
168
168
  _path = "/user"
169
169
  _obj_cls = CurrentUser
170
170
 
171
- def get(self, **kwargs: Any) -> CurrentUser:
172
- return cast(CurrentUser, super().get(**kwargs))
173
-
174
171
 
175
172
  class User(SaveMixin, ObjectDeleteMixin, RESTObject):
176
173
  _repr_attr = "username"
177
174
 
178
175
  customattributes: UserCustomAttributeManager
179
- emails: "UserEmailManager"
176
+ emails: UserEmailManager
180
177
  events: UserEventManager
181
- followers_users: "UserFollowersManager"
182
- following_users: "UserFollowingManager"
183
- gpgkeys: "UserGPGKeyManager"
184
- identityproviders: "UserIdentityProviderManager"
185
- impersonationtokens: "UserImpersonationTokenManager"
186
- keys: "UserKeyManager"
187
- memberships: "UserMembershipManager"
178
+ followers_users: UserFollowersManager
179
+ following_users: UserFollowingManager
180
+ gpgkeys: UserGPGKeyManager
181
+ identityproviders: UserIdentityProviderManager
182
+ impersonationtokens: UserImpersonationTokenManager
183
+ keys: UserKeyManager
184
+ memberships: UserMembershipManager
188
185
  personal_access_tokens: UserPersonalAccessTokenManager
189
- projects: "UserProjectManager"
190
- starred_projects: "StarredProjectManager"
191
- status: "UserStatusManager"
186
+ projects: UserProjectManager
187
+ contributed_projects: UserContributedProjectManager
188
+ starred_projects: StarredProjectManager
189
+ status: UserStatusManager
192
190
 
193
191
  @cli.register_custom_action(cls_names="User")
194
192
  @exc.on_http_error(exc.GitlabBlockError)
195
- def block(self, **kwargs: Any) -> Optional[bool]:
193
+ def block(self, **kwargs: Any) -> bool | None:
196
194
  """Block the user.
197
195
 
198
196
  Args:
@@ -217,7 +215,7 @@ class User(SaveMixin, ObjectDeleteMixin, RESTObject):
217
215
 
218
216
  @cli.register_custom_action(cls_names="User")
219
217
  @exc.on_http_error(exc.GitlabFollowError)
220
- def follow(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]:
218
+ def follow(self, **kwargs: Any) -> dict[str, Any] | requests.Response:
221
219
  """Follow the user.
222
220
 
223
221
  Args:
@@ -235,7 +233,7 @@ class User(SaveMixin, ObjectDeleteMixin, RESTObject):
235
233
 
236
234
  @cli.register_custom_action(cls_names="User")
237
235
  @exc.on_http_error(exc.GitlabUnfollowError)
238
- def unfollow(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]:
236
+ def unfollow(self, **kwargs: Any) -> dict[str, Any] | requests.Response:
239
237
  """Unfollow the user.
240
238
 
241
239
  Args:
@@ -253,7 +251,7 @@ class User(SaveMixin, ObjectDeleteMixin, RESTObject):
253
251
 
254
252
  @cli.register_custom_action(cls_names="User")
255
253
  @exc.on_http_error(exc.GitlabUnblockError)
256
- def unblock(self, **kwargs: Any) -> Optional[bool]:
254
+ def unblock(self, **kwargs: Any) -> bool | None:
257
255
  """Unblock the user.
258
256
 
259
257
  Args:
@@ -278,7 +276,7 @@ class User(SaveMixin, ObjectDeleteMixin, RESTObject):
278
276
 
279
277
  @cli.register_custom_action(cls_names="User")
280
278
  @exc.on_http_error(exc.GitlabDeactivateError)
281
- def deactivate(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]:
279
+ def deactivate(self, **kwargs: Any) -> dict[str, Any] | requests.Response:
282
280
  """Deactivate the user.
283
281
 
284
282
  Args:
@@ -299,7 +297,7 @@ class User(SaveMixin, ObjectDeleteMixin, RESTObject):
299
297
 
300
298
  @cli.register_custom_action(cls_names="User")
301
299
  @exc.on_http_error(exc.GitlabActivateError)
302
- def activate(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]:
300
+ def activate(self, **kwargs: Any) -> dict[str, Any] | requests.Response:
303
301
  """Activate the user.
304
302
 
305
303
  Args:
@@ -320,7 +318,7 @@ class User(SaveMixin, ObjectDeleteMixin, RESTObject):
320
318
 
321
319
  @cli.register_custom_action(cls_names="User")
322
320
  @exc.on_http_error(exc.GitlabUserApproveError)
323
- def approve(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]:
321
+ def approve(self, **kwargs: Any) -> dict[str, Any] | requests.Response:
324
322
  """Approve a user creation request.
325
323
 
326
324
  Args:
@@ -338,7 +336,7 @@ class User(SaveMixin, ObjectDeleteMixin, RESTObject):
338
336
 
339
337
  @cli.register_custom_action(cls_names="User")
340
338
  @exc.on_http_error(exc.GitlabUserRejectError)
341
- def reject(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]:
339
+ def reject(self, **kwargs: Any) -> dict[str, Any] | requests.Response:
342
340
  """Reject a user creation request.
343
341
 
344
342
  Args:
@@ -356,7 +354,7 @@ class User(SaveMixin, ObjectDeleteMixin, RESTObject):
356
354
 
357
355
  @cli.register_custom_action(cls_names="User")
358
356
  @exc.on_http_error(exc.GitlabBanError)
359
- def ban(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]:
357
+ def ban(self, **kwargs: Any) -> dict[str, Any] | requests.Response:
360
358
  """Ban the user.
361
359
 
362
360
  Args:
@@ -377,7 +375,7 @@ class User(SaveMixin, ObjectDeleteMixin, RESTObject):
377
375
 
378
376
  @cli.register_custom_action(cls_names="User")
379
377
  @exc.on_http_error(exc.GitlabUnbanError)
380
- def unban(self, **kwargs: Any) -> Union[Dict[str, Any], requests.Response]:
378
+ def unban(self, **kwargs: Any) -> dict[str, Any] | requests.Response:
381
379
  """Unban the user.
382
380
 
383
381
  Args:
@@ -397,7 +395,7 @@ class User(SaveMixin, ObjectDeleteMixin, RESTObject):
397
395
  return server_data
398
396
 
399
397
 
400
- class UserManager(CRUDMixin, RESTManager):
398
+ class UserManager(CRUDMixin[User]):
401
399
  _path = "/users"
402
400
  _obj_cls = User
403
401
 
@@ -439,7 +437,7 @@ class UserManager(CRUDMixin, RESTManager):
439
437
  "private_profile",
440
438
  "color_scheme_id",
441
439
  "theme_id",
442
- ),
440
+ )
443
441
  )
444
442
  _update_attrs = RequiredOptional(
445
443
  required=("email", "username", "name"),
@@ -468,15 +466,12 @@ class UserManager(CRUDMixin, RESTManager):
468
466
  )
469
467
  _types = {"confirm": types.LowercaseStringAttribute, "avatar": types.ImageAttribute}
470
468
 
471
- def get(self, id: Union[str, int], lazy: bool = False, **kwargs: Any) -> User:
472
- return cast(User, super().get(id=id, lazy=lazy, **kwargs))
473
-
474
469
 
475
470
  class ProjectUser(RESTObject):
476
471
  pass
477
472
 
478
473
 
479
- class ProjectUserManager(ListMixin, RESTManager):
474
+ class ProjectUserManager(ListMixin[ProjectUser]):
480
475
  _path = "/projects/{project_id}/users"
481
476
  _obj_cls = ProjectUser
482
477
  _from_parent_attrs = {"project_id": "id"}
@@ -488,15 +483,14 @@ class UserEmail(ObjectDeleteMixin, RESTObject):
488
483
  _repr_attr = "email"
489
484
 
490
485
 
491
- class UserEmailManager(RetrieveMixin, CreateMixin, DeleteMixin, RESTManager):
486
+ class UserEmailManager(
487
+ RetrieveMixin[UserEmail], CreateMixin[UserEmail], DeleteMixin[UserEmail]
488
+ ):
492
489
  _path = "/users/{user_id}/emails"
493
490
  _obj_cls = UserEmail
494
491
  _from_parent_attrs = {"user_id": "id"}
495
492
  _create_attrs = RequiredOptional(required=("email",))
496
493
 
497
- def get(self, id: Union[str, int], lazy: bool = False, **kwargs: Any) -> UserEmail:
498
- return cast(UserEmail, super().get(id=id, lazy=lazy, **kwargs))
499
-
500
494
 
501
495
  class UserActivities(RESTObject):
502
496
  _id_attr = "username"
@@ -507,16 +501,13 @@ class UserStatus(RESTObject):
507
501
  _repr_attr = "message"
508
502
 
509
503
 
510
- class UserStatusManager(GetWithoutIdMixin, RESTManager):
504
+ class UserStatusManager(GetWithoutIdMixin[UserStatus]):
511
505
  _path = "/users/{user_id}/status"
512
506
  _obj_cls = UserStatus
513
507
  _from_parent_attrs = {"user_id": "id"}
514
508
 
515
- def get(self, **kwargs: Any) -> UserStatus:
516
- return cast(UserStatus, super().get(**kwargs))
517
-
518
509
 
519
- class UserActivitiesManager(ListMixin, RESTManager):
510
+ class UserActivitiesManager(ListMixin[UserActivities]):
520
511
  _path = "/user/activities"
521
512
  _obj_cls = UserActivities
522
513
 
@@ -525,31 +516,29 @@ class UserGPGKey(ObjectDeleteMixin, RESTObject):
525
516
  pass
526
517
 
527
518
 
528
- class UserGPGKeyManager(RetrieveMixin, CreateMixin, DeleteMixin, RESTManager):
519
+ class UserGPGKeyManager(
520
+ RetrieveMixin[UserGPGKey], CreateMixin[UserGPGKey], DeleteMixin[UserGPGKey]
521
+ ):
529
522
  _path = "/users/{user_id}/gpg_keys"
530
523
  _obj_cls = UserGPGKey
531
524
  _from_parent_attrs = {"user_id": "id"}
532
525
  _create_attrs = RequiredOptional(required=("key",))
533
526
 
534
- def get(self, id: Union[str, int], lazy: bool = False, **kwargs: Any) -> UserGPGKey:
535
- return cast(UserGPGKey, super().get(id=id, lazy=lazy, **kwargs))
536
-
537
527
 
538
528
  class UserKey(ObjectDeleteMixin, RESTObject):
539
529
  pass
540
530
 
541
531
 
542
- class UserKeyManager(RetrieveMixin, CreateMixin, DeleteMixin, RESTManager):
532
+ class UserKeyManager(
533
+ RetrieveMixin[UserKey], CreateMixin[UserKey], DeleteMixin[UserKey]
534
+ ):
543
535
  _path = "/users/{user_id}/keys"
544
536
  _obj_cls = UserKey
545
537
  _from_parent_attrs = {"user_id": "id"}
546
538
  _create_attrs = RequiredOptional(required=("title", "key"))
547
539
 
548
- def get(self, id: Union[str, int], lazy: bool = False, **kwargs: Any) -> UserKey:
549
- return cast(UserKey, super().get(id=id, lazy=lazy, **kwargs))
550
540
 
551
-
552
- class UserIdentityProviderManager(DeleteMixin, RESTManager):
541
+ class UserIdentityProviderManager(DeleteMixin[User]):
553
542
  """Manager for user identities.
554
543
 
555
544
  This manager does not actually manage objects but enables
@@ -557,6 +546,7 @@ class UserIdentityProviderManager(DeleteMixin, RESTManager):
557
546
  """
558
547
 
559
548
  _path = "/users/{user_id}/identities"
549
+ _obj_cls = User
560
550
  _from_parent_attrs = {"user_id": "id"}
561
551
 
562
552
 
@@ -564,7 +554,7 @@ class UserImpersonationToken(ObjectDeleteMixin, RESTObject):
564
554
  pass
565
555
 
566
556
 
567
- class UserImpersonationTokenManager(NoUpdateMixin, RESTManager):
557
+ class UserImpersonationTokenManager(NoUpdateMixin[UserImpersonationToken]):
568
558
  _path = "/users/{user_id}/impersonation_tokens"
569
559
  _obj_cls = UserImpersonationToken
570
560
  _from_parent_attrs = {"user_id": "id"}
@@ -574,34 +564,24 @@ class UserImpersonationTokenManager(NoUpdateMixin, RESTManager):
574
564
  _list_filters = ("state",)
575
565
  _types = {"scopes": ArrayAttribute}
576
566
 
577
- def get(
578
- self, id: Union[str, int], lazy: bool = False, **kwargs: Any
579
- ) -> UserImpersonationToken:
580
- return cast(UserImpersonationToken, super().get(id=id, lazy=lazy, **kwargs))
581
-
582
567
 
583
568
  class UserMembership(RESTObject):
584
569
  _id_attr = "source_id"
585
570
 
586
571
 
587
- class UserMembershipManager(RetrieveMixin, RESTManager):
572
+ class UserMembershipManager(RetrieveMixin[UserMembership]):
588
573
  _path = "/users/{user_id}/memberships"
589
574
  _obj_cls = UserMembership
590
575
  _from_parent_attrs = {"user_id": "id"}
591
576
  _list_filters = ("type",)
592
577
 
593
- def get(
594
- self, id: Union[str, int], lazy: bool = False, **kwargs: Any
595
- ) -> UserMembership:
596
- return cast(UserMembership, super().get(id=id, lazy=lazy, **kwargs))
597
-
598
578
 
599
579
  # Having this outside projects avoids circular imports due to ProjectUser
600
580
  class UserProject(RESTObject):
601
581
  pass
602
582
 
603
583
 
604
- class UserProjectManager(ListMixin, CreateMixin, RESTManager):
584
+ class UserProjectManager(ListMixin[UserProject], CreateMixin[UserProject]):
605
585
  _path = "/projects/user/{user_id}"
606
586
  _obj_cls = UserProject
607
587
  _from_parent_attrs = {"user_id": "id"}
@@ -646,11 +626,28 @@ class UserProjectManager(ListMixin, CreateMixin, RESTManager):
646
626
  "id_before",
647
627
  )
648
628
 
649
- def list(self, **kwargs: Any) -> Union[RESTObjectList, List[RESTObject]]:
629
+ @overload
630
+ def list(
631
+ self, *, iterator: Literal[False] = False, **kwargs: Any
632
+ ) -> list[UserProject]: ...
633
+
634
+ @overload
635
+ def list(
636
+ self, *, iterator: Literal[True] = True, **kwargs: Any
637
+ ) -> RESTObjectList[UserProject]: ...
638
+
639
+ @overload
640
+ def list(
641
+ self, *, iterator: bool = False, **kwargs: Any
642
+ ) -> RESTObjectList[UserProject] | list[UserProject]: ...
643
+
644
+ def list(
645
+ self, *, iterator: bool = False, **kwargs: Any
646
+ ) -> RESTObjectList[UserProject] | list[UserProject]:
650
647
  """Retrieve a list of objects.
651
648
 
652
649
  Args:
653
- all: If True, return all the items, without pagination
650
+ get_all: If True, return all the items, without pagination
654
651
  per_page: Number of items to retrieve per request
655
652
  page: ID of the page to return (starts with page 1)
656
653
  iterator: If set to True and no pagination option is
@@ -668,14 +665,25 @@ class UserProjectManager(ListMixin, CreateMixin, RESTManager):
668
665
  path = f"/users/{self._parent.id}/projects"
669
666
  else:
670
667
  path = f"/users/{self._from_parent_attrs['user_id']}/projects"
671
- return ListMixin.list(self, path=path, **kwargs)
668
+ return super().list(path=path, iterator=iterator, **kwargs)
669
+
670
+
671
+ class UserContributedProject(RESTObject):
672
+ _id_attr = "id"
673
+ _repr_attr = "path_with_namespace"
674
+
675
+
676
+ class UserContributedProjectManager(ListMixin[UserContributedProject]):
677
+ _path = "/users/{user_id}/contributed_projects"
678
+ _obj_cls = UserContributedProject
679
+ _from_parent_attrs = {"user_id": "id"}
672
680
 
673
681
 
674
682
  class StarredProject(RESTObject):
675
683
  pass
676
684
 
677
685
 
678
- class StarredProjectManager(ListMixin, RESTManager):
686
+ class StarredProjectManager(ListMixin[StarredProject]):
679
687
  _path = "/users/{user_id}/starred_projects"
680
688
  _obj_cls = StarredProject
681
689
  _from_parent_attrs = {"user_id": "id"}
@@ -697,13 +705,13 @@ class StarredProjectManager(ListMixin, RESTManager):
697
705
  )
698
706
 
699
707
 
700
- class UserFollowersManager(ListMixin, RESTManager):
708
+ class UserFollowersManager(ListMixin[User]):
701
709
  _path = "/users/{user_id}/followers"
702
710
  _obj_cls = User
703
711
  _from_parent_attrs = {"user_id": "id"}
704
712
 
705
713
 
706
- class UserFollowingManager(ListMixin, RESTManager):
714
+ class UserFollowingManager(ListMixin[User]):
707
715
  _path = "/users/{user_id}/following"
708
716
  _obj_cls = User
709
717
  _from_parent_attrs = {"user_id": "id"}
@@ -5,9 +5,7 @@ https://docs.gitlab.com/ee/api/project_level_variables.html
5
5
  https://docs.gitlab.com/ee/api/group_level_variables.html
6
6
  """
7
7
 
8
- from typing import Any, cast, Union
9
-
10
- from gitlab.base import RESTManager, RESTObject
8
+ from gitlab.base import RESTObject
11
9
  from gitlab.mixins import CRUDMixin, ObjectDeleteMixin, SaveMixin
12
10
  from gitlab.types import RequiredOptional
13
11
 
@@ -25,7 +23,7 @@ class Variable(SaveMixin, ObjectDeleteMixin, RESTObject):
25
23
  _id_attr = "key"
26
24
 
27
25
 
28
- class VariableManager(CRUDMixin, RESTManager):
26
+ class VariableManager(CRUDMixin[Variable]):
29
27
  _path = "/admin/ci/variables"
30
28
  _obj_cls = Variable
31
29
  _create_attrs = RequiredOptional(
@@ -35,15 +33,12 @@ class VariableManager(CRUDMixin, RESTManager):
35
33
  required=("key", "value"), optional=("protected", "variable_type", "masked")
36
34
  )
37
35
 
38
- def get(self, id: Union[str, int], lazy: bool = False, **kwargs: Any) -> Variable:
39
- return cast(Variable, super().get(id=id, lazy=lazy, **kwargs))
40
-
41
36
 
42
37
  class GroupVariable(SaveMixin, ObjectDeleteMixin, RESTObject):
43
38
  _id_attr = "key"
44
39
 
45
40
 
46
- class GroupVariableManager(CRUDMixin, RESTManager):
41
+ class GroupVariableManager(CRUDMixin[GroupVariable]):
47
42
  _path = "/groups/{group_id}/variables"
48
43
  _obj_cls = GroupVariable
49
44
  _from_parent_attrs = {"group_id": "id"}
@@ -54,17 +49,12 @@ class GroupVariableManager(CRUDMixin, RESTManager):
54
49
  required=("key", "value"), optional=("protected", "variable_type", "masked")
55
50
  )
56
51
 
57
- def get(
58
- self, id: Union[str, int], lazy: bool = False, **kwargs: Any
59
- ) -> GroupVariable:
60
- return cast(GroupVariable, super().get(id=id, lazy=lazy, **kwargs))
61
-
62
52
 
63
53
  class ProjectVariable(SaveMixin, ObjectDeleteMixin, RESTObject):
64
54
  _id_attr = "key"
65
55
 
66
56
 
67
- class ProjectVariableManager(CRUDMixin, RESTManager):
57
+ class ProjectVariableManager(CRUDMixin[ProjectVariable]):
68
58
  _path = "/projects/{project_id}/variables"
69
59
  _obj_cls = ProjectVariable
70
60
  _from_parent_attrs = {"project_id": "id"}
@@ -76,8 +66,3 @@ class ProjectVariableManager(CRUDMixin, RESTManager):
76
66
  required=("key", "value"),
77
67
  optional=("protected", "variable_type", "masked", "environment_scope"),
78
68
  )
79
-
80
- def get(
81
- self, id: Union[str, int], lazy: bool = False, **kwargs: Any
82
- ) -> ProjectVariable:
83
- return cast(ProjectVariable, super().get(id=id, lazy=lazy, **kwargs))
@@ -1,15 +1,8 @@
1
- from typing import Any, cast, Union
2
-
3
- from gitlab.base import RESTManager, RESTObject
1
+ from gitlab.base import RESTObject
4
2
  from gitlab.mixins import CRUDMixin, ObjectDeleteMixin, SaveMixin, UploadMixin
5
3
  from gitlab.types import RequiredOptional
6
4
 
7
- __all__ = [
8
- "ProjectWiki",
9
- "ProjectWikiManager",
10
- "GroupWiki",
11
- "GroupWikiManager",
12
- ]
5
+ __all__ = ["ProjectWiki", "ProjectWikiManager", "GroupWiki", "GroupWikiManager"]
13
6
 
14
7
 
15
8
  class ProjectWiki(SaveMixin, ObjectDeleteMixin, UploadMixin, RESTObject):
@@ -18,7 +11,7 @@ class ProjectWiki(SaveMixin, ObjectDeleteMixin, UploadMixin, RESTObject):
18
11
  _upload_path = "/projects/{project_id}/wikis/attachments"
19
12
 
20
13
 
21
- class ProjectWikiManager(CRUDMixin, RESTManager):
14
+ class ProjectWikiManager(CRUDMixin[ProjectWiki]):
22
15
  _path = "/projects/{project_id}/wikis"
23
16
  _obj_cls = ProjectWiki
24
17
  _from_parent_attrs = {"project_id": "id"}
@@ -28,11 +21,6 @@ class ProjectWikiManager(CRUDMixin, RESTManager):
28
21
  _update_attrs = RequiredOptional(optional=("title", "content", "format"))
29
22
  _list_filters = ("with_content",)
30
23
 
31
- def get(
32
- self, id: Union[str, int], lazy: bool = False, **kwargs: Any
33
- ) -> ProjectWiki:
34
- return cast(ProjectWiki, super().get(id=id, lazy=lazy, **kwargs))
35
-
36
24
 
37
25
  class GroupWiki(SaveMixin, ObjectDeleteMixin, UploadMixin, RESTObject):
38
26
  _id_attr = "slug"
@@ -40,7 +28,7 @@ class GroupWiki(SaveMixin, ObjectDeleteMixin, UploadMixin, RESTObject):
40
28
  _upload_path = "/groups/{group_id}/wikis/attachments"
41
29
 
42
30
 
43
- class GroupWikiManager(CRUDMixin, RESTManager):
31
+ class GroupWikiManager(CRUDMixin[GroupWiki]):
44
32
  _path = "/groups/{group_id}/wikis"
45
33
  _obj_cls = GroupWiki
46
34
  _from_parent_attrs = {"group_id": "id"}
@@ -49,6 +37,3 @@ class GroupWikiManager(CRUDMixin, RESTManager):
49
37
  )
50
38
  _update_attrs = RequiredOptional(optional=("title", "content", "format"))
51
39
  _list_filters = ("with_content",)
52
-
53
- def get(self, id: Union[str, int], lazy: bool = False, **kwargs: Any) -> GroupWiki:
54
- return cast(GroupWiki, super().get(id=id, lazy=lazy, **kwargs))
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: python-gitlab
3
- Version: 5.6.0
3
+ Version: 6.1.0
4
4
  Summary: The python wrapper for the GitLab REST and GraphQL APIs.
5
5
  Author-email: Gauvain Pocentek <gauvain@pocentek.net>
6
6
  Maintainer-email: John Villalovos <john@sodarock.com>, Max Wittig <max.wittig@siemens.com>, Nejc Habjan <nejc.habjan@siemens.com>, Roger Meier <r.meier@siemens.com>
@@ -36,6 +36,7 @@ Provides-Extra: yaml
36
36
  Requires-Dist: PyYaml>=6.0.1; extra == "yaml"
37
37
  Provides-Extra: graphql
38
38
  Requires-Dist: gql[httpx]<4,>=3.5.0; extra == "graphql"
39
+ Dynamic: license-file
39
40
 
40
41
  python-gitlab
41
42
  =============