@@ -35,6 +35,7 @@ def default(self, obj):
35
35
return {'url' :obj ._url }
36
36
return json .JSONEncoder .default (self ,obj )
37
37
38
+
38
39
class GitlabConnectionError (Exception ):
39
40
pass
40
41
@@ -229,6 +230,14 @@ def delete(self, obj):
229
230
return False
230
231
231
232
def create (self ,obj ):
233
+ missing = []
234
+ for k in obj .requiredCreateAttrs :
235
+ if k not in obj .__dict__ :
236
+ missing .append (k )
237
+ if missing :
238
+ raise GitlabCreateError ('Missing attribute(s): %s' % \
239
+ ", " .join (missing ))
240
+
232
241
url = obj ._url % obj .__dict__
233
242
url = '%s%s?private_token=%s' % (self ._url ,url ,self .private_token )
234
243
@@ -346,6 +355,8 @@ class GitlabObject(object):
346
355
canCreate = True
347
356
canUpdate = True
348
357
canDelete = True
358
+ requiredCreateAttrs = []
359
+ optionalCreateAttrs = []
349
360
350
361
@classmethod
351
362
def list (cls ,gl ,** kwargs ):
@@ -436,6 +447,9 @@ def json(self):
436
447
437
448
class User (GitlabObject ):
438
449
_url = '/users'
450
+ requiredCreateAttrs = ['email' ,'password' ,'username' ,'name' ]
451
+ optionalCreateAttrs = ['skype' ,'linkedin' ,'twitter' ,'projects_limit' ,
452
+ 'extern_uid' ,'provider' ,'bio' ]
439
453
440
454
441
455
class CurrentUserKey (GitlabObject ):
@@ -460,6 +474,7 @@ def Key(self, id=None, **kwargs):
460
474
class Group (GitlabObject ):
461
475
_url = '/groups'
462
476
_constructorTypes = {'projects' :'Project' }
477
+ requiredCreateAttrs = ['name' ,'path' ]
463
478
464
479
def transfer_project (self ,id ):
465
480
url = '/groups/%d/projects/%d?private_token=%s' % \
@@ -471,6 +486,7 @@ def transfer_project(self, id):
471
486
472
487
class Hook (GitlabObject ):
473
488
_url = '/hooks'
489
+ requiredCreateAttrs = ['url' ]
474
490
475
491
476
492
class Issue (GitlabObject ):
@@ -520,24 +536,30 @@ class ProjectCommit(GitlabObject):
520
536
class ProjectKey (GitlabObject ):
521
537
_url = '/projects/%(project_id)d/keys'
522
538
canUpdate = False
539
+ requiredCreateAttrs = ['title' ,'key' ]
523
540
524
541
525
542
class ProjectHook (GitlabObject ):
526
543
_url = '/projects/%(project_id)d/hooks'
544
+ requiredCreateAttrs = ['url' ]
527
545
528
546
529
547
class ProjectIssueNote (GitlabObject ):
530
548
_url = '/projects/%(project_id)d/issues/%(issue_id)d/notes'
531
549
_constructorTypes = {'author' :'User' }
532
550
canUpdate = False
533
551
canDelete = False
552
+ requiredCreateAttrs = ['body' ]
534
553
535
554
536
555
class ProjectIssue (GitlabObject ):
537
556
_url = '/projects/%(project_id)s/issues/'
538
557
_constructorTypes = {'author' :'User' ,'assignee' :'User' ,
539
558
'milestone' :'ProjectMilestone' }
540
559
canDelete = False
560
+ requiredCreateAttrs = ['title' ]
561
+ optionalCreateAttrs = ['description' ,'assignee_id' ,'milestone_id' ,
562
+ 'labels' ]
541
563
542
564
def Note (self ,id = None ,** kwargs ):
543
565
return self ._getListOrObject (ProjectIssueNote ,id ,
@@ -549,13 +571,15 @@ def Note(self, id=None, **kwargs):
549
571
class ProjectMember (GitlabObject ):
550
572
_url = '/projects/%(project_id)d/members'
551
573
_returnClass = User
574
+ requiredCreateAttrs = ['user_id' ,'access_level' ]
552
575
553
576
554
577
class ProjectNote (GitlabObject ):
555
578
_url = '/projects/%(project_id)d/notes'
556
579
_constructorTypes = {'author' :'User' }
557
580
canUpdate = False
558
581
canDelete = False
582
+ requiredCreateAttrs = ['body' ]
559
583
560
584
561
585
class ProjectTag (GitlabObject ):
@@ -579,6 +603,8 @@ class ProjectMergeRequest(GitlabObject):
579
603
_url = '/projects/%(project_id)d/merge_request'
580
604
_constructorTypes = {'author' :'User' ,'assignee' :'User' }
581
605
canDelete = False
606
+ requiredCreateAttrs = ['source_branch' ,'target_branch' ,'title' ]
607
+ optionalCreateAttrs = ['assignee_id' ]
582
608
583
609
def Note (self ,id = None ,** kwargs ):
584
610
return self ._getListOrObject (ProjectMergeRequestNote ,id ,
@@ -590,18 +616,23 @@ def Note(self, id=None, **kwargs):
590
616
class ProjectMilestone (GitlabObject ):
591
617
_url = '/projects/%(project_id)s/milestones'
592
618
canDelete = False
619
+ requiredCreateAttrs = ['title' ]
620
+ optionalCreateAttrs = ['description' ,'due_date' ]
593
621
594
622
595
623
class ProjectSnippetNote (GitlabObject ):
596
624
_url = '/projects/%(project_id)d/snippets/%(snippet_id)d/notes'
597
625
_constructorTypes = {'author' :'User' }
598
626
canUpdate = False
599
627
canDelete = False
628
+ requiredCreateAttrs = ['body' ]
600
629
601
630
602
631
class ProjectSnippet (GitlabObject ):
603
632
_url = '/projects/%(project_id)d/snippets'
604
633
_constructorTypes = {'author' :'User' }
634
+ requiredCreateAttrs = ['title' ,'file_name' ,'code' ]
635
+ optionalCreateAttrs = ['lifetime' ]
605
636
606
637
def Note (self ,id = None ,** kwargs ):
607
638
return self ._getListOrObject (ProjectSnippetNote ,id ,
@@ -615,6 +646,10 @@ class Project(GitlabObject):
615
646
_constructorTypes = {'owner' :'User' ,'namespace' :'Group' }
616
647
canUpdate = False
617
648
canDelete = False
649
+ requiredCreateAttrs = ['name' ]
650
+ optionalCreateAttrs = ['default_branch' ,'issues_enabled' ,'wall_enabled' ,
651
+ 'merge_requests_enabled' ,'wiki_enabled' ,
652
+ 'namespace_id' ]
618
653
619
654
def Branch (self ,id = None ,** kwargs ):
620
655
return self ._getListOrObject (ProjectBranch ,id ,