mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
Removing asyncio.coroutine syntax from HASS core (#12509)
* changed asyncio.coroutine syntax to new async def/await * removed py34 from tox environment * reverted some changes within entity.py * - * reverted changes within bootstrap.py * reverted changes within discovery.py * switched decorators * Reverted change within aiohttp_client.py * reverted change within logging.py * switched decorators * Await lock properly * removed asyncio.coroutine from test
This commit is contained in:
parent
eacfbc048a
commit
16cb7388ee
@ -97,10 +97,10 @@ class ConfigManagerFlowIndexView(HomeAssistantView):
|
|||||||
flow for flow in hass.config_entries.flow.async_progress()
|
flow for flow in hass.config_entries.flow.async_progress()
|
||||||
if flow['source'] != config_entries.SOURCE_USER])
|
if flow['source'] != config_entries.SOURCE_USER])
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
@RequestDataValidator(vol.Schema({
|
@RequestDataValidator(vol.Schema({
|
||||||
vol.Required('domain'): str,
|
vol.Required('domain'): str,
|
||||||
}))
|
}))
|
||||||
|
@asyncio.coroutine
|
||||||
def post(self, request, data):
|
def post(self, request, data):
|
||||||
"""Handle a POST request."""
|
"""Handle a POST request."""
|
||||||
hass = request.app['hass']
|
hass = request.app['hass']
|
||||||
@ -139,8 +139,8 @@ class ConfigManagerFlowResourceView(HomeAssistantView):
|
|||||||
|
|
||||||
return self.json(result)
|
return self.json(result)
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
@RequestDataValidator(vol.Schema(dict), allow_empty=True)
|
@RequestDataValidator(vol.Schema(dict), allow_empty=True)
|
||||||
|
@asyncio.coroutine
|
||||||
def post(self, request, flow_id, data):
|
def post(self, request, flow_id, data):
|
||||||
"""Handle a POST request."""
|
"""Handle a POST request."""
|
||||||
hass = request.app['hass']
|
hass = request.app['hass']
|
||||||
|
@ -260,8 +260,7 @@ def create_default_config(config_dir, detect_location=True):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_hass_config_yaml(hass):
|
||||||
def async_hass_config_yaml(hass):
|
|
||||||
"""Load YAML from a Home Assistant configuration file.
|
"""Load YAML from a Home Assistant configuration file.
|
||||||
|
|
||||||
This function allow a component inside the asyncio loop to reload its
|
This function allow a component inside the asyncio loop to reload its
|
||||||
@ -274,7 +273,7 @@ def async_hass_config_yaml(hass):
|
|||||||
conf = load_yaml_config_file(path)
|
conf = load_yaml_config_file(path)
|
||||||
return conf
|
return conf
|
||||||
|
|
||||||
conf = yield from hass.async_add_job(_load_hass_yaml_config)
|
conf = await hass.async_add_job(_load_hass_yaml_config)
|
||||||
return conf
|
return conf
|
||||||
|
|
||||||
|
|
||||||
@ -373,8 +372,7 @@ def async_log_exception(ex, domain, config, hass):
|
|||||||
_LOGGER.error(message)
|
_LOGGER.error(message)
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_process_ha_core_config(hass, config):
|
||||||
def async_process_ha_core_config(hass, config):
|
|
||||||
"""Process the [homeassistant] section from the configuration.
|
"""Process the [homeassistant] section from the configuration.
|
||||||
|
|
||||||
This method is a coroutine.
|
This method is a coroutine.
|
||||||
@ -461,7 +459,7 @@ def async_process_ha_core_config(hass, config):
|
|||||||
# If we miss some of the needed values, auto detect them
|
# If we miss some of the needed values, auto detect them
|
||||||
if None in (hac.latitude, hac.longitude, hac.units,
|
if None in (hac.latitude, hac.longitude, hac.units,
|
||||||
hac.time_zone):
|
hac.time_zone):
|
||||||
info = yield from hass.async_add_job(
|
info = await hass.async_add_job(
|
||||||
loc_util.detect_location_info)
|
loc_util.detect_location_info)
|
||||||
|
|
||||||
if info is None:
|
if info is None:
|
||||||
@ -487,7 +485,7 @@ def async_process_ha_core_config(hass, config):
|
|||||||
|
|
||||||
if hac.elevation is None and hac.latitude is not None and \
|
if hac.elevation is None and hac.latitude is not None and \
|
||||||
hac.longitude is not None:
|
hac.longitude is not None:
|
||||||
elevation = yield from hass.async_add_job(
|
elevation = await hass.async_add_job(
|
||||||
loc_util.elevation, hac.latitude, hac.longitude)
|
loc_util.elevation, hac.latitude, hac.longitude)
|
||||||
hac.elevation = elevation
|
hac.elevation = elevation
|
||||||
discovered.append(('elevation', elevation))
|
discovered.append(('elevation', elevation))
|
||||||
@ -648,21 +646,20 @@ def async_process_component_config(hass, config, domain):
|
|||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_check_ha_config_file(hass):
|
||||||
def async_check_ha_config_file(hass):
|
|
||||||
"""Check if Home Assistant configuration file is valid.
|
"""Check if Home Assistant configuration file is valid.
|
||||||
|
|
||||||
This method is a coroutine.
|
This method is a coroutine.
|
||||||
"""
|
"""
|
||||||
proc = yield from asyncio.create_subprocess_exec(
|
proc = await asyncio.create_subprocess_exec(
|
||||||
sys.executable, '-m', 'homeassistant', '--script',
|
sys.executable, '-m', 'homeassistant', '--script',
|
||||||
'check_config', '--config', hass.config.config_dir,
|
'check_config', '--config', hass.config.config_dir,
|
||||||
stdout=asyncio.subprocess.PIPE,
|
stdout=asyncio.subprocess.PIPE,
|
||||||
stderr=asyncio.subprocess.STDOUT, loop=hass.loop)
|
stderr=asyncio.subprocess.STDOUT, loop=hass.loop)
|
||||||
|
|
||||||
# Wait for the subprocess exit
|
# Wait for the subprocess exit
|
||||||
log, _ = yield from proc.communicate()
|
log, _ = await proc.communicate()
|
||||||
exit_code = yield from proc.wait()
|
exit_code = await proc.wait()
|
||||||
|
|
||||||
# Convert to ASCII
|
# Convert to ASCII
|
||||||
log = RE_ASCII.sub('', log.decode())
|
log = RE_ASCII.sub('', log.decode())
|
||||||
|
@ -76,7 +76,7 @@ If the user input passes validation, you can again return one of the three
|
|||||||
return values. If you want to navigate the user to the next step, return the
|
return values. If you want to navigate the user to the next step, return the
|
||||||
return value of that step:
|
return value of that step:
|
||||||
|
|
||||||
return (await self.async_step_account())
|
return await self.async_step_account()
|
||||||
|
|
||||||
### Abort
|
### Abort
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ should follow the same return values as a normal step.
|
|||||||
If the result of the step is to show a form, the user will be able to continue
|
If the result of the step is to show a form, the user will be able to continue
|
||||||
the flow from the config panel.
|
the flow from the config panel.
|
||||||
"""
|
"""
|
||||||
import asyncio
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import uuid
|
import uuid
|
||||||
@ -176,14 +176,13 @@ class ConfigEntry:
|
|||||||
# State of the entry (LOADED, NOT_LOADED)
|
# State of the entry (LOADED, NOT_LOADED)
|
||||||
self.state = state
|
self.state = state
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_setup(self, hass, *, component=None):
|
||||||
def async_setup(self, hass, *, component=None):
|
|
||||||
"""Set up an entry."""
|
"""Set up an entry."""
|
||||||
if component is None:
|
if component is None:
|
||||||
component = getattr(hass.components, self.domain)
|
component = getattr(hass.components, self.domain)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = yield from component.async_setup_entry(hass, self)
|
result = await component.async_setup_entry(hass, self)
|
||||||
|
|
||||||
if not isinstance(result, bool):
|
if not isinstance(result, bool):
|
||||||
_LOGGER.error('%s.async_config_entry did not return boolean',
|
_LOGGER.error('%s.async_config_entry did not return boolean',
|
||||||
@ -199,8 +198,7 @@ class ConfigEntry:
|
|||||||
else:
|
else:
|
||||||
self.state = ENTRY_STATE_SETUP_ERROR
|
self.state = ENTRY_STATE_SETUP_ERROR
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_unload(self, hass):
|
||||||
def async_unload(self, hass):
|
|
||||||
"""Unload an entry.
|
"""Unload an entry.
|
||||||
|
|
||||||
Returns if unload is possible and was successful.
|
Returns if unload is possible and was successful.
|
||||||
@ -213,7 +211,7 @@ class ConfigEntry:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = yield from component.async_unload_entry(hass, self)
|
result = await component.async_unload_entry(hass, self)
|
||||||
|
|
||||||
if not isinstance(result, bool):
|
if not isinstance(result, bool):
|
||||||
_LOGGER.error('%s.async_unload_entry did not return boolean',
|
_LOGGER.error('%s.async_unload_entry did not return boolean',
|
||||||
@ -293,8 +291,7 @@ class ConfigEntries:
|
|||||||
return list(self._entries)
|
return list(self._entries)
|
||||||
return [entry for entry in self._entries if entry.domain == domain]
|
return [entry for entry in self._entries if entry.domain == domain]
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_remove(self, entry_id):
|
||||||
def async_remove(self, entry_id):
|
|
||||||
"""Remove an entry."""
|
"""Remove an entry."""
|
||||||
found = None
|
found = None
|
||||||
for index, entry in enumerate(self._entries):
|
for index, entry in enumerate(self._entries):
|
||||||
@ -308,25 +305,23 @@ class ConfigEntries:
|
|||||||
entry = self._entries.pop(found)
|
entry = self._entries.pop(found)
|
||||||
self._async_schedule_save()
|
self._async_schedule_save()
|
||||||
|
|
||||||
unloaded = yield from entry.async_unload(self.hass)
|
unloaded = await entry.async_unload(self.hass)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'require_restart': not unloaded
|
'require_restart': not unloaded
|
||||||
}
|
}
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_load(self):
|
||||||
def async_load(self):
|
|
||||||
"""Load the config."""
|
"""Load the config."""
|
||||||
path = self.hass.config.path(PATH_CONFIG)
|
path = self.hass.config.path(PATH_CONFIG)
|
||||||
if not os.path.isfile(path):
|
if not os.path.isfile(path):
|
||||||
self._entries = []
|
self._entries = []
|
||||||
return
|
return
|
||||||
|
|
||||||
entries = yield from self.hass.async_add_job(load_json, path)
|
entries = await self.hass.async_add_job(load_json, path)
|
||||||
self._entries = [ConfigEntry(**entry) for entry in entries]
|
self._entries = [ConfigEntry(**entry) for entry in entries]
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def _async_add_entry(self, entry):
|
||||||
def _async_add_entry(self, entry):
|
|
||||||
"""Add an entry."""
|
"""Add an entry."""
|
||||||
self._entries.append(entry)
|
self._entries.append(entry)
|
||||||
self._async_schedule_save()
|
self._async_schedule_save()
|
||||||
@ -334,10 +329,10 @@ class ConfigEntries:
|
|||||||
# Setup entry
|
# Setup entry
|
||||||
if entry.domain in self.hass.config.components:
|
if entry.domain in self.hass.config.components:
|
||||||
# Component already set up, just need to call setup_entry
|
# Component already set up, just need to call setup_entry
|
||||||
yield from entry.async_setup(self.hass)
|
await entry.async_setup(self.hass)
|
||||||
else:
|
else:
|
||||||
# Setting up component will also load the entries
|
# Setting up component will also load the entries
|
||||||
yield from async_setup_component(
|
await async_setup_component(
|
||||||
self.hass, entry.domain, self._hass_config)
|
self.hass, entry.domain, self._hass_config)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
@ -350,13 +345,12 @@ class ConfigEntries:
|
|||||||
SAVE_DELAY, self.hass.async_add_job, self._async_save
|
SAVE_DELAY, self.hass.async_add_job, self._async_save
|
||||||
)
|
)
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def _async_save(self):
|
||||||
def _async_save(self):
|
|
||||||
"""Save the entity registry to a file."""
|
"""Save the entity registry to a file."""
|
||||||
self._sched_save = None
|
self._sched_save = None
|
||||||
data = [entry.as_dict() for entry in self._entries]
|
data = [entry.as_dict() for entry in self._entries]
|
||||||
|
|
||||||
yield from self.hass.async_add_job(
|
await self.hass.async_add_job(
|
||||||
save_json, self.hass.config.path(PATH_CONFIG), data)
|
save_json, self.hass.config.path(PATH_CONFIG), data)
|
||||||
|
|
||||||
|
|
||||||
@ -379,8 +373,7 @@ class FlowManager:
|
|||||||
'source': flow.source,
|
'source': flow.source,
|
||||||
} for flow in self._progress.values()]
|
} for flow in self._progress.values()]
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_init(self, domain, *, source=SOURCE_USER, data=None):
|
||||||
def async_init(self, domain, *, source=SOURCE_USER, data=None):
|
|
||||||
"""Start a configuration flow."""
|
"""Start a configuration flow."""
|
||||||
handler = HANDLERS.get(domain)
|
handler = HANDLERS.get(domain)
|
||||||
|
|
||||||
@ -393,7 +386,7 @@ class FlowManager:
|
|||||||
raise self.hass.helpers.UnknownHandler
|
raise self.hass.helpers.UnknownHandler
|
||||||
|
|
||||||
# Make sure requirements and dependencies of component are resolved
|
# Make sure requirements and dependencies of component are resolved
|
||||||
yield from async_process_deps_reqs(
|
await async_process_deps_reqs(
|
||||||
self.hass, self._hass_config, domain, component)
|
self.hass, self._hass_config, domain, component)
|
||||||
|
|
||||||
flow_id = uuid.uuid4().hex
|
flow_id = uuid.uuid4().hex
|
||||||
@ -408,10 +401,9 @@ class FlowManager:
|
|||||||
else:
|
else:
|
||||||
step = source
|
step = source
|
||||||
|
|
||||||
return (yield from self._async_handle_step(flow, step, data))
|
return await self._async_handle_step(flow, step, data)
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_configure(self, flow_id, user_input=None):
|
||||||
def async_configure(self, flow_id, user_input=None):
|
|
||||||
"""Start or continue a configuration flow."""
|
"""Start or continue a configuration flow."""
|
||||||
flow = self._progress.get(flow_id)
|
flow = self._progress.get(flow_id)
|
||||||
|
|
||||||
@ -423,8 +415,8 @@ class FlowManager:
|
|||||||
if data_schema is not None and user_input is not None:
|
if data_schema is not None and user_input is not None:
|
||||||
user_input = data_schema(user_input)
|
user_input = data_schema(user_input)
|
||||||
|
|
||||||
return (yield from self._async_handle_step(
|
return await self._async_handle_step(
|
||||||
flow, step_id, user_input))
|
flow, step_id, user_input)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_abort(self, flow_id):
|
def async_abort(self, flow_id):
|
||||||
@ -432,8 +424,7 @@ class FlowManager:
|
|||||||
if self._progress.pop(flow_id, None) is None:
|
if self._progress.pop(flow_id, None) is None:
|
||||||
raise UnknownFlow
|
raise UnknownFlow
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def _async_handle_step(self, flow, step_id, user_input):
|
||||||
def _async_handle_step(self, flow, step_id, user_input):
|
|
||||||
"""Handle a step of a flow."""
|
"""Handle a step of a flow."""
|
||||||
method = "async_step_{}".format(step_id)
|
method = "async_step_{}".format(step_id)
|
||||||
|
|
||||||
@ -442,7 +433,7 @@ class FlowManager:
|
|||||||
raise UnknownStep("Handler {} doesn't support step {}".format(
|
raise UnknownStep("Handler {} doesn't support step {}".format(
|
||||||
flow.__class__.__name__, step_id))
|
flow.__class__.__name__, step_id))
|
||||||
|
|
||||||
result = yield from getattr(flow, method)(user_input)
|
result = await getattr(flow, method)(user_input)
|
||||||
|
|
||||||
if result['type'] not in (RESULT_TYPE_FORM, RESULT_TYPE_CREATE_ENTRY,
|
if result['type'] not in (RESULT_TYPE_FORM, RESULT_TYPE_CREATE_ENTRY,
|
||||||
RESULT_TYPE_ABORT):
|
RESULT_TYPE_ABORT):
|
||||||
@ -466,7 +457,7 @@ class FlowManager:
|
|||||||
data=result.pop('data'),
|
data=result.pop('data'),
|
||||||
source=flow.source
|
source=flow.source
|
||||||
)
|
)
|
||||||
yield from self._async_add_entry(entry)
|
await self._async_add_entry(entry)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@ -106,29 +106,28 @@ def async_aiohttp_proxy_web(hass, request, web_coro, buffer_size=102400,
|
|||||||
req.close()
|
req.close()
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
@bind_hass
|
@bind_hass
|
||||||
def async_aiohttp_proxy_stream(hass, request, stream, content_type,
|
async def async_aiohttp_proxy_stream(hass, request, stream, content_type,
|
||||||
buffer_size=102400, timeout=10):
|
buffer_size=102400, timeout=10):
|
||||||
"""Stream a stream to aiohttp web response."""
|
"""Stream a stream to aiohttp web response."""
|
||||||
response = web.StreamResponse()
|
response = web.StreamResponse()
|
||||||
response.content_type = content_type
|
response.content_type = content_type
|
||||||
yield from response.prepare(request)
|
await response.prepare(request)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
with async_timeout.timeout(timeout, loop=hass.loop):
|
with async_timeout.timeout(timeout, loop=hass.loop):
|
||||||
data = yield from stream.read(buffer_size)
|
data = await stream.read(buffer_size)
|
||||||
|
|
||||||
if not data:
|
if not data:
|
||||||
yield from response.write_eof()
|
await response.write_eof()
|
||||||
break
|
break
|
||||||
|
|
||||||
response.write(data)
|
response.write(data)
|
||||||
|
|
||||||
except (asyncio.TimeoutError, aiohttp.ClientError):
|
except (asyncio.TimeoutError, aiohttp.ClientError):
|
||||||
# Something went wrong fetching data, close connection gracefully
|
# Something went wrong fetching data, close connection gracefully
|
||||||
yield from response.write_eof()
|
await response.write_eof()
|
||||||
|
|
||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
# The user closed the connection
|
# The user closed the connection
|
||||||
|
@ -332,11 +332,10 @@ class Entity(object):
|
|||||||
if self.parallel_updates:
|
if self.parallel_updates:
|
||||||
self.parallel_updates.release()
|
self.parallel_updates.release()
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_remove(self):
|
||||||
def async_remove(self):
|
|
||||||
"""Remove entity from Home Assistant."""
|
"""Remove entity from Home Assistant."""
|
||||||
if self.platform is not None:
|
if self.platform is not None:
|
||||||
yield from self.platform.async_remove_entity(self.entity_id)
|
await self.platform.async_remove_entity(self.entity_id)
|
||||||
else:
|
else:
|
||||||
self.hass.states.async_remove(self.entity_id)
|
self.hass.states.async_remove(self.entity_id)
|
||||||
|
|
||||||
|
@ -75,8 +75,7 @@ class EntityComponent(object):
|
|||||||
"""
|
"""
|
||||||
self.hass.add_job(self.async_setup(config))
|
self.hass.add_job(self.async_setup(config))
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_setup(self, config):
|
||||||
def async_setup(self, config):
|
|
||||||
"""Set up a full entity component.
|
"""Set up a full entity component.
|
||||||
|
|
||||||
Loads the platforms from the config and will listen for supported
|
Loads the platforms from the config and will listen for supported
|
||||||
@ -92,14 +91,13 @@ class EntityComponent(object):
|
|||||||
tasks.append(self._async_setup_platform(p_type, p_config))
|
tasks.append(self._async_setup_platform(p_type, p_config))
|
||||||
|
|
||||||
if tasks:
|
if tasks:
|
||||||
yield from asyncio.wait(tasks, loop=self.hass.loop)
|
await asyncio.wait(tasks, loop=self.hass.loop)
|
||||||
|
|
||||||
# Generic discovery listener for loading platform dynamically
|
# Generic discovery listener for loading platform dynamically
|
||||||
# Refer to: homeassistant.components.discovery.load_platform()
|
# Refer to: homeassistant.components.discovery.load_platform()
|
||||||
@asyncio.coroutine
|
async def component_platform_discovered(platform, info):
|
||||||
def component_platform_discovered(platform, info):
|
|
||||||
"""Handle the loading of a platform."""
|
"""Handle the loading of a platform."""
|
||||||
yield from self._async_setup_platform(platform, {}, info)
|
await self._async_setup_platform(platform, {}, info)
|
||||||
|
|
||||||
discovery.async_listen_platform(
|
discovery.async_listen_platform(
|
||||||
self.hass, self.domain, component_platform_discovered)
|
self.hass, self.domain, component_platform_discovered)
|
||||||
@ -120,11 +118,10 @@ class EntityComponent(object):
|
|||||||
return [entity for entity in self.entities
|
return [entity for entity in self.entities
|
||||||
if entity.available and entity.entity_id in entity_ids]
|
if entity.available and entity.entity_id in entity_ids]
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def _async_setup_platform(self, platform_type, platform_config,
|
||||||
def _async_setup_platform(self, platform_type, platform_config,
|
discovery_info=None):
|
||||||
discovery_info=None):
|
|
||||||
"""Set up a platform for this component."""
|
"""Set up a platform for this component."""
|
||||||
platform = yield from async_prepare_setup_platform(
|
platform = await async_prepare_setup_platform(
|
||||||
self.hass, self.config, self.domain, platform_type)
|
self.hass, self.config, self.domain, platform_type)
|
||||||
|
|
||||||
if platform is None:
|
if platform is None:
|
||||||
@ -156,7 +153,7 @@ class EntityComponent(object):
|
|||||||
else:
|
else:
|
||||||
entity_platform = self._platforms[key]
|
entity_platform = self._platforms[key]
|
||||||
|
|
||||||
yield from entity_platform.async_setup(
|
await entity_platform.async_setup(
|
||||||
platform, platform_config, discovery_info)
|
platform, platform_config, discovery_info)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
@ -177,8 +174,7 @@ class EntityComponent(object):
|
|||||||
visible=False, entity_ids=ids
|
visible=False, entity_ids=ids
|
||||||
)
|
)
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def _async_reset(self):
|
||||||
def _async_reset(self):
|
|
||||||
"""Remove entities and reset the entity component to initial values.
|
"""Remove entities and reset the entity component to initial values.
|
||||||
|
|
||||||
This method must be run in the event loop.
|
This method must be run in the event loop.
|
||||||
@ -187,7 +183,7 @@ class EntityComponent(object):
|
|||||||
in self._platforms.values()]
|
in self._platforms.values()]
|
||||||
|
|
||||||
if tasks:
|
if tasks:
|
||||||
yield from asyncio.wait(tasks, loop=self.hass.loop)
|
await asyncio.wait(tasks, loop=self.hass.loop)
|
||||||
|
|
||||||
self._platforms = {
|
self._platforms = {
|
||||||
self.domain: self._platforms[self.domain]
|
self.domain: self._platforms[self.domain]
|
||||||
@ -197,21 +193,19 @@ class EntityComponent(object):
|
|||||||
if self.group_name is not None:
|
if self.group_name is not None:
|
||||||
self.hass.components.group.async_remove(slugify(self.group_name))
|
self.hass.components.group.async_remove(slugify(self.group_name))
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_remove_entity(self, entity_id):
|
||||||
def async_remove_entity(self, entity_id):
|
|
||||||
"""Remove an entity managed by one of the platforms."""
|
"""Remove an entity managed by one of the platforms."""
|
||||||
for platform in self._platforms.values():
|
for platform in self._platforms.values():
|
||||||
if entity_id in platform.entities:
|
if entity_id in platform.entities:
|
||||||
yield from platform.async_remove_entity(entity_id)
|
await platform.async_remove_entity(entity_id)
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_prepare_reload(self):
|
||||||
def async_prepare_reload(self):
|
|
||||||
"""Prepare reloading this entity component.
|
"""Prepare reloading this entity component.
|
||||||
|
|
||||||
This method must be run in the event loop.
|
This method must be run in the event loop.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
conf = yield from \
|
conf = await \
|
||||||
conf_util.async_hass_config_yaml(self.hass)
|
conf_util.async_hass_config_yaml(self.hass)
|
||||||
except HomeAssistantError as err:
|
except HomeAssistantError as err:
|
||||||
self.logger.error(err)
|
self.logger.error(err)
|
||||||
@ -223,5 +217,5 @@ class EntityComponent(object):
|
|||||||
if conf is None:
|
if conf is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
yield from self._async_reset()
|
await self._async_reset()
|
||||||
return conf
|
return conf
|
||||||
|
@ -51,9 +51,8 @@ class EntityPlatform(object):
|
|||||||
self.parallel_updates = asyncio.Semaphore(
|
self.parallel_updates = asyncio.Semaphore(
|
||||||
parallel_updates, loop=hass.loop)
|
parallel_updates, loop=hass.loop)
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_setup(self, platform, platform_config, discovery_info=None,
|
||||||
def async_setup(self, platform, platform_config, discovery_info=None,
|
tries=0):
|
||||||
tries=0):
|
|
||||||
"""Setup the platform."""
|
"""Setup the platform."""
|
||||||
logger = self.logger
|
logger = self.logger
|
||||||
hass = self.hass
|
hass = self.hass
|
||||||
@ -78,7 +77,7 @@ class EntityPlatform(object):
|
|||||||
None, platform.setup_platform, hass, platform_config,
|
None, platform.setup_platform, hass, platform_config,
|
||||||
self._schedule_add_entities, discovery_info
|
self._schedule_add_entities, discovery_info
|
||||||
)
|
)
|
||||||
yield from asyncio.wait_for(
|
await asyncio.wait_for(
|
||||||
asyncio.shield(task, loop=hass.loop),
|
asyncio.shield(task, loop=hass.loop),
|
||||||
SLOW_SETUP_MAX_WAIT, loop=hass.loop)
|
SLOW_SETUP_MAX_WAIT, loop=hass.loop)
|
||||||
|
|
||||||
@ -88,7 +87,7 @@ class EntityPlatform(object):
|
|||||||
self._tasks.clear()
|
self._tasks.clear()
|
||||||
|
|
||||||
if pending:
|
if pending:
|
||||||
yield from asyncio.wait(
|
await asyncio.wait(
|
||||||
pending, loop=self.hass.loop)
|
pending, loop=self.hass.loop)
|
||||||
|
|
||||||
hass.config.components.add(full_name)
|
hass.config.components.add(full_name)
|
||||||
@ -142,8 +141,7 @@ class EntityPlatform(object):
|
|||||||
self.async_add_entities(list(new_entities), update_before_add),
|
self.async_add_entities(list(new_entities), update_before_add),
|
||||||
self.hass.loop).result()
|
self.hass.loop).result()
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_add_entities(self, new_entities, update_before_add=False):
|
||||||
def async_add_entities(self, new_entities, update_before_add=False):
|
|
||||||
"""Add entities for a single platform async.
|
"""Add entities for a single platform async.
|
||||||
|
|
||||||
This method must be run in the event loop.
|
This method must be run in the event loop.
|
||||||
@ -155,14 +153,14 @@ class EntityPlatform(object):
|
|||||||
hass = self.hass
|
hass = self.hass
|
||||||
component_entities = set(hass.states.async_entity_ids(self.domain))
|
component_entities = set(hass.states.async_entity_ids(self.domain))
|
||||||
|
|
||||||
registry = yield from async_get_registry(hass)
|
registry = await async_get_registry(hass)
|
||||||
|
|
||||||
tasks = [
|
tasks = [
|
||||||
self._async_add_entity(entity, update_before_add,
|
self._async_add_entity(entity, update_before_add,
|
||||||
component_entities, registry)
|
component_entities, registry)
|
||||||
for entity in new_entities]
|
for entity in new_entities]
|
||||||
|
|
||||||
yield from asyncio.wait(tasks, loop=self.hass.loop)
|
await asyncio.wait(tasks, loop=self.hass.loop)
|
||||||
self.async_entities_added_callback()
|
self.async_entities_added_callback()
|
||||||
|
|
||||||
if self._async_unsub_polling is not None or \
|
if self._async_unsub_polling is not None or \
|
||||||
@ -174,9 +172,8 @@ class EntityPlatform(object):
|
|||||||
self.hass, self._update_entity_states, self.scan_interval
|
self.hass, self._update_entity_states, self.scan_interval
|
||||||
)
|
)
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def _async_add_entity(self, entity, update_before_add,
|
||||||
def _async_add_entity(self, entity, update_before_add, component_entities,
|
component_entities, registry):
|
||||||
registry):
|
|
||||||
"""Helper method to add an entity to the platform."""
|
"""Helper method to add an entity to the platform."""
|
||||||
if entity is None:
|
if entity is None:
|
||||||
raise ValueError('Entity cannot be None')
|
raise ValueError('Entity cannot be None')
|
||||||
@ -188,7 +185,7 @@ class EntityPlatform(object):
|
|||||||
# Update properties before we generate the entity_id
|
# Update properties before we generate the entity_id
|
||||||
if update_before_add:
|
if update_before_add:
|
||||||
try:
|
try:
|
||||||
yield from entity.async_device_update(warning=False)
|
await entity.async_device_update(warning=False)
|
||||||
except Exception: # pylint: disable=broad-except
|
except Exception: # pylint: disable=broad-except
|
||||||
self.logger.exception(
|
self.logger.exception(
|
||||||
"%s: Error on device update!", self.platform_name)
|
"%s: Error on device update!", self.platform_name)
|
||||||
@ -258,12 +255,11 @@ class EntityPlatform(object):
|
|||||||
component_entities.add(entity.entity_id)
|
component_entities.add(entity.entity_id)
|
||||||
|
|
||||||
if hasattr(entity, 'async_added_to_hass'):
|
if hasattr(entity, 'async_added_to_hass'):
|
||||||
yield from entity.async_added_to_hass()
|
await entity.async_added_to_hass()
|
||||||
|
|
||||||
yield from entity.async_update_ha_state()
|
await entity.async_update_ha_state()
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_reset(self):
|
||||||
def async_reset(self):
|
|
||||||
"""Remove all entities and reset data.
|
"""Remove all entities and reset data.
|
||||||
|
|
||||||
This method must be run in the event loop.
|
This method must be run in the event loop.
|
||||||
@ -274,16 +270,15 @@ class EntityPlatform(object):
|
|||||||
tasks = [self._async_remove_entity(entity_id)
|
tasks = [self._async_remove_entity(entity_id)
|
||||||
for entity_id in self.entities]
|
for entity_id in self.entities]
|
||||||
|
|
||||||
yield from asyncio.wait(tasks, loop=self.hass.loop)
|
await asyncio.wait(tasks, loop=self.hass.loop)
|
||||||
|
|
||||||
if self._async_unsub_polling is not None:
|
if self._async_unsub_polling is not None:
|
||||||
self._async_unsub_polling()
|
self._async_unsub_polling()
|
||||||
self._async_unsub_polling = None
|
self._async_unsub_polling = None
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_remove_entity(self, entity_id):
|
||||||
def async_remove_entity(self, entity_id):
|
|
||||||
"""Remove entity id from platform."""
|
"""Remove entity id from platform."""
|
||||||
yield from self._async_remove_entity(entity_id)
|
await self._async_remove_entity(entity_id)
|
||||||
|
|
||||||
# Clean up polling job if no longer needed
|
# Clean up polling job if no longer needed
|
||||||
if (self._async_unsub_polling is not None and
|
if (self._async_unsub_polling is not None and
|
||||||
@ -292,18 +287,16 @@ class EntityPlatform(object):
|
|||||||
self._async_unsub_polling()
|
self._async_unsub_polling()
|
||||||
self._async_unsub_polling = None
|
self._async_unsub_polling = None
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def _async_remove_entity(self, entity_id):
|
||||||
def _async_remove_entity(self, entity_id):
|
|
||||||
"""Remove entity id from platform."""
|
"""Remove entity id from platform."""
|
||||||
entity = self.entities.pop(entity_id)
|
entity = self.entities.pop(entity_id)
|
||||||
|
|
||||||
if hasattr(entity, 'async_will_remove_from_hass'):
|
if hasattr(entity, 'async_will_remove_from_hass'):
|
||||||
yield from entity.async_will_remove_from_hass()
|
await entity.async_will_remove_from_hass()
|
||||||
|
|
||||||
self.hass.states.async_remove(entity_id)
|
self.hass.states.async_remove(entity_id)
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def _update_entity_states(self, now):
|
||||||
def _update_entity_states(self, now):
|
|
||||||
"""Update the states of all the polling entities.
|
"""Update the states of all the polling entities.
|
||||||
|
|
||||||
To protect from flooding the executor, we will update async entities
|
To protect from flooding the executor, we will update async entities
|
||||||
@ -318,7 +311,7 @@ class EntityPlatform(object):
|
|||||||
self.scan_interval)
|
self.scan_interval)
|
||||||
return
|
return
|
||||||
|
|
||||||
with (yield from self._process_updates):
|
with (await self._process_updates):
|
||||||
tasks = []
|
tasks = []
|
||||||
for entity in self.entities.values():
|
for entity in self.entities.values():
|
||||||
if not entity.should_poll:
|
if not entity.should_poll:
|
||||||
@ -326,4 +319,4 @@ class EntityPlatform(object):
|
|||||||
tasks.append(entity.async_update_ha_state(True))
|
tasks.append(entity.async_update_ha_state(True))
|
||||||
|
|
||||||
if tasks:
|
if tasks:
|
||||||
yield from asyncio.wait(tasks, loop=self.hass.loop)
|
await asyncio.wait(tasks, loop=self.hass.loop)
|
||||||
|
@ -10,7 +10,7 @@ timer.
|
|||||||
After initializing, call EntityRegistry.async_ensure_loaded to load the data
|
After initializing, call EntityRegistry.async_ensure_loaded to load the data
|
||||||
from disk.
|
from disk.
|
||||||
"""
|
"""
|
||||||
import asyncio
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
import logging
|
import logging
|
||||||
@ -150,8 +150,7 @@ class EntityRegistry:
|
|||||||
|
|
||||||
return new
|
return new
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_ensure_loaded(self):
|
||||||
def async_ensure_loaded(self):
|
|
||||||
"""Load the registry from disk."""
|
"""Load the registry from disk."""
|
||||||
if self.entities is not None:
|
if self.entities is not None:
|
||||||
return
|
return
|
||||||
@ -159,16 +158,15 @@ class EntityRegistry:
|
|||||||
if self._load_task is None:
|
if self._load_task is None:
|
||||||
self._load_task = self.hass.async_add_job(self._async_load)
|
self._load_task = self.hass.async_add_job(self._async_load)
|
||||||
|
|
||||||
yield from self._load_task
|
await self._load_task
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def _async_load(self):
|
||||||
def _async_load(self):
|
|
||||||
"""Load the entity registry."""
|
"""Load the entity registry."""
|
||||||
path = self.hass.config.path(PATH_REGISTRY)
|
path = self.hass.config.path(PATH_REGISTRY)
|
||||||
entities = OrderedDict()
|
entities = OrderedDict()
|
||||||
|
|
||||||
if os.path.isfile(path):
|
if os.path.isfile(path):
|
||||||
data = yield from self.hass.async_add_job(load_yaml, path)
|
data = await self.hass.async_add_job(load_yaml, path)
|
||||||
|
|
||||||
for entity_id, info in data.items():
|
for entity_id, info in data.items():
|
||||||
entities[entity_id] = RegistryEntry(
|
entities[entity_id] = RegistryEntry(
|
||||||
@ -192,8 +190,7 @@ class EntityRegistry:
|
|||||||
SAVE_DELAY, self.hass.async_add_job, self._async_save
|
SAVE_DELAY, self.hass.async_add_job, self._async_save
|
||||||
)
|
)
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def _async_save(self):
|
||||||
def _async_save(self):
|
|
||||||
"""Save the entity registry to a file."""
|
"""Save the entity registry to a file."""
|
||||||
self._sched_save = None
|
self._sched_save = None
|
||||||
data = OrderedDict()
|
data = OrderedDict()
|
||||||
@ -205,7 +202,7 @@ class EntityRegistry:
|
|||||||
'name': entry.name,
|
'name': entry.name,
|
||||||
}
|
}
|
||||||
|
|
||||||
yield from self.hass.async_add_job(
|
await self.hass.async_add_job(
|
||||||
save_yaml, self.hass.config.path(PATH_REGISTRY), data)
|
save_yaml, self.hass.config.path(PATH_REGISTRY), data)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
"""Module to coordinate user intentions."""
|
"""Module to coordinate user intentions."""
|
||||||
import asyncio
|
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
|
||||||
@ -41,9 +40,9 @@ def async_register(hass, handler):
|
|||||||
intents[handler.intent_type] = handler
|
intents[handler.intent_type] = handler
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
@bind_hass
|
@bind_hass
|
||||||
def async_handle(hass, platform, intent_type, slots=None, text_input=None):
|
async def async_handle(hass, platform, intent_type, slots=None,
|
||||||
|
text_input=None):
|
||||||
"""Handle an intent."""
|
"""Handle an intent."""
|
||||||
handler = hass.data.get(DATA_KEY, {}).get(intent_type)
|
handler = hass.data.get(DATA_KEY, {}).get(intent_type)
|
||||||
|
|
||||||
@ -54,7 +53,7 @@ def async_handle(hass, platform, intent_type, slots=None, text_input=None):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
_LOGGER.info("Triggering intent handler %s", handler)
|
_LOGGER.info("Triggering intent handler %s", handler)
|
||||||
result = yield from handler.async_handle(intent)
|
result = await handler.async_handle(intent)
|
||||||
return result
|
return result
|
||||||
except vol.Invalid as err:
|
except vol.Invalid as err:
|
||||||
raise InvalidSlotInfo(
|
raise InvalidSlotInfo(
|
||||||
@ -114,8 +113,7 @@ class IntentHandler:
|
|||||||
|
|
||||||
return self._slot_schema(slots)
|
return self._slot_schema(slots)
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_handle(self, intent_obj):
|
||||||
def async_handle(self, intent_obj):
|
|
||||||
"""Handle the intent."""
|
"""Handle the intent."""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
@ -153,8 +151,7 @@ class ServiceIntentHandler(IntentHandler):
|
|||||||
self.service = service
|
self.service = service
|
||||||
self.speech = speech
|
self.speech = speech
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_handle(self, intent_obj):
|
||||||
def async_handle(self, intent_obj):
|
|
||||||
"""Handle the hass intent."""
|
"""Handle the hass intent."""
|
||||||
hass = intent_obj.hass
|
hass = intent_obj.hass
|
||||||
slots = self.async_validate_slots(intent_obj.slots)
|
slots = self.async_validate_slots(intent_obj.slots)
|
||||||
@ -175,7 +172,7 @@ class ServiceIntentHandler(IntentHandler):
|
|||||||
_LOGGER.error("Could not find entity id matching %s", name)
|
_LOGGER.error("Could not find entity id matching %s", name)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
yield from hass.services.async_call(
|
await hass.services.async_call(
|
||||||
self.domain, self.service, {
|
self.domain, self.service, {
|
||||||
ATTR_ENTITY_ID: entity_id
|
ATTR_ENTITY_ID: entity_id
|
||||||
})
|
})
|
||||||
|
@ -49,9 +49,8 @@ def _load_restore_cache(hass: HomeAssistant):
|
|||||||
_LOGGER.debug('Created cache with %s', list(hass.data[DATA_RESTORE_CACHE]))
|
_LOGGER.debug('Created cache with %s', list(hass.data[DATA_RESTORE_CACHE]))
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
@bind_hass
|
@bind_hass
|
||||||
def async_get_last_state(hass, entity_id: str):
|
async def async_get_last_state(hass, entity_id: str):
|
||||||
"""Restore state."""
|
"""Restore state."""
|
||||||
if DATA_RESTORE_CACHE in hass.data:
|
if DATA_RESTORE_CACHE in hass.data:
|
||||||
return hass.data[DATA_RESTORE_CACHE].get(entity_id)
|
return hass.data[DATA_RESTORE_CACHE].get(entity_id)
|
||||||
@ -66,7 +65,7 @@ def async_get_last_state(hass, entity_id: str):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
with async_timeout.timeout(RECORDER_TIMEOUT, loop=hass.loop):
|
with async_timeout.timeout(RECORDER_TIMEOUT, loop=hass.loop):
|
||||||
connected = yield from wait_connection_ready(hass)
|
connected = await wait_connection_ready(hass)
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -76,25 +75,24 @@ def async_get_last_state(hass, entity_id: str):
|
|||||||
if _LOCK not in hass.data:
|
if _LOCK not in hass.data:
|
||||||
hass.data[_LOCK] = asyncio.Lock(loop=hass.loop)
|
hass.data[_LOCK] = asyncio.Lock(loop=hass.loop)
|
||||||
|
|
||||||
with (yield from hass.data[_LOCK]):
|
with (await hass.data[_LOCK]):
|
||||||
if DATA_RESTORE_CACHE not in hass.data:
|
if DATA_RESTORE_CACHE not in hass.data:
|
||||||
yield from hass.async_add_job(
|
await hass.async_add_job(
|
||||||
_load_restore_cache, hass)
|
_load_restore_cache, hass)
|
||||||
|
|
||||||
return hass.data.get(DATA_RESTORE_CACHE, {}).get(entity_id)
|
return hass.data.get(DATA_RESTORE_CACHE, {}).get(entity_id)
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_restore_state(entity, extract_info):
|
||||||
def async_restore_state(entity, extract_info):
|
|
||||||
"""Call entity.async_restore_state with cached info."""
|
"""Call entity.async_restore_state with cached info."""
|
||||||
if entity.hass.state not in (CoreState.starting, CoreState.not_running):
|
if entity.hass.state not in (CoreState.starting, CoreState.not_running):
|
||||||
_LOGGER.debug("Not restoring state for %s: Hass is not starting: %s",
|
_LOGGER.debug("Not restoring state for %s: Hass is not starting: %s",
|
||||||
entity.entity_id, entity.hass.state)
|
entity.entity_id, entity.hass.state)
|
||||||
return
|
return
|
||||||
|
|
||||||
state = yield from async_get_last_state(entity.hass, entity.entity_id)
|
state = await async_get_last_state(entity.hass, entity.entity_id)
|
||||||
|
|
||||||
if not state:
|
if not state:
|
||||||
return
|
return
|
||||||
|
|
||||||
yield from entity.async_restore_state(**extract_info(state))
|
await entity.async_restore_state(**extract_info(state))
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""Helpers to execute scripts."""
|
"""Helpers to execute scripts."""
|
||||||
import asyncio
|
|
||||||
import logging
|
import logging
|
||||||
from itertools import islice
|
from itertools import islice
|
||||||
from typing import Optional, Sequence
|
from typing import Optional, Sequence
|
||||||
@ -68,8 +68,7 @@ class Script():
|
|||||||
run_coroutine_threadsafe(
|
run_coroutine_threadsafe(
|
||||||
self.async_run(variables), self.hass.loop).result()
|
self.async_run(variables), self.hass.loop).result()
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_run(self, variables: Optional[Sequence] = None) -> None:
|
||||||
def async_run(self, variables: Optional[Sequence] = None) -> None:
|
|
||||||
"""Run script.
|
"""Run script.
|
||||||
|
|
||||||
This method is a coroutine.
|
This method is a coroutine.
|
||||||
@ -151,7 +150,7 @@ class Script():
|
|||||||
self._async_fire_event(action, variables)
|
self._async_fire_event(action, variables)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
yield from self._async_call_service(action, variables)
|
await self._async_call_service(action, variables)
|
||||||
|
|
||||||
self._cur = -1
|
self._cur = -1
|
||||||
self.last_action = None
|
self.last_action = None
|
||||||
@ -172,15 +171,14 @@ class Script():
|
|||||||
if self._change_listener:
|
if self._change_listener:
|
||||||
self.hass.async_add_job(self._change_listener)
|
self.hass.async_add_job(self._change_listener)
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def _async_call_service(self, action, variables):
|
||||||
def _async_call_service(self, action, variables):
|
|
||||||
"""Call the service specified in the action.
|
"""Call the service specified in the action.
|
||||||
|
|
||||||
This method is a coroutine.
|
This method is a coroutine.
|
||||||
"""
|
"""
|
||||||
self.last_action = action.get(CONF_ALIAS, 'call service')
|
self.last_action = action.get(CONF_ALIAS, 'call service')
|
||||||
self._log("Executing step %s" % self.last_action)
|
self._log("Executing step %s" % self.last_action)
|
||||||
yield from service.async_call_from_config(
|
await service.async_call_from_config(
|
||||||
self.hass, action, True, variables, validate_config=False)
|
self.hass, action, True, variables, validate_config=False)
|
||||||
|
|
||||||
def _async_fire_event(self, action, variables):
|
def _async_fire_event(self, action, variables):
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
"""Service calling related helpers."""
|
"""Service calling related helpers."""
|
||||||
import asyncio
|
|
||||||
import logging
|
import logging
|
||||||
# pylint: disable=unused-import
|
# pylint: disable=unused-import
|
||||||
from typing import Optional # NOQA
|
from typing import Optional # NOQA
|
||||||
@ -36,10 +35,9 @@ def call_from_config(hass, config, blocking=False, variables=None,
|
|||||||
validate_config), hass.loop).result()
|
validate_config), hass.loop).result()
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
@bind_hass
|
@bind_hass
|
||||||
def async_call_from_config(hass, config, blocking=False, variables=None,
|
async def async_call_from_config(hass, config, blocking=False, variables=None,
|
||||||
validate_config=True):
|
validate_config=True):
|
||||||
"""Call a service based on a config hash."""
|
"""Call a service based on a config hash."""
|
||||||
if validate_config:
|
if validate_config:
|
||||||
try:
|
try:
|
||||||
@ -79,7 +77,7 @@ def async_call_from_config(hass, config, blocking=False, variables=None,
|
|||||||
if CONF_SERVICE_ENTITY_ID in config:
|
if CONF_SERVICE_ENTITY_ID in config:
|
||||||
service_data[ATTR_ENTITY_ID] = config[CONF_SERVICE_ENTITY_ID]
|
service_data[ATTR_ENTITY_ID] = config[CONF_SERVICE_ENTITY_ID]
|
||||||
|
|
||||||
yield from hass.services.async_call(
|
await hass.services.async_call(
|
||||||
domain, service_name, service_data, blocking)
|
domain, service_name, service_data, blocking)
|
||||||
|
|
||||||
|
|
||||||
@ -115,9 +113,8 @@ def extract_entity_ids(hass, service_call, expand_group=True):
|
|||||||
return service_ent_id
|
return service_ent_id
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
@bind_hass
|
@bind_hass
|
||||||
def async_get_all_descriptions(hass):
|
async def async_get_all_descriptions(hass):
|
||||||
"""Return descriptions (i.e. user documentation) for all service calls."""
|
"""Return descriptions (i.e. user documentation) for all service calls."""
|
||||||
if SERVICE_DESCRIPTION_CACHE not in hass.data:
|
if SERVICE_DESCRIPTION_CACHE not in hass.data:
|
||||||
hass.data[SERVICE_DESCRIPTION_CACHE] = {}
|
hass.data[SERVICE_DESCRIPTION_CACHE] = {}
|
||||||
@ -156,7 +153,7 @@ def async_get_all_descriptions(hass):
|
|||||||
break
|
break
|
||||||
|
|
||||||
if missing:
|
if missing:
|
||||||
loaded = yield from hass.async_add_job(load_services_files, missing)
|
loaded = await hass.async_add_job(load_services_files, missing)
|
||||||
|
|
||||||
# Build response
|
# Build response
|
||||||
catch_all_yaml_file = domain_yaml_file(ha.DOMAIN)
|
catch_all_yaml_file = domain_yaml_file(ha.DOMAIN)
|
||||||
|
@ -130,9 +130,8 @@ def reproduce_state(hass, states, blocking=False):
|
|||||||
async_reproduce_state(hass, states, blocking), hass.loop).result()
|
async_reproduce_state(hass, states, blocking), hass.loop).result()
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
@bind_hass
|
@bind_hass
|
||||||
def async_reproduce_state(hass, states, blocking=False):
|
async def async_reproduce_state(hass, states, blocking=False):
|
||||||
"""Reproduce given state."""
|
"""Reproduce given state."""
|
||||||
if isinstance(states, State):
|
if isinstance(states, State):
|
||||||
states = [states]
|
states = [states]
|
||||||
@ -193,16 +192,15 @@ def async_reproduce_state(hass, states, blocking=False):
|
|||||||
hass.services.async_call(service_domain, service, data, blocking)
|
hass.services.async_call(service_domain, service, data, blocking)
|
||||||
)
|
)
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_handle_service_calls(coro_list):
|
||||||
def async_handle_service_calls(coro_list):
|
|
||||||
"""Handle service calls by domain sequence."""
|
"""Handle service calls by domain sequence."""
|
||||||
for coro in coro_list:
|
for coro in coro_list:
|
||||||
yield from coro
|
await coro
|
||||||
|
|
||||||
execute_tasks = [async_handle_service_calls(coro_list)
|
execute_tasks = [async_handle_service_calls(coro_list)
|
||||||
for coro_list in domain_tasks.values()]
|
for coro_list in domain_tasks.values()]
|
||||||
if execute_tasks:
|
if execute_tasks:
|
||||||
yield from asyncio.wait(execute_tasks, loop=hass.loop)
|
await asyncio.wait(execute_tasks, loop=hass.loop)
|
||||||
|
|
||||||
|
|
||||||
def state_as_number(state):
|
def state_as_number(state):
|
||||||
|
@ -11,8 +11,7 @@ CONSTRAINT_FILE = 'package_constraints.txt'
|
|||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_process_requirements(hass, name, requirements):
|
||||||
def async_process_requirements(hass, name, requirements):
|
|
||||||
"""Install the requirements for a component or platform.
|
"""Install the requirements for a component or platform.
|
||||||
|
|
||||||
This method is a coroutine.
|
This method is a coroutine.
|
||||||
@ -24,9 +23,9 @@ def async_process_requirements(hass, name, requirements):
|
|||||||
pip_install = partial(pkg_util.install_package,
|
pip_install = partial(pkg_util.install_package,
|
||||||
**pip_kwargs(hass.config.config_dir))
|
**pip_kwargs(hass.config.config_dir))
|
||||||
|
|
||||||
with (yield from pip_lock):
|
async with pip_lock:
|
||||||
for req in requirements:
|
for req in requirements:
|
||||||
ret = yield from hass.async_add_job(pip_install, req)
|
ret = await hass.async_add_job(pip_install, req)
|
||||||
if not ret:
|
if not ret:
|
||||||
_LOGGER.error("Not initializing %s because could not install "
|
_LOGGER.error("Not initializing %s because could not install "
|
||||||
"requirement %s", name, req)
|
"requirement %s", name, req)
|
||||||
|
@ -50,8 +50,7 @@ def benchmark(func):
|
|||||||
|
|
||||||
|
|
||||||
@benchmark
|
@benchmark
|
||||||
@asyncio.coroutine
|
async def async_million_events(hass):
|
||||||
def async_million_events(hass):
|
|
||||||
"""Run a million events."""
|
"""Run a million events."""
|
||||||
count = 0
|
count = 0
|
||||||
event_name = 'benchmark_event'
|
event_name = 'benchmark_event'
|
||||||
@ -73,15 +72,14 @@ def async_million_events(hass):
|
|||||||
|
|
||||||
start = timer()
|
start = timer()
|
||||||
|
|
||||||
yield from event.wait()
|
await event.wait()
|
||||||
|
|
||||||
return timer() - start
|
return timer() - start
|
||||||
|
|
||||||
|
|
||||||
@benchmark
|
@benchmark
|
||||||
@asyncio.coroutine
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
def async_million_time_changed_helper(hass):
|
async def async_million_time_changed_helper(hass):
|
||||||
"""Run a million events through time changed helper."""
|
"""Run a million events through time changed helper."""
|
||||||
count = 0
|
count = 0
|
||||||
event = asyncio.Event(loop=hass.loop)
|
event = asyncio.Event(loop=hass.loop)
|
||||||
@ -105,15 +103,14 @@ def async_million_time_changed_helper(hass):
|
|||||||
|
|
||||||
start = timer()
|
start = timer()
|
||||||
|
|
||||||
yield from event.wait()
|
await event.wait()
|
||||||
|
|
||||||
return timer() - start
|
return timer() - start
|
||||||
|
|
||||||
|
|
||||||
@benchmark
|
@benchmark
|
||||||
@asyncio.coroutine
|
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
def async_million_state_changed_helper(hass):
|
async def async_million_state_changed_helper(hass):
|
||||||
"""Run a million events through state changed helper."""
|
"""Run a million events through state changed helper."""
|
||||||
count = 0
|
count = 0
|
||||||
entity_id = 'light.kitchen'
|
entity_id = 'light.kitchen'
|
||||||
@ -141,7 +138,7 @@ def async_million_state_changed_helper(hass):
|
|||||||
|
|
||||||
start = timer()
|
start = timer()
|
||||||
|
|
||||||
yield from event.wait()
|
await event.wait()
|
||||||
|
|
||||||
return timer() - start
|
return timer() - start
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""Script to ensure a configuration file exists."""
|
"""Script to ensure a configuration file exists."""
|
||||||
import asyncio
|
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
@ -46,8 +46,7 @@ C_HEAD = 'bold'
|
|||||||
ERROR_STR = 'General Errors'
|
ERROR_STR = 'General Errors'
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def mock_coro(*args):
|
||||||
def mock_coro(*args):
|
|
||||||
"""Coroutine that returns None."""
|
"""Coroutine that returns None."""
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -181,8 +180,7 @@ def check(config_path):
|
|||||||
# pylint: disable=unused-variable
|
# pylint: disable=unused-variable
|
||||||
def mock_get(comp_name):
|
def mock_get(comp_name):
|
||||||
"""Mock hass.loader.get_component to replace setup & setup_platform."""
|
"""Mock hass.loader.get_component to replace setup & setup_platform."""
|
||||||
@asyncio.coroutine
|
async def mock_async_setup(*args):
|
||||||
def mock_async_setup(*args):
|
|
||||||
"""Mock setup, only record the component name & config."""
|
"""Mock setup, only record the component name & config."""
|
||||||
assert comp_name not in res['components'], \
|
assert comp_name not in res['components'], \
|
||||||
"Components should contain a list of platforms"
|
"Components should contain a list of platforms"
|
||||||
|
@ -30,9 +30,8 @@ def setup_component(hass: core.HomeAssistant, domain: str,
|
|||||||
async_setup_component(hass, domain, config), loop=hass.loop).result()
|
async_setup_component(hass, domain, config), loop=hass.loop).result()
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_setup_component(hass: core.HomeAssistant, domain: str,
|
||||||
def async_setup_component(hass: core.HomeAssistant, domain: str,
|
config: Optional[Dict] = None) -> bool:
|
||||||
config: Optional[Dict] = None) -> bool:
|
|
||||||
"""Set up a component and all its dependencies.
|
"""Set up a component and all its dependencies.
|
||||||
|
|
||||||
This method is a coroutine.
|
This method is a coroutine.
|
||||||
@ -43,7 +42,7 @@ def async_setup_component(hass: core.HomeAssistant, domain: str,
|
|||||||
setup_tasks = hass.data.get(DATA_SETUP)
|
setup_tasks = hass.data.get(DATA_SETUP)
|
||||||
|
|
||||||
if setup_tasks is not None and domain in setup_tasks:
|
if setup_tasks is not None and domain in setup_tasks:
|
||||||
return (yield from setup_tasks[domain])
|
return await setup_tasks[domain]
|
||||||
|
|
||||||
if config is None:
|
if config is None:
|
||||||
config = {}
|
config = {}
|
||||||
@ -54,11 +53,10 @@ def async_setup_component(hass: core.HomeAssistant, domain: str,
|
|||||||
task = setup_tasks[domain] = hass.async_add_job(
|
task = setup_tasks[domain] = hass.async_add_job(
|
||||||
_async_setup_component(hass, domain, config))
|
_async_setup_component(hass, domain, config))
|
||||||
|
|
||||||
return (yield from task)
|
return await task
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def _async_process_dependencies(hass, config, name, dependencies):
|
||||||
def _async_process_dependencies(hass, config, name, dependencies):
|
|
||||||
"""Ensure all dependencies are set up."""
|
"""Ensure all dependencies are set up."""
|
||||||
blacklisted = [dep for dep in dependencies
|
blacklisted = [dep for dep in dependencies
|
||||||
if dep in loader.DEPENDENCY_BLACKLIST]
|
if dep in loader.DEPENDENCY_BLACKLIST]
|
||||||
@ -75,7 +73,7 @@ def _async_process_dependencies(hass, config, name, dependencies):
|
|||||||
if not tasks:
|
if not tasks:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
results = yield from asyncio.gather(*tasks, loop=hass.loop)
|
results = await asyncio.gather(*tasks, loop=hass.loop)
|
||||||
|
|
||||||
failed = [dependencies[idx] for idx, res
|
failed = [dependencies[idx] for idx, res
|
||||||
in enumerate(results) if not res]
|
in enumerate(results) if not res]
|
||||||
@ -89,9 +87,8 @@ def _async_process_dependencies(hass, config, name, dependencies):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def _async_setup_component(hass: core.HomeAssistant,
|
||||||
def _async_setup_component(hass: core.HomeAssistant,
|
domain: str, config) -> bool:
|
||||||
domain: str, config) -> bool:
|
|
||||||
"""Set up a component for Home Assistant.
|
"""Set up a component for Home Assistant.
|
||||||
|
|
||||||
This method is a coroutine.
|
This method is a coroutine.
|
||||||
@ -123,7 +120,7 @@ def _async_setup_component(hass: core.HomeAssistant,
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
yield from async_process_deps_reqs(hass, config, domain, component)
|
await async_process_deps_reqs(hass, config, domain, component)
|
||||||
except HomeAssistantError as err:
|
except HomeAssistantError as err:
|
||||||
log_error(str(err))
|
log_error(str(err))
|
||||||
return False
|
return False
|
||||||
@ -142,9 +139,9 @@ def _async_setup_component(hass: core.HomeAssistant,
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
if hasattr(component, 'async_setup'):
|
if hasattr(component, 'async_setup'):
|
||||||
result = yield from component.async_setup(hass, processed_config)
|
result = await component.async_setup(hass, processed_config)
|
||||||
else:
|
else:
|
||||||
result = yield from hass.async_add_job(
|
result = await hass.async_add_job(
|
||||||
component.setup, hass, processed_config)
|
component.setup, hass, processed_config)
|
||||||
except Exception: # pylint: disable=broad-except
|
except Exception: # pylint: disable=broad-except
|
||||||
_LOGGER.exception("Error during setup of component %s", domain)
|
_LOGGER.exception("Error during setup of component %s", domain)
|
||||||
@ -166,7 +163,7 @@ def _async_setup_component(hass: core.HomeAssistant,
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
for entry in hass.config_entries.async_entries(domain):
|
for entry in hass.config_entries.async_entries(domain):
|
||||||
yield from entry.async_setup(hass, component=component)
|
await entry.async_setup(hass, component=component)
|
||||||
|
|
||||||
hass.config.components.add(component.DOMAIN)
|
hass.config.components.add(component.DOMAIN)
|
||||||
|
|
||||||
@ -181,9 +178,8 @@ def _async_setup_component(hass: core.HomeAssistant,
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_prepare_setup_platform(hass: core.HomeAssistant, config,
|
||||||
def async_prepare_setup_platform(hass: core.HomeAssistant, config, domain: str,
|
domain: str, platform_name: str) \
|
||||||
platform_name: str) \
|
|
||||||
-> Optional[ModuleType]:
|
-> Optional[ModuleType]:
|
||||||
"""Load a platform and makes sure dependencies are setup.
|
"""Load a platform and makes sure dependencies are setup.
|
||||||
|
|
||||||
@ -209,7 +205,7 @@ def async_prepare_setup_platform(hass: core.HomeAssistant, config, domain: str,
|
|||||||
return platform
|
return platform
|
||||||
|
|
||||||
try:
|
try:
|
||||||
yield from async_process_deps_reqs(
|
await async_process_deps_reqs(
|
||||||
hass, config, platform_path, platform)
|
hass, config, platform_path, platform)
|
||||||
except HomeAssistantError as err:
|
except HomeAssistantError as err:
|
||||||
log_error(str(err))
|
log_error(str(err))
|
||||||
@ -218,8 +214,7 @@ def async_prepare_setup_platform(hass: core.HomeAssistant, config, domain: str,
|
|||||||
return platform
|
return platform
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_process_deps_reqs(hass, config, name, module):
|
||||||
def async_process_deps_reqs(hass, config, name, module):
|
|
||||||
"""Process all dependencies and requirements for a module.
|
"""Process all dependencies and requirements for a module.
|
||||||
|
|
||||||
Module is a Python module of either a component or platform.
|
Module is a Python module of either a component or platform.
|
||||||
@ -232,14 +227,14 @@ def async_process_deps_reqs(hass, config, name, module):
|
|||||||
return
|
return
|
||||||
|
|
||||||
if hasattr(module, 'DEPENDENCIES'):
|
if hasattr(module, 'DEPENDENCIES'):
|
||||||
dep_success = yield from _async_process_dependencies(
|
dep_success = await _async_process_dependencies(
|
||||||
hass, config, name, module.DEPENDENCIES)
|
hass, config, name, module.DEPENDENCIES)
|
||||||
|
|
||||||
if not dep_success:
|
if not dep_success:
|
||||||
raise HomeAssistantError("Could not setup all dependencies.")
|
raise HomeAssistantError("Could not setup all dependencies.")
|
||||||
|
|
||||||
if not hass.config.skip_pip and hasattr(module, 'REQUIREMENTS'):
|
if not hass.config.skip_pip and hasattr(module, 'REQUIREMENTS'):
|
||||||
req_success = yield from requirements.async_process_requirements(
|
req_success = await requirements.async_process_requirements(
|
||||||
hass, name, module.REQUIREMENTS)
|
hass, name, module.REQUIREMENTS)
|
||||||
|
|
||||||
if not req_success:
|
if not req_success:
|
||||||
|
@ -88,17 +88,17 @@ def get_user_site(deps_dir: str) -> str:
|
|||||||
return lib_dir
|
return lib_dir
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_get_user_site(deps_dir: str,
|
||||||
def async_get_user_site(deps_dir: str, loop: asyncio.AbstractEventLoop) -> str:
|
loop: asyncio.AbstractEventLoop) -> str:
|
||||||
"""Return user local library path.
|
"""Return user local library path.
|
||||||
|
|
||||||
This function is a coroutine.
|
This function is a coroutine.
|
||||||
"""
|
"""
|
||||||
args, env = _get_user_site(deps_dir)
|
args, env = _get_user_site(deps_dir)
|
||||||
process = yield from asyncio.create_subprocess_exec(
|
process = await asyncio.create_subprocess_exec(
|
||||||
*args, loop=loop, stdin=asyncio.subprocess.PIPE,
|
*args, loop=loop, stdin=asyncio.subprocess.PIPE,
|
||||||
stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.DEVNULL,
|
stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.DEVNULL,
|
||||||
env=env)
|
env=env)
|
||||||
stdout, _ = yield from process.communicate()
|
stdout, _ = await process.communicate()
|
||||||
lib_dir = stdout.decode().strip()
|
lib_dir = stdout.decode().strip()
|
||||||
return lib_dir
|
return lib_dir
|
||||||
|
@ -3,4 +3,4 @@
|
|||||||
|
|
||||||
cd "$(dirname "$0")/.."
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
tox -e py34
|
tox -e py35
|
||||||
|
@ -6,7 +6,6 @@ import threading
|
|||||||
import homeassistant.util.logging as logging_util
|
import homeassistant.util.logging as logging_util
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
def test_sensitive_data_filter():
|
def test_sensitive_data_filter():
|
||||||
"""Test the logging sensitive data filter."""
|
"""Test the logging sensitive data filter."""
|
||||||
log_filter = logging_util.HideSensitiveDataFilter('mock_sensitive')
|
log_filter = logging_util.HideSensitiveDataFilter('mock_sensitive')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user