run-test.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. # Copyright (c) Jupyter Development Team.
  2. # Distributed under the terms of the Modified BSD License.
  3. from __future__ import print_function, absolute_import
  4. import atexit
  5. import json
  6. import os
  7. from subprocess import Popen
  8. import sys
  9. import shutil
  10. import tempfile
  11. from tornado import gen
  12. from tornado.ioloop import IOLoop
  13. from notebook.notebookapp import NotebookApp
  14. from traitlets import Bool, Unicode
  15. HERE = os.path.dirname(__file__)
  16. def get_command(nbapp):
  17. """Get the command to run."""
  18. terminalsAvailable = nbapp.web_app.settings['terminals_available']
  19. # Compatibility with Notebook 4.2.
  20. token = getattr(nbapp, 'token', '')
  21. config = dict(baseUrl=nbapp.connection_url, token=token,
  22. terminalsAvailable=str(terminalsAvailable))
  23. print('\n\nNotebook config:')
  24. print(json.dumps(config))
  25. with open(os.path.join(HERE, 'build', 'injector.js'), 'w') as fid:
  26. fid.write("""
  27. var node = document.createElement('script');
  28. node.id = 'jupyter-config-data';
  29. node.type = 'application/json';
  30. node.textContent = '%s';
  31. document.body.appendChild(node);
  32. """ % json.dumps(config))
  33. return ['karma', 'start'] + sys.argv[1:]
  34. def create_notebook_dir():
  35. """Create a temporary directory with some file structure."""
  36. root_dir = tempfile.mkdtemp(prefix='mock_contents')
  37. os.mkdir(os.path.join(root_dir, 'src'))
  38. with open(os.path.join(root_dir, 'src', 'temp.txt'), 'w') as fid:
  39. fid.write('hello')
  40. atexit.register(lambda: shutil.rmtree(root_dir, True))
  41. return root_dir
  42. class TaskRunner(object):
  43. """Run a task using the notebook app and exit with the return code.
  44. """
  45. def __init__(self, nbapp):
  46. self.nbapp = nbapp
  47. def start(self, cmd):
  48. """Start the task."""
  49. # Run the command after the ioloop starts.
  50. self._command = cmd
  51. IOLoop.current().add_callback(self._run_command)
  52. def exit(self, returncode):
  53. """Safely stop the app and then exit with the given code."""
  54. self._return_code = returncode
  55. self.nbapp.io_loop.add_callback(self._exit)
  56. @gen.coroutine
  57. def _run_command(self):
  58. """Run a task in a thread and exit with the return code."""
  59. cmd = self._command
  60. shell = os.name == 'nt'
  61. proc = Popen(cmd, shell=shell)
  62. print('\n\nRunning command: "%s"\n\n' % ' '.join(cmd))
  63. # Poll the process once per second until finished.
  64. while 1:
  65. yield gen.sleep(1)
  66. if proc.poll() is not None:
  67. break
  68. self.exit(proc.returncode)
  69. def _exit(self):
  70. self.nbapp.io_loop.stop()
  71. sys.exit(self._return_code)
  72. class TestApp(NotebookApp):
  73. """A notebook app that supports a unit test."""
  74. open_browser = Bool(False)
  75. notebook_dir = Unicode(create_notebook_dir())
  76. allow_origin = Unicode('*')
  77. def main():
  78. """Run the unit test."""
  79. app = TestApp()
  80. if app.version == '4.3.0':
  81. msg = ('Cannot run unit tests against Notebook 4.3.0. '
  82. 'Please upgrade to Notebook 4.3.1+')
  83. print(msg)
  84. sys.exit(1)
  85. app.initialize([]) # reserve sys.argv for the command
  86. task = TaskRunner(app)
  87. task.start(get_command(app))
  88. try:
  89. app.start()
  90. except KeyboardInterrupt:
  91. task.exit(1)
  92. if __name__ == '__main__':
  93. main()