# write_jupyter_registry_kernel # ------------------------------- # Genera un script de startup de IPython que autoconfigura el acceso # al fn_registry en cada notebook: FN_REGISTRY_ROOT, sys.path a # python/functions, y un helper fn_query() para consultar registry.db. # # USO (sourced): # source write_jupyter_registry_kernel.sh # write_jupyter_registry_kernel /path/to/project write_jupyter_registry_kernel() { local project_dir="${1:-.}" local startup_dir="${project_dir}/.ipython/profile_default/startup" local registry_root registry_root="$(cd "$project_dir" && cd "$(git -C "$project_dir" rev-parse --show-toplevel 2>/dev/null || echo "../..")" && pwd)" # Fallback: si no es git, buscar registry.db subiendo directorios if [ ! -f "$registry_root/registry.db" ] && [ -f "$project_dir/../../registry.db" ]; then registry_root="$(cd "$project_dir/../.." && pwd)" fi mkdir -p "$startup_dir" cat > "${startup_dir}/00_fn_registry.py" << STARTUP """ fn_registry kernel startup Autoconfigura acceso al registry en cada notebook. Generado por write_jupyter_registry_kernel (fn_registry). """ import os import sys import sqlite3 from pathlib import Path # ── FN_REGISTRY_ROOT ──────────────────────────────────────── FN_REGISTRY_ROOT = Path("${registry_root}") os.environ["FN_REGISTRY_ROOT"] = str(FN_REGISTRY_ROOT) # ── sys.path: importar funciones Python del registry ──────── _python_functions = FN_REGISTRY_ROOT / "python" / "functions" for _domain in sorted(_python_functions.iterdir()) if _python_functions.exists() else []: if _domain.is_dir() and not _domain.name.startswith("_"): _path = str(_domain) if _path not in sys.path: sys.path.insert(0, _path) # Tambien el directorio padre para imports por dominio: from core import filter_list _pf = str(_python_functions) if _pf not in sys.path: sys.path.insert(0, _pf) # ── fn_query: consultar registry.db desde el notebook ─────── _REGISTRY_DB = FN_REGISTRY_ROOT / "registry.db" def fn_query(sql, params=()): """Ejecuta una consulta SQL sobre registry.db y retorna las filas. Ejemplos: fn_query("SELECT id, description FROM functions WHERE domain = ?", ("finance",)) fn_query("SELECT id FROM functions_fts WHERE functions_fts MATCH ?", ("slice*",)) """ if not _REGISTRY_DB.exists(): raise FileNotFoundError(f"registry.db no encontrado en {_REGISTRY_DB}") con = sqlite3.connect(str(_REGISTRY_DB)) con.row_factory = sqlite3.Row try: rows = con.execute(sql, params).fetchall() return [dict(r) for r in rows] finally: con.close() def fn_search(term): """Busca funciones y tipos en el registry por nombre o descripcion. Ejemplo: fn_search("slice") fn_search("finance") """ fts_term = f"name:{term}* OR description:{term}*" functions = fn_query( "SELECT id, kind, purity, lang, description FROM functions " "WHERE id IN (SELECT id FROM functions_fts WHERE functions_fts MATCH ?) " "ORDER BY name", (fts_term,) ) types = fn_query( "SELECT id, algebraic, lang, description FROM types " "WHERE id IN (SELECT id FROM types_fts WHERE types_fts MATCH ?) " "ORDER BY name", (fts_term,) ) return {"functions": functions, "types": types} def fn_code(function_id): """Retorna el codigo fuente de una funcion del registry. Ejemplo: print(fn_code("filter_list_py_core")) """ rows = fn_query("SELECT code FROM functions WHERE id = ?", (function_id,)) if not rows: raise KeyError(f"Funcion no encontrada: {function_id}") return rows[0]["code"] # ── Mensaje de bienvenida ─────────────────────────────────── print(f"fn_registry conectado: {FN_REGISTRY_ROOT}") print(f" registry.db: {'OK' if _REGISTRY_DB.exists() else 'NO ENCONTRADO'}") print(f" Python functions: {_pf}") print(f" Helpers: fn_query(), fn_search(), fn_code()") STARTUP echo "${startup_dir}/00_fn_registry.py" }