Skip to content

Commit e3d50b5

Browse files
author
Gauvain Pocentek
committed
Refactor the CLI
v3 and v4 CLI will be very different, so start moving things in their own folders. For now v4 isn't working at all.
1 parent fd5ac4d commit e3d50b5

File tree

3 files changed

+222
-177
lines changed

3 files changed

+222
-177
lines changed

gitlab/cli.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
#
4+
# Copyright (C) 2013-2017 Gauvain Pocentek <gauvain@pocentek.net>
5+
#
6+
# This program is free software: you can redistribute it and/or modify
7+
# it under the terms of the GNU Lesser General Public License as published by
8+
# the Free Software Foundation, either version 3 of the License, or
9+
# (at your option) any later version.
10+
#
11+
# This program is distributed in the hope that it will be useful,
12+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
# GNU Lesser General Public License for more details.
15+
#
16+
# You should have received a copy of the GNU Lesser General Public License
17+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
19+
from __future__ import print_function
20+
from __future__ import absolute_import
21+
import argparse
22+
import importlib
23+
import re
24+
import sys
25+
26+
import gitlab.config
27+
28+
camel_re = re.compile('(.)([A-Z])')
29+
30+
31+
def die(msg, e=None):
32+
if e:
33+
msg = "%s (%s)" % (msg, e)
34+
sys.stderr.write(msg + "\n")
35+
sys.exit(1)
36+
37+
38+
def what_to_cls(what):
39+
return "".join([s.capitalize() for s in what.split("-")])
40+
41+
42+
def cls_to_what(cls):
43+
return camel_re.sub(r'\1-\2', cls.__name__).lower()
44+
45+
46+
def _get_base_parser():
47+
parser = argparse.ArgumentParser(
48+
description="GitLab API Command Line Interface")
49+
parser.add_argument("--version", help="Display the version.",
50+
action="store_true")
51+
parser.add_argument("-v", "--verbose", "--fancy",
52+
help="Verbose mode",
53+
action="store_true")
54+
parser.add_argument("-c", "--config-file", action='append',
55+
help=("Configuration file to use. Can be used "
56+
"multiple times."))
57+
parser.add_argument("-g", "--gitlab",
58+
help=("Which configuration section should "
59+
"be used. If not defined, the default selection "
60+
"will be used."),
61+
required=False)
62+
63+
return parser
64+
65+
66+
def _get_parser(cli_module):
67+
parser = _get_base_parser()
68+
return cli_module.extend_parser(parser)
69+
70+
71+
def main():
72+
if "--version" in sys.argv:
73+
print(gitlab.__version__)
74+
exit(0)
75+
76+
parser = _get_base_parser()
77+
(options, args) = parser.parse_known_args(sys.argv)
78+
79+
config = gitlab.config.GitlabConfigParser(options.gitlab,
80+
options.config_file)
81+
cli_module = importlib.import_module('gitlab.v%s.cli' % config.api_version)
82+
parser = _get_parser(cli_module)
83+
args = parser.parse_args(sys.argv[1:])
84+
config_files = args.config_file
85+
gitlab_id = args.gitlab
86+
verbose = args.verbose
87+
action = args.action
88+
what = args.what
89+
90+
args = args.__dict__
91+
# Remove CLI behavior-related args
92+
for item in ('gitlab', 'config_file', 'verbose', 'what', 'action',
93+
'version'):
94+
args.pop(item)
95+
args = {k: v for k, v in args.items() if v is not None}
96+
97+
try:
98+
gl = gitlab.Gitlab.from_config(gitlab_id, config_files)
99+
gl.auth()
100+
except Exception as e:
101+
die(str(e))
102+
103+
cli_module.run(gl, what, action, args, verbose)
104+
105+
sys.exit(0)

gitlab/tests/test_cli.py

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,13 @@
2828
import unittest2 as unittest
2929

3030
from gitlab import cli
31+
import gitlab.v3.cli
3132

3233

3334
class TestCLI(unittest.TestCase):
3435
def test_what_to_cls(self):
35-
self.assertEqual("Foo", cli._what_to_cls("foo"))
36-
self.assertEqual("FooBar", cli._what_to_cls("foo-bar"))
36+
self.assertEqual("Foo", cli.what_to_cls("foo"))
37+
self.assertEqual("FooBar", cli.what_to_cls("foo-bar"))
3738

3839
def test_cls_to_what(self):
3940
class Class(object):
@@ -42,32 +43,33 @@ class Class(object):
4243
class TestClass(object):
4344
pass
4445

45-
self.assertEqual("test-class", cli._cls_to_what(TestClass))
46-
self.assertEqual("class", cli._cls_to_what(Class))
46+
self.assertEqual("test-class", cli.cls_to_what(TestClass))
47+
self.assertEqual("class", cli.cls_to_what(Class))
4748

4849
def test_die(self):
4950
with self.assertRaises(SystemExit) as test:
50-
cli._die("foobar")
51+
cli.die("foobar")
5152

5253
self.assertEqual(test.exception.code, 1)
5354

54-
def test_extra_actions(self):
55-
for cls, data in six.iteritems(cli.EXTRA_ACTIONS):
56-
for key in data:
57-
self.assertIsInstance(data[key], dict)
58-
59-
def test_parsing(self):
60-
args = cli._parse_args(['-v', '-g', 'gl_id',
61-
'-c', 'foo.cfg', '-c', 'bar.cfg',
62-
'project', 'list'])
55+
def test_base_parser(self):
56+
parser = cli._get_base_parser()
57+
args = parser.parse_args(['-v', '-g', 'gl_id',
58+
'-c', 'foo.cfg', '-c', 'bar.cfg'])
6359
self.assertTrue(args.verbose)
6460
self.assertEqual(args.gitlab, 'gl_id')
6561
self.assertEqual(args.config_file, ['foo.cfg', 'bar.cfg'])
62+
63+
64+
class TestV3CLI(unittest.TestCase):
65+
def test_parse_args(self):
66+
parser = cli._get_parser(gitlab.v3.cli)
67+
args = parser.parse_args(['project', 'list'])
6668
self.assertEqual(args.what, 'project')
6769
self.assertEqual(args.action, 'list')
6870

6971
def test_parser(self):
70-
parser = cli._build_parser()
72+
parser = cli._get_parser(gitlab.v3.cli)
7173
subparsers = None
7274
for action in parser._actions:
7375
if type(action) == argparse._SubParsersAction:
@@ -93,3 +95,8 @@ def test_parser(self):
9395
actions = user_subparsers.choices['create']._option_string_actions
9496
self.assertFalse(actions['--twitter'].required)
9597
self.assertTrue(actions['--username'].required)
98+
99+
def test_extra_actions(self):
100+
for cls, data in six.iteritems(gitlab.v3.cli.EXTRA_ACTIONS):
101+
for key in data:
102+
self.assertIsInstance(data[key], dict)

0 commit comments

Comments
 (0)