|
1 | | -class ServerKeywords(object): |
2 | | - def start_jupyter_notebook_server(): |
3 | | - pass |
| 1 | +import subprocess |
| 2 | +import time |
| 3 | +from six.moves.urllib.request import urlopen |
| 4 | + |
| 5 | +from robot.libraries.BuiltIn import BuiltIn |
| 6 | +from tornado.escape import json_decode |
| 7 | + |
| 8 | +from SeleniumLibrary.base import keyword, LibraryComponent |
| 9 | + |
| 10 | + |
| 11 | +class NBServer(object): |
| 12 | + process = None |
| 13 | + |
| 14 | + |
| 15 | +class ServerKeywords(LibraryComponent): |
| 16 | + _nbserver_handles = [] |
| 17 | + |
| 18 | + @keyword |
| 19 | + def start_new_jupyter_server(self, command="jupyter", *arguments, **configuration): |
| 20 | + """ Start a Jupyter server |
| 21 | + """ |
| 22 | + plib = BuiltIn().get_library_instance('Process') |
| 23 | + if not arguments: |
| 24 | + arguments = self.build_jupyter_server_arguments() |
| 25 | + |
| 26 | + handle = plib.start_process("jupyter", *arguments, **configuration) |
| 27 | + self._nbserver_handles += [handle] |
| 28 | + return handle |
| 29 | + |
| 30 | + @keyword |
| 31 | + def build_jupyter_server_arguments(self): |
| 32 | + return ["notebook", "--no-browser"] |
| 33 | + |
| 34 | + @keyword |
| 35 | + def wait_for_jupyter_server_to_be_ready(self, *nbservers, **kwargs): |
| 36 | + """ Wait for the most-recently started Jupyter server to be ready |
| 37 | + """ |
| 38 | + interval = float(kwargs.get("interval", 0.25)) |
| 39 | + retries = int(kwargs.get("retries", 20)) |
| 40 | + |
| 41 | + plib = BuiltIn().get_library_instance('Process') |
| 42 | + |
| 43 | + if not nbservers: |
| 44 | + if not self._nbserver_handles: |
| 45 | + return 0 |
| 46 | + nbservers = [self._nbserver_handles[-1]] |
| 47 | + |
| 48 | + ready = 0 |
| 49 | + last_error = None |
| 50 | + |
| 51 | + while retries and ready != len(nbservers): |
| 52 | + retries -= 1 |
| 53 | + ready = 0 |
| 54 | + |
| 55 | + try: |
| 56 | + nbservers_json = self.get_jupyter_servers() |
| 57 | + for nbhandle in nbservers: |
| 58 | + nbpopen = plib.get_process_object(nbhandle) |
| 59 | + nbj = nbservers_json[nbpopen.pid] |
| 60 | + urlopen("{url}favicon.ico".format(**nbj)) |
| 61 | + ready += 1 |
| 62 | + except Exception as err: |
| 63 | + time.sleep(interval) |
| 64 | + last_error = err |
| 65 | + |
| 66 | + assert ready == len(nbservers), ( |
| 67 | + "Only {} of {} servers were ready: {}".format( |
| 68 | + ready, len(nbservers), last_error |
| 69 | + )) |
| 70 | + return ready |
| 71 | + |
| 72 | + @keyword |
| 73 | + def terminate_all_jupyter_servers(self, kill=False): |
| 74 | + """ Close all Jupyter servers started by JupyterLibrary |
| 75 | + """ |
| 76 | + plib = BuiltIn().get_library_instance('Process') |
| 77 | + terminated = 0 |
| 78 | + for handle in self._nbserver_handles: |
| 79 | + plib.terminate_process(handle, kill=kill) |
| 80 | + terminated += 1 |
| 81 | + |
| 82 | + self._nbserver_handles = [] |
| 83 | + |
| 84 | + return terminated |
| 85 | + |
| 86 | + def get_jupyter_servers(self): |
| 87 | + nbservers = list(map(json_decode, subprocess.check_output( |
| 88 | + ["jupyter", "notebook", "list", "--json"] |
| 89 | + ).decode("utf-8").strip().split("\n"))) |
| 90 | + return {nbserver["pid"]: nbserver for nbserver in nbservers} |
0 commit comments