1- from gitlab import cli
1+ from typing import Any , Callable , cast , Dict , List , Optional , TYPE_CHECKING , Union
2+
3+ import requests
4+
5+ from gitlab import cli , client
26from gitlab import exceptions as exc
37from gitlab import types , utils
48from gitlab .base import RequiredOptional , RESTManager , RESTObject
@@ -163,7 +167,7 @@ class Project(RefreshMixin, SaveMixin, ObjectDeleteMixin, RepositoryMixin, RESTO
163167
164168 @cli .register_custom_action ("Project" , ("forked_from_id" ,))
165169 @exc .on_http_error (exc .GitlabCreateError )
166- def create_fork_relation (self , forked_from_id , ** kwargs ) :
170+ def create_fork_relation (self , forked_from_id : int , ** kwargs : Any ) -> None :
167171 """Create a forked from/to relation between existing projects.
168172
169173 Args:
@@ -179,7 +183,7 @@ def create_fork_relation(self, forked_from_id, **kwargs):
179183
180184 @cli .register_custom_action ("Project" )
181185 @exc .on_http_error (exc .GitlabDeleteError )
182- def delete_fork_relation (self , ** kwargs ) :
186+ def delete_fork_relation (self , ** kwargs : Any ) -> None :
183187 """Delete a forked relation between existing projects.
184188
185189 Args:
@@ -194,7 +198,7 @@ def delete_fork_relation(self, **kwargs):
194198
195199 @cli .register_custom_action ("Project" )
196200 @exc .on_http_error (exc .GitlabGetError )
197- def languages (self , ** kwargs ) :
201+ def languages (self , ** kwargs : Any ) -> Union [ Dict [ str , Any ], requests . Response ] :
198202 """Get languages used in the project with percentage value.
199203
200204 Args:
@@ -209,7 +213,7 @@ def languages(self, **kwargs):
209213
210214 @cli .register_custom_action ("Project" )
211215 @exc .on_http_error (exc .GitlabCreateError )
212- def star (self , ** kwargs ) :
216+ def star (self , ** kwargs : Any ) -> None :
213217 """Star a project.
214218
215219 Args:
@@ -221,11 +225,13 @@ def star(self, **kwargs):
221225 """
222226 path = "/projects/%s/star" % self .get_id ()
223227 server_data = self .manager .gitlab .http_post (path , ** kwargs )
228+ if TYPE_CHECKING :
229+ assert isinstance (server_data , dict )
224230 self ._update_attrs (server_data )
225231
226232 @cli .register_custom_action ("Project" )
227233 @exc .on_http_error (exc .GitlabDeleteError )
228- def unstar (self , ** kwargs ) :
234+ def unstar (self , ** kwargs : Any ) -> None :
229235 """Unstar a project.
230236
231237 Args:
@@ -237,11 +243,13 @@ def unstar(self, **kwargs):
237243 """
238244 path = "/projects/%s/unstar" % self .get_id ()
239245 server_data = self .manager .gitlab .http_post (path , ** kwargs )
246+ if TYPE_CHECKING :
247+ assert isinstance (server_data , dict )
240248 self ._update_attrs (server_data )
241249
242250 @cli .register_custom_action ("Project" )
243251 @exc .on_http_error (exc .GitlabCreateError )
244- def archive (self , ** kwargs ) :
252+ def archive (self , ** kwargs : Any ) -> None :
245253 """Archive a project.
246254
247255 Args:
@@ -253,11 +261,13 @@ def archive(self, **kwargs):
253261 """
254262 path = "/projects/%s/archive" % self .get_id ()
255263 server_data = self .manager .gitlab .http_post (path , ** kwargs )
264+ if TYPE_CHECKING :
265+ assert isinstance (server_data , dict )
256266 self ._update_attrs (server_data )
257267
258268 @cli .register_custom_action ("Project" )
259269 @exc .on_http_error (exc .GitlabDeleteError )
260- def unarchive (self , ** kwargs ) :
270+ def unarchive (self , ** kwargs : Any ) -> None :
261271 """Unarchive a project.
262272
263273 Args:
@@ -269,13 +279,21 @@ def unarchive(self, **kwargs):
269279 """
270280 path = "/projects/%s/unarchive" % self .get_id ()
271281 server_data = self .manager .gitlab .http_post (path , ** kwargs )
282+ if TYPE_CHECKING :
283+ assert isinstance (server_data , dict )
272284 self ._update_attrs (server_data )
273285
274286 @cli .register_custom_action (
275287 "Project" , ("group_id" , "group_access" ), ("expires_at" ,)
276288 )
277289 @exc .on_http_error (exc .GitlabCreateError )
278- def share (self , group_id , group_access , expires_at = None , ** kwargs ):
290+ def share (
291+ self ,
292+ group_id : int ,
293+ group_access : int ,
294+ expires_at : Optional [str ] = None ,
295+ ** kwargs : Any
296+ ) -> None :
279297 """Share the project with a group.
280298
281299 Args:
@@ -297,7 +315,7 @@ def share(self, group_id, group_access, expires_at=None, **kwargs):
297315
298316 @cli .register_custom_action ("Project" , ("group_id" ,))
299317 @exc .on_http_error (exc .GitlabDeleteError )
300- def unshare (self , group_id , ** kwargs ) :
318+ def unshare (self , group_id : int , ** kwargs : Any ) -> None :
301319 """Delete a shared project link within a group.
302320
303321 Args:
@@ -314,7 +332,13 @@ def unshare(self, group_id, **kwargs):
314332 # variables not supported in CLI
315333 @cli .register_custom_action ("Project" , ("ref" , "token" ))
316334 @exc .on_http_error (exc .GitlabCreateError )
317- def trigger_pipeline (self , ref , token , variables = None , ** kwargs ):
335+ def trigger_pipeline (
336+ self ,
337+ ref : str ,
338+ token : str ,
339+ variables : Optional [Dict [str , Any ]] = None ,
340+ ** kwargs : Any
341+ ) -> ProjectPipeline :
318342 """Trigger a CI build.
319343
320344 See https://gitlab.com/help/ci/triggers/README.md#trigger-a-build
@@ -333,11 +357,13 @@ def trigger_pipeline(self, ref, token, variables=None, **kwargs):
333357 path = "/projects/%s/trigger/pipeline" % self .get_id ()
334358 post_data = {"ref" : ref , "token" : token , "variables" : variables }
335359 attrs = self .manager .gitlab .http_post (path , post_data = post_data , ** kwargs )
360+ if TYPE_CHECKING :
361+ assert isinstance (attrs , dict )
336362 return ProjectPipeline (self .pipelines , attrs )
337363
338364 @cli .register_custom_action ("Project" )
339365 @exc .on_http_error (exc .GitlabHousekeepingError )
340- def housekeeping (self , ** kwargs ) :
366+ def housekeeping (self , ** kwargs : Any ) -> None :
341367 """Start the housekeeping task.
342368
343369 Args:
@@ -354,7 +380,13 @@ def housekeeping(self, **kwargs):
354380 # see #56 - add file attachment features
355381 @cli .register_custom_action ("Project" , ("filename" , "filepath" ))
356382 @exc .on_http_error (exc .GitlabUploadError )
357- def upload (self , filename , filedata = None , filepath = None , ** kwargs ):
383+ def upload (
384+ self ,
385+ filename : str ,
386+ filedata : Optional [bytes ] = None ,
387+ filepath : Optional [str ] = None ,
388+ ** kwargs : Any
389+ ) -> Dict [str , Any ]:
358390 """Upload the specified file into the project.
359391
360392 .. note::
@@ -394,13 +426,20 @@ def upload(self, filename, filedata=None, filepath=None, **kwargs):
394426 file_info = {"file" : (filename , filedata )}
395427 data = self .manager .gitlab .http_post (url , files = file_info )
396428
429+ if TYPE_CHECKING :
430+ assert isinstance (data , dict )
397431 return {"alt" : data ["alt" ], "url" : data ["url" ], "markdown" : data ["markdown" ]}
398432
399433 @cli .register_custom_action ("Project" , optional = ("wiki" ,))
400434 @exc .on_http_error (exc .GitlabGetError )
401435 def snapshot (
402- self , wiki = False , streamed = False , action = None , chunk_size = 1024 , ** kwargs
403- ):
436+ self ,
437+ wiki : bool = False ,
438+ streamed : bool = False ,
439+ action : Optional [Callable ] = None ,
440+ chunk_size : int = 1024 ,
441+ ** kwargs : Any
442+ ) -> Optional [bytes ]:
404443 """Return a snapshot of the repository.
405444
406445 Args:
@@ -424,11 +463,15 @@ def snapshot(
424463 result = self .manager .gitlab .http_get (
425464 path , streamed = streamed , raw = True , ** kwargs
426465 )
466+ if TYPE_CHECKING :
467+ assert isinstance (result , requests .Response )
427468 return utils .response_content (result , streamed , action , chunk_size )
428469
429470 @cli .register_custom_action ("Project" , ("scope" , "search" ))
430471 @exc .on_http_error (exc .GitlabSearchError )
431- def search (self , scope , search , ** kwargs ):
472+ def search (
473+ self , scope : str , search : str , ** kwargs : Any
474+ ) -> Union [client .GitlabList , List [Dict [str , Any ]]]:
432475 """Search the project resources matching the provided string.'
433476
434477 Args:
@@ -449,7 +492,7 @@ def search(self, scope, search, **kwargs):
449492
450493 @cli .register_custom_action ("Project" )
451494 @exc .on_http_error (exc .GitlabCreateError )
452- def mirror_pull (self , ** kwargs ) :
495+ def mirror_pull (self , ** kwargs : Any ) -> None :
453496 """Start the pull mirroring process for the project.
454497
455498 Args:
@@ -464,7 +507,7 @@ def mirror_pull(self, **kwargs):
464507
465508 @cli .register_custom_action ("Project" , ("to_namespace" ,))
466509 @exc .on_http_error (exc .GitlabTransferProjectError )
467- def transfer_project (self , to_namespace , ** kwargs ) :
510+ def transfer_project (self , to_namespace : str , ** kwargs : Any ) -> None :
468511 """Transfer a project to the given namespace ID
469512
470513 Args:
@@ -484,8 +527,14 @@ def transfer_project(self, to_namespace, **kwargs):
484527 @cli .register_custom_action ("Project" , ("ref_name" , "job" ), ("job_token" ,))
485528 @exc .on_http_error (exc .GitlabGetError )
486529 def artifacts (
487- self , ref_name , job , streamed = False , action = None , chunk_size = 1024 , ** kwargs
488- ):
530+ self ,
531+ ref_name : str ,
532+ job : str ,
533+ streamed : bool = False ,
534+ action : Optional [Callable ] = None ,
535+ chunk_size : int = 1024 ,
536+ ** kwargs : Any
537+ ) -> Optional [bytes ]:
489538 """Get the job artifacts archive from a specific tag or branch.
490539
491540 Args:
@@ -513,20 +562,22 @@ def artifacts(
513562 result = self .manager .gitlab .http_get (
514563 path , job = job , streamed = streamed , raw = True , ** kwargs
515564 )
565+ if TYPE_CHECKING :
566+ assert isinstance (result , requests .Response )
516567 return utils .response_content (result , streamed , action , chunk_size )
517568
518569 @cli .register_custom_action ("Project" , ("ref_name" , "artifact_path" , "job" ))
519570 @exc .on_http_error (exc .GitlabGetError )
520571 def artifact (
521572 self ,
522- ref_name ,
523- artifact_path ,
524- job ,
525- streamed = False ,
526- action = None ,
527- chunk_size = 1024 ,
528- ** kwargs
529- ):
573+ ref_name : str ,
574+ artifact_path : str ,
575+ job : str ,
576+ streamed : bool = False ,
577+ action : Optional [ Callable ] = None ,
578+ chunk_size : int = 1024 ,
579+ ** kwargs : Any
580+ ) -> Optional [ bytes ] :
530581 """Download a single artifact file from a specific tag or branch from within the job’s artifacts archive.
531582
532583 Args:
@@ -558,6 +609,8 @@ def artifact(
558609 result = self .manager .gitlab .http_get (
559610 path , streamed = streamed , raw = True , ** kwargs
560611 )
612+ if TYPE_CHECKING :
613+ assert isinstance (result , requests .Response )
561614 return utils .response_content (result , streamed , action , chunk_size )
562615
563616
@@ -725,16 +778,19 @@ class ProjectManager(CRUDMixin, RESTManager):
725778 )
726779 _types = {"avatar" : types .ImageAttribute , "topic" : types .ListAttribute }
727780
781+ def get (self , id : Union [str , int ], lazy : bool = False , ** kwargs : Any ) -> Project :
782+ return cast (Project , super ().get (id = id , lazy = lazy , ** kwargs ))
783+
728784 def import_project (
729785 self ,
730- file ,
731- path ,
732- name = None ,
733- namespace = None ,
734- overwrite = False ,
735- override_params = None ,
736- ** kwargs
737- ):
786+ file : str ,
787+ path : str ,
788+ name : Optional [ str ] = None ,
789+ namespace : Optional [ str ] = None ,
790+ overwrite : bool = False ,
791+ override_params : Optional [ Dict [ str , Any ]] = None ,
792+ ** kwargs : Any
793+ ) -> Union [ Dict [ str , Any ], requests . Response ] :
738794 """Import a project from an archive file.
739795
740796 Args:
@@ -769,15 +825,15 @@ def import_project(
769825
770826 def import_bitbucket_server (
771827 self ,
772- bitbucket_server_url ,
773- bitbucket_server_username ,
774- personal_access_token ,
775- bitbucket_server_project ,
776- bitbucket_server_repo ,
777- new_name = None ,
778- target_namespace = None ,
779- ** kwargs
780- ):
828+ bitbucket_server_url : str ,
829+ bitbucket_server_username : str ,
830+ personal_access_token : str ,
831+ bitbucket_server_project : str ,
832+ bitbucket_server_repo : str ,
833+ new_name : Optional [ str ] = None ,
834+ target_namespace : Optional [ str ] = None ,
835+ ** kwargs : Any
836+ ) -> Union [ Dict [ str , Any ], requests . Response ] :
781837 """Import a project from BitBucket Server to Gitlab (schedule the import)
782838
783839 This method will return when an import operation has been safely queued,
@@ -856,8 +912,13 @@ def import_bitbucket_server(
856912 return result
857913
858914 def import_github (
859- self , personal_access_token , repo_id , target_namespace , new_name = None , ** kwargs
860- ):
915+ self ,
916+ personal_access_token : str ,
917+ repo_id : int ,
918+ target_namespace : str ,
919+ new_name : Optional [str ] = None ,
920+ ** kwargs : Any
921+ ) -> Union [Dict [str , Any ], requests .Response ]:
861922 """Import a project from Github to Gitlab (schedule the import)
862923
863924 This method will return when an import operation has been safely queued,
@@ -944,7 +1005,9 @@ class ProjectForkManager(CreateMixin, ListMixin, RESTManager):
9441005 )
9451006 _create_attrs = RequiredOptional (optional = ("namespace" ,))
9461007
947- def create (self , data , ** kwargs ):
1008+ def create (
1009+ self , data : Optional [Dict [str , Any ]] = None , ** kwargs : Any
1010+ ) -> ProjectFork :
9481011 """Creates a new object.
9491012
9501013 Args:
@@ -960,8 +1023,10 @@ def create(self, data, **kwargs):
9601023 RESTObject: A new instance of the managed object class build with
9611024 the data sent by the server
9621025 """
1026+ if TYPE_CHECKING :
1027+ assert self .path is not None
9631028 path = self .path [:- 1 ] # drop the 's'
964- return CreateMixin .create (self , data , path = path , ** kwargs )
1029+ return cast ( ProjectFork , CreateMixin .create (self , data , path = path , ** kwargs ) )
9651030
9661031
9671032class ProjectRemoteMirror (SaveMixin , RESTObject ):
0 commit comments