datadis_python.utils.validators module

Validadores especializados para parámetros de la API de Datadis.

Este módulo proporciona funciones de validación específicas para los diferentes tipos de parámetros que acepta la API de Datadis. Cada validador implementa las reglas de negocio y restricciones técnicas específicas de la plataforma.

Los validadores están diseñados para detectar y prevenir errores comunes antes de realizar peticiones a la API, proporcionando mensajes de error claros y específicos que guían al usuario hacia la solución correcta.

Categorías de validación:
  • Identificadores: CUPS, códigos de distribuidor

  • Fechas y rangos: Validación temporal con restricciones de Datadis

  • Tipos de datos: Tipos de medida, tipos de punto

  • Formatos: Patrones específicos requeridos por la API

Características principales:
  • Validación temprana: Detecta errores antes de peticiones HTTP

  • Mensajes específicos: Guía clara sobre cómo corregir problemas

  • Reglas de negocio: Implementa restricciones específicas de Datadis

  • Robustez: Manejo de casos edge y entradas malformadas

Restricciones específicas de Datadis:
  • Rango temporal: Solo últimos 2 años de datos disponibles

  • Formato de fechas: Principalmente YYYY/MM (mensual)

  • Códigos limitados: Solo 8 distribuidores oficiales válidos

  • CUPS españoles: Formato específico ES + 20-22 caracteres

Ejemplo

Validaciones independientes:

from datadis_python.utils.validators import (
    validate_cups,
    validate_distributor_code,
    validate_date_range
)

# Validar CUPS
valid_cups = validate_cups("ES0031607515707001RC0F")

# Validar distribuidor
valid_code = validate_distributor_code("2")  # E-distribución

# Validar rango de fechas
from_date, to_date = validate_date_range("2024/01", "2024/12", "monthly")

Integración con conversores:

# Los validadores se llaman automáticamente desde los conversores
from datadis_python.utils.type_converters import (
    convert_cups_parameter,
    convert_distributor_code_parameter
)

# Conversión + validación automática
cups = convert_cups_parameter("ES0031607515707001RC0F")
code = convert_distributor_code_parameter(2)  # int → "2" + validación

Nota

Todos los validadores lanzan ValidationError con mensajes descriptivos cuando encuentran problemas. Esto permite manejo de errores consistente en todo el SDK.

Advertencia

Las validaciones están sincronizadas con las limitaciones actuales de la API de Datadis (2025). Si la API cambia sus restricciones, estos validadores necesitarán actualizarse.

author:

TacoronteRiveroCristian

datadis_python.utils.validators.validate_cups(cups)[fuente]

Valida el formato del código CUPS (Código Universal del Punto de Suministro).

Los códigos CUPS son identificadores únicos obligatorios para todos los puntos de suministro eléctrico en España. Esta función valida que el código cumple con el formato oficial establecido por el sistema eléctrico español.

Especificaciones del formato CUPS:
  • Prefijo obligatorio: «ES» (código ISO del país)

  • Longitud variable: 20-22 caracteres alfanuméricos después del prefijo

  • Total: 22-24 caracteres (incluyendo «ES»)

  • Caracteres válidos: Solo letras mayúsculas (A-Z) y números (0-9)

  • Sin separadores: No se permiten espacios, guiones u otros caracteres

Ejemplos de códigos CUPS reales:
  • Formato 20: ES0031607515707001RC0F (22 caracteres totales)

  • Formato 22: ES1234567890123456789012 (24 caracteres totales)

Proceso de validación:
  1. Verificación de vacío: El CUPS no puede estar vacío o ser None

  2. Normalización: Conversión a mayúsculas y eliminación de espacios

  3. Validación de patrón: Verificación contra regex oficial

  4. Verificación de longitud: Confirmar longitud dentro del rango válido

Parámetros:

cups (str) – Código CUPS a validar. Debe ser un string con formato válido

Devuelve:

Código CUPS validado, normalizado (mayúsculas, sin espacios)

Tipo del valor devuelto:

str

Muestra:

ValidationError – Si el CUPS no cumple con el formato esperado

Ejemplo

