| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -100,7 +100,7 @@ def get( | |||
| 100 | 100 | GitlabGetError: If the server cannot perform the request | |
| 101 | 101 | """ | |
| 102 | 102 | if not isinstance(id, int): | |
| 103 | - id = utils.clean_str_id(id) | ||
| 103 | + id = utils._url_encode(id) | ||
| 104 | 104 | path = f"{self.path}/{id}" | |
| 105 | 105 | if TYPE_CHECKING: | |
| 106 | 106 | assert self._obj_cls is not None | |
@@ -444,7 +444,7 @@ def set(self, key: str, value: str, **kwargs: Any) -> base.RESTObject: | |||
| 444 | 444 | Returns: | |
| 445 | 445 | The created/updated attribute | |
| 446 | 446 | """ | |
| 447 | - path = f"{self.path}/{utils.clean_str_id(key)}" | ||
| 447 | + path = f"{self.path}/{utils._url_encode(key)}" | ||
| 448 | 448 | data = {"value": value} | |
| 449 | 449 | server_data = self.gitlab.http_put(path, post_data=data, **kwargs) | |
| 450 | 450 | if TYPE_CHECKING: | |
@@ -478,7 +478,7 @@ def delete(self, id: Union[str, int], **kwargs: Any) -> None: | |||
| 478 | 478 | path = self.path | |
| 479 | 479 | else: | |
| 480 | 480 | if not isinstance(id, int): | |
| 481 | - id = utils.clean_str_id(id) | ||
| 481 | + id = utils._url_encode(id) | ||
| 482 | 482 | path = f"{self.path}/{id}" | |
| 483 | 483 | self.gitlab.http_delete(path, **kwargs) | |
| 484 | 484 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -15,8 +15,8 @@ | |||
| 15 | 15 | # You should have received a copy of the GNU Lesser General Public License | |
| 16 | 16 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 17 | 17 | ||
| 18 | + import urllib.parse | ||
| 18 | 19 | from typing import Any, Callable, Dict, Optional | |
| 19 | - from urllib.parse import quote | ||
| 20 | 20 | ||
| 21 | 21 | import requests | |
| 22 | 22 | ||
@@ -56,8 +56,25 @@ def copy_dict(dest: Dict[str, Any], src: Dict[str, Any]) -> None: | |||
| 56 | 56 | dest[k] = v | |
| 57 | 57 | ||
| 58 | 58 | ||
| 59 | - def clean_str_id(id: str) -> str: | ||
| 60 | - return quote(id, safe="") | ||
| 59 | + def _url_encode(id: str) -> str: | ||
| 60 | + """Encode/quote the characters in the string so that they can be used in a path. | ||
| 61 | + | ||
| 62 | + Reference to documentation on why this is necessary. | ||
| 63 | + | ||
| 64 | + https://docs.gitlab.com/ee/api/index.html#namespaced-path-encoding | ||
| 65 | + | ||
| 66 | + If using namespaced API requests, make sure that the NAMESPACE/PROJECT_PATH is | ||
| 67 | + URL-encoded. For example, / is represented by %2F | ||
| 68 | + | ||
| 69 | + https://docs.gitlab.com/ee/api/index.html#path-parameters | ||
| 70 | + | ||
| 71 | + Path parameters that are required to be URL-encoded must be followed. If not, it | ||
| 72 | + doesn’t match an API endpoint and responds with a 404. If there’s something in front | ||
| 73 | + of the API (for example, Apache), ensure that it doesn’t decode the URL-encoded path | ||
| 74 | + parameters. | ||
| 75 | + | ||
| 76 | + """ | ||
| 77 | + return urllib.parse.quote(id, safe="") | ||
| 61 | 78 | ||
| 62 | 79 | ||
| 63 | 80 | def remove_none_from_dict(data: Dict[str, Any]) -> Dict[str, Any]: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -75,7 +75,7 @@ def _process_from_parent_attrs(self) -> None: | |||
| 75 | 75 | if key not in self.args: | |
| 76 | 76 | continue | |
| 77 | 77 | ||
| 78 | - self.parent_args[key] = gitlab.utils.clean_str_id(self.args[key]) | ||
| 78 | + self.parent_args[key] = gitlab.utils._url_encode(self.args[key]) | ||
| 79 | 79 | # If we don't delete it then it will be added to the URL as a query-string | |
| 80 | 80 | del self.args[key] | |
| 81 | 81 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -52,7 +52,8 @@ def set( | |||
| 52 | 52 | Returns: | |
| 53 | 53 | The created/updated attribute | |
| 54 | 54 | """ | |
| 55 | - path = f"{self.path}/{name.replace('/', '%2F')}" | ||
| 55 | + name = utils._url_encode(name) | ||
| 56 | + path = f"{self.path}/{name}" | ||
| 56 | 57 | data = { | |
| 57 | 58 | "value": value, | |
| 58 | 59 | "feature_group": feature_group, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -56,7 +56,7 @@ def save( # type: ignore | |||
| 56 | 56 | """ | |
| 57 | 57 | self.branch = branch | |
| 58 | 58 | self.commit_message = commit_message | |
| 59 | - self.file_path = self.file_path.replace("/", "%2F") | ||
| 59 | + self.file_path = utils._url_encode(self.file_path) | ||
| 60 | 60 | super(ProjectFile, self).save(**kwargs) | |
| 61 | 61 | ||
| 62 | 62 | @exc.on_http_error(exc.GitlabDeleteError) | |
@@ -76,7 +76,7 @@ def delete( # type: ignore | |||
| 76 | 76 | GitlabAuthenticationError: If authentication is not correct | |
| 77 | 77 | GitlabDeleteError: If the server cannot perform the request | |
| 78 | 78 | """ | |
| 79 | - file_path = self.get_id().replace("/", "%2F") | ||
| 79 | + file_path = utils._url_encode(self.get_id()) | ||
| 80 | 80 | self.manager.delete(file_path, branch, commit_message, **kwargs) | |
| 81 | 81 | ||
| 82 | 82 | ||
@@ -144,7 +144,7 @@ def create( | |||
| 144 | 144 | assert data is not None | |
| 145 | 145 | self._check_missing_create_attrs(data) | |
| 146 | 146 | new_data = data.copy() | |
| 147 | - file_path = new_data.pop("file_path").replace("/", "%2F") | ||
| 147 | + file_path = utils._url_encode(new_data.pop("file_path")) | ||
| 148 | 148 | path = f"{self.path}/{file_path}" | |
| 149 | 149 | server_data = self.gitlab.http_post(path, post_data=new_data, **kwargs) | |
| 150 | 150 | if TYPE_CHECKING: | |
@@ -173,7 +173,7 @@ def update( # type: ignore | |||
| 173 | 173 | """ | |
| 174 | 174 | new_data = new_data or {} | |
| 175 | 175 | data = new_data.copy() | |
| 176 | - file_path = file_path.replace("/", "%2F") | ||
| 176 | + file_path = utils._url_encode(file_path) | ||
| 177 | 177 | data["file_path"] = file_path | |
| 178 | 178 | path = f"{self.path}/{file_path}" | |
| 179 | 179 | self._check_missing_update_attrs(data) | |
@@ -203,7 +203,8 @@ def delete( # type: ignore | |||
| 203 | 203 | GitlabAuthenticationError: If authentication is not correct | |
| 204 | 204 | GitlabDeleteError: If the server cannot perform the request | |
| 205 | 205 | """ | |
| 206 | - path = f"{self.path}/{file_path.replace('/', '%2F')}" | ||
| 206 | + file_path = utils._url_encode(file_path) | ||
| 207 | + path = f"{self.path}/{file_path}" | ||
| 207 | 208 | data = {"branch": branch, "commit_message": commit_message} | |
| 208 | 209 | self.gitlab.http_delete(path, query_data=data, **kwargs) | |
| 209 | 210 | ||
@@ -238,7 +239,7 @@ def raw( | |||
| 238 | 239 | Returns: | |
| 239 | 240 | The file content | |
| 240 | 241 | """ | |
| 241 | - file_path = file_path.replace("/", "%2F").replace(".", "%2E") | ||
| 242 | + file_path = utils._url_encode(file_path) | ||
| 242 | 243 | path = f"{self.path}/{file_path}/raw" | |
| 243 | 244 | query_data = {"ref": ref} | |
| 244 | 245 | result = self.gitlab.http_get( | |
@@ -265,7 +266,7 @@ def blame(self, file_path: str, ref: str, **kwargs: Any) -> List[Dict[str, Any]] | |||
| 265 | 266 | Returns: | |
| 266 | 267 | A list of commits/lines matching the file | |
| 267 | 268 | """ | |
| 268 | - file_path = file_path.replace("/", "%2F").replace(".", "%2E") | ||
| 269 | + file_path = utils._url_encode(file_path) | ||
| 269 | 270 | path = f"{self.path}/{file_path}/blame" | |
| 270 | 271 | query_data = {"ref": ref} | |
| 271 | 272 | result = self.gitlab.http_list(path, query_data, **kwargs) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -39,7 +39,7 @@ def update_submodule( | |||
| 39 | 39 | GitlabPutError: If the submodule could not be updated | |
| 40 | 40 | """ | |
| 41 | 41 | ||
| 42 | - submodule = submodule.replace("/", "%2F") # .replace('.', '%2E') | ||
| 42 | + submodule = utils._url_encode(submodule) | ||
| 43 | 43 | path = f"/projects/{self.get_id()}/repository/submodules/{submodule}" | |
| 44 | 44 | data = {"branch": branch, "commit_sha": commit_sha} | |
| 45 | 45 | if "commit_message" in kwargs: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,4 +1,5 @@ | |||
| 1 | 1 | import base64 | |
| 2 | + import os | ||
| 2 | 3 | import sys | |
| 3 | 4 | import tarfile | |
| 4 | 5 | import time | |
@@ -13,13 +14,13 @@ | |||
| 13 | 14 | def test_repository_files(project): | |
| 14 | 15 | project.files.create( | |
| 15 | 16 | { | |
| 16 | - "file_path": "README", | ||
| 17 | + "file_path": "README.md", | ||
| 17 | 18 | "branch": "main", | |
| 18 | 19 | "content": "Initial content", | |
| 19 | 20 | "commit_message": "Initial commit", | |
| 20 | 21 | } | |
| 21 | 22 | ) | |
| 22 | - readme = project.files.get(file_path="README", ref="main") | ||
| 23 | + readme = project.files.get(file_path="README.md", ref="main") | ||
| 23 | 24 | readme.content = base64.b64encode(b"Improved README").decode() | |
| 24 | 25 | ||
| 25 | 26 | time.sleep(2) | |
@@ -42,6 +43,9 @@ def test_repository_files(project): | |||
| 42 | 43 | blame = project.files.blame(file_path="README.rst", ref="main") | |
| 43 | 44 | assert blame | |
| 44 | 45 | ||
| 46 | + raw_file = project.files.raw(file_path="README.rst", ref="main") | ||
| 47 | + assert os.fsdecode(raw_file) == "Initial content" | ||
| 48 | + | ||
| 45 | 49 | ||
| 46 | 50 | def test_repository_tree(project): | |
| 47 | 51 | tree = project.repository_tree() | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -18,15 +18,20 @@ | |||
| 18 | 18 | from gitlab import utils | |
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | - def test_clean_str_id(): | ||
| 21 | + def test_url_encode(): | ||
| 22 | 22 | src = "nothing_special" | |
| 23 | 23 | dest = "nothing_special" | |
| 24 | - assert dest == utils.clean_str_id(src) | ||
| 24 | + assert dest == utils._url_encode(src) | ||
| 25 | 25 | ||
| 26 | 26 | src = "foo#bar/baz/" | |
| 27 | 27 | dest = "foo%23bar%2Fbaz%2F" | |
| 28 | - assert dest == utils.clean_str_id(src) | ||
| 28 | + assert dest == utils._url_encode(src) | ||
| 29 | 29 | ||
| 30 | 30 | src = "foo%bar/baz/" | |
| 31 | 31 | dest = "foo%25bar%2Fbaz%2F" | |
| 32 | - assert dest == utils.clean_str_id(src) | ||
| 32 | + assert dest == utils._url_encode(src) | ||
| 33 | + | ||
| 34 | + # periods/dots should not be modified | ||
| 35 | + src = "docs/README.md" | ||
| 36 | + dest = "docs%2FREADME.md" | ||
| 37 | + assert dest == utils._url_encode(src) | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments