Initial Home Assistant commit
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
""" 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("-"))
|
||||
Reference in New Issue
Block a user