mirror of
https://github.com/python-kasa/python-kasa.git
synced 2025-10-10 09:28:02 +00:00
Refactor devices into subpackages and deprecate old names (#716)
* Refactor devices into subpackages and deprecate old names * Tweak and add tests * Fix linting * Remove duplicate implementations affecting project coverage * Update post review * Add device base class attributes and rename subclasses * Rename Module to BaseModule * Remove has_emeter_history * Fix missing _time in init * Update post review * Fix test_readmeexamples * Fix erroneously duped files * Clean up iot and smart imports * Update post latest review * Tweak Device docstring
This commit is contained in:
@@ -13,18 +13,14 @@ import pytest # type: ignore # see https://github.com/pytest-dev/pytest/issues/
|
||||
|
||||
from kasa import (
|
||||
Credentials,
|
||||
Device,
|
||||
DeviceConfig,
|
||||
Discover,
|
||||
SmartBulb,
|
||||
SmartDevice,
|
||||
SmartDimmer,
|
||||
SmartLightStrip,
|
||||
SmartPlug,
|
||||
SmartProtocol,
|
||||
SmartStrip,
|
||||
)
|
||||
from kasa.iot import IotBulb, IotDimmer, IotLightStrip, IotPlug, IotStrip
|
||||
from kasa.protocol import BaseTransport
|
||||
from kasa.tapo import TapoBulb, TapoPlug
|
||||
from kasa.smart import SmartBulb, SmartPlug
|
||||
from kasa.xortransport import XorEncryption
|
||||
|
||||
from .fakeprotocol_iot import FakeIotProtocol
|
||||
@@ -350,37 +346,37 @@ def device_for_file(model, protocol):
|
||||
if protocol == "SMART":
|
||||
for d in PLUGS_SMART:
|
||||
if d in model:
|
||||
return TapoPlug
|
||||
return SmartPlug
|
||||
for d in BULBS_SMART:
|
||||
if d in model:
|
||||
return TapoBulb
|
||||
return SmartBulb
|
||||
for d in DIMMERS_SMART:
|
||||
if d in model:
|
||||
return TapoBulb
|
||||
return SmartBulb
|
||||
for d in STRIPS_SMART:
|
||||
if d in model:
|
||||
return TapoPlug
|
||||
return SmartPlug
|
||||
else:
|
||||
for d in STRIPS_IOT:
|
||||
if d in model:
|
||||
return SmartStrip
|
||||
return IotStrip
|
||||
|
||||
for d in PLUGS_IOT:
|
||||
if d in model:
|
||||
return SmartPlug
|
||||
return IotPlug
|
||||
|
||||
# Light strips are recognized also as bulbs, so this has to go first
|
||||
for d in BULBS_IOT_LIGHT_STRIP:
|
||||
if d in model:
|
||||
return SmartLightStrip
|
||||
return IotLightStrip
|
||||
|
||||
for d in BULBS_IOT:
|
||||
if d in model:
|
||||
return SmartBulb
|
||||
return IotBulb
|
||||
|
||||
for d in DIMMERS_IOT:
|
||||
if d in model:
|
||||
return SmartDimmer
|
||||
return IotDimmer
|
||||
|
||||
raise Exception("Unable to find type for %s", model)
|
||||
|
||||
@@ -446,11 +442,11 @@ async def dev(request):
|
||||
IP_MODEL_CACHE[ip] = model = d.model
|
||||
if model not in file:
|
||||
pytest.skip(f"skipping file {file}")
|
||||
dev: SmartDevice = (
|
||||
dev: Device = (
|
||||
d if d else await _discover_update_and_close(ip, username, password)
|
||||
)
|
||||
else:
|
||||
dev: SmartDevice = await get_device_for_file(file, protocol)
|
||||
dev: Device = await get_device_for_file(file, protocol)
|
||||
|
||||
yield dev
|
||||
|
||||
|
@@ -7,7 +7,8 @@ from voluptuous import (
|
||||
Schema,
|
||||
)
|
||||
|
||||
from kasa import DeviceType, SmartBulb, SmartBulbPreset, SmartDeviceException
|
||||
from kasa import Bulb, BulbPreset, DeviceType, SmartDeviceException
|
||||
from kasa.iot import IotBulb
|
||||
|
||||
from .conftest import (
|
||||
bulb,
|
||||
@@ -27,7 +28,7 @@ from .test_smartdevice import SYSINFO_SCHEMA
|
||||
|
||||
|
||||
@bulb
|
||||
async def test_bulb_sysinfo(dev: SmartBulb):
|
||||
async def test_bulb_sysinfo(dev: Bulb):
|
||||
assert dev.sys_info is not None
|
||||
SYSINFO_SCHEMA_BULB(dev.sys_info)
|
||||
|
||||
@@ -40,7 +41,7 @@ async def test_bulb_sysinfo(dev: SmartBulb):
|
||||
|
||||
|
||||
@bulb
|
||||
async def test_state_attributes(dev: SmartBulb):
|
||||
async def test_state_attributes(dev: Bulb):
|
||||
assert "Brightness" in dev.state_information
|
||||
assert dev.state_information["Brightness"] == dev.brightness
|
||||
|
||||
@@ -49,7 +50,7 @@ async def test_state_attributes(dev: SmartBulb):
|
||||
|
||||
|
||||
@bulb_iot
|
||||
async def test_light_state_without_update(dev: SmartBulb, monkeypatch):
|
||||
async def test_light_state_without_update(dev: IotBulb, monkeypatch):
|
||||
with pytest.raises(SmartDeviceException):
|
||||
monkeypatch.setitem(
|
||||
dev._last_update["system"]["get_sysinfo"], "light_state", None
|
||||
@@ -58,13 +59,13 @@ async def test_light_state_without_update(dev: SmartBulb, monkeypatch):
|
||||
|
||||
|
||||
@bulb_iot
|
||||
async def test_get_light_state(dev: SmartBulb):
|
||||
async def test_get_light_state(dev: IotBulb):
|
||||
LIGHT_STATE_SCHEMA(await dev.get_light_state())
|
||||
|
||||
|
||||
@color_bulb
|
||||
@turn_on
|
||||
async def test_hsv(dev: SmartBulb, turn_on):
|
||||
async def test_hsv(dev: Bulb, turn_on):
|
||||
await handle_turn_on(dev, turn_on)
|
||||
assert dev.is_color
|
||||
|
||||
@@ -83,8 +84,8 @@ async def test_hsv(dev: SmartBulb, turn_on):
|
||||
|
||||
|
||||
@color_bulb_iot
|
||||
async def test_set_hsv_transition(dev: SmartBulb, mocker):
|
||||
set_light_state = mocker.patch("kasa.SmartBulb.set_light_state")
|
||||
async def test_set_hsv_transition(dev: IotBulb, mocker):
|
||||
set_light_state = mocker.patch("kasa.iot.IotBulb.set_light_state")
|
||||
await dev.set_hsv(10, 10, 100, transition=1000)
|
||||
|
||||
set_light_state.assert_called_with(
|
||||
@@ -95,31 +96,31 @@ async def test_set_hsv_transition(dev: SmartBulb, mocker):
|
||||
|
||||
@color_bulb
|
||||
@turn_on
|
||||
async def test_invalid_hsv(dev: SmartBulb, turn_on):
|
||||
async def test_invalid_hsv(dev: Bulb, turn_on):
|
||||
await handle_turn_on(dev, turn_on)
|
||||
assert dev.is_color
|
||||
|
||||
for invalid_hue in [-1, 361, 0.5]:
|
||||
with pytest.raises(ValueError):
|
||||
await dev.set_hsv(invalid_hue, 0, 0)
|
||||
await dev.set_hsv(invalid_hue, 0, 0) # type: ignore[arg-type]
|
||||
|
||||
for invalid_saturation in [-1, 101, 0.5]:
|
||||
with pytest.raises(ValueError):
|
||||
await dev.set_hsv(0, invalid_saturation, 0)
|
||||
await dev.set_hsv(0, invalid_saturation, 0) # type: ignore[arg-type]
|
||||
|
||||
for invalid_brightness in [-1, 101, 0.5]:
|
||||
with pytest.raises(ValueError):
|
||||
await dev.set_hsv(0, 0, invalid_brightness)
|
||||
await dev.set_hsv(0, 0, invalid_brightness) # type: ignore[arg-type]
|
||||
|
||||
|
||||
@color_bulb
|
||||
async def test_color_state_information(dev: SmartBulb):
|
||||
async def test_color_state_information(dev: Bulb):
|
||||
assert "HSV" in dev.state_information
|
||||
assert dev.state_information["HSV"] == dev.hsv
|
||||
|
||||
|
||||
@non_color_bulb
|
||||
async def test_hsv_on_non_color(dev: SmartBulb):
|
||||
async def test_hsv_on_non_color(dev: Bulb):
|
||||
assert not dev.is_color
|
||||
|
||||
with pytest.raises(SmartDeviceException):
|
||||
@@ -129,7 +130,7 @@ async def test_hsv_on_non_color(dev: SmartBulb):
|
||||
|
||||
|
||||
@variable_temp
|
||||
async def test_variable_temp_state_information(dev: SmartBulb):
|
||||
async def test_variable_temp_state_information(dev: Bulb):
|
||||
assert "Color temperature" in dev.state_information
|
||||
assert dev.state_information["Color temperature"] == dev.color_temp
|
||||
|
||||
@@ -141,7 +142,7 @@ async def test_variable_temp_state_information(dev: SmartBulb):
|
||||
|
||||
@variable_temp
|
||||
@turn_on
|
||||
async def test_try_set_colortemp(dev: SmartBulb, turn_on):
|
||||
async def test_try_set_colortemp(dev: Bulb, turn_on):
|
||||
await handle_turn_on(dev, turn_on)
|
||||
await dev.set_color_temp(2700)
|
||||
await dev.update()
|
||||
@@ -149,15 +150,15 @@ async def test_try_set_colortemp(dev: SmartBulb, turn_on):
|
||||
|
||||
|
||||
@variable_temp_iot
|
||||
async def test_set_color_temp_transition(dev: SmartBulb, mocker):
|
||||
set_light_state = mocker.patch("kasa.SmartBulb.set_light_state")
|
||||
async def test_set_color_temp_transition(dev: IotBulb, mocker):
|
||||
set_light_state = mocker.patch("kasa.iot.IotBulb.set_light_state")
|
||||
await dev.set_color_temp(2700, transition=100)
|
||||
|
||||
set_light_state.assert_called_with({"color_temp": 2700}, transition=100)
|
||||
|
||||
|
||||
@variable_temp_iot
|
||||
async def test_unknown_temp_range(dev: SmartBulb, monkeypatch, caplog):
|
||||
async def test_unknown_temp_range(dev: IotBulb, monkeypatch, caplog):
|
||||
monkeypatch.setitem(dev._sys_info, "model", "unknown bulb")
|
||||
|
||||
assert dev.valid_temperature_range == (2700, 5000)
|
||||
@@ -165,7 +166,7 @@ async def test_unknown_temp_range(dev: SmartBulb, monkeypatch, caplog):
|
||||
|
||||
|
||||
@variable_temp
|
||||
async def test_out_of_range_temperature(dev: SmartBulb):
|
||||
async def test_out_of_range_temperature(dev: Bulb):
|
||||
with pytest.raises(ValueError):
|
||||
await dev.set_color_temp(1000)
|
||||
with pytest.raises(ValueError):
|
||||
@@ -173,7 +174,7 @@ async def test_out_of_range_temperature(dev: SmartBulb):
|
||||
|
||||
|
||||
@non_variable_temp
|
||||
async def test_non_variable_temp(dev: SmartBulb):
|
||||
async def test_non_variable_temp(dev: Bulb):
|
||||
with pytest.raises(SmartDeviceException):
|
||||
await dev.set_color_temp(2700)
|
||||
|
||||
@@ -186,7 +187,7 @@ async def test_non_variable_temp(dev: SmartBulb):
|
||||
|
||||
@dimmable
|
||||
@turn_on
|
||||
async def test_dimmable_brightness(dev: SmartBulb, turn_on):
|
||||
async def test_dimmable_brightness(dev: Bulb, turn_on):
|
||||
await handle_turn_on(dev, turn_on)
|
||||
assert dev.is_dimmable
|
||||
|
||||
@@ -199,12 +200,12 @@ async def test_dimmable_brightness(dev: SmartBulb, turn_on):
|
||||
assert dev.brightness == 10
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
await dev.set_brightness("foo")
|
||||
await dev.set_brightness("foo") # type: ignore[arg-type]
|
||||
|
||||
|
||||
@bulb_iot
|
||||
async def test_turn_on_transition(dev: SmartBulb, mocker):
|
||||
set_light_state = mocker.patch("kasa.SmartBulb.set_light_state")
|
||||
async def test_turn_on_transition(dev: IotBulb, mocker):
|
||||
set_light_state = mocker.patch("kasa.iot.IotBulb.set_light_state")
|
||||
await dev.turn_on(transition=1000)
|
||||
|
||||
set_light_state.assert_called_with({"on_off": 1}, transition=1000)
|
||||
@@ -215,15 +216,15 @@ async def test_turn_on_transition(dev: SmartBulb, mocker):
|
||||
|
||||
|
||||
@bulb_iot
|
||||
async def test_dimmable_brightness_transition(dev: SmartBulb, mocker):
|
||||
set_light_state = mocker.patch("kasa.SmartBulb.set_light_state")
|
||||
async def test_dimmable_brightness_transition(dev: IotBulb, mocker):
|
||||
set_light_state = mocker.patch("kasa.iot.IotBulb.set_light_state")
|
||||
await dev.set_brightness(10, transition=1000)
|
||||
|
||||
set_light_state.assert_called_with({"brightness": 10}, transition=1000)
|
||||
|
||||
|
||||
@dimmable
|
||||
async def test_invalid_brightness(dev: SmartBulb):
|
||||
async def test_invalid_brightness(dev: Bulb):
|
||||
assert dev.is_dimmable
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
@@ -234,7 +235,7 @@ async def test_invalid_brightness(dev: SmartBulb):
|
||||
|
||||
|
||||
@non_dimmable
|
||||
async def test_non_dimmable(dev: SmartBulb):
|
||||
async def test_non_dimmable(dev: Bulb):
|
||||
assert not dev.is_dimmable
|
||||
|
||||
with pytest.raises(SmartDeviceException):
|
||||
@@ -245,9 +246,9 @@ async def test_non_dimmable(dev: SmartBulb):
|
||||
|
||||
@bulb_iot
|
||||
async def test_ignore_default_not_set_without_color_mode_change_turn_on(
|
||||
dev: SmartBulb, mocker
|
||||
dev: IotBulb, mocker
|
||||
):
|
||||
query_helper = mocker.patch("kasa.SmartBulb._query_helper")
|
||||
query_helper = mocker.patch("kasa.iot.IotBulb._query_helper")
|
||||
# When turning back without settings, ignore default to restore the state
|
||||
await dev.turn_on()
|
||||
args, kwargs = query_helper.call_args_list[0]
|
||||
@@ -259,7 +260,7 @@ async def test_ignore_default_not_set_without_color_mode_change_turn_on(
|
||||
|
||||
|
||||
@bulb_iot
|
||||
async def test_list_presets(dev: SmartBulb):
|
||||
async def test_list_presets(dev: IotBulb):
|
||||
presets = dev.presets
|
||||
assert len(presets) == len(dev.sys_info["preferred_state"])
|
||||
|
||||
@@ -272,7 +273,7 @@ async def test_list_presets(dev: SmartBulb):
|
||||
|
||||
|
||||
@bulb_iot
|
||||
async def test_modify_preset(dev: SmartBulb, mocker):
|
||||
async def test_modify_preset(dev: IotBulb, mocker):
|
||||
"""Verify that modifying preset calls the and exceptions are raised properly."""
|
||||
if not dev.presets:
|
||||
pytest.skip("Some strips do not support presets")
|
||||
@@ -284,7 +285,7 @@ async def test_modify_preset(dev: SmartBulb, mocker):
|
||||
"saturation": 0,
|
||||
"color_temp": 0,
|
||||
}
|
||||
preset = SmartBulbPreset(**data)
|
||||
preset = BulbPreset(**data)
|
||||
|
||||
assert preset.index == 0
|
||||
assert preset.brightness == 10
|
||||
@@ -297,7 +298,7 @@ async def test_modify_preset(dev: SmartBulb, mocker):
|
||||
|
||||
with pytest.raises(SmartDeviceException):
|
||||
await dev.save_preset(
|
||||
SmartBulbPreset(index=5, hue=0, brightness=0, saturation=0, color_temp=0)
|
||||
BulbPreset(index=5, hue=0, brightness=0, saturation=0, color_temp=0)
|
||||
)
|
||||
|
||||
|
||||
@@ -306,21 +307,21 @@ async def test_modify_preset(dev: SmartBulb, mocker):
|
||||
("preset", "payload"),
|
||||
[
|
||||
(
|
||||
SmartBulbPreset(index=0, hue=0, brightness=1, saturation=0),
|
||||
BulbPreset(index=0, hue=0, brightness=1, saturation=0),
|
||||
{"index": 0, "hue": 0, "brightness": 1, "saturation": 0},
|
||||
),
|
||||
(
|
||||
SmartBulbPreset(index=0, brightness=1, id="testid", mode=2, custom=0),
|
||||
BulbPreset(index=0, brightness=1, id="testid", mode=2, custom=0),
|
||||
{"index": 0, "brightness": 1, "id": "testid", "mode": 2, "custom": 0},
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_modify_preset_payloads(dev: SmartBulb, preset, payload, mocker):
|
||||
async def test_modify_preset_payloads(dev: IotBulb, preset, payload, mocker):
|
||||
"""Test that modify preset payloads ignore none values."""
|
||||
if not dev.presets:
|
||||
pytest.skip("Some strips do not support presets")
|
||||
|
||||
query_helper = mocker.patch("kasa.SmartBulb._query_helper")
|
||||
query_helper = mocker.patch("kasa.iot.IotBulb._query_helper")
|
||||
await dev.save_preset(preset)
|
||||
query_helper.assert_called_with(dev.LIGHT_SERVICE, "set_preferred_state", payload)
|
||||
|
||||
|
@@ -3,8 +3,8 @@ import sys
|
||||
|
||||
import pytest
|
||||
|
||||
from kasa.smart.smartchilddevice import SmartChildDevice
|
||||
from kasa.smartprotocol import _ChildProtocolWrapper
|
||||
from kasa.tapo.childdevice import ChildDevice
|
||||
|
||||
from .conftest import strip_smart
|
||||
|
||||
@@ -42,7 +42,7 @@ async def test_childdevice_update(dev, dummy_protocol, mocker):
|
||||
sys.version_info < (3, 11),
|
||||
reason="exceptiongroup requires python3.11+",
|
||||
)
|
||||
async def test_childdevice_properties(dev: ChildDevice):
|
||||
async def test_childdevice_properties(dev: SmartChildDevice):
|
||||
"""Check that accessing childdevice properties do not raise exceptions."""
|
||||
assert len(dev.children) > 0
|
||||
|
||||
|
@@ -7,8 +7,8 @@ from asyncclick.testing import CliRunner
|
||||
|
||||
from kasa import (
|
||||
AuthenticationException,
|
||||
Device,
|
||||
EmeterStatus,
|
||||
SmartDevice,
|
||||
SmartDeviceException,
|
||||
UnsupportedDeviceException,
|
||||
)
|
||||
@@ -27,6 +27,7 @@ from kasa.cli import (
|
||||
wifi,
|
||||
)
|
||||
from kasa.discover import Discover, DiscoveryResult
|
||||
from kasa.iot import IotDevice
|
||||
|
||||
from .conftest import device_iot, device_smart, handle_turn_on, new_discovery, turn_on
|
||||
|
||||
@@ -107,9 +108,9 @@ async def test_alias(dev):
|
||||
async def test_raw_command(dev, mocker):
|
||||
runner = CliRunner()
|
||||
update = mocker.patch.object(dev, "update")
|
||||
from kasa.tapo import TapoDevice
|
||||
from kasa.smart import SmartDevice
|
||||
|
||||
if isinstance(dev, TapoDevice):
|
||||
if isinstance(dev, SmartDevice):
|
||||
params = ["na", "get_device_info"]
|
||||
else:
|
||||
params = ["system", "get_sysinfo"]
|
||||
@@ -216,7 +217,7 @@ async def test_update_credentials(dev):
|
||||
)
|
||||
|
||||
|
||||
async def test_emeter(dev: SmartDevice, mocker):
|
||||
async def test_emeter(dev: Device, mocker):
|
||||
runner = CliRunner()
|
||||
|
||||
res = await runner.invoke(emeter, obj=dev)
|
||||
@@ -245,16 +246,24 @@ async def test_emeter(dev: SmartDevice, mocker):
|
||||
assert "Voltage: 122.066 V" in res.output
|
||||
assert realtime_emeter.call_count == 2
|
||||
|
||||
monthly = mocker.patch.object(dev, "get_emeter_monthly")
|
||||
monthly.return_value = {1: 1234}
|
||||
if isinstance(dev, IotDevice):
|
||||
monthly = mocker.patch.object(dev, "get_emeter_monthly")
|
||||
monthly.return_value = {1: 1234}
|
||||
res = await runner.invoke(emeter, ["--year", "1900"], obj=dev)
|
||||
if not isinstance(dev, IotDevice):
|
||||
assert "Device has no historical statistics" in res.output
|
||||
return
|
||||
assert "For year" in res.output
|
||||
assert "1, 1234" in res.output
|
||||
monthly.assert_called_with(year=1900)
|
||||
|
||||
daily = mocker.patch.object(dev, "get_emeter_daily")
|
||||
daily.return_value = {1: 1234}
|
||||
if isinstance(dev, IotDevice):
|
||||
daily = mocker.patch.object(dev, "get_emeter_daily")
|
||||
daily.return_value = {1: 1234}
|
||||
res = await runner.invoke(emeter, ["--month", "1900-12"], obj=dev)
|
||||
if not isinstance(dev, IotDevice):
|
||||
assert "Device has no historical statistics" in res.output
|
||||
return
|
||||
assert "For month" in res.output
|
||||
assert "1, 1234" in res.output
|
||||
daily.assert_called_with(year=1900, month=12)
|
||||
@@ -279,7 +288,7 @@ async def test_brightness(dev):
|
||||
|
||||
|
||||
@device_iot
|
||||
async def test_json_output(dev: SmartDevice, mocker):
|
||||
async def test_json_output(dev: Device, mocker):
|
||||
"""Test that the json output produces correct output."""
|
||||
mocker.patch("kasa.Discover.discover", return_value=[dev])
|
||||
runner = CliRunner()
|
||||
@@ -292,10 +301,10 @@ async def test_json_output(dev: SmartDevice, mocker):
|
||||
async def test_credentials(discovery_mock, mocker):
|
||||
"""Test credentials are passed correctly from cli to device."""
|
||||
# Patch state to echo username and password
|
||||
pass_dev = click.make_pass_decorator(SmartDevice)
|
||||
pass_dev = click.make_pass_decorator(Device)
|
||||
|
||||
@pass_dev
|
||||
async def _state(dev: SmartDevice):
|
||||
async def _state(dev: Device):
|
||||
if dev.credentials:
|
||||
click.echo(
|
||||
f"Username:{dev.credentials.username} Password:{dev.credentials.password}"
|
||||
@@ -513,10 +522,10 @@ async def test_type_param(device_type, mocker):
|
||||
runner = CliRunner()
|
||||
|
||||
result_device = FileNotFoundError
|
||||
pass_dev = click.make_pass_decorator(SmartDevice)
|
||||
pass_dev = click.make_pass_decorator(Device)
|
||||
|
||||
@pass_dev
|
||||
async def _state(dev: SmartDevice):
|
||||
async def _state(dev: Device):
|
||||
nonlocal result_device
|
||||
result_device = dev
|
||||
|
||||
|
@@ -6,8 +6,8 @@ import pytest # type: ignore # https://github.com/pytest-dev/pytest/issues/3342
|
||||
|
||||
from kasa import (
|
||||
Credentials,
|
||||
Device,
|
||||
Discover,
|
||||
SmartDevice,
|
||||
SmartDeviceException,
|
||||
)
|
||||
from kasa.device_factory import connect, get_protocol
|
||||
@@ -83,7 +83,7 @@ async def test_connect_custom_port(all_fixture_data: dict, mocker, custom_port):
|
||||
mocker.patch("kasa.IotProtocol.query", return_value=all_fixture_data)
|
||||
mocker.patch("kasa.SmartProtocol.query", return_value=all_fixture_data)
|
||||
dev = await connect(config=config)
|
||||
assert issubclass(dev.__class__, SmartDevice)
|
||||
assert issubclass(dev.__class__, Device)
|
||||
assert dev.port == custom_port or dev.port == default_port
|
||||
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
from kasa.smartdevice import DeviceType
|
||||
from kasa.device_type import DeviceType
|
||||
|
||||
|
||||
async def test_device_type_from_value():
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import pytest
|
||||
|
||||
from kasa import SmartDimmer
|
||||
from kasa.iot import IotDimmer
|
||||
|
||||
from .conftest import dimmer, handle_turn_on, turn_on
|
||||
|
||||
@@ -23,7 +23,7 @@ async def test_set_brightness(dev, turn_on):
|
||||
@turn_on
|
||||
async def test_set_brightness_transition(dev, turn_on, mocker):
|
||||
await handle_turn_on(dev, turn_on)
|
||||
query_helper = mocker.spy(SmartDimmer, "_query_helper")
|
||||
query_helper = mocker.spy(IotDimmer, "_query_helper")
|
||||
|
||||
await dev.set_brightness(99, transition=1000)
|
||||
|
||||
@@ -53,7 +53,7 @@ async def test_set_brightness_invalid(dev):
|
||||
|
||||
@dimmer
|
||||
async def test_turn_on_transition(dev, mocker):
|
||||
query_helper = mocker.spy(SmartDimmer, "_query_helper")
|
||||
query_helper = mocker.spy(IotDimmer, "_query_helper")
|
||||
original_brightness = dev.brightness
|
||||
|
||||
await dev.turn_on(transition=1000)
|
||||
@@ -71,7 +71,7 @@ async def test_turn_on_transition(dev, mocker):
|
||||
@dimmer
|
||||
async def test_turn_off_transition(dev, mocker):
|
||||
await handle_turn_on(dev, True)
|
||||
query_helper = mocker.spy(SmartDimmer, "_query_helper")
|
||||
query_helper = mocker.spy(IotDimmer, "_query_helper")
|
||||
original_brightness = dev.brightness
|
||||
|
||||
await dev.turn_off(transition=1000)
|
||||
@@ -90,7 +90,7 @@ async def test_turn_off_transition(dev, mocker):
|
||||
@turn_on
|
||||
async def test_set_dimmer_transition(dev, turn_on, mocker):
|
||||
await handle_turn_on(dev, turn_on)
|
||||
query_helper = mocker.spy(SmartDimmer, "_query_helper")
|
||||
query_helper = mocker.spy(IotDimmer, "_query_helper")
|
||||
|
||||
await dev.set_dimmer_transition(99, 1000)
|
||||
|
||||
@@ -109,7 +109,7 @@ async def test_set_dimmer_transition(dev, turn_on, mocker):
|
||||
async def test_set_dimmer_transition_to_off(dev, turn_on, mocker):
|
||||
await handle_turn_on(dev, turn_on)
|
||||
original_brightness = dev.brightness
|
||||
query_helper = mocker.spy(SmartDimmer, "_query_helper")
|
||||
query_helper = mocker.spy(IotDimmer, "_query_helper")
|
||||
|
||||
await dev.set_dimmer_transition(0, 1000)
|
||||
|
||||
|
@@ -10,9 +10,9 @@ from async_timeout import timeout as asyncio_timeout
|
||||
|
||||
from kasa import (
|
||||
Credentials,
|
||||
Device,
|
||||
DeviceType,
|
||||
Discover,
|
||||
SmartDevice,
|
||||
SmartDeviceException,
|
||||
)
|
||||
from kasa.deviceconfig import (
|
||||
@@ -21,6 +21,7 @@ from kasa.deviceconfig import (
|
||||
)
|
||||
from kasa.discover import DiscoveryResult, _DiscoverProtocol, json_dumps
|
||||
from kasa.exceptions import AuthenticationException, UnsupportedDeviceException
|
||||
from kasa.iot import IotDevice
|
||||
from kasa.xortransport import XorEncryption
|
||||
|
||||
from .conftest import (
|
||||
@@ -55,14 +56,14 @@ UNSUPPORTED = {
|
||||
|
||||
|
||||
@plug
|
||||
async def test_type_detection_plug(dev: SmartDevice):
|
||||
async def test_type_detection_plug(dev: Device):
|
||||
d = Discover._get_device_class(dev._last_update)("localhost")
|
||||
assert d.is_plug
|
||||
assert d.device_type == DeviceType.Plug
|
||||
|
||||
|
||||
@bulb_iot
|
||||
async def test_type_detection_bulb(dev: SmartDevice):
|
||||
async def test_type_detection_bulb(dev: Device):
|
||||
d = Discover._get_device_class(dev._last_update)("localhost")
|
||||
# TODO: light_strip is a special case for now to force bulb tests on it
|
||||
if not d.is_light_strip:
|
||||
@@ -71,21 +72,21 @@ async def test_type_detection_bulb(dev: SmartDevice):
|
||||
|
||||
|
||||
@strip_iot
|
||||
async def test_type_detection_strip(dev: SmartDevice):
|
||||
async def test_type_detection_strip(dev: Device):
|
||||
d = Discover._get_device_class(dev._last_update)("localhost")
|
||||
assert d.is_strip
|
||||
assert d.device_type == DeviceType.Strip
|
||||
|
||||
|
||||
@dimmer
|
||||
async def test_type_detection_dimmer(dev: SmartDevice):
|
||||
async def test_type_detection_dimmer(dev: Device):
|
||||
d = Discover._get_device_class(dev._last_update)("localhost")
|
||||
assert d.is_dimmer
|
||||
assert d.device_type == DeviceType.Dimmer
|
||||
|
||||
|
||||
@lightstrip
|
||||
async def test_type_detection_lightstrip(dev: SmartDevice):
|
||||
async def test_type_detection_lightstrip(dev: Device):
|
||||
d = Discover._get_device_class(dev._last_update)("localhost")
|
||||
assert d.is_light_strip
|
||||
assert d.device_type == DeviceType.LightStrip
|
||||
@@ -111,7 +112,7 @@ async def test_discover_single(discovery_mock, custom_port, mocker):
|
||||
x = await Discover.discover_single(
|
||||
host, port=custom_port, credentials=Credentials()
|
||||
)
|
||||
assert issubclass(x.__class__, SmartDevice)
|
||||
assert issubclass(x.__class__, Device)
|
||||
assert x._discovery_info is not None
|
||||
assert x.port == custom_port or x.port == discovery_mock.default_port
|
||||
assert update_mock.call_count == 0
|
||||
@@ -144,7 +145,7 @@ async def test_discover_single_hostname(discovery_mock, mocker):
|
||||
update_mock = mocker.patch.object(device_class, "update")
|
||||
|
||||
x = await Discover.discover_single(host, credentials=Credentials())
|
||||
assert issubclass(x.__class__, SmartDevice)
|
||||
assert issubclass(x.__class__, Device)
|
||||
assert x._discovery_info is not None
|
||||
assert x.host == host
|
||||
assert update_mock.call_count == 0
|
||||
@@ -232,7 +233,7 @@ async def test_discover_datagram_received(mocker, discovery_data):
|
||||
# Check that unsupported device is 1
|
||||
assert len(proto.unsupported_device_exceptions) == 1
|
||||
dev = proto.discovered_devices[addr]
|
||||
assert issubclass(dev.__class__, SmartDevice)
|
||||
assert issubclass(dev.__class__, Device)
|
||||
assert dev.host == addr
|
||||
|
||||
|
||||
@@ -298,7 +299,7 @@ async def test_discover_single_authentication(discovery_mock, mocker):
|
||||
|
||||
@new_discovery
|
||||
async def test_device_update_from_new_discovery_info(discovery_data):
|
||||
device = SmartDevice("127.0.0.7")
|
||||
device = IotDevice("127.0.0.7")
|
||||
discover_info = DiscoveryResult(**discovery_data["result"])
|
||||
discover_dump = discover_info.get_dict()
|
||||
discover_dump["alias"] = "foobar"
|
||||
@@ -323,7 +324,7 @@ async def test_discover_single_http_client(discovery_mock, mocker):
|
||||
|
||||
http_client = aiohttp.ClientSession()
|
||||
|
||||
x: SmartDevice = await Discover.discover_single(host)
|
||||
x: Device = await Discover.discover_single(host)
|
||||
|
||||
assert x.config.uses_http == (discovery_mock.default_port == 80)
|
||||
|
||||
@@ -341,7 +342,7 @@ async def test_discover_http_client(discovery_mock, mocker):
|
||||
http_client = aiohttp.ClientSession()
|
||||
|
||||
devices = await Discover.discover(discovery_timeout=0)
|
||||
x: SmartDevice = devices[host]
|
||||
x: Device = devices[host]
|
||||
assert x.config.uses_http == (discovery_mock.default_port == 80)
|
||||
|
||||
if discovery_mock.default_port == 80:
|
||||
|
@@ -11,7 +11,8 @@ from voluptuous import (
|
||||
)
|
||||
|
||||
from kasa import EmeterStatus, SmartDeviceException
|
||||
from kasa.modules.emeter import Emeter
|
||||
from kasa.iot import IotDevice
|
||||
from kasa.iot.modules.emeter import Emeter
|
||||
|
||||
from .conftest import has_emeter, has_emeter_iot, no_emeter
|
||||
|
||||
@@ -39,12 +40,15 @@ async def test_no_emeter(dev):
|
||||
|
||||
with pytest.raises(SmartDeviceException):
|
||||
await dev.get_emeter_realtime()
|
||||
with pytest.raises(SmartDeviceException):
|
||||
await dev.get_emeter_daily()
|
||||
with pytest.raises(SmartDeviceException):
|
||||
await dev.get_emeter_monthly()
|
||||
with pytest.raises(SmartDeviceException):
|
||||
await dev.erase_emeter_stats()
|
||||
# Only iot devices support the historical stats so other
|
||||
# devices will not implement the methods below
|
||||
if isinstance(dev, IotDevice):
|
||||
with pytest.raises(SmartDeviceException):
|
||||
await dev.get_emeter_daily()
|
||||
with pytest.raises(SmartDeviceException):
|
||||
await dev.get_emeter_monthly()
|
||||
with pytest.raises(SmartDeviceException):
|
||||
await dev.erase_emeter_stats()
|
||||
|
||||
|
||||
@has_emeter
|
||||
@@ -121,7 +125,7 @@ async def test_erase_emeter_stats(dev):
|
||||
await dev.erase_emeter()
|
||||
|
||||
|
||||
@has_emeter
|
||||
@has_emeter_iot
|
||||
async def test_current_consumption(dev):
|
||||
if dev.has_emeter:
|
||||
x = await dev.current_consumption()
|
||||
|
@@ -1,27 +1,28 @@
|
||||
import pytest
|
||||
|
||||
from kasa import DeviceType, SmartLightStrip
|
||||
from kasa import DeviceType
|
||||
from kasa.exceptions import SmartDeviceException
|
||||
from kasa.iot import IotLightStrip
|
||||
|
||||
from .conftest import lightstrip
|
||||
|
||||
|
||||
@lightstrip
|
||||
async def test_lightstrip_length(dev: SmartLightStrip):
|
||||
async def test_lightstrip_length(dev: IotLightStrip):
|
||||
assert dev.is_light_strip
|
||||
assert dev.device_type == DeviceType.LightStrip
|
||||
assert dev.length == dev.sys_info["length"]
|
||||
|
||||
|
||||
@lightstrip
|
||||
async def test_lightstrip_effect(dev: SmartLightStrip):
|
||||
async def test_lightstrip_effect(dev: IotLightStrip):
|
||||
assert isinstance(dev.effect, dict)
|
||||
for k in ["brightness", "custom", "enable", "id", "name"]:
|
||||
assert k in dev.effect
|
||||
|
||||
|
||||
@lightstrip
|
||||
async def test_effects_lightstrip_set_effect(dev: SmartLightStrip):
|
||||
async def test_effects_lightstrip_set_effect(dev: IotLightStrip):
|
||||
with pytest.raises(SmartDeviceException):
|
||||
await dev.set_effect("Not real")
|
||||
|
||||
@@ -33,9 +34,9 @@ async def test_effects_lightstrip_set_effect(dev: SmartLightStrip):
|
||||
@lightstrip
|
||||
@pytest.mark.parametrize("brightness", [100, 50])
|
||||
async def test_effects_lightstrip_set_effect_brightness(
|
||||
dev: SmartLightStrip, brightness, mocker
|
||||
dev: IotLightStrip, brightness, mocker
|
||||
):
|
||||
query_helper = mocker.patch("kasa.SmartLightStrip._query_helper")
|
||||
query_helper = mocker.patch("kasa.iot.IotLightStrip._query_helper")
|
||||
|
||||
# test that default brightness works (100 for candy cane)
|
||||
if brightness == 100:
|
||||
@@ -51,9 +52,9 @@ async def test_effects_lightstrip_set_effect_brightness(
|
||||
@lightstrip
|
||||
@pytest.mark.parametrize("transition", [500, 1000])
|
||||
async def test_effects_lightstrip_set_effect_transition(
|
||||
dev: SmartLightStrip, transition, mocker
|
||||
dev: IotLightStrip, transition, mocker
|
||||
):
|
||||
query_helper = mocker.patch("kasa.SmartLightStrip._query_helper")
|
||||
query_helper = mocker.patch("kasa.iot.IotLightStrip._query_helper")
|
||||
|
||||
# test that default (500 for candy cane) transition works
|
||||
if transition == 500:
|
||||
@@ -67,6 +68,6 @@ async def test_effects_lightstrip_set_effect_transition(
|
||||
|
||||
|
||||
@lightstrip
|
||||
async def test_effects_lightstrip_has_effects(dev: SmartLightStrip):
|
||||
async def test_effects_lightstrip_has_effects(dev: IotLightStrip):
|
||||
assert dev.has_effects is True
|
||||
assert dev.effect_list
|
||||
|
@@ -8,54 +8,54 @@ from kasa.tests.conftest import get_device_for_file
|
||||
def test_bulb_examples(mocker):
|
||||
"""Use KL130 (bulb with all features) to test the doctests."""
|
||||
p = asyncio.run(get_device_for_file("KL130(US)_1.0_1.8.11.json", "IOT"))
|
||||
mocker.patch("kasa.smartbulb.SmartBulb", return_value=p)
|
||||
mocker.patch("kasa.smartbulb.SmartBulb.update")
|
||||
res = xdoctest.doctest_module("kasa.smartbulb", "all")
|
||||
mocker.patch("kasa.iot.iotbulb.IotBulb", return_value=p)
|
||||
mocker.patch("kasa.iot.iotbulb.IotBulb.update")
|
||||
res = xdoctest.doctest_module("kasa.iot.iotbulb", "all")
|
||||
assert not res["failed"]
|
||||
|
||||
|
||||
def test_smartdevice_examples(mocker):
|
||||
"""Use HS110 for emeter examples."""
|
||||
p = asyncio.run(get_device_for_file("HS110(EU)_1.0_1.2.5.json", "IOT"))
|
||||
mocker.patch("kasa.smartdevice.SmartDevice", return_value=p)
|
||||
mocker.patch("kasa.smartdevice.SmartDevice.update")
|
||||
res = xdoctest.doctest_module("kasa.smartdevice", "all")
|
||||
mocker.patch("kasa.iot.iotdevice.IotDevice", return_value=p)
|
||||
mocker.patch("kasa.iot.iotdevice.IotDevice.update")
|
||||
res = xdoctest.doctest_module("kasa.iot.iotdevice", "all")
|
||||
assert not res["failed"]
|
||||
|
||||
|
||||
def test_plug_examples(mocker):
|
||||
"""Test plug examples."""
|
||||
p = asyncio.run(get_device_for_file("HS110(EU)_1.0_1.2.5.json", "IOT"))
|
||||
mocker.patch("kasa.smartplug.SmartPlug", return_value=p)
|
||||
mocker.patch("kasa.smartplug.SmartPlug.update")
|
||||
res = xdoctest.doctest_module("kasa.smartplug", "all")
|
||||
mocker.patch("kasa.iot.iotplug.IotPlug", return_value=p)
|
||||
mocker.patch("kasa.iot.iotplug.IotPlug.update")
|
||||
res = xdoctest.doctest_module("kasa.iot.iotplug", "all")
|
||||
assert not res["failed"]
|
||||
|
||||
|
||||
def test_strip_examples(mocker):
|
||||
"""Test strip examples."""
|
||||
p = asyncio.run(get_device_for_file("KP303(UK)_1.0_1.0.3.json", "IOT"))
|
||||
mocker.patch("kasa.smartstrip.SmartStrip", return_value=p)
|
||||
mocker.patch("kasa.smartstrip.SmartStrip.update")
|
||||
res = xdoctest.doctest_module("kasa.smartstrip", "all")
|
||||
mocker.patch("kasa.iot.iotstrip.IotStrip", return_value=p)
|
||||
mocker.patch("kasa.iot.iotstrip.IotStrip.update")
|
||||
res = xdoctest.doctest_module("kasa.iot.iotstrip", "all")
|
||||
assert not res["failed"]
|
||||
|
||||
|
||||
def test_dimmer_examples(mocker):
|
||||
"""Test dimmer examples."""
|
||||
p = asyncio.run(get_device_for_file("HS220(US)_1.0_1.5.7.json", "IOT"))
|
||||
mocker.patch("kasa.smartdimmer.SmartDimmer", return_value=p)
|
||||
mocker.patch("kasa.smartdimmer.SmartDimmer.update")
|
||||
res = xdoctest.doctest_module("kasa.smartdimmer", "all")
|
||||
mocker.patch("kasa.iot.iotdimmer.IotDimmer", return_value=p)
|
||||
mocker.patch("kasa.iot.iotdimmer.IotDimmer.update")
|
||||
res = xdoctest.doctest_module("kasa.iot.iotdimmer", "all")
|
||||
assert not res["failed"]
|
||||
|
||||
|
||||
def test_lightstrip_examples(mocker):
|
||||
"""Test lightstrip examples."""
|
||||
p = asyncio.run(get_device_for_file("KL430(US)_1.0_1.0.10.json", "IOT"))
|
||||
mocker.patch("kasa.smartlightstrip.SmartLightStrip", return_value=p)
|
||||
mocker.patch("kasa.smartlightstrip.SmartLightStrip.update")
|
||||
res = xdoctest.doctest_module("kasa.smartlightstrip", "all")
|
||||
mocker.patch("kasa.iot.iotlightstrip.IotLightStrip", return_value=p)
|
||||
mocker.patch("kasa.iot.iotlightstrip.IotLightStrip.update")
|
||||
res = xdoctest.doctest_module("kasa.iot.iotlightstrip", "all")
|
||||
assert not res["failed"]
|
||||
|
||||
|
||||
|
@@ -1,5 +1,8 @@
|
||||
import importlib
|
||||
import inspect
|
||||
import pkgutil
|
||||
import re
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
@@ -17,20 +20,33 @@ from voluptuous import (
|
||||
)
|
||||
|
||||
import kasa
|
||||
from kasa import Credentials, DeviceConfig, SmartDevice, SmartDeviceException
|
||||
from kasa import Credentials, Device, DeviceConfig, SmartDeviceException
|
||||
from kasa.iot import IotDevice
|
||||
from kasa.smart import SmartChildDevice, SmartDevice
|
||||
|
||||
from .conftest import device_iot, handle_turn_on, has_emeter_iot, no_emeter_iot, turn_on
|
||||
from .fakeprotocol_iot import FakeIotProtocol
|
||||
|
||||
# List of all SmartXXX classes including the SmartDevice base class
|
||||
smart_device_classes = [
|
||||
dc
|
||||
for (mn, dc) in inspect.getmembers(
|
||||
kasa,
|
||||
lambda member: inspect.isclass(member)
|
||||
and (member == SmartDevice or issubclass(member, SmartDevice)),
|
||||
)
|
||||
]
|
||||
|
||||
def _get_subclasses(of_class):
|
||||
package = sys.modules["kasa"]
|
||||
subclasses = set()
|
||||
for _, modname, _ in pkgutil.iter_modules(package.__path__):
|
||||
importlib.import_module("." + modname, package="kasa")
|
||||
module = sys.modules["kasa." + modname]
|
||||
for name, obj in inspect.getmembers(module):
|
||||
if (
|
||||
inspect.isclass(obj)
|
||||
and issubclass(obj, of_class)
|
||||
and module.__package__ != "kasa"
|
||||
):
|
||||
subclasses.add((module.__package__ + "." + name, obj))
|
||||
return subclasses
|
||||
|
||||
|
||||
device_classes = pytest.mark.parametrize(
|
||||
"device_class_name_obj", _get_subclasses(Device), ids=lambda t: t[0]
|
||||
)
|
||||
|
||||
|
||||
@device_iot
|
||||
@@ -220,21 +236,26 @@ async def test_estimated_response_sizes(dev):
|
||||
assert mod.estimated_query_response_size > 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize("device_class", smart_device_classes)
|
||||
def test_device_class_ctors(device_class):
|
||||
@device_classes
|
||||
async def test_device_class_ctors(device_class_name_obj):
|
||||
"""Make sure constructor api not broken for new and existing SmartDevices."""
|
||||
host = "127.0.0.2"
|
||||
port = 1234
|
||||
credentials = Credentials("foo", "bar")
|
||||
config = DeviceConfig(host, port_override=port, credentials=credentials)
|
||||
dev = device_class(host, config=config)
|
||||
klass = device_class_name_obj[1]
|
||||
if issubclass(klass, SmartChildDevice):
|
||||
parent = SmartDevice(host, config=config)
|
||||
dev = klass(parent, 1)
|
||||
else:
|
||||
dev = klass(host, config=config)
|
||||
assert dev.host == host
|
||||
assert dev.port == port
|
||||
assert dev.credentials == credentials
|
||||
|
||||
|
||||
@device_iot
|
||||
async def test_modules_preserved(dev: SmartDevice):
|
||||
async def test_modules_preserved(dev: IotDevice):
|
||||
"""Make modules that are not being updated are preserved between updates."""
|
||||
dev._last_update["some_module_not_being_updated"] = "should_be_kept"
|
||||
await dev.update()
|
||||
@@ -244,6 +265,8 @@ async def test_modules_preserved(dev: SmartDevice):
|
||||
async def test_create_smart_device_with_timeout():
|
||||
"""Make sure timeout is passed to the protocol."""
|
||||
host = "127.0.0.1"
|
||||
dev = IotDevice(host, config=DeviceConfig(host, timeout=100))
|
||||
assert dev.protocol._transport._timeout == 100
|
||||
dev = SmartDevice(host, config=DeviceConfig(host, timeout=100))
|
||||
assert dev.protocol._transport._timeout == 100
|
||||
|
||||
@@ -258,7 +281,7 @@ async def test_create_thin_wrapper():
|
||||
credentials=Credentials("username", "password"),
|
||||
)
|
||||
with patch("kasa.device_factory.connect", return_value=mock) as connect:
|
||||
dev = await SmartDevice.connect(config=config)
|
||||
dev = await Device.connect(config=config)
|
||||
assert dev is mock
|
||||
|
||||
connect.assert_called_once_with(
|
||||
@@ -268,7 +291,7 @@ async def test_create_thin_wrapper():
|
||||
|
||||
|
||||
@device_iot
|
||||
async def test_modules_not_supported(dev: SmartDevice):
|
||||
async def test_modules_not_supported(dev: IotDevice):
|
||||
"""Test that unsupported modules do not break the device."""
|
||||
for module in dev.modules.values():
|
||||
assert module.is_supported is not None
|
||||
@@ -277,6 +300,21 @@ async def test_modules_not_supported(dev: SmartDevice):
|
||||
assert module.is_supported is not None
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"device_class, use_class", kasa.deprecated_smart_devices.items()
|
||||
)
|
||||
def test_deprecated_devices(device_class, use_class):
|
||||
package_name = ".".join(use_class.__module__.split(".")[:-1])
|
||||
msg = f"{device_class} is deprecated, use {use_class.__name__} from package {package_name} instead"
|
||||
with pytest.deprecated_call(match=msg):
|
||||
getattr(kasa, device_class)
|
||||
packages = package_name.split(".")
|
||||
module = __import__(packages[0])
|
||||
for _ in packages[1:]:
|
||||
module = importlib.import_module(package_name, package=module.__name__)
|
||||
getattr(module, use_class.__name__)
|
||||
|
||||
|
||||
def check_mac(x):
|
||||
if re.match("[0-9a-f]{2}([-:])[0-9a-f]{2}(\\1[0-9a-f]{2}){4}$", x.lower()):
|
||||
return x
|
||||
|
@@ -2,7 +2,8 @@ from datetime import datetime
|
||||
|
||||
import pytest
|
||||
|
||||
from kasa import SmartDeviceException, SmartStrip
|
||||
from kasa import SmartDeviceException
|
||||
from kasa.iot import IotStrip
|
||||
|
||||
from .conftest import handle_turn_on, strip, turn_on
|
||||
|
||||
@@ -68,7 +69,7 @@ async def test_children_on_since(dev):
|
||||
|
||||
|
||||
@strip
|
||||
async def test_get_plug_by_name(dev: SmartStrip):
|
||||
async def test_get_plug_by_name(dev: IotStrip):
|
||||
name = dev.children[0].alias
|
||||
assert dev.get_plug_by_name(name) == dev.children[0] # type: ignore[arg-type]
|
||||
|
||||
@@ -77,7 +78,7 @@ async def test_get_plug_by_name(dev: SmartStrip):
|
||||
|
||||
|
||||
@strip
|
||||
async def test_get_plug_by_index(dev: SmartStrip):
|
||||
async def test_get_plug_by_index(dev: IotStrip):
|
||||
assert dev.get_plug_by_index(0) == dev.children[0]
|
||||
|
||||
with pytest.raises(SmartDeviceException):
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import datetime
|
||||
from unittest.mock import Mock
|
||||
|
||||
from kasa.modules import Usage
|
||||
from kasa.iot.modules import Usage
|
||||
|
||||
|
||||
def test_usage_convert_stat_data():
|
||||
|
Reference in New Issue
Block a user