Skip to content

Commit f29e3bb

Browse files
authored
files: added url quote to mkdir and delete (#192)
Fixes #191 . Looks like this error was introduced in `0.7.0` version, where I refactored all code. _Fixed and adjusted tests suite to detect this_ --------- Signed-off-by: Alexander Piskun <[email protected]>
1 parent 549f058 commit f29e3bb

File tree

4 files changed

+19
-8
lines changed

4 files changed

+19
-8
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@
22

33
All notable changes to this project will be documented in this file.
44

5-
## [0.7.1 - 2022-12-2x]
5+
## [0.7.2 - 2022-12-27]
6+
7+
### Fixed
8+
9+
- files: proper url encoding of special chars in `mkdir` and `delete` methods. #191 Thanks to @tobenary
10+
11+
## [0.7.1 - 2022-12-21]
612

713
### Added
814

nc_py_api/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""Version of nc_py_api."""
22

3-
__version__ = "0.7.1"
3+
__version__ = "0.7.2.dev0"

nc_py_api/files/files.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import builtins
44
import os
55
from pathlib import Path
6+
from urllib.parse import quote
67

78
from httpx import Headers
89

@@ -166,7 +167,7 @@ def mkdir(self, path: str | FsNode) -> FsNode:
166167
"""
167168
path = path.user_path if isinstance(path, FsNode) else path
168169
full_path = dav_get_obj_path(self._session.user, path)
169-
response = self._session.adapter_dav.request("MKCOL", full_path)
170+
response = self._session.adapter_dav.request("MKCOL", quote(full_path))
170171
check_error(response)
171172
full_path += "/" if not full_path.endswith("/") else ""
172173
return FsNode(full_path.lstrip("/"), **etag_fileid_from_response(response))
@@ -201,7 +202,7 @@ def delete(self, path: str | FsNode, not_fail=False) -> None:
201202
:param not_fail: if set to ``True`` and the object is not found, it does not raise an exception.
202203
"""
203204
path = path.user_path if isinstance(path, FsNode) else path
204-
response = self._session.adapter_dav.delete(dav_get_obj_path(self._session.user, path))
205+
response = self._session.adapter_dav.delete(quote(dav_get_obj_path(self._session.user, path)))
205206
if response.status_code == 404 and not_fail:
206207
return
207208
check_error(response)
@@ -630,7 +631,7 @@ async def mkdir(self, path: str | FsNode) -> FsNode:
630631
"""
631632
path = path.user_path if isinstance(path, FsNode) else path
632633
full_path = dav_get_obj_path(await self._session.user, path)
633-
response = await self._session.adapter_dav.request("MKCOL", full_path)
634+
response = await self._session.adapter_dav.request("MKCOL", quote(full_path))
634635
check_error(response)
635636
full_path += "/" if not full_path.endswith("/") else ""
636637
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:
665666
:param not_fail: if set to ``True`` and the object is not found, it does not raise an exception.
666667
"""
667668
path = path.user_path if isinstance(path, FsNode) else path
668-
response = await self._session.adapter_dav.delete(dav_get_obj_path(await self._session.user, path))
669+
response = await self._session.adapter_dav.delete(quote(dav_get_obj_path(await self._session.user, path)))
669670
if response.status_code == 404 and not_fail:
670671
return
671672
check_error(response)

tests/actual_tests/files_test.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -452,31 +452,35 @@ async def test_file_upload_chunked_zero_size_async(anc_any, file_name):
452452
await anc_any.files.delete(f"/test_dir_tmp/{file_name}", not_fail=True)
453453

454454

455-
@pytest.mark.parametrize("dir_name", ("1 2", "Яё", "відео та картинки", "复杂 目录 Í", "Björn", "João"))
455+
@pytest.mark.parametrize("dir_name", ("1 2", "Яё", "відео та картинки", "复杂 目录 Í", "Björn", "João", "1##3"))
456456
def test_mkdir(nc_any, dir_name):
457457
nc_any.files.delete(dir_name, not_fail=True)
458458
result = nc_any.files.mkdir(dir_name)
459459
assert result.is_dir
460460
assert not result.has_extra
461+
result_by_id = nc_any.files.by_id(result.file_id)
461462
with pytest.raises(NextcloudException):
462463
nc_any.files.mkdir(dir_name)
463464
nc_any.files.delete(dir_name)
464465
with pytest.raises(NextcloudException):
465466
nc_any.files.delete(dir_name)
467+
assert result_by_id.full_path == result.full_path
466468

467469

468470
@pytest.mark.asyncio(scope="session")
469-
@pytest.mark.parametrize("dir_name", ("1 2", "Яё", "відео та картинки", "复杂 目录 Í", "Björn", "João"))
471+
@pytest.mark.parametrize("dir_name", ("1 2", "Яё", "відео та картинки", "复杂 目录 Í", "Björn", "João", "1##3"))
470472
async def test_mkdir_async(anc_any, dir_name):
471473
await anc_any.files.delete(dir_name, not_fail=True)
472474
result = await anc_any.files.mkdir(dir_name)
473475
assert result.is_dir
474476
assert not result.has_extra
477+
result_by_id = await anc_any.files.by_id(result.file_id)
475478
with pytest.raises(NextcloudException):
476479
await anc_any.files.mkdir(dir_name)
477480
await anc_any.files.delete(dir_name)
478481
with pytest.raises(NextcloudException):
479482
await anc_any.files.delete(dir_name)
483+
assert result_by_id.full_path == result.full_path
480484

481485

482486
def test_mkdir_invalid_args(nc_any):

0 commit comments

Comments
 (0)