def test_render_with_possible_json_value_with_invalid_json(self): """Render with possible JSON value with invalid JSON.""" tpl = template.Template('{{ value_json }}', self.hass) self.assertEqual( '', tpl.render_with_possible_json_value('{ I AM NOT JSON }'))
def test_render_with_possible_json_value_valid_with_is_defined(hass): """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_distance_function_with_1_coord(hass): """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_render_with_possible_json_value_with_valid_json(hass): """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_template_error_value(hass): """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_ord(hass): """Test the ord filter.""" assert template.Template('{{ "d" | ord }}', hass).async_render() == "100"
def test_passing_vars_as_keywords(hass): """Test passing variables as keywords.""" assert template.Template("{{ hello }}", hass).async_render(hello=127) == "127"
def test_distance_function_with_1_coord(self): """Test distance function with 1 coord.""" tpl = template.Template( '{{ distance("32.87336", "-117.22943") | round }}', self.hass) self.assertEqual('187', tpl.render())
def test_closest_function_no_location_states(self): """Test closest function without location states.""" self.assertEqual( '', template.Template('{{ closest(states).entity_id }}', self.hass).render())
def test_render_with_possible_json_value_undefined_json_error_value(self): """Render with possible JSON value with unknown JSON object.""" tpl = template.Template('{{ value_json.bye|is_defined }}', self.hass) self.assertEqual( '', tpl.render_with_possible_json_value('{"hello": "world"}', ''))
def test_raise_exception_on_error(self): """Test raising an exception on error.""" with self.assertRaises(TemplateError): template.Template('{{ invalid_syntax').ensure_valid()
def test_render_with_possible_json_value_valid_with_is_defined(self): """Render with possible JSON value with known JSON object.""" tpl = template.Template('{{ value_json.hello|is_defined }}', self.hass) self.assertEqual( 'world', tpl.render_with_possible_json_value('{"hello": "world"}'))
def test_render_with_possible_json_value_with_missing_json_value(self): """Render with possible JSON value with unknown JSON object.""" tpl = template.Template('{{ value_json.goodbye }}', self.hass) self.assertEqual( '', tpl.render_with_possible_json_value('{"hello": "world"}'))
def test_render_with_possible_json_value_with_template_error_value(self): """Render with possible JSON value with template error value.""" tpl = template.Template('{{ non_existing.variable }}', self.hass) self.assertEqual('-', tpl.render_with_possible_json_value('hello', '-'))
def test_min(hass): """Test the min filter.""" assert template.Template("{{ [1, 2, 3] | min }}", hass).async_render() == "1"
async def async_service_handler(service: ServiceCall) -> None: """Execute a shell command service.""" cmd = conf[service.service] if cmd in cache: prog, args, args_compiled = cache[cmd] elif " " not in cmd: prog = cmd args = None args_compiled = None cache[cmd] = prog, args, args_compiled else: prog, args = cmd.split(" ", 1) args_compiled = template.Template(args, hass) cache[cmd] = prog, args, args_compiled if args_compiled: try: rendered_args = args_compiled.async_render( variables=service.data, parse_result=False) except TemplateError as ex: _LOGGER.exception("Error rendering command template: %s", ex) return else: rendered_args = None if rendered_args == args: # No template used. default behavior # pylint: disable=no-member create_process = asyncio.subprocess.create_subprocess_shell( cmd, stdin=None, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, ) else: # Template used. Break into list and use create_subprocess_exec # (which uses shell=False) for security shlexed_cmd = [prog] + shlex.split(rendered_args) # pylint: disable=no-member create_process = asyncio.subprocess.create_subprocess_exec( *shlexed_cmd, stdin=None, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, ) process = await create_process try: stdout_data, stderr_data = await asyncio.wait_for( process.communicate(), COMMAND_TIMEOUT) except asyncio.TimeoutError: _LOGGER.exception("Timed out running command: `%s`, after: %ss", cmd, COMMAND_TIMEOUT) if process: try: await process.kill() except TypeError: pass del process return if stdout_data: _LOGGER.debug( "Stdout of command: `%s`, return code: %s:\n%s", cmd, process.returncode, stdout_data, ) if stderr_data: _LOGGER.debug( "Stderr of command: `%s`, return code: %s:\n%s", cmd, process.returncode, stderr_data, ) if process.returncode != 0: _LOGGER.exception("Error running command: `%s`, return code: %s", cmd, process.returncode)
def test_max(hass): """Test the max filter.""" assert template.Template("{{ [1, 2, 3] | max }}", hass).async_render() == "3"
async def handle_render_template(hass: HomeAssistant, connection: ActiveConnection, msg: dict[str, Any]) -> None: """Handle render_template command.""" template_str = msg["template"] template_obj = template.Template(template_str, hass) # type: ignore[no-untyped-call] variables = msg.get("variables") timeout = msg.get("timeout") info = None if timeout: try: timed_out = await template_obj.async_render_will_timeout( timeout, strict=msg["strict"]) except TemplateError as ex: connection.send_error(msg["id"], const.ERR_TEMPLATE_ERROR, str(ex)) return if timed_out: connection.send_error( msg["id"], const.ERR_TEMPLATE_ERROR, f"Exceeded maximum execution time of {timeout}s", ) return @callback def _template_listener(event: Event, updates: list[TrackTemplateResult]) -> None: nonlocal info track_template_result = updates.pop() result = track_template_result.result if isinstance(result, TemplateError): connection.send_error(msg["id"], const.ERR_TEMPLATE_ERROR, str(result)) return connection.send_message( messages.event_message( msg["id"], { "result": result, "listeners": info.listeners } # type: ignore[attr-defined] )) try: info = async_track_template_result( hass, [TrackTemplate(template_obj, variables)], _template_listener, raise_on_template_error=True, strict=msg["strict"], ) except TemplateError as ex: connection.send_error(msg["id"], const.ERR_TEMPLATE_ERROR, str(ex)) return connection.subscriptions[msg["id"]] = info.async_remove connection.send_result(msg["id"]) hass.loop.call_soon_threadsafe(info.async_refresh)
def test_base64_encode(hass): """Test the base64_encode filter.""" assert ( template.Template('{{ "homeassistant" | base64_encode }}', hass).async_render() == "aG9tZWFzc2lzdGFudA==" )
with contextlib.suppress(UnicodeDecodeError): if image.decode("utf-8").lstrip().startswith("<svg"): return "svg+xml" return fmt async def async_test_still( hass: HomeAssistant, info: Mapping[str, Any] ) -> tuple[dict[str, str], str | None]: """Verify that the still image is valid before we create an entity.""" fmt = None if not (url := info.get(CONF_STILL_IMAGE_URL)): return {}, info.get(CONF_CONTENT_TYPE, "image/jpeg") try: if not isinstance(url, template_helper.Template): url = template_helper.Template(url, hass) url = url.async_render(parse_result=False) except TemplateError as err: _LOGGER.warning("Problem rendering template %s: %s", url, err) return {CONF_STILL_IMAGE_URL: "template_error"}, None try: yarl_url = yarl.URL(url) except ValueError: return {CONF_STILL_IMAGE_URL: "malformed_url"}, None if not yarl_url.is_absolute(): return {CONF_STILL_IMAGE_URL: "relative_url"}, None verify_ssl = info[CONF_VERIFY_SSL] auth = generate_auth(info) try: async_client = get_async_client(hass, verify_ssl=verify_ssl) async with timeout(GET_IMAGE_TIMEOUT):
def test_passing_vars_as_vars(hass): """Test passing variables as variables.""" assert template.Template("{{ hello }}", hass).async_render({"hello": 127}) == "127"
def template(self, message): tpl = template.Template(message, self.hass) return tpl.async_render(None)
def test_render_with_possible_json_value_with_invalid_json(hass): """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_raise_exception_on_error(hass): """Test raising an exception on error.""" with pytest.raises(TemplateError): template.Template("{{ invalid_syntax").ensure_valid()
def test_render_with_possible_json_value_with_missing_json_value(hass): """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_closest_function_no_location_states(hass): """Test closest function without location states.""" assert ( template.Template("{{ closest(states).entity_id }}", hass).async_render() == "" )
def test_render_with_possible_json_value_undefined_json_error_value(hass): """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 render_to_info(hass, template_str, variables=None): """Create render info from template.""" tmp = template.Template(template_str, hass) return tmp.async_render_to_info(variables)
def test_distance_function_return_none_if_invalid_state(hass): """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) assert tpl.async_render() == "None"
def test_render_with_possible_json_value_with_valid_json(self): """Render with possible JSON value with valid JSON.""" tpl = template.Template('{{ value_json.hello }}', self.hass) self.assertEqual( 'world', tpl.render_with_possible_json_value('{"hello": "world"}'))