Update async_upnp_client to 0.29.0 (#70604)

pull/70703/head
J. Nick Koston 2022-04-25 06:53:35 -10:00 committed by GitHub
parent f6d9c75476
commit 5224cf5968
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 36 additions and 38 deletions

View File

@ -3,7 +3,7 @@
"name": "DLNA Digital Media Renderer", "name": "DLNA Digital Media Renderer",
"config_flow": true, "config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/dlna_dmr", "documentation": "https://www.home-assistant.io/integrations/dlna_dmr",
"requirements": ["async-upnp-client==0.28.0"], "requirements": ["async-upnp-client==0.29.0"],
"dependencies": ["ssdp"], "dependencies": ["ssdp"],
"after_dependencies": ["media_source"], "after_dependencies": ["media_source"],
"ssdp": [ "ssdp": [

View File

@ -3,7 +3,7 @@
"name": "DLNA Digital Media Server", "name": "DLNA Digital Media Server",
"config_flow": true, "config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/dlna_dms", "documentation": "https://www.home-assistant.io/integrations/dlna_dms",
"requirements": ["async-upnp-client==0.28.0"], "requirements": ["async-upnp-client==0.29.0"],
"dependencies": ["ssdp"], "dependencies": ["ssdp"],
"after_dependencies": ["media_source"], "after_dependencies": ["media_source"],
"ssdp": [ "ssdp": [

View File

@ -7,7 +7,7 @@
"samsungctl[websocket]==0.7.1", "samsungctl[websocket]==0.7.1",
"samsungtvws[async,encrypted]==2.5.0", "samsungtvws[async,encrypted]==2.5.0",
"wakeonlan==2.0.1", "wakeonlan==2.0.1",
"async-upnp-client==0.28.0" "async-upnp-client==0.29.0"
], ],
"ssdp": [ "ssdp": [
{ {

View File

@ -11,12 +11,7 @@ import logging
from typing import Any from typing import Any
from async_upnp_client.aiohttp import AiohttpSessionRequester from async_upnp_client.aiohttp import AiohttpSessionRequester
from async_upnp_client.const import ( from async_upnp_client.const import AddressTupleVXType, DeviceOrServiceType, SsdpSource
AddressTupleVXType,
DeviceOrServiceType,
SsdpHeaders,
SsdpSource,
)
from async_upnp_client.description_cache import DescriptionCache from async_upnp_client.description_cache import DescriptionCache
from async_upnp_client.ssdp import SSDP_PORT, determine_source_target, is_ipv4_address from async_upnp_client.ssdp import SSDP_PORT, determine_source_target, is_ipv4_address
from async_upnp_client.ssdp_listener import SsdpDevice, SsdpDeviceTracker, SsdpListener from async_upnp_client.ssdp_listener import SsdpDevice, SsdpDeviceTracker, SsdpListener
@ -246,13 +241,13 @@ async def _async_process_callbacks(
@core_callback @core_callback
def _async_headers_match( def _async_headers_match(
headers: Mapping[str, Any], match_dict: dict[str, str] headers: CaseInsensitiveDict, lower_match_dict: dict[str, str]
) -> bool: ) -> bool:
for header, val in match_dict.items(): for header, val in lower_match_dict.items():
if val == MATCH_ALL: if val == MATCH_ALL:
if header not in headers: if header not in headers:
return False return False
elif headers.get(header) != val: elif headers.get_lower(header) != val:
return False return False
return True return True
@ -328,7 +323,7 @@ class Scanner:
@property @property
def _all_headers_from_ssdp_devices( def _all_headers_from_ssdp_devices(
self, self,
) -> dict[tuple[str, str], Mapping[str, Any]]: ) -> dict[tuple[str, str], CaseInsensitiveDict]:
return { return {
(ssdp_device.udn, dst): headers (ssdp_device.udn, dst): headers
for ssdp_device in self._ssdp_devices for ssdp_device in self._ssdp_devices
@ -340,19 +335,21 @@ class Scanner:
) -> Callable[[], None]: ) -> Callable[[], None]:
"""Register a callback.""" """Register a callback."""
if match_dict is None: if match_dict is None:
match_dict = {} lower_match_dict = {}
else:
lower_match_dict = {k.lower(): v for k, v in match_dict.items()}
# Make sure any entries that happened # Make sure any entries that happened
# before the callback was registered are fired # before the callback was registered are fired
for headers in self._all_headers_from_ssdp_devices.values(): for headers in self._all_headers_from_ssdp_devices.values():
if _async_headers_match(headers, match_dict): if _async_headers_match(headers, lower_match_dict):
await _async_process_callbacks( await _async_process_callbacks(
[callback], [callback],
await self._async_headers_to_discovery_info(headers), await self._async_headers_to_discovery_info(headers),
SsdpChange.ALIVE, SsdpChange.ALIVE,
) )
callback_entry = (callback, match_dict) callback_entry = (callback, lower_match_dict)
self._callbacks.append(callback_entry) self._callbacks.append(callback_entry)
@core_callback @core_callback
@ -461,13 +458,13 @@ class Scanner:
@core_callback @core_callback
def _async_get_matching_callbacks( def _async_get_matching_callbacks(
self, self,
combined_headers: SsdpHeaders, combined_headers: CaseInsensitiveDict,
) -> list[SsdpCallback]: ) -> list[SsdpCallback]:
"""Return a list of callbacks that match.""" """Return a list of callbacks that match."""
return [ return [
callback callback
for callback, match_dict in self._callbacks for callback, lower_match_dict in self._callbacks
if _async_headers_match(combined_headers, match_dict) if _async_headers_match(combined_headers, lower_match_dict)
] ]
async def _ssdp_listener_callback( async def _ssdp_listener_callback(
@ -490,9 +487,8 @@ class Scanner:
# If there are no changes from a search, do not trigger a config flow # If there are no changes from a search, do not trigger a config flow
if source != SsdpSource.SEARCH_ALIVE: if source != SsdpSource.SEARCH_ALIVE:
info_desc = await self._async_get_description_dict(location) or {} info_desc = await self._async_get_description_dict(location) or {}
assert isinstance(combined_headers, CaseInsensitiveDict)
matching_domains = self.integration_matchers.async_matching_domains( matching_domains = self.integration_matchers.async_matching_domains(
CaseInsensitiveDict({**combined_headers.as_dict(), **info_desc}) CaseInsensitiveDict(combined_headers.as_dict(), **info_desc)
) )
if not callbacks and not matching_domains: if not callbacks and not matching_domains:
@ -530,7 +526,7 @@ class Scanner:
return await self._description_cache.async_get_description_dict(location) or {} return await self._description_cache.async_get_description_dict(location) or {}
async def _async_headers_to_discovery_info( async def _async_headers_to_discovery_info(
self, headers: Mapping[str, Any] self, headers: CaseInsensitiveDict
) -> SsdpServiceInfo: ) -> SsdpServiceInfo:
"""Combine the headers and description into discovery_info. """Combine the headers and description into discovery_info.
@ -571,7 +567,7 @@ class Scanner:
def discovery_info_from_headers_and_description( def discovery_info_from_headers_and_description(
combined_headers: Mapping[str, Any], combined_headers: CaseInsensitiveDict,
info_desc: Mapping[str, Any], info_desc: Mapping[str, Any],
) -> SsdpServiceInfo: ) -> SsdpServiceInfo:
"""Convert headers and description to discovery_info.""" """Convert headers and description to discovery_info."""

View File

@ -2,7 +2,7 @@
"domain": "ssdp", "domain": "ssdp",
"name": "Simple Service Discovery Protocol (SSDP)", "name": "Simple Service Discovery Protocol (SSDP)",
"documentation": "https://www.home-assistant.io/integrations/ssdp", "documentation": "https://www.home-assistant.io/integrations/ssdp",
"requirements": ["async-upnp-client==0.28.0"], "requirements": ["async-upnp-client==0.29.0"],
"dependencies": ["network"], "dependencies": ["network"],
"after_dependencies": ["zeroconf"], "after_dependencies": ["zeroconf"],
"codeowners": [], "codeowners": [],

View File

@ -3,7 +3,7 @@
"name": "UPnP/IGD", "name": "UPnP/IGD",
"config_flow": true, "config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/upnp", "documentation": "https://www.home-assistant.io/integrations/upnp",
"requirements": ["async-upnp-client==0.28.0", "getmac==0.8.2"], "requirements": ["async-upnp-client==0.29.0", "getmac==0.8.2"],
"dependencies": ["network", "ssdp"], "dependencies": ["network", "ssdp"],
"codeowners": ["@StevenLooman", "@ehendrix23"], "codeowners": ["@StevenLooman", "@ehendrix23"],
"ssdp": [ "ssdp": [

View File

@ -2,7 +2,7 @@
"domain": "yeelight", "domain": "yeelight",
"name": "Yeelight", "name": "Yeelight",
"documentation": "https://www.home-assistant.io/integrations/yeelight", "documentation": "https://www.home-assistant.io/integrations/yeelight",
"requirements": ["yeelight==0.7.10", "async-upnp-client==0.28.0"], "requirements": ["yeelight==0.7.10", "async-upnp-client==0.29.0"],
"codeowners": ["@zewelor", "@shenxn", "@starkillerOG", "@alexyao2015"], "codeowners": ["@zewelor", "@shenxn", "@starkillerOG", "@alexyao2015"],
"config_flow": true, "config_flow": true,
"dependencies": ["network"], "dependencies": ["network"],

View File

@ -9,7 +9,8 @@ from ipaddress import IPv4Address
import logging import logging
from urllib.parse import urlparse from urllib.parse import urlparse
from async_upnp_client.search import SsdpHeaders, SsdpSearchListener from async_upnp_client.search import SsdpSearchListener
from async_upnp_client.utils import CaseInsensitiveDict
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.components import network, ssdp from homeassistant.components import network, ssdp
@ -46,8 +47,8 @@ class YeelightScanner:
"""Initialize class.""" """Initialize class."""
self._hass = hass self._hass = hass
self._host_discovered_events: dict[str, list[asyncio.Event]] = {} self._host_discovered_events: dict[str, list[asyncio.Event]] = {}
self._unique_id_capabilities: dict[str, SsdpHeaders] = {} self._unique_id_capabilities: dict[str, CaseInsensitiveDict] = {}
self._host_capabilities: dict[str, SsdpHeaders] = {} self._host_capabilities: dict[str, CaseInsensitiveDict] = {}
self._track_interval: CALLBACK_TYPE | None = None self._track_interval: CALLBACK_TYPE | None = None
self._listeners: list[SsdpSearchListener] = [] self._listeners: list[SsdpSearchListener] = []
self._connected_events: list[asyncio.Event] = [] self._connected_events: list[asyncio.Event] = []
@ -123,7 +124,7 @@ class YeelightScanner:
if isinstance(source_ip, IPv4Address) and not source_ip.is_loopback if isinstance(source_ip, IPv4Address) and not source_ip.is_loopback
} }
async def async_discover(self) -> ValuesView[SsdpHeaders]: async def async_discover(self) -> ValuesView[CaseInsensitiveDict]:
"""Discover bulbs.""" """Discover bulbs."""
_LOGGER.debug("Yeelight discover with interval %s", DISCOVERY_SEARCH_INTERVAL) _LOGGER.debug("Yeelight discover with interval %s", DISCOVERY_SEARCH_INTERVAL)
await self.async_setup() await self.async_setup()
@ -139,7 +140,7 @@ class YeelightScanner:
for listener in self._listeners: for listener in self._listeners:
listener.async_search() listener.async_search()
async def async_get_capabilities(self, host: str) -> SsdpHeaders | None: async def async_get_capabilities(self, host: str) -> CaseInsensitiveDict | None:
"""Get capabilities via SSDP.""" """Get capabilities via SSDP."""
if host in self._host_capabilities: if host in self._host_capabilities:
return self._host_capabilities[host] return self._host_capabilities[host]
@ -157,7 +158,7 @@ class YeelightScanner:
self._host_discovered_events[host].remove(host_event) self._host_discovered_events[host].remove(host_event)
return self._host_capabilities.get(host) return self._host_capabilities.get(host)
def _async_discovered_by_ssdp(self, response: SsdpHeaders) -> None: def _async_discovered_by_ssdp(self, response: CaseInsensitiveDict) -> None:
@callback @callback
def _async_start_flow(*_) -> None: def _async_start_flow(*_) -> None:
asyncio.create_task( asyncio.create_task(
@ -177,7 +178,7 @@ class YeelightScanner:
# of another discovery # of another discovery
async_call_later(self._hass, 1, _async_start_flow) async_call_later(self._hass, 1, _async_start_flow)
async def _async_process_entry(self, headers: SsdpHeaders) -> None: async def _async_process_entry(self, headers: CaseInsensitiveDict) -> None:
"""Process a discovery.""" """Process a discovery."""
_LOGGER.debug("Discovered via SSDP: %s", headers) _LOGGER.debug("Discovered via SSDP: %s", headers)
unique_id = headers["id"] unique_id = headers["id"]

View File

@ -4,7 +4,7 @@ aiodiscover==1.4.11
aiohttp==3.8.1 aiohttp==3.8.1
aiohttp_cors==0.7.0 aiohttp_cors==0.7.0
astral==2.2 astral==2.2
async-upnp-client==0.28.0 async-upnp-client==0.29.0
async_timeout==4.0.2 async_timeout==4.0.2
atomicwrites==1.4.0 atomicwrites==1.4.0
attrs==21.2.0 attrs==21.2.0

View File

@ -333,7 +333,7 @@ asterisk_mbox==0.5.0
# homeassistant.components.ssdp # homeassistant.components.ssdp
# homeassistant.components.upnp # homeassistant.components.upnp
# homeassistant.components.yeelight # homeassistant.components.yeelight
async-upnp-client==0.28.0 async-upnp-client==0.29.0
# homeassistant.components.supla # homeassistant.components.supla
asyncpysupla==0.0.5 asyncpysupla==0.0.5

View File

@ -269,7 +269,7 @@ arcam-fmj==0.12.0
# homeassistant.components.ssdp # homeassistant.components.ssdp
# homeassistant.components.upnp # homeassistant.components.upnp
# homeassistant.components.yeelight # homeassistant.components.yeelight
async-upnp-client==0.28.0 async-upnp-client==0.29.0
# homeassistant.components.sleepiq # homeassistant.components.sleepiq
asyncsleepiq==1.2.3 asyncsleepiq==1.2.3

View File

@ -4,10 +4,11 @@ from datetime import timedelta
from unittest.mock import AsyncMock, MagicMock, patch from unittest.mock import AsyncMock, MagicMock, patch
from async_upnp_client.search import SsdpSearchListener from async_upnp_client.search import SsdpSearchListener
from async_upnp_client.utils import CaseInsensitiveDict
from yeelight import BulbException, BulbType from yeelight import BulbException, BulbType
from yeelight.main import _MODEL_SPECS from yeelight.main import _MODEL_SPECS
from homeassistant.components import ssdp, zeroconf from homeassistant.components import zeroconf
from homeassistant.components.yeelight import ( from homeassistant.components.yeelight import (
CONF_MODE_MUSIC, CONF_MODE_MUSIC,
CONF_NIGHTLIGHT_SWITCH_TYPE, CONF_NIGHTLIGHT_SWITCH_TYPE,
@ -157,7 +158,7 @@ def _mocked_bulb(cannot_connect=False):
return bulb return bulb
def _patched_ssdp_listener(info: ssdp.SsdpHeaders, *args, **kwargs): def _patched_ssdp_listener(info: CaseInsensitiveDict, *args, **kwargs):
listener = SsdpSearchListener(*args, **kwargs) listener = SsdpSearchListener(*args, **kwargs)
async def _async_callback(*_): async def _async_callback(*_):