Hello Python 3.5 (#12610)

* Hello Python 3.5

* Fix test

* Fix tests

* Fix never awaited block till done warnings
This commit is contained in:
Paulus Schoutsen 2018-02-22 23:22:27 -08:00 committed by GitHub
parent 156206dfee
commit 6ee3c1b3e5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 36 additions and 56 deletions

View file

@ -6,12 +6,10 @@ addons:
matrix:
fast_finish: true
include:
- python: "3.4.2"
- python: "3.5.3"
env: TOXENV=lint
- python: "3.4.2"
- python: "3.5.3"
env: TOXENV=pylint
- python: "3.4.2"
env: TOXENV=py34
# - python: "3.5"
# env: TOXENV=typing
- python: "3.5.3"

View file

@ -15,7 +15,6 @@ from homeassistant.const import (
__version__,
EVENT_HOMEASSISTANT_START,
REQUIRED_PYTHON_VER,
REQUIRED_PYTHON_VER_WIN,
RESTART_EXIT_CODE,
)
@ -33,12 +32,7 @@ def attempt_use_uvloop():
def validate_python() -> None:
"""Validate that the right Python version is running."""
if sys.platform == "win32" and \
sys.version_info[:3] < REQUIRED_PYTHON_VER_WIN:
print("Home Assistant requires at least Python {}.{}.{}".format(
*REQUIRED_PYTHON_VER_WIN))
sys.exit(1)
elif sys.version_info[:3] < REQUIRED_PYTHON_VER:
if sys.version_info[:3] < REQUIRED_PYTHON_VER:
print("Home Assistant requires at least Python {}.{}.{}".format(
*REQUIRED_PYTHON_VER))
sys.exit(1)

View file

@ -5,8 +5,7 @@ MINOR_VERSION = 65
PATCH_VERSION = '0.dev0'
__short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION)
__version__ = '{}.{}'.format(__short_version__, PATCH_VERSION)
REQUIRED_PYTHON_VER = (3, 4, 2)
REQUIRED_PYTHON_VER_WIN = (3, 5, 2)
REQUIRED_PYTHON_VER = (3, 5, 3)
# Format for platforms
PLATFORM_FORMAT = '{}.{}'

View file

