32
32
import graphql
33
33
import httpx
34
34
35
- from ._backends .graphql import GitlabTransport
35
+ from ._backends .graphql import GitlabAsyncTransport , GitlabTransport
36
36
37
37
_GQL_INSTALLED = True
38
38
except ImportError :# pragma: no cover
@@ -1278,14 +1278,13 @@ def next(self) -> Dict[str, Any]:
1278
1278
raise StopIteration
1279
1279
1280
1280
1281
- class GraphQL :
1281
+ class _BaseGraphQL :
1282
1282
def __init__ (
1283
1283
self ,
1284
1284
url :Optional [str ]= None ,
1285
1285
* ,
1286
1286
token :Optional [str ]= None ,
1287
1287
ssl_verify :Union [bool ,str ]= True ,
1288
- client :Optional [httpx .Client ]= None ,
1289
1288
timeout :Optional [float ]= None ,
1290
1289
user_agent :str = gitlab .const .USER_AGENT ,
1291
1290
fetch_schema_from_transport :bool = False ,
@@ -1308,9 +1307,50 @@ def __init__(
1308
1307
self ._max_retries = max_retries
1309
1308
self ._obey_rate_limit = obey_rate_limit
1310
1309
self ._retry_transient_errors = retry_transient_errors
1310
+ self ._client_opts = self ._get_client_opts ()
1311
+ self ._fetch_schema_from_transport = fetch_schema_from_transport
1312
+
1313
+ def _get_client_opts (self )-> Dict [str ,Any ]:
1314
+ headers = {"User-Agent" :self ._user_agent }
1315
+
1316
+ if self ._token :
1317
+ headers ["Authorization" ]= f"Bearer{ self ._token } "
1318
+
1319
+ return {
1320
+ "headers" :headers ,
1321
+ "timeout" :self ._timeout ,
1322
+ "verify" :self ._ssl_verify ,
1323
+ }
1324
+
1311
1325
1312
- opts = self ._get_client_opts ()
1313
- self ._http_client = client or httpx .Client (** opts )
1326
+ class GraphQL (_BaseGraphQL ):
1327
+ def __init__ (
1328
+ self ,
1329
+ url :Optional [str ]= None ,
1330
+ * ,
1331
+ token :Optional [str ]= None ,
1332
+ ssl_verify :Union [bool ,str ]= True ,
1333
+ client :Optional [httpx .Client ]= None ,
1334
+ timeout :Optional [float ]= None ,
1335
+ user_agent :str = gitlab .const .USER_AGENT ,
1336
+ fetch_schema_from_transport :bool = False ,
1337
+ max_retries :int = 10 ,
1338
+ obey_rate_limit :bool = True ,
1339
+ retry_transient_errors :bool = False ,
1340
+ )-> None :
1341
+ super ().__init__ (
1342
+ url = url ,
1343
+ token = token ,
1344
+ ssl_verify = ssl_verify ,
1345
+ timeout = timeout ,
1346
+ user_agent = user_agent ,
1347
+ fetch_schema_from_transport = fetch_schema_from_transport ,
1348
+ max_retries = max_retries ,
1349
+ obey_rate_limit = obey_rate_limit ,
1350
+ retry_transient_errors = retry_transient_errors ,
1351
+ )
1352
+
1353
+ self ._http_client = client or httpx .Client (** self ._client_opts )
1314
1354
self ._transport = GitlabTransport (self ._url ,client = self ._http_client )
1315
1355
self ._client = gql .Client (
1316
1356
transport = self ._transport ,
@@ -1324,19 +1364,81 @@ def __enter__(self) -> "GraphQL":
1324
1364
def __exit__ (self ,* args :Any )-> None :
1325
1365
self ._http_client .close ()
1326
1366
1327
- def _get_client_opts (self )-> Dict [str ,Any ]:
1328
- headers = {"User-Agent" :self ._user_agent }
1367
+ def execute (
1368
+ self ,request :Union [str ,graphql .Source ],* args :Any ,** kwargs :Any
1369
+ )-> Any :
1370
+ parsed_document = self ._gql (request )
1371
+ retry = utils .Retry (
1372
+ max_retries = self ._max_retries ,
1373
+ obey_rate_limit = self ._obey_rate_limit ,
1374
+ retry_transient_errors = self ._retry_transient_errors ,
1375
+ )
1329
1376
1330
- if self ._token :
1331
- headers ["Authorization" ]= f"Bearer{ self ._token } "
1377
+ while True :
1378
+ try :
1379
+ result = self ._client .execute (parsed_document ,* args ,** kwargs )
1380
+ except gql .transport .exceptions .TransportServerError as e :
1381
+ if retry .handle_retry_on_status (
1382
+ status_code = e .code ,headers = self ._transport .response_headers
1383
+ ):
1384
+ continue
1332
1385
1333
- return {
1334
- "headers" : headers ,
1335
- "timeout" : self . _timeout ,
1336
- "verify" : self . _ssl_verify ,
1337
- }
1386
+ if e . code == 401 :
1387
+ raise gitlab . exceptions . GitlabAuthenticationError (
1388
+ response_code = e . code ,
1389
+ error_message = str ( e ) ,
1390
+ )
1338
1391
1339
- def execute (
1392
+ raise gitlab .exceptions .GitlabHttpError (
1393
+ response_code = e .code ,
1394
+ error_message = str (e ),
1395
+ )
1396
+
1397
+ return result
1398
+
1399
+
1400
+ class AsyncGraphQL (_BaseGraphQL ):
1401
+ def __init__ (
1402
+ self ,
1403
+ url :Optional [str ]= None ,
1404
+ * ,
1405
+ token :Optional [str ]= None ,
1406
+ ssl_verify :Union [bool ,str ]= True ,
1407
+ client :Optional [httpx .AsyncClient ]= None ,
1408
+ timeout :Optional [float ]= None ,
1409
+ user_agent :str = gitlab .const .USER_AGENT ,
1410
+ fetch_schema_from_transport :bool = False ,
1411
+ max_retries :int = 10 ,
1412
+ obey_rate_limit :bool = True ,
1413
+ retry_transient_errors :bool = False ,
1414
+ )-> None :
1415
+ super ().__init__ (
1416
+ url = url ,
1417
+ token = token ,
1418
+ ssl_verify = ssl_verify ,
1419
+ timeout = timeout ,
1420
+ user_agent = user_agent ,
1421
+ fetch_schema_from_transport = fetch_schema_from_transport ,
1422
+ max_retries = max_retries ,
1423
+ obey_rate_limit = obey_rate_limit ,
1424
+ retry_transient_errors = retry_transient_errors ,
1425
+ )
1426
+
1427
+ self ._http_client = client or httpx .AsyncClient (** self ._client_opts )
1428
+ self ._transport = GitlabAsyncTransport (self ._url ,client = self ._http_client )
1429
+ self ._client = gql .Client (
1430
+ transport = self ._transport ,
1431
+ fetch_schema_from_transport = fetch_schema_from_transport ,
1432
+ )
1433
+ self ._gql = gql .gql
1434
+
1435
+ async def __aenter__ (self )-> "AsyncGraphQL" :
1436
+ return self
1437
+
1438
+ async def __aexit__ (self ,* args :Any )-> None :
1439
+ await self ._http_client .aclose ()
1440
+
1441
+ async def execute (
1340
1442
self ,request :Union [str ,graphql .Source ],* args :Any ,** kwargs :Any
1341
1443
)-> Any :
1342
1444
parsed_document = self ._gql (request )
@@ -1348,7 +1450,9 @@ def execute(
1348
1450
1349
1451
while True :
1350
1452
try :
1351
- result = self ._client .execute (parsed_document ,* args ,** kwargs )
1453
+ result = await self ._client .execute_async (
1454
+ parsed_document ,* args ,** kwargs
1455
+ )
1352
1456
except gql .transport .exceptions .TransportServerError as e :
1353
1457
if retry .handle_retry_on_status (
1354
1458
status_code = e .code ,headers = self ._transport .response_headers