Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion homeassistant/auth/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ def async_get_access_token(self, token):

return tkn

async def _async_create_login_flow(self, handler, *, source, data):
async def _async_create_login_flow(self, handler, *, context, data):
"""Create a login flow."""
auth_provider = self._providers[handler]

Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/cast/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Component to embed Google Cast."""
from homeassistant import data_entry_flow
from homeassistant import config_entries
from homeassistant.helpers import config_entry_flow


Expand All @@ -15,7 +15,7 @@ async def async_setup(hass, config):

if conf is not None:
hass.async_create_task(hass.config_entries.flow.async_init(
DOMAIN, source=data_entry_flow.SOURCE_IMPORT))
DOMAIN, context={'source': config_entries.SOURCE_IMPORT}))

return True

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/config/config_entries.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def get(self, request):

return self.json([
flw for flw in hass.config_entries.flow.async_progress()
if flw['source'] != data_entry_flow.SOURCE_USER])
if flw['source'] != config_entries.SOURCE_USER])


class ConfigManagerFlowResourceView(FlowManagerResourceView):
Expand Down
5 changes: 4 additions & 1 deletion homeassistant/components/deconz/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"""
import voluptuous as vol

from homeassistant import config_entries
from homeassistant.const import (
CONF_API_KEY, CONF_EVENT, CONF_HOST,
CONF_ID, CONF_PORT, EVENT_HOMEASSISTANT_STOP)
Expand Down Expand Up @@ -60,7 +61,9 @@ async def async_setup(hass, config):
deconz_config = config[DOMAIN]
if deconz_config and not configured_hosts(hass):
hass.async_add_job(hass.config_entries.flow.async_init(
DOMAIN, source='import', data=deconz_config
DOMAIN,
context={'source': config_entries.SOURCE_IMPORT},
data=deconz_config
))
return True

Expand Down
4 changes: 4 additions & 0 deletions homeassistant/components/deconz/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ def __init__(self):
self.bridges = []
self.deconz_config = {}

async def async_step_user(self, user_input=None):
"""Handle a flow initialized by the user."""
return await self.async_step_init(user_input)

async def async_step_init(self, user_input=None):
"""Handle a deCONZ config flow start.

Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

import voluptuous as vol

from homeassistant import data_entry_flow
from homeassistant import config_entries
from homeassistant.core import callback
from homeassistant.const import EVENT_HOMEASSISTANT_START
import homeassistant.helpers.config_validation as cv
Expand Down Expand Up @@ -138,7 +138,7 @@ async def new_service_found(service, info):
if service in CONFIG_ENTRY_HANDLERS:
await hass.config_entries.flow.async_init(
CONFIG_ENTRY_HANDLERS[service],
source=data_entry_flow.SOURCE_DISCOVERY,
context={'source': config_entries.SOURCE_DISCOVERY},
data=info
)
return
Expand Down
4 changes: 3 additions & 1 deletion homeassistant/components/homematicip_cloud/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import voluptuous as vol

import homeassistant.helpers.config_validation as cv
from homeassistant import config_entries

from .const import (
DOMAIN, HMIPC_HAPID, HMIPC_AUTHTOKEN, HMIPC_NAME,
Expand Down Expand Up @@ -41,7 +42,8 @@ async def async_setup(hass, config):
for conf in accesspoints:
if conf[CONF_ACCESSPOINT] not in configured_haps(hass):
hass.async_add_job(hass.config_entries.flow.async_init(
DOMAIN, source='import', data={
DOMAIN, context={'source': config_entries.SOURCE_IMPORT},
data={
HMIPC_HAPID: conf[CONF_ACCESSPOINT],
HMIPC_AUTHTOKEN: conf[CONF_AUTHTOKEN],
HMIPC_NAME: conf[CONF_NAME],
Expand Down
4 changes: 4 additions & 0 deletions homeassistant/components/homematicip_cloud/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ def __init__(self):
"""Initialize HomematicIP Cloud config flow."""
self.auth = None

async def async_step_user(self, user_input=None):
"""Handle a flow initialized by the user."""
return await self.async_step_init(user_input)

async def async_step_init(self, user_input=None):
"""Handle a flow start."""
errors = {}
Expand Down
5 changes: 3 additions & 2 deletions homeassistant/components/hue/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

import voluptuous as vol

from homeassistant import data_entry_flow
from homeassistant import config_entries
from homeassistant.const import CONF_FILENAME, CONF_HOST
from homeassistant.helpers import aiohttp_client, config_validation as cv

Expand Down Expand Up @@ -108,7 +108,8 @@ async def async_setup(hass, config):
# deadlock: creating a config entry will set up the component but the
# setup would block till the entry is created!
hass.async_add_job(hass.config_entries.flow.async_init(
DOMAIN, source=data_entry_flow.SOURCE_IMPORT, data={
DOMAIN, context={'source': config_entries.SOURCE_IMPORT},
data={
'host': bridge_conf[CONF_HOST],
'path': bridge_conf[CONF_FILENAME],
}
Expand Down
3 changes: 2 additions & 1 deletion homeassistant/components/hue/bridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ async def async_setup(self, tries=0):
# linking procedure. When linking succeeds, it will remove the
# old config entry.
hass.async_add_job(hass.config_entries.flow.async_init(
DOMAIN, source='import', data={
DOMAIN, context={'source': config_entries.SOURCE_IMPORT},
data={
'host': host,
}
))
Expand Down
4 changes: 4 additions & 0 deletions homeassistant/components/hue/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ def __init__(self):
"""Initialize the Hue flow."""
self.host = None

async def async_step_user(self, user_input=None):
"""Handle a flow initialized by the user."""
return await self.async_step_init(user_input)

async def async_step_init(self, user_input=None):
"""Handle a flow start."""
from aiohue.discovery import discover_nupnp
Expand Down
4 changes: 3 additions & 1 deletion homeassistant/components/nest/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import voluptuous as vol

from homeassistant import config_entries
from homeassistant.const import (
CONF_STRUCTURE, CONF_FILENAME, CONF_BINARY_SENSORS, CONF_SENSORS,
CONF_MONITORED_CONDITIONS,
Expand Down Expand Up @@ -103,7 +104,8 @@ async def async_setup(hass, config):
access_token_cache_file = hass.config.path(filename)

hass.async_add_job(hass.config_entries.flow.async_init(
DOMAIN, source='import', data={
DOMAIN, context={'source': config_entries.SOURCE_IMPORT},
data={
'nest_conf_path': access_token_cache_file,
}
))
Expand Down
4 changes: 4 additions & 0 deletions homeassistant/components/nest/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ def __init__(self):
"""Initialize the Nest config flow."""
self.flow_impl = None

async def async_step_user(self, user_input=None):
"""Handle a flow initialized by the user."""
return await self.async_step_init(user_input)

async def async_step_init(self, user_input=None):
"""Handle a flow start."""
flows = self.hass.data.get(DATA_FLOW_IMPL, {})
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/sonos/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Component to embed Sonos."""
from homeassistant import data_entry_flow
from homeassistant import config_entries
from homeassistant.helpers import config_entry_flow


