Skip to content
9 changes: 9 additions & 0 deletions gitlab/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ def get_for_api(self):
return ",".join(self._value)


class ScopesListAttribute(ListAttribute):
def get_for_api(self):
# scopes are expected to be a list of strings
if isinstance(self._value, str):
return [self._value]

return self._value


class LowercaseStringAttribute(GitlabAttribute):
def get_for_api(self):
return str(self._value).lower()
Expand Down
3 changes: 3 additions & 0 deletions gitlab/v4/objects/applications.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from gitlab.base import RESTManager, RESTObject
from gitlab.mixins import CreateMixin, DeleteMixin, ListMixin, ObjectDeleteMixin
from gitlab.types import ScopesListAttribute

__all__ = [
"Application",
Expand All @@ -16,3 +17,5 @@ class ApplicationManager(ListMixin, CreateMixin, DeleteMixin, RESTManager):
_path = "/applications"
_obj_cls = Application
_create_attrs = (("name", "redirect_uri", "scopes"), ("confidential",))

_types = {"scopes": ScopesListAttribute}
4 changes: 3 additions & 1 deletion gitlab/v4/objects/deploy_tokens.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from gitlab.base import RESTManager, RESTObject
from gitlab.mixins import CreateMixin, DeleteMixin, ListMixin, ObjectDeleteMixin

from gitlab.types import ScopesListAttribute

__all__ = [
"DeployToken",
Expand Down Expand Up @@ -39,6 +39,7 @@ class GroupDeployTokenManager(ListMixin, CreateMixin, DeleteMixin, RESTManager):
"username",
),
)
_types = {"scopes": ScopesListAttribute}


class ProjectDeployToken(ObjectDeleteMixin, RESTObject):
Expand All @@ -59,3 +60,4 @@ class ProjectDeployTokenManager(ListMixin, CreateMixin, DeleteMixin, RESTManager
"username",
),
)
_types = {"scopes": ScopesListAttribute}
2 changes: 2 additions & 0 deletions gitlab/v4/objects/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
SaveMixin,
UpdateMixin,
)
from gitlab.types import ScopesListAttribute

from .custom_attributes import UserCustomAttributeManager
from .events import UserEventManager
Expand Down Expand Up @@ -406,6 +407,7 @@ class UserImpersonationTokenManager(NoUpdateMixin, RESTManager):
_from_parent_attrs = {"user_id": "id"}
_create_attrs = (("name", "scopes"), ("expires_at",))
_list_filters = ("state",)
_types = {"scopes": ScopesListAttribute}


class UserMembership(RESTObject):
Expand Down
17 changes: 14 additions & 3 deletions tools/functional/cli/test_cli_v4.py
Original file line number Diff line number Diff line change
Expand Up @@ -561,11 +561,10 @@ def test_create_project_with_values_from_file(gitlab_cli, tmpdir):
assert description in ret.stdout


def test_create_project_deploy_token(gitlab_cli, project):
def do_test_create_project_deploy_token(gitlab_cli, project, scopes, expected_scopes):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hint: you could keep a single test function here and parametrize the input/expected output with pytest:

@pytest.mark.parametrize(
    "scopes,expected_scopes",
    [
        ("read_registry", "['read_registry']"),
        ("read_registry,read_repository", "['read_repository', 'read_registry']"),
    ],
)
def test_create_project_deploy_token(gitlab_cli, project, scopes, expected_scopes):
    ...

Then you don't need a custom helper function at all and it will be easy to add more edge cases later. See very similar example here:

@pytest.mark.parametrize(
"config_string,expected_agent",
[
(valid_config, USER_AGENT),
(custom_user_agent_config, custom_user_agent),
],
)
def test_config_user_agent(m_open, path_exists, config_string, expected_agent):
fd = io.StringIO(config_string)
fd.close = mock.Mock(return_value=None)
m_open.return_value = fd
cp = config.GitlabConfigParser()
assert cp.user_agent == expected_agent

name = "project-token"
username = "root"
expires_at = "2021-09-09"
scopes = "read_registry"

cmd = [
"-v",
Expand All @@ -588,7 +587,19 @@ def test_create_project_deploy_token(gitlab_cli, project):
assert name in ret.stdout
assert username in ret.stdout
assert expires_at in ret.stdout
assert scopes in ret.stdout
assert expected_scopes in ret.stdout


def test_create_project_deploy_token_one_scope(gitlab_cli, project):
scopes = "read_registry"
expected_scopes = "['read_registry']"
do_test_create_project_deploy_token(gitlab_cli, project, scopes, expected_scopes)


def test_create_project_deploy_token_many_scopes(gitlab_cli, project):
scopes = "read_registry,read_repository"
expected_scopes = "['read_repository', 'read_registry']"
do_test_create_project_deploy_token(gitlab_cli, project, scopes, expected_scopes)


def test_list_all_deploy_tokens(gitlab_cli, deploy_token):
Expand Down