diff --git a/src/wslPath/__init__.py b/src/wslPath/__init__.py index 482565d..d6e8966 100644 --- a/src/wslPath/__init__.py +++ b/src/wslPath/__init__.py @@ -2,4 +2,4 @@ .. include:: ../../README.md """ -from .main import * \ No newline at end of file +from .main import * diff --git a/src/wslPath/main.py b/src/wslPath/main.py index 398e694..09427a3 100644 --- a/src/wslPath/main.py +++ b/src/wslPath/main.py @@ -1,10 +1,13 @@ from __future__ import annotations import re +import sys from pathlib import Path, WindowsPath + """Convert between Linux and Windows path in WSL (Windows Subsystem for Linux). """ + def is_windows_path(path: str | Path) -> bool: """Determine if the given path is in Windows format.""" path = str(path) @@ -12,7 +15,7 @@ def is_windows_path(path: str | Path) -> bool: if path == ".": return True # Check for drive letter and backslashes - return bool(re.match(r'^[A-Za-z]:\\', path)) or '\\' in path + return bool(re.match(r"^[A-Za-z]:\\", path)) or "\\" in path def is_posix_path(path: str | Path) -> bool: @@ -21,7 +24,7 @@ def is_posix_path(path: str | Path) -> bool: # Check for the current directory if path == ".": return True - return '/' in path and not '\\' in path + return "/" in path and "\\" not in path def has_invalid_windows_path_chars(path: str | Path) -> bool: @@ -29,20 +32,22 @@ def has_invalid_windows_path_chars(path: str | Path) -> bool: path = str(path) # Check for invalid characters in filenames or directory names invalid_chars_pattern = re.compile(r'[\^<>"|?*]') - invalid_backslash = re.compile(r'(?<=[^A-Za-z0-9]):|:(?=[^\\])') + invalid_backslash = re.compile(r"(?<=[^A-Za-z0-9]):|:(?=[^\\])") ascii_control_chars = any(ord(char) < 32 for char in path) - invalid_colon = re.search(r'^(?![A-Za-z]:\\).*:', path) + invalid_colon = re.search(r"^(?![A-Za-z]:\\).*:", path) return bool( - invalid_chars_pattern.search(path) or - ascii_control_chars or - invalid_colon or - invalid_backslash.search(path) + invalid_chars_pattern.search(path) + or ascii_control_chars + or invalid_colon + or invalid_backslash.search(path) ) + ########################################################### # main ########################################################### + def to_posix(path: str | Path) -> str | Path: """Convert a Windows path to a POSIX path Examples: @@ -94,7 +99,6 @@ def to_windows(path: str | Path) -> str | Path: if has_invalid_windows_path_chars(path): raise ValueError(f"{path} includes invalid filepath characters on Windows") - if not is_posix_path(path) and not isinstance(path, WindowsPath): raise ValueError(f"{path} is not a POSIX path") @@ -115,4 +119,27 @@ def to_windows(path: str | Path) -> str | Path: return path - +def wslpath(path: str | Path) -> str | Path: + """Convert a path to the appropriate format for the current platform. + Examples: + >>> import wslPath + >>> # If the current platform is Windows and the path is POSIX, convert to Windows path + >>> wslPath.wslpath("hoge/fuga") + hoge\\fuga + >>> # If the current platform is Windows and the path is Windows, return the path as is + >>> wslPath.wslpath("hoge\\fuga") + hoge\\fuga + >>> # If the current platform is Linux and the path is Windows, convert to POSIX path + >>> wslPath.wslpath("hoge\\fuga") + hoge/fuga + >>> # If the current platform is Linux and the path is POSIX, return the path as is + >>> wslPath.wslpath("hoge/fuga") + hoge/fuga + """ + if sys.platform == "win32": + if not is_windows_path(path): + path = to_windows(path) + else: + if not is_posix_path(path): + path = to_posix(path) + return path diff --git a/tests/test_wslpath.py b/tests/test_wslpath.py index 40a8b71..f9f4078 100644 --- a/tests/test_wslpath.py +++ b/tests/test_wslpath.py @@ -1,9 +1,12 @@ -import pytest +from __future__ import annotations +import pytest +import sys from pathlib import Path from src.wslPath import to_posix from src.wslPath import to_windows from src.wslPath import has_invalid_windows_path_chars +from src.wslPath import wslpath def test_valid_paths(): @@ -54,7 +57,10 @@ def test_to_posix_absolute(): def test_to_posix_including_file(): - assert to_posix("C:\\Users\\user\\Documents\\file.txt") == "/mnt/c/Users/user/Documents/file.txt" + assert ( + to_posix("C:\\Users\\user\\Documents\\file.txt") + == "/mnt/c/Users/user/Documents/file.txt" + ) ################################ @@ -84,7 +90,7 @@ def test_to_windows_relatives3(): assert to_windows(r"hoge////fuga") == "hoge\\fuga" -def test_to_windows_relatives3(): +def test_to_windows_relatives4(): assert to_windows(r"./hoge////fuga") == ".\\hoge\\fuga" @@ -97,4 +103,26 @@ def test_to_windows_path_object(): def test_to_windows_including_file(): - assert to_windows("/mnt/c/Users/user/Documents/file.txt") == "C:\\Users\\user\\Documents\\file.txt" + assert ( + to_windows("/mnt/c/Users/user/Documents/file.txt") + == "C:\\Users\\user\\Documents\\file.txt" + ) + + +@pytest.mark.parametrize( + "input_path, expected, platform", + [ + ("hoge/fuga", "hoge\\fuga", "win32"), # POSIX -> Windows on Windows + ( + "hoge\\fuga", + "hoge\\fuga", + "win32", + ), # Windows -> Windows on Windows (no change) + ("hoge\\fuga", "hoge/fuga", "linux"), # Windows -> POSIX on Linux + ("hoge/fuga", "hoge/fuga", "linux"), # POSIX -> POSIX on Linux (no change) + ], +) +def test_wslpath(input_path, expected, platform, monkeypatch): + monkeypatch.setattr(sys, "platform", platform) + result = wslpath(input_path) + assert result == expected