Expand All @@ -15,7 +15,7 @@ async def async_setup(hass, config):

if conf is not None:
hass.async_create_task(hass.config_entries.flow.async_init(
DOMAIN, source=data_entry_flow.SOURCE_IMPORT))
DOMAIN, context={'source': config_entries.SOURCE_IMPORT}))

return True

Expand Down
4 changes: 4 additions & 0 deletions homeassistant/components/zone/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ def __init__(self):
"""Initialize zone configuration flow."""
pass

async def async_step_user(self, user_input=None):
"""Handle a flow initialized by the user."""
return await self.async_step_init(user_input)

async def async_step_init(self, user_input=None):
"""Handle a flow start."""
errors = {}
Expand Down
48 changes: 34 additions & 14 deletions homeassistant/config_entries.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,24 @@
dependencies and install the requirements of the component.

At a minimum, each config flow will have to define a version number and the
'init' step.
'user' step.

@config_entries.HANDLERS.register(DOMAIN)
class ExampleConfigFlow(config_entries.FlowHandler):
class ExampleConfigFlow(data_entry_flow.FlowHandler):

VERSION = 1

async def async_step_init(self, user_input=None):
async def async_step_user(self, user_input=None):

The 'init' step is the first step of a flow and is called when a user
The 'user' step is the first step of a flow and is called when a user
starts a new flow. Each step has three different possible results: "Show Form",
"Abort" and "Create Entry".

> Note: prior 0.76, the default step is 'init' step, some config flows still
keep 'init' step to avoid break localization. All new config flow should use
'user' step.

### Show Form

This will show a form to the user to fill in. You define the current step,
Expand All @@ -50,7 +54,7 @@ async def async_step_init(self, user_input=None):
data_schema[vol.Required('password')] = str

return self.async_show_form(
step_id='init',
step_id='user',
title='Account Info',
data_schema=vol.Schema(data_schema)
)
Expand Down Expand Up @@ -97,10 +101,10 @@ async def async_step_init(self, user_input=None):
You might want to initialize a config flow programmatically. For example, if
we discover a device on the network that requires user interaction to finish
setup. To do so, pass a source parameter and optional user input to the init
step:
method:

