Requisitos#

Comprender las dependencias de Python de Construbot y cómo gestionarlas.

Descripción general#

Construbot utiliza un enfoque estructurado para la gestión de dependencias con archivos de requisitos separados para diferentes entornos:

  • base.in / base.txt - Dependencias principales (compartidas en todos los entornos)

  • local.in / local.txt - Herramientas y utilidades de desarrollo

  • test.in / test.txt - Marcos y herramientas de prueba

  • production.txt - Dependencias de producción (heredadas de la base)

Nota

Archivos `.in`: Archivos fuente con dependencias de alto nivel

Archivos `.txt`: Archivos compilados con versiones fijadas (generadas por pip-compile)

Estructura de requisitos#

Organización de archivos#

requirements/
├── base.in          # Source: core dependencies
├── base.txt         # Compiled: pinned core dependencies
├── local.in         # Source: development dependencies
├── local.txt        # Compiled: pinned development dependencies
├── test.in          # Source: testing dependencies
├── test.txt         # Compiled: pinned testing dependencies
└── production.txt   # Production (just includes base.txt)

Flujo de trabajo:

  1. Edite archivos .in para agregar/eliminar paquetes

  2. Ejecute make pipcompile para generar archivos .txt

  3. Instale desde archivos .txt con pip install -r requisitos/<env>.txt

Dependencias principales (base.txt)#

Django y Extensiones#

Django 3.2.19:

Django==3.2.19

Versión de soporte a largo plazo (LTS) con actualizaciones de seguridad hasta abril de 2024.

Extensiones de Django:

django-environ==0.9.0        # Environment variable management
django-model-utils==4.2.0    # Model utilities and mixins
django-allauth==0.51.0       # Authentication and registration
django-crispy-forms==1.14.0  # Form rendering
django-bootstrap4==22.1      # Bootstrap 4 integration
django-treebeard==4.5.1      # Tree structures (hierarchical contracts)
django-compressor==4.0       # Static file compression
django-autocomplete-light==3.9.4  # Autocomplete widgets

¿Por qué estas extensiones?

  • django-environ: Administre la configuración a través de variables de entorno (aplicación de 12 factores)

  • django-allauth: Autenticación completa con correo electrónico, autenticación social

  • django-treebeard: Estructura de contrato jerárquica (ruta materializada)

  • django-autocomplete-light: Widgets de selección fáciles de usar para claves externas

Base de datos y almacenamiento en caché#

psycopg2-binary==2.9.6       # PostgreSQL adapter
redis==4.3.4                 # Redis client
hiredis==2.0.0               # C parser for Redis (performance)

¿Por qué PostgreSQL?

  • Cumplimiento ACID para datos financieros

  • Funciones avanzadas (campos JSON, búsqueda de texto completo)

  • Listo para producción y escalable

¿Por qué Redis?

  • Capa de almacenamiento en caché para rendimiento

  • Corredor de mensajes de apio

  • Almacenamiento de sesiones (opcional)

API DESCANSO#

djangorestframework==3.13.1           # REST framework
djangorestframework-simplejwt==5.2.0  # JWT authentication
django-cors-headers==3.13.0           # CORS support
drf-yasg==1.21.3                      # API documentation

Características:

  • Autenticación de token JWT (sin estado)

  • API navegable para desarrollo

  • Documentación API automática con Swagger

Cola de tareas#

celery==5.2.7                # Distributed task queue
django-celery-beat==2.4.0    # Periodic tasks
flower==1.2.0                # Celery monitoring

Casos de uso:

  • Envío de correos electrónicos de forma asincrónica

  • Generando informes PDF en segundo plano

  • Sincronización de datos programada

Generación de documentos#

reportlab==3.6.12            # PDF generation
openpyxl==3.0.10             # Excel file handling
Pillow==9.3.0                # Image processing

Características:

  • Generar presupuestos de construcción como PDF

  • Importar datos del catálogo desde Excel

  • Procesar imágenes cargadas

Correo electrónico#

django-anymail[mailgun]==9.0  # Email service integration

Proveedores admitidos:

  • pistola de correo

  • EnviarGrid

  • Matasellos

  • Amazon SES

Utilidades#

