From 29e2613c753c71899e5a0c926c3dd358d17521a8 Mon Sep 17 00:00:00 2001 From: Heiko Rothe Date: Sun, 15 Jan 2017 22:45:54 +0100 Subject: [PATCH 01/10] Fixed the lannouncer platform get_service method (#5352) --- homeassistant/components/notify/lannouncer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/notify/lannouncer.py b/homeassistant/components/notify/lannouncer.py index be1bc636fd6..4d038faeb9a 100644 --- a/homeassistant/components/notify/lannouncer.py +++ b/homeassistant/components/notify/lannouncer.py @@ -29,7 +29,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ _LOGGER = logging.getLogger(__name__) -def get_service(hass, config): +def get_service(hass, config, discovery_info=None): """Get the Lannouncer notification service.""" host = config.get(CONF_HOST) port = config.get(CONF_PORT) From 8a95cc4104ca29f00944fb53899fd31e5fdd4671 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Sun, 15 Jan 2017 23:53:37 +0100 Subject: [PATCH 02/10] Bugfix timedelta v2 (#5349) * Bugfix timedelta v2 * fix volvo * fix lint --- .../device_tracker/bluetooth_le_tracker.py | 14 +++++--------- .../components/device_tracker/bluetooth_tracker.py | 4 +--- .../components/device_tracker/volvooncall.py | 5 ++--- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/homeassistant/components/device_tracker/bluetooth_le_tracker.py b/homeassistant/components/device_tracker/bluetooth_le_tracker.py index 8c29bc94be5..454ab127af0 100644 --- a/homeassistant/components/device_tracker/bluetooth_le_tracker.py +++ b/homeassistant/components/device_tracker/bluetooth_le_tracker.py @@ -1,14 +1,12 @@ """Tracking for bluetooth low energy devices.""" import logging -from datetime import timedelta import voluptuous as vol from homeassistant.helpers.event import track_point_in_utc_time from homeassistant.components.device_tracker import ( YAML_DEVICES, CONF_TRACK_NEW, CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL, - PLATFORM_SCHEMA, load_config, DEFAULT_TRACK_NEW + PLATFORM_SCHEMA, load_config ) -import homeassistant.util as util import homeassistant.util.dt as dt_util import homeassistant.helpers.config_validation as cv @@ -86,14 +84,13 @@ def setup_scanner(hass, config, see): # if track new devices is true discover new devices # on every scan. - track_new = util.convert(config.get(CONF_TRACK_NEW), bool, - DEFAULT_TRACK_NEW) + track_new = config.get(CONF_TRACK_NEW) + if not devs_to_track and not track_new: _LOGGER.warning("No Bluetooth LE devices to track!") return False - interval = util.convert(config.get(CONF_SCAN_INTERVAL), int, - DEFAULT_SCAN_INTERVAL) + interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) def update_ble(now): """Lookup Bluetooth LE devices and update status.""" @@ -113,8 +110,7 @@ def setup_scanner(hass, config, see): _LOGGER.info("Discovered Bluetooth LE device %s", address) see_device(address, devs[address], new_device=True) - track_point_in_utc_time(hass, update_ble, - now + timedelta(seconds=interval)) + track_point_in_utc_time(hass, update_ble, now + interval) update_ble(dt_util.utcnow()) diff --git a/homeassistant/components/device_tracker/bluetooth_tracker.py b/homeassistant/components/device_tracker/bluetooth_tracker.py index 86e115c65c4..a8b3861cdc5 100644 --- a/homeassistant/components/device_tracker/bluetooth_tracker.py +++ b/homeassistant/components/device_tracker/bluetooth_tracker.py @@ -1,6 +1,5 @@ """Tracking for bluetooth devices.""" import logging -from datetime import timedelta import voluptuous as vol @@ -83,8 +82,7 @@ def setup_scanner(hass, config, see): see_device((mac, result)) except bluetooth.BluetoothError: _LOGGER.exception('Error looking up bluetooth device!') - track_point_in_utc_time(hass, update_bluetooth, - now + timedelta(seconds=interval)) + track_point_in_utc_time(hass, update_bluetooth, now + interval) update_bluetooth(dt_util.utcnow()) diff --git a/homeassistant/components/device_tracker/volvooncall.py b/homeassistant/components/device_tracker/volvooncall.py index a7dba230831..1be76d6139c 100644 --- a/homeassistant/components/device_tracker/volvooncall.py +++ b/homeassistant/components/device_tracker/volvooncall.py @@ -37,7 +37,7 @@ def setup_scanner(hass, config, see): config.get(CONF_USERNAME), config.get(CONF_PASSWORD)) - interval = max(MIN_TIME_BETWEEN_SCANS.seconds, + interval = max(MIN_TIME_BETWEEN_SCANS, config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)) def _see_vehicle(vehicle): @@ -91,8 +91,7 @@ def setup_scanner(hass, config, see): return True finally: - track_point_in_utc_time(hass, update, - now + timedelta(seconds=interval)) + track_point_in_utc_time(hass, update, now + interval) _LOGGER.info('Logging in to service') return update(utcnow()) From 63bf453c60ba03898eb7f957a23262490c44c30a Mon Sep 17 00:00:00 2001 From: Teemu R Date: Mon, 16 Jan 2017 06:48:36 +0100 Subject: [PATCH 03/10] Eq3bt bump version, expose away attribute (#5353) * eq3bt: read away ends attr * eq3bt: bump version to fix missing __init__, expose away_ends attribute. --- homeassistant/components/climate/eq3btsmart.py | 4 +++- requirements_all.txt | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/climate/eq3btsmart.py b/homeassistant/components/climate/eq3btsmart.py index 41697f7b31d..a8ab9bd30b2 100644 --- a/homeassistant/components/climate/eq3btsmart.py +++ b/homeassistant/components/climate/eq3btsmart.py @@ -17,7 +17,7 @@ from homeassistant.const import ( import homeassistant.helpers.config_validation as cv -REQUIREMENTS = ['python-eq3bt==0.1.2'] +REQUIREMENTS = ['python-eq3bt==0.1.4'] _LOGGER = logging.getLogger(__name__) @@ -29,6 +29,7 @@ ATTR_STATE_WINDOW_OPEN = "window_open" ATTR_STATE_VALVE = "valve" ATTR_STATE_LOCKED = "is_locked" ATTR_STATE_LOW_BAT = "low_battery" +ATTR_STATE_AWAY_END = "away_end" DEVICE_SCHEMA = vol.Schema({ vol.Required(CONF_MAC): cv.string, @@ -152,6 +153,7 @@ class EQ3BTSmartThermostat(ClimateDevice): ATTR_STATE_LOW_BAT: self._thermostat.low_battery, ATTR_STATE_VALVE: self._thermostat.valve_state, ATTR_STATE_WINDOW_OPEN: self._thermostat.window_open, + ATTR_STATE_AWAY_END: self._thermostat.away_end, } return dev_specific diff --git a/requirements_all.txt b/requirements_all.txt index ca9f9f422a7..3a1da1e78a9 100755 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -476,7 +476,7 @@ pysnmp==4.3.2 python-digitalocean==1.10.1 # homeassistant.components.climate.eq3btsmart -python-eq3bt==0.1.2 +python-eq3bt==0.1.4 # homeassistant.components.sensor.darksky python-forecastio==1.3.5 From 7af92d0bcaa3dae2a1bc1f3a51a1f04e6900649e Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Mon, 16 Jan 2017 11:06:23 +0100 Subject: [PATCH 04/10] Bugfix upc with aiohttp 1.2 (cookies) (#5362) --- .../components/device_tracker/upc_connect.py | 17 +++++------ tests/test_util/aiohttp.py | 29 ++++++++++++------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/homeassistant/components/device_tracker/upc_connect.py b/homeassistant/components/device_tracker/upc_connect.py index aafa9824a4e..13336e939a5 100644 --- a/homeassistant/components/device_tracker/upc_connect.py +++ b/homeassistant/components/device_tracker/upc_connect.py @@ -74,8 +74,11 @@ class UPCDeviceScanner(DeviceScanner): return [] raw = yield from self._async_ws_function(CMD_DEVICES) - xml_root = ET.fromstring(raw) + if raw is None: + _LOGGER.warning("Can't read device from %s", self.host) + return + xml_root = ET.fromstring(raw) return [mac.text for mac in xml_root.iter('MACAddr')] @asyncio.coroutine @@ -94,7 +97,8 @@ class UPCDeviceScanner(DeviceScanner): "http://{}/common_page/login.html".format(self.host) ) - self.token = self._async_get_token() + yield from response.text() + self.token = response.cookies['sessionToken'].value # login data = yield from self._async_ws_function(CMD_LOGIN, { @@ -144,7 +148,7 @@ class UPCDeviceScanner(DeviceScanner): # load data, store token for next request raw = yield from response.text() - self.token = self._async_get_token() + self.token = response.cookies['sessionToken'].value return raw @@ -155,10 +159,3 @@ class UPCDeviceScanner(DeviceScanner): finally: if response is not None: yield from response.release() - - def _async_get_token(self): - """Extract token from cookies.""" - cookie_manager = self.websession.cookie_jar.filter_cookies( - "http://{}".format(self.host)) - - return cookie_manager.get('sessionToken') diff --git a/tests/test_util/aiohttp.py b/tests/test_util/aiohttp.py index dcdf69395b4..afe2f626de7 100644 --- a/tests/test_util/aiohttp.py +++ b/tests/test_util/aiohttp.py @@ -37,11 +37,9 @@ class AiohttpClientMocker: content = b'' if params: url = str(yarl.URL(url).with_query(params)) - if cookies: - self._cookies.update(cookies) self._mocks.append(AiohttpClientMockResponse( - method, url, status, content, exc)) + method, url, status, content, cookies, exc)) def get(self, *args, **kwargs): """Register a mock get request.""" @@ -68,10 +66,6 @@ class AiohttpClientMocker: """Number of requests made.""" return len(self.mock_calls) - def filter_cookies(self, host): - """Return hosts cookies.""" - return self._cookies - def clear_requests(self): """Reset mock calls.""" self._mocks.clear() @@ -97,7 +91,7 @@ class AiohttpClientMocker: class AiohttpClientMockResponse: """Mock Aiohttp client response.""" - def __init__(self, method, url, status, response, exc=None): + def __init__(self, method, url, status, response, cookies=None, exc=None): """Initialize a fake response.""" self.method = method self._url = url @@ -107,6 +101,14 @@ class AiohttpClientMockResponse: self.response = response self.exc = exc + self._cookies = {} + + if cookies: + for name, data in cookies.items(): + cookie = mock.MagicMock() + cookie.value = data + self._cookies[name] = cookie + def match_request(self, method, url, params=None): """Test if response answers request.""" if method.lower() != self.method.lower(): @@ -140,6 +142,11 @@ class AiohttpClientMockResponse: return True + @property + def cookies(self): + """Return dict of cookies.""" + return self._cookies + @asyncio.coroutine def read(self): """Return mock response.""" @@ -160,6 +167,10 @@ class AiohttpClientMockResponse: """Mock release.""" pass + def close(self): + """Mock close.""" + pass + @contextmanager def mock_aiohttp_client(): @@ -173,6 +184,4 @@ def mock_aiohttp_client(): setattr(instance, method, functools.partial(mocker.match_request, method)) - instance.cookie_jar.filter_cookies = mocker.filter_cookies - yield mocker From 7bad0171ecfe2386e18b068ed0cae18971cbf450 Mon Sep 17 00:00:00 2001 From: Marcelo Moreira de Mello Date: Mon, 16 Jan 2017 11:36:35 -0500 Subject: [PATCH 05/10] Fixes #5357 which especify absolute path to save cookie used by USPS sensor. (#5358) Traceback (most recent call last): File "/home/hass/.virtualenvs/home_assistant/lib/python3.5/site-packages/homeassistant/helpers/entity_component.py", line 151, in _async_setup_platform entity_platform.add_entities, discovery_info File "/usr/local/lib/python3.5/asyncio/futures.py", line 361, in __iter__ yield self # This tells Task to wait for completion. File "/usr/local/lib/python3.5/asyncio/tasks.py", line 296, in _wakeup future.result() File "/usr/local/lib/python3.5/asyncio/futures.py", line 274, in result raise self._exception File "/usr/local/lib/python3.5/concurrent/futures/thread.py", line 55, in run result = self.fn(*self.args, **self.kwargs) File "/home/hass/.virtualenvs/home_assistant/lib/python3.5/site-packages/homeassistant/components/sensor/usps.py", line 48, in setup_platform add_devices([USPSSensor(session, config.get(CONF_UPDATE_INTERVAL))]) File "/home/hass/.virtualenvs/home_assistant/lib/python3.5/site-packages/homeassistant/components/sensor/usps.py", line 58, in __init__ self._profile = myusps.get_profile(session) File "/home/hass/.homeassistant/deps/myusps/__init__.py", line 100, in wrapped _login(*args) File "/home/hass/.homeassistant/deps/myusps/__init__.py", line 90, in _login _save_cookies(session.cookies, session.auth.cookie_path) File "/home/hass/.homeassistant/deps/myusps/__init__.py", line 41, in _save_cookies with open(filename, 'wb') as handle: PermissionError: [Errno 13] Permission denied: './usps_cookies.pickle' --- homeassistant/components/sensor/usps.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/usps.py b/homeassistant/components/sensor/usps.py index e9562667f6d..0bc7f6cbd5a 100644 --- a/homeassistant/components/sensor/usps.py +++ b/homeassistant/components/sensor/usps.py @@ -22,6 +22,7 @@ REQUIREMENTS = ['myusps==1.0.1'] _LOGGER = logging.getLogger(__name__) +COOKIE = 'usps_cookies.pickle' CONF_UPDATE_INTERVAL = 'update_interval' ICON = 'mdi:package-variant-closed' STATUS_DELIVERED = 'delivered' @@ -39,8 +40,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None): """Setup the USPS platform.""" import myusps try: + cookie = hass.config.path(COOKIE) session = myusps.get_session(config.get(CONF_USERNAME), - config.get(CONF_PASSWORD)) + config.get(CONF_PASSWORD), + cookie_path=cookie) except myusps.USPSError: _LOGGER.exception('Could not connect to My USPS') return False From 372b54534a5bacf6a06b317db1b494ccdcd2c4fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=B8yer=20Iversen?= Date: Mon, 16 Jan 2017 18:03:26 +0100 Subject: [PATCH 06/10] Fix python-nest release number (#5369) * fix_#5365 * fix_#5365 --- homeassistant/components/nest.py | 2 +- requirements_all.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/nest.py b/homeassistant/components/nest.py index 30a256f1c37..337cc8f9160 100644 --- a/homeassistant/components/nest.py +++ b/homeassistant/components/nest.py @@ -20,7 +20,7 @@ _LOGGER = logging.getLogger(__name__) REQUIREMENTS = [ 'http://github.com/technicalpickles/python-nest' '/archive/e6c9d56a8df455d4d7746389811f2c1387e8cb33.zip' # nest-cam branch - '#python-nest==3.0.3'] + '#python-nest==3.0.2'] DOMAIN = 'nest' diff --git a/requirements_all.txt b/requirements_all.txt index 3a1da1e78a9..9b4fbcd7aa6 100755 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -178,7 +178,7 @@ hikvision==0.4 # http://github.com/adafruit/Adafruit_Python_DHT/archive/310c59b0293354d07d94375f1365f7b9b9110c7d.zip#Adafruit_DHT==1.3.0 # homeassistant.components.nest -http://github.com/technicalpickles/python-nest/archive/e6c9d56a8df455d4d7746389811f2c1387e8cb33.zip#python-nest==3.0.3 +http://github.com/technicalpickles/python-nest/archive/e6c9d56a8df455d4d7746389811f2c1387e8cb33.zip#python-nest==3.0.2 # homeassistant.components.switch.dlink https://github.com/LinuxChristian/pyW215/archive/v0.3.7.zip#pyW215==0.3.7 From 836eed2a153a0994109d8be196c0db2443424b13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20H=C3=B8yer=20Iversen?= Date: Tue, 17 Jan 2017 06:52:12 +0100 Subject: [PATCH 07/10] fix bug in flux_led (#5373) --- homeassistant/components/light/flux_led.py | 1 + 1 file changed, 1 insertion(+) diff --git a/homeassistant/components/light/flux_led.py b/homeassistant/components/light/flux_led.py index 22dd40b30ef..46eec35724a 100644 --- a/homeassistant/components/light/flux_led.py +++ b/homeassistant/components/light/flux_led.py @@ -72,6 +72,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): continue device['name'] = device['id'] + " " + ipaddr device[ATTR_MODE] = 'rgbw' + device[CONF_PROTOCOL] = None light = FluxLight(device) if light.is_valid: lights.append(light) From 28e5659eee55f7a98d0946e2435d92236d91fddd Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 16 Jan 2017 22:08:47 -0800 Subject: [PATCH 08/10] Fix load_yaml default value (#5383) --- homeassistant/util/yaml.py | 2 +- tests/util/test_yaml.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/homeassistant/util/yaml.py b/homeassistant/util/yaml.py index 64b63b31ca6..00508862279 100644 --- a/homeassistant/util/yaml.py +++ b/homeassistant/util/yaml.py @@ -60,7 +60,7 @@ def load_yaml(fname: str) -> Union[List, Dict]: with open(fname, encoding='utf-8') as conf_file: # If configuration file is empty YAML returns None # We convert that to an empty dict - return yaml.load(conf_file, Loader=SafeLineLoader) or {} + return yaml.load(conf_file, Loader=SafeLineLoader) or OrderedDict() except yaml.YAMLError as exc: _LOGGER.error(exc) raise HomeAssistantError(exc) diff --git a/tests/util/test_yaml.py b/tests/util/test_yaml.py index 3305fbea6c9..79fd994ce86 100644 --- a/tests/util/test_yaml.py +++ b/tests/util/test_yaml.py @@ -74,6 +74,12 @@ class TestYaml(unittest.TestCase): doc = yaml.yaml.safe_load(file) assert doc["key"] == "value" + with patch_yaml_files({'test.yaml': None}): + conf = 'key: !include test.yaml' + with io.StringIO(conf) as file: + doc = yaml.yaml.safe_load(file) + assert doc["key"] == {} + @patch('homeassistant.util.yaml.os.walk') def test_include_dir_list(self, mock_walk): """Test include dir list yaml.""" From 4603cf4f386cca6fa5581db828b329813107c2be Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 16 Jan 2017 22:09:17 -0800 Subject: [PATCH 09/10] Bump release to 0.36.1 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index b5c04c26d0b..c6200fb331d 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -2,7 +2,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 0 MINOR_VERSION = 36 -PATCH_VERSION = '0' +PATCH_VERSION = '1' __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) REQUIRED_PYTHON_VER = (3, 4, 2) From 2625fee861798ce1e703b21ec1f5ddc576f9281f Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 15 Jan 2017 09:16:46 -0800 Subject: [PATCH 10/10] Fix script release (#5345) --- script/release | 3 --- 1 file changed, 3 deletions(-) diff --git a/script/release b/script/release index 3bcddcfef76..65a6339cedc 100755 --- a/script/release +++ b/script/release @@ -1,9 +1,6 @@ #!/bin/sh # Pushes a new version to PyPi. -# Stop on errors -set -e - cd "$(dirname "$0")/.." head -n 5 homeassistant/const.py | tail -n 1 | grep PATCH_VERSION > /dev/null