--- name: jupyter_exec kind: function lang: py domain: notebook version: "2.0.0" purity: impure signature: "jupyter_append_execute(notebook_path: str, code: str, server_url: str, token: str) -> dict" description: "Ejecuta codigo en kernels de Jupyter via REST + WebSocket clasico al kernel. Tres modos: append (añade celda y ejecuta), cell (ejecuta celda existente), kernel (ejecuta sin tocar notebook). NO usa el canal colaborativo Y.js." tags: [jupyter, notebook, kernel, websocket, execution, cells, pendiente-usar] uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: [jupyter_kernel_client, urllib, json, uuid] params: - name: notebook_path desc: "Ruta relativa al notebook" - name: code desc: "Código a ejecutar" - name: server_url desc: "URL del servidor Jupyter (default localhost:8888)" - name: token desc: "Token de autenticación (default vacío)" output: "Dict con cell_index y outputs del código ejecutado, o resultados del kernel" tested: true tests: - "test_notebook_exists_uses_get_not_head" - "test_notebook_exists_returns_false_on_404" - "test_create_notebook_skips_when_exists" - "test_new_code_cell_has_required_fields" - "test_extract_outputs_handles_streams_and_results" - "e2e: test_e2e_append_executes_and_persists" - "e2e: test_e2e_append_twice_increments_index" - "e2e: test_e2e_cell_executes_existing" - "e2e: test_e2e_kernel_mode" test_file_path: "python/functions/notebook/tests/test_jupyter_exec.py" file_path: "python/functions/notebook/jupyter_exec.py" --- ## Funciones ### `jupyter_append_execute(notebook_path, code, server_url, token)` Añade una celda de codigo al final del notebook, la ejecuta en el kernel y persiste celda + outputs a disco via REST `/api/contents`. Jupyter Lab detecta el cambio y lo refleja en el browser. ```python from notebook.jupyter_exec import jupyter_append_execute result = jupyter_append_execute( "notebooks/analisis.ipynb", "import pandas as pd\nprint(pd.__version__)", server_url="http://localhost:8888", token="", ) # {"cell_index": 5, "outputs": ["2.2.1"]} ``` ### `jupyter_execute_cell(notebook_path, cell_index, server_url, token)` Ejecuta una celda existente por indice (0-based) y persiste sus outputs. ```python result = jupyter_execute_cell("notebooks/analisis.ipynb", 3) # {"cell_index": 3, "outputs": ["42"]} ``` ### `jupyter_kernel_execute(code, server_url, token)` Ejecuta codigo directo en el kernel sin tocar ningun notebook. ```python result = jupyter_kernel_execute("len(df)") # {"outputs": ["1500"], "status": "ok"} ``` ## CLI ```bash python -m notebook.jupyter_exec append notebooks/mi.ipynb "print('hola')" python -m notebook.jupyter_exec cell notebooks/mi.ipynb 2 python -m notebook.jupyter_exec kernel "x = 42; print(x)" ``` Output siempre JSON. En error retorna `{"error": "..."}` por stderr con exit code 1. ## Extraccion de outputs | output_type | campo leido | |---|---| | stream | `text` | | display_data / execute_result | `data.text/plain` | | error | `traceback` (joined con `\n`) | ## Notas (v2.0.0 — fix Issue 0050) - **Bypassa el canal colaborativo Y.js**. Usa REST `/api/contents` para leer/escribir celdas y `KernelClient` (websocket clasico al kernel) para ejecutar. Robusto frente a versiones nuevas de `jupyter-collaboration` que rompian `NbModelClient`. - **Trade-off**: las celdas/outputs se persisten a disco, no se sincronizan en tiempo real via Y.js. Jupyter Lab detecta el cambio en el filesystem y lo refleja (puede pedir 'Revert to disk' segun version). - `_notebook_exists` usa `GET /api/contents?content=0` (HEAD devuelve 405 en Jupyter Server). - **Auto-init**: `jupyter_append_execute` crea el notebook si no existe y arranca una sesion con kernel si no hay ninguna activa para ese notebook. - El token puede ser cadena vacia si el servidor tiene autenticacion deshabilitada.