mirror of
https://github.com/esphome/esphome.git
synced 2026-10-06 19:06:37 +00:00
[ruff] Enable SIM rules and fix code simplification violations (#9872)
This commit is contained in:
@@ -183,19 +183,17 @@ async def yaml_config(request: pytest.FixtureRequest, unused_tcp_port: int) -> s
|
||||
content = content.replace("api:", f"api:\n port: {unused_tcp_port}")
|
||||
|
||||
# Add debug build flags for integration tests to enable assertions
|
||||
if "esphome:" in content:
|
||||
# Check if platformio_options already exists
|
||||
if "platformio_options:" not in content:
|
||||
# Add platformio_options with debug flags after esphome:
|
||||
content = content.replace(
|
||||
"esphome:",
|
||||
"esphome:\n"
|
||||
" # Enable assertions for integration tests\n"
|
||||
" platformio_options:\n"
|
||||
" build_flags:\n"
|
||||
' - "-DDEBUG" # Enable assert() statements\n'
|
||||
' - "-g" # Add debug symbols',
|
||||
)
|
||||
if "esphome:" in content and "platformio_options:" not in content:
|
||||
# Add platformio_options with debug flags after esphome:
|
||||
content = content.replace(
|
||||
"esphome:",
|
||||
"esphome:\n"
|
||||
" # Enable assertions for integration tests\n"
|
||||
" platformio_options:\n"
|
||||
" build_flags:\n"
|
||||
' - "-DDEBUG" # Enable assert() statements\n'
|
||||
' - "-g" # Add debug symbols',
|
||||
)
|
||||
|
||||
return content
|
||||
|
||||
|
||||
@@ -59,86 +59,86 @@ async def test_api_custom_services(
|
||||
custom_arrays_future.set_result(True)
|
||||
|
||||
# Run with log monitoring
|
||||
async with run_compiled(yaml_config, line_callback=check_output):
|
||||
async with api_client_connected() as client:
|
||||
# Verify device info
|
||||
device_info = await client.device_info()
|
||||
assert device_info is not None
|
||||
assert device_info.name == "api-custom-services-test"
|
||||
async with (
|
||||
run_compiled(yaml_config, line_callback=check_output),
|
||||
api_client_connected() as client,
|
||||
):
|
||||
# Verify device info
|
||||
device_info = await client.device_info()
|
||||
assert device_info is not None
|
||||
assert device_info.name == "api-custom-services-test"
|
||||
|
||||
# List services
|
||||
_, services = await client.list_entities_services()
|
||||
# List services
|
||||
_, services = await client.list_entities_services()
|
||||
|
||||
# Should have 4 services: 1 YAML + 3 CustomAPIDevice
|
||||
assert len(services) == 4, f"Expected 4 services, found {len(services)}"
|
||||
# Should have 4 services: 1 YAML + 3 CustomAPIDevice
|
||||
assert len(services) == 4, f"Expected 4 services, found {len(services)}"
|
||||
|
||||
# Find our services
|
||||
yaml_service: UserService | None = None
|
||||
custom_service: UserService | None = None
|
||||
custom_args_service: UserService | None = None
|
||||
custom_arrays_service: UserService | None = None
|
||||
# Find our services
|
||||
yaml_service: UserService | None = None
|
||||
custom_service: UserService | None = None
|
||||
custom_args_service: UserService | None = None
|
||||
custom_arrays_service: UserService | None = None
|
||||
|
||||
for service in services:
|
||||
if service.name == "test_yaml_service":
|
||||
yaml_service = service
|
||||
elif service.name == "custom_test_service":
|
||||
custom_service = service
|
||||
elif service.name == "custom_service_with_args":
|
||||
custom_args_service = service
|
||||
elif service.name == "custom_service_with_arrays":
|
||||
custom_arrays_service = service
|
||||
for service in services:
|
||||
if service.name == "test_yaml_service":
|
||||
yaml_service = service
|
||||
elif service.name == "custom_test_service":
|
||||
custom_service = service
|
||||
elif service.name == "custom_service_with_args":
|
||||
custom_args_service = service
|
||||
elif service.name == "custom_service_with_arrays":
|
||||
custom_arrays_service = service
|
||||
|
||||
assert yaml_service is not None, "test_yaml_service not found"
|
||||
assert custom_service is not None, "custom_test_service not found"
|
||||
assert custom_args_service is not None, "custom_service_with_args not found"
|
||||
assert custom_arrays_service is not None, (
|
||||
"custom_service_with_arrays not found"
|
||||
)
|
||||
assert yaml_service is not None, "test_yaml_service not found"
|
||||
assert custom_service is not None, "custom_test_service not found"
|
||||
assert custom_args_service is not None, "custom_service_with_args not found"
|
||||
assert custom_arrays_service is not None, "custom_service_with_arrays not found"
|
||||
|
||||
# Test YAML service
|
||||
client.execute_service(yaml_service, {})
|
||||
await asyncio.wait_for(yaml_service_future, timeout=5.0)
|
||||
# Test YAML service
|
||||
client.execute_service(yaml_service, {})
|
||||
await asyncio.wait_for(yaml_service_future, timeout=5.0)
|
||||
|
||||
# Test simple CustomAPIDevice service
|
||||
client.execute_service(custom_service, {})
|
||||
await asyncio.wait_for(custom_service_future, timeout=5.0)
|
||||
# Test simple CustomAPIDevice service
|
||||
client.execute_service(custom_service, {})
|
||||
await asyncio.wait_for(custom_service_future, timeout=5.0)
|
||||
|
||||
# Verify custom_args_service arguments
|
||||
assert len(custom_args_service.args) == 4
|
||||
arg_types = {arg.name: arg.type for arg in custom_args_service.args}
|
||||
assert arg_types["arg_string"] == UserServiceArgType.STRING
|
||||
assert arg_types["arg_int"] == UserServiceArgType.INT
|
||||
assert arg_types["arg_bool"] == UserServiceArgType.BOOL
|
||||
assert arg_types["arg_float"] == UserServiceArgType.FLOAT
|
||||
# Verify custom_args_service arguments
|
||||
assert len(custom_args_service.args) == 4
|
||||
arg_types = {arg.name: arg.type for arg in custom_args_service.args}
|
||||
assert arg_types["arg_string"] == UserServiceArgType.STRING
|
||||
assert arg_types["arg_int"] == UserServiceArgType.INT
|
||||
assert arg_types["arg_bool"] == UserServiceArgType.BOOL
|
||||
assert arg_types["arg_float"] == UserServiceArgType.FLOAT
|
||||
|
||||
# Test CustomAPIDevice service with arguments
|
||||
client.execute_service(
|
||||
custom_args_service,
|
||||
{
|
||||
"arg_string": "test_string",
|
||||
"arg_int": 456,
|
||||
"arg_bool": True,
|
||||
"arg_float": 78.9,
|
||||
},
|
||||
)
|
||||
await asyncio.wait_for(custom_args_future, timeout=5.0)
|
||||
# Test CustomAPIDevice service with arguments
|
||||
client.execute_service(
|
||||
custom_args_service,
|
||||
{
|
||||
"arg_string": "test_string",
|
||||
"arg_int": 456,
|
||||
"arg_bool": True,
|
||||
"arg_float": 78.9,
|
||||
},
|
||||
)
|
||||
await asyncio.wait_for(custom_args_future, timeout=5.0)
|
||||
|
||||
# Verify array service arguments
|
||||
assert len(custom_arrays_service.args) == 4
|
||||
array_arg_types = {arg.name: arg.type for arg in custom_arrays_service.args}
|
||||
assert array_arg_types["bool_array"] == UserServiceArgType.BOOL_ARRAY
|
||||
assert array_arg_types["int_array"] == UserServiceArgType.INT_ARRAY
|
||||
assert array_arg_types["float_array"] == UserServiceArgType.FLOAT_ARRAY
|
||||
assert array_arg_types["string_array"] == UserServiceArgType.STRING_ARRAY
|
||||
# Verify array service arguments
|
||||
assert len(custom_arrays_service.args) == 4
|
||||
array_arg_types = {arg.name: arg.type for arg in custom_arrays_service.args}
|
||||
assert array_arg_types["bool_array"] == UserServiceArgType.BOOL_ARRAY
|
||||
assert array_arg_types["int_array"] == UserServiceArgType.INT_ARRAY
|
||||
assert array_arg_types["float_array"] == UserServiceArgType.FLOAT_ARRAY
|
||||
assert array_arg_types["string_array"] == UserServiceArgType.STRING_ARRAY
|
||||
|
||||
# Test CustomAPIDevice service with arrays
|
||||
client.execute_service(
|
||||
custom_arrays_service,
|
||||
{
|
||||
"bool_array": [True, False],
|
||||
"int_array": [1, 2, 3],
|
||||
"float_array": [1.1, 2.2],
|
||||
"string_array": ["hello", "world"],
|
||||
},
|
||||
)
|
||||
await asyncio.wait_for(custom_arrays_future, timeout=5.0)
|
||||
# Test CustomAPIDevice service with arrays
|
||||
client.execute_service(
|
||||
custom_arrays_service,
|
||||
{
|
||||
"bool_array": [True, False],
|
||||
"int_array": [1, 2, 3],
|
||||
"float_array": [1.1, 2.2],
|
||||
"string_array": ["hello", "world"],
|
||||
},
|
||||
)
|
||||
await asyncio.wait_for(custom_arrays_future, timeout=5.0)
|
||||
|
||||
@@ -47,9 +47,7 @@ async def test_device_id_in_state(
|
||||
entity_device_mapping[entity.key] = device_ids["Humidity Monitor"]
|
||||
elif entity.name == "Motion Detected":
|
||||
entity_device_mapping[entity.key] = device_ids["Motion Sensor"]
|
||||
elif entity.name == "Temperature Monitor Power":
|
||||
entity_device_mapping[entity.key] = device_ids["Temperature Monitor"]
|
||||
elif entity.name == "Temperature Status":
|
||||
elif entity.name in {"Temperature Monitor Power", "Temperature Status"}:
|
||||
entity_device_mapping[entity.key] = device_ids["Temperature Monitor"]
|
||||
elif entity.name == "Motion Light":
|
||||
entity_device_mapping[entity.key] = device_ids["Motion Sensor"]
|
||||
|
||||
@@ -70,11 +70,13 @@ async def test_scheduler_defer_cancel(
|
||||
test_complete_future.set_result(True)
|
||||
return
|
||||
|
||||
if state.key == test_result_entity.key and not test_result_future.done():
|
||||
# Event type should be "defer_executed_X" where X is the defer number
|
||||
if state.event_type.startswith("defer_executed_"):
|
||||
defer_num = int(state.event_type.split("_")[-1])
|
||||
test_result_future.set_result(defer_num)
|
||||
if (
|
||||
state.key == test_result_entity.key
|
||||
and not test_result_future.done()
|
||||
and state.event_type.startswith("defer_executed_")
|
||||
):
|
||||
defer_num = int(state.event_type.split("_")[-1])
|
||||
test_result_future.set_result(defer_num)
|
||||
|
||||
client.subscribe_states(on_state)
|
||||
|
||||
|
||||
@@ -27,33 +27,33 @@ async def test_scheduler_null_name(
|
||||
if not test_complete_future.done() and test_complete_pattern.search(line):
|
||||
test_complete_future.set_result(True)
|
||||
|
||||
async with run_compiled(yaml_config, line_callback=check_output):
|
||||
async with api_client_connected() as client:
|
||||
# Verify we can connect
|
||||
device_info = await client.device_info()
|
||||
assert device_info is not None
|
||||
assert device_info.name == "scheduler-null-name"
|
||||
async with (
|
||||
run_compiled(yaml_config, line_callback=check_output),
|
||||
api_client_connected() as client,
|
||||
):
|
||||
# Verify we can connect
|
||||
device_info = await client.device_info()
|
||||
assert device_info is not None
|
||||
assert device_info.name == "scheduler-null-name"
|
||||
|
||||
# List services
|
||||
_, services = await asyncio.wait_for(
|
||||
client.list_entities_services(), timeout=5.0
|
||||
# List services
|
||||
_, services = await asyncio.wait_for(
|
||||
client.list_entities_services(), timeout=5.0
|
||||
)
|
||||
|
||||
# Find our test service
|
||||
test_null_name_service = next(
|
||||
(s for s in services if s.name == "test_null_name"), None
|
||||
)
|
||||
assert test_null_name_service is not None, "test_null_name service not found"
|
||||
|
||||
# Execute the test
|
||||
client.execute_service(test_null_name_service, {})
|
||||
|
||||
# Wait for test completion
|
||||
try:
|
||||
await asyncio.wait_for(test_complete_future, timeout=10.0)
|
||||
except TimeoutError:
|
||||
pytest.fail(
|
||||
"Test did not complete within timeout - likely crashed due to NULL name"
|
||||
)
|
||||
|
||||
# Find our test service
|
||||
test_null_name_service = next(
|
||||
(s for s in services if s.name == "test_null_name"), None
|
||||
)
|
||||
assert test_null_name_service is not None, (
|
||||
"test_null_name service not found"
|
||||
)
|
||||
|
||||
# Execute the test
|
||||
client.execute_service(test_null_name_service, {})
|
||||
|
||||
# Wait for test completion
|
||||
try:
|
||||
await asyncio.wait_for(test_complete_future, timeout=10.0)
|
||||
except TimeoutError:
|
||||
pytest.fail(
|
||||
"Test did not complete within timeout - likely crashed due to NULL name"
|
||||
)
|
||||
|
||||
@@ -61,9 +61,10 @@ async def test_scheduler_rapid_cancellation(
|
||||
elif "Total executed:" in line:
|
||||
if match := re.search(r"Total executed: (\d+)", line):
|
||||
test_stats["final_executed"] = int(match.group(1))
|
||||
elif "Implicit cancellations (replaced):" in line:
|
||||
if match := re.search(r"Implicit cancellations \(replaced\): (\d+)", line):
|
||||
test_stats["final_implicit_cancellations"] = int(match.group(1))
|
||||
elif "Implicit cancellations (replaced):" in line and (
|
||||
match := re.search(r"Implicit cancellations \(replaced\): (\d+)", line)
|
||||
):
|
||||
test_stats["final_implicit_cancellations"] = int(match.group(1))
|
||||
|
||||
# Check for crash indicators
|
||||
if any(
|
||||
|
||||
@@ -146,9 +146,11 @@ def test_main_list_components_fails(
|
||||
mock_subprocess_run.side_effect = subprocess.CalledProcessError(1, "cmd")
|
||||
|
||||
# Run main function with mocked argv - should raise
|
||||
with patch("sys.argv", ["determine-jobs.py"]):
|
||||
with pytest.raises(subprocess.CalledProcessError):
|
||||
determine_jobs.main()
|
||||
with (
|
||||
patch("sys.argv", ["determine-jobs.py"]),
|
||||
pytest.raises(subprocess.CalledProcessError),
|
||||
):
|
||||
determine_jobs.main()
|
||||
|
||||
|
||||
def test_main_with_branch_argument(
|
||||
@@ -243,17 +245,21 @@ def test_should_run_integration_tests_with_branch() -> None:
|
||||
|
||||
def test_should_run_integration_tests_component_dependency() -> None:
|
||||
"""Test that integration tests run when components used in fixtures change."""
|
||||
with patch.object(
|
||||
determine_jobs, "changed_files", return_value=["esphome/components/api/api.cpp"]
|
||||
):
|
||||
with patch.object(
|
||||
with (
|
||||
patch.object(
|
||||
determine_jobs,
|
||||
"changed_files",
|
||||
return_value=["esphome/components/api/api.cpp"],
|
||||
),
|
||||
patch.object(
|
||||
determine_jobs, "get_components_from_integration_fixtures"
|
||||
) as mock_fixtures:
|
||||
mock_fixtures.return_value = {"api", "sensor"}
|
||||
with patch.object(determine_jobs, "get_all_dependencies") as mock_deps:
|
||||
mock_deps.return_value = {"api", "sensor", "network"}
|
||||
result = determine_jobs.should_run_integration_tests()
|
||||
assert result is True
|
||||
) as mock_fixtures,
|
||||
):
|
||||
mock_fixtures.return_value = {"api", "sensor"}
|
||||
with patch.object(determine_jobs, "get_all_dependencies") as mock_deps:
|
||||
mock_deps.return_value = {"api", "sensor", "network"}
|
||||
result = determine_jobs.should_run_integration_tests()
|
||||
assert result is True
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -272,12 +278,14 @@ def test_should_run_clang_tidy(
|
||||
expected_result: bool,
|
||||
) -> None:
|
||||
"""Test should_run_clang_tidy function."""
|
||||
with patch.object(determine_jobs, "changed_files", return_value=changed_files):
|
||||
with (
|
||||
patch.object(determine_jobs, "changed_files", return_value=changed_files),
|
||||
patch("subprocess.run") as mock_run,
|
||||
):
|
||||
# Test with hash check returning specific code
|
||||
with patch("subprocess.run") as mock_run:
|
||||
mock_run.return_value = Mock(returncode=check_returncode)
|
||||
result = determine_jobs.should_run_clang_tidy()
|
||||
assert result == expected_result
|
||||
mock_run.return_value = Mock(returncode=check_returncode)
|
||||
result = determine_jobs.should_run_clang_tidy()
|
||||
assert result == expected_result
|
||||
|
||||
|
||||
def test_should_run_clang_tidy_hash_check_exception() -> None:
|
||||
|
||||
Reference in New Issue
Block a user