1
0
mirror of https://github.com/home-assistant/supervisor.git synced 2026-05-08 17:08:36 +01:00

Fix type annotations in backup and restore methods (#6523)

Update type hints throughout backup/restore code to match actual types:
- Change tarfile.TarFile to SecureTarFile for backup/restore methods
- Add None union types for Backup properties that can return None
- Fix exclude_database parameter to accept None in restore method
- Update API backup methods to handle None return from backup tasks
- Fix condition check for exclude_database to explicitly compare with True
- Add assertion to help type checker with indexed assignment

These changes improve type safety and resolve type checking issues
discovered by runtime type validation.

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Stefan Agner
2026-02-04 11:18:06 +01:00
committed by GitHub
parent d1a576e711
commit df03b8fb68
5 changed files with 15 additions and 17 deletions
+3 -3
View File
@@ -20,7 +20,7 @@ from typing import Any, Final, cast
import aiohttp
from awesomeversion import AwesomeVersion, AwesomeVersionCompareException
from deepmerge import Merger
from securetar import AddFileError, atomic_contents_add, secure_path
from securetar import AddFileError, SecureTarFile, atomic_contents_add, secure_path
import voluptuous as vol
from voluptuous.humanize import humanize_error
@@ -1308,7 +1308,7 @@ class Addon(AddonModel):
on_condition=AddonsJobError,
concurrency=JobConcurrency.GROUP_REJECT,
)
async def backup(self, tar_file: tarfile.TarFile) -> asyncio.Task | None:
async def backup(self, tar_file: SecureTarFile) -> asyncio.Task | None:
"""Backup state of an add-on.
Returns a Task that completes when addon has state 'started' (see start)
@@ -1414,7 +1414,7 @@ class Addon(AddonModel):
on_condition=AddonsJobError,
concurrency=JobConcurrency.GROUP_REJECT,
)
async def restore(self, tar_file: tarfile.TarFile) -> asyncio.Task | None:
async def restore(self, tar_file: SecureTarFile) -> asyncio.Task | None:
"""Restore state of an add-on.
Returns a Task that completes when addon has state 'started' (see start)
+2 -4
View File
@@ -4,10 +4,10 @@ import asyncio
from collections.abc import Awaitable
from contextlib import suppress
import logging
import tarfile
from typing import Self, Union
from attr import evolve
from securetar import SecureTarFile
from ..const import AddonBoot, AddonStartup, AddonState
from ..coresys import CoreSys, CoreSysAttributes
@@ -334,9 +334,7 @@ class AddonManager(CoreSysAttributes):
],
on_condition=AddonsJobError,
)
async def restore(
self, slug: str, tar_file: tarfile.TarFile
) -> asyncio.Task | None:
async def restore(self, slug: str, tar_file: SecureTarFile) -> asyncio.Task | None:
"""Restore state of an add-on.
Returns a Task that completes when addon has state 'started' (see addon.start)
+2 -2
View File
@@ -310,7 +310,7 @@ class APIBackups(CoreSysAttributes):
if background and not backup_task.done():
return {ATTR_JOB_ID: job_id}
backup: Backup = await backup_task
backup: Backup | None = await backup_task
if backup:
return {ATTR_JOB_ID: job_id, ATTR_SLUG: backup.slug}
raise APIError(
@@ -346,7 +346,7 @@ class APIBackups(CoreSysAttributes):
if background and not backup_task.done():
return {ATTR_JOB_ID: job_id}
backup: Backup = await backup_task
backup: Backup | None = await backup_task
if backup:
return {ATTR_JOB_ID: job_id, ATTR_SLUG: backup.slug}
raise APIError(
+4 -4
View File
@@ -170,21 +170,21 @@ class Backup(JobGroup):
self._data[ATTR_REPOSITORIES] = value
@property
def homeassistant_version(self) -> AwesomeVersion:
def homeassistant_version(self) -> AwesomeVersion | None:
"""Return backup Home Assistant version."""
if self.homeassistant is None:
return None
return self.homeassistant[ATTR_VERSION]
@property
def homeassistant_exclude_database(self) -> bool:
def homeassistant_exclude_database(self) -> bool | None:
"""Return whether database was excluded from Home Assistant backup."""
if self.homeassistant is None:
return None
return self.homeassistant[ATTR_EXCLUDE_DATABASE]
@property
def homeassistant(self) -> dict[str, Any]:
def homeassistant(self) -> dict[str, Any] | None:
"""Return backup Home Assistant data."""
return self._data[ATTR_HOMEASSISTANT]
@@ -863,7 +863,7 @@ class Backup(JobGroup):
await self.sys_homeassistant.backup(homeassistant_file, exclude_database)
# Store size
self.homeassistant[ATTR_SIZE] = await self.sys_run_in_executor(
self._data[ATTR_HOMEASSISTANT][ATTR_SIZE] = await self.sys_run_in_executor(
getattr, homeassistant_file, "size"
)
+4 -4
View File
@@ -13,7 +13,7 @@ from typing import Any
from uuid import UUID
from awesomeversion import AwesomeVersion, AwesomeVersionException
from securetar import AddFileError, atomic_contents_add, secure_path
from securetar import AddFileError, SecureTarFile, atomic_contents_add, secure_path
import voluptuous as vol
from voluptuous.humanize import humanize_error
@@ -410,7 +410,7 @@ class HomeAssistant(FileConfiguration, CoreSysAttributes):
@Job(name="home_assistant_module_backup")
async def backup(
self, tar_file: tarfile.TarFile, exclude_database: bool = False
self, tar_file: SecureTarFile, exclude_database: bool = False
) -> None:
"""Backup Home Assistant Core config/directory."""
excludes = HOMEASSISTANT_BACKUP_EXCLUDE.copy()
@@ -470,7 +470,7 @@ class HomeAssistant(FileConfiguration, CoreSysAttributes):
@Job(name="home_assistant_module_restore")
async def restore(
self, tar_file: tarfile.TarFile, exclude_database: bool = False
self, tar_file: SecureTarFile, exclude_database: bool | None = False
) -> None:
"""Restore Home Assistant Core config/ directory."""
@@ -502,7 +502,7 @@ class HomeAssistant(FileConfiguration, CoreSysAttributes):
temp_data = temp_path
_LOGGER.info("Restore Home Assistant Core config folder")
if exclude_database:
if exclude_database is True:
remove_folder_with_excludes(
self.sys_config.path_homeassistant,
excludes=HOMEASSISTANT_BACKUP_EXCLUDE_DATABASE,