Skip to content

Commit 7ffd478

Browse files
committed
Add support for os.truncate and os.ftruncate
- fixes #545
1 parent 9cee495 commit 7ffd478

File tree

4 files changed

+87
-0
lines changed

4 files changed

+87
-0
lines changed

CHANGES.md

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ The released versions correspond to PyPi releases.
66
#### Fixes
77
* suppress deprecation warnings while collecting modules
88
(see [#542](../../issues/542))
9+
* add support for `os.truncate` and `os.ftruncate`
10+
(see [#545](../../issues/545))
911

1012
## [Version 4.1.0](https://pypi.python.org/pypi/pyfakefs/4.1.0)
1113

pyfakefs/fake_filesystem.py

+32
Original file line numberDiff line numberDiff line change
@@ -4136,6 +4136,38 @@ def _path_with_dir_fd(self, path, fct, dir_fd):
41364136
dir_fd).get_object().path, path)
41374137
return path
41384138

4139+
def truncate(self, path, length):
4140+
"""Truncate the file corresponding to path, so that it is
4141+
length bytes in size. If length is larger than the current size,
4142+
the file is filled up with zero bytes.
4143+
4144+
Args:
4145+
path: (str or int) Path to the file, or an integer file
4146+
descriptor for the file object.
4147+
length: (int) Length of the file after truncating it.
4148+
4149+
Raises:
4150+
OSError: if the file does not exist or the file descriptor is
4151+
invalid.
4152+
"""
4153+
file_object = self.filesystem.resolve(path, allow_fd=True)
4154+
file_object.size = length
4155+
4156+
def ftruncate(self, fd, length):
4157+
"""Truncate the file corresponding to fd, so that it is
4158+
length bytes in size. If length is larger than the current size,
4159+
the file is filled up with zero bytes.
4160+
4161+
Args:
4162+
fd: (int) File descriptor for the file object.
4163+
length: (int) Maximum length of the file after truncating it.
4164+
4165+
Raises:
4166+
OSError: if the file descriptor is invalid
4167+
"""
4168+
file_object = self.filesystem.get_open_file(fd).get_object()
4169+
file_object.size = length
4170+
41394171
def access(self, path, mode, *, dir_fd=None, follow_symlinks=True):
41404172
"""Check if a file exists and has the specified permissions.
41414173

pyfakefs/tests/fake_os_test.py

+46
Original file line numberDiff line numberDiff line change
@@ -2708,6 +2708,52 @@ def test_write_to_read_fd(self):
27082708
self.os.close(read_fd)
27092709
self.os.close(write_fd)
27102710

2711+
def test_truncate(self):
2712+
file_path = self.make_path('foo', 'bar')
2713+
self.create_file(file_path, contents='012345678901234567')
2714+
self.os.truncate(file_path, 10)
2715+
with self.open(file_path) as f:
2716+
self.assertEqual('0123456789', f.read())
2717+
2718+
def test_truncate_non_existing(self):
2719+
self.assert_raises_os_error(errno.ENOENT, self.os.truncate, 'foo', 10)
2720+
2721+
def test_truncate_to_larger(self):
2722+
file_path = self.make_path('foo', 'bar')
2723+
self.create_file(file_path, contents='0123456789')
2724+
fd = self.os.open(file_path, os.O_RDWR)
2725+
self.os.truncate(fd, 20)
2726+
self.assertEqual(20, self.os.stat(file_path).st_size)
2727+
with self.open(file_path) as f:
2728+
self.assertEqual('0123456789' + '\0' * 10, f.read())
2729+
2730+
def test_truncate_with_fd(self):
2731+
if os.truncate not in os.supports_fd:
2732+
self.skip_real_fs()
2733+
self.assert_raises_os_error(errno.EBADF, self.os.ftruncate, 50, 10)
2734+
file_path = self.make_path('some_file')
2735+
self.create_file(file_path, contents='01234567890123456789')
2736+
2737+
fd = self.os.open(file_path, os.O_RDWR)
2738+
self.os.truncate(fd, 10)
2739+
self.assertEqual(10, self.os.stat(file_path).st_size)
2740+
with self.open(file_path) as f:
2741+
self.assertEqual('0123456789', f.read())
2742+
2743+
def test_ftruncate(self):
2744+
if self.is_pypy:
2745+
# not correctly supported
2746+
self.skip_real_fs()
2747+
self.assert_raises_os_error(errno.EBADF, self.os.ftruncate, 50, 10)
2748+
file_path = self.make_path('some_file')
2749+
self.create_file(file_path, contents='0123456789012345')
2750+
2751+
fd = self.os.open(file_path, os.O_RDWR)
2752+
self.os.truncate(fd, 10)
2753+
self.assertEqual(10, self.os.stat(file_path).st_size)
2754+
with self.open(file_path) as f:
2755+
self.assertEqual('0123456789', f.read())
2756+
27112757

27122758
class RealOsModuleTest(FakeOsModuleTest):
27132759
def use_real_fs(self):

pyfakefs/tests/fake_pathlib_test.py

+7
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,13 @@ def test_utime(self):
973973
self.assertEqual(1, st.st_atime)
974974
self.assertEqual(2, st.st_mtime)
975975

976+
def test_truncate(self):
977+
path = self.make_path('some_file')
978+
self.create_file(path, contents='test_test')
979+
self.os.truncate(self.path(path), length=4)
980+
st = self.os.stat(path)
981+
self.assertEqual(4, st.st_size)
982+
976983

977984
class RealPathlibUsageInOsFunctionsTest(FakePathlibUsageInOsFunctionsTest):
978985
def use_real_fs(self):

0 commit comments

Comments
 (0)