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
0 commit comments