@ -164,8 +164,7 @@ class HomeAssistant(object):
finally:
self.loop.close()
@asyncio.coroutine
def async_start(self):
async def async_start(self):
"""Finalize startup from inside the event loop.
This method is a coroutine.
@ -181,7 +180,7 @@ class HomeAssistant(object):
# Only block for EVENT_HOMEASSISTANT_START listener
self.async_stop_track_tasks()
with timeout(TIMEOUT_EVENT_START, loop=self.loop):
yield from self.async_block_till_done()
await self.async_block_till_done()
except asyncio.TimeoutError:
_LOGGER.warning(
'Something is blocking Home Assistant from wrapping up the '
@ -190,7 +189,7 @@ class HomeAssistant(object):
', '.join(self.config.components))
# Allow automations to set up the start triggers before changing state
yield from asyncio.sleep(0, loop=self.loop)
await asyncio.sleep(0, loop=self.loop)
self.state = CoreState.running
_async_create_timer(self)
@ -259,27 +258,25 @@ class HomeAssistant(object):
run_coroutine_threadsafe(
self.async_block_till_done(), loop=self.loop).result()
@asyncio.coroutine
def async_block_till_done(self):
async def async_block_till_done(self):
"""Block till all pending work is done."""
# To flush out any call_soon_threadsafe
yield from asyncio.sleep(0, loop=self.loop)
await asyncio.sleep(0, loop=self.loop)
while self._pending_tasks:
pending = [task for task in self._pending_tasks
if not task.done()]
self._pending_tasks.clear()
if pending:
yield from asyncio.wait(pending, loop=self.loop)
await asyncio.wait(pending, loop=self.loop)
else:
yield from asyncio.sleep(0, loop=self.loop)
await asyncio.sleep(0, loop=self.loop)
def stop(self) -> None:
"""Stop Home Assistant and shuts down all threads."""
fire_coroutine_threadsafe(self.async_stop(), self.loop)
@asyncio.coroutine
def async_stop(self, exit_code=0) -> None:
async def async_stop(self, exit_code=0) -> None:
"""Stop Home Assistant and shuts down all threads.
This method is a coroutine.
@ -288,12 +285,12 @@ class HomeAssistant(object):
self.state = CoreState.stopping
self.async_track_tasks()
self.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
yield from self.async_block_till_done()
await self.async_block_till_done()
# stage 2
self.state = CoreState.not_running
self.bus.async_fire(EVENT_HOMEASSISTANT_CLOSE)
yield from self.async_block_till_done()
await self.async_block_till_done()
self.executor.shutdown()
self.exit_code = exit_code
@ -912,8 +909,8 @@ class ServiceRegistry(object):
self._hass.loop
).result()
@asyncio.coroutine
def async_call(self, domain, service, service_data=None, blocking=False):
async def async_call(self, domain, service, service_data=None,
blocking=False):
"""
Call a service.
@ -956,14 +953,13 @@ class ServiceRegistry(object):
self._hass.bus.async_fire(EVENT_CALL_SERVICE, event_data)
if blocking:
done, _ = yield from asyncio.wait(
done, _ = await asyncio.wait(
[fut], loop=self._hass.loop, timeout=SERVICE_CALL_LIMIT)
success = bool(done)
unsub()
return success
@asyncio.coroutine
def _event_to_service_call(self, event):
async def _event_to_service_call(self, event):
"""Handle the SERVICE_CALLED events from the EventBus."""
service_data = event.data.get(ATTR_SERVICE_DATA) or {}
domain = event.data.get(ATTR_DOMAIN).lower()
@ -1007,7 +1003,7 @@ class ServiceRegistry(object):
service_handler.func(service_call)
fire_service_executed()
elif service_handler.is_coroutinefunction:
yield from service_handler.func(service_call)
await service_handler.func(service_call)
fire_service_executed()
else:
def execute_service():
@ -1015,7 +1011,7 @@ class ServiceRegistry(object):
service_handler.func(service_call)
fire_service_executed()
yield from self._hass.async_add_job(execute_service)
await self._hass.async_add_job(execute_service)
except Exception: # pylint: disable=broad-except
_LOGGER.exception('Error executing service %s', service_call)

View file

@ -1,7 +1,5 @@
#!/usr/bin/env python3
"""Home Assistant setup script."""
import sys
from setuptools import setup, find_packages
import homeassistant.const as hass_const
@ -27,7 +25,6 @@ PROJECT_CLASSIFIERS = [
'Intended Audience :: Developers',
'License :: OSI Approved :: Apache Software License',
'Operating System :: OS Independent',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Topic :: Home Automation'
@ -64,9 +61,7 @@ REQUIRES = [
MIN_PY_VERSION = '.'.join(map(
str,
hass_const.REQUIRED_PYTHON_VER_WIN
if sys.platform.startswith('win')
else hass_const.REQUIRED_PYTHON_VER))
hass_const.REQUIRED_PYTHON_VER))
setup(
name=PROJECT_PACKAGE_NAME,

View file

@ -114,8 +114,6 @@ def test_valid_credentials(
result = hass.loop.run_until_complete(
async_setup_scanner(hass, config, mock_see))
hass.async_block_till_done()
assert result
assert mock_create_session.called

View file

@ -420,11 +420,11 @@ def test_proper_put_state_request(hue_client):
# pylint: disable=invalid-name
def perform_put_test_on_ceiling_lights(hass_hue, hue_client,
async def perform_put_test_on_ceiling_lights(hass_hue, hue_client,
content_type='application/json'):
"""Test the setting of a light."""
# Turn the office light off first
yield from hass_hue.services.async_call(
await hass_hue.services.async_call(
light.DOMAIN, const.SERVICE_TURN_OFF,
{const.ATTR_ENTITY_ID: 'light.ceiling_lights'},
blocking=True)
@ -433,14 +433,14 @@ def perform_put_test_on_ceiling_lights(hass_hue, hue_client,
assert ceiling_lights.state == STATE_OFF
# Go through the API to turn it on
office_result = yield from perform_put_light_state(
office_result = await perform_put_light_state(
hass_hue, hue_client,
'light.ceiling_lights', True, 56, content_type)
assert office_result.status == 200
assert 'application/json' in office_result.headers['content-type']
office_result_json = yield from office_result.json()
office_result_json = await office_result.json()
assert len(office_result_json) == 2

View file

@ -21,8 +21,8 @@ def test_subscribing_config_topic(hass, mqtt_mock):
assert call_args[2] == 0
@asyncio.coroutine
@patch('homeassistant.components.mqtt.discovery.async_load_platform')
@asyncio.coroutine
def test_invalid_topic(mock_load_platform, hass, mqtt_mock):
"""Test sending to invalid topic."""
mock_load_platform.return_value = mock_coro()
@ -34,8 +34,8 @@ def test_invalid_topic(mock_load_platform, hass, mqtt_mock):
assert not mock_load_platform.called
@asyncio.coroutine
@patch('homeassistant.components.mqtt.discovery.async_load_platform')
@asyncio.coroutine
def test_invalid_json(mock_load_platform, hass, mqtt_mock, caplog):
"""Test sending in invalid JSON."""
mock_load_platform.return_value = mock_coro()
@ -48,8 +48,8 @@ def test_invalid_json(mock_load_platform, hass, mqtt_mock, caplog):
assert not mock_load_platform.called
@asyncio.coroutine
@patch('homeassistant.components.mqtt.discovery.async_load_platform')
@asyncio.coroutine
def test_only_valid_components(mock_load_platform, hass, mqtt_mock, caplog):
"""Test for a valid component."""
mock_load_platform.return_value = mock_coro()

View file

@ -165,7 +165,7 @@ class TestRecorderPurge(unittest.TestCase):
# run purge method - no service data, use defaults
self.hass.services.call('recorder', 'purge')
self.hass.async_block_till_done()
self.hass.block_till_done()
# Small wait for recorder thread
self.hass.data[DATA_INSTANCE].block_till_done()
@ -177,7 +177,7 @@ class TestRecorderPurge(unittest.TestCase):
# run purge method - correct service data
self.hass.services.call('recorder', 'purge',
service_data=service_data)
self.hass.async_block_till_done()
self.hass.block_till_done()
# Small wait for recorder thread
self.hass.data[DATA_INSTANCE].block_till_done()
@ -203,6 +203,6 @@ class TestRecorderPurge(unittest.TestCase):
self.assertFalse(self.hass.data[DATA_INSTANCE].did_vacuum)
self.hass.services.call('recorder', 'purge',
service_data=service_data)
self.hass.async_block_till_done()
self.hass.block_till_done()
self.hass.data[DATA_INSTANCE].block_till_done()
self.assertTrue(self.hass.data[DATA_INSTANCE].did_vacuum)

View file

@ -22,20 +22,20 @@ def test_validate_python(mock_exit):
mock_exit.reset_mock()
with patch('sys.version_info',
new_callable=PropertyMock(return_value=(3, 4, 1))):
new_callable=PropertyMock(return_value=(3, 4, 2))):
main.validate_python()
assert mock_exit.called is True
mock_exit.reset_mock()
with patch('sys.version_info',
new_callable=PropertyMock(return_value=(3, 4, 2))):
new_callable=PropertyMock(return_value=(3, 5, 2))):
main.validate_python()
assert mock_exit.called is False
assert mock_exit.called is True
mock_exit.reset_mock()
with patch('sys.version_info',
new_callable=PropertyMock(return_value=(3, 5, 1))):
new_callable=PropertyMock(return_value=(3, 5, 3))):
main.validate_python()
assert mock_exit.called is False