Skip to content

Commit

Permalink
Cover read_bytes and some write_text calls as well
Browse files Browse the repository at this point in the history
  • Loading branch information
mdegat01 committed Feb 28, 2025
1 parent d9f4f44 commit 487b188
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 30 deletions.
17 changes: 9 additions & 8 deletions supervisor/addons/addon.py
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,7 @@ async def write_options(self) -> None:

try:
options = self.schema.validate(self.options)
write_json_file(self.path_options, options)
await self.sys_run_in_executor(write_json_file, self.path_options, options)
except vol.Invalid as ex:
_LOGGER.error(
"Add-on %s has invalid options: %s",
Expand Down Expand Up @@ -940,19 +940,20 @@ async def rebuild(self) -> asyncio.Task | None:
)
return out

def write_pulse(self) -> None:
async def write_pulse(self) -> None:
"""Write asound config to file and return True on success."""
pulse_config = self.sys_plugins.audio.pulse_client(
input_profile=self.audio_input, output_profile=self.audio_output
)

# Cleanup wrong maps
if self.path_pulse.is_dir():
shutil.rmtree(self.path_pulse, ignore_errors=True)
def write_pulse_config():
# Cleanup wrong maps
if self.path_pulse.is_dir():
shutil.rmtree(self.path_pulse, ignore_errors=True)
self.path_pulse.write_text(pulse_config, encoding="utf-8")

# Write pulse config
try:
self.path_pulse.write_text(pulse_config, encoding="utf-8")
await self.sys_run_in_executor(write_pulse_config)
except OSError as err:
if err.errno == errno.EBADMSG:
self.sys_resolution.unhealthy = UnhealthyReason.OSERROR_BAD_MESSAGE
Expand Down Expand Up @@ -1072,7 +1073,7 @@ async def start(self) -> asyncio.Task:

# Sound
if self.with_audio:
self.write_pulse()
await self.write_pulse()

def _check_addon_config_dir():
if self.path_config.is_dir():
Expand Down
2 changes: 1 addition & 1 deletion supervisor/arch.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def supported(self) -> list[str]:
async def load(self) -> None:
"""Load data and initialize default arch."""
try:
arch_data = read_json_file(ARCH_JSON)
arch_data = await self.sys_run_in_executor(read_json_file, ARCH_JSON)
except ConfigurationFileError:
_LOGGER.warning("Can't read arch json file from %s", ARCH_JSON)
return
Expand Down
2 changes: 1 addition & 1 deletion supervisor/homeassistant/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ async def start(self) -> None:
await self.sys_homeassistant.save_data()

# Write audio settings
self.sys_homeassistant.write_pulse()
await self.sys_homeassistant.write_pulse()

try:
await self.instance.run(restore_job_id=self.sys_backups.current_restore)
Expand Down
13 changes: 7 additions & 6 deletions supervisor/homeassistant/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,19 +313,20 @@ async def load(self) -> None:
BusEvent.HARDWARE_REMOVE_DEVICE, self._hardware_events
)

def write_pulse(self):
async def write_pulse(self):
"""Write asound config to file and return True on success."""
pulse_config = self.sys_plugins.audio.pulse_client(
input_profile=self.audio_input, output_profile=self.audio_output
)

# Cleanup wrong maps
if self.path_pulse.is_dir():
shutil.rmtree(self.path_pulse, ignore_errors=True)
def write_pulse_config():
# Cleanup wrong maps
if self.path_pulse.is_dir():
shutil.rmtree(self.path_pulse, ignore_errors=True)
self.path_pulse.write_text(pulse_config, encoding="utf-8")

