Example #1
0
 def __getattr__(self, name):
     """Return the domain state."""
     if "." in name:
         if not valid_entity_id(name):
             raise TemplateError("Invalid entity ID '{}'".format(name))
         return _get_state(self._hass, name)
     if not valid_entity_id(name + ".entity"):
         raise TemplateError("Invalid domain name '{}'".format(name))
     return DomainStates(self._hass, name)
Example #2
0
 def test_update_template_error(self, mock_render):
     hass = mock.MagicMock()
     vs = template.BinarySensorTemplate(hass, 'parent', 'Parent', 'motion',
                                        '{{ 1 > 1 }}')
     mock_render.side_effect = TemplateError('foo')
     vs.update()
     mock_render.side_effect = TemplateError(
         "UndefinedError: 'None' has no attribute")
     vs.update()
Example #3
0
 def test_update_template_error(self, mock_render):
     """"Test the template update error."""
     vs = template.BinarySensorTemplate(
         self.hass, 'parent', 'Parent', 'motion',
         template_hlpr.Template('{{ 1 > 1 }}', self.hass), MATCH_ALL)
     mock_render.side_effect = TemplateError('foo')
     vs.update()
     mock_render.side_effect = TemplateError(
         "UndefinedError: 'None' has no attribute")
     vs.update()
Example #4
0
 def test_update_template_error(self, mock_render):
     """"Test the template update error."""
     vs = run_callback_threadsafe(
         self.hass.loop, template.BinarySensorTemplate, self.hass,
         'parent', 'Parent', 'motion',
         template_hlpr.Template('{{ 1 > 1 }}', self.hass), None, None,
         MATCH_ALL, None, None).result()
     mock_render.side_effect = TemplateError('foo')
     run_callback_threadsafe(self.hass.loop, vs.async_check_state).result()
     mock_render.side_effect = TemplateError(
         "UndefinedError: 'None' has no attribute")
     run_callback_threadsafe(self.hass.loop, vs.async_check_state).result()
Example #5
0
    def __getattr__(self, name):
        """Return the domain state."""
        if "." in name:
            if not valid_entity_id(name):
                raise TemplateError(f"Invalid entity ID '{name}'")
            return _get_state(self._hass, name)

        if name in _RESERVED_NAMES:
            return None

        if not valid_entity_id(f"{name}.entity"):
            raise TemplateError(f"Invalid domain name '{name}'")

        return DomainStates(self._hass, name)
Example #6
0
    def async_render(
        self,
        variables: TemplateVarsType = None,
        parse_result: bool = True,
        limited: bool = False,
        **kwargs: Any,
    ) -> Any:
        """Render given template.

        This method must be run in the event loop.

        If limited is True, the template is not allowed to access any function or filter depending on hass or the state machine.
        """
        if self.is_static:
            if self.hass.config.legacy_templates or not parse_result:
                return self.template
            return self._parse_result(self.template)

        compiled = self._compiled or self._ensure_compiled(limited)

        if variables is not None:
            kwargs.update(variables)

        try:
            render_result = compiled.render(kwargs)
        except Exception as err:
            raise TemplateError(err) from err

        render_result = render_result.strip()

        if self.hass.config.legacy_templates or not parse_result:
            return render_result

        return self._parse_result(render_result)
Example #7
0
def _get_state_if_valid(
    hass: HomeAssistantType, entity_id: str
) -> Optional[TemplateState]:
    state = hass.states.get(entity_id)
    if state is None and not valid_entity_id(entity_id):
        raise TemplateError(f"Invalid entity ID '{entity_id}'")  # type: ignore
    return _get_template_state_from_state(hass, entity_id, state)
Example #8
0
    def async_render(
        self,
        variables: TemplateVarsType = None,
        parse_result: bool = True,
        **kwargs: Any,
    ) -> Any:
        """Render given template.

        This method must be run in the event loop.
        """
        if self.is_static:
            if self.hass.config.legacy_templates or not parse_result:
                return self.template
            return self._parse_result(self.template)

        compiled = self._compiled or self._ensure_compiled()

        if variables is not None:
            kwargs.update(variables)

        try:
            render_result = compiled.render(kwargs)
        except Exception as err:  # pylint: disable=broad-except
            raise TemplateError(err) from err

        render_result = render_result.strip()

        if self.hass.config.legacy_templates or not parse_result:
            return render_result

        return self._parse_result(render_result)
Example #9
0
    def ensure_valid(self) -> None:
        """Return if template is valid."""
        if self._compiled_code is not None:
            return

        try:
            self._compiled_code = self._env.compile(self.template)  # type: ignore[no-untyped-call]
        except jinja2.TemplateError as err:
            raise TemplateError(err) from err
Example #10
0
    def ensure_valid(self):
        """Return if template is valid."""
        if self._compiled_code is not None:
            return

        try:
            self._compiled_code = self._env.compile(self.template)
        except jinja2.exceptions.TemplateSyntaxError as err:
            raise TemplateError(err)
