summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gitlab/cli.py105
-rw-r--r--gitlab/tests/test_cli.py37
-rw-r--r--gitlab/v3/cli.py257
3 files changed, 222 insertions, 177 deletions
diff --git a/gitlab/cli.py b/gitlab/cli.py
new file mode 100644
index 0000000..f23fff9
--- /dev/null
+++ b/gitlab/cli.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2013-2017 Gauvain Pocentek <gauvain@pocentek.net>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import print_function
+from __future__ import absolute_import
+import argparse
+import importlib
+import re
+import sys
+
+import gitlab.config
+
+camel_re = re.compile('(.)([A-Z])')
+
+
+def die(msg, e=None):
+ if e:
+ msg = "%s (%s)" % (msg, e)
+ sys.stderr.write(msg + "\n")
+ sys.exit(1)
+
+
+def what_to_cls(what):
+ return "".join([s.capitalize() for s in what.split("-")])
+
+
+def cls_to_what(cls):
+ return camel_re.sub(r'\1-\2', cls.__name__).lower()
+
+
+def _get_base_parser():
+ parser = argparse.ArgumentParser(
+ description="GitLab API Command Line Interface")
+ parser.add_argument("--version", help="Display the version.",
+ action="store_true")
+ parser.add_argument("-v", "--verbose", "--fancy",
+ help="Verbose mode",
+ action="store_true")
+ parser.add_argument("-c", "--config-file", action='append',
+ help=("Configuration file to use. Can be used "
+ "multiple times."))
+ parser.add_argument("-g", "--gitlab",
+ help=("Which configuration section should "
+ "be used. If not defined, the default selection "
+ "will be used."),
+ required=False)
+
+ return parser
+
+
+def _get_parser(cli_module):
+ parser = _get_base_parser()
+ return cli_module.extend_parser(parser)
+
+
+def main():
+ if "--version" in sys.argv:
+ print(gitlab.__version__)
+ exit(0)
+
+ parser = _get_base_parser()
+ (options, args) = parser.parse_known_args(sys.argv)
+
+ config = gitlab.config.GitlabConfigParser(options.gitlab,
+ options.config_file)
+ cli_module = importlib.import_module('gitlab.v%s.cli' % config.api_version)
+ parser = _get_parser(cli_module)
+ args = parser.parse_args(sys.argv[1:])
+ config_files = args.config_file
+ gitlab_id = args.gitlab
+ verbose = args.verbose
+ action = args.action
+ what = args.what
+
+ args = args.__dict__
+ # Remove CLI behavior-related args
+ for item in ('gitlab', 'config_file', 'verbose', 'what', 'action',
+ 'version'):
+ args.pop(item)
+ args = {k: v for k, v in args.items() if v is not None}
+
+ try:
+ gl = gitlab.Gitlab.from_config(gitlab_id, config_files)
+ gl.auth()
+ except Exception as e:
+ die(str(e))
+
+ cli_module.run(gl, what, action, args, verbose)
+
+ sys.exit(0)
diff --git a/gitlab/tests/test_cli.py b/gitlab/tests/test_cli.py
index 701655d..e6e290a 100644
--- a/gitlab/tests/test_cli.py
+++ b/gitlab/tests/test_cli.py
@@ -28,12 +28,13 @@ except ImportError:
import unittest2 as unittest
from gitlab import cli
+import gitlab.v3.cli
class TestCLI(unittest.TestCase):
def test_what_to_cls(self):
- self.assertEqual("Foo", cli._what_to_cls("foo"))
- self.assertEqual("FooBar", cli._what_to_cls("foo-bar"))
+ self.assertEqual("Foo", cli.what_to_cls("foo"))
+ self.assertEqual("FooBar", cli.what_to_cls("foo-bar"))
def test_cls_to_what(self):
class Class(object):
@@ -42,32 +43,33 @@ class TestCLI(unittest.TestCase):
class TestClass(object):
pass
- self.assertEqual("test-class", cli._cls_to_what(TestClass))
- self.assertEqual("class", cli._cls_to_what(Class))
+ self.assertEqual("test-class", cli.cls_to_what(TestClass))
+ self.assertEqual("class", cli.cls_to_what(Class))
def test_die(self):
with self.assertRaises(SystemExit) as test:
- cli._die("foobar")
+ cli.die("foobar")
self.assertEqual(test.exception.code, 1)
- def test_extra_actions(self):
- for cls, data in six.iteritems(cli.EXTRA_ACTIONS):
- for key in data:
- self.assertIsInstance(data[key], dict)
-
- def test_parsing(self):
- args = cli._parse_args(['-v', '-g', 'gl_id',
- '-c', 'foo.cfg', '-c', 'bar.cfg',
- 'project', 'list'])
+ def test_base_parser(self):
+ parser = cli._get_base_parser()
+ args = parser.parse_args(['-v', '-g', 'gl_id',
+ '-c', 'foo.cfg', '-c', 'bar.cfg'])
self.assertTrue(args.verbose)
self.assertEqual(args.gitlab, 'gl_id')
self.assertEqual(args.config_file, ['foo.cfg', 'bar.cfg'])
+
+
+class TestV3CLI(unittest.TestCase):
+ def test_parse_args(self):
+ parser = cli._get_parser(gitlab.v3.cli)
+ args = parser.parse_args(['project', 'list'])
self.assertEqual(args.what, 'project')
self.assertEqual(args.action, 'list')
def test_parser(self):
- parser = cli._build_parser()
+ parser = cli._get_parser(gitlab.v3.cli)
subparsers = None
for action in parser._actions:
if type(action) == argparse._SubParsersAction:
@@ -93,3 +95,8 @@ class TestCLI(unittest.TestCase):
actions = user_subparsers.choices['create']._option_string_actions
self.assertFalse(actions['--twitter'].required)
self.assertTrue(actions['--username'].required)
+
+ def test_extra_actions(self):
+ for cls, data in six.iteritems(gitlab.v3.cli.EXTRA_ACTIONS):
+ for key in data:
+ self.assertIsInstance(data[key], dict)
diff --git a/gitlab/v3/cli.py b/gitlab/v3/cli.py
index 142ccfa..b0450e8 100644
--- a/gitlab/v3/cli.py
+++ b/gitlab/v3/cli.py
@@ -18,145 +18,124 @@
from __future__ import print_function
from __future__ import absolute_import
-import argparse
import inspect
import operator
-import re
import sys
import six
import gitlab
+import gitlab.base
+from gitlab import cli
+import gitlab.v3.objects
-camel_re = re.compile('(.)([A-Z])')
EXTRA_ACTIONS = {
- gitlab.Group: {'search': {'required': ['query']}},
- gitlab.ProjectBranch: {'protect': {'required': ['id', 'project-id']},
- 'unprotect': {'required': ['id', 'project-id']}},
- gitlab.ProjectBuild: {'cancel': {'required': ['id', 'project-id']},
- 'retry': {'required': ['id', 'project-id']},
- 'artifacts': {'required': ['id', 'project-id']},
- 'trace': {'required': ['id', 'project-id']}},
- gitlab.ProjectCommit: {'diff': {'required': ['id', 'project-id']},
- 'blob': {'required': ['id', 'project-id',
- 'filepath']},
- 'builds': {'required': ['id', 'project-id']},
- 'cherrypick': {'required': ['id', 'project-id',
- 'branch']}},
- gitlab.ProjectIssue: {'subscribe': {'required': ['id', 'project-id']},
- 'unsubscribe': {'required': ['id', 'project-id']},
- 'move': {'required': ['id', 'project-id',
- 'to-project-id']}},
- gitlab.ProjectMergeRequest: {
+ gitlab.v3.objects.Group: {
+ 'search': {'required': ['query']}},
+ gitlab.v3.objects.ProjectBranch: {
+ 'protect': {'required': ['id', 'project-id']},
+ 'unprotect': {'required': ['id', 'project-id']}},
+ gitlab.v3.objects.ProjectBuild: {
+ 'cancel': {'required': ['id', 'project-id']},
+ 'retry': {'required': ['id', 'project-id']},
+ 'artifacts': {'required': ['id', 'project-id']},
+ 'trace': {'required': ['id', 'project-id']}},
+ gitlab.v3.objects.ProjectCommit: {
+ 'diff': {'required': ['id', 'project-id']},
+ 'blob': {'required': ['id', 'project-id', 'filepath']},
+ 'builds': {'required': ['id', 'project-id']},
+ 'cherrypick': {'required': ['id', 'project-id', 'branch']}},
+ gitlab.v3.objects.ProjectIssue: {
+ 'subscribe': {'required': ['id', 'project-id']},
+ 'unsubscribe': {'required': ['id', 'project-id']},
+ 'move': {'required': ['id', 'project-id', 'to-project-id']}},
+ gitlab.v3.objects.ProjectMergeRequest: {
'closes-issues': {'required': ['id', 'project-id']},
'cancel': {'required': ['id', 'project-id']},
'merge': {'required': ['id', 'project-id'],
'optional': ['merge-commit-message',
'should-remove-source-branch',
- 'merged-when-build-succeeds']}
- },
- gitlab.ProjectMilestone: {'issues': {'required': ['id', 'project-id']}},
- gitlab.Project: {'search': {'required': ['query']},
- 'owned': {},
- 'all': {'optional': [('all', bool)]},
- 'starred': {},
- 'star': {'required': ['id']},
- 'unstar': {'required': ['id']},
- 'archive': {'required': ['id']},
- 'unarchive': {'required': ['id']},
- 'share': {'required': ['id', 'group-id',
- 'group-access']}},
- gitlab.User: {'block': {'required': ['id']},
- 'unblock': {'required': ['id']},
- 'search': {'required': ['query']},
- 'get-by-username': {'required': ['query']}},
+ 'merged-when-build-succeeds']}},
+ gitlab.v3.objects.ProjectMilestone: {
+ 'issues': {'required': ['id', 'project-id']}},
+ gitlab.v3.objects.Project: {
+ 'search': {'required': ['query']},
+ 'owned': {},
+ 'all': {'optional': [('all', bool)]},
+ 'starred': {},
+ 'star': {'required': ['id']},
+ 'unstar': {'required': ['id']},
+ 'archive': {'required': ['id']},
+ 'unarchive': {'required': ['id']},
+ 'share': {'required': ['id', 'group-id', 'group-access']}},
+ gitlab.v3.objects.User: {
+ 'block': {'required': ['id']},
+ 'unblock': {'required': ['id']},
+ 'search': {'required': ['query']},
+ 'get-by-username': {'required': ['query']}},
}
-def _die(msg, e=None):
- if e:
- msg = "%s (%s)" % (msg, e)
- sys.stderr.write(msg + "\n")
- sys.exit(1)
-
-
-def _what_to_cls(what):
- return "".join([s.capitalize() for s in what.split("-")])
-
-
-def _cls_to_what(cls):
- return camel_re.sub(r'\1-\2', cls.__name__).lower()
-
-
-def do_auth(gitlab_id, config_files):
- try:
- gl = gitlab.Gitlab.from_config(gitlab_id, config_files)
- gl.auth()
- return gl
- except Exception as e:
- _die(str(e))
-
-
class GitlabCLI(object):
def _get_id(self, cls, args):
try:
id = args.pop(cls.idAttr)
except Exception:
- _die("Missing --%s argument" % cls.idAttr.replace('_', '-'))
+ cli.die("Missing --%s argument" % cls.idAttr.replace('_', '-'))
return id
def do_create(self, cls, gl, what, args):
if not cls.canCreate:
- _die("%s objects can't be created" % what)
+ cli.die("%s objects can't be created" % what)
try:
o = cls.create(gl, args)
except Exception as e:
- _die("Impossible to create object", e)
+ cli.die("Impossible to create object", e)
return o
def do_list(self, cls, gl, what, args):
if not cls.canList:
- _die("%s objects can't be listed" % what)
+ cli.die("%s objects can't be listed" % what)
try:
l = cls.list(gl, **args)
except Exception as e:
- _die("Impossible to list objects", e)
+ cli.die("Impossible to list objects", e)
return l
def do_get(self, cls, gl, what, args):
if cls.canGet is False:
- _die("%s objects can't be retrieved" % what)
+ cli.die("%s objects can't be retrieved" % what)
id = None
- if cls not in [gitlab.CurrentUser] and cls.getRequiresId:
+ if cls not in [gitlab.v3.objects.CurrentUser] and cls.getRequiresId:
id = self._get_id(cls, args)
try:
o = cls.get(gl, id, **args)
except Exception as e:
- _die("Impossible to get object", e)
+ cli.die("Impossible to get object", e)
return o
def do_delete(self, cls, gl, what, args):
if not cls.canDelete:
- _die("%s objects can't be deleted" % what)
+ cli.die("%s objects can't be deleted" % what)
id = args.pop(cls.idAttr)
try:
gl.delete(cls, id, **args)
except Exception as e:
- _die("Impossible to destroy object", e)
+ cli.die("Impossible to destroy object", e)
def do_update(self, cls, gl, what, args):
if not cls.canUpdate:
- _die("%s objects can't be updated" % what)
+ cli.die("%s objects can't be updated" % what)
o = self.do_get(cls, gl, what, args)
try:
@@ -164,7 +143,7 @@ class GitlabCLI(object):
o.__dict__[k] = v
o.save()
except Exception as e:
- _die("Impossible to update object", e)
+ cli.die("Impossible to update object", e)
return o
@@ -172,171 +151,171 @@ class GitlabCLI(object):
try:
return gl.groups.search(args['query'])
except Exception as e:
- _die("Impossible to search projects", e)
+ cli.die("Impossible to search projects", e)
def do_project_search(self, cls, gl, what, args):
try:
return gl.projects.search(args['query'])
except Exception as e:
- _die("Impossible to search projects", e)
+ cli.die("Impossible to search projects", e)
def do_project_all(self, cls, gl, what, args):
try:
return gl.projects.all(all=args.get('all', False))
except Exception as e:
- _die("Impossible to list all projects", e)
+ cli.die("Impossible to list all projects", e)
def do_project_starred(self, cls, gl, what, args):
try:
return gl.projects.starred()
except Exception as e:
- _die("Impossible to list starred projects", e)
+ cli.die("Impossible to list starred projects", e)
def do_project_owned(self, cls, gl, what, args):
try:
return gl.projects.owned()
except Exception as e:
- _die("Impossible to list owned projects", e)
+ cli.die("Impossible to list owned projects", e)
def do_project_star(self, cls, gl, what, args):
try:
o = self.do_get(cls, gl, what, args)
o.star()
except Exception as e:
- _die("Impossible to star project", e)
+ cli.die("Impossible to star project", e)
def do_project_unstar(self, cls, gl, what, args):
try:
o = self.do_get(cls, gl, what, args)
o.unstar()
except Exception as e:
- _die("Impossible to unstar project", e)
+ cli.die("Impossible to unstar project", e)
def do_project_archive(self, cls, gl, what, args):
try:
o = self.do_get(cls, gl, what, args)
o.archive_()
except Exception as e:
- _die("Impossible to archive project", e)
+ cli.die("Impossible to archive project", e)
def do_project_unarchive(self, cls, gl, what, args):
try:
o = self.do_get(cls, gl, what, args)
o.unarchive_()
except Exception as e:
- _die("Impossible to unarchive project", e)
+ cli.die("Impossible to unarchive project", e)
def do_project_share(self, cls, gl, what, args):
try:
o = self.do_get(cls, gl, what, args)
o.share(args['group_id'], args['group_access'])
except Exception as e:
- _die("Impossible to share project", e)
+ cli.die("Impossible to share project", e)
def do_user_block(self, cls, gl, what, args):
try:
o = self.do_get(cls, gl, what, args)
o.block()
except Exception as e:
- _die("Impossible to block user", e)
+ cli.die("Impossible to block user", e)
def do_user_unblock(self, cls, gl, what, args):
try:
o = self.do_get(cls, gl, what, args)
o.unblock()
except Exception as e:
- _die("Impossible to block user", e)
+ cli.die("Impossible to block user", e)
def do_project_commit_diff(self, cls, gl, what, args):
try:
o = self.do_get(cls, gl, what, args)
return [x['diff'] for x in o.diff()]
except Exception as e:
- _die("Impossible to get commit diff", e)
+ cli.die("Impossible to get commit diff", e)
def do_project_commit_blob(self, cls, gl, what, args):
try:
o = self.do_get(cls, gl, what, args)
return o.blob(args['filepath'])
except Exception as e:
- _die("Impossible to get commit blob", e)
+ cli.die("Impossible to get commit blob", e)
def do_project_commit_builds(self, cls, gl, what, args):
try:
o = self.do_get(cls, gl, what, args)
return o.builds()
except Exception as e:
- _die("Impossible to get commit builds", e)
+ cli.die("Impossible to get commit builds", e)
def do_project_commit_cherrypick(self, cls, gl, what, args):
try:
o = self.do_get(cls, gl, what, args)
o.cherry_pick(branch=args['branch'])
except Exception as e:
- _die("Impossible to cherry-pick commit", e)
+ cli.die("Impossible to cherry-pick commit", e)
def do_project_build_cancel(self, cls, gl, what, args):
try:
o = self.do_get(cls, gl, what, args)
return o.cancel()
except Exception as e:
- _die("Impossible to cancel project build", e)
+ cli.die("Impossible to cancel project build", e)
def do_project_build_retry(self, cls, gl, what, args):
try:
o = self.do_get(cls, gl, what, args)
return o.retry()
except Exception as e:
- _die("Impossible to retry project build", e)
+ cli.die("Impossible to retry project build", e)
def do_project_build_artifacts(self, cls, gl, what, args):
try:
o = self.do_get(cls, gl, what, args)
return o.artifacts()
except Exception as e:
- _die("Impossible to get project build artifacts", e)
+ cli.die("Impossible to get project build artifacts", e)
def do_project_build_trace(self, cls, gl, what, args):
try:
o = self.do_get(cls, gl, what, args)
return o.trace()
except Exception as e:
- _die("Impossible to get project build trace", e)
+ cli.die("Impossible to get project build trace", e)
def do_project_issue_subscribe(self, cls, gl, what, args):
try:
o = self.do_get(cls, gl, what, args)
o.subscribe()
except Exception as e:
- _die("Impossible to subscribe to issue", e)
+ cli.die("Impossible to subscribe to issue", e)
def do_project_issue_unsubscribe(self, cls, gl, what, args):
try:
o = self.do_get(cls, gl, what, args)
o.unsubscribe()
except Exception as e:
- _die("Impossible to subscribe to issue", e)
+ cli.die("Impossible to subscribe to issue", e)
def do_project_issue_move(self, cls, gl, what, args):
try:
o = self.do_get(cls, gl, what, args)
o.move(args['to_project_id'])
except Exception as e:
- _die("Impossible to move issue", e)
+ cli.die("Impossible to move issue", e)
def do_project_merge_request_closesissues(self, cls, gl, what, args):
try:
o = self.do_get(cls, gl, what, args)
return o.closes_issues()
except Exception as e:
- _die("Impossible to list issues closed by merge request", e)
+ cli.die("Impossible to list issues closed by merge request", e)
def do_project_merge_request_cancel(self, cls, gl, what, args):
try:
o = self.do_get(cls, gl, what, args)
return o.cancel_merge_when_build_succeeds()
except Exception as e:
- _die("Impossible to cancel merge request", e)
+ cli.die("Impossible to cancel merge request", e)
def do_project_merge_request_merge(self, cls, gl, what, args):
try:
@@ -348,26 +327,26 @@ class GitlabCLI(object):
should_remove_source_branch=should_remove,
merged_when_build_succeeds=build_succeeds)
except Exception as e:
- _die("Impossible to validate merge request", e)
+ cli.die("Impossible to validate merge request", e)
def do_project_milestone_issues(self, cls, gl, what, args):
try:
o = self.do_get(cls, gl, what, args)
return o.issues()
except Exception as e:
- _die("Impossible to get milestone issues", e)
+ cli.die("Impossible to get milestone issues", e)
def do_user_search(self, cls, gl, what, args):
try:
return gl.users.search(args['query'])
except Exception as e:
- _die("Impossible to search users", e)
+ cli.die("Impossible to search users", e)
def do_user_getbyusername(self, cls, gl, what, args):
try:
return gl.users.search(args['query'])
except Exception as e:
- _die("Impossible to get user %s" % args['query'], e)
+ cli.die("Impossible to get user %s" % args['query'], e)
def _populate_sub_parser_by_class(cls, sub_parser):
@@ -391,7 +370,7 @@ def _populate_sub_parser_by_class(cls, sub_parser):
action='store_true')
if action_name in ["get", "delete"]:
- if cls not in [gitlab.CurrentUser]:
+ if cls not in [gitlab.v3.objects.CurrentUser]:
if cls.getRequiresId:
id_attr = cls.idAttr.replace('_', '-')
sub_parser_action.add_argument("--%s" % id_attr,
@@ -456,39 +435,23 @@ def _populate_sub_parser_by_class(cls, sub_parser):
for arg in d.get('optional', [])]
-def _build_parser(args=sys.argv[1:]):
- parser = argparse.ArgumentParser(
- description="GitLab API Command Line Interface")
- parser.add_argument("--version", help="Display the version.",
- action="store_true")
- parser.add_argument("-v", "--verbose", "--fancy",
- help="Verbose mode",
- action="store_true")
- parser.add_argument("-c", "--config-file", action='append',
- help=("Configuration file to use. Can be used "
- "multiple times."))
- parser.add_argument("-g", "--gitlab",
- help=("Which configuration section should "
- "be used. If not defined, the default selection "
- "will be used."),
- required=False)
-
+def extend_parser(parser):
subparsers = parser.add_subparsers(title='object', dest='what',
help="Object to manipulate.")
subparsers.required = True
# populate argparse for all Gitlab Object
classes = []
- for cls in gitlab.__dict__.values():
+ for cls in gitlab.v3.objects.__dict__.values():
try:
- if gitlab.GitlabObject in inspect.getmro(cls):
+ if gitlab.base.GitlabObject in inspect.getmro(cls):
classes.append(cls)
except AttributeError:
pass
classes.sort(key=operator.attrgetter("__name__"))
for cls in classes:
- arg_name = _cls_to_what(cls)
+ arg_name = cli.cls_to_what(cls)
object_group = subparsers.add_parser(arg_name)
object_subparsers = object_group.add_subparsers(
@@ -499,47 +462,19 @@ def _build_parser(args=sys.argv[1:]):
return parser
-def _parse_args(args=sys.argv[1:]):
- parser = _build_parser()
- return parser.parse_args(args)
-
-
-def main():
- if "--version" in sys.argv:
- print(gitlab.__version__)
- exit(0)
-
- arg = _parse_args()
- args = arg.__dict__
-
- config_files = arg.config_file
- gitlab_id = arg.gitlab
- verbose = arg.verbose
- action = arg.action
- what = arg.what
-
- # Remove CLI behavior-related args
- for item in ("gitlab", "config_file", "verbose", "what", "action",
- "version"):
- args.pop(item)
-
- args = {k: v for k, v in args.items() if v is not None}
-
- cls = None
+def run(gl, what, action, args, verbose):
try:
- cls = gitlab.__dict__[_what_to_cls(what)]
- except Exception:
- _die("Unknown object: %s" % what)
+ cls = gitlab.v3.objects.__dict__[cli.what_to_cls(what)]
+ except ImportError:
+ cli.die("Unknown object: %s" % what)
- gl = do_auth(gitlab_id, config_files)
-
- cli = GitlabCLI()
+ g_cli = GitlabCLI()
method = None
what = what.replace('-', '_')
action = action.lower().replace('-', '')
for test in ["do_%s_%s" % (what, action),
"do_%s" % action]:
- if hasattr(cli, test):
+ if hasattr(g_cli, test):
method = test
break
@@ -547,7 +482,7 @@ def main():
sys.stderr.write("Don't know how to deal with this!\n")
sys.exit(1)
- ret_val = getattr(cli, method)(cls, gl, what, args)
+ ret_val = getattr(g_cli, method)(cls, gl, what, args)
if isinstance(ret_val, list):
for o in ret_val:
@@ -556,9 +491,7 @@ def main():
print("")
else:
print(o)
- elif isinstance(ret_val, gitlab.GitlabObject):
+ elif isinstance(ret_val, gitlab.base.GitlabObject):
ret_val.display(verbose)
elif isinstance(ret_val, six.string_types):
print(ret_val)
-
- sys.exit(0)