| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 455a8fc commit 1940fee
6 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -235,6 +235,12 @@ Use sudo to act as another user (admin only): | |||
| 235 | 235 | ||
| 236 | 236 | $ gitlab project create --name user_project1 --sudo username | |
| 237 | 237 | ||
| 238 | + List values are comma-separated: | ||
| 239 | + | ||
| 240 | + .. code-block:: console | ||
| 241 | + | ||
| 242 | + $ gitlab issue list --labels foo,bar | ||
| 243 | + | ||
| 238 | 244 | Reading values from files | |
| 239 | 245 | ------------------------- | |
| 240 | 246 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -108,9 +108,21 @@ def list(self, **kwargs): | |||
| 108 | 108 | GitlabListError: If the server cannot perform the request | |
| 109 | 109 | """ | |
| 110 | 110 | ||
| 111 | + # Duplicate data to avoid messing with what the user sent us | ||
| 112 | + data = kwargs.copy() | ||
| 113 | + | ||
| 114 | + # We get the attributes that need some special transformation | ||
| 115 | + types = getattr(self, '_types', {}) | ||
| 116 | + if types: | ||
| 117 | + for attr_name, type_cls in types.items(): | ||
| 118 | + if attr_name in data.keys(): | ||
| 119 | + type_obj = type_cls(data[attr_name]) | ||
| 120 | + data[attr_name] = type_obj.get_for_api() | ||
| 121 | + | ||
| 111 | 122 | # Allow to overwrite the path, handy for custom listings | |
| 112 | - path = kwargs.pop('path', self.path) | ||
| 113 | - obj = self.gitlab.http_list(path, **kwargs) | ||
| 123 | + path = data.pop('path', self.path) | ||
| 124 | + | ||
| 125 | + obj = self.gitlab.http_list(path, **data) | ||
| 114 | 126 | if isinstance(obj, list): | |
| 115 | 127 | return [self._obj_cls(self, item) for item in obj] | |
| 116 | 128 | else: | |
@@ -187,8 +199,22 @@ def create(self, data, **kwargs): | |||
| 187 | 199 | GitlabCreateError: If the server cannot perform the request | |
| 188 | 200 | """ | |
| 189 | 201 | self._check_missing_create_attrs(data) | |
| 202 | + | ||
| 203 | + # special handling of the object if needed | ||
| 190 | 204 | if hasattr(self, '_sanitize_data'): | |
| 191 | 205 | data = self._sanitize_data(data, 'create') | |
| 206 | + | ||
| 207 | + # We get the attributes that need some special transformation | ||
| 208 | + types = getattr(self, '_types', {}) | ||
| 209 | + | ||
| 210 | + if types: | ||
| 211 | + # Duplicate data to avoid messing with what the user sent us | ||
| 212 | + data = data.copy() | ||
| 213 | + for attr_name, type_cls in types.items(): | ||
| 214 | + if attr_name in data.keys(): | ||
| 215 | + type_obj = type_cls(data[attr_name]) | ||
| 216 | + data[attr_name] = type_obj.get_for_api() | ||
| 217 | + | ||
| 192 | 218 | # Handle specific URL for creation | |
| 193 | 219 | path = kwargs.pop('path', self.path) | |
| 194 | 220 | server_data = self.gitlab.http_post(path, post_data=data, **kwargs) | |
@@ -238,11 +264,20 @@ def update(self, id=None, new_data={}, **kwargs): | |||
| 238 | 264 | path = '%s/%s' % (self.path, id) | |
| 239 | 265 | ||
| 240 | 266 | self._check_missing_update_attrs(new_data) | |
| 267 | + | ||
| 268 | + # special handling of the object if needed | ||
| 241 | 269 | if hasattr(self, '_sanitize_data'): | |
| 242 | 270 | data = self._sanitize_data(new_data, 'update') | |
| 243 | 271 | else: | |
| 244 | 272 | data = new_data | |
| 245 | 273 | ||
| 274 | + # We get the attributes that need some special transformation | ||
| 275 | + types = getattr(self, '_types', {}) | ||
| 276 | + for attr_name, type_cls in types.items(): | ||
| 277 | + if attr_name in data.keys(): | ||
| 278 | + type_obj = type_cls(data[attr_name]) | ||
| 279 | + data[attr_name] = type_obj.get_for_api() | ||
| 280 | + | ||
| 246 | 281 | return self.gitlab.http_put(path, post_data=data, **kwargs) | |
| 247 | 282 | ||
| 248 | 283 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,66 @@ | |||
| 1 | + # -*- coding: utf-8 -*- | ||
| 2 | + # | ||
| 3 | + # Copyright (C) 2018 Gauvain Pocentek <gauvain@pocentek.net> | ||
| 4 | + # | ||
| 5 | + # This program is free software: you can redistribute it and/or modify | ||
| 6 | + # it under the terms of the GNU Lesser General Public License as published by | ||
| 7 | + # the Free Software Foundation, either version 3 of the License, or | ||
| 8 | + # (at your option) any later version. | ||
| 9 | + # | ||
| 10 | + # This program is distributed in the hope that it will be useful, | ||
| 11 | + # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | + # GNU Lesser General Public License for more details. | ||
| 14 | + # | ||
| 15 | + # You should have received a copy of the GNU Lesser General Public License | ||
| 16 | + # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 17 | + | ||
| 18 | + try: | ||
| 19 | + import unittest | ||
| 20 | + except ImportError: | ||
| 21 | + import unittest2 as unittest | ||
| 22 | + | ||
| 23 | + from gitlab import types | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + class TestGitlabAttribute(unittest.TestCase): | ||
| 27 | + def test_all(self): | ||
| 28 | + o = types.GitlabAttribute('whatever') | ||
| 29 | + self.assertEqual('whatever', o.get()) | ||
| 30 | + | ||
| 31 | + o.set_from_cli('whatever2') | ||
| 32 | + self.assertEqual('whatever2', o.get()) | ||
| 33 | + | ||
| 34 | + self.assertEqual('whatever2', o.get_for_api()) | ||
| 35 | + | ||
| 36 | + o = types.GitlabAttribute() | ||
| 37 | + self.assertEqual(None, o._value) | ||
| 38 | + | ||
| 39 | + | ||
| 40 | + class TestListAttribute(unittest.TestCase): | ||
| 41 | + def test_list_input(self): | ||
| 42 | + o = types.ListAttribute() | ||
| 43 | + o.set_from_cli('foo,bar,baz') | ||
| 44 | + self.assertEqual(['foo', 'bar', 'baz'], o.get()) | ||
| 45 | + | ||
| 46 | + o.set_from_cli('foo') | ||
| 47 | + self.assertEqual(['foo'], o.get()) | ||
| 48 | + | ||
| 49 | + def test_empty_input(self): | ||
| 50 | + o = types.ListAttribute() | ||
| 51 | + o.set_from_cli('') | ||
| 52 | + self.assertEqual([], o.get()) | ||
| 53 | + | ||
| 54 | + o.set_from_cli(' ') | ||
| 55 | + self.assertEqual([], o.get()) | ||
| 56 | + | ||
| 57 | + def test_get_for_api(self): | ||
| 58 | + o = types.ListAttribute() | ||
| 59 | + o.set_from_cli('foo,bar,baz') | ||
| 60 | + self.assertEqual('foo,bar,baz', o.get_for_api()) | ||
| 61 | + | ||
| 62 | + | ||
| 63 | + class TestLowercaseStringAttribute(unittest.TestCase): | ||
| 64 | + def test_get_for_api(self): | ||
| 65 | + o = types.LowercaseStringAttribute('FOO') | ||
| 66 | + self.assertEqual('foo', o.get_for_api()) | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,46 @@ | |||
| 1 | + # -*- coding: utf-8 -*- | ||
| 2 | + # | ||
| 3 | + # Copyright (C) 2018 Gauvain Pocentek <gauvain@pocentek.net> | ||
| 4 | + # | ||
| 5 | + # This program is free software: you can redistribute it and/or modify | ||
| 6 | + # it under the terms of the GNU Lesser General Public License as published by | ||
| 7 | + # the Free Software Foundation, either version 3 of the License, or | ||
| 8 | + # (at your option) any later version. | ||
| 9 | + # | ||
| 10 | + # This program is distributed in the hope that it will be useful, | ||
| 11 | + # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | + # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | + # GNU Lesser General Public License for more details. | ||
| 14 | + # | ||
| 15 | + # You should have received a copy of the GNU Lesser General Public License | ||
| 16 | + # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + class GitlabAttribute(object): | ||
| 20 | + def __init__(self, value=None): | ||
| 21 | + self._value = value | ||
| 22 | + | ||
| 23 | + def get(self): | ||
| 24 | + return self._value | ||
| 25 | + | ||
| 26 | + def set_from_cli(self, cli_value): | ||
| 27 | + self._value = cli_value | ||
| 28 | + | ||
| 29 | + def get_for_api(self): | ||
| 30 | + return self._value | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + class ListAttribute(GitlabAttribute): | ||
| 34 | + def set_from_cli(self, cli_value): | ||
| 35 | + if not cli_value.strip(): | ||
| 36 | + self._value = [] | ||
| 37 | + else: | ||
| 38 | + self._value = [item.strip() for item in cli_value.split(',')] | ||
| 39 | + | ||
| 40 | + def get_for_api(self): | ||
| 41 | + return ",".join(self._value) | ||
| 42 | + | ||
| 43 | + | ||
| 44 | + class LowercaseStringAttribute(GitlabAttribute): | ||
| 45 | + def get_for_api(self): | ||
| 46 | + return str(self._value).lower() | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -45,6 +45,14 @@ def __init__(self, gl, what, action, args): | |||
| 45 | 45 | self.mgr_cls._path = self.mgr_cls._path % self.args | |
| 46 | 46 | self.mgr = self.mgr_cls(gl) | |
| 47 | 47 | ||
| 48 | + types = getattr(self.mgr_cls, '_types', {}) | ||
| 49 | + if types: | ||
| 50 | + for attr_name, type_cls in types.items(): | ||
| 51 | + if attr_name in self.args.keys(): | ||
| 52 | + obj = type_cls() | ||
| 53 | + obj.set_from_cli(self.args[attr_name]) | ||
| 54 | + self.args[attr_name] = obj.get() | ||
| 55 | + | ||
| 48 | 56 | def __call__(self): | |
| 49 | 57 | method = 'do_%s' % self.action | |
| 50 | 58 | if hasattr(self, method): | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -23,6 +23,7 @@ | |||
| 23 | 23 | from gitlab import cli | |
| 24 | 24 | from gitlab.exceptions import * # noqa | |
| 25 | 25 | from gitlab.mixins import * # noqa | |
| 26 | + from gitlab import types | ||
| 26 | 27 | from gitlab import utils | |
| 27 | 28 | ||
| 28 | 29 | VISIBILITY_PRIVATE = 'private' | |
@@ -315,12 +316,7 @@ class UserManager(CRUDMixin, RESTManager): | |||
| 315 | 316 | 'website_url', 'skip_confirmation', 'external', 'organization', | |
| 316 | 317 | 'location') | |
| 317 | 318 | ) | |
| 318 | - | ||
| 319 | - def _sanitize_data(self, data, action): | ||
| 320 | - new_data = data.copy() | ||
| 321 | - if 'confirm' in data: | ||
| 322 | - new_data['confirm'] = str(new_data['confirm']).lower() | ||
| 323 | - return new_data | ||
| 319 | + _types = {'confirm': types.LowercaseStringAttribute} | ||
| 324 | 320 | ||
| 325 | 321 | ||
| 326 | 322 | class CurrentUserEmail(ObjectDeleteMixin, RESTObject): | |
@@ -528,6 +524,7 @@ class GroupIssueManager(GetFromListMixin, RESTManager): | |||
| 528 | 524 | _obj_cls = GroupIssue | |
| 529 | 525 | _from_parent_attrs = {'group_id': 'id'} | |
| 530 | 526 | _list_filters = ('state', 'labels', 'milestone', 'order_by', 'sort') | |
| 527 | + _types = {'labels': types.ListAttribute} | ||
| 531 | 528 | ||
| 532 | 529 | ||
| 533 | 530 | class GroupMember(SaveMixin, ObjectDeleteMixin, RESTObject): | |
@@ -736,6 +733,7 @@ class IssueManager(GetFromListMixin, RESTManager): | |||
| 736 | 733 | _path = '/issues' | |
| 737 | 734 | _obj_cls = Issue | |
| 738 | 735 | _list_filters = ('state', 'labels', 'order_by', 'sort') | |
| 736 | + _types = {'labels': types.ListAttribute} | ||
| 739 | 737 | ||
| 740 | 738 | ||
| 741 | 739 | class License(RESTObject): | |
@@ -1346,12 +1344,7 @@ class ProjectIssueManager(CRUDMixin, RESTManager): | |||
| 1346 | 1344 | _update_attrs = (tuple(), ('title', 'description', 'assignee_id', | |
| 1347 | 1345 | 'milestone_id', 'labels', 'created_at', | |
| 1348 | 1346 | 'updated_at', 'state_event', 'due_date')) | |
| 1349 | - | ||
| 1350 | - def _sanitize_data(self, data, action): | ||
| 1351 | - new_data = data.copy() | ||
| 1352 | - if 'labels' in data: | ||
| 1353 | - new_data['labels'] = ','.join(data['labels']) | ||
| 1354 | - return new_data | ||
| 1347 | + _types = {'labels': types.ListAttribute} | ||
| 1355 | 1348 | ||
| 1356 | 1349 | ||
| 1357 | 1350 | class ProjectMember(SaveMixin, ObjectDeleteMixin, RESTObject): | |
@@ -1669,12 +1662,7 @@ class ProjectMergeRequestManager(CRUDMixin, RESTManager): | |||
| 1669 | 1662 | 'description', 'state_event', 'labels', | |
| 1670 | 1663 | 'milestone_id')) | |
| 1671 | 1664 | _list_filters = ('iids', 'state', 'order_by', 'sort') | |
| 1672 | - | ||
| 1673 | - def _sanitize_data(self, data, action): | ||
| 1674 | - new_data = data.copy() | ||
| 1675 | - if 'labels' in data: | ||
| 1676 | - new_data['labels'] = ','.join(data['labels']) | ||
| 1677 | - return new_data | ||
| 1665 | + _types = {'labels': types.ListAttribute} | ||
| 1678 | 1666 | ||
| 1679 | 1667 | ||
| 1680 | 1668 | class ProjectMilestone(SaveMixin, ObjectDeleteMixin, RESTObject): | |
| Back | FazBrowse Home | New Git URL |
0 commit comments