ยปCore Development>Code coverage>Lib/asyncio/windows_utils.py

Python code coverage for Lib/asyncio/windows_utils.py

#countcontent
1n/a"""
2n/aVarious Windows specific bits and pieces
3n/a"""
4n/a
5n/aimport sys
6n/a
7n/aif sys.platform != 'win32': # pragma: no cover
8n/a raise ImportError('win32 only')
9n/a
10n/aimport _winapi
11n/aimport itertools
12n/aimport msvcrt
13n/aimport os
14n/aimport socket
15n/aimport subprocess
16n/aimport tempfile
17n/aimport warnings
18n/a
19n/a
20n/a__all__ = ['socketpair', 'pipe', 'Popen', 'PIPE', 'PipeHandle']
21n/a
22n/a
23n/a# Constants/globals
24n/a
25n/a
26n/aBUFSIZE = 8192
27n/aPIPE = subprocess.PIPE
28n/aSTDOUT = subprocess.STDOUT
29n/a_mmap_counter = itertools.count()
30n/a
31n/a
32n/aif hasattr(socket, 'socketpair'):
33n/a # Since Python 3.5, socket.socketpair() is now also available on Windows
34n/a socketpair = socket.socketpair
35n/aelse:
36n/a # Replacement for socket.socketpair()
37n/a def socketpair(family=socket.AF_INET, type=socket.SOCK_STREAM, proto=0):
38n/a """A socket pair usable as a self-pipe, for Windows.
39n/a
40n/a Origin: https://gist.github.com/4325783, by Geert Jansen.
41n/a Public domain.
42n/a """
43n/a if family == socket.AF_INET:
44n/a host = '127.0.0.1'
45n/a elif family == socket.AF_INET6:
46n/a host = '::1'
47n/a else:
48n/a raise ValueError("Only AF_INET and AF_INET6 socket address "
49n/a "families are supported")
50n/a if type != socket.SOCK_STREAM:
51n/a raise ValueError("Only SOCK_STREAM socket type is supported")
52n/a if proto != 0:
53n/a raise ValueError("Only protocol zero is supported")
54n/a
55n/a # We create a connected TCP socket. Note the trick with setblocking(0)
56n/a # that prevents us from having to create a thread.
57n/a lsock = socket.socket(family, type, proto)
58n/a try:
59n/a lsock.bind((host, 0))
60n/a lsock.listen(1)
61n/a # On IPv6, ignore flow_info and scope_id
62n/a addr, port = lsock.getsockname()[:2]
63n/a csock = socket.socket(family, type, proto)
64n/a try:
65n/a csock.setblocking(False)
66n/a try:
67n/a csock.connect((addr, port))
68n/a except (BlockingIOError, InterruptedError):
69n/a pass
70n/a csock.setblocking(True)
71n/a ssock, _ = lsock.accept()
72n/a except:
73n/a csock.close()
74n/a raise
75n/a finally:
76n/a lsock.close()
77n/a return (ssock, csock)
78n/a
79n/a
80n/a# Replacement for os.pipe() using handles instead of fds
81n/a
82n/a
83n/adef pipe(*, duplex=False, overlapped=(True, True), bufsize=BUFSIZE):
84n/a """Like os.pipe() but with overlapped support and using handles not fds."""
85n/a address = tempfile.mktemp(prefix=r'\\.\pipe\python-pipe-%d-%d-' %
86n/a (os.getpid(), next(_mmap_counter)))
87n/a
88n/a if duplex:
89n/a openmode = _winapi.PIPE_ACCESS_DUPLEX
90n/a access = _winapi.GENERIC_READ | _winapi.GENERIC_WRITE
91n/a obsize, ibsize = bufsize, bufsize
92n/a else:
93n/a openmode = _winapi.PIPE_ACCESS_INBOUND
94n/a access = _winapi.GENERIC_WRITE
95n/a obsize, ibsize = 0, bufsize
96n/a
97n/a openmode |= _winapi.FILE_FLAG_FIRST_PIPE_INSTANCE
98n/a
99n/a if overlapped[0]:
100n/a openmode |= _winapi.FILE_FLAG_OVERLAPPED
101n/a
102n/a if overlapped[1]:
103n/a flags_and_attribs = _winapi.FILE_FLAG_OVERLAPPED
104n/a else:
105n/a flags_and_attribs = 0
106n/a
107n/a h1 = h2 = None
108n/a try:
109n/a h1 = _winapi.CreateNamedPipe(
110n/a address, openmode, _winapi.PIPE_WAIT,
111n/a 1, obsize, ibsize, _winapi.NMPWAIT_WAIT_FOREVER, _winapi.NULL)
112n/a
113n/a h2 = _winapi.CreateFile(
114n/a address, access, 0, _winapi.NULL, _winapi.OPEN_EXISTING,
115n/a flags_and_attribs, _winapi.NULL)
116n/a
117n/a ov = _winapi.ConnectNamedPipe(h1, overlapped=True)
118n/a ov.GetOverlappedResult(True)
119n/a return h1, h2
120n/a except:
121n/a if h1 is not None:
122n/a _winapi.CloseHandle(h1)
123n/a if h2 is not None:
124n/a _winapi.CloseHandle(h2)
125n/a raise
126n/a
127n/a
128n/a# Wrapper for a pipe handle
129n/a
130n/a
131n/aclass PipeHandle:
132n/a """Wrapper for an overlapped pipe handle which is vaguely file-object like.
133n/a
134n/a The IOCP event loop can use these instead of socket objects.
135n/a """
136n/a def __init__(self, handle):
137n/a self._handle = handle
138n/a
139n/a def __repr__(self):
140n/a if self._handle is not None:
141n/a handle = 'handle=%r' % self._handle
142n/a else:
143n/a handle = 'closed'
144n/a return '<%s %s>' % (self.__class__.__name__, handle)
145n/a
146n/a @property
147n/a def handle(self):
148n/a return self._handle
149n/a
150n/a def fileno(self):
151n/a if self._handle is None:
152n/a raise ValueError("I/O operatioon on closed pipe")
153n/a return self._handle
154n/a
155n/a def close(self, *, CloseHandle=_winapi.CloseHandle):
156n/a if self._handle is not None:
157n/a CloseHandle(self._handle)
158n/a self._handle = None
159n/a
160n/a def __del__(self):
161n/a if self._handle is not None:
162n/a warnings.warn("unclosed %r" % self, ResourceWarning,
163n/a source=self)
164n/a self.close()
165n/a
166n/a def __enter__(self):
167n/a return self
168n/a
169n/a def __exit__(self, t, v, tb):
170n/a self.close()
171n/a
172n/a
173n/a# Replacement for subprocess.Popen using overlapped pipe handles
174n/a
175n/a
176n/aclass Popen(subprocess.Popen):
177n/a """Replacement for subprocess.Popen using overlapped pipe handles.
178n/a
179n/a The stdin, stdout, stderr are None or instances of PipeHandle.
180n/a """
181n/a def __init__(self, args, stdin=None, stdout=None, stderr=None, **kwds):
182n/a assert not kwds.get('universal_newlines')
183n/a assert kwds.get('bufsize', 0) == 0
184n/a stdin_rfd = stdout_wfd = stderr_wfd = None
185n/a stdin_wh = stdout_rh = stderr_rh = None
186n/a if stdin == PIPE:
187n/a stdin_rh, stdin_wh = pipe(overlapped=(False, True), duplex=True)
188n/a stdin_rfd = msvcrt.open_osfhandle(stdin_rh, os.O_RDONLY)
189n/a else:
190n/a stdin_rfd = stdin
191n/a if stdout == PIPE:
192n/a stdout_rh, stdout_wh = pipe(overlapped=(True, False))
193n/a stdout_wfd = msvcrt.open_osfhandle(stdout_wh, 0)
194n/a else:
195n/a stdout_wfd = stdout
196n/a if stderr == PIPE:
197n/a stderr_rh, stderr_wh = pipe(overlapped=(True, False))
198n/a stderr_wfd = msvcrt.open_osfhandle(stderr_wh, 0)
199n/a elif stderr == STDOUT:
200n/a stderr_wfd = stdout_wfd
201n/a else:
202n/a stderr_wfd = stderr
203n/a try:
204n/a super().__init__(args, stdin=stdin_rfd, stdout=stdout_wfd,
205n/a stderr=stderr_wfd, **kwds)
206n/a except:
207n/a for h in (stdin_wh, stdout_rh, stderr_rh):
208n/a if h is not None:
209n/a _winapi.CloseHandle(h)
210n/a raise
211n/a else:
212n/a if stdin_wh is not None:
213n/a self.stdin = PipeHandle(stdin_wh)
214n/a if stdout_rh is not None:
215n/a self.stdout = PipeHandle(stdout_rh)
216n/a if stderr_rh is not None:
217n/a self.stderr = PipeHandle(stderr_rh)
218n/a finally:
219n/a if stdin == PIPE:
220n/a os.close(stdin_rfd)
221n/a if stdout == PIPE:
222n/a os.close(stdout_wfd)
223n/a if stderr == PIPE:
224n/a os.close(stderr_wfd)