From 1d6ae7eecea7e772939c16201fb783b639fef7b2 Mon Sep 17 00:00:00 2001 From: Alexander Piskun Date: Tue, 26 Dec 2023 23:29:03 +0300 Subject: [PATCH 1/2] files: added url quote to mkdir and delete Signed-off-by: Alexander Piskun --- nc_py_api/files/files.py | 9 +++++---- tests/actual_tests/files_test.py | 8 ++++++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/nc_py_api/files/files.py b/nc_py_api/files/files.py index 2aae929d..6fa76f09 100644 --- a/nc_py_api/files/files.py +++ b/nc_py_api/files/files.py @@ -3,6 +3,7 @@ import builtins import os from pathlib import Path +from urllib.parse import quote from httpx import Headers @@ -166,7 +167,7 @@ def mkdir(self, path: str | FsNode) -> FsNode: """ path = path.user_path if isinstance(path, FsNode) else path full_path = dav_get_obj_path(self._session.user, path) - response = self._session.adapter_dav.request("MKCOL", full_path) + response = self._session.adapter_dav.request("MKCOL", quote(full_path)) check_error(response) full_path += "/" if not full_path.endswith("/") else "" return FsNode(full_path.lstrip("/"), **etag_fileid_from_response(response)) @@ -201,7 +202,7 @@ def delete(self, path: str | FsNode, not_fail=False) -> None: :param not_fail: if set to ``True`` and the object is not found, it does not raise an exception. """ path = path.user_path if isinstance(path, FsNode) else path - response = self._session.adapter_dav.delete(dav_get_obj_path(self._session.user, path)) + response = self._session.adapter_dav.delete(quote(dav_get_obj_path(self._session.user, path))) if response.status_code == 404 and not_fail: return check_error(response) @@ -630,7 +631,7 @@ async def mkdir(self, path: str | FsNode) -> FsNode: """ path = path.user_path if isinstance(path, FsNode) else path full_path = dav_get_obj_path(await self._session.user, path) - response = await self._session.adapter_dav.request("MKCOL", full_path) + response = await self._session.adapter_dav.request("MKCOL", quote(full_path)) check_error(response) full_path += "/" if not full_path.endswith("/") else "" return FsNode(full_path.lstrip("/"), **etag_fileid_from_response(response)) @@ -665,7 +666,7 @@ async def delete(self, path: str | FsNode, not_fail=False) -> None: :param not_fail: if set to ``True`` and the object is not found, it does not raise an exception. """ path = path.user_path if isinstance(path, FsNode) else path - response = await self._session.adapter_dav.delete(dav_get_obj_path(await self._session.user, path)) + response = await self._session.adapter_dav.delete(quote(dav_get_obj_path(await self._session.user, path))) if response.status_code == 404 and not_fail: return check_error(response) diff --git a/tests/actual_tests/files_test.py b/tests/actual_tests/files_test.py index 720dc630..1a25828e 100644 --- a/tests/actual_tests/files_test.py +++ b/tests/actual_tests/files_test.py @@ -452,31 +452,35 @@ async def test_file_upload_chunked_zero_size_async(anc_any, file_name): await anc_any.files.delete(f"/test_dir_tmp/{file_name}", not_fail=True) -@pytest.mark.parametrize("dir_name", ("1 2", "Яё", "відео та картинки", "复杂 目录 Í", "Björn", "João")) +@pytest.mark.parametrize("dir_name", ("1 2", "Яё", "відео та картинки", "复杂 目录 Í", "Björn", "João", "1##3")) def test_mkdir(nc_any, dir_name): nc_any.files.delete(dir_name, not_fail=True) result = nc_any.files.mkdir(dir_name) assert result.is_dir assert not result.has_extra + result_by_id = nc_any.files.by_id(result.file_id) with pytest.raises(NextcloudException): nc_any.files.mkdir(dir_name) nc_any.files.delete(dir_name) with pytest.raises(NextcloudException): nc_any.files.delete(dir_name) + assert result_by_id.full_path == result.full_path @pytest.mark.asyncio(scope="session") -@pytest.mark.parametrize("dir_name", ("1 2", "Яё", "відео та картинки", "复杂 目录 Í", "Björn", "João")) +@pytest.mark.parametrize("dir_name", ("1 2", "Яё", "відео та картинки", "复杂 目录 Í", "Björn", "João", "1##3")) async def test_mkdir_async(anc_any, dir_name): await anc_any.files.delete(dir_name, not_fail=True) result = await anc_any.files.mkdir(dir_name) assert result.is_dir assert not result.has_extra + result_by_id = await anc_any.files.by_id(result.file_id) with pytest.raises(NextcloudException): await anc_any.files.mkdir(dir_name) await anc_any.files.delete(dir_name) with pytest.raises(NextcloudException): await anc_any.files.delete(dir_name) + assert result_by_id.full_path == result.full_path def test_mkdir_invalid_args(nc_any): From 4c4608699b835a67057537b48824d38826bc5b3f Mon Sep 17 00:00:00 2001 From: Alexander Piskun Date: Tue, 26 Dec 2023 23:36:12 +0300 Subject: [PATCH 2/2] updated changelog Signed-off-by: Alexander Piskun --- CHANGELOG.md | 8 +++++++- nc_py_api/_version.py | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cb730c9..0d43dc11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,13 @@ All notable changes to this project will be documented in this file. -## [0.7.1 - 2022-12-2x] +## [0.7.2 - 2022-12-27] + +### Fixed + +- files: proper url encoding of special chars in `mkdir` and `delete` methods. #191 Thanks to @tobenary + +## [0.7.1 - 2022-12-21] ### Added diff --git a/nc_py_api/_version.py b/nc_py_api/_version.py index 5a05dfb4..4c5728bd 100644 --- a/nc_py_api/_version.py +++ b/nc_py_api/_version.py @@ -1,3 +1,3 @@ """Version of nc_py_api.""" -__version__ = "0.7.1" +__version__ = "0.7.2.dev0"