Skip to content

fix: avoid deprecated device_registry.devices mapping access - #92

Open
jmdevita wants to merge 1 commit into
mainfrom
fix/device-registry-mapping-deprecation
Open

jmdevita wants to merge 1 commit into
mainfrom
fix/device-registry-mapping-deprecation

Conversation

@jmdevita

Copy link
Copy Markdown
Owner

Fixes #91.

Problem

PR #90 fixed the deprecated async_get_device(identifiers=...) lookup in cleanup_old_device() by replacing it with an iteration over device_reg.devices.values(). That swapped one deprecation for another.

In HA 2026.9, DeviceRegistry.devices returns a _DeprecatedDeviceRegistryItemsView. Iterating it is the supported use, but any mapping-style access — .values(), .get(), subscription — calls report_usage() and breaks in HA Core 2027.9.0. Hence the startup warning users see on 2026.9.*:

Detected that custom integration 'parcelapp' uses `device_registry.devices` as a mapping
or calls its lookup methods, which is deprecated; iterate it to get the device entries,
or use `async_get`, `async_entries_for_config_entry` and similar helpers for lookups

Fix

Walk this integration's own config entries and use dr.async_entries_for_config_entry(). Verified against the 2026.9.1 source that this helper reads registry._devices directly, bypassing the deprecated view, so it emits no warning:

def async_entries_for_config_entry(registry, config_entry_id):
    """Return entries that match a config entry."""
    return registry._devices.get_devices_for_config_entry_id(  # noqa: SLF001
        config_entry_id
    )

Two notes on the implementation:

  • Iterating every config entry of the domain, rather than just the one being set up, preserves fix: replace deprecated device_registry.async_get_device (removed in HA 2027.8.0) #90's behaviour. cleanup_old_device() runs once globally (guarded by the processed_cleanup flag), and the legacy device may belong to an entry that isn't the first to set up.
  • The removed set guards against calling async_remove_device() twice on a device shared by two entries, which would raise KeyError. Defensive — the malformed device predates multi-hub support, so in practice it only ever belonged to one entry.

Testing

Adds a regression test for cleanup_old_device(), which had no coverage despite being rewritten twice. 272 tests pass.

Worth flagging: the test does not catch this specific deprecation. The pinned pytest-homeassistant-custom-component resolves to HA 2026.3.1, which predates the compatibility view entirely, so the test passes against the old code too. It pins the behavioural contract — bare (DOMAIN,) is removed, (DOMAIN, entry_id) is kept — not the API choice.

Also syncs manifest.json to 1.8.3, matching the existing tag. The release workflow patches this from the tag at publish time, so shipped artifacts were already correct; this is repo bookkeeping only.

PR #90 replaced the deprecated `async_get_device(identifiers=...)` lookup in
cleanup_old_device() with an iteration over `device_reg.devices.values()`.
That swapped one deprecation for another: HA 2026.9 wraps `DeviceRegistry.devices`
in a compatibility view that reports any mapping-style use and stops working in
HA Core 2027.9.0, so the integration logs a warning on every startup.

Walk this integration's own config entries and use the supported
`dr.async_entries_for_config_entry()` helper instead, which reads the registry's
internal container directly and is not deprecated. Iterating every config entry
of the domain (rather than just the one being set up) keeps the previous
behaviour of finding the legacy device regardless of which entry owns it.

Also adds a regression test for cleanup_old_device(), which had no coverage
despite being rewritten twice, and syncs the manifest version with tag v1.8.3.
@github-actions github-actions Bot added the fix label Sep 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deprecation warning in HA log for device_registry.devices

1 participant