Skip to content

Commit 0a6f9ad

Browse files
committed
Adjustments after AI to make it actually work
1 parent 3a1f8f2 commit 0a6f9ad

File tree

1 file changed

+18
-27
lines changed

1 file changed

+18
-27
lines changed

src/namedpipe/_win32.py

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
ERROR_MORE_DATA = 234
2121
ERROR_IO_PENDING = 997
2222
FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000
23-
INVALID_HANDLE_VALUE = wintypes.HANDLE(-1).value
23+
INVALID_HANDLE_VALUE = -1
2424

2525
id = 0
2626

@@ -41,18 +41,8 @@ def _name_pipe():
4141

4242
def _win_error(code=None):
4343
if not code:
44-
code = ctypes.GetLastError()
45-
buf = ctypes.create_unicode_buffer(256)
46-
ctypes.FormatMessageW(
47-
FORMAT_MESSAGE_FROM_SYSTEM,
48-
None,
49-
code,
50-
0,
51-
buf,
52-
len(buf),
53-
None
54-
)
55-
return OSError(f"[OS Error {code}] {buf.value}")
44+
code = ctypes.get_last_error()
45+
return ctypes.WinError(code)
5646

5747
class NPopen:
5848
def __init__(
@@ -69,6 +59,7 @@ def __init__(
6959
if not isinstance(bufsize, int):
7060
raise TypeError("bufsize must be an integer")
7161

62+
self.kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
7263
self.stream: Union[IO, None] = None # I/O stream of the pipe
7364
self._path = _name_pipe() if name is None else rf"\\.\pipe\{name}"
7465
self._rd = any(c in mode for c in "r+")
@@ -110,13 +101,12 @@ def __init__(
110101

111102
# TODO: assess options: PIPE_WAIT, PIPE_NOWAIT, PIPE_ACCEPT_REMOTE_CLIENTS, PIPE_REJECT_REMOTE_CLIENTS
112103

113-
max_instances = _wt(PIPE_UNLIMITED_INSTANCES)
114-
buffer_size = _wt(0)
104+
max_instances = _wt(1) # PIPE_UNLIMITED_INSTANCES returns 'invalid params'. Pipes are point-to-point anyway
105+
buffer_size = _wt(65536) # in all examples online provide 64KB buffer. 0 doesn't fail CreateNamedPipeW, but maybe performance better?
115106
timeout = _wt(0)
116107

117-
118108
# "open" named pipe
119-
self._pipe = ctypes.windll.kernel32.CreateNamedPipeW(
109+
h = self.kernel32.CreateNamedPipeW(
120110
self._path,
121111
access,
122112
pipe_mode,
@@ -126,8 +116,9 @@ def __init__(
126116
timeout,
127117
None,
128118
)
129-
if self._pipe == INVALID_HANDLE_VALUE:
119+
if h == INVALID_HANDLE_VALUE:
130120
raise _win_error()
121+
self._pipe = h
131122

132123
@property
133124
def path(self):
@@ -146,16 +137,16 @@ def close(self):
146137
self.stream.close()
147138
self.stream = None
148139
if self._pipe is not None:
149-
if not ctypes.windll.kernel32.CloseHandle(self._pipe):
140+
if not self.kernel32.CloseHandle(self._pipe):
150141
raise _win_error()
151142
self._pipe = None
152143

153144
def wait(self):
154145
"""Wait for the pipe to open (the other end to be opened) and return file object to read/write."""
155146
if not self._pipe:
156147
raise RuntimeError("pipe has already been closed.")
157-
if not ctypes.windll.kernel32.ConnectNamedPipe(self._pipe, None):
158-
code = ctypes.GetLastError()
148+
if not self.kernel32.ConnectNamedPipe(self._pipe, None):
149+
code = ctypes.get_last_error()
159150
if code != ERROR_PIPE_CONNECTED: # (ok, just indicating that the client has already connected)(Issue#3)
160151
raise _win_error(code)
161152

@@ -208,6 +199,7 @@ class Win32RawIO(io.RawIOBase):
208199

209200
def __init__(self, handle: PyHANDLE, rd: bool, wr: bool) -> None:
210201
super().__init__()
202+
self.kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
211203
self.handle = handle # Underlying Windows handle.
212204
self._readable: bool = rd
213205
self._writable: bool = wr
@@ -232,7 +224,7 @@ def close(self) -> None:
232224
if self.closed:
233225
return
234226
if self.handle is not None:
235-
ctypes.windll.kernel32.CloseHandle(self.handle)
227+
self.kernel32.CloseHandle(self.handle)
236228
self.handle = None
237229

238230
super().close()
@@ -248,9 +240,9 @@ def readinto(self, b: WritableBuffer) -> Union[int, None]:
248240
nread = _wt(0)
249241
buf = (ctypes.c_char * size).from_buffer(b)
250242

251-
success = ctypes.windll.kernel32.ReadFile(self.handle, buf, size, ctypes.byref(nread), None)
243+
success = self.kernel32.ReadFile(self.handle, buf, size, ctypes.byref(nread), None)
252244
if not success:
253-
code = ctypes.GetLastError()
245+
code = ctypes.get_last_error()
254246
if code not in (ERROR_MORE_DATA, ERROR_IO_PENDING):
255247
raise _win_error(code)
256248

@@ -267,8 +259,7 @@ def write(self, b):
267259
size = len(b)
268260
nwritten = wintypes.DWORD(0)
269261
buf = (ctypes.c_char * size).from_buffer_copy(b)
270-
if not ctypes.windll.kernel32.WriteFile(self.handle, buf, size, ctypes.byref(nwritten), None):
271-
code = ctypes.GetLastError()
272-
raise _win_error(code)
262+
if not self.kernel32.WriteFile(self.handle, buf, size, ctypes.byref(nwritten), None):
263+
raise _win_error()
273264

274265
return nwritten.value

0 commit comments

Comments
 (0)