@@ -35,6 +35,7 @@ def default(self, obj):
3535 return {'url' : obj ._url }
3636 return json .JSONEncoder .default (self , obj )
3737
38+
3839class GitlabConnectionError (Exception ):
3940 pass
4041
@@ -229,6 +230,14 @@ def delete(self, obj):
229230 return False
230231
231232 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+
232241 url = obj ._url % obj .__dict__
233242 url = '%s%s?private_token=%s' % (self ._url , url , self .private_token )
234243
@@ -346,6 +355,8 @@ class GitlabObject(object):
346355 canCreate = True
347356 canUpdate = True
348357 canDelete = True
358+ requiredCreateAttrs = []
359+ optionalCreateAttrs = []
349360
350361 @classmethod
351362 def list (cls , gl , ** kwargs ):
@@ -436,6 +447,9 @@ def json(self):
436447
437448class User (GitlabObject ):
438449 _url = '/users'
450+ requiredCreateAttrs = ['email' , 'password' , 'username' , 'name' ]
451+ optionalCreateAttrs = ['skype' , 'linkedin' , 'twitter' , 'projects_limit' ,
452+ 'extern_uid' , 'provider' , 'bio' ]
439453
440454
441455class CurrentUserKey (GitlabObject ):
@@ -460,6 +474,7 @@ def Key(self, id=None, **kwargs):
460474class Group (GitlabObject ):
461475 _url = '/groups'
462476 _constructorTypes = {'projects' : 'Project' }
477+ requiredCreateAttrs = ['name' , 'path' ]
463478
464479 def transfer_project (self , id ):
465480 url = '/groups/%d/projects/%d?private_token=%s' % \
@@ -471,6 +486,7 @@ def transfer_project(self, id):
471486
472487class Hook (GitlabObject ):
473488 _url = '/hooks'
489+ requiredCreateAttrs = ['url' ]
474490
475491
476492class Issue (GitlabObject ):
@@ -520,24 +536,30 @@ class ProjectCommit(GitlabObject):
520536class ProjectKey (GitlabObject ):
521537 _url = '/projects/%(project_id)d/keys'
522538 canUpdate = False
539+ requiredCreateAttrs = ['title' , 'key' ]
523540
524541
525542class ProjectHook (GitlabObject ):
526543 _url = '/projects/%(project_id)d/hooks'
544+ requiredCreateAttrs = ['url' ]
527545
528546
529547class ProjectIssueNote (GitlabObject ):
530548 _url = '/projects/%(project_id)d/issues/%(issue_id)d/notes'
531549 _constructorTypes = {'author' : 'User' }
532550 canUpdate = False
533551 canDelete = False
552+ requiredCreateAttrs = ['body' ]
534553
535554
536555class ProjectIssue (GitlabObject ):
537556 _url = '/projects/%(project_id)s/issues/'
538557 _constructorTypes = {'author' : 'User' , 'assignee' : 'User' ,
539558 'milestone' : 'ProjectMilestone' }
540559 canDelete = False
560+ requiredCreateAttrs = ['title' ]
561+ optionalCreateAttrs = ['description' , 'assignee_id' , 'milestone_id' ,
562+ 'labels' ]
541563
542564 def Note (self , id = None , ** kwargs ):
543565 return self ._getListOrObject (ProjectIssueNote , id ,
@@ -549,13 +571,15 @@ def Note(self, id=None, **kwargs):
549571class ProjectMember (GitlabObject ):
550572 _url = '/projects/%(project_id)d/members'
551573 _returnClass = User
574+ requiredCreateAttrs = ['user_id' , 'access_level' ]
552575
553576
554577class ProjectNote (GitlabObject ):
555578 _url = '/projects/%(project_id)d/notes'
556579 _constructorTypes = {'author' : 'User' }
557580 canUpdate = False
558581 canDelete = False
582+ requiredCreateAttrs = ['body' ]
559583
560584
561585class ProjectTag (GitlabObject ):
@@ -579,6 +603,8 @@ class ProjectMergeRequest(GitlabObject):
579603 _url = '/projects/%(project_id)d/merge_request'
580604 _constructorTypes = {'author' : 'User' , 'assignee' : 'User' }
581605 canDelete = False
606+ requiredCreateAttrs = ['source_branch' , 'target_branch' , 'title' ]
607+ optionalCreateAttrs = ['assignee_id' ]
582608
583609 def Note (self , id = None , ** kwargs ):
584610 return self ._getListOrObject (ProjectMergeRequestNote , id ,
@@ -590,18 +616,23 @@ def Note(self, id=None, **kwargs):
590616class ProjectMilestone (GitlabObject ):
591617 _url = '/projects/%(project_id)s/milestones'
592618 canDelete = False
619+ requiredCreateAttrs = ['title' ]
620+ optionalCreateAttrs = ['description' , 'due_date' ]
593621
594622
595623class ProjectSnippetNote (GitlabObject ):
596624 _url = '/projects/%(project_id)d/snippets/%(snippet_id)d/notes'
597625 _constructorTypes = {'author' : 'User' }
598626 canUpdate = False
599627 canDelete = False
628+ requiredCreateAttrs = ['body' ]
600629
601630
602631class ProjectSnippet (GitlabObject ):
603632 _url = '/projects/%(project_id)d/snippets'
604633 _constructorTypes = {'author' : 'User' }
634+ requiredCreateAttrs = ['title' , 'file_name' , 'code' ]
635+ optionalCreateAttrs = ['lifetime' ]
605636
606637 def Note (self , id = None , ** kwargs ):
607638 return self ._getListOrObject (ProjectSnippetNote , id ,
@@ -615,6 +646,10 @@ class Project(GitlabObject):
615646 _constructorTypes = {'owner' : 'User' , 'namespace' : 'Group' }
616647 canUpdate = False
617648 canDelete = False
649+ requiredCreateAttrs = ['name' ]
650+ optionalCreateAttrs = ['default_branch' , 'issues_enabled' , 'wall_enabled' ,
651+ 'merge_requests_enabled' , 'wiki_enabled' ,
652+ 'namespace_id' ]
618653
619654 def Branch (self , id = None , ** kwargs ):
620655 return self ._getListOrObject (ProjectBranch , id ,
0 commit comments