Skip to content

Commit

Permalink
Add wslpath to convert a path to the appropriate format for the curre…
Browse files Browse the repository at this point in the history
…nt platform #1
  • Loading branch information
akikuno committed Aug 31, 2024
1 parent 86b71a3 commit fe4d627
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 15 deletions.
2 changes: 1 addition & 1 deletion src/wslPath/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
.. include:: ../../README.md
"""

from .main import *
from .main import *
47 changes: 37 additions & 10 deletions src/wslPath/main.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
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)
# Check for the current directory
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:
Expand All @@ -21,28 +24,30 @@ 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:
"""Check if the given path contains invalid Windows path characters."""
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:
Expand Down Expand Up @@ -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")

Expand All @@ -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
36 changes: 32 additions & 4 deletions tests/test_wslpath.py
Original file line number Diff line number Diff line change
@@ -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():
Expand Down Expand Up @@ -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"
)


################################
Expand Down Expand Up @@ -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"


Expand All @@ -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

0 comments on commit fe4d627

Please sign in to comment.