You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@paimon.apache.org by lz...@apache.org on 2026/04/27 06:32:17 UTC
(paimon) branch master updated: [python] Fix pathlib.Path producing backslashes paths on Windows (#7700)
This is an automated email from the ASF dual-hosted git repository.
JingsongLi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git
The following commit(s) were added to refs/heads/master by this push:
new cec7050bfb [python] Fix pathlib.Path producing backslashes paths on Windows (#7700)
cec7050bfb is described below
commit cec7050bfb1b43e5e5f8e842116520c91f8c2526
Author: XiaoHongbo <xi...@alibaba-inc.com>
AuthorDate: Mon Apr 27 14:32:12 2026 +0800
[python] Fix pathlib.Path producing backslashes paths on Windows (#7700)
---
.../pypaimon/filesystem/pyarrow_file_io.py | 12 +++++------
paimon-python/pypaimon/tests/file_io_test.py | 25 ++++++++++++++++++++++
2 files changed, 31 insertions(+), 6 deletions(-)
diff --git a/paimon-python/pypaimon/filesystem/pyarrow_file_io.py b/paimon-python/pypaimon/filesystem/pyarrow_file_io.py
index db06eb6f99..b5e03c0151 100644
--- a/paimon-python/pypaimon/filesystem/pyarrow_file_io.py
+++ b/paimon-python/pypaimon/filesystem/pyarrow_file_io.py
@@ -21,7 +21,7 @@ import re
import subprocess
import uuid
from datetime import datetime, timezone
-from pathlib import Path
+from pathlib import PurePosixPath
from typing import Any, Dict, List, Optional
from urllib.parse import splitport, urlparse
@@ -235,7 +235,7 @@ class PyArrowFileIO(FileIO):
if parent_dir and not self.exists(parent_dir):
self.mkdirs(parent_dir)
else:
- parent_dir = Path(path_str).parent
+ parent_dir = PurePosixPath(path_str).parent
if str(parent_dir) and not self.exists(str(parent_dir)):
self.mkdirs(str(parent_dir))
@@ -326,7 +326,7 @@ class PyArrowFileIO(FileIO):
def rename(self, src: str, dst: str) -> bool:
dst_str = self.to_filesystem_path(dst)
- dst_parent = Path(dst_str).parent
+ dst_parent = PurePosixPath(dst_str).parent
if str(dst_parent) and not self.exists(str(dst_parent)):
self.mkdirs(str(dst_parent))
@@ -342,8 +342,8 @@ class PyArrowFileIO(FileIO):
return False
# Make it compatible with HadoopFileIO: if dst is an existing directory,
# dst=dst/srcFileName
- src_name = Path(src_str).name
- dst_str = str(Path(dst_str) / src_name)
+ src_name = PurePosixPath(src_str).name
+ dst_str = str(PurePosixPath(dst_str) / src_name)
final_dst_info = self._get_file_info(dst_str)
if final_dst_info.type != pafs.FileType.NotFound:
return False
@@ -402,7 +402,7 @@ class PyArrowFileIO(FileIO):
source_str = self.to_filesystem_path(source_path)
target_str = self.to_filesystem_path(target_path)
- target_parent = Path(target_str).parent
+ target_parent = PurePosixPath(target_str).parent
if str(target_parent) and not self.exists(str(target_parent)):
self.mkdirs(str(target_parent))
diff --git a/paimon-python/pypaimon/tests/file_io_test.py b/paimon-python/pypaimon/tests/file_io_test.py
index d39d0c6461..86c4c28f82 100644
--- a/paimon-python/pypaimon/tests/file_io_test.py
+++ b/paimon-python/pypaimon/tests/file_io_test.py
@@ -464,5 +464,30 @@ class FileIOTest(unittest.TestCase):
finally:
shutil.rmtree(temp_dir, ignore_errors=True)
+ def test_path_on_windows(self):
+ oss_io = PyArrowFileIO("oss://test-bucket/warehouse", Options({
+ OssOptions.OSS_ENDPOINT.key(): 'oss-cn-hangzhou.aliyuncs.com',
+ OssOptions.OSS_ACCESS_KEY_ID.key(): 'test-key',
+ OssOptions.OSS_ACCESS_KEY_SECRET.key(): 'test-secret',
+ OssOptions.OSS_IMPL.key(): 'legacy',
+ }))
+ mock_fs = MagicMock()
+ mock_fs.get_file_info.return_value = [MagicMock(type=pafs.FileType.NotFound)]
+ mock_fs.create_dir = MagicMock()
+ mock_fs.open_output_stream.return_value = MagicMock()
+ mock_fs.move = MagicMock()
+ mock_fs.copy_file = MagicMock()
+ oss_io.filesystem = mock_fs
+
+ oss_io.new_output_stream("oss://test-bucket/db.db/tbl/bucket-0/data.parquet")
+ oss_io.rename("oss://test-bucket/db.db/tbl/old.parquet",
+ "oss://test-bucket/db.db/tbl/new.parquet")
+ oss_io.copy_file("oss://test-bucket/db.db/tbl/src.parquet",
+ "oss://test-bucket/db.db/tbl/dst.parquet")
+
+ for call in mock_fs.create_dir.call_args_list:
+ self.assertNotIn("\\", call[0][0], f"backslash in path: {call[0][0]}")
+
+
if __name__ == '__main__':
unittest.main()