datadis_python.utils.text_utils module

Utilidades para normalización y procesamiento de texto de respuestas de Datadis.

Este módulo proporciona funciones especializadas para procesar y normalizar texto recibido de la API de Datadis, solucionando problemas comunes de encoding y caracteres especiales que pueden aparecer en las respuestas del servicio.

La API de Datadis frecuentemente devuelve texto con problemas de encoding, especialmente con caracteres españoles como tildes (á, é, í, ó, ú), eñes (ñ), cedillas (ç) y otros caracteres especiales. Este módulo proporciona herramientas robustas para detectar y corregir estos problemas automáticamente.

Problemas comunes solucionados:
  • Doble codificación UTF-8: Secuencias como «Ãx93» en lugar de «Ó»

  • Caracteres especiales mal codificados: «EDISTRIBUCIÃx93N» → «EDISTRIBUCION»

  • Inconsistencias de encoding: Mezcla de encodings en una misma respuesta

  • Caracteres no ASCII: Normalización a ASCII para compatibilidad

Funciones principales:

Ejemplo

Uso típico para procesar respuestas de Datadis:

from datadis_python.utils.text_utils import normalize_api_response

# Respuesta raw de Datadis con problemas de encoding
raw_response = {
    "distributor": "EDISTRIBUCIÃ\x93N",
    "address": "CALLE JOSÃπ MARTÃ\xadNEZ"
}

# Normalizar respuesta completa
clean_response = normalize_api_response(raw_response)
# Resultado: {"distributor": "EDISTRIBUCION", "address": "CALLE JOSE MARTINEZ"}

Normalización de texto individual:

from datadis_python.utils.text_utils import normalize_text

# Texto con problemas típicos de Datadis
problematic_text = "Málaga"
clean_text = normalize_text(problematic_text)
# Resultado: "Malaga"

Nota

Todas las funciones de este módulo son seguras de usar con datos None o de tipos incorrectos - retornan el valor original sin modificar si no pueden procesarlo.

Advertencia

La normalización elimina permanentemente caracteres especiales y acentos. Si necesita preservar el texto original, haga una copia antes de aplicar estas funciones.

author:

TacoronteRiveroCristian

datadis_python.utils.text_utils.normalize_text(text)[fuente]

Normaliza texto removiendo tildes, caracteres especiales y corrigiendo problemas de encoding.

Esta función es el núcleo del sistema de normalización de texto del SDK. Aplica múltiples estrategias para corregir problemas comunes de encoding que aparecen frecuentemente en las respuestas de la API de Datadis, especialmente con caracteres españoles.

Proceso de normalización:
  1. Detección de doble codificación: Identifica secuencias como «Ãx93» (debe ser «Ó»)

  2. Corrección de encoding: Recodifica usando latin-1 → UTF-8 cuando es necesario

  3. Normalización Unicode: Aplica descomposición NFD para separar caracteres base de acentos

  4. Eliminación de acentos: Convierte caracteres acentuados a su equivalente ASCII

  5. Reemplazos específicos: Maneja caracteres especiales españoles (ñ, ç, etc.)

Casos de uso típicos:
  • Nombres de distribuidores: «EDISTRIBUCIÃx93N» → «EDISTRIBUCION»

  • Direcciones: «CALLE JOSÃπ MARTÃxadNEZ» → «CALLE JOSE MARTINEZ»

  • Nombres de municipios: «Málaga», «Cádiz» → «Malaga», «Cadiz»

  • Códigos postales: Normalmente no necesitan normalización pero se procesan igual

Parámetros:

text (str) – Texto a normalizar. Puede contener caracteres especiales, acentos, o problemas de doble codificación típicos de Datadis

Devuelve:

Texto normalizado sin tildes, acentos ni caracteres especiales. Convertido completamente a caracteres ASCII seguros

Tipo del valor devuelto:

str

Ejemplo

Problemas típicos de encoding de Datadis:

# Doble codificación UTF-8
normalize_text("EDISTRIBUCIÃ\x93N")     # → "EDISTRIBUCION"
normalize_text("Málaga")               # → "Malaga"

# Caracteres españoles normales
normalize_text("Málaga")                # → "Malaga"
normalize_text("Coruña")                # → "Coruna"
normalize_text("Cáceres")               # → "Caceres"

# Caracteres especiales
normalize_text("Peñíscola")             # → "Peniscola"
normalize_text("François")              # → "Francois"

Casos extremos manejados:

# Texto ya normalizado - sin cambios
normalize_text("MADRID")                # → "MADRID"

# Mezcla de problemas
normalize_text("Cádiz - AndalucÃ\xada") # → "Cadiz - Andalucia"

Nota

La función es segura con datos de entrada inválidos - si recibe algo que no es string, retorna el valor original sin modificar. Esto evita errores en cadenas de procesamiento de datos.

Advertencia

La normalización es irreversible. Si necesita preservar el texto original con acentos, haga una copia antes de llamar esta función.

