Skip to content

Commit 23b05ba

Browse files
committed
Added possibility to switch off lazy directory reading
- may be needed for tests that check the disk usage to avoid the side effect of changing disk usage during delayed directory content access
1 parent 8573da5 commit 23b05ba

File tree

2 files changed

+46
-11
lines changed

2 files changed

+46
-11
lines changed

fake_filesystem_test.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4630,6 +4630,28 @@ def testGetObjectFromLazilyAddedRealDirectory(self):
46304630
self.assertTrue(self.filesystem.GetObject(os.path.join(real_dir_path, 'pyfakefs', 'fake_filesystem.py')))
46314631
self.assertTrue(self.filesystem.GetObject(os.path.join(real_dir_path, 'pyfakefs', '__init__.py')))
46324632

4633+
def testAddExistingRealDirectoryLazily(self):
4634+
disk_size = 1024*1024*1024
4635+
real_dir_path = os.path.join(os.path.dirname(__file__), 'pyfakefs')
4636+
self.filesystem.SetDiskUsage(disk_size, real_dir_path)
4637+
self.filesystem.add_real_directory(real_dir_path)
4638+
4639+
# the directory contents have not been read, the the disk usage has not changed
4640+
self.assertEqual(disk_size, self.filesystem.GetDiskUsage(real_dir_path).free)
4641+
# checking for existence shall read the directory contents
4642+
self.assertTrue(self.filesystem.GetObject(os.path.join(real_dir_path, 'fake_filesystem.py')))
4643+
# so now the free disk space shall have decreased
4644+
self.assertGreater(disk_size, self.filesystem.GetDiskUsage(real_dir_path).free)
4645+
4646+
def testAddExistingRealDirectoryNotLazily(self):
4647+
disk_size = 1024*1024*1024
4648+
real_dir_path = os.path.join(os.path.dirname(__file__), 'pyfakefs')
4649+
self.filesystem.SetDiskUsage(disk_size, real_dir_path)
4650+
self.filesystem.add_real_directory(real_dir_path, lazy_read=False)
4651+
4652+
# the directory has been read, so the file sizes have been subtracted from the free space
4653+
self.assertGreater(disk_size, self.filesystem.GetDiskUsage(real_dir_path).free)
4654+
46334655
def testAddExistingRealDirectoryReadWrite(self):
46344656
real_dir_path = os.path.join(os.path.dirname(__file__), 'pyfakefs')
46354657
self.filesystem.add_real_directory(real_dir_path, read_only=False)

pyfakefs/fake_filesystem.py

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1739,7 +1739,7 @@ def add_real_file(self, file_path, read_only=True):
17391739
read_from_real_fs=True,
17401740
read_only=read_only)
17411741

1742-
def add_real_directory(self, dir_path, read_only=True):
1742+
def add_real_directory(self, dir_path, read_only=True, lazy_read=True):
17431743
"""Create fake directory for the existing directory at path, and entries for all contained
17441744
files in the real file system.
17451745
New in pyfakefs 3.2.
@@ -1749,6 +1749,11 @@ def add_real_directory(self, dir_path, read_only=True):
17491749
read_only: if set, all files under the directory are treated as read-only,
17501750
e.g. a write access raises an exception;
17511751
otherwise, writing to the files changes the fake files only as usually.
1752+
lazy_read: if set (default), directory contents are only read when accessed,
1753+
and only until the needed subdirectory level
1754+
Note: this means that the file system size is only updated at the time
1755+
the directory contents are read; set this to False only if you
1756+
are dependent on accurate file system size in your test
17521757
17531758
Returns:
17541759
the newly created FakeDirectory object.
@@ -1759,18 +1764,24 @@ def add_real_directory(self, dir_path, read_only=True):
17591764
"""
17601765
if not os.path.exists(dir_path):
17611766
raise IOError(errno.ENOENT, 'No such directory', dir_path)
1762-
parent_path = os.path.split(dir_path)[0]
1763-
if self.Exists(parent_path):
1764-
parent_dir = self.GetObject(parent_path)
1767+
if lazy_read:
1768+
parent_path = os.path.split(dir_path)[0]
1769+
if self.Exists(parent_path):
1770+
parent_dir = self.GetObject(parent_path)
1771+
else:
1772+
parent_dir = self.CreateDirectory(parent_path)
1773+
new_dir = FakeDirectoryFromRealDirectory(dir_path, filesystem=self, read_only=read_only)
1774+
parent_dir.AddEntry(new_dir)
1775+
self.last_ino += 1
1776+
new_dir.SetIno(self.last_ino)
17651777
else:
1766-
parent_dir = self.CreateDirectory(parent_path)
1767-
new_dir = FakeDirectoryFromRealDirectory(dir_path, filesystem=self, read_only=read_only)
1768-
parent_dir.AddEntry(new_dir)
1769-
self.last_ino += 1
1770-
new_dir.SetIno(self.last_ino)
1778+
new_dir = self.CreateDirectory(dir_path)
1779+
for base, _, files in os.walk(dir_path):
1780+
for fileEntry in files:
1781+
self.add_real_file(os.path.join(base, fileEntry), read_only)
17711782
return new_dir
17721783

1773-
def add_real_paths(self, path_list, read_only=True):
1784+
def add_real_paths(self, path_list, read_only=True, lazy_dir_read=True):
17741785
"""Convenience method to add several files and directories from the real file system
17751786
in the fake file system. See `add_real_file()` and `add_real_directory()`.
17761787
New in pyfakefs 3.2.
@@ -1780,14 +1791,16 @@ def add_real_paths(self, path_list, read_only=True):
17801791
read_only: if set, all files and files under under the directories are treated as read-only,
17811792
e.g. a write access raises an exception;
17821793
otherwise, writing to the files changes the fake files only as usually.
1794+
lazy_dir_read: uses lazy reading of directory contents if set
1795+
(see `add_real_directory`)
17831796
17841797
Raises:
17851798
OSError: if any of the files and directories in the list does not exist in the real file system.
17861799
OSError: if any of the files and directories in the list already exists in the fake file system.
17871800
"""
17881801
for path in path_list:
17891802
if os.path.isdir(path):
1790-
self.add_real_directory(path, read_only)
1803+
self.add_real_directory(path, read_only, lazy_dir_read)
17911804
else:
17921805
self.add_real_file(path, read_only)
17931806

0 commit comments

Comments
 (0)