mirror of
https://github.com/esphome/esphome.git
synced 2025-09-14 01:02:19 +01:00
Checks for pins used in multiple places (#5666)
This commit is contained in:
@@ -7,6 +7,7 @@ import re
|
||||
from typing import Optional, Union
|
||||
|
||||
from contextlib import contextmanager
|
||||
import contextvars
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@@ -53,6 +54,7 @@ def iter_components(config):
|
||||
|
||||
|
||||
ConfigPath = list[Union[str, int]]
|
||||
path_context = contextvars.ContextVar("Config path")
|
||||
|
||||
|
||||
def _path_begins_with(path: ConfigPath, other: ConfigPath) -> bool:
|
||||
@@ -489,6 +491,7 @@ class SchemaValidationStep(ConfigValidationStep):
|
||||
def run(self, result: Config) -> None:
|
||||
if self.comp.config_schema is None:
|
||||
return
|
||||
token = path_context.set(self.path)
|
||||
with result.catch_error(self.path):
|
||||
if self.comp.is_platform:
|
||||
# Remove 'platform' key for validation
|
||||
@@ -507,6 +510,7 @@ class SchemaValidationStep(ConfigValidationStep):
|
||||
validated = schema(self.conf)
|
||||
result.set_by_path(self.path, validated)
|
||||
|
||||
path_context.reset(token)
|
||||
result.add_validation_step(FinalValidateValidationStep(self.path, self.comp))
|
||||
|
||||
|
||||
@@ -652,37 +656,24 @@ class FinalValidateValidationStep(ConfigValidationStep):
|
||||
if self.comp.final_validate_schema is not None:
|
||||
self.comp.final_validate_schema(conf)
|
||||
|
||||
fconf = fv.full_config.get()
|
||||
|
||||
def _check_pins(c):
|
||||
for value in c.values():
|
||||
if not isinstance(value, dict):
|
||||
continue
|
||||
for key, (
|
||||
_,
|
||||
_,
|
||||
pin_final_validate,
|
||||
) in pins.PIN_SCHEMA_REGISTRY.items():
|
||||
if (
|
||||
key != CORE.target_platform
|
||||
and key in value
|
||||
and pin_final_validate is not None
|
||||
):
|
||||
pin_final_validate(fconf, value)
|
||||
|
||||
# Check for pin configs and a final_validate schema in the pin registry
|
||||
confs = conf
|
||||
if not isinstance(
|
||||
confs, list
|
||||
): # Handle components like SPI that have a list instead of MULTI_CONF
|
||||
confs = [conf]
|
||||
for c in confs:
|
||||
if c: # Some component have None or empty schemas
|
||||
_check_pins(c)
|
||||
|
||||
fv.full_config.reset(token)
|
||||
|
||||
|
||||
class PinUseValidationCheck(ConfigValidationStep):
|
||||
"""Check for pin reuse"""
|
||||
|
||||
priority = -30 # Should happen after component final validations
|
||||
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
||||
def run(self, result: Config) -> None:
|
||||
if result.errors:
|
||||
# If result already has errors, skip this step
|
||||
return
|
||||
pins.PIN_SCHEMA_REGISTRY.final_validate(result)
|
||||
|
||||
|
||||
def validate_config(config, command_line_substitutions) -> Config:
|
||||
result = Config()
|
||||
|
||||
@@ -778,6 +769,7 @@ def validate_config(config, command_line_substitutions) -> Config:
|
||||
for domain, conf in config.items():
|
||||
result.add_validation_step(LoadValidationStep(domain, conf))
|
||||
result.add_validation_step(IDPassValidationStep())
|
||||
result.add_validation_step(PinUseValidationCheck())
|
||||
|
||||
result.run_validation_steps()
|
||||
|
||||
|
Reference in New Issue
Block a user