python-slugify==6.1.2        # Slug generation
python-dateutil==2.8.2       # Date utilities
pytz==2022.6                 # Timezone support
argon2-cffi==21.3.0          # Password hashing

¿Por qué Argón2?

  • Más seguro que PBKDF2 o bcrypt

  • Recomendado por OWASP

  • Resistente a ataques GPU/ASIC

Dependencias de desarrollo (local.txt)#

Herramientas de depuración#

django-debug-toolbar==3.7.0     # Debug panel
django-extensions==3.2.1        # Shell_plus, runserver_plus, etc.
ipython==8.5.0                  # Enhanced Python shell
Werkzeug==2.2.2                 # Debugger for runserver_plus

Uso:

# Enhanced Django shell with auto-imports
python manage.py shell_plus

# Run server with Werkzeug debugger
python manage.py runserver_plus

Calidad del código#

pylint==2.15.5                  # Linting
pylint-django==2.5.3            # Django-specific linting
black==22.10.0                  # Code formatting
isort==5.10.1                   # Import sorting
flake8==5.0.4                   # Style enforcement

Ganchos de confirmación previa:

# Format code
black .

# Sort imports
isort .

# Check linting
pylint construbot/

Documentación#

Sphinx==6.2.1                   # Documentation generator
sphinx-rtd-theme==1.3.0         # ReadTheDocs theme
sphinx-autobuild==2021.3.14     # Auto-rebuild docs

Documentos de compilación:

cd docs
make html
make livehtml  # Auto-rebuild on changes

Prueba de dependencias (test.txt)#

Marcos de prueba#

pytest==7.2.0                   # Test framework
pytest-django==4.5.2            # Django integration
pytest-cov==4.0.0               # Coverage plugin
pytest-sugar==0.9.6             # Better test output
coverage==6.5.0                 # Coverage measurement
django-coverage-plugin==2.0.4   # Django template coverage

¿Por qué pytest en lugar del integrado de Django?

  • Mejores accesorios y parametrización.

  • Sintaxis de prueba más limpia

  • Rico ecosistema de complementos

  • Mejor formato de salida

Utilidades de prueba#

factory-boy==3.2.1              # Test data factories
faker==15.3.4                   # Fake data generation
freezegun==1.2.2                # Time mocking

Uso de ejemplo:

# factories.py
import factory
from faker import Faker

fake = Faker()

class UserFactory(factory.django.DjangoModelFactory):
    class Meta:
        model = User

    email = factory.Sequence(lambda n: f'user{n}@example.com')
    first_name = factory.LazyAttribute(lambda _: fake.first_name())

# In tests
user = UserFactory()

Dependencias de producción (producción.txt)#

-r base.txt                     # Includes all base dependencies

# Production-specific
gunicorn==20.1.0                # WSGI server
whitenoise==6.2.0               # Static file serving
sentry-sdk==1.11.1              # Error tracking
django-storages[boto3]==1.13.1  # S3 storage backend

¿Por qué estas adiciones?

  • gunicorn: Servidor WSGI de producción (no servidor de ejecución)

  • whitenoise: Servicio eficiente de archivos estáticos

  • sentry-sdk: Seguimiento y supervisión de errores

  • django-storages: Almacena archivos multimedia en S3

Gestión de dependencias#

Instalación de dependencias#

Desarrollo:

pip install -r requirements/local.txt

Pruebas:

pip install -r requirements/test.txt

Producción:

pip install -r requirements/production.txt

Agregar nuevas dependencias#

Paso 1: Agregar al archivo .in apropiado

# Edit requirements/base.in
echo "requests>=2.28.0" >> requirements/base.in

Paso 2: Compile los requisitos

make pipcompile

Esto ejecuta pip-compile en todos los archivos .in y genera archivos .txt con versiones fijadas.

Paso 3: Instalar nuevos requisitos

pip install -r requirements/local.txt

Paso 4: Confirma ambos archivos

git add requirements/base.in requirements/base.txt
git commit -m "Add requests library"

Actualización de dependencias#

Actualizar paquete específico:

# Edit .in file with new version constraint
# Then recompile
make pipcompile

Actualizar todos los paquetes:

# Install pip-tools
pip install pip-tools

# Upgrade all packages
pip-compile --upgrade requirements/base.in
pip-compile --upgrade requirements/local.in
pip-compile --upgrade requirements/test.in

