Compare commits

...

11 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
085140f365 Fix malformed matrix include configuration for runs-on
Co-authored-by: agners <34061+agners@users.noreply.github.com>
2025-12-02 10:25:06 +00:00
copilot-swe-agent[bot]
30f5fdb5ad Initial plan 2025-12-02 10:23:34 +00:00
Jan Čermák
02a17868b8 Use unpublished local wheels during PR builds
Refactor wheel building to use the new `local-wheels-repo-path` and move wheels
building into a separate CI job. Wheels are only published on published (i.e.
release or merged dev), for PR builds they are passed as artifacts to the build
job instead.
2025-12-01 20:15:29 +01:00
Stefan Agner
fa490210cd Improve CpuArch type safety across codebase (#6372)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-01 19:56:05 +01:00
Jan Čermák
ba82eb0620 Clean up Dockerfile after dropping deprecated architectures (#6373)
Clean up unnecessary arguments that were needed for deprecated architectures,
bind-mount requirements file to reduce image bloat.
2025-12-01 19:43:19 +01:00
dependabot[bot]
11e3fa0bb7 Bump mypy from 1.18.2 to 1.19.0 (#6366)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Stefan Agner <stefan@agner.ch>
2025-12-01 16:38:13 +01:00
dependabot[bot]
9466111d56 Bump types-docker from 7.1.0.20251127 to 7.1.0.20251129 (#6369)
* Bump types-docker from 7.1.0.20251127 to 7.1.0.20251129

Bumps [types-docker](https://github.com/typeshed-internal/stub_uploader) from 7.1.0.20251127 to 7.1.0.20251129.
- [Commits](https://github.com/typeshed-internal/stub_uploader/commits)

---
updated-dependencies:
- dependency-name: types-docker
  dependency-version: 7.1.0.20251129
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Fix type errors for types-docker 7.1.0.20251129

- Cast stats() return to dict[str, Any] when stream=False since the
  type stubs return Iterator | dict but we know it's dict when not
  streaming
- Cast attach_socket() return to SocketIO for local Docker connections
  via Unix socket, as the type stubs include types for SSH and other
  connection methods

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Stefan Agner <stefan@agner.ch>
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-01 15:08:39 +01:00
Stefan Agner
5ec3bea0dd Remove UP038 from ruff ignore list (#6370)
The UP038 rule was removed from ruff in version 0.13.0, causing a warning
when running ruff. Remove it from the ignore list to eliminate the warning.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-12-01 13:57:41 +01:00
dependabot[bot]
72159a0ae2 Bump pylint from 4.0.3 to 4.0.4 (#6368)
Bumps [pylint](https://github.com/pylint-dev/pylint) from 4.0.3 to 4.0.4.
- [Release notes](https://github.com/pylint-dev/pylint/releases)
- [Commits](https://github.com/pylint-dev/pylint/compare/v4.0.3...v4.0.4)

---
updated-dependencies:
- dependency-name: pylint
  dependency-version: 4.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 08:41:31 +01:00
dependabot[bot]
0a7b26187d Bump ruff from 0.14.6 to 0.14.7 (#6367)
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.14.6 to 0.14.7.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.14.6...0.14.7)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.14.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 08:41:14 +01:00
dependabot[bot]
2dc1f9224e Bump home-assistant/builder from 2025.09.0 to 2025.11.0 (#6363)
Bumps [home-assistant/builder](https://github.com/home-assistant/builder) from 2025.09.0 to 2025.11.0.
- [Release notes](https://github.com/home-assistant/builder/releases)
- [Commits](https://github.com/home-assistant/builder/compare/2025.09.0...2025.11.0)

---
updated-dependencies:
- dependency-name: home-assistant/builder
  dependency-version: 2025.11.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 08:40:38 +01:00
20 changed files with 191 additions and 103 deletions

View File

@@ -1,6 +1,7 @@
# General files
.git
.github
.gitkeep
.devcontainer
.vscode

View File

@@ -78,13 +78,80 @@ jobs:
- name: Check if requirements files changed
id: requirements
run: |
if [[ "${{ steps.changed_files.outputs.all }}" =~ (requirements.txt|build.yaml) ]]; then
if [[ "${{ steps.changed_files.outputs.all }}" =~ (requirements.txt|build.yaml|builder.yml) ]]; then
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
build_wheels:
name: Build wheels for ${{ matrix.arch }}
needs: init
if: needs.init.outputs.requirements == 'true'
runs-on: ${{ matrix.runs-on }}
strategy:
matrix:
arch: ${{ fromJson(needs.init.outputs.architectures) }}
runs-on: [ubuntu-24.04]
include:
- arch: aarch64
runs-on: ubuntu-24.04-arm
env:
ABI: cp313
TAG: musllinux_1_2
APK_DEPS: "libffi-dev;openssl-dev;yaml-dev"
SKIP_BINARY: aiohttp
steps:
- name: Checkout the repository
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- name: Write env-file
run: |
(
# Fix out of memory issues with rust
echo "CARGO_NET_GIT_FETCH_WITH_CLI=true"
) > .env_file
- name: Build and publish wheels
if: needs.init.outputs.publish == 'true'
uses: home-assistant/wheels@e5742a69d69f0e274e2689c998900c7d19652c21 # 2025.12.0
with:
wheels-key: ${{ secrets.WHEELS_KEY }}
abi: ${{ env.ABI }}
tag: ${{ env.TAG }}
arch: ${{ matrix.arch }}
apk: ${{ env.APK_DEPS }}
skip-binary: ${{ env.SKIP_BINARY }}
env-file: true
requirements: "requirements.txt"
- name: Build local wheels
uses: home-assistant/wheels@e5742a69d69f0e274e2689c998900c7d19652c21 # 2025.12.0
if: needs.init.outputs.publish == 'false'
with:
wheels-host: ""
wheels-user: ""
wheels-key: ""
local-wheels-repo-path: "wheels"
abi: ${{ env.ABI }}
tag: ${{ env.TAG }}
arch: ${{ matrix.arch }}
apk: ${{ env.APK_DEPS }}
skip-binary: ${{ env.SKIP_BINARY }}
env-file: true
requirements: "requirements.txt"
- name: Upload local wheels artifact
if: needs.init.outputs.publish == 'false'
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: wheels-${{ matrix.arch }}
path: wheels
retention-days: 1
build:
name: Build ${{ matrix.arch }} supervisor
needs: init
needs: [init, build_wheels]
if: ${{ !cancelled() && !failure() }}
runs-on: ubuntu-latest
permissions:
contents: read
@@ -99,27 +166,12 @@ jobs:
with:
fetch-depth: 0
- name: Write env-file
if: needs.init.outputs.requirements == 'true'
run: |
(
# Fix out of memory issues with rust
echo "CARGO_NET_GIT_FETCH_WITH_CLI=true"
) > .env_file
# home-assistant/wheels doesn't support sha pinning
- name: Build wheels
if: needs.init.outputs.requirements == 'true'
uses: home-assistant/wheels@2025.11.0
- name: Download local wheels artifact
if: needs.init.outputs.requirements == 'true' && needs.init.outputs.publish == 'false'
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
abi: cp313
tag: musllinux_1_2
arch: ${{ matrix.arch }}
wheels-key: ${{ secrets.WHEELS_KEY }}
apk: "libffi-dev;openssl-dev;yaml-dev"
skip-binary: aiohttp
env-file: true
requirements: "requirements.txt"
name: wheels-${{ matrix.arch }}
path: wheels
- name: Set version
if: needs.init.outputs.publish == 'true'
@@ -165,7 +217,7 @@ jobs:
# home-assistant/builder doesn't support sha pinning
- name: Build supervisor
uses: home-assistant/builder@2025.09.0
uses: home-assistant/builder@2025.11.0
with:
args: |
$BUILD_ARGS \
@@ -208,10 +260,17 @@ jobs:
- name: Checkout the repository
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
- name: Download local wheels artifact
if: needs.init.outputs.requirements == 'true' && needs.init.outputs.publish == 'false'
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: wheels-amd64
path: wheels
# home-assistant/builder doesn't support sha pinning
- name: Build the Supervisor
if: needs.init.outputs.publish != 'true'
uses: home-assistant/builder@2025.09.0
uses: home-assistant/builder@2025.11.0
with:
args: |
--test \

5
.gitignore vendored
View File

@@ -24,6 +24,9 @@ var/
.installed.cfg
*.egg
# Local wheels
wheels/**/*.whl
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
@@ -102,4 +105,4 @@ ENV/
/.dmypy.json
# Mac
.DS_Store
.DS_Store

View File

@@ -8,9 +8,7 @@ ENV \
UV_SYSTEM_PYTHON=true
ARG \
COSIGN_VERSION \
BUILD_ARCH \
QEMU_CPU
COSIGN_VERSION
# Install base
WORKDIR /usr/src
@@ -32,15 +30,19 @@ RUN \
&& pip3 install uv==0.8.9
# Install requirements
COPY requirements.txt .
RUN \
if [ "${BUILD_ARCH}" = "i386" ]; then \
setarch="linux32"; \
--mount=type=bind,source=./requirements.txt,target=/usr/src/requirements.txt \
--mount=type=bind,source=./wheels,target=/usr/src/wheels \
if ls /usr/src/wheels/musllinux/* >/dev/null 2>&1; then \
LOCAL_WHEELS=/usr/src/wheels/musllinux; \
echo "Using local wheels from: $LOCAL_WHEELS"; \
else \
setarch=""; \
fi \
&& ${setarch} uv pip install --compile-bytecode --no-cache --no-build -r requirements.txt \
&& rm -f requirements.txt
LOCAL_WHEELS=; \
echo "No local wheels found"; \
fi && \
uv pip install --compile-bytecode --no-cache --no-build \
-r requirements.txt \
${LOCAL_WHEELS:+--find-links $LOCAL_WHEELS}
# Install Home Assistant Supervisor
COPY . supervisor

View File

@@ -321,8 +321,6 @@ lint.ignore = [
"PLW2901", # Outer {outer_kind} variable {name} overwritten by inner {inner_kind} target
"UP006", # keep type annotation style as is
"UP007", # keep type annotation style as is
# Ignored due to performance: https://github.com/charliermarsh/ruff/issues/2923
"UP038", # Use `X | Y` in `isinstance` call instead of `(X, Y)`
# May conflict with the formatter, https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules
"W191",

View File

@@ -1,16 +1,16 @@
astroid==4.0.2
coverage==7.12.0
mypy==1.18.2
mypy==1.19.0
pre-commit==4.5.0
pylint==4.0.3
pylint==4.0.4
pytest-aiohttp==1.1.0
pytest-asyncio==1.3.0
pytest-cov==7.0.0
pytest-timeout==2.4.0
pytest==9.0.1
ruff==0.14.6
ruff==0.14.7
time-machine==3.1.0
types-docker==7.1.0.20251127
types-docker==7.1.0.20251129
types-pyyaml==6.0.12.20250915
types-requests==2.32.4.20250913
urllib3==2.5.0

View File

@@ -20,6 +20,7 @@ from ..const import (
FILE_SUFFIX_CONFIGURATION,
META_ADDON,
SOCKET_DOCKER,
CpuArch,
)
from ..coresys import CoreSys, CoreSysAttributes
from ..docker.const import DOCKER_HUB
@@ -67,7 +68,7 @@ class AddonBuild(FileConfiguration, CoreSysAttributes):
raise RuntimeError()
@cached_property
def arch(self) -> str:
def arch(self) -> CpuArch:
"""Return arch of the add-on."""
return self.sys_arch.match([self.addon.arch])

View File

@@ -87,6 +87,7 @@ from ..const import (
AddonBootConfig,
AddonStage,
AddonStartup,
CpuArch,
)
from ..coresys import CoreSys
from ..docker.const import Capabilities
@@ -548,7 +549,7 @@ class AddonModel(JobGroup, ABC):
return self.data.get(ATTR_MACHINE, [])
@property
def arch(self) -> str:
def arch(self) -> CpuArch:
"""Return architecture to use for the addon's image."""
if ATTR_IMAGE in self.data:
return self.sys_arch.match(self.data[ATTR_ARCH])

View File

@@ -4,6 +4,7 @@ import logging
from pathlib import Path
import platform
from .const import CpuArch
from .coresys import CoreSys, CoreSysAttributes
from .exceptions import ConfigurationFileError, HassioArchNotFound
from .utils.json import read_json_file
@@ -12,38 +13,40 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
ARCH_JSON: Path = Path(__file__).parent.joinpath("data/arch.json")
MAP_CPU = {
"armv7": "armv7",
"armv6": "armhf",
"armv8": "aarch64",
"aarch64": "aarch64",
"i686": "i386",
"x86_64": "amd64",
MAP_CPU: dict[str, CpuArch] = {
"armv7": CpuArch.ARMV7,
"armv6": CpuArch.ARMHF,
"armv8": CpuArch.AARCH64,
"aarch64": CpuArch.AARCH64,
"i686": CpuArch.I386,
"x86_64": CpuArch.AMD64,
}
class CpuArch(CoreSysAttributes):
class CpuArchManager(CoreSysAttributes):
"""Manage available architectures."""
def __init__(self, coresys: CoreSys) -> None:
"""Initialize CPU Architecture handler."""
self.coresys = coresys
self._supported_arch: list[str] = []
self._supported_set: set[str] = set()
self._default_arch: str
self._supported_arch: list[CpuArch] = []
self._supported_set: set[CpuArch] = set()
self._default_arch: CpuArch
@property
def default(self) -> str:
def default(self) -> CpuArch:
"""Return system default arch."""
return self._default_arch
@property
def supervisor(self) -> str:
def supervisor(self) -> CpuArch:
"""Return supervisor arch."""
return self.sys_supervisor.arch or self._default_arch
if self.sys_supervisor.arch:
return CpuArch(self.sys_supervisor.arch)
return self._default_arch
@property
def supported(self) -> list[str]:
def supported(self) -> list[CpuArch]:
"""Return support arch by CPU/Machine."""
return self._supported_arch
@@ -65,7 +68,7 @@ class CpuArch(CoreSysAttributes):
return
# Use configs from arch.json
self._supported_arch.extend(arch_data[self.sys_machine])
self._supported_arch.extend(CpuArch(a) for a in arch_data[self.sys_machine])
self._default_arch = self.supported[0]
# Make sure native support is in supported list
@@ -78,14 +81,14 @@ class CpuArch(CoreSysAttributes):
"""Return True if there is a supported arch by this platform."""
return not self._supported_set.isdisjoint(arch_list)
def match(self, arch_list: list[str]) -> str:
def match(self, arch_list: list[str]) -> CpuArch:
"""Return best match for this CPU/Platform."""
for self_arch in self.supported:
if self_arch in arch_list:
return self_arch
raise HassioArchNotFound()
def detect_cpu(self) -> str:
def detect_cpu(self) -> CpuArch:
"""Return the arch type of local CPU."""
cpu = platform.machine()
for check, value in MAP_CPU.items():
@@ -96,9 +99,10 @@ class CpuArch(CoreSysAttributes):
"Unknown CPU architecture %s, falling back to Supervisor architecture.",
cpu,
)
return self.sys_supervisor.arch
return CpuArch(self.sys_supervisor.arch)
_LOGGER.warning(
"Unknown CPU architecture %s, assuming CPU architecture equals Supervisor architecture.",
cpu,
)
return cpu
# Return the cpu string as-is, wrapped in CpuArch (may fail if invalid)
return CpuArch(cpu)

View File

@@ -13,7 +13,7 @@ from colorlog import ColoredFormatter
from .addons.manager import AddonManager
from .api import RestAPI
from .arch import CpuArch
from .arch import CpuArchManager
from .auth import Auth
from .backups.manager import BackupManager
from .bus import Bus
@@ -71,7 +71,7 @@ async def initialize_coresys() -> CoreSys:
coresys.jobs = await JobManager(coresys).load_config()
coresys.core = await Core(coresys).post_init()
coresys.plugins = await PluginManager(coresys).load_config()
coresys.arch = CpuArch(coresys)
coresys.arch = CpuArchManager(coresys)
coresys.auth = await Auth(coresys).load_config()
coresys.updater = await Updater(coresys).load_config()
coresys.api = RestAPI(coresys)

View File

@@ -29,7 +29,7 @@ from .const import (
if TYPE_CHECKING:
from .addons.manager import AddonManager
from .api import RestAPI
from .arch import CpuArch
from .arch import CpuArchManager
from .auth import Auth
from .backups.manager import BackupManager
from .bus import Bus
@@ -78,7 +78,7 @@ class CoreSys:
# Internal objects pointers
self._docker: DockerAPI | None = None
self._core: Core | None = None
self._arch: CpuArch | None = None
self._arch: CpuArchManager | None = None
self._auth: Auth | None = None
self._homeassistant: HomeAssistant | None = None
self._supervisor: Supervisor | None = None
@@ -266,17 +266,17 @@ class CoreSys:
self._plugins = value
@property
def arch(self) -> CpuArch:
"""Return CpuArch object."""
def arch(self) -> CpuArchManager:
"""Return CpuArchManager object."""
if self._arch is None:
raise RuntimeError("CpuArch not set!")
raise RuntimeError("CpuArchManager not set!")
return self._arch
@arch.setter
def arch(self, value: CpuArch) -> None:
"""Set a CpuArch object."""
def arch(self, value: CpuArchManager) -> None:
"""Set a CpuArchManager object."""
if self._arch:
raise RuntimeError("CpuArch already set!")
raise RuntimeError("CpuArchManager already set!")
self._arch = value
@property
@@ -733,8 +733,8 @@ class CoreSysAttributes:
return self.coresys.plugins
@property
def sys_arch(self) -> CpuArch:
"""Return CpuArch object."""
def sys_arch(self) -> CpuArchManager:
"""Return CpuArchManager object."""
return self.coresys.arch
@property

View File

@@ -7,6 +7,7 @@ from ipaddress import IPv4Address
import logging
import os
from pathlib import Path
from socket import SocketIO
import tempfile
from typing import TYPE_CHECKING, cast
@@ -834,7 +835,10 @@ class DockerAddon(DockerInterface):
try:
# Load needed docker objects
container = self.sys_docker.containers.get(self.name)
socket = container.attach_socket(params={"stdin": 1, "stream": 1})
# attach_socket returns SocketIO for local Docker connections (Unix socket)
socket = cast(
SocketIO, container.attach_socket(params={"stdin": 1, "stream": 1})
)
except (docker.errors.DockerException, requests.RequestException) as err:
_LOGGER.error("Can't attach to %s stdin: %s", self.name, err)
raise DockerError() from err

View File

@@ -52,7 +52,7 @@ from .stats import DockerStats
_LOGGER: logging.Logger = logging.getLogger(__name__)
MAP_ARCH: dict[CpuArch | str, str] = {
MAP_ARCH: dict[CpuArch, str] = {
CpuArch.ARMV7: "linux/arm/v7",
CpuArch.ARMHF: "linux/arm/v6",
CpuArch.AARCH64: "linux/arm64",
@@ -366,7 +366,7 @@ class DockerInterface(JobGroup, ABC):
if not image:
raise ValueError("Cannot pull without an image!")
image_arch = str(arch) if arch else self.sys_arch.supervisor
image_arch = arch or self.sys_arch.supervisor
listener: EventListener | None = None
_LOGGER.info("Downloading docker image %s with tag %s.", image, version)
@@ -603,9 +603,7 @@ class DockerInterface(JobGroup, ABC):
expected_cpu_arch: CpuArch | None = None,
) -> None:
"""Check we have expected image with correct arch."""
expected_image_cpu_arch = (
str(expected_cpu_arch) if expected_cpu_arch else self.sys_arch.supervisor
)
arch = expected_cpu_arch or self.sys_arch.supervisor
image_name = f"{expected_image}:{version!s}"
if self.image == expected_image:
try:
@@ -623,7 +621,7 @@ class DockerInterface(JobGroup, ABC):
# If we have an image and its the right arch, all set
# It seems that newer Docker version return a variant for arm64 images.
# Make sure we match linux/arm64 and linux/arm64/v8.
expected_image_arch = MAP_ARCH[expected_image_cpu_arch]
expected_image_arch = MAP_ARCH[arch]
if image_arch.startswith(expected_image_arch):
return
_LOGGER.info(
@@ -636,7 +634,7 @@ class DockerInterface(JobGroup, ABC):
# We're missing the image we need. Stop and clean up what we have then pull the right one
with suppress(DockerError):
await self.remove()
await self.install(version, expected_image, arch=expected_image_cpu_arch)
await self.install(version, expected_image, arch=arch)
@Job(
name="docker_interface_update",

View File

@@ -708,7 +708,8 @@ class DockerAPI(CoreSysAttributes):
raise DockerError(f"Container {name} is not running", _LOGGER.error)
try:
return docker_container.stats(stream=False)
# When stream=False, stats() returns dict, not Iterator
return cast(dict[str, Any], docker_container.stats(stream=False))
except (docker_errors.DockerException, requests.RequestException) as err:
raise DockerError(
f"Can't read stats from {name}: {err}", _LOGGER.error

View File

@@ -7,6 +7,8 @@ import logging
from typing import Self, cast
import docker
from docker.models.containers import Container
from docker.models.networks import Network
import requests
from ..const import (
@@ -59,7 +61,7 @@ class DockerNetwork:
def __init__(self, docker_client: docker.DockerClient):
"""Initialize internal Supervisor network."""
self.docker: docker.DockerClient = docker_client
self._network: docker.models.networks.Network
self._network: Network
async def post_init(
self, enable_ipv6: bool | None = None, mtu: int | None = None
@@ -76,7 +78,7 @@ class DockerNetwork:
return DOCKER_NETWORK
@property
def network(self) -> docker.models.networks.Network:
def network(self) -> Network:
"""Return docker network."""
return self._network
@@ -117,7 +119,7 @@ class DockerNetwork:
def _get_network(
self, enable_ipv6: bool | None = None, mtu: int | None = None
) -> docker.models.networks.Network:
) -> Network:
"""Get supervisor network."""
try:
if network := self.docker.networks.get(DOCKER_NETWORK):
@@ -218,7 +220,7 @@ class DockerNetwork:
def attach_container(
self,
container: docker.models.containers.Container,
container: Container,
alias: list[str] | None = None,
ipv4: IPv4Address | None = None,
) -> None:
@@ -275,9 +277,7 @@ class DockerNetwork:
if container.id not in self.containers:
self.attach_container(container, alias, ipv4)
def detach_default_bridge(
self, container: docker.models.containers.Container
) -> None:
def detach_default_bridge(self, container: Container) -> None:
"""Detach default Docker bridge.
Need run inside executor.

View File

@@ -10,7 +10,7 @@ from awesomeversion import AwesomeVersion
import pytest
from supervisor.addons.addon import Addon
from supervisor.arch import CpuArch
from supervisor.arch import CpuArchManager
from supervisor.config import CoreConfig
from supervisor.const import AddonBoot, AddonStartup, AddonState, BusEvent
from supervisor.coresys import CoreSys
@@ -54,7 +54,9 @@ async def fixture_mock_arch_disk() -> AsyncGenerator[None]:
"""Mock supported arch and disk space."""
with (
patch("shutil.disk_usage", return_value=(42, 42, 2 * (1024.0**3))),
patch.object(CpuArch, "supported", new=PropertyMock(return_value=["amd64"])),
patch.object(
CpuArchManager, "supported", new=PropertyMock(return_value=["amd64"])
),
):
yield

View File

@@ -9,7 +9,7 @@ import pytest
from supervisor.addons.addon import Addon
from supervisor.addons.build import AddonBuild
from supervisor.arch import CpuArch
from supervisor.arch import CpuArchManager
from supervisor.const import AddonState
from supervisor.coresys import CoreSys
from supervisor.docker.addon import DockerAddon
@@ -236,7 +236,9 @@ async def test_api_addon_rebuild_healthcheck(
patch.object(AddonBuild, "is_valid", return_value=True),
patch.object(DockerAddon, "is_running", return_value=False),
patch.object(Addon, "need_build", new=PropertyMock(return_value=True)),
patch.object(CpuArch, "supported", new=PropertyMock(return_value=["amd64"])),
patch.object(
CpuArchManager, "supported", new=PropertyMock(return_value=["amd64"])
),
patch.object(DockerAddon, "run", new=container_events_task),
patch.object(
coresys.docker,
@@ -308,7 +310,9 @@ async def test_api_addon_rebuild_force(
patch.object(
Addon, "need_build", new=PropertyMock(return_value=False)
), # Image-based
patch.object(CpuArch, "supported", new=PropertyMock(return_value=["amd64"])),
patch.object(
CpuArchManager, "supported", new=PropertyMock(return_value=["amd64"])
),
):
resp = await api_client.post("/addons/local_ssh/rebuild")
@@ -326,7 +330,9 @@ async def test_api_addon_rebuild_force(
patch.object(
Addon, "need_build", new=PropertyMock(return_value=False)
), # Image-based
patch.object(CpuArch, "supported", new=PropertyMock(return_value=["amd64"])),
patch.object(
CpuArchManager, "supported", new=PropertyMock(return_value=["amd64"])
),
patch.object(DockerAddon, "run", new=container_events_task),
patch.object(
coresys.docker,

View File

@@ -10,7 +10,7 @@ from awesomeversion import AwesomeVersion
import pytest
from supervisor.addons.addon import Addon
from supervisor.arch import CpuArch
from supervisor.arch import CpuArchManager
from supervisor.backups.manager import BackupManager
from supervisor.config import CoreConfig
from supervisor.const import AddonState, CoreState
@@ -191,7 +191,9 @@ async def test_api_store_update_healthcheck(
patch.object(DockerAddon, "run", new=container_events_task),
patch.object(DockerInterface, "install"),
patch.object(DockerAddon, "is_running", return_value=False),
patch.object(CpuArch, "supported", new=PropertyMock(return_value=["amd64"])),
patch.object(
CpuArchManager, "supported", new=PropertyMock(return_value=["amd64"])
),
):
resp = await api_client.post(f"/store/addons/{TEST_ADDON_SLUG}/update")
@@ -548,7 +550,9 @@ async def test_api_store_addons_addon_availability_arch_not_supported(
coresys.addons.data.user[addon_obj.slug] = {"version": AwesomeVersion("0.0.1")}
# Mock the system architecture to be different
with patch.object(CpuArch, "supported", new=PropertyMock(return_value=["amd64"])):
with patch.object(
CpuArchManager, "supported", new=PropertyMock(return_value=["amd64"])
):
resp = await api_client.request(
api_method, f"/store/addons/{addon_obj.slug}/{api_action}"
)

View File

@@ -9,7 +9,7 @@ from awesomeversion import AwesomeVersion
import pytest
from supervisor.addons.addon import Addon
from supervisor.arch import CpuArch
from supervisor.arch import CpuArchManager
from supervisor.backups.manager import BackupManager
from supervisor.coresys import CoreSys
from supervisor.exceptions import AddonNotSupportedError, StoreJobError
@@ -163,7 +163,9 @@ async def test_update_unavailable_addon(
with (
patch.object(BackupManager, "do_backup_partial") as backup,
patch.object(AddonStore, "data", new=PropertyMock(return_value=addon_config)),
patch.object(CpuArch, "supported", new=PropertyMock(return_value=["amd64"])),
patch.object(
CpuArchManager, "supported", new=PropertyMock(return_value=["amd64"])
),
patch.object(CoreSys, "machine", new=PropertyMock(return_value="qemux86-64")),
patch.object(
HomeAssistant,
@@ -219,7 +221,9 @@ async def test_install_unavailable_addon(
with (
patch.object(AddonStore, "data", new=PropertyMock(return_value=addon_config)),
patch.object(CpuArch, "supported", new=PropertyMock(return_value=["amd64"])),
patch.object(
CpuArchManager, "supported", new=PropertyMock(return_value=["amd64"])
),
patch.object(CoreSys, "machine", new=PropertyMock(return_value="qemux86-64")),
patch.object(
HomeAssistant,

0
wheels/.gitkeep Normal file
View File