Deprecate the dynamic package sensors in seventeentrack (#116102)
* Add deprecation comments for the dynamic package sensors * Add deprecation comments for the dynamic package sensors * Add deprecation comments for the dynamic package sensors add more information when retrieving packages from service call * Add deprecation comments for the dynamic package sensors update deprecation comment * 1. 17Track repair flow 2. update deprecation comment * 1. remove description_placeholders 2. 2024.8 deprecated * Update homeassistant/components/seventeentrack/repairs.py Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * 1. extract deprecated to constant 2. fix types 3. check for issue_id 4. add listener only when not deprecated 5. update which service to call * Update homeassistant/components/seventeentrack/strings.json Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * Update homeassistant/components/seventeentrack/repairs.py Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * 1. move deprecate_sensor_issue to where needed 2. add entry_id to issue_id 3. use constant where needed * update breaks in ha version * Update homeassistant/components/seventeentrack/strings.json * Remove obsolete tests * Fix --------- Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
parent
a66631f1ee
commit
b6609fa77c
8 changed files with 221 additions and 7 deletions
|
@ -29,10 +29,14 @@ from homeassistant.util import slugify
|
|||
|
||||
from .const import (
|
||||
ATTR_CONFIG_ENTRY_ID,
|
||||
ATTR_DESTINATION_COUNTRY,
|
||||
ATTR_INFO_TEXT,
|
||||
ATTR_ORIGIN_COUNTRY,
|
||||
ATTR_PACKAGE_STATE,
|
||||
ATTR_PACKAGE_TYPE,
|
||||
ATTR_STATUS,
|
||||
ATTR_TIMESTAMP,
|
||||
ATTR_TRACKING_INFO_LANGUAGE,
|
||||
ATTR_TRACKING_NUMBER,
|
||||
DOMAIN,
|
||||
SERVICE_GET_PACKAGES,
|
||||
|
@ -104,6 +108,10 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||
return {
|
||||
"packages": [
|
||||
{
|
||||
ATTR_DESTINATION_COUNTRY: package.destination_country,
|
||||
ATTR_ORIGIN_COUNTRY: package.origin_country,
|
||||
ATTR_PACKAGE_TYPE: package.package_type,
|
||||
ATTR_TRACKING_INFO_LANGUAGE: package.tracking_info_language,
|
||||
ATTR_TRACKING_NUMBER: package.tracking_number,
|
||||
ATTR_LOCATION: package.location,
|
||||
ATTR_STATUS: package.status,
|
||||
|
|
|
@ -45,3 +45,5 @@ SERVICE_GET_PACKAGES = "get_packages"
|
|||
|
||||
ATTR_PACKAGE_STATE = "package_state"
|
||||
ATTR_CONFIG_ENTRY_ID = "config_entry_id"
|
||||
|
||||
DEPRECATED_KEY = "deprecated"
|
||||
|
|
49
homeassistant/components/seventeentrack/repairs.py
Normal file
49
homeassistant/components/seventeentrack/repairs.py
Normal file
|
@ -0,0 +1,49 @@
|
|||
"""Repairs for the SeventeenTrack integration."""
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.repairs import ConfirmRepairFlow, RepairsFlow
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.data_entry_flow import FlowResult
|
||||
|
||||
from .const import DEPRECATED_KEY
|
||||
|
||||
|
||||
class SensorDeprecationRepairFlow(RepairsFlow):
|
||||
"""Handler for an issue fixing flow."""
|
||||
|
||||
def __init__(self, entry: ConfigEntry) -> None:
|
||||
"""Create flow."""
|
||||
self.entry = entry
|
||||
|
||||
async def async_step_init(
|
||||
self, user_input: dict[str, str] | None = None
|
||||
) -> FlowResult:
|
||||
"""Handle the first step of a fix flow."""
|
||||
return await self.async_step_confirm()
|
||||
|
||||
async def async_step_confirm(
|
||||
self, user_input: dict[str, str] | None = None
|
||||
) -> FlowResult:
|
||||
"""Handle the confirm step of a fix flow."""
|
||||
if user_input is not None:
|
||||
data = {**self.entry.data, DEPRECATED_KEY: True}
|
||||
self.hass.config_entries.async_update_entry(self.entry, data=data)
|
||||
return self.async_create_entry(data={})
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="confirm",
|
||||
data_schema=vol.Schema({}),
|
||||
)
|
||||
|
||||
|
||||
async def async_create_fix_flow(
|
||||
hass: HomeAssistant, issue_id: str, data: dict
|
||||
) -> RepairsFlow:
|
||||
"""Create flow."""
|
||||
if issue_id.startswith("deprecate_sensor_"):
|
||||
entry = hass.config_entries.async_get_entry(data["entry_id"])
|
||||
assert entry
|
||||
return SensorDeprecationRepairFlow(entry)
|
||||
return ConfirmRepairFlow()
|
|
@ -20,7 +20,11 @@ from homeassistant.const import (
|
|||
)
|
||||
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant, callback
|
||||
from homeassistant.data_entry_flow import FlowResultType
|
||||
from homeassistant.helpers import config_validation as cv, entity_registry as er
|
||||
from homeassistant.helpers import (
|
||||
config_validation as cv,
|
||||
entity_registry as er,
|
||||
issue_registry as ir,
|
||||
)
|
||||
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
|
||||
|
@ -41,6 +45,7 @@ from .const import (
|
|||
ATTRIBUTION,
|
||||
CONF_SHOW_ARCHIVED,
|
||||
CONF_SHOW_DELIVERED,
|
||||
DEPRECATED_KEY,
|
||||
DOMAIN,
|
||||
LOGGER,
|
||||
NOTIFICATION_DELIVERED_MESSAGE,
|
||||
|
@ -113,8 +118,12 @@ async def async_setup_entry(
|
|||
coordinator: SeventeenTrackCoordinator = hass.data[DOMAIN][config_entry.entry_id]
|
||||
previous_tracking_numbers: set[str] = set()
|
||||
|
||||
# This has been deprecated in 2024.8, will be removed in 2025.2
|
||||
@callback
|
||||
def _async_create_remove_entities():
|
||||
if config_entry.data.get(DEPRECATED_KEY):
|
||||
remove_packages(hass, coordinator.account_id, previous_tracking_numbers)
|
||||
return
|
||||
live_tracking_numbers = set(coordinator.data.live_packages.keys())
|
||||
|
||||
new_tracking_numbers = live_tracking_numbers - previous_tracking_numbers
|
||||
|
@ -157,11 +166,12 @@ async def async_setup_entry(
|
|||
for status, summary_data in coordinator.data.summary.items()
|
||||
)
|
||||
|
||||
_async_create_remove_entities()
|
||||
|
||||
config_entry.async_on_unload(
|
||||
coordinator.async_add_listener(_async_create_remove_entities)
|
||||
)
|
||||
if not config_entry.data.get(DEPRECATED_KEY):
|
||||
deprecate_sensor_issue(hass, config_entry.entry_id)
|
||||
_async_create_remove_entities()
|
||||
config_entry.async_on_unload(
|
||||
coordinator.async_add_listener(_async_create_remove_entities)
|
||||
)
|
||||
|
||||
|
||||
class SeventeenTrackSensor(CoordinatorEntity[SeventeenTrackCoordinator], SensorEntity):
|
||||
|
@ -206,6 +216,7 @@ class SeventeenTrackSummarySensor(SeventeenTrackSensor):
|
|||
"""Return the state of the sensor."""
|
||||
return self.coordinator.data.summary[self._status]["quantity"]
|
||||
|
||||
# This has been deprecated in 2024.8, will be removed in 2025.2
|
||||
@property
|
||||
def extra_state_attributes(self) -> dict[str, Any] | None:
|
||||
"""Return the state attributes."""
|
||||
|
@ -225,6 +236,7 @@ class SeventeenTrackSummarySensor(SeventeenTrackSensor):
|
|||
}
|
||||
|
||||
|
||||
# The dynamic package sensors have been replaced by the seventeentrack.get_packages service
|
||||
class SeventeenTrackPackageSensor(SeventeenTrackSensor):
|
||||
"""Define an individual package sensor."""
|
||||
|
||||
|
@ -298,3 +310,20 @@ def notify_delivered(hass: HomeAssistant, friendly_name: str, tracking_number: s
|
|||
persistent_notification.create(
|
||||
hass, message, title=title, notification_id=notification_id
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
def deprecate_sensor_issue(hass: HomeAssistant, entry_id: str) -> None:
|
||||
"""Ensure an issue is registered."""
|
||||
ir.async_create_issue(
|
||||
hass,
|
||||
DOMAIN,
|
||||
f"deprecate_sensor_{entry_id}",
|
||||
breaks_in_ha_version="2025.2.0",
|
||||
issue_domain=DOMAIN,
|
||||
is_fixable=True,
|
||||
is_persistent=True,
|
||||
translation_key="deprecate_sensor",
|
||||
severity=ir.IssueSeverity.WARNING,
|
||||
data={"entry_id": entry_id},
|
||||
)
|
||||
|
|
|
@ -45,6 +45,17 @@
|
|||
"deprecated_yaml_import_issue_invalid_auth": {
|
||||
"title": "The 17Track YAML configuration import request failed due to invalid authentication",
|
||||
"description": "Configuring 17Track using YAML is being removed but there were invalid credentials provided while importing your existing configuration.\nSetup will not proceed.\n\nVerify that your 17Track credentials are correct and restart Home Assistant to attempt the import again.\n\nAlternatively, you may remove the 17Track configuration from your YAML configuration entirely, restart Home Assistant, and add the 17Track integration manually."
|
||||
},
|
||||
"deprecate_sensor": {
|
||||
"title": "17Track package sensors are being deprecated",
|
||||
"fix_flow": {
|
||||
"step": {
|
||||
"confirm": {
|
||||
"title": "[%key:component::seventeentrack::issues::deprecate_sensor::title%]",
|
||||
"description": "17Track package sensors are deprecated and will be removed.\nPlease update your automations and scripts to get data using the `seventeentrack.get_packages` service call."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
|
|
|
@ -3,27 +3,39 @@
|
|||
dict({
|
||||
'packages': list([
|
||||
dict({
|
||||
'destination_country': 'Belgium',
|
||||
'friendly_name': 'friendly name 3',
|
||||
'info_text': 'info text 1',
|
||||
'location': 'location 1',
|
||||
'origin_country': 'Belgium',
|
||||
'package_type': 'Registered Parcel',
|
||||
'status': 'Expired',
|
||||
'timestamp': datetime.datetime(2020, 8, 10, 10, 32, tzinfo=<UTC>),
|
||||
'tracking_info_language': 'Unknown',
|
||||
'tracking_number': '123',
|
||||
}),
|
||||
dict({
|
||||
'destination_country': 'Belgium',
|
||||
'friendly_name': 'friendly name 1',
|
||||
'info_text': 'info text 1',
|
||||
'location': 'location 1',
|
||||
'origin_country': 'Belgium',
|
||||
'package_type': 'Registered Parcel',
|
||||
'status': 'In Transit',
|
||||
'timestamp': datetime.datetime(2020, 8, 10, 10, 32, tzinfo=<UTC>),
|
||||
'tracking_info_language': 'Unknown',
|
||||
'tracking_number': '456',
|
||||
}),
|
||||
dict({
|
||||
'destination_country': 'Belgium',
|
||||
'friendly_name': 'friendly name 2',
|
||||
'info_text': 'info text 1',
|
||||
'location': 'location 1',
|
||||
'origin_country': 'Belgium',
|
||||
'package_type': 'Registered Parcel',
|
||||
'status': 'Delivered',
|
||||
'timestamp': datetime.datetime(2020, 8, 10, 10, 32, tzinfo=<UTC>),
|
||||
'tracking_info_language': 'Unknown',
|
||||
'tracking_number': '789',
|
||||
}),
|
||||
]),
|
||||
|
@ -33,19 +45,27 @@
|
|||
dict({
|
||||
'packages': list([
|
||||
dict({
|
||||
'destination_country': 'Belgium',
|
||||
'friendly_name': 'friendly name 1',
|
||||
'info_text': 'info text 1',
|
||||
'location': 'location 1',
|
||||
'origin_country': 'Belgium',
|
||||
'package_type': 'Registered Parcel',
|
||||
'status': 'In Transit',
|
||||
'timestamp': datetime.datetime(2020, 8, 10, 10, 32, tzinfo=<UTC>),
|
||||
'tracking_info_language': 'Unknown',
|
||||
'tracking_number': '456',
|
||||
}),
|
||||
dict({
|
||||
'destination_country': 'Belgium',
|
||||
'friendly_name': 'friendly name 2',
|
||||
'info_text': 'info text 1',
|
||||
'location': 'location 1',
|
||||
'origin_country': 'Belgium',
|
||||
'package_type': 'Registered Parcel',
|
||||
'status': 'Delivered',
|
||||
'timestamp': datetime.datetime(2020, 8, 10, 10, 32, tzinfo=<UTC>),
|
||||
'tracking_info_language': 'Unknown',
|
||||
'tracking_number': '789',
|
||||
}),
|
||||
]),
|
||||
|
|
95
tests/components/seventeentrack/test_repairs.py
Normal file
95
tests/components/seventeentrack/test_repairs.py
Normal file
|
@ -0,0 +1,95 @@
|
|||
"""Tests for the seventeentrack repair flow."""
|
||||
|
||||
from http import HTTPStatus
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
|
||||
from homeassistant.components.repairs import DOMAIN as REPAIRS_DOMAIN
|
||||
from homeassistant.components.repairs.websocket_api import RepairsFlowIndexView
|
||||
from homeassistant.components.seventeentrack import DOMAIN
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import issue_registry as ir
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from . import goto_future, init_integration
|
||||
from .conftest import DEFAULT_SUMMARY_LENGTH, get_package
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
from tests.typing import ClientSessionGenerator
|
||||
|
||||
|
||||
async def test_repair(
|
||||
hass: HomeAssistant,
|
||||
mock_seventeentrack: AsyncMock,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
hass_client: ClientSessionGenerator,
|
||||
mock_config_entry: MockConfigEntry,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Ensure everything starts correctly."""
|
||||
await init_integration(hass, mock_config_entry) # 2
|
||||
assert len(hass.states.async_entity_ids()) == DEFAULT_SUMMARY_LENGTH
|
||||
assert len(issue_registry.issues) == 1
|
||||
|
||||
package = get_package()
|
||||
mock_seventeentrack.return_value.profile.packages.return_value = [package]
|
||||
await goto_future(hass, freezer)
|
||||
|
||||
assert hass.states.get("sensor.17track_package_friendly_name_1")
|
||||
assert len(hass.states.async_entity_ids()) == DEFAULT_SUMMARY_LENGTH + 1
|
||||
|
||||
assert "deprecated" not in mock_config_entry.data
|
||||
|
||||
repair_issue = issue_registry.async_get_issue(
|
||||
domain=DOMAIN, issue_id=f"deprecate_sensor_{mock_config_entry.entry_id}"
|
||||
)
|
||||
|
||||
assert await async_setup_component(hass, REPAIRS_DOMAIN, {REPAIRS_DOMAIN: {}})
|
||||
|
||||
client = await hass_client()
|
||||
|
||||
resp = await client.post(
|
||||
RepairsFlowIndexView.url,
|
||||
json={"handler": DOMAIN, "issue_id": repair_issue.issue_id},
|
||||
)
|
||||
|
||||
assert resp.status == HTTPStatus.OK
|
||||
data = await resp.json()
|
||||
|
||||
flow_id = data["flow_id"]
|
||||
assert data == {
|
||||
"type": "form",
|
||||
"flow_id": flow_id,
|
||||
"handler": DOMAIN,
|
||||
"step_id": "confirm",
|
||||
"data_schema": [],
|
||||
"errors": None,
|
||||
"description_placeholders": None,
|
||||
"last_step": None,
|
||||
"preview": None,
|
||||
}
|
||||
|
||||
resp = await client.post(RepairsFlowIndexView.url + f"/{flow_id}")
|
||||
assert resp.status == HTTPStatus.OK
|
||||
data = await resp.json()
|
||||
|
||||
flow_id = data["flow_id"]
|
||||
assert data == {
|
||||
"type": "create_entry",
|
||||
"handler": DOMAIN,
|
||||
"flow_id": flow_id,
|
||||
"description": None,
|
||||
"description_placeholders": None,
|
||||
}
|
||||
|
||||
assert mock_config_entry.data["deprecated"]
|
||||
|
||||
repair_issue = issue_registry.async_get_issue(
|
||||
domain=DOMAIN, issue_id="deprecate_sensor"
|
||||
)
|
||||
|
||||
assert repair_issue is None
|
||||
|
||||
await goto_future(hass, freezer)
|
||||
assert len(hass.states.async_entity_ids()) == DEFAULT_SUMMARY_LENGTH
|
|
@ -317,4 +317,4 @@ async def test_full_valid_platform_config(
|
|||
assert await async_setup_component(hass, "sensor", VALID_PLATFORM_CONFIG_FULL)
|
||||
await hass.async_block_till_done()
|
||||
assert len(hass.states.async_entity_ids()) == len(DEFAULT_SUMMARY.keys())
|
||||
assert len(issue_registry.issues) == 1
|
||||
assert len(issue_registry.issues) == 2
|
||||
|
|
Loading…
Add table
Reference in a new issue