Skip to content

Commit

Permalink
Re-create the temp directory on resetting the filesystem (#818)
Browse files Browse the repository at this point in the history
* Re-create the temp directory on resetting the filesystem

- the temp dir is now created during filesystem
  initialization instead of at patcher setup if configured
- this is only done by default if created from the Patcher
- fixes #814

* Call reset() from __init__

- change from review
  • Loading branch information
mrbean-bremen authored Apr 23, 2023
1 parent 74150ae commit b79f556
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 27 deletions.
6 changes: 6 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# pyfakefs Release Notes
The released versions correspond to PyPI releases.

## Unreleased

### Fixes
* Re-create temp directory if it had been created before on resetting file system
(see [#814](../../issues/814)).

## [Version 5.2.2](https://pypi.python.org/pypi/pyfakefs/5.2.2) (2023-04-13)
Fixes a regression in 5.2.0

Expand Down
45 changes: 34 additions & 11 deletions pyfakefs/fake_filesystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
import os
import random
import sys
import tempfile
from collections import namedtuple, OrderedDict
from doctest import TestResults
from enum import Enum
Expand Down Expand Up @@ -197,12 +198,17 @@ def __init__(
path_separator: str = os.path.sep,
total_size: Optional[int] = None,
patcher: Any = None,
create_temp_dir: bool = False,
) -> None:
"""
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:
Expand All @@ -212,6 +218,7 @@ def __init__(
self.path_separator: str = path_separator
self.alternative_path_separator: Optional[str] = os.path.altsep
self.patcher = patcher
self.create_temp_dir = create_temp_dir
if path_separator != os.sep:
self.alternative_path_separator = None

Expand All @@ -228,7 +235,7 @@ def __init__(
# file systems on non-case-sensitive systems and vice verse
self.is_case_sensitive: bool = not (self.is_windows_fs or self._is_macos)

self.root = FakeDirectory(self.path_separator, filesystem=self)
self.root: FakeDirectory
self._cwd = ""

# We can't query the current value without changing it:
Expand All @@ -244,9 +251,9 @@ def __init__(
self.last_ino: int = 0
self.last_dev: int = 0
self.mount_points: Dict[AnyString, Dict] = OrderedDict()
self._add_root_mount_point(total_size)
self._add_standard_streams()
self.dev_null: Any = FakeNullFile(self)
self.dev_null: Any = None
self.reset(total_size=total_size, init_pathlib=False)

# set from outside if needed
self.patch_open_code = PatchMode.OFF
self.shuffle_listdir_results = False
Expand Down Expand Up @@ -330,21 +337,24 @@ def os(self, value: OSType) -> None:
self.reset()
FakePathModule.reset(self)

def reset(self, total_size: Optional[int] = None):
def reset(self, total_size: Optional[int] = None, init_pathlib: bool = True):
"""Remove all file system contents and reset the root."""
self.root = FakeDirectory(self.path_separator, filesystem=self)

self.dev_null = FakeNullFile(self)
self.open_files = []
self._free_fd_heap = []
self.open_files.clear()
self._free_fd_heap.clear()
self.last_ino = 0
self.last_dev = 0
self.mount_points = OrderedDict()
self.mount_points.clear()
self._add_root_mount_point(total_size)
self._add_standard_streams()
from pyfakefs import fake_pathlib
if self.create_temp_dir:
self._create_temp_dir()
if init_pathlib:
from pyfakefs import fake_pathlib

fake_pathlib.init_module(self)
fake_pathlib.init_module(self)

def _add_root_mount_point(self, total_size):
mount_point = "C:" if self.is_windows_fs else self.path_separator
Expand Down Expand Up @@ -1380,7 +1390,7 @@ def exists(self, file_path: AnyPath, check_link: bool = False) -> bool:
"""
if check_link and self.islink(file_path):
return True
path = to_string(make_string_path(file_path))
path = to_string(self.make_string_path(file_path))
if path is None:
raise TypeError
if not path:
Expand Down Expand Up @@ -2915,6 +2925,19 @@ def _add_standard_streams(self) -> None:
self._add_open_file(StandardStreamWrapper(sys.stdout))
self._add_open_file(StandardStreamWrapper(sys.stderr))

def _create_temp_dir(self):
# the temp directory is assumed to exist at least in `tempfile`,
# so we create it here for convenience
temp_dir = tempfile.gettempdir()
if not self.exists(temp_dir):
self.create_dir(temp_dir)
if sys.platform != "win32" and not self.exists("/tmp"):
# under Posix, we also create a link in /tmp if the path does not exist
self.create_symlink("/tmp", temp_dir)
# reset the used size to 0 to avoid having the link size counted
# which would make disk size tests more complicated
next(iter(self.mount_points.values()))["used_size"] = 0


def _run_doctest() -> TestResults:
import doctest
Expand Down
16 changes: 2 additions & 14 deletions pyfakefs/fake_filesystem_unittest.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
pyfakefs by simply changing their base class from `:py:class`unittest.TestCase`
to `:py:class`pyfakefs.fake_filesystem_unittest.TestCase`.
"""
import _io # type:ignore [import]
import _io # type:ignore[import]
import doctest
import functools
import genericpath
Expand Down Expand Up @@ -844,7 +844,7 @@ def _refresh(self) -> None:
self._stubs.smart_unset_all()
self._stubs = mox3_stubout.StubOutForTesting()

self.fs = fake_filesystem.FakeFilesystem(patcher=self)
self.fs = fake_filesystem.FakeFilesystem(patcher=self, create_temp_dir=True)
self.fs.patch_open_code = self.patch_open_code
for name in self._fake_module_classes:
self.fake_modules[name] = self._fake_module_classes[name](self.fs)
Expand Down Expand Up @@ -876,7 +876,6 @@ def setUp(self, doctester: Any = None) -> None:
if self.has_fcopy_file:
shutil._HAS_FCOPYFILE = False # type: ignore[attr-defined]

temp_dir = tempfile.gettempdir()
with warnings.catch_warnings():
# ignore warnings, see #542 and #614
warnings.filterwarnings("ignore")
Expand All @@ -891,17 +890,6 @@ def setUp(self, doctester: Any = None) -> None:
linecache.open = self.original_open # type: ignore[attr-defined]
tokenize._builtin_open = self.original_open # type: ignore

# the temp directory is assumed to exist at least in `tempfile`,
# so we create it here for convenience
assert self.fs is not None
self.fs.create_dir(temp_dir)
if sys.platform != "win32" and not self.fs.exists("/tmp"):
# under Posix, we also create a link in /tmp if the path does not exist
self.fs.create_symlink("/tmp", temp_dir)
# reset the used size to 0 to avoid having the link size counted
# which would make disk size tests more complicated
next(iter(self.fs.mount_points.values()))["used_size"] = 0

def start_patching(self) -> None:
if not self._patching:
self._patching = True
Expand Down
16 changes: 16 additions & 0 deletions pyfakefs/pytest_tests/pytest_plugin_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import os
import tempfile

from pyfakefs.fake_filesystem import OSType
from pyfakefs.fake_filesystem_unittest import Pause
import pyfakefs.pytest_tests.io

Expand Down Expand Up @@ -60,3 +61,18 @@ def test_use_own_io_module(fs):

stream = pyfakefs.pytest_tests.io.InputStream(filepath)
assert stream.read() == "bar"


def test_switch_to_windows(fs):
fs.os = OSType.WINDOWS
assert os.path.exists(tempfile.gettempdir())


def test_switch_to_linux(fs):
fs.os = OSType.LINUX
assert os.path.exists(tempfile.gettempdir())


def test_switch_to_macos(fs):
fs.os = OSType.MACOS
assert os.path.exists(tempfile.gettempdir())
4 changes: 2 additions & 2 deletions pyfakefs/tests/fake_filesystem_unittest_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -657,11 +657,11 @@ class TestTempDirCreation(fake_filesystem_unittest.TestCase):
def setUp(self):
self.setUpPyfakefs()

def testTempDirExists(self):
def test_tempdir_exists(self):
self.assertTrue(os.path.exists(tempfile.gettempdir()))

@unittest.skipIf(sys.platform == "win32", "POSIX only test")
def testTmpExists(self):
def test_tmp_exists(self):
# directory or link under Linux, link under macOS
self.assertTrue(os.path.exists("/tmp"))

Expand Down

0 comments on commit b79f556

Please sign in to comment.