Skip to content

Commit

Permalink
Merge 27366aa into e161dc3
Browse files Browse the repository at this point in the history
  • Loading branch information
scop committed Nov 4, 2018
2 parents e161dc3 + 27366aa commit 1ef7850
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 26 deletions.
17 changes: 11 additions & 6 deletions homeassistant/helpers/dispatcher.py
@@ -1,22 +1,25 @@
"""Helpers for Home Assistant dispatcher & internal component/platform."""
import logging
from typing import Any, Callable

from homeassistant.core import callback
from homeassistant.loader import bind_hass
from homeassistant.util.async_ import run_callback_threadsafe
from .typing import HomeAssistantType


_LOGGER = logging.getLogger(__name__)
DATA_DISPATCHER = 'dispatcher'


@bind_hass
def dispatcher_connect(hass, signal, target):
def dispatcher_connect(hass: HomeAssistantType, signal: str,
target: Callable[..., None]) -> Callable[[], None]:
"""Connect a callable function to a signal."""
async_unsub = run_callback_threadsafe(
hass.loop, async_dispatcher_connect, hass, signal, target).result()

def remove_dispatcher():
def remove_dispatcher() -> None:
"""Remove signal listener."""
run_callback_threadsafe(hass.loop, async_unsub).result()

Expand All @@ -25,7 +28,8 @@ def remove_dispatcher():

@callback
@bind_hass
def async_dispatcher_connect(hass, signal, target):
def async_dispatcher_connect(hass: HomeAssistantType, signal: str,
target: Callable[..., Any]) -> Callable[[], None]:
"""Connect a callable function to a signal.
This method must be run in the event loop.
Expand All @@ -39,7 +43,7 @@ def async_dispatcher_connect(hass, signal, target):
hass.data[DATA_DISPATCHER][signal].append(target)

@callback
def async_remove_dispatcher():
def async_remove_dispatcher() -> None:
"""Remove signal listener."""
try:
hass.data[DATA_DISPATCHER][signal].remove(target)
Expand All @@ -53,14 +57,15 @@ def async_remove_dispatcher():


@bind_hass
def dispatcher_send(hass, signal, *args):
def dispatcher_send(hass: HomeAssistantType, signal: str, *args: Any) -> None:
"""Send signal and data."""
hass.loop.call_soon_threadsafe(async_dispatcher_send, hass, signal, *args)


@callback
@bind_hass
def async_dispatcher_send(hass, signal, *args):
def async_dispatcher_send(
hass: HomeAssistantType, signal: str, *args: Any) -> None:
"""Send signal and data.
This method must be run in the event loop.
Expand Down
13 changes: 7 additions & 6 deletions homeassistant/helpers/entity_values.py
Expand Up @@ -2,31 +2,32 @@
from collections import OrderedDict
import fnmatch
import re
from typing import Dict
from typing import Any, Dict, Optional, Pattern # noqa: F401

from homeassistant.core import split_entity_id


class EntityValues:
"""Class to store entity id based values."""

def __init__(self, exact: Dict = None, domain: Dict = None,
glob: Dict = None) -> None:
def __init__(self, exact: Optional[Dict] = None,
domain: Optional[Dict] = None,
glob: Optional[Dict] = None) -> None:
"""Initialize an EntityConfigDict."""
self._cache = {}
self._cache = {} # type: Dict[str, Dict]
self._exact = exact
self._domain = domain

if glob is None:
compiled = None
compiled = None # type: Optional[Dict[Pattern[str], Any]]
else:
compiled = OrderedDict()
for key, value in glob.items():
compiled[re.compile(fnmatch.translate(key))] = value

self._glob = compiled

def get(self, entity_id):
def get(self, entity_id: str) -> Dict:
"""Get config for an entity id."""
if entity_id in self._cache:
return self._cache[entity_id]
Expand Down
5 changes: 3 additions & 2 deletions homeassistant/helpers/signal.py
Expand Up @@ -2,6 +2,7 @@
import logging
import signal
import sys
from types import FrameType

