Add precommit hooks & tox env to enforce code structure, add azure pipelines

Instead of leveraging hound & travis, add an option for azure pipelines,
which may replace the former in the future.

This also streamlines the contributing guidelines by:
* Adding pre-commit hooks to run isort, black, flake8, mypy
* Adding lint environment to allow checks to be run `tox -e lint`

This also contains a major cleanup to the SmartStrip handling which was due.
After seeing #184 I thought I should push this in as it is for comments before the codebase diverges too much.
This commit is contained in:
Teemu Rytilahti
2019-11-11 22:14:34 +01:00
parent 59424d2738
commit 8a131e1eeb
17 changed files with 354 additions and 549 deletions

View File

@@ -1,31 +1,31 @@
import datetime
from unittest.mock import patch
import pytest
from pyHS100 import DeviceType, SmartStripException, SmartDeviceException
from .newfakes import (
BULB_SCHEMA,
PLUG_SCHEMA,
FakeTransportProtocol,
CURRENT_CONSUMPTION_SCHEMA,
TZ_SCHEMA,
)
from pyHS100 import DeviceType, SmartDeviceException
from .conftest import (
turn_on,
handle_turn_on,
plug,
strip,
bulb,
color_bulb,
non_color_bulb,
dimmable,
handle_turn_on,
has_emeter,
no_emeter,
dimmable,
non_color_bulb,
non_dimmable,
variable_temp,
non_variable_temp,
plug,
strip,
turn_on,
variable_temp,
)
from .newfakes import (
BULB_SCHEMA,
CURRENT_CONSUMPTION_SCHEMA,
PLUG_SCHEMA,
TZ_SCHEMA,
FakeTransportProtocol,
)
@@ -436,67 +436,44 @@ def test_deprecated_hsv(dev, turn_on):
dev.hsv = (1, 1, 1)
@strip
def test_children_is_on(dev):
is_on = dev.get_is_on()
for i in range(dev.num_children):
assert is_on[i] == dev.get_is_on(index=i)
@strip
@turn_on
def test_children_change_state(dev, turn_on):
handle_turn_on(dev, turn_on)
for i in range(dev.num_children):
orig_state = dev.get_is_on(index=i)
for plug in dev.plugs:
orig_state = plug.is_on
if orig_state:
dev.turn_off(index=i)
assert not dev.get_is_on(index=i)
assert dev.get_is_off(index=i)
plug.turn_off()
assert not plug.is_on
assert plug.is_off
dev.turn_on(index=i)
assert dev.get_is_on(index=i)
assert not dev.get_is_off(index=i)
plug.turn_on()
assert plug.is_on
assert not plug.is_off
else:
dev.turn_on(index=i)
assert dev.get_is_on(index=i)
assert not dev.get_is_off(index=i)
dev.turn_off(index=i)
assert not dev.get_is_on(index=i)
assert dev.get_is_off(index=i)
@strip
def test_children_bounds(dev):
out_of_bounds = dev.num_children + 100
with pytest.raises(SmartDeviceException):
dev.turn_off(index=out_of_bounds)
with pytest.raises(SmartDeviceException):
dev.turn_on(index=out_of_bounds)
with pytest.raises(SmartDeviceException):
dev.get_is_on(index=out_of_bounds)
with pytest.raises(SmartDeviceException):
dev.get_alias(index=out_of_bounds)
with pytest.raises(SmartDeviceException):
dev.get_on_since(index=out_of_bounds)
plug.turn_on()
assert plug.is_on
assert not plug.is_off
plug.turn_off()
assert not plug.is_on
assert plug.is_off
@strip
def test_children_alias(dev):
original = dev.get_alias()
test_alias = "TEST1234"
for idx in range(dev.num_children):
dev.set_alias(alias=test_alias, index=idx)
assert dev.get_alias(index=idx) == test_alias
dev.set_alias(alias=original[idx], index=idx)
assert dev.get_alias(index=idx) == original[idx]
for plug in dev.plugs:
original = plug.get_alias()
plug.set_alias(alias=test_alias)
assert plug.get_alias() == test_alias
plug.set_alias(alias=original)
assert plug.get_alias() == original
@strip
def test_children_on_since(dev):
for idx in range(dev.num_children):
assert dev.get_on_since(index=idx)
for plug in dev.plugs:
assert plug.get_on_since()
@pytest.mark.skip("this test will wear out your relays")
@@ -548,78 +525,61 @@ def test_all_binary_states(dev):
def test_children_get_emeter_realtime(dev):
assert dev.has_emeter
# test with index
for plug_index in range(dev.num_children):
emeter = dev.get_emeter_realtime(index=plug_index)
for plug in dev.plugs:
emeter = plug.get_emeter_realtime()
CURRENT_CONSUMPTION_SCHEMA(emeter)
# test without index
for index, emeter in dev.get_emeter_realtime().items():
CURRENT_CONSUMPTION_SCHEMA(emeter)
# TODO test that sum matches the sum of individiaul plugs.
# out of bounds
with pytest.raises(SmartStripException):
dev.get_emeter_realtime(index=dev.num_children + 100)
# for index, emeter in dev.get_emeter_realtime().items():
# CURRENT_CONSUMPTION_SCHEMA(emeter)
@strip
def test_children_get_emeter_daily(dev):
assert dev.has_emeter
# test with index
for plug_index in range(dev.num_children):
emeter = dev.get_emeter_daily(year=1900, month=1, index=plug_index)
# test individual emeters
for plug in dev.plugs:
emeter = plug.get_emeter_daily(year=1900, month=1)
assert emeter == {}
emeter = dev.get_emeter_daily(index=plug_index)
emeter = plug.get_emeter_daily()
assert len(emeter) > 0
k, v = emeter.popitem()
assert isinstance(k, int)
assert isinstance(v, float)
# test without index
# test sum of emeters
all_emeter = dev.get_emeter_daily(year=1900, month=1)
for plug_index, emeter in all_emeter.items():
assert emeter == {}
emeter = dev.get_emeter_daily(index=plug_index)
k, v = emeter.popitem()
assert isinstance(k, int)
assert isinstance(v, float)
# out of bounds
with pytest.raises(SmartStripException):
dev.get_emeter_daily(year=1900, month=1, index=dev.num_children + 100)
k, v = all_emeter.popitem()
assert isinstance(k, int)
assert isinstance(v, float)
@strip
def test_children_get_emeter_monthly(dev):
assert dev.has_emeter
# test with index
for plug_index in range(dev.num_children):
emeter = dev.get_emeter_monthly(year=1900, index=plug_index)
# test individual emeters
for plug in dev.plugs:
emeter = plug.get_emeter_monthly(year=1900)
assert emeter == {}
emeter = dev.get_emeter_monthly()
emeter = plug.get_emeter_monthly()
assert len(emeter) > 0
k, v = emeter.popitem()
assert isinstance(k, int)
assert isinstance(v, float)
# test without index
# test sum of emeters
all_emeter = dev.get_emeter_monthly(year=1900)
for index, emeter in all_emeter.items():
assert emeter == {}
assert len(emeter) > 0
k, v = emeter.popitem()
assert isinstance(k, int)
assert isinstance(v, float)
# out of bounds
with pytest.raises(SmartStripException):
dev.get_emeter_monthly(year=1900, index=dev.num_children + 100)
k, v = all_emeter.popitem()
assert isinstance(k, int)
assert isinstance(v, float)
def test_cache(dev):
@@ -658,6 +618,6 @@ def test_cache_invalidates(dev):
def test_representation(dev):
import re
pattern = re.compile("<.* model .* at .* (.*), is_on: .* - dev specific: .*>")
assert pattern.match(str(dev))