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
| 1559 | |
| 1560 | |
| 1561 | class PipeIOStream(BaseIOStream): |
| 1562 | """Pipe-based `IOStream` implementation. |
| 1563 | |
| 1564 | The constructor takes an integer file descriptor (such as one returned |
| 1565 | by `os.pipe`) rather than an open file object. Pipes are generally |
| 1566 | one-way, so a `PipeIOStream` can be used for reading or writing but not |
| 1567 | both. |
| 1568 | |
| 1569 | ``PipeIOStream`` is only available on Unix-based platforms. |
| 1570 | """ |
| 1571 | |
| 1572 | def __init__(self, fd: int, *args: Any, **kwargs: Any) -> None: |
| 1573 | self.fd = fd |
| 1574 | self._fio = io.FileIO(self.fd, "r+") |
| 1575 | if sys.platform == "win32": |
| 1576 | # The form and placement of this assertion is important to mypy. |
| 1577 | # A plain assert statement isn't recognized here. If the assertion |
| 1578 | # were earlier it would worry that the attributes of self aren't |
| 1579 | # set on windows. If it were missing it would complain about |
| 1580 | # the absence of the set_blocking function. |
| 1581 | raise AssertionError("PipeIOStream is not supported on Windows") |
| 1582 | os.set_blocking(fd, False) |
| 1583 | super().__init__(*args, **kwargs) |
| 1584 | |
| 1585 | def fileno(self) -> int: |
| 1586 | return self.fd |
| 1587 | |
| 1588 | def close_fd(self) -> None: |
| 1589 | self._fio.close() |
| 1590 | |
| 1591 | def write_to_fd(self, data: memoryview) -> int: |
| 1592 | try: |
| 1593 | return os.write(self.fd, data) # type: ignore |
| 1594 | finally: |
| 1595 | # Avoid keeping to data, which can be a memoryview. |
| 1596 | # See https://github.com/tornadoweb/tornado/pull/2008 |
| 1597 | del data |
| 1598 | |
| 1599 | def read_from_fd(self, buf: Union[bytearray, memoryview]) -> Optional[int]: |
| 1600 | try: |
| 1601 | return self._fio.readinto(buf) # type: ignore |
| 1602 | except OSError as e: |
| 1603 | if errno_from_exception(e) == errno.EBADF: |
| 1604 | # If the writing half of a pipe is closed, select will |
| 1605 | # report it as readable but reads will fail with EBADF. |
| 1606 | self.close(exc_info=e) |
| 1607 | return None |
| 1608 | else: |
| 1609 | raise |
| 1610 | finally: |
| 1611 | del buf |
| 1612 | |
| 1613 | |
| 1614 | def doctests() -> Any: |
no outgoing calls