Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 7f6a8c2

Browse filesBrowse files
fix: use the [] after key names for array variables
1. If a value is of type ArrayAttribute then append '[]' to the name of the value. 2. Move processing of most GitlabAttributes into the client.py:http_request() method. Now we convert our params into a list of tuples so that we can have multiple identical keys but with different values. This is step 3 in a series of steps of our goal to add full support for the GitLab API data types[1]: * array * hash * array of hashes Step one was: commit 5127b15 Step two was: commit a57334f Fixes: #1698 [1] https://docs.gitlab.com/ee/api/#encoding-api-parameters-of-array-and-hash-types
1 parent 1ecbc7c commit 7f6a8c2
Copy full SHA for 7f6a8c2

File tree

Expand file treeCollapse file tree

5 files changed

+65
-23
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

5 files changed

+65
-23
lines changed
Open diff view settings
Collapse file

‎gitlab/types.py‎

Copy file name to clipboardExpand all lines: gitlab/types.py
+17-7Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ def get(self) -> Any:
6363
def set_from_cli(self, cli_value: Any) -> None:
6464
self._value = cli_value
6565

66-
def get_for_api(self) -> Any:
67-
return self._value
66+
def get_for_api(self, *, key: str) -> Tuple[str, Any]:
67+
return (key, self._value)
6868

6969

7070
class _ListArrayAttribute(GitlabAttribute):
@@ -76,30 +76,40 @@ def set_from_cli(self, cli_value: str) -> None:
7676
else:
7777
self._value = [item.strip() for item in cli_value.split(",")]
7878

79-
def get_for_api(self) -> str:
79+
def get_for_api(self, *, key: str) -> Tuple[str, str]:
8080
# Do not comma-split single value passed as string
8181
if isinstance(self._value, str):
82-
return self._value
82+
return (key, self._value)
8383

8484
if TYPE_CHECKING:
8585
assert isinstance(self._value, list)
86-
return ",".join([str(x) for x in self._value])
86+
return (key, ",".join([str(x) for x in self._value]))
8787

8888

8989
class ArrayAttribute(_ListArrayAttribute):
9090
"""To support `array` types as documented in
9191
https://docs.gitlab.com/ee/api/#array"""
9292

93+
def get_for_api(self, *, key: str) -> Tuple[str, Any]:
94+
if isinstance(self._value, str):
95+
return (f"{key}[]", self._value)
96+
97+
if TYPE_CHECKING:
98+
assert isinstance(self._value, list)
99+
return (f"{key}[]", self._value)
100+
93101

94102
class CommaSeparatedListAttribute(_ListArrayAttribute):
95103
"""For values which are sent to the server as a Comma Separated Values
96104
(CSV) string. We allow them to be specified as a list and we convert it
97105
into a CSV"""
98106

107+
pass
108+
99109

100110
class LowercaseStringAttribute(GitlabAttribute):
101-
def get_for_api(self) -> str:
102-
return str(self._value).lower()
111+
def get_for_api(self, *, key: str) -> Tuple[str, str]:
112+
return (key, str(self._value).lower())
103113

104114

105115
class FileAttribute(GitlabAttribute):
Collapse file

‎gitlab/utils.py‎

