diff --git a/esphome/config.py b/esphome/config.py index 5dc539f828..957494ceac 100644 --- a/esphome/config.py +++ b/esphome/config.py @@ -265,6 +265,8 @@ class Config(OrderedDict): doc_range = None for item_index in path: 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] except (KeyError, IndexError, TypeError): return doc_range @@ -461,7 +463,6 @@ def validate_config(config, command_line_substitutions): while load_queue: domain, conf = load_queue.popleft() - domain = str(domain) if domain.startswith('.'): # Ignore top-level keys starting with a dot continue @@ -698,17 +699,16 @@ def load_config(command_line_substitutions): 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.""" if not highlight: return None - if isinstance(obj, core.ID): - obj = obj.id - if isinstance(obj, ESPHomeDataBase) and obj.esp_range is not None: - mark = obj.esp_range.start_mark + obj = config.get_deepest_document_range_for_path(path) + if obj: + mark = obj.start_mark source = "[source {}:{}]".format(mark.document, mark.line + 1) return color('cyan', source) - return None + return 'None' def _print_on_next_line(obj): @@ -749,7 +749,7 @@ def dump_dict(config, path, at_root=True): sep = color('red', sep) msg, _ = dump_dict(config, path_, at_root=False) 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: msg = inf + '\n' + msg elif msg: @@ -772,7 +772,7 @@ def dump_dict(config, path, at_root=True): st = color('red', st) 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: msg = '\n' + indent(msg) @@ -849,8 +849,11 @@ def read_config(command_line_substitutions): if not res.is_in_error_path(path): continue - safe_print(color('bold_red', f'{domain}:') + ' ' + - (line_info(res.get_nested_item(path)) or '')) + errstr = color('bold_red', f'{domain}:') + errline = line_info(res, path) + if errline: + errstr += ' ' + errline + safe_print(errstr) safe_print(indent(dump_dict(res, path)[0])) return None return OrderedDict(res) diff --git a/esphome/yaml_util.py b/esphome/yaml_util.py index 5909e99cb2..eb88a8da62 100644 --- a/esphome/yaml_util.py +++ b/esphome/yaml_util.py @@ -146,6 +146,9 @@ class ESPHomeLoader(yaml.SafeLoader): # pylint: disable=too-many-ancestors raise yaml.constructor.ConstructorError( 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 if key in seen_keys: raise yaml.constructor.ConstructorError(