# Write pulse config
try:
self.path_pulse.write_text(pulse_config, encoding="utf-8")
await self.sys_run_in_executor(write_pulse_config)
except OSError as err:
if err.errno == errno.EBADMSG:
self.sys_resolution.unhealthy = UnhealthyReason.OSERROR_BAD_MESSAGE
Expand Down
4 changes: 3 additions & 1 deletion supervisor/host/logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ def default_identifiers(self) -> list[str]:
async def load(self) -> None:
"""Load log control."""
try:
self._default_identifiers = read_json_file(SYSLOG_IDENTIFIERS_JSON)
self._default_identifiers = await self.sys_run_in_executor(
read_json_file, SYSLOG_IDENTIFIERS_JSON
)
except ConfigurationFileError:
_LOGGER.warning(
"Can't read syslog identifiers json file from %s",
Expand Down
9 changes: 5 additions & 4 deletions supervisor/plugins/audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ async def update(self, version: str | None = None) -> None:
async def restart(self) -> None:
"""Restart Audio plugin."""
_LOGGER.info("Restarting Audio plugin")
self._write_config()
await self._write_config()
try:
await self.instance.restart()
except DockerError as err:
Expand All @@ -138,7 +138,7 @@ async def restart(self) -> None:
async def start(self) -> None:
"""Run Audio plugin."""
_LOGGER.info("Starting Audio plugin")
self._write_config()
await self._write_config()
try:
await self.instance.run()
except DockerError as err:
Expand Down Expand Up @@ -183,10 +183,11 @@ def pulse_client(self, input_profile=None, output_profile=None) -> str:
default_sink=output_profile,
)

def _write_config(self):
async def _write_config(self):
"""Write pulse audio config."""
try:
write_json_file(
await self.sys_run_in_executor(
write_json_file,
self.pulse_audio_config,
{
"debug": self.sys_config.logging == LogLevel.DEBUG,
Expand Down
9 changes: 5 additions & 4 deletions supervisor/plugins/dns.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ async def update(self, version: AwesomeVersion | None = None) -> None:

async def restart(self) -> None:
"""Restart CoreDNS plugin."""
self._write_config()
await self._write_config()
_LOGGER.info("Restarting CoreDNS plugin")
try:
await self.instance.restart()
Expand All @@ -205,7 +205,7 @@ async def restart(self) -> None:

async def start(self) -> None:
"""Run CoreDNS."""
self._write_config()
await self._write_config()

# Start Instance
_LOGGER.info("Starting CoreDNS plugin")
Expand Down Expand Up @@ -274,7 +274,7 @@ async def loop_detection(self) -> None:
else:
self._loop = False

def _write_config(self) -> None:
async def _write_config(self) -> None:
"""Write CoreDNS config."""
debug: bool = self.sys_config.logging == LogLevel.DEBUG
dns_servers: list[str] = []
Expand All @@ -298,7 +298,8 @@ def _write_config(self) -> None:

# Write config to plugin
try:
write_json_file(
await self.sys_run_in_executor(
write_json_file,
self.coredns_config,
{
"servers": dns_servers,
Expand Down
10 changes: 8 additions & 2 deletions supervisor/utils/json.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ def json_bytes(obj: Any) -> bytes:


def write_json_file(jsonfile: Path, data: Any) -> None:
"""Write a JSON file."""
"""Write a JSON file.
Must be run in executor.
"""
try:
with atomic_write(jsonfile, overwrite=True) as fp:
fp.write(
Expand All @@ -67,7 +70,10 @@ def write_json_file(jsonfile: Path, data: Any) -> None:


def read_json_file(jsonfile: Path) -> Any:
"""Read a JSON file and return a dict."""
"""Read a JSON file and return a dict.
Must be run in executor.
"""
try:
return json_loads(jsonfile.read_bytes())
except (OSError, ValueError, TypeError, UnicodeDecodeError) as err:
Expand Down
6 changes: 3 additions & 3 deletions tests/homeassistant/test_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,21 +66,21 @@ async def test_get_users_none(coresys: CoreSys, ha_ws_client: AsyncMock):
)


def test_write_pulse_error(coresys: CoreSys, caplog: pytest.LogCaptureFixture):
async def test_write_pulse_error(coresys: CoreSys, caplog: pytest.LogCaptureFixture):
"""Test errors writing pulse config."""
with patch(
"supervisor.homeassistant.module.Path.write_text",
side_effect=(err := OSError()),
):
err.errno = errno.EBUSY
coresys.homeassistant.write_pulse()
await coresys.homeassistant.write_pulse()

assert "can't write pulse/client.config" in caplog.text
assert coresys.core.healthy is True

caplog.clear()
err.errno = errno.EBADMSG
coresys.homeassistant.write_pulse()
await coresys.homeassistant.write_pulse()

assert "can't write pulse/client.config" in caplog.text
assert coresys.core.healthy is False
Expand Down

0 comments on commit 487b188

Please sign in to comment.