Códigos CUPS válidos:

# Formato estándar (20 caracteres después de ES)
validate_cups("ES0031607515707001RC0F")
# → "ES0031607515707001RC0F"

# Formato extendido (22 caracteres después de ES)
validate_cups("ES1234567890123456789012")
# → "ES1234567890123456789012"

# Con espacios (se limpian automáticamente)
validate_cups(" ES0031607515707001RC0F ")
# → "ES0031607515707001RC0F"

# Minúsculas (se convierten automáticamente)
validate_cups("es0031607515707001rc0f")
# → "ES0031607515707001RC0F"

Casos que fallan (errores esperados):

# ❌ Código vacío
validate_cups("")
# → ValidationError: "CUPS no puede estar vacío"

# ❌ Sin prefijo ES
validate_cups("0031607515707001RC0F")
# → ValidationError: "Formato CUPS inválido. Debe ser: ES + 20-22 caracteres alfanuméricos"

# ❌ Demasiado corto
validate_cups("ES123456")
# → ValidationError: "Formato CUPS inválido..."

# ❌ Caracteres inválidos
validate_cups("ES003160751570700@RC0F")
# → ValidationError: "Formato CUPS inválido..."

# ❌ Prefijo incorrecto
validate_cups("FR0031607515707001RC0F")
# → ValidationError: "Formato CUPS inválido..."

Uso en validación de entrada:

def get_consumption(self, cups: str, ...):
    # Validar antes de usar en petición
    validated_cups = validate_cups(cups)
    # validated_cups está garantizado como válido
    params = {"cups": validated_cups}

Nota

Esta función valida únicamente el formato del CUPS, no verifica que el código exista realmente o esté asociado a un usuario específico. Esa validación la realiza el servidor de Datadis.

Technical Details:
  • Regex utilizado: ^ES[A-Z0-9]{20,22}$

  • Normalización: .upper().strip() automática

  • Performance: Validación muy rápida usando regex compilado

  • Memoria: No guarda estado entre llamadas

Referencias

  • CNE (Comisión Nacional de Energía): Especificaciones oficiales CUPS

  • BOE: Normativa sobre identificación de puntos de suministro

  • Datadis: Documentación técnica de la API

Ver también

  • convert_cups_parameter() para conversión automática con validación

  • Documentación oficial sobre códigos CUPS en España

Added in version 1.0: Validación básica de formato CUPS

Distinto en la versión 2.0: Mejorado soporte para formatos CUPS extendidos (22 caracteres)

datadis_python.utils.validators.validate_date_range(date_from, date_to, format_type='monthly')[fuente]

Valida un rango de fechas según las restricciones específicas de Datadis.

Esta función implementa todas las reglas de validación temporal específicas de la API de Datadis, incluyendo formatos aceptados, rangos permitidos y limitaciones de acceso a datos históricos.

Restricciones de Datadis implementadas:
  • Rango temporal: Solo últimos 2 años desde la fecha actual

  • No fechas futuras: Las fechas no pueden ser posteriores al día actual

  • Orden lógico: date_from debe ser anterior o igual a date_to

  • Formatos específicos: YYYY/MM para mensual, YYYY/MM/DD para diario

Formatos soportados:
  • Mensual: «YYYY/MM» (ej: «2024/01») - Recomendado para Datadis

  • Diario: «YYYY/MM/DD» (ej: «2024/01/15») - Limitado en algunos endpoints

Validaciones aplicadas:
  1. Formato de entrada: Verificación contra patrones regex específicos

  2. Parseabilidad: Verificación de fechas válidas (no 30 de febrero)

  3. Orden lógico: date_from ≤ date_to

  4. Límite histórico: No más de 2 años hacia atrás

  5. Límite futuro: No fechas posteriores a hoy

Parámetros:
  • date_from (str) – Fecha de inicio del rango en formato string

  • date_to (str) – Fecha de fin del rango en formato string

  • format_type (str) – Tipo de formato («monthly» para YYYY/MM).

Devuelve:

Tupla con las fechas validadas (date_from, date_to)

Tipo del valor devuelto:

Tuple[str, str]

Muestra:

