Skip to content

Commit

Permalink
Ensure filename is shown when YAML raises an error (esphome#6139)
Browse files Browse the repository at this point in the history
* Ensure filename is shown when YAML raises an error

fixes esphome#5423
fixes esphome#5377

* Ensure filename is shown when YAML raises an error

fixes esphome#5423
fixes esphome#5377

* Ensure filename is shown when YAML raises an error

fixes esphome#5423
fixes esphome#5377

* Ensure filename is shown when YAML raises an error

fixes esphome#5423
fixes esphome#5377

* Ensure filename is shown when YAML raises an error

fixes esphome#5423
fixes esphome#5377
  • Loading branch information
bdraco authored Jan 24, 2024
1 parent 23071e9 commit 25ab6f0
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 8 deletions.
24 changes: 16 additions & 8 deletions esphome/yaml_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import math
import os
import uuid
from io import TextIOWrapper
from typing import Any

import yaml
Expand All @@ -19,7 +20,7 @@
FastestAvailableSafeLoader = PurePythonLoader

from esphome import core
from esphome.config_helpers import Extend, Remove, read_config_file
from esphome.config_helpers import Extend, Remove
from esphome.core import (
CORE,
DocumentRange,
Expand Down Expand Up @@ -418,19 +419,26 @@ def load_yaml(fname: str, clear_secrets: bool = True) -> Any:

def _load_yaml_internal(fname: str) -> Any:
"""Load a YAML file."""
content = read_config_file(fname)
try:
return _load_yaml_internal_with_type(ESPHomeLoader, fname, content)
except EsphomeError:
# Loading failed, so we now load with the Python loader which has more
# readable exceptions
return _load_yaml_internal_with_type(ESPHomePurePythonLoader, fname, content)
with open(fname, encoding="utf-8") as f_handle:
try:
return _load_yaml_internal_with_type(ESPHomeLoader, fname, f_handle)
except EsphomeError:
# Loading failed, so we now load with the Python loader which has more
# readable exceptions
# Rewind the stream so we can try again
f_handle.seek(0, 0)
return _load_yaml_internal_with_type(
ESPHomePurePythonLoader, fname, f_handle
)
except (UnicodeDecodeError, OSError) as err:
raise EsphomeError(f"Error reading file {fname}: {err}") from err


def _load_yaml_internal_with_type(
loader_type: type[ESPHomeLoader] | type[ESPHomePurePythonLoader],
fname: str,
content: str,
content: TextIOWrapper,
) -> Any:
"""Load a YAML file."""
loader = loader_type(content)
Expand Down
12 changes: 12 additions & 0 deletions tests/unit_tests/fixtures/yaml_util/missing_comp.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
esphome:
name: test

esp32:
board: esp32dev

wifi:
ap: ~

image:
- id: its_a_bug
file: "mdi:bug"
20 changes: 20 additions & 0 deletions tests/unit_tests/test_yaml_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,23 @@ def test_loading_a_broken_yaml_file(fixture_path):
yaml_util.load_yaml(yaml_file)
except EsphomeError as err:
assert "broken_included.yaml" in str(err)


def test_loading_a_yaml_file_with_a_missing_component(fixture_path):
"""Ensure we show the filename for a yaml file with a missing component."""
yaml_file = fixture_path / "yaml_util" / "missing_comp.yaml"

try:
yaml_util.load_yaml(yaml_file)
except EsphomeError as err:
assert "missing_comp.yaml" in str(err)


def test_loading_a_missing_file(fixture_path):
"""We throw EsphomeError when loading a missing file."""
yaml_file = fixture_path / "yaml_util" / "missing.yaml"

try:
yaml_util.load_yaml(yaml_file)
except EsphomeError as err:
assert "missing.yaml" in str(err)

0 comments on commit 25ab6f0

Please sign in to comment.