@@ -222,45 +222,6 @@ def connection_lost(self, exc):
222222 self .done .set_result (None )
223223
224224
225- class MySubprocessProtocol (asyncio .SubprocessProtocol ):
226- def __init__ (self , loop ):
227- self .state = 'INITIAL'
228- self .transport = None
229- self .connected = asyncio .Future (loop = loop )
230- self .completed = asyncio .Future (loop = loop )
231- self .disconnects = {fd : asyncio .Future (loop = loop ) for fd in range (3 )}
232- self .data = {1 : b'' , 2 : b'' }
233- self .returncode = None
234- self .got_data = {1 : asyncio .Event (loop = loop ), 2 : asyncio .Event (loop = loop )}
235-
236- def connection_made (self , transport ):
237- self .transport = transport
238- assert self .state == 'INITIAL' , self .state
239- self .state = 'CONNECTED'
240- self .connected .set_result (None )
241-
242- def connection_lost (self , exc ):
243- assert self .state == 'CONNECTED' , self .state
244- self .state = 'CLOSED'
245- self .completed .set_result (None )
246-
247- def pipe_data_received (self , fd , data ):
248- assert self .state == 'CONNECTED' , self .state
249- self .data [fd ] += data
250- self .got_data [fd ].set ()
251-
252- def pipe_connection_lost (self , fd , exc ):
253- assert self .state == 'CONNECTED' , self .state
254- if exc :
255- self .disconnects [fd ].set_exception (exc )
256- else :
257- self .disconnects [fd ].set_result (exc )
258-
259- def process_exited (self ):
260- assert self .state == 'CONNECTED' , self .state
261- self .returncode = self .transport .get_returncode ()
262-
263-
264225class EventLoopTestsMixin :
265226 def setUp (self ):
266227 super ().setUp ()
@@ -1796,296 +1757,13 @@ def test():
17961757 self .loop .add_signal_handler (signal .SIGTERM , func )
17971758
17981759
1799- class SubprocessTestsMixin :
1800- def check_terminated (self , returncode ):
1801- if sys .platform == 'win32' :
1802- self .assertIsInstance (returncode , int )
1803- # expect 1 but sometimes get 0
1804- else :
1805- self .assertEqual (- signal .SIGTERM , returncode )
1806-
1807- def check_killed (self , returncode ):
1808- if sys .platform == 'win32' :
1809- self .assertIsInstance (returncode , int )
1810- # expect 1 but sometimes get 0
1811- else :
1812- self .assertEqual (- signal .SIGKILL , returncode )
1813-
1814- def test_subprocess_exec (self ):
1815- prog = os .path .join (os .path .dirname (__file__ ), 'echo.py' )
1816-
1817- connect = self .loop .subprocess_exec (
1818- functools .partial (MySubprocessProtocol , self .loop ), sys .executable , prog
1819- )
1820- transp , proto = self .loop .run_until_complete (connect )
1821- self .assertIsInstance (proto , MySubprocessProtocol )
1822- self .loop .run_until_complete (proto .connected )
1823- self .assertEqual ('CONNECTED' , proto .state )
1824-
1825- stdin = transp .get_pipe_transport (0 )
1826- stdin .write (b'Python The Winner' )
1827- self .loop .run_until_complete (proto .got_data [1 ].wait ())
1828- with test_utils .disable_logger ():
1829- transp .close ()
1830- self .loop .run_until_complete (proto .completed )
1831- self .check_killed (proto .returncode )
1832- self .assertEqual (b'Python The Winner' , proto .data [1 ])
1833-
1834- def test_subprocess_interactive (self ):
1835- prog = os .path .join (os .path .dirname (__file__ ), 'echo.py' )
1836-
1837- connect = self .loop .subprocess_exec (
1838- functools .partial (MySubprocessProtocol , self .loop ), sys .executable , prog
1839- )
1840- transp , proto = self .loop .run_until_complete (connect )
1841- self .assertIsInstance (proto , MySubprocessProtocol )
1842- self .loop .run_until_complete (proto .connected )
1843- self .assertEqual ('CONNECTED' , proto .state )
1844-
1845- stdin = transp .get_pipe_transport (0 )
1846- stdin .write (b'Python ' )
1847- self .loop .run_until_complete (proto .got_data [1 ].wait ())
1848- proto .got_data [1 ].clear ()
1849- self .assertEqual (b'Python ' , proto .data [1 ])
1850-
1851- stdin .write (b'The Winner' )
1852- self .loop .run_until_complete (proto .got_data [1 ].wait ())
1853- self .assertEqual (b'Python The Winner' , proto .data [1 ])
1854-
1855- with test_utils .disable_logger ():
1856- transp .close ()
1857- self .loop .run_until_complete (proto .completed )
1858- self .check_killed (proto .returncode )
1859-
1860- def test_subprocess_shell (self ):
1861- connect = self .loop .subprocess_shell (
1862- functools .partial (MySubprocessProtocol , self .loop ), 'echo Python'
1863- )
1864- transp , proto = self .loop .run_until_complete (connect )
1865- self .assertIsInstance (proto , MySubprocessProtocol )
1866- self .loop .run_until_complete (proto .connected )
1867-
1868- transp .get_pipe_transport (0 ).close ()
1869- self .loop .run_until_complete (proto .completed )
1870- self .assertEqual (0 , proto .returncode )
1871- self .assertTrue (all (f .done () for f in proto .disconnects .values ()))
1872- self .assertEqual (proto .data [1 ].rstrip (b'\r \n ' ), b'Python' )
1873- self .assertEqual (proto .data [2 ], b'' )
1874- transp .close ()
1875-
1876- def test_subprocess_exitcode (self ):
1877- connect = self .loop .subprocess_shell (
1878- functools .partial (MySubprocessProtocol , self .loop ),
1879- 'exit 7' ,
1880- stdin = None ,
1881- stdout = None ,
1882- stderr = None
1883- )
1884- transp , proto = self .loop .run_until_complete (connect )
1885- self .assertIsInstance (proto , MySubprocessProtocol )
1886- self .loop .run_until_complete (proto .completed )
1887- self .assertEqual (7 , proto .returncode )
1888- transp .close ()
1889-
1890- def test_subprocess_close_after_finish (self ):
1891- connect = self .loop .subprocess_shell (
1892- functools .partial (MySubprocessProtocol , self .loop ),
1893- 'exit 7' ,
1894- stdin = None ,
1895- stdout = None ,
1896- stderr = None
1897- )
1898- transp , proto = self .loop .run_until_complete (connect )
1899- self .assertIsInstance (proto , MySubprocessProtocol )
1900- self .assertIsNone (transp .get_pipe_transport (0 ))
1901- self .assertIsNone (transp .get_pipe_transport (1 ))
1902- self .assertIsNone (transp .get_pipe_transport (2 ))
1903- self .loop .run_until_complete (proto .completed )
1904- self .assertEqual (7 , proto .returncode )
1905- self .assertIsNone (transp .close ())
1906-
1907- def test_subprocess_kill (self ):
1908- prog = os .path .join (os .path .dirname (__file__ ), 'echo.py' )
1909-
1910- connect = self .loop .subprocess_exec (
1911- functools .partial (MySubprocessProtocol , self .loop ), sys .executable , prog
1912- )
1913- transp , proto = self .loop .run_until_complete (connect )
1914- self .assertIsInstance (proto , MySubprocessProtocol )
1915- self .loop .run_until_complete (proto .connected )
1916-
1917- transp .kill ()
1918- self .loop .run_until_complete (proto .completed )
1919- self .check_killed (proto .returncode )
1920- transp .close ()
1921-
1922- def test_subprocess_terminate (self ):
1923- prog = os .path .join (os .path .dirname (__file__ ), 'echo.py' )
1924-
1925- connect = self .loop .subprocess_exec (
1926- functools .partial (MySubprocessProtocol , self .loop ), sys .executable , prog
1927- )
1928- transp , proto = self .loop .run_until_complete (connect )
1929- self .assertIsInstance (proto , MySubprocessProtocol )
1930- self .loop .run_until_complete (proto .connected )
1931-
1932- transp .terminate ()
1933- self .loop .run_until_complete (proto .completed )
1934- self .check_terminated (proto .returncode )
1935- transp .close ()
1936-
1937- @unittest .skipIf (sys .platform == 'win32' , "Don't have SIGHUP" )
1938- def test_subprocess_send_signal (self ):
1939- # bpo-31034: Make sure that we get the default signal handler (killing
1940- # the process). The parent process may have decided to ignore SIGHUP,
1941- # and signal handlers are inherited.
1942- old_handler = signal .signal (signal .SIGHUP , signal .SIG_DFL )
1943- try :
1944- prog = os .path .join (os .path .dirname (__file__ ), 'echo.py' )
1945-
1946- connect = self .loop .subprocess_exec (
1947- functools .partial (MySubprocessProtocol , self .loop ), sys .executable , prog
1948- )
1949- transp , proto = self .loop .run_until_complete (connect )
1950- self .assertIsInstance (proto , MySubprocessProtocol )
1951- self .loop .run_until_complete (proto .connected )
1952-
1953- transp .send_signal (signal .SIGHUP )
1954- self .loop .run_until_complete (proto .completed )
1955- self .assertEqual (- signal .SIGHUP , proto .returncode )
1956- transp .close ()
1957- finally :
1958- signal .signal (signal .SIGHUP , old_handler )
1959-
1960- def test_subprocess_stderr (self ):
1961- prog = os .path .join (os .path .dirname (__file__ ), 'echo2.py' )
1962-
1963- connect = self .loop .subprocess_exec (
1964- functools .partial (MySubprocessProtocol , self .loop ), sys .executable , prog
1965- )
1966- transp , proto = self .loop .run_until_complete (connect )
1967- self .assertIsInstance (proto , MySubprocessProtocol )
1968- self .loop .run_until_complete (proto .connected )
1969-
1970- stdin = transp .get_pipe_transport (0 )
1971- stdin .write (b'test' )
1972-
1973- self .loop .run_until_complete (proto .completed )
1974-
1975- transp .close ()
1976- self .assertEqual (b'OUT:test' , proto .data [1 ])
1977- self .assertTrue (proto .data [2 ].startswith (b'ERR:test' ), proto .data [2 ])
1978- self .assertEqual (0 , proto .returncode )
1979-
1980- def test_subprocess_stderr_redirect_to_stdout (self ):
1981- prog = os .path .join (os .path .dirname (__file__ ), 'echo2.py' )
1982-
1983- connect = self .loop .subprocess_exec (
1984- functools .partial (MySubprocessProtocol , self .loop ),
1985- sys .executable ,
1986- prog ,
1987- stderr = subprocess .STDOUT
1988- )
1989- transp , proto = self .loop .run_until_complete (connect )
1990- self .assertIsInstance (proto , MySubprocessProtocol )
1991- self .loop .run_until_complete (proto .connected )
1992-
1993- stdin = transp .get_pipe_transport (0 )
1994- self .assertIsNotNone (transp .get_pipe_transport (1 ))
1995- self .assertIsNone (transp .get_pipe_transport (2 ))
1996-
1997- stdin .write (b'test' )
1998- self .loop .run_until_complete (proto .completed )
1999- self .assertTrue (proto .data [1 ].startswith (b'OUT:testERR:test' ), proto .data [1 ])
2000- self .assertEqual (b'' , proto .data [2 ])
2001-
2002- transp .close ()
2003- self .assertEqual (0 , proto .returncode )
2004-
2005- def test_subprocess_close_client_stream (self ):
2006- prog = os .path .join (os .path .dirname (__file__ ), 'echo3.py' )
2007-
2008- connect = self .loop .subprocess_exec (
2009- functools .partial (MySubprocessProtocol , self .loop ), sys .executable , prog
2010- )
2011- transp , proto = self .loop .run_until_complete (connect )
2012- self .assertIsInstance (proto , MySubprocessProtocol )
2013- self .loop .run_until_complete (proto .connected )
2014-
2015- stdin = transp .get_pipe_transport (0 )
2016- stdout = transp .get_pipe_transport (1 )
2017- stdin .write (b'test' )
2018- self .loop .run_until_complete (proto .got_data [1 ].wait ())
2019- self .assertEqual (b'OUT:test' , proto .data [1 ])
2020-
2021- stdout .close ()
2022- self .loop .run_until_complete (proto .disconnects [1 ])
2023- stdin .write (b'xxx' )
2024- self .loop .run_until_complete (proto .got_data [2 ].wait ())
2025- if sys .platform != 'win32' :
2026- self .assertEqual (b'ERR:BrokenPipeError' , proto .data [2 ])
2027- else :
2028- # After closing the read-end of a pipe, writing to the
2029- # write-end using os.write() fails with errno==EINVAL and
2030- # GetLastError()==ERROR_INVALID_NAME on Windows!?! (Using
2031- # WriteFile() we get ERROR_BROKEN_PIPE as expected.)
2032- self .assertEqual (b'ERR:OSError' , proto .data [2 ])
2033- with test_utils .disable_logger ():
2034- transp .close ()
2035- self .loop .run_until_complete (proto .completed )
2036- self .check_killed (proto .returncode )
2037-
2038- def test_subprocess_wait_no_same_group (self ):
2039- # start the new process in a new session
2040- connect = self .loop .subprocess_shell (
2041- functools .partial (MySubprocessProtocol , self .loop ),
2042- 'exit 7' ,
2043- stdin = None ,
2044- stdout = None ,
2045- stderr = None ,
2046- start_new_session = True
2047- )
2048- _ , proto = yield self .loop .run_until_complete (connect )
2049- self .assertIsInstance (proto , MySubprocessProtocol )
2050- self .loop .run_until_complete (proto .completed )
2051- self .assertEqual (7 , proto .returncode )
2052-
2053- def test_subprocess_exec_invalid_args (self ):
2054- @asyncio .coroutine
2055- def connect (** kwds ):
2056- yield from self .loop .subprocess_exec (asyncio .SubprocessProtocol , 'pwd' , ** kwds )
2057-
2058- with self .assertRaises (ValueError ):
2059- self .loop .run_until_complete (connect (universal_newlines = True ))
2060- with self .assertRaises (ValueError ):
2061- self .loop .run_until_complete (connect (bufsize = 4096 ))
2062- with self .assertRaises (ValueError ):
2063- self .loop .run_until_complete (connect (shell = True ))
2064-
2065- def test_subprocess_shell_invalid_args (self ):
2066- @asyncio .coroutine
2067- def connect (cmd = None , ** kwds ):
2068- if not cmd :
2069- cmd = 'pwd'
2070- yield from self .loop .subprocess_shell (asyncio .SubprocessProtocol , cmd , ** kwds )
2071-
2072- with self .assertRaises (ValueError ):
2073- self .loop .run_until_complete (connect (['ls' , '-l' ]))
2074- with self .assertRaises (ValueError ):
2075- self .loop .run_until_complete (connect (universal_newlines = True ))
2076- with self .assertRaises (ValueError ):
2077- self .loop .run_until_complete (connect (bufsize = 4096 ))
2078- with self .assertRaises (ValueError ):
2079- self .loop .run_until_complete (connect (shell = False ))
2080-
2081-
20821760if sys .platform == 'win32' :
20831761
20841762 class SelectEventLoopTests (EventLoopTestsMixin , test_utils .TestCase ):
20851763 def create_event_loop (self ):
20861764 return asyncio .SelectorEventLoop ()
20871765
2088- class ProactorEventLoopTests (EventLoopTestsMixin , SubprocessTestsMixin , test_utils .TestCase ):
1766+ class ProactorEventLoopTests (EventLoopTestsMixin , test_utils .TestCase ):
20891767 def create_event_loop (self ):
20901768 return asyncio .ProactorEventLoop ()
20911769
@@ -2158,7 +1836,7 @@ async def main():
21581836
21591837 if False and hasattr (selectors , 'KqueueSelector' ):
21601838
2161- class KqueueEventLoopTests (UnixEventLoopTestsMixin , SubprocessTestsMixin ,
1839+ class KqueueEventLoopTests (UnixEventLoopTestsMixin ,
21621840 test_utils .TestCase ):
21631841 def create_event_loop (self ):
21641842 return asyncio .SelectorEventLoop (selectors .KqueueSelector ())
@@ -2180,20 +1858,20 @@ def test_write_pty(self):
21801858
21811859 if False and hasattr (selectors , 'EpollSelector' ):
21821860
2183- class EPollEventLoopTests (UnixEventLoopTestsMixin , SubprocessTestsMixin ,
1861+ class EPollEventLoopTests (UnixEventLoopTestsMixin ,
21841862 test_utils .TestCase ):
21851863 def create_event_loop (self ):
21861864 return asyncio .SelectorEventLoop (selectors .EpollSelector ())
21871865
21881866 if False and hasattr (selectors , 'PollSelector' ):
21891867
2190- class PollEventLoopTests (UnixEventLoopTestsMixin , SubprocessTestsMixin ,
1868+ class PollEventLoopTests (UnixEventLoopTestsMixin ,
21911869 test_utils .TestCase ):
21921870 def create_event_loop (self ):
21931871 return asyncio .SelectorEventLoop (selectors .PollSelector ())
21941872
21951873 # Should always exist.
2196- class TrioEventLoopTests (UnixEventLoopTestsMixin , SubprocessTestsMixin , test_utils .TestCase ):
1874+ class TrioEventLoopTests (UnixEventLoopTestsMixin , test_utils .TestCase ):
21971875 def create_event_loop (self ):
21981876 import trio_asyncio .sync
21991877 return trio_asyncio .sync .SyncTrioEventLoop ()
0 commit comments