mirror of
https://github.com/home-assistant/core.git
synced 2025-07-25 06:07:17 +00:00
2023.6.1 (#94288)
This commit is contained in:
commit
a5f86bff45
@ -391,6 +391,7 @@ def async_enable_logging(
|
||||
logging.getLogger("requests").setLevel(logging.WARNING)
|
||||
logging.getLogger("urllib3").setLevel(logging.WARNING)
|
||||
logging.getLogger("aiohttp.access").setLevel(logging.WARNING)
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
sys.excepthook = lambda *args: logging.getLogger(None).exception(
|
||||
"Uncaught exception", exc_info=args # type: ignore[arg-type]
|
||||
|
@ -12,6 +12,7 @@ from homeassistant.components.sensor import (
|
||||
SensorEntityDescription,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import LIGHT_LUX
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
@ -71,7 +72,7 @@ class AbodeSensor(AbodeDevice, SensorEntity):
|
||||
elif description.key == CONST.HUMI_STATUS_KEY:
|
||||
self._attr_native_unit_of_measurement = device.humidity_unit
|
||||
elif description.key == CONST.LUX_STATUS_KEY:
|
||||
self._attr_native_unit_of_measurement = device.lux_unit
|
||||
self._attr_native_unit_of_measurement = LIGHT_LUX
|
||||
|
||||
@property
|
||||
def native_value(self) -> float | None:
|
||||
|
@ -6,5 +6,5 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/airzone_cloud",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["aioairzone_cloud"],
|
||||
"requirements": ["aioairzone-cloud==0.1.7"]
|
||||
"requirements": ["aioairzone-cloud==0.1.8"]
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ async def async_setup_entry(
|
||||
|
||||
tasks = []
|
||||
for heater in data_connection.get_devices():
|
||||
tasks.append(heater.update_device_info())
|
||||
tasks.append(asyncio.create_task(heater.update_device_info()))
|
||||
await asyncio.wait(tasks)
|
||||
|
||||
devs = []
|
||||
|
@ -192,7 +192,7 @@ class Flexit(ClimateEntity):
|
||||
result = float(
|
||||
await self._async_read_int16_from_register(register_type, register)
|
||||
)
|
||||
if result == -1:
|
||||
if not result:
|
||||
return -1
|
||||
return result / 10.0
|
||||
|
||||
@ -200,6 +200,6 @@ class Flexit(ClimateEntity):
|
||||
result = await self._hub.async_pymodbus_call(
|
||||
self._slave, register, value, CALL_TYPE_WRITE_REGISTER
|
||||
)
|
||||
if result == -1:
|
||||
if not result:
|
||||
return False
|
||||
return True
|
||||
|
@ -20,5 +20,5 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/frontend",
|
||||
"integration_type": "system",
|
||||
"quality_scale": "internal",
|
||||
"requirements": ["home-assistant-frontend==20230607.0"]
|
||||
"requirements": ["home-assistant-frontend==20230608.0"]
|
||||
}
|
||||
|
@ -14,6 +14,6 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/homekit_controller",
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["aiohomekit", "commentjson"],
|
||||
"requirements": ["aiohomekit==2.6.4"],
|
||||
"requirements": ["aiohomekit==2.6.5"],
|
||||
"zeroconf": ["_hap._tcp.local.", "_hap._udp.local."]
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ class ImapMessage:
|
||||
@property
|
||||
def subject(self) -> str:
|
||||
"""Decode the message subject."""
|
||||
decoded_header = decode_header(self.email_message["Subject"])
|
||||
decoded_header = decode_header(self.email_message["Subject"] or "")
|
||||
subject_header = make_header(decoded_header)
|
||||
return str(subject_header)
|
||||
|
||||
|
@ -302,12 +302,9 @@ class InputSelect(collection.CollectionEntity, SelectEntity, RestoreEntity):
|
||||
async def async_select_option(self, option: str) -> None:
|
||||
"""Select new option."""
|
||||
if option not in self.options:
|
||||
_LOGGER.warning(
|
||||
"Invalid option: %s (possible options: %s)",
|
||||
option,
|
||||
", ".join(self.options),
|
||||
raise HomeAssistantError(
|
||||
f"Invalid option: {option} (possible options: {', '.join(self.options)})"
|
||||
)
|
||||
return
|
||||
self._attr_current_option = option
|
||||
self.async_write_ha_state()
|
||||
|
||||
|
@ -25,7 +25,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import SIGNAL_ADD_ENTITIES
|
||||
from .insteon_entity import InsteonEntity
|
||||
from .utils import async_add_insteon_entities
|
||||
from .utils import async_add_insteon_devices, async_add_insteon_entities
|
||||
|
||||
SENSOR_TYPES = {
|
||||
OPEN_CLOSE_SENSOR: BinarySensorDeviceClass.OPENING,
|
||||
@ -62,7 +62,12 @@ async def async_setup_entry(
|
||||
|
||||
signal = f"{SIGNAL_ADD_ENTITIES}_{Platform.BINARY_SENSOR}"
|
||||
async_dispatcher_connect(hass, signal, async_add_insteon_binary_sensor_entities)
|
||||
async_add_insteon_binary_sensor_entities()
|
||||
async_add_insteon_devices(
|
||||
hass,
|
||||
Platform.BINARY_SENSOR,
|
||||
InsteonBinarySensorEntity,
|
||||
async_add_entities,
|
||||
)
|
||||
|
||||
|
||||
class InsteonBinarySensorEntity(InsteonEntity, BinarySensorEntity):
|
||||
|
@ -23,7 +23,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import SIGNAL_ADD_ENTITIES
|
||||
from .insteon_entity import InsteonEntity
|
||||
from .utils import async_add_insteon_entities
|
||||
from .utils import async_add_insteon_devices, async_add_insteon_entities
|
||||
|
||||
FAN_ONLY = "fan_only"
|
||||
|
||||
@ -71,7 +71,12 @@ async def async_setup_entry(
|
||||
|
||||
signal = f"{SIGNAL_ADD_ENTITIES}_{Platform.CLIMATE}"
|
||||
async_dispatcher_connect(hass, signal, async_add_insteon_climate_entities)
|
||||
async_add_insteon_climate_entities()
|
||||
async_add_insteon_devices(
|
||||
hass,
|
||||
Platform.CLIMATE,
|
||||
InsteonClimateEntity,
|
||||
async_add_entities,
|
||||
)
|
||||
|
||||
|
||||
class InsteonClimateEntity(InsteonEntity, ClimateEntity):
|
||||
|
@ -15,7 +15,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import SIGNAL_ADD_ENTITIES
|
||||
from .insteon_entity import InsteonEntity
|
||||
from .utils import async_add_insteon_entities
|
||||
from .utils import async_add_insteon_devices, async_add_insteon_entities
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
@ -34,7 +34,12 @@ async def async_setup_entry(
|
||||
|
||||
signal = f"{SIGNAL_ADD_ENTITIES}_{Platform.COVER}"
|
||||
async_dispatcher_connect(hass, signal, async_add_insteon_cover_entities)
|
||||
async_add_insteon_cover_entities()
|
||||
async_add_insteon_devices(
|
||||
hass,
|
||||
Platform.COVER,
|
||||
InsteonCoverEntity,
|
||||
async_add_entities,
|
||||
)
|
||||
|
||||
|
||||
class InsteonCoverEntity(InsteonEntity, CoverEntity):
|
||||
|
@ -17,7 +17,7 @@ from homeassistant.util.percentage import (
|
||||
|
||||
from .const import SIGNAL_ADD_ENTITIES
|
||||
from .insteon_entity import InsteonEntity
|
||||
from .utils import async_add_insteon_entities
|
||||
from .utils import async_add_insteon_devices, async_add_insteon_entities
|
||||
|
||||
SPEED_RANGE = (1, 255) # off is not included
|
||||
|
||||
@ -38,7 +38,12 @@ async def async_setup_entry(
|
||||
|
||||
signal = f"{SIGNAL_ADD_ENTITIES}_{Platform.FAN}"
|
||||
async_dispatcher_connect(hass, signal, async_add_insteon_fan_entities)
|
||||
async_add_insteon_fan_entities()
|
||||
async_add_insteon_devices(
|
||||
hass,
|
||||
Platform.FAN,
|
||||
InsteonFanEntity,
|
||||
async_add_entities,
|
||||
)
|
||||
|
||||
|
||||
class InsteonFanEntity(InsteonEntity, FanEntity):
|
||||
|
@ -1,4 +1,7 @@
|
||||
"""Utility methods for the Insteon platform."""
|
||||
from collections.abc import Iterable
|
||||
|
||||
from pyinsteon.device_types.device_base import Device
|
||||
from pyinsteon.device_types.ipdb import (
|
||||
AccessControl_Morningstar,
|
||||
ClimateControl_Thermostat,
|
||||
@ -44,7 +47,7 @@ from pyinsteon.device_types.ipdb import (
|
||||
|
||||
from homeassistant.const import Platform
|
||||
|
||||
DEVICE_PLATFORM = {
|
||||
DEVICE_PLATFORM: dict[Device, dict[Platform, Iterable[int]]] = {
|
||||
AccessControl_Morningstar: {Platform.LOCK: [1]},
|
||||
DimmableLightingControl: {Platform.LIGHT: [1]},
|
||||
DimmableLightingControl_Dial: {Platform.LIGHT: [1]},
|
||||
@ -101,11 +104,11 @@ DEVICE_PLATFORM = {
|
||||
}
|
||||
|
||||
|
||||
def get_device_platforms(device):
|
||||
def get_device_platforms(device) -> dict[Platform, Iterable[int]]:
|
||||
"""Return the HA platforms for a device type."""
|
||||
return DEVICE_PLATFORM.get(type(device), {}).keys()
|
||||
return DEVICE_PLATFORM.get(type(device), {})
|
||||
|
||||
|
||||
def get_platform_groups(device, domain) -> dict:
|
||||
"""Return the platforms that a device belongs in."""
|
||||
return DEVICE_PLATFORM.get(type(device), {}).get(domain, {}) # type: ignore[attr-defined]
|
||||
def get_device_platform_groups(device: Device, platform: Platform) -> Iterable[int]:
|
||||
"""Return the list of device groups for a platform."""
|
||||
return get_device_platforms(device).get(platform, [])
|
||||
|
@ -12,7 +12,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import SIGNAL_ADD_ENTITIES
|
||||
from .insteon_entity import InsteonEntity
|
||||
from .utils import async_add_insteon_entities
|
||||
from .utils import async_add_insteon_devices, async_add_insteon_entities
|
||||
|
||||
MAX_BRIGHTNESS = 255
|
||||
|
||||
@ -37,7 +37,12 @@ async def async_setup_entry(
|
||||
|
||||
signal = f"{SIGNAL_ADD_ENTITIES}_{Platform.LIGHT}"
|
||||
async_dispatcher_connect(hass, signal, async_add_insteon_light_entities)
|
||||
async_add_insteon_light_entities()
|
||||
async_add_insteon_devices(
|
||||
hass,
|
||||
Platform.LIGHT,
|
||||
InsteonDimmerEntity,
|
||||
async_add_entities,
|
||||
)
|
||||
|
||||
|
||||
class InsteonDimmerEntity(InsteonEntity, LightEntity):
|
||||
|
@ -11,7 +11,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import SIGNAL_ADD_ENTITIES
|
||||
from .insteon_entity import InsteonEntity
|
||||
from .utils import async_add_insteon_entities
|
||||
from .utils import async_add_insteon_devices, async_add_insteon_entities
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
@ -30,7 +30,12 @@ async def async_setup_entry(
|
||||
|
||||
signal = f"{SIGNAL_ADD_ENTITIES}_{Platform.LOCK}"
|
||||
async_dispatcher_connect(hass, signal, async_add_insteon_lock_entities)
|
||||
async_add_insteon_lock_entities()
|
||||
async_add_insteon_devices(
|
||||
hass,
|
||||
Platform.LOCK,
|
||||
InsteonLockEntity,
|
||||
async_add_entities,
|
||||
)
|
||||
|
||||
|
||||
class InsteonLockEntity(InsteonEntity, LockEntity):
|
||||
|
@ -10,7 +10,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import SIGNAL_ADD_ENTITIES
|
||||
from .insteon_entity import InsteonEntity
|
||||
from .utils import async_add_insteon_entities
|
||||
from .utils import async_add_insteon_devices, async_add_insteon_entities
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
@ -33,7 +33,12 @@ async def async_setup_entry(
|
||||
|
||||
signal = f"{SIGNAL_ADD_ENTITIES}_{Platform.SWITCH}"
|
||||
async_dispatcher_connect(hass, signal, async_add_insteon_switch_entities)
|
||||
async_add_insteon_switch_entities()
|
||||
async_add_insteon_devices(
|
||||
hass,
|
||||
Platform.SWITCH,
|
||||
InsteonSwitchEntity,
|
||||
async_add_entities,
|
||||
)
|
||||
|
||||
|
||||
class InsteonSwitchEntity(InsteonEntity, SwitchEntity):
|
||||
|
@ -1,7 +1,10 @@
|
||||
"""Utilities used by insteon component."""
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from collections.abc import Callable
|
||||
import logging
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from pyinsteon import devices
|
||||
from pyinsteon.address import Address
|
||||
@ -30,6 +33,7 @@ from homeassistant.const import (
|
||||
CONF_ENTITY_ID,
|
||||
CONF_PLATFORM,
|
||||
ENTITY_MATCH_ALL,
|
||||
Platform,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, ServiceCall, callback
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
@ -38,6 +42,7 @@ from homeassistant.helpers.dispatcher import (
|
||||
async_dispatcher_send,
|
||||
dispatcher_send,
|
||||
)
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import (
|
||||
CONF_CAT,
|
||||
@ -78,7 +83,7 @@ from .const import (
|
||||
SRV_X10_ALL_LIGHTS_ON,
|
||||
SRV_X10_ALL_UNITS_OFF,
|
||||
)
|
||||
from .ipdb import get_device_platforms, get_platform_groups
|
||||
from .ipdb import get_device_platform_groups, get_device_platforms
|
||||
from .schemas import (
|
||||
ADD_ALL_LINK_SCHEMA,
|
||||
ADD_DEFAULT_LINKS_SCHEMA,
|
||||
@ -89,6 +94,9 @@ from .schemas import (
|
||||
X10_HOUSECODE_SCHEMA,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .insteon_entity import InsteonEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -132,6 +140,9 @@ def add_insteon_events(hass: HomeAssistant, device: Device) -> None:
|
||||
_LOGGER.debug("Firing event %s with %s", event, schema)
|
||||
hass.bus.async_fire(event, schema)
|
||||
|
||||
if str(device.address).startswith("X10"):
|
||||
return
|
||||
|
||||
for name_or_group, event in device.events.items():
|
||||
if isinstance(name_or_group, int):
|
||||
for _, event in device.events[name_or_group].items():
|
||||
@ -158,8 +169,10 @@ def register_new_device_callback(hass):
|
||||
await device.async_status()
|
||||
platforms = get_device_platforms(device)
|
||||
for platform in platforms:
|
||||
groups = get_device_platform_groups(device, platform)
|
||||
signal = f"{SIGNAL_ADD_ENTITIES}_{platform}"
|
||||
dispatcher_send(hass, signal, {"address": device.address})
|
||||
dispatcher_send(hass, signal, {"address": device.address, "groups": groups})
|
||||
add_insteon_events(hass, device)
|
||||
|
||||
devices.subscribe(async_new_insteon_device, force_strong_ref=True)
|
||||
|
||||
@ -383,20 +396,38 @@ def print_aldb_to_log(aldb):
|
||||
|
||||
@callback
|
||||
def async_add_insteon_entities(
|
||||
hass, platform, entity_type, async_add_entities, discovery_info
|
||||
):
|
||||
"""Add Insteon devices to a platform."""
|
||||
new_entities = []
|
||||
device_list = [discovery_info.get("address")] if discovery_info else devices
|
||||
|
||||
for address in device_list:
|
||||
device = devices[address]
|
||||
groups = get_platform_groups(device, platform)
|
||||
for group in groups:
|
||||
new_entities.append(entity_type(device, group))
|
||||
hass: HomeAssistant,
|
||||
platform: Platform,
|
||||
entity_type: type[InsteonEntity],
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
discovery_info: dict[str, Any],
|
||||
) -> None:
|
||||
"""Add an Insteon group to a platform."""
|
||||
address = discovery_info["address"]
|
||||
device = devices[address]
|
||||
new_entities = [
|
||||
entity_type(device=device, group=group) for group in discovery_info["groups"]
|
||||
]
|
||||
async_add_entities(new_entities)
|
||||
|
||||
|
||||
@callback
|
||||
def async_add_insteon_devices(
|
||||
hass: HomeAssistant,
|
||||
platform: Platform,
|
||||
entity_type: type[InsteonEntity],
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Add all entities to a platform."""
|
||||
for address in devices:
|
||||
device = devices[address]
|
||||
groups = get_device_platform_groups(device, platform)
|
||||
discovery_info = {"address": address, "groups": groups}
|
||||
async_add_insteon_entities(
|
||||
hass, platform, entity_type, async_add_entities, discovery_info
|
||||
)
|
||||
|
||||
|
||||
def get_usb_ports() -> dict[str, str]:
|
||||
"""Return a dict of USB ports and their friendly names."""
|
||||
ports = list_ports.comports()
|
||||
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from pylast import LastFMNetwork, User, WSError
|
||||
from pylast import LastFMNetwork, PyLastError, User, WSError
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.config_entries import (
|
||||
@ -128,11 +128,14 @@ class LastFmConfigFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
main_user, _ = get_lastfm_user(
|
||||
self.data[CONF_API_KEY], self.data[CONF_MAIN_USER]
|
||||
)
|
||||
friends_response = await self.hass.async_add_executor_job(
|
||||
main_user.get_friends
|
||||
)
|
||||
friends = [
|
||||
SelectOptionDict(value=friend.name, label=friend.get_name(True))
|
||||
for friend in main_user.get_friends()
|
||||
for friend in friends_response
|
||||
]
|
||||
except WSError:
|
||||
except PyLastError:
|
||||
friends = []
|
||||
return self.async_show_form(
|
||||
step_id="friends",
|
||||
@ -197,11 +200,14 @@ class LastFmOptionsFlowHandler(OptionsFlowWithConfigEntry):
|
||||
self.options[CONF_API_KEY],
|
||||
self.options[CONF_MAIN_USER],
|
||||
)
|
||||
friends_response = await self.hass.async_add_executor_job(
|
||||
main_user.get_friends
|
||||
)
|
||||
friends = [
|
||||
SelectOptionDict(value=friend.name, label=friend.get_name(True))
|
||||
for friend in main_user.get_friends()
|
||||
for friend in friends_response
|
||||
]
|
||||
except WSError:
|
||||
except PyLastError:
|
||||
friends = []
|
||||
else:
|
||||
friends = []
|
||||
|
@ -13,7 +13,6 @@ from homeassistant.helpers.typing import ConfigType
|
||||
from . import websocket_api
|
||||
from .const import (
|
||||
ATTR_LEVEL,
|
||||
DEFAULT_LOGSEVERITY,
|
||||
DOMAIN,
|
||||
LOGGER_DEFAULT,
|
||||
LOGGER_FILTERS,
|
||||
@ -39,9 +38,7 @@ CONFIG_SCHEMA = vol.Schema(
|
||||
{
|
||||
DOMAIN: vol.Schema(
|
||||
{
|
||||
vol.Optional(
|
||||
LOGGER_DEFAULT, default=DEFAULT_LOGSEVERITY
|
||||
): _VALID_LOG_LEVEL,
|
||||
vol.Optional(LOGGER_DEFAULT): _VALID_LOG_LEVEL,
|
||||
vol.Optional(LOGGER_LOGS): vol.Schema({cv.string: _VALID_LOG_LEVEL}),
|
||||
vol.Optional(LOGGER_FILTERS): vol.Schema({cv.string: [cv.is_regex]}),
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ class LoggerSettings:
|
||||
|
||||
self._yaml_config = yaml_config
|
||||
self._default_level = logging.INFO
|
||||
if DOMAIN in yaml_config:
|
||||
if DOMAIN in yaml_config and LOGGER_DEFAULT in yaml_config[DOMAIN]:
|
||||
self._default_level = yaml_config[DOMAIN][LOGGER_DEFAULT]
|
||||
self._store: Store[dict[str, dict[str, dict[str, Any]]]] = Store(
|
||||
hass, STORAGE_VERSION, STORAGE_KEY
|
||||
|
@ -38,7 +38,7 @@ def async_setup(hass: HomeAssistant) -> None:
|
||||
class LocalSource(MediaSource):
|
||||
"""Provide local directories as media sources."""
|
||||
|
||||
name: str = "Local Media"
|
||||
name: str = "My media"
|
||||
|
||||
def __init__(self, hass: HomeAssistant) -> None:
|
||||
"""Initialize local source."""
|
||||
|
@ -12,5 +12,5 @@
|
||||
"dependencies": ["bluetooth_adapters"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/melnor",
|
||||
"iot_class": "local_polling",
|
||||
"requirements": ["melnor-bluetooth==0.0.24"]
|
||||
"requirements": ["melnor-bluetooth==0.0.25"]
|
||||
}
|
||||
|
@ -4,5 +4,5 @@
|
||||
"codeowners": ["@joostlek"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/opensky",
|
||||
"iot_class": "cloud_polling",
|
||||
"requirements": ["python-opensky==0.0.7"]
|
||||
"requirements": ["python-opensky==0.0.9"]
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ def setup_platform(
|
||||
latitude = config.get(CONF_LATITUDE, hass.config.latitude)
|
||||
longitude = config.get(CONF_LONGITUDE, hass.config.longitude)
|
||||
radius = config.get(CONF_RADIUS, 0)
|
||||
bounding_box = OpenSky.get_bounding_box(latitude, longitude, radius)
|
||||
bounding_box = OpenSky.get_bounding_box(latitude, longitude, radius * 1000)
|
||||
session = async_get_clientsession(hass)
|
||||
opensky = OpenSky(session=session)
|
||||
add_entities(
|
||||
|
@ -8,5 +8,5 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/otbr",
|
||||
"integration_type": "service",
|
||||
"iot_class": "local_polling",
|
||||
"requirements": ["python-otbr-api==2.1.0"]
|
||||
"requirements": ["python-otbr-api==2.2.0"]
|
||||
}
|
||||
|
@ -95,6 +95,11 @@ class OTBRData:
|
||||
"""Create an active operational dataset."""
|
||||
return await self.api.create_active_dataset(dataset)
|
||||
|
||||
@_handle_otbr_error
|
||||
async def delete_active_dataset(self) -> None:
|
||||
"""Delete the active operational dataset."""
|
||||
return await self.api.delete_active_dataset()
|
||||
|
||||
@_handle_otbr_error
|
||||
async def set_active_dataset_tlvs(self, dataset: bytes) -> None:
|
||||
"""Set current active operational dataset in TLVS format."""
|
||||
|
@ -81,6 +81,12 @@ async def websocket_create_network(
|
||||
connection.send_error(msg["id"], "set_enabled_failed", str(exc))
|
||||
return
|
||||
|
||||
try:
|
||||
await data.delete_active_dataset()
|
||||
except HomeAssistantError as exc:
|
||||
connection.send_error(msg["id"], "delete_active_dataset_failed", str(exc))
|
||||
return
|
||||
|
||||
try:
|
||||
await data.create_active_dataset(
|
||||
python_otbr_api.ActiveDataSet(
|
||||
|
@ -13,7 +13,7 @@
|
||||
"integration_type": "hub",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["boto3", "botocore", "pyhumps", "pyoverkiz", "s3transfer"],
|
||||
"requirements": ["pyoverkiz==1.7.9"],
|
||||
"requirements": ["pyoverkiz==1.8.0"],
|
||||
"zeroconf": [
|
||||
{
|
||||
"type": "_kizbox._tcp.local.",
|
||||
|
@ -4,5 +4,5 @@
|
||||
"codeowners": [],
|
||||
"documentation": "https://www.home-assistant.io/integrations/pulseaudio_loopback",
|
||||
"iot_class": "local_polling",
|
||||
"requirements": ["pulsectl==20.2.4"]
|
||||
"requirements": ["pulsectl==23.5.2"]
|
||||
}
|
||||
|
@ -7,6 +7,6 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/thread",
|
||||
"integration_type": "service",
|
||||
"iot_class": "local_polling",
|
||||
"requirements": ["python-otbr-api==2.1.0", "pyroute2==0.7.5"],
|
||||
"requirements": ["python-otbr-api==2.2.0", "pyroute2==0.7.5"],
|
||||
"zeroconf": ["_meshcop._udp.local."]
|
||||
}
|
||||
|
@ -41,7 +41,7 @@
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["pyunifiprotect", "unifi_discovery"],
|
||||
"quality_scale": "platinum",
|
||||
"requirements": ["pyunifiprotect==4.10.1", "unifi-discovery==1.1.7"],
|
||||
"requirements": ["pyunifiprotect==4.10.2", "unifi-discovery==1.1.7"],
|
||||
"ssdp": [
|
||||
{
|
||||
"manufacturer": "Ubiquiti Networks",
|
||||
|
@ -8,7 +8,7 @@ from .backports.enum import StrEnum
|
||||
APPLICATION_NAME: Final = "HomeAssistant"
|
||||
MAJOR_VERSION: Final = 2023
|
||||
MINOR_VERSION: Final = 6
|
||||
PATCH_VERSION: Final = "0"
|
||||
PATCH_VERSION: Final = "1"
|
||||
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
|
||||
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 10, 0)
|
||||
|
@ -25,7 +25,7 @@ ha-av==10.1.0
|
||||
hass-nabucasa==0.67.1
|
||||
hassil==1.0.6
|
||||
home-assistant-bluetooth==1.10.0
|
||||
home-assistant-frontend==20230607.0
|
||||
home-assistant-frontend==20230608.0
|
||||
home-assistant-intents==2023.6.5
|
||||
httpx==0.24.1
|
||||
ifaddr==0.2.0
|
||||
@ -128,9 +128,8 @@ authlib<1.0
|
||||
# Version 2.0 added typing, prevent accidental fallbacks
|
||||
backoff>=2.0
|
||||
|
||||
# Breaking change in version
|
||||
# https://github.com/samuelcolvin/pydantic/issues/4092
|
||||
pydantic!=1.9.1
|
||||
# Require to avoid issues with decorators (#93904). v2 has breaking changes.
|
||||
pydantic>=1.10.8,<2.0
|
||||
|
||||
# Breaks asyncio
|
||||
# https://github.com/pubnub/python/issues/130
|
||||
|
@ -245,7 +245,10 @@ async def _async_setup_component(
|
||||
severity=IssueSeverity.ERROR,
|
||||
issue_domain=domain,
|
||||
translation_key="integration_key_no_support",
|
||||
translation_placeholders={"domain": domain},
|
||||
translation_placeholders={
|
||||
"domain": domain,
|
||||
"add_integration": f"/config/integrations/dashboard/add?domain={domain}",
|
||||
},
|
||||
)
|
||||
|
||||
start = timer()
|
||||
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "homeassistant"
|
||||
version = "2023.6.0"
|
||||
version = "2023.6.1"
|
||||
license = {text = "Apache-2.0"}
|
||||
description = "Open-source home automation platform running on Python 3."
|
||||
readme = "README.rst"
|
||||
|
@ -116,7 +116,7 @@ aio_georss_gdacs==0.8
|
||||
aioairq==0.2.4
|
||||
|
||||
# homeassistant.components.airzone_cloud
|
||||
aioairzone-cloud==0.1.7
|
||||
aioairzone-cloud==0.1.8
|
||||
|
||||
# homeassistant.components.airzone
|
||||
aioairzone==0.6.3
|
||||
@ -177,7 +177,7 @@ aioguardian==2022.07.0
|
||||
aioharmony==0.2.10
|
||||
|
||||
# homeassistant.components.homekit_controller
|
||||
aiohomekit==2.6.4
|
||||
aiohomekit==2.6.5
|
||||
|
||||
# homeassistant.components.emulated_hue
|
||||
# homeassistant.components.http
|
||||
@ -924,7 +924,7 @@ hole==0.8.0
|
||||
holidays==0.21.13
|
||||
|
||||
# homeassistant.components.frontend
|
||||
home-assistant-frontend==20230607.0
|
||||
home-assistant-frontend==20230608.0
|
||||
|
||||
# homeassistant.components.conversation
|
||||
home-assistant-intents==2023.6.5
|
||||
@ -1122,7 +1122,7 @@ mcstatus==6.0.0
|
||||
meater-python==0.0.8
|
||||
|
||||
# homeassistant.components.melnor
|
||||
melnor-bluetooth==0.0.24
|
||||
melnor-bluetooth==0.0.25
|
||||
|
||||
# homeassistant.components.message_bird
|
||||
messagebird==1.2.0
|
||||
@ -1418,7 +1418,7 @@ psutil-home-assistant==0.0.1
|
||||
psutil==5.9.5
|
||||
|
||||
# homeassistant.components.pulseaudio_loopback
|
||||
pulsectl==20.2.4
|
||||
pulsectl==23.5.2
|
||||
|
||||
# homeassistant.components.androidtv
|
||||
pure-python-adb[async]==0.3.0.dev0
|
||||
@ -1872,7 +1872,7 @@ pyotgw==2.1.3
|
||||
pyotp==2.8.0
|
||||
|
||||
# homeassistant.components.overkiz
|
||||
pyoverkiz==1.7.9
|
||||
pyoverkiz==1.8.0
|
||||
|
||||
# homeassistant.components.openweathermap
|
||||
pyowm==3.2.0
|
||||
@ -2102,11 +2102,11 @@ python-mystrom==2.2.0
|
||||
python-nest==4.2.0
|
||||
|
||||
# homeassistant.components.opensky
|
||||
python-opensky==0.0.7
|
||||
python-opensky==0.0.9
|
||||
|
||||
# homeassistant.components.otbr
|
||||
# homeassistant.components.thread
|
||||
python-otbr-api==2.1.0
|
||||
python-otbr-api==2.2.0
|
||||
|
||||
# homeassistant.components.picnic
|
||||
python-picnic-api==1.1.0
|
||||
@ -2168,7 +2168,7 @@ pytrafikverket==0.3.3
|
||||
pyudev==0.23.2
|
||||
|
||||
# homeassistant.components.unifiprotect
|
||||
pyunifiprotect==4.10.1
|
||||
pyunifiprotect==4.10.2
|
||||
|
||||
# homeassistant.components.uptimerobot
|
||||
pyuptimerobot==22.2.0
|
||||
|
@ -106,7 +106,7 @@ aio_georss_gdacs==0.8
|
||||
aioairq==0.2.4
|
||||
|
||||
# homeassistant.components.airzone_cloud
|
||||
aioairzone-cloud==0.1.7
|
||||
aioairzone-cloud==0.1.8
|
||||
|
||||
# homeassistant.components.airzone
|
||||
aioairzone==0.6.3
|
||||
@ -164,7 +164,7 @@ aioguardian==2022.07.0
|
||||
aioharmony==0.2.10
|
||||
|
||||
# homeassistant.components.homekit_controller
|
||||
aiohomekit==2.6.4
|
||||
aiohomekit==2.6.5
|
||||
|
||||
# homeassistant.components.emulated_hue
|
||||
# homeassistant.components.http
|
||||
@ -716,7 +716,7 @@ hole==0.8.0
|
||||
holidays==0.21.13
|
||||
|
||||
# homeassistant.components.frontend
|
||||
home-assistant-frontend==20230607.0
|
||||
home-assistant-frontend==20230608.0
|
||||
|
||||
# homeassistant.components.conversation
|
||||
home-assistant-intents==2023.6.5
|
||||
@ -848,7 +848,7 @@ mcstatus==6.0.0
|
||||
meater-python==0.0.8
|
||||
|
||||
# homeassistant.components.melnor
|
||||
melnor-bluetooth==0.0.24
|
||||
melnor-bluetooth==0.0.25
|
||||
|
||||
# homeassistant.components.meteo_france
|
||||
meteofrance-api==1.2.0
|
||||
@ -1382,7 +1382,7 @@ pyotgw==2.1.3
|
||||
pyotp==2.8.0
|
||||
|
||||
# homeassistant.components.overkiz
|
||||
pyoverkiz==1.7.9
|
||||
pyoverkiz==1.8.0
|
||||
|
||||
# homeassistant.components.openweathermap
|
||||
pyowm==3.2.0
|
||||
@ -1532,7 +1532,7 @@ python-nest==4.2.0
|
||||
|
||||
# homeassistant.components.otbr
|
||||
# homeassistant.components.thread
|
||||
python-otbr-api==2.1.0
|
||||
python-otbr-api==2.2.0
|
||||
|
||||
# homeassistant.components.picnic
|
||||
python-picnic-api==1.1.0
|
||||
@ -1579,7 +1579,7 @@ pytrafikverket==0.3.3
|
||||
pyudev==0.23.2
|
||||
|
||||
# homeassistant.components.unifiprotect
|
||||
pyunifiprotect==4.10.1
|
||||
pyunifiprotect==4.10.2
|
||||
|
||||
# homeassistant.components.uptimerobot
|
||||
pyuptimerobot==22.2.0
|
||||
|
@ -132,9 +132,8 @@ authlib<1.0
|
||||
# Version 2.0 added typing, prevent accidental fallbacks
|
||||
backoff>=2.0
|
||||
|
||||
# Breaking change in version
|
||||
# https://github.com/samuelcolvin/pydantic/issues/4092
|
||||
pydantic!=1.9.1
|
||||
# Require to avoid issues with decorators (#93904). v2 has breaking changes.
|
||||
pydantic>=1.10.8,<2.0
|
||||
|
||||
# Breaks asyncio
|
||||
# https://github.com/pubnub/python/issues/130
|
||||
|
@ -39,7 +39,7 @@ async def test_attributes(hass: HomeAssistant) -> None:
|
||||
|
||||
state = hass.states.get("sensor.environment_sensor_lux")
|
||||
assert state.state == "1.0"
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == "lux"
|
||||
assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == "lx"
|
||||
|
||||
state = hass.states.get("sensor.environment_sensor_temperature")
|
||||
# Abodepy device JSON reports 19.5, but Home Assistant shows 19.4
|
||||
|
@ -24,7 +24,12 @@ TEST_MESSAGE_HEADERS2 = (
|
||||
b"Subject: Test subject\r\n"
|
||||
)
|
||||
|
||||
TEST_MESSAGE_HEADERS3 = b""
|
||||
|
||||
TEST_MESSAGE = TEST_MESSAGE_HEADERS1 + DATE_HEADER1 + TEST_MESSAGE_HEADERS2
|
||||
TEST_MESSAGE_NO_SUBJECT_TO_FROM = (
|
||||
TEST_MESSAGE_HEADERS1 + DATE_HEADER1 + TEST_MESSAGE_HEADERS3
|
||||
)
|
||||
TEST_MESSAGE_ALT = TEST_MESSAGE_HEADERS1 + DATE_HEADER2 + TEST_MESSAGE_HEADERS2
|
||||
TEST_INVALID_DATE1 = (
|
||||
TEST_MESSAGE_HEADERS1 + DATE_HEADER_INVALID1 + TEST_MESSAGE_HEADERS2
|
||||
@ -204,4 +209,19 @@ TEST_FETCH_RESPONSE_MULTIPART = (
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
TEST_FETCH_RESPONSE_NO_SUBJECT_TO_FROM = (
|
||||
"OK",
|
||||
[
|
||||
b"1 FETCH (BODY[] {"
|
||||
+ str(len(TEST_MESSAGE_NO_SUBJECT_TO_FROM + TEST_CONTENT_TEXT_PLAIN)).encode(
|
||||
"utf-8"
|
||||
)
|
||||
+ b"}",
|
||||
bytearray(TEST_MESSAGE_NO_SUBJECT_TO_FROM + TEST_CONTENT_TEXT_PLAIN),
|
||||
b")",
|
||||
b"Fetch completed (0.0001 + 0.000 secs).",
|
||||
],
|
||||
)
|
||||
|
||||
RESPONSE_BAD = ("BAD", [])
|
||||
|
@ -1,6 +1,6 @@
|
||||
"""Test the imap entry initialization."""
|
||||
import asyncio
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from typing import Any
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
@ -22,6 +22,7 @@ from .const import (
|
||||
TEST_FETCH_RESPONSE_INVALID_DATE2,
|
||||
TEST_FETCH_RESPONSE_INVALID_DATE3,
|
||||
TEST_FETCH_RESPONSE_MULTIPART,
|
||||
TEST_FETCH_RESPONSE_NO_SUBJECT_TO_FROM,
|
||||
TEST_FETCH_RESPONSE_TEXT_BARE,
|
||||
TEST_FETCH_RESPONSE_TEXT_OTHER,
|
||||
TEST_FETCH_RESPONSE_TEXT_PLAIN,
|
||||
@ -153,6 +154,44 @@ async def test_receiving_message_successfully(
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("imap_search", [TEST_SEARCH_RESPONSE])
|
||||
@pytest.mark.parametrize("imap_fetch", [TEST_FETCH_RESPONSE_NO_SUBJECT_TO_FROM])
|
||||
@pytest.mark.parametrize("imap_has_capability", [True, False], ids=["push", "poll"])
|
||||
async def test_receiving_message_no_subject_to_from(
|
||||
hass: HomeAssistant, mock_imap_protocol: MagicMock
|
||||
) -> None:
|
||||
"""Test receiving a message successfully without subject, to and from in body."""
|
||||
event_called = async_capture_events(hass, "imap_content")
|
||||
|
||||
config_entry = MockConfigEntry(domain=DOMAIN, data=MOCK_CONFIG)
|
||||
config_entry.add_to_hass(hass)
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
# Make sure we have had one update (when polling)
|
||||
async_fire_time_changed(hass, utcnow() + timedelta(seconds=5))
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("sensor.imap_email_email_com")
|
||||
# we should have received one message
|
||||
assert state is not None
|
||||
assert state.state == "1"
|
||||
|
||||
# we should have received one event
|
||||
assert len(event_called) == 1
|
||||
data: dict[str, Any] = event_called[0].data
|
||||
assert data["server"] == "imap.server.com"
|
||||
assert data["username"] == "email@email.com"
|
||||
assert data["search"] == "UnSeen UnDeleted"
|
||||
assert data["folder"] == "INBOX"
|
||||
assert data["sender"] == ""
|
||||
assert data["subject"] == ""
|
||||
assert data["date"] == datetime(
|
||||
2023, 3, 24, 13, 52, tzinfo=timezone(timedelta(seconds=3600))
|
||||
)
|
||||
assert data["text"] == "Test body\r\n\r\n"
|
||||
assert data["headers"]["Return-Path"] == ("<john.doe@example.com>",)
|
||||
assert data["headers"]["Delivered-To"] == ("notify@example.com",)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("imap_has_capability", [True, False], ids=["push", "poll"])
|
||||
@pytest.mark.parametrize(
|
||||
("imap_login_state", "success"), [(AUTH, True), (NONAUTH, False)]
|
||||
|
@ -102,12 +102,13 @@ async def test_select_option(hass: HomeAssistant) -> None:
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == "another option"
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_SELECT_OPTION,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_OPTION: "non existing option"},
|
||||
blocking=True,
|
||||
)
|
||||
with pytest.raises(HomeAssistantError):
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_SELECT_OPTION,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_OPTION: "non existing option"},
|
||||
blocking=True,
|
||||
)
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == "another option"
|
||||
|
||||
@ -305,12 +306,13 @@ async def test_set_options_service(hass: HomeAssistant) -> None:
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == "test1"
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_SELECT_OPTION,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_OPTION: "first option"},
|
||||
blocking=True,
|
||||
)
|
||||
with pytest.raises(HomeAssistantError):
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_SELECT_OPTION,
|
||||
{ATTR_ENTITY_ID: entity_id, ATTR_OPTION: "first option"},
|
||||
blocking=True,
|
||||
)
|
||||
state = hass.states.get(entity_id)
|
||||
assert state.state == "test1"
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
import pytest
|
||||
|
||||
from homeassistant.core import HomeAssistant, State
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.state import async_reproduce_state
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
@ -60,7 +61,8 @@ async def test_reproducing_states(
|
||||
assert hass.states.get(ENTITY).state == VALID_OPTION3
|
||||
|
||||
# Test setting state to invalid state
|
||||
await async_reproduce_state(hass, [State(ENTITY, INVALID_OPTION)])
|
||||
with pytest.raises(HomeAssistantError):
|
||||
await async_reproduce_state(hass, [State(ENTITY, INVALID_OPTION)])
|
||||
|
||||
# The entity state should be unchanged
|
||||
assert hass.states.get(ENTITY).state == VALID_OPTION3
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""The tests for lastfm."""
|
||||
from unittest.mock import patch
|
||||
|
||||
from pylast import Track, WSError
|
||||
from pylast import PyLastError, Track
|
||||
|
||||
from homeassistant.components.lastfm.const import CONF_MAIN_USER, CONF_USERS
|
||||
from homeassistant.const import CONF_API_KEY
|
||||
@ -65,7 +65,7 @@ class MockUser:
|
||||
def get_friends(self):
|
||||
"""Get mock friends."""
|
||||
if self._has_friends is False:
|
||||
raise WSError("network", "status", "Page not found")
|
||||
raise PyLastError("network", "status", "Page not found")
|
||||
return [MockUser(None, None, True, USERNAME_2)]
|
||||
|
||||
|
||||
|
@ -95,7 +95,7 @@ async def test_async_browse_media(hass: HomeAssistant) -> None:
|
||||
media = await media_source.async_browse_media(hass, const.URI_SCHEME)
|
||||
assert isinstance(media, media_source.models.BrowseMediaSource)
|
||||
assert len(media.children) == 1
|
||||
assert media.children[0].title == "Local Media"
|
||||
assert media.children[0].title == "My media"
|
||||
|
||||
|
||||
async def test_async_resolve_media(hass: HomeAssistant) -> None:
|
||||
|
@ -84,6 +84,8 @@ async def test_create_network(
|
||||
with patch(
|
||||
"python_otbr_api.OTBR.create_active_dataset"
|
||||
) as create_dataset_mock, patch(
|
||||
"python_otbr_api.OTBR.delete_active_dataset"
|
||||
) as delete_dataset_mock, patch(
|
||||
"python_otbr_api.OTBR.set_enabled"
|
||||
) as set_enabled_mock, patch(
|
||||
"python_otbr_api.OTBR.get_active_dataset_tlvs", return_value=DATASET_CH16
|
||||
@ -99,6 +101,7 @@ async def test_create_network(
|
||||
create_dataset_mock.assert_called_once_with(
|
||||
python_otbr_api.models.ActiveDataSet(channel=15, network_name="home-assistant")
|
||||
)
|
||||
delete_dataset_mock.assert_called_once_with()
|
||||
assert len(set_enabled_mock.mock_calls) == 2
|
||||
assert set_enabled_mock.mock_calls[0][1][0] is False
|
||||
assert set_enabled_mock.mock_calls[1][1][0] is True
|
||||
@ -151,7 +154,7 @@ async def test_create_network_fails_2(
|
||||
), patch(
|
||||
"python_otbr_api.OTBR.create_active_dataset",
|
||||
side_effect=python_otbr_api.OTBRError,
|
||||
):
|
||||
), patch("python_otbr_api.OTBR.delete_active_dataset"):
|
||||
await websocket_client.send_json_auto_id({"type": "otbr/create_network"})
|
||||
msg = await websocket_client.receive_json()
|
||||
|
||||
@ -171,6 +174,8 @@ async def test_create_network_fails_3(
|
||||
side_effect=[None, python_otbr_api.OTBRError],
|
||||
), patch(
|
||||
"python_otbr_api.OTBR.create_active_dataset",
|
||||
), patch(
|
||||
"python_otbr_api.OTBR.delete_active_dataset"
|
||||
):
|
||||
await websocket_client.send_json_auto_id({"type": "otbr/create_network"})
|
||||
msg = await websocket_client.receive_json()
|
||||
@ -191,6 +196,8 @@ async def test_create_network_fails_4(
|
||||
), patch(
|
||||
"python_otbr_api.OTBR.get_active_dataset_tlvs",
|
||||
side_effect=python_otbr_api.OTBRError,
|
||||
), patch(
|
||||
"python_otbr_api.OTBR.delete_active_dataset"
|
||||
):
|
||||
await websocket_client.send_json_auto_id({"type": "otbr/create_network"})
|
||||
msg = await websocket_client.receive_json()
|
||||
@ -208,7 +215,9 @@ async def test_create_network_fails_5(
|
||||
"""Test create network."""
|
||||
with patch("python_otbr_api.OTBR.set_enabled"), patch(
|
||||
"python_otbr_api.OTBR.create_active_dataset"
|
||||
), patch("python_otbr_api.OTBR.get_active_dataset_tlvs", return_value=None):
|
||||
), patch("python_otbr_api.OTBR.get_active_dataset_tlvs", return_value=None), patch(
|
||||
"python_otbr_api.OTBR.delete_active_dataset"
|
||||
):
|
||||
await websocket_client.send_json_auto_id({"type": "otbr/create_network"})
|
||||
msg = await websocket_client.receive_json()
|
||||
|
||||
@ -216,6 +225,26 @@ async def test_create_network_fails_5(
|
||||
assert msg["error"]["code"] == "get_active_dataset_tlvs_empty"
|
||||
|
||||
|
||||
async def test_create_network_fails_6(
|
||||
hass: HomeAssistant,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
otbr_config_entry,
|
||||
websocket_client,
|
||||
) -> None:
|
||||
"""Test create network."""
|
||||
with patch("python_otbr_api.OTBR.set_enabled"), patch(
|
||||
"python_otbr_api.OTBR.create_active_dataset"
|
||||
), patch("python_otbr_api.OTBR.get_active_dataset_tlvs", return_value=None), patch(
|
||||
"python_otbr_api.OTBR.delete_active_dataset",
|
||||
side_effect=python_otbr_api.OTBRError,
|
||||
):
|
||||
await websocket_client.send_json_auto_id({"type": "otbr/create_network"})
|
||||
msg = await websocket_client.receive_json()
|
||||
|
||||
assert not msg["success"]
|
||||
assert msg["error"]["code"] == "delete_active_dataset_failed"
|
||||
|
||||
|
||||
async def test_set_network(
|
||||
hass: HomeAssistant,
|
||||
aioclient_mock: AiohttpClientMocker,
|
||||
|
@ -864,7 +864,7 @@ async def test_media_browse_local_source(
|
||||
assert msg["result"]["children"][0]["title"] == "Apps"
|
||||
assert msg["result"]["children"][0]["media_content_type"] == MediaType.APPS
|
||||
|
||||
assert msg["result"]["children"][1]["title"] == "Local Media"
|
||||
assert msg["result"]["children"][1]["title"] == "My media"
|
||||
assert msg["result"]["children"][1]["media_class"] == MediaClass.DIRECTORY
|
||||
assert msg["result"]["children"][1]["media_content_type"] is None
|
||||
assert (
|
||||
@ -892,7 +892,7 @@ async def test_media_browse_local_source(
|
||||
assert msg["success"]
|
||||
|
||||
assert msg["result"]
|
||||
assert msg["result"]["title"] == "Local Media"
|
||||
assert msg["result"]["title"] == "My media"
|
||||
assert msg["result"]["media_class"] == MediaClass.DIRECTORY
|
||||
assert msg["result"]["media_content_type"] is None
|
||||
assert len(msg["result"]["children"]) == 2
|
||||
|
Loading…
x
Reference in New Issue
Block a user