Skip to content

Commit 9e6317b

Browse files
committed
More performance improvements
- do not import pytest if not needed - moved SKIPMODULE setting back to pytest plugin - move warning supression out of loop - slight improvement of temp path creation performance
1 parent 802aef8 commit 9e6317b

File tree

4 files changed

+51
-41
lines changed

4 files changed

+51
-41
lines changed

CHANGES.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ The released versions correspond to PyPi releases.
33

44
## Version 4.3.0 (as yet unreleased)
55

6-
76
### Changes
87
* The `patchfs` decorator now expects a positional argument instead of the
98
keyword arguments `fs`. This avoids confusion with the pytest `fs`
@@ -14,6 +13,7 @@ The released versions correspond to PyPi releases.
1413
default to avoid a large performance impact. An additional parameter
1514
`patch_default_args` has been added that switches this behavior on
1615
(see [#567](../../issues/567)).
16+
* Some setup performance improvements have been added
1717

1818
## [Version 4.2.1](https://pypi.python.org/pypi/pyfakefs/4.2.1) (2020-11-02)
1919

pyfakefs/fake_filesystem.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,17 @@ def _starts_with_sep(self, path):
10141014
return (path.startswith(sep) or altsep is not None and
10151015
path.startswith(altsep))
10161016

1017+
def _add_c_drive(self):
1018+
"""Optimized version for the default Windows C drive.
1019+
For internal use only.
1020+
"""
1021+
if self.is_windows_fs:
1022+
self.last_dev += 1
1023+
self.mount_points['C:'] = {
1024+
'idev': self.last_dev, 'total_size': None, 'used_size': 0
1025+
}
1026+
self.root.get_entry('C:') .st_dev = self.last_dev
1027+
10171028
def add_mount_point(self, path, total_size=None):
10181029
"""Add a new mount point for a filesystem device.
10191030
The mount point gets a new unique device number.
@@ -2306,14 +2317,15 @@ def make_string_path(self, path):
23062317
fake_sep = matching_string(path, self.path_separator)
23072318
return path.replace(os_sep, fake_sep)
23082319

2309-
def create_dir(self, directory_path, perm_bits=PERM_DEF):
2320+
def create_dir(self, directory_path, perm_bits=PERM_DEF, check=True):
23102321
"""Create `directory_path`, and all the parent directories.
23112322
23122323
Helper method to set up your test faster.
23132324
23142325
Args:
23152326
directory_path: The full directory path to create.
23162327
perm_bits: The permission bits as set by `chmod`.
2328+
check: For internal use only.
23172329
23182330
Returns:
23192331
The newly created FakeDirectory object.
@@ -2322,10 +2334,11 @@ def create_dir(self, directory_path, perm_bits=PERM_DEF):
23222334
OSError: if the directory already exists.
23232335
"""
23242336
directory_path = self.make_string_path(directory_path)
2325-
directory_path = self.absnormpath(directory_path)
2326-
self._auto_mount_drive_if_needed(directory_path)
2327-
if self.exists(directory_path, check_link=True):
2328-
self.raise_os_error(errno.EEXIST, directory_path)
2337+
if check:
2338+
directory_path = self.absnormpath(directory_path)
2339+
self._auto_mount_drive_if_needed(directory_path)
2340+
if self.exists(directory_path, check_link=True):
2341+
self.raise_os_error(errno.EEXIST, directory_path)
23292342
path_components = self._path_components(directory_path)
23302343
current_dir = self.root
23312344

@@ -2338,10 +2351,10 @@ def create_dir(self, directory_path, perm_bits=PERM_DEF):
23382351
current_dir.add_entry(new_dir)
23392352
current_dir = new_dir
23402353
else:
2341-
if S_ISLNK(directory.st_mode):
2354+
if check and S_ISLNK(directory.st_mode):
23422355
directory = self.resolve(directory.contents)
23432356
current_dir = directory
2344-
if directory.st_mode & S_IFDIR != S_IFDIR:
2357+
if check and directory.st_mode & S_IFDIR != S_IFDIR:
23452358
self.raise_os_error(errno.ENOTDIR, current_dir.path)
23462359

23472360
# set the permission after creating the directories

pyfakefs/fake_filesystem_unittest.py

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -362,13 +362,6 @@ class Patcher:
362362
None, fake_filesystem, fake_filesystem_shutil,
363363
sys, linecache, tokenize
364364
}
365-
try:
366-
import py
367-
import pytest
368-
SKIPMODULES.add(py)
369-
SKIPMODULES.add(pytest)
370-
except ImportError:
371-
pass
372365

373366
assert None in SKIPMODULES, ("sys.modules contains 'None' values;"
374367
" must skip them.")
@@ -606,7 +599,6 @@ def _find_modules(self):
606599
Later, `setUp()` will stub these with the fake file system
607600
modules.
608601
"""
609-
610602
module_names = list(self._fake_module_classes.keys()) + [PATH_MODULE]
611603
for name, module in list(sys.modules.items()):
612604
try:
@@ -622,33 +614,27 @@ def _find_modules(self):
622614
for sn in self._skip_names]))
623615
module_items = module.__dict__.copy().items()
624616