Entorno de sincronización:

pip-sync requirements/local.txt

Eliminar dependencias#

Paso 1: Eliminar del archivo .in

# Edit requirements/base.in and remove the package

Paso 2: Recompilar

make pipcompile

Paso 3: Desinstalar el paquete

pip uninstall <package-name>

# Or sync to ensure clean state
pip-sync requirements/local.txt

Versiones de fijación#

¿Por qué fijar versiones?#

Beneficios:

  • Reproducibilidad: El mismo entorno siempre

  • Estabilidad: Evite cambios importantes

  • Seguridad: Controla cuándo actualizar

Acercarse:

  • Anclar versiones exactas en archivos .txt (Django==3.2.19)

  • Usar rangos en archivos .in (Django>=3.2,<4.0)

Restricciones de versión#

# Exact version (compiled .txt files)
Django==3.2.19

# Minimum version (.in files)
Django>=3.2

# Version range (.in files)
Django>=3.2,<4.0

# Compatible release (.in files)
Django~=3.2.0  # Equivalent to >=3.2.0,<3.3.0

Actualizaciones de seguridad#

Compruebe si hay vulnerabilidades:

# Install safety
pip install safety

# Check dependencies
safety check

# Or use pip-audit
pip install pip-audit
pip-audit

Actualizar paquetes vulnerables:

# Update constraint in .in file
# Recompile and test
make pipcompile
make test

Análisis de dependencia#

Ver árbol de dependencias#

# Install pipdeptree
pip install pipdeptree

# Show dependency tree
pipdeptree

# Show reversed dependencies
pipdeptree -r -p django

# Find conflicts
pipdeptree --warn

Buscar dependencias no utilizadas#

# Install pip-check
pip install pip-check

# Check for unused packages
pip-check

Buscar actualizaciones#

# List outdated packages
pip list --outdated

# Show latest versions
pip-outdated

Problemas comunes#

Conflictos de dependencia#

Error: «No se pueden instalar el paquete a y el paquete b»

Solución: Verifique las restricciones de dependencia

# Find conflicting requirements
pipdeptree --warn

# Update constraints in .in files
# Recompile
make pipcompile

Errores de compilación#

Error: «No se pudo encontrar una versión que cumpla con el requisito»

Causa: Restricciones de versión incompatibles

Solución:

# Check .in files for version conflicts
# Relax constraints if needed
# Try compiling with --resolver=backtracking
pip-compile --resolver=backtracking requirements/base.in

Fallos de instalación#

Error: «Error en la rueda de construcción para psycopg2»

Causa: Faltan encabezados de desarrollo de PostgreSQL

Solución:

# macOS
brew install postgresql

# Ubuntu/Debian
sudo apt-get install libpq-dev python3-dev

Error: «Error en la rueda de construcción de Pillow»

Causa: Faltan bibliotecas de imágenes

Solución:

# macOS
brew install libjpeg libtiff

# Ubuntu/Debian
sudo apt-get install libjpeg-dev libtiff-dev

Problemas del entorno virtual#

Problema: Dependencias instaladas globalmente

Solución: Utilice siempre un entorno virtual

# Create venv
python3 -m venv venv

# Activate
source venv/bin/activate

# Verify
which python  # Should show venv path

Mejores prácticas#

  1. Utilice siempre archivos .in - No edite archivos .txt manualmente

  2. Fijar versiones exactas en .txt - Para reproducibilidad

  3. Utilice rangos en .in: permita flexibilidad durante la compilación

  4. Actualizaciones periódicas - Revisión mensual de dependencias

  5. Escaneo de seguridad - Utilice seguridad o auditoría pip

  6. Prueba después de las actualizaciones - Ejecute el conjunto de pruebas completo

  7. Motivos del documento - Agregue comentarios para restricciones inusuales

Flujo de trabajo de ejemplo#

# 1. Add new dependency
echo "requests>=2.28.0" >> requirements/base.in

# 2. Compile requirements
make pipcompile

# 3. Review changes
git diff requirements/base.txt

# 4. Install
pip install -r requirements/local.txt

# 5. Test
make test

# 6. Commit
git add requirements/
git commit -m "Add requests library for API integration"

Ver también#