mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 19:27:45 +00:00
Run statistics on 5-minute intervals in tests (#122592)
* Run statistics on 5-minute intervals in tests * Fix test failing when mysql does not return rows in insert order
This commit is contained in:
parent
08d7beb803
commit
ec957e4a94
@ -79,10 +79,18 @@ async def async_block_recorder(hass: HomeAssistant, seconds: float) -> None:
|
|||||||
await event.wait()
|
await event.wait()
|
||||||
|
|
||||||
|
|
||||||
|
def get_start_time(start: datetime) -> datetime:
|
||||||
|
"""Calculate a valid start time for statistics."""
|
||||||
|
start_minutes = start.minute - start.minute % 5
|
||||||
|
return start.replace(minute=start_minutes, second=0, microsecond=0)
|
||||||
|
|
||||||
|
|
||||||
def do_adhoc_statistics(hass: HomeAssistant, **kwargs: Any) -> None:
|
def do_adhoc_statistics(hass: HomeAssistant, **kwargs: Any) -> None:
|
||||||
"""Trigger an adhoc statistics run."""
|
"""Trigger an adhoc statistics run."""
|
||||||
if not (start := kwargs.get("start")):
|
if not (start := kwargs.get("start")):
|
||||||
start = statistics.get_start_time()
|
start = statistics.get_start_time()
|
||||||
|
elif (start.minute % 5) != 0 or start.second != 0 or start.microsecond != 0:
|
||||||
|
raise ValueError(f"Statistics must start on 5 minute boundary got {start}")
|
||||||
get_instance(hass).queue_task(StatisticsTask(start, False))
|
get_instance(hass).queue_task(StatisticsTask(start, False))
|
||||||
|
|
||||||
|
|
||||||
@ -291,11 +299,11 @@ def record_states(hass):
|
|||||||
wait_recording_done(hass)
|
wait_recording_done(hass)
|
||||||
return hass.states.get(entity_id)
|
return hass.states.get(entity_id)
|
||||||
|
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow())
|
||||||
one = zero + timedelta(seconds=1 * 5)
|
one = zero + timedelta(seconds=1 * 5)
|
||||||
two = one + timedelta(seconds=15 * 5)
|
two = one + timedelta(seconds=15 * 5)
|
||||||
three = two + timedelta(seconds=30 * 5)
|
three = two + timedelta(seconds=30 * 5)
|
||||||
four = three + timedelta(seconds=15 * 5)
|
four = three + timedelta(seconds=14 * 5)
|
||||||
|
|
||||||
states = {mp: [], sns1: [], sns2: [], sns3: [], sns4: []}
|
states = {mp: [], sns1: [], sns2: [], sns3: [], sns4: []}
|
||||||
with freeze_time(one) as freezer:
|
with freeze_time(one) as freezer:
|
||||||
|
@ -44,6 +44,7 @@ from .common import (
|
|||||||
async_record_states,
|
async_record_states,
|
||||||
async_wait_recording_done,
|
async_wait_recording_done,
|
||||||
do_adhoc_statistics,
|
do_adhoc_statistics,
|
||||||
|
get_start_time,
|
||||||
statistics_during_period,
|
statistics_during_period,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -342,7 +343,7 @@ async def test_compile_periodic_statistics_exception(
|
|||||||
"""Test exception handling when compiling periodic statistics."""
|
"""Test exception handling when compiling periodic statistics."""
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
|
|
||||||
now = dt_util.utcnow()
|
now = get_start_time(dt_util.utcnow())
|
||||||
do_adhoc_statistics(hass, start=now)
|
do_adhoc_statistics(hass, start=now)
|
||||||
do_adhoc_statistics(hass, start=now + timedelta(minutes=5))
|
do_adhoc_statistics(hass, start=now + timedelta(minutes=5))
|
||||||
await async_wait_recording_done(hass)
|
await async_wait_recording_done(hass)
|
||||||
|
@ -35,6 +35,7 @@ from .common import (
|
|||||||
async_wait_recording_done,
|
async_wait_recording_done,
|
||||||
create_engine_test,
|
create_engine_test,
|
||||||
do_adhoc_statistics,
|
do_adhoc_statistics,
|
||||||
|
get_start_time,
|
||||||
statistics_during_period,
|
statistics_during_period,
|
||||||
)
|
)
|
||||||
from .conftest import InstrumentedMigration
|
from .conftest import InstrumentedMigration
|
||||||
@ -155,12 +156,17 @@ async def test_statistics_during_period(
|
|||||||
recorder_mock: Recorder, hass: HomeAssistant, hass_ws_client: WebSocketGenerator
|
recorder_mock: Recorder, hass: HomeAssistant, hass_ws_client: WebSocketGenerator
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test statistics_during_period."""
|
"""Test statistics_during_period."""
|
||||||
now = dt_util.utcnow()
|
now = get_start_time(dt_util.utcnow())
|
||||||
|
|
||||||
hass.config.units = US_CUSTOMARY_SYSTEM
|
hass.config.units = US_CUSTOMARY_SYSTEM
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
hass.states.async_set("sensor.test", 10, attributes=POWER_SENSOR_KW_ATTRIBUTES)
|
hass.states.async_set(
|
||||||
|
"sensor.test",
|
||||||
|
10,
|
||||||
|
attributes=POWER_SENSOR_KW_ATTRIBUTES,
|
||||||
|
timestamp=now.timestamp(),
|
||||||
|
)
|
||||||
await async_wait_recording_done(hass)
|
await async_wait_recording_done(hass)
|
||||||
|
|
||||||
do_adhoc_statistics(hass, start=now)
|
do_adhoc_statistics(hass, start=now)
|
||||||
@ -608,7 +614,12 @@ async def test_statistic_during_period(
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Test we can automatically convert units
|
# Test we can automatically convert units
|
||||||
hass.states.async_set("sensor.test", None, attributes=ENERGY_SENSOR_WH_ATTRIBUTES)
|
hass.states.async_set(
|
||||||
|
"sensor.test",
|
||||||
|
None,
|
||||||
|
attributes=ENERGY_SENSOR_WH_ATTRIBUTES,
|
||||||
|
timestamp=now.timestamp(),
|
||||||
|
)
|
||||||
await client.send_json_auto_id(
|
await client.send_json_auto_id(
|
||||||
{
|
{
|
||||||
"type": "recorder/statistic_during_period",
|
"type": "recorder/statistic_during_period",
|
||||||
@ -1265,11 +1276,13 @@ async def test_statistics_during_period_unit_conversion(
|
|||||||
converted_value,
|
converted_value,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test statistics_during_period."""
|
"""Test statistics_during_period."""
|
||||||
now = dt_util.utcnow()
|
now = get_start_time(dt_util.utcnow())
|
||||||
|
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
hass.states.async_set("sensor.test", state, attributes=attributes)
|
hass.states.async_set(
|
||||||
|
"sensor.test", state, attributes=attributes, timestamp=now.timestamp()
|
||||||
|
)
|
||||||
await async_wait_recording_done(hass)
|
await async_wait_recording_done(hass)
|
||||||
|
|
||||||
do_adhoc_statistics(hass, start=now)
|
do_adhoc_statistics(hass, start=now)
|
||||||
@ -1350,12 +1363,16 @@ async def test_sum_statistics_during_period_unit_conversion(
|
|||||||
converted_value,
|
converted_value,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test statistics_during_period."""
|
"""Test statistics_during_period."""
|
||||||
now = dt_util.utcnow()
|
now = get_start_time(dt_util.utcnow())
|
||||||
|
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
hass.states.async_set("sensor.test", 0, attributes=attributes)
|
hass.states.async_set(
|
||||||
hass.states.async_set("sensor.test", state, attributes=attributes)
|
"sensor.test", 0, attributes=attributes, timestamp=now.timestamp()
|
||||||
|
)
|
||||||
|
hass.states.async_set(
|
||||||
|
"sensor.test", state, attributes=attributes, timestamp=now.timestamp()
|
||||||
|
)
|
||||||
await async_wait_recording_done(hass)
|
await async_wait_recording_done(hass)
|
||||||
|
|
||||||
do_adhoc_statistics(hass, start=now)
|
do_adhoc_statistics(hass, start=now)
|
||||||
@ -1471,7 +1488,7 @@ async def test_statistics_during_period_in_the_past(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Test statistics_during_period in the past."""
|
"""Test statistics_during_period in the past."""
|
||||||
await hass.config.async_set_time_zone("UTC")
|
await hass.config.async_set_time_zone("UTC")
|
||||||
now = dt_util.utcnow().replace()
|
now = get_start_time(dt_util.utcnow())
|
||||||
|
|
||||||
hass.config.units = US_CUSTOMARY_SYSTEM
|
hass.config.units = US_CUSTOMARY_SYSTEM
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
@ -1726,7 +1743,7 @@ async def test_list_statistic_ids(
|
|||||||
unit_class,
|
unit_class,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test list_statistic_ids."""
|
"""Test list_statistic_ids."""
|
||||||
now = dt_util.utcnow()
|
now = get_start_time(dt_util.utcnow())
|
||||||
has_mean = attributes["state_class"] == "measurement"
|
has_mean = attributes["state_class"] == "measurement"
|
||||||
has_sum = not has_mean
|
has_sum = not has_mean
|
||||||
|
|
||||||
@ -1740,7 +1757,9 @@ async def test_list_statistic_ids(
|
|||||||
assert response["success"]
|
assert response["success"]
|
||||||
assert response["result"] == []
|
assert response["result"] == []
|
||||||
|
|
||||||
hass.states.async_set("sensor.test", 10, attributes=attributes)
|
hass.states.async_set(
|
||||||
|
"sensor.test", 10, attributes=attributes, timestamp=now.timestamp()
|
||||||
|
)
|
||||||
await async_wait_recording_done(hass)
|
await async_wait_recording_done(hass)
|
||||||
|
|
||||||
await client.send_json_auto_id({"type": "recorder/list_statistic_ids"})
|
await client.send_json_auto_id({"type": "recorder/list_statistic_ids"})
|
||||||
@ -1890,7 +1909,7 @@ async def test_list_statistic_ids_unit_change(
|
|||||||
unit_class,
|
unit_class,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test list_statistic_ids."""
|
"""Test list_statistic_ids."""
|
||||||
now = dt_util.utcnow()
|
now = get_start_time(dt_util.utcnow())
|
||||||
has_mean = attributes["state_class"] == "measurement"
|
has_mean = attributes["state_class"] == "measurement"
|
||||||
has_sum = not has_mean
|
has_sum = not has_mean
|
||||||
|
|
||||||
@ -1903,7 +1922,9 @@ async def test_list_statistic_ids_unit_change(
|
|||||||
assert response["success"]
|
assert response["success"]
|
||||||
assert response["result"] == []
|
assert response["result"] == []
|
||||||
|
|
||||||
hass.states.async_set("sensor.test", 10, attributes=attributes)
|
hass.states.async_set(
|
||||||
|
"sensor.test", 10, attributes=attributes, timestamp=now.timestamp()
|
||||||
|
)
|
||||||
await async_wait_recording_done(hass)
|
await async_wait_recording_done(hass)
|
||||||
|
|
||||||
do_adhoc_statistics(hass, start=now)
|
do_adhoc_statistics(hass, start=now)
|
||||||
@ -1926,7 +1947,9 @@ async def test_list_statistic_ids_unit_change(
|
|||||||
]
|
]
|
||||||
|
|
||||||
# Change the state unit
|
# Change the state unit
|
||||||
hass.states.async_set("sensor.test", 10, attributes=attributes2)
|
hass.states.async_set(
|
||||||
|
"sensor.test", 10, attributes=attributes2, timestamp=now.timestamp()
|
||||||
|
)
|
||||||
|
|
||||||
await client.send_json_auto_id({"type": "recorder/list_statistic_ids"})
|
await client.send_json_auto_id({"type": "recorder/list_statistic_ids"})
|
||||||
response = await client.receive_json()
|
response = await client.receive_json()
|
||||||
@ -1965,7 +1988,7 @@ async def test_clear_statistics(
|
|||||||
recorder_mock: Recorder, hass: HomeAssistant, hass_ws_client: WebSocketGenerator
|
recorder_mock: Recorder, hass: HomeAssistant, hass_ws_client: WebSocketGenerator
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test removing statistics."""
|
"""Test removing statistics."""
|
||||||
now = dt_util.utcnow()
|
now = get_start_time(dt_util.utcnow())
|
||||||
|
|
||||||
units = METRIC_SYSTEM
|
units = METRIC_SYSTEM
|
||||||
attributes = POWER_SENSOR_KW_ATTRIBUTES
|
attributes = POWER_SENSOR_KW_ATTRIBUTES
|
||||||
@ -1975,9 +1998,15 @@ async def test_clear_statistics(
|
|||||||
hass.config.units = units
|
hass.config.units = units
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
hass.states.async_set("sensor.test1", state, attributes=attributes)
|
hass.states.async_set(
|
||||||
hass.states.async_set("sensor.test2", state * 2, attributes=attributes)
|
"sensor.test1", state, attributes=attributes, timestamp=now.timestamp()
|
||||||
hass.states.async_set("sensor.test3", state * 3, attributes=attributes)
|
)
|
||||||
|
hass.states.async_set(
|
||||||
|
"sensor.test2", state * 2, attributes=attributes, timestamp=now.timestamp()
|
||||||
|
)
|
||||||
|
hass.states.async_set(
|
||||||
|
"sensor.test3", state * 3, attributes=attributes, timestamp=now.timestamp()
|
||||||
|
)
|
||||||
await async_wait_recording_done(hass)
|
await async_wait_recording_done(hass)
|
||||||
|
|
||||||
do_adhoc_statistics(hass, start=now)
|
do_adhoc_statistics(hass, start=now)
|
||||||
@ -2088,7 +2117,7 @@ async def test_update_statistics_metadata(
|
|||||||
new_display_unit,
|
new_display_unit,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test removing statistics."""
|
"""Test removing statistics."""
|
||||||
now = dt_util.utcnow()
|
now = get_start_time(dt_util.utcnow())
|
||||||
|
|
||||||
units = METRIC_SYSTEM
|
units = METRIC_SYSTEM
|
||||||
attributes = POWER_SENSOR_KW_ATTRIBUTES | {"device_class": None}
|
attributes = POWER_SENSOR_KW_ATTRIBUTES | {"device_class": None}
|
||||||
@ -2097,7 +2126,9 @@ async def test_update_statistics_metadata(
|
|||||||
hass.config.units = units
|
hass.config.units = units
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
hass.states.async_set("sensor.test", state, attributes=attributes)
|
hass.states.async_set(
|
||||||
|
"sensor.test", state, attributes=attributes, timestamp=now.timestamp()
|
||||||
|
)
|
||||||
await async_wait_recording_done(hass)
|
await async_wait_recording_done(hass)
|
||||||
|
|
||||||
do_adhoc_statistics(hass, period="hourly", start=now)
|
do_adhoc_statistics(hass, period="hourly", start=now)
|
||||||
@ -2177,7 +2208,7 @@ async def test_change_statistics_unit(
|
|||||||
recorder_mock: Recorder, hass: HomeAssistant, hass_ws_client: WebSocketGenerator
|
recorder_mock: Recorder, hass: HomeAssistant, hass_ws_client: WebSocketGenerator
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test change unit of recorded statistics."""
|
"""Test change unit of recorded statistics."""
|
||||||
now = dt_util.utcnow()
|
now = get_start_time(dt_util.utcnow())
|
||||||
|
|
||||||
units = METRIC_SYSTEM
|
units = METRIC_SYSTEM
|
||||||
attributes = POWER_SENSOR_KW_ATTRIBUTES | {"device_class": None}
|
attributes = POWER_SENSOR_KW_ATTRIBUTES | {"device_class": None}
|
||||||
@ -2186,7 +2217,9 @@ async def test_change_statistics_unit(
|
|||||||
hass.config.units = units
|
hass.config.units = units
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
hass.states.async_set("sensor.test", state, attributes=attributes)
|
hass.states.async_set(
|
||||||
|
"sensor.test", state, attributes=attributes, timestamp=now.timestamp()
|
||||||
|
)
|
||||||
await async_wait_recording_done(hass)
|
await async_wait_recording_done(hass)
|
||||||
|
|
||||||
do_adhoc_statistics(hass, period="hourly", start=now)
|
do_adhoc_statistics(hass, period="hourly", start=now)
|
||||||
@ -2322,7 +2355,7 @@ async def test_change_statistics_unit_errors(
|
|||||||
caplog: pytest.LogCaptureFixture,
|
caplog: pytest.LogCaptureFixture,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test change unit of recorded statistics."""
|
"""Test change unit of recorded statistics."""
|
||||||
now = dt_util.utcnow()
|
now = get_start_time(dt_util.utcnow())
|
||||||
|
|
||||||
units = METRIC_SYSTEM
|
units = METRIC_SYSTEM
|
||||||
attributes = POWER_SENSOR_KW_ATTRIBUTES | {"device_class": None}
|
attributes = POWER_SENSOR_KW_ATTRIBUTES | {"device_class": None}
|
||||||
@ -2376,7 +2409,9 @@ async def test_change_statistics_unit_errors(
|
|||||||
hass.config.units = units
|
hass.config.units = units
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
hass.states.async_set("sensor.test", state, attributes=attributes)
|
hass.states.async_set(
|
||||||
|
"sensor.test", state, attributes=attributes, timestamp=now.timestamp()
|
||||||
|
)
|
||||||
await async_wait_recording_done(hass)
|
await async_wait_recording_done(hass)
|
||||||
|
|
||||||
do_adhoc_statistics(hass, period="hourly", start=now)
|
do_adhoc_statistics(hass, period="hourly", start=now)
|
||||||
@ -2599,7 +2634,7 @@ async def test_get_statistics_metadata(
|
|||||||
unit_class,
|
unit_class,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test get_statistics_metadata."""
|
"""Test get_statistics_metadata."""
|
||||||
now = dt_util.utcnow()
|
now = get_start_time(dt_util.utcnow())
|
||||||
has_mean = attributes["state_class"] == "measurement"
|
has_mean = attributes["state_class"] == "measurement"
|
||||||
has_sum = not has_mean
|
has_sum = not has_mean
|
||||||
|
|
||||||
@ -2678,10 +2713,14 @@ async def test_get_statistics_metadata(
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
hass.states.async_set("sensor.test", 10, attributes=attributes)
|
hass.states.async_set(
|
||||||
|
"sensor.test", 10, attributes=attributes, timestamp=now.timestamp()
|
||||||
|
)
|
||||||
await async_wait_recording_done(hass)
|
await async_wait_recording_done(hass)
|
||||||
|
|
||||||
hass.states.async_set("sensor.test2", 10, attributes=attributes)
|
hass.states.async_set(
|
||||||
|
"sensor.test2", 10, attributes=attributes, timestamp=now.timestamp()
|
||||||
|
)
|
||||||
await async_wait_recording_done(hass)
|
await async_wait_recording_done(hass)
|
||||||
|
|
||||||
await client.send_json_auto_id(
|
await client.send_json_auto_id(
|
||||||
|
@ -50,6 +50,7 @@ from tests.components.recorder.common import (
|
|||||||
async_recorder_block_till_done,
|
async_recorder_block_till_done,
|
||||||
async_wait_recording_done,
|
async_wait_recording_done,
|
||||||
do_adhoc_statistics,
|
do_adhoc_statistics,
|
||||||
|
get_start_time,
|
||||||
statistics_during_period,
|
statistics_during_period,
|
||||||
)
|
)
|
||||||
from tests.typing import (
|
from tests.typing import (
|
||||||
@ -194,7 +195,7 @@ async def test_compile_hourly_statistics(
|
|||||||
max,
|
max,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test compiling hourly statistics."""
|
"""Test compiling hourly statistics."""
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow())
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
# Wait for the sensor recorder platform to be added
|
# Wait for the sensor recorder platform to be added
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -278,7 +279,7 @@ async def test_compile_hourly_statistics_with_some_same_last_updated(
|
|||||||
|
|
||||||
If the last updated value is the same we will have a zero duration.
|
If the last updated value is the same we will have a zero duration.
|
||||||
"""
|
"""
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow())
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
# Wait for the sensor recorder platform to be added
|
# Wait for the sensor recorder platform to be added
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -392,7 +393,7 @@ async def test_compile_hourly_statistics_with_all_same_last_updated(
|
|||||||
|
|
||||||
If the last updated value is the same we will have a zero duration.
|
If the last updated value is the same we will have a zero duration.
|
||||||
"""
|
"""
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow())
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
# Wait for the sensor recorder platform to be added
|
# Wait for the sensor recorder platform to be added
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -498,7 +499,7 @@ async def test_compile_hourly_statistics_only_state_is_and_end_of_period(
|
|||||||
max,
|
max,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test compiling hourly statistics when the only state at end of period."""
|
"""Test compiling hourly statistics when the only state at end of period."""
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow())
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
# Wait for the sensor recorder platform to be added
|
# Wait for the sensor recorder platform to be added
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -592,7 +593,7 @@ async def test_compile_hourly_statistics_purged_state_changes(
|
|||||||
unit_class,
|
unit_class,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test compiling hourly statistics."""
|
"""Test compiling hourly statistics."""
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow())
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
# Wait for the sensor recorder platform to be added
|
# Wait for the sensor recorder platform to be added
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -663,7 +664,7 @@ async def test_compile_hourly_statistics_wrong_unit(
|
|||||||
attributes,
|
attributes,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test compiling hourly statistics for sensor with unit not matching device class."""
|
"""Test compiling hourly statistics for sensor with unit not matching device class."""
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow())
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
# Wait for the sensor recorder platform to be added
|
# Wait for the sensor recorder platform to be added
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -887,7 +888,7 @@ async def test_compile_hourly_sum_statistics_amount(
|
|||||||
factor,
|
factor,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test compiling hourly statistics."""
|
"""Test compiling hourly statistics."""
|
||||||
period0 = dt_util.utcnow()
|
period0 = get_start_time(dt_util.utcnow())
|
||||||
period0_end = period1 = period0 + timedelta(minutes=5)
|
period0_end = period1 = period0 + timedelta(minutes=5)
|
||||||
period1_end = period2 = period0 + timedelta(minutes=10)
|
period1_end = period2 = period0 + timedelta(minutes=10)
|
||||||
period2_end = period0 + timedelta(minutes=15)
|
period2_end = period0 + timedelta(minutes=15)
|
||||||
@ -1071,7 +1072,7 @@ async def test_compile_hourly_sum_statistics_amount_reset_every_state_change(
|
|||||||
factor,
|
factor,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test compiling hourly statistics."""
|
"""Test compiling hourly statistics."""
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow())
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
# Wait for the sensor recorder platform to be added
|
# Wait for the sensor recorder platform to be added
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -1194,7 +1195,7 @@ async def test_compile_hourly_sum_statistics_amount_invalid_last_reset(
|
|||||||
factor,
|
factor,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test compiling hourly statistics."""
|
"""Test compiling hourly statistics."""
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow())
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
# Wait for the sensor recorder platform to be added
|
# Wait for the sensor recorder platform to be added
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -1294,7 +1295,7 @@ async def test_compile_hourly_sum_statistics_nan_inf_state(
|
|||||||
factor,
|
factor,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test compiling hourly statistics with nan and inf states."""
|
"""Test compiling hourly statistics with nan and inf states."""
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow())
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
# Wait for the sensor recorder platform to be added
|
# Wait for the sensor recorder platform to be added
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -1429,7 +1430,7 @@ async def test_compile_hourly_sum_statistics_negative_state(
|
|||||||
offset,
|
offset,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test compiling hourly statistics with negative states."""
|
"""Test compiling hourly statistics with negative states."""
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow())
|
||||||
hass.data.pop(loader.DATA_CUSTOM_COMPONENTS)
|
hass.data.pop(loader.DATA_CUSTOM_COMPONENTS)
|
||||||
|
|
||||||
mocksensor = MockSensor(name="custom_sensor")
|
mocksensor = MockSensor(name="custom_sensor")
|
||||||
@ -1437,6 +1438,7 @@ async def test_compile_hourly_sum_statistics_negative_state(
|
|||||||
setup_test_component_platform(hass, DOMAIN, [mocksensor], built_in=False)
|
setup_test_component_platform(hass, DOMAIN, [mocksensor], built_in=False)
|
||||||
|
|
||||||
await async_setup_component(hass, "homeassistant", {})
|
await async_setup_component(hass, "homeassistant", {})
|
||||||
|
with freeze_time(zero) as freezer:
|
||||||
await async_setup_component(
|
await async_setup_component(
|
||||||
hass, "sensor", {"sensor": [{"platform": "demo"}, {"platform": "test"}]}
|
hass, "sensor", {"sensor": [{"platform": "demo"}, {"platform": "test"}]}
|
||||||
)
|
)
|
||||||
@ -1541,7 +1543,7 @@ async def test_compile_hourly_sum_statistics_total_no_reset(
|
|||||||
factor,
|
factor,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test compiling hourly statistics."""
|
"""Test compiling hourly statistics."""
|
||||||
period0 = dt_util.utcnow()
|
period0 = get_start_time(dt_util.utcnow())
|
||||||
period0_end = period1 = period0 + timedelta(minutes=5)
|
period0_end = period1 = period0 + timedelta(minutes=5)
|
||||||
period1_end = period2 = period0 + timedelta(minutes=10)
|
period1_end = period2 = period0 + timedelta(minutes=10)
|
||||||
period2_end = period0 + timedelta(minutes=15)
|
period2_end = period0 + timedelta(minutes=15)
|
||||||
@ -1654,7 +1656,7 @@ async def test_compile_hourly_sum_statistics_total_increasing(
|
|||||||
factor,
|
factor,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test compiling hourly statistics."""
|
"""Test compiling hourly statistics."""
|
||||||
period0 = dt_util.utcnow()
|
period0 = get_start_time(dt_util.utcnow())
|
||||||
period0_end = period1 = period0 + timedelta(minutes=5)
|
period0_end = period1 = period0 + timedelta(minutes=5)
|
||||||
period1_end = period2 = period0 + timedelta(minutes=10)
|
period1_end = period2 = period0 + timedelta(minutes=10)
|
||||||
period2_end = period0 + timedelta(minutes=15)
|
period2_end = period0 + timedelta(minutes=15)
|
||||||
@ -1767,7 +1769,7 @@ async def test_compile_hourly_sum_statistics_total_increasing_small_dip(
|
|||||||
factor,
|
factor,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test small dips in sensor readings do not trigger a reset."""
|
"""Test small dips in sensor readings do not trigger a reset."""
|
||||||
period0 = dt_util.utcnow()
|
period0 = get_start_time(dt_util.utcnow())
|
||||||
period0_end = period1 = period0 + timedelta(minutes=5)
|
period0_end = period1 = period0 + timedelta(minutes=5)
|
||||||
period1_end = period2 = period0 + timedelta(minutes=10)
|
period1_end = period2 = period0 + timedelta(minutes=10)
|
||||||
period2_end = period0 + timedelta(minutes=15)
|
period2_end = period0 + timedelta(minutes=15)
|
||||||
@ -1869,7 +1871,7 @@ async def test_compile_hourly_energy_statistics_unsupported(
|
|||||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test compiling hourly statistics."""
|
"""Test compiling hourly statistics."""
|
||||||
period0 = dt_util.utcnow()
|
period0 = get_start_time(dt_util.utcnow())
|
||||||
period0_end = period1 = period0 + timedelta(minutes=5)
|
period0_end = period1 = period0 + timedelta(minutes=5)
|
||||||
period1_end = period2 = period0 + timedelta(minutes=10)
|
period1_end = period2 = period0 + timedelta(minutes=10)
|
||||||
period2_end = period0 + timedelta(minutes=15)
|
period2_end = period0 + timedelta(minutes=15)
|
||||||
@ -1973,7 +1975,7 @@ async def test_compile_hourly_energy_statistics_multiple(
|
|||||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test compiling multiple hourly statistics."""
|
"""Test compiling multiple hourly statistics."""
|
||||||
period0 = dt_util.utcnow()
|
period0 = get_start_time(dt_util.utcnow())
|
||||||
period0_end = period1 = period0 + timedelta(minutes=5)
|
period0_end = period1 = period0 + timedelta(minutes=5)
|
||||||
period1_end = period2 = period0 + timedelta(minutes=10)
|
period1_end = period2 = period0 + timedelta(minutes=10)
|
||||||
period2_end = period0 + timedelta(minutes=15)
|
period2_end = period0 + timedelta(minutes=15)
|
||||||
@ -2187,7 +2189,7 @@ async def test_compile_hourly_statistics_unchanged(
|
|||||||
value,
|
value,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test compiling hourly statistics, with no changes during the hour."""
|
"""Test compiling hourly statistics, with no changes during the hour."""
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow())
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
# Wait for the sensor recorder platform to be added
|
# Wait for the sensor recorder platform to be added
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -2230,7 +2232,7 @@ async def test_compile_hourly_statistics_partially_unavailable(
|
|||||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test compiling hourly statistics, with the sensor being partially unavailable."""
|
"""Test compiling hourly statistics, with the sensor being partially unavailable."""
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow())
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
# Wait for the sensor recorder platform to be added
|
# Wait for the sensor recorder platform to be added
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -2299,7 +2301,7 @@ async def test_compile_hourly_statistics_unavailable(
|
|||||||
sensor.test1 is unavailable and should not have statistics generated
|
sensor.test1 is unavailable and should not have statistics generated
|
||||||
sensor.test2 should have statistics generated
|
sensor.test2 should have statistics generated
|
||||||
"""
|
"""
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow())
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
# Wait for the sensor recorder platform to be added
|
# Wait for the sensor recorder platform to be added
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -2346,7 +2348,7 @@ async def test_compile_hourly_statistics_fails(
|
|||||||
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test compiling hourly statistics throws."""
|
"""Test compiling hourly statistics throws."""
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow())
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
# Wait for the sensor recorder platform to be added
|
# Wait for the sensor recorder platform to be added
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -2523,7 +2525,7 @@ async def test_compile_hourly_statistics_changing_units_1(
|
|||||||
|
|
||||||
This tests the case where the recorder cannot convert between the units.
|
This tests the case where the recorder cannot convert between the units.
|
||||||
"""
|
"""
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow())
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
# Wait for the sensor recorder platform to be added
|
# Wait for the sensor recorder platform to be added
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -2652,7 +2654,7 @@ async def test_compile_hourly_statistics_changing_units_2(
|
|||||||
This tests the behaviour when the sensor units are note supported by any unit
|
This tests the behaviour when the sensor units are note supported by any unit
|
||||||
converter.
|
converter.
|
||||||
"""
|
"""
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow()) - timedelta(seconds=30 * 5)
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
# Wait for the sensor recorder platform to be added
|
# Wait for the sensor recorder platform to be added
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -2731,7 +2733,7 @@ async def test_compile_hourly_statistics_changing_units_3(
|
|||||||
This tests the behaviour when the sensor units are note supported by any unit
|
This tests the behaviour when the sensor units are note supported by any unit
|
||||||
converter.
|
converter.
|
||||||
"""
|
"""
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow())
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
# Wait for the sensor recorder platform to be added
|
# Wait for the sensor recorder platform to be added
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -2852,7 +2854,7 @@ async def test_compile_hourly_statistics_convert_units_1(
|
|||||||
|
|
||||||
This tests the case where the recorder can convert between the units.
|
This tests the case where the recorder can convert between the units.
|
||||||
"""
|
"""
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow())
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
# Wait for the sensor recorder platform to be added
|
# Wait for the sensor recorder platform to be added
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -3011,7 +3013,7 @@ async def test_compile_hourly_statistics_equivalent_units_1(
|
|||||||
max,
|
max,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test compiling hourly statistics where units change from one hour to the next."""
|
"""Test compiling hourly statistics where units change from one hour to the next."""
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow())
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
# Wait for the sensor recorder platform to be added
|
# Wait for the sensor recorder platform to be added
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -3136,7 +3138,7 @@ async def test_compile_hourly_statistics_equivalent_units_2(
|
|||||||
max,
|
max,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test compiling hourly statistics where units change during an hour."""
|
"""Test compiling hourly statistics where units change during an hour."""
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow())
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
# Wait for the sensor recorder platform to be added
|
# Wait for the sensor recorder platform to be added
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -3160,7 +3162,7 @@ async def test_compile_hourly_statistics_equivalent_units_2(
|
|||||||
)
|
)
|
||||||
assert_dict_of_states_equal_without_context_and_last_changed(states, hist)
|
assert_dict_of_states_equal_without_context_and_last_changed(states, hist)
|
||||||
|
|
||||||
do_adhoc_statistics(hass, start=zero + timedelta(seconds=30 * 5))
|
do_adhoc_statistics(hass, start=zero + timedelta(seconds=30 * 10))
|
||||||
await async_wait_recording_done(hass)
|
await async_wait_recording_done(hass)
|
||||||
assert "The unit of sensor.test1 is changing" not in caplog.text
|
assert "The unit of sensor.test1 is changing" not in caplog.text
|
||||||
assert "and matches the unit of already compiled statistics" not in caplog.text
|
assert "and matches the unit of already compiled statistics" not in caplog.text
|
||||||
@ -3182,9 +3184,9 @@ async def test_compile_hourly_statistics_equivalent_units_2(
|
|||||||
"sensor.test1": [
|
"sensor.test1": [
|
||||||
{
|
{
|
||||||
"start": process_timestamp(
|
"start": process_timestamp(
|
||||||
zero + timedelta(seconds=30 * 5)
|
zero + timedelta(seconds=30 * 10)
|
||||||
).timestamp(),
|
).timestamp(),
|
||||||
"end": process_timestamp(zero + timedelta(seconds=30 * 15)).timestamp(),
|
"end": process_timestamp(zero + timedelta(seconds=30 * 20)).timestamp(),
|
||||||
"mean": pytest.approx(mean),
|
"mean": pytest.approx(mean),
|
||||||
"min": pytest.approx(min),
|
"min": pytest.approx(min),
|
||||||
"max": pytest.approx(max),
|
"max": pytest.approx(max),
|
||||||
@ -3229,7 +3231,7 @@ async def test_compile_hourly_statistics_changing_device_class_1(
|
|||||||
|
|
||||||
Device class is ignored, meaning changing device class should not influence the statistics.
|
Device class is ignored, meaning changing device class should not influence the statistics.
|
||||||
"""
|
"""
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow())
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
# Wait for the sensor recorder platform to be added
|
# Wait for the sensor recorder platform to be added
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -3440,7 +3442,7 @@ async def test_compile_hourly_statistics_changing_device_class_2(
|
|||||||
|
|
||||||
Device class is ignored, meaning changing device class should not influence the statistics.
|
Device class is ignored, meaning changing device class should not influence the statistics.
|
||||||
"""
|
"""
|
||||||
zero = dt_util.utcnow()
|
zero = get_start_time(dt_util.utcnow())
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
# Wait for the sensor recorder platform to be added
|
# Wait for the sensor recorder platform to be added
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -3578,7 +3580,7 @@ async def test_compile_hourly_statistics_changing_state_class(
|
|||||||
max,
|
max,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test compiling hourly statistics where state class changes."""
|
"""Test compiling hourly statistics where state class changes."""
|
||||||
period0 = dt_util.utcnow()
|
period0 = get_start_time(dt_util.utcnow())
|
||||||
period0_end = period1 = period0 + timedelta(minutes=5)
|
period0_end = period1 = period0 + timedelta(minutes=5)
|
||||||
period1_end = period0 + timedelta(minutes=10)
|
period1_end = period0 + timedelta(minutes=10)
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
@ -4148,7 +4150,7 @@ async def async_record_states(
|
|||||||
one = zero + timedelta(seconds=1 * 5)
|
one = zero + timedelta(seconds=1 * 5)
|
||||||
two = one + timedelta(seconds=10 * 5)
|
two = one + timedelta(seconds=10 * 5)
|
||||||
three = two + timedelta(seconds=40 * 5)
|
three = two + timedelta(seconds=40 * 5)
|
||||||
four = three + timedelta(seconds=10 * 5)
|
four = three + timedelta(seconds=9 * 5)
|
||||||
|
|
||||||
states = {entity_id: []}
|
states = {entity_id: []}
|
||||||
freezer.move_to(one)
|
freezer.move_to(one)
|
||||||
@ -4210,7 +4212,7 @@ async def test_validate_unit_change_convertible(
|
|||||||
The test also asserts that the sensor's device class is ignored.
|
The test also asserts that the sensor's device class is ignored.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
now = dt_util.utcnow()
|
now = get_start_time(dt_util.utcnow())
|
||||||
|
|
||||||
hass.config.units = units
|
hass.config.units = units
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
@ -4222,14 +4224,20 @@ async def test_validate_unit_change_convertible(
|
|||||||
|
|
||||||
# No statistics, unit in state matching device class - empty response
|
# No statistics, unit in state matching device class - empty response
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
"sensor.test", 10, attributes={**attributes, "unit_of_measurement": unit}
|
"sensor.test",
|
||||||
|
10,
|
||||||
|
attributes={**attributes, "unit_of_measurement": unit},
|
||||||
|
timestamp=now.timestamp(),
|
||||||
)
|
)
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
|
|
||||||
# No statistics, unit in state not matching device class - empty response
|
# No statistics, unit in state not matching device class - empty response
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
"sensor.test", 11, attributes={**attributes, "unit_of_measurement": "dogs"}
|
"sensor.test",
|
||||||
|
11,
|
||||||
|
attributes={**attributes, "unit_of_measurement": "dogs"},
|
||||||
|
timestamp=now.timestamp(),
|
||||||
)
|
)
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
@ -4238,7 +4246,10 @@ async def test_validate_unit_change_convertible(
|
|||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
do_adhoc_statistics(hass, start=now)
|
do_adhoc_statistics(hass, start=now)
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
"sensor.test", 12, attributes={**attributes, "unit_of_measurement": "dogs"}
|
"sensor.test",
|
||||||
|
12,
|
||||||
|
attributes={**attributes, "unit_of_measurement": "dogs"},
|
||||||
|
timestamp=now.timestamp(),
|
||||||
)
|
)
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
expected = {
|
expected = {
|
||||||
@ -4258,7 +4269,10 @@ async def test_validate_unit_change_convertible(
|
|||||||
|
|
||||||
# Valid state - empty response
|
# Valid state - empty response
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
"sensor.test", 13, attributes={**attributes, "unit_of_measurement": unit}
|
"sensor.test",
|
||||||
|
13,
|
||||||
|
attributes={**attributes, "unit_of_measurement": unit},
|
||||||
|
timestamp=now.timestamp(),
|
||||||
)
|
)
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
@ -4270,7 +4284,10 @@ async def test_validate_unit_change_convertible(
|
|||||||
|
|
||||||
# Valid state in compatible unit - empty response
|
# Valid state in compatible unit - empty response
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
"sensor.test", 13, attributes={**attributes, "unit_of_measurement": unit2}
|
"sensor.test",
|
||||||
|
13,
|
||||||
|
attributes={**attributes, "unit_of_measurement": unit2},
|
||||||
|
timestamp=now.timestamp(),
|
||||||
)
|
)
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
@ -4309,7 +4326,7 @@ async def test_validate_statistics_unit_ignore_device_class(
|
|||||||
|
|
||||||
The test asserts that the sensor's device class is ignored.
|
The test asserts that the sensor's device class is ignored.
|
||||||
"""
|
"""
|
||||||
now = dt_util.utcnow()
|
now = get_start_time(dt_util.utcnow())
|
||||||
|
|
||||||
hass.config.units = units
|
hass.config.units = units
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
@ -4321,7 +4338,9 @@ async def test_validate_statistics_unit_ignore_device_class(
|
|||||||
|
|
||||||
# No statistics, no device class - empty response
|
# No statistics, no device class - empty response
|
||||||
initial_attributes = {"state_class": "measurement", "unit_of_measurement": "dogs"}
|
initial_attributes = {"state_class": "measurement", "unit_of_measurement": "dogs"}
|
||||||
hass.states.async_set("sensor.test", 10, attributes=initial_attributes)
|
hass.states.async_set(
|
||||||
|
"sensor.test", 10, attributes=initial_attributes, timestamp=now.timestamp()
|
||||||
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
|
|
||||||
@ -4329,7 +4348,10 @@ async def test_validate_statistics_unit_ignore_device_class(
|
|||||||
do_adhoc_statistics(hass, start=now)
|
do_adhoc_statistics(hass, start=now)
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
"sensor.test", 12, attributes={**attributes, "unit_of_measurement": "dogs"}
|
"sensor.test",
|
||||||
|
12,
|
||||||
|
attributes={**attributes, "unit_of_measurement": "dogs"},
|
||||||
|
timestamp=now.timestamp(),
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
@ -4389,7 +4411,7 @@ async def test_validate_statistics_unit_change_no_device_class(
|
|||||||
attributes = dict(attributes)
|
attributes = dict(attributes)
|
||||||
attributes.pop("device_class")
|
attributes.pop("device_class")
|
||||||
|
|
||||||
now = dt_util.utcnow()
|
now = get_start_time(dt_util.utcnow())
|
||||||
|
|
||||||
hass.config.units = units
|
hass.config.units = units
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
@ -4401,14 +4423,20 @@ async def test_validate_statistics_unit_change_no_device_class(
|
|||||||
|
|
||||||
# No statistics, sensor state set - empty response
|
# No statistics, sensor state set - empty response
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
"sensor.test", 10, attributes={**attributes, "unit_of_measurement": unit}
|
"sensor.test",
|
||||||
|
10,
|
||||||
|
attributes={**attributes, "unit_of_measurement": unit},
|
||||||
|
timestamp=now.timestamp(),
|
||||||
)
|
)
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
|
|
||||||
# No statistics, sensor state set to an incompatible unit - empty response
|
# No statistics, sensor state set to an incompatible unit - empty response
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
"sensor.test", 11, attributes={**attributes, "unit_of_measurement": "dogs"}
|
"sensor.test",
|
||||||
|
11,
|
||||||
|
attributes={**attributes, "unit_of_measurement": "dogs"},
|
||||||
|
timestamp=now.timestamp(),
|
||||||
)
|
)
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
@ -4417,7 +4445,10 @@ async def test_validate_statistics_unit_change_no_device_class(
|
|||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
do_adhoc_statistics(hass, start=now)
|
do_adhoc_statistics(hass, start=now)
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
"sensor.test", 12, attributes={**attributes, "unit_of_measurement": "dogs"}
|
"sensor.test",
|
||||||
|
12,
|
||||||
|
attributes={**attributes, "unit_of_measurement": "dogs"},
|
||||||
|
timestamp=now.timestamp(),
|
||||||
)
|
)
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
expected = {
|
expected = {
|
||||||
@ -4437,7 +4468,10 @@ async def test_validate_statistics_unit_change_no_device_class(
|
|||||||
|
|
||||||
# Valid state - empty response
|
# Valid state - empty response
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
"sensor.test", 13, attributes={**attributes, "unit_of_measurement": unit}
|
"sensor.test",
|
||||||
|
13,
|
||||||
|
attributes={**attributes, "unit_of_measurement": unit},
|
||||||
|
timestamp=now.timestamp(),
|
||||||
)
|
)
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
@ -4449,7 +4483,10 @@ async def test_validate_statistics_unit_change_no_device_class(
|
|||||||
|
|
||||||
# Valid state in compatible unit - empty response
|
# Valid state in compatible unit - empty response
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
"sensor.test", 13, attributes={**attributes, "unit_of_measurement": unit2}
|
"sensor.test",
|
||||||
|
13,
|
||||||
|
attributes={**attributes, "unit_of_measurement": unit2},
|
||||||
|
timestamp=now.timestamp(),
|
||||||
)
|
)
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
@ -4486,7 +4523,7 @@ async def test_validate_statistics_unsupported_state_class(
|
|||||||
unit,
|
unit,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test validate_statistics."""
|
"""Test validate_statistics."""
|
||||||
now = dt_util.utcnow()
|
now = get_start_time(dt_util.utcnow())
|
||||||
|
|
||||||
hass.config.units = units
|
hass.config.units = units
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
@ -4497,7 +4534,9 @@ async def test_validate_statistics_unsupported_state_class(
|
|||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
|
|
||||||
# No statistics, valid state - empty response
|
# No statistics, valid state - empty response
|
||||||
hass.states.async_set("sensor.test", 10, attributes=attributes)
|
hass.states.async_set(
|
||||||
|
"sensor.test", 10, attributes=attributes, timestamp=now.timestamp()
|
||||||
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
|
|
||||||
@ -4509,7 +4548,9 @@ async def test_validate_statistics_unsupported_state_class(
|
|||||||
# State update with invalid state class, expect error
|
# State update with invalid state class, expect error
|
||||||
_attributes = dict(attributes)
|
_attributes = dict(attributes)
|
||||||
_attributes.pop("state_class")
|
_attributes.pop("state_class")
|
||||||
hass.states.async_set("sensor.test", 12, attributes=_attributes)
|
hass.states.async_set(
|
||||||
|
"sensor.test", 12, attributes=_attributes, timestamp=now.timestamp()
|
||||||
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
expected = {
|
expected = {
|
||||||
"sensor.test": [
|
"sensor.test": [
|
||||||
@ -4539,7 +4580,7 @@ async def test_validate_statistics_sensor_no_longer_recorded(
|
|||||||
unit,
|
unit,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test validate_statistics."""
|
"""Test validate_statistics."""
|
||||||
now = dt_util.utcnow()
|
now = get_start_time(dt_util.utcnow())
|
||||||
|
|
||||||
hass.config.units = units
|
hass.config.units = units
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
@ -4550,7 +4591,9 @@ async def test_validate_statistics_sensor_no_longer_recorded(
|
|||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
|
|
||||||
# No statistics, valid state - empty response
|
# No statistics, valid state - empty response
|
||||||
hass.states.async_set("sensor.test", 10, attributes=attributes)
|
hass.states.async_set(
|
||||||
|
"sensor.test", 10, attributes=attributes, timestamp=now.timestamp()
|
||||||
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
|
|
||||||
@ -4591,7 +4634,7 @@ async def test_validate_statistics_sensor_not_recorded(
|
|||||||
unit,
|
unit,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test validate_statistics."""
|
"""Test validate_statistics."""
|
||||||
now = dt_util.utcnow()
|
now = get_start_time(dt_util.utcnow())
|
||||||
|
|
||||||
hass.config.units = units
|
hass.config.units = units
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
@ -4616,7 +4659,9 @@ async def test_validate_statistics_sensor_not_recorded(
|
|||||||
"entity_filter",
|
"entity_filter",
|
||||||
return_value=False,
|
return_value=False,
|
||||||
):
|
):
|
||||||
hass.states.async_set("sensor.test", 10, attributes=attributes)
|
hass.states.async_set(
|
||||||
|
"sensor.test", 10, attributes=attributes, timestamp=now.timestamp()
|
||||||
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
await assert_validation_result(client, expected)
|
await assert_validation_result(client, expected)
|
||||||
|
|
||||||
@ -4640,7 +4685,7 @@ async def test_validate_statistics_sensor_removed(
|
|||||||
unit,
|
unit,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test validate_statistics."""
|
"""Test validate_statistics."""
|
||||||
now = dt_util.utcnow()
|
now = get_start_time(dt_util.utcnow())
|
||||||
|
|
||||||
hass.config.units = units
|
hass.config.units = units
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
@ -4651,7 +4696,9 @@ async def test_validate_statistics_sensor_removed(
|
|||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
|
|
||||||
# No statistics, valid state - empty response
|
# No statistics, valid state - empty response
|
||||||
hass.states.async_set("sensor.test", 10, attributes=attributes)
|
hass.states.async_set(
|
||||||
|
"sensor.test", 10, attributes=attributes, timestamp=now.timestamp()
|
||||||
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
|
|
||||||
@ -4688,7 +4735,7 @@ async def test_validate_statistics_unit_change_no_conversion(
|
|||||||
unit2,
|
unit2,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test validate_statistics."""
|
"""Test validate_statistics."""
|
||||||
now = dt_util.utcnow()
|
now = get_start_time(dt_util.utcnow())
|
||||||
|
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -4699,13 +4746,19 @@ async def test_validate_statistics_unit_change_no_conversion(
|
|||||||
|
|
||||||
# No statistics, original unit - empty response
|
# No statistics, original unit - empty response
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
"sensor.test", 10, attributes={**attributes, "unit_of_measurement": unit1}
|
"sensor.test",
|
||||||
|
10,
|
||||||
|
attributes={**attributes, "unit_of_measurement": unit1},
|
||||||
|
timestamp=now.timestamp(),
|
||||||
)
|
)
|
||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
|
|
||||||
# No statistics, changed unit - empty response
|
# No statistics, changed unit - empty response
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
"sensor.test", 11, attributes={**attributes, "unit_of_measurement": unit2}
|
"sensor.test",
|
||||||
|
11,
|
||||||
|
attributes={**attributes, "unit_of_measurement": unit2},
|
||||||
|
timestamp=now.timestamp(),
|
||||||
)
|
)
|
||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
|
|
||||||
@ -4717,7 +4770,10 @@ async def test_validate_statistics_unit_change_no_conversion(
|
|||||||
|
|
||||||
# No statistics, original unit - empty response
|
# No statistics, original unit - empty response
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
"sensor.test", 12, attributes={**attributes, "unit_of_measurement": unit1}
|
"sensor.test",
|
||||||
|
12,
|
||||||
|
attributes={**attributes, "unit_of_measurement": unit1},
|
||||||
|
timestamp=now.timestamp(),
|
||||||
)
|
)
|
||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
|
|
||||||
@ -4732,7 +4788,10 @@ async def test_validate_statistics_unit_change_no_conversion(
|
|||||||
|
|
||||||
# Change unit - expect error
|
# Change unit - expect error
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
"sensor.test", 13, attributes={**attributes, "unit_of_measurement": unit2}
|
"sensor.test",
|
||||||
|
13,
|
||||||
|
attributes={**attributes, "unit_of_measurement": unit2},
|
||||||
|
timestamp=now.timestamp(),
|
||||||
)
|
)
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
expected = {
|
expected = {
|
||||||
@ -4752,7 +4811,10 @@ async def test_validate_statistics_unit_change_no_conversion(
|
|||||||
|
|
||||||
# Original unit - empty response
|
# Original unit - empty response
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
"sensor.test", 14, attributes={**attributes, "unit_of_measurement": unit1}
|
"sensor.test",
|
||||||
|
14,
|
||||||
|
attributes={**attributes, "unit_of_measurement": unit1},
|
||||||
|
timestamp=now.timestamp(),
|
||||||
)
|
)
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
@ -4796,7 +4858,7 @@ async def test_validate_statistics_unit_change_equivalent_units(
|
|||||||
This tests no validation issue is created when a sensor's unit changes to an
|
This tests no validation issue is created when a sensor's unit changes to an
|
||||||
equivalent unit.
|
equivalent unit.
|
||||||
"""
|
"""
|
||||||
now = dt_util.utcnow()
|
now = get_start_time(dt_util.utcnow())
|
||||||
|
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -4807,7 +4869,10 @@ async def test_validate_statistics_unit_change_equivalent_units(
|
|||||||
|
|
||||||
# No statistics, original unit - empty response
|
# No statistics, original unit - empty response
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
"sensor.test", 10, attributes={**attributes, "unit_of_measurement": unit1}
|
"sensor.test",
|
||||||
|
10,
|
||||||
|
attributes={**attributes, "unit_of_measurement": unit1},
|
||||||
|
timestamp=now.timestamp(),
|
||||||
)
|
)
|
||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
|
|
||||||
@ -4821,7 +4886,10 @@ async def test_validate_statistics_unit_change_equivalent_units(
|
|||||||
|
|
||||||
# Units changed to an equivalent unit - empty response
|
# Units changed to an equivalent unit - empty response
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
"sensor.test", 12, attributes={**attributes, "unit_of_measurement": unit2}
|
"sensor.test",
|
||||||
|
12,
|
||||||
|
attributes={**attributes, "unit_of_measurement": unit2},
|
||||||
|
timestamp=now.timestamp() + 1,
|
||||||
)
|
)
|
||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
|
|
||||||
@ -4854,7 +4922,7 @@ async def test_validate_statistics_unit_change_equivalent_units_2(
|
|||||||
This tests a validation issue is created when a sensor's unit changes to an
|
This tests a validation issue is created when a sensor's unit changes to an
|
||||||
equivalent unit which is not known to the unit converters.
|
equivalent unit which is not known to the unit converters.
|
||||||
"""
|
"""
|
||||||
now = dt_util.utcnow()
|
now = get_start_time(dt_util.utcnow())
|
||||||
|
|
||||||
await async_setup_component(hass, "sensor", {})
|
await async_setup_component(hass, "sensor", {})
|
||||||
await async_recorder_block_till_done(hass)
|
await async_recorder_block_till_done(hass)
|
||||||
@ -4865,7 +4933,10 @@ async def test_validate_statistics_unit_change_equivalent_units_2(
|
|||||||
|
|
||||||
# No statistics, original unit - empty response
|
# No statistics, original unit - empty response
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
"sensor.test", 10, attributes={**attributes, "unit_of_measurement": unit1}
|
"sensor.test",
|
||||||
|
10,
|
||||||
|
attributes={**attributes, "unit_of_measurement": unit1},
|
||||||
|
timestamp=now.timestamp(),
|
||||||
)
|
)
|
||||||
await assert_validation_result(client, {})
|
await assert_validation_result(client, {})
|
||||||
|
|
||||||
@ -4879,7 +4950,10 @@ async def test_validate_statistics_unit_change_equivalent_units_2(
|
|||||||
|
|
||||||
# Units changed to an equivalent unit which is not known by the unit converters
|
# Units changed to an equivalent unit which is not known by the unit converters
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
"sensor.test", 12, attributes={**attributes, "unit_of_measurement": unit2}
|
"sensor.test",
|
||||||
|
12,
|
||||||
|
attributes={**attributes, "unit_of_measurement": unit2},
|
||||||
|
timestamp=now.timestamp(),
|
||||||
)
|
)
|
||||||
expected = {
|
expected = {
|
||||||
"sensor.test": [
|
"sensor.test": [
|
||||||
@ -5045,7 +5119,7 @@ async def async_record_states_partially_unavailable(hass, zero, entity_id, attri
|
|||||||
one = zero + timedelta(seconds=1 * 5)
|
one = zero + timedelta(seconds=1 * 5)
|
||||||
two = one + timedelta(seconds=15 * 5)
|
two = one + timedelta(seconds=15 * 5)
|
||||||
three = two + timedelta(seconds=30 * 5)
|
three = two + timedelta(seconds=30 * 5)
|
||||||
four = three + timedelta(seconds=15 * 5)
|
four = three + timedelta(seconds=14 * 5)
|
||||||
|
|
||||||
states = {entity_id: []}
|
states = {entity_id: []}
|
||||||
with freeze_time(one) as freezer:
|
with freeze_time(one) as freezer:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user