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.
- 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 +15 -25
- gitlab/client.py +114 -140
- gitlab/config.py +16 -17
- gitlab/const.py +2 -0
- gitlab/exceptions.py +7 -5
- gitlab/mixins.py +154 -238
- gitlab/types.py +13 -14
- gitlab/utils.py +32 -43
- gitlab/v4/cli.py +51 -54
- 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 +26 -14
- 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 +31 -44
- 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 +63 -77
- 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 +4 -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 +101 -93
- gitlab/v4/objects/variables.py +4 -19
- gitlab/v4/objects/wikis.py +4 -19
- {python_gitlab-5.6.0.dist-info → python_gitlab-6.1.0.dist-info}/METADATA +3 -2
- python_gitlab-6.1.0.dist-info/RECORD +107 -0
- {python_gitlab-5.6.0.dist-info → python_gitlab-6.1.0.dist-info}/WHEEL +1 -1
- python_gitlab-5.6.0.dist-info/RECORD +0 -106
- {python_gitlab-5.6.0.dist-info → python_gitlab-6.1.0.dist-info}/entry_points.txt +0 -0
- {python_gitlab-5.6.0.dist-info → python_gitlab-6.1.0.dist-info/licenses}/AUTHORS +0 -0
- {python_gitlab-5.6.0.dist-info → python_gitlab-6.1.0.dist-info/licenses}/COPYING +0 -0
- {python_gitlab-5.6.0.dist-info → python_gitlab-6.1.0.dist-info}/top_level.txt +0 -0
gitlab/client.py
CHANGED
@@ -4,18 +4,7 @@ from __future__ import annotations
|
|
4
4
|
|
5
5
|
import os
|
6
6
|
import re
|
7
|
-
from typing import
|
8
|
-
Any,
|
9
|
-
BinaryIO,
|
10
|
-
cast,
|
11
|
-
Dict,
|
12
|
-
List,
|
13
|
-
Optional,
|
14
|
-
Tuple,
|
15
|
-
Type,
|
16
|
-
TYPE_CHECKING,
|
17
|
-
Union,
|
18
|
-
)
|
7
|
+
from typing import Any, BinaryIO, cast, TYPE_CHECKING
|
19
8
|
from urllib import parse
|
20
9
|
|
21
10
|
import requests
|
@@ -83,26 +72,26 @@ class Gitlab:
|
|
83
72
|
|
84
73
|
def __init__(
|
85
74
|
self,
|
86
|
-
url:
|
87
|
-
private_token:
|
88
|
-
oauth_token:
|
89
|
-
job_token:
|
90
|
-
ssl_verify:
|
91
|
-
http_username:
|
92
|
-
http_password:
|
93
|
-
timeout:
|
75
|
+
url: str | None = None,
|
76
|
+
private_token: str | None = None,
|
77
|
+
oauth_token: str | None = None,
|
78
|
+
job_token: str | None = None,
|
79
|
+
ssl_verify: bool | str = True,
|
80
|
+
http_username: str | None = None,
|
81
|
+
http_password: str | None = None,
|
82
|
+
timeout: float | None = None,
|
94
83
|
api_version: str = "4",
|
95
|
-
per_page:
|
96
|
-
pagination:
|
97
|
-
order_by:
|
84
|
+
per_page: int | None = None,
|
85
|
+
pagination: str | None = None,
|
86
|
+
order_by: str | None = None,
|
98
87
|
user_agent: str = gitlab.const.USER_AGENT,
|
99
88
|
retry_transient_errors: bool = False,
|
100
89
|
keep_base_url: bool = False,
|
101
90
|
**kwargs: Any,
|
102
91
|
) -> None:
|
103
92
|
self._api_version = str(api_version)
|
104
|
-
self._server_version:
|
105
|
-
self._server_revision:
|
93
|
+
self._server_version: str | None = None
|
94
|
+
self._server_revision: str | None = None
|
106
95
|
self._base_url = utils.get_base_url(url)
|
107
96
|
self._url = f"{self._base_url}/api/v{api_version}"
|
108
97
|
#: Timeout to use for requests to gitlab server
|
@@ -123,7 +112,7 @@ class Gitlab:
|
|
123
112
|
self._set_auth_info()
|
124
113
|
|
125
114
|
#: Create a session object for requests
|
126
|
-
_backend:
|
115
|
+
_backend: type[_backends.DefaultBackend] = kwargs.pop(
|
127
116
|
"backend", _backends.DefaultBackend
|
128
117
|
)
|
129
118
|
self._backend = _backend(**kwargs)
|
@@ -141,7 +130,7 @@ class Gitlab:
|
|
141
130
|
from gitlab.v4 import objects
|
142
131
|
|
143
132
|
self._objects = objects
|
144
|
-
self.user:
|
133
|
+
self.user: objects.CurrentUser | None = None
|
145
134
|
|
146
135
|
self.broadcastmessages = objects.BroadcastMessageManager(self)
|
147
136
|
"""See :class:`~gitlab.v4.objects.BroadcastMessageManager`"""
|
@@ -177,6 +166,8 @@ class Gitlab:
|
|
177
166
|
"""See :class:`~gitlab.v4.objects.LicenseManager`"""
|
178
167
|
self.namespaces = objects.NamespaceManager(self)
|
179
168
|
"""See :class:`~gitlab.v4.objects.NamespaceManager`"""
|
169
|
+
self.member_roles = objects.MemberRoleManager(self)
|
170
|
+
"""See :class:`~gitlab.v4.objects.MergeRequestManager`"""
|
180
171
|
self.mergerequests = objects.MergeRequestManager(self)
|
181
172
|
"""See :class:`~gitlab.v4.objects.MergeRequestManager`"""
|
182
173
|
self.notificationsettings = objects.NotificationSettingsManager(self)
|
@@ -224,18 +215,18 @@ class Gitlab:
|
|
224
215
|
self.statistics = objects.ApplicationStatisticsManager(self)
|
225
216
|
"""See :class:`~gitlab.v4.objects.ApplicationStatisticsManager`"""
|
226
217
|
|
227
|
-
def __enter__(self) ->
|
218
|
+
def __enter__(self) -> Gitlab:
|
228
219
|
return self
|
229
220
|
|
230
221
|
def __exit__(self, *args: Any) -> None:
|
231
222
|
self.session.close()
|
232
223
|
|
233
|
-
def __getstate__(self) ->
|
224
|
+
def __getstate__(self) -> dict[str, Any]:
|
234
225
|
state = self.__dict__.copy()
|
235
226
|
state.pop("_objects")
|
236
227
|
return state
|
237
228
|
|
238
|
-
def __setstate__(self, state:
|
229
|
+
def __setstate__(self, state: dict[str, Any]) -> None:
|
239
230
|
self.__dict__.update(state)
|
240
231
|
# We only support v4 API at this time
|
241
232
|
if self._api_version not in ("4",):
|
@@ -266,10 +257,10 @@ class Gitlab:
|
|
266
257
|
@classmethod
|
267
258
|
def from_config(
|
268
259
|
cls,
|
269
|
-
gitlab_id:
|
270
|
-
config_files:
|
260
|
+
gitlab_id: str | None = None,
|
261
|
+
config_files: list[str] | None = None,
|
271
262
|
**kwargs: Any,
|
272
|
-
) ->
|
263
|
+
) -> Gitlab:
|
273
264
|
"""Create a Gitlab connection from configuration files.
|
274
265
|
|
275
266
|
Args:
|
@@ -310,10 +301,10 @@ class Gitlab:
|
|
310
301
|
@classmethod
|
311
302
|
def merge_config(
|
312
303
|
cls,
|
313
|
-
options:
|
314
|
-
gitlab_id:
|
315
|
-
config_files:
|
316
|
-
) ->
|
304
|
+
options: dict[str, Any],
|
305
|
+
gitlab_id: str | None = None,
|
306
|
+
config_files: list[str] | None = None,
|
307
|
+
) -> Gitlab:
|
317
308
|
"""Create a Gitlab connection by merging configuration with
|
318
309
|
the following precedence:
|
319
310
|
|
@@ -364,8 +355,8 @@ class Gitlab:
|
|
364
355
|
|
365
356
|
@staticmethod
|
366
357
|
def _merge_auth(
|
367
|
-
options:
|
368
|
-
) ->
|
358
|
+
options: dict[str, Any], config: gitlab.config.GitlabConfigParser
|
359
|
+
) -> tuple[str | None, str | None, str | None]:
|
369
360
|
"""
|
370
361
|
Return a tuple where at most one of 3 token types ever has a value.
|
371
362
|
Since multiple types of tokens may be present in the environment,
|
@@ -402,7 +393,7 @@ class Gitlab:
|
|
402
393
|
if hasattr(self.user, "web_url") and hasattr(self.user, "username"):
|
403
394
|
self._check_url(self.user.web_url, path=self.user.username)
|
404
395
|
|
405
|
-
def version(self) ->
|
396
|
+
def version(self) -> tuple[str, str]:
|
406
397
|
"""Returns the version and revision of the gitlab server.
|
407
398
|
|
408
399
|
Note that self.version and self.revision will be set on the gitlab
|
@@ -429,7 +420,7 @@ class Gitlab:
|
|
429
420
|
|
430
421
|
@gitlab.exceptions.on_http_error(gitlab.exceptions.GitlabMarkdownError)
|
431
422
|
def markdown(
|
432
|
-
self, text: str, gfm: bool = False, project:
|
423
|
+
self, text: str, gfm: bool = False, project: str | None = None, **kwargs: Any
|
433
424
|
) -> str:
|
434
425
|
"""Render an arbitrary Markdown document.
|
435
426
|
|
@@ -456,7 +447,7 @@ class Gitlab:
|
|
456
447
|
return data["html"]
|
457
448
|
|
458
449
|
@gitlab.exceptions.on_http_error(gitlab.exceptions.GitlabLicenseError)
|
459
|
-
def get_license(self, **kwargs: Any) ->
|
450
|
+
def get_license(self, **kwargs: Any) -> dict[str, str | dict[str, str]]:
|
460
451
|
"""Retrieve information about the current license.
|
461
452
|
|
462
453
|
Args:
|
@@ -475,7 +466,7 @@ class Gitlab:
|
|
475
466
|
return {}
|
476
467
|
|
477
468
|
@gitlab.exceptions.on_http_error(gitlab.exceptions.GitlabLicenseError)
|
478
|
-
def set_license(self, license: str, **kwargs: Any) ->
|
469
|
+
def set_license(self, license: str, **kwargs: Any) -> dict[str, Any]:
|
479
470
|
"""Add a new license.
|
480
471
|
|
481
472
|
Args:
|
@@ -516,7 +507,7 @@ class Gitlab:
|
|
516
507
|
"authentication should be defined"
|
517
508
|
)
|
518
509
|
|
519
|
-
self._auth:
|
510
|
+
self._auth: requests.auth.AuthBase | None = None
|
520
511
|
if self.private_token:
|
521
512
|
self._auth = _backends.PrivateTokenAuth(self.private_token)
|
522
513
|
|
@@ -564,7 +555,7 @@ class Gitlab:
|
|
564
555
|
logger.handlers.clear()
|
565
556
|
logger.addHandler(handler)
|
566
557
|
|
567
|
-
def _get_session_opts(self) ->
|
558
|
+
def _get_session_opts(self) -> dict[str, Any]:
|
568
559
|
return {
|
569
560
|
"headers": self.headers.copy(),
|
570
561
|
"auth": self._auth,
|
@@ -585,7 +576,7 @@ class Gitlab:
|
|
585
576
|
return path
|
586
577
|
return f"{self._url}{path}"
|
587
578
|
|
588
|
-
def _check_url(self, url:
|
579
|
+
def _check_url(self, url: str | None, *, path: str = "api") -> str | None:
|
589
580
|
"""
|
590
581
|
Checks if ``url`` starts with a different base URL from the user-provided base
|
591
582
|
URL and warns the user before returning it. If ``keep_base_url`` is set to
|
@@ -645,16 +636,16 @@ class Gitlab:
|
|
645
636
|
self,
|
646
637
|
verb: str,
|
647
638
|
path: str,
|
648
|
-
query_data:
|
649
|
-
post_data:
|
639
|
+
query_data: dict[str, Any] | None = None,
|
640
|
+
post_data: dict[str, Any] | bytes | BinaryIO | None = None,
|
650
641
|
raw: bool = False,
|
651
642
|
streamed: bool = False,
|
652
|
-
files:
|
653
|
-
timeout:
|
643
|
+
files: dict[str, Any] | None = None,
|
644
|
+
timeout: float | None = None,
|
654
645
|
obey_rate_limit: bool = True,
|
655
|
-
retry_transient_errors:
|
646
|
+
retry_transient_errors: bool | None = None,
|
656
647
|
max_retries: int = 10,
|
657
|
-
extra_headers:
|
648
|
+
extra_headers: dict[str, Any] | None = None,
|
658
649
|
**kwargs: Any,
|
659
650
|
) -> requests.Response:
|
660
651
|
"""Make an HTTP request to the Gitlab server.
|
@@ -785,11 +776,11 @@ class Gitlab:
|
|
785
776
|
def http_get(
|
786
777
|
self,
|
787
778
|
path: str,
|
788
|
-
query_data:
|
779
|
+
query_data: dict[str, Any] | None = None,
|
789
780
|
streamed: bool = False,
|
790
781
|
raw: bool = False,
|
791
782
|
**kwargs: Any,
|
792
|
-
) ->
|
783
|
+
) -> dict[str, Any] | requests.Response:
|
793
784
|
"""Make a GET request to the Gitlab server.
|
794
785
|
|
795
786
|
Args:
|
@@ -829,8 +820,8 @@ class Gitlab:
|
|
829
820
|
return result
|
830
821
|
|
831
822
|
def http_head(
|
832
|
-
self, path: str, query_data:
|
833
|
-
) ->
|
823
|
+
self, path: str, query_data: dict[str, Any] | None = None, **kwargs: Any
|
824
|
+
) -> requests.structures.CaseInsensitiveDict[Any]:
|
834
825
|
"""Make a HEAD request to the Gitlab server.
|
835
826
|
|
836
827
|
Args:
|
@@ -852,12 +843,12 @@ class Gitlab:
|
|
852
843
|
def http_list(
|
853
844
|
self,
|
854
845
|
path: str,
|
855
|
-
query_data:
|
846
|
+
query_data: dict[str, Any] | None = None,
|
856
847
|
*,
|
857
|
-
iterator:
|
858
|
-
message_details:
|
848
|
+
iterator: bool | None = None,
|
849
|
+
message_details: utils.WarnMessageData | None = None,
|
859
850
|
**kwargs: Any,
|
860
|
-
) ->
|
851
|
+
) -> GitlabList | list[dict[str, Any]]:
|
861
852
|
"""Make a GET request to the Gitlab server for list-oriented queries.
|
862
853
|
|
863
854
|
Args:
|
@@ -892,18 +883,16 @@ class Gitlab:
|
|
892
883
|
|
893
884
|
page = kwargs.get("page")
|
894
885
|
|
895
|
-
if iterator
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
)
|
886
|
+
if iterator:
|
887
|
+
if page is not None:
|
888
|
+
utils.warn(
|
889
|
+
message=(
|
890
|
+
f"`{iterator=}` and `{page=}` were both specified. "
|
891
|
+
f"`{page=}` will be ignored."
|
892
|
+
),
|
893
|
+
category=UserWarning,
|
894
|
+
)
|
905
895
|
|
906
|
-
if iterator and page is None:
|
907
896
|
# Generator requested
|
908
897
|
return GitlabList(self, url, query_data, **kwargs)
|
909
898
|
|
@@ -958,22 +947,18 @@ class Gitlab:
|
|
958
947
|
f"`get_all=False` to the `list()` call."
|
959
948
|
)
|
960
949
|
show_caller = True
|
961
|
-
utils.warn(
|
962
|
-
message=message,
|
963
|
-
category=UserWarning,
|
964
|
-
show_caller=show_caller,
|
965
|
-
)
|
950
|
+
utils.warn(message=message, category=UserWarning, show_caller=show_caller)
|
966
951
|
return items
|
967
952
|
|
968
953
|
def http_post(
|
969
954
|
self,
|
970
955
|
path: str,
|
971
|
-
query_data:
|
972
|
-
post_data:
|
956
|
+
query_data: dict[str, Any] | None = None,
|
957
|
+
post_data: dict[str, Any] | None = None,
|
973
958
|
raw: bool = False,
|
974
|
-
files:
|
959
|
+
files: dict[str, Any] | None = None,
|
975
960
|
**kwargs: Any,
|
976
|
-
) ->
|
961
|
+
) -> dict[str, Any] | requests.Response:
|
977
962
|
"""Make a POST request to the Gitlab server.
|
978
963
|
|
979
964
|
Args:
|
@@ -1023,12 +1008,12 @@ class Gitlab:
|
|
1023
1008
|
def http_put(
|
1024
1009
|
self,
|
1025
1010
|
path: str,
|
1026
|
-
query_data:
|
1027
|
-
post_data:
|
1011
|
+
query_data: dict[str, Any] | None = None,
|
1012
|
+
post_data: dict[str, Any] | bytes | BinaryIO | None = None,
|
1028
1013
|
raw: bool = False,
|
1029
|
-
files:
|
1014
|
+
files: dict[str, Any] | None = None,
|
1030
1015
|
**kwargs: Any,
|
1031
|
-
) ->
|
1016
|
+
) -> dict[str, Any] | requests.Response:
|
1032
1017
|
"""Make a PUT request to the Gitlab server.
|
1033
1018
|
|
1034
1019
|
Args:
|
@@ -1076,11 +1061,11 @@ class Gitlab:
|
|
1076
1061
|
self,
|
1077
1062
|
path: str,
|
1078
1063
|
*,
|
1079
|
-
query_data:
|
1080
|
-
post_data:
|
1064
|
+
query_data: dict[str, Any] | None = None,
|
1065
|
+
post_data: dict[str, Any] | bytes | None = None,
|
1081
1066
|
raw: bool = False,
|
1082
1067
|
**kwargs: Any,
|
1083
|
-
) ->
|
1068
|
+
) -> dict[str, Any] | requests.Response:
|
1084
1069
|
"""Make a PATCH request to the Gitlab server.
|
1085
1070
|
|
1086
1071
|
Args:
|
@@ -1103,12 +1088,7 @@ class Gitlab:
|
|
1103
1088
|
post_data = post_data or {}
|
1104
1089
|
|
1105
1090
|
result = self.http_request(
|
1106
|
-
"patch",
|
1107
|
-
path,
|
1108
|
-
query_data=query_data,
|
1109
|
-
post_data=post_data,
|
1110
|
-
raw=raw,
|
1111
|
-
**kwargs,
|
1091
|
+
"patch", path, query_data=query_data, post_data=post_data, raw=raw, **kwargs
|
1112
1092
|
)
|
1113
1093
|
if result.status_code in gitlab.const.NO_JSON_RESPONSE_CODES:
|
1114
1094
|
return result
|
@@ -1141,7 +1121,7 @@ class Gitlab:
|
|
1141
1121
|
@gitlab.exceptions.on_http_error(gitlab.exceptions.GitlabSearchError)
|
1142
1122
|
def search(
|
1143
1123
|
self, scope: str, search: str, **kwargs: Any
|
1144
|
-
) ->
|
1124
|
+
) -> GitlabList | list[dict[str, Any]]:
|
1145
1125
|
"""Search GitLab resources matching the provided string.'
|
1146
1126
|
|
1147
1127
|
Args:
|
@@ -1171,7 +1151,7 @@ class GitlabList:
|
|
1171
1151
|
self,
|
1172
1152
|
gl: Gitlab,
|
1173
1153
|
url: str,
|
1174
|
-
query_data:
|
1154
|
+
query_data: dict[str, Any],
|
1175
1155
|
get_next: bool = True,
|
1176
1156
|
**kwargs: Any,
|
1177
1157
|
) -> None:
|
@@ -1187,7 +1167,7 @@ class GitlabList:
|
|
1187
1167
|
self._kwargs.pop("query_parameters", None)
|
1188
1168
|
|
1189
1169
|
def _query(
|
1190
|
-
self, url: str, query_data:
|
1170
|
+
self, url: str, query_data: dict[str, Any] | None = None, **kwargs: Any
|
1191
1171
|
) -> None:
|
1192
1172
|
query_data = query_data or {}
|
1193
1173
|
result = self._gl.http_request("get", url, query_data=query_data, **kwargs)
|
@@ -1197,15 +1177,15 @@ class GitlabList:
|
|
1197
1177
|
next_url = None
|
1198
1178
|
|
1199
1179
|
self._next_url = self._gl._check_url(next_url)
|
1200
|
-
self._current_page:
|
1201
|
-
self._prev_page:
|
1202
|
-
self._next_page:
|
1203
|
-
self._per_page:
|
1204
|
-
self._total_pages:
|
1205
|
-
self._total:
|
1180
|
+
self._current_page: str | None = result.headers.get("X-Page")
|
1181
|
+
self._prev_page: str | None = result.headers.get("X-Prev-Page")
|
1182
|
+
self._next_page: str | None = result.headers.get("X-Next-Page")
|
1183
|
+
self._per_page: str | None = result.headers.get("X-Per-Page")
|
1184
|
+
self._total_pages: str | None = result.headers.get("X-Total-Pages")
|
1185
|
+
self._total: str | None = result.headers.get("X-Total")
|
1206
1186
|
|
1207
1187
|
try:
|
1208
|
-
self._data:
|
1188
|
+
self._data: list[dict[str, Any]] = result.json()
|
1209
1189
|
except Exception as e:
|
1210
1190
|
raise gitlab.exceptions.GitlabParsingError(
|
1211
1191
|
error_message="Failed to parse the server message"
|
@@ -1221,7 +1201,7 @@ class GitlabList:
|
|
1221
1201
|
return int(self._current_page)
|
1222
1202
|
|
1223
1203
|
@property
|
1224
|
-
def prev_page(self) ->
|
1204
|
+
def prev_page(self) -> int | None:
|
1225
1205
|
"""The previous page number.
|
1226
1206
|
|
1227
1207
|
If None, the current page is the first.
|
@@ -1229,7 +1209,7 @@ class GitlabList:
|
|
1229
1209
|
return int(self._prev_page) if self._prev_page else None
|
1230
1210
|
|
1231
1211
|
@property
|
1232
|
-
def next_page(self) ->
|
1212
|
+
def next_page(self) -> int | None:
|
1233
1213
|
"""The next page number.
|
1234
1214
|
|
1235
1215
|
If None, the current page is the last.
|
@@ -1237,7 +1217,7 @@ class GitlabList:
|
|
1237
1217
|
return int(self._next_page) if self._next_page else None
|
1238
1218
|
|
1239
1219
|
@property
|
1240
|
-
def per_page(self) ->
|
1220
|
+
def per_page(self) -> int | None:
|
1241
1221
|
"""The number of items per page."""
|
1242
1222
|
return int(self._per_page) if self._per_page is not None else None
|
1243
1223
|
|
@@ -1245,20 +1225,20 @@ class GitlabList:
|
|
1245
1225
|
# the headers 'x-total-pages' and 'x-total'. In those cases we return None.
|
1246
1226
|
# https://docs.gitlab.com/ee/user/gitlab_com/index.html#pagination-response-headers
|
1247
1227
|
@property
|
1248
|
-
def total_pages(self) ->
|
1228
|
+
def total_pages(self) -> int | None:
|
1249
1229
|
"""The total number of pages."""
|
1250
1230
|
if self._total_pages is not None:
|
1251
1231
|
return int(self._total_pages)
|
1252
1232
|
return None
|
1253
1233
|
|
1254
1234
|
@property
|
1255
|
-
def total(self) ->
|
1235
|
+
def total(self) -> int | None:
|
1256
1236
|
"""The total number of items."""
|
1257
1237
|
if self._total is not None:
|
1258
1238
|
return int(self._total)
|
1259
1239
|
return None
|
1260
1240
|
|
1261
|
-
def __iter__(self) ->
|
1241
|
+
def __iter__(self) -> GitlabList:
|
1262
1242
|
return self
|
1263
1243
|
|
1264
1244
|
def __len__(self) -> int:
|
@@ -1266,10 +1246,10 @@ class GitlabList:
|
|
1266
1246
|
return 0
|
1267
1247
|
return int(self._total)
|
1268
1248
|
|
1269
|
-
def __next__(self) ->
|
1249
|
+
def __next__(self) -> dict[str, Any]:
|
1270
1250
|
return self.next()
|
1271
1251
|
|
1272
|
-
def next(self) ->
|
1252
|
+
def next(self) -> dict[str, Any]:
|
1273
1253
|
try:
|
1274
1254
|
item = self._data[self._current]
|
1275
1255
|
self._current += 1
|
@@ -1287,11 +1267,11 @@ class GitlabList:
|
|
1287
1267
|
class _BaseGraphQL:
|
1288
1268
|
def __init__(
|
1289
1269
|
self,
|
1290
|
-
url:
|
1270
|
+
url: str | None = None,
|
1291
1271
|
*,
|
1292
|
-
token:
|
1293
|
-
ssl_verify:
|
1294
|
-
timeout:
|
1272
|
+
token: str | None = None,
|
1273
|
+
ssl_verify: bool | str = True,
|
1274
|
+
timeout: float | None = None,
|
1295
1275
|
user_agent: str = gitlab.const.USER_AGENT,
|
1296
1276
|
fetch_schema_from_transport: bool = False,
|
1297
1277
|
max_retries: int = 10,
|
@@ -1316,7 +1296,7 @@ class _BaseGraphQL:
|
|
1316
1296
|
self._client_opts = self._get_client_opts()
|
1317
1297
|
self._fetch_schema_from_transport = fetch_schema_from_transport
|
1318
1298
|
|
1319
|
-
def _get_client_opts(self) ->
|
1299
|
+
def _get_client_opts(self) -> dict[str, Any]:
|
1320
1300
|
headers = {"User-Agent": self._user_agent}
|
1321
1301
|
|
1322
1302
|
if self._token:
|
@@ -1332,12 +1312,12 @@ class _BaseGraphQL:
|
|
1332
1312
|
class GraphQL(_BaseGraphQL):
|
1333
1313
|
def __init__(
|
1334
1314
|
self,
|
1335
|
-
url:
|
1315
|
+
url: str | None = None,
|
1336
1316
|
*,
|
1337
|
-
token:
|
1338
|
-
ssl_verify:
|
1339
|
-
client:
|
1340
|
-
timeout:
|
1317
|
+
token: str | None = None,
|
1318
|
+
ssl_verify: bool | str = True,
|
1319
|
+
client: httpx.Client | None = None,
|
1320
|
+
timeout: float | None = None,
|
1341
1321
|
user_agent: str = gitlab.const.USER_AGENT,
|
1342
1322
|
fetch_schema_from_transport: bool = False,
|
1343
1323
|
max_retries: int = 10,
|
@@ -1364,15 +1344,13 @@ class GraphQL(_BaseGraphQL):
|
|
1364
1344
|
)
|
1365
1345
|
self._gql = gql.gql
|
1366
1346
|
|
1367
|
-
def __enter__(self) ->
|
1347
|
+
def __enter__(self) -> GraphQL:
|
1368
1348
|
return self
|
1369
1349
|
|
1370
1350
|
def __exit__(self, *args: Any) -> None:
|
1371
1351
|
self._http_client.close()
|
1372
1352
|
|
1373
|
-
def execute(
|
1374
|
-
self, request: Union[str, graphql.Source], *args: Any, **kwargs: Any
|
1375
|
-
) -> Any:
|
1353
|
+
def execute(self, request: str | graphql.Source, *args: Any, **kwargs: Any) -> Any:
|
1376
1354
|
parsed_document = self._gql(request)
|
1377
1355
|
retry = utils.Retry(
|
1378
1356
|
max_retries=self._max_retries,
|
@@ -1391,13 +1369,11 @@ class GraphQL(_BaseGraphQL):
|
|
1391
1369
|
|
1392
1370
|
if e.code == 401:
|
1393
1371
|
raise gitlab.exceptions.GitlabAuthenticationError(
|
1394
|
-
response_code=e.code,
|
1395
|
-
error_message=str(e),
|
1372
|
+
response_code=e.code, error_message=str(e)
|
1396
1373
|
)
|
1397
1374
|
|
1398
1375
|
raise gitlab.exceptions.GitlabHttpError(
|
1399
|
-
response_code=e.code,
|
1400
|
-
error_message=str(e),
|
1376
|
+
response_code=e.code, error_message=str(e)
|
1401
1377
|
)
|
1402
1378
|
|
1403
1379
|
return result
|
@@ -1406,12 +1382,12 @@ class GraphQL(_BaseGraphQL):
|
|
1406
1382
|
class AsyncGraphQL(_BaseGraphQL):
|
1407
1383
|
def __init__(
|
1408
1384
|
self,
|
1409
|
-
url:
|
1385
|
+
url: str | None = None,
|
1410
1386
|
*,
|
1411
|
-
token:
|
1412
|
-
ssl_verify:
|
1413
|
-
client:
|
1414
|
-
timeout:
|
1387
|
+
token: str | None = None,
|
1388
|
+
ssl_verify: bool | str = True,
|
1389
|
+
client: httpx.AsyncClient | None = None,
|
1390
|
+
timeout: float | None = None,
|
1415
1391
|
user_agent: str = gitlab.const.USER_AGENT,
|
1416
1392
|
fetch_schema_from_transport: bool = False,
|
1417
1393
|
max_retries: int = 10,
|
@@ -1438,14 +1414,14 @@ class AsyncGraphQL(_BaseGraphQL):
|
|
1438
1414
|
)
|
1439
1415
|
self._gql = gql.gql
|
1440
1416
|
|
1441
|
-
async def __aenter__(self) ->
|
1417
|
+
async def __aenter__(self) -> AsyncGraphQL:
|
1442
1418
|
return self
|
1443
1419
|
|
1444
1420
|
async def __aexit__(self, *args: Any) -> None:
|
1445
1421
|
await self._http_client.aclose()
|
1446
1422
|
|
1447
1423
|
async def execute(
|
1448
|
-
self, request:
|
1424
|
+
self, request: str | graphql.Source, *args: Any, **kwargs: Any
|
1449
1425
|
) -> Any:
|
1450
1426
|
parsed_document = self._gql(request)
|
1451
1427
|
retry = utils.Retry(
|
@@ -1467,13 +1443,11 @@ class AsyncGraphQL(_BaseGraphQL):
|
|
1467
1443
|
|
1468
1444
|
if e.code == 401:
|
1469
1445
|
raise gitlab.exceptions.GitlabAuthenticationError(
|
1470
|
-
response_code=e.code,
|
1471
|
-
error_message=str(e),
|
1446
|
+
response_code=e.code, error_message=str(e)
|
1472
1447
|
)
|
1473
1448
|
|
1474
1449
|
raise gitlab.exceptions.GitlabHttpError(
|
1475
|
-
response_code=e.code,
|
1476
|
-
error_message=str(e),
|
1450
|
+
response_code=e.code, error_message=str(e)
|
1477
1451
|
)
|
1478
1452
|
|
1479
1453
|
return result
|
gitlab/config.py
CHANGED
@@ -1,14 +1,15 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
1
3
|
import configparser
|
2
4
|
import os
|
3
5
|
import shlex
|
4
6
|
import subprocess
|
5
7
|
from os.path import expanduser, expandvars
|
6
8
|
from pathlib import Path
|
7
|
-
from typing import List, Optional, Union
|
8
9
|
|
9
10
|
from gitlab.const import USER_AGENT
|
10
11
|
|
11
|
-
_DEFAULT_FILES:
|
12
|
+
_DEFAULT_FILES: list[str] = [
|
12
13
|
"/etc/python-gitlab.cfg",
|
13
14
|
str(Path.home() / ".python-gitlab.cfg"),
|
14
15
|
]
|
@@ -20,14 +21,12 @@ HELPER_ATTRIBUTES = ["job_token", "http_password", "private_token", "oauth_token
|
|
20
21
|
_CONFIG_PARSER_ERRORS = (configparser.NoOptionError, configparser.NoSectionError)
|
21
22
|
|
22
23
|
|
23
|
-
def _resolve_file(filepath:
|
24
|
+
def _resolve_file(filepath: Path | str) -> str:
|
24
25
|
resolved = Path(filepath).resolve(strict=True)
|
25
26
|
return str(resolved)
|
26
27
|
|
27
28
|
|
28
|
-
def _get_config_files(
|
29
|
-
config_files: Optional[List[str]] = None,
|
30
|
-
) -> Union[str, List[str]]:
|
29
|
+
def _get_config_files(config_files: list[str] | None = None) -> str | list[str]:
|
31
30
|
"""
|
32
31
|
Return resolved path(s) to config files if they exist, with precedence:
|
33
32
|
1. Files passed in config_files
|
@@ -90,23 +89,23 @@ class GitlabConfigHelperError(ConfigError):
|
|
90
89
|
|
91
90
|
class GitlabConfigParser:
|
92
91
|
def __init__(
|
93
|
-
self, gitlab_id:
|
92
|
+
self, gitlab_id: str | None = None, config_files: list[str] | None = None
|
94
93
|
) -> None:
|
95
94
|
self.gitlab_id = gitlab_id
|
96
|
-
self.http_username:
|
97
|
-
self.http_password:
|
98
|
-
self.job_token:
|
99
|
-
self.oauth_token:
|
100
|
-
self.private_token:
|
95
|
+
self.http_username: str | None = None
|
96
|
+
self.http_password: str | None = None
|
97
|
+
self.job_token: str | None = None
|
98
|
+
self.oauth_token: str | None = None
|
99
|
+
self.private_token: str | None = None
|
101
100
|
|
102
101
|
self.api_version: str = "4"
|
103
|
-
self.order_by:
|
104
|
-
self.pagination:
|
105
|
-
self.per_page:
|
102
|
+
self.order_by: str | None = None
|
103
|
+
self.pagination: str | None = None
|
104
|
+
self.per_page: int | None = None
|
106
105
|
self.retry_transient_errors: bool = False
|
107
|
-
self.ssl_verify:
|
106
|
+
self.ssl_verify: bool | str = True
|
108
107
|
self.timeout: int = 60
|
109
|
-
self.url:
|
108
|
+
self.url: str | None = None
|
110
109
|
self.user_agent: str = USER_AGENT
|
111
110
|
self.keep_base_url: bool = False
|
112
111
|
|