Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move all setup/startup tasks to new TaskManager #2165

Merged
merged 6 commits into from
Aug 25, 2021
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
1 change: 0 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ jobs:

- name: "Set version number"
run: |
sed -i '/INTEGRATION_VERSION = /c\INTEGRATION_VERSION = "${{ steps.version.outputs.version }}"' ${{ github.workspace }}/custom_components/hacs/const.py
python3 ${{ github.workspace }}/manage/update_manifest.py --version ${{ steps.version.outputs.version }}

# Pack the HACS dir as a zip and upload to the release
Expand Down
80 changes: 70 additions & 10 deletions custom_components/hacs/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,39 @@
from __future__ import annotations

import logging
import math
import pathlib
from dataclasses import asdict, dataclass, field
from typing import TYPE_CHECKING, Any

from aiogithubapi import GitHub, GitHubAPI
from aiogithubapi import (
GitHub,
GitHubAPI,
GitHubAuthenticationException,
GitHubRatelimitException,
)
from aiogithubapi.objects.repository import AIOGitHubAPIRepository
from aiohttp.client import ClientSession
from awesomeversion import AwesomeVersion
from homeassistant.core import HomeAssistant

from .const import INTEGRATION_VERSION
from .enums import ConfigurationType, HacsDisabledReason, HacsStage, LovelaceMode
from homeassistant.loader import Integration
from queueman.manager import QueueManager

from .enums import (
ConfigurationType,
HacsCategory,
HacsDisabledReason,
HacsStage,
LovelaceMode,
)
from .exceptions import HacsException
from .utils.logger import getLogger

if TYPE_CHECKING:
from .hacsbase.data import HacsData
from .helpers.classes.repository import HacsRepository
from .operational.factory import HacsTaskFactory
from .tasks.manager import HacsTaskManager


@dataclass
Expand Down Expand Up @@ -87,7 +103,7 @@ class HacsCore:
class HacsCommon:
"""Common for HACS."""

categories: list[str] = field(default_factory=list)
categories: set[str] = field(default_factory=set)
default: list[str] = field(default_factory=list)
installed: list[str] = field(default_factory=list)
renamed_repositories: dict[str, str] = field(default_factory=dict)
Expand All @@ -113,7 +129,6 @@ class HacsSystem:
disabled: bool = False
disabled_reason: str | None = None
running: bool = False
version = AwesomeVersion(INTEGRATION_VERSION)
stage = HacsStage.SETUP
action: bool = False

Expand All @@ -124,29 +139,45 @@ class HacsBase:
_repositories = []
_repositories_by_full_name = {}
_repositories_by_id = {}

common = HacsCommon()
configuration = HacsConfiguration()
core = HacsCore()
data = None
data: HacsData | None = None
data_repo: AIOGitHubAPIRepository | None = None
factory: HacsTaskFactory | None = None
frontend = HacsFrontend()
github: GitHub | None = None
githubapi: GitHubAPI | None = None
hass: HomeAssistant | None = None
integration: Integration | None = None
log: logging.Logger = getLogger()
queue: QueueManager | None = None
recuring_tasks = []
repositories: list[HacsRepository] = []
repository: AIOGitHubAPIRepository | None = None
session: ClientSession | None = None
stage = HacsStage.SETUP
stage: HacsStage | None = None
status = HacsStatus()
system = HacsSystem()
version: AwesomeVersion | None = None
tasks: HacsTaskManager | None = None
version: str | None = None

@property
def integration_dir(self) -> pathlib.Path:
"""Return the HACS integration dir."""
return pathlib.Path(__file__).parent
return self.integration.file_path

async def async_set_stage(self, stage: HacsStage | None) -> None:
"""Set HACS stage."""
if stage and self.stage == stage:
return

self.stage = stage
if stage is not None:
self.log.info("Stage changed: %s", self.stage)
self.hass.bus.async_fire("hacs/stage", {"stage": self.stage})
await self.tasks.async_execute_runtume_tasks()