Copy file name to clipboardExpand all lines: gitlab/utils.py
+15-7Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,19 @@ def _transform_types(
7676
continue
7777

7878
type_obj = type_cls(data[attr_name])
79-
80-
# if the type if FileAttribute we need to pass the data as file
81-
if transform_files and isinstance(type_obj, types.FileAttribute):
82-
key = type_obj.get_file_name(attr_name)
83-
files[attr_name] = (key, data.pop(attr_name))
84-
else:
85-
data[attr_name] = type_obj.get_for_api()
79+
assert isinstance(type_obj, types.GitlabAttribute)
80+
81+
if isinstance(type_obj, types.GitlabAttribute):
82+
# if the type is FileAttribute we need to pass the data as file
83+
if isinstance(type_obj, types.FileAttribute):
84+
if transform_files:
85+
key = type_obj.get_file_name(attr_name)
86+
files[attr_name] = (key, data.pop(attr_name))
87+
continue
88+
key, value = type_obj.get_for_api(key=attr_name)
89+
if key != attr_name:
90+
del data[attr_name]
91+
data[key] = value
8692

8793
return data, files
8894

@@ -94,6 +100,8 @@ def copy_dict(
94100
) -> None:
95101
for k, v in src.items():
96102
if isinstance(v, dict):
103+
# NOTE(jlvillal): This provides some support for the `hash` type
104+
# https://docs.gitlab.com/ee/api/#hash
97105
# Transform dict values to new attributes. For example:
98106
# custom_attributes: {'foo', 'bar'} =>
99107
# "custom_attributes['foo']": "bar"
Collapse file

‎tests/functional/api/test_groups.py‎

Copy file name to clipboardExpand all lines: tests/functional/api/test_groups.py
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@ def test_groups(gl):
9999
assert len(group1.members.list()) == 3
100100
assert len(group2.members.list()) == 2
101101

102+
# Test `user_ids` array
103+
result = group1.members.list(user_ids=[user.id, 99999])
104+
assert len(result) == 1
105+
assert result[0].id == user.id
106+
102107
group1.members.delete(user.id)
103108
assert user not in group1.members.list()
104109
assert group1.members_all.list()
Collapse file

‎tests/unit/mixins/test_mixin_methods.py‎

Copy file name to clipboardExpand all lines: tests/unit/mixins/test_mixin_methods.py
+19Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,25 @@ class M(ListMixin, FakeManager):
205205
assert responses.assert_call_count(url, 2) is True
206206

207207

208+
@responses.activate
209+
def test_list_mixin_with_attributes(gl):
210+
class M(ListMixin, FakeManager):
211+
_types = {"my_array": gl_types.ArrayAttribute}
212+
213+
url = "http://localhost/api/v4/tests?my_array%5B%5D=1&my_array%5B%5D=2&my_array%5B%5D=3"
214+
responses.add(
215+
method=responses.GET,
216+
headers={},
217+
url=url,
218+
json=[],
219+
status=200,
220+
match=[responses.matchers.query_param_matcher({"my_array[]": ["1", "2", "3"]})],
221+
)
222+
223+
mgr = M(gl)
224+
mgr.list(iterator=True, my_array=[1, 2, 3])
225+
226+
208227
@responses.activate
209228
def test_list_other_url(gl):
210229
class M(ListMixin, FakeManager):
Collapse file

‎tests/unit/test_types.py‎

Copy file name to clipboardExpand all lines: tests/unit/test_types.py
+9-9Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def test_gitlab_attribute_get():
7373

7474
o.set_from_cli("whatever2")
7575
assert o.get() == "whatever2"
76-
assert o.get_for_api() == "whatever2"
76+
assert o.get_for_api(key="spam") == ("spam", "whatever2")
7777

7878
o = types.GitlabAttribute()
7979
assert o._value is None
@@ -100,42 +100,42 @@ def test_array_attribute_empty_input():
100100
def test_array_attribute_get_for_api_from_cli():
101101
o = types.ArrayAttribute()
102102
o.set_from_cli("foo,bar,baz")
103-
assert o.get_for_api() == "foo,bar,baz"
103+
assert o.get_for_api(key="spam") == ("spam[]", ["foo", "bar", "baz"])
104104

105105

106106
def test_array_attribute_get_for_api_from_list():
107107
o = types.ArrayAttribute(["foo", "bar", "baz"])
108-
assert o.get_for_api() == "foo,bar,baz"
108+
assert o.get_for_api(key="spam") == ("spam[]", ["foo", "bar", "baz"])
109109

110110

111111
def test_array_attribute_get_for_api_from_int_list():
112112
o = types.ArrayAttribute([1, 9, 7])
113-
assert o.get_for_api() == "1,9,7"
113+
assert o.get_for_api(key="spam") == ("spam[]", [1, 9, 7])
114114

115115

116116
def test_array_attribute_does_not_split_string():
117117
o = types.ArrayAttribute("foo")
118-
assert o.get_for_api() == "foo"
118+
assert o.get_for_api(key="spam") == ("spam[]", "foo")
119119

120120

121121
# CommaSeparatedListAttribute tests
122122
def test_csv_string_attribute_get_for_api_from_cli():
123123
o = types.CommaSeparatedListAttribute()
124124
o.set_from_cli("foo,bar,baz")
125-
assert o.get_for_api() == "foo,bar,baz"
125+
assert o.get_for_api(key="spam") == ("spam", "foo,bar,baz")
126126

127127

128128
def test_csv_string_attribute_get_for_api_from_list():
129129
o = types.CommaSeparatedListAttribute(["foo", "bar", "baz"])
130-
assert o.get_for_api() == "foo,bar,baz"
130+
assert o.get_for_api(key="spam") == ("spam", "foo,bar,baz")
131131

132132

133133
def test_csv_string_attribute_get_for_api_from_int_list():
134134
o = types.CommaSeparatedListAttribute([1, 9, 7])
135-
assert o.get_for_api() == "1,9,7"
135+
assert o.get_for_api(key="spam") == ("spam", "1,9,7")
136136

137137

138138
# LowercaseStringAttribute tests
139139
def test_lowercase_string_attribute_get_for_api():
140140
o = types.LowercaseStringAttribute("FOO")
141-
assert o.get_for_api() == "foo"
141+
assert o.get_for_api(key="spam") == ("spam", "foo")

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.