netdaemon.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. """Class for netdaemon apps in HACS."""
  2. from __future__ import annotations
  3. from typing import TYPE_CHECKING
  4. from ..enums import HacsCategory, HacsDispatchEvent
  5. from ..exceptions import HacsException
  6. from ..utils import filters
  7. from ..utils.decorator import concurrent
  8. from .base import HacsRepository
  9. if TYPE_CHECKING:
  10. from ..base import HacsBase
  11. class HacsNetdaemonRepository(HacsRepository):
  12. """Netdaemon apps in HACS."""
  13. def __init__(self, hacs: HacsBase, full_name: str):
  14. """Initialize."""
  15. super().__init__(hacs=hacs)
  16. self.data.full_name = full_name
  17. self.data.full_name_lower = full_name.lower()
  18. self.data.category = HacsCategory.NETDAEMON
  19. self.content.path.local = self.localpath
  20. self.content.path.remote = "apps"
  21. @property
  22. def localpath(self):
  23. """Return localpath."""
  24. return f"{self.hacs.core.config_path}/netdaemon/apps/{self.data.name}"
  25. async def validate_repository(self):
  26. """Validate."""
  27. await self.common_validate()
  28. # Custom step 1: Validate content.
  29. if self.repository_manifest:
  30. if self.repository_manifest.content_in_root:
  31. self.content.path.remote = ""
  32. if self.content.path.remote == "apps":
  33. self.data.domain = filters.get_first_directory_in_directory(
  34. self.tree, self.content.path.remote
  35. )
  36. self.content.path.remote = f"apps/{self.data.name}"
  37. compliant = False
  38. for treefile in self.treefiles:
  39. if treefile.startswith(f"{self.content.path.remote}") and treefile.endswith(".cs"):
  40. compliant = True
  41. break
  42. if not compliant:
  43. raise HacsException(
  44. f"{self.string} Repository structure for {self.ref.replace('tags/','')} is not compliant"
  45. )
  46. # Handle potential errors
  47. if self.validate.errors:
  48. for error in self.validate.errors:
  49. if not self.hacs.status.startup:
  50. self.logger.error("%s %s", self.string, error)
  51. return self.validate.success
  52. @concurrent(concurrenttasks=10, backoff_time=5)
  53. async def update_repository(self, ignore_issues=False, force=False):
  54. """Update."""
  55. if not await self.common_update(ignore_issues, force) and not force:
  56. return
  57. # Get appdaemon objects.
  58. if self.repository_manifest:
  59. if self.repository_manifest.content_in_root:
  60. self.content.path.remote = ""
  61. if self.content.path.remote == "apps":
  62. self.data.domain = filters.get_first_directory_in_directory(
  63. self.tree, self.content.path.remote
  64. )
  65. self.content.path.remote = f"apps/{self.data.name}"
  66. # Set local path
  67. self.content.path.local = self.localpath
  68. # Signal entities to refresh
  69. if self.data.installed:
  70. self.hacs.async_dispatch(
  71. HacsDispatchEvent.REPOSITORY,
  72. {
  73. "id": 1337,
  74. "action": "update",
  75. "repository": self.data.full_name,
  76. "repository_id": self.data.id,
  77. },
  78. )
  79. async def async_post_installation(self):
  80. """Run post installation steps."""
  81. try:
  82. await self.hacs.hass.services.async_call(
  83. "hassio", "addon_restart", {"addon": "c6a2317c_netdaemon"}
  84. )
  85. except BaseException: # lgtm [py/catch-base-exception] pylint: disable=broad-except
  86. pass