mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 16:57:53 +00:00
Yaml use dict (#88977)
* Use built-in dict instead of OrderedDict * Use dict instead of OrderedDict in YAML
This commit is contained in:
parent
89c276bb6b
commit
3f32c5d2ad
@ -4,7 +4,7 @@ from typing import Any
|
||||
|
||||
import yaml
|
||||
|
||||
from .objects import Input, NodeListClass
|
||||
from .objects import Input, NodeDictClass, NodeListClass
|
||||
|
||||
# mypy: allow-untyped-calls, no-warn-return-any
|
||||
|
||||
@ -74,6 +74,11 @@ add_representer(
|
||||
lambda dumper, value: represent_odict(dumper, "tag:yaml.org,2002:map", value),
|
||||
)
|
||||
|
||||
add_representer(
|
||||
NodeDictClass,
|
||||
lambda dumper, value: represent_odict(dumper, "tag:yaml.org,2002:map", value),
|
||||
)
|
||||
|
||||
add_representer(
|
||||
NodeListClass,
|
||||
lambda dumper, value: dumper.represent_sequence("tag:yaml.org,2002:seq", value),
|
||||
|
@ -1,7 +1,6 @@
|
||||
"""Custom loader."""
|
||||
from __future__ import annotations
|
||||
|
||||
from collections import OrderedDict
|
||||
from collections.abc import Iterator
|
||||
import fnmatch
|
||||
from io import StringIO, TextIOWrapper
|
||||
@ -25,7 +24,7 @@ except ImportError:
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
|
||||
from .const import SECRET_YAML
|
||||
from .objects import Input, NodeListClass, NodeStrClass
|
||||
from .objects import Input, NodeDictClass, NodeListClass, NodeStrClass
|
||||
|
||||
# mypy: allow-untyped-calls, no-warn-return-any
|
||||
|
||||
@ -205,7 +204,7 @@ def _parse_yaml(
|
||||
# We convert that to an empty dict
|
||||
return (
|
||||
yaml.load(content, Loader=lambda stream: loader(stream, secrets))
|
||||
or OrderedDict()
|
||||
or NodeDictClass()
|
||||
)
|
||||
|
||||
|
||||
@ -276,9 +275,9 @@ def _find_files(directory: str, pattern: str) -> Iterator[str]:
|
||||
yield filename
|
||||
|
||||
|
||||
def _include_dir_named_yaml(loader: LoaderType, node: yaml.nodes.Node) -> OrderedDict:
|
||||
def _include_dir_named_yaml(loader: LoaderType, node: yaml.nodes.Node) -> NodeDictClass:
|
||||
"""Load multiple files from directory as a dictionary."""
|
||||
mapping: OrderedDict = OrderedDict()
|
||||
mapping = NodeDictClass()
|
||||
loc = os.path.join(os.path.dirname(loader.get_name()), node.value)
|
||||
for fname in _find_files(loc, "*.yaml"):
|
||||
filename = os.path.splitext(os.path.basename(fname))[0]
|
||||
@ -290,9 +289,9 @@ def _include_dir_named_yaml(loader: LoaderType, node: yaml.nodes.Node) -> Ordere
|
||||
|
||||
def _include_dir_merge_named_yaml(
|
||||
loader: LoaderType, node: yaml.nodes.Node
|
||||
) -> OrderedDict:
|
||||
) -> NodeDictClass:
|
||||
"""Load multiple files from directory as a merged dictionary."""
|
||||
mapping: OrderedDict = OrderedDict()
|
||||
mapping = NodeDictClass()
|
||||
loc = os.path.join(os.path.dirname(loader.get_name()), node.value)
|
||||
for fname in _find_files(loc, "*.yaml"):
|
||||
if os.path.basename(fname) == SECRET_YAML:
|
||||
@ -330,7 +329,9 @@ def _include_dir_merge_list_yaml(
|
||||
return _add_reference(merged_list, loader, node)
|
||||
|
||||
|
||||
def _ordered_dict(loader: LoaderType, node: yaml.nodes.MappingNode) -> OrderedDict:
|
||||
def _handle_mapping_tag(
|
||||
loader: LoaderType, node: yaml.nodes.MappingNode
|
||||
) -> NodeDictClass:
|
||||
"""Load YAML mappings into an ordered dictionary to preserve key order."""
|
||||
loader.flatten_mapping(node)
|
||||
nodes = loader.construct_pairs(node)
|
||||
@ -361,7 +362,7 @@ def _ordered_dict(loader: LoaderType, node: yaml.nodes.MappingNode) -> OrderedDi
|
||||
)
|
||||
seen[key] = line
|
||||
|
||||
return _add_reference(OrderedDict(nodes), loader, node)
|
||||
return _add_reference(NodeDictClass(nodes), loader, node)
|
||||
|
||||
|
||||
def _construct_seq(loader: LoaderType, node: yaml.nodes.Node) -> JSON_TYPE:
|
||||
@ -398,7 +399,7 @@ def add_constructor(tag: Any, constructor: Any) -> None:
|
||||
|
||||
|
||||
add_constructor("!include", _include_yaml)
|
||||
add_constructor(yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, _ordered_dict)
|
||||
add_constructor(yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, _handle_mapping_tag)
|
||||
add_constructor(yaml.resolver.BaseResolver.DEFAULT_SEQUENCE_TAG, _construct_seq)
|
||||
add_constructor("!env_var", _env_var_yaml)
|
||||
add_constructor("!secret", secret_yaml)
|
||||
|
@ -14,6 +14,10 @@ class NodeStrClass(str):
|
||||
"""Wrapper class to be able to add attributes on a string."""
|
||||
|
||||
|
||||
class NodeDictClass(dict):
|
||||
"""Wrapper class to be able to add attributes on a dict."""
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Input:
|
||||
"""Input that should be substituted."""
|
||||
|
@ -1,25 +1,79 @@
|
||||
# serializer version: 1
|
||||
# name: test_extract_blueprint_from_community_topic
|
||||
OrderedDict({
|
||||
'remote': OrderedDict({
|
||||
'name': 'Remote',
|
||||
'description': 'IKEA remote to use',
|
||||
NodeDictClass({
|
||||
'brightness': NodeDictClass({
|
||||
'default': 50,
|
||||
'description': 'Brightness of the light(s) when turning on',
|
||||
'name': 'Brightness',
|
||||
'selector': dict({
|
||||
'device': OrderedDict({
|
||||
'integration': 'zha',
|
||||
'manufacturer': 'IKEA of Sweden',
|
||||
'model': 'TRADFRI remote control',
|
||||
'multiple': False,
|
||||
'number': NodeDictClass({
|
||||
'max': 100.0,
|
||||
'min': 0.0,
|
||||
'mode': 'slider',
|
||||
'step': 1.0,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'light': OrderedDict({
|
||||
'name': 'Light(s)',
|
||||
'description': 'The light(s) to control',
|
||||
'button_left_long': NodeDictClass({
|
||||
'default': NodeListClass([
|
||||
]),
|
||||
'description': 'Action to run on long left button press',
|
||||
'name': 'Left button - long press',
|
||||
'selector': dict({
|
||||
'target': OrderedDict({
|
||||
'action': dict({
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'button_left_short': NodeDictClass({
|
||||
'default': NodeListClass([
|
||||
]),
|
||||
'description': 'Action to run on short left button press',
|
||||
'name': 'Left button - short press',
|
||||
'selector': dict({
|
||||
'action': dict({
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'button_right_long': NodeDictClass({
|
||||
'default': NodeListClass([
|
||||
]),
|
||||
'description': 'Action to run on long right button press',
|
||||
'name': 'Right button - long press',
|
||||
'selector': dict({
|
||||
'action': dict({
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'button_right_short': NodeDictClass({
|
||||
'default': NodeListClass([
|
||||
]),
|
||||
'description': 'Action to run on short right button press',
|
||||
'name': 'Right button - short press',
|
||||
'selector': dict({
|
||||
'action': dict({
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'force_brightness': NodeDictClass({
|
||||
'default': False,
|
||||
'description': '''
|
||||
Force the brightness to the set level below, when the "on" button on the remote is pushed and lights turn on.
|
||||
|
||||
''',
|
||||
'name': 'Force turn on brightness',
|
||||
'selector': dict({
|
||||
'boolean': dict({
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'light': NodeDictClass({
|
||||
'description': 'The light(s) to control',
|
||||
'name': 'Light(s)',
|
||||
'selector': dict({
|
||||
'target': NodeDictClass({
|
||||
'entity': list([
|
||||
OrderedDict({
|
||||
NodeDictClass({
|
||||
'domain': list([
|
||||
'light',
|
||||
]),
|
||||
@ -28,95 +82,95 @@
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'force_brightness': OrderedDict({
|
||||
'name': 'Force turn on brightness',
|
||||
'description': '''
|
||||
Force the brightness to the set level below, when the "on" button on the remote is pushed and lights turn on.
|
||||
|
||||
''',
|
||||
'default': False,
|
||||
'remote': NodeDictClass({
|
||||
'description': 'IKEA remote to use',
|
||||
'name': 'Remote',
|
||||
'selector': dict({
|
||||
'boolean': dict({
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'brightness': OrderedDict({
|
||||
'name': 'Brightness',
|
||||
'description': 'Brightness of the light(s) when turning on',
|
||||
'default': 50,
|
||||
'selector': dict({
|
||||
'number': OrderedDict({
|
||||
'min': 0.0,
|
||||
'max': 100.0,
|
||||
'mode': 'slider',
|
||||
'step': 1.0,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'button_left_short': OrderedDict({
|
||||
'name': 'Left button - short press',
|
||||
'description': 'Action to run on short left button press',
|
||||
'default': NodeListClass([
|
||||
]),
|
||||
'selector': dict({
|
||||
'action': dict({
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'button_left_long': OrderedDict({
|
||||
'name': 'Left button - long press',
|
||||
'description': 'Action to run on long left button press',
|
||||
'default': NodeListClass([
|
||||
]),
|
||||
'selector': dict({
|
||||
'action': dict({
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'button_right_short': OrderedDict({
|
||||
'name': 'Right button - short press',
|
||||
'description': 'Action to run on short right button press',
|
||||
'default': NodeListClass([
|
||||
]),
|
||||
'selector': dict({
|
||||
'action': dict({
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'button_right_long': OrderedDict({
|
||||
'name': 'Right button - long press',
|
||||
'description': 'Action to run on long right button press',
|
||||
'default': NodeListClass([
|
||||
]),
|
||||
'selector': dict({
|
||||
'action': dict({
|
||||
'device': NodeDictClass({
|
||||
'integration': 'zha',
|
||||
'manufacturer': 'IKEA of Sweden',
|
||||
'model': 'TRADFRI remote control',
|
||||
'multiple': False,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
# ---
|
||||
# name: test_fetch_blueprint_from_community_url
|
||||
OrderedDict({
|
||||
'remote': OrderedDict({
|
||||
'name': 'Remote',
|
||||
'description': 'IKEA remote to use',
|
||||
NodeDictClass({
|
||||
'brightness': NodeDictClass({
|
||||
'default': 50,
|
||||
'description': 'Brightness of the light(s) when turning on',
|
||||
'name': 'Brightness',
|
||||
'selector': dict({
|
||||
'device': OrderedDict({
|
||||
'integration': 'zha',
|
||||
'manufacturer': 'IKEA of Sweden',
|
||||
'model': 'TRADFRI remote control',
|
||||
'multiple': False,
|
||||
'number': NodeDictClass({
|
||||
'max': 100.0,
|
||||
'min': 0.0,
|
||||
'mode': 'slider',
|
||||
'step': 1.0,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'light': OrderedDict({
|
||||
'name': 'Light(s)',
|
||||
'description': 'The light(s) to control',
|
||||
'button_left_long': NodeDictClass({
|
||||
'default': NodeListClass([
|
||||
]),
|
||||
'description': 'Action to run on long left button press',
|
||||
'name': 'Left button - long press',
|
||||
'selector': dict({
|
||||
'target': OrderedDict({
|
||||
'action': dict({
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'button_left_short': NodeDictClass({
|
||||
'default': NodeListClass([
|
||||
]),
|
||||
'description': 'Action to run on short left button press',
|
||||
'name': 'Left button - short press',
|
||||
'selector': dict({
|
||||
'action': dict({
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'button_right_long': NodeDictClass({
|
||||
'default': NodeListClass([
|
||||
]),
|
||||
'description': 'Action to run on long right button press',
|
||||
'name': 'Right button - long press',
|
||||
'selector': dict({
|
||||
'action': dict({
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'button_right_short': NodeDictClass({
|
||||
'default': NodeListClass([
|
||||
]),
|
||||
'description': 'Action to run on short right button press',
|
||||
'name': 'Right button - short press',
|
||||
'selector': dict({
|
||||
'action': dict({
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'force_brightness': NodeDictClass({
|
||||
'default': False,
|
||||
'description': '''
|
||||
Force the brightness to the set level below, when the "on" button on the remote is pushed and lights turn on.
|
||||
|
||||
''',
|
||||
'name': 'Force turn on brightness',
|
||||
'selector': dict({
|
||||
'boolean': dict({
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'light': NodeDictClass({
|
||||
'description': 'The light(s) to control',
|
||||
'name': 'Light(s)',
|
||||
'selector': dict({
|
||||
'target': NodeDictClass({
|
||||
'entity': list([
|
||||
OrderedDict({
|
||||
NodeDictClass({
|
||||
'domain': list([
|
||||
'light',
|
||||
]),
|
||||
@ -125,94 +179,26 @@
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'force_brightness': OrderedDict({
|
||||
'name': 'Force turn on brightness',
|
||||
'description': '''
|
||||
Force the brightness to the set level below, when the "on" button on the remote is pushed and lights turn on.
|
||||
|
||||
''',
|
||||
'default': False,
|
||||
'remote': NodeDictClass({
|
||||
'description': 'IKEA remote to use',
|
||||
'name': 'Remote',
|
||||
'selector': dict({
|
||||
'boolean': dict({
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'brightness': OrderedDict({
|
||||
'name': 'Brightness',
|
||||
'description': 'Brightness of the light(s) when turning on',
|
||||
'default': 50,
|
||||
'selector': dict({
|
||||
'number': OrderedDict({
|
||||
'min': 0.0,
|
||||
'max': 100.0,
|
||||
'mode': 'slider',
|
||||
'step': 1.0,
|
||||
'unit_of_measurement': '%',
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'button_left_short': OrderedDict({
|
||||
'name': 'Left button - short press',
|
||||
'description': 'Action to run on short left button press',
|
||||
'default': NodeListClass([
|
||||
]),
|
||||
'selector': dict({
|
||||
'action': dict({
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'button_left_long': OrderedDict({
|
||||
'name': 'Left button - long press',
|
||||
'description': 'Action to run on long left button press',
|
||||
'default': NodeListClass([
|
||||
]),
|
||||
'selector': dict({
|
||||
'action': dict({
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'button_right_short': OrderedDict({
|
||||
'name': 'Right button - short press',
|
||||
'description': 'Action to run on short right button press',
|
||||
'default': NodeListClass([
|
||||
]),
|
||||
'selector': dict({
|
||||
'action': dict({
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'button_right_long': OrderedDict({
|
||||
'name': 'Right button - long press',
|
||||
'description': 'Action to run on long right button press',
|
||||
'default': NodeListClass([
|
||||
]),
|
||||
'selector': dict({
|
||||
'action': dict({
|
||||
'device': NodeDictClass({
|
||||
'integration': 'zha',
|
||||
'manufacturer': 'IKEA of Sweden',
|
||||
'model': 'TRADFRI remote control',
|
||||
'multiple': False,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
# ---
|
||||
# name: test_fetch_blueprint_from_github_gist_url
|
||||
OrderedDict({
|
||||
'motion_entity': OrderedDict({
|
||||
'name': 'Motion Sensor',
|
||||
'selector': dict({
|
||||
'entity': OrderedDict({
|
||||
'domain': list([
|
||||
'binary_sensor',
|
||||
]),
|
||||
'device_class': list([
|
||||
'motion',
|
||||
]),
|
||||
'multiple': False,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'light_entity': OrderedDict({
|
||||
NodeDictClass({
|
||||
'light_entity': NodeDictClass({
|
||||
'name': 'Light',
|
||||
'selector': dict({
|
||||
'entity': OrderedDict({
|
||||
'entity': NodeDictClass({
|
||||
'domain': list([
|
||||
'light',
|
||||
]),
|
||||
@ -220,5 +206,19 @@
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
'motion_entity': NodeDictClass({
|
||||
'name': 'Motion Sensor',
|
||||
'selector': dict({
|
||||
'entity': NodeDictClass({
|
||||
'device_class': list([
|
||||
'motion',
|
||||
]),
|
||||
'domain': list([
|
||||
'binary_sensor',
|
||||
]),
|
||||
'multiple': False,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
# ---
|
||||
|
Loading…
x
Reference in New Issue
Block a user