Metadata-Version: 2.4
Name: antigravity-lite
Version: 0.1.1
Summary: Herramienta open-source para auditar despilfarros financieros en clústeres PySpark (AWS Glue) y manipular S3.
Author-email: Arquitecto B2B <arquitecto@antigravity.dev>
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: boto3>=1.26.0

# 🛸 Antigravity PySpark Framework

Enterprise framework para resolver problemas complejos de Big Data en AWS Glue y entornos PySpark puros sin esfuerzo. Este proyecto estandariza las mejores prácticas de la industria con un solo `import`.

## 📦 Empaquetado y Licenciamiento Comercial (SaaS B2B)

Si deseas vender y distribuir este framework a una empresa externa, es imperativo **proteger tu Propiedad Intelectual** (ofuscar el código fuente) y **venderlo con una licencia temporal** (para que te paguen la renovación).

### 1. Ofuscar el código y armar la "Bomba de Tiempo" (Expiración)
Antes de construir el paquete, encripta el código fuente y configúrale la fecha de vencimiento exacta del contrato del cliente (ej. 31 de Diciembre de 2027):

```bash
# 1. Asegúrate de estar en el entorno virtual
source .venv/bin/activate

# 2. Generar el binario comercial ofuscado (.whl) con Bomba de Tiempo (2027)
python build_commercial.py
```
Este script (que te escribí a la medida) automatizará por ti la encriptación con PyArmor y el empaquetado directo hacia la carpeta `dist/`. Cualquier ingeniero externo que intente abrir tus archivos allí dentro verá código basura indescifrable.

### 2. Construcción de uso interno / Open-Source (`.whl`)
Para el empaquetado inicial (sin ofuscación) para probar el framework dentro de tu propio AWS Glue, ejecuta el empaquetado estándar de Python:
```bash
# Construye el antigravity-0.1.0-py3-none-any.whl en la carpeta dist/
pip install build
python -m build
```

---

## 🚀 Guía de Uso Rápido para Ingenieros

### Motor A: Optimizador Core (`DataFrameChunker`)
**¿Cuándo usarlo?** Cuando lidias con DataFrames anchos (Wide DataFrames) o realizas analítica que provoca errores de `OutOfMemory` (OOM), demoras extremas, o fallos de `StackOverflowError`. Funciona fluidamente con cualquier volumen de datos y columnas, auto-regulando la memoria del clúster para acelerar los cruces matemáticos pesados.

**¿Cómo funciona?**
Particiona el DataFrame verticalmente e inyecta `localCheckpoint()` para aislar la memoria del Catalyst Optimizer.

```python
from antigravity.core import DataFrameChunker

# 1. Instancias el chunker indicando la llave primaria y cuántas columnas procesar a la vez.
chunker = DataFrameChunker(df_masivo, id_cols=["id_cliente"], chunk_size=50)

# 2. Defines tú lógica matemática. Spark solo le pasará 50 variables por iteración.
def mi_logica(chunk_df, indice):
    # Calcula algo y retorna un DF más pequeño
    return chunk_df.select("id_cliente", ...)

# 3. El framework ejecuta el bucle de forma segura en el clúster
resultados_parciales = chunker.process_chunks(mi_logica)
```

### Motor B: Generador Legacy (`LegacyTextTransformer`)
**¿Cuándo usarlo?** Cuando el negocio, banco, o gobierno te exige generar archivos `.TXT` planos, asimétricos o posicionales a partir de datos tabulares modernos.

**¿Cómo funciona?**
Recibe el DataFrame y usa `RDD.flatMap` para aplicar lógica de python puro distribuidamente.

```python
from antigravity.legacy import LegacyTextTransformer

# 1. Escribes las reglas del negocio (1 Fila de Spark = N líneas de texto)
def reglas_bancarias(fila):
    yield f"HEADER_{fila.id}"
    yield f"BODY_{fila.saldo}"

# 2. Invocas el framework
transformer = LegacyTextTransformer(df)

# 3. Generas la salida
transformer.save_as_text(reglas_bancarias, "s3://mi-bucket/banco_txt/")
```

### Motor IO: Smart Exporter (`S3Finalizer`)
**¿Cuándo usarlo?** Cuando detestas que PySpark guarde tus archivos como `part-0000X.csv` y deje basura como los archivos `_SUCCESS` en tu S3.

**¿Cómo funciona?**
Se conecta mediante `boto3` para listar, ordenar, secuenciar y renombrar la salida de Spark.

```python
from antigravity.io import S3Finalizer

# 1. Escribes tu DataFrame normal en Spark
df.write.parquet("s3://mi-bucket/salida_sucia/")

# 2. Invocas el framework para secuenciarlos inteligentemente e inyectar el formato
finalizador = S3Finalizer(bucket_name="mi-bucket")
finalizador.sequence_spark_outputs(
    s3_prefix="salida_sucia/",
    pattern="MI_EMPRESA_DATA_{seq:04d}.parquet" # Resultado: MI_EMPRESA_DATA_0001.parquet
)
```
