Stub light profiles (#42232)

This commit is contained in:
Paulus Schoutsen 2020-10-23 16:28:21 +02:00 committed by GitHub
parent b626df1316
commit 5dac3883b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 220 additions and 243 deletions

View File

@ -199,11 +199,11 @@ def lifx_features(bulb):
) or aiolifx().products.features_map.get(1)
def find_hsbk(**kwargs):
def find_hsbk(hass, **kwargs):
"""Find the desired color from a number of possible inputs."""
hue, saturation, brightness, kelvin = [None] * 4
preprocess_turn_on_alternatives(kwargs)
preprocess_turn_on_alternatives(hass, kwargs)
if ATTR_HS_COLOR in kwargs:
hue, saturation = kwargs[ATTR_HS_COLOR]
@ -330,11 +330,11 @@ class LIFXManager:
period=kwargs.get(ATTR_PERIOD),
cycles=kwargs.get(ATTR_CYCLES),
mode=kwargs.get(ATTR_MODE),
hsbk=find_hsbk(**kwargs),
hsbk=find_hsbk(self.hass, **kwargs),
)
await self.effects_conductor.start(effect, bulbs)
elif service == SERVICE_EFFECT_COLORLOOP:
preprocess_turn_on_alternatives(kwargs)
preprocess_turn_on_alternatives(self.hass, kwargs)
brightness = None
if ATTR_BRIGHTNESS in kwargs:
@ -600,7 +600,7 @@ class LIFXLight(LightEntity):
power_on = kwargs.get(ATTR_POWER, False)
power_off = not kwargs.get(ATTR_POWER, True)
hsbk = find_hsbk(**kwargs)
hsbk = find_hsbk(self.hass, **kwargs)
# Send messages, waiting for ACK each time
ack = AwaitAioLIFX().wait

View File

