from typing import Any, Dict from backup.const import SOURCE_HA from backup.exceptions import ensureKey from backup.time import Time from .backups import AbstractBackup from backup.logger import getLogger from backup.util import DataCache, KEY_I_MADE_THIS, KEY_IGNORE, KEY_NOTE from backup.config import Config, Setting logger = getLogger(__name__) HA_KEY_TEXT = "Home Assistant's backup metadata" class HABackup(AbstractBackup): """ Represents a Home Assistant backup stored locally in Home Assistant """ def __init__(self, data: Dict[str, Any], data_cache: DataCache, config: Config, retained=False): super().__init__( name=ensureKey('name', data, HA_KEY_TEXT), slug=ensureKey('slug', data, HA_KEY_TEXT), date=Time.parse(ensureKey('date', data, HA_KEY_TEXT)), size=float(ensureKey("size", data, HA_KEY_TEXT)) * 1024 * 1024, source=SOURCE_HA, backupType=ensureKey('type', data, HA_KEY_TEXT), version=ensureKey('homeassistant', data, HA_KEY_TEXT), protected=ensureKey('protected', data, HA_KEY_TEXT), retained=retained, uploadable=True, details=data, pending=False) self._data_cache = data_cache self._config = config def madeByTheAddon(self): return self._data_cache.backup(self.slug()).get(KEY_I_MADE_THIS, False) def note(self): parent = super().note() if parent is None: return self._data_cache.backup(self.slug()).get(KEY_NOTE, None) else: return parent def ignore(self): override = self._data_cache.backup(self.slug()).get(KEY_IGNORE, None) if override is not None: return override if self.madeByTheAddon(): return False if self._config.get(Setting.IGNORE_OTHER_BACKUPS): return True archive_count = len(self.details().get("addons", [])) + len(self.details().get("folders", [])) if self.details().get("homeassistant", None) is not None: # Supervisor backup query API doesn't quite match the create API, if the HA config folder # is present in a backup then the Home Assistant version is present in its details archive_count += 1 if archive_count == 1 and self._config.get(Setting.IGNORE_UPGRADE_BACKUPS): return True return super().ignore() def __str__(self) -> str: return "".format(self.slug(), self.name(), self.date().isoformat()) def __format__(self, format_spec: str) -> str: return self.__str__() def __repr__(self) -> str: return self.__str__()