Improve type hints in yaml util tests (#119358)

This commit is contained in:
epenet 2024-06-11 15:01:54 +02:00 committed by GitHub
parent d9b3ee35a0
commit 1974ea4fdd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -23,7 +23,7 @@ from tests.common import extract_stack_to_frame, get_test_config_dir, patch_yaml
@pytest.fixture(params=["enable_c_loader", "disable_c_loader"])
def try_both_loaders(request):
def try_both_loaders(request: pytest.FixtureRequest) -> Generator[None]:
"""Disable the yaml c loader."""
if request.param != "disable_c_loader":
yield
@ -40,7 +40,7 @@ def try_both_loaders(request):
@pytest.fixture(params=["enable_c_dumper", "disable_c_dumper"])
def try_both_dumpers(request):
def try_both_dumpers(request: pytest.FixtureRequest) -> Generator[None]:
"""Disable the yaml c dumper."""
if request.param != "disable_c_dumper":
yield
@ -56,7 +56,8 @@ def try_both_dumpers(request):
importlib.reload(yaml_loader)
def test_simple_list(try_both_loaders) -> None:
@pytest.mark.usefixtures("try_both_loaders")
def test_simple_list() -> None:
"""Test simple list."""
conf = "config:\n - simple\n - list"
with io.StringIO(conf) as file:
@ -64,7 +65,8 @@ def test_simple_list(try_both_loaders) -> None:
assert doc["config"] == ["simple", "list"]
def test_simple_dict(try_both_loaders) -> None:
@pytest.mark.usefixtures("try_both_loaders")
def test_simple_dict() -> None:
"""Test simple dict."""
conf = "key: value"
with io.StringIO(conf) as file:
@ -73,20 +75,23 @@ def test_simple_dict(try_both_loaders) -> None:
@pytest.mark.parametrize("hass_config_yaml", ["message:\n {{ states.state }}"])
def test_unhashable_key(try_both_loaders, mock_hass_config_yaml: None) -> None:
@pytest.mark.usefixtures("try_both_loaders", "mock_hass_config_yaml")
def test_unhashable_key() -> None:
"""Test an unhashable key."""
with pytest.raises(HomeAssistantError):
load_yaml_config_file(YAML_CONFIG_FILE)
@pytest.mark.parametrize("hass_config_yaml", ["a: a\nnokeyhere"])
def test_no_key(try_both_loaders, mock_hass_config_yaml: None) -> None:
@pytest.mark.usefixtures("try_both_loaders", "mock_hass_config_yaml")
def test_no_key() -> None:
"""Test item without a key."""
with pytest.raises(HomeAssistantError):
yaml.load_yaml(YAML_CONFIG_FILE)
def test_environment_variable(try_both_loaders) -> None:
@pytest.mark.usefixtures("try_both_loaders")
def test_environment_variable() -> None:
"""Test config file with environment variable."""
os.environ["PASSWORD"] = "secret_password"
conf = "password: !env_var PASSWORD"
@ -96,7 +101,8 @@ def test_environment_variable(try_both_loaders) -> None:
del os.environ["PASSWORD"]
def test_environment_variable_default(try_both_loaders) -> None:
@pytest.mark.usefixtures("try_both_loaders")
def test_environment_variable_default() -> None:
"""Test config file with default value for environment variable."""
conf = "password: !env_var PASSWORD secret_password"
with io.StringIO(conf) as file:
@ -104,7 +110,8 @@ def test_environment_variable_default(try_both_loaders) -> None:
assert doc["password"] == "secret_password"
def test_invalid_environment_variable(try_both_loaders) -> None:
@pytest.mark.usefixtures("try_both_loaders")
def test_invalid_environment_variable() -> None:
"""Test config file with no environment variable sat."""
conf = "password: !env_var PASSWORD"
with pytest.raises(HomeAssistantError), io.StringIO(conf) as file:
@ -119,9 +126,8 @@ def test_invalid_environment_variable(try_both_loaders) -> None:
({"test.yaml": "123"}, 123),
],
)
def test_include_yaml(
try_both_loaders, mock_hass_config_yaml: None, value: Any
) -> None:
@pytest.mark.usefixtures("try_both_loaders", "mock_hass_config_yaml")
def test_include_yaml(value: Any) -> None:
"""Test include yaml."""
conf = "key: !include test.yaml"
with io.StringIO(conf) as file:
@ -138,9 +144,8 @@ def test_include_yaml(
({"/test/one.yaml": "1", "/test/two.yaml": None}, [1]),
],
)
def test_include_dir_list(
mock_walk, try_both_loaders, mock_hass_config_yaml: None, value: Any
) -> None:
@pytest.mark.usefixtures("try_both_loaders", "mock_hass_config_yaml")
def test_include_dir_list(mock_walk: Mock, value: Any) -> None:
"""Test include dir list yaml."""
mock_walk.return_value = [["/test", [], ["two.yaml", "one.yaml"]]]
@ -161,9 +166,8 @@ def test_include_dir_list(
}
],
)
def test_include_dir_list_recursive(
mock_walk, try_both_loaders, mock_hass_config_yaml: None
) -> None:
@pytest.mark.usefixtures("try_both_loaders", "mock_hass_config_yaml")
def test_include_dir_list_recursive(mock_walk: Mock) -> None:
"""Test include dir recursive list yaml."""
mock_walk.return_value = [
["/test", ["tmp2", ".ignore", "ignore"], ["zero.yaml"]],
@ -198,9 +202,8 @@ def test_include_dir_list_recursive(
),
],
)
def test_include_dir_named(
mock_walk, try_both_loaders, mock_hass_config_yaml: None, value: Any
) -> None:
@pytest.mark.usefixtures("try_both_loaders", "mock_hass_config_yaml")
def test_include_dir_named(mock_walk: Mock, value: Any) -> None:
"""Test include dir named yaml."""
mock_walk.return_value = [
["/test", [], ["first.yaml", "second.yaml", "secrets.yaml"]]
@ -223,9 +226,8 @@ def test_include_dir_named(
}
],
)
def test_include_dir_named_recursive(
mock_walk, try_both_loaders, mock_hass_config_yaml: None
) -> None:
@pytest.mark.usefixtures("try_both_loaders", "mock_hass_config_yaml")
def test_include_dir_named_recursive(mock_walk: Mock) -> None:
"""Test include dir named yaml."""
mock_walk.return_value = [
["/test", ["tmp2", ".ignore", "ignore"], ["first.yaml"]],
@ -261,9 +263,8 @@ def test_include_dir_named_recursive(
),
],
)
def test_include_dir_merge_list(
mock_walk, try_both_loaders, mock_hass_config_yaml: None, value: Any
) -> None:
@pytest.mark.usefixtures("try_both_loaders", "mock_hass_config_yaml")
def test_include_dir_merge_list(mock_walk: Mock, value: Any) -> None:
"""Test include dir merge list yaml."""
mock_walk.return_value = [["/test", [], ["first.yaml", "second.yaml"]]]
@ -284,9 +285,8 @@ def test_include_dir_merge_list(
}
],
)
def test_include_dir_merge_list_recursive(
mock_walk, try_both_loaders, mock_hass_config_yaml: None
) -> None:
@pytest.mark.usefixtures("try_both_loaders", "mock_hass_config_yaml")
def test_include_dir_merge_list_recursive(mock_walk: Mock) -> None:
"""Test include dir merge list yaml."""
mock_walk.return_value = [
["/test", ["tmp2", ".ignore", "ignore"], ["first.yaml"]],
@ -330,9 +330,8 @@ def test_include_dir_merge_list_recursive(
),
],
)
def test_include_dir_merge_named(
mock_walk, try_both_loaders, mock_hass_config_yaml: None, value: Any
) -> None:
@pytest.mark.usefixtures("try_both_loaders", "mock_hass_config_yaml")
def test_include_dir_merge_named(mock_walk: Mock, value: Any) -> None:
"""Test include dir merge named yaml."""
mock_walk.return_value = [["/test", [], ["first.yaml", "second.yaml"]]]
@ -353,9 +352,8 @@ def test_include_dir_merge_named(
}
],
)
def test_include_dir_merge_named_recursive(
mock_walk, try_both_loaders, mock_hass_config_yaml: None
) -> None:
@pytest.mark.usefixtures("try_both_loaders", "mock_hass_config_yaml")
def test_include_dir_merge_named_recursive(mock_walk: Mock) -> None:
"""Test include dir merge named yaml."""
mock_walk.return_value = [
["/test", ["tmp2", ".ignore", "ignore"], ["first.yaml"]],
@ -378,19 +376,22 @@ def test_include_dir_merge_named_recursive(
@patch("homeassistant.util.yaml.loader.open", create=True)
def test_load_yaml_encoding_error(mock_open, try_both_loaders) -> None:
@pytest.mark.usefixtures("try_both_loaders")
def test_load_yaml_encoding_error(mock_open: Mock) -> None:
"""Test raising a UnicodeDecodeError."""
mock_open.side_effect = UnicodeDecodeError("", b"", 1, 0, "")
with pytest.raises(HomeAssistantError):
yaml_loader.load_yaml("test")
def test_dump(try_both_dumpers) -> None:
@pytest.mark.usefixtures("try_both_dumpers")
def test_dump() -> None:
"""The that the dump method returns empty None values."""
assert yaml.dump({"a": None, "b": "b"}) == "a:\nb: b\n"
def test_dump_unicode(try_both_dumpers) -> None:
@pytest.mark.usefixtures("try_both_dumpers")
def test_dump_unicode() -> None:
"""The that the dump method returns empty None values."""
assert yaml.dump({"a": None, "b": "привет"}) == "a:\nb: привет\n"
@ -535,18 +536,16 @@ class TestSecrets(unittest.TestCase):
@pytest.mark.parametrize("hass_config_yaml", ['key: [1, "2", 3]'])
def test_representing_yaml_loaded_data(
try_both_dumpers, mock_hass_config_yaml: None
) -> None:
@pytest.mark.usefixtures("try_both_dumpers", "mock_hass_config_yaml")
def test_representing_yaml_loaded_data() -> None:
"""Test we can represent YAML loaded data."""
data = load_yaml_config_file(YAML_CONFIG_FILE)
assert yaml.dump(data) == "key:\n- 1\n- '2'\n- 3\n"
@pytest.mark.parametrize("hass_config_yaml", ["key: thing1\nkey: thing2"])
def test_duplicate_key(
caplog: pytest.LogCaptureFixture, try_both_loaders, mock_hass_config_yaml: None
) -> None:
@pytest.mark.usefixtures("try_both_loaders", "mock_hass_config_yaml")
def test_duplicate_key(caplog: pytest.LogCaptureFixture) -> None:
"""Test duplicate dict keys."""
load_yaml_config_file(YAML_CONFIG_FILE)
assert "contains duplicate key" in caplog.text
@ -556,9 +555,8 @@ def test_duplicate_key(
"hass_config_yaml_files",
[{YAML_CONFIG_FILE: "key: !secret a", yaml.SECRET_YAML: "a: 1\nb: !secret a"}],
)
def test_no_recursive_secrets(
caplog: pytest.LogCaptureFixture, try_both_loaders, mock_hass_config_yaml: None
) -> None:
@pytest.mark.usefixtures("try_both_loaders", "mock_hass_config_yaml")
def test_no_recursive_secrets() -> None:
"""Test that loading of secrets from the secrets file fails correctly."""
with pytest.raises(HomeAssistantError) as e:
load_yaml_config_file(YAML_CONFIG_FILE)
@ -577,7 +575,8 @@ def test_input_class() -> None:
assert len({yaml_input, yaml_input2}) == 1
def test_input(try_both_loaders, try_both_dumpers) -> None:
@pytest.mark.usefixtures("try_both_loaders", "try_both_dumpers")
def test_input() -> None:
"""Test loading inputs."""
data = {"hello": yaml.Input("test_name")}
assert yaml.parse_yaml(yaml.dump(data)) == data
@ -592,9 +591,8 @@ def test_c_loader_is_available_in_ci() -> None:
assert yaml.loader.HAS_C_LOADER is True
async def test_loading_actual_file_with_syntax_error(
hass: HomeAssistant, try_both_loaders
) -> None:
@pytest.mark.usefixtures("try_both_loaders")
async def test_loading_actual_file_with_syntax_error(hass: HomeAssistant) -> None:
"""Test loading a real file with syntax errors."""
fixture_path = pathlib.Path(__file__).parent.joinpath("fixtures", "bad.yaml.txt")
with pytest.raises(HomeAssistantError):
@ -646,11 +644,10 @@ def mock_integration_frame() -> Generator[Mock]:
),
],
)
@pytest.mark.usefixtures("mock_integration_frame")
async def test_deprecated_loaders(
hass: HomeAssistant,
mock_integration_frame: Mock,
caplog: pytest.LogCaptureFixture,
loader_class,
loader_class: type,
message: str,
) -> None:
"""Test instantiating the deprecated yaml loaders logs a warning."""
@ -662,7 +659,8 @@ async def test_deprecated_loaders(
assert (f"Detected that integration 'hue' uses deprecated {message}") in caplog.text
def test_string_annotated(try_both_loaders) -> None:
@pytest.mark.usefixtures("try_both_loaders")
def test_string_annotated() -> None:
"""Test strings are annotated with file + line."""
conf = (
"key1: str\n"
@ -695,7 +693,8 @@ def test_string_annotated(try_both_loaders) -> None:
assert getattr(value, "__line__", None) == expected_annotations[key][1][1]
def test_string_used_as_vol_schema(try_both_loaders) -> None:
@pytest.mark.usefixtures("try_both_loaders")
def test_string_used_as_vol_schema() -> None:
"""Test the subclassed strings can be used in voluptuous schemas."""
conf = "wanted_data:\n key_1: value_1\n key_2: value_2\n"
with io.StringIO(conf) as file:
@ -715,15 +714,15 @@ def test_string_used_as_vol_schema(try_both_loaders) -> None:
@pytest.mark.parametrize(
("hass_config_yaml", "expected_data"), [("", {}), ("bla:", {"bla": None})]
)
def test_load_yaml_dict(
try_both_loaders, mock_hass_config_yaml: None, expected_data: Any
) -> None:
@pytest.mark.usefixtures("try_both_loaders", "mock_hass_config_yaml")
def test_load_yaml_dict(expected_data: Any) -> None:
"""Test item without a key."""
assert yaml.load_yaml_dict(YAML_CONFIG_FILE) == expected_data
@pytest.mark.parametrize("hass_config_yaml", ["abc", "123", "[]"])
def test_load_yaml_dict_fail(try_both_loaders, mock_hass_config_yaml: None) -> None:
@pytest.mark.usefixtures("try_both_loaders", "mock_hass_config_yaml")
def test_load_yaml_dict_fail() -> None:
"""Test item without a key."""
with pytest.raises(yaml_loader.YamlTypeError):
yaml_loader.load_yaml_dict(YAML_CONFIG_FILE)