@ -3,7 +3,6 @@ import csv
from datetime import timedelta
import logging
import os
from typing import Dict, Optional, Tuple
import voluptuous as vol
@ -13,6 +12,7 @@ from homeassistant.const import (
SERVICE_TURN_ON,
STATE_ON,
)
from homeassistant.core import callback
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.config_validation import ( # noqa: F401
PLATFORM_SCHEMA,
@ -28,6 +28,7 @@ import homeassistant.util.color as color_util
DOMAIN = "light"
SCAN_INTERVAL = timedelta(seconds=30)
DATA_PROFILES = "light_profiles"
ENTITY_ID_FORMAT = DOMAIN + ".{}"
@ -122,15 +123,6 @@ LIGHT_TURN_ON_SCHEMA = {
}
PROFILE_SCHEMA = vol.Schema(
vol.Any(
vol.ExactSequence((str, cv.small_float, cv.small_float, cv.byte)),
vol.ExactSequence(
(str, cv.small_float, cv.small_float, cv.byte, cv.positive_int)
),
)
)
_LOGGER = logging.getLogger(__name__)
@ -140,14 +132,17 @@ def is_on(hass, entity_id):
return hass.states.is_state(entity_id, STATE_ON)
def preprocess_turn_on_alternatives(params):
"""Process extra data for turn light on request."""
profile = Profiles.get(params.pop(ATTR_PROFILE, None))
if profile is not None:
params.setdefault(ATTR_XY_COLOR, profile[:2])
params.setdefault(ATTR_BRIGHTNESS, profile[2])
if len(profile) > 3:
params.setdefault(ATTR_TRANSITION, profile[3])
def preprocess_turn_on_alternatives(hass, params):
"""Process extra data for turn light on request.
Async friendly.
"""
# Bail out, we process this later.
if ATTR_BRIGHTNESS_STEP in params or ATTR_BRIGHTNESS_STEP_PCT in params:
return
if ATTR_PROFILE in params:
hass.data[DATA_PROFILES].apply_profile(params.pop(ATTR_PROFILE), params)
color_name = params.pop(ATTR_COLOR_NAME, None)
if color_name is not None:
@ -174,24 +169,12 @@ def preprocess_turn_on_alternatives(params):
if rgb_color is not None:
params[ATTR_HS_COLOR] = color_util.color_RGB_to_hs(*rgb_color)
return params
def filter_turn_off_params(params):
"""Filter out params not used in turn off."""
return {k: v for k, v in params.items() if k in (ATTR_TRANSITION, ATTR_FLASH)}
def preprocess_turn_off(params):
"""Process data for turning light off if brightness is 0."""
if ATTR_BRIGHTNESS in params and params[ATTR_BRIGHTNESS] == 0:
# Zero brightness: Light will be turned off
params = filter_turn_off_params(params)
return (True, params) # Light should be turned off
return (False, None) # Light should be turned on
async def async_setup(hass, config):
"""Expose light control via state machine and services."""
component = hass.data[DOMAIN] = EntityComponent(
@ -199,10 +182,8 @@ async def async_setup(hass, config):
)
await component.async_setup(config)
# load profiles from files
profiles_valid = await Profiles.load_profiles(hass)
if not profiles_valid:
return False
profiles = hass.data[DATA_PROFILES] = Profiles(hass)
await profiles.async_initialize()
def preprocess_data(data):
"""Preprocess the service data."""
@ -212,7 +193,8 @@ async def async_setup(hass, config):
if entity_field in data
}
base["params"] = preprocess_turn_on_alternatives(data)
preprocess_turn_on_alternatives(hass, data)
base["params"] = data
return base
async def async_handle_light_on_service(light, call):
@ -223,17 +205,14 @@ async def async_setup(hass, config):
params = call.data["params"]
if not params:
default_profile = Profiles.get_default(light.entity_id)
profiles.apply_default(light.entity_id, params)
if default_profile is not None:
params = {ATTR_PROFILE: default_profile}
preprocess_turn_on_alternatives(params)
elif ATTR_BRIGHTNESS_STEP in params or ATTR_BRIGHTNESS_STEP_PCT in params:
# Only process params once we processed brightness step
if params and (
ATTR_BRIGHTNESS_STEP in params or ATTR_BRIGHTNESS_STEP_PCT in params
):
brightness = light.brightness if light.is_on else 0
params = params.copy()
if ATTR_BRIGHTNESS_STEP in params:
brightness += params.pop(ATTR_BRIGHTNESS_STEP)
@ -242,19 +221,18 @@ async def async_setup(hass, config):
params[ATTR_BRIGHTNESS] = max(0, min(255, brightness))
turn_light_off, off_params = preprocess_turn_off(params)
if turn_light_off:
await light.async_turn_off(**off_params)
preprocess_turn_on_alternatives(hass, params)
# Zero brightness: Light will be turned off
if params.get(ATTR_BRIGHTNESS) == 0:
await light.async_turn_off(**filter_turn_off_params(params))
else:
await light.async_turn_on(**params)
async def async_handle_toggle_service(light, call):
"""Handle toggling a light.
If brightness is set to 0, this service will turn the light off.
"""
"""Handle toggling a light."""
if light.is_on:
off_params = filter_turn_off_params(call.data["params"])
off_params = filter_turn_off_params(call.data)
await light.async_turn_off(**off_params)
else:
await async_handle_light_on_service(light, call)
@ -295,73 +273,89 @@ async def async_unload_entry(hass, entry):
class Profiles:
"""Representation of available color profiles."""
_all: Optional[Dict[str, Tuple[float, float, int]]] = None
SCHEMA = vol.Schema(
vol.Any(
vol.ExactSequence((str, cv.small_float, cv.small_float, cv.byte)),
vol.ExactSequence(
(str, cv.small_float, cv.small_float, cv.byte, cv.positive_int)
),
)
)
@classmethod
async def load_profiles(cls, hass):
"""Load and cache profiles."""
def __init__(self, hass):
"""Initialize profiles."""
self.hass = hass
self.data = None
def load_profile_data(hass):
"""Load built-in profiles and custom profiles."""
profile_paths = [
os.path.join(os.path.dirname(__file__), LIGHT_PROFILES_FILE),
hass.config.path(LIGHT_PROFILES_FILE),
]
profiles = {}
def _load_profile_data(self):
"""Load built-in profiles and custom profiles."""
profile_paths = [
os.path.join(os.path.dirname(__file__), LIGHT_PROFILES_FILE),
self.hass.config.path(LIGHT_PROFILES_FILE),
]
profiles = {}
for profile_path in profile_paths:
if not os.path.isfile(profile_path):
continue
with open(profile_path) as inp:
reader = csv.reader(inp)
for profile_path in profile_paths:
if not os.path.isfile(profile_path):
continue
with open(profile_path) as inp:
reader = csv.reader(inp)
# Skip the header
next(reader, None)
# Skip the header
next(reader, None)
try:
for rec in reader:
(
profile,
color_x,
color_y,
brightness,
*transition,
) = PROFILE_SCHEMA(rec)
try:
for rec in reader:
(
profile,
color_x,
color_y,
brightness,
*transition,
) = Profiles.SCHEMA(rec)
transition = transition[0] if transition else 0
transition = transition[0] if transition else 0
profiles[profile] = (
color_x,
color_y,
brightness,
transition,
)
except vol.MultipleInvalid as ex:
_LOGGER.error(
"Error parsing light profile from %s: %s", profile_path, ex
profiles[profile] = color_util.color_xy_to_hs(
color_x, color_y
) + (
brightness,
transition,
)
return None
return profiles
except vol.MultipleInvalid as ex:
_LOGGER.error(
"Error parsing light profile from %s: %s", profile_path, ex
)
continue
return profiles
cls._all = await hass.async_add_executor_job(load_profile_data, hass)
return cls._all is not None
async def async_initialize(self):
"""Load and cache profiles."""
self.data = await self.hass.async_add_executor_job(self._load_profile_data)
@classmethod
def get(cls, name):
"""Return a named profile."""
return cls._all.get(name)
@classmethod
def get_default(cls, entity_id):
@callback
def apply_default(self, entity_id, params):
"""Return the default turn-on profile for the given light."""
# pylint: disable=unsupported-membership-test
name = f"{entity_id}.default"
if name in cls._all:
return name
if name in self.data:
self.apply_profile(name, params)
return
name = "group.all_lights.default"
if name in cls._all:
return name
return None
if name in self.data:
self.apply_profile(name, params)
@callback
def apply_profile(self, name, params):
"""Apply a profile."""
profile = self.data.get(name)
if profile is None:
return
params.setdefault(ATTR_HS_COLOR, profile[:2])
params.setdefault(ATTR_BRIGHTNESS, profile[2])
params.setdefault(ATTR_TRANSITION, profile[3])
class LightEntity(ToggleEntity):

View File

@ -3,6 +3,7 @@ import abodepy.helpers.constants as CONST
import pytest
from tests.common import load_fixture
from tests.components.light.conftest import mock_light_profiles # noqa
@pytest.fixture(autouse=True)

View File

@ -0,0 +1,2 @@
"""axis conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -1,5 +1,4 @@
"""PyTest fixtures and test helpers."""
from unittest import mock
import blebox_uniapi
@ -11,6 +10,7 @@ from homeassistant.setup import async_setup_component
from tests.async_mock import AsyncMock, PropertyMock, patch
from tests.common import MockConfigEntry
from tests.components.light.conftest import mock_light_profiles # noqa
def patch_product_identify(path=None, **kwargs):

View File

@ -0,0 +1,2 @@
"""bond conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,2 @@
"""deconz conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,2 @@
"""demo conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,2 @@
"""dynalite conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,2 @@
"""elgato conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,2 @@
"""everlights conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,2 @@
"""group conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -8,6 +8,7 @@ import pytest
import homeassistant.util.dt as dt_util
import tests.async_mock
from tests.components.light.conftest import mock_light_profiles # noqa
@pytest.fixture

View File

@ -24,6 +24,7 @@ from .helper import AUTH_TOKEN, HAPID, HAPPIN, HomeFactory
from tests.async_mock import AsyncMock, MagicMock, Mock, patch
from tests.common import MockConfigEntry
from tests.components.light.conftest import mock_light_profiles # noqa
@pytest.fixture(name="mock_connection")

View File

@ -12,6 +12,7 @@ from homeassistant.components import hue
from homeassistant.components.hue import sensor_base as hue_sensor_base
from tests.async_mock import AsyncMock, Mock, patch
from tests.components.light.conftest import mock_light_profiles # noqa
@pytest.fixture(autouse=True)

View File

@ -0,0 +1,2 @@
"""hyperion conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,26 @@
"""Light conftest."""
import pytest
from homeassistant.components.light import Profiles
from tests.async_mock import AsyncMock, patch
@pytest.fixture(autouse=True)
def mock_light_profiles():
"""Mock loading of profiles."""
data = {}
def mock_profiles_class(hass):
profiles = Profiles(hass)
profiles.data = data
profiles.async_initialize = AsyncMock()
return profiles
with patch(
"homeassistant.components.light.Profiles",
SCHEMA=Profiles.SCHEMA,
side_effect=mock_profiles_class,
):
yield data

View File

@ -1,8 +1,4 @@
"""The tests for the Light component."""
# pylint: disable=protected-access
from io import StringIO
import os
import pytest
import voluptuous as vol
@ -20,19 +16,11 @@ from homeassistant.const import (
)
from homeassistant.exceptions import Unauthorized
from homeassistant.setup import async_setup_component
from homeassistant.util import color
import tests.async_mock as mock
from tests.common import async_mock_service
@pytest.fixture
def mock_storage(hass, hass_storage):
"""Clean up user light files at the end."""
yield
user_light_file = hass.config.path(light.LIGHT_PROFILES_FILE)
if os.path.isfile(user_light_file):
os.remove(user_light_file)
orig_Profiles = light.Profiles
async def test_methods(hass):
@ -117,7 +105,7 @@ async def test_methods(hass):
assert call.data[light.ATTR_TRANSITION] == "transition_val"
async def test_services(hass):
async def test_services(hass, mock_light_profiles):
"""Test the provided services."""
platform = getattr(hass.components, "test.light")
@ -292,6 +280,7 @@ async def test_services(hass):
assert data == {}
# One of the light profiles
mock_light_profiles["relax"] = (35.932, 69.412, 144, 0)
prof_name, prof_h, prof_s, prof_bri, prof_t = "relax", 35.932, 69.412, 144, 0
# Test light profiles
@ -418,34 +407,13 @@ async def test_services(hass):
assert data == {}
async def test_broken_light_profiles(hass, mock_storage):
async def test_light_profiles(hass, mock_light_profiles):
"""Test light profiles."""
platform = getattr(hass.components, "test.light")
platform.init()
user_light_file = hass.config.path(light.LIGHT_PROFILES_FILE)
# Setup a wrong light file
with open(user_light_file, "w") as user_file:
user_file.write("id,x,y,brightness,transition\n")
user_file.write("I,WILL,NOT,WORK,EVER\n")
assert not await async_setup_component(
hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: "test"}}
)
async def test_light_profiles(hass, mock_storage):
"""Test light profiles."""
platform = getattr(hass.components, "test.light")
platform.init()
user_light_file = hass.config.path(light.LIGHT_PROFILES_FILE)
with open(user_light_file, "w") as user_file:
user_file.write("id,x,y,brightness\n")
user_file.write("test,.4,.6,100\n")
user_file.write("test_off,0,0,0\n")
mock_light_profiles["test"] = color.color_xy_to_hs(0.4, 0.6) + (100, 0)
mock_light_profiles["test_off"] = 0, 0, 0, 0
assert await async_setup_component(
hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: "test"}}
@ -484,80 +452,21 @@ async def test_light_profiles(hass, mock_storage):
assert data == {light.ATTR_TRANSITION: 0}
async def test_light_profiles_with_transition(hass, mock_storage):
"""Test light profiles with transition."""
async def test_default_profiles_group(hass, mock_light_profiles):
"""Test default turn-on light profile for all lights."""
platform = getattr(hass.components, "test.light")
platform.init()
user_light_file = hass.config.path(light.LIGHT_PROFILES_FILE)
with open(user_light_file, "w") as user_file:
user_file.write("id,x,y,brightness,transition\n")
user_file.write("test,.4,.6,100,2\n")
user_file.write("test_off,0,0,0,0\n")
assert await async_setup_component(
hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: "test"}}
)
await hass.async_block_till_done()
ent1, _, _ = platform.ENTITIES
await hass.services.async_call(
light.DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: ent1.entity_id, light.ATTR_PROFILE: "test"},
blocking=True,
mock_light_profiles["group.all_lights.default"] = color.color_xy_to_hs(0.4, 0.6) + (
99,
2,
)
_, data = ent1.last_call("turn_on")
assert light.is_on(hass, ent1.entity_id)
assert data == {
light.ATTR_HS_COLOR: (71.059, 100),
light.ATTR_BRIGHTNESS: 100,
light.ATTR_TRANSITION: 2,
}
await hass.services.async_call(
light.DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: ent1.entity_id, light.ATTR_PROFILE: "test_off"},
blocking=True,
)
_, data = ent1.last_call("turn_off")
assert not light.is_on(hass, ent1.entity_id)
assert data == {light.ATTR_TRANSITION: 0}
async def test_default_profiles_group(hass, mock_storage):
"""Test default turn-on light profile for all lights."""
platform = getattr(hass.components, "test.light")
platform.init()
user_light_file = hass.config.path(light.LIGHT_PROFILES_FILE)
real_isfile = os.path.isfile
real_open = open
def _mock_isfile(path):
if path == user_light_file:
return True
return real_isfile(path)
def _mock_open(path, *args, **kwargs):
if path == user_light_file:
return StringIO(profile_data)
return real_open(path, *args, **kwargs)
profile_data = "id,x,y,brightness,transition\ngroup.all_lights.default,.4,.6,99,2\n"
with mock.patch("os.path.isfile", side_effect=_mock_isfile), mock.patch(
"builtins.open", side_effect=_mock_open
):
assert await async_setup_component(
hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: "test"}}
)
await hass.async_block_till_done()
ent, _, _ = platform.ENTITIES
await hass.services.async_call(
light.DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: ent.entity_id}, blocking=True
@ -571,37 +480,24 @@ async def test_default_profiles_group(hass, mock_storage):
}
async def test_default_profiles_light(hass, mock_storage):
async def test_default_profiles_light(hass, mock_light_profiles):
"""Test default turn-on light profile for a specific light."""
platform = getattr(hass.components, "test.light")
platform.init()
user_light_file = hass.config.path(light.LIGHT_PROFILES_FILE)
real_isfile = os.path.isfile
real_open = open
def _mock_isfile(path):
if path == user_light_file:
return True
return real_isfile(path)
def _mock_open(path, *args, **kwargs):
if path == user_light_file:
return StringIO(profile_data)
return real_open(path, *args, **kwargs)
profile_data = (
"id,x,y,brightness,transition\n"
+ "group.all_lights.default,.3,.5,200,0\n"
+ "light.ceiling_2.default,.6,.6,100,3\n"
assert await async_setup_component(
hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: "test"}}
)
await hass.async_block_till_done()
mock_light_profiles["group.all_lights.default"] = color.color_xy_to_hs(0.3, 0.5) + (
200,
0,
)
mock_light_profiles["light.ceiling_2.default"] = color.color_xy_to_hs(0.6, 0.6) + (
100,
3,
)
with mock.patch("os.path.isfile", side_effect=_mock_isfile), mock.patch(
"builtins.open", side_effect=_mock_open
):
assert await async_setup_component(
hass, light.DOMAIN, {light.DOMAIN: {CONF_PLATFORM: "test"}}
)
await hass.async_block_till_done()
dev = next(filter(lambda x: x.entity_id == "light.ceiling_2", platform.ENTITIES))
await hass.services.async_call(
@ -775,3 +671,15 @@ def test_deprecated_base_class(caplog):
CustomLight()
assert "Light is deprecated, modify CustomLight" in caplog.text
async def test_profiles(hass):
"""Test profiles loading."""
profiles = orig_Profiles(hass)
await profiles.async_initialize()
assert profiles.data == {
"concentrate": (35.932, 69.412, 219, 0),
"energize": (43.333, 21.176, 203, 0),
"reading": (38.88, 49.02, 240, 0),
"relax": (35.932, 69.412, 144, 0),
}

View File

@ -0,0 +1,2 @@
"""litejet conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,2 @@
"""mochad conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -1 +1,2 @@
"""Test fixtures for mqtt component."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -7,6 +7,7 @@ from .common import MQTTMessage
from tests.async_mock import patch
from tests.common import load_fixture
from tests.components.light.conftest import mock_light_profiles # noqa
@pytest.fixture(name="generic_data", scope="session")

View File

@ -0,0 +1,2 @@
"""rflink conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -9,6 +9,7 @@ from homeassistant.util.dt import utcnow
from tests.async_mock import patch
from tests.common import MockConfigEntry, async_fire_time_changed
from tests.components.light.conftest import mock_light_profiles # noqa
def create_rfx_test_cfg(device="abcd", automatic_add=False, devices=None):

View File

@ -5,6 +5,7 @@ import pytest
import requests_mock
from tests.common import load_fixture
from tests.components.light.conftest import mock_light_profiles # noqa
@pytest.fixture(name="requests_mock")

View File

@ -47,6 +47,7 @@ from homeassistant.setup import async_setup_component
from tests.async_mock import Mock, patch
from tests.common import MockConfigEntry
from tests.components.light.conftest import mock_light_profiles # noqa
COMPONENT_PREFIX = "homeassistant.components.smartthings."

View File

@ -0,0 +1,2 @@
"""switch conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -1,5 +1,4 @@
"""Test fixtures for Tasmota component."""
from hatasmota.discovery import get_status_sensor_entities
import pytest
@ -17,6 +16,7 @@ from tests.common import (
mock_device_registry,
mock_registry,
)
from tests.components.light.conftest import mock_light_profiles # noqa
@pytest.fixture

View File

@ -0,0 +1,2 @@
"""template conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,2 @@
"""tplink conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -4,6 +4,7 @@ import pytest
from . import MOCK_GATEWAY_ID
from tests.async_mock import Mock, patch
from tests.components.light.conftest import mock_light_profiles # noqa
# pylint: disable=protected-access

View File

@ -1,10 +1,10 @@
"""Fixtures for tests."""
import pytest
from .common import ComponentFactory
from tests.async_mock import patch
from tests.components.light.conftest import mock_light_profiles # noqa
@pytest.fixture()

View File

@ -0,0 +1,2 @@
"""wilight conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,2 @@
"""wled conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,2 @@
"""yeelight conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -0,0 +1,2 @@
"""zerproc conftest."""
from tests.components.light.conftest import mock_light_profiles # noqa

View File

@ -1,5 +1,4 @@
"""Test configuration for the ZHA component."""
import pytest
import zigpy
from zigpy.application import ControllerApplication
@ -16,6 +15,7 @@ from .common import FakeDevice, FakeEndpoint, get_zha_gateway
from tests.async_mock import AsyncMock, MagicMock, PropertyMock, patch
from tests.common import MockConfigEntry
from tests.components.light.conftest import mock_light_profiles # noqa
FIXTURE_GRP_ID = 0x1001
FIXTURE_GRP_NAME = "fixture group"

View File

@ -4,6 +4,7 @@ import pytest
from homeassistant.components.zwave import const
from tests.async_mock import AsyncMock, MagicMock, patch
from tests.components.light.conftest import mock_light_profiles # noqa
from tests.mock.zwave import MockNetwork, MockNode, MockOption, MockValue