--- name: jupyter_write kind: function lang: py domain: notebook version: "1.1.0" purity: impure signature: "def jupyter_append_code(notebook_path: str, source: str, server_url: str = 'http://localhost:8888', token: str = '') -> dict" description: "Operaciones de escritura sobre celdas de un notebook Jupyter via colaboracion en tiempo real (WebSocket) y API REST. Expone siete operaciones: append_code, append_markdown, insert, edit, delete, create y batch. NO ejecuta celdas — solo modifica la estructura del notebook. create usa PUT /api/contents para crear notebooks nuevos sin necesidad de websocket. batch abre una unica conexion WebSocket para insertar N celdas en una sola operacion." tags: [jupyter, notebook, websocket, cell, write, append, insert, edit, delete, create, batch, nbmodel, rest] uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: [jupyter_nbmodel_client] output: "Múltiples funciones para escribir en notebooks: append_code/markdown, insert, edit, delete, create, batch (retornan dicts con action y posición)" tested: false tests: [] test_file_path: "" file_path: "python/functions/notebook/jupyter_write.py" --- ## Funciones expuestas | Funcion | Descripcion | |---------|-------------| | `jupyter_append_code(notebook_path, source, server_url, token)` | Anade celda de codigo al final | | `jupyter_append_markdown(notebook_path, source, server_url, token)` | Anade celda markdown al final | | `jupyter_insert_cell(notebook_path, cell_index, source, cell_type, server_url, token)` | Inserta celda en posicion especifica | | `jupyter_edit_cell(notebook_path, cell_index, source, server_url, token)` | Sobrescribe contenido de celda existente | | `jupyter_delete_cell(notebook_path, cell_index, server_url, token)` | Elimina una celda | | `jupyter_create_notebook(notebook_path, kernel_name, server_url, token, force)` | Crea un notebook vacio nbformat 4 via API REST | | `jupyter_batch_write(notebook_path, cells, server_url, token)` | Anade N celdas en una sola conexion WebSocket | ## Ejemplo ```python from notebook.jupyter_write import ( jupyter_append_code, jupyter_append_markdown, jupyter_insert_cell, jupyter_edit_cell, jupyter_delete_cell, jupyter_create_notebook, jupyter_batch_write, ) # Crear notebook nuevo result = jupyter_create_notebook( notebook_path="notebooks/01_analisis.ipynb", kernel_name="python3", server_url="http://localhost:8888", ) # {"action": "create", "notebook": "notebooks/01_analisis.ipynb", "created": true} # Si ya existe, lanza FileExistsError. Usar force=True para sobreescribir: result = jupyter_create_notebook("notebooks/01.ipynb", force=True) # Anadir multiples celdas de golpe (una sola conexion WebSocket) cells = [ {"type": "markdown", "source": "## Analisis inicial"}, {"type": "code", "source": "import pandas as pd"}, {"type": "code", "source": "df = pd.read_csv('data.csv')\ndf.head()"}, ] result = jupyter_batch_write( notebook_path="notebooks/01_analisis.ipynb", cells=cells, server_url="http://localhost:8888", ) # {"action": "batch", "cells_added": 3, "notebook": "notebooks/01_analisis.ipynb"} # Anadir celda de codigo al final result = jupyter_append_code( notebook_path="notebooks/01_analisis.ipynb", source="import pandas as pd\ndf = pd.read_csv('data.csv')", ) # {"action": "append_code", "cell_index": 5, "notebook": "notebooks/01_analisis.ipynb"} # Anadir celda markdown result = jupyter_append_markdown( notebook_path="notebooks/01_analisis.ipynb", source="## Resultados\n\nAnalisis de los datos obtenidos.", ) # {"action": "append_markdown", "cell_index": 6, "notebook": "..."} # Insertar celda en posicion 2 result = jupyter_insert_cell( notebook_path="notebooks/01_analisis.ipynb", cell_index=2, source="# celda insertada", cell_type="code", ) # {"action": "insert", "cell_index": 2, "cell_type": "code", "notebook": "..."} # Editar celda existente (indice 0) result = jupyter_edit_cell( notebook_path="notebooks/01_analisis.ipynb", cell_index=0, source="# Titulo actualizado", ) # {"action": "edit", "cell_index": 0, "notebook": "..."} # Eliminar celda result = jupyter_delete_cell( notebook_path="notebooks/01_analisis.ipynb", cell_index=3, ) # {"action": "delete", "cell_index": 3, "notebook": "..."} ``` ## CLI ```bash # Crear notebook nuevo python -m notebook.jupyter_write create notebooks/01.ipynb python -m notebook.jupyter_write create notebooks/01.ipynb --kernel python3 python -m notebook.jupyter_write create notebooks/01.ipynb --force # Anadir multiples celdas desde archivo JSON python -m notebook.jupyter_write batch notebooks/01.ipynb --from cells.json # O via stdin cat cells.json | python -m notebook.jupyter_write batch notebooks/01.ipynb --from - echo '[{"type":"code","source":"import pandas"}]' | python -m notebook.jupyter_write batch notebooks/01.ipynb # Formato JSON de entrada para batch: # [{"type": "markdown", "source": "# Titulo"}, {"type": "code", "source": "import pandas"}] # Anadir celda de codigo python -m notebook.jupyter_write append-code notebooks/01.ipynb "print('hola')" --server http://localhost:8888 --token mi-token # Anadir celda markdown python -m notebook.jupyter_write append-markdown notebooks/01.ipynb "## Titulo" # Insertar en posicion 2 python -m notebook.jupyter_write insert notebooks/01.ipynb 2 "x = 42" --type code # Editar celda 0 python -m notebook.jupyter_write edit notebooks/01.ipynb 0 "# Nuevo titulo" # Eliminar celda 3 python -m notebook.jupyter_write delete notebooks/01.ipynb 3 ``` ## Notas - Todas las funciones son sincronas publicamente. Internamente usan `asyncio.run()` sobre corutinas async que se comunican via WebSocket con `NbModelClient`. - `create` es la excepcion: usa urllib (PUT /api/contents) sin WebSocket. Crea un nbformat 4 con celdas vacias. Lanza `FileExistsError` si el notebook ya existe y `force=False`. - `batch` es mucho mas eficiente que N llamadas a `append-code`/`append-markdown`: abre una sola conexion WebSocket y hace un unico `asyncio.sleep(2)` de sincronizacion al final. - El `notebook_path` es relativo al servidor Jupyter (no al filesystem local). - Si el servidor no esta corriendo o el token es incorrecto, lanza excepcion de conexion de `jupyter_nbmodel_client`. - NO ejecuta celdas — solo modifica la estructura. Para ejecutar, usar `jupyter_exec`. - `server_url` y `token` tienen defaults convenientes para desarrollo local (`http://localhost:8888`, token vacio). - El campo `cell_index` en el resultado refleja la posicion final de la celda en el notebook. - Patron tipico: `create` para crear el notebook, luego `batch` para poblar las celdas iniciales.