Skip to content

Commit

Permalink
Add support for os.truncate and os.ftruncate
Browse files Browse the repository at this point in the history
- fixes #545
  • Loading branch information
mrbean-bremen committed Aug 14, 2020
1 parent 9cee495 commit 7ffd478
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ The released versions correspond to PyPi releases.
#### Fixes
* suppress deprecation warnings while collecting modules
(see [#542](../../issues/542))
* add support for `os.truncate` and `os.ftruncate`
(see [#545](../../issues/545))

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

Expand Down
32 changes: 32 additions & 0 deletions pyfakefs/fake_filesystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -4136,6 +4136,38 @@ def _path_with_dir_fd(self, path, fct, dir_fd):
dir_fd).get_object().path, path)
return path

def truncate(self, path, length):
"""Truncate the file corresponding to path, so that it is
length bytes in size. If length is larger than the current size,
the file is filled up with zero bytes.
Args:
path: (str or int) Path to the file, or an integer file
descriptor for the file object.
length: (int) Length of the file after truncating it.
Raises:
OSError: if the file does not exist or the file descriptor is
invalid.
"""
file_object = self.filesystem.resolve(path, allow_fd=True)
file_object.size = length

def ftruncate(self, fd, length):
"""Truncate the file corresponding to fd, so that it is
length bytes in size. If length is larger than the current size,
the file is filled up with zero bytes.
Args:
fd: (int) File descriptor for the file object.
length: (int) Maximum length of the file after truncating it.
Raises:
OSError: if the file descriptor is invalid
"""
file_object = self.filesystem.get_open_file(fd).get_object()
file_object.size = length

def access(self, path, mode, *, dir_fd=None, follow_symlinks=True):
"""Check if a file exists and has the specified permissions.
Expand Down
46 changes: 46 additions & 0 deletions pyfakefs/tests/fake_os_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2708,6 +2708,52 @@ def test_write_to_read_fd(self):
self.os.close(read_fd)
self.os.close(write_fd)

def test_truncate(self):
file_path = self.make_path('foo', 'bar')
self.create_file(file_path, contents='012345678901234567')
self.os.truncate(file_path, 10)
with self.open(file_path) as f:
self.assertEqual('0123456789', f.read())

def test_truncate_non_existing(self):
self.assert_raises_os_error(errno.ENOENT, self.os.truncate, 'foo', 10)

def test_truncate_to_larger(self):
file_path = self.make_path('foo', 'bar')
self.create_file(file_path, contents='0123456789')
fd = self.os.open(file_path, os.O_RDWR)
self.os.truncate(fd, 20)
self.assertEqual(20, self.os.stat(file_path).st_size)
with self.open(file_path) as f:
self.assertEqual('0123456789' + '\0' * 10, f.read())

def test_truncate_with_fd(self):
if os.truncate not in os.supports_fd:
self.skip_real_fs()
self.assert_raises_os_error(errno.EBADF, self.os.ftruncate, 50, 10)
file_path = self.make_path('some_file')
self.create_file(file_path, contents='01234567890123456789')

fd = self.os.open(file_path, os.O_RDWR)
self.os.truncate(fd, 10)
self.assertEqual(10, self.os.stat(file_path).st_size)
with self.open(file_path) as f:
self.assertEqual('0123456789', f.read())

def test_ftruncate(self):
if self.is_pypy:
# not correctly supported
self.skip_real_fs()
self.assert_raises_os_error(errno.EBADF, self.os.ftruncate, 50, 10)
file_path = self.make_path('some_file')
self.create_file(file_path, contents='0123456789012345')

fd = self.os.open(file_path, os.O_RDWR)
self.os.truncate(fd, 10)
self.assertEqual(10, self.os.stat(file_path).st_size)
with self.open(file_path) as f:
self.assertEqual('0123456789', f.read())


class RealOsModuleTest(FakeOsModuleTest):
def use_real_fs(self):
Expand Down
7 changes: 7 additions & 0 deletions pyfakefs/tests/fake_pathlib_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,13 @@ def test_utime(self):
self.assertEqual(1, st.st_atime)
self.assertEqual(2, st.st_mtime)

def test_truncate(self):
path = self.make_path('some_file')
self.create_file(path, contents='test_test')
self.os.truncate(self.path(path), length=4)
st = self.os.stat(path)
self.assertEqual(4, st.st_size)


class RealPathlibUsageInOsFunctionsTest(FakePathlibUsageInOsFunctionsTest):
def use_real_fs(self):
Expand Down

0 comments on commit 7ffd478

Please sign in to comment.