Wrapper for an overlapped pipe handle which is vaguely file-object like. The IOCP event loop can use these instead of socket objects.
| 79 | |
| 80 | |
| 81 | class PipeHandle: |
| 82 | """Wrapper for an overlapped pipe handle which is vaguely file-object like. |
| 83 | |
| 84 | The IOCP event loop can use these instead of socket objects. |
| 85 | """ |
| 86 | def __init__(self, handle): |
| 87 | self._handle = handle |
| 88 | |
| 89 | def __repr__(self): |
| 90 | if self._handle is not None: |
| 91 | handle = f'handle={self._handle!r}' |
| 92 | else: |
| 93 | handle = 'closed' |
| 94 | return f'<{self.__class__.__name__} {handle}>' |
| 95 | |
| 96 | @property |
| 97 | def handle(self): |
| 98 | return self._handle |
| 99 | |
| 100 | def fileno(self): |
| 101 | if self._handle is None: |
| 102 | raise ValueError("I/O operation on closed pipe") |
| 103 | return self._handle |
| 104 | |
| 105 | def close(self, *, CloseHandle=_winapi.CloseHandle): |
| 106 | if self._handle is not None: |
| 107 | CloseHandle(self._handle) |
| 108 | self._handle = None |
| 109 | |
| 110 | def __del__(self, _warn=warnings.warn): |
| 111 | if self._handle is not None: |
| 112 | _warn(f"unclosed {self!r}", ResourceWarning, source=self) |
| 113 | self.close() |
| 114 | |
| 115 | def __enter__(self): |
| 116 | return self |
| 117 | |
| 118 | def __exit__(self, t, v, tb): |
| 119 | self.close() |
| 120 | |
| 121 | |
| 122 | # Replacement for subprocess.Popen using overlapped pipe handles |