Skip to content

Commit 54b2374

Browse files
authored
Add remove and download location (#35)
1 parent 202f070 commit 54b2374

File tree

5 files changed

+91
-11
lines changed

5 files changed

+91
-11
lines changed

aiohasupervisor/backups.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414
BackupList,
1515
BackupsInfo,
1616
BackupsOptions,
17+
DownloadBackupOptions,
1718
FreezeOptions,
1819
FullBackupOptions,
1920
FullRestoreOptions,
2021
NewBackup,
2122
PartialBackupOptions,
2223
PartialRestoreOptions,
24+
RemoveBackupOptions,
2325
UploadBackupOptions,
2426
UploadedBackup,
2527
)
@@ -81,9 +83,13 @@ async def backup_info(self, backup: str) -> BackupComplete:
8183
result = await self._client.get(f"backups/{backup}/info")
8284
return BackupComplete.from_dict(result.data)
8385

84-
async def remove_backup(self, backup: str) -> None:
86+
async def remove_backup(
87+
self, backup: str, options: RemoveBackupOptions | None = None
88+
) -> None:
8589
"""Remove a backup."""
86-
await self._client.delete(f"backups/{backup}")
90+
await self._client.delete(
91+
f"backups/{backup}", json=options.to_dict() if options else None
92+
)
8793