Technical details:
  • Usa unicodedata.normalize('NFD', text) para descomposición Unicode

  • Aplica encode('ascii', 'ignore') para eliminar caracteres no-ASCII

  • Maneja específicamente problemas de doble codificación latin-1/UTF-8

  • Incluye tabla de reemplazos para caracteres que unicodedata no maneja

Ver también

datadis_python.utils.text_utils.normalize_dict_strings(data)[fuente]

Normaliza recursivamente todas las cadenas de texto en un diccionario.

Esta función recorre un diccionario de forma recursiva aplicando normalización de texto a todas las cadenas encontradas, manteniendo la estructura original del diccionario pero limpiando el contenido textual.

Procesamiento recursivo:

Esta función es especialmente útil para procesar respuestas JSON estructuradas de la API de Datadis donde los problemas de encoding pueden aparecer en cualquier campo de texto dentro de estructuras complejas.

Parámetros:

data (Dict[str, Any]) – Diccionario con datos a normalizar. Puede contener estructuras anidadas complejas con strings que necesiten limpieza de caracteres especiales

Devuelve:

Nuevo diccionario con la misma estructura pero con todos los strings normalizados. Los valores no-string se mantienen exactamente igual

Tipo del valor devuelto:

Dict[str, Any]

Ejemplo

Normalizar respuesta estructurada de Datadis:

raw_supply_data = {
    "cups": "ES001234567890123456AB",
    "address": "CALLE JOSÃπ MARTÃ\xadNEZ",
    "distributor": "EDISTRIBUCIÃ\x93N",
    "postalCode": "28001",
    "province": "Mádrid",
    "details": {
        "city": "Málaga",
        "municipality": "AndalucÃ\xada"
    },
    "contracts": [
        {"startDate": "2024/01/01", "type": "Normal"}
    ],
    "active": True,
    "pointType": 2
}

normalized_data = normalize_dict_strings(raw_supply_data)
# Resultado:
# {
#     "cups": "ES001234567890123456AB",          # Sin cambio
#     "address": "CALLE JOSE MARTINEZ",          # Normalizado
#     "distributor": "EDISTRIBUCION",            # Normalizado
#     "postalCode": "28001",                     # Sin cambio
#     "province": "Madrid",                      # Normalizado
#     "details": {
#         "city": "Malaga",                      # Normalizado (recursivo)
#         "municipality": "Andalucia"            # Normalizado (recursivo)
#     },
#     "contracts": [
#         {"startDate": "2024/01/01", "type": "Normal"}  # Procesado recursivamente
#     ],
#     "active": True,                            # Sin cambio (boolean)
#     "pointType": 2                             # Sin cambio (int)
# }

Casos extremos manejados:

# Diccionario vacío
normalize_dict_strings({})  # → {}

# Diccionario con valores None
normalize_dict_strings({"key": None})  # → {"key": None}

# Anidación profunda
deep_dict = {"level1": {"level2": {"text": "Málaga"}}}
normalize_dict_strings(deep_dict)  # → {"level1": {"level2": {"text": "Malaga"}}}

Nota

La función es segura con datos de entrada inválidos - si recibe algo que no es diccionario, retorna el valor original sin modificar. Esto permite su uso seguro en cadenas de procesamiento donde el tipo de dato puede ser incierto.

Performance:

La función crea un nuevo diccionario en lugar de modificar el original, lo que la hace segura para uso concurrente pero puede consumir más memoria con estructuras muy grandes.

Ver también

datadis_python.utils.text_utils.normalize_list_strings(data)[fuente]

Normaliza recursivamente todas las cadenas de texto en una lista.

Esta función procesa listas de forma recursiva aplicando normalización de texto a todos los elementos string encontrados, mientras mantiene la estructura y orden original de la lista. Es especialmente útil para procesar arrays de datos de Datadis.

Procesamiento recursivo por tipo:
Casos de uso típicos en Datadis:
  • Arrays de suministros: Lista de objetos SupplyData con addresses problemáticas

  • Arrays de consumo: Lista de ConsumptionData con distributors mal codificados

  • Arrays mixtos: Listas que combinan strings, números y objetos

Parámetros:

data (List[Any]) – Lista con datos a normalizar. Puede contener elementos de cualquier tipo, incluidas estructuras anidadas complejas

Devuelve:

Nueva lista con la misma estructura y orden, pero con todos los strings normalizados. Los elementos no-string se mantienen exactamente igual

Tipo del valor devuelto:

List[Any]

Ejemplo

Normalizar array de respuesta de Datadis:

raw_supplies_list = [
    "EDISTRIBUCIÃ\x93N",  # String simple problemático
    {
        "distributor": "Málaga Eléctrica",
        "address": "CALLE JOSÃπ MARTÃ\xadNEZ"
    },
    ["Cádiz", "Sevillá"],  # Lista anidada
    42,  # Número
    None,  # Valor nulo
    True  # Booleano
]

