diff options
author | Gauvain Pocentek <gauvain@pocentek.net> | 2017-05-28 10:53:54 +0200 |
---|---|---|
committer | Gauvain Pocentek <gauvain@pocentek.net> | 2017-06-02 15:41:37 +0200 |
commit | a50690288f9c03ec37ff374839d1f465c74ecf0a (patch) | |
tree | 35f9e07f1c36cd50bcc4bcf791a1294bb50c2028 | |
parent | 9fbdb9461a660181a3a268cd398865cafd0b4a89 (diff) | |
download | gitlab-a50690288f9c03ec37ff374839d1f465c74ecf0a.tar.gz |
Add support for managers in objects for new API
Convert User* to the new REST* API.
-rw-r--r-- | gitlab/base.py | 33 | ||||
-rw-r--r-- | gitlab/mixins.py | 14 | ||||
-rw-r--r-- | gitlab/v4/objects.py | 160 |
3 files changed, 119 insertions, 88 deletions
diff --git a/gitlab/base.py b/gitlab/base.py index 2ecf1d2..afbcd38 100644 --- a/gitlab/base.py +++ b/gitlab/base.py @@ -575,8 +575,14 @@ class RESTObject(object): 'manager': manager, '_attrs': attrs, '_updated_attrs': {}, + '_module': importlib.import_module(self.__module__) }) + # TODO(gpocentek): manage the creation of new objects from the received + # data (_constructor_types) + + self._create_managers() + def __getattr__(self, name): try: return self.__dict__['_updated_attrs'][name] @@ -602,6 +608,16 @@ class RESTObject(object): else: return '<%s>' % self.__class__.__name__ + def _create_managers(self): + managers = getattr(self, '_managers', None) + if managers is None: + return + + for attr, cls_name in self._managers: + cls = getattr(self._module, cls_name) + manager = cls(self.manager.gitlab, parent=self) + self.__dict__[attr] = manager + def get_id(self): if self._id_attr is None: return None @@ -653,6 +669,19 @@ class RESTManager(object): _path = None _obj_cls = None - def __init__(self, gl, parent_attrs={}): + def __init__(self, gl, parent=None): self.gitlab = gl - self._parent_attrs = {} # for nested managers + self._parent = parent # for nested managers + self._computed_path = self._compute_path() + + def _compute_path(self): + if self._parent is None or not hasattr(self, '_from_parent_attrs'): + return self._path + + data = {self_attr: getattr(self._parent, parent_attr) + for self_attr, parent_attr in self._from_parent_attrs.items()} + return self._path % data + + @property + def path(self): + return self._computed_path diff --git a/gitlab/mixins.py b/gitlab/mixins.py index a81b2ae..80ce6c9 100644 --- a/gitlab/mixins.py +++ b/gitlab/mixins.py @@ -32,7 +32,7 @@ class GetMixin(object): Raises: GitlabGetError: If the server cannot perform the request. """ - path = '%s/%s' % (self._path, id) + path = '%s/%s' % (self.path, id) server_data = self.gitlab.http_get(path, **kwargs) return self._obj_cls(self, server_data) @@ -50,7 +50,7 @@ class GetWithoutIdMixin(object): Raises: GitlabGetError: If the server cannot perform the request. """ - server_data = self.gitlab.http_get(self._path, **kwargs) + server_data = self.gitlab.http_get(self.path, **kwargs) return self._obj_cls(self, server_data) @@ -70,7 +70,7 @@ class ListMixin(object): list(RESTObjectList). """ - obj = self.gitlab.http_list(self._path, **kwargs) + obj = self.gitlab.http_list(self.path, **kwargs) if isinstance(obj, list): return [self._obj_cls(self, item) for item in obj] else: @@ -139,7 +139,7 @@ class CreateMixin(object): self._check_missing_attrs(data) if hasattr(self, '_sanitize_data'): data = self._sanitize_data(data, 'create') - server_data = self.gitlab.http_post(self._path, post_data=data, + server_data = self.gitlab.http_post(self.path, post_data=data, **kwargs) return self._obj_cls(self, server_data) @@ -180,9 +180,9 @@ class UpdateMixin(object): """ if id is None: - path = self._path + path = self.path else: - path = '%s/%s' % (self._path, id) + path = '%s/%s' % (self.path, id) self._check_missing_attrs(new_data) if hasattr(self, '_sanitize_data'): @@ -199,7 +199,7 @@ class DeleteMixin(object): id: ID of the object to delete **kwargs: Extra data to send to the Gitlab server (e.g. sudo) """ - path = '%s/%s' % (self._path, id) + path = '%s/%s' % (self.path, id) self.gitlab.http_delete(path, **kwargs) diff --git a/gitlab/v4/objects.py b/gitlab/v4/objects.py index 9f16a50..34100d8 100644 --- a/gitlab/v4/objects.py +++ b/gitlab/v4/objects.py @@ -77,105 +77,107 @@ class SidekiqManager(RESTManager): return self._simple_get('/sidekiq/compound_metrics', **kwargs) -class UserEmail(GitlabObject): - _url = '/users/%(user_id)s/emails' - canUpdate = False - shortPrintAttr = 'email' - requiredUrlAttrs = ['user_id'] - requiredCreateAttrs = ['email'] +class UserEmail(RESTObject): + _short_print_attr = 'email' -class UserEmailManager(BaseManager): - obj_cls = UserEmail +class UserEmailManager(RetrieveMixin, CreateMixin, DeleteMixin, RESTManager): + _path = '/users/%(user_id)s/emails' + _obj_cls = UserEmail + _from_parent_attrs = {'user_id': 'id'} + _create_attrs = {'required': ('email', ), 'optional': tuple()} -class UserKey(GitlabObject): - _url = '/users/%(user_id)s/keys' - canGet = 'from_list' - canUpdate = False - requiredUrlAttrs = ['user_id'] - requiredCreateAttrs = ['title', 'key'] +class UserKey(RESTObject): + pass -class UserKeyManager(BaseManager): - obj_cls = UserKey +class UserKeyManager(GetFromListMixin, CreateMixin, DeleteMixin, RESTManager): + _path = '/users/%(user_id)s/emails' + _obj_cls = UserKey + _from_parent_attrs = {'user_id': 'id'} + _create_attrs = {'required': ('title', 'key'), 'optional': tuple()} -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', - 'description', 'builds_enabled', 'public_builds', - 'import_url', 'only_allow_merge_if_build_succeeds'] +class UserProject(RESTObject): + _constructor_types = {'owner': 'User', 'namespace': 'Group'} -class UserProjectManager(BaseManager): - obj_cls = UserProject +class UserProjectManager(CreateMixin, RESTManager): + _path = '/projects/user/%(user_id)s' + _obj_cls = UserProject + _from_parent_attrs = {'user_id': 'id'} + _create_attrs = { + 'required': ('name', ), + 'optional': ('default_branch', 'issues_enabled', 'wall_enabled', + 'merge_requests_enabled', 'wiki_enabled', + 'snippets_enabled', 'public', 'visibility', 'description', + 'builds_enabled', 'public_builds', 'import_url', + 'only_allow_merge_if_build_succeeds') + } -class User(GitlabObject): - _url = '/users' - shortPrintAttr = 'username' - optionalListAttrs = ['active', 'blocked', 'username', 'extern_uid', - 'provider', 'external'] - requiredCreateAttrs = ['email', 'username', 'name'] - optionalCreateAttrs = ['password', 'reset_password', 'skype', 'linkedin', - 'twitter', 'projects_limit', 'extern_uid', - 'provider', 'bio', 'admin', 'can_create_group', - 'website_url', 'skip_confirmation', 'external', - 'organization', 'location'] - requiredUpdateAttrs = ['email', 'username', 'name'] - optionalUpdateAttrs = ['password', 'skype', 'linkedin', 'twitter', - 'projects_limit', 'extern_uid', 'provider', 'bio', - 'admin', 'can_create_group', 'website_url', - 'skip_confirmation', 'external', 'organization', - 'location'] - managers = ( - ('emails', 'UserEmailManager', [('user_id', 'id')]), - ('keys', 'UserKeyManager', [('user_id', 'id')]), - ('projects', 'UserProjectManager', [('user_id', 'id')]), +class User(SaveMixin, RESTObject): + _short_print_attr = 'username' + _managers = ( + ('emails', 'UserEmailManager'), + ('keys', 'UserKeyManager'), + ('projects', 'UserProjectManager'), ) - def _data_for_gitlab(self, extra_parameters={}, update=False, - as_json=True): - if hasattr(self, 'confirm'): - self.confirm = str(self.confirm).lower() - return super(User, self)._data_for_gitlab(extra_parameters) - def block(self, **kwargs): - """Blocks the user.""" - url = '/users/%s/block' % self.id - r = self.gitlab._raw_post(url, **kwargs) - raise_error_from_response(r, GitlabBlockError, 201) - self.state = 'blocked' + """Blocks the user. + + Returns: + bool: whether the user status has been changed. + """ + path = '/users/%s/block' % self.id + server_data = self.manager.gitlab.http_post(path, **kwargs) + if server_data is True: + self._attrs['state'] = 'blocked' + return server_data def unblock(self, **kwargs): - """Unblocks the user.""" - url = '/users/%s/unblock' % self.id - r = self.gitlab._raw_post(url, **kwargs) - raise_error_from_response(r, GitlabUnblockError, 201) - self.state = 'active' + """Unblocks the user. + + Returns: + bool: whether the user status has been changed. + """ + path = '/users/%s/unblock' % self.id + server_data = self.manager.gitlab.http_post(path, **kwargs) + if server_data is True: + self._attrs['state'] = 'active' + return server_data - def __eq__(self, other): - if type(other) is type(self): - selfdict = self.as_dict() - otherdict = other.as_dict() - selfdict.pop('password', None) - otherdict.pop('password', None) - return selfdict == otherdict - return False +class UserManager(CRUDMixin, RESTManager): + _path = '/users' + _obj_cls = User -class UserManager(BaseManager): - obj_cls = User + _list_filters = ('active', 'blocked', 'username', 'extern_uid', 'provider', + 'external') + _create_attrs = { + 'required': ('email', 'username', 'name'), + 'optional': ('password', 'reset_password', 'skype', 'linkedin', + 'twitter', 'projects_limit', 'extern_uid', 'provider', + 'bio', 'admin', 'can_create_group', 'website_url', + 'skip_confirmation', 'external', 'organization', + 'location') + } + _update_attrs = { + 'required': ('email', 'username', 'name'), + 'optional': ('password', 'skype', 'linkedin', 'twitter', + 'projects_limit', 'extern_uid', 'provider', 'bio', + 'admin', 'can_create_group', 'website_url', + 'skip_confirmation', 'external', 'organization', + 'location') + } + + def _sanitize_data(self, data, action): + new_data = data.copy() + if 'confirm' in data: + new_data['confirm'] = str(new_data['confirm']).lower() + return new_data class CurrentUserEmail(GitlabObject): |