Skip to content

Commit 5edd2e6

Browse files
rickbrouwerJohnVillalovos
authored andcommitted
feat(api): add support for avatar removal
When attempting to remove for example a group or project avatar by setting it to an empty string, the current implementation raises a validation error about unsupported file formats.
1 parent 8dbdd7e commit 5edd2e6

File tree

7 files changed

+125
-0
lines changed

7 files changed

+125
-0
lines changed

docs/gl_objects/groups.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ Set the avatar image for a group::
8282
group.avatar = open('path/to/file.png', 'rb')
8383
group.save()
8484

85+
Remove the avatar image for a group::
86+
87+
group.avatar = ""
88+
group.save()
89+
8590
Remove a group::
8691

8792
gl.groups.delete(group_id)

docs/gl_objects/projects.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@ Set the avatar image for a project::
109109
project.avatar = open('path/to/file.png', 'rb')
110110
project.save()
111111

112+
Remove the avatar image for a project::
113+
114+
project.avatar = ""
115+
project.save()
116+
112117
Delete a project::
113118

114119
gl.projects.delete(project_id)

docs/gl_objects/topics.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,16 @@ Delete a topic::
5050
Merge a source topic into a target topic::
5151

5252
gl.topics.merge(topic_id, target_topic_id)
53+
54+
Set the avatar image for a topic::
55+
56+
# the avatar image can be passed as data (content of the file) or as a file
57+
# object opened in binary mode
58+
topic.avatar = open('path/to/file.png', 'rb')
59+
topic.save()
60+
61+
Remove the avatar image for a topic::
62+
63+
topic.avatar = ""
64+
topic.save()
65+

gitlab/utils.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,12 @@ def _transform_types(
188188

189189
# if the type is FileAttribute we need to pass the data as file
190190
if isinstance(gitlab_attribute, types.FileAttribute) and transform_files:
191+
# The GitLab API accepts mixed types
192+
# (e.g. a file for avatar image or empty string for removing the avatar)
193+
# So if string is empty, keep it in data dict
194+
if isinstance(data[attr_name], str) and data[attr_name] == "":
195+
continue
196+
191197
key = gitlab_attribute.get_file_name(attr_name)
192198
files[attr_name] = (key, data.pop(attr_name))
193199
continue

tests/functional/api/test_groups.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,34 @@ def test_group_labels(group):
138138
label.delete()
139139

140140

141+
def test_group_avatar_upload(gl, group, fixture_dir):
142+
"""Test uploading an avatar to a group."""
143+
# Upload avatar
144+
with open(fixture_dir / "avatar.png", "rb") as avatar_file:
145+
group.avatar = avatar_file
146+
group.save()
147+
148+
# Verify the avatar was set
149+
updated_group = gl.groups.get(group.id)
150+
assert updated_group.avatar_url is not None
151+
152+
153+
def test_group_avatar_remove(gl, group, fixture_dir):
154+
"""Test removing an avatar from a group."""
155+
# First set an avatar
156+
with open(fixture_dir / "avatar.png", "rb") as avatar_file:
157+
group.avatar = avatar_file
158+
group.save()
159+
160+
# Now remove the avatar
161+
group.avatar = ""
162+
group.save()
163+
164+
# Verify the avatar was removed
165+
updated_group = gl.groups.get(group.id)
166+
assert updated_group.avatar_url is None
167+
168+
141169
@pytest.mark.gitlab_premium
142170
@pytest.mark.xfail(reason="/ldap/groups endpoint not documented")
143171
def test_ldap_groups(gl):

tests/functional/api/test_projects.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,29 @@ def test_project_members(user, project):
4848
member.delete()
4949

5050

51+
def test_project_avatar_upload(gl, project, fixture_dir):
52+
"""Test uploading an avatar to a project."""
53+
with open(fixture_dir / "avatar.png", "rb") as avatar_file:
54+
project.avatar = avatar_file
55+
project.save()
56+
57+
updated_project = gl.projects.get(project.id)
58+
assert updated_project.avatar_url is not None
59+
60+
61+
def test_project_avatar_remove(gl, project, fixture_dir):
62+
"""Test removing an avatar from a project."""
63+
with open(fixture_dir / "avatar.png", "rb") as avatar_file:
64+
project.avatar = avatar_file
65+
project.save()
66+
67+
project.avatar = ""
68+
project.save()
69+
70+
updated_project = gl.projects.get(project.id)
71+
assert updated_project.avatar_url is None
72+
73+
5174
def test_project_badges(project):
5275
badge_image = "http://example.com"
5376
badge_link = "http://example/img.svg"

tests/functional/api/test_topics.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,48 @@ def test_topics(gl, gitlab_version):
3131
assert merged_topic["id"] == topic2.id
3232

3333
topic2.delete()
34+
35+
36+
def test_topic_avatar_upload(gl, fixture_dir):
37+
"""Test uploading an avatar to a topic."""
38+
39+
topic = gl.topics.create(
40+
{
41+
"name": "avatar-topic",
42+
"description": "Topic with avatar",
43+
"title": "Avatar Topic",
44+
}
45+
)
46+
47+
with open(fixture_dir / "avatar.png", "rb") as avatar_file:
48+
topic.avatar = avatar_file
49+
topic.save()
50+
51+
updated_topic = gl.topics.get(topic.id)
52+
assert updated_topic.avatar_url is not None
53+
54+
topic.delete()
55+
56+
57+
def test_topic_avatar_remove(gl, fixture_dir):
58+
"""Test removing an avatar from a topic."""
59+
60+
topic = gl.topics.create(
61+
{
62+
"name": "avatar-topic-remove",
63+
"description": "Remove avatar",
64+
"title": "Remove Avatar",
65+
}
66+
)
67+
68+
with open(fixture_dir / "avatar.png", "rb") as avatar_file:
69+
topic.avatar = avatar_file
70+
topic.save()
71+
72+
topic.avatar = ""
73+
topic.save()
74+
75+
updated_topic = gl.topics.get(topic.id)
76+
assert updated_topic.avatar_url is None
77+
78+
topic.delete()

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy