Show More
@@ -19,8 +19,8 b' test suite.' | |||||
19 | from __future__ import print_function |
|
19 | from __future__ import print_function | |
20 |
|
20 | |||
21 | import argparse |
|
21 | import argparse | |
|
22 | import json | |||
22 | import multiprocessing.pool |
|
23 | import multiprocessing.pool | |
23 | from multiprocessing import Process, Queue |
|
|||
24 | import os |
|
24 | import os | |
25 | import shutil |
|
25 | import shutil | |
26 | import signal |
|
26 | import signal | |
@@ -28,7 +28,7 b' import sys' | |||||
28 | import subprocess |
|
28 | import subprocess | |
29 | import time |
|
29 | import time | |
30 |
|
30 | |||
31 | from .iptest import have, test_group_names as py_test_group_names, test_sections |
|
31 | from .iptest import have, test_group_names as py_test_group_names, test_sections, StreamCapturer | |
32 | from IPython.utils.path import compress_user |
|
32 | from IPython.utils.path import compress_user | |
33 | from IPython.utils.py3compat import bytes_to_str |
|
33 | from IPython.utils.py3compat import bytes_to_str | |
34 | from IPython.utils.sysinfo import get_sys_info |
|
34 | from IPython.utils.sysinfo import get_sys_info | |
@@ -211,8 +211,10 b' class JSController(TestController):' | |||||
211 | os.makedirs(os.path.join(self.nbdir.name, os.path.join(u'sub βir2', u'sub βir 1b'))) |
|
211 | os.makedirs(os.path.join(self.nbdir.name, os.path.join(u'sub βir2', u'sub βir 1b'))) | |
212 |
|
212 | |||
213 | # start the ipython notebook, so we get the port number |
|
213 | # start the ipython notebook, so we get the port number | |
|
214 | self.server_port = 0 | |||
214 | self._init_server() |
|
215 | self._init_server() | |
215 |
|
|
216 | if self.server_port: | |
|
217 | self.cmd.append("--port=%i" % self.server_port) | |||
216 |
|
218 | |||
217 | def print_extra_info(self): |
|
219 | def print_extra_info(self): | |
218 | print("Running tests with notebook directory %r" % self.nbdir.name) |
|
220 | print("Running tests with notebook directory %r" % self.nbdir.name) | |
@@ -223,36 +225,60 b' class JSController(TestController):' | |||||
223 |
|
225 | |||
224 | def _init_server(self): |
|
226 | def _init_server(self): | |
225 | "Start the notebook server in a separate process" |
|
227 | "Start the notebook server in a separate process" | |
226 | self.queue = q = Queue() |
|
228 | self.server_command = command = [sys.executable, | |
227 | self.server = Process(target=run_webapp, args=(q, self.ipydir.name, self.nbdir.name)) |
|
229 | '-m', 'IPython.html', | |
228 | self.server.start() |
|
230 | '--no-browser', | |
229 | self.server_port = q.get() |
|
231 | '--ipython-dir', self.ipydir.name, | |
|
232 | '--notebook-dir', self.nbdir.name, | |||
|
233 | ] | |||
|
234 | # ipc doesn't work on Windows, and darwin has crazy-long temp paths, | |||
|
235 | # which run afoul of ipc's maximum path length. | |||
|
236 | if sys.platform.startswith('linux'): | |||
|
237 | command.append('--KernelManager.transport=ipc') | |||
|
238 | self.stream_capturer = c = StreamCapturer() | |||
|
239 | c.start() | |||
|
240 | self.server = subprocess.Popen(command, stdout=c.writefd, stderr=subprocess.STDOUT) | |||
|
241 | self.server_info_file = os.path.join(self.ipydir.name, | |||
|
242 | 'profile_default', 'security', 'nbserver-%i.json' % self.server.pid | |||
|
243 | ) | |||
|
244 | self._wait_for_server() | |||
|
245 | ||||
|
246 | def _wait_for_server(self): | |||
|
247 | """Wait 30 seconds for the notebook server to start""" | |||
|
248 | for i in range(300): | |||
|
249 | if self.server.poll() is not None: | |||
|
250 | return self._failed_to_start() | |||
|
251 | if os.path.exists(self.server_info_file): | |||
|
252 | self._load_server_info() | |||
|
253 | return | |||
|
254 | time.sleep(0.1) | |||
|
255 | print("Notebook server-info file never arrived: %s" % self.server_info_file, | |||
|
256 | file=sys.stderr | |||
|
257 | ) | |||
|
258 | ||||
|
259 | def _failed_to_start(self): | |||
|
260 | """Notebook server exited prematurely""" | |||
|
261 | captured = self.stream_capturer.get_buffer().decode('utf-8', 'replace') | |||
|
262 | print("Notebook failed to start: ", file=sys.stderr) | |||
|
263 | print(self.server_command) | |||
|
264 | print(captured, file=sys.stderr) | |||
|
265 | ||||
|
266 | def _load_server_info(self): | |||
|
267 | """Notebook server started, load connection info from JSON""" | |||
|
268 | with open(self.server_info_file) as f: | |||
|
269 | info = json.load(f) | |||
|
270 | self.server_port = info['port'] | |||
230 |
|
271 | |||
231 | def cleanup(self): |
|
272 | def cleanup(self): | |
|
273 | self.stream_capturer.halt() | |||
|
274 | try: | |||
232 | self.server.terminate() |
|
275 | self.server.terminate() | |
233 | self.server.join() |
|
276 | except OSError: | |
|
277 | # already dead | |||
|
278 | pass | |||
|
279 | self.server.wait() | |||
234 | TestController.cleanup(self) |
|
280 | TestController.cleanup(self) | |
235 |
|
281 | |||
236 | def run_webapp(q, ipydir, nbdir, loglevel=0): |
|
|||
237 | """start the IPython Notebook, and pass port back to the queue""" |
|
|||
238 | import os |
|
|||
239 | import IPython.html.notebookapp as nbapp |
|
|||
240 | import sys |
|
|||
241 | sys.stderr = open(os.devnull, 'w') |
|
|||
242 | server = nbapp.NotebookApp() |
|
|||
243 | args = ['--no-browser'] |
|
|||
244 | args.extend(['--ipython-dir', ipydir, |
|
|||
245 | '--notebook-dir', nbdir, |
|
|||
246 | '--log-level', str(loglevel), |
|
|||
247 | ]) |
|
|||
248 | # ipc doesn't work on Windows, and darwin has crazy-long temp paths, |
|
|||
249 | # which run afoul of ipc's maximum path length. |
|
|||
250 | if sys.platform.startswith('linux'): |
|
|||
251 | args.append('--KernelManager.transport=ipc') |
|
|||
252 | server.initialize(args) |
|
|||
253 | # communicate the port number to the parent process |
|
|||
254 | q.put(server.port) |
|
|||
255 | server.start() |
|
|||
256 |
|
282 | |||
257 | def prepare_controllers(options): |
|
283 | def prepare_controllers(options): | |
258 | """Returns two lists of TestController instances, those to run, and those |
|
284 | """Returns two lists of TestController instances, those to run, and those |
General Comments 0
You need to be logged in to leave comments.
Login now