Files
HomeAssistance/custom_components/teamtracker/utils.py
T
2026-06-05 22:34:31 -04:00

143 lines
3.7 KiB
Python

""" Miscellaneous Utilities """
import json
import logging
import os
import re
from homeassistant.core import HomeAssistant
from .const import DEFAULT_OVERRIDE_FILE, LOCAL_OVERRIDE_FILE
_LOGGER = logging.getLogger(__name__)
#
# deep_merge()
#
def deep_merge(base: dict, override: dict) -> dict:
"""Recursively merge override into base."""
result = base.copy()
for key, value in override.items():
if (
key in result
and isinstance(result[key], dict)
and isinstance(value, dict)
):
result[key] = deep_merge(result[key], value)
else:
result[key] = value
return result
#
# get_value()
# Traverse json and return the value at the end of the chain of keys.
# json - json to be traversed
# *keys - list of keys to use to retrieve the value
# default - default value to be returned if a key is missing
#
def get_value(json_input, *keys, default=None):
"""Traverse the json using keys to return the associated value, or default if invalid keys"""
j = json_input
try:
for k in keys:
j = j[k]
return j
except:
return default
#
# has_team()
#
def has_team(data, target_team_id):
"""Search for team in json data"""
for event in data.get("events", []):
for comp in event.get("competitions", []):
for competitor in comp.get("competitors", []):
if competitor.get("team", {}).get("id") == target_team_id:
return True
return False
#
# is_integer()
#
def is_integer(val):
"""Check if a value is an integer"""
try:
int(val)
return True
except ValueError:
return False
#
# load_file_overrides()
#
def load_file_overrides(hass: HomeAssistant) -> dict:
"""Thread-safe file loading utility."""
component_dir = os.path.dirname(__file__)
default_file = os.path.join(component_dir, "overrides", DEFAULT_OVERRIDE_FILE)
custom_file = hass.config.path(LOCAL_OVERRIDE_FILE)
base_data = {}
if os.path.exists(default_file):
try:
with open(default_file, "r", encoding="utf-8") as f:
base_data = json.load(f)
except json.JSONDecodeError as err:
_LOGGER.debug(
"File Override Error: Invalid JSON in %s: %s",
default_file,
err,
)
except OSError as err:
_LOGGER.debug(
"File Override Error: Unable to read %s: %s",
default_file,
err,
)
custom_data = {}
if os.path.exists(custom_file):
try:
with open(custom_file, "r", encoding="utf-8") as f:
custom_data = json.load(f)
except json.JSONDecodeError as err:
_LOGGER.warning(
"File Override Error: Invalid JSON in %s: %s",
custom_file,
err,
)
except OSError as err:
_LOGGER.debug(
"File Override Error: Unable to read %s: %s",
custom_file,
err,
)
override_data = deep_merge(base_data, custom_data)
return override_data
#
# season_slug_to_name()
#
def season_slug_to_name(slug: str) -> str:
"""Convert a season slug like '2025-26-english-premier-league' to 'English Premier League'."""
if not slug:
return ""
body = re.sub(r"^\d{4}(-\d{2})?-", "", slug)
if body == slug:
return ""
def _fmt_word(w):
# Uppercase abbreviations (no vowels, e.g. "mls", "nfl"); title-case real words
return w.upper() if w.isalpha() and not re.search(r"[aeiou]", w, re.I) else w.title()
return " ".join(_fmt_word(w) for w in body.split("-"))