python-gitlab 4.9.0__py3-none-any.whl → 4.11.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 +2 -1
- gitlab/_backends/graphql.py +24 -0
- gitlab/_version.py +1 -1
- gitlab/client.py +116 -47
- gitlab/exceptions.py +5 -0
- gitlab/utils.py +91 -2
- gitlab/v4/objects/hooks.py +29 -0
- gitlab/v4/objects/members.py +4 -2
- {python_gitlab-4.9.0.dist-info → python_gitlab-4.11.0.dist-info}/METADATA +3 -1
- {python_gitlab-4.9.0.dist-info → python_gitlab-4.11.0.dist-info}/RECORD +15 -14
- {python_gitlab-4.9.0.dist-info → python_gitlab-4.11.0.dist-info}/WHEEL +1 -1
- {python_gitlab-4.9.0.dist-info → python_gitlab-4.11.0.dist-info}/AUTHORS +0 -0
- {python_gitlab-4.9.0.dist-info → python_gitlab-4.11.0.dist-info}/COPYING +0 -0
- {python_gitlab-4.9.0.dist-info → python_gitlab-4.11.0.dist-info}/entry_points.txt +0 -0
- {python_gitlab-4.9.0.dist-info → python_gitlab-4.11.0.dist-info}/top_level.txt +0 -0
gitlab/__init__.py
CHANGED
@@ -27,7 +27,7 @@ from gitlab._version import ( # noqa: F401
|
|
27
27
|
__title__,
|
28
28
|
__version__,
|
29
29
|
)
|
30
|
-
from gitlab.client import Gitlab, GitlabList # noqa: F401
|
30
|
+
from gitlab.client import Gitlab, GitlabList, GraphQL # noqa: F401
|
31
31
|
from gitlab.exceptions import * # noqa: F401,F403
|
32
32
|
|
33
33
|
warnings.filterwarnings("default", category=DeprecationWarning, module="^gitlab")
|
@@ -42,5 +42,6 @@ __all__ = [
|
|
42
42
|
"__version__",
|
43
43
|
"Gitlab",
|
44
44
|
"GitlabList",
|
45
|
+
"GraphQL",
|
45
46
|
]
|
46
47
|
__all__.extend(gitlab.exceptions.__all__)
|
@@ -0,0 +1,24 @@
|
|
1
|
+
from typing import Any
|
2
|
+
|
3
|
+
import httpx
|
4
|
+
from gql.transport.httpx import HTTPXTransport
|
5
|
+
|
6
|
+
|
7
|
+
class GitlabTransport(HTTPXTransport):
|
8
|
+
"""A gql httpx transport that reuses an existing httpx.Client.
|
9
|
+
By default, gql's transports do not have a keep-alive session
|
10
|
+
and do not enable providing your own session that's kept open.
|
11
|
+
This transport lets us provide and close our session on our own
|
12
|
+
and provide additional auth.
|
13
|
+
For details, see https://github.com/graphql-python/gql/issues/91.
|
14
|
+
"""
|
15
|
+
|
16
|
+
def __init__(self, *args: Any, client: httpx.Client, **kwargs: Any):
|
17
|
+
super().__init__(*args, **kwargs)
|
18
|
+
self.client = client
|
19
|
+
|
20
|
+
def connect(self) -> None:
|
21
|
+
pass
|
22
|
+
|
23
|
+
def close(self) -> None:
|
24
|
+
pass
|
gitlab/_version.py
CHANGED
gitlab/client.py
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
import os
|
4
4
|
import re
|
5
|
-
import time
|
6
5
|
from typing import (
|
7
6
|
Any,
|
8
7
|
BinaryIO,
|
@@ -25,6 +24,19 @@ import gitlab.const
|
|
25
24
|
import gitlab.exceptions
|
26
25
|
from gitlab import _backends, utils
|
27
26
|
|
27
|
+
try:
|
28
|
+
import gql
|
29
|
+
import gql.transport.exceptions
|
30
|
+
import graphql
|
31
|
+
import httpx
|
32
|
+
|
33
|
+
from ._backends.graphql import GitlabTransport
|
34
|
+
|
35
|
+
_GQL_INSTALLED = True
|
36
|
+
except ImportError: # pragma: no cover
|
37
|
+
_GQL_INSTALLED = False
|
38
|
+
|
39
|
+
|
28
40
|
REDIRECT_MSG = (
|
29
41
|
"python-gitlab detected a {status_code} ({reason!r}) redirection. You must update "
|
30
42
|
"your GitLab URL to the correct URL to avoid issues. The redirection was from: "
|
@@ -89,7 +101,7 @@ class Gitlab:
|
|
89
101
|
self._api_version = str(api_version)
|
90
102
|
self._server_version: Optional[str] = None
|
91
103
|
self._server_revision: Optional[str] = None
|
92
|
-
self._base_url =
|
104
|
+
self._base_url = utils.get_base_url(url)
|
93
105
|
self._url = f"{self._base_url}/api/v{api_version}"
|
94
106
|
#: Timeout to use for requests to gitlab server
|
95
107
|
self.timeout = timeout
|
@@ -557,18 +569,6 @@ class Gitlab:
|
|
557
569
|
"verify": self.ssl_verify,
|
558
570
|
}
|
559
571
|
|
560
|
-
@staticmethod
|
561
|
-
def _get_base_url(url: Optional[str] = None) -> str:
|
562
|
-
"""Return the base URL with the trailing slash stripped.
|
563
|
-
If the URL is a Falsy value, return the default URL.
|
564
|
-
Returns:
|
565
|
-
The base URL
|
566
|
-
"""
|
567
|
-
if not url:
|
568
|
-
return gitlab.const.DEFAULT_URL
|
569
|
-
|
570
|
-
return url.rstrip("/")
|
571
|
-
|
572
572
|
def _build_url(self, path: str) -> str:
|
573
573
|
"""Returns the full url from path.
|
574
574
|
|
@@ -718,7 +718,12 @@ class Gitlab:
|
|
718
718
|
send_data = self._backend.prepare_send_data(files, post_data, raw)
|
719
719
|
opts["headers"]["Content-type"] = send_data.content_type
|
720
720
|
|
721
|
-
|
721
|
+
retry = utils.Retry(
|
722
|
+
max_retries=max_retries,
|
723
|
+
obey_rate_limit=obey_rate_limit,
|
724
|
+
retry_transient_errors=retry_transient_errors,
|
725
|
+
)
|
726
|
+
|
722
727
|
while True:
|
723
728
|
try:
|
724
729
|
result = self._backend.http_request(
|
@@ -733,14 +738,8 @@ class Gitlab:
|
|
733
738
|
**opts,
|
734
739
|
)
|
735
740
|
except (requests.ConnectionError, requests.exceptions.ChunkedEncodingError):
|
736
|
-
if
|
737
|
-
max_retries == -1 or cur_retries < max_retries
|
738
|
-
):
|
739
|
-
wait_time = 2**cur_retries * 0.1
|
740
|
-
cur_retries += 1
|
741
|
-
time.sleep(wait_time)
|
741
|
+
if retry.handle_retry():
|
742
742
|
continue
|
743
|
-
|
744
743
|
raise
|
745
744
|
|
746
745
|
self._check_redirects(result.response)
|
@@ -748,31 +747,10 @@ class Gitlab:
|
|
748
747
|
if 200 <= result.status_code < 300:
|
749
748
|
return result.response
|
750
749
|
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
if not retry_transient_errors:
|
756
|
-
return False
|
757
|
-
if result.status_code in gitlab.const.RETRYABLE_TRANSIENT_ERROR_CODES:
|
758
|
-
return True
|
759
|
-
if result.status_code == 409 and "Resource lock" in result.reason:
|
760
|
-
return True
|
761
|
-
|
762
|
-
return False
|
763
|
-
|
764
|
-
if should_retry():
|
765
|
-
# Response headers documentation:
|
766
|
-
# https://docs.gitlab.com/ee/user/admin_area/settings/user_and_ip_rate_limits.html#response-headers
|
767
|
-
if max_retries == -1 or cur_retries < max_retries:
|
768
|
-
wait_time = 2**cur_retries * 0.1
|
769
|
-
if "Retry-After" in result.headers:
|
770
|
-
wait_time = int(result.headers["Retry-After"])
|
771
|
-
elif "RateLimit-Reset" in result.headers:
|
772
|
-
wait_time = int(result.headers["RateLimit-Reset"]) - time.time()
|
773
|
-
cur_retries += 1
|
774
|
-
time.sleep(wait_time)
|
775
|
-
continue
|
750
|
+
if retry.handle_retry_on_status(
|
751
|
+
result.status_code, result.headers, result.reason
|
752
|
+
):
|
753
|
+
continue
|
776
754
|
|
777
755
|
error_message = result.content
|
778
756
|
try:
|
@@ -1296,3 +1274,94 @@ class GitlabList:
|
|
1296
1274
|
return self.next()
|
1297
1275
|
|
1298
1276
|
raise StopIteration
|
1277
|
+
|
1278
|
+
|
1279
|
+
class GraphQL:
|
1280
|
+
def __init__(
|
1281
|
+
self,
|
1282
|
+
url: Optional[str] = None,
|
1283
|
+
*,
|
1284
|
+
token: Optional[str] = None,
|
1285
|
+
ssl_verify: Union[bool, str] = True,
|
1286
|
+
client: Optional[httpx.Client] = None,
|
1287
|
+
timeout: Optional[float] = None,
|
1288
|
+
user_agent: str = gitlab.const.USER_AGENT,
|
1289
|
+
fetch_schema_from_transport: bool = False,
|
1290
|
+
max_retries: int = 10,
|
1291
|
+
obey_rate_limit: bool = True,
|
1292
|
+
retry_transient_errors: bool = False,
|
1293
|
+
) -> None:
|
1294
|
+
if not _GQL_INSTALLED:
|
1295
|
+
raise ImportError(
|
1296
|
+
"The GraphQL client could not be initialized because "
|
1297
|
+
"the gql dependencies are not installed. "
|
1298
|
+
"Install them with 'pip install python-gitlab[graphql]'"
|
1299
|
+
)
|
1300
|
+
self._base_url = utils.get_base_url(url)
|
1301
|
+
self._timeout = timeout
|
1302
|
+
self._token = token
|
1303
|
+
self._url = f"{self._base_url}/api/graphql"
|
1304
|
+
self._user_agent = user_agent
|
1305
|
+
self._ssl_verify = ssl_verify
|
1306
|
+
self._max_retries = max_retries
|
1307
|
+
self._obey_rate_limit = obey_rate_limit
|
1308
|
+
self._retry_transient_errors = retry_transient_errors
|
1309
|
+
|
1310
|
+
opts = self._get_client_opts()
|
1311
|
+
self._http_client = client or httpx.Client(**opts)
|
1312
|
+
self._transport = GitlabTransport(self._url, client=self._http_client)
|
1313
|
+
self._client = gql.Client(
|
1314
|
+
transport=self._transport,
|
1315
|
+
fetch_schema_from_transport=fetch_schema_from_transport,
|
1316
|
+
)
|
1317
|
+
self._gql = gql.gql
|
1318
|
+
|
1319
|
+
def __enter__(self) -> "GraphQL":
|
1320
|
+
return self
|
1321
|
+
|
1322
|
+
def __exit__(self, *args: Any) -> None:
|
1323
|
+
self._http_client.close()
|
1324
|
+
|
1325
|
+
def _get_client_opts(self) -> Dict[str, Any]:
|
1326
|
+
headers = {"User-Agent": self._user_agent}
|
1327
|
+
|
1328
|
+
if self._token:
|
1329
|
+
headers["Authorization"] = f"Bearer {self._token}"
|
1330
|
+
|
1331
|
+
return {
|
1332
|
+
"headers": headers,
|
1333
|
+
"timeout": self._timeout,
|
1334
|
+
"verify": self._ssl_verify,
|
1335
|
+
}
|
1336
|
+
|
1337
|
+
def execute(
|
1338
|
+
self, request: Union[str, graphql.Source], *args: Any, **kwargs: Any
|
1339
|
+
) -> Any:
|
1340
|
+
parsed_document = self._gql(request)
|
1341
|
+
retry = utils.Retry(
|
1342
|
+
max_retries=self._max_retries,
|
1343
|
+
obey_rate_limit=self._obey_rate_limit,
|
1344
|
+
retry_transient_errors=self._retry_transient_errors,
|
1345
|
+
)
|
1346
|
+
|
1347
|
+
while True:
|
1348
|
+
try:
|
1349
|
+
result = self._client.execute(parsed_document, *args, **kwargs)
|
1350
|
+
except gql.transport.exceptions.TransportServerError as e:
|
1351
|
+
if retry.handle_retry_on_status(
|
1352
|
+
status_code=e.code, headers=self._transport.response_headers
|
1353
|
+
):
|
1354
|
+
continue
|
1355
|
+
|
1356
|
+
if e.code == 401:
|
1357
|
+
raise gitlab.exceptions.GitlabAuthenticationError(
|
1358
|
+
response_code=e.code,
|
1359
|
+
error_message=str(e),
|
1360
|
+
)
|
1361
|
+
|
1362
|
+
raise gitlab.exceptions.GitlabHttpError(
|
1363
|
+
response_code=e.code,
|
1364
|
+
error_message=str(e),
|
1365
|
+
)
|
1366
|
+
|
1367
|
+
return result
|
gitlab/exceptions.py
CHANGED
@@ -316,6 +316,10 @@ class GitlabDeploymentApprovalError(GitlabOperationError):
|
|
316
316
|
pass
|
317
317
|
|
318
318
|
|
319
|
+
class GitlabHookTestError(GitlabOperationError):
|
320
|
+
pass
|
321
|
+
|
322
|
+
|
319
323
|
# For an explanation of how these type-hints work see:
|
320
324
|
# https://mypy.readthedocs.io/en/stable/generics.html#declaring-decorators
|
321
325
|
#
|
@@ -370,6 +374,7 @@ __all__ = [
|
|
370
374
|
"GitlabGetError",
|
371
375
|
"GitlabGroupTransferError",
|
372
376
|
"GitlabHeadError",
|
377
|
+
"GitlabHookTestError",
|
373
378
|
"GitlabHousekeepingError",
|
374
379
|
"GitlabHttpError",
|
375
380
|
"GitlabImportError",
|
gitlab/utils.py
CHANGED
@@ -2,14 +2,26 @@ import dataclasses
|
|
2
2
|
import email.message
|
3
3
|
import logging
|
4
4
|
import pathlib
|
5
|
+
import time
|
5
6
|
import traceback
|
6
7
|
import urllib.parse
|
7
8
|
import warnings
|
8
|
-
from typing import
|
9
|
+
from typing import (
|
10
|
+
Any,
|
11
|
+
Callable,
|
12
|
+
Dict,
|
13
|
+
Iterator,
|
14
|
+
Literal,
|
15
|
+
MutableMapping,
|
16
|
+
Optional,
|
17
|
+
Tuple,
|
18
|
+
Type,
|
19
|
+
Union,
|
20
|
+
)
|
9
21
|
|
10
22
|
import requests
|
11
23
|
|
12
|
-
from gitlab import types
|
24
|
+
from gitlab import const, types
|
13
25
|
|
14
26
|
|
15
27
|
class _StdoutStream:
|
@@ -17,6 +29,18 @@ class _StdoutStream:
|
|
17
29
|
print(chunk)
|
18
30
|
|
19
31
|
|
32
|
+
def get_base_url(url: Optional[str] = None) -> str:
|
33
|
+
"""Return the base URL with the trailing slash stripped.
|
34
|
+
If the URL is a Falsy value, return the default URL.
|
35
|
+
Returns:
|
36
|
+
The base URL
|
37
|
+
"""
|
38
|
+
if not url:
|
39
|
+
return const.DEFAULT_URL
|
40
|
+
|
41
|
+
return url.rstrip("/")
|
42
|
+
|
43
|
+
|
20
44
|
def get_content_type(content_type: Optional[str]) -> str:
|
21
45
|
message = email.message.Message()
|
22
46
|
if content_type is not None:
|
@@ -73,6 +97,71 @@ def response_content(
|
|
73
97
|
return None
|
74
98
|
|
75
99
|
|
100
|
+
class Retry:
|
101
|
+
def __init__(
|
102
|
+
self,
|
103
|
+
max_retries: int,
|
104
|
+
obey_rate_limit: Optional[bool] = True,
|
105
|
+
retry_transient_errors: Optional[bool] = False,
|
106
|
+
) -> None:
|
107
|
+
self.cur_retries = 0
|
108
|
+
self.max_retries = max_retries
|
109
|
+
self.obey_rate_limit = obey_rate_limit
|
110
|
+
self.retry_transient_errors = retry_transient_errors
|
111
|
+
|
112
|
+
def _retryable_status_code(
|
113
|
+
self, status_code: Optional[int], reason: str = ""
|
114
|
+
) -> bool:
|
115
|
+
if status_code == 429 and self.obey_rate_limit:
|
116
|
+
return True
|
117
|
+
|
118
|
+
if not self.retry_transient_errors:
|
119
|
+
return False
|
120
|
+
if status_code in const.RETRYABLE_TRANSIENT_ERROR_CODES:
|
121
|
+
return True
|
122
|
+
if status_code == 409 and "Resource lock" in reason:
|
123
|
+
return True
|
124
|
+
|
125
|
+
return False
|
126
|
+
|
127
|
+
def handle_retry_on_status(
|
128
|
+
self,
|
129
|
+
status_code: Optional[int],
|
130
|
+
headers: Optional[MutableMapping[str, str]] = None,
|
131
|
+
reason: str = "",
|
132
|
+
) -> bool:
|
133
|
+
if not self._retryable_status_code(status_code, reason):
|
134
|
+
return False
|
135
|
+
|
136
|
+
if headers is None:
|
137
|
+
headers = {}
|
138
|
+
|
139
|
+
# Response headers documentation:
|
140
|
+
# https://docs.gitlab.com/ee/user/admin_area/settings/user_and_ip_rate_limits.html#response-headers
|
141
|
+
if self.max_retries == -1 or self.cur_retries < self.max_retries:
|
142
|
+
wait_time = 2**self.cur_retries * 0.1
|
143
|
+
if "Retry-After" in headers:
|
144
|
+
wait_time = int(headers["Retry-After"])
|
145
|
+
elif "RateLimit-Reset" in headers:
|
146
|
+
wait_time = int(headers["RateLimit-Reset"]) - time.time()
|
147
|
+
self.cur_retries += 1
|
148
|
+
time.sleep(wait_time)
|
149
|
+
return True
|
150
|
+
|
151
|
+
return False
|
152
|
+
|
153
|
+
def handle_retry(self) -> bool:
|
154
|
+
if self.retry_transient_errors and (
|
155
|
+
self.max_retries == -1 or self.cur_retries < self.max_retries
|
156
|
+
):
|
157
|
+
wait_time = 2**self.cur_retries * 0.1
|
158
|
+
self.cur_retries += 1
|
159
|
+
time.sleep(wait_time)
|
160
|
+
return True
|
161
|
+
|
162
|
+
return False
|
163
|
+
|
164
|
+
|
76
165
|
def _transform_types(
|
77
166
|
data: Dict[str, Any],
|
78
167
|
custom_types: Dict[str, Any],
|
gitlab/v4/objects/hooks.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
from typing import Any, cast, Union
|
2
2
|
|
3
|
+
from gitlab import exceptions as exc
|
3
4
|
from gitlab.base import RESTManager, RESTObject
|
4
5
|
from gitlab.mixins import CRUDMixin, NoUpdateMixin, ObjectDeleteMixin, SaveMixin
|
5
6
|
from gitlab.types import RequiredOptional
|
@@ -31,6 +32,20 @@ class HookManager(NoUpdateMixin, RESTManager):
|
|
31
32
|
class ProjectHook(SaveMixin, ObjectDeleteMixin, RESTObject):
|
32
33
|
_repr_attr = "url"
|
33
34
|
|
35
|
+
@exc.on_http_error(exc.GitlabHookTestError)
|
36
|
+
def test(self, trigger: str) -> None:
|
37
|
+
"""
|
38
|
+
Test a Project Hook
|
39
|
+
|
40
|
+
Args:
|
41
|
+
trigger: Type of trigger event to test
|
42
|
+
|
43
|
+
Raises:
|
44
|
+
GitlabHookTestError: If the hook test attempt failed
|
45
|
+
"""
|
46
|
+
path = f"{self.manager.path}/{self.encoded_id}/test/{trigger}"
|
47
|
+
self.manager.gitlab.http_post(path)
|
48
|
+
|
34
49
|
|
35
50
|
class ProjectHookManager(CRUDMixin, RESTManager):
|
36
51
|
_path = "/projects/{project_id}/hooks"
|
@@ -78,6 +93,20 @@ class ProjectHookManager(CRUDMixin, RESTManager):
|
|
78
93
|
class GroupHook(SaveMixin, ObjectDeleteMixin, RESTObject):
|
79
94
|
_repr_attr = "url"
|
80
95
|
|
96
|
+
@exc.on_http_error(exc.GitlabHookTestError)
|
97
|
+
def test(self, trigger: str) -> None:
|
98
|
+
"""
|
99
|
+
Test a Group Hook
|
100
|
+
|
101
|
+
Args:
|
102
|
+
trigger: Type of trigger event to test
|
103
|
+
|
104
|
+
Raises:
|
105
|
+
GitlabHookTestError: If the hook test attempt failed
|
106
|
+
"""
|
107
|
+
path = f"{self.manager.path}/{self.encoded_id}/test/{trigger}"
|
108
|
+
self.manager.gitlab.http_post(path)
|
109
|
+
|
81
110
|
|
82
111
|
class GroupHookManager(CRUDMixin, RESTManager):
|
83
112
|
_path = "/groups/{group_id}/hooks"
|
gitlab/v4/objects/members.py
CHANGED
@@ -37,8 +37,9 @@ class GroupMemberManager(CRUDMixin, RESTManager):
|
|
37
37
|
_obj_cls = GroupMember
|
38
38
|
_from_parent_attrs = {"group_id": "id"}
|
39
39
|
_create_attrs = RequiredOptional(
|
40
|
-
required=("access_level",
|
40
|
+
required=("access_level",),
|
41
41
|
optional=("expires_at", "tasks_to_be_done"),
|
42
|
+
exclusive=("username", "user_id"),
|
42
43
|
)
|
43
44
|
_update_attrs = RequiredOptional(
|
44
45
|
required=("access_level",), optional=("expires_at",)
|
@@ -101,8 +102,9 @@ class ProjectMemberManager(CRUDMixin, RESTManager):
|
|
101
102
|
_obj_cls = ProjectMember
|
102
103
|
_from_parent_attrs = {"project_id": "id"}
|
103
104
|
_create_attrs = RequiredOptional(
|
104
|
-
required=("access_level",
|
105
|
+
required=("access_level",),
|
105
106
|
optional=("expires_at", "tasks_to_be_done"),
|
107
|
+
exclusive=("username", "user_id"),
|
106
108
|
)
|
107
109
|
_update_attrs = RequiredOptional(
|
108
110
|
required=("access_level",), optional=("expires_at",)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: python-gitlab
|
3
|
-
Version: 4.
|
3
|
+
Version: 4.11.0
|
4
4
|
Summary: A python wrapper for the GitLab API
|
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>
|
@@ -32,6 +32,8 @@ Requires-Dist: requests >=2.32.0
|
|
32
32
|
Requires-Dist: requests-toolbelt >=1.0.0
|
33
33
|
Provides-Extra: autocompletion
|
34
34
|
Requires-Dist: argcomplete <3,>=1.10.0 ; extra == 'autocompletion'
|
35
|
+
Provides-Extra: graphql
|
36
|
+
Requires-Dist: gql[httpx] <4,>=3.5.0 ; extra == 'graphql'
|
35
37
|
Provides-Extra: yaml
|
36
38
|
Requires-Dist: PyYaml >=6.0.1 ; extra == 'yaml'
|
37
39
|
|
@@ -1,17 +1,18 @@
|
|
1
|
-
gitlab/__init__.py,sha256=
|
1
|
+
gitlab/__init__.py,sha256=DlY_IEbIbeTJnMfkcl4866XbJ_50UiaE4yI0PwOq36E,1406
|
2
2
|
gitlab/__main__.py,sha256=HTesNl0UAU6mPb9EXWkTKMy6Q6pAUxGi3iPnDHTE2uE,68
|
3
|
-
gitlab/_version.py,sha256=
|
3
|
+
gitlab/_version.py,sha256=_ZHsoVye-Iaog0jEDXMthyNXtQA9GiK4pyR3vDJgPVM,250
|
4
4
|
gitlab/base.py,sha256=5cotawlHD01Vw88aN4o7wNIhDyk_bmcwubX4mbOpnVo,13780
|
5
5
|
gitlab/cli.py,sha256=d3-LtZuA1Fgon5wZWn4c3E70fTIu4mM4Juyhh3F8EBs,12416
|
6
|
-
gitlab/client.py,sha256=
|
6
|
+
gitlab/client.py,sha256=BCglR-5hrEQVEc7FdsfAT3u4_sIYQBkbdaEj2feDzPo,51181
|
7
7
|
gitlab/config.py,sha256=T1DgUXD0-MN2qNszrv-SO5d4uy0FITnNN0vWJgOt2yo,9088
|
8
8
|
gitlab/const.py,sha256=rtPU-fxVSOvgpueoQVTvZGQp6iAZ-aa3nsY4RcSs_M4,5352
|
9
|
-
gitlab/exceptions.py,sha256=
|
9
|
+
gitlab/exceptions.py,sha256=VOQftPzEq5mpVj6vke7z6Xe4S7Yf_rDTab0lNHqf3AY,8390
|
10
10
|
gitlab/mixins.py,sha256=7iPlzqGmd5Ew2RLzRzRWsJ4r8Bn6wteUj791BJrjtXc,36645
|
11
11
|
gitlab/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
12
|
gitlab/types.py,sha256=lepiiI_YOr94B4koqIHuY70tszZC_X3YW4lDvbadbI8,3312
|
13
|
-
gitlab/utils.py,sha256=
|
13
|
+
gitlab/utils.py,sha256=3OngV45Gb4UO2GR-6-kXax1Ghdw6bpyRdUC2cHpyCSw,9027
|
14
14
|
gitlab/_backends/__init__.py,sha256=WalQZRIDzw19FuNxraG7fvck6ddg4cdNd3bi53QKvZM,392
|
15
|
+
gitlab/_backends/graphql.py,sha256=SiGEfqqBqRey_EhozhF1pWFO81c_VVKdM50XvCQ4PZc,737
|
15
16
|
gitlab/_backends/protocol.py,sha256=m5qSz1o3i0H4XJCWnqx0wIFilOIU9cKxzFsYxLL6Big,842
|
16
17
|
gitlab/_backends/requests_backend.py,sha256=CrSDTfkvi17dT4kTU8R3qQFBNCPJqEfBJq4gJ2GXleA,5534
|
17
18
|
gitlab/v4/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -48,7 +49,7 @@ gitlab/v4/objects/files.py,sha256=9M7pocu_n9JDRAPu5BqIt398emYD5WVnGh3wAJinPX8,10
|
|
48
49
|
gitlab/v4/objects/geo_nodes.py,sha256=tD9piU7OIZgbNQRUeLTFPtAJ6PVL_SI6tR_zh6Tm2M8,3686
|
49
50
|
gitlab/v4/objects/group_access_tokens.py,sha256=EijY0sfsp0Gtx_q4JLBeLL3jphx5b_6-nTzKxV272jc,1023
|
50
51
|
gitlab/v4/objects/groups.py,sha256=YxOeaRYUjhu8PicCicVT7Eua04YuyOLAc8J13V7r9Gg,15958
|
51
|
-
gitlab/v4/objects/hooks.py,sha256=
|
52
|
+
gitlab/v4/objects/hooks.py,sha256=ig8qyC6ZWpZXqcGYCSS7LVvTpD1xnLkNNtfJAOXeYv8,4445
|
52
53
|
gitlab/v4/objects/integrations.py,sha256=QWl5ZnE1oivt4ho9qJa_o268ORdaW35D4klBRy1jUyQ,9229
|
53
54
|
gitlab/v4/objects/invitations.py,sha256=ya9x7xhL1oSbx-FLJud-lHKmbYQoTplZlAbjsZip2CI,2734
|
54
55
|
gitlab/v4/objects/issues.py,sha256=kxciXrLGxCsevJ2eoxpDdMLnw1kF4VrQTy4YB4AoN1U,10393
|
@@ -58,7 +59,7 @@ gitlab/v4/objects/jobs.py,sha256=g7l5dA6-99tyLDoohjJ_xZvGyMbeytn4L9T-h78NQaE,914
|
|
58
59
|
gitlab/v4/objects/keys.py,sha256=IclYGSzcVEZPIhDdIz-p16rvb68FnBTgAf1cWCXWjkY,882
|
59
60
|
gitlab/v4/objects/labels.py,sha256=JvOciJ6V76pF9HuJp5OT_Ykq8oqaa6ItxvpKf3hiEzs,4736
|
60
61
|
gitlab/v4/objects/ldap.py,sha256=adpkdfk7VBjshuh8SpCsc77Pax4QgqCx1N12CuzitDE,1662
|
61
|
-
gitlab/v4/objects/members.py,sha256=
|
62
|
+
gitlab/v4/objects/members.py,sha256=YJO9MaqlCSUnozHIlI7MfSlcWTju4xRmW8QIlEiBmok,3902
|
62
63
|
gitlab/v4/objects/merge_request_approvals.py,sha256=oPZFd4AUtrAVhBTa0iM4krNkk2UTNOTw_MWlEWo2HAQ,6400
|
63
64
|
gitlab/v4/objects/merge_requests.py,sha256=tpFCMmTVWyL9X7HtUoZuHJP4MVZUz1kk9-Bv-SbnwfU,17422
|
64
65
|
gitlab/v4/objects/merge_trains.py,sha256=e0Gp2Ri75elcG_r9w8qxdrcWW_YiebPRwUYIH5od8kc,422
|
@@ -94,10 +95,10 @@ gitlab/v4/objects/triggers.py,sha256=UAERq_C-QdPBbBQPHLh5IfhpkdDeIxdnVGPHfu9Qy5Y
|
|
94
95
|
gitlab/v4/objects/users.py,sha256=_gGrTwcE17jeoXIPgfFSv54jtF1_9C1R0Y0hhssTvXY,21381
|
95
96
|
gitlab/v4/objects/variables.py,sha256=S0Vz32jEpUbo4J2js8gMPPTVpcy1ge5FYVHLiPz9c-A,2627
|
96
97
|
gitlab/v4/objects/wikis.py,sha256=JtI1cQqZV1_PRfKVlQRMh4LZjdxEfi9T2VuFYv6PrV8,1775
|
97
|
-
python_gitlab-4.
|
98
|
-
python_gitlab-4.
|
99
|
-
python_gitlab-4.
|
100
|
-
python_gitlab-4.
|
101
|
-
python_gitlab-4.
|
102
|
-
python_gitlab-4.
|
103
|
-
python_gitlab-4.
|
98
|
+
python_gitlab-4.11.0.dist-info/AUTHORS,sha256=Z0P61GJSVnp7iFbRcMezhx3f4zMyPkVmG--TWaRo768,526
|
99
|
+
python_gitlab-4.11.0.dist-info/COPYING,sha256=2n6rt7r999OuXp8iOqW9we7ORaxWncIbOwN1ILRGR2g,7651
|
100
|
+
python_gitlab-4.11.0.dist-info/METADATA,sha256=iSsCzBj4kepfxKWEmWopKZuOmm7aWrbIW_0aIr156Fg,8311
|
101
|
+
python_gitlab-4.11.0.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
|
102
|
+
python_gitlab-4.11.0.dist-info/entry_points.txt,sha256=nhpKLLP_uQPFByn8UtE9zsvQQwa402t52o_Cw9IFXMo,43
|
103
|
+
python_gitlab-4.11.0.dist-info/top_level.txt,sha256=MvIaP8p_Oaf4gO_hXmHkX-5y2deHLp1pe6tJR3ukQ6o,7
|
104
|
+
python_gitlab-4.11.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|