-
-
Notifications
You must be signed in to change notification settings - Fork 37.6k
Support templating MQTT triggers #45614
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
emontnemery
merged 15 commits into
home-assistant:dev
from
emontnemery:mqtt_trigger_template
Feb 8, 2021
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
aa3eb1f
Add support for limited templates (no HASS access)
emontnemery f8388b3
Pass variables to automation triggers
emontnemery 2160b0c
Support templates in MQTT triggers
emontnemery 106cd75
Spelling
emontnemery 2fdcf6a
Handle trigger referenced by variables
emontnemery 9cf182b
Raise on unsupported function in limited templates
emontnemery 22506d4
Validate MQTT trigger schema in MQTT device trigger
emontnemery 1ac04a3
Add trigger_variables to automation config schema
emontnemery eeac975
Don't print stacktrace when setting up trigger throws
emontnemery 0256c00
Make pylint happy
emontnemery baa72ce
Add trigger_variables to variables
emontnemery d185abc
Add debug prints, document limited template
emontnemery be5908d
Add tests
emontnemery 5c7a50e
Validate MQTT trigger topic early when possible
emontnemery df7598b
Improve valid_subscribe_topic_template
emontnemery File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -84,7 +84,9 @@ def attach(hass: HomeAssistantType, obj: Any) -> None: | |
| obj.hass = hass | ||
|
|
||
|
|
||
| def render_complex(value: Any, variables: TemplateVarsType = None) -> Any: | ||
| def render_complex( | ||
| value: Any, variables: TemplateVarsType = None, limited: bool = False | ||
| ) -> Any: | ||
| """Recursive template creator helper function.""" | ||
| if isinstance(value, list): | ||
| return [render_complex(item, variables) for item in value] | ||
|
|
@@ -94,7 +96,7 @@ def render_complex(value: Any, variables: TemplateVarsType = None) -> Any: | |
| for key, item in value.items() | ||
| } | ||
| if isinstance(value, Template): | ||
| return value.async_render(variables) | ||
| return value.async_render(variables, limited=limited) | ||
|
|
||
| return value | ||
|
|
||
|
|
@@ -279,6 +281,7 @@ class Template: | |
| "is_static", | ||
| "_compiled_code", | ||
| "_compiled", | ||
| "_limited", | ||
| ) | ||
|
|
||
| def __init__(self, template, hass=None): | ||
|
|
@@ -291,10 +294,11 @@ def __init__(self, template, hass=None): | |
| self._compiled: Optional[Template] = None | ||
| self.hass = hass | ||
| self.is_static = not is_template_string(template) | ||
| self._limited = None | ||
|
|
||
| @property | ||
| def _env(self) -> "TemplateEnvironment": | ||
| if self.hass is None: | ||
| if self.hass is None or self._limited: | ||
| return _NO_HASS_ENV | ||
| ret: Optional[TemplateEnvironment] = self.hass.data.get(_ENVIRONMENT) | ||
| if ret is None: | ||
|
|
@@ -315,36 +319,43 @@ def render( | |
| self, | ||
| variables: TemplateVarsType = None, | ||
| parse_result: bool = True, | ||
| limited: bool = False, | ||
| **kwargs: Any, | ||
| ) -> Any: | ||
| """Render given template.""" | ||
| """Render given template. | ||
|
|
||
| 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) | ||
|
|
||
| return run_callback_threadsafe( | ||
| self.hass.loop, | ||
| partial(self.async_render, variables, parse_result, **kwargs), | ||
| partial(self.async_render, variables, parse_result, limited, **kwargs), | ||
| ).result() | ||
|
|
||
| @callback | ||
| def async_render( | ||
| self, | ||
| variables: TemplateVarsType = None, | ||
| parse_result: bool = True, | ||
| limited: bool = False, | ||
|
balloob marked this conversation as resolved.
|
||
| **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. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's nice to break long strings around 88 characters. |
||
| """ | ||
| 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() | ||
| compiled = self._compiled or self._ensure_compiled(limited) | ||
|
|
||
| if variables is not None: | ||
| kwargs.update(variables) | ||
|
|
@@ -519,12 +530,16 @@ def async_render_with_possible_json_value( | |
| ) | ||
| return value if error_value is _SENTINEL else error_value | ||
|
|
||
| def _ensure_compiled(self) -> "Template": | ||
| def _ensure_compiled(self, limited: bool = False) -> "Template": | ||
| """Bind a template to a specific hass instance.""" | ||
| self.ensure_valid() | ||
|
|
||
| assert self.hass is not None, "hass variable not set on template" | ||
| assert ( | ||
| self._limited is None or self._limited == limited | ||
| ), "can't change between limited and non limited template" | ||
|
|
||
| self._limited = limited | ||
| env = self._env | ||
|
|
||
| self._compiled = cast( | ||
|
|
@@ -1352,6 +1367,31 @@ def __init__(self, hass): | |
| self.globals["strptime"] = strptime | ||
| self.globals["urlencode"] = urlencode | ||
| if hass is None: | ||
|
|
||
| def unsupported(name): | ||
| def warn_unsupported(*args, **kwargs): | ||
| raise TemplateError( | ||
| f"Use of '{name}' is not supported in limited templates" | ||
| ) | ||
|
|
||
| return warn_unsupported | ||
|
|
||
| hass_globals = [ | ||
| "closest", | ||
| "distance", | ||
| "expand", | ||
| "is_state", | ||
| "is_state_attr", | ||
| "state_attr", | ||
| "states", | ||
| "utcnow", | ||
| "now", | ||
| ] | ||
| hass_filters = ["closest", "expand"] | ||
| for glob in hass_globals: | ||
| self.globals[glob] = unsupported(glob) | ||
| for filt in hass_filters: | ||
| self.filters[filt] = unsupported(filt) | ||
| return | ||
|
|
||
| # We mark these as a context functions to ensure they get | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.