Last active
August 17, 2019 14:55
-
-
Save psychemedia/ca2d41ea5fcf37d1c6473d4384742021 to your computer and use it in GitHub Desktop.
Attempt at running code from a Python script in a MyBinder remote code execution sandbox
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# A Minimal Python Client for MyBinder\n", | |
"\n", | |
"Some experiments trying to figure out how to convert juniper.js to Python so we can run code in a remote MyBinder code execution sandbox using a minimal Python API...." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"#!pip3 install aiohttp asyncio" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Juniper.js\n", | |
"\n", | |
" - https://github.com/ines/juniper/blob/master/src/index.js\n", | |
" \n", | |
" *Juniper.js* is a minimal javascript client, based on *thebelab.js*, that shows how to:\n", | |
" \n", | |
" - launch a mybinder repo;\n", | |
" - request a kernel;\n", | |
" - run code on the kernel.\n", | |
" \n", | |
" Can we use it as a crib for a minimal Python client for using MyBinder as a simple remote code execution environment?" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Fire Up a MyBinder Repo\n", | |
"\n", | |
"We start a MyBinder repo from a standardised URL:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 87, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"'https://mybinder.org/build/gh/binder-examples/requirements/master'" | |
] | |
}, | |
"execution_count": 87, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"import requests\n", | |
"\n", | |
"url = 'https://mybinder.org'\n", | |
"branch = 'master'\n", | |
"\n", | |
"repo = 'binder-examples/requirements'\n", | |
"\n", | |
"binderURL = '{url}/build/gh/{repo}/{branch}'.format(url=url, repo=repo, branch=branch)\n", | |
"binderURL" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 29, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"#!pip3 install sseclient-py" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"The connection seems to be a streaming one, so let's see if we can fire one up:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 166, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
"/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings\n", | |
" InsecureRequestWarning)\n", | |
"/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings\n", | |
" InsecureRequestWarning)\n" | |
] | |
}, | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"{'imageName': 'gcr.io/binder-prod/r2d-f18835fd-binder-2dexamples-2drequirements-55ab5c:da202b4dd88edf6aef2b5ec516ba5b991806691d',\n", | |
" 'message': 'Found built image, launching...\\n',\n", | |
" 'phase': 'built'}\n", | |
"{'message': 'Launching server...\\n', 'phase': 'launching'}\n", | |
"{'image': 'gcr.io/binder-prod/r2d-f18835fd-binder-2dexamples-2drequirements-55ab5c:da202b4dd88edf6aef2b5ec516ba5b991806691d',\n", | |
" 'message': 'server running at '\n", | |
" 'https://hub.gke.mybinder.org/user/binder-examples-requirements-5jbonbcm/\\n',\n", | |
" 'phase': 'ready',\n", | |
" 'repo_url': 'https://github.com/binder-examples/requirements',\n", | |
" 'token': 'Cdfg0TYrSRe-ZSGrqNcrPA',\n", | |
" 'url': 'https://hub.gke.mybinder.org/user/binder-examples-requirements-5jbonbcm/'}\n" | |
] | |
} | |
], | |
"source": [ | |
"import json\n", | |
"import pprint\n", | |
"import sseclient\n", | |
"\n", | |
"def with_urllib3(url):\n", | |
" \"\"\"Get a streaming response for the given event feed using urllib3.\"\"\"\n", | |
" import urllib3\n", | |
" http = urllib3.PoolManager()\n", | |
" return http.request('GET', url, preload_content=False)\n", | |
"\n", | |
"def with_requests(url):\n", | |
" \"\"\"Get a streaming response for the given event feed using requests.\"\"\"\n", | |
" import requests\n", | |
" return requests.get(url, stream=True)\n", | |
"\n", | |
"\n", | |
"response = with_urllib3(binderURL) # or with_requests(url)\n", | |
"client = sseclient.SSEClient(response)\n", | |
"for event in client.events():\n", | |
" msg = json.loads(event.data)\n", | |
" pprint.pprint(msg)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"So it looks like we can start a MyBinder server running.\n", | |
"\n", | |
"Let's grab the details..." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 167, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"{'phase': 'ready',\n", | |
" 'message': 'server running at https://hub.gke.mybinder.org/user/binder-examples-requirements-5jbonbcm/\\n',\n", | |
" 'image': 'gcr.io/binder-prod/r2d-f18835fd-binder-2dexamples-2drequirements-55ab5c:da202b4dd88edf6aef2b5ec516ba5b991806691d',\n", | |
" 'repo_url': 'https://github.com/binder-examples/requirements',\n", | |
" 'token': 'Cdfg0TYrSRe-ZSGrqNcrPA',\n", | |
" 'url': 'https://hub.gke.mybinder.org/user/binder-examples-requirements-5jbonbcm/'}" | |
] | |
}, | |
"execution_count": 167, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"resp = json.loads(event.data)\n", | |
"resp" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Inspecting the Juniper.js traffic, it looks like good form to create some sort of numerical connection ID, perhaps as a callback identifie?, although in practice it appears to be optional. Let's create one anyway:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 168, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"1897797548" | |
] | |
}, | |
"execution_count": 168, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"#We can generate a rand session ID as a long-ish number\n", | |
"import random\n", | |
"random.getrandbits(32)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Now we can make a request for a kernel:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 169, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"{'id': 'fc4bc8fb-9320-44f6-9702-5c7983ccc403',\n", | |
" 'name': 'python3',\n", | |
" 'last_activity': '2019-08-12T13:16:38.527822Z',\n", | |
" 'execution_state': 'starting',\n", | |
" 'connections': 0}" | |
] | |
}, | |
"execution_count": 169, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"import requests\n", | |
"\n", | |
"randsessionId = random.getrandbits(32)\n", | |
"\n", | |
"r = requests.post('{}api/kernels?{}'.format(resp['url'], randsessionId),\n", | |
" headers={'Authorization': 'token {}'.format(resp['token'])})\n", | |
"r.json()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"The kernel conversation is handled over a websocket. So we need to create a websocket connection" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 170, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"'wss://hub.gke.mybinder.org/user/binder-examples-requirements-5jbonbcm/api/kernels/fc4bc8fb-9320-44f6-9702-5c7983ccc403/channels?token=Cdfg0TYrSRe-ZSGrqNcrPA'" | |
] | |
}, | |
"execution_count": 170, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"wss = 'wss://{}api/kernels/{}/channels?token={}'.format(resp['url'].split('//')[1],\n", | |
" r.json()['id'],\n", | |
" resp['token'])\n", | |
"#Also need &session_id=NNNN; does wss supply that?\n", | |
"wss" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"It looks like we can fire up a websocket client..." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 185, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
"--- request header ---\n", | |
"GET /user/binder-examples-requirements-5jbonbcm/api/kernels/fc4bc8fb-9320-44f6-9702-5c7983ccc403/channels?token=Cdfg0TYrSRe-ZSGrqNcrPA HTTP/1.1\n", | |
"Upgrade: websocket\n", | |
"Connection: Upgrade\n", | |
"Host: hub.gke.mybinder.org\n", | |
"Origin: http://hub.gke.mybinder.org\n", | |
"Sec-WebSocket-Key: tQgOzdv2Uca53euGqV41Cg==\n", | |
"Sec-WebSocket-Version: 13\n", | |
"\n", | |
"\n", | |
"-----------------------\n", | |
"--- response header ---\n", | |
"HTTP/1.1 101 Switching Protocols\n", | |
"Server: nginx/1.13.12\n", | |
"Date: Mon, 12 Aug 2019 13:28:29 GMT\n", | |
"Connection: upgrade\n", | |
"upgrade: websocket\n", | |
"sec-websocket-accept: PtlEdANrqF0AebQU8QgzX6WZ3Ac=\n", | |
"set-cookie: username-hub-gke-mybinder-org=\"2|1:0|10:1565616509|29:username-hub-gke-mybinder-org|44:ZDQyOGZhMmY0OWNkNDk1YzkxZDNjMjg0OTVjMTU3NDk=|a29549d881cb76b3623439d7102d569b9b03f978419f0ab5eccfec27490c7200\"; expires=Wed, 11 Sep 2019 13:28:29 GMT; HttpOnly; Path=/user/binder-examples-requirements-5jbonbcm/; Secure\n", | |
"Strict-Transport-Security: max-age=15724800; includeSubDomains\n", | |
"-----------------------\n" | |
] | |
} | |
], | |
"source": [ | |
"#https://github.com/websocket-client/websocket-client\n", | |
"#!pip3 install websocket_client wsaccel\n", | |
"\n", | |
"import json\n", | |
"import websocket\n", | |
"\n", | |
"ws = websocket.WebSocket()\n", | |
"ws.connect(wss)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 172, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"from uuid import uuid4\n", | |
"\n", | |
"session = str(uuid4())" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 173, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"kernel_info_request = {\n", | |
" 'channel': 'shell',\n", | |
" 'header': {\n", | |
" 'msg_type': 'kernel_info_request',\n", | |
" 'msg_id': str(uuid4()), \n", | |
" 'username': '',\n", | |
" 'session': session,\n", | |
" 'version': \"5.2\"\n", | |
" },\n", | |
" 'parent_header':{},\n", | |
" 'metadata': {},\n", | |
" 'content': {}\n", | |
" }" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 178, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
"send: b'\\x81\\xfe\\x00\\xfe\\xf8\\xfb\\xe8b\\x83\\xd9\\x8b\\n\\x99\\x95\\x86\\x07\\x94\\xd9\\xd2B\\xda\\x88\\x80\\x07\\x94\\x97\\xcaN\\xd8\\xd9\\x80\\x07\\x99\\x9f\\x8d\\x10\\xda\\xc1\\xc8\\x19\\xda\\x96\\x9b\\x05\\xa7\\x8f\\x91\\x12\\x9d\\xd9\\xd2B\\xda\\x90\\x8d\\x10\\x96\\x9e\\x84=\\x91\\x95\\x8e\\r\\xa7\\x89\\x8d\\x13\\x8d\\x9e\\x9b\\x16\\xda\\xd7\\xc8@\\x95\\x88\\x8f=\\x91\\x9f\\xcaX\\xd8\\xd9\\xda\\x07\\xc8\\xc3\\x8e\\x06\\x99\\xcd\\xc5V\\xcf\\x9e\\x8bO\\xcc\\xc9\\x8bS\\xd5\\x99\\xdf\\x00\\xcf\\xd6\\xdbP\\xc1\\xc8\\xd1V\\xc8\\xc3\\xdfP\\x9a\\xc2\\xcaN\\xd8\\xd9\\x9d\\x11\\x9d\\x89\\x86\\x03\\x95\\x9e\\xcaX\\xd8\\xd9\\xcaN\\xd8\\xd9\\x9b\\x07\\x8b\\x88\\x81\\r\\x96\\xd9\\xd2B\\xda\\xcc\\xda\\x00\\x9c\\xc9\\xdaW\\xcf\\xd6\\xd0\\x07\\xcf\\xc2\\xc5V\\xc9\\x9f\\xd8O\\x99\\xcc\\xdd\\x04\\xd5\\x9f\\x8aP\\xcb\\xc2\\xdbR\\x9b\\x9e\\xd1U\\xce\\xd9\\xc4B\\xda\\x8d\\x8d\\x10\\x8b\\x92\\x87\\x0c\\xda\\xc1\\xc8@\\xcd\\xd5\\xda@\\x85\\xd7\\xc8@\\x88\\x9a\\x9a\\x07\\x96\\x8f\\xb7\\n\\x9d\\x9a\\x8c\\x07\\x8a\\xd9\\xd2B\\x83\\x86\\xc4B\\xda\\x96\\x8d\\x16\\x99\\x9f\\x89\\x16\\x99\\xd9\\xd2B\\x83\\x86\\xc4B\\xda\\x98\\x87\\x0c\\x8c\\x9e\\x86\\x16\\xda\\xc1\\xc8\\x19\\x85\\x86'\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"'{\"header\": {\"version\": \"5.3\", \"date\": \"2019-08-12T13:19:04.959124Z\", \"session\": \"9ff46be9-0b5e75f9195cd16d23f9e3d6\", \"username\": \"jovyan\", \"msg_type\": \"status\", \"msg_id\": \"caa8283c-1ab9b0ba4223efdf77a89c6c\"}, \"msg_id\": \"caa8283c-1ab9b0ba4223efdf77a89c6c\", \"msg_type\": \"status\", \"parent_header\": {\"msg_type\": \"kernel_info_request\", \"msg_id\": \"2e08fda6-47ec-42c1-b7b7-3293940872b9\", \"username\": \"\", \"session\": \"72bd2257-8e79-41d0-a75f-db23930ce976\", \"version\": \"5.2\", \"date\": \"2019-08-12T13:19:04.956714Z\"}, \"metadata\": {}, \"content\": {\"execution_state\": \"busy\"}, \"buffers\": [], \"channel\": \"iopub\"}'" | |
] | |
}, | |
"execution_count": 178, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"ws.send( json.dumps(kernel_info_request) )\n", | |
"\n", | |
"ws.recv()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 179, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"'{\"header\": {\"version\": \"5.3\", \"date\": \"2019-08-12T13:19:04.959563Z\", \"session\": \"9ff46be9-0b5e75f9195cd16d23f9e3d6\", \"username\": \"jovyan\", \"msg_type\": \"kernel_info_reply\", \"msg_id\": \"7321f2d2-b6a8d8bb46bfe467287c2df3\"}, \"msg_id\": \"7321f2d2-b6a8d8bb46bfe467287c2df3\", \"msg_type\": \"kernel_info_reply\", \"parent_header\": {\"msg_type\": \"kernel_info_request\", \"msg_id\": \"2e08fda6-47ec-42c1-b7b7-3293940872b9\", \"username\": \"\", \"session\": \"72bd2257-8e79-41d0-a75f-db23930ce976\", \"version\": \"5.2\", \"date\": \"2019-08-12T13:19:04.956714Z\"}, \"metadata\": {}, \"content\": {\"status\": \"ok\", \"protocol_version\": \"5.1\", \"implementation\": \"ipython\", \"implementation_version\": \"7.6.1\", \"language_info\": {\"name\": \"python\", \"version\": \"3.6.7\", \"mimetype\": \"text/x-python\", \"codemirror_mode\": {\"name\": \"ipython\", \"version\": 3}, \"pygments_lexer\": \"ipython3\", \"nbconvert_exporter\": \"python\", \"file_extension\": \".py\"}, \"banner\": \"Python 3.6.7 | packaged by conda-forge | (default, Jul 2 2019, 02:18:42) \\\\nType \\'copyright\\', \\'credits\\' or \\'license\\' for more information\\\\nIPython 7.6.1 -- An enhanced Interactive Python. Type \\'?\\' for help.\\\\n\", \"help_links\": [{\"text\": \"Python Reference\", \"url\": \"https://docs.python.org/3.6\"}, {\"text\": \"IPython Reference\", \"url\": \"https://ipython.org/documentation.html\"}, {\"text\": \"NumPy Reference\", \"url\": \"https://docs.scipy.org/doc/numpy/reference/\"}, {\"text\": \"SciPy Reference\", \"url\": \"https://docs.scipy.org/doc/scipy/reference/\"}, {\"text\": \"Matplotlib Reference\", \"url\": \"https://matplotlib.org/contents.html\"}, {\"text\": \"SymPy Reference\", \"url\": \"http://docs.sympy.org/latest/index.html\"}, {\"text\": \"pandas Reference\", \"url\": \"https://pandas.pydata.org/pandas-docs/stable/\"}]}, \"buffers\": [], \"channel\": \"shell\"}'" | |
] | |
}, | |
"execution_count": 179, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"ws.recv()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 180, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"'{\"header\": {\"version\": \"5.3\", \"date\": \"2019-08-12T13:19:04.960844Z\", \"session\": \"9ff46be9-0b5e75f9195cd16d23f9e3d6\", \"username\": \"jovyan\", \"msg_type\": \"status\", \"msg_id\": \"91c3cba1-d7e85fc5eaaa453097a49d24\"}, \"msg_id\": \"91c3cba1-d7e85fc5eaaa453097a49d24\", \"msg_type\": \"status\", \"parent_header\": {\"msg_type\": \"kernel_info_request\", \"msg_id\": \"2e08fda6-47ec-42c1-b7b7-3293940872b9\", \"username\": \"\", \"session\": \"72bd2257-8e79-41d0-a75f-db23930ce976\", \"version\": \"5.2\", \"date\": \"2019-08-12T13:19:04.956714Z\"}, \"metadata\": {}, \"content\": {\"execution_state\": \"idle\"}, \"buffers\": [], \"channel\": \"iopub\"}'" | |
] | |
}, | |
"execution_count": 180, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"ws.recv()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 187, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
"send: b\"\\x81\\xfe\\x00\\xfee\\xa4\\x1f\\x9d\\x1e\\x86|\\xf5\\x04\\xcaq\\xf8\\t\\x86%\\xbdG\\xd7w\\xf8\\t\\xc8=\\xb1E\\x86w\\xf8\\x04\\xc0z\\xefG\\x9e?\\xe6G\\xc9l\\xfa:\\xd0f\\xed\\x00\\x86%\\xbdG\\xcfz\\xef\\x0b\\xc1s\\xc2\\x0c\\xcay\\xf2:\\xd6z\\xec\\x10\\xc1l\\xe9G\\x88?\\xbf\\x08\\xd7x\\xc2\\x0c\\xc0=\\xa7E\\x86-\\xf8U\\x9cy\\xf9\\x04\\x922\\xa9R\\xc1|\\xb0Q\\x96|\\xacH\\xc6(\\xffR\\x89,\\xaf\\\\\\x97&\\xa9U\\x9c(\\xaf\\x07\\x9d=\\xb1E\\x86j\\xee\\x00\\xd6q\\xfc\\x08\\xc1=\\xa7E\\x86=\\xb1E\\x86l\\xf8\\x16\\xd7v\\xf2\\x0b\\x86%\\xbdG\\x93-\\xff\\x01\\x96-\\xa8R\\x89'\\xf8R\\x9d2\\xa9T\\xc0/\\xb0\\x04\\x93*\\xfbH\\xc0}\\xafV\\x9d,\\xad\\x06\\xc1&\\xaaS\\x863\\xbdG\\xd2z\\xef\\x16\\xcdp\\xf3G\\x9e?\\xbfP\\x8a-\\xbf\\x18\\x88?\\xbf\\x15\\xc5m\\xf8\\x0b\\xd0@\\xf5\\x00\\xc5{\\xf8\\x17\\x86%\\xbd\\x1e\\xd93\\xbdG\\xc9z\\xe9\\x04\\xc0~\\xe9\\x04\\x86%\\xbd\\x1e\\xd93\\xbdG\\xc7p\\xf3\\x11\\xc1q\\xe9G\\x9e?\\xe6\\x18\\xd9\"\n", | |
"send: b'\\x8a\\x80\\xaf4\\xc0\\xe2'\n", | |
"send: b'\\x8a\\x80m\\x01\\x14\\x00'\n" | |
] | |
}, | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"{'header': {'version': '5.3', 'date': '2019-08-12T13:31:06.161132Z', 'session': '9ff46be9-0b5e75f9195cd16d23f9e3d6', 'username': 'jovyan', 'msg_type': 'status', 'msg_id': '0ad839e0-30782ebc6f64fa2d7f19dc30'}, 'msg_id': '0ad839e0-30782ebc6f64fa2d7f19dc30', 'msg_type': 'status', 'parent_header': {'msg_type': 'kernel_info_request', 'msg_id': '2e08fda6-47ec-42c1-b7b7-3293940872b9', 'username': '', 'session': '72bd2257-8e79-41d0-a75f-db23930ce976', 'version': '5.2', 'date': '2019-08-12T13:31:06.158324Z'}, 'metadata': {}, 'content': {'execution_state': 'busy'}, 'buffers': [], 'channel': 'iopub'}\n", | |
"{'header': {'version': '5.3', 'date': '2019-08-12T13:31:06.161587Z', 'session': '9ff46be9-0b5e75f9195cd16d23f9e3d6', 'username': 'jovyan', 'msg_type': 'kernel_info_reply', 'msg_id': '14b159bd-2d437064897587725524068d'}, 'msg_id': '14b159bd-2d437064897587725524068d', 'msg_type': 'kernel_info_reply', 'parent_header': {'msg_type': 'kernel_info_request', 'msg_id': '2e08fda6-47ec-42c1-b7b7-3293940872b9', 'username': '', 'session': '72bd2257-8e79-41d0-a75f-db23930ce976', 'version': '5.2', 'date': '2019-08-12T13:31:06.158324Z'}, 'metadata': {}, 'content': {'status': 'ok', 'protocol_version': '5.1', 'implementation': 'ipython', 'implementation_version': '7.6.1', 'language_info': {'name': 'python', 'version': '3.6.7', 'mimetype': 'text/x-python', 'codemirror_mode': {'name': 'ipython', 'version': 3}, 'pygments_lexer': 'ipython3', 'nbconvert_exporter': 'python', 'file_extension': '.py'}, 'banner': \"Python 3.6.7 | packaged by conda-forge | (default, Jul 2 2019, 02:18:42) \\nType 'copyright', 'credits' or 'license' for more information\\nIPython 7.6.1 -- An enhanced Interactive Python. Type '?' for help.\\n\", 'help_links': [{'text': 'Python Reference', 'url': 'https://docs.python.org/3.6'}, {'text': 'IPython Reference', 'url': 'https://ipython.org/documentation.html'}, {'text': 'NumPy Reference', 'url': 'https://docs.scipy.org/doc/numpy/reference/'}, {'text': 'SciPy Reference', 'url': 'https://docs.scipy.org/doc/scipy/reference/'}, {'text': 'Matplotlib Reference', 'url': 'https://matplotlib.org/contents.html'}, {'text': 'SymPy Reference', 'url': 'http://docs.sympy.org/latest/index.html'}, {'text': 'pandas Reference', 'url': 'https://pandas.pydata.org/pandas-docs/stable/'}]}, 'buffers': [], 'channel': 'shell'}\n", | |
"{'header': {'version': '5.3', 'date': '2019-08-12T13:31:06.162923Z', 'session': '9ff46be9-0b5e75f9195cd16d23f9e3d6', 'username': 'jovyan', 'msg_type': 'status', 'msg_id': '6bb7b2fd-ef6da7c2337e25f958e4505e'}, 'msg_id': '6bb7b2fd-ef6da7c2337e25f958e4505e', 'msg_type': 'status', 'parent_header': {'msg_type': 'kernel_info_request', 'msg_id': '2e08fda6-47ec-42c1-b7b7-3293940872b9', 'username': '', 'session': '72bd2257-8e79-41d0-a75f-db23930ce976', 'version': '5.2', 'date': '2019-08-12T13:31:06.158324Z'}, 'metadata': {}, 'content': {'execution_state': 'idle'}, 'buffers': [], 'channel': 'iopub'}\n" | |
] | |
} | |
], | |
"source": [ | |
"iopub_messages = []\n", | |
"shell_messages = []\n", | |
"\n", | |
"ws.send( json.dumps(kernel_info_request) )\n", | |
"\n", | |
"import time\n", | |
"\n", | |
"\n", | |
"got_execute_reply = False\n", | |
"got_idle_status = False\n", | |
"while not (got_execute_reply and got_idle_status):\n", | |
" time.sleep(1)\n", | |
" msg = json.loads(ws.recv())\n", | |
" print(msg)\n", | |
" if msg['channel'] == 'shell':\n", | |
" shell_messages.append(msg)\n", | |
" # an execute_reply message signifies the computation is done\n", | |
" if msg['header']['msg_type'] == 'kernel_info_reply':\n", | |
" got_execute_reply = True\n", | |
" elif msg['channel'] == 'iopub':\n", | |
" iopub_messages.append(msg)\n", | |
" # the kernel status idle message signifies the kernel is done\n", | |
" if (msg['header']['msg_type'] == 'status' and\n", | |
" msg['content']['execution_state'] == 'idle'):\n", | |
" got_idle_status = True" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 158, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"code = 'print(\"Hello World\")'" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 159, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"execute_request = {\n", | |
" 'channel': 'shell',\n", | |
" 'header': {\n", | |
" 'msg_type': 'execute_request',\n", | |
" 'msg_id': str(uuid4()), \n", | |
" 'username': '', 'session': session,\n", | |
" },\n", | |
" 'parent_header':{},\n", | |
" 'metadata': {},\n", | |
" 'content': {\n", | |
" 'code': code, \n", | |
" 'silent': False,\n", | |
" 'stop_on_error': False,\n", | |
" 'user_expressions': {}, \n", | |
" 'allow_stdin': True,\n", | |
" 'store_history': True,\n", | |
" }\n", | |
" }\n", | |
"\n", | |
"\n", | |
"#code: \"%matplotlib inline↵import numpy as np↵import matplotlib.pyplot as plt↵plt.ion()↵fig, ax = plt.subplots()↵ax.scatter(*np.random.randn(2, 100), c=np.random.randn(100))↵ax.set(title=\"Wow, an interactive plot!\")\"\n", | |
" " | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"ws.send( json.dumps(execute_request) )" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 161, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"'{\"header\": {\"version\": \"5.3\", \"date\": \"2019-08-12T13:01:39.492225Z\", \"session\": \"9c5668e9-d94e3ab740cb5b155db252b0\", \"username\": \"jovyan\", \"msg_type\": \"execute_input\", \"msg_id\": \"99adcdae-86561b987871fd23a25cdc88\"}, \"msg_id\": \"99adcdae-86561b987871fd23a25cdc88\", \"msg_type\": \"execute_input\", \"parent_header\": {\"msg_type\": \"execute_request\", \"msg_id\": \"56b6e765-d54e-4682-a35f-b2947b45cde8\", \"username\": \"\", \"session\": \"2744dbd5-7d72-4bc9-947d-c9c5730ed70a\", \"date\": \"2019-08-12T13:01:39.489574Z\", \"version\": \"5.0\"}, \"metadata\": {}, \"content\": {\"code\": \"print(\\\\\"Hello World\\\\\")\", \"execution_count\": 1}, \"buffers\": [], \"channel\": \"iopub\"}'" | |
] | |
}, | |
"execution_count": 161, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"ws.recv()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 162, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"'{\"header\": {\"version\": \"5.3\", \"date\": \"2019-08-12T13:01:39.495367Z\", \"session\": \"9c5668e9-d94e3ab740cb5b155db252b0\", \"username\": \"jovyan\", \"msg_type\": \"stream\", \"msg_id\": \"3fa93ef1-0c80124e0407ea96537dd12d\"}, \"msg_id\": \"3fa93ef1-0c80124e0407ea96537dd12d\", \"msg_type\": \"stream\", \"parent_header\": {\"msg_type\": \"execute_request\", \"msg_id\": \"56b6e765-d54e-4682-a35f-b2947b45cde8\", \"username\": \"\", \"session\": \"2744dbd5-7d72-4bc9-947d-c9c5730ed70a\", \"date\": \"2019-08-12T13:01:39.489574Z\", \"version\": \"5.0\"}, \"metadata\": {}, \"content\": {\"name\": \"stdout\", \"text\": \"Hello World\\\\n\"}, \"buffers\": [], \"channel\": \"iopub\"}'" | |
] | |
}, | |
"execution_count": 162, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"ws.recv()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 201, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"#https://github.com/sagemath/sagecell/blob/master/contrib/sagecell-client/sagecell-client.py\n", | |
"\"\"\"\n", | |
"A small client illustrating how to interact with the Sage Cell Server, version 2\n", | |
"Requires the websocket-client package: http://pypi.python.org/pypi/websocket-client\n", | |
"\"\"\"\n", | |
"\n", | |
"import websocket\n", | |
"import json\n", | |
"import requests\n", | |
"\n", | |
"\n", | |
"class MyBinderCell(object):\n", | |
"\n", | |
" def __init__(self, binderURL, timeout=10):\n", | |
" response = with_urllib3(binderURL) # or with_requests(url)\n", | |
" client = sseclient.SSEClient(response)\n", | |
" for event in client.events():\n", | |
" #msg = json.loads(event.data)\n", | |
" #pprint.pprint(msg)\n", | |
" pass\n", | |
" \n", | |
" resp = json.loads(event.data)\n", | |
" self._binder = resp\n", | |
" \n", | |
" randsessionId = random.getrandbits(32)\n", | |
"\n", | |
" r = requests.post('{}api/kernels?{}'.format(resp['url'], randsessionId),\n", | |
" headers={'Authorization': 'token {}'.format(resp['token'])})\n", | |
" \n", | |
" wss = 'wss://{}api/kernels/{}/channels?token={}'.format(resp['url'].split('//')[1],\n", | |
" r.json()['id'],\n", | |
" resp['token'])\n", | |
"\n", | |
" self.kernel_url = wss\n", | |
" print(self.kernel_url)\n", | |
" websocket.setdefaulttimeout(timeout)\n", | |
" self._ws = websocket.WebSocket()\n", | |
" self._ws.connect(wss)\n", | |
" # initialize our list of messages\n", | |
" self.shell_messages = []\n", | |
" self.iopub_messages = []\n", | |
"\n", | |
" def _wait_on_response(self, response):\n", | |
" # Wait until we get both a kernel status idle message and an execute_reply message\n", | |
" got_execute_reply = False\n", | |
" got_idle_status = False\n", | |
" while not (got_execute_reply and got_idle_status):\n", | |
" msg = json.loads(self._ws.recv())\n", | |
" if msg['channel'] == 'shell':\n", | |
" self.shell_messages.append(msg)\n", | |
" # an execute_reply message signifies the computation is done\n", | |
" if msg['header']['msg_type'] == response:\n", | |
" got_execute_reply = True\n", | |
" elif msg['channel'] == 'iopub':\n", | |
" self.iopub_messages.append(msg)\n", | |
" # the kernel status idle message signifies the kernel is done\n", | |
" if (msg['header']['msg_type'] == 'status' and\n", | |
" msg['content']['execution_state'] == 'idle'):\n", | |
" got_idle_status = True\n", | |
"\n", | |
" return {'shell': self.shell_messages, 'iopub': self.iopub_messages}\n", | |
"\n", | |
" def execute_request(self, code):\n", | |
" # zero out our list of messages, in case this is not the first request\n", | |
" self.shell_messages = []\n", | |
" self.iopub_messages = []\n", | |
"\n", | |
" # Send the JSON execute_request message string down the shell channel\n", | |
" msg = self._make_execute_request(code)\n", | |
" self._ws.send(msg)\n", | |
" return self._wait_on_response('execute_reply')\n", | |
" \n", | |
" def _make_execute_request(self, code):\n", | |
" from uuid import uuid4\n", | |
" session = str(uuid4())\n", | |
"\n", | |
" # Here is the general form for an execute_request message\n", | |
" execute_request = {\n", | |
" 'channel': 'shell',\n", | |
" 'header': {\n", | |
" 'msg_type': 'execute_request',\n", | |
" 'msg_id': str(uuid4()), \n", | |
" 'username': '', 'session': session,\n", | |
" },\n", | |
" 'parent_header':{},\n", | |
" 'metadata': {},\n", | |
" 'content': {\n", | |
" 'code': code, \n", | |
" 'silent': False,\n", | |
" 'stop_on_error': False,\n", | |
" 'user_expressions': {}, \n", | |
" 'allow_stdin': True,\n", | |
" 'store_history': True,\n", | |
" }\n", | |
" }\n", | |
" return json.dumps(execute_request)\n", | |
"\n", | |
" def _make_kernel_info_request(self):\n", | |
" kernel_info_request = {\n", | |
" 'channel': 'shell',\n", | |
" 'header': {\n", | |
" 'msg_type': 'kernel_info_request',\n", | |
" 'msg_id': str(uuid4()), \n", | |
" 'username': '',\n", | |
" 'session': session,\n", | |
" 'version': \"5.2\"\n", | |
" },\n", | |
" 'parent_header':{},\n", | |
" 'metadata': {},\n", | |
" 'content': {}\n", | |
" }\n", | |
" return json.dumps(kernel_info_request)\n", | |
" \n", | |
" def kernel_info__request(self):\n", | |
" # zero out our list of messages, in case this is not the first request\n", | |
" self.shell_messages = []\n", | |
" self.iopub_messages = []\n", | |
"\n", | |
" # Send the JSON execute_request message string down the shell channel\n", | |
" msg = self._make_kernel_info_request()\n", | |
" self._ws.send(msg)\n", | |
" return self._wait_on_response('kernel_info_reply')\n", | |
" \n", | |
" def close(self):\n", | |
" # If we define this, we can use the closing() context manager to automatically close the channels\n", | |
" self._ws.close()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 202, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
"/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings\n", | |
" InsecureRequestWarning)\n", | |
"/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py:857: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings\n", | |
" InsecureRequestWarning)\n" | |
] | |
}, | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"wss://hub.gke.mybinder.org/user/binder-examples-requirements-5xthjxjt/api/kernels/77345c0b-14ed-4724-bc01-bc745512a038/channels?token=p9rVYouBR5eAMJ5LzsX86w\n" | |
] | |
}, | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
"--- request header ---\n", | |
"GET /user/binder-examples-requirements-5xthjxjt/api/kernels/77345c0b-14ed-4724-bc01-bc745512a038/channels?token=p9rVYouBR5eAMJ5LzsX86w HTTP/1.1\n", | |
"Upgrade: websocket\n", | |
"Connection: Upgrade\n", | |
"Host: hub.gke.mybinder.org\n", | |
"Origin: http://hub.gke.mybinder.org\n", | |
"Sec-WebSocket-Key: l24dihI38SVrRDbkz1icvQ==\n", | |
"Sec-WebSocket-Version: 13\n", | |
"\n", | |
"\n", | |
"-----------------------\n", | |
"--- response header ---\n", | |
"HTTP/1.1 101 Switching Protocols\n", | |
"Server: nginx/1.13.12\n", | |
"Date: Mon, 12 Aug 2019 13:48:57 GMT\n", | |
"Connection: upgrade\n", | |
"upgrade: websocket\n", | |
"sec-websocket-accept: veILnARiJVSZUR5MMg5ebknw5UE=\n", | |
"set-cookie: username-hub-gke-mybinder-org=\"2|1:0|10:1565617737|29:username-hub-gke-mybinder-org|44:NjU5NzAxYzgxYmVkNDhiNzlmNDUyMTNhZTgyZTQxY2Y=|1c3e9a2721b0726fbb7edd7c8369ffb1f980de54f94e5125f88b001371c75583\"; expires=Wed, 11 Sep 2019 13:48:57 GMT; HttpOnly; Path=/user/binder-examples-requirements-5xthjxjt/; Secure\n", | |
"Strict-Transport-Security: max-age=15724800; includeSubDomains\n", | |
"-----------------------\n" | |
] | |
} | |
], | |
"source": [ | |
"b = MyBinderCell(binderURL)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 203, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"{'phase': 'ready',\n", | |
" 'message': 'server running at https://hub.gke.mybinder.org/user/binder-examples-requirements-5xthjxjt/\\n',\n", | |
" 'image': 'gcr.io/binder-prod/r2d-f18835fd-binder-2dexamples-2drequirements-55ab5c:da202b4dd88edf6aef2b5ec516ba5b991806691d',\n", | |
" 'repo_url': 'https://github.com/binder-examples/requirements',\n", | |
" 'token': 'p9rVYouBR5eAMJ5LzsX86w',\n", | |
" 'url': 'https://hub.gke.mybinder.org/user/binder-examples-requirements-5xthjxjt/'}" | |
] | |
}, | |
"execution_count": 203, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"b._binder" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 204, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
"send: b'\\x81\\xfe\\x00\\xfe,;9\\xebW\\x19Z\\x83MUW\\x8e@\\x19\\x03\\xcb\\x0eHQ\\x8e@W\\x1b\\xc7\\x0c\\x19Q\\x8eM_\\\\\\x99\\x0e\\x01\\x19\\x90\\x0eVJ\\x8csO@\\x9bI\\x19\\x03\\xcb\\x0eP\\\\\\x99B^U\\xb4EU_\\x84sI\\\\\\x9aY^J\\x9f\\x0e\\x17\\x19\\xc9AH^\\xb4E_\\x1b\\xd1\\x0c\\x19X\\xdb\\x14\\t\\r\\x8eH\\x0e\\x14\\x88\\x18ZX\\xc6\\x18XX\\xd3\\x01\\x03_\\xdd\\x1b\\x16\\\\\\xd3\\x1b\\x08[\\x8eH\\x0b]\\x89\\x1f\\t\\x1b\\xc7\\x0c\\x19L\\x98IIW\\x8aA^\\x1b\\xd1\\x0c\\x19\\x1b\\xc7\\x0c\\x19J\\x8e_HP\\x84B\\x19\\x03\\xcb\\x0e\\x0c\\x0b\\x89H\\t\\x0b\\xde\\x1b\\x16\\x01\\x8e\\x1b\\x02\\x14\\xdf\\x1d_\\t\\xc6M\\x0c\\x0c\\x8d\\x01_[\\xd9\\x1f\\x02\\n\\xdbO^\\x00\\xdc\\x1a\\x19\\x15\\xcb\\x0eM\\\\\\x99_RV\\x85\\x0e\\x01\\x19\\xc9\\x19\\x15\\x0b\\xc9Q\\x17\\x19\\xc9\\\\ZK\\x8eBOf\\x83IZ]\\x8e^\\x19\\x03\\xcbWF\\x15\\xcb\\x0eV\\\\\\x9fM_X\\x9fM\\x19\\x03\\xcbWF\\x15\\xcb\\x0eXV\\x85X^W\\x9f\\x0e\\x01\\x19\\x90QF'\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"{'shell': [{'header': {'version': '5.3',\n", | |
" 'date': '2019-08-12T13:48:58.055802Z',\n", | |
" 'session': '627c3889-70a3d665f8c21b2b6f562930',\n", | |
" 'username': 'jovyan',\n", | |
" 'msg_type': 'kernel_info_reply',\n", | |
" 'msg_id': 'a98648d4-98374863867dedd1905886c4'},\n", | |
" 'msg_id': 'a98648d4-98374863867dedd1905886c4',\n", | |
" 'msg_type': 'kernel_info_reply',\n", | |
" 'parent_header': {'msg_type': 'kernel_info_request',\n", | |
" 'msg_id': 'a0824ed5-c4aa-4ca8-8f67-e873bed0db32',\n", | |
" 'username': '',\n", | |
" 'session': '72bd2257-8e79-41d0-a75f-db23930ce976',\n", | |
" 'version': '5.2',\n", | |
" 'date': '2019-08-12T13:48:58.053317Z'},\n", | |
" 'metadata': {},\n", | |
" 'content': {'status': 'ok',\n", | |
" 'protocol_version': '5.1',\n", | |
" 'implementation': 'ipython',\n", | |
" 'implementation_version': '7.6.1',\n", | |
" 'language_info': {'name': 'python',\n", | |
" 'version': '3.6.7',\n", | |
" 'mimetype': 'text/x-python',\n", | |
" 'codemirror_mode': {'name': 'ipython', 'version': 3},\n", | |
" 'pygments_lexer': 'ipython3',\n", | |
" 'nbconvert_exporter': 'python',\n", | |
" 'file_extension': '.py'},\n", | |
" 'banner': \"Python 3.6.7 | packaged by conda-forge | (default, Jul 2 2019, 02:18:42) \\nType 'copyright', 'credits' or 'license' for more information\\nIPython 7.6.1 -- An enhanced Interactive Python. Type '?' for help.\\n\",\n", | |
" 'help_links': [{'text': 'Python Reference',\n", | |
" 'url': 'https://docs.python.org/3.6'},\n", | |
" {'text': 'IPython Reference',\n", | |
" 'url': 'https://ipython.org/documentation.html'},\n", | |
" {'text': 'NumPy Reference',\n", | |
" 'url': 'https://docs.scipy.org/doc/numpy/reference/'},\n", | |
" {'text': 'SciPy Reference',\n", | |
" 'url': 'https://docs.scipy.org/doc/scipy/reference/'},\n", | |
" {'text': 'Matplotlib Reference',\n", | |
" 'url': 'https://matplotlib.org/contents.html'},\n", | |
" {'text': 'SymPy Reference',\n", | |
" 'url': 'http://docs.sympy.org/latest/index.html'},\n", | |
" {'text': 'pandas Reference',\n", | |
" 'url': 'https://pandas.pydata.org/pandas-docs/stable/'}]},\n", | |
" 'buffers': [],\n", | |
" 'channel': 'shell'}],\n", | |
" 'iopub': [{'header': {'version': '5.3',\n", | |
" 'date': '2019-08-12T13:48:58.055436Z',\n", | |
" 'session': '627c3889-70a3d665f8c21b2b6f562930',\n", | |
" 'username': 'jovyan',\n", | |
" 'msg_type': 'status',\n", | |
" 'msg_id': 'f96c5abe-8e009f5c6284005859bac6f0'},\n", | |
" 'msg_id': 'f96c5abe-8e009f5c6284005859bac6f0',\n", | |
" 'msg_type': 'status',\n", | |
" 'parent_header': {'msg_type': 'kernel_info_request',\n", | |
" 'msg_id': 'a0824ed5-c4aa-4ca8-8f67-e873bed0db32',\n", | |
" 'username': '',\n", | |
" 'session': '72bd2257-8e79-41d0-a75f-db23930ce976',\n", | |
" 'version': '5.2',\n", | |
" 'date': '2019-08-12T13:48:58.053317Z'},\n", | |
" 'metadata': {},\n", | |
" 'content': {'execution_state': 'busy'},\n", | |
" 'buffers': [],\n", | |
" 'channel': 'iopub'},\n", | |
" {'header': {'version': '5.3',\n", | |
" 'date': '2019-08-12T13:48:58.056936Z',\n", | |
" 'session': '627c3889-70a3d665f8c21b2b6f562930',\n", | |
" 'username': 'jovyan',\n", | |
" 'msg_type': 'status',\n", | |
" 'msg_id': 'e4559151-bb5a502ccd6857921124d010'},\n", | |
" 'msg_id': 'e4559151-bb5a502ccd6857921124d010',\n", | |
" 'msg_type': 'status',\n", | |
" 'parent_header': {'msg_type': 'kernel_info_request',\n", | |
" 'msg_id': 'a0824ed5-c4aa-4ca8-8f67-e873bed0db32',\n", | |
" 'username': '',\n", | |
" 'session': '72bd2257-8e79-41d0-a75f-db23930ce976',\n", | |
" 'version': '5.2',\n", | |
" 'date': '2019-08-12T13:48:58.053317Z'},\n", | |
" 'metadata': {},\n", | |
" 'content': {'execution_state': 'idle'},\n", | |
" 'buffers': [],\n", | |
" 'channel': 'iopub'}]}" | |
] | |
}, | |
"execution_count": 204, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"b.kernel_info__request()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 205, | |
"metadata": { | |
"scrolled": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stderr", | |
"output_type": "stream", | |
"text": [ | |
"send: b'\\x81\\xfe\\x01s\\xd9\\xb0P\\x97\\xa2\\x923\\xff\\xb8\\xde>\\xf2\\xb5\\x92j\\xb7\\xfb\\xc38\\xf2\\xb5\\xdcr\\xbb\\xf9\\x928\\xf2\\xb8\\xd45\\xe5\\xfb\\x8ap\\xec\\xfb\\xdd#\\xf0\\x86\\xc4)\\xe7\\xbc\\x92j\\xb7\\xfb\\xd5(\\xf2\\xba\\xc5$\\xf2\\x86\\xc25\\xe6\\xac\\xd5#\\xe3\\xfb\\x9cp\\xb5\\xb4\\xc37\\xc8\\xb0\\xd4r\\xad\\xf9\\x92d\\xa1\\xbc\\x83b\\xaf\\xe1\\xd3}\\xa5\\xe0\\x884\\xba\\xed\\xd5f\\xf3\\xf4\\xd2e\\xf2\\xe9\\x9dg\\xa5\\xe8\\xd66\\xa2\\xbf\\x895\\xf4\\xbd\\xd5r\\xbb\\xf9\\x92%\\xe4\\xbc\\xc2>\\xf6\\xb4\\xd5r\\xad\\xf9\\x92r\\xbb\\xf9\\x92#\\xf2\\xaa\\xc39\\xf8\\xb7\\x92j\\xb7\\xfb\\x84b\\xf6\\xbb\\x83g\\xf6\\xef\\x9d`\\xf1\\xbb\\x85}\\xa3\\xe1\\x83f\\xba\\xbb\\x87h\\xf5\\xf4\\xd25\\xf6\\xe0\\x81c\\xf3\\xb8\\xd1f\\xf2\\xec\\x92-\\xbb\\xf9\\x92 \\xf6\\xab\\xd5>\\xe3\\x86\\xd85\\xf6\\xbd\\xd5\"\\xb5\\xe3\\x90+\\xea\\xf5\\x90r\\xfa\\xbc\\xc41\\xf3\\xb8\\xc41\\xb5\\xe3\\x90+\\xea\\xf5\\x90r\\xf4\\xb6\\xde$\\xf2\\xb7\\xc4r\\xad\\xf9\\xcbr\\xf4\\xb6\\xd45\\xb5\\xe3\\x90r\\xe7\\xab\\xd9>\\xe3\\xf1\\x978\\xf2\\xb5\\xdc?\\xb7\\xae\\xdf\"\\xfb\\xbd\\x97y\\xb5\\xf5\\x90r\\xe4\\xb0\\xdc5\\xf9\\xad\\x92j\\xb7\\xbf\\xd1<\\xe4\\xbc\\x9cp\\xb5\\xaa\\xc4?\\xe7\\x86\\xdf>\\xc8\\xbc\\xc2\"\\xf8\\xab\\x92j\\xb7\\xbf\\xd1<\\xe4\\xbc\\x9cp\\xb5\\xac\\xc35\\xe5\\x86\\xd5(\\xe7\\xab\\xd5#\\xe4\\xb0\\xdf>\\xe4\\xfb\\x8ap\\xec\\xa4\\x9cp\\xb5\\xb8\\xdc<\\xf8\\xae\\xef#\\xe3\\xbd\\xd9>\\xb5\\xe3\\x90$\\xe5\\xac\\xd5|\\xb7\\xfb\\xc3$\\xf8\\xab\\xd5\\x0f\\xff\\xb0\\xc3$\\xf8\\xab\\xc9r\\xad\\xf9\\xc4\"\\xe2\\xbc\\xcd-'\n" | |
] | |
}, | |
{ | |
"data": { | |
"text/plain": [ | |
"{'shell': [{'header': {'version': '5.3',\n", | |
" 'date': '2019-08-12T13:48:58.188788Z',\n", | |
" 'session': '627c3889-70a3d665f8c21b2b6f562930',\n", | |
" 'username': 'jovyan',\n", | |
" 'msg_type': 'execute_reply',\n", | |
" 'msg_id': '703e9049-9c5ffd94196cf9d9b94fc207'},\n", | |
" 'msg_id': '703e9049-9c5ffd94196cf9d9b94fc207',\n", | |
" 'msg_type': 'execute_reply',\n", | |
" 'parent_header': {'msg_type': 'execute_request',\n", | |
" 'msg_id': '46e3288c-298d-4e6d-b5e0-721ff5f9ecde',\n", | |
" 'username': '',\n", | |
" 'session': '42ab37a6-0fb5-4836-b78b-bea913daa6e5',\n", | |
" 'date': '2019-08-12T13:48:58.178891Z',\n", | |
" 'version': '5.0'},\n", | |
" 'metadata': {'started': '2019-08-12T13:48:58.182227Z',\n", | |
" 'dependencies_met': True,\n", | |
" 'engine': '2b4176b6-91dc-4b5f-8767-4c980d2f70a6',\n", | |
" 'status': 'ok'},\n", | |
" 'content': {'status': 'ok',\n", | |
" 'execution_count': 1,\n", | |
" 'user_expressions': {},\n", | |
" 'payload': []},\n", | |
" 'buffers': [],\n", | |
" 'channel': 'shell'}],\n", | |
" 'iopub': [{'header': {'version': '5.3',\n", | |
" 'date': '2019-08-12T13:48:58.181493Z',\n", | |
" 'session': '627c3889-70a3d665f8c21b2b6f562930',\n", | |
" 'username': 'jovyan',\n", | |
" 'msg_type': 'status',\n", | |
" 'msg_id': '725c49f1-d48ffd8dc52703a49e91d781'},\n", | |
" 'msg_id': '725c49f1-d48ffd8dc52703a49e91d781',\n", | |
" 'msg_type': 'status',\n", | |
" 'parent_header': {'msg_type': 'execute_request',\n", | |
" 'msg_id': '46e3288c-298d-4e6d-b5e0-721ff5f9ecde',\n", | |
" 'username': '',\n", | |
" 'session': '42ab37a6-0fb5-4836-b78b-bea913daa6e5',\n", | |
" 'date': '2019-08-12T13:48:58.178891Z',\n", | |
" 'version': '5.0'},\n", | |
" 'metadata': {},\n", | |
" 'content': {'execution_state': 'busy'},\n", | |
" 'buffers': [],\n", | |
" 'channel': 'iopub'},\n", | |
" {'header': {'version': '5.3',\n", | |
" 'date': '2019-08-12T13:48:58.182312Z',\n", | |
" 'session': '627c3889-70a3d665f8c21b2b6f562930',\n", | |
" 'username': 'jovyan',\n", | |
" 'msg_type': 'execute_input',\n", | |
" 'msg_id': '0dd15980-9bfabc31fbbafc8e2c21a3ec'},\n", | |
" 'msg_id': '0dd15980-9bfabc31fbbafc8e2c21a3ec',\n", | |
" 'msg_type': 'execute_input',\n", | |
" 'parent_header': {'msg_type': 'execute_request',\n", | |
" 'msg_id': '46e3288c-298d-4e6d-b5e0-721ff5f9ecde',\n", | |
" 'username': '',\n", | |
" 'session': '42ab37a6-0fb5-4836-b78b-bea913daa6e5',\n", | |
" 'date': '2019-08-12T13:48:58.178891Z',\n", | |
" 'version': '5.0'},\n", | |
" 'metadata': {},\n", | |
" 'content': {'code': \"print('hello world')\", 'execution_count': 1},\n", | |
" 'buffers': [],\n", | |
" 'channel': 'iopub'},\n", | |
" {'header': {'version': '5.3',\n", | |
" 'date': '2019-08-12T13:48:58.186739Z',\n", | |
" 'session': '627c3889-70a3d665f8c21b2b6f562930',\n", | |
" 'username': 'jovyan',\n", | |
" 'msg_type': 'stream',\n", | |
" 'msg_id': '227dee1b-1edf0b620656881b9e29db50'},\n", | |
" 'msg_id': '227dee1b-1edf0b620656881b9e29db50',\n", | |
" 'msg_type': 'stream',\n", | |
" 'parent_header': {'msg_type': 'execute_request',\n", | |
" 'msg_id': '46e3288c-298d-4e6d-b5e0-721ff5f9ecde',\n", | |
" 'username': '',\n", | |
" 'session': '42ab37a6-0fb5-4836-b78b-bea913daa6e5',\n", | |
" 'date': '2019-08-12T13:48:58.178891Z',\n", | |
" 'version': '5.0'},\n", | |
" 'metadata': {},\n", | |
" 'content': {'name': 'stdout', 'text': 'hello world\\n'},\n", | |
" 'buffers': [],\n", | |
" 'channel': 'iopub'},\n", | |
" {'header': {'version': '5.3',\n", | |
" 'date': '2019-08-12T13:48:58.189964Z',\n", | |
" 'session': '627c3889-70a3d665f8c21b2b6f562930',\n", | |
" 'username': 'jovyan',\n", | |
" 'msg_type': 'status',\n", | |
" 'msg_id': '6cac0e2b-a946d941f3dfc1545cc5f419'},\n", | |
" 'msg_id': '6cac0e2b-a946d941f3dfc1545cc5f419',\n", | |
" 'msg_type': 'status',\n", | |
" 'parent_header': {'msg_type': 'execute_request',\n", | |
" 'msg_id': '46e3288c-298d-4e6d-b5e0-721ff5f9ecde',\n", | |
" 'username': '',\n", | |
" 'session': '42ab37a6-0fb5-4836-b78b-bea913daa6e5',\n", | |
" 'date': '2019-08-12T13:48:58.178891Z',\n", | |
" 'version': '5.0'},\n", | |
" 'metadata': {},\n", | |
" 'content': {'execution_state': 'idle'},\n", | |
" 'buffers': [],\n", | |
" 'channel': 'iopub'}]}" | |
] | |
}, | |
"execution_count": 205, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"b.execute_request(\"print('hello world')\")" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"gist": { | |
"data": { | |
"description": "Attempt at running code from a Python script in a MyBinder remote code execution sandbox", | |
"public": true | |
}, | |
"id": "" | |
}, | |
"kernelspec": { | |
"display_name": "Python 3", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.7.3" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment