mirror of
https://github.com/home-assistant/core.git
synced 2026-11-06 05:32:45 -04:00
Fix unifi_discovery deepcopy crash on Python 3.14 (#168153)
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
from collections.abc import Generator
|
||||
from contextlib import contextmanager
|
||||
from types import MappingProxyType
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
from unifi_discovery import AIOUnifiScanner, UnifiDevice, UnifiService
|
||||
@@ -30,6 +31,21 @@ UNIFI_DISCOVERY_NO_MAC = UnifiDevice(
|
||||
direct_connect_domain=DIRECT_CONNECT_DOMAIN,
|
||||
)
|
||||
|
||||
# In production the crash happens because asdict() deep-copies Enum keys in
|
||||
# the services dict, and on Python 3.14+ deepcopy traverses into
|
||||
# Enum.__members__ (a mappingproxy) which cannot be pickled. Whether
|
||||
# deepcopy(enum) actually fails depends on the specific CPython build, so
|
||||
# we force the error reliably by using MappingProxyType directly as the
|
||||
# services value — deepcopy always fails on it.
|
||||
UNIFI_DISCOVERY_MAPPINGPROXY_SERVICES = UnifiDevice(
|
||||
source_ip=DEVICE_IP_ADDRESS,
|
||||
hw_addr=DEVICE_MAC_ADDRESS,
|
||||
platform=DEVICE_HOSTNAME,
|
||||
hostname=DEVICE_HOSTNAME,
|
||||
services=MappingProxyType({UnifiService.Protect: True}),
|
||||
direct_connect_domain=DIRECT_CONNECT_DOMAIN,
|
||||
)
|
||||
|
||||
|
||||
def _patch_discovery(
|
||||
device: UnifiDevice | None = None, no_device: bool = False
|
||||
|
||||
@@ -7,7 +7,11 @@ from homeassistant.components.unifi_discovery.const import DOMAIN
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from . import UNIFI_DISCOVERY_NO_MAC, _patch_discovery
|
||||
from . import (
|
||||
UNIFI_DISCOVERY_MAPPINGPROXY_SERVICES,
|
||||
UNIFI_DISCOVERY_NO_MAC,
|
||||
_patch_discovery,
|
||||
)
|
||||
|
||||
|
||||
async def test_setup_starts_discovery(hass: HomeAssistant) -> None:
|
||||
@@ -54,3 +58,20 @@ async def test_dependency_loads_discovery(
|
||||
flows = hass.config_entries.flow.async_progress_by_handler("unifiprotect")
|
||||
assert len(flows) == 1
|
||||
assert flows[0]["context"]["source"] == config_entries.SOURCE_INTEGRATION_DISCOVERY
|
||||
|
||||
|
||||
async def test_discovery_does_not_deepcopy_device(hass: HomeAssistant) -> None:
|
||||
"""Test discovery works without deepcopy.
|
||||
|
||||
In production asdict() deep-copies Enum keys in the services dict which
|
||||
can crash on Python 3.14+ because Enum.__members__ is a mappingproxy that
|
||||
cannot be pickled. We force the crash reliably by using MappingProxyType
|
||||
as the services value.
|
||||
"""
|
||||
with _patch_discovery(device=UNIFI_DISCOVERY_MAPPINGPROXY_SERVICES):
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
flows = hass.config_entries.flow.async_progress_by_handler("unifiprotect")
|
||||
assert len(flows) == 1
|
||||
assert flows[0]["context"]["source"] == config_entries.SOURCE_INTEGRATION_DISCOVERY
|
||||
|
||||
Reference in New Issue
Block a user