from homeassistant.core import callback, HomeAssistant
from homeassistant.const import RESTART_EXIT_CODE
Expand All @@ -16,7 +17,7 @@ def async_register_signal_handling(hass: HomeAssistant) -> None:
"""Register system signal handler for core."""
if sys.platform != 'win32':
@callback
def async_signal_handle(exit_code):
def async_signal_handle(exit_code: int) -> None:
"""Wrap signal handling.
* queue call to shutdown task
Expand Down Expand Up @@ -49,7 +50,7 @@ def async_signal_handle(exit_code):
old_sigint = None

@callback
def async_signal_handle(exit_code, frame):
def async_signal_handle(exit_code: int, frame: FrameType) -> None:
"""Wrap signal handling.
* queue call to shutdown task
Expand Down
34 changes: 23 additions & 11 deletions homeassistant/helpers/sun.py
@@ -1,23 +1,28 @@
"""Helpers for sun events."""
import datetime
from typing import Optional, Union, TYPE_CHECKING

from homeassistant.const import SUN_EVENT_SUNRISE, SUN_EVENT_SUNSET
from homeassistant.core import callback
from homeassistant.util import dt as dt_util
from homeassistant.loader import bind_hass
from .typing import HomeAssistantType

if TYPE_CHECKING:
import astral # pylint: disable=unused-import

DATA_LOCATION_CACHE = 'astral_location_cache'


@callback
@bind_hass
def get_astral_location(hass):
def get_astral_location(hass: HomeAssistantType) -> 'astral.Location':
"""Get an astral location for the current Home Assistant configuration."""
from astral import Location

latitude = hass.config.latitude
longitude = hass.config.longitude
timezone = hass.config.time_zone.zone
timezone = str(hass.config.time_zone)
elevation = hass.config.elevation
info = ('', '', latitude, longitude, timezone, elevation)

Expand All @@ -33,9 +38,12 @@ def get_astral_location(hass):

@callback
@bind_hass
def get_astral_event_next(hass, event, utc_point_in_time=None, offset=None):
def get_astral_event_next(
hass: HomeAssistantType, event: str,
utc_point_in_time: Optional[datetime.datetime] = None,
offset: Optional[datetime.timedelta] = None) -> datetime.datetime:
"""Calculate the next specified solar event."""
import astral
from astral import AstralError

location = get_astral_location(hass)

Expand All @@ -51,19 +59,22 @@ def get_astral_event_next(hass, event, utc_point_in_time=None, offset=None):
next_dt = getattr(location, event)(
dt_util.as_local(utc_point_in_time).date() +
datetime.timedelta(days=mod),
local=False) + offset
local=False) + offset # type: datetime.datetime
if next_dt > utc_point_in_time:
return next_dt
except astral.AstralError:
except AstralError:
pass
mod += 1


@callback
@bind_hass
def get_astral_event_date(hass, event, date=None):
def get_astral_event_date(
hass: HomeAssistantType, event: str,
date: Union[datetime.date, datetime.datetime, None] = None) \
-> Optional[datetime.datetime]:
"""Calculate the astral event time for the specified date."""
import astral
from astral import AstralError

location = get_astral_location(hass)

Expand All @@ -74,15 +85,16 @@ def get_astral_event_date(hass, event, date=None):
date = dt_util.as_local(date).date()

try:
return getattr(location, event)(date, local=False)
except astral.AstralError:
return getattr(location, event)(date, local=False) # type: ignore
except AstralError:
# Event never occurs for specified date.
return None


@callback
@bind_hass
def is_up(hass, utc_point_in_time=None):
def is_up(hass: HomeAssistantType,
utc_point_in_time: Optional[datetime.datetime] = None) -> bool:
"""Calculate if the sun is currently up."""
if utc_point_in_time is None:
utc_point_in_time = dt_util.utcnow()
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Expand Up @@ -60,4 +60,4 @@ whitelist_externals=/bin/bash
deps =
-r{toxinidir}/requirements_test.txt
commands =
/bin/bash -c 'mypy homeassistant/*.py homeassistant/{auth,util}/ homeassistant/helpers/{icon,intent,json,location,state,translation,typing}.py'
/bin/bash -c 'mypy homeassistant/*.py homeassistant/{auth,util}/ homeassistant/helpers/{__init__,dispatcher,entity_values,icon,intent,json,location,signal,state,sun,temperature,translation,typing}.py'

0 comments on commit 1ef7850

Please sign in to comment.