Add file and line annotation to strings when loading yaml (#103586)
This commit is contained in:
parent
6276c4483c
commit
05deae09fc
3 changed files with 50 additions and 1 deletions
|
@ -4,7 +4,7 @@ from typing import Any
|
|||
|
||||
import yaml
|
||||
|
||||
from .objects import Input, NodeDictClass, NodeListClass
|
||||
from .objects import Input, NodeDictClass, NodeListClass, NodeStrClass
|
||||
|
||||
# mypy: allow-untyped-calls, no-warn-return-any
|
||||
|
||||
|
@ -84,6 +84,11 @@ add_representer(
|
|||
lambda dumper, value: dumper.represent_sequence("tag:yaml.org,2002:seq", value),
|
||||
)
|
||||
|
||||
add_representer(
|
||||
NodeStrClass,
|
||||
lambda dumper, value: dumper.represent_scalar("tag:yaml.org,2002:str", str(value)),
|
||||
)
|
||||
|
||||
add_representer(
|
||||
Input,
|
||||
lambda dumper, value: dumper.represent_scalar("!input", value.name),
|
||||
|
|
|
@ -371,6 +371,16 @@ def _construct_seq(loader: LoaderType, node: yaml.nodes.Node) -> JSON_TYPE:
|
|||
return _add_reference(obj, loader, node)
|
||||
|
||||
|
||||
def _handle_scalar_tag(
|
||||
loader: LoaderType, node: yaml.nodes.ScalarNode
|
||||
) -> str | int | float | None:
|
||||
"""Add line number and file name to Load YAML sequence."""
|
||||
obj = loader.construct_scalar(node)
|
||||
if not isinstance(obj, str):
|
||||
return obj
|
||||
return _add_reference(obj, loader, node)
|
||||
|
||||
|
||||
def _env_var_yaml(loader: LoaderType, node: yaml.nodes.Node) -> str:
|
||||
"""Load environment variables and embed it into the configuration YAML."""
|
||||
args = node.value.split()
|
||||
|
@ -400,6 +410,7 @@ def add_constructor(tag: Any, constructor: Any) -> None:
|
|||
|
||||
add_constructor("!include", _include_yaml)
|
||||
add_constructor(yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, _handle_mapping_tag)
|
||||
add_constructor(yaml.resolver.BaseResolver.DEFAULT_SCALAR_TAG, _handle_scalar_tag)
|
||||
add_constructor(yaml.resolver.BaseResolver.DEFAULT_SEQUENCE_TAG, _construct_seq)
|
||||
add_constructor("!env_var", _env_var_yaml)
|
||||
add_constructor("!secret", secret_yaml)
|
||||
|
|
|
@ -547,3 +547,36 @@ async def test_loading_actual_file_with_syntax(
|
|||
"fixtures", "bad.yaml.txt"
|
||||
)
|
||||
await hass.async_add_executor_job(load_yaml_config_file, fixture_path)
|
||||
|
||||
|
||||
def test_string_annotated(try_both_loaders) -> None:
|
||||
"""Test strings are annotated with file + line."""
|
||||
conf = (
|
||||
"key1: str\n"
|
||||
"key2:\n"
|
||||
" blah: blah\n"
|
||||
"key3:\n"
|
||||
" - 1\n"
|
||||
" - 2\n"
|
||||
" - 3\n"
|
||||
"key4: yes\n"
|
||||
"key5: 1\n"
|
||||
"key6: 1.0\n"
|
||||
)
|
||||
expected_annotations = {
|
||||
"key1": [("<file>", 0), ("<file>", 0)],
|
||||
"key2": [("<file>", 1), ("<file>", 2)],
|
||||
"key3": [("<file>", 3), ("<file>", 4)],
|
||||
"key4": [("<file>", 7), (None, None)],
|
||||
"key5": [("<file>", 8), (None, None)],
|
||||
"key6": [("<file>", 9), (None, None)],
|
||||
}
|
||||
with io.StringIO(conf) as file:
|
||||
doc = yaml_loader.parse_yaml(file)
|
||||
for key, value in doc.items():
|
||||
assert getattr(key, "__config_file__", None) == expected_annotations[key][0][0]
|
||||
assert getattr(key, "__line__", None) == expected_annotations[key][0][1]
|
||||
assert (
|
||||
getattr(value, "__config_file__", None) == expected_annotations[key][1][0]
|
||||
)
|
||||
assert getattr(value, "__line__", None) == expected_annotations[key][1][1]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue