Skip to content

Commit c5bfc06

Browse files
authored
Merge branch 'main' into feat/group-protected-branches
2 parents 86727cb + af137ca commit c5bfc06

File tree

11 files changed

+137
-12
lines changed

11 files changed

+137
-12
lines changed

.github/workflows/test.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ jobs:
7979
TOXENV: ${{ matrix.toxenv }}
8080
run: tox -- --override-ini='log_cli=True'
8181
- name: Upload codecov coverage
82-
uses: codecov/codecov-action@v5.4.0
82+
uses: codecov/codecov-action@v5.4.2
8383
with:
8484
files: ./coverage.xml
8585
flags: ${{ matrix.toxenv }}
@@ -102,7 +102,7 @@ jobs:
102102
TOXENV: cover
103103
run: tox
104104
- name: Upload codecov coverage
105-
uses: codecov/codecov-action@v5.4.0
105+
uses: codecov/codecov-action@v5.4.2
106106
with:
107107
files: ./coverage.xml
108108
flags: unit

.pre-commit-config.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,6 @@ repos:
5151
- id: rst-directive-colons
5252
- id: rst-inline-touching-normal
5353
- repo: https://github.com/maxbrunet/pre-commit-renovate
54-
rev: 39.240.1
54+
rev: 39.253.1
5555
hooks:
5656
- id: renovate-config-validator

docs/api-usage-graphql.rst

+8-8
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,12 @@ Get the result of a query:
4949

5050
.. code-block:: python
5151
52-
query = """{
53-
query {
54-
currentUser {
52+
query = """
53+
{
54+
currentUser {
5555
name
56-
}
5756
}
57+
}
5858
"""
5959
6060
result = gq.execute(query)
@@ -63,12 +63,12 @@ Get the result of a query using the async client:
6363

6464
.. code-block:: python
6565
66-
query = """{
67-
query {
68-
currentUser {
66+
query = """
67+
{
68+
currentUser {
6969
name
70-
}
7170
}
71+
}
7272
"""
7373
7474
result = await async_gq.execute(query)

docs/gl_objects/groups.rst

+5
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

+5
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

+13
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

+6
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

requirements-test.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ pytest==8.3.5
99
PyYaml==6.0.2
1010
responses==0.25.7
1111
respx==0.22.0
12-
trio==0.29.0
12+
trio==0.30.0
1313
wheel==0.45.1

tests/functional/api/test_groups.py

+28
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

+23
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

+45
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)