chore: sync from fn-registry agent
This commit is contained in:
@@ -0,0 +1,40 @@
|
|||||||
|
# JUPYTER HABILITADO EN ESTE ANALISIS
|
||||||
|
|
||||||
|
## Reglas OBLIGATORIAS para Claude
|
||||||
|
|
||||||
|
### 1. CODIGO INMUTABLE — NUNCA MODIFICAR CELDAS EXISTENTES
|
||||||
|
- **PROHIBIDO** usar NotebookEdit para reemplazar celdas existentes
|
||||||
|
- **SIEMPRE** anadir celdas NUEVAS al final del notebook
|
||||||
|
- Si hay un error en una celda, crear celda nueva con la correccion
|
||||||
|
- El historial de trabajo debe quedar intacto para trazabilidad
|
||||||
|
|
||||||
|
### 2. PROGRAMACION FUNCIONAL OBLIGATORIA
|
||||||
|
- **Funciones puras**: sin efectos secundarios, mismo input -> mismo output
|
||||||
|
- **Inmutabilidad**: nunca mutar datos, crear copias transformadas
|
||||||
|
- **Composicion**: funciones pequenas que se combinan
|
||||||
|
- Preferir: `map`, `filter`, `reduce`, list comprehensions
|
||||||
|
- Evitar: loops con mutacion, `global`, modificar argumentos in-place
|
||||||
|
|
||||||
|
### 3. SIEMPRE usar MCP jupyter para ejecutar codigo Python
|
||||||
|
- Las ejecuciones se ven en tiempo real en Jupyter Lab del usuario
|
||||||
|
- Compartimos variables y estado del kernel
|
||||||
|
- **NUNCA usar bash para ejecutar Python en este analisis**
|
||||||
|
|
||||||
|
### 4. Verificar Jupyter activo ANTES de ejecutar
|
||||||
|
- Si no esta activo: pedir al usuario que ejecute `./run-jupyter-lab.sh`
|
||||||
|
|
||||||
|
### 5. Gestion de notebooks
|
||||||
|
- Notebooks en la carpeta `notebooks/` o subcarpetas
|
||||||
|
- Si un notebook tiene >50 celdas, crear uno nuevo
|
||||||
|
- Nombrar descriptivamente: `01_exploracion.ipynb`, `02_limpieza.ipynb`
|
||||||
|
|
||||||
|
### 6. Gestion de Python
|
||||||
|
- **SIEMPRE usar `uv`** para gestionar dependencias
|
||||||
|
- Anadir paquetes con `uv add nombre_paquete`
|
||||||
|
|
||||||
|
### 7. Acceso al fn_registry
|
||||||
|
- `FN_REGISTRY_ROOT` apunta a la raiz del registry
|
||||||
|
- Para importar funciones Python: `sys.path.insert(0, os.path.join(os.environ["FN_REGISTRY_ROOT"], "python", "functions"))`
|
||||||
|
- Para consultar registry.db: `sqlite3` o `import sqlite3` con la ruta `$FN_REGISTRY_ROOT/registry.db`
|
||||||
|
|
||||||
|
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
# Python venv (regenerable con uv sync)
|
||||||
|
.venv/
|
||||||
|
|
||||||
|
# Secrets
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
|
||||||
|
# Data local (per-PC, no se sube)
|
||||||
|
data/
|
||||||
|
|
||||||
|
# Jupyter runtime (per-PC)
|
||||||
|
.jupyter/
|
||||||
|
.jupyter-port
|
||||||
|
.jupyter_ystore.db
|
||||||
|
.mcp.json
|
||||||
|
|
||||||
|
# IPython runtime — mantiene startup/ (registry helpers), ignora el resto
|
||||||
|
.ipython/profile_default/history.sqlite
|
||||||
|
.ipython/profile_default/log/
|
||||||
|
.ipython/profile_default/db/
|
||||||
|
.ipython/profile_default/security/
|
||||||
|
|
||||||
|
# Python bytecode
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
|
||||||
|
# Jupyter checkpoints
|
||||||
|
.ipynb_checkpoints/
|
||||||
|
**/.ipynb_checkpoints/
|
||||||
|
|
||||||
|
# Operations DB
|
||||||
|
operations.db
|
||||||
|
operations.db-shm
|
||||||
|
operations.db-wal
|
||||||
|
operations.db-journal
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
"""
|
||||||
|
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 ────────────────────────────────────────
|
||||||
|
# Prioridad: env var > path hardcoded > descubrimiento automatico
|
||||||
|
def _discover_registry_root():
|
||||||
|
if os.environ.get("FN_REGISTRY_ROOT"):
|
||||||
|
return Path(os.environ["FN_REGISTRY_ROOT"]).resolve()
|
||||||
|
hardcoded = Path("/home/egutierrez/fn_registry")
|
||||||
|
if (hardcoded / "registry.db").exists():
|
||||||
|
return hardcoded
|
||||||
|
# Subir desde CWD hasta encontrar registry.db
|
||||||
|
p = Path.cwd()
|
||||||
|
for _ in range(10):
|
||||||
|
if (p / "registry.db").exists():
|
||||||
|
return p
|
||||||
|
if p.parent == p:
|
||||||
|
break
|
||||||
|
p = p.parent
|
||||||
|
return hardcoded
|
||||||
|
|
||||||
|
FN_REGISTRY_ROOT = _discover_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()")
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
3.13
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
name: venta_web
|
||||||
|
lang: py
|
||||||
|
domain: datascience
|
||||||
|
description: "Exploracion de tablas relacionadas con venta web"
|
||||||
|
tags: []
|
||||||
|
uses_functions: []
|
||||||
|
uses_types: []
|
||||||
|
framework: "jupyterlab"
|
||||||
|
entry_point: "notebooks/main.ipynb"
|
||||||
|
dir_path: "projects/aurgi/analysis/venta_web"
|
||||||
|
repo_url: ""
|
||||||
|
---
|
||||||
|
|
||||||
|
## Notas
|
||||||
|
|
||||||
|
Exploracion de tablas relacionadas con venta web
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
def main():
|
||||||
|
print("Hello from venta-web!")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
|||||||
|
[project]
|
||||||
|
name = "venta-web"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Add your description here"
|
||||||
|
readme = "README.md"
|
||||||
|
requires-python = ">=3.13"
|
||||||
|
dependencies = [
|
||||||
|
"jupyter>=1.1.1",
|
||||||
|
"jupyter-collaboration>=4.3.0",
|
||||||
|
"jupyter-mcp-server>=0.4.0",
|
||||||
|
"jupyterlab>=4.5.6",
|
||||||
|
"matplotlib>=3.10.8",
|
||||||
|
"numpy>=2.4.4",
|
||||||
|
"pandas>=3.0.2",
|
||||||
|
]
|
||||||
Executable
+50
@@ -0,0 +1,50 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Jupyter Lab — modo colaborativo con autodeteccion de puerto
|
||||||
|
# Generado por write_jupyter_launcher (fn_registry)
|
||||||
|
|
||||||
|
find_free_port() {
|
||||||
|
for port in 8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899; do
|
||||||
|
if ! ss -tln 2>/dev/null | grep -q ":${port} " && \
|
||||||
|
! lsof -i:"$port" >/dev/null 2>&1; then
|
||||||
|
echo $port
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo 8888
|
||||||
|
}
|
||||||
|
|
||||||
|
PORT=${1:-$(find_free_port)}
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
echo $PORT > .jupyter-port
|
||||||
|
|
||||||
|
source .venv/bin/activate 2>/dev/null || true
|
||||||
|
|
||||||
|
# IPython startup: cargar .ipython/ local (FN_REGISTRY_ROOT, helpers, sys.path)
|
||||||
|
if [ -d "$(pwd)/.ipython" ]; then
|
||||||
|
export IPYTHONDIR="$(pwd)/.ipython"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! python -c "import jupyter_collaboration" 2>/dev/null; then
|
||||||
|
echo "ERROR: jupyter-collaboration no esta instalado"
|
||||||
|
echo "Instala con: uv add jupyter-collaboration"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "════════════════════════════════════════════════"
|
||||||
|
echo " Jupyter Lab + Colaboracion en puerto $PORT"
|
||||||
|
echo "════════════════════════════════════════════════"
|
||||||
|
echo ""
|
||||||
|
echo " Abre: http://localhost:$PORT"
|
||||||
|
echo " Ctrl+C para detener"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
jupyter lab \
|
||||||
|
--port=$PORT \
|
||||||
|
--no-browser \
|
||||||
|
--ServerApp.token='' \
|
||||||
|
--ServerApp.password='' \
|
||||||
|
--ServerApp.disable_check_xsrf=True \
|
||||||
|
--ServerApp.allow_origin='*' \
|
||||||
|
--ServerApp.root_dir="$(pwd)" \
|
||||||
|
--collaborative
|
||||||
Reference in New Issue
Block a user