%PDF- %PDF-
Direktori : /opt/cloudlinux/venv/lib/python3.11/site-packages/pyfakefs/ |
Current File : //opt/cloudlinux/venv/lib/python3.11/site-packages/pyfakefs/fake_path.py |
# Copyright 2009 Google Inc. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Faked ``os.path`` module replacement. See ``fake_filesystem`` for usage. """ import errno import os import sys from stat import ( S_IFDIR, S_IFMT, ) from types import ModuleType from typing import ( List, Optional, Union, Any, Dict, Tuple, AnyStr, overload, ClassVar, TYPE_CHECKING, ) from pyfakefs.helpers import ( make_string_path, to_string, matching_string, ) if TYPE_CHECKING: from pyfakefs.fake_filesystem import FakeFilesystem from pyfakefs.fake_os import FakeOsModule def _copy_module(old: ModuleType) -> ModuleType: """Recompiles and creates new module object.""" saved = sys.modules.pop(old.__name__, None) new = __import__(old.__name__) if saved is not None: sys.modules[old.__name__] = saved return new class FakePathModule: """Faked os.path module replacement. FakePathModule should *only* be instantiated by FakeOsModule. See the FakeOsModule docstring for details. """ _OS_PATH_COPY: Any = _copy_module(os.path) devnull: ClassVar[str] = "" sep: ClassVar[str] = "" altsep: ClassVar[Optional[str]] = None linesep: ClassVar[str] = "" pathsep: ClassVar[str] = "" @staticmethod def dir() -> List[str]: """Return the list of patched function names. Used for patching functions imported from the module. """ dir_list = [ "abspath", "dirname", "exists", "expanduser", "getatime", "getctime", "getmtime", "getsize", "isabs", "isdir", "isfile", "islink", "ismount", "join", "lexists", "normcase", "normpath", "realpath", "relpath", "split", "splitdrive", "samefile", ] if sys.version_info >= (3, 12): dir_list += ["isjunction", "splitroot"] return dir_list def __init__(self, filesystem: "FakeFilesystem", os_module: "FakeOsModule"): """Init. Args: filesystem: FakeFilesystem used to provide file system information """ self.filesystem = filesystem self._os_path = self._OS_PATH_COPY self._os_path.os = self.os = os_module # type: ignore[attr-defined] self.reset(filesystem) @classmethod def reset(cls, filesystem: "FakeFilesystem") -> None: cls.sep = filesystem.path_separator cls.altsep = filesystem.alternative_path_separator cls.linesep = filesystem.line_separator() cls.devnull = "nul" if filesystem.is_windows_fs else "/dev/null" cls.pathsep = ";" if filesystem.is_windows_fs else ":" def exists(self, path: AnyStr) -> bool: """Determine whether the file object exists within the fake filesystem. Args: path: The path to the file object. Returns: (bool) `True` if the file exists. """ return self.filesystem.exists(path) def lexists(self, path: AnyStr) -> bool: """Test whether a path exists. Returns True for broken symbolic links. Args: path: path to the symlink object. Returns: bool (if file exists). """ return self.filesystem.exists(path, check_link=True) def getsize(self, path: AnyStr): """Return the file object size in bytes. Args: path: path to the file object. Returns: file size in bytes. """ file_obj = self.filesystem.resolve(path) if ( self.filesystem.ends_with_path_separator(path) and S_IFMT(file_obj.st_mode) != S_IFDIR ): error_nr = errno.EINVAL if self.filesystem.is_windows_fs else errno.ENOTDIR self.filesystem.raise_os_error(error_nr, path) return file_obj.st_size def isabs(self, path: AnyStr) -> bool: """Return True if path is an absolute pathname.""" if self.filesystem.is_windows_fs: path = self.splitdrive(path)[1] path = make_string_path(path) return self.filesystem.starts_with_sep(path) def isdir(self, path: AnyStr) -> bool: """Determine if path identifies a directory.""" return self.filesystem.isdir(path) def isfile(self, path: AnyStr) -> bool: """Determine if path identifies a regular file.""" return self.filesystem.isfile(path) def islink(self, path: AnyStr) -> bool: """Determine if path identifies a symbolic link. Args: path: Path to filesystem object. Returns: `True` if path points to a symbolic link. Raises: TypeError: if path is None. """ return self.filesystem.islink(path) if sys.version_info >= (3, 12): def isjunction(self, path: AnyStr) -> bool: """Returns False. Junctions are never faked.""" return self.filesystem.isjunction(path) def splitroot(self, path: AnyStr): """Split a pathname into drive, root and tail. Implementation taken from ntpath and posixpath. """ return self.filesystem.splitroot(path) def getmtime(self, path: AnyStr) -> float: """Returns the modification time of the fake file. Args: path: the path to fake file. Returns: (int, float) the modification time of the fake file in number of seconds since the epoch. Raises: OSError: if the file does not exist. """ try: file_obj = self.filesystem.resolve(path) return file_obj.st_mtime except OSError: self.filesystem.raise_os_error(errno.ENOENT, winerror=3) def getatime(self, path: AnyStr) -> float: """Returns the last access time of the fake file. Note: Access time is not set automatically in fake filesystem on access. Args: path: the path to fake file. Returns: (int, float) the access time of the fake file in number of seconds since the epoch. Raises: OSError: if the file does not exist. """ try: file_obj = self.filesystem.resolve(path) except OSError: self.filesystem.raise_os_error(errno.ENOENT) return file_obj.st_atime def getctime(self, path: AnyStr) -> float: """Returns the creation time of the fake file. Args: path: the path to fake file. Returns: (int, float) the creation time of the fake file in number of seconds since the epoch. Raises: OSError: if the file does not exist. """ try: file_obj = self.filesystem.resolve(path) except OSError: self.filesystem.raise_os_error(errno.ENOENT) return file_obj.st_ctime def abspath(self, path: AnyStr) -> AnyStr: """Return the absolute version of a path.""" def getcwd(): """Return the current working directory.""" # pylint: disable=undefined-variable if isinstance(path, bytes): return self.os.getcwdb() else: return self.os.getcwd() path = make_string_path(path) if not self.isabs(path): path = self.join(getcwd(), path) elif self.filesystem.is_windows_fs and self.filesystem.starts_with_sep(path): cwd = getcwd() if self.filesystem.starts_with_drive_letter(cwd): path = self.join(cwd[:2], path) return self.normpath(path) def join(self, *p: AnyStr) -> AnyStr: """Return the completed path with a separator of the parts.""" return self.filesystem.joinpaths(*p) def split(self, path: AnyStr) -> Tuple[AnyStr, AnyStr]: """Split the path into the directory and the filename of the path.""" return self.filesystem.splitpath(path) def splitdrive(self, path: AnyStr) -> Tuple[AnyStr, AnyStr]: """Split the path into the drive part and the rest of the path, if supported.""" return self.filesystem.splitdrive(path) def normpath(self, path: AnyStr) -> AnyStr: """Normalize path, eliminating double slashes, etc.""" return self.filesystem.normpath(path) def normcase(self, path: AnyStr) -> AnyStr: """Convert to lower case under windows, replaces additional path separator.""" path = self.filesystem.normcase(path) if self.filesystem.is_windows_fs: path = path.lower() return path def relpath(self, path: AnyStr, start: Optional[AnyStr] = None) -> AnyStr: """We mostly rely on the native implementation and adapt the path separator.""" if not path: raise ValueError("no path specified") path = make_string_path(path) path = self.filesystem.replace_windows_root(path) sep = matching_string(path, self.filesystem.path_separator) if start is not None: start = make_string_path(start) else: start = matching_string(path, self.filesystem.cwd) start = self.filesystem.replace_windows_root(start) system_sep = matching_string(path, self._os_path.sep) if self.filesystem.alternative_path_separator is not None: altsep = matching_string(path, self.filesystem.alternative_path_separator) path = path.replace(altsep, system_sep) start = start.replace(altsep, system_sep) path = path.replace(sep, system_sep) start = start.replace(sep, system_sep) path = self._os_path.relpath(path, start) return path.replace(system_sep, sep) def realpath(self, filename: AnyStr, strict: Optional[bool] = None) -> AnyStr: """Return the canonical path of the specified filename, eliminating any symbolic links encountered in the path. """ if strict is not None and sys.version_info < (3, 10): raise TypeError("realpath() got an unexpected " "keyword argument 'strict'") if strict: # raises in strict mode if the file does not exist self.filesystem.resolve(filename) if self.filesystem.is_windows_fs: return self.abspath(filename) filename = make_string_path(filename) path, ok = self._join_real_path(filename[:0], filename, {}) path = self.abspath(path) return path def samefile(self, path1: AnyStr, path2: AnyStr) -> bool: """Return whether path1 and path2 point to the same file. Args: path1: first file path or path object (Python >=3.6) path2: second file path or path object (Python >=3.6) Raises: OSError: if one of the paths does not point to an existing file system object. """ stat1 = self.filesystem.stat(path1) stat2 = self.filesystem.stat(path2) return stat1.st_ino == stat2.st_ino and stat1.st_dev == stat2.st_dev @overload def _join_real_path( self, path: str, rest: str, seen: Dict[str, Optional[str]] ) -> Tuple[str, bool]: ... @overload def _join_real_path( self, path: bytes, rest: bytes, seen: Dict[bytes, Optional[bytes]] ) -> Tuple[bytes, bool]: ... def _join_real_path( self, path: AnyStr, rest: AnyStr, seen: Dict[AnyStr, Optional[AnyStr]] ) -> Tuple[AnyStr, bool]: """Join two paths, normalizing and eliminating any symbolic links encountered in the second path. Taken from Python source and adapted. """ curdir = matching_string(path, ".") pardir = matching_string(path, "..") sep = self.filesystem.get_path_separator(path) if self.isabs(rest): rest = rest[1:] path = sep while rest: name, _, rest = rest.partition(sep) if not name or name == curdir: # current dir continue if name == pardir: # parent dir if path: path, name = self.filesystem.splitpath(path) if name == pardir: path = self.filesystem.joinpaths(path, pardir, pardir) else: path = pardir continue newpath = self.filesystem.joinpaths(path, name) if not self.filesystem.islink(newpath): path = newpath continue # Resolve the symbolic link if newpath in seen: # Already seen this path seen_path = seen[newpath] if seen_path is not None: # use cached value path = seen_path continue # The symlink is not resolved, so we must have a symlink loop. # Return already resolved part + rest of the path unchanged. return self.filesystem.joinpaths(newpath, rest), False seen[newpath] = None # not resolved symlink path, ok = self._join_real_path( path, matching_string(path, self.filesystem.readlink(newpath)), seen, ) if not ok: return self.filesystem.joinpaths(path, rest), False seen[newpath] = path # resolved symlink return path, True def dirname(self, path: AnyStr) -> AnyStr: """Returns the first part of the result of `split()`.""" return self.split(path)[0] def expanduser(self, path: AnyStr) -> AnyStr: """Return the argument with an initial component of ~ or ~user replaced by that user's home directory. """ path = self._os_path.expanduser(path) return path.replace( matching_string(path, self._os_path.sep), matching_string(path, self.sep), ) def ismount(self, path: AnyStr) -> bool: """Return true if the given path is a mount point. Args: path: Path to filesystem object to be checked Returns: `True` if path is a mount point added to the fake file system. Under Windows also returns True for drive and UNC roots (independent of their existence). """ if not path: return False path_str = to_string(make_string_path(path)) normed_path = self.filesystem.absnormpath(path_str) sep = self.filesystem.path_separator if self.filesystem.is_windows_fs: path_seps: Union[Tuple[str, Optional[str]], Tuple[str]] if self.filesystem.alternative_path_separator is not None: path_seps = (sep, self.filesystem.alternative_path_separator) else: path_seps = (sep,) drive, rest = self.filesystem.splitdrive(normed_path) if drive and drive[:1] in path_seps: return (not rest) or (rest in path_seps) if rest in path_seps: return True for mount_point in self.filesystem.mount_points: if to_string(normed_path).rstrip(sep) == to_string(mount_point).rstrip(sep): return True return False def __getattr__(self, name: str) -> Any: """Forwards any non-faked calls to the real os.path.""" return getattr(self._os_path, name) if sys.platform == "win32": class FakeNtModule: """Under windows, a few function of `os.path` are taken from the `nt` module for performance reasons. These are patched here. """ @staticmethod def dir(): if sys.version_info >= (3, 12): return ["_path_exists", "_path_isfile", "_path_isdir", "_path_islink"] else: return ["_isdir"] def __init__(self, filesystem: "FakeFilesystem"): """Init. Args: filesystem: FakeFilesystem used to provide file system information """ import nt # type:ignore[import] self.filesystem = filesystem self.nt_module: Any = nt if sys.version_info >= (3, 12): def _path_isdir(self, path: AnyStr) -> bool: return self.filesystem.isdir(path) def _path_isfile(self, path: AnyStr) -> bool: return self.filesystem.isfile(path) def _path_islink(self, path: AnyStr) -> bool: return self.filesystem.islink(path) def _path_exists(self, path: AnyStr) -> bool: return self.filesystem.exists(path) else: def _isdir(self, path: AnyStr) -> bool: return self.filesystem.isdir(path) def __getattr__(self, name: str) -> Any: """Forwards any non-faked calls to the real nt module.""" return getattr(self.nt_module, name)