Skip to content

Commit 58df897

Browse files
committed
feat(UploadMixin): added with tests and docs
Added UploadMixin to mixin module; Added dependency in objects Project and ProjectWiki; Added api tests; Added unit test for UploadMixin; Added docs section in wikis.rst
1 parent f14a2cc commit 58df897

File tree

4 files changed

+72
-51
lines changed

4 files changed

+72
-51
lines changed

docs/gl_objects/wikis.rst

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,28 @@ Update a wiki page::
5454
Delete a wiki page::
5555

5656
page.delete()
57+
58+
59+
File uploads
60+
============
61+
62+
Reference
63+
---------
64+
65+
* v4 API:
66+
67+
+ :attr:`gitlab.v4.objects.ProjectWiki.upload`
68+
69+
* Gitlab API: https://docs.gitlab.com/ee/api/wikis.html#upload-an-attachment-to-the-wiki-repository
70+
71+
Examples
72+
--------
73+
74+
Upload a file into a project wiki using a filesystem path::
75+
76+
page.upload("filename.txt", filepath="/some/path/filename.txt")
77+
78+
Upload a file into a project wiki without a filesystem path::
79+
80+
page.upload("filename.txt", filedata="Raw data")
81+

gitlab/mixins.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -956,15 +956,11 @@ class UploadMixin(_RestObjectBase):
956956
manager: base.RESTManager
957957

958958
def _get_upload_path(self) -> str:
959-
"""Formats _upload_string with object attributes.
959+
"""Formats _upload_path with object attributes.
960960
961961
Returns:
962962
The upload path
963963
"""
964-
if not self._upload_path:
965-
raise exc.GitlabUploadError(
966-
f"No upload path set for {self.__class__.__name__}"
967-
)
968964
if TYPE_CHECKING:
969965
assert isinstance(self._upload_path, str)
970966
data = self.attributes

tests/unit/mixins/test_mixin_methods.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
from unittest.mock import mock_open, patch
2+
13
import pytest
24
import requests
35
import responses
46

5-
from gitlab import base
7+
from gitlab import base, GitlabUploadError
68
from gitlab import types as gl_types
79
from gitlab.mixins import (
810
CreateMixin,
@@ -15,6 +17,7 @@
1517
SetMixin,
1618
UpdateMethod,
1719
UpdateMixin,
20+
UploadMixin,
1821
)
1922

2023

@@ -502,3 +505,44 @@ class M(SetMixin, FakeManager):
502505
assert obj.key == "foo"
503506
assert obj.value == "bar"
504507
assert responses.assert_call_count(url, 1) is True
508+
509+
510+
@responses.activate
511+
def test_upload_mixin(gl):
512+
class TestClass(UploadMixin, FakeObject):
513+
_upload_path = "/tests/{id}/uploads"
514+
515+
url = "http://localhost/api/v4/tests/42/uploads"
516+
responses.add(
517+
method=responses.POST,
518+
url=url,
519+
json={"id": 42, "file_name": "test.txt", "file_content": "testing contents"},
520+
status=200,
521+
match=[responses.matchers.query_param_matcher({})],
522+
)
523+
524+
mgr = FakeManager(gl)
525+
obj = TestClass(mgr, {"id": 42})
526+
527+
with pytest.raises(
528+
GitlabUploadError, match="File contents and file path specified"
529+
):
530+
obj.upload("test.txt", "testing contents", "/home/test.txt")
531+
532+
with pytest.raises(GitlabUploadError, match="No file contents or path specified"):
533+
obj.upload("test.txt")
534+
535+
res_only_data = obj.upload("test.txt", "testing contents")
536+
assert obj._get_upload_path() == "/tests/42/uploads"
537+
assert isinstance(res_only_data, dict)
538+
assert res_only_data["file_name"] == "test.txt"
539+
assert res_only_data["file_content"] == "testing contents"
540+
assert responses.assert_call_count(url, 1) is True
541+
542+
with patch("builtins.open", mock_open(read_data="raw\nfile\ndata")):
543+
res_only_path = obj.upload("test.txt", None, "/filepath")
544+
assert obj._get_upload_path() == "/tests/42/uploads"
545+
assert isinstance(res_only_path, dict)
546+
assert res_only_path["file_name"] == "test.txt"
547+
assert res_only_path["file_content"] == "testing contents"
548+
assert responses.assert_call_count(url, 2) is True

tests/unit/objects/test_projects.py

Lines changed: 1 addition & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@
22
GitLab API: https://docs.gitlab.com/ce/api/projects.html
33
"""
44

5-
from unittest.mock import mock_open, patch
6-
75
import pytest
86
import responses
97

10-
from gitlab import exceptions
118
from gitlab.const import DEVELOPER_ACCESS, SEARCH_SCOPE_ISSUES
129
from gitlab.v4.objects import (
1310
Project,
@@ -52,12 +49,7 @@
5249
"name": "name",
5350
},
5451
}
55-
upload_file_content = {
56-
"alt": "filename",
57-
"url": "/uploads/66dbcd21ec5d24ed6ea225176098d52b/filename.png",
58-
"full_path": "/namespace/project/uploads/66dbcd21ec5d24ed6ea225176098d52b/filename.png",
59-
"markdown": "![dk](/uploads/66dbcd21ec5d24ed6ea225176098d52b/filename.png)",
60-
}
52+
6153
share_project_content = {
6254
"id": 1,
6355
"project_id": 1,
@@ -334,19 +326,6 @@ def resp_delete_project(accepted_content):
334326
yield rsps
335327

336328

337-
@pytest.fixture
338-
def resp_upload_file_project():
339-
with responses.RequestsMock() as rsps:
340-
rsps.add(
341-
method=responses.POST,
342-
url="http://localhost/api/v4/projects/1/uploads",
343-
json=upload_file_content,
344-
content_type="application/json",
345-
status=201,
346-
)
347-
yield rsps
348-
349-
350329
@pytest.fixture
351330
def resp_share_project():
352331
with responses.RequestsMock() as rsps:
@@ -682,29 +661,6 @@ def test_delete_project(project, resp_delete_project):
682661
project.delete()
683662

684663

685-
def test_upload_file(project, resp_upload_file_project):
686-
project.upload("filename.png", "raw\nfile\ndata")
687-
688-
689-
def test_upload_file_with_filepath(project, resp_upload_file_project):
690-
with patch("builtins.open", mock_open(read_data="raw\nfile\ndata")):
691-
project.upload("filename.png", None, "/filepath")
692-
693-
694-
def test_upload_file_without_filepath_nor_filedata(project):
695-
with pytest.raises(
696-
exceptions.GitlabUploadError, match="No file contents or path specified"
697-
):
698-
project.upload("filename.png")
699-
700-
701-
def test_upload_file_with_filepath_and_filedata(project):
702-
with pytest.raises(
703-
exceptions.GitlabUploadError, match="File contents and file path specified"
704-
):
705-
project.upload("filename.png", "filedata", "/filepath")
706-
707-
708664
def test_share_project(project, group, resp_share_project):
709665
project.share(group.id, DEVELOPER_ACCESS)
710666

0 commit comments

Comments
 (0)