File: store.py

package info (click to toggle)
python-aiohasupervisor 0.3.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 932 kB
  • sloc: python: 4,666; sh: 37; makefile: 3
file content (132 lines) | stat: -rw-r--r-- 4,953 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
"""Store client for supervisor."""

from typing import Any

from .client import _SupervisorComponentClient
from .const import ResponseType
from .models.addons import (
    Repository,
    StoreAddon,
    StoreAddonComplete,
    StoreAddonInstall,
    StoreAddonsList,
    StoreAddonUpdate,
    StoreAddRepository,
    StoreInfo,
)


class StoreClient(_SupervisorComponentClient):
    """Handles store access in Supervisor."""

    async def info(self) -> StoreInfo:
        """Get store info."""
        result = await self._client.get("store")
        return StoreInfo.from_dict(result.data)

    async def addons_list(self) -> list[StoreAddon]:
        """Get list of store addons."""
        result = await self._client.get("store/addons")
        return StoreAddonsList.from_dict(result.data).addons

    async def addon_info(self, addon: str) -> StoreAddonComplete:
        """Get store addon info."""
        result = await self._client.get(f"store/addons/{addon}")
        return StoreAddonComplete.from_dict(result.data)

    async def addon_changelog(self, addon: str) -> str:
        """Get addon changelog."""
        result = await self._client.get(
            f"store/addons/{addon}/changelog", response_type=ResponseType.TEXT
        )
        return result.data

    async def addon_documentation(self, addon: str) -> str:
        """Get addon documentation."""
        result = await self._client.get(
            f"store/addons/{addon}/documentation", response_type=ResponseType.TEXT
        )
        return result.data

    async def addon_availability(self, addon: str) -> None:
        """Determine if latest version of addon can be installed on this system.

        No return means it can be. If not, raises one of the following errors:
        - AddonUnavailableHomeAssistantVersionError
        - AddonUnavailableArchitectureError
        - AddonUnavailableMachineTypeError

        If Supervisor adds a new reason an add-on can be restricted from being
        installed on some systems in the future, older versions of this client
        will raise the generic SupervisorBadRequestError for that reason.
        """
        await self._client.get(
            f"store/addons/{addon}/availability", response_type=ResponseType.NONE
        )

    async def install_addon(
        self, addon: str, options: StoreAddonInstall | None = None
    ) -> None:
        """Install an addon.

        Supervisor does an availability check before install. If the addon
        cannot be installed on this system it will raise one of those errors
        shown in the `addon_availability` method.
        """
        # Must disable timeout if API call waits for install to complete
        kwargs: dict[str, Any] = {}
        if not options or not options.background:
            kwargs["timeout"] = None

        await self._client.post(
            f"store/addons/{addon}/install",
            json=options.to_dict() if options else None,
            **kwargs,
        )

    async def update_addon(
        self, addon: str, options: StoreAddonUpdate | None = None
    ) -> None:
        """Update an addon to latest version.

        Supervisor does an availability check before update. If the new version
        cannot be installed on this system it will raise one of those errors
        shown in the `addon_availability` method.
        """
        # Must disable timeout if API call waits for update to complete
        kwargs: dict[str, Any] = {}
        if not options or not options.background:
            kwargs["timeout"] = None

        await self._client.post(
            f"store/addons/{addon}/update",
            json=options.to_dict() if options else None,
            **kwargs,
        )

    async def reload(self) -> None:
        """Reload the store."""
        await self._client.post("store/reload")

    async def repositories_list(self) -> list[Repository]:
        """Get list of repositories."""
        result = await self._client.get("store/repositories")
        # This API is inconsistent with Supervisor's API model, data should be
        # a dictionary with a "repositories" field. It would break the CLI like
        # this but the CLI doesn't use it so it went unnoticed.
        return [Repository.from_dict(repo) for repo in result.data]

    async def repository_info(self, repository: str) -> Repository:
        """Get repository info."""
        result = await self._client.get(f"store/repositories/{repository}")
        return Repository.from_dict(result.data)

    async def add_repository(self, options: StoreAddRepository) -> None:
        """Add a repository to the store."""
        await self._client.post("store/repositories", json=options.to_dict())

    async def remove_repository(self, repository: str) -> None:
        """Remove a repository from the store."""
        await self._client.delete(f"store/repositories/{repository}")

    # Omitted for now - Icon/Logo endpoints