##// END OF EJS Templates
Merge pull request #12639 from jetpacktuxedo/buffering
Matthias Bussonnier -
r26204:3b094c83 merge
parent child Browse files
Show More
@@ -34,11 +34,6 b' before_install:'
34 34 install:
35 35 - pip install pip --upgrade
36 36 - pip install setuptools --upgrade
37 - if [[ "$TRAVIS_PYTHON_VERSION" == "3.6" ]]; then
38 echo "for the time being still test on 3.6";
39 sed -ibkp s/7/6/g setup.py;
40 git diff;
41 fi
42 37 - pip install -e file://$PWD#egg=ipython[test] --upgrade
43 38 - pip install trio curio --upgrade --upgrade-strategy eager
44 39 - pip install 'pytest' 'matplotlib !=3.2.0'
@@ -73,9 +68,6 b' after_success:'
73 68 matrix:
74 69 include:
75 70 - arch: amd64
76 python: "3.6"
77 dist: xenial
78 - arch: amd64
79 71 python: "3.7"
80 72 dist: xenial
81 73 - arch: amd64
@@ -8,7 +8,7 b' import os'
8 8 import sys
9 9 import signal
10 10 import time
11 from subprocess import Popen, PIPE, CalledProcessError
11 import asyncio
12 12 import atexit
13 13
14 14 from IPython.core import magic_arguments
@@ -175,11 +175,44 b' class ScriptMagics(Magics):'
175 175 2
176 176 3
177 177 """
178 argv = arg_split(line, posix = not sys.platform.startswith('win'))
179 args, cmd = self.shebang.parser.parse_known_args(argv)
180 178
179 async def _handle_stream(stream, stream_arg, file_object):
180 while True:
181 line = (await stream.readline()).decode("utf8")
182 if not line:
183 break
184 if stream_arg:
185 self.shell.user_ns[stream_arg] = line
186 else:
187 file_object.write(line)
188 file_object.flush()
189
190 async def _stream_communicate(process, cell):
191 process.stdin.write(cell)
192 process.stdin.close()
193 stdout_task = asyncio.create_task(
194 _handle_stream(process.stdout, args.out, sys.stdout)
195 )
196 stderr_task = asyncio.create_task(
197 _handle_stream(process.stderr, args.err, sys.stderr)
198 )
199 await asyncio.wait([stdout_task, stderr_task])
200
201 if sys.platform.startswith("win"):
202 asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
203 loop = asyncio.get_event_loop()
204
205 argv = arg_split(line, posix=not sys.platform.startswith("win"))
206 args, cmd = self.shebang.parser.parse_known_args(argv)
181 207 try:
182 p = Popen(cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE)
208 p = loop.run_until_complete(
209 asyncio.create_subprocess_exec(
210 *cmd,
211 stdout=asyncio.subprocess.PIPE,
212 stderr=asyncio.subprocess.PIPE,
213 stdin=asyncio.subprocess.PIPE
214 )
215 )
183 216 except OSError as e:
184 217 if e.errno == errno.ENOENT:
185 218 print("Couldn't find program: %r" % cmd[0])
@@ -208,17 +241,17 b' class ScriptMagics(Magics):'
208 241 return
209 242
210 243 try:
211 out, err = p.communicate(cell)
244 loop.run_until_complete(_stream_communicate(p, cell))
212 245 except KeyboardInterrupt:
213 246 try:
214 247 p.send_signal(signal.SIGINT)
215 248 time.sleep(0.1)
216 if p.poll() is not None:
249 if p.returncode is not None:
217 250 print("Process is interrupted.")
218 251 return
219 252 p.terminate()
220 253 time.sleep(0.1)
221 if p.poll() is not None:
254 if p.returncode is not None:
222 255 print("Process is terminated.")
223 256 return
224 257 p.kill()
@@ -229,20 +262,8 b' class ScriptMagics(Magics):'
229 262 print("Error while terminating subprocess (pid=%i): %s" \
230 263 % (p.pid, e))
231 264 return
232 out = py3compat.decode(out)
233 err = py3compat.decode(err)
234 if args.out:
235 self.shell.user_ns[args.out] = out
236 else:
237 sys.stdout.write(out)
238 sys.stdout.flush()
239 if args.err:
240 self.shell.user_ns[args.err] = err
241 else:
242 sys.stderr.write(err)
243 sys.stderr.flush()
244 265 if args.raise_error and p.returncode!=0:
245 raise CalledProcessError(p.returncode, cell, output=out, stderr=err)
266 raise CalledProcessError(p.returncode, cell)
246 267
247 268 def _run_script(self, p, cell, to_close):
248 269 """callback for running the script in the background"""
@@ -263,7 +284,7 b' class ScriptMagics(Magics):'
263 284 if not self.bg_processes:
264 285 return
265 286 for p in self.bg_processes:
266 if p.poll() is None:
287 if p.returncode is None:
267 288 try:
268 289 p.send_signal(signal.SIGINT)
269 290 except:
@@ -273,7 +294,7 b' class ScriptMagics(Magics):'
273 294 if not self.bg_processes:
274 295 return
275 296 for p in self.bg_processes:
276 if p.poll() is None:
297 if p.returncode is None:
277 298 try:
278 299 p.terminate()
279 300 except:
@@ -283,7 +304,7 b' class ScriptMagics(Magics):'
283 304 if not self.bg_processes:
284 305 return
285 306 for p in self.bg_processes:
286 if p.poll() is None:
307 if p.returncode is None:
287 308 try:
288 309 p.kill()
289 310 except:
@@ -291,4 +312,4 b' class ScriptMagics(Magics):'
291 312 self._gc_bg_processes()
292 313
293 314 def _gc_bg_processes(self):
294 self.bg_processes = [p for p in self.bg_processes if p.poll() is None]
315 self.bg_processes = [p for p in self.bg_processes if p.returncode is None]
@@ -948,28 +948,32 b' def test_script_out_err():'
948 948 nt.assert_equal(ip.user_ns['error'], 'hello\n')
949 949
950 950 @dec.skip_win32
951 def test_script_bg_out():
951 async def test_script_bg_out():
952 952 ip = get_ipython()
953 953 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
954
955 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
954 nt.assert_equal((await ip.user_ns["output"].read()), b"hi\n")
956 955 ip.user_ns['output'].close()
957 956
957
958 958 @dec.skip_win32
959 def test_script_bg_err():
959 async def test_script_bg_err():
960 960 ip = get_ipython()
961 961 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
962 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
963 ip.user_ns['error'].close()
962 nt.assert_equal((await ip.user_ns["error"].read()), b"hello\n")
963 ip.user_ns["error"].close()
964
964 965
965 966 @dec.skip_win32
966 def test_script_bg_out_err():
967 async def test_script_bg_out_err():
967 968 ip = get_ipython()
968 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
969 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
970 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
971 ip.user_ns['output'].close()
972 ip.user_ns['error'].close()
969 ip.run_cell_magic(
970 "script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2"
971 )
972 nt.assert_equal((await ip.user_ns["output"].read()), b"hi\n")
973 nt.assert_equal((await ip.user_ns["error"].read()), b"hello\n")
974 ip.user_ns["output"].close()
975 ip.user_ns["error"].close()
976
973 977
974 978 def test_script_defaults():
975 979 ip = get_ipython()
General Comments 0
You need to be logged in to leave comments. Login now