Skip to content

Commit

Permalink
Allow to open existing pipe file descriptor
Browse files Browse the repository at this point in the history
- fixes #493
  • Loading branch information
mrbean-bremen committed Sep 13, 2020
1 parent c8a0f0c commit 6f8d80a
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 3 deletions.
8 changes: 5 additions & 3 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ The released versions correspond to PyPi releases.
(see [#549](../../issues/549))

#### Fixes
* allow to open existing pipe file descriptor
(see [#493](../../issues/493))
* do not truncate file on failed flush
(see [#548](../../issues/548))
(see [#548](../../issues/548))
* suppress deprecation warnings while collecting modules
(see [#542](../../issues/542))
(see [#542](../../issues/542))
* add support for `os.truncate` and `os.ftruncate`
(see [#545](../../issues/545))
(see [#545](../../issues/545))

#### Infrastructure
* fixed another problem with CI test scripts not always propagating errors
Expand Down
20 changes: 20 additions & 0 deletions pyfakefs/fake_filesystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -4997,6 +4997,14 @@ def __init__(self, filesystem, fd):
self.file_object = None
self.filedes = None

def __enter__(self):
"""To support usage of this fake pipe with the 'with' statement."""
return self

def __exit__(self, type, value, traceback):
"""To support usage of this fake pipe with the 'with' statement."""
self.close()

def get_object(self):
return self.file_object

Expand All @@ -5008,6 +5016,10 @@ def read(self, numBytes):
"""Read from the real pipe."""
return os.read(self.fd, numBytes)

def flush(self):
"""Flush the real pipe?"""
pass

def write(self, contents):
"""Write to the real pipe."""
return os.write(self.fd, contents)
Expand Down Expand Up @@ -5084,6 +5096,12 @@ def call(self, file_, mode='r', buffering=-1, encoding=None,

file_object, file_path, filedes, real_path = self._handle_file_arg(
file_)
if file_object is None and file_path is None:
wrapper = FakePipeWrapper(self.filesystem, filedes)
file_des = self.filesystem._add_open_file(wrapper)
wrapper.filedes = file_des
return wrapper

if not filedes:
closefd = True

Expand Down Expand Up @@ -5170,6 +5188,8 @@ def _handle_file_arg(self, file_):
# opening a file descriptor
filedes = file_
wrapper = self.filesystem.get_open_file(filedes)
if isinstance(wrapper, FakePipeWrapper):
return None, None, filedes, None
self._delete_on_close = wrapper.delete_on_close
file_object = self.filesystem.get_open_file(filedes).get_object()
file_path = file_object.name
Expand Down
16 changes: 16 additions & 0 deletions pyfakefs/tests/fake_os_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2694,6 +2694,22 @@ def test_open_file_with_existing_pipe(self):
self.os.close(write_fd)
self.os.close(fd)

def test_read_write_pipe(self):
read_fd, write_fd = self.os.pipe()
self.assertEqual(4, self.os.write(write_fd, b'test'))
self.assertEqual(b'test', self.os.read(read_fd, 4))
self.os.close(read_fd)
self.os.close(write_fd)

def test_open_existing_pipe(self):
if self.is_pypy:
raise unittest.SkipTest('Does not work correctly with PyPy')
read_fd, write_fd = self.os.pipe()
with self.open(write_fd, 'wb') as f:
self.assertEqual(4, f.write(b'test'))
with self.open(read_fd, 'rb') as f:
self.assertEqual(b'test', f.read(4))

def test_write_to_pipe(self):
read_fd, write_fd = self.os.pipe()
self.os.write(write_fd, b'test')
Expand Down

0 comments on commit 6f8d80a

Please sign in to comment.