WS: Improve service calling errors (#23840)

* WS: Improve service calling errors

* Docstyle

* Types

* Update text
pull/23857/head
Paulus Schoutsen 2019-05-14 07:09:11 +02:00 committed by GitHub
parent 0d96095646
commit de1fd5a7fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 68 additions and 8 deletions

View File

@ -168,8 +168,14 @@ class ScriptEntity(ToggleEntity):
ATTR_NAME: self.script.name, ATTR_NAME: self.script.name,
ATTR_ENTITY_ID: self.entity_id, ATTR_ENTITY_ID: self.entity_id,
}, context=context) }, context=context)
await self.script.async_run( try:
kwargs.get(ATTR_VARIABLES), context) await self.script.async_run(
kwargs.get(ATTR_VARIABLES), context)
except Exception as err: # pylint: disable=broad-except
self.script.async_log_exception(
_LOGGER, "Error executing script {}".format(self.entity_id),
err)
raise err
async def async_turn_off(self, **kwargs): async def async_turn_off(self, **kwargs):
"""Turn script off.""" """Turn script off."""

View File

@ -120,17 +120,21 @@ async def handle_call_service(hass, connection, msg):
msg['domain'], msg['service'], msg.get('service_data'), blocking, msg['domain'], msg['service'], msg.get('service_data'), blocking,
connection.context(msg)) connection.context(msg))
connection.send_message(messages.result_message(msg['id'])) connection.send_message(messages.result_message(msg['id']))
except ServiceNotFound: except ServiceNotFound as err:
connection.send_message(messages.error_message( if err.domain == msg['domain'] and err.service == msg['service']:
msg['id'], const.ERR_NOT_FOUND, 'Service not found.')) connection.send_message(messages.error_message(
msg['id'], const.ERR_NOT_FOUND, 'Service not found.'))
else:
connection.send_message(messages.error_message(
msg['id'], const.ERR_HOME_ASSISTANT_ERROR, str(err)))
except HomeAssistantError as err: except HomeAssistantError as err:
connection.logger.exception(err) connection.logger.exception(err)
connection.send_message(messages.error_message( connection.send_message(messages.error_message(
msg['id'], const.ERR_HOME_ASSISTANT_ERROR, '{}'.format(err))) msg['id'], const.ERR_HOME_ASSISTANT_ERROR, str(err)))
except Exception as err: # pylint: disable=broad-except except Exception as err: # pylint: disable=broad-except
connection.logger.exception(err) connection.logger.exception(err)
connection.send_message(messages.error_message( connection.send_message(messages.error_message(
msg['id'], const.ERR_UNKNOWN_ERROR, '{}'.format(err))) msg['id'], const.ERR_UNKNOWN_ERROR, str(err)))
@callback @callback

View File

@ -75,3 +75,7 @@ class ServiceNotFound(HomeAssistantError):
self, "Service {}.{} not found".format(domain, service)) self, "Service {}.{} not found".format(domain, service))
self.domain = domain self.domain = domain
self.service = service self.service = service
def __str__(self) -> str:
"""Return string representation."""
return "Unable to find service {}/{}".format(self.domain, self.service)

View File

@ -893,4 +893,4 @@ async def test_automation_with_error_in_script(hass, caplog):
hass.bus.async_fire('test_event') hass.bus.async_fire('test_event')
await hass.async_block_till_done() await hass.async_block_till_done()
assert 'Service test.automation not found' in caplog.text assert 'Service not found' in caplog.text

View File

@ -3,6 +3,8 @@
import unittest import unittest
from unittest.mock import patch, Mock from unittest.mock import patch, Mock
import pytest
from homeassistant.components import script from homeassistant.components import script
from homeassistant.components.script import DOMAIN from homeassistant.components.script import DOMAIN
from homeassistant.const import ( from homeassistant.const import (
@ -11,6 +13,7 @@ from homeassistant.const import (
from homeassistant.core import Context, callback, split_entity_id from homeassistant.core import Context, callback, split_entity_id
from homeassistant.loader import bind_hass from homeassistant.loader import bind_hass
from homeassistant.setup import setup_component, async_setup_component from homeassistant.setup import setup_component, async_setup_component
from homeassistant.exceptions import ServiceNotFound
from tests.common import get_test_home_assistant from tests.common import get_test_home_assistant
@ -300,3 +303,22 @@ async def test_shared_context(hass):
state = hass.states.get('script.test') state = hass.states.get('script.test')
assert state is not None assert state is not None
assert state.context == context assert state.context == context
async def test_logging_script_error(hass, caplog):
"""Test logging script error."""
assert await async_setup_component(hass, 'script', {
'script': {
'hello': {
'sequence': [
{'service': 'non.existing'}
]
}
}
})
with pytest.raises(ServiceNotFound) as err:
await hass.services.async_call('script', 'hello', blocking=True)
assert err.value.domain == 'non'
assert err.value.service == 'existing'
assert 'Error executing script' in caplog.text

View File

@ -67,6 +67,30 @@ async def test_call_service_not_found(hass, websocket_client):
assert msg['error']['code'] == const.ERR_NOT_FOUND assert msg['error']['code'] == const.ERR_NOT_FOUND
async def test_call_service_child_not_found(hass, websocket_client):
"""Test not reporting not found errors if it's not the called service."""
async def serv_handler(call):
await hass.services.async_call('non', 'existing')
hass.services.async_register('domain_test', 'test_service', serv_handler)
await websocket_client.send_json({
'id': 5,
'type': 'call_service',
'domain': 'domain_test',
'service': 'test_service',
'service_data': {
'hello': 'world'
}
})
msg = await websocket_client.receive_json()
assert msg['id'] == 5
assert msg['type'] == const.TYPE_RESULT
assert not msg['success']
assert msg['error']['code'] == const.ERR_HOME_ASSISTANT_ERROR
async def test_call_service_error(hass, websocket_client): async def test_call_service_error(hass, websocket_client):
"""Test call service command with error.""" """Test call service command with error."""
@callback @callback