10000 fix(api): head requests for projectfilemanager (#2977) · python-gitlab/python-gitlab@96a18b0 · GitHub
[go: up one dir, main page]

Skip to content

Commit 96a18b0

Browse files
holysolesPatrick Evansnejch
authored
fix(api): head requests for projectfilemanager (#2977)
* fix(api): head requests for projectfilemanager --------- Co-authored-by: Patrick Evans <patrick.evans@gehealthcare.com> Co-authored-by: Nejc Habjan <hab.nejc@gmail.com>
1 parent 10c7aee commit 96a18b0

File tree

2 files changed

+82
-9
lines changed

2 files changed

+82
-9
lines changed

gitlab/v4/objects/files.py

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
from typing import (
33
Any,
44
Callable,
5-
cast,
65
Dict,
76
Iterator,
87
List,
98
Optional,
9+
Tuple,
1010
TYPE_CHECKING,
1111
Union,
1212
)
@@ -20,7 +20,6 @@
2020
from gitlab.mixins import (
2121
CreateMixin,
2222
DeleteMixin,
23-
GetMixin,
2423
ObjectDeleteMixin,
2524
SaveMixin,
2625
UpdateMixin,
@@ -96,10 +95,11 @@ def delete( # type: ignore
9695
self.manager.delete(file_path, branch, commit_message, **kwargs)
9796

9897

99-
class ProjectFileManager(GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTManager):
98+
class ProjectFileManager(CreateMixin, UpdateMixin, DeleteMixin, RESTManager):
10099
_path = "/projects/{project_id}/repository/files"
101100
_obj_cls = ProjectFile
102101
_from_parent_attrs = {"project_id": "id"}
102+
_optional_get_attrs: Tuple[str, ...] = ()
103103
_create_attrs = RequiredOptional(
104104
required=("file_path", "branch", "content", "commit_message"),
105105
optional=("encoding", "author_email", "author_name"),
@@ -112,11 +112,7 @@ class ProjectFileManager(GetMixin, CreateMixin, UpdateMixin, DeleteMixin, RESTMa
112112
@cli.register_custom_action(
113113
cls_names="ProjectFileManager", required=("file_path", "ref")
114114
)
115-
# NOTE(jlvillal): Signature doesn't match UpdateMixin.update() so ignore
116-
# type error
117-
def get( # type: ignore
118-
self, file_path: str, ref: str, **kwargs: Any
119-
) -> ProjectFile:
115+
def get(self, file_path: str, ref: str, **kwargs: Any) -> ProjectFile:
120116
"""Retrieve a single file.
121117
122118
Args:
@@ -131,7 +127,37 @@ def get( # type: ignore
131127
Returns:
132128
The generated RESTObject
133129
"""
134-
return cast(ProjectFile, GetMixin.get(self, file_path, ref=ref, **kwargs))
130+
if TYPE_CHECKING:
131+
assert file_path is not None
132+
file_path = utils.EncodedId(file_path)
133+
path = f"{self.path}/{file_path}"
134+
server_data = self.gitlab.http_get(path, ref=ref, **kwargs)
135+
if TYPE_CHECKING:
136+
assert isinstance(server_data, dict)
137+
return self._obj_cls(self, server_data)
138+
139+
def head(
140+
self, file_path: str, ref: str, **kwargs: Any
141+
) -> "requests.structures.CaseInsensitiveDict[Any]":
142+
"""Retrieve just metadata for a single file.
143+
144+
Args:
145+
file_path: Path of the file to retrieve
146+
ref: Name of the branch, tag or commit
147+
**kwargs: Extra options to send to the server (e.g. sudo)
148+
149+
Raises:
150+
GitlabAuthenticationError: If authentication is not correct
151+
GitlabGetError: If the file could not be retrieved
152+
153+
Returns:
154+
The response headers as a dictionary
155+
"""
156+
if TYPE_CHECKING:
157+
assert file_path is not None
158+
file_path = utils.EncodedId(file_path)
159+
path = f"{self.path}/{file_path}"
160+
return self.gitlab.http_head(path, ref=ref, **kwargs)
135161

136162
@cli.register_custom_action(
137163
cls_names="ProjectFileManager",

tests/unit/objects/test_repositories.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,60 @@
88

99
import pytest
1010
import responses
11+
from requests.structures import CaseInsensitiveDict
1112

1213
from gitlab.v4.objects import ProjectFile
1314

1415
file_path = "app/models/key.rb"
1516
ref = "main"
1617

1718

19+
@pytest.fixture
20+
def resp_head_repository_file():
21+
header_response = {
22+
"Cache-Control": "no-cache",
23+
"Content-Length": "0",
24+
"Content-Type": "application/json",
25+
"Date": "Thu, 12 Sep 2024 14:27:49 GMT",
26+
"Referrer-Policy": "strict-origin-when-cross-origin",
27+
"Server": "nginx",
28+
"Strict-Transport-Security": "max-age=63072000",
29+
"Vary": "Origin",
30+
"X-Content-Type-Options": "nosniff",
31+
"X-Frame-Options": "SAMEORIGIN",
32+
"X-Gitlab-Blob-Id": "79f7bbd25901e8334750839545a9bd021f0e4c83",
33+
"X-Gitlab-Commit-Id": "d5a3ff139356ce33e37e73add446f16869741b50",
34+
"X-Gitlab-Content-Sha256": "4c294617b60715c1d218e61164a3abd4808a4284cbc30e6728a01ad9aada4481",
35+
"X-Gitlab-Encoding": "base64",
36+
"X-Gitlab-Execute-Filemode": "false",
37+
"X-Gitlab-File-Name": "key.rb",
38+
"X-Gitlab-File-Path": file_path,
39+
"X-Gitlab-Last-Commit-Id": "570e7b2abdd848b95f2f578043fc23bd6f6fd24d",
40+
"X-Gitlab-Meta": '{"correlation_id":"01J7KFRPXBX65Y04HEH7MFX4GD","version":"1"}',
41+
"X-Gitlab-Ref": ref,
42+
"X-Gitlab-Size": "1476",
43+
"X-Request-Id": "01J7KFRPXBX65Y04HEH7MFX4GD",
44+
"X-Runtime": "0.083199",
45+
"Connection": "keep-alive",
46+
}
47+
encoded_path = quote(file_path, safe="")
48+
49+
with responses.RequestsMock() as rsps:
50+
rsps.add(
51+
method=responses.HEAD,
52+
url=f"http://localhost/api/v4/projects/1/repository/files/{encoded_path}",
53+
headers=header_response,
54+
status=200,
55+
)
56+
yield rsps
57+
58+
59+
def test_head_repository_file(project, resp_head_repository_file):
60+
headers = project.files.head(file_path, ref=ref)
61+
assert isinstance(headers, CaseInsensitiveDict)
62+
assert headers["X-Gitlab-File-Path"] == file_path
63+
64+
1865
@pytest.fixture
1966
def resp_get_repository_file():
2067
file_response = {

0 commit comments

Comments
 (0)
0