Merge pull request #16064 from home-assistant/rc

0.76.1
This commit is contained in:
Paulus Schoutsen 2018-08-19 20:07:44 +02:00 committed by GitHub
commit e1b2e00cf6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 78 additions and 30 deletions

View File

@ -26,7 +26,7 @@ from homeassistant.helpers.translation import async_get_translations
from homeassistant.loader import bind_hass from homeassistant.loader import bind_hass
from homeassistant.util.yaml import load_yaml from homeassistant.util.yaml import load_yaml
REQUIREMENTS = ['home-assistant-frontend==20180816.1'] REQUIREMENTS = ['home-assistant-frontend==20180818.0']
DOMAIN = 'frontend' DOMAIN = 'frontend'
DEPENDENCIES = ['api', 'websocket_api', 'http', 'system_log', DEPENDENCIES = ['api', 'websocket_api', 'http', 'system_log',

View File

@ -156,6 +156,8 @@ def async_setup(hass, config):
DOMAIN, platform_name_slug, async_notify_message, DOMAIN, platform_name_slug, async_notify_message,
schema=NOTIFY_SERVICE_SCHEMA) schema=NOTIFY_SERVICE_SCHEMA)
hass.config.components.add('{}.{}'.format(DOMAIN, p_type))
return True return True
setup_tasks = [async_setup_platform(p_type, p_config) for p_type, p_config setup_tasks = [async_setup_platform(p_type, p_config) for p_type, p_config

View File

@ -1,24 +1,35 @@
"""Schema migration helpers.""" """Schema migration helpers."""
import logging import logging
import os
from .util import session_scope from .util import session_scope
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
PROGRESS_FILE = '.migration_progress'
def migrate_schema(instance): def migrate_schema(instance):
"""Check if the schema needs to be upgraded.""" """Check if the schema needs to be upgraded."""
from .models import SchemaChanges, SCHEMA_VERSION from .models import SchemaChanges, SCHEMA_VERSION
progress_path = instance.hass.config.path(PROGRESS_FILE)
with session_scope(session=instance.get_session()) as session: with session_scope(session=instance.get_session()) as session:
res = session.query(SchemaChanges).order_by( res = session.query(SchemaChanges).order_by(
SchemaChanges.change_id.desc()).first() SchemaChanges.change_id.desc()).first()
current_version = getattr(res, 'schema_version', None) current_version = getattr(res, 'schema_version', None)
if current_version == SCHEMA_VERSION: if current_version == SCHEMA_VERSION:
# Clean up if old migration left file
if os.path.isfile(progress_path):
_LOGGER.warning("Found existing migration file, cleaning up")
os.remove(instance.hass.config.path(PROGRESS_FILE))
return return
_LOGGER.debug("Database requires upgrade. Schema version: %s", with open(progress_path, 'w'):
pass
_LOGGER.warning("Database requires upgrade. Schema version: %s",
current_version) current_version)
if current_version is None: if current_version is None:
@ -26,6 +37,7 @@ def migrate_schema(instance):
_LOGGER.debug("No schema version found. Inspected version: %s", _LOGGER.debug("No schema version found. Inspected version: %s",
current_version) current_version)
try:
for version in range(current_version, SCHEMA_VERSION): for version in range(current_version, SCHEMA_VERSION):
new_version = version + 1 new_version = version + 1
_LOGGER.info("Upgrading recorder db schema to version %s", _LOGGER.info("Upgrading recorder db schema to version %s",
@ -34,6 +46,8 @@ def migrate_schema(instance):
session.add(SchemaChanges(schema_version=new_version)) session.add(SchemaChanges(schema_version=new_version))
_LOGGER.info("Upgrade to version %s done", new_version) _LOGGER.info("Upgrade to version %s done", new_version)
finally:
os.remove(instance.hass.config.path(PROGRESS_FILE))
def _create_index(engine, table_name, index_name): def _create_index(engine, table_name, index_name):
@ -117,22 +131,37 @@ def _drop_index(engine, table_name, index_name):
def _add_columns(engine, table_name, columns_def): def _add_columns(engine, table_name, columns_def):
"""Add columns to a table.""" """Add columns to a table."""
from sqlalchemy import text from sqlalchemy import text
from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.exc import OperationalError
columns_def = ['ADD COLUMN {}'.format(col_def) for col_def in columns_def] _LOGGER.info("Adding columns %s to table %s. Note: this can take several "
"minutes on large databases and slow computers. Please "
"be patient!",
', '.join(column.split(' ')[0] for column in columns_def),
table_name)
columns_def = ['ADD {}'.format(col_def) for col_def in columns_def]
try: try:
engine.execute(text("ALTER TABLE {table} {columns_def}".format( engine.execute(text("ALTER TABLE {table} {columns_def}".format(
table=table_name, table=table_name,
columns_def=', '.join(columns_def)))) columns_def=', '.join(columns_def))))
return return
except SQLAlchemyError: except OperationalError:
pass # Some engines support adding all columns at once,
# this error is when they dont'
_LOGGER.info('Unable to use quick column add. Adding 1 by 1.')
for column_def in columns_def: for column_def in columns_def:
try:
engine.execute(text("ALTER TABLE {table} {column_def}".format( engine.execute(text("ALTER TABLE {table} {column_def}".format(
table=table_name, table=table_name,
column_def=column_def))) column_def=column_def)))
except OperationalError as err:
if 'duplicate' not in str(err).lower():
raise
_LOGGER.warning('Column %s already exists on %s, continueing',
column_def.split(' ')[1], table_name)
def _apply_update(engine, new_version, old_version): def _apply_update(engine, new_version, old_version):

View File

@ -10,14 +10,14 @@ import voluptuous as vol
from homeassistant.core import callback from homeassistant.core import callback
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.const import (CONF_USERNAME, CONF_PASSWORD) from homeassistant.const import (CONF_USERNAME, CONF_PASSWORD, CONF_PLATFORM)
from homeassistant.helpers import discovery from homeassistant.helpers import discovery
from homeassistant.helpers.dispatcher import ( from homeassistant.helpers.dispatcher import (
dispatcher_send, async_dispatcher_connect) dispatcher_send, async_dispatcher_connect)
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from homeassistant.helpers.event import track_time_interval from homeassistant.helpers.event import track_time_interval
REQUIREMENTS = ['tuyapy==0.1.2'] REQUIREMENTS = ['tuyapy==0.1.3']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -45,7 +45,8 @@ CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({ DOMAIN: vol.Schema({
vol.Required(CONF_PASSWORD): cv.string, vol.Required(CONF_PASSWORD): cv.string,
vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_COUNTRYCODE): cv.string vol.Required(CONF_COUNTRYCODE): cv.string,
vol.Optional(CONF_PLATFORM, default='tuya'): cv.string,
}) })
}, extra=vol.ALLOW_EXTRA) }, extra=vol.ALLOW_EXTRA)
@ -58,9 +59,10 @@ def setup(hass, config):
username = config[DOMAIN][CONF_USERNAME] username = config[DOMAIN][CONF_USERNAME]
password = config[DOMAIN][CONF_PASSWORD] password = config[DOMAIN][CONF_PASSWORD]
country_code = config[DOMAIN][CONF_COUNTRYCODE] country_code = config[DOMAIN][CONF_COUNTRYCODE]
platform = config[DOMAIN][CONF_PLATFORM]
hass.data[DATA_TUYA] = tuya hass.data[DATA_TUYA] = tuya
tuya.init(username, password, country_code) tuya.init(username, password, country_code, platform)
hass.data[DOMAIN] = { hass.data[DOMAIN] = {
'entities': {} 'entities': {}
} }

