Skip to content

Instantly share code, notes, and snippets.

@psychemedia
Last active August 17, 2019 14:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save psychemedia/ca2d41ea5fcf37d1c6473d4384742021 to your computer and use it in GitHub Desktop.
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
Display the source blob
Display the rendered blob
Raw
{
"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