class IPythonSession(object): def __init__(self): self.comm = None folder = os.path.dirname(__file__) with open(os.path.join(folder, "../js", "initIPython.js"), "r") as fd: initIPython = fd.read() display_javascript(Javascript(initIPython)) css = """ <style> div.output_area img, div.output_area svg { max-width: 100%; height: 100%; } </style> """ display_html(HTML(css)) time.sleep(0.5) self.comm = Comm(target_name='nvd3_stat', data={'event': 'open'}) def registerFunction(self, funcName, funcBody): # Zeppelin only pass def call(self, funcName, args, delay): # Explicitely open comm channel in case notebook has been reloaded self.comm.open() self.comm.send({"funcName": funcName, "args": args, "delay": delay})
def add_widget(self, widget_id, client_id, widget_type, comm_target): """Add a widget to manager. # Returns: """ comm = self.find_comm( comm_target=comm_target) # Try to find a comm object if not comm: # Create comm if does not exist comm = Comm(target_name=comm_target) self._comms[widget_id] = comm @comm.on_msg def handle_msg(msg): comm_id = msg["content"]["comm_id"] data = msg["content"]["data"] nonlocal self widget = self.find_widget_by_comm_id(comm_id) self.last_active = widget widget.msg_data = data widget.parse_data(data) if data == "dispose": widget.isDisposed = True self.callback_manager.run(comm_id, data) @comm.on_close def handle_close(msg): comm_id = msg["content"]["comm_id"] nonlocal self widget = self.find_widget_by_comm_id(comm_id) widget.commOpen = False if widget_id not in self.widgets: self.widgets[widget_id] = Widget( widget_type=widget_type, widget_id=widget_id, client_id=client_id, model=None, comm=comm, isDisposed=False, msg_data=None, ) self.last_active = self.widgets[widget_id] # make sure that comm is open comm.open()
class WWTLabApplication(BaseWWTWidget): """ A handle the WWT JupyterLab application. While other parts of pywwt create "widgets", bound to variables running inside Python notebooks, this class represents a connection to the standalone "application", which exists in JupyterLab independently of any one specific notebook. The Python API is the same, it's just that the JSON messages we send are routed to the separate application rather than our own iframe. """ _comm = None _controls = None # View state that gets synchronized back to us. This is the same scheme as # the widget, just with manual synchronization over our comm to the viewer # app. _raRad = 0.0 _decRad = 0.0 _fovDeg = 60.0 _engineTime = Time('2017-03-09T12:30:00', format='isot') _systemTime = Time('2017-03-09T12:30:00', format='isot') _timeRate = 1.0 def __init__(self): self._comm = Comm(target_name='@wwtelescope/jupyterlab:research', data={}) self._comm.on_msg(self._on_message_received) self._comm.open() self._send_msg(event='trigger') # get bidirectional updates flowing BaseWWTWidget.__init__(self) def _send_msg(self, **kwargs): self._comm.send(kwargs) def _on_message_received(self, msg): payload = msg['content']['data'] if payload['type'] != 'wwt_view_state': return try: self._raRad = float(payload['raRad']) self._decRad = float(payload['decRad']) self._fovDeg = float(payload['fovDeg']) self._engineTime = Time(payload['engineClockISOT'], format='isot') self._systemTime = Time(payload['systemClockISOT'], format='isot') self._timeRate = float(payload['engineClockRateFactor']) except ValueError: pass # report a warning somehow? def _serve_file(self, filename, extension=''): return serve_file(filename, extension=extension) def _get_view_data(self, field): if field == 'ra': return self._raRad * R2H elif field == 'dec': return self._decRad * R2D elif field == 'fov': return self._fovDeg elif field == 'datetime': engine_delta = self._timeRate * (Time.now() - self._systemTime) return self._engineTime + engine_delta else: raise ValueError('internal problem: unexpected "field" value') def _create_image_layer(self, **kwargs): """Returns a specialized subclass of ImageLayer that has some extra hooks for creating UI control points. """ return JupyterImageLayer(parent=self, **kwargs) @property def layer_controls(self): if self._controls is None: opacity_slider = widgets.FloatSlider(value=self.foreground_opacity, min=0, max=1, readout=False) foreground_menu = widgets.Dropdown(options=self.available_layers, value=self.foreground) background_menu = widgets.Dropdown(options=self.available_layers, value=self.background) link((opacity_slider, 'value'), (self, 'foreground_opacity')) link((foreground_menu, 'value'), (self, 'foreground')) link((background_menu, 'value'), (self, 'background')) self._controls = widgets.HBox([background_menu, opacity_slider, foreground_menu]) return self._controls
class BeakerX: def __init__(self): BeakerX.pandas_display_table() self._comm = None self._queue = Queue() self._server = BeakerxZMQServer(self._queue) self._url = self._server.url @staticmethod def pandas_display_default(): pandas.DataFrame._ipython_display_ = None @staticmethod def pandas_display_table(): pandas.DataFrame._ipython_display_ = TableDisplayWrapper() def set4(self, var, val, unset, sync): args = {'name': var, 'sync': sync} if not unset: val = transform(val) args['value'] = json.dumps(val, cls=DataFrameEncoder) state = {'state': args} if self._comm is None: self.init_autotranslation_comm() self._comm.send(data=state) def init_autotranslation_comm(self): self._comm = Comm(target_name='beakerx.autotranslation') self._comm.open() def get(self, var): result = autotranslation_get(var) if result == 'undefined': raise NameError('name \'' + var + '\' is not defined on the beakerx object') return transformBack(json.loads(result)) def set_session(self, id): self.session_id = id def register_output(self): ip = IPython.InteractiveShell.instance() ip.display_formatter.formatters['application/json'] = MyJSONFormatter(parent=ip.display_formatter) def set(self, var, val): autotranslation_update(var, val) return self.set4(var, val, False, True) def unset(self, var): return self.set4(var, None, True, True) def isDefined(self, var): return autotranslation_get(var) != 'undefined' def createOutputContainer(self): return OutputContainer() def showProgressUpdate(self): return "WARNING: python3 language plugin does not support progress updates" def evaluate(self, filter): args = {'filter': filter, 'session': self.session_id} req = urllib.request.Request(self.core_url + '/rest/notebookctrl/evaluate', urllib.parse.urlencode(args).encode('utf8')) conn = self._beaker_url_opener.open(req) result = json.loads(conn.read().decode()) return transformBack(result) def evaluateCode(self, evaluator, code): args = {'evaluator': evaluator, 'code': code, 'session': self.session_id} req = urllib.request.Request(self.core_url + '/rest/notebookctrl/evaluateCode', urllib.parse.urlencode(args).encode('utf8')) conn = self._beaker_url_opener.open(req) result = json.loads(conn.read().decode()) return transformBack(result) def showStatus(self, msg): args = {'msg': msg, 'session': self.session_id} req = urllib.request.Request(self.core_url + '/rest/notebookctrl/showStatus', urllib.parse.urlencode(args).encode('utf8')) conn = self._beaker_url_opener.open(req) result = conn.read() return result == "true" def clearStatus(self, msg): args = {'msg': msg, 'session': self.session_id} req = urllib.request.Request(self.core_url + '/rest/notebookctrl/clearStatus', urllib.parse.urlencode(args).encode('utf8')) conn = self._beaker_url_opener.open(req) result = conn.read() return result == "true" def showTransientStatus(self, msg): args = {'msg': msg, 'session': self.session_id} req = urllib.request.Request(self.core_url + '/rest/notebookctrl/showTransientStatus', urllib.parse.urlencode(args).encode('utf8')) conn = self._beaker_url_opener.open(req) result = conn.read() return result == "true" def getEvaluators(self): req = urllib.request.Request(self.core_url + '/rest/notebookctrl/getEvaluators?' + urllib.parse.urlencode({ 'session': self.session_id})) conn = self._beaker_url_opener.open(req) result = json.loads(conn.read().decode()) return transformBack(result) def getVersion(self): req = urllib.request.Request( self.core_url + '/rest/util/version?' + urllib.parse.urlencode({'session': self.session_id})) conn = self._beaker_url_opener.open(req) return transformBack(conn.read().decode()) def getVersionNumber(self): req = urllib.request.Request( self.core_url + '/rest/util/getVersionInfo?' + urllib.parse.urlencode({'session': self.session_id})) conn = self._beaker_url_opener.open(req) result = json.loads(conn.read().decode()) return transformBack(result['version']) def getCodeCells(self, filter): req = urllib.request.Request(self.core_url + '/rest/notebookctrl/getCodeCells?' + urllib.parse.urlencode({ 'filter': filter})) conn = self._beaker_url_opener.open(req) result = json.loads(conn.read().decode()) return transformBack(result) def setCodeCellBody(self, name, body): args = {'name': name, 'body': body, 'session': self.session_id} req = urllib.request.Request(self.core_url + '/rest/notebookctrl/setCodeCellBody', urllib.parse.urlencode(args).encode('utf8')) conn = self._beaker_url_opener.open(req) result = conn.read() return result == "true" def setCodeCellEvaluator(self, name, evaluator): args = {'name': name, 'evaluator': evaluator, 'session': self.session_id} req = urllib.request.Request(self.core_url + '/rest/notebookctrl/setCodeCellEvaluator', urllib.parse.urlencode(args).encode('utf8')) conn = self._beaker_url_opener.open(req) result = conn.read() return result == "true" def setCodeCellTags(self, name, tags): args = {'name': name, 'tags': tags, 'session': self.session_id} req = urllib.request.Request(self.core_url + '/rest/notebookctrl/setCodeCellTags', urllib.parse.urlencode(args).encode('utf8')) conn = self._beaker_url_opener.open(req) result = conn.read() return result == "true" def runByTag(self, tag): arguments = dict(target_name='beakerx.tag.run') comm = Comm(**arguments) msg = {'runByTag': tag} state = {'state': msg} comm.send(data=state, buffers=[]) def urlArg(self, argName): arguments = dict(target_name='beakerx.geturlarg') comm = Comm(**arguments) state = { 'name': 'URL_ARG', 'arg_name': argName } data = { 'state': state, 'url': self._url, 'type': 'python' } comm.send(data=data, buffers=[]) data = self._queue.get() params = json.loads(data) return params['argValue'] def __setattr__(self, name, value): if 'session_id' == name: self.__dict__['session_id'] = value return if '_comm' == name: self.__dict__['_comm'] = value return if '_url' == name: self.__dict__['_url'] = value return if '_queue' == name: self.__dict__['_queue'] = value return if '_server' == name: self.__dict__['_server'] = value return return self.set(name, value) def __getattr__(self, name): if '_comm' == name: return self.__dict__['_comm'] if '_url' == name: return self.__dict__['_url'] if '_queue' == name: return self.__dict__['_queue'] if '_server' == name: return self.__dict__['_server'] return self.get(name) def __contains__(self, name): return self.isDefined(name) def __delattr__(self, name): return self.unset(name)
class BeakerX: def __init__(self): self._comm = None self._queue = Queue() self._server = BeakerxZMQServer(self._queue) self._url = self._server.url if BeakerXTabledisplay is not None: BeakerXTabledisplay.pandas_display_table() @staticmethod def pandas_display_default(): pandas.DataFrame._ipython_display_ = None @staticmethod def pandas_display_table(): if BeakerXTabledisplay is not None: BeakerXTabledisplay.pandas_display_table() else: html = BeakerxHTML() html.value = 'You need beakerx_tabledisplay to use this' IPython.display.display_html(html) def set4(self, var, val, unset, sync): args = {'name': var, 'sync': sync} if not unset: val = transform(val) args['value'] = json.dumps(val, cls=DataFrameEncoder) state = {'state': args} if self._comm is None: self.init_autotranslation_comm() self._comm.send(data=state) def init_autotranslation_comm(self): self._comm = Comm(target_name='beakerx.autotranslation') self._comm.open() def get(self, var): result = autotranslation_get(var) if result == 'undefined': raise NameError('name \'' + var + '\' is not defined on the beakerx object') return transformBack(json.loads(result)) def set_session(self, id): self.session_id = id def register_output(self): ip = IPython.InteractiveShell.instance() ip.display_formatter.formatters['application/json'] = MyJSONFormatter(parent=ip.display_formatter) def set(self, var, val): autotranslation_update(var, val) return self.set4(var, val, False, True) def unset(self, var): return self.set4(var, None, True, True) def isDefined(self, var): return autotranslation_get(var) != 'undefined' def createOutputContainer(self): return OutputContainer() def showProgressUpdate(self): return "WARNING: python3 language plugin does not support progress updates" def evaluate(self, filter): args = {'filter': filter, 'session': self.session_id} req = urllib.request.Request(self.core_url + '/rest/notebookctrl/evaluate', urllib.parse.urlencode(args).encode('utf8')) conn = self._beaker_url_opener.open(req) result = json.loads(conn.read().decode()) return transformBack(result) def evaluateCode(self, evaluator, code): args = {'evaluator': evaluator, 'code': code, 'session': self.session_id} req = urllib.request.Request(self.core_url + '/rest/notebookctrl/evaluateCode', urllib.parse.urlencode(args).encode('utf8')) conn = self._beaker_url_opener.open(req) result = json.loads(conn.read().decode()) return transformBack(result) def showStatus(self, msg): args = {'msg': msg, 'session': self.session_id} req = urllib.request.Request(self.core_url + '/rest/notebookctrl/showStatus', urllib.parse.urlencode(args).encode('utf8')) conn = self._beaker_url_opener.open(req) result = conn.read() return result == "true" def clearStatus(self, msg): args = {'msg': msg, 'session': self.session_id} req = urllib.request.Request(self.core_url + '/rest/notebookctrl/clearStatus', urllib.parse.urlencode(args).encode('utf8')) conn = self._beaker_url_opener.open(req) result = conn.read() return result == "true" def showTransientStatus(self, msg): args = {'msg': msg, 'session': self.session_id} req = urllib.request.Request(self.core_url + '/rest/notebookctrl/showTransientStatus', urllib.parse.urlencode(args).encode('utf8')) conn = self._beaker_url_opener.open(req) result = conn.read() return result == "true" def getEvaluators(self): req = urllib.request.Request(self.core_url + '/rest/notebookctrl/getEvaluators?' + urllib.parse.urlencode({ 'session': self.session_id})) conn = self._beaker_url_opener.open(req) result = json.loads(conn.read().decode()) return transformBack(result) def getVersion(self): req = urllib.request.Request( self.core_url + '/rest/util/version?' + urllib.parse.urlencode({'session': self.session_id})) conn = self._beaker_url_opener.open(req) return transformBack(conn.read().decode()) def getVersionNumber(self): req = urllib.request.Request( self.core_url + '/rest/util/getVersionInfo?' + urllib.parse.urlencode({'session': self.session_id})) conn = self._beaker_url_opener.open(req) result = json.loads(conn.read().decode()) return transformBack(result['version']) def getCodeCells(self, filter): req = urllib.request.Request(self.core_url + '/rest/notebookctrl/getCodeCells?' + urllib.parse.urlencode({ 'filter': filter})) conn = self._beaker_url_opener.open(req) result = json.loads(conn.read().decode()) return transformBack(result) def setCodeCellBody(self, name, body): args = {'name': name, 'body': body, 'session': self.session_id} req = urllib.request.Request(self.core_url + '/rest/notebookctrl/setCodeCellBody', urllib.parse.urlencode(args).encode('utf8')) conn = self._beaker_url_opener.open(req) result = conn.read() return result == "true" def setCodeCellEvaluator(self, name, evaluator): args = {'name': name, 'evaluator': evaluator, 'session': self.session_id} req = urllib.request.Request(self.core_url + '/rest/notebookctrl/setCodeCellEvaluator', urllib.parse.urlencode(args).encode('utf8')) conn = self._beaker_url_opener.open(req) result = conn.read() return result == "true" def setCodeCellTags(self, name, tags): args = {'name': name, 'tags': tags, 'session': self.session_id} req = urllib.request.Request(self.core_url + '/rest/notebookctrl/setCodeCellTags', urllib.parse.urlencode(args).encode('utf8')) conn = self._beaker_url_opener.open(req) result = conn.read() return result == "true" def runByTag(self, tag): arguments = dict(target_name='beakerx.tag.run') comm = Comm(**arguments) msg = {'runByTag': tag} state = {'state': msg} comm.send(data=state, buffers=[]) def urlArg(self, argName): arguments = dict(target_name='beakerx.geturlarg') comm = Comm(**arguments) state = { 'name': 'URL_ARG', 'arg_name': argName } data = { 'state': state, 'url': self._url, 'type': 'python' } comm.send(data=data, buffers=[]) data = self._queue.get() params = json.loads(data) return params['argValue'] def __setattr__(self, name, value): if 'session_id' == name: self.__dict__['session_id'] = value return if '_comm' == name: self.__dict__['_comm'] = value return if '_url' == name: self.__dict__['_url'] = value return if '_queue' == name: self.__dict__['_queue'] = value return if '_server' == name: self.__dict__['_server'] = value return return self.set(name, value) def __getattr__(self, name): if '_comm' == name: return self.__dict__['_comm'] if '_url' == name: return self.__dict__['_url'] if '_queue' == name: return self.__dict__['_queue'] if '_server' == name: return self.__dict__['_server'] return self.get(name) def __contains__(self, name): return self.isDefined(name) def __delattr__(self, name): return self.unset(name)
class WWTLabApplication(BaseWWTWidget): """ A handle the WWT JupyterLab application. While other parts of pywwt create "widgets", bound to variables running inside Python notebooks, this class represents a connection to the standalone "application", which exists in JupyterLab independently of any one specific notebook. The Python API is the same, it's just that the JSON messages we send are routed to the separate application rather than our own iframe. """ _comm = None _controls = None def __init__(self): _maybe_perpetrate_mega_kernel_hack() self._comm = Comm(target_name='@wwtelescope/jupyterlab:research', data={}) self._comm.on_msg(self._on_comm_message_received) self._comm.open() super(WWTLabApplication, self).__init__() def _on_comm_message_received(self, msg): """ Called when we receive a comms message. NOTE: because this code is run asynchronously in Jupyter's comms architecture, exceptions and printouts don't get reported to the user -- they just disappear. I don't know if there's a "right" way to address that. """ payload = msg['content']['data'] # Special message from the hub indicating app liveness status if payload.get('type') == 'wwt_jupyter_viewer_status': self._on_app_status_change(alive=payload['alive']) # don't return -- maybe someone downstream can use this, and message # processing needs to handle all sorts of unexpected messages anyway self._on_app_message_received(payload) def _actually_send_msg(self, payload): self._comm.send(payload) def _serve_file(self, filename, extension=''): return serve_file(filename, extension=extension) def _create_image_layer(self, **kwargs): """Returns a specialized subclass of ImageLayer that has some extra hooks for creating UI control points. """ return JupyterImageLayer(parent=self, **kwargs) @property def layer_controls(self): if self._controls is None: opacity_slider = widgets.FloatSlider(value=self.foreground_opacity, min=0, max=1, readout=False) foreground_menu = widgets.Dropdown(options=self.available_layers, value=self.foreground) background_menu = widgets.Dropdown(options=self.available_layers, value=self.background) link((opacity_slider, 'value'), (self, 'foreground_opacity')) link((foreground_menu, 'value'), (self, 'foreground')) link((background_menu, 'value'), (self, 'background')) self._controls = widgets.HBox( [background_menu, opacity_slider, foreground_menu]) return self._controls
class Nep: # def __init__(self,comm_name=None): # if comm_name is None: # comm_name=str(uuid.uuid4()) def __init__(self, comm=None, kernel_id=None): # self.comm = Comm(target_name=comm_name) # self.comm = Comm(target_name="neos_comm") print(kernel_id) self.kernel_id = kernel_id if comm is None: self.comm = Comm(target_name="neos_comm") else: self.comm = comm self.comm.open() self.vars = Variables(self.comm, self) self.comm.on_msg(self._on_msg) self.vars_to_update = [] self.var_types = {} self.neos_updates_locked = False self.var_temp_vals = {} def start(self, base='http://localhost:8888', notebook_path='/Untitled.ipynb', auth_token='', ws_port=8766): if self.kernel_id is None: server_process = Process(target=run_server, args=(self.comm.comm_id, base, notebook_path, auth_token, ws_port), daemon=True) else: server_process = Process(target=run_server_from_id, args=(self.comm.comm_id, self.kernel_id, auth_token, ws_port), daemon=True) server_process.start() #guido forgive me coz i know this is ugly static_server_process = Process(target=subprocess.call, args=('python -m http.server 8000', ), kwargs={"shell": True}) static_server_process.start() #TODO: nep.stop() !! def _on_msg(self, msg): #handler for message recived for this Nep #we update the value of the variable msg = msg["content"]["data"] i = msg.index("/") msg_format_correct = (i != -1) if msg_format_correct: varname = msg[:i] if varname in self.vars_to_update: val_str = msg[i + 1:] if self.var_types[varname] == "float": varvalue = float(val_str) elif self.var_types[varname] == "int": varvalue = int(val_str) elif self.var_types[varname] == "float_vec": val_str = val_str[1:-1] varvalue = tuple([float(x) for x in val_str.split(";")]) elif self.var_types[varname] == "int_vec": val_str = val_str[1:-1] varvalue = tuple([int(x) for x in val_str.split(";")]) elif self.var_types[varname] == "list": varvalue = val_str.split("|")[:-1] else: varvalue = val_str if not self.neos_updates_locked: setattr(Variables, "_" + varname, varvalue) else: self.var_temp_vals[varname] = varvalue else: print("Warning: Neos is trying to update variable " + varname + " that is not Nep's vars_to_update") else: print( "Warning: Neos message type not supported (it doesn't have the format varname/varvalue)" ) def _send_var(self, var_name, var_value): var_type = type(var_value) value_str = "" if var_type is str: value_str = var_value elif var_type is tuple: value_str = "[" + ";" + join([str(x) for x in var_value]) + "]" elif var_type is list: value_str = "|" + join([str(x) for x in var_value]) + "|" else: value_str = str(var_value) self.comm.send("updateVar/" + var_name + "/" + value_str) def send(self, var_name, custom_name=None, value=None): var_value = value #IDEA: Maybe put this functionality in another method. send_custom or something! if value is None: frame = inspect.currentframe() locals = frame.f_back.f_locals # local variables from calling scope var_value = locals[var_name] if custom_name is not None: var_name = custom_name self._send_var(var_name, var_value) def bind(self, varname, callback=None, type="float", update_neos=True, update_python=True): prop = property(fset=Variables._generate_set(varname, update_neos, callback), fget=lambda self: Variables.__dict__["_" + varname], fdel=Variables._generate_del(varname, update_neos)) setattr(Variables, "_" + varname, None) setattr(Variables, varname, prop) self.comm.send("addVar/" + varname) if update_python: if varname not in self.vars_to_update: self.vars_to_update.append(varname) self.var_types[varname] = type def plot(self, plt): plt.plot() figname = "img/" + uuid.uuid1().hex + ".png" plt.savefig(figname) self.comm.send("media/" + "http://localhost:8000/" + figname) def listen(self, varname): frame = inspect.currentframe() locals = frame.f_back.f_locals # local variables from calling scope #TODO: this one only upates the local variable when neos changes the variable def lock(self): #freeze updating of variables from Neos, and instead update to a temp storage of variables self.neos_updates_locked = True def unlock(self): #unfreeze the variables from Neos, and update them according to the stored updates self.neos_updates_locked = False for varname in self.var_temp_vals: setattr(Variables, "_" + varname, self.var_temp_vals[varname]) self.var_temp_vals = {} def reactive_loop(self, function, iterable, *args, **kwargs): #TODO: iterate function with iterable, unlocking and locking the self.vars before every iteration. # run iteration in another thread to allow for neos to update the variables between each iteration def loop(): for it in iterable: self.lock() function(it, *args, **kwargs) self.unlock() t = threading.Thread(target=loop) t.start() pass