A robust, flexible configuration management system for Python applications
Project description
config-loader 🚀
Una librería robusta y flexible para gestionar configuración en aplicaciones Python. Carga configuración desde múltiples archivos YAML, aplica overrides desde variables de entorno y valida todo con Pydantic.
Versión: 0.1.0
Estado: Alpha
Licencia: MIT
📋 Tabla de Contenidos
- Características
- Instalación
- Uso Rápido
- Ejemplos Detallados
- Desarrollo
- Configuración del Ambiente de Desarrollo
- API Reference
- Manejo de Errores
- Convenciones
- GitHub Actions Pipelines
- Branching Strategy
- Commit Conventions
- Development Workflow
- Semantic Versioning
- Best Practices
- Troubleshooting
✨ Características
✅ Carga desde múltiples YAML - Combina archivos base + overrides con precedencia clara
✅ Overrides de variables de entorno - Aplica ENV vars con convención PREFIX__NESTED__KEY
✅ Validación con Pydantic - Type-safe con mensajes de error claros
✅ Manejo granular de errores - Excepciones específicas para cada tipo de error
✅ Tipos seguros - Type hints completos para mejor IDE support
✅ Sin mutaciones - Las funciones retornan nuevos objetos, no modifican los originales
📦 Instalación
Instalación básica
pip install config-loader
Instalación desde repositorio (desarrollo)
git clone https://github.com/dev-brainstack/config-loader.git
cd config-loader
pip install -e .
Instalación con dependencias de desarrollo
pip install -e ".[dev]"
🚀 Uso Rápido
Ejemplo Básico
from pydantic import BaseModel
from config_loader import load_config
# 1. Define tu modelo de configuración
class DatabaseConfig(BaseModel):
host: str
port: int = 5432
username: str
password: str
class AppConfig(BaseModel):
debug: bool = False
database: DatabaseConfig
# 2. Crea archivos YAML
# config/base.yaml
# debug: false
# database:
# host: localhost
# port: 5432
# username: admin
# password: secret
# 3. Carga la configuración
config = load_config(
AppConfig,
paths=["config/base.yaml"],
use_env=True,
env_prefix="APP"
)
# 4. Usa la configuración
print(config.debug) # False
print(config.database.host) # localhost
📚 Ejemplos Detallados
Ejemplo 1: Configuración Simple
Entrada - Archivo YAML (config.yaml):
app_name: MyApp
debug: true
port: 8000
Código Python:
from pydantic import BaseModel
from config_loader import load_config
class Config(BaseModel):
app_name: str
debug: bool
port: int
config = load_config(Config, paths=["config.yaml"])
# Salida
print(config.app_name) # "MyApp"
print(config.debug) # True
print(config.port) # 8000
Ejemplo 2: Múltiples Archivos YAML con Overrides
Entrada - Archivos YAML:
config/base.yaml:
app_name: MyApp
debug: false
database:
host: localhost
port: 5432
username: admin
config/production.yaml:
debug: false
database:
host: prod-db.example.com
port: 5432
Código Python:
from pydantic import BaseModel
from typing import Dict, Any
from config_loader import load_config
class AppConfig(BaseModel):
app_name: str
debug: bool
database: Dict[str, Any]
# Los archivos se cargan en orden, el último sobrescribe al anterior
config = load_config(
AppConfig,
paths=[
"config/base.yaml",
"config/production.yaml"
]
)
# Salida
print(config.app_name) # "MyApp" (del base.yaml)
print(config.database["host"]) # "prod-db.example.com" (del production.yaml)
print(config.database["port"]) # 5432 (del production.yaml)
print(config.database["username"]) # "admin" (del base.yaml, no sobrescrito)
Ejemplo 3: Overrides desde Variables de Entorno
Entrada - Variables de Entorno:
export APP__DEBUG=true
export APP__DATABASE__HOST=env-db.example.com
export APP__DATABASE__PORT=3306
export APP__DATABASE__USERNAME=envuser
export APP__DATABASE__PASSWORD=envpass
Código Python:
from pydantic import BaseModel
from typing import Dict, Any
from config_loader import load_config
class AppConfig(BaseModel):
debug: bool = False
database: Dict[str, Any]
# use_env=True habilita los overrides desde variables de entorno
config = load_config(
AppConfig,
paths=["config/base.yaml"],
use_env=True,
env_prefix="APP"
)
# Salida
print(config.debug) # True (de ENV)
print(config.database["host"]) # "env-db.example.com" (de ENV)
print(config.database["port"]) # 3306 (de ENV, convertido a int)
print(config.database["username"]) # "envuser" (de ENV)
print(config.database["password"]) # "envpass" (de ENV)
Ejemplo 4: Combinación Completa (YAML + ENV)
Entrada - Archivo YAML (config/base.yaml):
app_name: MyApp
debug: false
database:
host: localhost
port: 5432
username: admin
password: secret
cache:
enabled: true
ttl: 3600
Entrada - Variables de Entorno:
export APP__DEBUG=true
export APP__DATABASE__HOST=prod-db.example.com
export APP__CACHE__TTL=7200
Código Python:
from pydantic import BaseModel
from typing import Dict, Any
from config_loader import load_config
class CacheConfig(BaseModel):
enabled: bool
ttl: int
class DatabaseConfig(BaseModel):
host: str
port: int
username: str
password: str
class AppConfig(BaseModel):
app_name: str
debug: bool
database: DatabaseConfig
cache: CacheConfig
config = load_config(
AppConfig,
paths=["config/base.yaml"],
use_env=True,
env_prefix="APP"
)
# Salida
print(config.app_name) # "MyApp" (del YAML)
print(config.debug) # True (de ENV, sobrescribe YAML)
print(config.database.host) # "prod-db.example.com" (de ENV)
print(config.database.port) # 5432 (del YAML, no sobrescrito)
print(config.database.username) # "admin" (del YAML)
print(config.database.password) # "secret" (del YAML)
print(config.cache.enabled) # True (del YAML)
print(config.cache.ttl) # 7200 (de ENV, sobrescribe YAML)
Ejemplo 5: Coerción Automática de Tipos
Las variables de entorno son siempre strings, pero config-loader las convierte automáticamente:
Entrada - Variables de Entorno:
export APP__DEBUG=true # String "true" → Boolean True
export APP__PORT=8000 # String "8000" → Integer 8000
export APP__TIMEOUT=30.5 # String "30.5" → Float 30.5
export APP__NAME=MyApp # String "MyApp" → String "MyApp"
Código Python:
from pydantic import BaseModel
from config_loader import load_config
class AppConfig(BaseModel):
debug: bool
port: int
timeout: float
name: str
config = load_config(
AppConfig,
paths=[], # Sin archivos YAML
use_env=True,
env_prefix="APP"
)
# Salida
print(config.debug) # True (bool)
print(config.port) # 8000 (int)
print(config.timeout) # 30.5 (float)
print(config.name) # "MyApp" (str)
🛠️ Desarrollo
Comandos Rápidos con Makefile
El proyecto incluye un Makefile para facilitar tareas comunes de desarrollo:
# Ver todos los comandos disponibles
make help
# Ejecutar verificaciones de calidad (Black, Flake8, Mypy)
make lint
# Auto-formatear código con Black
make format
# Ejecutar tests con reporte de cobertura
make test
# Construir paquete de distribución
make build
# Limpiar artefactos de build y cache
make clean
# Instalar paquete en modo producción
make install
# Instalar paquete con dependencias de desarrollo
make dev-install
Flujo de Desarrollo Recomendado
- Hacer cambios en el código
- Formatear automáticamente:
make format - Verificar calidad:
make lint - Ejecutar tests:
make test
- Si todo pasa, hacer commit
🛠️ Configuración del Ambiente de Desarrollo
Requisitos Previos
- Python 3.7 o superior
- pip (gestor de paquetes de Python)
- git (para clonar el repositorio)
Pasos de Instalación
1. Clonar el repositorio
git clone https://github.com/dev-brainstack/config-loader.git
cd config-loader
2. Crear un ambiente virtual (recomendado)
# En Linux/macOS
python3 -m venv .venv
source .venv/bin/activate
# En Windows
python -m venv .venv
.venv\Scripts\activate
3. Instalar dependencias de desarrollo
pip install -e ".[dev]"
Esto instala:
- config-loader en modo editable (cambios se reflejan inmediatamente)
- pytest - Framework de testing
- pytest-cov - Cobertura de código
- black - Formateador de código
- flake8 - Linter
- mypy - Type checker
4. Verificar la instalación
# Ejecutar tests
pytest
# Ver cobertura de código
pytest --cov=src --cov-report=html
# Verificar formato de código
black --check src/
# Ejecutar linter
flake8 src/
# Type checking
mypy src/
Estructura del Proyecto
config-loader/
├── .clinerules/ # Documentación interna
├── .gitignore
├── pyproject.toml # Configuración del proyecto
├── README.md # Este archivo
├── requirements.txt # Dependencias (alternativa a pip)
├── src/
│ └── config_loader/ # Código fuente
│ ├── __init__.py # API pública
│ ├── loader.py # Orquestación principal
│ ├── env.py # Manejo de variables de entorno
│ ├── exceptions.py # Excepciones personalizadas
│ ├── types.py # Definiciones de tipos
│ └── utils.py # Utilidades internas
├── test/
│ └── test_loader.py # Suite de tests (60+ tests)
└── openspec/ # Documentación de cambios
Comandos Útiles para Desarrollo
# Ejecutar todos los tests
pytest
# Ejecutar tests con salida detallada
pytest -v
# Ejecutar un archivo de test específico
pytest test/test_loader.py
# Ejecutar un test específico
pytest test/test_loader.py::test_load_config_simple
# Ver cobertura de código
pytest --cov=src --cov-report=term-missing
# Generar reporte HTML de cobertura
pytest --cov=src --cov-report=html
# Abre htmlcov/index.html en el navegador
# Formatear código con black
black src/ test/
# Verificar formato sin cambiar archivos
black --check src/ test/
# Ejecutar linter
flake8 src/ test/
# Type checking
mypy src/
# Ejecutar todo (tests + coverage + lint + type check)
pytest && black --check src/ && flake8 src/ && mypy src/
Flujo de Desarrollo Típico
-
Crear una rama para tu cambio:
git checkout -b feature/mi-cambio
-
Hacer cambios en el código
-
Ejecutar tests para verificar:
pytest
-
Formatear código:
black src/ -
Verificar linting:
flake8 src/ -
Hacer commit:
git add . git commit -m "Descripción del cambio"
-
Push a GitHub:
git push origin feature/mi-cambio
📖 API Reference
load_config()
Función principal para cargar y validar configuración.
def load_config(
model_class: Type[T],
paths: List[str],
use_env: bool = True,
env_prefix: str = ""
) -> T:
"""
Carga configuración desde múltiples YAML + ENV + Validación.
Args:
model_class: Clase Pydantic que define el esquema de configuración
paths: Lista de rutas a archivos YAML (orden = prioridad)
use_env: Habilitar overrides desde variables de entorno (default: True)
env_prefix: Prefijo para filtrar variables de entorno (default: "")
Returns:
Instancia del modelo validado
Raises:
ConfigFileNotFoundError: Si un archivo YAML no existe
ConfigParseError: Si hay error al parsear YAML
ConfigTypeError: Si la estructura no es válida
ConfigValidationError: Si la validación Pydantic falla
"""
Ejemplo:
config = load_config(
AppConfig,
paths=["config/base.yaml", "config/production.yaml"],
use_env=True,
env_prefix="APP"
)
Excepciones
ConfigError (base)
Excepción base para todos los errores de configuración.
ConfigFileNotFoundError
Se lanza cuando un archivo YAML no existe.
try:
config = load_config(AppConfig, paths=["nonexistent.yaml"])
except ConfigFileNotFoundError as e:
print(f"Archivo no encontrado: {e.path}")
ConfigParseError
Se lanza cuando hay error al parsear YAML.
try:
config = load_config(AppConfig, paths=["invalid.yaml"])
except ConfigParseError as e:
print(f"Error parseando {e.path}: {e.original_error}")
ConfigTypeError
Se lanza cuando la estructura no es válida.
try:
config = load_config(AppConfig, paths=["config.yaml"])
except ConfigTypeError as e:
print(f"Se esperaba {e.expected}, se recibió {e.received}")
ConfigValidationError
Se lanza cuando la validación Pydantic falla.
try:
config = load_config(AppConfig, paths=["config.yaml"])
except ConfigValidationError as e:
print(f"Error de validación: {e.raw_message}")
⚠️ Manejo de Errores
Ejemplo Completo
from config_loader import load_config, ConfigError
from config_loader.exceptions import (
ConfigFileNotFoundError,
ConfigParseError,
ConfigValidationError
)
try:
config = load_config(
AppConfig,
paths=["config/base.yaml"],
use_env=True,
env_prefix="APP"
)
except ConfigFileNotFoundError as e:
print(f"❌ Archivo no encontrado: {e.path}")
exit(1)
except ConfigParseError as e:
print(f"❌ Error parseando YAML: {e.original_error}")
exit(1)
except ConfigValidationError as e:
print(f"❌ Configuración inválida: {e.raw_message}")
exit(1)
except ConfigError as e:
print(f"❌ Error de configuración: {e}")
exit(1)
print("✅ Configuración cargada exitosamente")
📋 Convenciones
Convención de Variables de Entorno
Las variables de entorno siguen la convención PREFIX__NESTED__KEY:
APP__DEBUG=true
APP__DATABASE__HOST=localhost
APP__DATABASE__PORT=5432
APP__CACHE__REDIS__HOST=redis.local
Se convierte en:
{
"debug": True,
"database": {
"host": "localhost",
"port": 5432
},
"cache": {
"redis": {
"host": "redis.local"
}
}
}
Reglas de Coerción de Tipos
Las variables de entorno se convierten automáticamente:
| Valor ENV | Tipo Detectado | Resultado |
|---|---|---|
"true" o "false" |
Boolean | True o False |
"123" |
Integer | 123 |
"45.67" |
Float | 45.67 |
"hello" |
String | "hello" |
Precedencia de Configuración
- Archivos YAML - Base (primer archivo)
- Archivos YAML - Overrides (archivos posteriores sobrescriben anteriores)
- Variables de Entorno - Máxima prioridad (sobrescriben todo)
base.yaml → override.yaml → ENV vars
↓ ↓ ↓
└────────────┴────────────┘
Configuración Final
🧪 Testing
El proyecto incluye una suite completa de tests con >90% de cobertura.
# Ejecutar todos los tests
pytest
# Ver cobertura detallada
pytest --cov=src --cov-report=term-missing
# Generar reporte HTML
pytest --cov=src --cov-report=html
🔄 GitHub Actions Pipelines
El proyecto utiliza dos pipelines de GitHub Actions para automatizar la validación y el lanzamiento de versiones.
CI Pipeline
Cuándo se ejecuta:
- En cada Pull Request (creación y actualizaciones)
- En cada push a la rama main
Qué valida:
- ✅ Formato de código (Black)
- ✅ Linting (Flake8)
- ✅ Tests unitarios e integración
- ✅ Cobertura de código
Requisitos:
- Python 3.9
- Todas las dependencias de desarrollo instaladas
Si falla:
- El Pull Request no puede ser mergeado a main
- Se bloquea el merge hasta que se corrijan los errores
Pasos del pipeline:
- Checkout del código
- Setup de Python 3.9
- Instalación de dependencias (
pip install -e ".[dev]") - Verificación de formato (
make format) - Ejecución de tests (
make test)
Release Pipeline
Cuándo se ejecuta:
- Solo en pushes a la rama main (después de merges)
- NO se ejecuta en Pull Requests
Qué hace:
- Analiza los commits desde el último release
- Determina el tipo de versión a crear (major, minor, patch)
- Crea un tag de versión en GitHub
- Publica el paquete en PyPI
- Genera notas de release automáticamente
Requisitos:
- Python 3.9
- Tokens de autenticación (GH_TOKEN, PYPI_API_TOKEN)
Cómo funciona:
- Lee los mensajes de commit
- Usa semantic versioning para determinar el bump de versión
- Crea releases automáticamente basadas en los tipos de commits
Comparación de Pipelines
| Aspecto | CI Pipeline | Release Pipeline |
|---|---|---|
| Trigger | PR + push a main | Push a main |
| Propósito | Validar código | Crear releases |
| Validaciones | Format, Lint, Tests | Tests + Semantic Release |
| Bloquea merge | Sí | No |
| Crea releases | No | Sí |
| Publica a PyPI | No | Sí |
Flujo de Ejecución
Developer crea PR
↓
CI Pipeline ejecuta (format, lint, tests)
↓
¿Pasa CI? → No → PR bloqueado, developer corrige
↓ Sí
Code review y aprobación
↓
Merge a main
↓
Release Pipeline ejecuta
↓
Analiza commits desde último release
↓
¿Hay cambios que justifiquen release? → No → Fin
↓ Sí
Determina versión (feat→minor, fix→patch)
↓
Crea tag y release en GitHub
↓
Publica en PyPI
↓
Fin
🌿 Branching Strategy
El proyecto utiliza una estrategia de branching simple pero efectiva.
Estructura de Branches
Main Branch
- Rama principal donde reside el código en producción
- Solo acepta cambios a través de Pull Requests
- Todos los commits en main deben pasar CI
- Protegida contra pushes directos
Feature Branches
- Ramas temporales para desarrollar nuevas características o fixes
- Se crean desde main
- Se eliminan después de mergear a main
- Convención de nombres:
feature/<descripción>ofix/<descripción>
Flujo de Trabajo
1. Crear rama desde main
git checkout -b feature/nueva-caracteristica
2. Hacer cambios y commits
git add .
git commit -m "feat: agregar nueva caracteristica"
3. Push a GitHub
git push origin feature/nueva-caracteristica
4. Crear Pull Request
- Describe los cambios
- Espera a que CI pase
- Solicita revisión de código
5. Code Review
- Otros desarrolladores revisan
- Sugieren cambios si es necesario
- Aprueban cuando está listo
6. Merge a main
- Squash o merge según preferencia
- CI ejecuta nuevamente
- Release pipeline se ejecuta si hay cambios que justifiquen release
7. Eliminar rama
- GitHub ofrece eliminar automáticamente
- O manualmente: git branch -d feature/nueva-caracteristica
Reglas de Branch Protection
- ✅ Requiere Pull Request para cambios
- ✅ Requiere que CI pase antes de merge
- ✅ Requiere revisión de código (recomendado)
- ✅ Bloquea pushes directos a main
Mejores Prácticas
- Mantén branches pequeñas y enfocadas
- Crea un PR por cada feature/fix
- Actualiza tu rama con main antes de mergear
- Resuelve conflictos localmente antes de push
- Elimina branches después de mergear
📝 Commit Conventions
El proyecto utiliza Semantic Commit Conventions para automatizar el versionado.
Formato de Commits
<tipo>: <descripción>
[cuerpo opcional]
[pie opcional]
Ejemplo:
feat: agregar soporte para archivos JSON
Permite cargar configuración desde archivos JSON además de YAML.
Implementa parser JSON con validación de esquema.
BREAKING CHANGE: El parámetro 'format' ahora es requerido
Tipos de Commits
| Tipo | Descripción | ¿Release? | Versión |
|---|---|---|---|
feat |
Nueva característica | ✅ Sí | Minor (1.0.0 → 1.1.0) |
fix |
Corrección de bug | ✅ Sí | Patch (1.0.0 → 1.0.1) |
perf |
Mejora de performance | ✅ Sí | Patch (1.0.0 → 1.0.1) |
docs |
Cambios en documentación | ❌ No | - |
chore |
Tareas de mantenimiento | ❌ No | - |
test |
Cambios en tests | ❌ No | - |
refactor |
Refactorización de código | ❌ No | - |
Ejemplos de Commits
Feature (crea release minor):
feat: agregar soporte para TOML
feat: implementar hot-reloading de configuración
feat: agregar validación de esquema JSON
Fix (crea release patch):
fix: corregir parsing de YAML anidado
fix: resolver memory leak en merge profundo
fix: manejar variables de entorno vacías
Performance (crea release patch):
perf: optimizar merge de diccionarios grandes
perf: cachear archivos YAML parseados
Documentation (NO crea release):
docs: actualizar README con ejemplos
docs: agregar guía de contribución
docs: documentar API de excepciones
Chore (NO crea release):
chore: actualizar dependencias
chore: configurar pre-commit hooks
chore: limpiar código legacy
Test (NO crea release):
test: agregar tests para edge cases
test: aumentar cobertura a 95%
test: agregar tests de integración
Refactor (NO crea release):
refactor: simplificar lógica de merge
refactor: extraer funciones comunes
refactor: mejorar nombres de variables
Breaking Changes
Para cambios que rompen compatibilidad, agrega BREAKING CHANGE: en el cuerpo:
feat: cambiar firma de load_config
BREAKING CHANGE: El parámetro 'env_prefix' ahora es requerido
Esto crea un release major (1.0.0 → 2.0.0).
🔄 Development Workflow
Flujo completo de desarrollo desde idea hasta producción.
Paso 1: Crear una Rama
# Actualizar main
git checkout main
git pull origin main
# Crear rama para tu trabajo
git checkout -b feature/mi-caracteristica
Paso 2: Hacer Cambios
# Editar archivos
# Agregar tests
# Actualizar documentación
Paso 3: Commit Local
# Ver cambios
git status
# Agregar cambios
git add .
# Commit con mensaje semántico
git commit -m "feat: agregar nueva caracteristica"
Paso 4: Verificar Localmente
# Ejecutar tests
make test
# Verificar formato
make format
# Verificar linting
make lint
Paso 5: Push a GitHub
# Push de la rama
git push origin feature/mi-caracteristica
Paso 6: Crear Pull Request
- Ve a GitHub
- Haz click en "Compare & pull request"
- Describe los cambios
- Espera a que CI pase
Paso 7: Code Review
- Otros desarrolladores revisan
- Responde a comentarios
- Haz cambios si es necesario
- Solicita re-review
Paso 8: Merge
Una vez aprobado:
# GitHub: Click en "Merge pull request"
# O desde línea de comandos:
git checkout main
git pull origin main
git merge feature/mi-caracteristica
git push origin main
Paso 9: Cleanup
# Eliminar rama local
git branch -d feature/mi-caracteristica
# Eliminar rama remota
git push origin --delete feature/mi-caracteristica
Qué Sucede Después del Merge
- CI Pipeline ejecuta - Valida el código en main
- Release Pipeline ejecuta - Analiza commits
- Si hay cambios que justifiquen release:
- Crea nuevo tag de versión
- Publica en PyPI
- Genera release notes en GitHub
📊 Semantic Versioning
El proyecto utiliza Semantic Versioning (SemVer) para versiones.
Formato de Versión
MAJOR.MINOR.PATCH
↓ ↓ ↓
1 2 3
- MAJOR: Cambios incompatibles (breaking changes)
- MINOR: Nuevas características (backward compatible)
- PATCH: Correcciones de bugs (backward compatible)
Ejemplos de Progresión
Scenario 1: Múltiples fixes
1.0.0
↓ (fix: corregir parsing)
1.0.1
↓ (fix: manejar edge case)
1.0.2
Scenario 2: Feature + fixes
1.0.0
↓ (feat: agregar JSON support)
1.1.0
↓ (fix: corregir JSON parsing)
1.1.1
Scenario 3: Breaking change
1.0.0
↓ (feat: cambiar API - BREAKING CHANGE)
2.0.0
Cómo Funciona el Versionado Automático
- Merge a main → Release Pipeline ejecuta
- Analiza commits desde último tag
- Determina tipo de cambio:
- ¿Hay
feat:? → MINOR bump - ¿Hay
fix:operf:? → PATCH bump - ¿Solo
docs:,chore:, etc.? → Sin release
- ¿Hay
- Crea nuevo tag con versión calculada
- Publica en PyPI con nueva versión
Verificar Versión Actual
# Ver último tag
git describe --tags
# Ver todos los tags
git tag -l
# Ver releases en GitHub
# https://github.com/dev-brainstack/config-loader/releases
✨ Best Practices
Recomendaciones para trabajar efectivamente con el proyecto.
Commits
- ✅ Commits atómicos: Un cambio lógico por commit
- ✅ Mensajes claros: Describe QUÉ y POR QUÉ
- ✅ Usa tipos semánticos: feat, fix, docs, etc.
- ✅ Minúsculas:
feat:noFeat: - ❌ Evita: Commits genéricos como "fix stuff" o "update"
Buen commit:
feat: agregar validación de esquema JSON
Implementa validación de esquema JSON usando jsonschema.
Permite a usuarios validar configuración contra esquemas.
Mal commit:
fix stuff
Branches
- ✅ Nombres descriptivos:
feature/json-support,fix/yaml-parsing - ✅ Ramas cortas: Completa en 1-2 días
- ✅ Actualiza desde main: Antes de mergear
- ❌ Evita: Branches de larga vida, nombres genéricos
Pull Requests
- ✅ Descripción clara: Explica QUÉ y POR QUÉ
- ✅ PRs pequeños: Más fáciles de revisar
- ✅ Tests incluidos: Nuevas features deben tener tests
- ✅ CI debe pasar: Antes de merge
- ❌ Evita: PRs gigantes, sin descripción
Buen PR:
## Descripción
Agrega soporte para archivos de configuración JSON.
## Cambios
- Implementa parser JSON
- Agrega validación de esquema
- Incluye 15 nuevos tests
## Testing
- Todos los tests pasan
- Cobertura aumenta a 95%
Code Review
- ✅ Sé constructivo: Sugiere mejoras, no critiques
- ✅ Sé rápido: Revisa en 24 horas
- ✅ Aprende: Usa reviews para aprender
- ❌ Evita: Bloquear sin razón, comentarios vagos
Testing
- ✅ Tests para nuevas features: Siempre
- ✅ Tests para bugs: Antes de fix
- ✅ Mantén cobertura >90%: Objetivo del proyecto
- ✅ Tests claros: Nombres descriptivos
- ❌ Evita: Tests que pasan por suerte
Documentación
- ✅ Actualiza README: Si cambias comportamiento
- ✅ Docstrings claros: En funciones públicas
- ✅ Ejemplos: Para features complejas
- ❌ Evita: Documentación desactualizada
Errores Comunes
-
Commit directo a main
- ❌ Incorrecto:
git push origin main - ✅ Correcto: Crear PR, pasar CI, mergear
- ❌ Incorrecto:
-
Mensaje de commit vago
- ❌ Incorrecto:
fix: bug - ✅ Correcto:
fix: corregir parsing de YAML anidado
- ❌ Incorrecto:
-
PR sin tests
- ❌ Incorrecto: Feature sin tests
- ✅ Correcto: Feature + tests + documentación
-
Ignorar CI failures
- ❌ Incorrecto: Mergear con CI rojo
- ✅ Correcto: Corregir errores, pasar CI
-
Branches no actualizadas
- ❌ Incorrecto: Mergear sin actualizar desde main
- ✅ Correcto:
git rebase origin/mainantes de merge
🔧 Troubleshooting
Soluciones para problemas comunes.
CI Pipeline Failures
Error: Format Check Failed
Problema: Black detecta código mal formateado
Solución:
# Auto-formatear código
make format
# O manualmente
black src/ test/
# Commit cambios
git add .
git commit -m "style: formatear código"
git push
Error: Tests Failed
Problema: Uno o más tests fallan
Solución:
# Ver qué tests fallan
pytest -v
# Ver detalles del error
pytest -v --tb=long
# Ejecutar test específico
pytest test/test_loader.py::test_name -v
# Corregir código
# ...
# Verificar que pasa
pytest
# Commit
git add .
git commit -m "fix: corregir test fallido"
git push
Error: Linting Failed
Problema: Flake8 detecta problemas de estilo
Solución:
# Ver errores
flake8 src/
# Corregir manualmente o con herramientas
# Algunos errores se pueden auto-corregir con black
# Verificar
flake8 src/
# Commit
git add .
git commit -m "style: corregir linting"
git push
Merge Conflicts
Problema: Conflicto al mergear rama
Solución:
# Actualizar rama desde main
git fetch origin
git rebase origin/main
# O merge (menos limpio)
git merge origin/main
# Resolver conflictos manualmente
# Editar archivos con conflictos
# Buscar marcadores: <<<<<<<, =======, >>>>>>>
# Después de resolver
git add .
git rebase --continue # Si usaste rebase
# O
git commit -m "Merge main" # Si usaste merge
# Push
git push origin feature/mi-rama --force-with-lease
Pull Request Feedback
Problema: Reviewer solicita cambios
Solución:
# Hacer cambios solicitados
# Editar archivos
# Commit con cambios
git add .
git commit -m "Cambios solicitados en review"
# Push (actualiza automáticamente el PR)
git push origin feature/mi-rama
# Responder en GitHub indicando que hiciste los cambios
Check Pipeline Status
Problema: Quiero ver el estado del CI/Release pipeline
Solución:
# En GitHub:
# 1. Ve a tu PR
# 2. Scroll down a "Checks"
# 3. Haz click en "Details" para ver logs
# O desde línea de comandos:
# Ver commits recientes
git log --oneline
# Ver tags (releases)
git tag -l
# Ver releases en GitHub
# https://github.com/dev-brainstack/config-loader/releases
Local Testing Before Push
Problema: Quiero verificar que todo pasa antes de push
Solución:
# Ejecutar todo localmente
make test # Tests
make format # Formateo
make lint # Linting
# O todo junto
pytest && black --check src/ && flake8 src/ && mypy src/
# Si todo pasa, push con confianza
git push origin feature/mi-rama
📝 Licencia
MIT License - Ver LICENSE para más detalles.
🤝 Contribuciones
Las contribuciones son bienvenidas. Por favor:
- Fork el repositorio
- Crea una rama para tu cambio (
git checkout -b feature/mi-cambio) - Commit tus cambios (
git commit -am 'Agrega mi cambio') - Push a la rama (
git push origin feature/mi-cambio) - Abre un Pull Request
📞 Soporte
Para reportar bugs o sugerir mejoras, abre un issue en: https://github.com/dev-brainstack/config-loader/issues
Hecho con ❤️ por el equipo de desarrollo
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file brainstack_config_loader-0.1.1.tar.gz.
File metadata
- Download URL: brainstack_config_loader-0.1.1.tar.gz
- Upload date:
- Size: 38.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b3a4ccc5e0cc07ac18ebe4250ad44d47ecbeafe2fadf9227f41a602c6095f4f9
|
|
| MD5 |
9c2081b96d885d4c54308107a573d715
|
|
| BLAKE2b-256 |
9faea968f870e2ac920540b6ca244a1462a77441ebc7e433e40018024ab7674a
|
File details
Details for the file brainstack_config_loader-0.1.1-py3-none-any.whl.
File metadata
- Download URL: brainstack_config_loader-0.1.1-py3-none-any.whl
- Upload date:
- Size: 17.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6c0e69ea1d68b4e9016aeace8aa2e58847fc2dfcfab3df7e2f02dd8d9d0b943b
|
|
| MD5 |
6071a32207c2c1b855b1590342162717
|
|
| BLAKE2b-256 |
4a85edef2325b71a6ff3133d55317ce54af98b320a8552db17a96d8e77363ead
|