From 4283481695b4f992403987446f550a647428656d Mon Sep 17 00:00:00 2001 From: Yoshihiro OKUMURA Date: Mon, 20 Apr 2026 12:25:59 +0900 Subject: [PATCH] fix: apply NFC normalization to filenames and folder names sent to server On macOS, local filenames and directory names may be in NFD encoding (decomposed Unicode). Without normalization, files and folders are created on the server with NFD names, inconsistent with the server's NFC convention. Apply normalize("NFC", ...) before sending names to the server in: - FilesApi.create(): filename in multipart upload - FilesApi.update(): filename in multipart upload - UploadCommand: directory name in FoldersApi.create() Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- mdrsclient/api/files.py | 5 +++-- mdrsclient/commands/upload.py | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/mdrsclient/api/files.py b/mdrsclient/api/files.py index 4e75e9e..e047a9d 100644 --- a/mdrsclient/api/files.py +++ b/mdrsclient/api/files.py @@ -1,6 +1,7 @@ import mimetypes import os from typing import Any, Final +from unicodedata import normalize from pydantic import TypeAdapter from pydantic.dataclasses import dataclass @@ -53,7 +54,7 @@ class FilesApi(BaseApi): try: with open(os.path.realpath(path), mode="rb") as fp: data = MultipartEncoder( - fields={"folder_id": folder_id, "file": (os.path.basename(path), fp, self._get_mime_type(path))} + fields={"folder_id": folder_id, "file": (normalize("NFC", os.path.basename(path)), fp, self._get_mime_type(path))} ) response = self.connection.post(url, data=data, headers={"Content-Type": data.content_type}) self._raise_response_error(response) @@ -75,7 +76,7 @@ class FilesApi(BaseApi): # update file body try: with open(os.path.realpath(path), mode="rb") as fp: - data = MultipartEncoder(fields={"file": (os.path.basename(path), fp, self._get_mime_type(path))}) + data = MultipartEncoder(fields={"file": (normalize("NFC", os.path.basename(path)), fp, self._get_mime_type(path))}) response = self.connection.put(url, data=data, headers={"Content-Type": data.content_type}) except OSError: raise UnexpectedException(f"Could not open `{path}` file.") diff --git a/mdrsclient/commands/upload.py b/mdrsclient/commands/upload.py index 379ba65..6f82ebd 100644 --- a/mdrsclient/commands/upload.py +++ b/mdrsclient/commands/upload.py @@ -2,6 +2,7 @@ import os from argparse import Namespace from concurrent.futures import ThreadPoolExecutor from typing import Any +from unicodedata import normalize from pydantic.dataclasses import dataclass @@ -81,7 +82,7 @@ class UploadCommand(BaseCommand): if folder_map.get(d_dirname) is None: d_folder = folder_map[d_parent_dirname].find_sub_folder(d_basename) if d_folder is None: - d_folder_id = folder_api.create(d_basename, folder_map[d_parent_dirname].id) + d_folder_id = folder_api.create(normalize("NFC", d_basename), folder_map[d_parent_dirname].id) else: d_folder_id = d_folder.id print(d_dirname)