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 handling of default repositories to HacsRepositories #2348

Merged
merged 1 commit into from
Dec 19, 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
47 changes: 37 additions & 10 deletions custom_components/hacs/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
GitHub,
GitHubAPI,
GitHubAuthenticationException,
GitHubRatelimitException,
GitHubNotModifiedException,
GitHubException,
GitHubNotModifiedException,
GitHubRatelimitException,
)
from aiogithubapi.objects.repository import AIOGitHubAPIRepository
from aiohttp.client import ClientSession
Expand Down Expand Up @@ -101,8 +101,6 @@ class HacsCommon:
"""Common for HACS."""

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)
archived_repositories: list[str] = field(default_factory=list)
skip: list[str] = field(default_factory=list)
Expand Down Expand Up @@ -138,6 +136,7 @@ def disabled(self) -> bool:
class HacsRepositories:
"""HACS Repositories."""

_default_repositories: set[HacsRepository] = field(default_factory=set)
_repositories: list[str] = field(default_factory=list)
_repositories_by_full_name: dict[str, str] = field(default_factory=dict)
_repositories_by_id: dict[str, str] = field(default_factory=dict)
Expand All @@ -152,7 +151,7 @@ def list_downloaded(self) -> list[HacsRepository]:
"""Return a list of downloaded repositories."""
return [repo for repo in self._repositories if repo.data.installed]

def register(self, repository: HacsRepository) -> None:
def register(self, repository: HacsRepository, default: bool = False) -> None:
"""Register a repository."""
repo_id = str(repository.data.id)

Expand All @@ -162,10 +161,15 @@ def register(self, repository: HacsRepository) -> None:
if self.is_registered(repository_id=repo_id):
return

self._repositories.append(repository)
if repository not in self._repositories:
self._repositories.append(repository)

self._repositories_by_id[repo_id] = repository
self._repositories_by_full_name[repository.data.full_name_lower] = repository

if default:
self.mark_default(repository)

def unregister(self, repository: HacsRepository) -> None:
"""Unregister a repository."""
repo_id = str(repository.data.id)
Expand All @@ -176,9 +180,32 @@ def unregister(self, repository: HacsRepository) -> None:
if not self.is_registered(repository_id=repo_id):
return

self._repositories.remove(repository)
del self._repositories_by_id[repo_id]
del self._repositories_by_full_name[repository.data.full_name_lower]
if self.is_default(repo_id):
self._default_repositories.remove(repo_id)

if repository in self._repositories:
self._repositories.remove(repository)

self._repositories_by_id.pop(repo_id, None)
self._repositories_by_full_name.pop(repository.data.full_name_lower, None)

def mark_default(self, repository: HacsRepository) -> None:
"""Mark a repository as default."""
repo_id = str(repository.data.id)

if repo_id == "0":
return

if not self.is_registered(repository_id=repo_id):
return

self._default_repositories.add(repo_id)

def is_default(self, repository_id: str | None = None) -> bool:
"""Check if a repository is default."""
if not repository_id:
return False
return repository_id in self._default_repositories

