mirror of
https://github.com/home-assistant/core.git
synced 2025-07-15 17:27:10 +00:00
Update typing of BackupAgent.async_get_backup
(#139923)
* Update typing of BackupAgent.async_get_backup * Remove manual reset of frame helper
This commit is contained in:
parent
88f18fdfdc
commit
6ba45a32c0
@ -83,7 +83,7 @@ class BackupAgent(abc.ABC):
|
|||||||
self,
|
self,
|
||||||
backup_id: str,
|
backup_id: str,
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
) -> AgentBackup | None:
|
) -> AgentBackup:
|
||||||
"""Return a backup.
|
"""Return a backup.
|
||||||
|
|
||||||
Raises BackupNotFound if the backup does not exist.
|
Raises BackupNotFound if the backup does not exist.
|
||||||
|
@ -15,6 +15,7 @@ from multidict import istr
|
|||||||
from homeassistant.components.http import KEY_HASS, HomeAssistantView, require_admin
|
from homeassistant.components.http import KEY_HASS, HomeAssistantView, require_admin
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
|
from homeassistant.helpers import frame
|
||||||
from homeassistant.util import slugify
|
from homeassistant.util import slugify
|
||||||
|
|
||||||
from . import util
|
from . import util
|
||||||
@ -66,7 +67,12 @@ class DownloadBackupView(HomeAssistantView):
|
|||||||
|
|
||||||
# Check for None to be backwards compatible with the old BackupAgent API,
|
# Check for None to be backwards compatible with the old BackupAgent API,
|
||||||
# this can be removed in HA Core 2025.10
|
# this can be removed in HA Core 2025.10
|
||||||
if backup is None:
|
if not backup:
|
||||||
|
frame.report_usage(
|
||||||
|
"returns None from BackupAgent.async_get_backup",
|
||||||
|
breaks_in_ha_version="2025.10",
|
||||||
|
integration_domain=agent_id.partition(".")[0],
|
||||||
|
)
|
||||||
return Response(status=HTTPStatus.NOT_FOUND)
|
return Response(status=HTTPStatus.NOT_FOUND)
|
||||||
|
|
||||||
headers = {
|
headers = {
|
||||||
|
@ -30,6 +30,7 @@ from homeassistant.backup_restore import (
|
|||||||
from homeassistant.const import __version__ as HAVERSION
|
from homeassistant.const import __version__ as HAVERSION
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers import (
|
from homeassistant.helpers import (
|
||||||
|
frame,
|
||||||
instance_id,
|
instance_id,
|
||||||
integration_platform,
|
integration_platform,
|
||||||
issue_registry as ir,
|
issue_registry as ir,
|
||||||
@ -665,6 +666,11 @@ class BackupManager:
|
|||||||
# Check for None to be backwards compatible with the old BackupAgent API,
|
# Check for None to be backwards compatible with the old BackupAgent API,
|
||||||
# this can be removed in HA Core 2025.10
|
# this can be removed in HA Core 2025.10
|
||||||
if not result:
|
if not result:
|
||||||
|
frame.report_usage(
|
||||||
|
"returns None from BackupAgent.async_get_backup",
|
||||||
|
breaks_in_ha_version="2025.10",
|
||||||
|
integration_domain=agent_id.partition(".")[0],
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
if backup is None:
|
if backup is None:
|
||||||
if known_backup := self.known_backups.get(backup_id):
|
if known_backup := self.known_backups.get(backup_id):
|
||||||
@ -1280,6 +1286,11 @@ class BackupManager:
|
|||||||
# Check for None to be backwards compatible with the old BackupAgent API,
|
# Check for None to be backwards compatible with the old BackupAgent API,
|
||||||
# this can be removed in HA Core 2025.10
|
# this can be removed in HA Core 2025.10
|
||||||
if not backup:
|
if not backup:
|
||||||
|
frame.report_usage(
|
||||||
|
"returns None from BackupAgent.async_get_backup",
|
||||||
|
breaks_in_ha_version="2025.10",
|
||||||
|
integration_domain=agent_id.partition(".")[0],
|
||||||
|
)
|
||||||
raise BackupManagerError(
|
raise BackupManagerError(
|
||||||
f"Backup {backup_id} not found in agent {agent_id}"
|
f"Backup {backup_id} not found in agent {agent_id}"
|
||||||
)
|
)
|
||||||
@ -1376,6 +1387,11 @@ class BackupManager:
|
|||||||
# Check for None to be backwards compatible with the old BackupAgent API,
|
# Check for None to be backwards compatible with the old BackupAgent API,
|
||||||
# this can be removed in HA Core 2025.10
|
# this can be removed in HA Core 2025.10
|
||||||
if not backup:
|
if not backup:
|
||||||
|
frame.report_usage(
|
||||||
|
"returns None from BackupAgent.async_get_backup",
|
||||||
|
breaks_in_ha_version="2025.10",
|
||||||
|
integration_domain=agent_id.partition(".")[0],
|
||||||
|
)
|
||||||
raise BackupManagerError(
|
raise BackupManagerError(
|
||||||
f"Backup {backup_id} not found in agent {agent_id}"
|
f"Backup {backup_id} not found in agent {agent_id}"
|
||||||
)
|
)
|
||||||
|
@ -229,6 +229,17 @@
|
|||||||
'type': 'result',
|
'type': 'result',
|
||||||
})
|
})
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_can_decrypt_on_download_get_backup_returns_none
|
||||||
|
dict({
|
||||||
|
'error': dict({
|
||||||
|
'code': 'home_assistant_error',
|
||||||
|
'message': 'Backup abc123 not found in agent test.remote',
|
||||||
|
}),
|
||||||
|
'id': 1,
|
||||||
|
'success': False,
|
||||||
|
'type': 'result',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
# name: test_can_decrypt_on_download_with_agent_error[BackupAgentError]
|
# name: test_can_decrypt_on_download_with_agent_error[BackupAgentError]
|
||||||
dict({
|
dict({
|
||||||
'error': dict({
|
'error': dict({
|
||||||
@ -4930,6 +4941,18 @@
|
|||||||
'type': 'result',
|
'type': 'result',
|
||||||
})
|
})
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_details_get_backup_returns_none
|
||||||
|
dict({
|
||||||
|
'id': 1,
|
||||||
|
'result': dict({
|
||||||
|
'agent_errors': dict({
|
||||||
|
}),
|
||||||
|
'backup': None,
|
||||||
|
}),
|
||||||
|
'success': True,
|
||||||
|
'type': 'result',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
# name: test_details_with_errors[BackupAgentUnreachableError]
|
# name: test_details_with_errors[BackupAgentUnreachableError]
|
||||||
dict({
|
dict({
|
||||||
'id': 1,
|
'id': 1,
|
||||||
@ -5728,6 +5751,17 @@
|
|||||||
# name: test_restore_remote_agent[remote_agents1-backups1].1
|
# name: test_restore_remote_agent[remote_agents1-backups1].1
|
||||||
1
|
1
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_restore_remote_agent_get_backup_returns_none
|
||||||
|
dict({
|
||||||
|
'error': dict({
|
||||||
|
'code': 'home_assistant_error',
|
||||||
|
'message': 'Backup abc123 not found in agent test.remote',
|
||||||
|
}),
|
||||||
|
'id': 1,
|
||||||
|
'success': False,
|
||||||
|
'type': 'result',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
# name: test_restore_wrong_password
|
# name: test_restore_wrong_password
|
||||||
dict({
|
dict({
|
||||||
'error': dict({
|
'error': dict({
|
||||||
|
@ -234,6 +234,26 @@ async def test_downloading_backup_not_found(
|
|||||||
assert resp.status == 404
|
assert resp.status == 404
|
||||||
|
|
||||||
|
|
||||||
|
async def test_downloading_backup_not_found_get_backup_returns_none(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
hass_client: ClientSessionGenerator,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
) -> None:
|
||||||
|
"""Test downloading a backup file that does not exist."""
|
||||||
|
mock_agents = await setup_backup_integration(hass, remote_agents=["test.test"])
|
||||||
|
mock_agents["test.test"].async_get_backup.return_value = None
|
||||||
|
mock_agents["test.test"].async_get_backup.side_effect = None
|
||||||
|
|
||||||
|
client = await hass_client()
|
||||||
|
|
||||||
|
resp = await client.get("/api/backup/download/abc123?agent_id=test.test")
|
||||||
|
assert resp.status == 404
|
||||||
|
assert (
|
||||||
|
"Detected that integration 'test' returns None from BackupAgent.async_get_backup."
|
||||||
|
in caplog.text
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_downloading_as_non_admin(
|
async def test_downloading_as_non_admin(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
hass_client: ClientSessionGenerator,
|
hass_client: ClientSessionGenerator,
|
||||||
|
@ -234,6 +234,31 @@ async def test_details_with_errors(
|
|||||||
assert await client.receive_json() == snapshot
|
assert await client.receive_json() == snapshot
|
||||||
|
|
||||||
|
|
||||||
|
async def test_details_get_backup_returns_none(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
hass_ws_client: WebSocketGenerator,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
snapshot: SnapshotAssertion,
|
||||||
|
) -> None:
|
||||||
|
"""Test getting backup info when the agent returns None from get_backup."""
|
||||||
|
mock_agents = await setup_backup_integration(hass, remote_agents=["test.remote"])
|
||||||
|
mock_agents["test.remote"].async_get_backup.return_value = None
|
||||||
|
mock_agents["test.remote"].async_get_backup.side_effect = None
|
||||||
|
|
||||||
|
client = await hass_ws_client(hass)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
with patch("pathlib.Path.exists", return_value=True):
|
||||||
|
await client.send_json_auto_id(
|
||||||
|
{"type": "backup/details", "backup_id": "abc123"}
|
||||||
|
)
|
||||||
|
assert await client.receive_json() == snapshot
|
||||||
|
assert (
|
||||||
|
"Detected that integration 'test' returns None from BackupAgent.async_get_backup."
|
||||||
|
in caplog.text
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("remote_agents", "backups"),
|
("remote_agents", "backups"),
|
||||||
[
|
[
|
||||||
@ -724,6 +749,36 @@ async def test_restore_remote_agent(
|
|||||||
assert len(restart_calls) == snapshot
|
assert len(restart_calls) == snapshot
|
||||||
|
|
||||||
|
|
||||||
|
async def test_restore_remote_agent_get_backup_returns_none(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
hass_ws_client: WebSocketGenerator,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
snapshot: SnapshotAssertion,
|
||||||
|
) -> None:
|
||||||
|
"""Test calling the restore command when the agent returns None from get_backup."""
|
||||||
|
mock_agents = await setup_backup_integration(hass, remote_agents=["test.remote"])
|
||||||
|
mock_agents["test.remote"].async_get_backup.return_value = None
|
||||||
|
mock_agents["test.remote"].async_get_backup.side_effect = None
|
||||||
|
restart_calls = async_mock_service(hass, "homeassistant", "restart")
|
||||||
|
|
||||||
|
client = await hass_ws_client(hass)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
await client.send_json_auto_id(
|
||||||
|
{
|
||||||
|
"type": "backup/restore",
|
||||||
|
"backup_id": "abc123",
|
||||||
|
"agent_id": "test.remote",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assert await client.receive_json() == snapshot
|
||||||
|
assert len(restart_calls) == 0
|
||||||
|
assert (
|
||||||
|
"Detected that integration 'test' returns None from BackupAgent.async_get_backup."
|
||||||
|
in caplog.text
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_restore_wrong_password(
|
async def test_restore_wrong_password(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
hass_ws_client: WebSocketGenerator,
|
hass_ws_client: WebSocketGenerator,
|
||||||
@ -3543,3 +3598,32 @@ async def test_can_decrypt_on_download_with_agent_error(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
assert await client.receive_json() == snapshot
|
assert await client.receive_json() == snapshot
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("mock_backups")
|
||||||
|
async def test_can_decrypt_on_download_get_backup_returns_none(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
hass_ws_client: WebSocketGenerator,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
snapshot: SnapshotAssertion,
|
||||||
|
) -> None:
|
||||||
|
"""Test can decrypt on download when the agent returns None from get_backup."""
|
||||||
|
|
||||||
|
mock_agents = await setup_backup_integration(hass, remote_agents=["test.remote"])
|
||||||
|
mock_agents["test.remote"].async_get_backup.return_value = None
|
||||||
|
mock_agents["test.remote"].async_get_backup.side_effect = None
|
||||||
|
|
||||||
|
client = await hass_ws_client(hass)
|
||||||
|
await client.send_json_auto_id(
|
||||||
|
{
|
||||||
|
"type": "backup/can_decrypt_on_download",
|
||||||
|
"backup_id": TEST_BACKUP_ABC123.backup_id,
|
||||||
|
"agent_id": "test.remote",
|
||||||
|
"password": "hunter2",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
assert await client.receive_json() == snapshot
|
||||||
|
assert (
|
||||||
|
"Detected that integration 'test' returns None from BackupAgent.async_get_backup."
|
||||||
|
in caplog.text
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user