mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	Add config validator location (#1490)
* show validation source location for id * show validation source location for lambda * refactor lambda #line position * account content offset on made lambdas * lint * remove redundant check
This commit is contained in:
		
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							de3377132d
						
					
				
				
					commit
					28e39f7f76
				
			| @@ -268,6 +268,8 @@ class Config(OrderedDict): | ||||
|                 data = data[item_index] | ||||
|             except (KeyError, IndexError, TypeError): | ||||
|                 return doc_range | ||||
|             if isinstance(data, core.ID): | ||||
|                 data = data.id | ||||
|             if isinstance(data, ESPHomeDataBase) and data.esp_range is not None: | ||||
|                 doc_range = data.esp_range | ||||
|  | ||||
| @@ -700,6 +702,8 @@ def line_info(obj, 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 | ||||
|         source = "[source {}:{}]".format(mark.document, mark.line + 1) | ||||
|   | ||||
| @@ -17,10 +17,10 @@ from esphome.const import ALLOWED_NAME_CHARS, CONF_AVAILABILITY, CONF_COMMAND_TO | ||||
|     CONF_HOUR, CONF_MINUTE, CONF_SECOND, CONF_VALUE, CONF_UPDATE_INTERVAL, CONF_TYPE_ID, \ | ||||
|     CONF_TYPE, CONF_PACKAGES | ||||
| from esphome.core import CORE, HexInt, IPAddress, Lambda, TimePeriod, TimePeriodMicroseconds, \ | ||||
|     TimePeriodMilliseconds, TimePeriodSeconds, TimePeriodMinutes, DocumentLocation | ||||
|     TimePeriodMilliseconds, TimePeriodSeconds, TimePeriodMinutes | ||||
| from esphome.helpers import list_starts_with, add_class_to_obj | ||||
| from esphome.voluptuous_schema import _Schema | ||||
| from esphome.yaml_util import ESPHomeDataBase | ||||
| from esphome.yaml_util import make_data_base | ||||
|  | ||||
| _LOGGER = logging.getLogger(__name__) | ||||
|  | ||||
| @@ -983,11 +983,7 @@ LAMBDA_ENTITY_ID_PROG = re.compile(r'id\(\s*([a-zA-Z0-9_]+\.[.a-zA-Z0-9_]+)\s*\) | ||||
| def lambda_(value): | ||||
|     """Coerce this configuration option to a lambda.""" | ||||
|     if not isinstance(value, Lambda): | ||||
|         start_mark = None | ||||
|         if isinstance(value, ESPHomeDataBase) and value.esp_range is not None: | ||||
|             start_mark = DocumentLocation.copy(value.esp_range.start_mark) | ||||
|             start_mark.line += value.content_offset | ||||
|         value = Lambda(string_strict(value), start_mark) | ||||
|         value = make_data_base(Lambda(string_strict(value)), value) | ||||
|     entity_id_parts = re.split(LAMBDA_ENTITY_ID_PROG, value.value) | ||||
|     if len(entity_id_parts) != 1: | ||||
|         entity_ids = ' '.join("'{}'".format(entity_id_parts[i]) | ||||
|   | ||||
| @@ -227,7 +227,7 @@ LAMBDA_PROG = re.compile(r'id\(\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\)(\.?)') | ||||
|  | ||||
|  | ||||
| class Lambda: | ||||
|     def __init__(self, value, start_mark=None): | ||||
|     def __init__(self, value): | ||||
|         # pylint: disable=protected-access | ||||
|         if isinstance(value, Lambda): | ||||
|             self._value = value._value | ||||
| @@ -235,7 +235,6 @@ class Lambda: | ||||
|             self._value = value | ||||
|         self._parts = None | ||||
|         self._requires_ids = None | ||||
|         self._source_location = start_mark | ||||
|  | ||||
|     # https://stackoverflow.com/a/241506/229052 | ||||
|     def comment_remover(self, text): | ||||
| @@ -278,10 +277,6 @@ class Lambda: | ||||
|     def __repr__(self): | ||||
|         return f'Lambda<{self.value}>' | ||||
|  | ||||
|     @property | ||||
|     def source_location(self): | ||||
|         return self._source_location | ||||
|  | ||||
|  | ||||
| class ID: | ||||
|     def __init__(self, id, is_declaration=False, type=None, is_manual=None): | ||||
| @@ -339,14 +334,6 @@ class DocumentLocation: | ||||
|             mark.column | ||||
|         ) | ||||
|  | ||||
|     @classmethod | ||||
|     def copy(cls, location): | ||||
|         return cls( | ||||
|             location.document, | ||||
|             location.line, | ||||
|             location.column | ||||
|         ) | ||||
|  | ||||
|     def __str__(self): | ||||
|         return f'{self.document} {self.line}:{self.column}' | ||||
|  | ||||
|   | ||||
| @@ -2,6 +2,7 @@ import abc | ||||
| import inspect | ||||
| import math | ||||
| import re | ||||
| from esphome.yaml_util import ESPHomeDataBase | ||||
|  | ||||
| # pylint: disable=unused-import, wrong-import-order | ||||
| from typing import Any, Generator, List, Optional, Tuple, Type, Union, Sequence | ||||
| @@ -560,7 +561,13 @@ def process_lambda( | ||||
|         else: | ||||
|             parts[i * 3 + 1] = var | ||||
|         parts[i * 3 + 2] = '' | ||||
|     yield LambdaExpression(parts, parameters, capture, return_type, value.source_location) | ||||
|  | ||||
|     if isinstance(value, ESPHomeDataBase) and value.esp_range is not None: | ||||
|         location = value.esp_range.start_mark | ||||
|         location.line += value.content_offset | ||||
|     else: | ||||
|         location = None | ||||
|     yield LambdaExpression(parts, parameters, capture, return_type, location) | ||||
|  | ||||
|  | ||||
| def is_template(value): | ||||
|   | ||||
| @@ -12,7 +12,7 @@ import yaml.constructor | ||||
| from esphome import core | ||||
| from esphome.config_helpers import read_config_file | ||||
| from esphome.core import EsphomeError, IPAddress, Lambda, MACAddress, TimePeriod, \ | ||||
|     DocumentRange, DocumentLocation | ||||
|     DocumentRange | ||||
| from esphome.helpers import add_class_to_obj | ||||
| from esphome.util import OrderedDict, filter_yaml_files | ||||
|  | ||||
| @@ -42,14 +42,22 @@ class ESPHomeDataBase: | ||||
|             if node.style is not None and node.style in '|>': | ||||
|                 self._content_offset = 1 | ||||
|  | ||||
|     def from_database(self, database): | ||||
|         # pylint: disable=attribute-defined-outside-init | ||||
|         self._esp_range = database.esp_range | ||||
|         self._content_offset = database.content_offset | ||||
|  | ||||
|  | ||||
| class ESPForceValue: | ||||
|     pass | ||||
|  | ||||
|  | ||||
| def make_data_base(value): | ||||
| def make_data_base(value, from_database: ESPHomeDataBase = None): | ||||
|     try: | ||||
|         return add_class_to_obj(value, ESPHomeDataBase) | ||||
|         value = add_class_to_obj(value, ESPHomeDataBase) | ||||
|         if from_database is not None: | ||||
|             value.from_database(from_database) | ||||
|         return value | ||||
|     except TypeError: | ||||
|         # Adding class failed, ignore error | ||||
|         return value | ||||
| @@ -265,10 +273,7 @@ class ESPHomeLoader(yaml.SafeLoader):  # pylint: disable=too-many-ancestors | ||||
|  | ||||
|     @_add_data_ref | ||||
|     def construct_lambda(self, node): | ||||
|         start_mark = DocumentLocation.from_mark(node.start_mark) | ||||
|         if node.style is not None and node.style in '|>': | ||||
|             start_mark.line += 1 | ||||
|         return Lambda(str(node.value), start_mark) | ||||
|         return Lambda(str(node.value)) | ||||
|  | ||||
|     @_add_data_ref | ||||
|     def construct_force(self, node): | ||||
|   | ||||
		Reference in New Issue
	
	Block a user