Skip to content

Commit

Permalink
Bump HACS versions & migrate server
Browse files Browse the repository at this point in the history
  • Loading branch information
gerritjandebruin committed Feb 25, 2024
1 parent 1e94c0d commit 811ca0c
Show file tree
Hide file tree
Showing 2,310 changed files with 16,256 additions and 14,954 deletions.
2 changes: 1 addition & 1 deletion .HA_VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2024.2.1
2024.2.3
49 changes: 49 additions & 0 deletions automations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -987,3 +987,52 @@
- switch.desk_east
- switch.bike_socket
mode: single
- id: '1707682123353'
alias: Wekker GJ
description: ''
trigger:
- platform: template
value_template: '{% if has_value(''sensor.telefoon_gj_next_alarm'') %}
{{ (states(''sensor.telefoon_gj_next_alarm'') | as_datetime - now()).total_seconds()
< 30 }}
{% else %}
false
{% endif %}'
condition:
- condition: zone
entity_id: person.gerrit_jan
zone: zone.home
- condition: time
after: 04:00:00
before: '12:00:00'
enabled: true
action:
- service: light.turn_on
metadata: {}
data:
brightness_pct: 50
target:
entity_id: light.bedroom_1
mode: single
- id: '1708682164461'
alias: CPU bewaking
description: ''
trigger:
- platform: numeric_state
entity_id:
- sensor.system_monitor_processor_temperature
for:
hours: 0
minutes: 5
seconds: 0
above: 55
condition: []
action:
- service: hassio.host_shutdown
metadata: {}
data: {}
mode: single
57 changes: 33 additions & 24 deletions custom_components/hacs/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,13 @@ def list_downloaded(self) -> list[HacsRepository]:
"""Return a list of downloaded repositories."""
return [repo for repo in self._repositories if repo.data.installed]

def category_downloaded(self, category: HacsCategory) -> bool:
"""Check if a given category has been downloaded."""
for repository in self.list_downloaded:
if repository.data.category == category:
return True
return False

def register(self, repository: HacsRepository, default: bool = False) -> None:
"""Register a repository."""
repo_id = str(repository.data.id)
Expand Down Expand Up @@ -368,7 +375,7 @@ class HacsBase:
status = HacsStatus()
system = HacsSystem()
validation: ValidationManager | None = None
version: str | None = None
version: AwesomeVersion | None = None

