mirror of
https://github.com/esphome/esphome.git
synced 2026-10-07 11:26:39 +00:00
[core] Sensitive redaction via yaml_util representer
cv.sensitive(...) now returns a SensitiveStr (thin str subclass) so the tag travels with the validated value. yaml_util.dump constructs a per-call ESPHomeDumper subclass with a class-attribute redaction flag; the PyYAML representer for SensitiveStr renders values wrapped in literal \\033[8m...\\033[28m text when show_secrets is False and raw when True. The post-dump regex in command_config is deleted. Also tags wifi.ssid sites with cv.sensitive so SSID coverage isn't lost when the regex (which matched 'ssid:' via substring) goes away. No module-level mutable state; the per-call subclass keeps each dump invocation self-contained and thread-safe by construction.
This commit is contained in:
@@ -145,6 +145,46 @@ def test_sensitive__custom_inner_delegates_validation() -> None:
|
||||
validator(123)
|
||||
|
||||
|
||||
def test_sensitive__wraps_string_result_in_sensitive_str() -> None:
|
||||
from esphome.yaml_util import SensitiveStr
|
||||
|
||||
validator = config_validation.sensitive()
|
||||
result = validator("hunter2")
|
||||
|
||||
assert isinstance(result, SensitiveStr)
|
||||
assert isinstance(result, str)
|
||||
assert result == "hunter2"
|
||||
|
||||
|
||||
def test_sensitive__does_not_double_tag_already_sensitive() -> None:
|
||||
from esphome.yaml_util import SensitiveStr
|
||||
|
||||
# If the inner validator already returns a SensitiveStr (e.g., nested
|
||||
# cv.sensitive wrappers), re-tagging is a no-op rather than a new
|
||||
# SensitiveStr around the same value.
|
||||
pre_tagged = SensitiveStr("hunter2")
|
||||
|
||||
def inner(_value):
|
||||
return pre_tagged
|
||||
|
||||
validator = config_validation.sensitive(inner)
|
||||
result = validator("anything")
|
||||
|
||||
assert result is pre_tagged
|
||||
|
||||
|
||||
def test_sensitive__non_string_result_passes_through() -> None:
|
||||
# If an inner validator returns something other than a string (e.g., a
|
||||
# Lambda template), the sensitive wrapper must not coerce it.
|
||||
sentinel = object()
|
||||
|
||||
def inner(_value):
|
||||
return sentinel
|
||||
|
||||
validator = config_validation.sensitive(inner)
|
||||
assert validator("anything") is sentinel
|
||||
|
||||
|
||||
def test_sensitive__is_detectable_via_isinstance() -> None:
|
||||
validator = config_validation.sensitive()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user