await hass.config_entries.flow.async_init(
'hue', source='discovery', data=discovery_info)
'hue', context={'source': 'discovery'}, data=discovery_info)

The config flow handler will need to add a step to support the source. The step
should follow the same return values as a normal step.
Expand All @@ -123,6 +127,11 @@ async def async_step_discovery(info):


_LOGGER = logging.getLogger(__name__)

SOURCE_USER = 'user'
SOURCE_DISCOVERY = 'discovery'
SOURCE_IMPORT = 'import'

HANDLERS = Registry()
# Components that have config flows. In future we will auto-generate this list.
FLOWS = [
Expand Down Expand Up @@ -151,8 +160,8 @@ async def async_step_discovery(info):

DISCOVERY_NOTIFICATION_ID = 'config_entry_discovery'
DISCOVERY_SOURCES = (
data_entry_flow.SOURCE_DISCOVERY,
data_entry_flow.SOURCE_IMPORT,
SOURCE_DISCOVERY,
SOURCE_IMPORT,
)

EVENT_FLOW_DISCOVERED = 'config_entry_discovered'
Expand Down Expand Up @@ -374,12 +383,15 @@ async def _async_finish_flow(self, result):
if result['type'] != data_entry_flow.RESULT_TYPE_CREATE_ENTRY:
return None

source = result['source']
if source is None:
source = SOURCE_USER
entry = ConfigEntry(
version=result['version'],
domain=result['handler'],
title=result['title'],
data=result['data'],
source=result['source'],
source=source,
)
self._entries.append(entry)
await self._async_schedule_save()
Expand All @@ -399,17 +411,22 @@ async def _async_finish_flow(self, result):

return entry

async def _async_create_flow(self, handler, *, source, data):
async def _async_create_flow(self, handler_key, *, context, data):
"""Create a flow for specified handler.

Handler key is the domain of the component that we want to setup.
"""
component = getattr(self.hass.components, handler)
handler = HANDLERS.get(handler)
component = getattr(self.hass.components, handler_key)
handler = HANDLERS.get(handler_key)

if handler is None:
raise data_entry_flow.UnknownHandler

if context is not None:
source = context.get('source', SOURCE_USER)
else:
source = SOURCE_USER

# Make sure requirements and dependencies of component are resolved
await async_process_deps_reqs(
self.hass, self._hass_config, handler, component)
Expand All @@ -424,7 +441,10 @@ async def _async_create_flow(self, handler, *, source, data):
notification_id=DISCOVERY_NOTIFICATION_ID
)

return handler()
flow = handler()
flow.source = source
flow.init_step = source
return flow

async def _async_schedule_save(self):
"""Save the entity registry to a file."""
Expand Down
24 changes: 9 additions & 15 deletions homeassistant/data_entry_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@

_LOGGER = logging.getLogger(__name__)

SOURCE_USER = 'user'
SOURCE_DISCOVERY = 'discovery'
SOURCE_IMPORT = 'import'

RESULT_TYPE_FORM = 'form'
RESULT_TYPE_CREATE_ENTRY = 'create_entry'
RESULT_TYPE_ABORT = 'abort'
Expand Down Expand Up @@ -53,22 +49,17 @@ def async_progress(self) -> List[Dict]:
'source': flow.source,
} for flow in self._progress.values()]

async def async_init(self, handler: Callable, *, source: str = SOURCE_USER,
data: str = None) -> Any:
async def async_init(self, handler: Callable, *, context: Dict = None,
data: Any = None) -> Any:
"""Start a configuration flow."""
flow = await self._async_create_flow(handler, source=source, data=data)
flow = await self._async_create_flow(
handler, context=context, data=data)
flow.hass = self.hass
flow.handler = handler
flow.flow_id = uuid.uuid4().hex
flow.source = source
self._progress[flow.flow_id] = flow

if source == SOURCE_USER:
step = 'init'
else:
step = source

return await self._async_handle_step(flow, step, data)
return await self._async_handle_step(flow, flow.init_step, data)

async def async_configure(
self, flow_id: str, user_input: str = None) -> Any:
Expand Down Expand Up @@ -131,9 +122,12 @@ class FlowHandler:
flow_id = None
hass = None
handler = None
source = SOURCE_USER
source = None
cur_step = None

# Set by _async_create_flow callback
init_step = 'init'

# Set by developer
VERSION = 1

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/helpers/config_entry_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def __init__(self, domain, title, discovery_function):
self._title = title
self._discovery_function = discovery_function

async def async_step_init(self, user_input=None):
async def async_step_user(self, user_input=None):
"""Handle a flow initialized by the user."""
if self._async_current_entries():
return self.async_abort(
Expand Down
Loading