Skip to content

Commit 4e7a881

Browse files
committed
feat(api): added UploadMixin
Added UploadMixin in mixin module Added UplaodMixin dependency for Project, ProjectWiki, GroupWiki Added api tests for wiki upload Added unit test for mixin Added docs sections to wikis.rst
1 parent fce6896 commit 4e7a881

File tree

8 files changed

+112
-17
lines changed

8 files changed

+112
-17
lines changed

.github/workflows/lock.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ jobs:
1515
action:
1616
runs-on: ubuntu-latest
1717
steps:
18-
- uses: dessant/lock-threads@v4.0.1
18+
- uses: dessant/lock-threads@v5.0.0
1919
with:
2020
process-only: 'issues'

.pre-commit-config.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ default_language_version:
33

44
repos:
55
- repo: https://github.com/psf/black
6-
rev: 23.10.1
6+
rev: 23.11.0
77
hooks:
88
- id: black
99
- repo: https://github.com/commitizen-tools/commitizen
@@ -30,7 +30,7 @@ repos:
3030
- requests-toolbelt==1.0.0
3131
files: 'gitlab/'
3232
- repo: https://github.com/pre-commit/mirrors-mypy
33-
rev: v1.6.1
33+
rev: v1.7.0
3434
hooks:
3535
- id: mypy
3636
args: []
@@ -47,6 +47,6 @@ repos:
4747
- id: rst-directive-colons
4848
- id: rst-inline-touching-normal
4949
- repo: https://github.com/maxbrunet/pre-commit-renovate
50-
rev: 37.46.0
50+
rev: 37.61.3
5151
hooks:
5252
- id: renovate-config-validator

docs/gl_objects/wikis.rst

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,17 +76,19 @@ Examples
7676

7777
Upload a file into a project wiki using a filesystem path::
7878

79+
page = project.wikis.get(page_slug)
7980
page.upload("filename.txt", filepath="/some/path/filename.txt")
8081

81-
Upload a file into a project wiki without a filesystem path::
82+
Upload a file into a project wiki with raw data::
8283

8384
page.upload("filename.txt", filedata="Raw data")
8485

85-
Upload a file into a project wiki using a filesystem path::
86+
Upload a file into a group wiki using a filesystem path::
8687

88+
page = group.wikis.get(page_slug)
8789
page.upload("filename.txt", filepath="/some/path/filename.txt")
8890

89-
Upload a file into a project wiki without a filesystem path::
91+
Upload a file into a group wiki using raw data::
9092

9193
page.upload("filename.txt", filedata="Raw data")
9294

