Skip to content

Commit 4252070

Browse files
committed
fix(cli): fix parsing CLI objects to classnames
1 parent f35c73e commit 4252070

File tree

3 files changed

+48
-19
lines changed

3 files changed

+48
-19
lines changed

gitlab/cli.py

+19-7
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,18 @@
2121
import functools
2222
import re
2323
import sys
24-
from typing import Any, Callable, cast, Dict, Optional, Tuple, TypeVar, Union
24+
from typing import Any, Callable, cast, Dict, Optional, Tuple, Type, TypeVar, Union
2525

26-
import gitlab.config # noqa: F401
26+
from requests.structures import CaseInsensitiveDict
2727

28-
camel_re = re.compile("(.)([A-Z])")
28+
import gitlab.config
29+
from gitlab.base import RESTObject
30+
31+
32+
# This regex is based on:
33+
# https://github.com/jpvanhal/inflection/blob/master/inflection/__init__.py
34+
camel_upperlower_regex = re.compile(r"([A-Z]+)([A-Z][a-z])")
35+
camel_lowerupper_regex = re.compile(r"([a-z\d])([A-Z])")
2936

3037
# custom_actions = {
3138
# cls: {
@@ -82,12 +89,17 @@ def die(msg: str, e: Optional[Exception] = None) -> None:
8289
sys.exit(1)
8390

8491

85-
def what_to_cls(what: str) -> str:
86-
return "".join([s.capitalize() for s in what.split("-")])
92+
def what_to_cls(what: str, namespace: Type) -> RESTObject:
93+
classes = CaseInsensitiveDict(namespace.__dict__)
94+
lowercase_class = what.replace("-", "")
95+
96+
return classes[lowercase_class]
8797

8898

89-
def cls_to_what(cls: Any) -> str:
90-
return camel_re.sub(r"\1-\2", cls.__name__).lower()
99+
def cls_to_what(cls: RESTObject) -> str:
100+
dasherized_uppercase = camel_upperlower_regex.sub(r"\1-\2", cls.__name__)
101+
dasherized_lowercase = camel_lowerupper_regex.sub(r"\1-\2", dasherized_uppercase)
102+
return dasherized_lowercase.lower()
91103

92104

93105
def _get_base_parser(add_help: bool = True) -> argparse.ArgumentParser:

gitlab/tests/test_cli.py

+27-10
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,37 @@
2828
from gitlab import cli
2929

3030

31-
def test_what_to_cls():
32-
assert "Foo" == cli.what_to_cls("foo")
33-
assert "FooBar" == cli.what_to_cls("foo-bar")
31+
@pytest.mark.parametrize(
32+
"what,expected_class",
33+
[
34+
("class", "Class"),
35+
("test-class", "TestClass"),
36+
("test-longer-class", "TestLongerClass"),
37+
],
38+
)
39+
def test_what_to_cls(what, expected_class):
40+
def _namespace():
41+
pass
3442

43+
ExpectedClass = type(expected_class, (), {})
44+
_namespace.__dict__[expected_class] = ExpectedClass
3545

36-
def test_cls_to_what():
37-
class Class(object):
38-
pass
46+
assert cli.what_to_cls(what, _namespace) == ExpectedClass
3947

40-
class TestClass(object):
41-
pass
4248

43-
assert "test-class" == cli.cls_to_what(TestClass)
44-
assert "class" == cli.cls_to_what(Class)
49+
@pytest.mark.parametrize(
50+
"class_name,expected_what",
51+
[
52+
("Class", "class"),
53+
("TestClass", "test-class"),
54+
("TestUPPERCASEClass", "test-uppercase-class"),
55+
("UPPERCASETestClass", "uppercase-test-class"),
56+
],
57+
)
58+
def test_cls_to_what(class_name, expected_what):
59+
TestClass = type(class_name, (), {})
60+
61+
assert cli.cls_to_what(TestClass) == expected_what
4562

4663

4764
def test_die():

gitlab/v4/cli.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828

2929
class GitlabCLI(object):
3030
def __init__(self, gl, what, action, args):
31-
self.cls_name = cli.what_to_cls(what)
32-
self.cls = gitlab.v4.objects.__dict__[self.cls_name]
31+
self.cls = cli.what_to_cls(what, namespace=gitlab.v4.objects)
32+
self.cls_name = self.cls.__name__
3333
self.what = what.replace("-", "_")
3434
self.action = action.lower()
3535
self.gl = gl

0 commit comments

Comments
 (0)