normalized_list = normalize_list_strings(raw_supplies_list)
# Resultado:
# [
#     "EDISTRIBUCION",                    # String normalizado
#     {
#         "distributor": "Malaga Electrica",  # Dict normalizado recursivamente
#         "address": "CALLE JOSE MARTINEZ"
#     },
#     ["Cadiz", "Sevilla"],               # Lista normalizada recursivamente
#     42,                                 # Sin cambio (int)
#     None,                               # Sin cambio (None)
#     True                                # Sin cambio (bool)
# ]

Array de objetos de consumo:

consumption_data = [
    {
        "date": "2024/01/01",
        "consumptionKWh": 5.2,
        "distributor": "EDISTRIBUCIÃ\x93N"
    },
    {
        "date": "2024/01/02",
        "consumptionKWh": 4.8,
        "distributor": "Málaga Eléctrica"
    }
]

normalized_consumption = normalize_list_strings(consumption_data)
# Solo los campos "distributor" se normalizan, fechas y números quedan igual

Casos extremos:

# Lista vacía
normalize_list_strings([])  # → []

# Lista con solo valores no-string
normalize_list_strings([1, 2, 3, True, None])  # → [1, 2, 3, True, None]

# Anidación profunda
deep_list = [[[["Málaga"]]]]
normalize_list_strings(deep_list)  # → [[[["Malaga"]]]]

Nota

La función es segura con datos de entrada inválidos - si recibe algo que no es lista, retorna el valor original sin modificar. Esto permite su uso seguro en cadenas de procesamiento de datos heterogéneos.

Performance:

Crea una nueva lista en lugar de modificar la original, garantizando inmutabilidad pero puede consumir más memoria con listas muy grandes.

Ver también

datadis_python.utils.text_utils.normalize_api_response(response)[fuente]

Función principal para normalizar respuestas completas de la API de Datadis.

Esta es la función de entrada principal del sistema de normalización del SDK. Detecta automáticamente el tipo de respuesta (diccionario o lista) y aplica la estrategia de normalización correspondiente para limpiar todos los strings de problemas de encoding y caracteres especiales.

Función de router inteligente:

Esta función es llamada automáticamente por el HTTPClient del SDK, por lo que los usuarios normalmente no necesitan llamarla manualmente. Sin embargo, puede ser útil para procesar datos cacheados o respuestas guardadas localmente.

Casos de uso típicos:
  • Auto-procesamiento: Llamada automática por HTTPClient en todas las respuestas JSON

  • Procesamiento manual: Para limpiar datos guardados localmente o cacheados

  • Testing: Para normalizar respuestas mock en tests unitarios

  • Debugging: Para limpiar respuestas antes de análisis manual

Parámetros:

response (Union[Dict[str, Any], List[Any]]) – Respuesta completa de la API de Datadis en formato JSON deserializado. Puede ser un diccionario (respuesta de objeto) o lista (respuesta de array)

Devuelve:

Respuesta normalizada con la misma estructura pero con todos los strings limpios de problemas de encoding y caracteres especiales

Tipo del valor devuelto:

Union[Dict[str, Any], List[Any]]

Ejemplo

Respuestas típicas de diferentes endpoints:

# Respuesta de get_supplies (lista de objetos)
supplies_response = [
    {"cups": "ES001...", "distributor": "EDISTRIBUCIÃ\x93N"},
    {"cups": "ES002...", "distributor": "Málaga Eléctrica"}
]
clean_supplies = normalize_api_response(supplies_response)
# Resultado: [{"cups": "ES001...", "distributor": "EDISTRIBUCION"}, ...]

# Respuesta de get_consumption (objeto con arrays)
consumption_response = {
    "consumption": [
        {"date": "2024/01/01", "distributor": "EDISTRIBUCIÃ\x93N"}
    ],
    "distributor_error": []
}
clean_consumption = normalize_api_response(consumption_response)
# Resultado: {"consumption": [{"date": "2024/01/01", "distributor": "EDISTRIBUCION"}], ...}

Procesamiento manual de datos guardados:

# Datos cacheados que pueden tener problemas de encoding
cached_data = load_from_cache("datadis_supplies.json")
clean_data = normalize_api_response(cached_data)
# Ahora clean_data está libre de problemas de encoding

Uso en testing:

# Mock response con problemas simulados de Datadis
mock_response = {"distributor": "EDISTRIBUCIÃ\x93N"}
normalized_mock = normalize_api_response(mock_response)
# Para tests con datos normalizados

Nota

Esta función es completamente segura con cualquier tipo de entrada. Si recibe datos que no puede procesar, los retorna sin modificar, garantizando que nunca cause errores en el pipeline de datos.

Performance:

La función crea nuevas estructuras de datos en lugar de modificar las originales, lo que la hace segura para uso concurrente pero puede consumir más memoria con respuestas muy grandes (miles de registros).

Integration:

Esta función está integrada automáticamente en la cadena de procesamiento de respuestas del HTTPClient, por lo que todos los datos que llegan a los usuarios finales ya están normalizados.

Ver también

Added in version 1.0: Normalización automática integrada en todo el SDK

Distinto en la versión 2.0: Mejorada detección de problemas de doble codificación UTF-8