Example #11
0
    async def async_render_will_timeout(
        self,
        timeout: float,
        variables: TemplateVarsType = None,
        strict: bool = False,
        **kwargs: Any,
    ) -> bool:
        """Check to see if rendering a template will timeout during render.

        This is intended to check for expensive templates
        that will make the system unstable.  The template
        is rendered in the executor to ensure it does not
        tie up the event loop.

        This function is not a security control and is only
        intended to be used as a safety check when testing
        templates.

        This method must be run in the event loop.
        """
        if self.is_static:
            return False

        compiled = self._compiled or self._ensure_compiled(strict=strict)

        if variables is not None:
            kwargs.update(variables)

        self._exc_info = None
        finish_event = asyncio.Event()

        def _render_template() -> None:
            try:
                _render_with_context(self.template, compiled, **kwargs)
            except TimeoutError:
                pass
            except Exception:  # pylint: disable=broad-except
                self._exc_info = sys.exc_info()
            finally:
                run_callback_threadsafe(self.hass.loop, finish_event.set)

        try:
            template_render_thread = ThreadWithException(
                target=_render_template)
            template_render_thread.start()
            await asyncio.wait_for(finish_event.wait(), timeout=timeout)
            if self._exc_info:
                raise TemplateError(self._exc_info[1].with_traceback(
                    self._exc_info[2]))
        except asyncio.TimeoutError:
            template_render_thread.raise_exc(TimeoutError)
            return True
        finally:
            template_render_thread.join()

        return False
Example #12
0
def render(hass, template, variables=None, **kwargs):
    """ Render given template. """
    if variables is not None:
        kwargs.update(variables)

    try:
        return ENV.from_string(template, {
            'states': AllStates(hass),
            'is_state': hass.states.is_state
        }).render(kwargs).strip()
    except jinja2.TemplateError as err:
        raise TemplateError(err)
Example #13
0
    def async_render(self, variables: TemplateVarsType = None, **kwargs) -> str:
        """Render given template.

        This method must be run in the event loop.
        """
        compiled = self._compiled or self._ensure_compiled()

        if variables is not None:
            kwargs.update(variables)

        try:
            return compiled.render(kwargs).strip()
        except jinja2.TemplateError as err:
            raise TemplateError(err)
Example #14
0
    def async_render(self,
                     variables: TemplateVarsType = None,
                     **kwargs: Any) -> str:
        """Render given template.

        This method must be run in the event loop.
        """
        if self.is_static:
            return self.template.strip()

        compiled = self._compiled or self._ensure_compiled()

        if variables is not None:
            kwargs.update(variables)

        try:
            return compiled.render(kwargs).strip()
        except Exception as err:  # pylint: disable=broad-except
            raise TemplateError(err) from err
Example #15
0
def render(hass, template, variables=None, **kwargs):
    """Render given template."""
    if variables is not None:
        kwargs.update(variables)

    location_methods = LocationMethods(hass)
    utcnow = dt_util.utcnow()

    try:
        return ENV.from_string(template, {
            'closest': location_methods.closest,
            'distance': location_methods.distance,
            'float': forgiving_float,
            'is_state': hass.states.is_state,
            'is_state_attr': hass.states.is_state_attr,
            'now': dt_util.as_local(utcnow),
            'states': AllStates(hass),
            'utcnow': utcnow,
        }).render(kwargs).strip()
    except jinja2.TemplateError as err:
        raise TemplateError(err)
Example #16
0
    def async_render(self,
                     variables: TemplateVarsType = None,
                     **kwargs: Any) -> Any:
        """Render given template.

        This method must be run in the event loop.
        """
        if self.is_static:
            return self.template.strip()

        compiled = self._compiled or self._ensure_compiled()

        if variables is not None:
            kwargs.update(variables)

        try:
            render_result = compiled.render(kwargs)
        except jinja2.TemplateError as err:
            raise TemplateError(err) from err

        render_result = render_result.strip()

        if not self.hass.config.legacy_templates:
            try:
                result = literal_eval(render_result)

                # If the literal_eval result is a string, use the original
                # render, by not returning right here. The evaluation of strings
                # resulting in strings impacts quotes, to avoid unexpected
                # output; use the original render instead of the evaluated one.
                if not isinstance(result, str):
                    return result
            except (ValueError, SyntaxError, MemoryError):
                pass

        return render_result
Example #17
0
 def __getattr__(self, name):
     """Return the states."""
     entity_id = "{}.{}".format(self._domain, name)
     if not valid_entity_id(entity_id):
         raise TemplateError("Invalid entity ID '{}'".format(entity_id))
     return _get_state(self._hass, entity_id)
Example #18
0
 def warn_unsupported(*args, **kwargs):
     raise TemplateError(
         f"Use of '{name}' is not supported in limited templates"
     )
Example #19
0
 def __getattr__(self, name):
     """Return the states."""
     entity_id = f"{self._domain}.{name}"
     if not valid_entity_id(entity_id):
         raise TemplateError(f"Invalid entity ID '{entity_id}'")
     return _get_state(self._hass, entity_id)