ValidationError – Si cualquier validación falla

Ejemplo

Validaciones exitosas:

# Rango mensual válido
validate_date_range("2024/01", "2024/12", "monthly")
# → ("2024/01", "2024/12")

# Rango diario válido
validate_date_range("2024/01/01", "2024/01/31", "daily")
# → ("2024/01/01", "2024/01/31")

# Rango de un mes
validate_date_range("2024/06", "2024/06", "monthly")
# → ("2024/06", "2024/06")

Casos que fallan (errores esperados):

# ❌ Formato incorrecto
validate_date_range("2024-01", "2024-12", "monthly")
# → ValidationError: "Formato de fecha_desde inválido: 2024-01. Use 2024/01"

# ❌ Rango invertido
validate_date_range("2024/12", "2024/01", "monthly")
# → ValidationError: "fecha_desde no puede ser posterior a fecha_hasta"

# ❌ Demasiado antigua (más de 2 años)
validate_date_range("2020/01", "2020/12", "monthly")
# → ValidationError: "fecha_desde no puede ser anterior a hace 2 años"

# ❌ Fecha futura
validate_date_range("2030/01", "2030/12", "monthly")
# → ValidationError: "fecha_hasta no puede ser futura"

# ❌ Fecha inválida
validate_date_range("2024/02/30", "2024/02/30", "daily")
# → ValidationError: "Fecha inválida: day is out of range for month"

Uso típico en métodos del SDK:

def get_consumption(self, date_from, date_to):
    # Validación robusta antes de petición API
    validated_from, validated_to = validate_date_range(
        date_from, date_to, "monthly"
    )
    # Las fechas están garantizadas como válidas
    params = {"dateFrom": validated_from, "dateTo": validated_to}

Nota

El límite de 2 años se basa en las limitaciones actuales de Datadis para acceso a datos históricos. Este límite puede cambiar en el futuro según las políticas de la plataforma.

Performance:

La validación incluye cálculos de fecha para verificar límites temporales. Para uso intensivo, considere cachear los límites calculados.

Technical Details:
  • Regex patterns: Específicos para cada formato (daily/monthly)

  • Parsing: Usa datetime.strptime() para validación completa

  • Límites dinámicos: Calculados en tiempo real basados en datetime.now()

  • Timezone: Usa timezone local del sistema

Ver también

  • convert_date_range_to_api_format() para conversión + validación

  • convert_date_to_api_format() para fechas individuales

  • Documentación de Datadis sobre disponibilidad de datos históricos

Added in version 1.0: Validación básica de rangos de fechas

Distinto en la versión 2.0: Añadidas validaciones específicas para limitaciones de Datadis

datadis_python.utils.validators.validate_distributor_code(distributor_code)[fuente]

Valida códigos de distribuidor eléctrico españoles oficiales.

Parámetros:

distributor_code (str) – Código de distribuidor a validar

Devuelve:

Código de distribuidor validado

Tipo del valor devuelto:

str

Muestra:

ValidationError – Si el código no corresponde a un distribuidor válido

Ejemplo

Códigos válidos:

# Distribuidores nacionales principales
validate_distributor_code("2")  # → "2" (E-distribución/Endesa)
validate_distributor_code("5")  # → "5" (UFD/Naturgy)

# Distribuidores regionales
validate_distributor_code("1")  # → "1" (Viesgo - Norte)
validate_distributor_code("3")  # → "3" (E-redes - Galicia)
validate_distributor_code("6")  # → "6" (EOSA - Aragón)

# Distribuidores insulares/locales
validate_distributor_code("8")  # → "8" (IDE - Baleares)
validate_distributor_code("4")  # → "4" (ASEME - Melilla)
validate_distributor_code("7")  # → "7" (CIDE - Ceuta)

Casos que fallan (errores esperados):

# ❌ Código inexistente
validate_distributor_code("9")
# → ValidationError: "Código de distribuidor inválido: 9. Válidos: 1, 2, 3, 4, 5, 6, 7, 8"

# ❌ Código múltiple
validate_distributor_code("12")
# → ValidationError: "Código de distribuidor inválido: 12..."