gitlab/mixins.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -982,7 +982,6 @@ def upload(
982982
Either ``filedata`` or ``filepath`` *MUST* be specified.
983983
984984
Args:
985-
path: api endpoint where file is to be posted
986985
filename: The name of the file being uploaded
987986
filedata: The raw data of the file being uploaded
988987
filepath: The path to a local file to upload (optional)

requirements-lint.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
-r requirements.txt
22
argcomplete==2.0.0
3-
black==23.10.1
3+
black==23.11.0
44
commitizen==3.12.0
55
flake8==6.1.0
66
isort==5.12.0
7-
mypy==1.6.1
7+
mypy==1.7.0
88
pylint==3.0.2
99
pytest==7.4.3
10-
responses==0.24.0
10+
responses==0.24.1
1111
types-PyYAML==6.0.12.12
1212
types-requests==2.31.0.10
13-
types-setuptools==68.2.0.0
13+
types-setuptools==68.2.0.1

requirements-test.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ pytest-cov==4.1.0
66
pytest-github-actions-annotate-failures==0.2.0
77
pytest==7.4.3
88
PyYaml==6.0.1
9-
responses==0.24.0
9+
responses==0.24.1
1010
wheel==0.41.3

tests/unit/mixins/test_mixin_methods.py

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ class M(SetMixin, FakeManager):
508508

509509

510510
@responses.activate
511-
def test_upload_mixin(gl):
511+
def test_upload_mixin_with_filepath_and_filedata(gl):
512512
class TestClass(UploadMixin, FakeObject):
513513
_upload_path = "/tests/{id}/uploads"
514514

@@ -523,26 +523,76 @@ class TestClass(UploadMixin, FakeObject):
523523

524524
mgr = FakeManager(gl)
525525
obj = TestClass(mgr, {"id": 42})
526-
527526
with pytest.raises(
528527
GitlabUploadError, match="File contents and file path specified"
529528
):
530529
obj.upload("test.txt", "testing contents", "/home/test.txt")
531530

531+
532+
@responses.activate
533+
def test_upload_mixin_without_filepath_nor_filedata(gl):
534+
class TestClass(UploadMixin, FakeObject):
535+
_upload_path = "/tests/{id}/uploads"
536+
537+
url = "http://localhost/api/v4/tests/42/uploads"
538+
responses.add(
539+
method=responses.POST,
540+
url=url,
541+
json={"id": 42, "file_name": "test.txt", "file_content": "testing contents"},
542+
status=200,
543+
match=[responses.matchers.query_param_matcher({})],
544+
)
545+
546+
mgr = FakeManager(gl)
547+
obj = TestClass(mgr, {"id": 42})
532548
with pytest.raises(GitlabUploadError, match="No file contents or path specified"):
533549
obj.upload("test.txt")
534550

551+
552+
@responses.activate
553+
def test_upload_mixin_with_filedata(gl):
554+
class TestClass(UploadMixin, FakeObject):
555+
_upload_path = "/tests/{id}/uploads"
556+
557+
url = "http://localhost/api/v4/tests/42/uploads"
558+
responses.add(
559+
method=responses.POST,
560+
url=url,
561+
json={"id": 42, "file_name": "test.txt", "file_content": "testing contents"},
562+
status=200,
563+
match=[responses.matchers.query_param_matcher({})],
564+
)
565+
566+
mgr = FakeManager(gl)
567+
obj = TestClass(mgr, {"id": 42})
535568
res_only_data = obj.upload("test.txt", "testing contents")
536569
assert obj._get_upload_path() == "/tests/42/uploads"
537570
assert isinstance(res_only_data, dict)
538571
assert res_only_data["file_name"] == "test.txt"
539572
assert res_only_data["file_content"] == "testing contents"
540573
assert responses.assert_call_count(url, 1) is True
541574

575+
576+
@responses.activate
577+
def test_upload_mixin_with_filepath(gl):
578+
class TestClass(UploadMixin, FakeObject):
579+
_upload_path = "/tests/{id}/uploads"
580+
581+
url = "http://localhost/api/v4/tests/42/uploads"
582+
responses.add(
583+
method=responses.POST,
584+
url=url,
585+
json={"id": 42, "file_name": "test.txt", "file_content": "testing contents"},
586+
status=200,
587+
match=[responses.matchers.query_param_matcher({})],
588+
)
589+
590+
mgr = FakeManager(gl)
591+
obj = TestClass(mgr, {"id": 42})
542592
with patch("builtins.open", mock_open(read_data="raw\nfile\ndata")):
543593
res_only_path = obj.upload("test.txt", None, "/filepath")
544594
assert obj._get_upload_path() == "/tests/42/uploads"
545595
assert isinstance(res_only_path, dict)
546596
assert res_only_path["file_name"] == "test.txt"
547597
assert res_only_path["file_content"] == "testing contents"
548-
assert responses.assert_call_count(url, 2) is True
598+
assert responses.assert_call_count(url, 1) is True

tests/unit/objects/test_projects.py

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

5+
from unittest.mock import mock_open, patch
6+
57
import pytest
68
import responses
79

10+
from gitlab import exceptions
811
from gitlab.const import DEVELOPER_ACCESS, SEARCH_SCOPE_ISSUES
912
from gitlab.v4.objects import (
1013
Project,
@@ -49,7 +52,12 @@
4952
"name": "name",
5053
},
5154
}
52-
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+
}
5361
share_project_content = {
5462
"id": 1,
5563
"project_id": 1,
@@ -326,6 +334,19 @@ def resp_delete_project(accepted_content):
326334
yield rsps
327335

328336

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+
329350
@pytest.fixture
330351
def resp_share_project():
331352
with responses.RequestsMock() as rsps:
@@ -661,6 +682,29 @@ def test_delete_project(project, resp_delete_project):
661682
project.delete()
662683

663684

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+
664708
def test_share_project(project, group, resp_share_project):
665709
project.share(group.id, DEVELOPER_ACCESS)
666710

0 commit comments

Comments
 (0)