mirror of
https://github.com/home-assistant/core.git
synced 2025-07-16 09:47:13 +00:00
Prioritize integration_domain passed to helper.frame.report_usage (#139819)
* Prioritize integration_domain passed to helper.frame.report_usage * Update tests * Update tests * Improve docstring * Rename according to suggestion
This commit is contained in:
parent
dc4464a347
commit
c51e644203
@ -180,8 +180,8 @@ def report_usage(
|
|||||||
breaking version
|
breaking version
|
||||||
:param exclude_integrations: skip specified integration when reviewing the stack.
|
:param exclude_integrations: skip specified integration when reviewing the stack.
|
||||||
If no integration is found, the core behavior will be applied
|
If no integration is found, the core behavior will be applied
|
||||||
:param integration_domain: fallback for identifying the integration if the
|
:param integration_domain: domain of the integration causing the issue. If None, the
|
||||||
frame is not found
|
stack frame will be searched to identify the integration causing the issue.
|
||||||
"""
|
"""
|
||||||
if (hass := _hass.hass) is None:
|
if (hass := _hass.hass) is None:
|
||||||
raise RuntimeError("Frame helper not set up")
|
raise RuntimeError("Frame helper not set up")
|
||||||
@ -220,13 +220,9 @@ def _report_usage(
|
|||||||
|
|
||||||
Must be called from the event loop.
|
Must be called from the event loop.
|
||||||
"""
|
"""
|
||||||
try:
|
if integration_domain:
|
||||||
integration_frame = get_integration_frame(
|
|
||||||
exclude_integrations=exclude_integrations
|
|
||||||
)
|
|
||||||
except MissingIntegrationFrame as err:
|
|
||||||
if integration := async_get_issue_integration(hass, integration_domain):
|
if integration := async_get_issue_integration(hass, integration_domain):
|
||||||
_report_integration_domain(
|
_report_usage_integration_domain(
|
||||||
hass,
|
hass,
|
||||||
what,
|
what,
|
||||||
breaks_in_ha_version,
|
breaks_in_ha_version,
|
||||||
@ -236,16 +232,15 @@ def _report_usage(
|
|||||||
level,
|
level,
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
msg = f"Detected code that {what}. Please report this issue"
|
_report_usage_no_integration(what, core_behavior, breaks_in_ha_version, None)
|
||||||
if core_behavior is ReportBehavior.ERROR:
|
return
|
||||||
raise RuntimeError(msg) from err
|
|
||||||
if core_behavior is ReportBehavior.LOG:
|
try:
|
||||||
if breaks_in_ha_version:
|
integration_frame = get_integration_frame(
|
||||||
msg = (
|
exclude_integrations=exclude_integrations
|
||||||
f"Detected code that {what}. This will stop working in Home "
|
)
|
||||||
f"Assistant {breaks_in_ha_version}, please report this issue"
|
except MissingIntegrationFrame as err:
|
||||||
)
|
_report_usage_no_integration(what, core_behavior, breaks_in_ha_version, err)
|
||||||
_LOGGER.warning(msg, stack_info=True)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
integration_behavior = core_integration_behavior
|
integration_behavior = core_integration_behavior
|
||||||
@ -253,7 +248,7 @@ def _report_usage(
|
|||||||
integration_behavior = custom_integration_behavior
|
integration_behavior = custom_integration_behavior
|
||||||
|
|
||||||
if integration_behavior is not ReportBehavior.IGNORE:
|
if integration_behavior is not ReportBehavior.IGNORE:
|
||||||
_report_integration_frame(
|
_report_usage_integration_frame(
|
||||||
hass,
|
hass,
|
||||||
what,
|
what,
|
||||||
breaks_in_ha_version,
|
breaks_in_ha_version,
|
||||||
@ -263,7 +258,7 @@ def _report_usage(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _report_integration_domain(
|
def _report_usage_integration_domain(
|
||||||
hass: HomeAssistant | None,
|
hass: HomeAssistant | None,
|
||||||
what: str,
|
what: str,
|
||||||
breaks_in_ha_version: str | None,
|
breaks_in_ha_version: str | None,
|
||||||
@ -313,7 +308,7 @@ def _report_integration_domain(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _report_integration_frame(
|
def _report_usage_integration_frame(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
what: str,
|
what: str,
|
||||||
breaks_in_ha_version: str | None,
|
breaks_in_ha_version: str | None,
|
||||||
@ -362,6 +357,29 @@ def _report_integration_frame(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _report_usage_no_integration(
|
||||||
|
what: str,
|
||||||
|
core_behavior: ReportBehavior,
|
||||||
|
breaks_in_ha_version: str | None,
|
||||||
|
err: MissingIntegrationFrame | None,
|
||||||
|
) -> None:
|
||||||
|
"""Report incorrect usage without an integration.
|
||||||
|
|
||||||
|
This could happen because the offending call happened outside of an integration,
|
||||||
|
or because the integration could not be identified.
|
||||||
|
"""
|
||||||
|
msg = f"Detected code that {what}. Please report this issue"
|
||||||
|
if core_behavior is ReportBehavior.ERROR:
|
||||||
|
raise RuntimeError(msg) from err
|
||||||
|
if core_behavior is ReportBehavior.LOG:
|
||||||
|
if breaks_in_ha_version:
|
||||||
|
msg = (
|
||||||
|
f"Detected code that {what}. This will stop working in Home "
|
||||||
|
f"Assistant {breaks_in_ha_version}, please report this issue"
|
||||||
|
)
|
||||||
|
_LOGGER.warning(msg, stack_info=True)
|
||||||
|
|
||||||
|
|
||||||
def warn_use[_CallableT: Callable](func: _CallableT, what: str) -> _CallableT:
|
def warn_use[_CallableT: Callable](func: _CallableT, what: str) -> _CallableT:
|
||||||
"""Mock a function to warn when it was about to be used."""
|
"""Mock a function to warn when it was about to be used."""
|
||||||
if asyncio.iscoroutinefunction(func):
|
if asyncio.iscoroutinefunction(func):
|
||||||
|
@ -292,13 +292,13 @@ async def test_alarm_control_panel_log_deprecated_state_warning_using_state_prop
|
|||||||
assert state is not None
|
assert state is not None
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
"Detected that custom integration 'alarm_control_panel' is setting state"
|
"Detected that custom integration 'test' is setting state "
|
||||||
" directly. Entity None (<class 'tests.components.alarm_control_panel."
|
"directly. Entity None (<class 'tests.components.alarm_control_panel."
|
||||||
"test_init.test_alarm_control_panel_log_deprecated_state_warning_using"
|
"test_init.test_alarm_control_panel_log_deprecated_state_warning_using"
|
||||||
"_state_prop.<locals>.MockLegacyAlarmControlPanel'>) should implement"
|
"_state_prop.<locals>.MockLegacyAlarmControlPanel'>) should implement"
|
||||||
" the 'alarm_state' property and return its state using the AlarmControlPanelState"
|
" the 'alarm_state' property and return its state using the AlarmControlPanelState"
|
||||||
" enum at test_init.py, line 123: yield. This will stop working in Home Assistant"
|
" enum. This will stop working in Home Assistant 2025.11, please report it to"
|
||||||
" 2025.11, please create a bug report at" in caplog.text
|
" the author of the 'test' custom integration" in caplog.text
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -345,6 +345,7 @@ async def test_alarm_control_panel_log_deprecated_state_warning_using_attr_state
|
|||||||
async_setup_entry=help_async_setup_entry_init,
|
async_setup_entry=help_async_setup_entry_init,
|
||||||
async_unload_entry=help_async_unload_entry,
|
async_unload_entry=help_async_unload_entry,
|
||||||
),
|
),
|
||||||
|
built_in=False,
|
||||||
)
|
)
|
||||||
setup_test_component_platform(
|
setup_test_component_platform(
|
||||||
hass, ALARM_CONTROL_PANEL_DOMAIN, [entity], from_config_entry=True
|
hass, ALARM_CONTROL_PANEL_DOMAIN, [entity], from_config_entry=True
|
||||||
@ -355,7 +356,7 @@ async def test_alarm_control_panel_log_deprecated_state_warning_using_attr_state
|
|||||||
assert state is not None
|
assert state is not None
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
"Detected that custom integration 'alarm_control_panel' is setting state directly."
|
"Detected that custom integration 'test' is setting state directly."
|
||||||
not in caplog.text
|
not in caplog.text
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -364,14 +365,14 @@ async def test_alarm_control_panel_log_deprecated_state_warning_using_attr_state
|
|||||||
)
|
)
|
||||||
|
|
||||||
assert (
|
assert (
|
||||||
"Detected that custom integration 'alarm_control_panel' is setting state directly."
|
"Detected that custom integration 'test' is setting state directly."
|
||||||
" Entity alarm_control_panel.test_alarm_control_panel"
|
" Entity alarm_control_panel.test_alarm_control_panel"
|
||||||
" (<class 'tests.components.alarm_control_panel.test_init."
|
" (<class 'tests.components.alarm_control_panel.test_init."
|
||||||
"test_alarm_control_panel_log_deprecated_state_warning_using_attr_state_attr."
|
"test_alarm_control_panel_log_deprecated_state_warning_using_attr_state_attr."
|
||||||
"<locals>.MockLegacyAlarmControlPanel'>) should implement the 'alarm_state' property"
|
"<locals>.MockLegacyAlarmControlPanel'>) should implement the 'alarm_state' property"
|
||||||
" and return its state using the AlarmControlPanelState enum at test_init.py, line 123:"
|
" and return its state using the AlarmControlPanelState enum. "
|
||||||
" yield. This will stop working in Home Assistant 2025.11,"
|
"This will stop working in Home Assistant 2025.11, please report "
|
||||||
" please create a bug report at" in caplog.text
|
"it to the author of the 'test' custom integration" in caplog.text
|
||||||
)
|
)
|
||||||
caplog.clear()
|
caplog.clear()
|
||||||
await help_test_async_alarm_control_panel_service(
|
await help_test_async_alarm_control_panel_service(
|
||||||
@ -379,7 +380,7 @@ async def test_alarm_control_panel_log_deprecated_state_warning_using_attr_state
|
|||||||
)
|
)
|
||||||
# Test we only log once
|
# Test we only log once
|
||||||
assert (
|
assert (
|
||||||
"Detected that custom integration 'alarm_control_panel' is setting state directly."
|
"Detected that custom integration 'test' is setting state directly."
|
||||||
not in caplog.text
|
not in caplog.text
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -428,6 +429,7 @@ async def test_alarm_control_panel_deprecated_state_does_not_break_state(
|
|||||||
async_setup_entry=help_async_setup_entry_init,
|
async_setup_entry=help_async_setup_entry_init,
|
||||||
async_unload_entry=help_async_unload_entry,
|
async_unload_entry=help_async_unload_entry,
|
||||||
),
|
),
|
||||||
|
built_in=False,
|
||||||
)
|
)
|
||||||
setup_test_component_platform(
|
setup_test_component_platform(
|
||||||
hass, ALARM_CONTROL_PANEL_DOMAIN, [entity], from_config_entry=True
|
hass, ALARM_CONTROL_PANEL_DOMAIN, [entity], from_config_entry=True
|
||||||
|
@ -356,6 +356,7 @@ async def test_vacuum_log_deprecated_state_warning_using_state_prop(
|
|||||||
async_setup_entry=help_async_setup_entry_init,
|
async_setup_entry=help_async_setup_entry_init,
|
||||||
async_unload_entry=help_async_unload_entry,
|
async_unload_entry=help_async_unload_entry,
|
||||||
),
|
),
|
||||||
|
built_in=False,
|
||||||
)
|
)
|
||||||
setup_test_component_platform(hass, VACUUM_DOMAIN, [entity], from_config_entry=True)
|
setup_test_component_platform(hass, VACUUM_DOMAIN, [entity], from_config_entry=True)
|
||||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
@ -399,6 +400,7 @@ async def test_vacuum_log_deprecated_state_warning_using_attr_state_attr(
|
|||||||
async_setup_entry=help_async_setup_entry_init,
|
async_setup_entry=help_async_setup_entry_init,
|
||||||
async_unload_entry=help_async_unload_entry,
|
async_unload_entry=help_async_unload_entry,
|
||||||
),
|
),
|
||||||
|
built_in=False,
|
||||||
)
|
)
|
||||||
setup_test_component_platform(hass, VACUUM_DOMAIN, [entity], from_config_entry=True)
|
setup_test_component_platform(hass, VACUUM_DOMAIN, [entity], from_config_entry=True)
|
||||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
@ -463,6 +465,7 @@ async def test_vacuum_deprecated_state_does_not_break_state(
|
|||||||
async_setup_entry=help_async_setup_entry_init,
|
async_setup_entry=help_async_setup_entry_init,
|
||||||
async_unload_entry=help_async_unload_entry,
|
async_unload_entry=help_async_unload_entry,
|
||||||
),
|
),
|
||||||
|
built_in=False,
|
||||||
)
|
)
|
||||||
setup_test_component_platform(hass, VACUUM_DOMAIN, [entity], from_config_entry=True)
|
setup_test_component_platform(hass, VACUUM_DOMAIN, [entity], from_config_entry=True)
|
||||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
|
@ -538,21 +538,21 @@ async def test_report_error_if_integration(
|
|||||||
False,
|
False,
|
||||||
id="custom integration",
|
id="custom integration",
|
||||||
),
|
),
|
||||||
# Assert integration found in stack frame has priority over integration_domain
|
# Assert integration_domain has priority over integration found in stack frame
|
||||||
pytest.param(
|
pytest.param(
|
||||||
"core_integration_behavior",
|
"core_integration_behavior",
|
||||||
"sensor",
|
"sensor",
|
||||||
"homeassistant/components/hue",
|
"homeassistant/components/hue",
|
||||||
"that integration 'hue'",
|
"that integration 'sensor'",
|
||||||
False,
|
False,
|
||||||
id="core integration stack mismatch",
|
id="core integration stack mismatch",
|
||||||
),
|
),
|
||||||
# Assert integration found in stack frame has priority over integration_domain
|
# Assert integration_domain has priority over integration found in stack frame
|
||||||
pytest.param(
|
pytest.param(
|
||||||
"custom_integration_behavior",
|
"custom_integration_behavior",
|
||||||
"test_package",
|
"test_package",
|
||||||
"custom_components/hue",
|
"custom_components/hue",
|
||||||
"that custom integration 'hue'",
|
"that custom integration 'test_package'",
|
||||||
False,
|
False,
|
||||||
id="custom integration stack mismatch",
|
id="custom integration stack mismatch",
|
||||||
),
|
),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user