-
-
Notifications
You must be signed in to change notification settings - Fork 37.8k
Lazy loading of service descriptions #11479
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
Changes from 1 commit
2000bad
0e52af7
a1d0a89
94555de
aff3d73
ad57ef8
959a34a
aba4b18
c3e9fab
990fa1f
4fe0b96
136a8c5
d1cd820
9052ba6
e1b0a24
a162015
2ee3909
9b2ea2d
817f69a
38bccc5
e310c0b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| # Describes the format for available scene services | ||
|
|
||
| turn_on: | ||
| description: Activate a scene. | ||
| fields: | ||
| entity_id: | ||
| description: Name(s) of scenes to turn on | ||
| example: 'scene.romantic' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,13 +3,15 @@ | |
| import logging | ||
| # pylint: disable=unused-import | ||
| from typing import Optional # NOQA | ||
| from os import path | ||
|
|
||
| import voluptuous as vol | ||
|
|
||
| from homeassistant.const import ATTR_ENTITY_ID | ||
| from homeassistant.core import HomeAssistant # NOQA | ||
| import homeassistant.core as ha | ||
| from homeassistant.exceptions import TemplateError | ||
| from homeassistant.loader import get_component, bind_hass | ||
| from homeassistant.config import load_yaml_config_file | ||
| import homeassistant.helpers.config_validation as cv | ||
| from homeassistant.util.async import run_coroutine_threadsafe | ||
|
|
||
|
|
@@ -21,6 +23,8 @@ | |
|
|
||
| _LOGGER = logging.getLogger(__name__) | ||
|
|
||
| DESCRIPTION_CACHE = {} | ||
|
|
||
|
|
||
| @bind_hass | ||
| def call_from_config(hass, config, blocking=False, variables=None, | ||
|
|
@@ -112,3 +116,44 @@ def extract_entity_ids(hass, service_call, expand_group=True): | |
| return [service_ent_id] | ||
|
|
||
| return service_ent_id | ||
|
|
||
| @bind_hass | ||
|
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. expected 2 blank lines, found 1 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. expected 2 blank lines, found 1 |
||
| def get_description(hass, domain, service): | ||
| """Return the description (i.e. user documentation) for a service call.""" | ||
|
|
||
| if domain == ha.DOMAIN: | ||
| import homeassistant.components as components | ||
| file = components.__file__ | ||
|
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.
|
||
| else: | ||
| file = get_component(domain).__file__ | ||
|
|
||
| descriptions = DESCRIPTION_CACHE.get(file) | ||
| if descriptions is None: | ||
| descriptions = load_yaml_config_file( | ||
|
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. This call will do I/O. Since
Contributor
Author
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. Oh. This was moved from the LIFX I am a bit confused by the main/executor transitions available. What is the proper way to schedule the function in this situation?
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. I think the function that schedules the job for the executor, via
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. You are correct Martin
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. this file might not exist |
||
| path.join(path.dirname(file), 'services.yaml')) | ||
| DESCRIPTION_CACHE[file] = descriptions | ||
|
|
||
| if domain == ha.DOMAIN: | ||
| description = descriptions[domain].get(service, {}) | ||
| else: | ||
| description = descriptions.get(service, {}) | ||
|
|
||
| return { | ||
| 'description': description.get('description', ''), | ||
| 'fields': description.get('fields', {}) | ||
| } | ||
|
|
||
| @bind_hass | ||
|
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. expected 2 blank lines, found 1 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. expected 2 blank lines, found 1 |
||
| def async_get_all_descriptions(hass): | ||
| """Return the descriptions for all service calls.""" | ||
|
|
||
| services = hass.services.async_services() | ||
| descriptions = {} | ||
| for domain in services: | ||
| descriptions[domain] = {} | ||
| for service in services[domain]: | ||
| description = get_description(hass, domain, service) | ||
| if description: | ||
| descriptions[domain][service] = description | ||
|
|
||
| return descriptions | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't store the description cache in a global. Instead store it in
hass.data, which is a dict for globals during the runtime of a hass instance.