Pep257 fixes for core.
parent
473d6b1d05
commit
d9b30d1421
|
@ -1,6 +1,5 @@
|
|||
"""
|
||||
homeassistant
|
||||
~~~~~~~~~~~~~
|
||||
Core components of Home Assistant.
|
||||
|
||||
Home Assistant is a Home Automation framework for observing the state
|
||||
of entities and react to changes.
|
||||
|
@ -53,9 +52,10 @@ _MockHA = namedtuple("MockHomeAssistant", ['bus'])
|
|||
|
||||
|
||||
class HomeAssistant(object):
|
||||
""" Core class to route all communication to right components. """
|
||||
"""Root object of the Home Assistant home automation."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize new Home Assistant object."""
|
||||
self.pool = pool = create_worker_pool()
|
||||
self.bus = EventBus(pool)
|
||||
self.services = ServiceRegistry(self.bus, pool)
|
||||
|
@ -63,7 +63,7 @@ class HomeAssistant(object):
|
|||
self.config = Config()
|
||||
|
||||
def start(self):
|
||||
""" Start home assistant. """
|
||||
"""Start home assistant."""
|
||||
_LOGGER.info(
|
||||
"Starting Home Assistant (%d threads)", self.pool.worker_count)
|
||||
|
||||
|
@ -71,12 +71,11 @@ class HomeAssistant(object):
|
|||
self.bus.fire(EVENT_HOMEASSISTANT_START)
|
||||
|
||||
def block_till_stopped(self):
|
||||
""" Will register service homeassistant/stop and
|
||||
will block until called. """
|
||||
"""Register service homeassistant/stop and will block until called."""
|
||||
request_shutdown = threading.Event()
|
||||
|
||||
def stop_homeassistant(*args):
|
||||
""" Stops Home Assistant. """
|
||||
"""Stop Home Assistant."""
|
||||
request_shutdown.set()
|
||||
|
||||
self.services.register(
|
||||
|
@ -98,7 +97,7 @@ class HomeAssistant(object):
|
|||
self.stop()
|
||||
|
||||
def stop(self):
|
||||
""" Stops Home Assistant and shuts down all threads. """
|
||||
"""Stop Home Assistant and shuts down all threads."""
|
||||
_LOGGER.info("Stopping")
|
||||
|
||||
self.bus.fire(EVENT_HOMEASSISTANT_STOP)
|
||||
|
@ -150,8 +149,7 @@ class HomeAssistant(object):
|
|||
|
||||
|
||||
class JobPriority(util.OrderedEnum):
|
||||
""" Provides priorities for bus events. """
|
||||
# pylint: disable=no-init,too-few-public-methods
|
||||
"""Provides job priorities for event bus jobs."""
|
||||
|
||||
EVENT_CALLBACK = 0
|
||||
EVENT_SERVICE = 1
|
||||
|
@ -161,7 +159,7 @@ class JobPriority(util.OrderedEnum):
|
|||
|
||||
@staticmethod
|
||||
def from_event_type(event_type):
|
||||
""" Returns a priority based on event type. """
|
||||
"""Return a priority based on event type."""
|
||||
if event_type == EVENT_TIME_CHANGED:
|
||||
return JobPriority.EVENT_TIME
|
||||
elif event_type == EVENT_STATE_CHANGED:
|
||||
|
@ -175,8 +173,7 @@ class JobPriority(util.OrderedEnum):
|
|||
|
||||
|
||||
class EventOrigin(enum.Enum):
|
||||
""" Distinguish between origin of event. """
|
||||
# pylint: disable=no-init,too-few-public-methods
|
||||
"""Represents origin of an event."""
|
||||
|
||||
local = "LOCAL"
|
||||
remote = "REMOTE"
|
||||
|
@ -185,14 +182,15 @@ class EventOrigin(enum.Enum):
|
|||
return self.value
|
||||
|
||||
|
||||
# pylint: disable=too-few-public-methods
|
||||
class Event(object):
|
||||
""" Represents an event within the Bus. """
|
||||
# pylint: disable=too-few-public-methods
|
||||
"""Represents an event within the Bus."""
|
||||
|
||||
__slots__ = ['event_type', 'data', 'origin', 'time_fired']
|
||||
|
||||
def __init__(self, event_type, data=None, origin=EventOrigin.local,
|
||||
time_fired=None):
|
||||
"""Initialize a new event."""
|
||||
self.event_type = event_type
|
||||
self.data = data or {}
|
||||
self.origin = origin
|
||||
|
@ -200,7 +198,7 @@ class Event(object):
|
|||
time_fired or dt_util.utcnow())
|
||||
|
||||
def as_dict(self):
|
||||
""" Returns a dict representation of this Event. """
|
||||
"""Create a dict representation of this Event."""
|
||||
return {
|
||||
'event_type': self.event_type,
|
||||
'data': dict(self.data),
|
||||
|
@ -227,26 +225,23 @@ class Event(object):
|
|||
|
||||
|
||||
class EventBus(object):
|
||||
""" Class that allows different components to communicate via services
|
||||
and events.
|
||||
"""
|
||||
"""Allows firing of and listening for events."""
|
||||
|
||||
def __init__(self, pool=None):
|
||||
"""Initialize a new event bus."""
|
||||
self._listeners = {}
|
||||
self._lock = threading.Lock()
|
||||
self._pool = pool or create_worker_pool()
|
||||
|
||||
@property
|
||||
def listeners(self):
|
||||
""" Dict with events that is being listened for and the number
|
||||
of listeners.
|
||||
"""
|
||||
"""Dict with events and the number of listeners."""
|
||||
with self._lock:
|
||||
return {key: len(self._listeners[key])
|
||||
for key in self._listeners}
|
||||
|
||||
def fire(self, event_type, event_data=None, origin=EventOrigin.local):
|
||||
""" Fire an event. """
|
||||
"""Fire an event."""
|
||||
if not self._pool.running:
|
||||
raise HomeAssistantError('Home Assistant has shut down.')
|
||||
|
||||
|
@ -271,7 +266,7 @@ class EventBus(object):
|
|||
self._pool.add_job(job_priority, (func, event))
|
||||
|
||||
def listen(self, event_type, listener):
|
||||
""" Listen for all events or events of a specific type.
|
||||
"""Listen for all events or events of a specific type.
|
||||
|
||||
To listen to all events specify the constant ``MATCH_ALL``
|
||||
as event_type.
|
||||
|
@ -283,7 +278,7 @@ class EventBus(object):
|
|||
self._listeners[event_type] = [listener]
|
||||
|
||||
def listen_once(self, event_type, listener):
|
||||
""" Listen once for event of a specific type.
|
||||
"""Listen once for event of a specific type.
|
||||
|
||||
To listen to all events specify the constant ``MATCH_ALL``
|
||||
as event_type.
|
||||
|
@ -292,7 +287,7 @@ class EventBus(object):
|
|||
"""
|
||||
@ft.wraps(listener)
|
||||
def onetime_listener(event):
|
||||
""" Removes listener from eventbus and then fires listener. """
|
||||
"""Remove listener from eventbus and then fires listener."""
|
||||
if hasattr(onetime_listener, 'run'):
|
||||
return
|
||||
# Set variable so that we will never run twice.
|
||||
|
@ -311,7 +306,7 @@ class EventBus(object):
|
|||
return onetime_listener
|
||||
|
||||
def remove_listener(self, event_type, listener):
|
||||
""" Removes a listener of a specific event_type. """
|
||||
"""Remove a listener of a specific event_type."""
|
||||
with self._lock:
|
||||
try:
|
||||
self._listeners[event_type].remove(listener)
|
||||
|
@ -343,6 +338,7 @@ class State(object):
|
|||
# pylint: disable=too-many-arguments
|
||||
def __init__(self, entity_id, state, attributes=None, last_changed=None,
|
||||
last_updated=None):
|
||||
"""Initialize a new state."""
|
||||
if not ENTITY_ID_PATTERN.match(entity_id):
|
||||
raise InvalidEntityFormatError((
|
||||
"Invalid entity id encountered: {}. "
|
||||
|
@ -363,31 +359,33 @@ class State(object):
|
|||
|
||||
@property
|
||||
def domain(self):
|
||||
""" Returns domain of this state. """
|
||||
"""Domain of this state."""
|
||||
return util.split_entity_id(self.entity_id)[0]
|
||||
|
||||
@property
|
||||
def object_id(self):
|
||||
""" Returns object_id of this state. """
|
||||
"""Object id of this state."""
|
||||
return util.split_entity_id(self.entity_id)[1]
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
""" Name to represent this state. """
|
||||
"""Name of this state."""
|
||||
return (
|
||||
self.attributes.get(ATTR_FRIENDLY_NAME) or
|
||||
self.object_id.replace('_', ' '))
|
||||
|
||||
def copy(self):
|
||||
""" Creates a copy of itself. """
|
||||
"""Return a copy of the state."""
|
||||
return State(self.entity_id, self.state,
|
||||
dict(self.attributes), self.last_changed,
|
||||
self.last_updated)
|
||||
|
||||
def as_dict(self):
|
||||
""" Converts State to a dict to be used within JSON.
|
||||
Ensures: state == State.from_dict(state.as_dict()) """
|
||||
"""Return a dict representation of the State.
|
||||
|
||||
To be used for JSON serialization.
|
||||
Ensures: state == State.from_dict(state.as_dict())
|
||||
"""
|
||||
return {'entity_id': self.entity_id,
|
||||
'state': self.state,
|
||||
'attributes': self.attributes,
|
||||
|
@ -396,11 +394,11 @@ class State(object):
|
|||
|
||||
@classmethod
|
||||
def from_dict(cls, json_dict):
|
||||
""" Static method to create a state from a dict.
|
||||
Ensures: state == State.from_json_dict(state.to_json_dict()) """
|
||||
"""Initialize a state from a dict.
|
||||
|
||||
if not (json_dict and
|
||||
'entity_id' in json_dict and
|
||||
Ensures: state == State.from_json_dict(state.to_json_dict())
|
||||
"""
|
||||
if not (json_dict and 'entity_id' in json_dict and
|
||||
'state' in json_dict):
|
||||
return None
|
||||
|
||||
|
@ -433,15 +431,16 @@ class State(object):
|
|||
|
||||
|
||||
class StateMachine(object):
|
||||
""" Helper class that tracks the state of different entities. """
|
||||
"""Helper class that tracks the state of different entities."""
|
||||
|
||||
def __init__(self, bus):
|
||||
"""Initialize state machine."""
|
||||
self._states = {}
|
||||
self._bus = bus
|
||||
self._lock = threading.Lock()
|
||||
|
||||
def entity_ids(self, domain_filter=None):
|
||||
""" List of entity ids that are being tracked. """
|
||||
"""List of entity ids that are being tracked."""
|
||||
if domain_filter is None:
|
||||
return list(self._states.keys())
|
||||
|
||||
|
@ -451,35 +450,36 @@ class StateMachine(object):
|
|||
if state.domain == domain_filter]
|
||||
|
||||
def all(self):
|
||||
""" Returns a list of all states. """
|
||||
"""Create a list of all states."""
|
||||
with self._lock:
|
||||
return [state.copy() for state in self._states.values()]
|
||||
|
||||
def get(self, entity_id):
|
||||
""" Returns the state of the specified entity. """
|
||||
"""Retrieve state of entity_id or None if not found."""
|
||||
state = self._states.get(entity_id.lower())
|
||||
|
||||
# Make a copy so people won't mutate the state
|
||||
return state.copy() if state else None
|
||||
|
||||
def is_state(self, entity_id, state):
|
||||
""" Returns True if entity exists and is specified state. """
|
||||
"""Test if entity exists and is specified state."""
|
||||
entity_id = entity_id.lower()
|
||||
|
||||
return (entity_id in self._states and
|
||||
self._states[entity_id].state == state)
|
||||
|
||||
def remove(self, entity_id):
|
||||
""" Removes an entity from the state machine.
|
||||
"""Remove the state of an entity.
|
||||
|
||||
Returns boolean to indicate if an entity was removed. """
|
||||
Returns boolean to indicate if an entity was removed.
|
||||
"""
|
||||
entity_id = entity_id.lower()
|
||||
|
||||
with self._lock:
|
||||
return self._states.pop(entity_id, None) is not None
|
||||
|
||||
def set(self, entity_id, new_state, attributes=None):
|
||||
""" Set the state of an entity, add entity if it does not exist.
|
||||
"""Set the state of an entity, add entity if it does not exist.
|
||||
|
||||
Attributes is an optional dict to specify attributes of this state.
|
||||
|
||||
|
@ -514,9 +514,7 @@ class StateMachine(object):
|
|||
self._bus.fire(EVENT_STATE_CHANGED, event_data)
|
||||
|
||||
def track_change(self, entity_ids, action, from_state=None, to_state=None):
|
||||
"""
|
||||
DEPRECATED AS OF 8/4/2015
|
||||
"""
|
||||
"""DEPRECATED AS OF 8/4/2015."""
|
||||
_LOGGER.warning(
|
||||
'hass.states.track_change is deprecated. '
|
||||
'Use homeassistant.helpers.event.track_state_change instead.')
|
||||
|
@ -527,33 +525,36 @@ class StateMachine(object):
|
|||
|
||||
# pylint: disable=too-few-public-methods
|
||||
class Service(object):
|
||||
""" Represents a service. """
|
||||
"""Represents a callable service."""
|
||||
|
||||
__slots__ = ['func', 'description', 'fields']
|
||||
|
||||
def __init__(self, func, description, fields):
|
||||
"""Initialize a service."""
|
||||
self.func = func
|
||||
self.description = description or ''
|
||||
self.fields = fields or {}
|
||||
|
||||
def as_dict(self):
|
||||
""" Return dictionary representation of this service. """
|
||||
"""Return dictionary representation of this service."""
|
||||
return {
|
||||
'description': self.description,
|
||||
'fields': self.fields,
|
||||
}
|
||||
|
||||
def __call__(self, call):
|
||||
"""Execute the service."""
|
||||
self.func(call)
|
||||
|
||||
|
||||
# pylint: disable=too-few-public-methods
|
||||
class ServiceCall(object):
|
||||
""" Represents a call to a service. """
|
||||
"""Represents a call to a service."""
|
||||
|
||||
__slots__ = ['domain', 'service', 'data']
|
||||
|
||||
def __init__(self, domain, service, data=None):
|
||||
"""Initialize a service call."""
|
||||
self.domain = domain
|
||||
self.service = service
|
||||
self.data = data or {}
|
||||
|
@ -567,9 +568,10 @@ class ServiceCall(object):
|
|||
|
||||
|
||||
class ServiceRegistry(object):
|
||||
""" Offers services over the eventbus. """
|
||||
"""Offers services over the eventbus."""
|
||||
|
||||
def __init__(self, bus, pool=None):
|
||||
"""Initialize a service registry."""
|
||||
self._services = {}
|
||||
self._lock = threading.Lock()
|
||||
self._pool = pool or create_worker_pool()
|
||||
|
@ -579,14 +581,14 @@ class ServiceRegistry(object):
|
|||
|
||||
@property
|
||||
def services(self):
|
||||
""" Dict with per domain a list of available services. """
|
||||
"""Dict with per domain a list of available services."""
|
||||
with self._lock:
|
||||
return {domain: {key: value.as_dict() for key, value
|
||||
in self._services[domain].items()}
|
||||
for domain in self._services}
|
||||
|
||||
def has_service(self, domain, service):
|
||||
""" Returns True if specified service exists. """
|
||||
"""Test if specified service exists."""
|
||||
return service in self._services.get(domain, [])
|
||||
|
||||
def register(self, domain, service, service_func, description=None):
|
||||
|
@ -611,7 +613,8 @@ class ServiceRegistry(object):
|
|||
|
||||
def call(self, domain, service, service_data=None, blocking=False):
|
||||
"""
|
||||
Calls specified service.
|
||||
Call a service.
|
||||
|
||||
Specify blocking=True to wait till service is executed.
|
||||
Waits a maximum of SERVICE_CALL_LIMIT.
|
||||
|
||||
|
@ -635,10 +638,7 @@ class ServiceRegistry(object):
|
|||
executed_event = threading.Event()
|
||||
|
||||
def service_executed(call):
|
||||
"""
|
||||
Called when a service is executed.
|
||||
Will set the event if matches our service call.
|
||||
"""
|
||||
"""Callback method that is called when service is executed."""
|
||||
if call.data[ATTR_SERVICE_CALL_ID] == call_id:
|
||||
executed_event.set()
|
||||
|
||||
|
@ -653,7 +653,7 @@ class ServiceRegistry(object):
|
|||
return success
|
||||
|
||||
def _event_to_service_call(self, event):
|
||||
""" Calls a service from an event. """
|
||||
"""Callback for SERVICE_CALLED events from the event bus."""
|
||||
service_data = dict(event.data)
|
||||
domain = service_data.pop(ATTR_DOMAIN, None)
|
||||
service = service_data.pop(ATTR_SERVICE, None)
|
||||
|
@ -670,7 +670,7 @@ class ServiceRegistry(object):
|
|||
(service_handler, service_call)))
|
||||
|
||||
def _execute_service(self, service_and_call):
|
||||
""" Executes a service and fires a SERVICE_EXECUTED event. """
|
||||
"""Execute a service and fires a SERVICE_EXECUTED event."""
|
||||
service, call = service_and_call
|
||||
service(call)
|
||||
|
||||
|
@ -680,16 +680,17 @@ class ServiceRegistry(object):
|
|||
{ATTR_SERVICE_CALL_ID: call.data[ATTR_SERVICE_CALL_ID]})
|
||||
|
||||
def _generate_unique_id(self):
|
||||
""" Generates a unique service call id. """
|
||||
"""Generate a unique service call id."""
|
||||
self._cur_id += 1
|
||||
return "{}-{}".format(id(self), self._cur_id)
|
||||
|
||||
|
||||
class Config(object):
|
||||
""" Configuration settings for Home Assistant. """
|
||||
"""Configuration settings for Home Assistant."""
|
||||
|
||||
# pylint: disable=too-many-instance-attributes
|
||||
def __init__(self):
|
||||
"""Initialize a new config object."""
|
||||
self.latitude = None
|
||||
self.longitude = None
|
||||
self.temperature_unit = None
|
||||
|
@ -709,15 +710,15 @@ class Config(object):
|
|||
self.config_dir = get_default_config_dir()
|
||||
|
||||
def distance(self, lat, lon):
|
||||
""" Calculate distance from Home Assistant in meters. """
|
||||
"""Calculate distance from Home Assistant in meters."""
|
||||
return location.distance(self.latitude, self.longitude, lat, lon)
|
||||
|
||||
def path(self, *path):
|
||||
""" Returns path to the file within the config dir. """
|
||||
"""Generate path to the file within the config dir."""
|
||||
return os.path.join(self.config_dir, *path)
|
||||
|
||||
def temperature(self, value, unit):
|
||||
""" Converts temperature to user preferred unit if set. """
|
||||
"""Convert temperature to user preferred unit if set."""
|
||||
if not (unit in (TEMP_CELCIUS, TEMP_FAHRENHEIT) and
|
||||
self.temperature_unit and unit != self.temperature_unit):
|
||||
return value, unit
|
||||
|
@ -732,7 +733,7 @@ class Config(object):
|
|||
self.temperature_unit)
|
||||
|
||||
def as_dict(self):
|
||||
""" Converts config to a dictionary. """
|
||||
"""Create a dict representation of this dict."""
|
||||
time_zone = self.time_zone or dt_util.UTC
|
||||
|
||||
return {
|
||||
|
@ -747,7 +748,7 @@ class Config(object):
|
|||
|
||||
|
||||
def create_timer(hass, interval=TIMER_INTERVAL):
|
||||
""" Creates a timer. Timer will start on HOMEASSISTANT_START. """
|
||||
"""Create a timer that will start on HOMEASSISTANT_START."""
|
||||
# We want to be able to fire every time a minute starts (seconds=0).
|
||||
# We want this so other modules can use that to make sure they fire
|
||||
# every minute.
|
||||
|
@ -810,12 +811,12 @@ def create_timer(hass, interval=TIMER_INTERVAL):
|
|||
|
||||
|
||||
def create_worker_pool(worker_count=None):
|
||||
""" Creates a worker pool to be used. """
|
||||
"""Create a worker pool."""
|
||||
if worker_count is None:
|
||||
worker_count = MIN_WORKER_THREAD
|
||||
|
||||
def job_handler(job):
|
||||
""" Called whenever a job is available to do. """
|
||||
"""Called whenever a job is available to do."""
|
||||
try:
|
||||
func, arg = job
|
||||
func(arg)
|
||||
|
@ -825,8 +826,7 @@ def create_worker_pool(worker_count=None):
|
|||
_LOGGER.exception("BusHandler:Exception doing job")
|
||||
|
||||
def busy_callback(worker_count, current_jobs, pending_jobs_count):
|
||||
""" Callback to be called when the pool queue gets too big. """
|
||||
|
||||
"""Callback to be called when the pool queue gets too big."""
|
||||
_LOGGER.warning(
|
||||
"WorkerPool:All %d threads are busy and %d jobs pending",
|
||||
worker_count, pending_jobs_count)
|
||||
|
|
Loading…
Reference in New Issue