Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hello Python 3.5 #12610

Merged
merged 4 commits into from
Feb 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)

# 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