Pipe-based `IOStream` implementation. The constructor takes an integer file descriptor (such as one returned by `os.pipe`) rather than an open file object. Pipes are generally one-way, so a `PipeIOStream` can be used for reading or writing but not both. ``PipeIOStream`` is onl
| 1618 | |
| 1619 | |
| 1620 | class PipeIOStream(BaseIOStream): |
| 1621 | """Pipe-based `IOStream` implementation. |
| 1622 | |
| 1623 | The constructor takes an integer file descriptor (such as one returned |
| 1624 | by `os.pipe`) rather than an open file object. Pipes are generally |
| 1625 | one-way, so a `PipeIOStream` can be used for reading or writing but not |
| 1626 | both. |
| 1627 | |
| 1628 | ``PipeIOStream`` is only available on Unix-based platforms. |
| 1629 | """ |
| 1630 | |
| 1631 | def __init__(self, fd: int, *args: Any, **kwargs: Any) -> None: |
| 1632 | self.fd = fd |
| 1633 | self._fio = io.FileIO(self.fd, "r+") |
| 1634 | if sys.platform == "win32": |
| 1635 | # The form and placement of this assertion is important to mypy. |
| 1636 | # A plain assert statement isn't recognized here. If the assertion |
| 1637 | # were earlier it would worry that the attributes of self aren't |
| 1638 | # set on windows. If it were missing it would complain about |
| 1639 | # the absence of the set_blocking function. |
| 1640 | raise AssertionError("PipeIOStream is not supported on Windows") |
| 1641 | os.set_blocking(fd, False) |
| 1642 | super().__init__(*args, **kwargs) |
| 1643 | |
| 1644 | def fileno(self) -> int: |
| 1645 | return self.fd |
| 1646 | |
| 1647 | def close_fd(self) -> None: |
| 1648 | self._fio.close() |
| 1649 | |
| 1650 | def write_to_fd(self, data: memoryview) -> int: |
| 1651 | try: |
| 1652 | return os.write(self.fd, data) # type: ignore |
| 1653 | finally: |
| 1654 | # Avoid keeping to data, which can be a memoryview. |
| 1655 | # See https://github.com/tornadoweb/tornado/pull/2008 |
| 1656 | del data |
| 1657 | |
| 1658 | def read_from_fd(self, buf: Union[bytearray, memoryview]) -> Optional[int]: |
| 1659 | try: |
| 1660 | return self._fio.readinto(buf) # type: ignore |
| 1661 | except (IOError, OSError) as e: |
| 1662 | if errno_from_exception(e) == errno.EBADF: |
| 1663 | # If the writing half of a pipe is closed, select will |
| 1664 | # report it as readable but reads will fail with EBADF. |
| 1665 | self.close(exc_info=e) |
| 1666 | return None |
| 1667 | else: |
| 1668 | raise |
| 1669 | finally: |
| 1670 | del buf |
| 1671 | |
| 1672 | |
| 1673 | def doctests() -> Any: |
no outgoing calls