View File

@ -2,7 +2,7 @@
"""Constants used by Home Assistant components.""" """Constants used by Home Assistant components."""
MAJOR_VERSION = 0 MAJOR_VERSION = 0
MINOR_VERSION = 76 MINOR_VERSION = 76
PATCH_VERSION = '0' PATCH_VERSION = '1'
__short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION)
__version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION)
REQUIRED_PYTHON_VER = (3, 5, 3) REQUIRED_PYTHON_VER = (3, 5, 3)

View File

@ -432,7 +432,7 @@ hole==0.3.0
holidays==0.9.6 holidays==0.9.6
# homeassistant.components.frontend # homeassistant.components.frontend
home-assistant-frontend==20180816.1 home-assistant-frontend==20180818.0
# homeassistant.components.homekit_controller # homeassistant.components.homekit_controller
# homekit==0.10 # homekit==0.10
@ -1389,7 +1389,7 @@ tplink==0.2.1
transmissionrpc==0.11 transmissionrpc==0.11
# homeassistant.components.tuya # homeassistant.components.tuya
tuyapy==0.1.2 tuyapy==0.1.3
# homeassistant.components.twilio # homeassistant.components.twilio
twilio==5.7.0 twilio==5.7.0

View File

@ -81,7 +81,7 @@ hbmqtt==0.9.2
holidays==0.9.6 holidays==0.9.6
# homeassistant.components.frontend # homeassistant.components.frontend
home-assistant-frontend==20180816.1 home-assistant-frontend==20180818.0
# homeassistant.components.homematicip_cloud # homeassistant.components.homematicip_cloud
homematicip==0.9.8 homematicip==0.9.8

View File

@ -5,11 +5,11 @@ from unittest.mock import patch, call
import pytest import pytest
from sqlalchemy import create_engine from sqlalchemy import create_engine
from sqlalchemy.pool import StaticPool
from homeassistant.bootstrap import async_setup_component from homeassistant.bootstrap import async_setup_component
from homeassistant.components.recorder import wait_connection_ready, migration from homeassistant.components.recorder import (
from homeassistant.components.recorder.models import SCHEMA_VERSION wait_connection_ready, migration, const, models)
from homeassistant.components.recorder.const import DATA_INSTANCE
from tests.components.recorder import models_original from tests.components.recorder import models_original
@ -37,8 +37,8 @@ def test_schema_update_calls(hass):
yield from wait_connection_ready(hass) yield from wait_connection_ready(hass)
update.assert_has_calls([ update.assert_has_calls([
call(hass.data[DATA_INSTANCE].engine, version+1, 0) for version call(hass.data[const.DATA_INSTANCE].engine, version+1, 0) for version
in range(0, SCHEMA_VERSION)]) in range(0, models.SCHEMA_VERSION)])
@asyncio.coroutine @asyncio.coroutine
@ -65,3 +65,18 @@ def test_invalid_update():
"""Test that an invalid new version raises an exception.""" """Test that an invalid new version raises an exception."""
with pytest.raises(ValueError): with pytest.raises(ValueError):
migration._apply_update(None, -1, 0) migration._apply_update(None, -1, 0)
def test_forgiving_add_column():
"""Test that add column will continue if column exists."""
engine = create_engine(
'sqlite://',
poolclass=StaticPool
)
engine.execute('CREATE TABLE hello (id int)')
migration._add_columns(engine, 'hello', [
'context_id CHARACTER(36)',
])
migration._add_columns(engine, 'hello', [
'context_id CHARACTER(36)',
])