Files
fn_registry/python/pyproject.toml
T
egutierrez 105e56cf05 feat(eda): capítulo text_distr (TEXTO/NLP) — primer capítulo de datos no tabulares
Añade el capítulo `text_distr` al motor AutomaticEDA: perfila columnas de texto
libre largo (reseñas, descripciones, comentarios) que la distribución categórica
no resume bien. Sigue el patrón de cat_distr/num_distr (build_text_distr(profile,
ctx) -> Chapter | None) y se registra en CHAPTER_ORDER tras cat_distr.

Activación en dos fases: gate barato desde el perfil (columna no numérica con
len_mean >= 50 chars) + confirmación con muestra cruda (mediana de palabras >= 20).
Un dataset sin texto largo (p.ej. titanic) devuelve None sin tocar el informe.

Bloques por columna (Group con page_break): resumen (longitudes, vocabulario con
TTR y % hapax, idioma dominante, % duplicados, legibilidad), histograma de
longitudes, top términos (tabla + barras), bigramas/trigramas, idiomas detectados
y nube de palabras opcional. Términos ttr/hapax enganchados al glosario clicable.

Lógica delegada a 7 funciones nuevas del registry (datascience, tag eda),
estilo dict-no-throw:
- extract_text_sample (impura, push-down SQL DuckDB/Postgres)
- compute_text_length_stats, compute_vocabulary_stats, compute_top_ngrams (puras, stdlib)
- detect_corpus_language (langdetect opcional), compute_text_readability (textstat
  opcional), compute_text_duplicates (hash + datasketch opcional)

Versión barata sin modelos pesados: las piezas que dependen de una librería
opcional (langdetect, textstat, wordcloud, datasketch) degradan a omitidas sin
lanzar. Añade langdetect y textstat (ligeras) al pyproject + uv.lock.

Verificado: golden sobre dataset de reviews multi-idioma (capítulo presente en
PDF+PPTX+MD con métricas reales), titanic sin capítulo (None), degradación sin
libs, suite automatic_eda + pipeline verde (128 passed), fn index OK.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 20:38:17 +02:00

72 lines
1.8 KiB
TOML

[project]
name = "fn-registry-python"
version = "0.1.0"
description = "Funciones Python del fn-registry: Metabase API, ML, utilidades"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"chardet>=7.4.3",
"contextily>=1.7.0",
"cryptography>=46.0.6",
"duckdb>=1.5.2",
"fpdf2>=2.8.7",
"geopandas>=1.1.3",
"google-api-python-client>=2.197.0",
"google-auth>=2.49.1",
"google-cloud-bigquery>=3.25",
"google-cloud-bigquery-datatransfer>=3.22.0",
"google-cloud-bigquery-storage>=2.27",
"google-cloud-storage>=3.10.1",
"httpx",
"langdetect>=1.0.9",
"matplotlib>=3.10.9",
"opencv-contrib-python-headless>=4.13.0.92",
"openpyxl>=3.1.5",
"pillow>=12.2.0",
"polars>=1.40.1",
"pymeshlab>=2025.7.post1",
"pymssql>=2.3.13",
"pymupdf>=1.28.0",
"pypdf>=6.10.0",
"pyproj>=3.7.2",
"python-docx>=1.2.0",
"python-pptx>=1.0.2",
"pyyaml>=6.0.3",
"qrcode[pil]>=8.2",
"rapidfuzz>=3.14.5",
"reportlab>=4.5.0",
"scikit-image>=0.26.0",
"scikit-learn>=1.8.0",
"scipy>=1.17.1",
"seaborn>=0.13.2",
"shapely>=2.1.2",
"statsmodels>=0.14.6",
"textstat>=0.7.13",
"trimesh>=4.12.2",
"xlrd>=2.0.2",
]
[project.optional-dependencies]
nlp = [
"gliner>=0.2.13",
"glirel>=1.0.0",
]
jupyter = [
"jupyterlab>=4.0",
"jupyter-collaboration>=2.0",
"jupyter-mcp-server",
]
[dependency-groups]
dev = [
"pytest>=9.0.2",
]
[tool.pytest.ini_options]
# Las funciones del registry importan paquetes por su nombre raiz
# (p.ej. `from obsidian import format_obsidian_note`), por lo que el
# directorio `functions/` debe estar en sys.path al recolectar tests.
# `functions/obsidian` permite a los tests importar los modulos hoja por
# su nombre directo (p.ej. `from format_obsidian_note import ...`).
pythonpath = ["functions", "functions/obsidian"]