def disable_hacs(self, reason: HacsDisabledReason) -> None:
"""Disable HACS."""
Expand All @@ -160,3 +191,32 @@ def enable_hacs(self) -> None:
self.system.disabled = False
self.system.disabled_reason = None
self.log.info("HACS is enabled")

def enable_hacs_category(self, category: HacsCategory):
"""Enable HACS category."""
if category not in self.common.categories:
self.log.info("Enable category: %s", category)
self.common.categories.add(category)

def disable_hacs_category(self, category: HacsCategory):
"""Disable HACS category."""
if category in self.common.categories:
self.log.info("Disabling category: %s", category)
self.common.categories.pop(category)

async def async_can_update(self) -> int:
"""Helper to calculate the number of repositories we can fetch data for."""
try:
result = await self.githubapi.rate_limit()
if ((limit := result.data.resources.core.remaining or 0) - 1000) >= 15:
return math.floor((limit - 1000) / 15)
except GitHubAuthenticationException as exception:
self.log.error("GitHub authentication failed - %s", exception)
self.disable_hacs(HacsDisabledReason.INVALID_TOKEN)
except GitHubRatelimitException as exception:
self.log.error("GitHub API ratelimited - %s", exception)
self.disable_hacs(HacsDisabledReason.RATE_LIMIT)
except BaseException as exception: # pylint: disable=broad-except
self.log.exception(exception)

return 0
11 changes: 4 additions & 7 deletions custom_components/hacs/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,9 @@
from homeassistant.core import callback
from homeassistant.helpers import aiohttp_client
from homeassistant.helpers.event import async_call_later
from homeassistant.loader import async_get_integration

from custom_components.hacs.const import (
CLIENT_ID,
DOMAIN,
INTEGRATION_VERSION,
MINIMUM_HA_VERSION,
)
from custom_components.hacs.const import CLIENT_ID, DOMAIN, MINIMUM_HA_VERSION
from custom_components.hacs.enums import ConfigurationType
from custom_components.hacs.helpers.functions.configuration_schema import (
RELEASE_LIMIT,
Expand Down Expand Up @@ -72,11 +68,12 @@ async def _wait_for_activation(_=None):
)

if not self.activation:
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}"},
**{"client_name": f"HACS/{integration.version}"},
)
async_call_later(self.hass, 1, _wait_for_activation)
try:
Expand Down
22 changes: 3 additions & 19 deletions custom_components/hacs/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,17 @@

NAME_LONG = "HACS (Home Assistant Community Store)"
NAME_SHORT = "HACS"
INTEGRATION_VERSION = "main"
DOMAIN = "hacs"
CLIENT_ID = "395a8e669c5de9f7c6e8"
MINIMUM_HA_VERSION = "2021.2.0"
PROJECT_URL = "https://github.com/hacs/integration/"
CUSTOM_UPDATER_LOCATIONS = [
"{}/custom_components/custom_updater.py",
"{}/custom_components/custom_updater/__init__.py",
]


ISSUE_URL = f"{PROJECT_URL}issues"
DOMAIN_DATA = f"{NAME_SHORT.lower()}_data"

ELEMENT_TYPES = ["integration", "plugin"]

PACKAGE_NAME = "custom_components.hacs"

HACS_GITHUB_API_HEADERS = {
"User-Agent": f"HACS/{INTEGRATION_VERSION}",
"Accept": ACCEPT_HEADERS["preview"],
}

