Skip to content
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
8 changes: 8 additions & 0 deletions homeassistant_api/_async/asyncclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,14 @@ async def async_get_domains(self) -> Tuple[Domain, ...]:
)
return tuple(services)

async def async_get_domain(self, domain_id: str) -> Optional[Domain]:
"""Fetchers all services under a particular domain."""
domains = await self.async_get_domains()
for domain in domains:
if domain.domain_id == domain_id:
return domain
return None

async def async_trigger_service(
self,
domain: str,
Expand Down
22 changes: 15 additions & 7 deletions homeassistant_api/_async/models/domains.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@

from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple, cast

from pydantic import BaseModel, Field
from pydantic import Field, validator

from ...models import State
from ...models.domains import ServiceField
from ...models import ServiceField, State, base

if TYPE_CHECKING:
from homeassistant_api import Client


class AsyncDomain(BaseModel):
class AsyncDomain(base.BaseModel):
"""A class representing the domain that services belong to."""

domain_id: str
Expand All @@ -30,7 +29,7 @@ def add_service(self, service_id: str, **data) -> None:
}
)

def get_service(self, service_id: str):
def get_service(self, service_id: str) -> Optional["AsyncService"]:
"""Return a Service with the given service_id, returns None if no such service exists"""
return self.services.get(service_id)

Expand All @@ -43,16 +42,25 @@ def __getattr__(self, attr: str):
return super().__getattribute__(attr)


class AsyncService(BaseModel):
class AsyncService(base.BaseModel):
"""Class representing services from homeassistant"""

service_id: str
domain: AsyncDomain
domain: AsyncDomain = Field(exlude=True, repr=False)
name: Optional[str] = None
description: Optional[str] = None
fields: Optional[Dict[str, ServiceField]] = None
target: Optional[Dict[str, dict]] = None

@classmethod
@validator("domain")
def validate_domain(cls, domain: AsyncDomain) -> AsyncDomain:
"""
Explicitly do nothing to validate the parent domain.
Elimintates recursive validation errors.
"""
return domain

async def async_trigger(self, **service_data) -> Tuple[State, ...]:
"""Triggers the service associated with this object."""
data = await self.domain.client.async_trigger_service(
Expand Down
2 changes: 1 addition & 1 deletion homeassistant_api/_async/models/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class AsyncEntity(BaseModel):

slug: str
state: State
group: AsyncGroup
group: AsyncGroup = Field(exclude=True, repr=False)

async def async_get_state(self) -> State:
"""Asks Home Assistant for the state of the entity and sets it locally"""
Expand Down
6 changes: 5 additions & 1 deletion homeassistant_api/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""The Model objects for the entire library."""
from .base import BaseModel
from .domains import Domain, Service
from .domains import Domain, Service, ServiceField
from .entity import Entity, Group
from .events import Event
from .history import History
Expand All @@ -10,6 +10,10 @@
__all__ = (
"Domain",
"Service",
"BaseModel",
"Domain",
"Service",
"ServiceField",
"Entity",
"Group",
"Event",
Expand Down
15 changes: 12 additions & 3 deletions homeassistant_api/models/domains.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""File for Service and Domain data models"""
from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple

from pydantic import Field
from pydantic import Field, validator

from .base import BaseModel
from .states import State
Expand Down Expand Up @@ -29,7 +29,7 @@ def add_service(self, service_id: str, **data) -> None:
}
)

def get_service(self, service_id: str):
def get_service(self, service_id: str) -> Optional["Service"]:
"""Return a Service with the given service_id, returns None if no such service exists"""
return self.services.get(service_id)

Expand All @@ -56,12 +56,21 @@ class Service(BaseModel):
"""Model representing services from homeassistant"""

service_id: str
domain: Domain
domain: Domain = Field(exlucde=True, repr=False)
name: Optional[str] = None
description: Optional[str] = None
fields: Optional[Dict[str, ServiceField]] = None
target: Optional[Dict[str, dict]] = None

@classmethod
@validator("domain")
def validate_domain(cls, domain: Domain) -> Domain:
"""
Explicitly do nothing to validate the parent domain.
Elimintates recursive validation errors.
"""
return domain

def trigger(self, **service_data) -> Tuple[State, ...]:
"""Triggers the service associated with this object."""
return self.domain.client.trigger_service(
Expand Down
76 changes: 38 additions & 38 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ version = "3.0.3.post5"
[tool.poetry.dependencies]
aiohttp = "^3.8.1"
aiohttp-client-cache = "^0.6.1"
pydantic = "^1.9.0"
pydantic = "<=1.9.0"
python = "^3.8"
requests = "^2.26.0"
requests-cache = "^0.9.2"
Expand Down