def is_registered(
self,
Expand All @@ -198,7 +225,7 @@ def get_by_id(self, repository_id: str | None) -> HacsRepository | None:
return None
return self._repositories_by_id.get(str(repository_id))

def get_by_full_name(self, repository_full_name: str) -> HacsRepository | None:
def get_by_full_name(self, repository_full_name: str | None) -> HacsRepository | None:
"""Get repository by full name."""
if not repository_full_name:
return None
Expand Down
1 change: 1 addition & 0 deletions custom_components/hacs/const.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Constants for HACS"""
from typing import TypeVar

from aiogithubapi.common.const import ACCEPT_HEADERS

NAME_LONG = "HACS (Home Assistant Community Store)"
Expand Down
7 changes: 2 additions & 5 deletions custom_components/hacs/hacsbase/hacs.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,9 +282,6 @@ async def async_get_category_repositories(self, category: HacsCategory):
continue
repository = self.repositories.get_by_full_name(repo)
if repository is not None:
if str(repository.data.id) not in self.common.default:
self.common.default.append(str(repository.data.id))
else:
continue
self.repositories.mark_default(repository)
continue
self.queue.add(self.factory.safe_register(repo, category))
self.queue.add(self.factory.safe_register(repo=repo, category=category, default=True))
9 changes: 2 additions & 7 deletions custom_components/hacs/helpers/classes/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,11 +386,8 @@ def remove(self):
"""Run remove tasks."""
self.logger.info("%s Starting removal", self)

if self.data.id in self.hacs.common.installed:
self.hacs.common.installed.remove(self.data.id)
for repository in self.hacs.repositories.list_all:
if repository.data.id == self.data.id:
self.hacs.repositories.unregister(repository)
if self.hacs.repositories.is_registered(repository_id=str(self.data.id)):
self.hacs.repositories.unregister(self)

async def uninstall(self):
"""Run uninstall tasks."""
Expand All @@ -408,8 +405,6 @@ async def uninstall(self):
await self.hacs.hass.services.async_call("frontend", "reload_themes", {})
except (Exception, BaseException): # pylint: disable=broad-except
pass
if self.data.full_name in self.hacs.common.installed:
self.hacs.common.installed.remove(self.data.full_name)

await async_remove_store(self.hacs.hass, f"hacs/{self.data.id}.hacs")

Expand Down
11 changes: 9 additions & 2 deletions custom_components/hacs/helpers/functions/register_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,14 @@
from ..classes.repository import HacsRepository

# @concurrent(15, 5)
async def register_repository(full_name, category, check=True, ref=None, repo_id=None):
async def register_repository(
full_name,
category,
check=True,
ref=None,
repo_id=None,
default=False,
):
"""Register a repository."""
hacs = get_hacs()

Expand Down Expand Up @@ -72,4 +79,4 @@ async def register_repository(full_name, category, check=True, ref=None, repo_id
"repository_id": repository.data.id,
},
)
hacs.repositories.register(repository)
hacs.repositories.register(repository, default)
1 change: 0 additions & 1 deletion custom_components/hacs/helpers/functions/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

from ...const import VERSION_STORAGE
from ...exceptions import HacsException

from ...utils.logger import getLogger

_LOGGER = getLogger()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ async def common_update_data(repository: HacsRepository, ignore_issues=False, fo
hacs.common.renamed_repositories[
repository.data.full_name
] = repository_object.full_name
if str(repository_object.id) not in hacs.common.default:
hacs.common.default.append(str(repository_object.id))
raise HacsRepositoryExistException
repository.data.update_data(repository_object.attributes)
repository.data.etag_repository = etag
Expand Down
3 changes: 0 additions & 3 deletions custom_components/hacs/helpers/methods/installation.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,6 @@ async def async_install_repository(repository):
await hacs.hass.async_add_executor_job(persistent_directory.cleanup)

if repository.validate.success:
if repository.data.full_name not in repository.hacs.common.installed:
if repository.data.full_name == "hacs/integration":
repository.hacs.common.installed.append(repository.data.full_name)
repository.data.installed = True
repository.data.installed_commit = repository.data.last_commit

Expand Down
2 changes: 0 additions & 2 deletions custom_components/hacs/helpers/properties/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@
from custom_components.hacs.helpers.properties.can_be_installed import (
RepositoryPropertyCanBeInstalled,
)
from custom_components.hacs.helpers.properties.custom import RepositoryPropertyCustom
from custom_components.hacs.helpers.properties.pending_update import (
RepositoryPropertyPendingUpdate,
)


class RepositoryHelperProperties(
RepositoryPropertyPendingUpdate,
RepositoryPropertyCustom,
RepositoryPropertyCanBeInstalled,
):
pass
13 changes: 0 additions & 13 deletions custom_components/hacs/helpers/properties/custom.py

This file was deleted.

4 changes: 2 additions & 2 deletions custom_components/hacs/operational/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ async def safe_update(self, repository):
# Due to GitHub ratelimits we need to sleep a bit
await asyncio.sleep(sleeper)

async def safe_register(self, repo, category):
async def safe_register(self, repo, category, default=False):
async with max_concurrent_tasks:
try:
await register_repository(repo, category)
await register_repository(full_name=repo, category=category, default=default)
except (AIOGitHubAPIException, HacsException) as exception:
_LOGGER.error("%s - %s", repo, exception)

Expand Down
3 changes: 2 additions & 1 deletion custom_components/hacs/tasks/load_hacs_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,15 @@ async def async_execute(self) -> None:
try:
repository = self.hacs.repositories.get_by_full_name("hacs/integration")
if repository is None:
await register_repository("hacs/integration", "integration")
await register_repository("hacs/integration", "integration", default=True)
repository = self.hacs.repositories.get_by_full_name("hacs/integration")
if repository is None:
raise HacsException("Unknown error")
repository.data.installed = True
repository.data.installed_version = self.hacs.integration.version
repository.data.new = False
self.hacs.repository = repository.repository_object
self.hacs.repositories.mark_default(repository)
except HacsException as exception:
if "403" in f"{exception}":
self.task_logger(
Expand Down
2 changes: 1 addition & 1 deletion custom_components/hacs/tasks/setup_websocket_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ async def hacs_repositories(_hass, connection, msg):
"category": repo.data.category,
"config_flow": repo.data.config_flow,
"country": repo.data.country,
"custom": repo.custom,
"custom": not hacs.repositories.is_default(str(repo.data.id)),
"default_branch": repo.data.default_branch,
"description": repo.data.description,
"domain": repo.data.domain,
Expand Down
7 changes: 6 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@
from homeassistant.runner import HassEventLoopPolicy
import pytest

from custom_components.hacs.base import HacsCommon, HacsCore, HacsRepositories, HacsSystem
from custom_components.hacs.base import (
HacsCommon,
HacsCore,
HacsRepositories,
HacsSystem,
)
from custom_components.hacs.const import DOMAIN
from custom_components.hacs.hacsbase.hacs import Hacs
from custom_components.hacs.helpers.classes.repository import HacsRepository
Expand Down
2 changes: 1 addition & 1 deletion tests/hacsbase/test_hacs.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# pylint: disable=missing-module-docstring, missing-function-docstring
import pytest
from custom_components.hacs.base import HacsRepositories

from custom_components.hacs.base import HacsRepositories
from custom_components.hacs.enums import HacsStage


Expand Down
2 changes: 1 addition & 1 deletion tests/hacsbase/test_hacsbase_data.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Data Test Suite."""
import pytest
from custom_components.hacs.base import HacsRepositories

from custom_components.hacs.base import HacsRepositories
from custom_components.hacs.hacsbase.data import HacsData

from tests.async_mock import patch
Expand Down
19 changes: 0 additions & 19 deletions tests/repositories/helpers/test_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,6 @@ def test_repository_helpers_properties_can_be_installed():
assert repository.can_be_installed


def test_repository_helpers_properties_custom():
repository = HacsRepository()

repository.data.full_name = "test/test"
repository.data.full_name_lower = "test/test"
assert repository.custom

repository.data.id = 1337
repository.hacs.common.default.append(str(repository.data.id))
assert not repository.custom

repository.hacs.common.default = []
assert repository.custom

repository.data.full_name = "hacs/integration"
repository.data.full_name_lower = "hacs/integration"
assert not repository.custom


def test_repository_helpers_properties_pending_update():
repository = HacsRepository()
repository.hacs.core.ha_version = "0.109.0"
Expand Down
1 change: 0 additions & 1 deletion tests/repositories/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ def test_hacs_repository_core_mostly_defaults():
repository.data.description = "Awesome GitHub repository"

assert repository.display_name == "Repository"
assert repository.custom
assert repository.display_status == "new"
assert repository.display_status_description == "This is a newly added repository."
assert repository.main_action == "INSTALL"
Expand Down