def test_nt_helpers(self): # Trivial validation that the helpers do not break, and support both # unicode and bytes (UTF-8) paths executable = nt._getfinalpathname(sys.executable) for path in executable, os.fsencode(executable): volume_path = nt._getvolumepathname(path) path_drive = ntpath.splitdrive(path)[0] volume_path_drive = ntpath.splitdrive(volume_path)[0] self.assertEqualCI(path_drive, volume_path_drive) cap, free = nt._getdiskusage(sys.exec_prefix) self.assertGreater(cap, 0) self.assertGreater(free, 0) b_cap, b_free = nt._getdiskusage(sys.exec_prefix.encode()) # Free space may change, so only test the capacity is equal self.assertEqual(b_cap, cap) self.assertGreater(b_free, 0) for path in [sys.prefix, sys.executable]: final_path = nt._getfinalpathname(path) self.assertIsInstance(final_path, str) self.assertGreater(len(final_path), 0) b_final_path = nt._getfinalpathname(path.encode()) self.assertIsInstance(b_final_path, bytes) self.assertGreater(len(b_final_path), 0)
def test_nt_helpers(self): # Trivial validation that the helpers do not break, and support both # unicode and bytes (UTF-8) paths drive, path = ntpath.splitdrive(sys.executable) drive = drive.rstrip(ntpath.sep) + ntpath.sep self.assertEqual(drive, nt._getvolumepathname(sys.executable)) self.assertEqual(drive.encode(), nt._getvolumepathname(sys.executable.encode())) cap, free = nt._getdiskusage(sys.exec_prefix) self.assertGreater(cap, 0) self.assertGreater(free, 0) b_cap, b_free = nt._getdiskusage(sys.exec_prefix.encode()) # Free space may change, so only test the capacity is equal self.assertEqual(b_cap, cap) self.assertGreater(b_free, 0) for path in [sys.prefix, sys.executable]: final_path = nt._getfinalpathname(path) self.assertIsInstance(final_path, str) self.assertGreater(len(final_path), 0) b_final_path = nt._getfinalpathname(path.encode()) self.assertIsInstance(b_final_path, bytes) self.assertGreater(len(b_final_path), 0)
def _getfinalpathname_nonstrict(path): # Fast path to get the final path name. If this succeeds, there # is no need to go any further. try: return _getfinalpathname(path) except OSError: pass # Allow file (2) or directory (3) not found, invalid syntax (123), # and symlinks that cannot be followed (1921) allowed_winerror = 2, 3, 123, 1921 # Non-strict algorithm is to find as much of the target directory # as we can and join the rest. tail = '' seen = set() while path: try: path = _readlink_deep(path, seen) path = _getfinalpathname(path) return join(path, tail) if tail else path except OSError as ex: if ex.winerror not in allowed_winerror: raise path, name = split(path) if path and not name: return abspath(path + tail) tail = join(name, tail) if tail else name return abspath(tail)
def resolve(self, path, strict=False): s = str(path) if not s: return os.getcwd() previous_s = None if _getfinalpathname is not None: if strict: return self._ext_to_normal(_getfinalpathname(s)) else: while True: try: s = self._ext_to_normal(_getfinalpathname(s)) except FileNotFoundError: previous_s = s s = os.path.dirname(s) if previous_s == s: return path else: if previous_s is None: return s else: return s + os.path.sep + os.path.basename( previous_s) # Means fallback on absolute return None
def realpath(path, *, strict=False): path = normpath(path) if isinstance(path, bytes): prefix = b'\\\\?\\' unc_prefix = b'\\\\?\\UNC\\' new_unc_prefix = b'\\\\' cwd = os.getcwdb() # bpo-38081: Special case for realpath(b'nul') if normcase(path) == normcase(os.fsencode(devnull)): return b'\\\\.\\NUL' else: prefix = '\\\\?\\' unc_prefix = '\\\\?\\UNC\\' new_unc_prefix = '\\\\' cwd = os.getcwd() # bpo-38081: Special case for realpath('nul') if normcase(path) == normcase(devnull): return '\\\\.\\NUL' had_prefix = path.startswith(prefix) if not had_prefix and not isabs(path): path = join(cwd, path) try: path = _getfinalpathname(path) initial_winerror = 0 except OSError as ex: if strict: raise initial_winerror = ex.winerror path = _getfinalpathname_nonstrict(path) # The path returned by _getfinalpathname will always start with \\?\ - # strip off that prefix unless it was already provided on the original # path. if not had_prefix and path.startswith(prefix): # For UNC paths, the prefix will actually be \\?\UNC\ # Handle that case as well. if path.startswith(unc_prefix): spath = new_unc_prefix + path[len(unc_prefix):] else: spath = path[len(prefix):] # Ensure that the non-prefixed path resolves to the same path try: if _getfinalpathname(spath) == path: path = spath except OSError as ex: # If the path does not exist and originally did not exist, then # strip the prefix anyway. if ex.winerror == initial_winerror: path = spath return path
def realpath(path): """Resolve symlinks and return real path to file. Note: This is a fix for the issue of `os.path.realpath()` not to resolve symlinks on Windows as it is an alias to `os.path.abspath()` only. see: http://bugs.python.org/issue9949 This fix applies to local paths only as symlinks are not resolved by _getfinalpathname on network drives anyway. Also note that _getfinalpathname in Python 3.3 throws `NotImplementedError` on Windows versions prior to Windows Vista, hence we fallback to `os.path.abspath()` on these platforms. Arguments: path (string): The path to resolve. Returns: string: The resolved absolute path if exists or path as provided otherwise. """ try: if path: real_path = _getfinalpathname(path) if real_path[5] == ':': # Remove \\?\ from beginning of resolved path return real_path[4:] return os.path.abspath(path) except FileNotFoundError: pass return path
def realpath(path): path = normpath(path) if isinstance(path, bytes): prefix = b'\\\\?\\' unc_prefix = b'\\\\?\\UNC\\' new_unc_prefix = b'\\\\' cwd = os.getcwdb() else: prefix = '\\\\?\\' unc_prefix = '\\\\?\\UNC\\' new_unc_prefix = '\\\\' cwd = os.getcwd() did_not_exist = not exists(path) had_prefix = path.startswith(prefix) path = _getfinalpathname_nonstrict(path) # The path returned by _getfinalpathname will always start with \\?\ - # strip off that prefix unless it was already provided on the original # path. if not had_prefix and path.startswith(prefix): # For UNC paths, the prefix will actually be \\?\UNC\ # Handle that case as well. if path.startswith(unc_prefix): spath = new_unc_prefix + path[len(unc_prefix):] else: spath = path[len(prefix):] # Ensure that the non-prefixed path resolves to the same path try: if _getfinalpathname(spath) == path: path = spath except OSError as ex: # If the path does not exist and originally did not exist, then # strip the prefix anyway. if ex.winerror in {2, 3} and did_not_exist: path = spath return path
def resolve(self, path): s = str(path) if not s: return os.getcwd() if _getfinalpathname is not None: return self._ext_to_normal(_getfinalpathname(s)) # Means fallback on absolute return None
def _getfinalpathname_nonstrict(path): # Fast path to get the final path name. If this succeeds, there # is no need to go any further. try: return _getfinalpathname(path) except OSError: pass # These error codes indicate that we should stop resolving the path # and return the value we currently have. # 1: ERROR_INVALID_FUNCTION # 2: ERROR_FILE_NOT_FOUND # 3: ERROR_DIRECTORY_NOT_FOUND # 5: ERROR_ACCESS_DENIED # 21: ERROR_NOT_READY (implies drive with no media) # 32: ERROR_SHARING_VIOLATION (probably an NTFS paging file) # 50: ERROR_NOT_SUPPORTED # 67: ERROR_BAD_NET_NAME (implies remote server unavailable) # 87: ERROR_INVALID_PARAMETER # 123: ERROR_INVALID_NAME # 1921: ERROR_CANT_RESOLVE_FILENAME (implies unfollowable symlink) allowed_winerror = 1, 2, 3, 5, 21, 32, 50, 67, 87, 123, 1921 # Non-strict algorithm is to find as much of the target directory # as we can and join the rest. tail = '' seen = set() while path: try: path = _readlink_deep(path, seen) path = _getfinalpathname(path) return join(path, tail) if tail else path except OSError as ex: if ex.winerror not in allowed_winerror: raise path, name = split(path) # TODO (bpo-38186): Request the real file name from the directory # entry using FindFirstFileW. For now, we will return the path # as best we have it if path and not name: return abspath(path + tail) tail = join(name, tail) if tail else name return abspath(tail)
def samefile(file1, file2): """ Test whether two pathnames reference the same actual file This is a workaround for the fact that some platforms do not have os.path.samefile (particularly windows). This is the patch that was integrated in python 3.0 (at which time we can probably remove this workaround). """ try: return os.path.samefile(file1, file2) except AttributeError: try: from nt import _getfinalpathname return _getfinalpathname(file1) == _getfinalpathname(file2) except (NotImplementedError, ImportError): # On Windows XP and earlier, two files are the same if their # absolute pathnames are the same. # Also, on other operating systems, fake this method with a # Windows-XP approximation. return os.path.abspath(file1) == os.path.abspath(file2)
def realpath(path): path = os.path.realpath(path) # If file exist try to resolve the symbolic links if os.path.exists(path): has_prefix = path.startswith(DOS_DEVICE_PATH_PREFIX) path = _getfinalpathname(path) if not has_prefix and path.startswith(DOS_DEVICE_PATH_PREFIX): if path.startswith(DOS_DEVICE_PATH_PREFIX_UNC): path = path[len(DOS_DEVICE_PATH_PREFIX_UNC) :] else: path = path[len(DOS_DEVICE_PATH_PREFIX) :] return path
def resolve(self, path, strict=False): s = str(path) if not s: return os.getcwd() previous_s = None if _getfinalpathname is not None: if strict: return self._ext_to_normal(_getfinalpathname(s)) else: tail_parts = [] while True: try: s = self._ext_to_normal(_getfinalpathname(s)) except FileNotFoundError: previous_s = s s, tail = os.path.split(s) tail_parts.append(tail) if previous_s == s: return path else: return os.path.join(s, *reversed(tail_parts)) return None
def resolve(self, path, strict=False): s = str(path) if not s: return os.getcwd() previous_s = None if _getfinalpathname is not None: if strict: return self._ext_to_normal(_getfinalpathname(s)) else: while True: try: s = self._ext_to_normal(_getfinalpathname(s)) except FileNotFoundError: previous_s = s s = os.path.abspath(os.path.join(s, os.pardir)) else: if previous_s is None: return s else: return s + os.path.sep + os.path.basename(previous_s) # Means fallback on absolute return None
def resolve(self, path, strict=False): s = str(path) if not s: return os.getcwd() previous_s = None if _getfinalpathname is not None: if strict: return self._ext_to_normal(_getfinalpathname(s)) tail_parts = [] # End of the path after the first one not found while True: try: s = self._ext_to_normal(_getfinalpathname(s)) except FileNotFoundError: previous_s = s s, tail = os.path.split(s) tail_parts.append(tail) if previous_s == s: return path else: return os.path.join(s, *reversed(tail_parts)) # Means fallback on absolute return None
def resolve(self, path, strict=False): s = str(path) if not s: return os.getcwd() previous_s = None if _getfinalpathname is not None: if strict: return self._ext_to_normal(_getfinalpathname(s)) else: tail_parts = [] # End of the path after the first one not found while True: try: s = self._ext_to_normal(_getfinalpathname(s)) except FileNotFoundError: previous_s = s s, tail = os.path.split(s) tail_parts.append(tail) if previous_s == s: return path else: return os.path.join(s, *reversed(tail_parts)) # Means fallback on absolute return None
def _getfinalpathname_nonstrict(path): # These error codes indicate that we should stop resolving the path # and return the value we currently have. # 1: ERROR_INVALID_FUNCTION # 2: ERROR_FILE_NOT_FOUND # 3: ERROR_DIRECTORY_NOT_FOUND # 5: ERROR_ACCESS_DENIED # 21: ERROR_NOT_READY (implies drive with no media) # 32: ERROR_SHARING_VIOLATION (probably an NTFS paging file) # 50: ERROR_NOT_SUPPORTED # 67: ERROR_BAD_NET_NAME (implies remote server unavailable) # 87: ERROR_INVALID_PARAMETER # 123: ERROR_INVALID_NAME # 1920: ERROR_CANT_ACCESS_FILE # 1921: ERROR_CANT_RESOLVE_FILENAME (implies unfollowable symlink) allowed_winerror = 1, 2, 3, 5, 21, 32, 50, 67, 87, 123, 1920, 1921 # Non-strict algorithm is to find as much of the target directory # as we can and join the rest. tail = '' while path: try: path = _getfinalpathname(path) return join(path, tail) if tail else path except OSError as ex: if ex.winerror not in allowed_winerror: raise try: # The OS could not resolve this path fully, so we attempt # to follow the link ourselves. If we succeed, join the tail # and return. new_path = _readlink_deep(path) if new_path != path: return join(new_path, tail) if tail else new_path except OSError: # If we fail to readlink(), let's keep traversing pass path, name = split(path) # TODO (bpo-38186): Request the real file name from the directory # entry using FindFirstFileW. For now, we will return the path # as best we have it if path and not name: return path + tail tail = join(name, tail) if tail else name return tail
def _fixed_nt_realpath(path): """Return the absolute version of a path with symlinks resolved.""" from nt import _getfinalpathname # pylint: disable=import-error from ntpath import normpath if path: # Empty path must return current working directory. try: path = _getfinalpathname(path) if str(path[:4]) == '\\\\?\\': path = path[4:] # remove the \\?\ except WindowsError: # pylint: disable=undefined-variable pass # Bad path - return unchanged. elif isinstance(path, bytes): path = os.getcwdb() else: path = os.getcwd() return normpath(path)
def realpath(path): """Resolve symlinks and return real path to file. Note: This is a fix for the issue of os.path.realpath() not to resolve symlinks on Windows as it is an alias to abspath() only. see: http://bugs.python.org/issue9949 Arguments: path (string): The path to resolve. Returns: string: The resolved absolute path if exists or path as provided otherwise. """ try: return _getfinalpathname(path).replace('\\\\?\\', '') if path else None except FileNotFoundError: return path
def samefile(f1, f2): return _getfinalpathname(f1) == _getfinalpathname(f2)
def samefile(f1, f2): "Test whether two pathnames reference the same actual file" return _getfinalpathname(f1) == _getfinalpathname(f2)