Further untangle data entry flow (#13855)

* Further untangle data entry flow

* Fix test

* Remove helper class
This commit is contained in:
Paulus Schoutsen 2018-04-14 14:38:24 -04:00 committed by GitHub
parent 5a5dad689b
commit 4d44c0feff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 47 additions and 47 deletions

View File

@ -115,9 +115,9 @@ import logging
import os import os
import uuid import uuid
from . import data_entry_flow
from .core import callback from .core import callback
from .exceptions import HomeAssistantError from .exceptions import HomeAssistantError
from .data_entry_flow import FlowManager
from .setup import async_setup_component, async_process_deps_reqs from .setup import async_setup_component, async_process_deps_reqs
from .util.json import load_json, save_json from .util.json import load_json, save_json
from .util.decorator import Registry from .util.decorator import Registry
@ -255,8 +255,8 @@ class ConfigEntries:
def __init__(self, hass, hass_config): def __init__(self, hass, hass_config):
"""Initialize the entry manager.""" """Initialize the entry manager."""
self.hass = hass self.hass = hass
self.flow = FlowManager(hass, HANDLERS, self._async_missing_handler, self.flow = data_entry_flow.FlowManager(
self._async_save_entry) hass, self._async_create_flow, self._async_save_entry)
self._hass_config = hass_config self._hass_config = hass_config
self._entries = None self._entries = None
self._sched_save = None self._sched_save = None
@ -345,7 +345,7 @@ class ConfigEntries:
"""Add an entry.""" """Add an entry."""
entry = ConfigEntry( entry = ConfigEntry(
version=result['version'], version=result['version'],
domain=result['domain'], domain=result['handler'],
title=result['title'], title=result['title'],
data=result['data'], data=result['data'],
source=result['source'], source=result['source'],
@ -362,17 +362,22 @@ class ConfigEntries:
await async_setup_component( await async_setup_component(
self.hass, entry.domain, self._hass_config) self.hass, entry.domain, self._hass_config)
async def _async_missing_handler(self, domain): async def _async_create_flow(self, handler):
"""Called when a flow handler is not loaded.""" """Create a flow for specified handler.
# This will load the component and thus register the handler
component = getattr(self.hass.components, domain)
if domain not in HANDLERS: Handler key is the domain of the component that we want to setup.
return """
component = getattr(self.hass.components, handler)
handler = HANDLERS.get(handler)
if handler is None:
raise data_entry_flow.UnknownHandler
# Make sure requirements and dependencies of component are resolved # Make sure requirements and dependencies of component are resolved
await async_process_deps_reqs( await async_process_deps_reqs(
self.hass, self._hass_config, domain, component) self.hass, self._hass_config, handler, component)
return handler()
@callback @callback
def _async_schedule_save(self): def _async_schedule_save(self):

View File

@ -34,13 +34,11 @@ class UnknownStep(FlowError):
class FlowManager: class FlowManager:
"""Manage all the flows that are in progress.""" """Manage all the flows that are in progress."""
def __init__(self, hass, handlers, async_missing_handler, def __init__(self, hass, async_create_flow, async_save_entry):
async_save_entry):
"""Initialize the flow manager.""" """Initialize the flow manager."""
self.hass = hass self.hass = hass
self._handlers = handlers
self._progress = {} self._progress = {}
self._async_missing_handler = async_missing_handler self._async_create_flow = async_create_flow
self._async_save_entry = async_save_entry self._async_save_entry = async_save_entry
@callback @callback
@ -48,27 +46,18 @@ class FlowManager:
"""Return the flows in progress.""" """Return the flows in progress."""
return [{ return [{
'flow_id': flow.flow_id, 'flow_id': flow.flow_id,
'domain': flow.domain, 'handler': flow.handler,
'source': flow.source, 'source': flow.source,
} for flow in self._progress.values()] } for flow in self._progress.values()]
async def async_init(self, domain, *, source=SOURCE_USER, data=None): async def async_init(self, handler, *, source=SOURCE_USER, data=None):
"""Start a configuration flow.""" """Start a configuration flow."""
handler = self._handlers.get(domain) flow = await self._async_create_flow(handler)
if handler is None:
await self._async_missing_handler(domain)
handler = self._handlers.get(domain)
if handler is None:
raise UnknownHandler
flow_id = uuid.uuid4().hex
flow = self._progress[flow_id] = handler()
flow.hass = self.hass flow.hass = self.hass
flow.domain = domain flow.handler = handler
flow.flow_id = flow_id flow.flow_id = uuid.uuid4().hex
flow.source = source flow.source = source
self._progress[flow.flow_id] = flow
if source == SOURCE_USER: if source == SOURCE_USER:
step = 'init' step = 'init'
@ -137,7 +126,7 @@ class FlowHandler:
# Set by flow manager # Set by flow manager
flow_id = None flow_id = None
hass = None hass = None
domain = None handler = None
source = SOURCE_USER source = SOURCE_USER
cur_step = None cur_step = None
@ -150,7 +139,7 @@ class FlowHandler:
return { return {
'type': RESULT_TYPE_FORM, 'type': RESULT_TYPE_FORM,
'flow_id': self.flow_id, 'flow_id': self.flow_id,
'domain': self.domain, 'handler': self.handler,
'step_id': step_id, 'step_id': step_id,
'data_schema': data_schema, 'data_schema': data_schema,
'errors': errors, 'errors': errors,
@ -163,7 +152,7 @@ class FlowHandler:
'version': self.VERSION, 'version': self.VERSION,
'type': RESULT_TYPE_CREATE_ENTRY, 'type': RESULT_TYPE_CREATE_ENTRY,
'flow_id': self.flow_id, 'flow_id': self.flow_id,
'domain': self.domain, 'handler': self.handler,
'title': title, 'title': title,
'data': data, 'data': data,
'source': self.source, 'source': self.source,
@ -175,6 +164,6 @@ class FlowHandler:
return { return {
'type': RESULT_TYPE_ABORT, 'type': RESULT_TYPE_ABORT,
'flow_id': self.flow_id, 'flow_id': self.flow_id,
'domain': self.domain, 'handler': self.handler,
'reason': reason 'reason': reason
} }

View File

@ -120,7 +120,7 @@ def test_initialize_flow(hass, client):
assert data == { assert data == {
'type': 'form', 'type': 'form',
'domain': 'test', 'handler': 'test',
'step_id': 'init', 'step_id': 'init',
'data_schema': [ 'data_schema': [
{ {
@ -156,7 +156,7 @@ def test_abort(hass, client):
data = yield from resp.json() data = yield from resp.json()
data.pop('flow_id') data.pop('flow_id')
assert data == { assert data == {
'domain': 'test', 'handler': 'test',
'reason': 'bla', 'reason': 'bla',
'type': 'abort' 'type': 'abort'
} }
@ -186,7 +186,7 @@ def test_create_account(hass, client):
data = yield from resp.json() data = yield from resp.json()
data.pop('flow_id') data.pop('flow_id')
assert data == { assert data == {
'domain': 'test', 'handler': 'test',
'title': 'Test Entry', 'title': 'Test Entry',
'type': 'create_entry', 'type': 'create_entry',
'source': 'user', 'source': 'user',
@ -226,7 +226,7 @@ def test_two_step_flow(hass, client):
flow_id = data.pop('flow_id') flow_id = data.pop('flow_id')
assert data == { assert data == {
'type': 'form', 'type': 'form',
'domain': 'test', 'handler': 'test',
'step_id': 'account', 'step_id': 'account',
'data_schema': [ 'data_schema': [
{ {
@ -245,7 +245,7 @@ def test_two_step_flow(hass, client):
data = yield from resp.json() data = yield from resp.json()
data.pop('flow_id') data.pop('flow_id')
assert data == { assert data == {
'domain': 'test', 'handler': 'test',
'type': 'create_entry', 'type': 'create_entry',
'title': 'user-title', 'title': 'user-title',
'version': 1, 'version': 1,
@ -279,7 +279,7 @@ def test_get_progress_index(hass, client):
assert data == [ assert data == [
{ {
'flow_id': form['flow_id'], 'flow_id': form['flow_id'],
'domain': 'test', 'handler': 'test',
'source': 'hassio' 'source': 'hassio'
} }
] ]

View File

@ -169,7 +169,7 @@ async def test_discover_config_flow(hass):
with patch.dict(discovery.CONFIG_ENTRY_HANDLERS, { with patch.dict(discovery.CONFIG_ENTRY_HANDLERS, {
'mock-service': 'mock-component'}), patch( 'mock-service': 'mock-component'}), patch(
'homeassistant.config_entries.FlowManager.async_init') as m_init: 'homeassistant.data_entry_flow.FlowManager.async_init') as m_init:
await mock_discovery(hass, discover) await mock_discovery(hass, discover)
assert len(m_init.mock_calls) == 1 assert len(m_init.mock_calls) == 1

View File

@ -5,8 +5,6 @@ import voluptuous as vol
from homeassistant import data_entry_flow from homeassistant import data_entry_flow
from homeassistant.util.decorator import Registry from homeassistant.util.decorator import Registry
from tests.common import mock_coro
@pytest.fixture @pytest.fixture
def manager(): def manager():
@ -14,11 +12,19 @@ def manager():
handlers = Registry() handlers = Registry()
entries = [] entries = []
async def async_create_flow(handler_name):
handler = handlers.get(handler_name)
if handler is None:
raise data_entry_flow.UnknownHandler
return handler()
async def async_add_entry(result): async def async_add_entry(result):
entries.append(result) entries.append(result)
manager = data_entry_flow.FlowManager( manager = data_entry_flow.FlowManager(
None, handlers, mock_coro, async_add_entry) None, async_create_flow, async_add_entry)
manager.mock_created_entries = entries manager.mock_created_entries = entries
manager.mock_reg_handler = handlers.register manager.mock_reg_handler = handlers.register
return manager return manager
@ -84,7 +90,7 @@ async def test_configure_two_steps(manager):
assert len(manager.async_progress()) == 0 assert len(manager.async_progress()) == 0
assert len(manager.mock_created_entries) == 1 assert len(manager.mock_created_entries) == 1
result = manager.mock_created_entries[0] result = manager.mock_created_entries[0]
assert result['domain'] == 'test' assert result['handler'] == 'test'
assert result['data'] == ['INIT-DATA', 'SECOND-DATA'] assert result['data'] == ['INIT-DATA', 'SECOND-DATA']
@ -153,7 +159,7 @@ async def test_create_saves_data(manager):
entry = manager.mock_created_entries[0] entry = manager.mock_created_entries[0]
assert entry['version'] == 5 assert entry['version'] == 5
assert entry['domain'] == 'test' assert entry['handler'] == 'test'
assert entry['title'] == 'Test Title' assert entry['title'] == 'Test Title'
assert entry['data'] == 'Test Data' assert entry['data'] == 'Test Data'
assert entry['source'] == data_entry_flow.SOURCE_USER assert entry['source'] == data_entry_flow.SOURCE_USER
@ -180,7 +186,7 @@ async def test_discovery_init_flow(manager):
entry = manager.mock_created_entries[0] entry = manager.mock_created_entries[0]
assert entry['version'] == 5 assert entry['version'] == 5
assert entry['domain'] == 'test' assert entry['handler'] == 'test'
assert entry['title'] == 'hello' assert entry['title'] == 'hello'
assert entry['data'] == data assert entry['data'] == data
assert entry['source'] == data_entry_flow.SOURCE_DISCOVERY assert entry['source'] == data_entry_flow.SOURCE_DISCOVERY