625-
with warnings.catch_warnings():
626-
# ignore deprecation warnings, see #542
627-
warnings.filterwarnings(
628-
'ignore',
629-
category=DeprecationWarning
630-
)
631-
modules = {name: mod for name, mod in module_items
632-
if self._is_fs_module(mod, name, module_names)}
633-
634-
if skipped:
635-
for name, mod in modules.items():
636-
self._skipped_modules.setdefault(name, set()).add(
637-
(module, mod.__name__))
638-
continue
617+
modules = {name: mod for name, mod in module_items
618+
if self._is_fs_module(mod, name, module_names)}
639619

620+
if skipped:
640621
for name, mod in modules.items():
641-
self._modules.setdefault(name, set()).add(
622+
self._skipped_modules.setdefault(name, set()).add(
642623
(module, mod.__name__))
643-
functions = {name: fct for name, fct in
644-
module_items
645-
if self._is_fs_function(fct)}
624+
continue
625+
626+
for name, mod in modules.items():
627+
self._modules.setdefault(name, set()).add(
628+
(module, mod.__name__))
629+
functions = {name: fct for name, fct in
630+
module_items
631+
if self._is_fs_function(fct)}
646632

647-
# find default arguments that are file system functions
648-
if self.patch_default_args:
649-
for _, fct in module_items:
650-
for f, i, d in self._def_values(fct):
651-
self._def_functions.append((f, i, d))
633+
# find default arguments that are file system functions
634+
if self.patch_default_args:
635+
for _, fct in module_items:
636+
for f, i, d in self._def_values(fct):
637+
self._def_functions.append((f, i, d))
652638

653639
for name, fct in functions.items():
654640
self._fct_modules.setdefault(
@@ -684,7 +670,13 @@ def setUp(self, doctester=None):
684670
shutil._HAS_FCOPYFILE = False
685671

686672
temp_dir = tempfile.gettempdir()
687-
self._find_modules()
673+
with warnings.catch_warnings():
674+
# ignore deprecation warnings, see #542
675+
warnings.filterwarnings(
676+
'ignore',
677+
category=DeprecationWarning
678+
)
679+
self._find_modules()
688680
self._refresh()
689681

690682
if doctester is not None:
@@ -696,7 +688,8 @@ def setUp(self, doctester=None):
696688

697689
# the temp directory is assumed to exist at least in `tempfile1`,
698690
# so we create it here for convenience
699-
self.fs.create_dir(temp_dir)
691+
self.fs.create_dir(temp_dir, check=False)
692+
self.fs._add_c_drive()
700693

701694
def start_patching(self):
702695
if not self._patching:

pyfakefs/pytest_plugin.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,14 @@ def my_fakefs_test(fs):
99
assert os.path.exists('/var/data/xx1.txt')
1010
"""
1111

12+
import py
1213
import pytest
1314

1415
from pyfakefs.fake_filesystem_unittest import Patcher
1516

17+
Patcher.SKIPMODULES.add(py)
18+
Patcher.SKIPMODULES.add(pytest)
19+
1620

1721
@pytest.fixture
1822
def fs(request):

0 commit comments

Comments
 (0)