g`dZddlZddlZddlZddlZddlZddlZddlZddlZddl m Z m Z ddl m Z ddlmZddlmZmZmZmZmZmZmZddlmZmZmZmZmZmZmZm Z m!Z!m"Z"m#Z#ddl$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*dd l+m,Z,m-Z-dd l.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7ej89d rd Z:nd Z:GddeZ;e%j<ZZ>e%j?Z?e%j@Z@e%jAZAe%jBZBe%jCZCe%jDZDe&jEZEe(jFZFe*jGZGe'jHZHej8dkre'jIZIe'jJZJe)jKZKe)jLZLe)jMZMe)jNZNe)jOZOe)jPZPe)jQZQe)jRZRe)jSZSe)jTZTe)jUZUe)jVZVGddZWde fdZXdZYeZdkr eXdSdS)a"A fake filesystem implementation for unit testing. :Usage: >>> from pyfakefs import fake_filesystem, fake_os >>> filesystem = fake_filesystem.FakeFilesystem() >>> os_module = fake_os.FakeOsModule(filesystem) >>> pathname = '/a/new/dir/new-file' Create a new file object, creating parent directory objects as needed: >>> os_module.path.exists(pathname) False >>> new_file = filesystem.create_file(pathname) File objects can't be overwritten: >>> os_module.path.exists(pathname) True >>> try: ... filesystem.create_file(pathname) ... except OSError as e: ... assert e.errno == errno.EEXIST, 'unexpected errno: %d' % e.errno ... assert e.strerror == 'File exists in the fake filesystem' Remove a file object: >>> filesystem.remove_object(pathname) >>> os_module.path.exists(pathname) False Create a new file object at the previous path: >>> beatles_file = filesystem.create_file(pathname, ... contents='Dear Prudence\nWon\'t you come out to play?\n') >>> os_module.path.exists(pathname) True Use the FakeFileOpen class to read fake file objects: >>> file_module = fake_filesystem.FakeFileOpen(filesystem) >>> for line in file_module(pathname): ... print(line.rstrip()) ... Dear Prudence Won't you come out to play? File objects cannot be treated like directory objects: >>> try: ... os_module.listdir(pathname) ... except OSError as e: ... assert e.errno == errno.ENOTDIR, 'unexpected errno: %d' % e.errno ... assert e.strerror == 'Not a directory in the fake filesystem' The FakeOsModule can list fake directory objects: >>> os_module.listdir(os_module.path.dirname(pathname)) ['new-file'] The FakeOsModule also supports stat operations: >>> import stat >>> stat.S_ISREG(os_module.stat(pathname).st_mode) True >>> stat.S_ISDIR(os_module.stat(os_module.path.dirname(pathname)).st_mode) True N) namedtuple OrderedDict) TestResults)Enum)S_IFREGS_IFDIRS_ISLNKS_IFMTS_ISDIRS_IFLNKS_ISREG) ListCallableUnionAnyDictTuplecastAnyStroverloadNoReturnOptional) fake_file fake_pathfake_iofake_oshelpers fake_open)AnyFileWrapperAnyFile) is_int_typemake_string_path to_stringmatching_stringAnyPath AnyStringWINDOWS_PROPERTIESPOSIX_PROPERTIESFSTypelinux( ceZdZdZdZdZdZdS)OSTypez?Defines the real or simulated OS of the underlying file system.r*macoswindowsN)__name__ __module__ __qualname____doc__LINUXMACOSWINDOWSj/builddir/build/BUILD/cloudlinux-venv-1.0.10/venv/lib/python3.11/site-packages/pyfakefs/fake_filesystem.pyr.r.s#II E EGGGr9r.win32ceZdZdZejjdddfdedee de de ddf d Z e de fd Ze de fd Zejd e ddfd Ze de fdZejd e ddfdZe defdZejd eddfdZe deefdZejd eeddfdZe defdZe defdZe defdZe defdZejd eddfdZe defdZe defdZe defdZejd eddfdZddee de fdZejd efd!Z d"Z!dd#Z"dd$Z#dd%Z$ dd&e d'ee%d(ee de&fd)Z'd*e(de(fd+Z)d*e(dee(fd,Z*d*e(de fd-Z+ dd*e(dee d.e de,fd/Z-d0e.defd1Z/d*e(dee,fd2Z0d*e(de,fd3Z1defd4Z2d5e dee,fd6Z3dd*ee(de4e e e ffd7Z5dde d*ee(ddfd8Z6d9e d:e(d;e ddfd<Z7dd=e(d>e fd?Z8 dd=e(d@e9d>e dAe ddf dBZ: dd*e;e(e fdCe d>e dDe ddf dEZ< ddddFd*e(dGee4e;e e=fe;e e=ffdHee4e e fd>e ddf dIZ>e?dHee4e e fdGee4e;e e=fe;e e=fffdJZ@ddLeAdMe de fdNZBdOe ddfdPZCdOe deAfdQZDdOe deEeAfdRZFd@e9de fdSZGd*e(de(fdTZHd*e(de(fdUZId*e(de(fdVZJd*e(de(fdWZKd*e(de(fdXZLd*e(de4e(e(ffdYZMd*e(de4e(e(ffdZZNd*e(fd[ZOd\e(de(fd]ZPd^e(de(fd_ZQeRd*edeEefd`ZSeRd*eTdeEeTfdaZSd*e(deEe(fdbZSd:e(de fdcZUd:e(de fddZVd*e(de(fdeZWd:e(de fdfZXd:e(de fdgZYd*e;e e.fde fdhZZd*e(de fdiZ[djedkede4eeee\ffdlZ]dd:e.dme de fdnZ^dd:e(doe de(fdpZ_dqZ`dreEe(deEefdsZad:e(de fdtZbdueEedve\defdwZc dd:e.dxe dye dze de\f d{Zde?d|Ze dd:e.dxe dye de9fd}Zfd:e.de9fd~Zg dd:e;e(e fd>e doe dxe dye dze de9fdZhd*e.de9fdZid:e(d@e\ddfdZj dde.de.de ddfdZkdZld*e(ddfdZmde(de(de ddfdZnde de(de(de9de dee(f dZode de(de9de9de ddf dZpde(de(dee(fdZqd:e(ddfdZrd*e.de(fdZsetjudfd0e.de de defdZvewetjxzdddddddfd:e.de de%dee de de deedeedeeyde9fdZz dde.de dee.de9fdZ{ dde.dee.de9fdZ| dde.de de dee.def dZ}dZ~dZ ddeEe(de de ddfdZdeddfdZewetjxzddddddddf d:e.de de%dee de de deedeede deeyde9fdZ dd:e.de.de de9fdZ dde.de.d>e de de9f dZ dde.de.d>e de9fdZde9de fdZd*e.defdZetjufde.dCe ddfdZd*e(de(fdZetjudfde(dCe de ddfdZ dd*e.de d>e de fdZdd*e.d>e de fdZdd*e.d>e de fdZd*e.de fdZejdkrd*e.de fd„Z dde(dxe dye dze def dĄZd*e(ddfdńZdde(de ddfdDŽZde(deEe(fdȄZdefdɄZejdkrMehdˣd̄dDzd΄dDzZedτedЦDhdѣzZd҄ZddӄZdԄZdՄZdS)FakeFilesystemaBProvides the appearance of a real directory tree for unit testing. Attributes: is_case_sensitive: `True` if a case-sensitive file system is assumed. root: The root :py:class:`FakeDirectory` entry of the file system. umask: The umask used for newly created files, see `os.umask`. patcher: Holds the Patcher object if created from it. Allows access to the patcher object if using the pytest fs fixture. patch_open_code: Defines how `io.open_code `__ will be patched; patching can be on, off, or in automatic mode. shuffle_listdir_results: If `True`, `os.listdir` will not sort the results to match the real file system behavior. NFpath_separator total_sizepatchercreate_temp_dirreturnc||_||_tjdk|_tjdk|_|jp|j |_tj|_ |jrtnt}tj |ttg|_||_|d|_t#jd|_t#j|jg|_g|_d|_d|_t/|_d|_||dt6j|_d|_dS) ap Args: path_separator: optional substitute for os.path.sep total_size: if not `None`, the total size in bytes of the root filesystem. patcher: the Patcher instance if created from the Patcher create_temp_dir: If `True`, a temp directory is created on initialization. Under Posix, if the temp directory is not `/tmp`, a link to the temp path is additionally created at `/tmp`. Example usage to use the same path separator under all systems: >>> filesystem = FakeFilesystem(path_separator='/') r;darwinrNF)r? init_pathlib)r@rAsysplatform_is_windows_fs _is_macosis_case_sensitiver)DEFAULTfs_typer'r( dataclassesreplace fs_propertiesr>_cwdosumask open_files _free_fd_heaplast_inolast_devr mount_pointsdev_nullreset PatchModeOFFpatch_open_codeshuffle_listdir_results)selfr>r?r@rAbase_propertiess r:__init__zFakeFilesystem.__init__s+, . "lg51-1,?,Q4>'R~ "&"5 K  ;K    0 0    -   (4..  AC(*  3>==!  ju === )}',$$$r9c"|j o|j S)z4Returns `True` in a real or faked Linux file system.) is_windows_fsis_macosr`s r:is_linuxzFakeFilesystem.is_linuxs%%;dm*;;r9cd|jtjkp|jtjko|jS)z6Returns `True` in a real or faked Windows file system.)rNr)r7rMrJrfs r:rdzFakeFilesystem.is_windows_fss.|v~- LFN * Bt/B r9valuec|j|kr@||_|rd|_|t|dSdSNF)rJrKr[FakePathModuler`ris r:rdzFakeFilesystem.is_windows_fssV  % ' '"'D  '!& JJLLL   & & & & & ( 'r9c|jS)z4Returns `True` in a real or faked macOS file system.)rKrfs r:rezFakeFilesystem.is_macos's ~r9c|j|kr@||_|rd|_|t|dSdSrk)rKrJr[rlrms r:rezFakeFilesystem.is_macos,sU >U " ""DN ,&+# JJLLL   & & & & & # "r9c:|j|jjjS)z9Returns the path separator, corresponds to `os.path.sep`.)rQrNriseprfs r:r>zFakeFilesystem.path_separator5s!$,"4599r9c\||jd_|tjkr d|_dSdSNr)rQrqrSalternative_path_separatorrms r:r>zFakeFilesystem.path_separator:s2$)1! BF??.2D + + + ?r9c:|j|jjjS)zHReturns the alternative path separator, corresponds to `os.path.altsep`.)rQrNrialtseprfs r:rtz)FakeFilesystem.alternative_path_separator@s!$,"45<rR_auto_mount_drive_if_needed)r`rirRs r:rzFakeFilesystem.cwdZs`  &&LL D"& ) )?4AT+U+U    ((/////r9cF|jr|S|jS)ziReturn the root directory, which represents "/" under POSIX, and the current drive under Windows.)rd_mount_point_dir_for_cwdrootrfs r:root_dirzFakeFilesystem.root_dires)   30022 2yr9ct|jj}||js ||jzS|S)zwReturn the root directory name, which is "/" under POSIX, and the root path of the current drive under Windows.)r#rnameendswithr>)r`rs r: root_dir_namezFakeFilesystem.root_dir_namemsBT]/00  !455 2d11 1r9cf|jr tjn|jr tjn tjS)z6Return the real or simulated type of operating system.)rdr.r7rer6r5rfs r:rSzFakeFilesystem.osvs1 ! FNN}  r9c@|tjk|_|tjk|_|tjk|_tj|_ |jrtnt}||j d<| t |dS)zSSet the simulated type of operating system underlying the fake file system.rN)r.r7rJr6rKr5rLr)rMrNr'r(rQr[rl)r`riras r:rSzFakeFilesystem.oss$v~5&,.!&&,!6~ "&"5 K  ;K !01 T"""""r9TrGct|j||_t||_|j|jd|_d|_ |j | || |j r||rddlm}||dSdS)z3Remove all file system contents and reset the root. filesystemr) fake_pathlibN) FakeDirectoryr>r FakeNullFilerZrUclearrVrWrXrY_add_root_mount_point_add_standard_streamsrA_create_temp_dirpyfakefsr init_module)r`r?rGrs r:r[zFakeFilesystem.resets!$"5$GGG $T**     """   !!! "":... ""$$$   $  ! ! # # #  + - - - - - -  $ $T * * * * * + +r9rNc#VK|j} ||_dV||_dS#||_wxYwry)rN)r`rN old_fs_types r: use_fs_typezFakeFilesystem.use_fs_types@l  '"DL EEE&DLLL;DL & & & &s  (c|jrdn|j}||_|j|js|xj|jz c_|||dS)NzC:)rdr>rRrradd_mount_point)r`r? mount_points r:rz$FakeFilesystem._add_root_mount_pointsg"0Iddd6I  x  !455 - II, ,II [*55555r9cd|jtd|jdS)aPause the patching of the file system modules until :py:meth:`resume` is called. After that call, all file system calls are executed in the real file system. Calling `pause()` twice is silently ignored. Only allowed if the file system object was created by a `Patcher` object. This is also the case for the pytest `fs` fixture. Raises: RuntimeError: if the file system was not created by a `Patcher`. NzUpause() can only be called from a fake file system object created by a Patcher object)r@ RuntimeErrorpauserfs r:rzFakeFilesystem.pauses? < <  r9cd|jtd|jdS)aPResume the patching of the file system modules if :py:meth:`pause` has been called before. After that call, all file system calls are executed in the fake file system. Does nothing if patching is not paused. Raises: RuntimeError: if the file system has not been created by `Patcher`. NzVresume() can only be called from a fake file system object created by a Patcher object)r@rresumerfs r:rzFakeFilesystem.resumes? < <  r9cJ|jr|jdSdS)z'Clear the cache of non-patched modules.N)r@ clear_cacherfs r:rzFakeFilesystem.clear_caches0 < ' L $ $ & & & & & ' 'r9err_nofilenamewinerrorctj|}|)tjdkr|jrt ||||t |||)a+Raises OSError. The error message is constructed from the given error code and shall start with the error string issued in the real system. Note: this is not true under Windows if winerror is given - in this case a localized message specific to winerror will be shown in the real file system. Args: err_no: A numeric error code from the C variable errno. filename: The name of the affected file, if any. winerror: Windows only - the specific Windows error code. Nr;)rSstrerrorrHrIrdOSError)r`rrrmessages r:raise_os_errorzFakeFilesystem.raise_os_errorsS$+f%%  CLG$;$;@R$;&'8X>> >fgx000r9pathc,t||jS)z2Return the path separator as the same type as path)r$r>r`rs r:get_path_separatorz!FakeFilesystem.get_path_separatorstT%8999r9c,t||jS)z>Return the alternative path separator as the same type as path)r$rtrs r:_alternative_path_separatorz*FakeFilesystem._alternative_path_separatorstT%DEEEr9c||}||}||p|duo||S)z3Return `True` if path starts with a path separator.N)rr startswith)r`rrqrvs r:starts_with_sepzFakeFilesystem.starts_with_sepsU%%d++11$77s##UvT'9'Udoof>U>UUr9 can_existc|||}|jD]}|jr|t ||ks?|jsi|t ||kr1|r|j|cS|tj||xj dz c_ |j |dd|j|<|t ||j j kr$|j }|xj dz c_ |j |_ n||}|j |_|j|S)ahAdd a new mount point for a filesystem device. The mount point gets a new unique device number. Args: path: The root path for the new mount path. total_size: The new total size of the added filesystem device in bytes. Defaults to infinite size. can_exist: If `True`, no error is raised if the mount point already exists. Returns: The newly created mount point dict. Raises: OSError: if trying to mount an existing mount point again, and ``can_exist`` is `False`. r)idevr? used_size)normpathnormcaserYrLr$lowerrerrnoEEXISTrXrrrWst_ino_create_mount_point_dirst_dev)r`rr?rrrs r:rzFakeFilesystem.add_mount_pointsR2}}T]]40011, 8 8K& 8OD+>>>>-?JJLLOD+:K:K:M:M$N$NNN:,[9999##EL$777  M$# # $ ?488 8 8yH MMQ MM"mHOO33D99H- &&r9directory_pathc||}||}|j}g}d|DD]}||t |d}|s>t ||}|||||}ktt |}|D]}ttj z|_ |S)zA version of `create_dir` for the mount point directory creation, which avoids circular calls and unneeded checks. c,g|]}t|Sr8r#.0ps r: z:FakeFilesystem._create_mount_point_dir..<@@@1)A,,@@@r9rr) r"_path_componentsr_directory_contentr#rappend add_entryrrrPERM_DEFst_mode) r`rdir_pathpath_components current_dirnew_dirs component directorynew_dirs r:rz&FakeFilesystem._create_mount_point_dir3s((88//99i @@@@@ = =I// Yy=Q=QRRSTUI =' dCCC(((%%g...% "=)<<  9 9G%(88GOOr9c||jr4||d}|r||dSdS)zWindows only: if `path` is located on an unmounted drive or UNC mount point, the drive/mount point is added to the mount points.rT)rrN)rd splitdriver)r`rdrives r:rz*FakeFilesystem._auto_mount_drive_if_neededKsM   HOOD))!,E H++$+GGGtr9cB|||}|jD]%}|t||kr|j|cS&t|d}||d}|jD]a}t||}|r||s*||r"t |t |kr|}b|r|jt|S||}|sJ|S)NrEr) absnormpath_original_pathrYr$rrlenr#r)r`r mount_pathr root_pathrs r:_mount_point_for_pathz$FakeFilesystem._mount_point_for_pathTs; 3 3D 9 9::+ 5 5JtZ8888(44449$T2.. %%a(* ' 'I'i88I Y11%88 y)) 'c)nns:.N.N&  <$Yz%:%:; ;66t<< {r9cdtffd }tj}jD]"}|t|kr ||cS#d}t|d}jD]`}t|}|r||s)||r"t |t |kr|}a||S)zjReturn the fake directory object of the mount point where the current working directory points to.rBc|}j}|D]*}tt||}+|Sry)rrrr get_entry) file_pathrtargetrr`s r:object_from_pathzAFakeFilesystem._mount_point_dir_for_cwd..object_from_pathksR"33I>>OYF, J J mV-=-=i-H-HIIMr9rEr)rr#rrYrrr)r`rrrrr str_root_paths` r:rz'FakeFilesystem._mount_point_dir_for_cwdgs =      ""+ 4 4Jy,,,,'' 33333- $//$//233* ' 'I%i00M ]55e<< }-- '#m2D2Ds:2V2V&  +++r9rc^|jD]}|d|kr|cSdS)Nr)rYvalues)r`rrs r:_mount_point_for_devicez&FakeFilesystem._mount_point_for_devicesF,3355 # #K6"d**""""+tr9cTtdd}|4tt|j}n$t |}||}|r0|d(||d|d|d|dz S|dddS)aReturn the total, used and free disk space in bytes as named tuple, or placeholder values simulating unlimited space if not set. .. note:: This matches the return value of ``shutil.disk_usage()``. Args: path: The disk space is returned for the file system device where `path` resides. Defaults to the root path (e.g. '/' on Unix systems). DiskUsageztotal, used, freeNr?rlr)rnextiterrYrr"r)r`rrrrs r:get_disk_usagezFakeFilesystem.get_disk_usages{,?@@ <tD$5$<$<$>$>??@@KK(..I44Y??K  ;|4@9L)K(L)K ,DD  y2A7PQQQr9c||n|j}||}|d,|d|kr |tj|||d<dS)aChanges the total size of the file system, preserving the used space. Example usage: set the size of an auto-mounted Windows drive. Args: total_size: The new total size of the filesystem in bytes. path: The disk space is changed for the file system device where `path` resides. Defaults to the root path (e.g. '/' on Unix systems). Raises: OSError: if the new space is smaller than the used size. Nr?r)rrrrENOSPC)r`r?rrrs r:set_disk_usagezFakeFilesystem.set_disk_usagesp $DD$*< 00;;  % 1K(:55    d 3 3 3$. L!!!r9 usage_changerrc||}|rK|d}|/||dz |kr |tj||dxx|z cc<dSdS)aChange the used disk space by the given amount. Args: usage_change: Number of bytes added to the used space. If negative, the used space will be decreased. file_path: The path of the object needing the disk space. st_dev: The device ID for the respective file system. Raises: OSError: if `usage_change` exceeds the free file system space r?Nr)rrrr)r`rrrrr?s r:change_disk_usagez FakeFilesystem.change_disk_usages 226::  5$\2J% K 88<GG'' i@@@  $ $ $ 4 $ $ $ $ $  5 5r9 entry_pathfollow_symlinkscJ |||ddd}n%#t$r||}YnwxYwts%|j}|r||jd|||||jS)aReturn the os.stat-like tuple for the FakeFile object of ``entry_path``. Args: entry_path: Path to filesystem object to retrieve. follow_symlinks: If `False` and ``entry_path`` points to a symlink, the link itself is inspected instead of the linked object. Returns: The `FakeStatResult` object corresponding to ``entry_path``. Raises: OSError: if the filesystem object doesn't exist. TF)allow_fdcheck_read_permcheck_exe_permr) resolve TypeErroris_root parent_dir _get_objectr(raise_for_filepath_ending_with_separator stat_resultcopy)r`rr file_objectrs r:statzFakeFilesystem.stats 3,, %$ 'KK 3 3 3,,z22KKK 3yy I$/J I  % HHH 55  _   &++---s ??r macos_handlingcP||r t|jr ||}n\#t$rO}|jr|jt jkrYd}~dS|jr | t j |d}~wwxYw|r|js|jr|}|jrt|j}n4|jr|rt|j }nt|j }|r$| t j |dSdSdSry) ends_with_path_separatorr rrrrerENOENTrdrENOTDIRr r )r`rr rr  link_objectexcis_errors r:rz7FakeFilesystem.raise_for_filepath_ending_with_separatorsb  ( ( 4 4 ?{*++ ."&,,z":":KK}el)B)B)G++EM:FFF  '.$*<. ."-K! <";#677 <> <&{':;;;&{':;;; ?##EM:>>>>>' ? ?$ ? ?sA B B.(BBmodeforce_unix_modec\|j ptjdk}||||d}|jr1|s/|tjzr|jdz|_n:|jdz|_n*|jtjz|tjzz|_t j|_ dS)aChange the permissions of a file as encoded in integer mode. Args: path: (str | int) Path to the file or file descriptor. mode: (int) Permissions. follow_symlinks: If `False` and `path` points to a symlink, the link itself is affected instead of the linked object. force_unix_mode: if `True` and run under Windows, the mode is not adapted for Windows to allow making dirs unreadable  T)r check_ownerimN) rdrH version_inforr PERM_WRITErPERM_ALLnowst_ctime)r`rrrrrr s r:chmodzFakeFilesystem.chmods"))HS-=-Hll /H$#     o g(( E&1&9E&A ##&1&9H&D ###.#6':J9J#Jw''#K  '{}} r9)nsrtimesr"c||||||d}|L|D]-}t|ttfst d.|d|_|d|_dS|E|D]&}t|tst d'|d|_|d|_ dStj }||_||_dS)aChange the access and modified times of a file. Args: path: (str) Path to the file. times: 2-tuple of int or float numbers, of the form (atime, mtime) which is used to set the access and modified times in seconds. If `None`, both times are set to the current time. ns: 2-tuple of int numbers, of the form (atime, mtime) which is used to set the access and modified times in nanoseconds. If `None`, both times are set to the current time. follow_symlinks: If `False` and ``path`` points to a symlink, the link itself is queried instead of the linked object. Raises: TypeError: If anything other than the expected types is specified in the passed ``times`` or ``ns`` tuple, or if the tuple length is not equal to 2. ValueError: If both ``times`` and ``ns`` are specified. TrNzatime and mtime must be numbersrrzatime and mtime must be ints) _handle_utime_arg_errorsr isinstanceintfloatrst_atimest_mtime st_atime_ns st_mtime_nsrr)r`rr#r"rr  file_time current_times r:utimezFakeFilesystem.utime2s6 %%b%000ll44lHH  " G G !)c5\::G#$EFFFG$)8K #(8K ^ D D !)S11D#$BCCCD')eK #&(eK # # #";==L#/K #/K r9c||td|"t|dkrtd|"t|dkrtddSdS)Nz:utime: you may specify either 'times' or 'ns' but not bothz9utime: 'times' must be either a tuple of two ints or Nonez'utime: 'ns' must be a tuple of two ints) ValueErrorrr)r"r#s r:r&z'FakeFilesystem._handle_utime_arg_errorscsu  L   UqWXX X >c"ggllEFF F >llr9file_objnew_fdc|dkrt|j}||krh|j|}|r*|D]'} |#t$rY$wxYw||jvr|j||g|j|<nbt ||D]6}|jgtj |j|7|j|g|S|jr&tj |j}|g|j|<|S|j|gt|jdz S)aAdd file_obj to the list of open files on the filesystem. Used internally to manage open files. The position in the open_files array is the file descriptor number. Args: file_obj: File object to be added to open files list. new_fd: The optional new file descriptor. Returns: File descriptor number for the file object. rr) rrUcloserrVremoverangerheapqheappushheappop)r`r5r6sizerUffdopen_fds r: add_open_filezFakeFilesystem.add_open_fileqss Q;;t''D}}!_V4 !'!!!GGIIII&!!! D!T///&--f555+3*''f--;;BO**2...N4#5r::::&&z222M   mD$677G(0zDOG $N z***4?##a''sA  AAfile_descNd|j|<tj|j|dS)zRemove file object with given descriptor from the list of open files. Sets the entry in `open_files` to `None`. Args: file_des: Descriptor of file object to be removed from open files list. N)rUr;r<rVr`rCs r:close_open_filezFakeFilesystem.close_open_files+%)! t)844444r9c ||dS#t$r1|tjt |YdSwxYw)aReturn an open file. Args: file_des: File descriptor of the open file. Raises: OSError: an invalid file descriptor. TypeError: filedes is not an integer. Returns: Open file object. rN)get_open_files IndexErrorrrEBADFstrrEs r: get_open_filezFakeFilesystem.get_open_filesb <&&x003 3 < < <    S]] ; ; ; ; ; ; .s=   )1 QK " " $ $   r9)rU)r`r s r: has_open_filezFakeFilesystem.has_open_files/  59_     r9c||}|)||||S|Sry)rrPr)r`ralt_seps r:_normalize_path_sepz"FakeFilesystem._normalize_path_sepsB22488  <<)@)@)F)FGG G r9cJt|}||S)aReplace all appearances of alternative path separator with path separator. Do nothing if no alternative separator is set. Args: path: The path to be normalized. Returns: The normalized path that will be used internally. )r"rV)r`rrs r:rzFakeFilesystem.normcases%%T** '' 222r9c||}||\}}||}||}||}g}t |d}t |d} |D]L} | r| |kr | | kr&|r!|d| kr|4|r7|| M||} |r|| z} || zp|S)aMimic os.path.normpath using the specified path_separator. Mimics os.path.normpath using the path_separator that was specified for this FakeFilesystem. Normalizes the path, but unlike the method absnormpath, does not make it absolute. Eliminates dot components (. and ..) and combines repeated path separators (//). Initial .. components are left in place for relative paths. If the result is an empty path, '.' is returned instead. This also replaces alternative path separator with path separator. That is, it behaves like the real os.path.normpath on Windows if initialized with '\' as path separator and '/' as alternative separator. Args: path: (str) The path to normalize. Returns: (str) A copy of path with empty components and dot components removed. ...r4) rrrrsplitr$poprjoin) r`rpath_strrrqis_absolute_pathrcollapsed_path_componentsdotdotdotrcollapsed_paths r:rzFakeFilesystem.normpathsG,==&&//(33x%%h//#..s33(0 ) )   "h,, 400( 8 8I 9#3#3F"", -b1V;;.11333% % , ,Y 7 7 7 7";<<  2 >1N~%,,r9cfd}jssSgj}D]}t |t s |cS|t|\}}|'t |t r|j|j dkr |cStt |} ||S)aDReturn a normalized case version of the given path for case-insensitive file systems. For case-sensitive file systems, return path unchanged. Args: path: the file path to be transformed Returns: A version of path matching the case of existing path elements. cttkr4dtdDj}|}r|s||z}t|dkr|r||z }|S)Nc34K|]}t|VdSryrrs r: zLFakeFilesystem._original_path..components_to_path..3s9--%&IaLL------r9r2)rextendr>r]rstarts_with_drive_letter)rqnormalized_pathnormalized_componentsrrr`s r:components_to_pathz9FakeFilesystem._original_path..components_to_path1s?##c*?&@&@@@%,,--*9#>S:T:T:V:V*W---%C!hh'<==O##D)) 8$2F2F2W2W 8"%"7?##q((T-J-J..( 3&" "r9Nr) rLreplace_windows_rootrrr'rrr#_byte_contentsst_sizerr) r`rrlrrdir_namerrkrs `` @@r:rzFakeFilesystem._original_path%sR # # # # # # # #  !  K((..//55 "i ( 3 3Ik=99 ,))+++++"&"9"9Yy11## Hi 9m44!,4%**))+++++}i88K ! ( ( 2 2 2 2!!###r9c||}t||j}|s||}|t|dkr|}n||s]t||jj}t|d}||||kr|p||f}n||}| |S)arAbsolutize and minimalize the given path. Forces all relative paths to be absolute, and normalizes the path to eliminate dot and empty components. Args: path: Path to normalize. Returns: The normalized path relative to the current working directory, or the root directory if path is empty. rYrE) rr$rr_starts_with_root_pathrrr]rmr)r`rr root_nameemptys r:rzFakeFilesystem.absnormpathVs}}T""dDH-- 1**400D ?4-- - -DD,,T22 3'din==I#D"--E**40055 !)c2UD9DD,,T22D}}T"""r9c~t|}||}||}||n||z}||\}}t |}|r!||dz |vr|dz}|r ||dz |v|d|||d}}||p|}||z|fS)aMimic os.path.split using the specified path_separator. Mimics os.path.split using the path_separator that was specified for this FakeFilesystem. Args: path: (str) The path to split. Returns: (str) A duple (pathname, basename) for which pathname does not end with a slash, and basename does not contain a slash. Nr)r"rrrrrstrip) r`rrqrUsepsriheadtails r: splitpathzFakeFilesystem.splitpathts %%%%d++22488oss3=ood++ t II DQKt++ FA DQKt++"1"XtABBxd{{4  (Dt|T!!r9c^t|}|jr t|dkr||}||}|dd|dzkr|dd|kr||d}|dkr |dd|fS|||dz}||dzkr |dd|fS|dkrt|}|d|||dfS|ddt |dkr|dd|ddfS|dd|fS)aSplits the path into the drive part and the rest of the path. Taken from Windows specific implementation in Python 3.5 and slightly adapted. Args: path: the full path to be splitpath. Returns: A tuple of the drive part and the rest of the path, or of an empty string and the full path if drive letters are not supported or no drive is present. r2rrr4Nr:)r"rdrrrfindr$)r`rr^norm_strrq sep_index sep_index2s r:rzFakeFilesystem.splitdrivesb$D))   68}}!!==22--h77QqSMS1W,,8AaC=C3G3G!) c1 5 5I B'|X55!)sIM!B!BJ!Y]22'|X55!R''%(]] #KZK0(:;;2GGGAaC=OHc$B$BBB#BQB<!""55|X%%r9ctj|}t|tr?|j}d}|j}||}d}d}d}n|j}|j}d}d}d}|jr*|r|||n|} | dd|kr| dd |kr| dd  |krd nd } | || } | d kr|||fS| || dz} | d kr|||fS|d| || | dz|| dzdfS||dd|ddfS| dd |kr@| d d |kr|dd |d d |d dfS|dd ||d dfS|||fS|dd|kr|||fS|dd |ks|d d |kr |||ddfS||dd |d dfS) zlSplit a pathname into drive, root and tail. Implementation taken from ntpath and posixpath. N:s\\?\UNC\r9r}z\\?\UNC\rErr2r4r) rSfspathr'bytesr>encodertrdrPupperr~) r`rrrqrvrtcolon unc_prefixrtnormpstartindexindex2s r: splitrootzFakeFilesystem.splitroots IdOO a   %,,..CF)-)H &)53::<<E(JEE%C4FE'JE  # +.4;AIIfc***!ERaRyC1:$$"'rr!2!2j!@!@AAaE!JJsE22E{{ %."ZZUQY77F|| %.WfW:q&1*)<'=q!NN!!BQB%122..qsu$$1:$$RaR5!AaC&!ABB%//RaR5%122..eQ&!u||eQ&1Q33!AaC&C--c1QRR5((aeQqrrU**r9 all_pathsc<|d}|dd}||}|||g}||\}}|D]}||\} } | r| dd|vr | s|s| }| }1| r>| |kr8|js*| |kr| }| }o| }|r|dd|vr||z}|| z}t |d} |r$|dd|vr|r|dd| kr||z|zS||zS)zSTaken from Python 3.5 os.path.join() code in ntpath.py and slightly adaptedrrNr4r})rrrrLrr$) r`r base_path paths_to_addrqrw result_drive result_pathr drive_part path_partrs r:_join_paths_with_drive_supportz-FakeFilesystem._join_paths_with_drive_supportsaL  } %%i00T55i@@A$(OOI$>$>! k  2 2D$(OOD$9$9 !J  *Yrr]d22.\.#-L'  * l : :)Z-=-=-?-?.s 888$bioo888r9rrN)rrdrrrr)r`r file_pathsrrq path_segments r: joinpathszFakeFilesystem.joinpathss98%888 z??a  8O   D646 C C!}%%jm44&qrrN + +L&&s++ +4 +#s## + $l** r9cdSryr8rs r:rzFakeFilesystem._path_components-s8;r9cdSryr8rs r:rzFakeFilesystem._path_components0s.ts@$)!& 1B1B Br9F) r$risalphardrSranyrentriesget_object_from_normpathr)r`rrs ` r:riz'FakeFilesystem.starts_with_drive_letter^s 3// y>>Q  9QqS>#9#9#;#;  !A#RW@W@W! tw$ !9~~**"-1]-B   11)<<<4!!! 55!us)7B8!B88 CCc6t||jj}||}||pU|j o8||p||Sry)r$rrrVrrLrrir`rrss r:rrz%FakeFilesystem._starts_with_root_paths#Ity~>> ,,Y77   + + 8))@!!,,Y__->->?? 8,,Y77  r9cX|r|jr|jr||}|dd|krvt|dks|dd|krU|jD]+}t ||}||r|cS,t ||j}||ddz}|S)zIn windows, if a path starts with a single separator, it points to the root dir of the current mount point, usually a drive - replace it with that mount point path to get the real path. rrr2N)rdrrrrYr$rr)r`rrqrrs r:rmz#FakeFilesystem.replace_windows_roots  .D& .4= .))$//CAaCyCSYY!^^tAaCyC7G7G!%!2$$I /i @ @Iy11$# $.dD4FGG "T!""X- r9clt||jj}||kp||Sry)r$rris_mount_pointrs r: _is_root_pathzFakeFilesystem._is_root_paths3#Ity~>> I%G)<)->-@-@@@ttur9ct|trdSt|}|sdS||}||}|||fvo-||p|duo||S)z@Return `True` if ``file_path`` ends with a valid path separator.FN)r'r(r"rrr)r`rrrqrvs r:rz'FakeFilesystem.ends_with_path_separators dC  5$T**  5%%i0011)<<f -   s # # XvT'9'Xi>P>PQW>X>X r9c||sdS|||Srk)risfile!_path_without_trailing_separatorsrs r:!is_filepath_ending_with_separatorz0FakeFilesystem.is_filepath_ending_with_separators=,,T22 5{{4AA$GGHHHr9rrcttsdSjvrjfS|jsfdjD}|r|dSdS)NNNcg|];}|k,|j|f.sM   <<>>Y__%6%666*623666r9r)r'rrrL)r`rrmatching_contents `` r:rz!FakeFilesystem._directory_contents)]33 :  ) ) )i/ :: :% +     '/       +'**zr9 check_linkcP|r||rdSt||}|t|sdS||jkr|j pt jdkS ||rdS| |}n#t$rYdSwxYw| |rdS| |}|j }|D]E}||t|d}|dStt |}FdS)aNReturn true if a path points to an existing file system object. Args: file_path: The path to examine. check_link: If `True`, links are not followed Returns: (bool) `True` if the corresponding object exists. Raises: TypeError: if file_path is `None`. TNFrrr)islinkr#r"rrzrdrHrr resolve_pathrrrrrrr)r`rrrrrrrs r:existszFakeFilesystem.existss]  $++i00 4..y99:: <O 5 4<  ))GS-=-G G 55d;; u$$T**DD   55    d # # 4%)%:%:4%@%@i ( 9 9I// Yy=Q=QRRSTUI uu}i88KKts-BB B('B(rc|rAt|tr,||jSt |}|t dtjdkrV|j tj krA| t|tjt||j}|r||s |t$j||||}||}||r|S|t||jkr|S||}||}||}||S)aFollow a path, resolving symlinks. ResolvePath traverses the filesystem along the specified file path, resolving file names and symbolic links until all elements of the path are exhausted, or we reach a file which does not exist. If all the elements are not consumed, they just get appended to the path resolved so far. This gives us the path which is as resolved as it can be, even if the file does not exist. This behavior mimics Unix semantics, and is best shown by example. Given a file system that looks like this: /a/b/ /a/b/c -> /a/b2 c is a symlink to /a/b2 /a/b2/x /a/c -> ../d /a/x -> y Then: /a/b/x => /a/b/x /a/c => /a/d /a/x => /a/y /a/b/c/d/e => /a/b2/d/e Args: file_path: The path to examine. allow_fd: If `True`, `file_path` may be open file descriptor. Returns: The resolved_path (str or byte). Raises: TypeError: if `file_path` is `None`. OSError: if `file_path` is '' or a part of the path doesn't exist. Nz/Expected file system path string, received Noner;)r'r(rLrQrr"rrHrIrSr.r7rPr$rqr>_valid_relative_pathrrrrrrmrrzr_resolve_components_components_to_path)r`rrrrresolved_componentss r:rzFakeFilesystem.resolve_pathsL  C 9c22 C%%i00;;==B B ** <MNN N <7 " "tw&.'@'@<<bf--d&9::D 4444T:: 4    d 3 3 3 3 3D 9 9::((..   d # # K ?466 6 6K//55"66GG''(;<<((...r9c|r||dn|j}||}||s||z}|Srs)rr>r]rr)r`component_foldersrqrs r:rz"FakeFilesystem._components_to_pathAsh! %D # #$5a$8 9 9 9$ xx)****400 :D r9 componentscH|j}d}d|D}g}|r|d}|||||d}|||nt |jr}|tkr3|tj | || ||}| |} | |z}g}|j}|dz }ntt|}||S)Nrc,g|]}t|Sr8r)rcomps r:rz6FakeFilesystem._resolve_components..OsBBBt9T??BBBr9r)rr\rrrhr r_MAX_LINK_DEPTHrrELOOPr _follow_linkrrr) r`rr link_depthrrrr link_pathtarget_componentss r:rz"FakeFilesystem._resolve_componentsLsQi  BBzBBB)+! ='++A..I  & &y 1 1 1// YGGJI $**?;;;*++ =//'' 001DEE!--.A9MM %)$9$9)$D$D!"3o"E&(#"i a "=)<< C! =D#"r9c|jrdSt||jdz}|rQ||vrM|d||}|||sdS|r||vMdS)NTrZF)rdr$r>rfindrr)r`r slash_dotdots r:rz#FakeFilesystem._valid_relative_pathus   4&y$2E2LMM  LI55!"AIOOL$A$A"ABI;;t// ::;; u LI55tr9link_path_componentslinkcd|j}||jr|dr |dd}||}||s4|dd}||||}||Std)a9Follow a link w.r.t. a path resolved so far. The component is either a real file, which is a no-op, or a symlink. In the case of a symlink, we have to modify the path as built up so far /a/b => ../c should yield /a/../c (which will normalize to /a/c) /a/b => x should yield /a/x /a/b => /x/y/z should yield /x/y/z The modified path may land us in a new spot which is itself a link, so we may repeat the process. Args: link_path_components: The resolved path built up to the link so far. link: The link object itself. Returns: (string) The updated path resolved after following the link. Raises: OSError: if there are too many levels of symbolic link Nz\\?\r4z Invalid link) contentsrdrrrrrr]rr3)r`rrrrqrs r:rzFakeFilesystem._follow_links.M  ! *i&:&:9&E&E *%abbM )))44C..y99 1 2#2#6 !!),,,HHZ00 ==++ +(((r9rrrct|}|t||jjkr|jS|t||jkr|jS||}||}|j} |D] }t|j r4|j r-tt| |j }t|j sG|js |t"j||t"j|||}t+sC|s|r?|r=|||||s%|t"j|jn0#t2$r#|t"j|YnwxYw|S)aUSearch for the specified filesystem object within the fake filesystem. Args: file_path: Specifies target FakeFile object to retrieve, with a path that has already been normalized/resolved. check_read_perm: If `True`, raises `OSError` if a parent directory does not have read permission check_exe_perm: If `True`, raises `OSError` if a parent directory does not have execute (e.g. search) permission check_owner: If `True`, and ``check_read_perm`` is also `True`, only checks read permission if the current user id is different from the file object user id Returns: The FakeFile object corresponding to file_path. Raises: OSError: if the object is not found. )r"r$rrrzrZrrr rrrrrr rdrrrrrr _can_readEACCESrKeyError) r`rrrrrrrrs r:rz'FakeFilesystem.get_object_from_normpaths6 ** ?488 8 89  ?466 6 6= ""4((//55 4, C C 6>**TT!%mT\\&/5R5R!S!Sv~..<-A++EM4@@@'' d;;;)))44 C(C,:CC!NN C'' fkBBB# C$ 4 4 4    d 3 3 3 3 3 4 sDF*GGc|r|jtjkrdS|r tjnd}t |jr|r|tjz}|sdS||S)NTr)st_uidrget_uid PERM_READr rPERM_EXEhas_permission)rrrowner_can_read permissions r:rzFakeFilesystem._can_reads|  fmw/@/@@@4*9@W&&q 6> " " +~ + '* *J 4$$Z000r9ct|}|||}||||S)aSearch for the specified filesystem object within the fake filesystem. By default, consider read and execute permissions. Args: file_path: Specifies the target :py:class:`FakeFile` object to retrieve. check_read_perm: If `True`, raises `OSError` if a parent directory does not have read permission check_exe_perm: If `True`, raises `OSError` if a parent directory does not have execute (e.g. search) permission Returns: The :py:class:`FakeFile` object corresponding to `file_path`. Raises: OSError: if the object is not found. )r"rrr)r`rrrrs r:rzFakeFilesystem._get_objectsJ0 ** 3 3D 9 9::,,T?NSSSr9c2||ddS)aSearch for the specified filesystem object within the fake filesystem and return it. Ignore any read permissions. Args: file_path: Specifies the target :py:class:`FakeFile` object to retrieve. Returns: The :py:class:`FakeFile` object corresponding to `file_path`. Raises: OSError: if the object is not found. Frr)r)r`rs r:rQzFakeFilesystem.get_objects  5QVWWWr9cTt|trQ|r@||}t|tsJ|St d|r,|||||||S||S)aSearch for the specified filesystem object, resolving all links. Args: file_path: Specifies the target FakeFile object to retrieve. follow_symlinks: If `False`, the link itself is resolved, otherwise the object linked to. allow_fd: If `True`, `file_path` may be an open file descriptor check_read_perm: If `True`, raises `OSError` if a parent directory does not have read permission check_read_perm: If `True`, raises `OSError` if a parent directory does not have execute permission check_owner: If `True`, and ``check_read_perm`` is also `True`, only checks read permission if the current user id is different from the file object user id Returns: The FakeFile object corresponding to ``file_path``. Raises: OSError: if the object is not found. z4path should be string, bytes or os.PathLike, not int) r'r(rLrQFakeFilerrrlresolve)r`rrrrrr open_files r:rzFakeFilesystem.resolve s< i % % T ! ..y99DDFF !)X66666  RSS S  00!!)X66   }}Y'''r9ct|}|s |tj||t ||jjkr|jS||}|t |dkrt ||j}| |}| |\}}|st ||j} | |}|sJt|ts\|js5t|tr |tj||tj||t$js |tj||r"|t-|n|S#t.$rYnwxYw|tj|dS)aSearch for the specified object, resolving only parent links. This is analogous to the stat/lstat difference. This resolves links *to* the object but not of the final object itself. Args: path: Specifies target FakeFile object to retrieve. Returns: The FakeFile object corresponding to path. Raises: OSError: if the object is not found. rYN)r"rrrr$rrrrrr{rr'rrdrrrrrrrr#r)r`rr^parent_directory child_name parent_objs r:rzFakeFilesystem.lresolveNs$D)) 8    h 7 7 7 x@@ @ @9 99(CC x55 5 5&x::H&&x00'+~~h'?'?$* C.xBB  &677J  :j-88 <)AjX.N.NA'' x@@@##EL(;;;,,W->?? D##EL2BCCC $$Yz%:%:;;;      D  EL(33333sC.G GGc,|s|j}nttt||dd}t |js5|jr tjn tj }| ||| |dS)a:Add a fake file or directory into the filesystem at file_path. Args: file_path: The path to the file to be added relative to self. file_object: File or directory to add. Raises: OSError: if file_path does not correspond to a directory. FTrN) rrrrr rrdrrrrr)r`rr target_directoryerrors r: add_objectzFakeFilesystem.add_objects 6#}  # Yd SS   +344 6(,(:M  ##E9555"";/////r9 old_file_path new_file_path force_replacect|}t|}||}||}||}||ds!|t j|d|r||||}|j s| |||||dr| |||||}|dS|}| |\} } | |\} } || s |t j| | | } | | }| j|jkr |t j|t!|js3||j r t jn t j|||r |t j||| | || dS)aRenames a FakeFile object at old_file_path to new_file_path, preserving all properties. Args: old_file_path: Path to filesystem object to rename. new_file_path: Path to where the filesystem object will live after this call. force_replace: If set and destination is an existing file, it will be replaced even under Windows if the user has permissions, otherwise replacement happens under Unix only. Raises: OSError: if old_file_path does not exist. OSError: if new_file_path is an existing directory (Windows, or Posix if old_file_path points to a regular file) OSError: if old_file_path is a directory and new_file_path a file OSError: if new_file_path is an existing file and force_replace not set (Windows only). OSError: if new_file_path is an existing file and could not be removed (Posix, or Windows with force_replace set). OSError: if dirname(new_file_path) does not exist. OSError: if the file would be moved to another filesystem (e.g. mount point). Trr2N)r"rrrrrr%_handle_broken_link_with_trailing_seprrd_handle_posix_dir_link_errors_rename_to_existing_pathr{rrEXDEVr rEINVALrhas_parent_object _do_rename)r`rrrold_pathnew_path ends_with_sep old_object renamed_pathold_dirold_namernew_nameold_dir_objectnew_dir_objects r:renamezFakeFilesystem.renamesV<$M22#M2255h?? ##H--##H--{{8{55 ;    h : : :  A  6 6x @ @ @]]8,, ! R  . .x= Q Q Q ;;xD; 1 1 (88x:}L#' NN844 NN844{{7## 7    g 6 6 6g..g..  N$9 9 9    X 6 6 6~-..     $ 2E  x     + +J 7 7 8    h 7 7 7 .(KKKKKr9c||}||d||_||}||jvr||nd} |r||||dS#t $r>|r||jvr||||_||wxYw)NF) recursive)r remove_entryr_normalized_entrynamerrr)r`r r r r object_to_rename old_entrys r:rzFakeFilesystem._do_renames)33H==##H#>>> (!77AA>111  $ $X . . .   6++H555  $ $%5 6 6 6 6 6    4X^-CCC((333$,  !  $ $%5 6 6 6   s *,BAC c||rL||s9|jr tjn tj}|||dSdSdSry)rrrerrrr)r`rrs r:rz4FakeFilesystem._handle_broken_link_with_trailing_sepsn ;;t   1;;t$$ 1(, H 5=##E400000 1 1 1 1r9rc||dr5||r |tj|||drP||r;|r |jrdS|r tjn tj}||||rD||r1||kr-|js(|tj|dSdSdSdSdSNFr)isdirrrrrreEISDIRrd)r`rrrrs r:rz,FakeFilesystem._handle_posix_dir_link_errorss8 ::mU: ; ; > A A  >    } = = = ::mU: ; ; 6 A A  6  %2DEMM E   } 5 5 5  > M** >..&/    } = = = = =  > > > >/...r9rc||}||krMt|js7|r5|jr tjn tj}|||dS||kr|||St|jst|jr| |||||nt|jr6|jr tj n tj}|||n?|jr#|s!|tj |n| ||Sry) rr rrdrrr_rename_same_objectr $_handle_rename_error_for_dir_or_linkr remove_object)r`rrrrr new_objectrs r:rz'FakeFilesystem._rename_to_existing_pathsh%%m44 M ) ):-.. := :)-);N ##E=9994  # #++M=II I :% & & .'*2D*E*E .  5 5     Z' ( ( .$($6IELLEME   } 5 5 5 5   .  .    m < < < <   } - - -r9rc|jrC|r!|tj|n |tj|t |jsz|jr=t |jr |r|js |tj |t|jr$|tj |dSdSdSry) rdrrrrr rrre ENOTEMPTYr r)r`rrrrrs r:rz3FakeFilesystem._handle_rename_error_for_dir_or_link3s   A A##EL-@@@@##EL-@@@z)** A! H 233H(H =H ''GGGz)** A##EL-@@@@@ A A A Ar9c||k}|s> ||}||}||}||krz||k||kkrH||d}tj||jkp|j }n*||k}|rA| |\}} | ||| }n#t$rYnwxYw|sdS|Sr) rrrrrSrbasenamerrer{rr) r`rr do_rename real_old_pathoriginal_old_path real_new_path real_objectparent file_names r:rz"FakeFilesystem._rename_same_objectKs"''))]-@-@-B-BB    $ 1 1- @ @ $($7$7 $F$F! $ 1 1- @ @  $555!]2#))++}/B/B/D/DD;F;F#',,}e,"T"TK((77;;KK-#},I !. 3 3 5 59L9L9N9N NI)-}(E(E%FI$(NN++F33Y%%M       4sD,E E)(E)c|||}||r |tj| ||\}}||d}||dS#t$r$|tj |YdSt$r$|tj |YdSwxYw)anRemove an existing file or directory. Args: file_path: The path to the file relative to self. Raises: OSError: if file_path does not correspond to an existing file, or if part of the path refers to something other than a directory. OSError: if the directory is in use (eg, if it is '/'). FrN) rrrrrEBUSYr{rrrrAttributeErrorr)r`rdirnamer"rs r:rzFakeFilesystem.remove_objectos $$T%8%8%C%CDD   i ( ( 8    Y 7 7 7 : $y 9 9 GX#||GU|KK   ) )( 3 3 3 3 3 9 9 9    i 8 8 8 8 8 8 : : :    y 9 9 9 9 9 9 :sAB%%*C?)C?>C?ct|}t|tj}||}|||Sry)r"r$rSrqrrP)r`rr^os_sepfake_seps r:r"zFakeFilesystem.make_string_pathsI#D)) 2622**844111r9 perm_bits apply_umaskc||}||}||||dr)||jvr |t j|||}|j }g}d|DD]}| |t|d} | sWt||} | | |jr||j kr|j}|| | }t#| jr'| jsJ|| j} | sJt+t| }| jt,zt,kr%|t j|j|D]} |r ||jz}t,|z| _|S)aCreate `directory_path` and all the parent directories, and return the created :py:class:`FakeDirectory` object. Helper method to set up your test faster. Args: directory_path: The full directory path to create. perm_bits: The permission bits as set by ``chmod``. apply_umask: If `True` (default), the current umask is applied to `perm_bits`. Returns: The newly created :py:class:`FakeDirectory` object. Raises: OSError: if the directory already exists. Trc,g|]}t|Sr8rrs r:rz-FakeFilesystem.create_dir..rr9rr)r"rrrrYrrrrrrr#rrrdrrr rrrrrrrrT) r`rr1r2rrrrrrrs r: create_dirzFakeFilesystem.create_dirs0((88##H-- ((222 ;;xD; 1 1 8hdFW6W6W    h 7 7 7//99i @@@@@ I II// Yy=Q=QRRSTUI I' dCCC(((%0+*B*B"&-K%%g...% 9,--%$---- $ Y-? @ @I$$$9"=)<< $w.'99'' {7GHHH  2 2G )dj[( % 1GOOr9rErrrocreate_missing_dirsencodingerrors side_effectc >||||||||||  S)aCreate `file_path`, including all the parent directories along the way, and return the created :py:class:`FakeFile` object. This helper method can be used to set up tests more easily. Args: file_path: The path to the file to create. st_mode: The `stat` constant representing the file type. contents: the contents of the file. If not given and `st_size` is `None`, an empty file is assumed. st_size: file size; only valid if contents not given. If given, the file is considered to be in "large file mode" and trying to read from or write to the file will result in an exception. create_missing_dirs: If `True`, auto create missing directories. apply_umask: If `True` (default), the current umask is applied to `st_mode`. encoding: If ``contents`` is of type `str`, the encoding used for serialization. errors: The error mode used for encoding/decoding errors. side_effect: function handle that is executed when the file is written, must accept the file object as an argument. Returns: The newly created :py:class:`FakeFile` object. Raises: OSError: if the file already exists. OSError: if the containing directory is required and missing. )r9)create_file_internally) r`rrrror6r2r7r8r9s r: create_filezFakeFilesystem.create_files=T**        #+   r9 source_path read_only target_pathc4|p|}t|}tj|}||d}|j||r|xjdzc_||_||j |j |j |S)aCreate `file_path`, including all the parent directories along the way, for an existing real file, and return the created :py:class:`FakeFile` object. The contents of the real file are read only on demand. Args: source_path: Path to an existing file in the real file system read_only: If `True` (the default), writing to the fake file raises an exception. Otherwise, writing to the file changes the fake file only. target_path: If given, the path of the target direction, otherwise it is equal to `source_path`. Returns: the newly created :py:class:`FakeFile` object. Raises: OSError: if the file does not exist in the real file system. OSError: if the file already exists in the fake file system. .. note:: On most systems, accessing the fake file's contents may update both the real and fake files' `atime` (access time). In this particular case, `add_real_file()` violates the rule that `pyfakefs` must not modify the real file system. T)read_from_real_fsi$) r"rSr r;rset_from_stat_resultrrrr>rr)r`r=r>r?source_path_str real_statrs r: add_real_filezFakeFilesystem.add_real_files>"0[ *;77GO,, // t/TT  229===  *    )  -  y~y~y?OPPPr9ct|}||}tj|s?tj|s |tj|tj |}|r| ||S| ||S)aCreate a symlink at `source_path` (or `target_path`, if given) and return the created :py:class:`FakeFile` object. It will point to the same path as the symlink on the real filesystem. Relative symlinks will point relative to their new location. Absolute symlinks will point to the same, absolute path as on the real filesystem. Args: source_path: The path to the existing symlink. target_path: If given, the name of the symlink in the fake filesystem, otherwise, the same as `source_path`. Returns: the newly created :py:class:`FakeFile` object. Raises: OSError: if the directory does not exist in the real file system. OSError: if the symlink could not be created (see :py:meth:`create_file`). OSError: if the directory already exists in the fake file system. ) r"rrSrrrrrrreadlinkcreate_symlink)r`r=r?rCrs r:add_real_symlinkzFakeFilesystem.add_real_symlink* s.+;77@@QQw~~o.. ?rw~~o7V7V ?    o > > >_--  @&&{F;; ;&&?? ?r9 lazy_readct|}||}tj|s |t j|t|p|}tjtj |}tj |j kr%| tj |j }| ||r||||n||||t!t"||S)aCreate a fake directory corresponding to the real directory at the specified path, and return the created :py:class:`FakeDirectory` object. Add entries in the fake directory corresponding to the entries in the real directory. Symlinks are supported. If the target directory already exists in the fake filesystem, the directory contents are merged. Overwriting existing files is not allowed. Args: source_path: The path to the existing directory. read_only: If set, all files under the directory are treated as read-only, e.g. a write access raises an exception; otherwise, writing to the files changes the fake files only as usually. lazy_read: If set (default), directory contents are only read when accessed, and only until the needed subdirectory level. .. note:: This means that the file system size is only updated at the time the directory contents are read; set this to `False` only if you are dependent on accurate file system size in your test target_path: If given, the target directory, otherwise, the target directory is the same as `source_path`. Returns: the newly created :py:class:`FakeDirectory` object. Raises: OSError: if the directory does not exist in the real filesystem. OSError: if a file or link exists in the fake filesystem where a real file or directory shall be mapped. )r"rrSrrrrrrvrrqr>rPr!_create_fake_from_real_dir_lazily_create_fake_from_real_dirrrr)r`r=r>rJr?rCtarget_path_strs r:add_real_directoryz!FakeFilesystem.add_real_directoryM s'P+;77@@QQw~~o.. ?    o > > >*;+I/JJ 9  g..??O 6T( ( (-55bfd>QRRO ((999  Y  2 2)      + +O_i X X XM4#3#3O#D#DEEEr9c ||s||tj|D]H\}}}tj|tj||}tj|D]u}tj||} tj| r4| | tj||v|D]v}tj||} tj| s5| | |tj||wJdSry) rr5rSwalkrr]relpathlistdirrrIrE) r`rCrNr>base_filesnew_base file_entryrrs r:rMz)FakeFilesystem._create_fake_from_real_dir s[{{?++ - OOO , , , go66  ND!Uw||o66H!j.. Y Y GLLz:: 7>>),,Y)))RW\\(J5W5WXXX#   w||D*55w~~d++&&ih )K)K   r9c||r?||sttjdt j|D]}t j||}t j||}t j|r| ||d|zt j |r| ||t j |r| |||||St j|d}||r||}n||}t#||||} || | S)Nz!Mapping target is not a directoryTr)rrrrrrSrSrr]rOrrIrrErr[r5FakeDirectoryFromRealDirectoryr) r`rCrNr>rsrc_entry_pathtarget_entry_path parent_pathrrs r:rLz0FakeFilesystem._create_fake_from_real_dir_lazily s ;; ' ' 5::o.. Rem-PQQQO44 U U!#ou!E!E$&GLL%$H$H!7==00U++& 49JW^^N33U)).:KLLLLW^^N33U&&~yBSTTT##O44 4gmmO44Q7 ;;{ # # 6))+66JJ55J0 T9o   W%%%r9 path_list lazy_dir_readc|D]O}tj|r||||9|||PdS)aThis convenience method adds multiple files and/or directories from the real file system to the fake file system. See :py:meth:`add_real_file` and :py:meth:`add_real_directory`. Args: path_list: List of file and directory paths in the real file system. read_only: If set, all files and files under the directories are treated as read-only, e.g. a write access raises an exception; otherwise, writing to the files changes the fake files only as usually. lazy_dir_read: Uses lazy reading of directory contents if set (see :py:meth:`add_real_directory`) Raises: OSError: if any of the files and directories in the list does not exist in the real file system. OSError: if a file or link exists in the fake filesystem where a real file or directory shall be mapped. N)rSrrrOrE)r`r^r>r_rs r:add_real_pathszFakeFilesystem.add_real_paths sg4 4 4Dw}}T"" 4''iGGGG""43333  4 4r9 package_namectjdkrtdddlm}m}|jr| ||j}| |||D])}| | * |jr| dSdS#|jr| wwxYw)a Convenience function to add all metadata distribution files of the package with the given name to the fake filesystem. These are the files that are usually located under `-.dist-info` beside the actual package. The files are accessed by the functions in `importlib.metadata`. Args: package_name: Name of the package whose metadata shall be copied Raises: PackageNotFoundError: if the package with the given name is not found rzNot available in Python 3.7r) distributionPackageNotFoundErrorN) rHrNotImplementedErrorimportlib.metadatardrer@rrVrElocater)r`rbrdre dist_files metadata_files r:add_package_metadataz#FakeFilesystem.add_package_metadata s  f $ $%&CDD DIIIIIIII <  JJLLL %l339J!**<888!+ ; ; ""=#7#7#9#9:::: ;|    t|   s A B--C rAc ||} || } t|std|| dr |t j| || \} } | st| |j } | | || sK|s |t j | t| | | j} n|| } |r ||jz}| r t#t%| || }nt'| ||||| }|| |||d}| sW||S |||n||n$#t.$r|| wxYw|S)aInternal fake file creator that supports both normal fake files and fake files based on real files. Args: file_path: path to the file to create. st_mode: the stat.S_IF constant representing the file type. contents: the contents of the file. If not given and st_size is None, an empty file is assumed. st_size: file size; only valid if contents not given. If given, the file is considered to be in "large file mode" and trying to read from or write to the file will result in an exception. create_missing_dirs: if `True`, auto create missing directories. apply_umask: whether the current umask must be applied on st_mode. encoding: if contents is a Unicode string, the encoding used for serialization. errors: the error mode used for encoding/decoding errors read_from_real_fs: if `True`, the contents are read from the real file system on demand. side_effect: function handle that is executed when file is written, must accept the file object as an argument. z;st_mode must be of int type - did you mean to set contents?Tr)rr9)rr7r8r9NrE)r"rr!rrrrrr{r$rrrr5rrrTFakeFileFromRealFiler#rrset_large_file_sizeset_initial_contentsrr)r`rrrror6r2r7r8rAr9rrnew_filer s r:r;z%FakeFilesystem.create_file_internally sRF$$Y//%%7## M  ;;t; - - 4    d 3 3 3%)^^D%9%9"( ?.tTX>>  (()9:::{{+,, E& D##EL2BCCC. 0116     $223CDD   #  { "G  .$DkKK#!' K (+666 ?x/H  h&:g>Q &33G<<<<44X>>>   ""4((( s -G!G/ link_targetc||}||}||}||r7||r |t j|||r(|js |t j|n|jr |t j ||| |ds |t j||j r-||dr| |n |t j|| |s||}|jr tjn tj}||t&|z|||j S)aCreate the specified symlink, pointed at the specified link target, and return the created :py:class:`FakeFile` object representing the link. Args: file_path: path to the symlink to create link_target: the target of the symlink create_missing_dirs: If `True`, any missing parent directories of `file_path` will be created Returns: The newly created :py:class:`FakeFile` object. Raises: OSError: if the symlink could not be created (see :py:meth:`create_file`). Tr)rrr6r2)r"rrrrrrrdrrrrerrrr PERM_DEF_FILErr;r )r`rrqr6rlink_target_pathrs r:rHzFakeFilesystem.create_symlinkT s.)))44 00==MM),,  ( ( 3 3 H{{9%% =##EL)<<<{{+,, H)A'' i@@@%I'' 7GHHH{{::9EE##H'' 6FGGG=H{{9{>>6**9555'' 6FGGG{{9%% 5)))44I.2.@VW**gFV ** j(% 3 +   r9rrct|}t|}||}||dr |tj|||\}} |st||j}||s8|r| |n |tj || |r |tj ||j s5| |r |tj | |||} n0#t$r#|tj |YnwxYw| jt"zr3||j r tjn tj|| | _||| | S)aCreate a hard link at `new_path`, pointing at `old_path`, and return the created :py:class:`FakeFile` object representing the link. Args: old_path: An existing link to the target file. new_path: The destination path to create a new link at. follow_symlinks: If `False` and `old_path` is a symlink, link the symlink instead of the object it points to. create_missing_dirs: If `True`, any missing parent directories of `file_path` will be created Returns: The :py:class:`FakeFile` object referred to by `old_path`. Raises: OSError: if something already exists at `new_path`. OSError: if `old_path` is a directory. OSError: if the parent directory doesn't exist. Trr)r"rrrrrr{r$rr5rrrrdrrrrrEPERMrr) r`rrrr6 old_path_str new_path_strnew_path_normalizednew_parent_directory new_basenameold_files r: create_linkzFakeFilesystem.create_link s8(11 '11 "..|<< ;;*t; < < <    l ; ; ;-1^^r partitionrrrrrrerrr#rrT)r`rrrprrrestbase_direllipsis dummy_dotdotrUerror_nrryrzs r:makedirzFakeFilesystem.makedir sa$H--55h?? 99(CC 2    b 1 1 1   2''11H>>(33 D  <}}Z00H&z43F3MNNH""8,, KT5G K,6,@,@,J,J),! =$ =t{{87L7L =00<<<;;x(( <##EL(;;;##H-- ;;xD; 1 1 8! (h$2D&D&D < < 8 8t{{87L7L 8""8,,,,##Hh777^^H-- d  dOO )D//44:++=$ O O O     r9cn||r|dd}|||S)Nr4)rrs r:rz0FakeFilesystem._path_without_trailing_separatorsR sB++D11 9D++D11  r9rpexist_okc|s |tjd||}||}|rH|jrA||dr*||s||t|}| |}|j }|D]=}t|dr ||j vrn!tt|j |}> |||dS#t $r} | jtjkr|r(t%||tsf|jr&| jtjkrtj| _|tt,| j| jYd} ~ dSYd} ~ dSd} ~ wwxYw)a~Create a leaf Fake directory and create any non-existent parent dirs. Args: dir_name: (str) Name of directory to create. mode: (int) Mode to create directory (and any necessary parent directories) with. This argument defaults to 0o777. The umask is applied to this mode. exist_ok: (boolean) If exist_ok is `False` (the default), an `OSError` is raised if the target directory already exists. Raises: OSError: if the directory already exists and exist_ok=False, or as per :py:meth:`create_dir`. rETrrN)rrrrrrerrr#rrhasattrrrrr5rrr'rrdrr(r) r`rprrr dir_name_strrrres r:makedirszFakeFilesystem.makedirsW s$ 2    b 1 1 155h?? ##H--  )  ) H 66 )KK))  )   x ( ( ( ** // ==m ( R RIK33 RK$777"=+2Ei2PQQ  D OOHd + + + + + D D Dw%,&& D:dll8.D.Dm#T#T D%+!'U]*B*B#lAG##Dag$6$6 CCCCCCCCC  D D D D D D  DsD G%B GGst_flagc|tt|} |||d}|r1|||| t |j|kSn#t $rYdSwxYwdS)a$Helper function to implement isdir(), islink(), etc. See the stat(2) man page for valid stat.S_I* flag values Args: path: Path to file to stat and test st_flag: The stat.S_I* flag checked for the file's st_mode follow_symlinks: If `False` and path points to a symlink, the link itself is checked instead of the linked object. Returns: (boolean) `True` if the st_flag is set in path's st_mode. Raises: TypeError: if path is `None` NFr)r )rr"rrr rr)r`rrrrobjs r: _is_of_typezFakeFilesystem._is_of_type s, <O$T**  ,,y/5,QQC 6==s3F>ck**g55  6    55 usA A&& A43A4c:||t|S)aDetermine if path identifies a directory. Args: path: Path to filesystem object. follow_symlinks: If `False` and path points to a symlink, the link itself is checked instead of the linked object. Returns: `True` if path points to a directory (following symlinks). Raises: TypeError: if path is `None`. )rrr`rrs r:rzFakeFilesystem.isdir g???r9c:||t|S)aDetermine if path identifies a regular file. Args: path: Path to filesystem object. follow_symlinks: If `False` and path points to a symlink, the link itself is checked instead of the linked object. Returns: `True` if path points to a regular file (following symlinks). Raises: TypeError: if path is `None`. )rrrs r:rzFakeFilesystem.isfile rr9c<||tdS)aDetermine if path identifies a symbolic link. Args: path: Path to filesystem object. Returns: `True` if path points to a symlink (S_IFLNK set in st_mode) Raises: TypeError: if path is `None`. Fr)rr rs r:rzFakeFilesystem.islink sguEEEr9)r cdS)z+Returns `False`. Junctions are never faked.Fr8rs r: isjunctionzFakeFilesystem.isjunction s5r9rc tt|||||}|jtzs!|t j|d|S)aTest that the target is actually a directory, raising OSError if not. Args: target_directory: Path to the target directory within the fake filesystem. check_read_perm: If `True`, raises `OSError` if the directory does not have read permission check_exe_perm: If `True`, raises `OSError` if the directory does not have execute (e.g. search) permission check_owner: If `True`, only checks read permission if the current user id is different from the file object user id Returns: The FakeDirectory object corresponding to target_directory. Raises: OSError: if the target is not a directory. )rrri )rrrrrrrr)r`rrrrrs r: confirmdirzFakeFilesystem.confirmdir sl4  LL /-'      7* F    /? E E Er9cjt|}||}||r||||r9||d}t |jtkr| |}t |jtkrJ|j r tj }n |jr tj}n tj}||||||rJ|j r tj }n |jr tj}n tj}|||n|||||dS)aRemove the FakeFile object at the specified file path. Args: path: Path to file to be removed. Raises: OSError: if path points to a directory. OSError: if path does not exist. OSError: if removal failed. FrN)r"rrrrrr rrrr rdrrrervrrrrrrr)r`r norm_pathrrrs r:r9zFakeFilesystem.remove s%T** $$Y//  ( ( . . B  6 6y A A A ;;y ! ! I,,y%,@@Cck""g--==33(*++w66)- % - %  % ''y999==!8!8!>!>??:). % . %  % ''y999==dCHHH 9%%%%%r9 allow_symlinkcV|t|dkr5|jr tjn tj}|||||}||}||dr|jsB| |r-|rdS|r|j s |tj || |d}|j r |tj|||dSdS)aRemove a leaf Fake directory. Args: target_directory: (str) Name of directory to remove. allow_symlink: (bool) if `target_directory` is a symlink, the function just returns, otherwise it raises (Posix only) Raises: OSError: if target_directory does not exist. OSError: if target_directory does not point to a directory. OSError: if removal failed per FakeFilesystem.RemoveObject. Cannot remove '.'. rYT)rN)r$rdrrrrrrrrrerrrr r)r`rrrr dir_objects r:rmdirzFakeFilesystem.rmdir8 sB /?EE E E'+'9Ku||u|H   *: ; ; ;556FGG ++,<== ??+? > > 1% I$++6F*G*G I F$IDMI'' 7GHHH&6DIIJ! G##EO5EFFF   / 0 0 0 0 0 1 1r9c|gS||d}||d}t|j}|jrt j||S)aReturn a list of file names in target_directory. Args: target_directory: Path to the target directory within the fake filesystem. Returns: A list of file names within the target directory in arbitrary order. If `shuffle_listdir_results` is set, the order is not the same in subsequent calls to avoid tests relying on any ordering. Raises: OSError: if the target is not a directory. NTr%F)r)rrlistrkeysr_randomshuffle)r`rrdirectory_contentss r:rSzFakeFilesystem.listdirW s~  #I,,-=,MMOO$4UOKK !)"3"8"8":":;;  ' / N- . . .!!r9c*t|jSry)rKrrfs r:__str__zFakeFilesystem.__str__o s4=!!!r9r>CONIN$CONOUT$AUXCONNULPRNch|]}d|S)COMr8rcs r: zFakeFilesystem.v :::QyQyy:::r9u123456789¹²³ch|]}d|S)LPTr8rs r:rzFakeFilesystem.w rr9c,h|]}t|Sr8)chr)rrxs r:rzFakeFilesystem.z s ' ' 'SVV ' ' 'r9r,> *"/r}<>?r|cJjsdSfdtj|d}j |jj}tfdt| jDS)NFc0tjdkrddlm}||S|dddvr|dvSj|rdS|ddd }|j vS) Nr;r)_isreservednamer4)rY )rYrZTrYr) rHrIos.pathr_WIN_RESERVED_CHARS intersectionrrvr_WIN_RESERVED_NAMES)rrr`s r:is_reserved_namez3FakeFilesystem.isreserved..is_reserved_name s<7**777777*?40009 **{22+88>> 4~~c**1-44S99??AAt777r9r2c3.K|]}|VdSryr8)rrrs r:rgz,FakeFilesystem.isreserved.. sB! &&r9) rdrSfsdecoderrtrPr>rreversedr[)r`rrs` @r: isreservedzFakeFilesystem.isreserved} s% u 8 8 8 8 8;t~~d33A677D.:||3T5H$TZZ0C%D%DEE r9c|ttj|ttj|ttjdSry)rBStandardStreamWrapperrHstdinstdoutstderrrfs r:rz$FakeFilesystem._add_standard_streams se 0;;<<< 0<<=== 0<<=====r9cdt_dD]}tj|}|r|cStjdkrtjdSdS)zThis logic is extracted from tempdir._candidate_tempdir_list. We cannot rely on tempdir.gettempdir() in an empty filesystem, as it tries to write to the filesystem to ensure that the tempdir is valid. N)TMPDIRTEMPTMPrz~\AppData\Local\Temp/tmp)tempfiletempdirrSgetenvrr expanduser)r`env_namerps r: _tempdir_namezFakeFilesystem._tempdir_name si  /  Hy**H   7d??7%%&=>> >vr9cl|}||s||tjdkrc|dsP|d|dt t|j d<dSdSdS)Nr;rrr) rrr5rHrIrHrrrYr)r`temp_dirs r:rzFakeFilesystem._create_temp_dir s%%''{{8$$ & OOH % % % <7 " "4;;v+>+> "    1 1 1CDDd'..0011 2 2; ? ? ? # " " "r9)NT)rBNrrkry)T)TF)r4)F)TTF)TT)TFTTF)TN)TTN)r1r2r3r4rSrrqrKrr(rboolrbpropertyrgrdsetterrer>rtrzr}rrrrrr.r[ contextlibcontextmanagerr)rrrrrr&rrrrrrrrr%rrrrrrrrrr rrrr!r)r0 staticmethodr&rrBrFrLrrHrSrVrrrrr{rrrrrrrrirrrmrrrrr rrrrrrrrrrrQrrrr rrrrrrrr"rrr5rrsrr<rErIrOrMrLrarkr;rHr}rrrGrrrrrrrrHrrrr9rrSr frozensetrr:rrrrrr8r9r:r=r=s$!gk$( % G-G-G-SMG- G-  G-  G-G-G-G-R<$<<<X< t   X '4'D''''$X_'d't'''_'::::X:3C3D3333 =HSM===X= &- -$---'&->>>>X>>>>>X>>>>>X>SX Z00000Z0-XsX F   X Y # #4 # # #Y #++ +D++++&'6''''666$    '''')-"& 1119%13- 1  1111.:v:&::::FF8F;KFFFFVFVtVVVV%) 3'3'3'SM3' 3'  3'3'3'3'jg-08D>&T&,-,,,,2CHTN RR8F#3RuS#s]?SRRRR2///HV4D/PT////455,25""""4"&v"&%*?"&"&"&"&H7+f7+7+7+7+r%*%*F%*%*%*%*N66;S;T#Y;;;X; ?U?tE{???X?)V)V ))))V&TB  4    F&HvH$HHHH4(  U3<-@  T     IfIIIII &36 x}hw// 0$&&&T&d&&&&P?/?/f?/?/?/?/?/?/B   '#d6l'#tCy'#'#'#'#Rf,)c,)',)c,),),),)b!%#! 9999 9  9  9999v11\1!%# TTTT T  TTTT8XGXXXXX(!% $#!,(,(%,(,( ,(  ,(  ,(,( ,(,(,(,(\/4W/4/4/4/4/4b0F00T00006$ ELELELEL EL  ELELELELN.1&1T1111>#>4:>KO> >>>>,         &     DAAA A  A  A AAAA0"#"4:" & """"H:v:$::::.2W22222!) :::: :  ::::~!66 !%$( "& $*.4 4 4 4  4 # 4 " 4 4 3-4  4 h'4  4 4 4 4 r)- ****g& *  ****ZFJ!@!@"!@19'1B!@ !@!@!@!@L)- ;F;F;F;F ;F g& ;F  ;F;F;F;Fz&B" 44<44 4  4444@D!66 !%$( "& $"'*.XXXX X # X " XX3-X X Xh'X XXXX|%) ; ; ; ; " ;  ; ; ; ; B!%$( BBBB B " B  BBBBP!%            4(t%!W%!%!%!%!%!N6=5E2 2 2 s2 $2 2 2 2 hf -4,""4<""""0""""" 7""'i = = =::"9::: ;::"9::: ;   (i ' 'UU2YY ' ' '*X*X*X X     8>>>> " D D D D Dr9r=rBcFddl}ddl}||jSrs)doctestrtestmodfake_filesystem)rrs r: _run_doctestr s)NNNOOO ??83 4 44r9cp|dkr tjS|dkr tjStd|d)NUSER_IDGROUP_IDz No attribute rY)rrrr,)rs r: __getattr__r sC y z 2222 3 33r9__main__)[r4rrOrr;rSrrHr collectionsrrrrenumrr rrr r r r r typingrrrrrrrrrrrrrrrrrrpyfakefs.fake_filerr pyfakefs.helpersr!r"r#r$r%r&r'r(r)rIrrr.rrrmrrZFakeFileWrapperrFakeDirWrapperFakePipeWrapperrl FakeOsModule FakeFileOpen FakeIoModuleFakeFcntlModuler\rrset_uidget_gidset_gid reset_idsrrrrrsrr=rrr1r8r9r:rsCCJ ////////                          POOOOOOOOOOOOOOO66666666                      <7##OOOT  %  5' !*!I+!7)+)# % # <7-O   / / / / /          %  B0DB0DB0DB0DB0DB0DB0DB0DJ`5k5555444 zLNNNNNr9