@property
def integration_dir(self) -> pathlib.Path:
Expand Down Expand Up @@ -592,7 +599,7 @@ async def async_register_repository(
repository.data.id = repository_id

else:
if self.hass is not None and ((check and repository.data.new) or self.status.new):
if self.hass is not None and check and repository.data.new:
self.async_dispatch(
HacsDispatchEvent.REPOSITORY,
{
Expand Down Expand Up @@ -689,15 +696,23 @@ async def startup_tasks(self, _=None) -> None:

self.async_dispatch(HacsDispatchEvent.STATUS, {})

async def async_download_file(self, url: str, *, headers: dict | None = None) -> bytes | None:
async def async_download_file(
self,
url: str,
*,
headers: dict | None = None,
keep_url: bool = False,
nolog: bool = False,
**_,
) -> bytes | None:
"""Download files, and return the content."""
if url is None:
return None

if "tags/" in url:
if not keep_url and "tags/" in url:
url = url.replace("tags/", "")

self.log.debug("Downloading %s", url)
self.log.debug("Trying to download %s", url)
timeouts = 0

while timeouts < 5:
Expand Down Expand Up @@ -733,7 +748,8 @@ async def async_download_file(self, url: str, *, headers: dict | None = None) ->
except (
BaseException # lgtm [py/catch-base-exception] pylint: disable=broad-except
) as exception:
self.log.exception("Download failed - %s", exception)
if not nolog:
self.log.exception("Download failed - %s", exception)

return None

Expand Down Expand Up @@ -763,24 +779,24 @@ def set_active_categories(self) -> None:
for category in (HacsCategory.INTEGRATION, HacsCategory.PLUGIN):
self.enable_hacs_category(HacsCategory(category))

if self.configuration.experimental and self.core.ha_version >= "2023.4.0b0":
if self.configuration.experimental:
self.enable_hacs_category(HacsCategory.TEMPLATE)

if HacsCategory.PYTHON_SCRIPT in self.hass.config.components:
if (
HacsCategory.PYTHON_SCRIPT in self.hass.config.components
or self.repositories.category_downloaded(HacsCategory.PYTHON_SCRIPT)
):
self.enable_hacs_category(HacsCategory.PYTHON_SCRIPT)

if self.hass.services.has_service("frontend", "reload_themes"):
if self.hass.services.has_service(
"frontend", "reload_themes"
) or self.repositories.category_downloaded(HacsCategory.THEME):
self.enable_hacs_category(HacsCategory.THEME)

if self.configuration.appdaemon:
self.enable_hacs_category(HacsCategory.APPDAEMON)
if self.configuration.netdaemon:
downloaded_netdaemon = [
x
for x in self.repositories.list_downloaded
if x.data.category == HacsCategory.NETDAEMON
]
if len(downloaded_netdaemon) != 0:
if self.repositories.category_downloaded(HacsCategory.NETDAEMON):
self.log.warning(
"NetDaemon in HACS is deprectaded. It will stop working in the future. "
"Please remove all your current NetDaemon repositories from HACS "
Expand Down Expand Up @@ -871,15 +887,6 @@ async def async_get_category_repositories_experimental(self, category: str) -> N
repository.repository_manifest.update_data(
{**dict(HACS_MANIFEST_KEYS_TO_EXPORT), **manifest}
)
self.async_dispatch(
HacsDispatchEvent.REPOSITORY,
{
"id": 1337,
"action": "update",
"repository": repository.data.full_name,
"repository_id": repository.data.id,
},
)

if category == "integration":
self.status.inital_fetch_done = True
Expand All @@ -896,6 +903,8 @@ async def async_get_category_repositories_experimental(self, category: str) -> N
)
self.repositories.unregister(repository)

self.async_dispatch(HacsDispatchEvent.REPOSITORY, {})

async def async_get_category_repositories(self, category: HacsCategory) -> None:
"""Get repositories from category."""
if self.system.disabled:
Expand Down
117 changes: 70 additions & 47 deletions custom_components/hacs/config_flow.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
"""Adds config flow for HACS."""
from __future__ import annotations

import asyncio
from contextlib import suppress
from typing import TYPE_CHECKING

from aiogithubapi import GitHubDeviceAPI, GitHubException
from aiogithubapi import (
GitHubDeviceAPI,
GitHubException,
GitHubLoginDeviceModel,
GitHubLoginOauthModel,
)
from aiogithubapi.common.const import OAUTH_USER_LOGIN
from awesomeversion import AwesomeVersion
from homeassistant import config_entries
from homeassistant.config_entries import ConfigFlow, OptionsFlow
from homeassistant.const import __version__ as HAVERSION
from homeassistant.core import callback
from homeassistant.data_entry_flow import UnknownFlow
from homeassistant.helpers import aiohttp_client
from homeassistant.helpers.event import async_call_later
from homeassistant.loader import async_get_integration
import voluptuous as vol

Expand All @@ -33,23 +40,22 @@
from homeassistant.core import HomeAssistant


class HacsFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
class HacsFlowHandler(ConfigFlow, domain=DOMAIN):
"""Config flow for HACS."""

VERSION = 1

hass: HomeAssistant
activation_task: asyncio.Task | None = None
device: GitHubDeviceAPI | None = None

VERSION = 1
CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_POLL
_registration: GitHubLoginDeviceModel | None = None
_activation: GitHubLoginOauthModel | None = None
_reauth: bool = False

def __init__(self):
def __init__(self) -> None:
"""Initialize."""
self._errors = {}
self.device = None
self.activation = None
self.log = LOGGER
self._progress_task = None
self._login_device = None
self._reauth = False
self._user_input = {}

async def async_step_user(self, user_input):
Expand All @@ -72,45 +78,58 @@ async def async_step_user(self, user_input):
## Initial form
return await self._show_config_form(user_input)

@callback
def async_remove(self):
"""Cleanup."""
if self.activation_task and not self.activation_task.done():
self.activation_task.cancel()

async def async_step_device(self, _user_input):
"""Handle device steps"""
"""Handle device steps."""

async def _wait_for_activation(_=None):
if self._login_device is None or self._login_device.expires_in is None:
async_call_later(self.hass, 1, _wait_for_activation)
return
async def _wait_for_activation() -> None:
try:
response = await self.device.activation(device_code=self._registration.device_code)
self._activation = response.data
finally:

response = await self.device.activation(device_code=self._login_device.device_code)
self.activation = response.data
self.hass.async_create_task(
self.hass.config_entries.flow.async_configure(flow_id=self.flow_id)
)
async def _progress():
with suppress(UnknownFlow):
await self.hass.config_entries.flow.async_configure(flow_id=self.flow_id)

self.hass.async_create_task(_progress())

if not self.activation:
if not self.device:
integration = await async_get_integration(self.hass, DOMAIN)
if not self.device:
self.device = GitHubDeviceAPI(
client_id=CLIENT_ID,
session=aiohttp_client.async_get_clientsession(self.hass),
**{"client_name": f"HACS/{integration.version}"},
)
async_call_later(self.hass, 1, _wait_for_activation)
self.device = GitHubDeviceAPI(
client_id=CLIENT_ID,
session=aiohttp_client.async_get_clientsession(self.hass),
**{"client_name": f"HACS/{integration.version}"},
)
try:
response = await self.device.register()
self._login_device = response.data
return self.async_show_progress(
step_id="device",
progress_action="wait_for_device",
description_placeholders={
"url": OAUTH_USER_LOGIN,
"code": self._login_device.user_code,
},
)
self._registration = response.data
except GitHubException as exception:
self.log.error(exception)
return self.async_abort(reason="github")

return self.async_show_progress_done(next_step_id="device_done")
LOGGER.exception(exception)
return self.async_abort(reason="could_not_register")

if self.activation_task is None:
self.activation_task = self.hass.async_create_task(_wait_for_activation())

if self.activation_task.done():
if (exception := self.activation_task.exception()) is not None:
LOGGER.exception(exception)
return self.async_show_progress_done(next_step_id="could_not_register")
return self.async_show_progress_done(next_step_id="device_done")

return self.async_show_progress(
step_id="device",
progress_action="wait_for_device",
description_placeholders={
"url": OAUTH_USER_LOGIN,
"code": self._registration.user_code,
},
)

async def _show_config_form(self, user_input):
"""Show the configuration form to edit location data."""
Expand Down Expand Up @@ -146,21 +165,25 @@ async def async_step_device_done(self, user_input: dict[str, bool] | None = None
if self._reauth:
existing_entry = self.hass.config_entries.async_get_entry(self.context["entry_id"])
self.hass.config_entries.async_update_entry(
existing_entry, data={**existing_entry.data, "token": self.activation.access_token}
existing_entry, data={**existing_entry.data, "token": self._activation.access_token}
)
await self.hass.config_entries.async_reload(existing_entry.entry_id)
return self.async_abort(reason="reauth_successful")

return self.async_create_entry(
title="",
data={
"token": self.activation.access_token,
"token": self._activation.access_token,
},
options={
"experimental": self._user_input.get("experimental", False),
},
)

async def async_step_could_not_register(self, _user_input=None):
"""Handle issues that need transition await from progress step."""
return self.async_abort(reason="could_not_register")

async def async_step_reauth(self, _user_input=None):
"""Perform reauth upon an API authentication error."""
return await self.async_step_reauth_confirm()
Expand All @@ -181,7 +204,7 @@ def async_get_options_flow(config_entry):
return HacsOptionsFlowHandler(config_entry)


class HacsOptionsFlowHandler(config_entries.OptionsFlow):
class HacsOptionsFlowHandler(OptionsFlow):
"""HACS config flow options handler."""

def __init__(self, config_entry):
Expand Down
Loading

0 comments on commit 811ca0c

Please sign in to comment.