mirror of
https://github.com/esphome/esphome.git
synced 2026-06-24 12:17:23 +00:00
[cli] Allow state reporting control via env (#16746)
This commit is contained in:
@@ -1351,6 +1351,19 @@ def _validate_bootloader_binary(binary: Path) -> None:
|
||||
)
|
||||
|
||||
|
||||
def _should_subscribe_states(args: ArgsProtocol) -> bool:
|
||||
"""Determine whether entity state changes should be shown in log output.
|
||||
|
||||
The ``--states``/``--no-states`` command line flags take precedence. When
|
||||
neither is given, the ``ESPHOME_LOG_STATES`` environment variable controls
|
||||
the behavior, defaulting to showing states.
|
||||
"""
|
||||
states = getattr(args, "states", None)
|
||||
if states is not None:
|
||||
return states
|
||||
return get_bool_env("ESPHOME_LOG_STATES", True)
|
||||
|
||||
|
||||
def show_logs(config: ConfigType, args: ArgsProtocol, devices: list[str]) -> int | None:
|
||||
try:
|
||||
module = importlib.import_module("esphome.components." + CORE.target_platform)
|
||||
@@ -1380,7 +1393,7 @@ def show_logs(config: ConfigType, args: ArgsProtocol, devices: list[str]) -> int
|
||||
return run_logs(
|
||||
config,
|
||||
network_devices,
|
||||
subscribe_states=not getattr(args, "no_states", False),
|
||||
subscribe_states=_should_subscribe_states(args),
|
||||
)
|
||||
|
||||
if port_type in (PortType.NETWORK, PortType.MQTT) and has_mqtt_logging():
|
||||
@@ -2019,6 +2032,29 @@ SIMPLE_CONFIG_ACTIONS = [
|
||||
]
|
||||
|
||||
|
||||
def _add_states_args(parser: argparse.ArgumentParser) -> None:
|
||||
"""Add mutually exclusive ``--states``/``--no-states`` flags to a parser.
|
||||
|
||||
When neither flag is given, the ``ESPHOME_LOG_STATES`` environment variable
|
||||
controls whether entity state changes are shown (defaulting to showing them).
|
||||
"""
|
||||
states_group = parser.add_mutually_exclusive_group()
|
||||
states_group.add_argument(
|
||||
"--states",
|
||||
dest="states",
|
||||
action="store_true",
|
||||
default=None,
|
||||
help="Show entity state changes in log output (overrides ESPHOME_LOG_STATES).",
|
||||
)
|
||||
states_group.add_argument(
|
||||
"--no-states",
|
||||
dest="states",
|
||||
action="store_false",
|
||||
default=None,
|
||||
help="Do not show entity state changes in log output.",
|
||||
)
|
||||
|
||||
|
||||
def parse_args(argv):
|
||||
options_parser = argparse.ArgumentParser(add_help=False)
|
||||
options_parser.add_argument(
|
||||
@@ -2195,11 +2231,7 @@ def parse_args(argv):
|
||||
help="Reset the device before starting serial logs.",
|
||||
default=os.getenv("ESPHOME_SERIAL_LOGGING_RESET"),
|
||||
)
|
||||
parser_logs.add_argument(
|
||||
"--no-states",
|
||||
action="store_true",
|
||||
help="Do not show entity state changes in log output.",
|
||||
)
|
||||
_add_states_args(parser_logs)
|
||||
|
||||
parser_discover = subparsers.add_parser(
|
||||
"discover",
|
||||
@@ -2231,11 +2263,7 @@ def parse_args(argv):
|
||||
"--no-logs", help="Disable starting logs.", action="store_true"
|
||||
)
|
||||
|
||||
parser_run.add_argument(
|
||||
"--no-states",
|
||||
action="store_true",
|
||||
help="Do not show entity state changes in log output.",
|
||||
)
|
||||
_add_states_args(parser_run)
|
||||
|
||||
parser_run.add_argument(
|
||||
"--reset",
|
||||
|
||||
@@ -1269,6 +1269,7 @@ class MockArgs:
|
||||
ota_platform: str | None = None
|
||||
partition_table: bool = False
|
||||
bootloader: bool = False
|
||||
states: bool | None = None
|
||||
|
||||
|
||||
def test_upload_program_serial_esp32(
|
||||
@@ -2663,7 +2664,7 @@ def test_show_logs_api_no_states(
|
||||
mock_run_logs.return_value = 0
|
||||
|
||||
args = MockArgs()
|
||||
args.no_states = True
|
||||
args.states = False
|
||||
devices = ["192.168.1.100"]
|
||||
|
||||
result = show_logs(CORE.config, args, devices)
|
||||
@@ -5989,19 +5990,68 @@ def test_upload_using_esptool_subprocess_passes_crystal_callback(
|
||||
def test_parse_args_run_no_states() -> None:
|
||||
"""Test that --no-states is parsed for the run command."""
|
||||
args = parse_args(["esphome", "run", "--no-states", "device.yaml"])
|
||||
assert args.no_states is True
|
||||
assert args.states is False
|
||||
|
||||
|
||||
def test_parse_args_run_no_states_default() -> None:
|
||||
"""Test that no_states defaults to False for the run command."""
|
||||
def test_parse_args_run_states() -> None:
|
||||
"""Test that --states is parsed for the run command."""
|
||||
args = parse_args(["esphome", "run", "--states", "device.yaml"])
|
||||
assert args.states is True
|
||||
|
||||
|
||||
def test_parse_args_run_states_default() -> None:
|
||||
"""Test that states defaults to None (unset) for the run command."""
|
||||
args = parse_args(["esphome", "run", "device.yaml"])
|
||||
assert args.no_states is False
|
||||
assert args.states is None
|
||||
|
||||
|
||||
def test_parse_args_logs_no_states() -> None:
|
||||
"""Test that --no-states is parsed for the logs command."""
|
||||
args = parse_args(["esphome", "logs", "--no-states", "device.yaml"])
|
||||
assert args.no_states is True
|
||||
assert args.states is False
|
||||
|
||||
|
||||
def test_parse_args_logs_states() -> None:
|
||||
"""Test that --states is parsed for the logs command."""
|
||||
args = parse_args(["esphome", "logs", "--states", "device.yaml"])
|
||||
assert args.states is True
|
||||
|
||||
|
||||
def test_should_subscribe_states_default() -> None:
|
||||
"""Test that states are shown by default when nothing is set."""
|
||||
from esphome.__main__ import _should_subscribe_states
|
||||
|
||||
args = parse_args(["esphome", "logs", "device.yaml"])
|
||||
with patch.dict(os.environ, {}, clear=False):
|
||||
os.environ.pop("ESPHOME_LOG_STATES", None)
|
||||
assert _should_subscribe_states(args) is True
|
||||
|
||||
|
||||
def test_should_subscribe_states_env_suppresses() -> None:
|
||||
"""Test that ESPHOME_LOG_STATES=false suppresses states by default."""
|
||||
from esphome.__main__ import _should_subscribe_states
|
||||
|
||||
args = parse_args(["esphome", "logs", "device.yaml"])
|
||||
with patch.dict(os.environ, {"ESPHOME_LOG_STATES": "false"}):
|
||||
assert _should_subscribe_states(args) is False
|
||||
|
||||
|
||||
def test_should_subscribe_states_flag_overrides_env() -> None:
|
||||
"""Test that --states overrides ESPHOME_LOG_STATES=false."""
|
||||
from esphome.__main__ import _should_subscribe_states
|
||||
|
||||
args = parse_args(["esphome", "logs", "--states", "device.yaml"])
|
||||
with patch.dict(os.environ, {"ESPHOME_LOG_STATES": "false"}):
|
||||
assert _should_subscribe_states(args) is True
|
||||
|
||||
|
||||
def test_should_subscribe_states_no_flag_overrides_env() -> None:
|
||||
"""Test that --no-states overrides ESPHOME_LOG_STATES=true."""
|
||||
from esphome.__main__ import _should_subscribe_states
|
||||
|
||||
args = parse_args(["esphome", "logs", "--no-states", "device.yaml"])
|
||||
with patch.dict(os.environ, {"ESPHOME_LOG_STATES": "true"}):
|
||||
assert _should_subscribe_states(args) is False
|
||||
|
||||
|
||||
@patch("esphome.components.api.client.run_logs")
|
||||
@@ -6020,7 +6070,7 @@ def test_command_run_passes_no_states_to_show_logs(
|
||||
mock_run_logs.return_value = 0
|
||||
|
||||
args = MockArgs()
|
||||
args.no_states = True
|
||||
args.states = False
|
||||
args.no_logs = False
|
||||
args.device = None
|
||||
|
||||
|
||||
Reference in New Issue
Block a user