1
+ from __future__import annotations
2
+
1
3
import copy
2
4
import importlib
3
5
import json
4
6
import pprint
5
7
import textwrap
8
+ from collections .abc import Iterable
6
9
from types import ModuleType
7
10
from typing import (
8
11
Any ,
9
12
ClassVar ,
10
- Dict ,
11
13
Generic ,
12
- Iterable ,
13
- Optional ,
14
- Type ,
15
14
TYPE_CHECKING ,
16
15
TypeVar ,
17
- Union ,
18
16
)
19
17
20
18
import gitlab
@@ -51,20 +49,20 @@ class RESTObject:
51
49
object's ``__repr__()`` method.
52
50
"""
53
51
54
- _id_attr :Optional [ str ] = "id"
55
- _attrs :Dict [str ,Any ]
52
+ _id_attr :str | None = "id"
53
+ _attrs :dict [str ,Any ]
56
54
_created_from_list :bool # Indicates if object was created from a list() action
57
55
_module :ModuleType
58
- _parent_attrs :Dict [str ,Any ]
59
- _repr_attr :Optional [ str ] = None
60
- _updated_attrs :Dict [str ,Any ]
56
+ _parent_attrs :dict [str ,Any ]
57
+ _repr_attr :str | None = None
58
+ _updated_attrs :dict [str ,Any ]
61
59
_lazy :bool
62
- manager :" RESTManager[Any]"
60
+ manager :RESTManager [Any ]
63
61
64
62
def __init__ (
65
63
self ,
66
- manager :" RESTManager[Any]" ,
67
- attrs :Dict [str ,Any ],
64
+ manager :RESTManager [Any ],
65
+ attrs :dict [str ,Any ],
68
66
* ,
69
67
created_from_list :bool = False ,
70
68
lazy :bool = False ,
@@ -88,13 +86,13 @@ def __init__(
88
86
self .__dict__ ["_parent_attrs" ]= self .manager .parent_attrs
89
87
self ._create_managers ()
90
88
91
- def __getstate__ (self )-> Dict [str ,Any ]:
89
+ def __getstate__ (self )-> dict [str ,Any ]:
92
90
state = self .__dict__ .copy ()
93
91
module = state .pop ("_module" )
94
92
state ["_module_name" ]= module .__name__
95
93
return state
96
94
97
- def __setstate__ (self ,state :Dict [str ,Any ])-> None :
95
+ def __setstate__ (self ,state :dict [str ,Any ])-> None :
98
96
module_name = state .pop ("_module_name" )
99
97
self .__dict__ .update (state )
100
98
self .__dict__ ["_module" ]= importlib .import_module (module_name )
@@ -147,7 +145,7 @@ def __getattr__(self, name: str) -> Any:
147
145
def __setattr__ (self ,name :str ,value :Any )-> None :
148
146
self .__dict__ ["_updated_attrs" ][name ]= value
149
147
150
- def asdict (self ,* ,with_parent_attrs :bool = False )-> Dict [str ,Any ]:
148
+ def asdict (self ,* ,with_parent_attrs :bool = False )-> dict [str ,Any ]:
151
149
data = {}
152
150
if with_parent_attrs :
153
151
data .update (copy .deepcopy (self ._parent_attrs ))
@@ -156,7 +154,7 @@ def asdict(self, *, with_parent_attrs: bool = False) -> Dict[str, Any]:
156
154
return data
157
155
158
156
@property
159
- def attributes (self )-> Dict [str ,Any ]:
157
+ def attributes (self )-> dict [str ,Any ]:
160
158
return self .asdict (with_parent_attrs = True )
161
159
162
160
def to_json (self ,* ,with_parent_attrs :bool = False ,** kwargs :Any )-> str :
@@ -231,11 +229,11 @@ def _create_managers(self) -> None:
231
229
# Since we have our own __setattr__ method, we can't use setattr()
232
230
self .__dict__ [attr ]= manager
233
231
234
- def _update_attrs (self ,new_attrs :Dict [str ,Any ])-> None :
232
+ def _update_attrs (self ,new_attrs :dict [str ,Any ])-> None :
235
233
self .__dict__ ["_updated_attrs" ]= {}
236
234
self .__dict__ ["_attrs" ]= new_attrs
237
235
238
- def get_id (self )-> Optional [ Union [ int , str ]] :
236
+ def get_id (self )-> int | str | None :
239
237
"""Returns the id of the resource."""
240
238
if self ._id_attr is None or not hasattr (self ,self ._id_attr ):
241
239
return None
@@ -245,7 +243,7 @@ def get_id(self) -> Optional[Union[int, str]]:
245
243
return id_val
246
244
247
245
@property
248
- def _repr_value (self )-> Optional [ str ] :
246
+ def _repr_value (self )-> str | None :
249
247
"""Safely returns the human-readable resource name if present."""
250
248
if self ._repr_attr is None or not hasattr (self ,self ._repr_attr ):
251
249
return None
@@ -255,7 +253,7 @@ def _repr_value(self) -> Optional[str]:
255
253
return repr_val
256
254
257
255
@property
258
- def encoded_id (self )-> Optional [ Union [ int , str ]] :
256
+ def encoded_id (self )-> int | str | None :
259
257
"""Ensure that the ID is url-encoded so that it can be safely used in a URL
260
258
path"""
261
259
obj_id = self .get_id ()
@@ -280,7 +278,7 @@ class RESTObjectList:
280
278
"""
281
279
282
280
def __init__ (
283
- self ,manager :" RESTManager[Any]" ,obj_cls :Type [RESTObject ],_list :GitlabList
281
+ self ,manager :RESTManager [Any ],obj_cls :type [RESTObject ],_list :GitlabList
284
282
)-> None :
285
283
"""Creates an objects list from a GitlabList.
286
284
@@ -296,7 +294,7 @@ def __init__(
296
294
self ._obj_cls = obj_cls
297
295
self ._list = _list
298
296
299
- def __iter__ (self )-> " RESTObjectList" :
297
+ def __iter__ (self )-> RESTObjectList :
300
298
return self
301
299
302
300
def __len__ (self )-> int :
@@ -315,33 +313,33 @@ def current_page(self) -> int:
315
313
return self ._list .current_page
316
314
317
315
@property
318
- def prev_page (self )-> Optional [ int ] :
316
+ def prev_page (self )-> int | None :
319
317
"""The previous page number.
320
318
321
319
If None, the current page is the first.
322
320
"""
323
321
return self ._list .prev_page
324
322
325
323
@property
326
- def next_page (self )-> Optional [ int ] :
324
+ def next_page (self )-> int | None :
327
325
"""The next page number.
328
326
329
327
If None, the current page is the last.
330
328
"""
331
329
return self ._list .next_page
332
330
333
331
@property
334
- def per_page (self )-> Optional [ int ] :
332
+ def per_page (self )-> int | None :
335
333
"""The number of items per page."""
336
334
return self ._list .per_page
337
335
338
336
@property
339
- def total_pages (self )-> Optional [ int ] :
337
+ def total_pages (self )-> int | None :
340
338
"""The total number of pages."""
341
339
return self ._list .total_pages
342
340
343
341
@property
344
- def total (self )-> Optional [ int ] :
342
+ def total (self )-> int | None :
345
343
"""The total number of items."""
346
344
return self ._list .total
347
345
@@ -362,15 +360,15 @@ class RESTManager(Generic[TObjCls]):
362
360
_update_attrs :g_types .RequiredOptional = g_types .RequiredOptional ()
363
361
_path :ClassVar [str ]
364
362
_obj_cls :type [TObjCls ]
365
- _from_parent_attrs :Dict [str ,Any ]= {}
366
- _types :Dict [str ,Type [g_types .GitlabAttribute ]]= {}
363
+ _from_parent_attrs :dict [str ,Any ]= {}
364
+ _types :dict [str ,type [g_types .GitlabAttribute ]]= {}
367
365
368
366
_computed_path :str
369
- _parent :Optional [ RESTObject ]
370
- _parent_attrs :Dict [str ,Any ]
367
+ _parent :RESTObject | None
368
+ _parent_attrs :dict [str ,Any ]
371
369
gitlab :Gitlab
372
370
373
- def __init__ (self ,gl :Gitlab ,parent :Optional [ RESTObject ] = None )-> None :
371
+ def __init__ (self ,gl :Gitlab ,parent :RESTObject | None = None )-> None :
374
372
"""REST manager constructor.
375
373
376
374
Args:
@@ -382,17 +380,17 @@ def __init__(self, gl: Gitlab, parent: Optional[RESTObject] = None) -> None:
382
380
self ._computed_path = self ._compute_path ()
383
381
384
382
@property
385
- def parent_attrs (self )-> Optional [ Dict [ str ,Any ]] :
383
+ def parent_attrs (self )-> dict [ str ,Any ]| None :
386
384
return self ._parent_attrs
387
385
388
- def _compute_path (self ,path :Optional [ str ] = None )-> str :
386
+ def _compute_path (self ,path :str | None = None )-> str :
389
387
self ._parent_attrs = {}
390
388
if path is None :
391
389
path = self ._path
392
390
if self ._parent is None or not self ._from_parent_attrs :
393
391
return path
394
392
395
- data :Dict [str ,Optional [ gitlab .utils .EncodedId ] ]= {}
393
+ data :dict [str ,gitlab .utils .EncodedId | None ]= {}
396
394
for self_attr ,parent_attr in self ._from_parent_attrs .items ():
397
395
if not hasattr (self ._parent ,parent_attr ):
398
396
data [self_attr ]= None