# ❌ Código negativo
validate_distributor_code("-1")
# → ValidationError: "Código de distribuidor inválido: -1..."

Uso con constantes descriptivas:

from datadis_python.utils.constants import DISTRIBUTOR_CODES

# Usar nombres descriptivos en lugar de números
endesa_code = DISTRIBUTOR_CODES["E_DISTRIBUCION"]  # "2"
validated = validate_distributor_code(endesa_code)  # "2"

# Iterar sobre todos los distribuidores válidos
for name, code in DISTRIBUTOR_CODES.items():
    validated_code = validate_distributor_code(code)
    print(f"{name}: {validated_code}")

Nota

Los códigos de distribuidor son siempre strings en la API de Datadis, aunque representen números. Use convert_distributor_code_parameter() si necesita conversión automática desde enteros.

Technical Details:
  • Lista estática: Los 8 códigos están hardcodeados (no cambian frecuentemente)

  • Validación rápida: Lookup en lista pequeña, muy eficiente

  • Case sensitive: Los códigos deben ser exactamente como se especifican

  • No conversión: Esta función no convierte tipos, solo valida

Referencias

  • CNE: Comisión Nacional de Energía - Listado oficial de distribuidores

  • CNMC: Comisión Nacional de los Mercados y la Competencia

  • Datadis: Documentación oficial de códigos soportados

Ver también

Added in version 1.0: Validación de códigos de distribuidor

Distinto en la versión 2.0: Actualizada lista con información geográfica detallada

datadis_python.utils.validators.validate_measurement_type(measurement_type)[fuente]

Valida y normaliza tipos de medida eléctrica para la API de Datadis.

Los tipos de medida distinguen entre consumo de energía (tomada de la red) y generación de energía (inyectada a la red). Esta distinción es importante para usuarios con instalaciones de autoconsumo que pueden tanto consumir como generar electricidad.

Tipos de medida oficiales:
  • 0 - CONSUMO: Energía consumida desde la red eléctrica (por defecto)

  • 1 - GENERACIÓN: Energía generada e inyectada a la red

Casos de uso:
  • Consumo doméstico: Siempre tipo 0 (viviendas sin generación)

  • Autoconsumo con inyección: Tipo 0 para consumo, tipo 1 para excedentes

  • Plantas de generación: Principalmente tipo 1

  • Instalaciones mixtas: Ambos tipos según el flujo de energía

Manejo de valores por defecto:
  • None: Se convierte automáticamente a 0 (consumo)

  • Valor explícito: Se valida que esté en el rango permitido

Parámetros:

measurement_type (Optional[int]) –

Tipo de medida a validar:

  • 0 o None: Consumo (energía tomada de la red)

  • 1: Generación (energía inyectada a la red)

Devuelve:

Tipo de medida validado (siempre 0 o 1)

Tipo del valor devuelto:

int

Muestra:

ValidationError – Si el tipo no está en el rango válido (0-1)

Ejemplo

Valores válidos:

# Consumo explícito
validate_measurement_type(0)     # → 0 (consumo)

# Generación explícita
validate_measurement_type(1)     # → 1 (generación)

# Valor por defecto (None → consumo)
validate_measurement_type(None)  # → 0 (consumo por defecto)

Casos que fallan (errores esperados):

# ❌ Tipo inválido
validate_measurement_type(2)
# → ValidationError: "measurement_type debe ser 0 (consumo) o 1 (generación)"

# ❌ Tipo negativo
validate_measurement_type(-1)
# → ValidationError: "measurement_type debe ser 0 (consumo) o 1 (generación)"

Uso típico en consultas:

# Consulta de consumo doméstico (por defecto)
consumption_data = client.get_consumption(
    cups="ES001234567890123456AB",
    distributor_code="2",
    date_from="2024/01",
    date_to="2024/12",
    measurement_type=validate_measurement_type(None)  # → 0
)

# Consulta de generación solar
generation_data = client.get_consumption(
    cups="ES001234567890123456AB",
    distributor_code="2",
    date_from="2024/01",
    date_to="2024/12",
    measurement_type=validate_measurement_type(1)  # → 1
)