8894
async def full_restore(
8995
self, backup: str, options: FullRestoreOptions | None = None
@@ -129,9 +135,17 @@ async def upload_backup(
129135

130136
return UploadedBackup.from_dict(result.data).slug
131137

132-
async def download_backup(self, backup: str) -> AsyncIterator[bytes]:
138+
async def download_backup(
139+
self, backup: str, options: DownloadBackupOptions | None = None
140+
) -> AsyncIterator[bytes]:
133141
"""Download backup and return stream."""
142+
params = MultiDict()
143+
if options and options.location:
144+
params.add("location", options.location or "")
145+
134146
result = await self._client.get(
135-
f"backups/{backup}/download", response_type=ResponseType.STREAM
147+
f"backups/{backup}/download",
148+
params=params,
149+
response_type=ResponseType.STREAM,
136150
)
137151
return result.data

aiohasupervisor/client.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ async def delete(
212212
uri: str,
213213
*,
214214
params: dict[str, str] | MultiDict[str] | None = None,
215+
json: dict[str, Any] | None = None,
215216
timeout: ClientTimeout | None = DEFAULT_TIMEOUT,
216217
) -> Response:
217218
"""Handle a DELETE request to Supervisor."""
@@ -220,6 +221,7 @@ async def delete(
220221
uri,
221222
params=params,
222223
response_type=ResponseType.NONE,
224+
json=json,
223225
timeout=timeout,
224226
)
225227

aiohasupervisor/models/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,15 @@
3333
BackupsInfo,
3434
BackupsOptions,
3535
BackupType,
36+
DownloadBackupOptions,
3637
Folder,
3738
FreezeOptions,
3839
FullBackupOptions,
3940
FullRestoreOptions,
4041
NewBackup,
4142
PartialBackupOptions,
4243
PartialRestoreOptions,
44+
RemoveBackupOptions,
4345
UploadBackupOptions,
4446
)
4547
from aiohasupervisor.models.discovery import (
@@ -209,13 +211,15 @@
209211
"BackupsInfo",
210212
"BackupsOptions",
211213
"BackupType",
214+
"DownloadBackupOptions",
212215
"Folder",
213216
"FreezeOptions",
214217
"FullBackupOptions",
215218
"FullRestoreOptions",
216219
"NewBackup",
217220
"PartialBackupOptions",
218221
"PartialRestoreOptions",
222+
"RemoveBackupOptions",
219223
"UploadBackupOptions",
220224
"Discovery",
221225
"DiscoveryConfig",

aiohasupervisor/models/backups.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from datetime import datetime
66
from enum import StrEnum
77

8-
from .base import Request, ResponseData
8+
from .base import DEFAULT, Request, ResponseData
99

1010
# --- ENUMS ----
1111

@@ -135,7 +135,7 @@ class FullBackupOptions(Request):
135135
name: str | None = None
136136
password: str | None = None
137137
compressed: bool | None = None
138-
location: set[str | None] | str | None = None
138+
location: list[str | None] | str | None = DEFAULT # type: ignore[assignment]
139139
homeassistant_exclude_database: bool | None = None
140140
background: bool | None = None
141141
extra: dict | None = None
@@ -185,3 +185,17 @@ class UploadedBackup(ResponseData):
185185
"""UploadedBackup model."""
186186

187187
slug: str
188+
189+
190+
@dataclass(frozen=True, slots=True)
191+
class RemoveBackupOptions(Request):
192+
"""RemoveBackupOptions model."""
193+
194+
location: set[str | None] = None
195+
196+
197+
@dataclass(frozen=True, slots=True)
198+
class DownloadBackupOptions(Request):
199+
"""DownloadBackupOptions model."""
200+
201+
location: str | None = DEFAULT # type: ignore[assignment]

tests/test_backups.py

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212
from aiohasupervisor import SupervisorClient
1313
from aiohasupervisor.models import (
1414
BackupsOptions,
15+
DownloadBackupOptions,
1516
Folder,
1617
FreezeOptions,
1718
FullBackupOptions,
1819
PartialBackupOptions,
1920
PartialRestoreOptions,
21+
RemoveBackupOptions,
2022
UploadBackupOptions,
2123
)
2224

@@ -131,6 +133,32 @@ async def test_partial_restore_options() -> None:
131133
PartialRestoreOptions(background=True)
132134

133135

136+
async def test_backup_options_location() -> None:
137+
"""Test location field in backup options."""
138+
assert FullBackupOptions(location=["test", None]).to_dict() == {
139+
"location": ["test", None]
140+
}
141+
assert FullBackupOptions(location="test").to_dict() == {"location": "test"}
142+
assert FullBackupOptions(location=None).to_dict() == {"location": None}
143+
assert FullBackupOptions().to_dict() == {}
144+
145+
assert PartialBackupOptions(
146+
location=["test", None], folders={Folder.SSL}
147+
).to_dict() == {
148+
"location": ["test", None],
149+
"folders": ["ssl"],
150+
}
151+
assert PartialBackupOptions(location="test", folders={Folder.SSL}).to_dict() == {
152+
"location": "test",
153+
"folders": ["ssl"],
154+
}
155+
assert PartialBackupOptions(location=None, folders={Folder.SSL}).to_dict() == {
156+
"location": None,
157+
"folders": ["ssl"],
158+
}
159+
assert PartialBackupOptions(folders={Folder.SSL}).to_dict() == {"folders": ["ssl"]}
160+
161+
134162
def backup_callback(url: str, **kwargs: dict[str, Any]) -> CallbackResult: # noqa: ARG001
135163
"""Return response based on whether backup was in background or not."""
136164
if kwargs["json"] and kwargs["json"].get("background"):
@@ -323,12 +351,17 @@ async def test_backup_info_with_multiple_locations(
323351
assert result.locations == {None, "Test"}
324352

325353

354+
@pytest.mark.parametrize(
355+
"options", [None, RemoveBackupOptions(location={"test", None})]
356+
)
326357
async def test_remove_backup(
327-
responses: aioresponses, supervisor_client: SupervisorClient
358+
responses: aioresponses,
359+
supervisor_client: SupervisorClient,
360+
options: RemoveBackupOptions | None,
328361
) -> None:
329362
"""Test remove backup API."""
330363
responses.delete(f"{SUPERVISOR_URL}/backups/abc123", status=200)
331-
assert await supervisor_client.backups.remove_backup("abc123") is None
364+
assert await supervisor_client.backups.remove_backup("abc123", options) is None
332365
assert responses.requests.keys() == {
333366
("DELETE", URL(f"{SUPERVISOR_URL}/backups/abc123"))
334367
}
@@ -398,14 +431,27 @@ async def test_upload_backup_to_locations(
398431
assert result == "7fed74c8"
399432

400433

434+
@pytest.mark.parametrize(
435+
("options", "query"),
436+
[
437+
(None, ""),
438+
(DownloadBackupOptions(location="test"), "?location=test"),
439+
(DownloadBackupOptions(location=None), "?location="),
440+
],
441+
)
401442
async def test_download_backup(
402-
responses: aioresponses, supervisor_client: SupervisorClient
443+
responses: aioresponses,
444+
supervisor_client: SupervisorClient,
445+
options: DownloadBackupOptions | None,
446+
query: str,
403447
) -> None:
404448
"""Test download backup API."""
405449
responses.get(
406-
f"{SUPERVISOR_URL}/backups/7fed74c8/download", status=200, body=b"backup test"
450+
f"{SUPERVISOR_URL}/backups/7fed74c8/download{query}",
451+
status=200,
452+
body=b"backup test",
407453
)
408-
result = await supervisor_client.backups.download_backup("7fed74c8")
454+
result = await supervisor_client.backups.download_backup("7fed74c8", options)
409455
assert isinstance(result, AsyncIterator)
410456
async for chunk in result:
411457
assert chunk == b"backup test"

0 commit comments

Comments
 (0)