1 """Config flow for GitHub integration."""
3 from __future__
import annotations
6 from typing
import TYPE_CHECKING, Any
8 from aiogithubapi
import (
12 GitHubLoginDeviceModel,
13 GitHubLoginOauthModel,
15 from aiogithubapi.const
import OAUTH_USER_LOGIN
16 import voluptuous
as vol
28 async_get_clientsession,
32 from .const
import CLIENT_ID, CONF_REPOSITORIES, DEFAULT_REPOSITORIES, DOMAIN, LOGGER
36 """Return a list of repositories that the user owns or has starred."""
40 async
def _get_starred_repositories() -> None:
41 response = await client.user.starred(params={
"per_page": 100})
42 if not response.is_last_page:
43 results = await asyncio.gather(
46 params={
"per_page": 100,
"page": page_number},
48 for page_number
in range(
49 response.next_page_number, response.last_page_number + 1
53 for result
in results:
54 response.data.extend(result.data)
56 repositories.update(response.data)
58 async
def _get_personal_repositories() -> None:
59 response = await client.user.repos(params={
"per_page": 100})
60 if not response.is_last_page:
61 results = await asyncio.gather(
64 params={
"per_page": 100,
"page": page_number},
66 for page_number
in range(
67 response.next_page_number, response.last_page_number + 1
71 for result
in results:
72 response.data.extend(result.data)
74 repositories.update(response.data)
79 _get_starred_repositories(),
80 _get_personal_repositories(),
84 except GitHubException:
85 return DEFAULT_REPOSITORIES
87 if len(repositories) == 0:
88 return DEFAULT_REPOSITORIES
91 (repo.full_name
for repo
in repositories),
97 """Handle a config flow for GitHub."""
101 login_task: asyncio.Task |
None =
None
105 self.
_device_device: GitHubDeviceAPI |
None =
None
106 self.
_login_login: GitHubLoginOauthModel |
None =
None
107 self.
_login_device_login_device: GitHubLoginDeviceModel |
None =
None
111 user_input: dict[str, Any] |
None =
None,
112 ) -> ConfigFlowResult:
113 """Handle the initial step."""
121 user_input: dict[str, Any] |
None =
None,
122 ) -> ConfigFlowResult:
123 """Handle device steps."""
125 async
def _wait_for_login() -> None:
128 assert self.
_device_device
is not None
131 response = await self.
_device_device.activation(
140 client_name=SERVER_SOFTWARE,
146 except GitHubException
as exception:
147 LOGGER.exception(exception)
151 self.
login_tasklogin_task = self.hass.async_create_task(_wait_for_login())
164 progress_action=
"wait_for_device",
165 description_placeholders={
166 "url": OAUTH_USER_LOGIN,
174 user_input: dict[str, Any] |
None =
None,
175 ) -> ConfigFlowResult:
176 """Handle repositories step."""
180 assert self.
_login_login
is not None
185 step_id=
"repositories",
186 data_schema=vol.Schema(
188 vol.Required(CONF_REPOSITORIES): cv.multi_select(
189 {k: k
for k
in repositories}
197 data={CONF_ACCESS_TOKEN: self.
_login_login.access_token},
198 options={CONF_REPOSITORIES: user_input[CONF_REPOSITORIES]},
203 user_input: dict[str, Any] |
None =
None,
204 ) -> ConfigFlowResult:
205 """Handle issues that need transition await from progress step."""
211 config_entry: ConfigEntry,
212 ) -> OptionsFlowHandler:
213 """Get the options flow for this handler."""
218 """Handle a option flow for GitHub."""
222 user_input: dict[str, Any] |
None =
None,
223 ) -> ConfigFlowResult:
224 """Handle options flow."""
234 for repository
in configured_repositories:
235 if repository
not in repositories:
236 repositories.append(repository)
240 data_schema=vol.Schema(
244 default=configured_repositories,
245 ): cv.multi_select({k: k
for k
in repositories}),
ConfigFlowResult async_step_could_not_register(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_repositories(self, dict[str, Any]|None user_input=None)
OptionsFlowHandler async_get_options_flow(ConfigEntry config_entry)
ConfigFlowResult async_step_device(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_init(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_create_entry(self, *str title, Mapping[str, Any] data, str|None description=None, Mapping[str, str]|None description_placeholders=None, Mapping[str, Any]|None options=None)
list[ConfigEntry] _async_current_entries(self, bool|None include_ignore=None)
ConfigFlowResult async_abort(self, *str reason, Mapping[str, str]|None description_placeholders=None)
ConfigFlowResult async_show_form(self, *str|None step_id=None, vol.Schema|None data_schema=None, dict[str, str]|None errors=None, Mapping[str, str]|None description_placeholders=None, bool|None last_step=None, str|None preview=None)
ConfigEntry config_entry(self)
None config_entry(self, ConfigEntry value)
_FlowResultT async_show_form(self, *str|None step_id=None, vol.Schema|None data_schema=None, dict[str, str]|None errors=None, Mapping[str, str]|None description_placeholders=None, bool|None last_step=None, str|None preview=None)
_FlowResultT async_show_progress(self, *str|None step_id=None, str progress_action, Mapping[str, str]|None description_placeholders=None, asyncio.Task[Any]|None progress_task=None)
_FlowResultT async_show_progress_done(self, *str next_step_id)
_FlowResultT async_create_entry(self, *str|None title=None, Mapping[str, Any] data, str|None description=None, Mapping[str, str]|None description_placeholders=None)
_FlowResultT async_abort(self, *str reason, Mapping[str, str]|None description_placeholders=None)
list[str] get_repositories(HomeAssistant hass, str access_token)
def register(HomeAssistant hass, Heos controller)
aiohttp.ClientSession async_get_clientsession(HomeAssistant hass, bool verify_ssl=True, socket.AddressFamily family=socket.AF_UNSPEC, ssl_util.SSLCipherList ssl_cipher=ssl_util.SSLCipherList.PYTHON_DEFAULT)