More yaml validation (#1568)

* validate keys

* refactor line info
This commit is contained in:
Guillermo Ruffino 2021-02-27 19:21:07 -03:00 committed by GitHub
parent 69d39ef0cd
commit 342d5166a0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 17 additions and 11 deletions

View file

@ -265,6 +265,8 @@ class Config(OrderedDict):
doc_range = None doc_range = None
for item_index in path: for item_index in path:
try: try:
if item_index in data:
doc_range = [x for x in data.keys() if x == item_index][0].esp_range
data = data[item_index] data = data[item_index]
except (KeyError, IndexError, TypeError): except (KeyError, IndexError, TypeError):
return doc_range return doc_range
@ -461,7 +463,6 @@ def validate_config(config, command_line_substitutions):
while load_queue: while load_queue:
domain, conf = load_queue.popleft() domain, conf = load_queue.popleft()
domain = str(domain)
if domain.startswith('.'): if domain.startswith('.'):
# Ignore top-level keys starting with a dot # Ignore top-level keys starting with a dot
continue continue
@ -698,17 +699,16 @@ def load_config(command_line_substitutions):
raise EsphomeError(f"Error while parsing config: {err}") from err raise EsphomeError(f"Error while parsing config: {err}") from err
def line_info(obj, highlight=True): def line_info(config, path, highlight=True):
"""Display line config source.""" """Display line config source."""
if not highlight: if not highlight:
return None return None
if isinstance(obj, core.ID): obj = config.get_deepest_document_range_for_path(path)
obj = obj.id if obj:
if isinstance(obj, ESPHomeDataBase) and obj.esp_range is not None: mark = obj.start_mark
mark = obj.esp_range.start_mark
source = "[source {}:{}]".format(mark.document, mark.line + 1) source = "[source {}:{}]".format(mark.document, mark.line + 1)
return color('cyan', source) return color('cyan', source)
return None return 'None'
def _print_on_next_line(obj): def _print_on_next_line(obj):
@ -749,7 +749,7 @@ def dump_dict(config, path, at_root=True):
sep = color('red', sep) sep = color('red', sep)
msg, _ = dump_dict(config, path_, at_root=False) msg, _ = dump_dict(config, path_, at_root=False)
msg = indent(msg) msg = indent(msg)
inf = line_info(config.get_nested_item(path_), highlight=config.is_in_error_path(path_)) inf = line_info(config, path_, highlight=config.is_in_error_path(path_))
if inf is not None: if inf is not None:
msg = inf + '\n' + msg msg = inf + '\n' + msg
elif msg: elif msg:
@ -772,7 +772,7 @@ def dump_dict(config, path, at_root=True):
st = color('red', st) st = color('red', st)
msg, m = dump_dict(config, path_, at_root=False) msg, m = dump_dict(config, path_, at_root=False)
inf = line_info(config.get_nested_item(path_), highlight=config.is_in_error_path(path_)) inf = line_info(config, path_, highlight=config.is_in_error_path(path_))
if m: if m:
msg = '\n' + indent(msg) msg = '\n' + indent(msg)
@ -849,8 +849,11 @@ def read_config(command_line_substitutions):
if not res.is_in_error_path(path): if not res.is_in_error_path(path):
continue continue
safe_print(color('bold_red', f'{domain}:') + ' ' + errstr = color('bold_red', f'{domain}:')
(line_info(res.get_nested_item(path)) or '')) errline = line_info(res, path)
if errline:
errstr += ' ' + errline
safe_print(errstr)
safe_print(indent(dump_dict(res, path)[0])) safe_print(indent(dump_dict(res, path)[0]))
return None return None
return OrderedDict(res) return OrderedDict(res)

View file

@ -146,6 +146,9 @@ class ESPHomeLoader(yaml.SafeLoader): # pylint: disable=too-many-ancestors
raise yaml.constructor.ConstructorError( raise yaml.constructor.ConstructorError(
f'Invalid key "{key}" (not hashable)', key_node.start_mark) f'Invalid key "{key}" (not hashable)', key_node.start_mark)
key = make_data_base(str(key))
key.from_node(key_node)
# Check if it is a duplicate key # Check if it is a duplicate key
if key in seen_keys: if key in seen_keys:
raise yaml.constructor.ConstructorError( raise yaml.constructor.ConstructorError(