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:
epenet 2024-11-20 21:41:57 +01:00 committed by GitHub
parent 5539228ba2
commit deeb55ac50
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 78 additions and 36 deletions

View File

@ -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

View File

@ -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}"
)

View File

@ -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

View File

@ -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(

View File

@ -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:

View File

@ -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

View File

@ -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()

View File

@ -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
)

View File

@ -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")

View File

@ -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")

View File

@ -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)