mirror of
https://github.com/home-assistant/core.git
synced 2025-07-09 22:37:11 +00:00
Add ability to set HA breaking version in report_usage (#130858)
* Add ability to set breaking version in report_usage * Adjust tests * Adjust test * Adjust tests * Rename breaks_in_version => breaks_in_ha_version
This commit is contained in:
parent
5539228ba2
commit
deeb55ac50
@ -1195,9 +1195,9 @@ def _report_non_awaited_platform_forwards(entry: ConfigEntry, what: str) -> None
|
||||
f"calls {what} for integration {entry.domain} with "
|
||||
f"title: {entry.title} and entry_id: {entry.entry_id}, "
|
||||
f"during setup without awaiting {what}, which can cause "
|
||||
"the setup lock to be released before the setup is done. "
|
||||
"This will stop working in Home Assistant 2025.1",
|
||||
"the setup lock to be released before the setup is done",
|
||||
core_behavior=ReportBehavior.LOG,
|
||||
breaks_in_ha_version="2025.1",
|
||||
)
|
||||
|
||||
|
||||
@ -1267,6 +1267,7 @@ class ConfigEntriesFlowManager(
|
||||
# Deprecated in 2024.12, should fail in 2025.12
|
||||
report_usage(
|
||||
f"initialises a {source} flow without a link to the config entry",
|
||||
breaks_in_ha_version="2025.12",
|
||||
)
|
||||
|
||||
flow_id = ulid_util.ulid_now()
|
||||
@ -2321,10 +2322,10 @@ class ConfigEntries:
|
||||
report_usage(
|
||||
"calls async_forward_entry_setup for "
|
||||
f"integration, {entry.domain} with title: {entry.title} "
|
||||
f"and entry_id: {entry.entry_id}, which is deprecated and "
|
||||
"will stop working in Home Assistant 2025.6, "
|
||||
f"and entry_id: {entry.entry_id}, which is deprecated, "
|
||||
"await async_forward_entry_setups instead",
|
||||
core_behavior=ReportBehavior.LOG,
|
||||
breaks_in_ha_version="2025.6",
|
||||
)
|
||||
if not entry.setup_lock.locked():
|
||||
async with entry.setup_lock:
|
||||
@ -3155,11 +3156,11 @@ class OptionsFlow(ConfigEntryBaseFlow):
|
||||
def config_entry(self, value: ConfigEntry) -> None:
|
||||
"""Set the config entry value."""
|
||||
report_usage(
|
||||
"sets option flow config_entry explicitly, which is deprecated "
|
||||
"and will stop working in 2025.12",
|
||||
"sets option flow config_entry explicitly, which is deprecated",
|
||||
core_behavior=ReportBehavior.ERROR,
|
||||
core_integration_behavior=ReportBehavior.ERROR,
|
||||
custom_integration_behavior=ReportBehavior.LOG,
|
||||
breaks_in_ha_version="2025.12",
|
||||
)
|
||||
self._config_entry = value
|
||||
|
||||
|
@ -181,6 +181,7 @@ class ReportBehavior(enum.Enum):
|
||||
def report_usage(
|
||||
what: str,
|
||||
*,
|
||||
breaks_in_ha_version: str | None = None,
|
||||
core_behavior: ReportBehavior = ReportBehavior.ERROR,
|
||||
core_integration_behavior: ReportBehavior = ReportBehavior.LOG,
|
||||
custom_integration_behavior: ReportBehavior = ReportBehavior.LOG,
|
||||
@ -189,17 +190,25 @@ def report_usage(
|
||||
) -> None:
|
||||
"""Report incorrect code usage.
|
||||
|
||||
Similar to `report` but allows more fine-grained reporting.
|
||||
:param what: will be wrapped with "Detected that integration 'integration' {what}.
|
||||
Please create a bug report at https://..."
|
||||
:param breaks_in_ha_version: if set, the report will be adjusted to specify the
|
||||
breaking version
|
||||
"""
|
||||
try:
|
||||
integration_frame = get_integration_frame(
|
||||
exclude_integrations=exclude_integrations
|
||||
)
|
||||
except MissingIntegrationFrame as err:
|
||||
msg = f"Detected code that {what}. Please report this issue."
|
||||
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)
|
||||
return
|
||||
|
||||
@ -209,12 +218,17 @@ def report_usage(
|
||||
|
||||
if integration_behavior is not ReportBehavior.IGNORE:
|
||||
_report_integration(
|
||||
what, integration_frame, level, integration_behavior is ReportBehavior.ERROR
|
||||
what,
|
||||
breaks_in_ha_version,
|
||||
integration_frame,
|
||||
level,
|
||||
integration_behavior is ReportBehavior.ERROR,
|
||||
)
|
||||
|
||||
|
||||
def _report_integration(
|
||||
what: str,
|
||||
breaks_in_ha_version: str | None,
|
||||
integration_frame: IntegrationFrame,
|
||||
level: int = logging.WARNING,
|
||||
error: bool = False,
|
||||
@ -237,13 +251,16 @@ def _report_integration(
|
||||
integration_type = "custom " if integration_frame.custom_integration else ""
|
||||
_LOGGER.log(
|
||||
level,
|
||||
"Detected that %sintegration '%s' %s at %s, line %s: %s, please %s",
|
||||
"Detected that %sintegration '%s' %s at %s, line %s: %s. %s %s",
|
||||
integration_type,
|
||||
integration_frame.integration,
|
||||
what,
|
||||
integration_frame.relative_filename,
|
||||
integration_frame.line_number,
|
||||
integration_frame.line,
|
||||
f"This will stop working in Home Assistant {breaks_in_ha_version}, please"
|
||||
if breaks_in_ha_version
|
||||
else "Please",
|
||||
report_issue,
|
||||
)
|
||||
if not error:
|
||||
@ -253,7 +270,7 @@ def _report_integration(
|
||||
f"'{integration_frame.integration}' {what} at "
|
||||
f"{integration_frame.relative_filename}, line "
|
||||
f"{integration_frame.line_number}: {integration_frame.line}. "
|
||||
f"Please {report_issue}."
|
||||
f"Please {report_issue}"
|
||||
)
|
||||
|
||||
|
||||
|
@ -286,8 +286,8 @@ async def test_warning_close_session_integration(
|
||||
await session.close()
|
||||
assert (
|
||||
"Detected that integration 'hue' closes the Home Assistant aiohttp session at "
|
||||
"homeassistant/components/hue/light.py, line 23: await session.close(), "
|
||||
"please create a bug report at https://github.com/home-assistant/core/issues?"
|
||||
"homeassistant/components/hue/light.py, line 23: await session.close(). "
|
||||
"Please create a bug report at https://github.com/home-assistant/core/issues?"
|
||||
"q=is%3Aopen+is%3Aissue+label%3A%22integration%3A+hue%22"
|
||||
) in caplog.text
|
||||
|
||||
@ -330,8 +330,8 @@ async def test_warning_close_session_custom(
|
||||
await session.close()
|
||||
assert (
|
||||
"Detected that custom integration 'hue' closes the Home Assistant aiohttp "
|
||||
"session at custom_components/hue/light.py, line 23: await session.close(), "
|
||||
"please report it to the author of the 'hue' custom integration"
|
||||
"session at custom_components/hue/light.py, line 23: await session.close(). "
|
||||
"Please report it to the author of the 'hue' custom integration"
|
||||
) in caplog.text
|
||||
|
||||
|
||||
|
@ -4895,7 +4895,7 @@ async def test_track_state_change_deprecated(
|
||||
assert (
|
||||
"Detected code that calls `async_track_state_change` instead "
|
||||
"of `async_track_state_change_event` which is deprecated and "
|
||||
"will be removed in Home Assistant 2025.5. Please report this issue."
|
||||
"will be removed in Home Assistant 2025.5. Please report this issue"
|
||||
) in caplog.text
|
||||
|
||||
|
||||
@ -4946,7 +4946,7 @@ async def test_async_track_template_no_hass_deprecated(
|
||||
"""Test async_track_template with a template without hass is deprecated."""
|
||||
message = (
|
||||
"Detected code that calls async_track_template_result with template without "
|
||||
"hass, which will stop working in HA Core 2025.10. Please report this issue."
|
||||
"hass, which will stop working in HA Core 2025.10. Please report this issue"
|
||||
)
|
||||
|
||||
async_track_template(hass, Template("blah"), lambda x, y, z: None)
|
||||
@ -4964,7 +4964,7 @@ async def test_async_track_template_result_no_hass_deprecated(
|
||||
"""Test async_track_template_result with a template without hass is deprecated."""
|
||||
message = (
|
||||
"Detected code that calls async_track_template_result with template without "
|
||||
"hass, which will stop working in HA Core 2025.10. Please report this issue."
|
||||
"hass, which will stop working in HA Core 2025.10. Please report this issue"
|
||||
)
|
||||
|
||||
async_track_template_result(
|
||||
|
@ -261,8 +261,8 @@ async def test_prevent_flooding(
|
||||
|
||||
expected_message = (
|
||||
f"Detected that integration '{integration}' {what} at {filename}, line "
|
||||
f"{mock_integration_frame.lineno}: {mock_integration_frame.line}, "
|
||||
f"please create a bug report at https://github.com/home-assistant/core/issues?"
|
||||
f"{mock_integration_frame.lineno}: {mock_integration_frame.line}. "
|
||||
f"Please create a bug report at https://github.com/home-assistant/core/issues?"
|
||||
f"q=is%3Aopen+is%3Aissue+label%3A%22integration%3A+{integration}%22"
|
||||
)
|
||||
|
||||
@ -279,6 +279,28 @@ async def test_prevent_flooding(
|
||||
assert len(frame._REPORTED_INTEGRATIONS) == 1
|
||||
|
||||
|
||||
@patch.object(frame, "_REPORTED_INTEGRATIONS", set())
|
||||
async def test_breaks_in_ha_version(
|
||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, mock_integration_frame: Mock
|
||||
) -> None:
|
||||
"""Test to ensure a report is only written once to the log."""
|
||||
|
||||
what = "accessed hi instead of hello"
|
||||
integration = "hue"
|
||||
filename = "homeassistant/components/hue/light.py"
|
||||
|
||||
expected_message = (
|
||||
f"Detected that integration '{integration}' {what} at {filename}, line "
|
||||
f"{mock_integration_frame.lineno}: {mock_integration_frame.line}. "
|
||||
f"This will stop working in Home Assistant 2024.11, please create a bug "
|
||||
"report at https://github.com/home-assistant/core/issues?"
|
||||
f"q=is%3Aopen+is%3Aissue+label%3A%22integration%3A+{integration}%22"
|
||||
)
|
||||
|
||||
frame.report_usage(what, breaks_in_ha_version="2024.11")
|
||||
assert expected_message in caplog.text
|
||||
|
||||
|
||||
async def test_report_missing_integration_frame(
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
|
@ -138,8 +138,8 @@ async def test_warning_close_session_integration(
|
||||
|
||||
assert (
|
||||
"Detected that integration 'hue' closes the Home Assistant httpx client at "
|
||||
"homeassistant/components/hue/light.py, line 23: await session.aclose(), "
|
||||
"please create a bug report at https://github.com/home-assistant/core/issues?"
|
||||
"homeassistant/components/hue/light.py, line 23: await session.aclose(). "
|
||||
"Please create a bug report at https://github.com/home-assistant/core/issues?"
|
||||
"q=is%3Aopen+is%3Aissue+label%3A%22integration%3A+hue%22"
|
||||
) in caplog.text
|
||||
|
||||
@ -182,6 +182,6 @@ async def test_warning_close_session_custom(
|
||||
await httpx_session.aclose()
|
||||
assert (
|
||||
"Detected that custom integration 'hue' closes the Home Assistant httpx client "
|
||||
"at custom_components/hue/light.py, line 23: await session.aclose(), "
|
||||
"please report it to the author of the 'hue' custom integration"
|
||||
"at custom_components/hue/light.py, line 23: await session.aclose(). "
|
||||
"Please report it to the author of the 'hue' custom integration"
|
||||
) in caplog.text
|
||||
|
@ -629,7 +629,7 @@ async def test_async_config_entry_first_refresh_invalid_state(
|
||||
match="Detected code that uses `async_config_entry_first_refresh`, which "
|
||||
"is only supported when entry state is ConfigEntryState.SETUP_IN_PROGRESS, "
|
||||
"but it is in state ConfigEntryState.NOT_LOADED. This will stop working "
|
||||
"in Home Assistant 2025.11. Please report this issue.",
|
||||
"in Home Assistant 2025.11. Please report this issue",
|
||||
):
|
||||
await crd.async_config_entry_first_refresh()
|
||||
|
||||
@ -666,7 +666,7 @@ async def test_async_config_entry_first_refresh_no_entry(hass: HomeAssistant) ->
|
||||
RuntimeError,
|
||||
match="Detected code that uses `async_config_entry_first_refresh`, "
|
||||
"which is only supported for coordinators with a config entry and will "
|
||||
"stop working in Home Assistant 2025.11. Please report this issue.",
|
||||
"stop working in Home Assistant 2025.11. Please report this issue",
|
||||
):
|
||||
await crd.async_config_entry_first_refresh()
|
||||
|
||||
|
@ -1115,8 +1115,8 @@ async def test_async_forward_entry_setup_deprecated(
|
||||
assert (
|
||||
"Detected code that calls async_forward_entry_setup for integration, "
|
||||
f"original with title: Mock Title and entry_id: {entry_id}, "
|
||||
"which is deprecated and will stop working in Home Assistant 2025.6, "
|
||||
"await async_forward_entry_setups instead. Please report this issue."
|
||||
"which is deprecated, await async_forward_entry_setups instead. "
|
||||
"This will stop working in Home Assistant 2025.6, please report this issue"
|
||||
) in caplog.text
|
||||
|
||||
|
||||
@ -4802,7 +4802,7 @@ async def test_reauth_reconfigure_missing_entry(
|
||||
with pytest.raises(
|
||||
RuntimeError,
|
||||
match=f"Detected code that initialises a {source} flow without a link "
|
||||
"to the config entry. Please report this issue.",
|
||||
"to the config entry. Please report this issue",
|
||||
):
|
||||
await manager.flow.async_init("test", context={"source": source})
|
||||
await hass.async_block_till_done()
|
||||
@ -6244,7 +6244,7 @@ async def test_non_awaited_async_forward_entry_setups(
|
||||
"test with title: Mock Title and entry_id: test2, during setup without "
|
||||
"awaiting async_forward_entry_setups, which can cause the setup lock "
|
||||
"to be released before the setup is done. This will stop working in "
|
||||
"Home Assistant 2025.1. Please report this issue."
|
||||
"Home Assistant 2025.1, please report this issue"
|
||||
) in caplog.text
|
||||
|
||||
|
||||
@ -6316,7 +6316,7 @@ async def test_non_awaited_async_forward_entry_setup(
|
||||
"test with title: Mock Title and entry_id: test2, during setup without "
|
||||
"awaiting async_forward_entry_setup, which can cause the setup lock "
|
||||
"to be released before the setup is done. This will stop working in "
|
||||
"Home Assistant 2025.1. Please report this issue."
|
||||
"Home Assistant 2025.1, please report this issue"
|
||||
) in caplog.text
|
||||
|
||||
|
||||
@ -7560,8 +7560,10 @@ async def test_options_flow_deprecated_config_entry_setter(
|
||||
|
||||
assert (
|
||||
"Detected that custom integration 'my_integration' sets option flow "
|
||||
"config_entry explicitly, which is deprecated and will stop working "
|
||||
"in 2025.12" in caplog.text
|
||||
"config_entry explicitly, which is deprecated at "
|
||||
"custom_components/my_integration/light.py, line 23: "
|
||||
"self.light.is_on. This will stop working in Home Assistant 2025.12, please "
|
||||
"create a bug report at " in caplog.text
|
||||
)
|
||||
|
||||
|
||||
|
@ -3310,7 +3310,7 @@ async def test_thread_safety_message(hass: HomeAssistant) -> None:
|
||||
"which may cause Home Assistant to crash or data to corrupt. For more "
|
||||
"information, see "
|
||||
"https://developers.home-assistant.io/docs/asyncio_thread_safety/#test"
|
||||
". Please report this issue.",
|
||||
". Please report this issue",
|
||||
),
|
||||
):
|
||||
await hass.async_add_executor_job(hass.verify_event_loop_thread, "test")
|
||||
|
@ -1077,7 +1077,7 @@ async def test_set_time_zone_deprecated(hass: HomeAssistant) -> None:
|
||||
match=re.escape(
|
||||
"Detected code that set the time zone using set_time_zone instead of "
|
||||
"async_set_time_zone which will stop working in Home Assistant 2025.6. "
|
||||
"Please report this issue.",
|
||||
"Please report this issue",
|
||||
),
|
||||
):
|
||||
await hass.config.set_time_zone("America/New_York")
|
||||
|
@ -140,7 +140,7 @@ async def test_create_eager_task_from_thread(hass: HomeAssistant) -> None:
|
||||
with pytest.raises(
|
||||
RuntimeError,
|
||||
match=(
|
||||
"Detected code that attempted to create an asyncio task from a thread. Please report this issue."
|
||||
"Detected code that attempted to create an asyncio task from a thread. Please report this issue"
|
||||
),
|
||||
):
|
||||
await hass.async_add_executor_job(create_task)
|
||||
|
Loading…
x
Reference in New Issue
Block a user