Skip to content

Instantly share code, notes, and snippets.

@jarnaldich
Last active January 29, 2023 08:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jarnaldich/6418a53b50568a2b201bf592d854c0df to your computer and use it in GitHub Desktop.
Save jarnaldich/6418a53b50568a2b201bf592d854c0df to your computer and use it in GitHub Desktop.
[JSONP Helper] in JupyterLite #cors #jupyterlite #python #javascript
Display the source blob
Display the rendered blob
Raw
{
"metadata": {
"language_info": {
"codemirror_mode": {
"name": "python",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8"
},
"kernelspec": {
"name": "python",
"display_name": "Python (Pyodide)",
"language": "python"
}
},
"nbformat_minor": 4,
"nbformat": 4,
"cells": [
{
"cell_type": "code",
"source": "import pandas as pd\nimport json",
"metadata": {
"tags": [],
"trusted": true
},
"execution_count": 1,
"outputs": []
},
{
"cell_type": "code",
"source": "%%javascript\nwindow.saveJSONP = async (urlString, file_path, mime_type='text/json', binary=false) => {\n const sc = document.createElement('script');\n var url = new URL(urlString);\n url.searchParams.append('callback', 'window.corsCallBack');\n \n sc.src = url.toString();\n\n window.corsCallBack = async (data) => {\n console.log(data);\n\n // Open (or create) the file storage\n var open = indexedDB.open('JupyterLite Storage');\n\n // Create the schema\n open.onupgradeneeded = function() {\n throw Error('Error opening IndexedDB. Should not ever need to upgrade JupyterLite Storage Schema');\n };\n\n open.onsuccess = function() {\n // Start a new transaction\n var db = open.result;\n var tx = db.transaction(\"files\", \"readwrite\");\n var store = tx.objectStore(\"files\");\n\n var now = new Date();\n\n var value = {\n 'name': file_path.split(/[\\\\/]/).pop(),\n 'path': file_path,\n 'format': binary ? 'binary' : 'text',\n 'created': now.toISOString(),\n 'last_modified': now.toISOString(),\n 'content': JSON.stringify(data),\n 'mimetype': mime_type,\n 'type': 'file',\n 'writable': true\n }; \n\n const countRequest = store.count(file_path);\n countRequest.onsuccess = () => {\n console.log(countRequest.result);\n if(countRequest.result > 0) {\n store.put(value, file_path);\n } else {\n store.add(value, file_path);\n } \n }; \n\n // Close the db when the transaction is done\n tx.oncomplete = function() {\n db.close();\n };\n }\n }\n\n document.getElementsByTagName('head')[0].appendChild(sc);\n}\n",
"metadata": {
"tags": [],
"trusted": true
},
"execution_count": 2,
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": "<IPython.core.display.Javascript object>",
"application/javascript": "window.saveJSONP = async (urlString, file_path, mime_type='text/json', binary=false) => {\n const sc = document.createElement('script');\n var url = new URL(urlString);\n url.searchParams.append('callback', 'window.corsCallBack');\n \n sc.src = url.toString();\n\n window.corsCallBack = async (data) => {\n console.log(data);\n\n // Open (or create) the file storage\n var open = indexedDB.open('JupyterLite Storage');\n\n // Create the schema\n open.onupgradeneeded = function() {\n throw Error('Error opening IndexedDB. Should not ever need to upgrade JupyterLite Storage Schema');\n };\n\n open.onsuccess = function() {\n // Start a new transaction\n var db = open.result;\n var tx = db.transaction(\"files\", \"readwrite\");\n var store = tx.objectStore(\"files\");\n\n var now = new Date();\n\n var value = {\n 'name': file_path.split(/[\\\\/]/).pop(),\n 'path': file_path,\n 'format': binary ? 'binary' : 'text',\n 'created': now.toISOString(),\n 'last_modified': now.toISOString(),\n 'content': JSON.stringify(data),\n 'mimetype': mime_type,\n 'type': 'file',\n 'writable': true\n }; \n\n const countRequest = store.count(file_path);\n countRequest.onsuccess = () => {\n console.log(countRequest.result);\n if(countRequest.result > 0) {\n store.put(value, file_path);\n } else {\n store.add(value, file_path);\n } \n }; \n\n // Close the db when the transaction is done\n tx.oncomplete = function() {\n db.close();\n };\n }\n }\n\n document.getElementsByTagName('head')[0].appendChild(sc);\n}\n"
},
"metadata": {}
}
]
},
{
"cell_type": "code",
"source": "from js import fetch\n\nWORKS = \"https://raw.githubusercontent.com/jupyterlite/jupyterlite/main/examples/data/iris.csv\"\nWORKS_CORS_ENABLED = \"https://data.wa.gov/api/views/f6w7-q2d2/rows.csv?accessType=DOWNLOAD\"\nFAILS_CORS_DISABLED = \"https://opendata-ajuntament.barcelona.cat/data/dataset/1121f3e2-bfb1-4dc4-9f39-1c5d1d72cba1/resource/69ae574f-adfc-4660-8f81-73103de169ff/download/2018_menors.csv\"\n\nres = await fetch(FAILS_CORS_DISABLED) # Change it to see what happend\ntext = await res.text()\nprint(text)",
"metadata": {
"tags": [],
"collapsed": true,
"jupyter": {
"outputs_hidden": true
}
},
"execution_count": null,
"outputs": [
{
"ename": "<class 'pyodide.JsException'>",
"evalue": "TypeError: Failed to fetch",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mJsException\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn[3], line 7\u001b[0m\n\u001b[1;32m 4\u001b[0m WORKS_CORS_ENABLED \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhttps://data.wa.gov/api/views/f6w7-q2d2/rows.csv?accessType=DOWNLOAD\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 5\u001b[0m FAILS_CORS_DISABLED \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhttps://opendata-ajuntament.barcelona.cat/data/dataset/1121f3e2-bfb1-4dc4-9f39-1c5d1d72cba1/resource/69ae574f-adfc-4660-8f81-73103de169ff/download/2018_menors.csv\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m----> 7\u001b[0m res \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mawait\u001b[39;00m fetch(FAILS_CORS_DISABLED) \u001b[38;5;66;03m# Change it to see what happend\u001b[39;00m\n\u001b[1;32m 8\u001b[0m text \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mawait\u001b[39;00m res\u001b[38;5;241m.\u001b[39mtext()\n\u001b[1;32m 9\u001b[0m \u001b[38;5;28mprint\u001b[39m(text)\n",
"File \u001b[0;32m/lib/python3.10/asyncio/futures.py:284\u001b[0m, in \u001b[0;36mFuture.__await__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 282\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdone():\n\u001b[1;32m 283\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_asyncio_future_blocking \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[0;32m--> 284\u001b[0m \u001b[38;5;28;01myield\u001b[39;00m \u001b[38;5;28mself\u001b[39m \u001b[38;5;66;03m# This tells Task to wait for completion.\u001b[39;00m\n\u001b[1;32m 285\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdone():\n\u001b[1;32m 286\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mawait wasn\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mt used with future\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n",
"File \u001b[0;32m/lib/python3.10/asyncio/tasks.py:304\u001b[0m, in \u001b[0;36mTask.__wakeup\u001b[0;34m(self, future)\u001b[0m\n\u001b[1;32m 302\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__wakeup\u001b[39m(\u001b[38;5;28mself\u001b[39m, future):\n\u001b[1;32m 303\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 304\u001b[0m \u001b[43mfuture\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mresult\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 305\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mBaseException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m exc:\n\u001b[1;32m 306\u001b[0m \u001b[38;5;66;03m# This may also be a cancellation.\u001b[39;00m\n\u001b[1;32m 307\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m__step(exc)\n",
"File \u001b[0;32m/lib/python3.10/asyncio/futures.py:201\u001b[0m, in \u001b[0;36mFuture.result\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 199\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m__log_traceback \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[1;32m 200\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_exception \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m--> 201\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_exception\n\u001b[1;32m 202\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_result\n",
"\u001b[0;31mJsException\u001b[0m: TypeError: Failed to fetch"
],
"output_type": "error"
}
]
},
{
"cell_type": "code",
"source": "%%javascript\nvar url = 'https://opendata-ajuntament.barcelona.cat/data/es/api/3/action/datastore_search?resource_id=69ae574f-adfc-4660-8f81-73103de169ff'\nwindow.saveJSONP(url, 'data/menors.json')",
"metadata": {
"trusted": true
},
"execution_count": 4,
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": "<IPython.core.display.Javascript object>",
"application/javascript": "var url = 'https://opendata-ajuntament.barcelona.cat/data/es/api/3/action/datastore_search?resource_id=69ae574f-adfc-4660-8f81-73103de169ff'\nwindow.saveJSONP(url, 'data/menors.json')\n"
},
"metadata": {}
}
]
},
{
"cell_type": "code",
"source": "with open('data/menors.json', 'r') as f:\n data = json.load(f)\npd.read_json(json.dumps(data['result']['records']))",
"metadata": {
"trusted": true
},
"execution_count": 5,
"outputs": [
{
"execution_count": 5,
"output_type": "execute_result",
"data": {
"text/plain": " Data \\nadjudicació Import adjudicat NIF \\\n0 2018-02-01T00:00:00 24.500,00 € B08323404 \n1 2018-02-01T00:00:00 1.500,00 € A41810920 \n2 2018-02-01T00:00:00 2.000,00 € B61395141 \n3 2018-02-01T00:00:00 600,00 € A80907397 \n4 2018-02-01T00:00:00 5.517,60 € B61016523 \n.. ... ... ... \n95 2018-01-29T00:00:00 1.117,82 € xxxxx150N \n96 2018-01-29T00:00:00 1.089,73 € xxxxx675V \n97 2018-01-29T00:00:00 1.484,79 € B61563169 \n98 2018-01-29T00:00:00 356,95 € B64048465 \n99 2018-01-30T00:00:00 1.143,01 € A20167649 \n\n Proveïdor \\\n0 CENTRAL DE VIAJES, S.L. \n1 VIVA AQUA SERVICE SPAIN,S.A. \n2 TRACK ASISTENCIA Y CONSULTING, S.L. \n3 VODAFONE ESPAÑA,S.A.U \n4 LEGAL ADVISORY CONSUL. SERV. 4U,S.L \n.. ... \n95 ROBERTO EXPÓSITO RUIZ \n96 JULI GÓMEZ ROIG \n97 SERVICIOS E INSTALACIONES ALDAGO, S.L. \n98 CONSTRUCCIONES ISIDRO CASANOVAS, S.L. \n99 COSMO CONSULT INIKER, S.A. \n\n Òrgan contractant \\\n0 CONSORCI AGÈNCIA LOCAL D'ECOLOGIA URBANA DE BA... \n1 CONSORCI AGÈNCIA LOCAL D'ECOLOGIA URBANA DE BA... \n2 CONSORCI AGÈNCIA LOCAL D'ECOLOGIA URBANA DE BA... \n3 CONSORCI AGÈNCIA LOCAL D'ECOLOGIA URBANA DE BA... \n4 CONSORCI AGÈNCIA LOCAL D'ECOLOGIA URBANA DE BA... \n.. ... \n95 BARCELONA CICLE DE L'AIGUA, S.A. \n96 BARCELONA CICLE DE L'AIGUA, S.A. \n97 BARCELONA CICLE DE L'AIGUA, S.A. \n98 BARCELONA CICLE DE L'AIGUA, S.A. \n99 BARCELONA CICLE DE L'AIGUA, S.A. \n\n Objecte del contracte Durada Trimestre \\\n0 Contractació servei agència de viatges 12 M 1 \n1 Subministrament aigua embotellada 12M 1 \n2 Servei manteniment dominis 12M 1 \n3 Contractació línia telefònica de dades 12 M 1 \n4 Servei de personal i nòmines 12 M 1 \n.. ... ... ... \n95 Retirada hidrant al carrer Fra Juníper Serra 1 Dia 1 \n96 Inspecció periòdica equips a pressió instal.la... 12 Mesos 1 \n97 Substitució comptador entrada Viver Tres Pins 1 Dia 1 \n98 Ampliació reforma oficina de claveguerons, c/R... 1 Dia 1 \n99 Manteniment anual del servei de suport del sot... 12 Mesos 1 \n\n Tipus Contracte _id Tipus ens \n0 Serveis 1 CONSORCIS \n1 Subministrament 2 CONSORCIS \n2 Serveis 3 CONSORCIS \n3 Serveis 4 CONSORCIS \n4 Serveis 5 CONSORCIS \n.. ... ... ... \n95 Serveis 95 SOCIETATS PRIVADES MUNICIPALS \n96 Serveis 96 SOCIETATS PRIVADES MUNICIPALS \n97 Serveis 97 SOCIETATS PRIVADES MUNICIPALS \n98 Serveis 98 SOCIETATS PRIVADES MUNICIPALS \n99 Serveis 99 SOCIETATS PRIVADES MUNICIPALS \n\n[100 rows x 11 columns]",
"text/html": "<div>\n<style scoped>\n .dataframe tbody tr th:only-of-type {\n vertical-align: middle;\n }\n\n .dataframe tbody tr th {\n vertical-align: top;\n }\n\n .dataframe thead th {\n text-align: right;\n }\n</style>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>Data \\nadjudicació</th>\n <th>Import adjudicat</th>\n <th>NIF</th>\n <th>Proveïdor</th>\n <th>Òrgan contractant</th>\n <th>Objecte del contracte</th>\n <th>Durada</th>\n <th>Trimestre</th>\n <th>Tipus Contracte</th>\n <th>_id</th>\n <th>Tipus ens</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>2018-02-01T00:00:00</td>\n <td>24.500,00 €</td>\n <td>B08323404</td>\n <td>CENTRAL DE VIAJES, S.L.</td>\n <td>CONSORCI AGÈNCIA LOCAL D'ECOLOGIA URBANA DE BA...</td>\n <td>Contractació servei agència de viatges</td>\n <td>12 M</td>\n <td>1</td>\n <td>Serveis</td>\n <td>1</td>\n <td>CONSORCIS</td>\n </tr>\n <tr>\n <th>1</th>\n <td>2018-02-01T00:00:00</td>\n <td>1.500,00 €</td>\n <td>A41810920</td>\n <td>VIVA AQUA SERVICE SPAIN,S.A.</td>\n <td>CONSORCI AGÈNCIA LOCAL D'ECOLOGIA URBANA DE BA...</td>\n <td>Subministrament aigua embotellada</td>\n <td>12M</td>\n <td>1</td>\n <td>Subministrament</td>\n <td>2</td>\n <td>CONSORCIS</td>\n </tr>\n <tr>\n <th>2</th>\n <td>2018-02-01T00:00:00</td>\n <td>2.000,00 €</td>\n <td>B61395141</td>\n <td>TRACK ASISTENCIA Y CONSULTING, S.L.</td>\n <td>CONSORCI AGÈNCIA LOCAL D'ECOLOGIA URBANA DE BA...</td>\n <td>Servei manteniment dominis</td>\n <td>12M</td>\n <td>1</td>\n <td>Serveis</td>\n <td>3</td>\n <td>CONSORCIS</td>\n </tr>\n <tr>\n <th>3</th>\n <td>2018-02-01T00:00:00</td>\n <td>600,00 €</td>\n <td>A80907397</td>\n <td>VODAFONE ESPAÑA,S.A.U</td>\n <td>CONSORCI AGÈNCIA LOCAL D'ECOLOGIA URBANA DE BA...</td>\n <td>Contractació línia telefònica de dades</td>\n <td>12 M</td>\n <td>1</td>\n <td>Serveis</td>\n <td>4</td>\n <td>CONSORCIS</td>\n </tr>\n <tr>\n <th>4</th>\n <td>2018-02-01T00:00:00</td>\n <td>5.517,60 €</td>\n <td>B61016523</td>\n <td>LEGAL ADVISORY CONSUL. SERV. 4U,S.L</td>\n <td>CONSORCI AGÈNCIA LOCAL D'ECOLOGIA URBANA DE BA...</td>\n <td>Servei de personal i nòmines</td>\n <td>12 M</td>\n <td>1</td>\n <td>Serveis</td>\n <td>5</td>\n <td>CONSORCIS</td>\n </tr>\n <tr>\n <th>...</th>\n <td>...</td>\n <td>...</td>\n <td>...</td>\n <td>...</td>\n <td>...</td>\n <td>...</td>\n <td>...</td>\n <td>...</td>\n <td>...</td>\n <td>...</td>\n <td>...</td>\n </tr>\n <tr>\n <th>95</th>\n <td>2018-01-29T00:00:00</td>\n <td>1.117,82 €</td>\n <td>xxxxx150N</td>\n <td>ROBERTO EXPÓSITO RUIZ</td>\n <td>BARCELONA CICLE DE L'AIGUA, S.A.</td>\n <td>Retirada hidrant al carrer Fra Juníper Serra</td>\n <td>1 Dia</td>\n <td>1</td>\n <td>Serveis</td>\n <td>95</td>\n <td>SOCIETATS PRIVADES MUNICIPALS</td>\n </tr>\n <tr>\n <th>96</th>\n <td>2018-01-29T00:00:00</td>\n <td>1.089,73 €</td>\n <td>xxxxx675V</td>\n <td>JULI GÓMEZ ROIG</td>\n <td>BARCELONA CICLE DE L'AIGUA, S.A.</td>\n <td>Inspecció periòdica equips a pressió instal.la...</td>\n <td>12 Mesos</td>\n <td>1</td>\n <td>Serveis</td>\n <td>96</td>\n <td>SOCIETATS PRIVADES MUNICIPALS</td>\n </tr>\n <tr>\n <th>97</th>\n <td>2018-01-29T00:00:00</td>\n <td>1.484,79 €</td>\n <td>B61563169</td>\n <td>SERVICIOS E INSTALACIONES ALDAGO, S.L.</td>\n <td>BARCELONA CICLE DE L'AIGUA, S.A.</td>\n <td>Substitució comptador entrada Viver Tres Pins</td>\n <td>1 Dia</td>\n <td>1</td>\n <td>Serveis</td>\n <td>97</td>\n <td>SOCIETATS PRIVADES MUNICIPALS</td>\n </tr>\n <tr>\n <th>98</th>\n <td>2018-01-29T00:00:00</td>\n <td>356,95 €</td>\n <td>B64048465</td>\n <td>CONSTRUCCIONES ISIDRO CASANOVAS, S.L.</td>\n <td>BARCELONA CICLE DE L'AIGUA, S.A.</td>\n <td>Ampliació reforma oficina de claveguerons, c/R...</td>\n <td>1 Dia</td>\n <td>1</td>\n <td>Serveis</td>\n <td>98</td>\n <td>SOCIETATS PRIVADES MUNICIPALS</td>\n </tr>\n <tr>\n <th>99</th>\n <td>2018-01-30T00:00:00</td>\n <td>1.143,01 €</td>\n <td>A20167649</td>\n <td>COSMO CONSULT INIKER, S.A.</td>\n <td>BARCELONA CICLE DE L'AIGUA, S.A.</td>\n <td>Manteniment anual del servei de suport del sot...</td>\n <td>12 Mesos</td>\n <td>1</td>\n <td>Serveis</td>\n <td>99</td>\n <td>SOCIETATS PRIVADES MUNICIPALS</td>\n </tr>\n </tbody>\n</table>\n<p>100 rows × 11 columns</p>\n</div>"
},
"metadata": {}
}
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment