From 876978d64a026d9c4f0427758e1d42fdc2569426 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Mon, 7 Mar 2016 23:20:48 +0100 Subject: [PATCH 1/3] Fix PEP257 issues --- homeassistant/util/__init__.py | 84 ++++++++++++++++++------------- homeassistant/util/dt.py | 47 ++++++++--------- homeassistant/util/package.py | 14 ++---- homeassistant/util/temperature.py | 10 ++-- homeassistant/util/yaml.py | 11 ++-- 5 files changed, 82 insertions(+), 84 deletions(-) diff --git a/homeassistant/util/__init__.py b/homeassistant/util/__init__.py index ca89226846e..c19f08b6a79 100644 --- a/homeassistant/util/__init__.py +++ b/homeassistant/util/__init__.py @@ -1,9 +1,4 @@ -""" -homeassistant.util -~~~~~~~~~~~~~~~~~~ - -Helper methods for various modules. -""" +"""Helper methods for various modules.""" import collections from itertools import chain import threading @@ -25,24 +20,24 @@ RE_SLUGIFY = re.compile(r'[^a-z0-9_]+') def sanitize_filename(filename): - """ Sanitizes a filename by removing .. / and \\. """ + r"""Sanitize a filename by removing .. / and \\.""" return RE_SANITIZE_FILENAME.sub("", filename) def sanitize_path(path): - """ Sanitizes a path by removing ~ and .. """ + """Sanitize a path by removing ~ and ..""" return RE_SANITIZE_PATH.sub("", path) def slugify(text): - """ Slugifies a given text. """ + """Slugify a given text.""" text = text.lower().replace(" ", "_") return RE_SLUGIFY.sub("", text) def repr_helper(inp): - """ Helps creating a more readable string representation of objects. """ + """Help creating a more readable string representation of objects.""" if isinstance(inp, (dict, MappingProxyType)): return ", ".join( repr_helper(key)+"="+repr_helper(item) for key, item @@ -54,7 +49,7 @@ def repr_helper(inp): def convert(value, to_type, default=None): - """ Converts value to to_type, returns default if fails. """ + """Convert value to to_type, returns default if fails.""" try: return default if value is None else to_type(value) except (ValueError, TypeError): @@ -63,8 +58,10 @@ def convert(value, to_type, default=None): def ensure_unique_string(preferred_string, current_strings): - """ Returns a string that is not present in current_strings. - If preferred string exists will append _2, _3, .. """ + """Return a string that is not present in current_strings. + + If preferred string exists will append _2, _3, .. + """ test_string = preferred_string current_strings = set(current_strings) @@ -79,7 +76,7 @@ def ensure_unique_string(preferred_string, current_strings): # Taken from: http://stackoverflow.com/a/11735897 def get_local_ip(): - """ Tries to determine the local IP address of the machine. """ + """Try to determine the local IP address of the machine.""" try: sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) @@ -95,7 +92,7 @@ def get_local_ip(): # Taken from http://stackoverflow.com/a/23728630 def get_random_string(length=10): - """ Returns a random string with letters and digits. """ + """Return a random string with letters and digits.""" generator = random.SystemRandom() source_chars = string.ascii_letters + string.digits @@ -103,34 +100,39 @@ def get_random_string(length=10): class OrderedEnum(enum.Enum): - """ Taken from Python 3.4.0 docs. """ - # pylint: disable=no-init, too-few-public-methods + """Taken from Python 3.4.0 docs.""" + # pylint: disable=no-init, too-few-public-methods def __ge__(self, other): + """Return the greater than element.""" if self.__class__ is other.__class__: return self.value >= other.value return NotImplemented def __gt__(self, other): + """Return the greater element.""" if self.__class__ is other.__class__: return self.value > other.value return NotImplemented def __le__(self, other): + """Return the lower than element.""" if self.__class__ is other.__class__: return self.value <= other.value return NotImplemented def __lt__(self, other): + """Return the lower element.""" if self.__class__ is other.__class__: return self.value < other.value return NotImplemented class OrderedSet(collections.MutableSet): - """ Ordered set taken from http://code.activestate.com/recipes/576694/ """ + """Ordered set taken from http://code.activestate.com/recipes/576694/.""" def __init__(self, iterable=None): + """Initialize the set.""" self.end = end = [] end += [None, end, end] # sentinel node for doubly linked list self.map = {} # key --> [key, prev, next] @@ -138,20 +140,22 @@ class OrderedSet(collections.MutableSet): self |= iterable def __len__(self): + """Return the length of the set.""" return len(self.map) def __contains__(self, key): + """Check if key is in set.""" return key in self.map def add(self, key): - """ Add an element to the end of the set. """ + """Add an element to the end of the set.""" if key not in self.map: end = self.end curr = end[1] curr[2] = end[1] = self.map[key] = [key, curr, end] def promote(self, key): - """ Promote element to beginning of the set, add if not there. """ + """Promote element to beginning of the set, add if not there.""" if key in self.map: self.discard(key) @@ -160,13 +164,14 @@ class OrderedSet(collections.MutableSet): curr[2] = begin[1] = self.map[key] = [key, curr, begin] def discard(self, key): - """ Discard an element from the set. """ + """Discard an element from the set.""" if key in self.map: key, prev_item, next_item = self.map.pop(key) prev_item[2] = next_item next_item[1] = prev_item def __iter__(self): + """Iteration of the set.""" end = self.end curr = end[2] while curr is not end: @@ -174,6 +179,7 @@ class OrderedSet(collections.MutableSet): curr = curr[2] def __reversed__(self): + """reverse the ordering.""" end = self.end curr = end[1] while curr is not end: @@ -181,8 +187,8 @@ class OrderedSet(collections.MutableSet): curr = curr[1] def pop(self, last=True): # pylint: disable=arguments-differ - """ - Pops element of the end of the set. + """Pop element of the end of the set. + Set last=False to pop from the beginning. """ if not self: @@ -192,24 +198,27 @@ class OrderedSet(collections.MutableSet): return key def update(self, *args): - """ Add elements from args to the set. """ + """Add elements from args to the set.""" for item in chain(*args): self.add(item) def __repr__(self): + """Return the representation.""" if not self: return '%s()' % (self.__class__.__name__,) return '%s(%r)' % (self.__class__.__name__, list(self)) def __eq__(self, other): + """Return the comparision.""" if isinstance(other, OrderedSet): return len(self) == len(other) and list(self) == list(other) return set(self) == set(other) class Throttle(object): - """ - A method decorator to add a cooldown to a method to prevent it from being + """A class for throttling the execution of tasks. + + This method decorator adds a cooldown to a method to prevent it from being called more then 1 time within the timedelta interval `min_time` after it returned its result. @@ -223,13 +232,15 @@ class Throttle(object): Adds a datetime attribute `last_call` to the method. """ - # pylint: disable=too-few-public-methods + # pylint: disable=too-few-public-methods def __init__(self, min_time, limit_no_throttle=None): + """Initialize the throttle.""" self.min_time = min_time self.limit_no_throttle = limit_no_throttle def __call__(self, method): + """Caller for the throttle.""" if self.limit_no_throttle is not None: method = Throttle(self.limit_no_throttle)(method) @@ -248,8 +259,8 @@ class Throttle(object): @wraps(method) def wrapper(*args, **kwargs): - """ - Wrapper that allows wrapped to be called only once per min_time. + """Wrapper that allows wrapped to be called only once per min_time. + If we cannot acquire the lock, it is running so return None. """ # pylint: disable=protected-access @@ -288,10 +299,11 @@ class Throttle(object): class ThreadPool(object): """A priority queue-based thread pool.""" - # pylint: disable=too-many-instance-attributes + # pylint: disable=too-many-instance-attributes def __init__(self, job_handler, worker_count=0, busy_callback=None): - """ + """Initialize the pool. + job_handler: method to be called from worker thread to handle job worker_count: number of threads to run that handle jobs busy_callback: method to be called when queue gets too big. @@ -338,18 +350,18 @@ class ThreadPool(object): self.busy_warning_limit = self.worker_count * 3 def add_job(self, priority, job): - """ Add a job to the queue. """ + """Add a job to the queue.""" with self._lock: if not self.running: raise RuntimeError("ThreadPool not running") self._work_queue.put(PriorityQueueItem(priority, job)) - # check if our queue is getting too big + # Check if our queue is getting too big. if self._work_queue.qsize() > self.busy_warning_limit \ and self._busy_callback is not None: - # Increase limit we will issue next warning + # Increase limit we will issue next warning. self.busy_warning_limit *= 2 self._busy_callback( @@ -404,12 +416,14 @@ class ThreadPool(object): class PriorityQueueItem(object): - """ Holds a priority and a value. Used within PriorityQueue. """ + """Holds a priority and a value. Used within PriorityQueue.""" # pylint: disable=too-few-public-methods def __init__(self, priority, item): + """Initialize the queue.""" self.priority = priority self.item = item def __lt__(self, other): + """Return the ordering.""" return self.priority < other.priority diff --git a/homeassistant/util/dt.py b/homeassistant/util/dt.py index 604777399ec..ff4fd6e13bd 100644 --- a/homeassistant/util/dt.py +++ b/homeassistant/util/dt.py @@ -1,10 +1,4 @@ -""" -homeassistant.util.dt -~~~~~~~~~~~~~~~~~~~~~ - -Provides helper methods to handle the time in HA. - -""" +"""Provides helper methods to handle the time in HA.""" import datetime as dt import pytz @@ -16,7 +10,7 @@ UTC = DEFAULT_TIME_ZONE = pytz.utc def set_default_time_zone(time_zone): - """ Sets a default time zone to be used when none is specified. """ + """Set a default time zone to be used when none is specified.""" global DEFAULT_TIME_ZONE # pylint: disable=global-statement assert isinstance(time_zone, dt.tzinfo) @@ -25,7 +19,7 @@ def set_default_time_zone(time_zone): def get_time_zone(time_zone_str): - """ Get time zone from string. Return None if unable to determine. """ + """Get time zone from string. Return None if unable to determine.""" try: return pytz.timezone(time_zone_str) except pytz.exceptions.UnknownTimeZoneError: @@ -33,18 +27,20 @@ def get_time_zone(time_zone_str): def utcnow(): - """ Get now in UTC time. """ + """Get now in UTC time.""" return dt.datetime.now(UTC) def now(time_zone=None): - """ Get now in specified time zone. """ + """Get now in specified time zone.""" return dt.datetime.now(time_zone or DEFAULT_TIME_ZONE) def as_utc(dattim): - """ Return a datetime as UTC time. - Assumes datetime without tzinfo to be in the DEFAULT_TIME_ZONE. """ + """Return a datetime as UTC time. + + Assumes datetime without tzinfo to be in the DEFAULT_TIME_ZONE. + """ if dattim.tzinfo == UTC: return dattim elif dattim.tzinfo is None: @@ -54,7 +50,7 @@ def as_utc(dattim): def as_local(dattim): - """ Converts a UTC datetime object to local time_zone. """ + """Convert a UTC datetime object to local time zone.""" if dattim.tzinfo == DEFAULT_TIME_ZONE: return dattim elif dattim.tzinfo is None: @@ -64,12 +60,12 @@ def as_local(dattim): def utc_from_timestamp(timestamp): - """ Returns a UTC time from a timestamp. """ + """Return a UTC time from a timestamp.""" return dt.datetime.utcfromtimestamp(timestamp).replace(tzinfo=UTC) def start_of_local_day(dt_or_d=None): - """ Return local datetime object of start of day from date or datetime. """ + """Return local datetime object of start of day from date or datetime.""" if dt_or_d is None: dt_or_d = now().date() elif isinstance(dt_or_d, dt.datetime): @@ -80,12 +76,12 @@ def start_of_local_day(dt_or_d=None): def datetime_to_local_str(dattim): - """ Converts datetime to specified time_zone and returns a string. """ + """Convert datetime to specified time_zone and returns a string.""" return datetime_to_str(as_local(dattim)) def datetime_to_str(dattim): - """ Converts datetime to a string format. + """Convert datetime to a string format. @rtype : str """ @@ -93,7 +89,7 @@ def datetime_to_str(dattim): def datetime_to_time_str(dattim): - """ Converts datetime to a string containing only the time. + """Convert datetime to a string containing only the time. @rtype : str """ @@ -101,7 +97,7 @@ def datetime_to_time_str(dattim): def datetime_to_date_str(dattim): - """ Converts datetime to a string containing only the date. + """Convert datetime to a string containing only the date. @rtype : str """ @@ -109,7 +105,7 @@ def datetime_to_date_str(dattim): def str_to_datetime(dt_str, dt_format=DATETIME_STR_FORMAT): - """ Converts a string to a UTC datetime object. + """Convert a string to a UTC datetime object. @rtype: datetime """ @@ -121,7 +117,7 @@ def str_to_datetime(dt_str, dt_format=DATETIME_STR_FORMAT): def date_str_to_date(dt_str): - """ Converts a date string to a date object. """ + """Convert a date string to a date object.""" try: return dt.datetime.strptime(dt_str, DATE_STR_FORMAT).date() except ValueError: # If dt_str did not match our format @@ -129,13 +125,14 @@ def date_str_to_date(dt_str): def strip_microseconds(dattim): - """ Returns a copy of dattime object but with microsecond set to 0. """ + """Return a copy of dattime object but with microsecond set to 0.""" return dattim.replace(microsecond=0) def parse_time_str(time_str): - """ Parse a time string (00:20:00) into Time object. - Return None if invalid. + """Parse a time string (00:20:00) into Time object. + + Return None if invalid. """ parts = str(time_str).split(':') if len(parts) < 2: diff --git a/homeassistant/util/package.py b/homeassistant/util/package.py index 91ef15cc7a0..6894524d963 100644 --- a/homeassistant/util/package.py +++ b/homeassistant/util/package.py @@ -1,8 +1,4 @@ -""" -homeassistant.util.package -~~~~~~~~~~~~~~~~~~~~~~~~~~ -Helpers to install PyPi packages. -""" +"""Helpers to install PyPi packages.""" import logging import os import subprocess @@ -17,8 +13,8 @@ INSTALL_LOCK = threading.Lock() def install_package(package, upgrade=True, target=None): - """ - Install a package on PyPi. Accepts pip compatible package strings. + """Install a package on PyPi. Accepts pip compatible package strings. + Return boolean if install successful. """ # Not using 'import pip; pip.main([])' because it breaks the logger @@ -41,8 +37,8 @@ def install_package(package, upgrade=True, target=None): def check_package_exists(package, lib_dir): - """ - Check if a package is installed globally or in lib_dir. + """Check if a package is installed globally or in lib_dir. + Returns True when the requirement is met. Returns False when the package is not installed or doesn't meet req. """ diff --git a/homeassistant/util/temperature.py b/homeassistant/util/temperature.py index 943744597b1..99a524c5212 100644 --- a/homeassistant/util/temperature.py +++ b/homeassistant/util/temperature.py @@ -1,15 +1,11 @@ -""" -homeassistant.util.temperature -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Temperature util functions. -""" +"""Temperature util functions.""" def fahrenheit_to_celcius(fahrenheit): - """ Convert a Fahrenheit temperature to Celcius. """ + """Convert a Fahrenheit temperature to Celsius.""" return (fahrenheit - 32.0) / 1.8 def celcius_to_fahrenheit(celcius): - """ Convert a Celcius temperature to Fahrenheit. """ + """Convert a Celsius temperature to Fahrenheit.""" return celcius * 1.8 + 32.0 diff --git a/homeassistant/util/yaml.py b/homeassistant/util/yaml.py index fa7783d7e83..517ed6c4fb0 100644 --- a/homeassistant/util/yaml.py +++ b/homeassistant/util/yaml.py @@ -1,6 +1,4 @@ -""" -YAML utility functions. -""" +"""YAML utility functions.""" import logging import os from collections import OrderedDict @@ -26,8 +24,7 @@ def load_yaml(fname): def _include_yaml(loader, node): - """ - Loads another YAML file and embeds it using the !include tag. + """Load another YAML file and embeds it using the !include tag. Example: device_tracker: !include device_tracker.yaml @@ -37,9 +34,7 @@ def _include_yaml(loader, node): def _ordered_dict(loader, node): - """ - Loads YAML mappings into an ordered dict to preserve key order. - """ + """Load YAML mappings into an ordered dict to preserve key order.""" loader.flatten_mapping(node) return OrderedDict(loader.construct_pairs(node)) From 4f536ac63d28e7f025af7dfad5949bbbabd78d11 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Mon, 7 Mar 2016 23:39:52 +0100 Subject: [PATCH 2/3] Fix PEP257 issues --- homeassistant/helpers/__init__.py | 15 +++---- homeassistant/helpers/entity.py | 32 +++++---------- homeassistant/helpers/entity_component.py | 7 ++-- homeassistant/helpers/event.py | 50 +++++++++-------------- homeassistant/helpers/event_decorators.py | 28 +++++-------- homeassistant/helpers/service.py | 9 ++-- homeassistant/helpers/state.py | 9 ++-- homeassistant/helpers/temperature.py | 10 +---- homeassistant/helpers/template.py | 22 ++++++---- 9 files changed, 74 insertions(+), 108 deletions(-) diff --git a/homeassistant/helpers/__init__.py b/homeassistant/helpers/__init__.py index b94530e525c..07e14c260fc 100644 --- a/homeassistant/helpers/__init__.py +++ b/homeassistant/helpers/__init__.py @@ -1,20 +1,17 @@ -""" -Helper methods for components within Home Assistant. -""" +"""Helper methods for components within Home Assistant.""" import re from homeassistant.const import CONF_PLATFORM def validate_config(config, items, logger): - """ - Validates if all items are available in the configuration. + """Validate if all items are available in the configuration. config is the general dictionary with all the configurations. items is a dict with per domain which attributes we require. logger is the logger from the caller to log the errors to. - Returns True if all required items were found. + Return True if all required items were found. """ errors_found = False for domain in items.keys(): @@ -33,8 +30,8 @@ def validate_config(config, items, logger): def config_per_platform(config, domain, logger): - """ - Generator to break a component config into different platforms. + """Generator to break a component config into different platforms. + For example, will find 'switch', 'switch 2', 'switch 3', .. etc """ config_key = domain @@ -59,6 +56,6 @@ def config_per_platform(config, domain, logger): def extract_domain_configs(config, domain): - """ Extract keys from config for given domain name. """ + """Extract keys from config for given domain name.""" pattern = re.compile(r'^{}(| .+)$'.format(domain)) return [key for key in config.keys() if pattern.match(key)] diff --git a/homeassistant/helpers/entity.py b/homeassistant/helpers/entity.py index d7d37135cb2..422c05bac4d 100644 --- a/homeassistant/helpers/entity.py +++ b/homeassistant/helpers/entity.py @@ -1,8 +1,4 @@ -""" -homeassistant.helpers.entity. - -Provides ABC for entities in HA. -""" +"""An abstract class for entities in HA.""" import re from collections import defaultdict @@ -49,15 +45,12 @@ class Entity(object): """ABC for Home Assistant entities.""" # pylint: disable=no-self-use - # SAFE TO OVERWRITE # The properties and methods here are safe to overwrite when inherting this # class. These may be used to customize the behavior of the entity. - @property def should_poll(self): - """ - Return True if entity has to be polled for state. + """Return True if entity has to be polled for state. False if entity pushes its state to HA. """ @@ -80,8 +73,7 @@ class Entity(object): @property def state_attributes(self): - """ - Return the state attributes. + """Return the state attributes. Implemented by component base class. """ @@ -89,8 +81,7 @@ class Entity(object): @property def device_state_attributes(self): - """ - Return device specific state attributes. + """Return device specific state attributes. Implemented by platform classes. """ @@ -140,8 +131,7 @@ class Entity(object): hass = None def update_ha_state(self, force_refresh=False): - """ - Update Home Assistant with current state of entity. + """Update Home Assistant with current state of entity. If force_refresh == True will update entity before setting state. """ @@ -176,10 +166,10 @@ class Entity(object): self._attr_setter('hidden', bool, ATTR_HIDDEN, attr) self._attr_setter('assumed_state', bool, ATTR_ASSUMED_STATE, attr) - # overwrite properties that have been set in the config file + # Overwrite properties that have been set in the config file. attr.update(_OVERWRITE.get(self.entity_id, {})) - # remove hidden property if false so it won't show up + # Remove hidden property if false so it won't show up. if not attr.get(ATTR_HIDDEN, True): attr.pop(ATTR_HIDDEN) @@ -210,16 +200,17 @@ class Entity(object): pass def __eq__(self, other): + """Return the comparison.""" return (isinstance(other, Entity) and other.unique_id == self.unique_id) def __repr__(self): + """Return the representation.""" return "".format(self.name, self.state) @staticmethod def overwrite_attribute(entity_id, attrs, vals): - """ - Overwrite any attribute of an entity. + """Overwrite any attribute of an entity. This function should receive a list of attributes and a list of values. Set attribute to None to remove any overwritten @@ -236,7 +227,6 @@ class ToggleEntity(Entity): """ABC for entities that can be turned on and off.""" # pylint: disable=no-self-use - @property def state(self): """Return the state.""" @@ -244,7 +234,7 @@ class ToggleEntity(Entity): @property def is_on(self): - """True if entity is on.""" + """Return True if entity is on.""" return False def turn_on(self, **kwargs): diff --git a/homeassistant/helpers/entity_component.py b/homeassistant/helpers/entity_component.py index 26dc4500e78..da82066ba67 100644 --- a/homeassistant/helpers/entity_component.py +++ b/homeassistant/helpers/entity_component.py @@ -41,8 +41,7 @@ class EntityComponent(object): self.scan_interval).add_entities def setup(self, config): - """ - Set up a full entity component. + """Set up a full entity component. Loads the platforms from the config and will listen for supported discovered platforms. @@ -63,8 +62,7 @@ class EntityComponent(object): info)) def extract_from_service(self, service): - """ - Extract all known entities from a service call. + """Extract all known entities from a service call. Will return all entities if no entities specified in call. Will return an empty list if entities specified but unknown. @@ -134,6 +132,7 @@ class EntityPlatform(object): # pylint: disable=too-few-public-methods def __init__(self, component, scan_interval): + """Initalize the entity platform.""" self.component = component self.scan_interval = scan_interval self.platform_entities = [] diff --git a/homeassistant/helpers/event.py b/homeassistant/helpers/event.py index e19d1646959..b6a08cc59d0 100644 --- a/homeassistant/helpers/event.py +++ b/homeassistant/helpers/event.py @@ -1,6 +1,4 @@ -""" -Helpers for listening to events -""" +"""Helpers for listening to events.""" import functools as ft from datetime import timedelta @@ -11,8 +9,8 @@ from ..util import dt as dt_util def track_state_change(hass, entity_ids, action, from_state=None, to_state=None): - """ - Track specific state changes. + """Track specific state changes. + entity_ids, from_state and to_state can be string or list. Use list to match multiple. @@ -30,7 +28,7 @@ def track_state_change(hass, entity_ids, action, from_state=None, @ft.wraps(action) def state_change_listener(event): - """ The listener that listens for specific state changes. """ + """The listener that listens for specific state changes.""" if event.data['entity_id'] not in entity_ids: return @@ -55,29 +53,25 @@ def track_state_change(hass, entity_ids, action, from_state=None, def track_point_in_time(hass, action, point_in_time): - """ - Adds a listener that fires once after a spefic point in time. - """ + """Add a listener that fires once after a spefic point in time.""" utc_point_in_time = dt_util.as_utc(point_in_time) @ft.wraps(action) def utc_converter(utc_now): - """ Converts passed in UTC now to local now. """ + """Convert passed in UTC now to local now.""" action(dt_util.as_local(utc_now)) return track_point_in_utc_time(hass, utc_converter, utc_point_in_time) def track_point_in_utc_time(hass, action, point_in_time): - """ - Adds a listener that fires once after a specific point in UTC time. - """ + """Add a listener that fires once after a specific point in UTC time.""" # Ensure point_in_time is UTC point_in_time = dt_util.as_utc(point_in_time) @ft.wraps(action) def point_in_time_listener(event): - """ Listens for matching time_changed events. """ + """Listen for matching time_changed events.""" now = event.data[ATTR_NOW] if now >= point_in_time and \ @@ -100,14 +94,12 @@ def track_point_in_utc_time(hass, action, point_in_time): def track_sunrise(hass, action, offset=None): - """ - Adds a listener that will fire a specified offset from sunrise daily. - """ + """Add a listener that will fire a specified offset from sunrise daily.""" from homeassistant.components import sun offset = offset or timedelta() def next_rise(): - """ Returns next sunrise. """ + """Return the next sunrise.""" next_time = sun.next_rising_utc(hass) + offset while next_time < dt_util.utcnow(): @@ -116,7 +108,7 @@ def track_sunrise(hass, action, offset=None): return next_time def sunrise_automation_listener(now): - """ Called when it's time for action. """ + """Called when it's time for action.""" track_point_in_utc_time(hass, sunrise_automation_listener, next_rise()) action() @@ -124,14 +116,12 @@ def track_sunrise(hass, action, offset=None): def track_sunset(hass, action, offset=None): - """ - Adds a listener that will fire a specified offset from sunset daily. - """ + """Add a listener that will fire a specified offset from sunset daily.""" from homeassistant.components import sun offset = offset or timedelta() def next_set(): - """ Returns next sunrise. """ + """Return next sunrise.""" next_time = sun.next_setting_utc(hass) + offset while next_time < dt_util.utcnow(): @@ -140,7 +130,7 @@ def track_sunset(hass, action, offset=None): return next_time def sunset_automation_listener(now): - """ Called when it's time for action. """ + """Called when it's time for action.""" track_point_in_utc_time(hass, sunset_automation_listener, next_set()) action() @@ -150,13 +140,13 @@ def track_sunset(hass, action, offset=None): # pylint: disable=too-many-arguments def track_utc_time_change(hass, action, year=None, month=None, day=None, hour=None, minute=None, second=None, local=False): - """ Adds a listener that will fire if time matches a pattern. """ + """Add a listener that will fire if time matches a pattern.""" # We do not have to wrap the function with time pattern matching logic # if no pattern given if all(val is None for val in (year, month, day, hour, minute, second)): @ft.wraps(action) def time_change_listener(event): - """ Fires every time event that comes in. """ + """Fire every time event that comes in.""" action(event.data[ATTR_NOW]) hass.bus.listen(EVENT_TIME_CHANGED, time_change_listener) @@ -168,7 +158,7 @@ def track_utc_time_change(hass, action, year=None, month=None, day=None, @ft.wraps(action) def pattern_time_change_listener(event): - """ Listens for matching time_changed events. """ + """Listen for matching time_changed events.""" now = event.data[ATTR_NOW] if local: @@ -192,13 +182,13 @@ def track_utc_time_change(hass, action, year=None, month=None, day=None, # pylint: disable=too-many-arguments def track_time_change(hass, action, year=None, month=None, day=None, hour=None, minute=None, second=None): - """ Adds a listener that will fire if UTC time matches a pattern. """ + """Add a listener that will fire if UTC time matches a pattern.""" track_utc_time_change(hass, action, year, month, day, hour, minute, second, local=True) def _process_match_param(parameter): - """ Wraps parameter in a tuple if it is not one and returns it. """ + """Wrap parameter in a tuple if it is not one and returns it.""" if parameter is None or parameter == MATCH_ALL: return MATCH_ALL elif isinstance(parameter, str) and parameter.startswith('/'): @@ -210,7 +200,7 @@ def _process_match_param(parameter): def _matcher(subject, pattern): - """ Returns True if subject matches the pattern. + """Return True if subject matches the pattern. Pattern is either a tuple of allowed subjects or a `MATCH_ALL`. """ diff --git a/homeassistant/helpers/event_decorators.py b/homeassistant/helpers/event_decorators.py index e98f912ef64..d4292f20a5f 100644 --- a/homeassistant/helpers/event_decorators.py +++ b/homeassistant/helpers/event_decorators.py @@ -1,5 +1,4 @@ -""" Event Decorators for custom components """ - +"""Event Decorators for custom components.""" import functools from homeassistant.helpers import event @@ -8,10 +7,9 @@ HASS = None def track_state_change(entity_ids, from_state=None, to_state=None): - """ Decorator factory to track state changes for entity id """ - + """Decorator factory to track state changes for entity id.""" def track_state_change_decorator(action): - """ Decorator to track state changes """ + """Decorator to track state changes.""" event.track_state_change(HASS, entity_ids, functools.partial(action, HASS), from_state, to_state) @@ -21,10 +19,9 @@ def track_state_change(entity_ids, from_state=None, to_state=None): def track_sunrise(offset=None): - """ Decorator factory to track sunrise events """ - + """Decorator factory to track sunrise events.""" def track_sunrise_decorator(action): - """ Decorator to track sunrise events """ + """Decorator to track sunrise events.""" event.track_sunrise(HASS, functools.partial(action, HASS), offset) @@ -34,10 +31,9 @@ def track_sunrise(offset=None): def track_sunset(offset=None): - """ Decorator factory to track sunset events """ - + """Decorator factory to track sunset events.""" def track_sunset_decorator(action): - """ Decorator to track sunset events """ + """Decorator to track sunset events.""" event.track_sunset(HASS, functools.partial(action, HASS), offset) @@ -49,10 +45,9 @@ def track_sunset(offset=None): # pylint: disable=too-many-arguments def track_time_change(year=None, month=None, day=None, hour=None, minute=None, second=None): - """ Decorator factory to track time changes """ - + """Decorator factory to track time changes.""" def track_time_change_decorator(action): - """ Decorator to track time changes """ + """Decorator to track time changes.""" event.track_time_change(HASS, functools.partial(action, HASS), year, month, day, hour, minute, second) @@ -64,10 +59,9 @@ def track_time_change(year=None, month=None, day=None, hour=None, minute=None, # pylint: disable=too-many-arguments def track_utc_time_change(year=None, month=None, day=None, hour=None, minute=None, second=None): - """ Decorator factory to track time changes """ - + """Decorator factory to track time changes.""" def track_utc_time_change_decorator(action): - """ Decorator to track time changes """ + """Decorator to track time changes.""" event.track_utc_time_change(HASS, functools.partial(action, HASS), year, month, day, hour, minute, second) diff --git a/homeassistant/helpers/service.py b/homeassistant/helpers/service.py index 2d198910408..6d85c08b866 100644 --- a/homeassistant/helpers/service.py +++ b/homeassistant/helpers/service.py @@ -16,10 +16,9 @@ _LOGGER = logging.getLogger(__name__) def service(domain, service_name): - """ Decorator factory to register a service """ - + """Decorator factory to register a service.""" def register_service_decorator(action): - """ Decorator to register a service """ + """Decorator to register a service.""" HASS.services.register(domain, service_name, functools.partial(action, HASS)) return action @@ -60,8 +59,8 @@ def call_from_config(hass, config, blocking=False): def extract_entity_ids(hass, service_call): - """ - Helper method to extract a list of entity ids from a service call. + """Helper method to extract a list of entity ids from a service call. + Will convert group entity ids to the entity ids it represents. """ if not (service_call.data and ATTR_ENTITY_ID in service_call.data): diff --git a/homeassistant/helpers/state.py b/homeassistant/helpers/state.py index 9d81b95b18a..2abe8e1555e 100644 --- a/homeassistant/helpers/state.py +++ b/homeassistant/helpers/state.py @@ -18,10 +18,10 @@ _LOGGER = logging.getLogger(__name__) # pylint: disable=too-few-public-methods, attribute-defined-outside-init class TrackStates(object): - """ - Records the time when the with-block is entered. Will add all states - that have changed since the start time to the return list when with-block - is exited. + """Record the time when the with-block is entered. + + Will add all states that have changed since the start time to the return + list when with-block is exited. """ def __init__(self, hass): @@ -100,7 +100,6 @@ def state_as_number(state): Raises ValueError if this is not possible. """ - if state.state in (STATE_ON, STATE_LOCKED, STATE_ABOVE_HORIZON, STATE_OPEN): return 1 diff --git a/homeassistant/helpers/temperature.py b/homeassistant/helpers/temperature.py index 90f3236d111..3fd0ef76a89 100644 --- a/homeassistant/helpers/temperature.py +++ b/homeassistant/helpers/temperature.py @@ -1,16 +1,10 @@ -""" -homeassistant.helpers.temperature -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Methods to help handle temperature in Home Assistant. -""" - +"""Methods to help handle temperature in Home Assistant.""" import homeassistant.util.temperature as temp_util from homeassistant.const import TEMP_CELCIUS def convert(temperature, unit, to_unit): - """ Converts temperature to correct unit. """ + """Convert temperature to correct unit.""" if unit == to_unit or unit is None or to_unit is None: return temperature elif unit == TEMP_CELCIUS: diff --git a/homeassistant/helpers/template.py b/homeassistant/helpers/template.py index 9c9ebd42913..3c08670b42b 100644 --- a/homeassistant/helpers/template.py +++ b/homeassistant/helpers/template.py @@ -1,6 +1,4 @@ -""" -Template helper methods for rendering strings with HA data. -""" +"""Template helper methods for rendering strings with HA data.""" # pylint: disable=too-few-public-methods import json import logging @@ -21,8 +19,8 @@ _SENTINEL = object() def render_with_possible_json_value(hass, template, value, error_value=_SENTINEL): - """ - Renders template with value exposed. + """Render template with value exposed. + If valid JSON will expose value_json too. """ variables = { @@ -65,17 +63,22 @@ def render(hass, template, variables=None, **kwargs): class AllStates(object): """Class to expose all HA states as attributes.""" + def __init__(self, hass): + """Initialize all states.""" self._hass = hass def __getattr__(self, name): + """Return the domain state.""" return DomainStates(self._hass, name) def __iter__(self): + """Return all states.""" return iter(sorted(self._hass.states.all(), key=lambda state: state.entity_id)) def __call__(self, entity_id): + """Return the states.""" state = self._hass.states.get(entity_id) return STATE_UNKNOWN if state is None else state.state @@ -84,13 +87,16 @@ class DomainStates(object): """Class to expose a specific HA domain as attributes.""" def __init__(self, hass, domain): + """Initialize the domain states.""" self._hass = hass self._domain = domain def __getattr__(self, name): + """Return the states.""" return self._hass.states.get('{}.{}'.format(self._domain, name)) def __iter__(self): + """Return the iteration over all the states.""" return iter(sorted( (state for state in self._hass.states.all() if state.domain == self._domain), @@ -101,7 +107,7 @@ class LocationMethods(object): """Class to expose distance helpers to templates.""" def __init__(self, hass): - """Initialize distance helpers.""" + """Initialize the distance helpers.""" self._hass = hass def closest(self, *args): @@ -118,7 +124,6 @@ class LocationMethods(object): closest('zone.school', 'group.children') closest(states.zone.school, 'group.children') """ - if len(args) == 1: latitude = self._hass.config.latitude longitude = self._hass.config.longitude @@ -250,8 +255,7 @@ def forgiving_float(value): class TemplateEnvironment(ImmutableSandboxedEnvironment): - """Home Assistant template environment.""" - + """The Home Assistant template environment.""" def is_safe_callable(self, obj): """Test if callback is safe.""" return isinstance(obj, AllStates) or super().is_safe_callable(obj) From 897b5c668f868e6cf1eed9c0a396bcb32035b141 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Tue, 8 Mar 2016 00:06:04 +0100 Subject: [PATCH 3/3] Fix PEP257 issues --- homeassistant/__init__.py | 1 + homeassistant/__main__.py | 48 ++++++++-------- homeassistant/bootstrap.py | 30 +++++----- homeassistant/config.py | 27 +++++---- homeassistant/core.py | 13 +++-- homeassistant/exceptions.py | 15 +++-- homeassistant/loader.py | 42 +++++++------- homeassistant/remote.py | 110 ++++++++++++++++++------------------ 8 files changed, 145 insertions(+), 141 deletions(-) diff --git a/homeassistant/__init__.py b/homeassistant/__init__.py index e69de29bb2d..32da6ab0afb 100644 --- a/homeassistant/__init__.py +++ b/homeassistant/__init__.py @@ -0,0 +1 @@ +"""Init file for Home Assistant.""" diff --git a/homeassistant/__main__.py b/homeassistant/__main__.py index 1a0419471ff..02ccc239f2b 100644 --- a/homeassistant/__main__.py +++ b/homeassistant/__main__.py @@ -1,4 +1,4 @@ -""" Starts home assistant. """ +"""Starts home assistant.""" from __future__ import print_function import argparse @@ -20,7 +20,7 @@ from homeassistant.const import ( def validate_python(): - """ Validate we're running the right Python version. """ + """Validate we're running the right Python version.""" major, minor = sys.version_info[:2] req_major, req_minor = REQUIRED_PYTHON_VER @@ -31,8 +31,7 @@ def validate_python(): def ensure_config_path(config_dir): - """ Validates configuration directory. """ - + """Validate the configuration directory.""" lib_dir = os.path.join(config_dir, 'lib') # Test if configuration directory exists @@ -60,7 +59,7 @@ def ensure_config_path(config_dir): def ensure_config_file(config_dir): - """ Ensure configuration file exists. """ + """Ensure configuration file exists.""" config_path = config_util.ensure_config_exists(config_dir) if config_path is None: @@ -71,7 +70,7 @@ def ensure_config_file(config_dir): def get_arguments(): - """ Get parsed passed in arguments. """ + """Get parsed passed in arguments.""" parser = argparse.ArgumentParser( description="Home Assistant: Observe, Control, Automate.") parser.add_argument('--version', action='version', version=__version__) @@ -136,25 +135,25 @@ def get_arguments(): def daemonize(): - """ Move current process to daemon process """ - # create first fork + """Move current process to daemon process.""" + # Create first fork pid = os.fork() if pid > 0: sys.exit(0) - # decouple fork + # Decouple fork os.setsid() os.umask(0) - # create second fork + # Create second fork pid = os.fork() if pid > 0: sys.exit(0) def check_pid(pid_file): - """ Check that HA is not already running """ - # check pid file + """Check that HA is not already running.""" + # Check pid file try: pid = int(open(pid_file, 'r').readline()) except IOError: @@ -171,7 +170,7 @@ def check_pid(pid_file): def write_pid(pid_file): - """ Create PID File """ + """Create a PID File.""" pid = os.getpid() try: open(pid_file, 'w').write(str(pid)) @@ -181,7 +180,7 @@ def write_pid(pid_file): def install_osx(): - """ Setup to run via launchd on OS X """ + """Setup to run via launchd on OS X.""" with os.popen('which hass') as inp: hass_path = inp.read().strip() @@ -213,7 +212,7 @@ def install_osx(): def uninstall_osx(): - """ Unload from launchd on OS X """ + """Unload from launchd on OS X.""" path = os.path.expanduser("~/Library/LaunchAgents/org.homeassistant.plist") os.popen('launchctl unload ' + path) @@ -221,9 +220,10 @@ def uninstall_osx(): def setup_and_run_hass(config_dir, args, top_process=False): - """ - Setup HASS and run. Block until stopped. Will assume it is running in a - subprocess unless top_process is set to true. + """Setup HASS and run. + + Block until stopped. Will assume it is running in a subprocess unless + top_process is set to true. """ if args.demo_mode: config = { @@ -243,7 +243,7 @@ def setup_and_run_hass(config_dir, args, top_process=False): if args.open_ui: def open_browser(event): - """ Open the webinterface in a browser. """ + """Open the webinterface in a browser.""" if hass.config.api is not None: import webbrowser webbrowser.open(hass.config.api.base_url) @@ -259,12 +259,12 @@ def setup_and_run_hass(config_dir, args, top_process=False): def run_hass_process(hass_proc): - """ Runs a child hass process. Returns True if it should be restarted. """ + """Run a child hass process. Returns True if it should be restarted.""" requested_stop = threading.Event() hass_proc.daemon = True def request_stop(*args): - """ request hass stop, *args is for signal handler callback """ + """Request hass stop, *args is for signal handler callback.""" requested_stop.set() hass_proc.terminate() @@ -289,7 +289,7 @@ def run_hass_process(hass_proc): def main(): - """ Starts Home Assistant. """ + """Start Home Assistant.""" validate_python() args = get_arguments() @@ -297,7 +297,7 @@ def main(): config_dir = os.path.join(os.getcwd(), args.config) ensure_config_path(config_dir) - # os x launchd functions + # OS X launchd functions if args.install_osx: install_osx() return 0 @@ -311,7 +311,7 @@ def main(): install_osx() return 0 - # daemon functions + # Daemon functions if args.pid_file: check_pid(args.pid_file) if args.daemon: diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index 9db3f79e498..c6f1a75b8a6 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -34,8 +34,7 @@ ERROR_LOG_FILENAME = 'home-assistant.log' def setup_component(hass, domain, config=None): - """ Setup a component and all its dependencies. """ - + """Setup a component and all its dependencies.""" if domain in hass.config.components: return True @@ -58,7 +57,7 @@ def setup_component(hass, domain, config=None): def _handle_requirements(hass, component, name): - """ Installs requirements for component. """ + """Install the requirements for a component.""" if hass.config.skip_pip or not hasattr(component, 'REQUIREMENTS'): return True @@ -126,7 +125,7 @@ def _setup_component(hass, domain, config): def prepare_setup_platform(hass, config, domain, platform_name): - """ Loads a platform and makes sure dependencies are setup. """ + """Load a platform and makes sure dependencies are setup.""" _ensure_loader_prepared(hass) platform_path = PLATFORM_FORMAT.format(domain, platform_name) @@ -158,7 +157,7 @@ def prepare_setup_platform(hass, config, domain, platform_name): def mount_local_lib_path(config_dir): - """ Add local library to Python Path """ + """Add local library to Python Path.""" sys.path.insert(0, os.path.join(config_dir, 'lib')) @@ -166,8 +165,7 @@ def mount_local_lib_path(config_dir): def from_config_dict(config, hass=None, config_dir=None, enable_log=True, verbose=False, daemon=False, skip_pip=False, log_rotate_days=None): - """ - Tries to configure Home Assistant from a config dict. + """Try to configure Home Assistant from a config dict. Dynamically loads required components and its dependencies. """ @@ -209,7 +207,7 @@ def from_config_dict(config, hass=None, config_dir=None, enable_log=True, _LOGGER.info('Home Assistant core initialized') - # give event decorators access to HASS + # Give event decorators access to HASS event_decorators.HASS = hass service.HASS = hass @@ -222,9 +220,9 @@ def from_config_dict(config, hass=None, config_dir=None, enable_log=True, def from_config_file(config_path, hass=None, verbose=False, daemon=False, skip_pip=True, log_rotate_days=None): - """ - Reads the configuration file and tries to start all the required - functionality. Will add functionality to 'hass' parameter if given, + """Read the configuration file and try to start all the functionality. + + Will add functionality to 'hass' parameter if given, instantiates a new Home Assistant object if 'hass' is not given. """ if hass is None: @@ -244,7 +242,7 @@ def from_config_file(config_path, hass=None, verbose=False, daemon=False, def enable_logging(hass, verbose=False, daemon=False, log_rotate_days=None): - """ Setup the logging for home assistant. """ + """Setup the logging.""" if not daemon: logging.basicConfig(level=logging.INFO) fmt = ("%(log_color)s%(asctime)s %(levelname)s (%(threadName)s) " @@ -297,7 +295,7 @@ def enable_logging(hass, verbose=False, daemon=False, log_rotate_days=None): def process_ha_config_upgrade(hass): - """ Upgrade config if necessary. """ + """Upgrade config if necessary.""" version_path = hass.config.path('.HA_VERSION') try: @@ -322,11 +320,11 @@ def process_ha_config_upgrade(hass): def process_ha_core_config(hass, config): - """ Processes the [homeassistant] section from the config. """ + """Process the [homeassistant] section from the config.""" hac = hass.config def set_time_zone(time_zone_str): - """ Helper method to set time zone in HA. """ + """Helper method to set time zone.""" if time_zone_str is None: return @@ -397,6 +395,6 @@ def process_ha_core_config(hass, config): def _ensure_loader_prepared(hass): - """ Ensure Home Assistant loader is prepared. """ + """Ensure Home Assistant loader is prepared.""" if not loader.PREPARED: loader.prepare(hass) diff --git a/homeassistant/config.py b/homeassistant/config.py index d87dd3d89ad..f18ab0fe037 100644 --- a/homeassistant/config.py +++ b/homeassistant/config.py @@ -1,9 +1,4 @@ -""" -homeassistant.config -~~~~~~~~~~~~~~~~~~~~ - -Module to help with parsing and generating configuration files. -""" +"""Module to help with parsing and generating configuration files.""" import logging import os @@ -43,16 +38,18 @@ DEFAULT_COMPONENTS = { def get_default_config_dir(): - """ Put together the default configuration directory based on OS. """ + """Put together the default configuration directory based on OS.""" data_dir = os.getenv('APPDATA') if os.name == "nt" \ else os.path.expanduser('~') return os.path.join(data_dir, CONFIG_DIR_NAME) def ensure_config_exists(config_dir, detect_location=True): - """ Ensures a config file exists in given config dir. - Creating a default one if needed. - Returns path to the config file. """ + """Ensure a config file exists in given configuration directory. + + Creating a default one if needed. + Return path to the config file. + """ config_path = find_config_file(config_dir) if config_path is None: @@ -64,8 +61,10 @@ def ensure_config_exists(config_dir, detect_location=True): def create_default_config(config_dir, detect_location=True): - """ Creates a default configuration file in given config dir. - Returns path to new config file if success, None if failed. """ + """Create a default configuration file in given configuration directory. + + Return path to new config file if success, None if failed. + """ config_path = os.path.join(config_dir, YAML_CONFIG_FILE) info = {attr: default for attr, default, _, _ in DEFAULT_CONFIG} @@ -108,14 +107,14 @@ def create_default_config(config_dir, detect_location=True): def find_config_file(config_dir): - """ Looks in given directory for supported config files. """ + """Look in given directory for supported configuration files.""" config_path = os.path.join(config_dir, YAML_CONFIG_FILE) return config_path if os.path.isfile(config_path) else None def load_yaml_config_file(config_path): - """ Parse a YAML configuration file. """ + """Parse a YAML configuration file.""" conf_dict = load_yaml(config_path) if not isinstance(conf_dict, dict): diff --git a/homeassistant/core.py b/homeassistant/core.py index 991de9c6189..a0d63d16018 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -132,12 +132,13 @@ class JobPriority(util.OrderedEnum): class EventOrigin(enum.Enum): - """Represents origin of an event.""" + """Represent the origin of an event.""" local = "LOCAL" remote = "REMOTE" def __str__(self): + """Return the event.""" return self.value @@ -166,6 +167,7 @@ class Event(object): } def __repr__(self): + """Return the representation.""" # pylint: disable=maybe-no-member if self.data: return "".format( @@ -176,6 +178,7 @@ class Event(object): str(self.origin)[0]) def __eq__(self, other): + """Return the comparison.""" return (self.__class__ == other.__class__ and self.event_type == other.event_type and self.data == other.data and @@ -246,7 +249,7 @@ class EventBus(object): """ @ft.wraps(listener) def onetime_listener(event): - """Remove listener from eventbus and then fires listener.""" + """Remove listener from eventbus and then fire listener.""" if hasattr(onetime_listener, 'run'): return # Set variable so that we will never run twice. @@ -281,8 +284,7 @@ class EventBus(object): class State(object): - """ - Object to represent a state within the state machine. + """Object to represent a state within the state machine. entity_id: the entity that is represented. state: the state of the entity @@ -369,12 +371,14 @@ class State(object): json_dict.get('attributes'), last_changed, last_updated) def __eq__(self, other): + """Return the comparison of the state.""" return (self.__class__ == other.__class__ and self.entity_id == other.entity_id and self.state == other.state and self.attributes == other.attributes) def __repr__(self): + """Return the representation of the states.""" attr = "; {}".format(util.repr_helper(self.attributes)) \ if self.attributes else "" @@ -524,6 +528,7 @@ class ServiceCall(object): self.call_id = call_id def __repr__(self): + """Return the represenation of the service.""" if self.data: return "".format( self.domain, self.service, util.repr_helper(self.data)) diff --git a/homeassistant/exceptions.py b/homeassistant/exceptions.py index 510bc9b4e54..f45fd3c3841 100644 --- a/homeassistant/exceptions.py +++ b/homeassistant/exceptions.py @@ -1,23 +1,28 @@ -""" Exceptions used by Home Assistant """ +"""Exceptions used by Home Assistant.""" class HomeAssistantError(Exception): - """ General Home Assistant exception occured. """ + """General Home Assistant exception occurred.""" + pass class InvalidEntityFormatError(HomeAssistantError): - """ When an invalid formatted entity is encountered. """ + """When an invalid formatted entity is encountered.""" + pass class NoEntitySpecifiedError(HomeAssistantError): - """ When no entity is specified. """ + """When no entity is specified.""" + pass class TemplateError(HomeAssistantError): - """ Error during template rendering. """ + """Error during template rendering.""" + def __init__(self, exception): + """Initalize the error.""" super().__init__('{}: {}'.format(exception.__class__.__name__, exception)) diff --git a/homeassistant/loader.py b/homeassistant/loader.py index 3dd831c4fb0..cb530946530 100644 --- a/homeassistant/loader.py +++ b/homeassistant/loader.py @@ -1,7 +1,4 @@ """ -homeassistant.loader -~~~~~~~~~~~~~~~~~~~~ - Provides methods for loading Home Assistant components. This module has quite some complex parts. I have tried to add as much @@ -33,7 +30,7 @@ _LOGGER = logging.getLogger(__name__) def prepare(hass): - """ Prepares the loading of components. """ + """Prepare the loading of components.""" global PREPARED # pylint: disable=global-statement # Load the built-in components @@ -74,17 +71,18 @@ def prepare(hass): def set_component(comp_name, component): - """ Sets a component in the cache. """ + """Set a component in the cache.""" _check_prepared() _COMPONENT_CACHE[comp_name] = component def get_component(comp_name): - """ Tries to load specified component. - Looks in config dir first, then built-in components. - Only returns it if also found to be valid. """ + """Try to load specified component. + Looks in config dir first, then built-in components. + Only returns it if also found to be valid. + """ if comp_name in _COMPONENT_CACHE: return _COMPONENT_CACHE[comp_name] @@ -145,14 +143,14 @@ def get_component(comp_name): def load_order_components(components): - """ - Takes in a list of components we want to load: - - filters out components we cannot load - - filters out components that have invalid/circular dependencies - - Will make sure the recorder component is loaded first - - Will ensure that all components that do not directly depend on - the group component will be loaded before the group component. - - returns an OrderedSet load order. + """Take in a list of components we want to load. + + - filters out components we cannot load + - filters out components that have invalid/circular dependencies + - Will make sure the recorder component is loaded first + - Will ensure that all components that do not directly depend on + the group component will be loaded before the group component. + - returns an OrderedSet load order. """ _check_prepared() @@ -175,8 +173,8 @@ def load_order_components(components): def load_order_component(comp_name): - """ - Returns an OrderedSet of components in the correct order of loading. + """Return an OrderedSet of components in the correct order of loading. + Raises HomeAssistantError if a circular dependency is detected. Returns an empty list if component could not be loaded. """ @@ -184,10 +182,10 @@ def load_order_component(comp_name): def _load_order_component(comp_name, load_order, loading): - """ Recursive function to get load order of components. """ + """Recursive function to get load order of components.""" component = get_component(comp_name) - # if None it does not exist, error already thrown by get_component + # If None it does not exist, error already thrown by get_component. if component is None: return OrderedSet() @@ -198,7 +196,7 @@ def _load_order_component(comp_name, load_order, loading): if dependency in load_order: continue - # If we are already loading it, we have a circular dependency + # If we are already loading it, we have a circular dependency. if dependency in loading: _LOGGER.error('Circular dependency detected: %s -> %s', comp_name, dependency) @@ -221,7 +219,7 @@ def _load_order_component(comp_name, load_order, loading): def _check_prepared(): - """ Issues a warning if loader.prepare() has never been called. """ + """Issue a warning if loader.prepare() has never been called.""" if not PREPARED: _LOGGER.warning(( "You did not call loader.prepare() yet. " diff --git a/homeassistant/remote.py b/homeassistant/remote.py index 11dd6c6be89..8eb96f7511c 100644 --- a/homeassistant/remote.py +++ b/homeassistant/remote.py @@ -1,8 +1,5 @@ """ -homeassistant.remote -~~~~~~~~~~~~~~~~~~~~ -A module containing drop in replacements for core parts that will interface -with a remote instance of Home Assistant. +Support for an interface to work with a remote instance of Home Assistant. If a connection error occurs while communicating with the API a HomeAssistantError will be raised. @@ -34,23 +31,25 @@ _LOGGER = logging.getLogger(__name__) class APIStatus(enum.Enum): - """ Represents API status. """ - # pylint: disable=no-init,invalid-name,too-few-public-methods + """Represent API status.""" + # pylint: disable=no-init,invalid-name,too-few-public-methods OK = "ok" INVALID_PASSWORD = "invalid_password" CANNOT_CONNECT = "cannot_connect" UNKNOWN = "unknown" def __str__(self): + """Return the state.""" return self.value class API(object): - """ Object to pass around Home Assistant API location and credentials. """ - # pylint: disable=too-few-public-methods + """Object to pass around Home Assistant API location and credentials.""" + # pylint: disable=too-few-public-methods def __init__(self, host, api_password=None, port=None, use_ssl=False): + """Initalize the API.""" self.host = host self.port = port or SERVER_PORT self.api_password = api_password @@ -65,14 +64,14 @@ class API(object): self._headers[HTTP_HEADER_HA_AUTH] = api_password def validate_api(self, force_validate=False): - """ Tests if we can communicate with the API. """ + """Test if we can communicate with the API.""" if self.status is None or force_validate: self.status = validate_api(self) return self.status == APIStatus.OK def __call__(self, method, path, data=None): - """ Makes a call to the Home Assistant API. """ + """Make a call to the Home Assistant API.""" if data is not None: data = json.dumps(data, cls=JSONEncoder) @@ -96,15 +95,17 @@ class API(object): raise HomeAssistantError(error) def __repr__(self): + """Return the representation of the API.""" return "API({}, {}, {})".format( self.host, self.api_password, self.port) class HomeAssistant(ha.HomeAssistant): - """ Home Assistant that forwards work. """ - # pylint: disable=super-init-not-called,too-many-instance-attributes + """Home Assistant that forwards work.""" + # pylint: disable=super-init-not-called,too-many-instance-attributes def __init__(self, remote_api, local_api=None): + """Initalize the forward instance.""" if not remote_api.validate_api(): raise HomeAssistantError( "Remote API at {}:{} not valid: {}".format( @@ -122,6 +123,7 @@ class HomeAssistant(ha.HomeAssistant): self.config.api = local_api def start(self): + """Start the instance.""" # Ensure a local API exists to connect with remote if self.config.api is None: if not bootstrap.setup_component(self, 'api'): @@ -141,7 +143,7 @@ class HomeAssistant(ha.HomeAssistant): 'local api {}').format(self.remote_api, self.config.api)) 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(ha.EVENT_HOMEASSISTANT_STOP, @@ -154,16 +156,19 @@ class HomeAssistant(ha.HomeAssistant): class EventBus(ha.EventBus): - """ EventBus implementation that forwards fire_event to remote API. """ - # pylint: disable=too-few-public-methods + """EventBus implementation that forwards fire_event to remote API.""" + # pylint: disable=too-few-public-methods def __init__(self, api, pool=None): + """Initalize the eventbus.""" super().__init__(pool) self._api = api def fire(self, event_type, event_data=None, origin=ha.EventOrigin.local): - """ Forward local events to remote target, - handles remote event as usual. """ + """Forward local events to remote target. + + Handles remote event as usual. + """ # All local events that are not TIME_CHANGED are forwarded to API if origin == ha.EventOrigin.local and \ event_type != ha.EVENT_TIME_CHANGED: @@ -175,9 +180,10 @@ class EventBus(ha.EventBus): class EventForwarder(object): - """ Listens for events and forwards to specified APIs. """ + """Listens for events and forwards to specified APIs.""" def __init__(self, hass, restrict_origin=None): + """Initalize the event forwarder.""" self.hass = hass self.restrict_origin = restrict_origin @@ -188,8 +194,7 @@ class EventForwarder(object): self._lock = threading.Lock() def connect(self, api): - """ - Attach to a Home Assistant instance and forward events. + """Attach to a Home Assistant instance and forward events. Will overwrite old target if one exists with same host/port. """ @@ -203,7 +208,7 @@ class EventForwarder(object): self._targets[key] = api def disconnect(self, api): - """ Removes target from being forwarded to. """ + """Remove target from being forwarded to.""" with self._lock: key = (api.host, api.port) @@ -217,7 +222,7 @@ class EventForwarder(object): return did_remove def _event_listener(self, event): - """ Listen and forwards all events. """ + """Listen and forward all events.""" with self._lock: # We don't forward time events or, if enabled, non-local events if event.event_type == ha.EVENT_TIME_CHANGED or \ @@ -229,16 +234,12 @@ class EventForwarder(object): class StateMachine(ha.StateMachine): - """ - Fires set events to an API. - Uses state_change events to track states. - """ + """Fire set events to an API. Uses state_change events to track states.""" def __init__(self, bus, api): + """Initalize the statemachine.""" super().__init__(None) - self._api = api - self.mirror() bus.listen(ha.EVENT_STATE_CHANGED, self._state_changed_listener) @@ -251,16 +252,16 @@ class StateMachine(ha.StateMachine): return remove_state(self._api, entity_id) def set(self, entity_id, new_state, attributes=None): - """ Calls set_state on remote API . """ + """Call set_state on remote API.""" set_state(self._api, entity_id, new_state, attributes) def mirror(self): - """ Discards current data and mirrors the remote state machine. """ + """Discard current data and mirrors the remote state machine.""" self._states = {state.entity_id: state for state in get_states(self._api)} def _state_changed_listener(self, event): - """ Listens for state changed events and applies them. """ + """Listen for state changed events and applies them.""" if event.data['new_state'] is None: self._states.pop(event.data['entity_id'], None) else: @@ -268,12 +269,14 @@ class StateMachine(ha.StateMachine): class JSONEncoder(json.JSONEncoder): - """ JSONEncoder that supports Home Assistant objects. """ - # pylint: disable=too-few-public-methods,method-hidden + """JSONEncoder that supports Home Assistant objects.""" + # pylint: disable=too-few-public-methods,method-hidden def default(self, obj): - """ Converts Home Assistant objects and hands - other objects to the original method. """ + """Convert Home Assistant objects. + + Hand other objects to the original method. + """ if hasattr(obj, 'as_dict'): return obj.as_dict() @@ -291,7 +294,7 @@ class JSONEncoder(json.JSONEncoder): def validate_api(api): - """ Makes a call to validate API. """ + """Make a call to validate API.""" try: req = api(METHOD_GET, URL_API) @@ -309,8 +312,7 @@ def validate_api(api): def connect_remote_events(from_api, to_api): - """ Sets up from_api to forward all events to to_api. """ - + """Setup from_api to forward all events to to_api.""" data = { 'host': to_api.host, 'api_password': to_api.api_password, @@ -335,7 +337,7 @@ def connect_remote_events(from_api, to_api): def disconnect_remote_events(from_api, to_api): - """ Disconnects forwarding events from from_api to to_api. """ + """Disconnect forwarding events from from_api to to_api.""" data = { 'host': to_api.host, 'port': to_api.port @@ -359,7 +361,7 @@ def disconnect_remote_events(from_api, to_api): def get_event_listeners(api): - """ List of events that is being listened for. """ + """List of events that is being listened for.""" try: req = api(METHOD_GET, URL_API_EVENTS) @@ -373,8 +375,7 @@ def get_event_listeners(api): def fire_event(api, event_type, data=None): - """ Fire an event at remote API. """ - + """Fire an event at remote API.""" try: req = api(METHOD_POST, URL_API_EVENTS_EVENT.format(event_type), data) @@ -387,8 +388,7 @@ def fire_event(api, event_type, data=None): def get_state(api, entity_id): - """ Queries given API for state of entity_id. """ - + """Query given API for state of entity_id.""" try: req = api(METHOD_GET, URL_API_STATES_ENTITY.format(entity_id)) @@ -405,8 +405,7 @@ def get_state(api, entity_id): def get_states(api): - """ Queries given API for all states. """ - + """Query given API for all states.""" try: req = api(METHOD_GET, URL_API_STATES) @@ -424,7 +423,7 @@ def get_states(api): def remove_state(api, entity_id): """Call API to remove state for entity_id. - Returns True if entity is gone (removed/never existed). + Return True if entity is gone (removed/never existed). """ try: req = api(METHOD_DELETE, URL_API_STATES_ENTITY.format(entity_id)) @@ -442,11 +441,10 @@ def remove_state(api, entity_id): def set_state(api, entity_id, new_state, attributes=None): - """ - Tells API to update state for entity_id. - Returns True if success. - """ + """Tell API to update state for entity_id. + Return True if success. + """ attributes = attributes or {} data = {'state': new_state, @@ -471,16 +469,16 @@ def set_state(api, entity_id, new_state, attributes=None): def is_state(api, entity_id, state): - """ Queries API to see if entity_id is specified state. """ + """Query API to see if entity_id is specified state.""" cur_state = get_state(api, entity_id) return cur_state and cur_state.state == state def get_services(api): - """ - Returns a list of dicts. Each dict has a string "domain" and - a list of strings "services". + """Return a list of dicts. + + Each dict has a string "domain" and a list of strings "services". """ try: req = api(METHOD_GET, URL_API_SERVICES) @@ -495,7 +493,7 @@ def get_services(api): def call_service(api, domain, service, service_data=None): - """ Calls a service at the remote API. """ + """Call a service at the remote API.""" try: req = api(METHOD_POST, URL_API_SERVICES_SERVICE.format(domain, service),