HACS_ACTION_GITHUB_API_HEADERS = {
"User-Agent": "HACS/action",
"Accept": ACCEPT_HEADERS["preview"],
Expand All @@ -44,16 +33,11 @@
# Messages
NO_ELEMENTS = "No elements to show, open the store to install some awesome stuff."

CUSTOM_UPDATER_WARNING = """
This cannot be used with custom_updater.
To use this you need to remove custom_updater form {}
"""

STARTUP = f"""
STARTUP = """
-------------------------------------------------------------------
HACS (Home Assistant Community Store)

Version: {INTEGRATION_VERSION}
Version: {version}
This is a custom integration
If you have any issues with this you need to open an issue here:
https://github.com/hacs/integration/issues
Expand Down
10 changes: 10 additions & 0 deletions custom_components/hacs/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ class LovelaceMode(str, Enum):
YAML = "yaml"


class HacsTaskType(str, Enum):
"""HacsTaskType"""

RUNTIME = "runtime"
EVENT = "event"
SCHEDULE = "schedule"
MANUAL = "manual"
BASE = "base"


class HacsStage(str, Enum):
SETUP = "setup"
STARTUP = "startup"
Expand Down
3 changes: 1 addition & 2 deletions custom_components/hacs/hacsbase/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

from homeassistant.core import callback

from custom_components.hacs.const import INTEGRATION_VERSION
from custom_components.hacs.helpers.classes.manifest import HacsManifest
from custom_components.hacs.helpers.functions.register_repository import (
register_repository,
Expand Down Expand Up @@ -207,7 +206,7 @@ def async_restore_repository(self, entry, repository_data):
repository.status.first_install = False

if repository_data["full_name"] == "hacs/integration":
repository.data.installed_version = INTEGRATION_VERSION
repository.data.installed_version = self.hacs.version
repository.data.installed = True

return True
24 changes: 4 additions & 20 deletions custom_components/hacs/hacsbase/hacs.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,20 @@
from custom_components.hacs.helpers.functions.register_repository import (
register_repository,
)
from custom_components.hacs.helpers.functions.remaining_github_calls import (
get_fetch_updates_for,
)

from custom_components.hacs.helpers.functions.store import (
async_load_from_store,
async_save_to_store,
)
from custom_components.hacs.operational.setup_actions.categories import (
async_setup_extra_stores,
)
from custom_components.hacs.share import (
get_factory,
get_queue,
get_removed,
is_removed,
list_removed_repositories,
)

from ..base import HacsBase
from ..enums import HacsCategory, HacsStage
from ..share import get_factory, get_queue


class Hacs(HacsBase, HacsHelpers):
Expand Down Expand Up @@ -121,7 +115,6 @@ async def startup_tasks(self, _event=None):
"""Tasks that are started after startup."""
await self.async_set_stage(HacsStage.STARTUP)
self.status.background_task = True
await async_setup_extra_stores()
self.hass.bus.async_fire("hacs/status", {})

await self.handle_critical_repositories_startup()
Expand Down Expand Up @@ -241,15 +234,13 @@ async def prosess_queue(self, _notarealarg=None):
self.log.debug("Queue is already running")
return

can_update = await get_fetch_updates_for(self.githubapi)
can_update = await self.async_can_update()
self.log.debug(
"Can update %s repositories, items in queue %s",
can_update,
self.queue.pending_tasks,
)
if can_update == 0:
self.log.info("HACS is ratelimited, repository updates will resume later.")
else:
if can_update != 0:
self.status.background_task = True
self.hass.bus.async_fire("hacs/status", {})
try:
Expand Down Expand Up @@ -283,7 +274,6 @@ async def recurring_tasks_installed(self, _notarealarg=None):
async def recurring_tasks_all(self, _notarealarg=None):
"""Recurring tasks for all repositories."""
self.log.debug("Starting recurring background task for all repositories")
await async_setup_extra_stores()
self.status.background_task = True
self.hass.bus.async_fire("hacs/status", {})

Expand Down Expand Up @@ -351,9 +341,3 @@ async def async_get_category_repositories(self, category: HacsCategory):
continue
continue
self.queue.add(self.factory.safe_register(repo, category))

async def async_set_stage(self, stage: str) -> None:
"""Set the stage of HACS."""
self.stage = HacsStage(stage)
self.log.info("Stage changed: %s", self.stage)
self.hass.bus.async_fire("hacs/stage", {"stage": self.stage})
43 changes: 0 additions & 43 deletions custom_components/hacs/helpers/functions/constrains.py

This file was deleted.

Loading