datadis_python.utils.http module
Cliente HTTP robusto y reutilizable para el SDK de Datadis.
Este módulo proporciona una clase HTTPClient especializada para realizar peticiones
HTTP a la API de Datadis con funcionalidades avanzadas como reintentos automáticos,
manejo de timeouts, gestión de headers y procesamiento de respuestas.
La clase está optimizada específicamente para las características de la API de Datadis: - Timeouts largos debido a la lentitud característica del servicio - Reintentos automáticos con backoff exponencial para manejar inestabilidad - Soporte para autenticación Bearer Token - Manejo especial de diferentes tipos de contenido (JSON, form-data, texto plano) - Procesamiento de respuestas con normalización de texto para caracteres especiales
- Características principales:
Gestión automática de reintentos: Backoff exponencial para timeouts y errores de red
Flexibilidad de contenido: Soporte para JSON y form-data según el endpoint
Manejo robusto de errores: Clasificación inteligente de errores HTTP
Integración con Pydantic: Preparado para validación de datos
Rate limiting integrado: Delays automáticos para evitar sobrecarga del servidor
Ejemplo
Uso básico del cliente HTTP:
from datadis_python.utils.http import HTTPClient
# Inicializar con configuración personalizada
client = HTTPClient(timeout=120, retries=5)
# Petición GET simple
response = client.make_request(
method="GET",
url="https://api.example.com/data",
params={"param1": "value1"}
)
# Petición POST con autenticación
client.set_auth_header("bearer_token_here")
response = client.make_request(
method="POST",
url="https://api.example.com/auth",
data={"username": "user", "password": "pass"},
use_form_data=True
)
# Cerrar recursos
client.close()
Uso como context manager (recomendado):
with HTTPClient(timeout=90, retries=3) as client:
client.set_auth_header("token")
response = client.make_request("GET", "https://api.example.com/data")
# El cliente se cierra automáticamente
Advertencia
Este cliente está específicamente optimizado para la API de Datadis. Para uso
general, considere usar directamente la biblioteca requests o un cliente
HTTP más genérico.
- author:
TacoronteRiveroCristian
- class datadis_python.utils.http.HTTPClient(timeout=60, retries=3)[fuente]
Bases:
objectCliente HTTP robusto especializado para la API de Datadis.
Esta clase proporciona una interfaz de alto nivel para realizar peticiones HTTP con características específicamente optimizadas para interactuar con la API de Datadis. Incluye manejo automático de reintentos, timeouts largos, gestión de autenticación y procesamiento especializado de respuestas.
- Optimizaciones para Datadis:
Timeouts largos: Por defecto 60s, recomendado 90-120s para Datadis
Reintentos robustos: Backoff exponencial con hasta 5 reintentos
Rate limiting: Delays automáticos para evitar sobrecarga del servidor
Manejo de encoding: Desactiva compresión gzip para evitar problemas
Procesamiento de texto: Normalización automática de caracteres especiales
- Estrategia de reintentos:
Errores de red y timeouts: Se reintentan automáticamente
Errores HTTP 4xx/5xx: Se propagan inmediatamente (no reintentos)
Backoff exponencial: 2s → 4s → 8s → 16s → 32s (máximo 10s para timeouts)
Error 401: Se propaga para permitir renovación de token
Ejemplo
Configuración típica para Datadis:
# Configuración robusta para API lenta de Datadis client = HTTPClient(timeout=120, retries=5) # Autenticación Bearer Token client.set_auth_header("jwt_token_from_datadis") # Petición con gestión automática de errores response = client.make_request( method="GET", url="https://datadis.es/api-private/api/get-supplies", params={"distributor_code": "2"} )
Diferentes tipos de contenido:
# Para autenticación (form-data) auth_response = client.make_request( method="POST", url="https://datadis.es/nikola-auth/tokens/login", data={"username": "12345678A", "password": "password"}, use_form_data=True ) # Para endpoints de datos (JSON, por defecto) data_response = client.make_request( method="GET", url="https://datadis.es/api-private/api/get-consumption-data", params={"cups": "ES001234567890123456AB"} )
- Parámetros:
Nota
La API de Datadis puede ser muy lenta (60-90 segundos) al procesar consultas complejas que requieren agregar datos de múltiples distribuidoras eléctricas.
Ver también
SimpleDatadisClientV1ySimpleDatadisClientV2para uso de alto nivelDocumentación oficial de Datadis para límites de rate limiting
- __init__(timeout=60, retries=3)[fuente]
Inicializa el cliente HTTP con configuración optimizada para Datadis.
Configura una sesión HTTP persistente con headers optimizados y timeouts apropiados para la API de Datadis. La configuración por defecto está pensada para un uso general, pero se recomienda ajustar los valores para Datadis.
- Configuración recomendada para Datadis:
timeout: 90-120 segundos (la API puede ser muy lenta)
retries: 3-5 reintentos (para manejar inestabilidad ocasional)
- Parámetros:
Ejemplo
Configuraciones típicas:
# Configuración conservadora (rápida, pocos reintentos) client = HTTPClient(timeout=60, retries=2) # Configuración robusta para Datadis (recomendada) client = HTTPClient(timeout=120, retries=5) # Configuración para desarrollo/testing (muy paciente) client = HTTPClient(timeout=180, retries=3)
- make_request(method, url, data=None, params=None, headers=None, use_form_data=False)[fuente]
Realiza una petición HTTP robusta con reintentos automáticos y manejo de errores.
Este método es el núcleo del cliente HTTP y maneja toda la lógica de peticiones incluyendo reintentos con backoff exponencial, manejo de diferentes tipos de contenido, rate limiting automático y procesamiento especializado de respuestas.
- Flujo de operación:
Rate limiting: Delay automático de 0.1s (excepto para autenticación)
Configuración de headers: Combina headers por defecto con personalizados
Selección de formato: JSON o form-data según
use_form_dataEjecución con reintentos: Hasta
self.retriesintentos con backoff exponencialProcesamiento de respuesta: Manejo especializado según tipo de contenido
- Estrategia de reintentos:
Errores de red/timeout: Reintentos con backoff: 2s → 4s → 8s → 16s…
Errores HTTP: Propagación inmediata sin reintentos
Máximo wait: 10 segundos entre reintentos para evitar timeouts excesivos
- Tipos de contenido soportados:
JSON (por defecto): Para la mayoría de endpoints de datos
Form-data: Para autenticación y algunos endpoints legacy
Detección automática: Basada en el parámetro
use_form_data
- Parámetros:
method (str) – Método HTTP a usar (GET, POST, PUT, DELETE, etc.)
url (str) – URL completa del endpoint a consultar
data (Optional[Dict[str, Any]]) – Datos a enviar en el cuerpo de la petición. Para GET se ignora, para POST se usa según
use_form_dataparams (Optional[Dict[str, Any]]) – Parámetros de query string a añadir a la URL
headers (Optional[Dict[str, str]]) – Headers HTTP adicionales a combinar con los por defecto. Los headers personalizados tienen prioridad sobre los por defecto
use_form_data (bool) – Si
True, envía datos como application/x-www-form-urlencoded. SiFalse(por defecto), envía como application/json
- Devuelve:
Respuesta procesada del servidor. El tipo depende del endpoint:
JWT tokens:
str(para endpoints de autenticación)Datos JSON:
Dict[str, Any]oList[Any](para endpoints de datos)Respuestas de texto:
str(para endpoints que no devuelven JSON)
- Tipo del valor devuelto:
- Muestra:
DatadisError – Si se agotan todos los reintentos por errores de red/timeouts
AuthenticationError – Si hay errores de autenticación (401)
APIError – Si la API devuelve errores HTTP (400, 403, 404, 500, etc.)
Ejemplo
Diferentes tipos de peticiones:
# GET con parámetros de query response = client.make_request( method="GET", url="https://datadis.es/api-private/api/get-supplies", params={"distributor_code": "2", "authorized_nif": "12345678A"} ) # POST con autenticación (form-data) token = client.make_request( method="POST", url="https://datadis.es/nikola-auth/tokens/login", data={"username": "12345678A", "password": "mi_password"}, use_form_data=True ) # GET con headers personalizados response = client.make_request( method="GET", url="https://datadis.es/api-private/api/get-consumption-data", params={"cups": "ES001234567890123456AB"}, headers={"Authorization": f"Bearer {token}"} )
Nota
El rate limiting automático (delay de 0.1s) se aplica a todas las peticiones excepto las de autenticación para evitar sobrecargar los servidores de Datadis que pueden tener límites de rate restrictivos.
Ver también
_handle_response()para detalles del procesamiento de respuestasLa normalización de texto se realiza automáticamente en respuestas JSON
- close()[fuente]
Cierra la sesión HTTP y libera recursos asociados.
Cierra explícitamente la sesión HTTP subyacente, liberando conexiones de red y otros recursos. Es una buena práctica llamar este método cuando se termina de usar el cliente, especialmente en aplicaciones de larga duración.
Este método es seguro de llamar múltiples veces y no genera errores si la sesión ya está cerrada.
Ejemplo
Uso manual de cierre:
client = HTTPClient(timeout=120, retries=5) try: # Usar cliente para peticiones... response = client.make_request("GET", "https://example.com") finally: # Asegurar limpieza de recursos client.close()
Uso como context manager (recomendado):
with HTTPClient(timeout=120, retries=5) as client: # Usar cliente... response = client.make_request("GET", "https://example.com") # client.close() se llama automáticamente
Nota
Cuando se usa el cliente como context manager (
withstatement), este método se llama automáticamente al salir del bloque, por lo que no es necesario llamarlo manualmente.- Tipo del valor devuelto:
None
- set_auth_header(token)[fuente]
Establece el header de autorización Bearer Token para todas las peticiones futuras.
Configura el token de autenticación que se añadirá automáticamente a todas las peticiones HTTP subsecuentes. Este método es típicamente llamado después de una autenticación exitosa para configurar el cliente para peticiones autenticadas.
El token se almacena en los headers de la sesión persistent, por lo que se aplicará automáticamente a todas las peticiones realizadas con este cliente hasta que se reemplace con un nuevo token o se elimine.
- Parámetros:
token (str) – Token JWT obtenido del endpoint de autenticación de Datadis. Debe ser un token válido sin el prefijo «Bearer « (se añade automáticamente)
- Tipo del valor devuelto:
None
Ejemplo
Configurar autenticación después del login:
client = HTTPClient(timeout=120, retries=5) # Autenticar y obtener token token = client.make_request( method="POST", url="https://datadis.es/nikola-auth/tokens/login", data={"username": "12345678A", "password": "mi_password"}, use_form_data=True ) # Configurar token para peticiones futuras client.set_auth_header(token) # Ahora todas las peticiones incluirán el header Authorization response = client.make_request( method="GET", url="https://datadis.es/api-private/api/get-supplies" )
Nota
El token se prefija automáticamente con «Bearer « según el estándar RFC 6750. No incluya este prefijo en el parámetro
token.Ver también
remove_auth_header()para eliminar la autenticaciónRFC 6750 para especificación completa de Bearer Token
- remove_auth_header()[fuente]
Elimina el header de autorización de todas las peticiones futuras.
Remueve el token de autenticación de los headers de la sesión, haciendo que las peticiones subsecuentes se realicen sin autenticación. Esto es útil para limpiar credenciales cuando se cambia de usuario o cuando se quiere realizar peticiones no autenticadas.
Esta operación es segura y no genera errores si no existe un header de autorización configurado.
Ejemplo
Limpiar autenticación para cambio de usuario:
# Usuario 1 autenticado client.set_auth_header(token_user1) data_user1 = client.make_request("GET", "/get-supplies") # Cambiar a usuario 2 client.remove_auth_header() # Limpiar credenciales anteriores token_user2 = client.make_request( "POST", "/nikola-auth/tokens/login", data={"username": "87654321B", "password": "other_password"}, use_form_data=True ) client.set_auth_header(token_user2) data_user2 = client.make_request("GET", "/get-supplies")
Peticiones sin autenticación:
client.remove_auth_header() # Ahora las peticiones no incluirán Authorization header public_data = client.make_request("GET", "/public-endpoint")
Nota
Después de llamar este método, las peticiones a endpoints que requieren autenticación fallarán con error 401 hasta que se establezca un nuevo token con
set_auth_header().Ver también
set_auth_header()para establecer nuevo token de autenticación
- Tipo del valor devuelto:
None
- __enter__()[fuente]
Método de entrada para context manager.
Permite usar el HTTPClient con la declaración
withde Python para gestión automática de recursos. Al entrar en el bloquewith, retorna la instancia del cliente lista para usar.- Devuelve:
La instancia del cliente HTTP configurada
- Tipo del valor devuelto:
Ejemplo
Uso como context manager:
with HTTPClient(timeout=120, retries=5) as client: # Configurar autenticación token = client.make_request( "POST", "/auth", data={"user": "12345678A", "pass": "password"}, use_form_data=True ) client.set_auth_header(token) # Realizar peticiones data = client.make_request("GET", "/api/data") # client.close() se llama automáticamente aquí
Nota
El uso como context manager es la forma recomendada de usar HTTPClient ya que garantiza la liberación adecuada de recursos de red.
- __exit__(exc_type, exc_val, exc_tb)[fuente]
Método de salida para context manager.
Se llama automáticamente al salir del bloque
with, garantizando que los recursos del cliente HTTP se liberen adecuadamente, independientemente de si el bloque se completó exitosamente o se produjo una excepción.- Parámetros:
exc_type – Tipo de excepción si ocurrió una excepción, None en caso contrario
exc_val – Valor de la excepción si ocurrió una excepción, None en caso contrario
exc_tb – Traceback de la excepción si ocurrió una excepción, None en caso contrario
Nota
Este método siempre retorna None, lo que significa que no suprime ninguna excepción que pueda haber ocurrido dentro del bloque
with. Las excepciones se propagan normalmente después de la limpieza de recursos.