Uso con constantes:

from datadis_python.utils.constants import MEASUREMENT_TYPES

# Usar constantes descriptivas
consumption_type = validate_measurement_type(MEASUREMENT_TYPES["CONSUMPTION"])  # 0
generation_type = validate_measurement_type(MEASUREMENT_TYPES["GENERATION"])    # 1

Nota

La mayoría de usuarios domésticos solo necesitarán el tipo 0 (consumo). El tipo 1 (generación) es relevante principalmente para instalaciones con paneles solares u otras fuentes de generación distribuida.

Technical Details:
  • Rango válido: Solo 0 y 1 según especificación de Datadis

  • Default seguro: None se convierte a 0 (caso más común)

  • Validación estricta: No se permiten otros valores enteros

  • Performance: Validación muy rápida (comparación simple)

Ver también

Added in version 1.0: Validación de tipos de medida

Distinto en la versión 2.0: Mejorada documentación con casos de uso específicos

datadis_python.utils.validators.validate_point_type(point_type)[fuente]

Valida y normaliza tipos de punto de medida según normativa eléctrica española.

Parámetros:

point_type (Optional[int]) – Tipo de punto, None para usar por defecto (1)

Devuelve:

Tipo de punto validado (siempre 1-5)

Tipo del valor devuelto:

int

Muestra:

ValidationError – Si el tipo no está en el rango válido (1-5)

Ejemplo

Valores válidos:

# Frontera (por defecto)
validate_point_type(None)  # → 1 (frontera por defecto)
validate_point_type(1)     # → 1 (frontera explícito)

# Consumo doméstico/comercial
validate_point_type(2)     # → 2 (consumo)

# Generación eléctrica
validate_point_type(3)     # → 3 (generación)

# Servicios del sistema
validate_point_type(4)     # → 4 (servicios auxiliares)
validate_point_type(5)     # → 5 (servicios auxiliares alt)

Casos que fallan (errores esperados):

# ❌ Tipo fuera de rango
validate_point_type(6)
# → ValidationError: "point_type debe ser 1 (frontera), 2 (consumo), 3 (generación) o 4 (servicios auxiliares)"

# ❌ Tipo cero o negativo
validate_point_type(0)
# → ValidationError: "point_type debe ser 1 (frontera)..."

Uso típico por contexto:

# Consulta de consumo doméstico típico
domestic_data = client.get_consumption(
    cups="ES001234567890123456AB",
    distributor_code="2",
    date_from="2024/01",
    date_to="2024/12",
    point_type=validate_point_type(2)  # Consumo doméstico
)

# Consulta de generación renovable
generation_data = client.get_consumption(
    cups="ES001234567890123456AB",
    distributor_code="2",
    date_from="2024/01",
    date_to="2024/12",
    point_type=validate_point_type(3)  # Generación
)

Uso con constantes descriptivas:

from datadis_python.utils.constants import POINT_TYPES

# Usar nombres descriptivos en lugar de números
consumption_type = validate_point_type(POINT_TYPES["CONSUMPTION"])  # 2
generation_type = validate_point_type(POINT_TYPES["GENERATION"])    # 3
border_type = validate_point_type(POINT_TYPES["BORDER"])            # 1

Nota

Para la mayoría de usuarios domésticos y comerciales, el tipo 2 (CONSUMO) será el más relevante. Los tipos 3-5 son principalmente para instalaciones industriales y de servicios eléctricos.

Technical Details:
  • Rango válido: 1-5 según normativa del sistema eléctrico español

  • Default conservador: None → 1 (frontera, valor neutro)

  • Validación estricta: Solo enteros en el rango específico

  • Mapeo normativo: Basado en clasificación oficial CNE/CNMC

Referencias

  • CNE: Comisión Nacional de Energía - Clasificación de puntos de medida

  • CNMC: Comisión Nacional de los Mercados y la Competencia

  • BOE: Normativa sobre tipos de punto en el sistema eléctrico

Ver también

Added in version 1.0: Validación de tipos de punto

Distinto en la versión 2.0: Añadido soporte para tipo 5 y documentación extendida