Files
pagasis/backend/LINTING.md
T

483 lines
9.3 KiB
Markdown
Raw Normal View History

2025-10-15 23:45:32 -06:00
# Guía de Linting y Calidad de Código
Esta guía explica cómo usar las herramientas de linting y formateo configuradas en el proyecto para mantener un código Python de alta calidad siguiendo PEP8 y mejores prácticas.
## Tabla de Contenidos
- [Herramientas Configuradas](#herramientas-configuradas)
- [Instalación](#instalación)
- [Uso Rápido](#uso-rápido)
- [Herramientas Individuales](#herramientas-individuales)
- [Pre-commit Hooks](#pre-commit-hooks)
- [Integración con Docker](#integración-con-docker)
- [CI/CD](#cicd)
- [Configuración de IDEs](#configuración-de-ides)
## Herramientas Configuradas
### Formateo Automático
- **Black**: Formateador de código opinionado (PEP8)
- **isort**: Ordenador de imports
- **autopep8**: Corrector automático de PEP8
### Linting (Análisis Estático)
- **Flake8**: Verificador de estilo PEP8
- **pycodestyle**: Verificador oficial de PEP8
- **Pylint**: Analizador estático completo
- **Bandit**: Verificador de seguridad
### Type Checking
- **MyPy**: Verificador de tipos estáticos
- **django-stubs**: Type hints para Django
- **djangorestframework-stubs**: Type hints para DRF
### Testing
- **pytest**: Framework de testing
- **pytest-django**: Plugin para Django
- **pytest-cov**: Cobertura de tests
- **coverage**: Reporte de cobertura
## Instalación
### Opción 1: Usando Make (Recomendado)
```bash
# Instalar todas las dependencias de desarrollo
make install-dev
```
### Opción 2: Usando pip directamente
```bash
# Instalar dependencias de producción
pip install -r requirements.txt
# Instalar dependencias de desarrollo
pip install -r requirements-dev.txt
# Instalar pre-commit hooks
pre-commit install
```
### Opción 3: En Docker
```bash
# Construir imagen con herramientas de desarrollo
docker-compose exec backend pip install -r requirements-dev.txt
```
## Uso Rápido
### Formatear Código Automáticamente
```bash
# Usando Make
make format
# O manualmente
bash scripts/format.sh
```
Este comando ejecutará automáticamente:
1. **isort** - Ordena los imports
2. **black** - Formatea el código
3. **autopep8** - Aplica correcciones adicionales de PEP8
### Verificar Calidad de Código
```bash
# Usando Make
make lint
# O manualmente
bash scripts/lint.sh
```
Este comando ejecutará:
1. Black (verificación sin modificar)
2. isort (verificación)
3. Flake8 (PEP8)
4. Pylint (análisis estático)
5. Bandit (seguridad)
6. MyPy (type checking)
### Ver Todos los Comandos Disponibles
```bash
make help
```
## Herramientas Individuales
### Black - Formateador de Código
```bash
# Verificar formato sin modificar
black --check --diff .
# Formatear todo el código
black .
# Formatear archivo específico
black path/to/file.py
```
**Configuración**: `pyproject.toml` - Longitud de línea: 120
### isort - Ordenador de Imports
```bash
# Verificar imports sin modificar
isort --check-only --diff .
# Ordenar imports
isort .
# Ordenar archivo específico
isort path/to/file.py
```
**Configuración**: `pyproject.toml` - Compatible con Black
### Flake8 - Verificador PEP8
```bash
# Verificar todo el proyecto
flake8 .
# Verificar directorio específico
flake8 authentication/
# Verificar archivo específico
flake8 path/to/file.py
# Ignorar reglas específicas
flake8 --ignore=E501,W503 .
```
**Configuración**: `.flake8`
### Pylint - Análisis Estático
```bash
# Analizar todo el código
pylint authentication attendance events mac_attendance
# Analizar archivo específico
pylint path/to/file.py
# Generar reporte de calificación
pylint --output-format=text authentication/ | tee pylint-report.txt
```
**Configuración**: `pyproject.toml`
### Bandit - Verificador de Seguridad
```bash
# Verificar seguridad en todo el proyecto
bandit -r . -c pyproject.toml
# Verificar directorio específico
bandit -r authentication/
# Generar reporte detallado
bandit -r . -f json -o bandit-report.json
```
**Configuración**: `pyproject.toml`
### MyPy - Type Checking
```bash
# Verificar tipos
mypy --config-file=pyproject.toml .
# Verificar archivo específico
mypy path/to/file.py
# Generar reporte HTML
mypy --html-report mypy-report .
```
**Configuración**: `pyproject.toml`
## Pre-commit Hooks
Los pre-commit hooks ejecutan automáticamente las herramientas de linting antes de cada commit.
### Instalar Hooks
```bash
pre-commit install
```
### Ejecutar Hooks Manualmente
```bash
# Ejecutar en archivos staged
pre-commit run
# Ejecutar en todos los archivos
pre-commit run --all-files
# Usando Make
make pre-commit-all
```
### Saltar Hooks (No Recomendado)
```bash
git commit --no-verify -m "mensaje"
```
### Actualizar Hooks
```bash
pre-commit autoupdate
```
## Integración con Docker
### Ejecutar Linting en Docker
```bash
# Formatear código
docker-compose exec backend bash scripts/format.sh
# Verificar código
docker-compose exec backend bash scripts/lint.sh
# Usando Make
docker-compose exec backend make format
docker-compose exec backend make lint
```
### Agregar al Dockerfile
```dockerfile
# En Dockerfile.backend, agregar antes del CMD
COPY requirements-dev.txt .
RUN pip install -r requirements-dev.txt
# Ejecutar linting en el build
RUN flake8 . || true
```
## CI/CD
### GitHub Actions
Crear `.github/workflows/lint.yml`:
```yaml
name: Lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install -r backend/requirements-dev.txt
- name: Run linters
run: |
cd backend
make lint
```
### GitLab CI
Crear `.gitlab-ci.yml`:
```yaml
lint:
stage: test
image: python:3.11
script:
- cd backend
- pip install -r requirements-dev.txt
- make lint
```
## Configuración de IDEs
### Visual Studio Code
Crear `.vscode/settings.json`:
```json
{
"python.linting.enabled": true,
"python.linting.flake8Enabled": true,
"python.linting.pylintEnabled": true,
"python.linting.banditEnabled": true,
"python.linting.mypyEnabled": true,
"python.formatting.provider": "black",
"python.formatting.blackArgs": ["--line-length", "120"],
"python.sortImports.args": ["--profile", "black"],
"[python]": {
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true
}
},
"python.linting.flake8Args": ["--config=backend/.flake8"],
"python.linting.pylintArgs": ["--rcfile=backend/pyproject.toml"]
}
```
### PyCharm
1. **Configurar Black**:
- Settings → Tools → External Tools → Add
- Name: Black
- Program: `black`
- Arguments: `$FilePath$`
2. **Configurar Flake8**:
- Settings → Tools → External Tools → Add
- Name: Flake8
- Program: `flake8`
- Arguments: `$FilePath$`
3. **Configurar File Watcher**:
- Settings → Tools → File Watchers → Add
- File type: Python
- Program: `black`
## Métricas de Calidad
### Cobertura de Tests
```bash
# Ejecutar tests con cobertura
make coverage
# Ver reporte HTML
open htmlcov/index.html
```
### Complejidad Ciclomática
```bash
# Instalar radon
pip install radon
# Analizar complejidad
radon cc . -a -nb
# Generar reporte JSON
radon cc . -j > complexity-report.json
```
### Mantenibilidad
```bash
# Índice de mantenibilidad
radon mi . -s
# Mostrar solo archivos con baja mantenibilidad
radon mi . -s -n C
```
## Consejos y Mejores Prácticas
### 1. Formateo Automático
Ejecuta `make format` antes de cada commit para mantener el código formateado.
### 2. Pre-commit Hooks
Deja que los pre-commit hooks trabajen por ti. No los saltes a menos que sea absolutamente necesario.
### 3. Gradual
Si el proyecto tiene mucho código legacy, puedes aplicar linting gradualmente:
```bash
# Solo en archivos modificados
git diff --name-only | xargs flake8
```
### 4. Ignorar Reglas Específicas
Si necesitas ignorar una regla en una línea específica:
```python
# noqa: E501
long_line = "Esta línea es muy larga pero es necesaria" # noqa: E501
# Para múltiples reglas
code = "something" # noqa: E501,W503
```
### 5. Documentación
Mantén docstrings en funciones importantes:
```python
def calculate_attendance(student_id: int, event_id: int) -> float:
"""
Calcula el porcentaje de asistencia de un estudiante.
Args:
student_id: ID del estudiante
event_id: ID del evento
Returns:
Porcentaje de asistencia (0-100)
Raises:
ValueError: Si el estudiante o evento no existe
"""
pass
```
## Solución de Problemas
### Error: "command not found"
Asegúrate de haber instalado las dependencias:
```bash
make install-dev
```
### Error: "pre-commit: command not found"
```bash
pip install pre-commit
pre-commit install
```
### Conflictos entre Black e isort
La configuración está ajustada para que sean compatibles. Si hay conflictos:
```bash
# Ejecutar en orden
isort .
black .
```
### Demasiados errores de Flake8
Puedes ajustar las reglas en `.flake8` o formatear automáticamente:
```bash
make format
```
## Referencias
- [PEP 8 Style Guide for Python Code](https://peps.python.org/pep-0008/)
- [Black Documentation](https://black.readthedocs.io/)
- [Flake8 Documentation](https://flake8.pycqa.org/)
- [Pylint Documentation](https://pylint.pycqa.org/)
- [isort Documentation](https://pycqa.github.io/isort/)
- [Pre-commit Documentation](https://pre-commit.com/)