Skip to content

Capítulo 9 — Contribuciones de la comunidad y manejo de errores

Commits: 75c6875 (birbbit), 912547b, ae8e489, 160399c (Killian, feb-mar 2024)

¿Qué se arregló?

Una serie de pequeños pero importantes fixes de estabilidad. El proyecto ya funcionaba en condiciones normales, pero en el "mundo real" los archivos pueden estar corruptos, ser binarios, tener encodings extraños, o el índice puede contener entradas nulas.

Fix 1: Ignorar funciones privadas

python
# Commit 75c6875 — birbbit
def traverse(node):
    for child in ast.iter_child_nodes(node):
        if isinstance(child, ast.FunctionDef):
            if child.name.startswith("_"):
                # ignore private functions
                continue

Las funciones que empiezan con _ en Python son privadas por convención: _helper(), __init__(), __repr__(). No tiene sentido exponerlas en un índice semántico porque el usuario externo no debería llamarlas directamente.

Esto reduce el ruido en los resultados de búsqueda.

Fix 2: El bug del common_prefix para directorios

python
# Commit 75c6875 — birbbit
common_prefix = os.path.commonprefix(file_paths)
if not common_prefix.endswith("/"):
    common_prefix = os.path.dirname(common_prefix)  # ← FIX
path_to_index = os.path.join(common_prefix, "_.aifs")

os.path.commonprefix() es una función tramposa. Trabaja carácter a carácter, no por segmentos de path:

python
os.path.commonprefix(["/proyecto/src/payments.py", "/proyecto/src/orders.py"])
# → "/proyecto/src/" ✅ (termina en /)

os.path.commonprefix(["/proyecto/src/payments.py", "/proyecto/server.py"])  
# → "/proyecto/s" ❌ (no es un directorio válido!)

El fix: si el prefijo no termina en /, tomar el directorio padre con os.path.dirname().

Fix 3: Defensa contra file_index nulo

python
# Commit 160399c
def handle_modified_files(index: dict, python_docstrings_only: bool) -> List[str]:
    for file_path, file_index in index.items():
        if file_path == None or file_index == None:  # ← GUARD
            continue
        if os.path.getmtime(file_path) != file_index["last_modified"]:

¿Cuándo puede file_index ser None? Cuando index_file() falla y retorna implícitamente None. Esto puede pasar con archivos binarios, imágenes, PDFs corruptos, etc.

python
def index_file(file_path, python_docstrings_only=False):
    try:
        chunks = chunk_file(file_path)
    except Exception as e:
        chunks = [f"There is a file at `{file_path}`."]
    
    embeddings = embed(chunks)  # ← Puede fallar aquí
    # Si hay excepción, Python retorna None implícitamente

El guard previene que un None en el índice rompa el loop completo.

Fix 4: Defensa contra chunks nulos en ChromaDB

python
# Commit ae8e489
for file_path, file_index in index.items():
    if "__pycache__" in file_path:
        continue
    # ANTES: asumía que file_index siempre tenía "chunks"
    # DESPUÉS:
    if file_index and "chunks" in file_index:
        ids = [str(id) for id in range(id_counter, id_counter + len(file_index["chunks"]))]
        id_counter += len(file_index["chunks"])
    else:
        ids = []
    if ids:  # Solo insertar en ChromaDB si hay IDs
        collection.add(...)

ChromaDB lanza excepción si intentas hacer collection.add() con listas vacías. El fix es sencillo: verificar antes de insertar.

El patrón de robustez emergente

Cada capa de código tiene su propio guard. No hay un punto central de manejo de errores — el sistema "falla suavemente" en cada paso.

Lección del capítulo

En sistemas que procesan datos del mundo real (archivos del usuario), siempre hay casos borde: archivos corruptos, encodings extraños, entradas nulas. Los sistemas robustos defienden cada operación individualmente, no solo el punto de entrada.


Siguiente: Cap 10 — Soporte Python 3.12 y dependencias opcionales

Libro generado por El Profe 🧑‍🏫