Skip to content

Commit

Permalink
Hello Python 3.5 (#12610)
Browse files Browse the repository at this point in the history
* Hello Python 3.5

* Fix test

* Fix tests

* Fix never awaited block till done warnings
  • Loading branch information
balloob authored Feb 23, 2018
1 parent 156206d commit 6ee3c1b
Show file tree
Hide file tree
Showing 10 changed files with 36 additions and 56 deletions.
6 changes: 2 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
8 changes: 1 addition & 7 deletions homeassistant/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
__version__,
EVENT_HOMEASSISTANT_START,
REQUIRED_PYTHON_VER,
REQUIRED_PYTHON_VER_WIN,
RESTART_EXIT_CODE,
)

Expand All @@ -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)
Expand Down
3 changes: 1 addition & 2 deletions homeassistant/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
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)

This comment has been minimized.

Copy link
@pintman

pintman Mar 16, 2018

Is there anything special with Python 3.5.3 or is homeassistant still running with 3.5.2? Asking because my distribution currently only delivers 3.5.2.

This comment has been minimized.

This comment has been minimized.

Copy link
@pintman

pintman via email Mar 17, 2018


# Format for platforms
PLATFORM_FORMAT = '{}.{}'
Expand Down
36 changes: 16 additions & 20 deletions homeassistant/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,7 @@ def start(self) -> None:
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.
Expand All @@ -181,7 +180,7 @@ def async_start(self):
# 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 '
Expand All @@ -190,7 +189,7 @@ def async_start(self):
', '.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)

Expand Down Expand Up @@ -259,27 +258,25 @@ def block_till_done(self) -> None:
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.
Expand All @@ -288,12 +285,12 @@ def async_stop(self, exit_code=0) -> None:
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
Expand Down Expand Up @@ -912,8 +909,8 @@ def call(self, domain, service, service_data=None, blocking=False):
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.
Expand Down Expand Up @@ -956,14 +953,13 @@ def service_executed(event):
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()
Expand Down Expand Up @@ -1007,15 +1003,15 @@ def fire_service_executed():
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():
"""Execute a service and fires a SERVICE_EXECUTED event."""
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)

Expand Down
7 changes: 1 addition & 6 deletions setup.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -27,7 +25,6 @@
'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'
Expand Down Expand Up @@ -64,9 +61,7 @@

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,
Expand Down
2 changes: 0 additions & 2 deletions tests/components/device_tracker/test_automatic.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,6 @@ def ws_connect():
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
Expand Down
10 changes: 5 additions & 5 deletions tests/components/emulated_hue/test_hue_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
content_type='application/json'):
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)
Expand All @@ -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

Expand Down
6 changes: 3 additions & 3 deletions tests/components/mqtt/test_discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand Down
6 changes: 3 additions & 3 deletions tests/components/recorder/test_purge.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def test_purge_method(self):

# 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()
Expand All @@ -177,7 +177,7 @@ def test_purge_method(self):
# 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()
Expand All @@ -203,6 +203,6 @@ def test_purge_method(self):
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)
8 changes: 4 additions & 4 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 6ee3c1b

Please sign in to comment.