diff options
author | Gauvain Pocentek <gauvain.pocentek@objectif-libre.com> | 2016-01-03 09:24:20 +0100 |
---|---|---|
committer | Gauvain Pocentek <gauvain.pocentek@objectif-libre.com> | 2016-01-03 09:24:20 +0100 |
commit | 46f74e8e4e6cd093a3be4309802f5a72ed305080 (patch) | |
tree | 7d39b93e8df6d3f8b5b0711d7e2579ce4db50ac3 /gitlab/objects.py | |
parent | e5246bffd17eb9863516677a086928af40fba9f5 (diff) | |
download | gitlab-46f74e8e4e6cd093a3be4309802f5a72ed305080.tar.gz |
Implement managers to get access to resources
This changes the 'default' API, using managers is the recommended way to
get/list/create objects. Additional operations will be implemented in
followup patchs.
Old methods are deprecated and will disappear in a while.
Diffstat (limited to 'gitlab/objects.py')
-rw-r--r-- | gitlab/objects.py | 284 |
1 files changed, 258 insertions, 26 deletions
diff --git a/gitlab/objects.py b/gitlab/objects.py index 1060564..e6f5467 100644 --- a/gitlab/objects.py +++ b/gitlab/objects.py @@ -36,6 +36,42 @@ class jsonEncoder(json.JSONEncoder): return json.JSONEncoder.default(self, obj) +class BaseManager(object): + obj_cls = None + + def __init__(self, gl, parent=None, args=[]): + self.gitlab = gl + self.args = args + self.parent = parent + + def get(self, id, **kwargs): + if self.parent is not None: + for attr, parent_attr in self.args: + kwargs.setdefault(attr, getattr(self.parent, parent_attr)) + + if not self.obj_cls.canGet: + raise NotImplementedError + return self.obj_cls.get(self.gitlab, id, **kwargs) + + def list(self, **kwargs): + if self.parent is not None: + for attr, parent_attr in self.args: + kwargs.setdefault(attr, getattr(self.parent, parent_attr)) + + if not self.obj_cls.canList: + raise NotImplementedError + return self.obj_cls.list(self.gitlab, **kwargs) + + def create(self, data, **kwargs): + if self.parent is not None: + for attr, parent_attr in self.args: + kwargs.setdefault(attr, getattr(self.parent, parent_attr)) + + if not self.obj_cls.canCreate: + raise NotImplementedError + return self.obj_cls.create(self.gitlab, data, **kwargs) + + class GitlabObject(object): """Base class for all classes that interface with GitLab @@ -84,6 +120,8 @@ class GitlabObject(object): optionalUpdateAttrs = None #: Whether the object ID is required in the GET url getRequiresId = True + #: List of managers to create + managers = [] idAttr = 'id' shortPrintAttr = None @@ -209,6 +247,13 @@ class GitlabObject(object): if not hasattr(self, "id"): self.id = None + self._set_managers() + + def _set_managers(self): + for var, cls, attrs in self.managers: + manager = cls(self.gitlab, self, attrs) + setattr(self, var, manager) + def __str__(self): return '%s => %s' % (type(self), str(self.__dict__)) @@ -282,6 +327,10 @@ class UserKey(GitlabObject): requiredCreateAttrs = ['title', 'key'] +class UserKeyManager(BaseManager): + obj_cls = UserKey + + class User(GitlabObject): _url = '/users' shortPrintAttr = 'username' @@ -291,6 +340,7 @@ class User(GitlabObject): 'projects_limit', 'extern_uid', 'provider', 'bio', 'admin', 'can_create_group', 'website_url', 'confirm'] + managers = [('keys', UserKeyManager, [('user_id', 'id')])] def _data_for_gitlab(self, extra_parameters={}): if hasattr(self, 'confirm'): @@ -298,11 +348,17 @@ class User(GitlabObject): return super(User, self)._data_for_gitlab(extra_parameters) def Key(self, id=None, **kwargs): + warnings.warn("`Key` is deprecated, use `keys` instead", + DeprecationWarning) return UserKey._get_list_or_object(self.gitlab, id, user_id=self.id, **kwargs) +class UserManager(BaseManager): + obj_cls = User + + class CurrentUserKey(GitlabObject): _url = '/user/keys' canUpdate = False @@ -310,6 +366,10 @@ class CurrentUserKey(GitlabObject): requiredCreateAttrs = ['title', 'key'] +class CurrentUserKeyManager(BaseManager): + obj_cls = CurrentUserKey + + class CurrentUser(GitlabObject): _url = '/user' canList = False @@ -317,8 +377,11 @@ class CurrentUser(GitlabObject): canUpdate = False canDelete = False shortPrintAttr = 'username' + managers = [('keys', CurrentUserKeyManager, [('user_id', 'id')])] def Key(self, id=None, **kwargs): + warnings.warn("`Key` is deprecated, use `keys` instead", + DeprecationWarning) return CurrentUserKey._get_list_or_object(self.gitlab, id, **kwargs) @@ -335,12 +398,17 @@ class GroupMember(GitlabObject): super(GroupMember, self)._update(**kwargs) +class GroupMemberManager(BaseManager): + obj_cls = GroupMember + + class Group(GitlabObject): _url = '/groups' canUpdate = False _constructorTypes = {'projects': 'Project'} requiredCreateAttrs = ['name', 'path'] shortPrintAttr = 'name' + managers = [('members', GroupMemberManager, [('group_id', 'id')])] GUEST_ACCESS = 10 REPORTER_ACCESS = 20 @@ -349,6 +417,8 @@ class Group(GitlabObject): OWNER_ACCESS = 50 def Member(self, id=None, **kwargs): + warnings.warn("`Member` is deprecated, use `members` instead", + DeprecationWarning) return GroupMember._get_list_or_object(self.gitlab, id, group_id=self.id, **kwargs) @@ -359,6 +429,10 @@ class Group(GitlabObject): raise_error_from_response(r, GitlabTransferProjectError, 201) +class GroupManager(BaseManager): + obj_cls = Group + + class Hook(GitlabObject): _url = '/hooks' canUpdate = False @@ -366,6 +440,10 @@ class Hook(GitlabObject): shortPrintAttr = 'url' +class HookManager(BaseManager): + obj_cls = Hook + + class Issue(GitlabObject): _url = '/issues' _constructorTypes = {'author': 'User', 'assignee': 'User', @@ -377,6 +455,10 @@ class Issue(GitlabObject): shortPrintAttr = 'title' +class IssueManager(BaseManager): + obj_cls = Issue + + class ProjectBranch(GitlabObject): _url = '/projects/%(project_id)s/repository/branches' _constructorTypes = {'author': 'User', "committer": "User"} @@ -403,6 +485,10 @@ class ProjectBranch(GitlabObject): self.protect(False, **kwargs) +class ProjectBranchManager(BaseManager): + obj_cls = ProjectBranch + + class ProjectCommit(GitlabObject): _url = '/projects/%(project_id)s/repository/commits' canDelete = False @@ -424,12 +510,15 @@ class ProjectCommit(GitlabObject): {'project_id': self.project_id, 'commit_id': self.id}) url += '?filepath=%s' % filepath r = self.gitlab._raw_get(url, **kwargs) - raise_error_from_response(r, GitlabGetError) return r.content +class ProjectCommitManager(BaseManager): + obj_cls = ProjectCommit + + class ProjectKey(GitlabObject): _url = '/projects/%(project_id)s/keys' canUpdate = False @@ -437,6 +526,10 @@ class ProjectKey(GitlabObject): requiredCreateAttrs = ['title', 'key'] +class ProjectKeyManager(BaseManager): + obj_cls = ProjectKey + + class ProjectEvent(GitlabObject): _url = '/projects/%(project_id)s/events' canGet = 'from_list' @@ -447,6 +540,10 @@ class ProjectEvent(GitlabObject): shortPrintAttr = 'target_title' +class ProjectEventManager(BaseManager): + obj_cls = ProjectEvent + + class ProjectHook(GitlabObject): _url = '/projects/%(project_id)s/hooks' requiredUrlAttrs = ['project_id'] @@ -456,6 +553,10 @@ class ProjectHook(GitlabObject): shortPrintAttr = 'url' +class ProjectHookManager(BaseManager): + obj_cls = ProjectHook + + class ProjectIssueNote(GitlabObject): _url = '/projects/%(project_id)s/issues/%(issue_id)s/notes' _constructorTypes = {'author': 'User'} @@ -465,6 +566,10 @@ class ProjectIssueNote(GitlabObject): requiredCreateAttrs = ['body'] +class ProjectIssueNoteManager(BaseManager): + obj_cls = ProjectIssueNote + + class ProjectIssue(GitlabObject): _url = '/projects/%(project_id)s/issues/' _constructorTypes = {'author': 'User', 'assignee': 'User', @@ -475,8 +580,9 @@ class ProjectIssue(GitlabObject): # FIXME: state_event is only valid with update optionalCreateAttrs = ['description', 'assignee_id', 'milestone_id', 'labels', 'state_event'] - shortPrintAttr = 'title' + managers = [('notes', ProjectIssueNoteManager, + [('project_id', 'project_id'), ('issue_id', 'id')])] def _data_for_gitlab(self, extra_parameters={}): # Gitlab-api returns labels in a json list and takes them in a @@ -490,12 +596,18 @@ class ProjectIssue(GitlabObject): return super(ProjectIssue, self)._data_for_gitlab(extra_parameters) def Note(self, id=None, **kwargs): + warnings.warn("`Note` is deprecated, use `notes` instead", + DeprecationWarning) return ProjectIssueNote._get_list_or_object(self.gitlab, id, project_id=self.project_id, issue_id=self.id, **kwargs) +class ProjectIssueManager(BaseManager): + obj_cls = ProjectIssue + + class ProjectMember(GitlabObject): _url = '/projects/%(project_id)s/members' requiredUrlAttrs = ['project_id'] @@ -503,6 +615,10 @@ class ProjectMember(GitlabObject): shortPrintAttr = 'username' +class ProjectMemberManager(BaseManager): + obj_cls = ProjectMember + + class ProjectNote(GitlabObject): _url = '/projects/%(project_id)s/notes' _constructorTypes = {'author': 'User'} @@ -512,6 +628,10 @@ class ProjectNote(GitlabObject): requiredCreateAttrs = ['body'] +class ProjectNoteManager(BaseManager): + obj_cls = ProjectNote + + class ProjectTag(GitlabObject): _url = '/projects/%(project_id)s/repository/tags' idAttr = 'name' @@ -524,6 +644,10 @@ class ProjectTag(GitlabObject): shortPrintAttr = 'name' +class ProjectTagManager(BaseManager): + obj_cls = ProjectTag + + class ProjectMergeRequestNote(GitlabObject): _url = '/projects/%(project_id)s/merge_requests/%(merge_request_id)s/notes' _constructorTypes = {'author': 'User'} @@ -532,6 +656,10 @@ class ProjectMergeRequestNote(GitlabObject): requiredCreateAttrs = ['body'] +class ProjectMergeRequestNoteManager(BaseManager): + obj_cls = ProjectMergeRequestNote + + class ProjectMergeRequest(GitlabObject): _url = '/projects/%(project_id)s/merge_request' _urlPlural = '/projects/%(project_id)s/merge_requests' @@ -540,13 +668,21 @@ class ProjectMergeRequest(GitlabObject): requiredUrlAttrs = ['project_id'] requiredCreateAttrs = ['source_branch', 'target_branch', 'title'] optionalCreateAttrs = ['assignee_id'] + managers = [('notes', ProjectMergeRequestNoteManager, + [('project_id', 'project_id'), ('merge_request_id', 'id')])] def Note(self, id=None, **kwargs): + warnings.warn("`Note` is deprecated, use `notes` instead", + DeprecationWarning) return ProjectMergeRequestNote._get_list_or_object( self.gitlab, id, project_id=self.project_id, merge_request_id=self.id, **kwargs) +class ProjectMergeRequestManager(BaseManager): + obj_cls = ProjectMergeRequest + + class ProjectMilestone(GitlabObject): _url = '/projects/%(project_id)s/milestones' canDelete = False @@ -556,6 +692,10 @@ class ProjectMilestone(GitlabObject): shortPrintAttr = 'title' +class ProjectMilestoneManager(BaseManager): + obj_cls = ProjectMilestone + + class ProjectLabel(GitlabObject): _url = '/projects/%(project_id)s/labels' requiredUrlAttrs = ['project_id'] @@ -567,6 +707,10 @@ class ProjectLabel(GitlabObject): optionalCreateAttrs = ['new_name'] +class ProjectLabelManager(BaseManager): + obj_cls = ProjectLabel + + class ProjectFile(GitlabObject): _url = '/projects/%(project_id)s/repository/files' canList = False @@ -581,6 +725,10 @@ class ProjectFile(GitlabObject): getRequiresId = False +class ProjectFileManager(BaseManager): + obj_cls = ProjectFile + + class ProjectSnippetNote(GitlabObject): _url = '/projects/%(project_id)s/snippets/%(snippet_id)s/notes' _constructorTypes = {'author': 'User'} @@ -590,6 +738,10 @@ class ProjectSnippetNote(GitlabObject): requiredCreateAttrs = ['body'] +class ProjectSnippetNoteManager(BaseManager): + obj_cls = ProjectSnippetNote + + class ProjectSnippet(GitlabObject): _url = '/projects/%(project_id)s/snippets' _constructorTypes = {'author': 'User'} @@ -597,6 +749,8 @@ class ProjectSnippet(GitlabObject): requiredCreateAttrs = ['title', 'file_name', 'code'] optionalCreateAttrs = ['lifetime'] shortPrintAttr = 'title' + managers = [('notes', ProjectSnippetNoteManager, + [('project_id', 'project_id'), ('snippet_id', 'id')])] def Content(self, **kwargs): url = ("/projects/%(project_id)s/snippets/%(snippet_id)s/raw" % @@ -606,6 +760,8 @@ class ProjectSnippet(GitlabObject): return r.content def Note(self, id=None, **kwargs): + warnings.warn("`Note` is deprecated, use `notes` instead", + DeprecationWarning) return ProjectSnippetNote._get_list_or_object( self.gitlab, id, project_id=self.project_id, @@ -613,19 +769,8 @@ class ProjectSnippet(GitlabObject): **kwargs) -class UserProject(GitlabObject): - _url = '/projects/user/%(user_id)s' - _constructorTypes = {'owner': 'User', 'namespace': 'Group'} - canUpdate = False - canDelete = False - canList = False - canGet = False - requiredUrlAttrs = ['user_id'] - requiredCreateAttrs = ['name'] - optionalCreateAttrs = ['default_branch', 'issues_enabled', 'wall_enabled', - 'merge_requests_enabled', 'wiki_enabled', - 'snippets_enabled', 'public', 'visibility_level', - 'description'] +class ProjectSnippetManager(BaseManager): + obj_cls = ProjectSnippet class Project(GitlabObject): @@ -637,75 +782,119 @@ class Project(GitlabObject): 'merge_requests_enabled', 'wiki_enabled', 'snippets_enabled', 'public', 'visibility_level', 'namespace_id', 'description', 'path', 'import_url'] - shortPrintAttr = 'path' + managers = [ + ('branches', ProjectBranchManager, [('project_id', 'id')]), + ('commits', ProjectCommitManager, [('project_id', 'id')]), + ('events', ProjectEventManager, [('project_id', 'id')]), + ('files', ProjectFileManager, [('project_id', 'id')]), + ('hooks', ProjectHookManager, [('project_id', 'id')]), + ('keys', ProjectKeyManager, [('project_id', 'id')]), + ('issues', ProjectIssueManager, [('project_id', 'id')]), + ('labels', ProjectLabelManager, [('project_id', 'id')]), + ('members', ProjectMemberManager, [('project_id', 'id')]), + ('mergerequests', ProjectMergeRequestManager, [('project_id', 'id')]), + ('milestones', ProjectMilestoneManager, [('project_id', 'id')]), + ('notes', ProjectNoteManager, [('project_id', 'id')]), + ('snippets', ProjectSnippetManager, [('project_id', 'id')]), + ('tags', ProjectTagManager, [('project_id', 'id')]), + ] def Branch(self, id=None, **kwargs): + warnings.warn("`Branch` is deprecated, use `branches` instead", + DeprecationWarning) return ProjectBranch._get_list_or_object(self.gitlab, id, project_id=self.id, **kwargs) def Commit(self, id=None, **kwargs): + warnings.warn("`Commit` is deprecated, use `commits` instead", + DeprecationWarning) return ProjectCommit._get_list_or_object(self.gitlab, id, project_id=self.id, **kwargs) def Event(self, id=None, **kwargs): + warnings.warn("`Event` is deprecated, use `events` instead", + DeprecationWarning) return ProjectEvent._get_list_or_object(self.gitlab, id, project_id=self.id, **kwargs) + def File(self, id=None, **kwargs): + warnings.warn("`File` is deprecated, use `files` instead", + DeprecationWarning) + return ProjectFile._get_list_or_object(self.gitlab, id, + project_id=self.id, + **kwargs) + def Hook(self, id=None, **kwargs): + warnings.warn("`Hook` is deprecated, use `hooks` instead", + DeprecationWarning) return ProjectHook._get_list_or_object(self.gitlab, id, project_id=self.id, **kwargs) def Key(self, id=None, **kwargs): + warnings.warn("`Key` is deprecated, use `keys` instead", + DeprecationWarning) return ProjectKey._get_list_or_object(self.gitlab, id, project_id=self.id, **kwargs) def Issue(self, id=None, **kwargs): + warnings.warn("`Issue` is deprecated, use `issues` instead", + DeprecationWarning) return ProjectIssue._get_list_or_object(self.gitlab, id, project_id=self.id, **kwargs) + def Label(self, id=None, **kwargs): + warnings.warn("`Label` is deprecated, use `labels` instead", + DeprecationWarning) + return ProjectLabel._get_list_or_object(self.gitlab, id, + project_id=self.id, + **kwargs) + def Member(self, id=None, **kwargs): + warnings.warn("`Member` is deprecated, use `members` instead", + DeprecationWarning) return ProjectMember._get_list_or_object(self.gitlab, id, project_id=self.id, **kwargs) def MergeRequest(self, id=None, **kwargs): + warnings.warn( + "`MergeRequest` is deprecated, use `mergerequests` instead", + DeprecationWarning) return ProjectMergeRequest._get_list_or_object(self.gitlab, id, project_id=self.id, **kwargs) def Milestone(self, id=None, **kwargs): + warnings.warn("`Milestone` is deprecated, use `milestones` instead", + DeprecationWarning) return ProjectMilestone._get_list_or_object(self.gitlab, id, project_id=self.id, **kwargs) def Note(self, id=None, **kwargs): + warnings.warn("`Note` is deprecated, use `notes` instead", + DeprecationWarning) return ProjectNote._get_list_or_object(self.gitlab, id, project_id=self.id, **kwargs) def Snippet(self, id=None, **kwargs): + warnings.warn("`Snippet` is deprecated, use `snippets` instead", + DeprecationWarning) return ProjectSnippet._get_list_or_object(self.gitlab, id, project_id=self.id, **kwargs) - def Label(self, id=None, **kwargs): - return ProjectLabel._get_list_or_object(self.gitlab, id, - project_id=self.id, - **kwargs) - - def File(self, id=None, **kwargs): - return ProjectFile._get_list_or_object(self.gitlab, id, - project_id=self.id, - **kwargs) - def Tag(self, id=None, **kwargs): + warnings.warn("`Tag` is deprecated, use `tags` instead", + DeprecationWarning) return ProjectTag._get_list_or_object(self.gitlab, id, project_id=self.id, **kwargs) @@ -775,6 +964,33 @@ class TeamMember(GitlabObject): shortPrintAttr = 'username' +class UserProject(GitlabObject): + _url = '/projects/user/%(user_id)s' + _constructorTypes = {'owner': 'User', 'namespace': 'Group'} + canUpdate = False + canDelete = False + canList = False + canGet = False + requiredUrlAttrs = ['user_id'] + requiredCreateAttrs = ['name'] + optionalCreateAttrs = ['default_branch', 'issues_enabled', 'wall_enabled', + 'merge_requests_enabled', 'wiki_enabled', + 'snippets_enabled', 'public', 'visibility_level', + 'description'] + + +class ProjectManager(BaseManager): + obj_cls = Project + + +class UserProjectManager(BaseManager): + obj_cls = UserProject + + +class TeamMemberManager(BaseManager): + obj_cls = TeamMember + + class TeamProject(GitlabObject): _url = '/user_teams/%(team_id)s/projects' _constructorTypes = {'owner': 'User', 'namespace': 'Group'} @@ -784,18 +1000,34 @@ class TeamProject(GitlabObject): shortPrintAttr = 'name' +class TeamProjectManager(BaseManager): + obj_cls = TeamProject + + class Team(GitlabObject): _url = '/user_teams' shortPrintAttr = 'name' requiredCreateAttrs = ['name', 'path'] canUpdate = False + managers = [ + ('members', TeamMemberManager, [('team_id', 'id')]), + ('projects', TeamProjectManager, [('team_id', 'id')]) + ] def Member(self, id=None, **kwargs): + warnings.warn("`Member` is deprecated, use `members` instead", + DeprecationWarning) return TeamMember._get_list_or_object(self.gitlab, id, team_id=self.id, **kwargs) def Project(self, id=None, **kwargs): + warnings.warn("`Project` is deprecated, use `projects` instead", + DeprecationWarning) return TeamProject._get_list_or_object(self.gitlab, id, team_id=self.id, **kwargs) + + +class TeamManager(BaseManager): + obj_cls = Team |