Merge branch 'dev' into upgrade-sphinx

This commit is contained in:
Daniel Høyer Iversen 2018-12-02 08:46:34 +01:00 committed by GitHub
commit 3bc83920b4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 75 additions and 99 deletions

View file

@ -18,7 +18,7 @@ from homeassistant.util.async_ import run_coroutine_threadsafe
import homeassistant.util.dt as dt_util
from homeassistant.components.camera import async_get_still_stream
REQUIREMENTS = ['pillow==5.2.0']
REQUIREMENTS = ['pillow==5.3.0']
_LOGGER = logging.getLogger(__name__)

View file

@ -14,7 +14,7 @@ from homeassistant.components.device_tracker import (
DOMAIN, PLATFORM_SCHEMA, DeviceScanner)
from homeassistant.const import CONF_HOST
REQUIREMENTS = ['ghlocalapi==0.1.0']
REQUIREMENTS = ['ghlocalapi==0.3.5']
_LOGGER = logging.getLogger(__name__)
@ -89,4 +89,5 @@ class GoogleHomeDeviceScanner(DeviceScanner):
devices[uuid]['btle_mac_address'] = device['mac_address']
devices[uuid]['ghname'] = ghname
devices[uuid]['source_type'] = 'bluetooth'
await self.scanner.clear_scan_result()
self.last_results = devices

View file

