Coverage for /pythoncovmergedfiles/medio/medio/src/paramiko/paramiko/pipe.py: 28%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# Copyright (C) 2003-2007 Robey Pointer <robeypointer@gmail.com>
2#
3# This file is part of paramiko.
4#
5# Paramiko is free software; you can redistribute it and/or modify it under the
6# terms of the GNU Lesser General Public License as published by the Free
7# Software Foundation; either version 2.1 of the License, or (at your option)
8# any later version.
9#
10# Paramiko is distributed in the hope that it will be useful, but WITHOUT ANY
11# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13# details.
14#
15# You should have received a copy of the GNU Lesser General Public License
16# along with Paramiko; if not, write to the Free Software Foundation, Inc.,
17# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19"""
20Abstraction of a one-way pipe where the read end can be used in
21`select.select`. Normally this is trivial, but Windows makes it nearly
22impossible.
24The pipe acts like an Event, which can be set or cleared. When set, the pipe
25will trigger as readable in `select <select.select>`.
26"""
28import sys
29import os
30import socket
33def make_pipe():
34 if sys.platform[:3] != "win":
35 p = PosixPipe()
36 else:
37 p = WindowsPipe()
38 return p
41class PosixPipe:
42 def __init__(self):
43 self._rfd, self._wfd = os.pipe()
44 self._set = False
45 self._forever = False
46 self._closed = False
48 def close(self):
49 os.close(self._rfd)
50 os.close(self._wfd)
51 # used for unit tests:
52 self._closed = True
54 def fileno(self):
55 return self._rfd
57 def clear(self):
58 if not self._set or self._forever:
59 return
60 os.read(self._rfd, 1)
61 self._set = False
63 def set(self):
64 if self._set or self._closed:
65 return
66 self._set = True
67 os.write(self._wfd, b"*")
69 def set_forever(self):
70 self._forever = True
71 self.set()
74class WindowsPipe:
75 """
76 On Windows, only an OS-level "WinSock" may be used in select(), but reads
77 and writes must be to the actual socket object.
78 """
80 def __init__(self):
81 serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
82 serv.bind(("127.0.0.1", 0))
83 serv.listen(1)
85 # need to save sockets in _rsock/_wsock so they don't get closed
86 self._rsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
87 self._rsock.connect(("127.0.0.1", serv.getsockname()[1]))
89 self._wsock, addr = serv.accept()
90 serv.close()
91 self._set = False
92 self._forever = False
93 self._closed = False
95 def close(self):
96 self._rsock.close()
97 self._wsock.close()
98 # used for unit tests:
99 self._closed = True
101 def fileno(self):
102 return self._rsock.fileno()
104 def clear(self):
105 if not self._set or self._forever:
106 return
107 self._rsock.recv(1)
108 self._set = False
110 def set(self):
111 if self._set or self._closed:
112 return
113 self._set = True
114 self._wsock.send(b"*")
116 def set_forever(self):
117 self._forever = True
118 self.set()
121class OrPipe:
122 def __init__(self, pipe):
123 self._set = False
124 self._partner = None
125 self._pipe = pipe
127 def set(self):
128 self._set = True
129 if not self._partner._set:
130 self._pipe.set()
132 def clear(self):
133 self._set = False
134 if not self._partner._set:
135 self._pipe.clear()
138def make_or_pipe(pipe):
139 """
140 wraps a pipe into two pipe-like objects which are "or"d together to
141 affect the real pipe. if either returned pipe is set, the wrapped pipe
142 is set. when both are cleared, the wrapped pipe is cleared.
143 """
144 p1 = OrPipe(pipe)
145 p2 = OrPipe(pipe)
146 p1._partner = p2
147 p2._partner = p1
148 return p1, p2