From 6b85d17e7c0d1e2b89c958d575eacabb4e3ff756 Mon Sep 17 00:00:00 2001 From: epenet <6771947+epenet@users.noreply.github.com> Date: Wed, 23 Nov 2022 20:28:52 +0100 Subject: [PATCH] Add type hints to template tests (#82566) --- tests/helpers/test_template.py | 311 ++++++++++++++++++--------------- 1 file changed, 170 insertions(+), 141 deletions(-) diff --git a/tests/helpers/test_template.py b/tests/helpers/test_template.py index 63a6154a190..cd73e663b71 100644 --- a/tests/helpers/test_template.py +++ b/tests/helpers/test_template.py @@ -1,8 +1,12 @@ """Test Home Assistant template helper methods.""" +from __future__ import annotations + +from collections.abc import Iterable from datetime import datetime, timedelta import logging import math import random +from typing import Any from unittest.mock import patch from freezegun import freeze_time @@ -27,6 +31,7 @@ from homeassistant.exceptions import TemplateError from homeassistant.helpers import device_registry as dr, entity, template from homeassistant.helpers.entity_platform import EntityPlatform from homeassistant.helpers.json import json_dumps +from homeassistant.helpers.typing import TemplateVarsType from homeassistant.setup import async_setup_component import homeassistant.util.dt as dt_util from homeassistant.util.unit_system import UnitSystem @@ -39,7 +44,7 @@ from tests.common import ( ) -def _set_up_units(hass): +def _set_up_units(hass: HomeAssistant) -> None: """Set up the tests.""" hass.config.units = UnitSystem( "custom", @@ -54,25 +59,37 @@ def _set_up_units(hass): ) -def render(hass, template_str, variables=None): +def render( + hass: HomeAssistant, template_str: str, variables: TemplateVarsType | None = None +) -> Any: """Create render info from template.""" tmp = template.Template(template_str, hass) return tmp.async_render(variables) -def render_to_info(hass, template_str, variables=None): +def render_to_info( + hass: HomeAssistant, template_str: str, variables: TemplateVarsType | None = None +) -> template.RenderInfo: """Create render info from template.""" tmp = template.Template(template_str, hass) return tmp.async_render_to_info(variables) -def extract_entities(hass, template_str, variables=None): +def extract_entities( + hass: HomeAssistant, template_str: str, variables: TemplateVarsType | None = None +) -> set[str]: """Extract entities from a template.""" info = render_to_info(hass, template_str, variables) return info.entities -def assert_result_info(info, result, entities=None, domains=None, all_states=False): +def assert_result_info( + info: template.RenderInfo, + result: Any, + entities: Iterable[str] | None = None, + domains: Iterable[str] | None = None, + all_states: bool = False, +) -> None: """Check result info.""" assert info.result() == result assert info.all_states == all_states @@ -91,7 +108,7 @@ def assert_result_info(info, result, entities=None, domains=None, all_states=Fal assert not hasattr(info, "_domains") -def test_template_equality(): +def test_template_equality() -> None: """Test template comparison and hashing.""" template_one = template.Template("{{ template_one }}") template_one_1 = template.Template("{{ template_one }}") @@ -108,7 +125,7 @@ def test_template_equality(): template.Template(["{{ template_one }}"]) -def test_invalid_template(hass): +def test_invalid_template(hass: HomeAssistant) -> None: """Invalid template raises error.""" tmpl = template.Template("{{", hass) @@ -130,7 +147,7 @@ def test_invalid_template(hass): tmpl.async_render() -def test_referring_states_by_entity_id(hass): +def test_referring_states_by_entity_id(hass: HomeAssistant) -> None: """Test referring states by entity id.""" hass.states.async_set("test.object", "happy") assert ( @@ -148,7 +165,7 @@ def test_referring_states_by_entity_id(hass): ) -def test_invalid_entity_id(hass): +def test_invalid_entity_id(hass: HomeAssistant) -> None: """Test referring states by entity id.""" with pytest.raises(TemplateError): template.Template('{{ states["big.fat..."] }}', hass).async_render() @@ -158,13 +175,13 @@ def test_invalid_entity_id(hass): template.Template('{{ states["invalid/domain"] }}', hass).async_render() -def test_raise_exception_on_error(hass): +def test_raise_exception_on_error(hass: HomeAssistant) -> None: """Test raising an exception on error.""" with pytest.raises(TemplateError): template.Template("{{ invalid_syntax").ensure_valid() -def test_iterating_all_states(hass): +def test_iterating_all_states(hass: HomeAssistant) -> None: """Test iterating all states.""" tmpl_str = "{% for state in states %}{{ state.state }}{% endfor %}" @@ -179,7 +196,7 @@ def test_iterating_all_states(hass): assert_result_info(info, "10happy", entities=[], all_states=True) -def test_iterating_all_states_unavailable(hass): +def test_iterating_all_states_unavailable(hass: HomeAssistant) -> None: """Test iterating all states unavailable.""" hass.states.async_set("test.object", "on") @@ -197,7 +214,7 @@ def test_iterating_all_states_unavailable(hass): assert_result_info(info, 1, entities=[], all_states=True) -def test_iterating_domain_states(hass): +def test_iterating_domain_states(hass: HomeAssistant) -> None: """Test iterating domain states.""" tmpl_str = "{% for state in states.sensor %}{{ state.state }}{% endfor %}" @@ -218,7 +235,7 @@ def test_iterating_domain_states(hass): ) -def test_float_function(hass): +def test_float_function(hass: HomeAssistant) -> None: """Test float function.""" hass.states.async_set("sensor.temperature", "12") @@ -245,7 +262,7 @@ def test_float_function(hass): assert render(hass, "{{ float('bad', default=1) }}") == 1 -def test_float_filter(hass): +def test_float_filter(hass: HomeAssistant) -> None: """Test float filter.""" hass.states.async_set("sensor.temperature", "12") @@ -261,7 +278,7 @@ def test_float_filter(hass): assert render(hass, "{{ 'bad' | float(default=1) }}") == 1 -def test_int_filter(hass): +def test_int_filter(hass: HomeAssistant) -> None: """Test int filter.""" hass.states.async_set("sensor.temperature", "12.2") assert render(hass, "{{ states.sensor.temperature.state | int }}") == 12 @@ -279,7 +296,7 @@ def test_int_filter(hass): assert render(hass, "{{ 'bad' | int(default=1) }}") == 1 -def test_int_function(hass): +def test_int_function(hass: HomeAssistant) -> None: """Test int filter.""" hass.states.async_set("sensor.temperature", "12.2") assert render(hass, "{{ int(states.sensor.temperature.state) }}") == 12 @@ -297,7 +314,7 @@ def test_int_function(hass): assert render(hass, "{{ int('bad', default=1) }}") == 1 -def test_bool_function(hass): +def test_bool_function(hass: HomeAssistant) -> None: """Test bool function.""" assert render(hass, "{{ bool(true) }}") is True assert render(hass, "{{ bool(false) }}") is False @@ -311,7 +328,7 @@ def test_bool_function(hass): assert render(hass, "{{ bool('unavailable', default=none) }}") is None -def test_bool_filter(hass): +def test_bool_filter(hass: HomeAssistant) -> None: """Test bool filter.""" assert render(hass, "{{ true | bool }}") is True assert render(hass, "{{ false | bool }}") is False @@ -366,7 +383,7 @@ def test_isnumber(hass, value, expected): ) -def test_rounding_value(hass): +def test_rounding_value(hass: HomeAssistant) -> None: """Test rounding value.""" hass.states.async_set("sensor.temperature", 12.78) @@ -406,7 +423,7 @@ def test_rounding_value(hass): ) -def test_rounding_value_on_error(hass): +def test_rounding_value_on_error(hass: HomeAssistant) -> None: """Test rounding value handling of error.""" # Test handling of invalid input with pytest.raises(TemplateError): @@ -419,7 +436,7 @@ def test_rounding_value_on_error(hass): assert render(hass, "{{ 'no_number' | round(default=1) }}") == 1 -def test_multiply(hass): +def test_multiply(hass: HomeAssistant) -> None: """Test multiply.""" tests = {10: 100} @@ -440,7 +457,7 @@ def test_multiply(hass): assert render(hass, "{{ 'no_number' | multiply(10, default=1) }}") == 1 -def test_logarithm(hass): +def test_logarithm(hass: HomeAssistant) -> None: """Test logarithm.""" tests = [ (4, 2, 2.0), @@ -482,7 +499,7 @@ def test_logarithm(hass): assert render(hass, "{{ log(0, 10, default=1) }}") == 1 -def test_sine(hass): +def test_sine(hass: HomeAssistant) -> None: """Test sine.""" tests = [ (0, 0.0), @@ -512,7 +529,7 @@ def test_sine(hass): assert render(hass, "{{ sin('no_number', default=1) }}") == 1 -def test_cos(hass): +def test_cos(hass: HomeAssistant) -> None: """Test cosine.""" tests = [ (0, 1.0), @@ -542,7 +559,7 @@ def test_cos(hass): assert render(hass, "{{ cos('no_number', default=1) }}") == 1 -def test_tan(hass): +def test_tan(hass: HomeAssistant) -> None: """Test tangent.""" tests = [ (0, 0.0), @@ -572,7 +589,7 @@ def test_tan(hass): assert render(hass, "{{ tan('no_number', default=1) }}") == 1 -def test_sqrt(hass): +def test_sqrt(hass: HomeAssistant) -> None: """Test square root.""" tests = [ (0, 0.0), @@ -602,7 +619,7 @@ def test_sqrt(hass): assert render(hass, "{{ sqrt('no_number', default=1) }}") == 1 -def test_arc_sine(hass): +def test_arc_sine(hass: HomeAssistant) -> None: """Test arcus sine.""" tests = [ (-1.0, -1.571), @@ -639,7 +656,7 @@ def test_arc_sine(hass): assert render(hass, "{{ asin('no_number', default=1) }}") == 1 -def test_arc_cos(hass): +def test_arc_cos(hass: HomeAssistant) -> None: """Test arcus cosine.""" tests = [ (-1.0, 3.142), @@ -676,7 +693,7 @@ def test_arc_cos(hass): assert render(hass, "{{ acos('no_number', default=1) }}") == 1 -def test_arc_tan(hass): +def test_arc_tan(hass: HomeAssistant) -> None: """Test arcus tangent.""" tests = [ (-10.0, -1.471), @@ -710,7 +727,7 @@ def test_arc_tan(hass): assert render(hass, "{{ atan('no_number', default=1) }}") == 1 -def test_arc_tan2(hass): +def test_arc_tan2(hass: HomeAssistant) -> None: """Test two parameter version of arcus tangent.""" tests = [ (-10.0, -10.0, -2.356), @@ -754,7 +771,7 @@ def test_arc_tan2(hass): assert render(hass, "{{ atan2('duck', 'goose', default=1) }}") == 1 -def test_strptime(hass): +def test_strptime(hass: HomeAssistant) -> None: """Test the parse timestamp method.""" tests = [ ("2016-10-19 15:22:05.588122 UTC", "%Y-%m-%d %H:%M:%S.%f %Z", None), @@ -790,7 +807,7 @@ def test_strptime(hass): assert render(hass, "{{ strptime('invalid', '%Y', default=1) }}") == 1 -def test_timestamp_custom(hass): +def test_timestamp_custom(hass: HomeAssistant) -> None: """Test the timestamps to custom filter.""" hass.config.set_time_zone("UTC") now = dt_util.utcnow() @@ -832,7 +849,7 @@ def test_timestamp_custom(hass): assert render(hass, "{{ None | timestamp_custom(default=1) }}") == 1 -def test_timestamp_local(hass): +def test_timestamp_local(hass: HomeAssistant) -> None: """Test the timestamps to local filter.""" hass.config.set_time_zone("UTC") tests = [ @@ -886,7 +903,7 @@ def test_as_datetime(hass, input): ) -def test_as_datetime_from_timestamp(hass): +def test_as_datetime_from_timestamp(hass: HomeAssistant) -> None: """Test converting a UNIX timestamp to a date object.""" tests = [ (1469119144, "2016-07-21 16:39:04+00:00"), @@ -916,7 +933,7 @@ def test_as_datetime_from_timestamp(hass): ) -def test_as_local(hass): +def test_as_local(hass: HomeAssistant) -> None: """Test converting time to local.""" hass.states.async_set("test.object", "available") @@ -929,7 +946,7 @@ def test_as_local(hass): ).async_render() == str(dt_util.as_local(last_updated)) -def test_to_json(hass): +def test_to_json(hass: HomeAssistant) -> None: """Test the object to JSON string filter.""" # Note that we're not testing the actual json.loads and json.dumps methods, @@ -941,7 +958,7 @@ def test_to_json(hass): assert actual_result == expected_result -def test_to_json_string(hass): +def test_to_json_string(hass: HomeAssistant) -> None: """Test the object to JSON string filter.""" # Note that we're not testing the actual json.loads and json.dumps methods, @@ -956,7 +973,7 @@ def test_to_json_string(hass): assert actual_value == '"Bar ҝ éèà"' -def test_from_json(hass): +def test_from_json(hass: HomeAssistant) -> None: """Test the JSON string to object filter.""" # Note that we're not testing the actual json.loads and json.dumps methods, @@ -968,7 +985,7 @@ def test_from_json(hass): assert actual_result == expected_result -def test_average(hass): +def test_average(hass: HomeAssistant) -> None: """Test the average filter.""" assert template.Template("{{ [1, 2, 3] | average }}", hass).async_render() == 2 assert template.Template("{{ average([1, 2, 3]) }}", hass).async_render() == 2 @@ -996,7 +1013,7 @@ def test_average(hass): template.Template("{{ average([]) }}", hass).async_render() -def test_min(hass): +def test_min(hass: HomeAssistant) -> None: """Test the min filter.""" assert template.Template("{{ [1, 2, 3] | min }}", hass).async_render() == 1 assert template.Template("{{ min([1, 2, 3]) }}", hass).async_render() == 1 @@ -1012,7 +1029,7 @@ def test_min(hass): template.Template("{{ min(1) }}", hass).async_render() -def test_max(hass): +def test_max(hass: HomeAssistant) -> None: """Test the max filter.""" assert template.Template("{{ [1, 2, 3] | max }}", hass).async_render() == 3 assert template.Template("{{ max([1, 2, 3]) }}", hass).async_render() == 3 @@ -1095,12 +1112,12 @@ def test_min_max_attribute(hass, attribute): ) -def test_ord(hass): +def test_ord(hass: HomeAssistant) -> None: """Test the ord filter.""" assert template.Template('{{ "d" | ord }}', hass).async_render() == 100 -def test_base64_encode(hass): +def test_base64_encode(hass: HomeAssistant) -> None: """Test the base64_encode filter.""" assert ( template.Template('{{ "homeassistant" | base64_encode }}', hass).async_render() @@ -1108,7 +1125,7 @@ def test_base64_encode(hass): ) -def test_base64_decode(hass): +def test_base64_decode(hass: HomeAssistant) -> None: """Test the base64_decode filter.""" assert ( template.Template( @@ -1118,7 +1135,7 @@ def test_base64_decode(hass): ) -def test_slugify(hass): +def test_slugify(hass: HomeAssistant) -> None: """Test the slugify filter.""" assert ( template.Template('{{ slugify("Home Assistant") }}', hass).async_render() @@ -1138,7 +1155,7 @@ def test_slugify(hass): ) -def test_ordinal(hass): +def test_ordinal(hass: HomeAssistant) -> None: """Test the ordinal filter.""" tests = [ (1, "1st"), @@ -1158,7 +1175,7 @@ def test_ordinal(hass): ) -def test_timestamp_utc(hass): +def test_timestamp_utc(hass: HomeAssistant) -> None: """Test the timestamps to local filter.""" now = dt_util.utcnow() tests = [ @@ -1186,7 +1203,7 @@ def test_timestamp_utc(hass): assert render(hass, "{{ None | timestamp_utc(default=1) }}") == 1 -def test_as_timestamp(hass): +def test_as_timestamp(hass: HomeAssistant) -> None: """Test the as_timestamp function.""" with pytest.raises(TemplateError): template.Template('{{ as_timestamp("invalid") }}', hass).async_render() @@ -1218,24 +1235,24 @@ def test_random_every_time(test_choice, hass): assert tpl.async_render() == "bar" -def test_passing_vars_as_keywords(hass): +def test_passing_vars_as_keywords(hass: HomeAssistant) -> None: """Test passing variables as keywords.""" assert template.Template("{{ hello }}", hass).async_render(hello=127) == 127 -def test_passing_vars_as_vars(hass): +def test_passing_vars_as_vars(hass: HomeAssistant) -> None: """Test passing variables as variables.""" assert template.Template("{{ hello }}", hass).async_render({"hello": 127}) == 127 -def test_passing_vars_as_list(hass): +def test_passing_vars_as_list(hass: HomeAssistant) -> None: """Test passing variables as list.""" assert template.render_complex( template.Template("{{ hello }}", hass), {"hello": ["foo", "bar"]} ) == ["foo", "bar"] -def test_passing_vars_as_list_element(hass): +def test_passing_vars_as_list_element(hass: HomeAssistant) -> None: """Test passing variables as list.""" assert ( template.render_complex( @@ -1245,7 +1262,7 @@ def test_passing_vars_as_list_element(hass): ) -def test_passing_vars_as_dict_element(hass): +def test_passing_vars_as_dict_element(hass: HomeAssistant) -> None: """Test passing variables as list.""" assert ( template.render_complex( @@ -1255,44 +1272,50 @@ def test_passing_vars_as_dict_element(hass): ) -def test_passing_vars_as_dict(hass): +def test_passing_vars_as_dict(hass: HomeAssistant) -> None: """Test passing variables as list.""" assert template.render_complex( template.Template("{{ hello }}", hass), {"hello": {"foo": "bar"}} ) == {"foo": "bar"} -def test_render_with_possible_json_value_with_valid_json(hass): +def test_render_with_possible_json_value_with_valid_json(hass: HomeAssistant) -> None: """Render with possible JSON value with valid JSON.""" tpl = template.Template("{{ value_json.hello }}", hass) assert tpl.async_render_with_possible_json_value('{"hello": "world"}') == "world" -def test_render_with_possible_json_value_with_invalid_json(hass): +def test_render_with_possible_json_value_with_invalid_json(hass: HomeAssistant) -> None: """Render with possible JSON value with invalid JSON.""" tpl = template.Template("{{ value_json }}", hass) assert tpl.async_render_with_possible_json_value("{ I AM NOT JSON }") == "" -def test_render_with_possible_json_value_with_template_error_value(hass): +def test_render_with_possible_json_value_with_template_error_value( + hass: HomeAssistant, +) -> None: """Render with possible JSON value with template error value.""" tpl = template.Template("{{ non_existing.variable }}", hass) assert tpl.async_render_with_possible_json_value("hello", "-") == "-" -def test_render_with_possible_json_value_with_missing_json_value(hass): +def test_render_with_possible_json_value_with_missing_json_value( + hass: HomeAssistant, +) -> None: """Render with possible JSON value with unknown JSON object.""" tpl = template.Template("{{ value_json.goodbye }}", hass) assert tpl.async_render_with_possible_json_value('{"hello": "world"}') == "" -def test_render_with_possible_json_value_valid_with_is_defined(hass): +def test_render_with_possible_json_value_valid_with_is_defined( + hass: HomeAssistant, +) -> None: """Render with possible JSON value with known JSON object.""" tpl = template.Template("{{ value_json.hello|is_defined }}", hass) assert tpl.async_render_with_possible_json_value('{"hello": "world"}') == "world" -def test_render_with_possible_json_value_undefined_json(hass): +def test_render_with_possible_json_value_undefined_json(hass: HomeAssistant) -> None: """Render with possible JSON value with unknown JSON object.""" tpl = template.Template("{{ value_json.bye|is_defined }}", hass) assert ( @@ -1301,13 +1324,15 @@ def test_render_with_possible_json_value_undefined_json(hass): ) -def test_render_with_possible_json_value_undefined_json_error_value(hass): +def test_render_with_possible_json_value_undefined_json_error_value( + hass: HomeAssistant, +) -> None: """Render with possible JSON value with unknown JSON object.""" tpl = template.Template("{{ value_json.bye|is_defined }}", hass) assert tpl.async_render_with_possible_json_value('{"hello": "world"}', "") == "" -def test_render_with_possible_json_value_non_string_value(hass): +def test_render_with_possible_json_value_non_string_value(hass: HomeAssistant) -> None: """Render with possible JSON value with non-string value.""" tpl = template.Template( """ @@ -1320,7 +1345,7 @@ def test_render_with_possible_json_value_non_string_value(hass): assert tpl.async_render_with_possible_json_value(value) == expected -def test_if_state_exists(hass): +def test_if_state_exists(hass: HomeAssistant) -> None: """Test if state exists works.""" hass.states.async_set("test.object", "available") tpl = template.Template( @@ -1329,7 +1354,7 @@ def test_if_state_exists(hass): assert tpl.async_render() == "exists" -def test_is_state(hass): +def test_is_state(hass: HomeAssistant) -> None: """Test is_state method.""" hass.states.async_set("test.object", "available") tpl = template.Template( @@ -1365,7 +1390,7 @@ def test_is_state(hass): assert tpl.async_render() == "test.object" -def test_is_state_attr(hass): +def test_is_state_attr(hass: HomeAssistant) -> None: """Test is_state_attr method.""" hass.states.async_set("test.object", "available", {"mode": "on"}) tpl = template.Template( @@ -1401,7 +1426,7 @@ def test_is_state_attr(hass): assert tpl.async_render() == "test.object" -def test_state_attr(hass): +def test_state_attr(hass: HomeAssistant) -> None: """Test state_attr method.""" hass.states.async_set( "test.object", "available", {"effect": "action", "mode": "on"} @@ -1439,7 +1464,7 @@ def test_state_attr(hass): assert tpl.async_render() == "action" -def test_states_function(hass): +def test_states_function(hass: HomeAssistant) -> None: """Test using states as a function.""" hass.states.async_set("test.object", "available") tpl = template.Template('{{ states("test.object") }}', hass) @@ -1648,7 +1673,7 @@ def test_timedelta(mock_is_safe, hass): assert result == "15 days" -def test_version(hass): +def test_version(hass: HomeAssistant) -> None: """Test version filter and function.""" filter_result = template.Template( "{{ '2099.9.9' | version}}", @@ -1687,7 +1712,7 @@ def test_version(hass): ).async_render() -def test_regex_match(hass): +def test_regex_match(hass: HomeAssistant) -> None: """Test regex_match method.""" tpl = template.Template( r""" @@ -1722,7 +1747,7 @@ def test_regex_match(hass): assert tpl.async_render() is True -def test_match_test(hass): +def test_match_test(hass: HomeAssistant) -> None: """Test match test.""" tpl = template.Template( r""" @@ -1733,7 +1758,7 @@ def test_match_test(hass): assert tpl.async_render() is True -def test_regex_search(hass): +def test_regex_search(hass: HomeAssistant) -> None: """Test regex_search method.""" tpl = template.Template( r""" @@ -1768,7 +1793,7 @@ def test_regex_search(hass): assert tpl.async_render() is True -def test_search_test(hass): +def test_search_test(hass: HomeAssistant) -> None: """Test search test.""" tpl = template.Template( r""" @@ -1779,7 +1804,7 @@ def test_search_test(hass): assert tpl.async_render() is True -def test_regex_replace(hass): +def test_regex_replace(hass: HomeAssistant) -> None: """Test regex_replace method.""" tpl = template.Template( r""" @@ -1798,7 +1823,7 @@ def test_regex_replace(hass): assert tpl.async_render() == ["Home Assistant test"] -def test_regex_findall(hass): +def test_regex_findall(hass: HomeAssistant) -> None: """Test regex_findall method.""" tpl = template.Template( """ @@ -1809,7 +1834,7 @@ def test_regex_findall(hass): assert tpl.async_render() == ["JFK", "LHR"] -def test_regex_findall_index(hass): +def test_regex_findall_index(hass: HomeAssistant) -> None: """Test regex_findall_index method.""" tpl = template.Template( """ @@ -1836,7 +1861,7 @@ def test_regex_findall_index(hass): assert tpl.async_render() == "LHR" -def test_bitwise_and(hass): +def test_bitwise_and(hass: HomeAssistant) -> None: """Test bitwise_and method.""" tpl = template.Template( """ @@ -1861,7 +1886,7 @@ def test_bitwise_and(hass): assert tpl.async_render() == 8 & 2 -def test_bitwise_or(hass): +def test_bitwise_or(hass: HomeAssistant) -> None: """Test bitwise_or method.""" tpl = template.Template( """ @@ -2020,7 +2045,7 @@ def test_unpack(hass, caplog): ) -def test_distance_function_with_1_state(hass): +def test_distance_function_with_1_state(hass: HomeAssistant) -> None: """Test distance function with 1 state.""" _set_up_units(hass) hass.states.async_set( @@ -2030,7 +2055,7 @@ def test_distance_function_with_1_state(hass): assert tpl.async_render() == 187 -def test_distance_function_with_2_states(hass): +def test_distance_function_with_2_states(hass: HomeAssistant) -> None: """Test distance function with 2 states.""" _set_up_units(hass) hass.states.async_set( @@ -2047,14 +2072,14 @@ def test_distance_function_with_2_states(hass): assert tpl.async_render() == 187 -def test_distance_function_with_1_coord(hass): +def test_distance_function_with_1_coord(hass: HomeAssistant) -> None: """Test distance function with 1 coord.""" _set_up_units(hass) tpl = template.Template('{{ distance("32.87336", "-117.22943") | round }}', hass) assert tpl.async_render() == 187 -def test_distance_function_with_2_coords(hass): +def test_distance_function_with_2_coords(hass: HomeAssistant) -> None: """Test distance function with 2 coords.""" _set_up_units(hass) assert ( @@ -2067,7 +2092,7 @@ def test_distance_function_with_2_coords(hass): ) -def test_distance_function_with_1_state_1_coord(hass): +def test_distance_function_with_1_state_1_coord(hass: HomeAssistant) -> None: """Test distance function with 1 state 1 coord.""" _set_up_units(hass) hass.states.async_set( @@ -2088,7 +2113,7 @@ def test_distance_function_with_1_state_1_coord(hass): assert tpl2.async_render() == 187 -def test_distance_function_return_none_if_invalid_state(hass): +def test_distance_function_return_none_if_invalid_state(hass: HomeAssistant) -> None: """Test distance function return None if invalid state.""" hass.states.async_set("test.object_2", "happy", {"latitude": 10}) tpl = template.Template("{{ distance(states.test.object_2) | round }}", hass) @@ -2096,7 +2121,7 @@ def test_distance_function_return_none_if_invalid_state(hass): tpl.async_render() -def test_distance_function_return_none_if_invalid_coord(hass): +def test_distance_function_return_none_if_invalid_coord(hass: HomeAssistant) -> None: """Test distance function return None if invalid coord.""" assert ( template.Template('{{ distance("123", "abc") }}', hass).async_render() is None @@ -2113,7 +2138,7 @@ def test_distance_function_return_none_if_invalid_coord(hass): assert tpl.async_render() is None -def test_distance_function_with_2_entity_ids(hass): +def test_distance_function_with_2_entity_ids(hass: HomeAssistant) -> None: """Test distance function with 2 entity ids.""" _set_up_units(hass) hass.states.async_set( @@ -2130,7 +2155,7 @@ def test_distance_function_with_2_entity_ids(hass): assert tpl.async_render() == 187 -def test_distance_function_with_1_entity_1_coord(hass): +def test_distance_function_with_1_entity_1_coord(hass: HomeAssistant) -> None: """Test distance function with 1 entity_id and 1 coord.""" _set_up_units(hass) hass.states.async_set( @@ -2144,7 +2169,7 @@ def test_distance_function_with_1_entity_1_coord(hass): assert tpl.async_render() == 187 -def test_closest_function_home_vs_domain(hass): +def test_closest_function_home_vs_domain(hass: HomeAssistant) -> None: """Test closest function home vs domain.""" hass.states.async_set( "test_domain.object", @@ -2176,7 +2201,7 @@ def test_closest_function_home_vs_domain(hass): ) -def test_closest_function_home_vs_all_states(hass): +def test_closest_function_home_vs_all_states(hass: HomeAssistant) -> None: """Test closest function home vs all states.""" hass.states.async_set( "test_domain.object", @@ -2204,7 +2229,7 @@ def test_closest_function_home_vs_all_states(hass): ) -async def test_closest_function_home_vs_group_entity_id(hass): +async def test_closest_function_home_vs_group_entity_id(hass: HomeAssistant) -> None: """Test closest function home vs group entity id.""" hass.states.async_set( "test_domain.object", @@ -2232,7 +2257,7 @@ async def test_closest_function_home_vs_group_entity_id(hass): assert info.rate_limit is None -async def test_closest_function_home_vs_group_state(hass): +async def test_closest_function_home_vs_group_state(hass: HomeAssistant) -> None: """Test closest function home vs group state.""" hass.states.async_set( "test_domain.object", @@ -2266,7 +2291,7 @@ async def test_closest_function_home_vs_group_state(hass): assert info.rate_limit is None -async def test_expand(hass): +async def test_expand(hass: HomeAssistant) -> None: """Test expand function.""" info = render_to_info(hass, "{{ expand('test.object') }}") assert_result_info(info, [], ["test.object"]) @@ -2429,7 +2454,7 @@ async def test_expand(hass): ) -async def test_device_entities(hass): +async def test_device_entities(hass: HomeAssistant) -> None: """Test device_entities function.""" config_entry = MockConfigEntry(domain="light") device_registry = mock_device_registry(hass) @@ -2502,7 +2527,7 @@ async def test_device_entities(hass): assert info.rate_limit is None -async def test_integration_entities(hass): +async def test_integration_entities(hass: HomeAssistant) -> None: """Test integration_entities function.""" entity_registry = mock_registry(hass) @@ -2540,7 +2565,7 @@ async def test_integration_entities(hass): assert info.rate_limit is None -async def test_config_entry_id(hass): +async def test_config_entry_id(hass: HomeAssistant) -> None: """Test config_entry_id function.""" config_entry = MockConfigEntry(domain="light", title="Some integration") config_entry.add_to_hass(hass) @@ -2566,7 +2591,7 @@ async def test_config_entry_id(hass): assert info.rate_limit is None -async def test_device_id(hass): +async def test_device_id(hass: HomeAssistant) -> None: """Test device_id function.""" config_entry = MockConfigEntry(domain="light") device_registry = mock_device_registry(hass) @@ -2609,7 +2634,7 @@ async def test_device_id(hass): assert info.rate_limit is None -async def test_device_attr(hass): +async def test_device_attr(hass: HomeAssistant) -> None: """Test device_attr and is_device_attr functions.""" config_entry = MockConfigEntry(domain="light") device_registry = mock_device_registry(hass) @@ -2714,7 +2739,7 @@ async def test_device_attr(hass): assert info.rate_limit is None -async def test_area_id(hass): +async def test_area_id(hass: HomeAssistant) -> None: """Test area_id function.""" config_entry = MockConfigEntry(domain="light") device_registry = mock_device_registry(hass) @@ -2818,7 +2843,7 @@ async def test_area_id(hass): assert info.rate_limit is None -async def test_area_name(hass): +async def test_area_name(hass: HomeAssistant) -> None: """Test area_name function.""" config_entry = MockConfigEntry(domain="light") device_registry = mock_device_registry(hass) @@ -2897,7 +2922,7 @@ async def test_area_name(hass): assert info.rate_limit is None -async def test_area_entities(hass): +async def test_area_entities(hass: HomeAssistant) -> None: """Test area_entities function.""" config_entry = MockConfigEntry(domain="light") entity_registry = mock_registry(hass) @@ -2950,7 +2975,7 @@ async def test_area_entities(hass): assert info.rate_limit is None -async def test_area_devices(hass): +async def test_area_devices(hass: HomeAssistant) -> None: """Test area_devices function.""" config_entry = MockConfigEntry(domain="light") device_registry = mock_device_registry(hass) @@ -2982,7 +3007,7 @@ async def test_area_devices(hass): assert info.rate_limit is None -def test_closest_function_to_coord(hass): +def test_closest_function_to_coord(hass: HomeAssistant) -> None: """Test closest function to coord.""" hass.states.async_set( "test_domain.closest_home", @@ -3028,7 +3053,7 @@ def test_closest_function_to_coord(hass): assert tpl.async_render() == "test_domain.closest_zone" -def test_async_render_to_info_with_branching(hass): +def test_async_render_to_info_with_branching(hass: HomeAssistant) -> None: """Test async_render_to_info function by domain.""" hass.states.async_set("light.a", "off") hass.states.async_set("light.b", "on") @@ -3060,7 +3085,7 @@ def test_async_render_to_info_with_branching(hass): assert info.rate_limit is None -def test_async_render_to_info_with_complex_branching(hass): +def test_async_render_to_info_with_complex_branching(hass: HomeAssistant) -> None: """Test async_render_to_info function by domain.""" hass.states.async_set("light.a", "off") hass.states.async_set("light.b", "on") @@ -3097,7 +3122,9 @@ def test_async_render_to_info_with_complex_branching(hass): assert info.rate_limit == template.DOMAIN_STATES_RATE_LIMIT -async def test_async_render_to_info_with_wildcard_matching_entity_id(hass): +async def test_async_render_to_info_with_wildcard_matching_entity_id( + hass: HomeAssistant, +) -> None: """Test tracking template with a wildcard.""" template_complex_str = r""" @@ -3119,7 +3146,9 @@ async def test_async_render_to_info_with_wildcard_matching_entity_id(hass): assert info.rate_limit == template.DOMAIN_STATES_RATE_LIMIT -async def test_async_render_to_info_with_wildcard_matching_state(hass): +async def test_async_render_to_info_with_wildcard_matching_state( + hass: HomeAssistant, +) -> None: """Test tracking template with a wildcard.""" template_complex_str = """ @@ -3170,7 +3199,7 @@ async def test_async_render_to_info_with_wildcard_matching_state(hass): assert info.rate_limit == template.DOMAIN_STATES_RATE_LIMIT -def test_nested_async_render_to_info_case(hass): +def test_nested_async_render_to_info_case(hass: HomeAssistant) -> None: """Test a deeply nested state with async_render_to_info.""" hass.states.async_set("input_select.picker", "vacuum.a") @@ -3183,7 +3212,7 @@ def test_nested_async_render_to_info_case(hass): assert info.rate_limit is None -def test_result_as_boolean(hass): +def test_result_as_boolean(hass: HomeAssistant) -> None: """Test converting a template result to a boolean.""" assert template.result_as_boolean(True) is True @@ -3213,7 +3242,7 @@ def test_result_as_boolean(hass): assert template.result_as_boolean(None) is False -def test_closest_function_to_entity_id(hass): +def test_closest_function_to_entity_id(hass: HomeAssistant) -> None: """Test closest function to entity id.""" hass.states.async_set( "test_domain.closest_home", @@ -3270,7 +3299,7 @@ def test_closest_function_to_entity_id(hass): ) -def test_closest_function_to_state(hass): +def test_closest_function_to_state(hass: HomeAssistant) -> None: """Test closest function to state.""" hass.states.async_set( "test_domain.closest_home", @@ -3307,7 +3336,7 @@ def test_closest_function_to_state(hass): ) -def test_closest_function_invalid_state(hass): +def test_closest_function_invalid_state(hass: HomeAssistant) -> None: """Test closest function invalid state.""" hass.states.async_set( "test_domain.closest_home", @@ -3325,7 +3354,7 @@ def test_closest_function_invalid_state(hass): ) -def test_closest_function_state_with_invalid_location(hass): +def test_closest_function_state_with_invalid_location(hass: HomeAssistant) -> None: """Test closest function state with invalid location.""" hass.states.async_set( "test_domain.closest_home", @@ -3341,7 +3370,7 @@ def test_closest_function_state_with_invalid_location(hass): ) -def test_closest_function_invalid_coordinates(hass): +def test_closest_function_invalid_coordinates(hass: HomeAssistant) -> None: """Test closest function invalid coordinates.""" hass.states.async_set( "test_domain.closest_home", @@ -3366,14 +3395,14 @@ def test_closest_function_invalid_coordinates(hass): ) -def test_closest_function_no_location_states(hass): +def test_closest_function_no_location_states(hass: HomeAssistant) -> None: """Test closest function without location states.""" assert ( template.Template("{{ closest(states).entity_id }}", hass).async_render() == "" ) -def test_generate_filter_iterators(hass): +def test_generate_filter_iterators(hass: HomeAssistant) -> None: """Test extract entities function with none entities stuff.""" info = render_to_info( hass, @@ -3430,7 +3459,7 @@ def test_generate_filter_iterators(hass): assert_result_info(info, "sensor.test_sensor=value,", [], ["sensor"]) -def test_generate_select(hass): +def test_generate_select(hass: HomeAssistant) -> None: """Test extract entities function with none entities stuff.""" template_str = """ {{ states.sensor|selectattr("state","equalto","off") @@ -3455,7 +3484,7 @@ def test_generate_select(hass): assert info.domains_lifecycle == {"sensor"} -async def test_async_render_to_info_in_conditional(hass): +async def test_async_render_to_info_in_conditional(hass: HomeAssistant) -> None: """Test extract entities function with none entities stuff.""" template_str = """ {{ states("sensor.xyz") == "dog" }} @@ -3491,7 +3520,7 @@ async def test_async_render_to_info_in_conditional(hass): assert_result_info(info, "oink", ["sensor.xyz", "sensor.pig"], []) -def test_jinja_namespace(hass): +def test_jinja_namespace(hass: HomeAssistant) -> None: """Test Jinja's namespace command can be used.""" test_template = template.Template( ( @@ -3509,7 +3538,7 @@ def test_jinja_namespace(hass): assert test_template.async_render() == "another value" -def test_state_with_unit(hass): +def test_state_with_unit(hass: HomeAssistant) -> None: """Test the state_with_unit property helper.""" hass.states.async_set("sensor.test", "23", {ATTR_UNIT_OF_MEASUREMENT: "beers"}) hass.states.async_set("sensor.test2", "wow") @@ -3533,7 +3562,7 @@ def test_state_with_unit(hass): assert tpl.async_render() == "" -def test_length_of_states(hass): +def test_length_of_states(hass: HomeAssistant) -> None: """Test fetching the length of states.""" hass.states.async_set("sensor.test", "23") hass.states.async_set("sensor.test2", "wow") @@ -3546,14 +3575,14 @@ def test_length_of_states(hass): assert tpl.async_render() == 2 -def test_render_complex_handling_non_template_values(hass): +def test_render_complex_handling_non_template_values(hass: HomeAssistant) -> None: """Test that we can render non-template fields.""" assert template.render_complex( {True: 1, False: template.Template("{{ hello }}", hass)}, {"hello": 2} ) == {True: 1, False: 2} -def test_urlencode(hass): +def test_urlencode(hass: HomeAssistant) -> None: """Test the urlencode method.""" tpl = template.Template( ("{% set dict = {'foo': 'x&y', 'bar': 42} %}{{ dict | urlencode }}"), @@ -3611,7 +3640,7 @@ def test_iif(hass: HomeAssistant) -> None: assert tpl.async_render() == "no" -async def test_cache_garbage_collection(): +async def test_cache_garbage_collection() -> None: """Test caching a template.""" template_string = ( "{% set dict = {'foo': 'x&y', 'bar': 42} %} {{ dict | urlencode }}" @@ -3642,7 +3671,7 @@ async def test_cache_garbage_collection(): ) # pylint: disable=protected-access -def test_is_template_string(): +def test_is_template_string() -> None: """Test is template string.""" assert template.is_template_string("{{ x }}") is True assert template.is_template_string("{% if x == 2 %}1{% else %}0{%end if %}") is True @@ -3651,7 +3680,7 @@ def test_is_template_string(): assert template.is_template_string("Some Text") is False -async def test_protected_blocked(hass): +async def test_protected_blocked(hass: HomeAssistant) -> None: """Test accessing __getattr__ produces a template error.""" tmp = template.Template('{{ states.__getattr__("any") }}', hass) with pytest.raises(TemplateError): @@ -3666,7 +3695,7 @@ async def test_protected_blocked(hass): tmp.async_render() -async def test_demo_template(hass): +async def test_demo_template(hass: HomeAssistant) -> None: """Test the demo template works as expected.""" hass.states.async_set( "sun.sun", @@ -3709,7 +3738,7 @@ For loop example getting 3 entity values: assert "sun" in result -async def test_slice_states(hass): +async def test_slice_states(hass: HomeAssistant) -> None: """Test iterating states with a slice.""" hass.states.async_set("sensor.test", "23") @@ -3720,7 +3749,7 @@ async def test_slice_states(hass): assert tpl.async_render() == "sensor.test" -async def test_lifecycle(hass): +async def test_lifecycle(hass: HomeAssistant) -> None: """Test that we limit template render info for lifecycle events.""" hass.states.async_set("sun.sun", "above", {"elevation": 50, "next_rising": "later"}) for i in range(2): @@ -3756,7 +3785,7 @@ async def test_lifecycle(hass): assert info.filter_lifecycle("sensor.removed") is True -async def test_template_timeout(hass): +async def test_template_timeout(hass: HomeAssistant) -> None: """Test to see if a template will timeout.""" for i in range(2): hass.states.async_set(f"sensor.sensor{i}", "on") @@ -3781,14 +3810,14 @@ async def test_template_timeout(hass): assert await tmp5.async_render_will_timeout(0.000001) is True -async def test_template_timeout_raise(hass): +async def test_template_timeout_raise(hass: HomeAssistant) -> None: """Test we can raise from.""" tmp2 = template.Template("{{ error_invalid + 1 }}", hass) with pytest.raises(TemplateError): assert await tmp2.async_render_will_timeout(3) is False -async def test_lights(hass): +async def test_lights(hass: HomeAssistant) -> None: """Test we can sort lights.""" tmpl = """ @@ -3818,7 +3847,7 @@ async def test_lights(hass): assert f"sensor{i}" in info.result() -async def test_template_errors(hass): +async def test_template_errors(hass: HomeAssistant) -> None: """Test template rendering wraps exceptions with TemplateError.""" with pytest.raises(TemplateError): @@ -3834,7 +3863,7 @@ async def test_template_errors(hass): template.Template("{{ utcnow() | random }}", hass).async_render() -async def test_state_attributes(hass): +async def test_state_attributes(hass: HomeAssistant) -> None: """Test state attributes.""" hass.states.async_set("sensor.test", "23") @@ -3882,7 +3911,7 @@ async def test_state_attributes(hass): tpl.async_render() -async def test_unavailable_states(hass): +async def test_unavailable_states(hass: HomeAssistant) -> None: """Test watching unavailable states.""" for i in range(10): @@ -3905,7 +3934,7 @@ async def test_unavailable_states(hass): assert tpl.async_render() == "light.none, light.unavailable, light.unknown" -async def test_legacy_templates(hass): +async def test_legacy_templates(hass: HomeAssistant) -> None: """Test if old template behavior works when legacy templates are enabled.""" hass.states.async_set("sensor.temperature", "12") @@ -3921,7 +3950,7 @@ async def test_legacy_templates(hass): ) -async def test_no_result_parsing(hass): +async def test_no_result_parsing(hass: HomeAssistant) -> None: """Test if templates results are not parsed.""" hass.states.async_set("sensor.temperature", "12") @@ -3943,14 +3972,14 @@ async def test_no_result_parsing(hass): ) -async def test_is_static_still_ast_evals(hass): +async def test_is_static_still_ast_evals(hass: HomeAssistant) -> None: """Test is_static still converts to native type.""" tpl = template.Template("[1, 2]", hass) assert tpl.is_static assert tpl.async_render() == [1, 2] -async def test_result_wrappers(hass): +async def test_result_wrappers(hass: HomeAssistant) -> None: """Test result wrappers.""" for text, native, orig_type, schema in ( ("[1, 2]", [1, 2], list, vol.Schema([int])), @@ -3973,7 +4002,7 @@ async def test_result_wrappers(hass): ) -async def test_parse_result(hass): +async def test_parse_result(hass: HomeAssistant) -> None: """Test parse result.""" for tpl, result in ( ('{{ "{{}}" }}', "{{}}"), @@ -4010,7 +4039,7 @@ async def test_undefined_variable(hass, caplog): ) -async def test_template_states_blocks_setitem(hass): +async def test_template_states_blocks_setitem(hass: HomeAssistant) -> None: """Test we cannot setitem on TemplateStates.""" hass.states.async_set("light.new", STATE_ON) state = hass.states.get("light.new") @@ -4019,7 +4048,7 @@ async def test_template_states_blocks_setitem(hass): template_state["any"] = "any" -async def test_template_states_can_serialize(hass): +async def test_template_states_can_serialize(hass: HomeAssistant) -> None: """Test TemplateState is serializable.""" hass.states.async_set("light.new", STATE_ON) state = hass.states.get("light.new")