diff --git a/homeassistant/util/yaml/loader.py b/homeassistant/util/yaml/loader.py index e3add3a7c44..09e19af6840 100644 --- a/homeassistant/util/yaml/loader.py +++ b/homeassistant/util/yaml/loader.py @@ -4,7 +4,7 @@ from __future__ import annotations from collections import OrderedDict from collections.abc import Iterator import fnmatch -from io import StringIO +from io import StringIO, TextIOWrapper import logging import os from pathlib import Path @@ -169,7 +169,7 @@ def parse_yaml( except yaml.YAMLError: # Loading failed, so we now load with the slow line loader # since the C one will not give us line numbers - if isinstance(content, (StringIO, TextIO)): + if isinstance(content, (StringIO, TextIO, TextIOWrapper)): # Rewind the stream so we can try again content.seek(0, 0) return _parse_yaml_pure_python(content, secrets) diff --git a/tests/util/yaml/fixtures/bad.yaml.txt b/tests/util/yaml/fixtures/bad.yaml.txt new file mode 100644 index 00000000000..8f6a62a6511 --- /dev/null +++ b/tests/util/yaml/fixtures/bad.yaml.txt @@ -0,0 +1,26 @@ +- id: '1658085239190' + alias: Config validation test + description: '' + trigger: + - platform: time + at: 00:02:03 + condition: [] + action: + - service: script.notify_admin + data: + title: 'Here's something that does not work...!' + message: failing + mode: single +- id: '165808523911590' + alias: Config validation test FIXED + description: '' + trigger: + - platform: time + at: 00:02:03 + condition: [] + action: + - service: script.notify_admin + data: + title: 'Here is something that should work...!' + message: fixed? + mode: single diff --git a/tests/util/yaml/test_init.py b/tests/util/yaml/test_init.py index 11dc40233dc..8d1b7c1adf1 100644 --- a/tests/util/yaml/test_init.py +++ b/tests/util/yaml/test_init.py @@ -2,6 +2,7 @@ import importlib import io import os +import pathlib import unittest from unittest.mock import patch @@ -490,3 +491,12 @@ def test_input(try_both_loaders, try_both_dumpers): def test_c_loader_is_available_in_ci(): """Verify we are testing the C loader in the CI.""" assert yaml.loader.HAS_C_LOADER is True + + +async def test_loading_actual_file_with_syntax(hass, try_both_loaders): + """Test loading a real file with syntax errors.""" + with pytest.raises(HomeAssistantError): + fixture_path = pathlib.Path(__file__).parent.joinpath( + "fixtures", "bad.yaml.txt" + ) + await hass.async_add_executor_job(load_yaml_config_file, fixture_path)