-
Notifications
You must be signed in to change notification settings - Fork 5
/
winpathlib.py
47 lines (39 loc) · 1.55 KB
/
winpathlib.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# Copyright (C) 2019-2020 Patryk Obara <[email protected]>
# SPDX-License-Identifier: GPL-2.0-or-later
"""
Module providing conversion between DOS/Windows and Posix paths.
"""
import os
import pathlib
def to_posix_path(windows_path_str, *, strict=True):
"""Convert a string representing case-insensitive path to a posix path
to an existing file or directory.
Return None when there's no file nor directory, that could be
referenced as this windows path.
If windows path is ambiguous and can be mapped to more than one
file, then raise FileNotFoundError. When strict is set to False, then
first file will be returned instead.
"""
if windows_path_str == '.':
return '.'
win_path = pathlib.PureWindowsPath(windows_path_str)
paths = __posix_paths_matching__(win_path.parts)
path_1 = next(paths, None)
path_2 = next(paths, None)
if strict and path_2 is not None:
err = "Windows path '{}' is ambiguous. " \
"It can be '{}' or '{}'.".format(win_path, path_1, path_2)
raise FileNotFoundError(err)
return path_1
def __posix_paths_matching__(parts):
if parts == ():
yield ''
return
prefix_parts, last_part = parts[:-1], parts[-1]
for prefix in __posix_paths_matching__(prefix_parts):
if last_part in ('.', '..'):
yield os.path.join(prefix, last_part)
continue
for candidate in os.listdir(prefix or '.'):
if candidate.casefold() == last_part.casefold():
yield os.path.join(prefix, candidate)