from __future__ import absolute_import
import ctypes
import posixpath
import os
import re
import sys
def normsep(path):
if os.sep != '/':
path = path.replace(os.sep, '/')
if os.altsep and os.altsep != '/':
path = path.replace(os.altsep, '/')
return path
def relpath(path, start):
rel = normsep(os.path.relpath(path, start))
return '' if rel == '.' else rel
def realpath(path):
return normsep(os.path.realpath(path))
def abspath(path):
return normsep(os.path.abspath(path))
def join(*paths):
return normsep(os.path.join(*paths))
def normpath(path):
return posixpath.normpath(normsep(path))
def dirname(path):
return posixpath.dirname(normsep(path))
def commonprefix(paths):
return posixpath.commonprefix([normsep(path) for path in paths])
def basename(path):
return os.path.basename(path)
def splitext(path):
return posixpath.splitext(normsep(path))
def split(path):
return normsep(path).split('/')
def basedir(path, bases):
path = normsep(path)
bases = [normsep(b) for b in bases]
if path in bases:
return path
for b in sorted(bases, reverse=True):
if b == '' or path.startswith(b + '/'):
return b
re_cache = {}
def match(path, pattern):
if not pattern:
return True
if pattern not in re_cache:
p = re.escape(pattern)
p = re.sub(r'(^|\\\/)\\\*\\\*\\\/', r'\1(?:.+/)?', p)
p = re.sub(r'(^|\\\/)\\\*\\\*$', r'(?:\1.+)?', p)
p = p.replace(r'\*', '[^/]*') + '(?:/.*)?$'
re_cache[pattern] = re.compile(p)
return re_cache[pattern].match(path) is not None
def rebase(oldbase, base, relativepath):
if base == oldbase:
return relativepath
if len(base) < len(oldbase):
assert basedir(oldbase, [base]) == base
relbase = relpath(oldbase, base)
result = join(relbase, relativepath)
else:
assert basedir(base, [oldbase]) == oldbase
relbase = relpath(base, oldbase)
result = relpath(relativepath, relbase)
result = normpath(result)
if relativepath.endswith('/') and not result.endswith('/'):
result += '/'
return result
def readlink(path):
if hasattr(os, 'readlink'):
return normsep(os.readlink(path))
assert sys.platform == 'win32'
CreateFileW = ctypes.windll.kernel32.CreateFileW
CreateFileW.argtypes = [
ctypes.wintypes.LPCWSTR,
ctypes.wintypes.DWORD,
ctypes.wintypes.DWORD,
ctypes.wintypes.LPVOID,
ctypes.wintypes.DWORD,
ctypes.wintypes.DWORD,
ctypes.wintypes.HANDLE,
]
CreateFileW.restype = ctypes.wintypes.HANDLE
GENERIC_READ = 0x80000000
FILE_SHARE_READ = 0x00000001
OPEN_EXISTING = 3
FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, 0)
assert handle != 1, 'Failed getting a handle to: {}'.format(path)
MAX_PATH = 260
buf = ctypes.create_unicode_buffer(MAX_PATH)
GetFinalPathNameByHandleW = ctypes.windll.kernel32.GetFinalPathNameByHandleW
GetFinalPathNameByHandleW.argtypes = [
ctypes.wintypes.HANDLE,
ctypes.wintypes.LPWSTR,
ctypes.wintypes.DWORD,
ctypes.wintypes.DWORD,
]
GetFinalPathNameByHandleW.restype = ctypes.wintypes.DWORD
FILE_NAME_NORMALIZED = 0x0
rv = GetFinalPathNameByHandleW(handle, buf, MAX_PATH, FILE_NAME_NORMALIZED)
assert rv != 0 and rv <= MAX_PATH, 'Failed getting final path for: {}'.format(path)
CloseHandle = ctypes.windll.kernel32.CloseHandle
CloseHandle.argtypes = [ctypes.wintypes.HANDLE]
CloseHandle.restype = ctypes.wintypes.BOOL
rv = CloseHandle(handle)
assert rv != 0, 'Failed closing handle'
return normsep(buf.value[4:])