@ -117,23 +117,19 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
def __init__(self, config, discovery_hash):
"""Initialize the MQTT fan."""
self._unique_id = config.get(CONF_UNIQUE_ID)
self._state = False
self._speed = None
self._oscillation = None
self._supported_features = 0
self._sub_state = None
self._name = None
self._topic = None
self._qos = None
self._retain = None
self._payload = None
self._templates = None
self._speed_list = None
self._optimistic = None
self._optimistic_oscillation = None
self._optimistic_speed = None
self._unique_id = None
# Load config
self._setup_from_config(config)
@ -141,9 +137,10 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
availability_topic = config.get(CONF_AVAILABILITY_TOPIC)
payload_available = config.get(CONF_PAYLOAD_AVAILABLE)
payload_not_available = config.get(CONF_PAYLOAD_NOT_AVAILABLE)
qos = config.get(CONF_QOS)
device_config = config.get(CONF_DEVICE)
MqttAvailability.__init__(self, availability_topic, self._qos,
MqttAvailability.__init__(self, availability_topic, qos,
payload_available, payload_not_available)
MqttDiscoveryUpdate.__init__(self, discovery_hash,
self.discovery_update)
@ -164,7 +161,7 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
def _setup_from_config(self, config):
"""(Re)Setup the entity."""
self._name = config.get(CONF_NAME)
self._config = config
self._topic = {
key: config.get(key) for key in (
CONF_STATE_TOPIC,
@ -180,8 +177,6 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
ATTR_SPEED: config.get(CONF_SPEED_VALUE_TEMPLATE),
OSCILLATION: config.get(CONF_OSCILLATION_VALUE_TEMPLATE)
}
self._qos = config.get(CONF_QOS)
self._retain = config.get(CONF_RETAIN)
self._payload = {
STATE_ON: config.get(CONF_PAYLOAD_ON),
STATE_OFF: config.get(CONF_PAYLOAD_OFF),
@ -191,7 +186,6 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
SPEED_MEDIUM: config.get(CONF_PAYLOAD_MEDIUM_SPEED),
SPEED_HIGH: config.get(CONF_PAYLOAD_HIGH_SPEED),
}
self._speed_list = config.get(CONF_SPEED_LIST)
optimistic = config.get(CONF_OPTIMISTIC)
self._optimistic = optimistic or self._topic[CONF_STATE_TOPIC] is None
self._optimistic_oscillation = (
@ -232,7 +226,7 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
topics[CONF_STATE_TOPIC] = {
'topic': self._topic[CONF_STATE_TOPIC],
'msg_callback': state_received,
'qos': self._qos}
'qos': self._config.get(CONF_QOS)}
@callback
def speed_received(topic, payload, qos):
@ -250,7 +244,7 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
topics[CONF_SPEED_STATE_TOPIC] = {
'topic': self._topic[CONF_SPEED_STATE_TOPIC],
'msg_callback': speed_received,
'qos': self._qos}
'qos': self._config.get(CONF_QOS)}
self._speed = SPEED_OFF
@callback
@ -267,7 +261,7 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
topics[CONF_OSCILLATION_STATE_TOPIC] = {
'topic': self._topic[CONF_OSCILLATION_STATE_TOPIC],
'msg_callback': oscillation_received,
'qos': self._qos}
'qos': self._config.get(CONF_QOS)}
self._oscillation = False
self._sub_state = await subscription.async_subscribe_topics(
@ -297,12 +291,12 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
@property
def name(self) -> str:
"""Get entity name."""
return self._name
return self._config.get(CONF_NAME)
@property
def speed_list(self) -> list:
"""Get the list of available speeds."""
return self._speed_list
return self._config.get(CONF_SPEED_LIST)
@property
def supported_features(self) -> int:
@ -326,7 +320,8 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
"""
mqtt.async_publish(
self.hass, self._topic[CONF_COMMAND_TOPIC],
self._payload[STATE_ON], self._qos, self._retain)
self._payload[STATE_ON], self._config.get(CONF_QOS),
self._config.get(CONF_RETAIN))
if speed:
await self.async_set_speed(speed)
@ -337,7 +332,8 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
"""
mqtt.async_publish(
self.hass, self._topic[CONF_COMMAND_TOPIC],
self._payload[STATE_OFF], self._qos, self._retain)
self._payload[STATE_OFF], self._config.get(CONF_QOS),
self._config.get(CONF_RETAIN))
async def async_set_speed(self, speed: str) -> None:
"""Set the speed of the fan.
@ -358,7 +354,8 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
mqtt.async_publish(
self.hass, self._topic[CONF_SPEED_COMMAND_TOPIC],
mqtt_payload, self._qos, self._retain)
mqtt_payload, self._config.get(CONF_QOS),
self._config.get(CONF_RETAIN))
if self._optimistic_speed:
self._speed = speed
@ -379,7 +376,7 @@ class MqttFan(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
mqtt.async_publish(
self.hass, self._topic[CONF_OSCILLATION_COMMAND_TOPIC],
payload, self._qos, self._retain)
payload, self._config.get(CONF_QOS), self._config.get(CONF_RETAIN))
if self._optimistic_oscillation:
self._oscillation = oscillating

View file

@ -20,7 +20,7 @@ from homeassistant.core import split_entity_id
from homeassistant.helpers import template
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['numpy==1.15.4', 'pillow==5.2.0', 'protobuf==3.6.1']
REQUIREMENTS = ['numpy==1.15.4', 'pillow==5.3.0', 'protobuf==3.6.1']
_LOGGER = logging.getLogger(__name__)

View file

@ -17,7 +17,7 @@ from homeassistant.components.notify import (
BaseNotificationService)
from homeassistant.const import (CONF_API_KEY, CONF_USERNAME, CONF_ICON)
REQUIREMENTS = ['slacker==0.9.65']
REQUIREMENTS = ['slacker==0.11.0']
_LOGGER = logging.getLogger(__name__)
@ -39,14 +39,15 @@ ATTR_FILE_AUTH_DIGEST = 'digest'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_API_KEY): cv.string,
vol.Required(CONF_CHANNEL): cv.string,
vol.Optional(CONF_USERNAME): cv.string,
vol.Optional(CONF_ICON): cv.string,
vol.Optional(CONF_USERNAME): cv.string,
})
def get_service(hass, config, discovery_info=None):
"""Get the Slack notification service."""
import slacker
channel = config.get(CONF_CHANNEL)
api_key = config.get(CONF_API_KEY)
username = config.get(CONF_USERNAME)
@ -115,15 +116,15 @@ class SlackNotificationService(BaseNotificationService):
'content': None,
'filetype': None,
'filename': filename,
# if optional title is none use the filename
# If optional title is none use the filename
'title': title if title else filename,
'initial_comment': message,
'channels': target
}
# Post to slack
self.slack.files.post('files.upload',
data=data,
files={'file': file_as_bytes})
self.slack.files.post(
'files.upload', data=data,
files={'file': file_as_bytes})
else:
self.slack.chat.post_message(
target, message, as_user=self._as_user,
@ -154,13 +155,13 @@ class SlackNotificationService(BaseNotificationService):
elif local_path:
# Check whether path is whitelisted in configuration.yaml
if self.is_allowed_path(local_path):
return open(local_path, "rb")
_LOGGER.warning("'%s' is not secure to load data from!",
local_path)
return open(local_path, 'rb')
_LOGGER.warning(
"'%s' is not secure to load data from!", local_path)
else:
_LOGGER.warning("Neither URL nor local path found in params!")
except OSError as error:
_LOGGER.error("Can't load from url or local path: %s", error)
_LOGGER.error("Can't load from URL or local path: %s", error)
return None

View file

@ -18,7 +18,7 @@ from homeassistant.loader import bind_hass
from homeassistant.util import sanitize_filename
import homeassistant.util.dt as dt_util
REQUIREMENTS = ['restrictedpython==4.0b6']
REQUIREMENTS = ['restrictedpython==4.0b7']
_LOGGER = logging.getLogger(__name__)

View file

@ -48,8 +48,8 @@ PLATFORM_SCHEMA = mqtt.MQTT_RO_PLATFORM_SCHEMA.extend({
vol.Optional(CONF_JSON_ATTRS, default=[]): cv.ensure_list_csv,
vol.Optional(CONF_EXPIRE_AFTER): cv.positive_int,
vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean,
# Integrations shouldn't never expose unique_id through configuration
# this here is an exception because MQTT is a msg transport, not a protocol
# Integrations should never expose unique_id through configuration.
# This is an exception because MQTT is a message transport, not a protocol.
vol.Optional(CONF_UNIQUE_ID): cv.string,
vol.Optional(CONF_DEVICE): mqtt.MQTT_ENTITY_DEVICE_INFO_SCHEMA,
}).extend(mqtt.MQTT_AVAILABILITY_SCHEMA.schema)
@ -86,32 +86,20 @@ class MqttSensor(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
def __init__(self, config, discovery_hash):
"""Initialize the sensor."""
self._config = config
self._unique_id = config.get(CONF_UNIQUE_ID)
self._state = STATE_UNKNOWN
self._sub_state = None
self._expiration_trigger = None
self._attributes = None
self._name = None
self._state_topic = None
self._qos = None
self._unit_of_measurement = None
self._force_update = None
self._template = None
self._expire_after = None
self._icon = None
self._device_class = None
self._json_attributes = None
self._unique_id = None
# Load config
self._setup_from_config(config)
availability_topic = config.get(CONF_AVAILABILITY_TOPIC)
payload_available = config.get(CONF_PAYLOAD_AVAILABLE)
payload_not_available = config.get(CONF_PAYLOAD_NOT_AVAILABLE)
qos = config.get(CONF_QOS)
device_config = config.get(CONF_DEVICE)
MqttAvailability.__init__(self, availability_topic, self._qos,
MqttAvailability.__init__(self, availability_topic, qos,
payload_available, payload_not_available)
MqttDiscoveryUpdate.__init__(self, discovery_hash,
self.discovery_update)
@ -125,35 +113,23 @@ class MqttSensor(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
async def discovery_update(self, discovery_payload):
"""Handle updated discovery message."""
config = PLATFORM_SCHEMA(discovery_payload)
self._setup_from_config(config)
self._config = config
await self.availability_discovery_update(config)
await self._subscribe_topics()
self.async_schedule_update_ha_state()
def _setup_from_config(self, config):
"""(Re)Setup the entity."""
self._name = config.get(CONF_NAME)
self._state_topic = config.get(CONF_STATE_TOPIC)
self._qos = config.get(CONF_QOS)
self._unit_of_measurement = config.get(CONF_UNIT_OF_MEASUREMENT)
self._force_update = config.get(CONF_FORCE_UPDATE)
self._expire_after = config.get(CONF_EXPIRE_AFTER)
self._icon = config.get(CONF_ICON)
self._device_class = config.get(CONF_DEVICE_CLASS)
self._template = config.get(CONF_VALUE_TEMPLATE)
self._json_attributes = set(config.get(CONF_JSON_ATTRS))
self._unique_id = config.get(CONF_UNIQUE_ID)
async def _subscribe_topics(self):
"""(Re)Subscribe to topics."""
if self._template is not None:
self._template.hass = self.hass
template = self._config.get(CONF_VALUE_TEMPLATE)
if template is not None:
template.hass = self.hass
@callback
def message_received(topic, payload, qos):
"""Handle new MQTT messages."""
# auto-expire enabled?
if self._expire_after is not None and self._expire_after > 0:
expire_after = self._config.get(CONF_EXPIRE_AFTER)
if expire_after is not None and expire_after > 0:
# Reset old trigger
if self._expiration_trigger:
self._expiration_trigger()
@ -161,18 +137,19 @@ class MqttSensor(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
# Set new trigger
expiration_at = (
dt_util.utcnow() + timedelta(seconds=self._expire_after))
dt_util.utcnow() + timedelta(seconds=expire_after))
self._expiration_trigger = async_track_point_in_utc_time(
self.hass, self.value_is_expired, expiration_at)
if self._json_attributes:
json_attributes = set(self._config.get(CONF_JSON_ATTRS))
if json_attributes:
self._attributes = {}
try:
json_dict = json.loads(payload)
if isinstance(json_dict, dict):
attrs = {k: json_dict[k] for k in
self._json_attributes & json_dict.keys()}
json_attributes & json_dict.keys()}
self._attributes = attrs
else:
_LOGGER.warning("JSON result was not a dictionary")
@ -180,17 +157,17 @@ class MqttSensor(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
_LOGGER.warning("MQTT payload could not be parsed as JSON")
_LOGGER.debug("Erroneous JSON: %s", payload)
if self._template is not None:
payload = self._template.async_render_with_possible_json_value(
if template is not None:
payload = template.async_render_with_possible_json_value(
payload, self._state)
self._state = payload
self.async_schedule_update_ha_state()
self._sub_state = await subscription.async_subscribe_topics(
self.hass, self._sub_state,
{'state_topic': {'topic': self._state_topic,
{'state_topic': {'topic': self._config.get(CONF_STATE_TOPIC),
'msg_callback': message_received,
'qos': self._qos}})
'qos': self._config.get(CONF_QOS)}})
async def async_will_remove_from_hass(self):
"""Unsubscribe when removed."""
@ -212,17 +189,17 @@ class MqttSensor(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
@property
def name(self):
"""Return the name of the sensor."""
return self._name
return self._config.get(CONF_NAME)
@property
def unit_of_measurement(self):
"""Return the unit this state is expressed in."""
return self._unit_of_measurement
return self._config.get(CONF_UNIT_OF_MEASUREMENT)
@property
def force_update(self):
"""Force update."""
return self._force_update
return self._config.get(CONF_FORCE_UPDATE)
@property
def state(self):
@ -242,9 +219,9 @@ class MqttSensor(MqttAvailability, MqttDiscoveryUpdate, MqttEntityDeviceInfo,
@property
def icon(self):
"""Return the icon."""
return self._icon
return self._config.get(CONF_ICON)
@property
def device_class(self) -> Optional[str]:
"""Return the device class of the sensor."""
return self._device_class
return self._config.get(CONF_DEVICE_CLASS)

View file

@ -19,7 +19,7 @@ import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity
from homeassistant.util import Throttle
REQUIREMENTS = ['pytautulli==0.4.0']
REQUIREMENTS = ['pytautulli==0.4.1']
_LOGGER = logging.getLogger(__name__)
@ -90,9 +90,9 @@ class TautulliSensor(Entity):
await self.tautulli.async_update()
self.home = self.tautulli.api.home_data
self.sessions = self.tautulli.api.session_data
self._attributes['Top Movie'] = self.home[0]['rows'][0]['title']
self._attributes['Top TV Show'] = self.home[3]['rows'][0]['title']
self._attributes['Top User'] = self.home[7]['rows'][0]['user']
self._attributes['Top Movie'] = self.home.get('movie')
self._attributes['Top TV Show'] = self.home.get('tv')
self._attributes['Top User'] = self.home.get('user')
for key in self.sessions:
if 'sessions' not in key:
self._attributes[key] = self.sessions[key]

View file

@ -15,7 +15,7 @@ from homeassistant.helpers import config_validation as cv
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
REQUIREMENTS = ['pywemo==0.4.29']
REQUIREMENTS = ['pywemo==0.4.33']
DOMAIN = 'wemo'

View file

@ -11,7 +11,7 @@ pip>=8.0.3
pytz>=2018.04
pyyaml>=3.13,<4
requests==2.20.1
ruamel.yaml==0.15.78
ruamel.yaml==0.15.80
voluptuous==0.11.5
voluptuous-serialize==2.0.0

View file

@ -5,7 +5,7 @@ import os
from homeassistant.util.yaml import _SECRET_NAMESPACE
REQUIREMENTS = ['keyring==15.1.0', 'keyrings.alt==3.1']
REQUIREMENTS = ['keyring==17.0.0', 'keyrings.alt==3.1']
def run(args):

View file

@ -12,7 +12,7 @@ pip>=8.0.3
pytz>=2018.04
pyyaml>=3.13,<4
requests==2.20.1
ruamel.yaml==0.15.78
ruamel.yaml==0.15.80
voluptuous==0.11.5
voluptuous-serialize==2.0.0
@ -426,7 +426,7 @@ geojson_client==0.3
georss_client==0.4
# homeassistant.components.device_tracker.googlehome
ghlocalapi==0.1.0
ghlocalapi==0.3.5
# homeassistant.components.sensor.gitter
gitterpy==0.1.7
@ -548,7 +548,7 @@ jsonrpc-async==0.6
jsonrpc-websocket==0.6
# homeassistant.scripts.keyring
keyring==15.1.0
keyring==17.0.0
# homeassistant.scripts.keyring
keyrings.alt==3.1
@ -748,7 +748,7 @@ pilight==0.1.1
# homeassistant.components.camera.proxy
# homeassistant.components.image_processing.tensorflow
pillow==5.2.0
pillow==5.3.0
# homeassistant.components.dominos
pizzapi==0.0.3
@ -1158,7 +1158,7 @@ pystride==0.1.7
pysyncthru==0.3.1
# homeassistant.components.sensor.tautulli
pytautulli==0.4.0
pytautulli==0.4.1
# homeassistant.components.media_player.liveboxplaytv
pyteleloisirs==3.4
@ -1327,7 +1327,7 @@ pyvlx==0.1.3
pywebpush==1.6.0
# homeassistant.components.wemo
pywemo==0.4.29
pywemo==0.4.33
# homeassistant.components.camera.xeoma
pyxeoma==1.4.0
@ -1357,7 +1357,7 @@ raincloudy==0.0.5
regenmaschine==1.0.7
# homeassistant.components.python_script
restrictedpython==4.0b6
restrictedpython==4.0b7
# homeassistant.components.rflink
rflink==0.0.37
@ -1427,7 +1427,7 @@ sisyphus-control==2.1
skybellpy==0.1.2
# homeassistant.components.notify.slack
slacker==0.9.65
slacker==0.11.0
# homeassistant.components.sleepiq
sleepyq==0.6

View file

@ -1,3 +1,3 @@
Sphinx==1.8.2
sphinx-autodoc-typehints==1.5.0
sphinx-autodoc-typehints==1.5.1
sphinx-autodoc-annotation==1.0.post1

View file

@ -221,7 +221,7 @@ pywebpush==1.6.0
regenmaschine==1.0.7
# homeassistant.components.python_script
restrictedpython==4.0b6
restrictedpython==4.0b7
# homeassistant.components.rflink
rflink==0.0.37

View file

@ -46,7 +46,7 @@ REQUIRES = [
'pytz>=2018.04',
'pyyaml>=3.13,<4',
'requests==2.20.1',
'ruamel.yaml==0.15.78',
'ruamel.yaml==0.15.80',
'voluptuous==0.11.5',
'voluptuous-serialize==2.0.0',
]