diff --git a/CODEOWNERS b/CODEOWNERS index d6d2b236eb6..bd21c2fd494 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -82,6 +82,7 @@ homeassistant/components/gearbest/* @HerrHofrat homeassistant/components/gitter/* @fabaff homeassistant/components/glances/* @fabaff homeassistant/components/gntp/* @robbiet480 +homeassistant/components/google_translate/* @awarecan homeassistant/components/google_travel_time/* @robbiet480 homeassistant/components/googlehome/* @ludeeus homeassistant/components/gpsd/* @fabaff diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index 77714f8f10d..c2039161ceb 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -78,9 +78,6 @@ async def async_from_config_dict(config: Dict[str, Any], "Further initialization aborted") return None - await hass.async_add_executor_job( - conf_util.process_ha_config_upgrade, hass) - # Make a copy because we are mutating it. config = OrderedDict(config) @@ -167,6 +164,9 @@ async def async_from_config_file(config_path: str, async_enable_logging(hass, verbose, log_rotate_days, log_file, log_no_color) + await hass.async_add_executor_job( + conf_util.process_ha_config_upgrade, hass) + try: config_dict = await hass.async_add_executor_job( conf_util.load_yaml_config_file, config_path) diff --git a/homeassistant/components/google/manifest.json b/homeassistant/components/google/manifest.json index 2db50b2d5b9..4c7e82ecfef 100644 --- a/homeassistant/components/google/manifest.json +++ b/homeassistant/components/google/manifest.json @@ -3,7 +3,6 @@ "name": "Google", "documentation": "https://www.home-assistant.io/components/google", "requirements": [ - "gTTS-token==1.1.3", "google-api-python-client==1.6.4", "httplib2==0.10.3", "oauth2client==4.0.0" diff --git a/homeassistant/components/google_translate/__init__.py b/homeassistant/components/google_translate/__init__.py new file mode 100644 index 00000000000..f7860c57d99 --- /dev/null +++ b/homeassistant/components/google_translate/__init__.py @@ -0,0 +1 @@ +"""The google_translate component.""" diff --git a/homeassistant/components/google_translate/manifest.json b/homeassistant/components/google_translate/manifest.json new file mode 100644 index 00000000000..cb3cd350c04 --- /dev/null +++ b/homeassistant/components/google_translate/manifest.json @@ -0,0 +1,12 @@ +{ + "domain": "google_translate", + "name": "Google Translate", + "documentation": "https://www.home-assistant.io/components/google_translate", + "requirements": [ + "gTTS-token==1.1.3" + ], + "dependencies": [], + "codeowners": [ + "@awarecan" + ] +} diff --git a/homeassistant/components/google/tts.py b/homeassistant/components/google_translate/tts.py similarity index 100% rename from homeassistant/components/google/tts.py rename to homeassistant/components/google_translate/tts.py diff --git a/homeassistant/components/tts/__init__.py b/homeassistant/components/tts/__init__.py index ccb7989a6cf..8af22fbb460 100644 --- a/homeassistant/components/tts/__init__.py +++ b/homeassistant/components/tts/__init__.py @@ -17,7 +17,7 @@ from homeassistant.components.media_player.const import ( ATTR_MEDIA_CONTENT_ID, ATTR_MEDIA_CONTENT_TYPE, MEDIA_TYPE_MUSIC, SERVICE_PLAY_MEDIA) from homeassistant.components.media_player.const import DOMAIN as DOMAIN_MP -from homeassistant.const import ATTR_ENTITY_ID, ENTITY_MATCH_ALL +from homeassistant.const import ATTR_ENTITY_ID, ENTITY_MATCH_ALL, CONF_PLATFORM from homeassistant.core import callback from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import config_per_platform @@ -32,11 +32,12 @@ ATTR_MESSAGE = 'message' ATTR_OPTIONS = 'options' ATTR_PLATFORM = 'platform' +CONF_BASE_URL = 'base_url' CONF_CACHE = 'cache' CONF_CACHE_DIR = 'cache_dir' CONF_LANG = 'language' +CONF_SERVICE_NAME = 'service_name' CONF_TIME_MEMORY = 'time_memory' -CONF_BASE_URL = 'base_url' DEFAULT_CACHE = True DEFAULT_CACHE_DIR = 'tts' @@ -53,12 +54,24 @@ _RE_VOICE_FILE = re.compile( r"([a-f0-9]{40})_([^_]+)_([^_]+)_([a-z_]+)\.[a-z0-9]{3,4}") KEY_PATTERN = '{0}_{1}_{2}_{3}' + +def _deprecated_platform(value): + """Validate if platform is deprecated.""" + if value == 'google': + raise vol.Invalid( + 'google tts service has been renamed to google_translate,' + ' please update your configuration.') + return value + + PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA.extend({ + vol.Required(CONF_PLATFORM): vol.All(cv.string, _deprecated_platform), vol.Optional(CONF_CACHE, default=DEFAULT_CACHE): cv.boolean, vol.Optional(CONF_CACHE_DIR, default=DEFAULT_CACHE_DIR): cv.string, vol.Optional(CONF_TIME_MEMORY, default=DEFAULT_TIME_MEMORY): vol.All(vol.Coerce(int), vol.Range(min=60, max=57600)), vol.Optional(CONF_BASE_URL): cv.string, + vol.Optional(CONF_SERVICE_NAME): cv.string, }) PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE.extend(PLATFORM_SCHEMA.schema) @@ -142,8 +155,10 @@ async def async_setup(hass, config): await hass.services.async_call( DOMAIN_MP, SERVICE_PLAY_MEDIA, data, blocking=True) + service_name = p_config.get(CONF_SERVICE_NAME, "{}_{}".format( + p_type, SERVICE_SAY)) hass.services.async_register( - DOMAIN, "{}_{}".format(p_type, SERVICE_SAY), async_say_handle, + DOMAIN, service_name, async_say_handle, schema=SCHEMA_SERVICE_SAY) setup_tasks = [async_setup_platform(p_type, p_config) for p_type, p_config diff --git a/homeassistant/config.py b/homeassistant/config.py index e86a6bf754a..0688e4db097 100644 --- a/homeassistant/config.py +++ b/homeassistant/config.py @@ -84,7 +84,7 @@ sensor: # Text to speech tts: - - platform: google + - platform: google_translate group: !include groups.yaml automation: !include automations.yaml @@ -95,6 +95,15 @@ DEFAULT_SECRETS = """ # Learn more at https://home-assistant.io/docs/configuration/secrets/ some_password: welcome """ +TTS_PRE_92 = """ +tts: + - platform: google +""" +TTS_92 = """ +tts: + - platform: google_translate + service_name: google_say +""" def _no_duplicate_auth_provider(configs: Sequence[Dict[str, Any]]) \ @@ -378,10 +387,24 @@ def process_ha_config_upgrade(hass: HomeAssistant) -> None: if os.path.isdir(lib_path): shutil.rmtree(lib_path) + if LooseVersion(conf_version) < LooseVersion('0.92'): + # 0.92 moved google/tts.py to google_translate/tts.py + config_path = find_config_file(hass.config.config_dir) + assert config_path is not None + + with open(config_path, 'rt') as config_file: + config_raw = config_file.read() + + if TTS_PRE_92 in config_raw: + _LOGGER.info("Migrating google tts to google_translate tts") + config_raw = config_raw.replace(TTS_PRE_92, TTS_92) + with open(config_path, 'wt') as config_file: + config_file.write(config_raw) + with open(version_path, 'wt') as outp: outp.write(__version__) - _LOGGER.info("Migrating old system configuration files to new locations") + _LOGGER.debug("Migrating old system configuration files to new locations") for oldf, newf in FILE_MIGRATION: if os.path.isfile(hass.config.path(oldf)): _LOGGER.info("Migrating %s to %s", oldf, newf) diff --git a/requirements_all.txt b/requirements_all.txt index 1e280eb69dd..190a4b97815 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -449,7 +449,7 @@ freesms==0.1.2 # homeassistant.components.fritzdect fritzhome==1.0.4 -# homeassistant.components.google +# homeassistant.components.google_translate gTTS-token==1.1.3 # homeassistant.components.gearbest diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 0b7da328ee1..038b2260a38 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -100,7 +100,7 @@ feedparser-homeassistant==5.2.2.dev1 # homeassistant.components.foobot foobot_async==0.3.1 -# homeassistant.components.google +# homeassistant.components.google_translate gTTS-token==1.1.3 # homeassistant.components.geo_json_events diff --git a/tests/components/google_translate/__init__.py b/tests/components/google_translate/__init__.py new file mode 100644 index 00000000000..bc96e5028dd --- /dev/null +++ b/tests/components/google_translate/__init__.py @@ -0,0 +1 @@ +"""Tests for the Google Translate integration.""" diff --git a/tests/components/google/test_tts.py b/tests/components/google_translate/test_tts.py similarity index 91% rename from tests/components/google/test_tts.py rename to tests/components/google_translate/test_tts.py index 78bdd50b6d7..f5791085453 100644 --- a/tests/components/google/test_tts.py +++ b/tests/components/google_translate/test_tts.py @@ -47,7 +47,7 @@ class TestTTSGooglePlatform: """Test setup component.""" config = { tts.DOMAIN: { - 'platform': 'google', + 'platform': 'google_translate', } } @@ -65,14 +65,14 @@ class TestTTSGooglePlatform: config = { tts.DOMAIN: { - 'platform': 'google', + 'platform': 'google_translate', } } with assert_setup_component(1, tts.DOMAIN): setup_component(self.hass, tts.DOMAIN, config) - self.hass.services.call(tts.DOMAIN, 'google_say', { + self.hass.services.call(tts.DOMAIN, 'google_translate_say', { tts.ATTR_MESSAGE: "90% of I person is on front of your door.", }) self.hass.block_till_done() @@ -93,7 +93,7 @@ class TestTTSGooglePlatform: config = { tts.DOMAIN: { - 'platform': 'google', + 'platform': 'google_translate', 'language': 'de', } } @@ -101,7 +101,7 @@ class TestTTSGooglePlatform: with assert_setup_component(1, tts.DOMAIN): setup_component(self.hass, tts.DOMAIN, config) - self.hass.services.call(tts.DOMAIN, 'google_say', { + self.hass.services.call(tts.DOMAIN, 'google_translate_say', { tts.ATTR_MESSAGE: "90% of I person is on front of your door.", }) self.hass.block_till_done() @@ -121,7 +121,8 @@ class TestTTSGooglePlatform: config = { tts.DOMAIN: { - 'platform': 'google', + 'platform': 'google_translate', + 'service_name': 'google_say', } } @@ -148,14 +149,14 @@ class TestTTSGooglePlatform: config = { tts.DOMAIN: { - 'platform': 'google', + 'platform': 'google_translate', } } with assert_setup_component(1, tts.DOMAIN): setup_component(self.hass, tts.DOMAIN, config) - self.hass.services.call(tts.DOMAIN, 'google_say', { + self.hass.services.call(tts.DOMAIN, 'google_translate_say', { tts.ATTR_MESSAGE: "90% of I person is on front of your door.", }) self.hass.block_till_done() @@ -174,14 +175,14 @@ class TestTTSGooglePlatform: config = { tts.DOMAIN: { - 'platform': 'google', + 'platform': 'google_translate', } } with assert_setup_component(1, tts.DOMAIN): setup_component(self.hass, tts.DOMAIN, config) - self.hass.services.call(tts.DOMAIN, 'google_say', { + self.hass.services.call(tts.DOMAIN, 'google_translate_say', { tts.ATTR_MESSAGE: "90% of I person is on front of your door.", }) self.hass.block_till_done() @@ -205,7 +206,8 @@ class TestTTSGooglePlatform: config = { tts.DOMAIN: { - 'platform': 'google', + 'platform': 'google_translate', + 'service_name': 'google_say', } } diff --git a/tests/test_config.py b/tests/test_config.py index fa194d17c11..d92c96c4083 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -315,7 +315,7 @@ class TestConfig(unittest.TestCase): def test_process_config_upgrade(self): """Test update of version on upgrade.""" - ha_version = '0.8.0' + ha_version = '0.92.0' mock_open = mock.mock_open() with mock.patch('homeassistant.config.open', mock_open, create=True): @@ -342,10 +342,13 @@ class TestConfig(unittest.TestCase): assert opened_file.write.call_count == 0 + @mock.patch('homeassistant.config.find_config_file', mock.Mock()) def test_config_upgrade_no_file(self): """Test update of version on upgrade, with no version file.""" mock_open = mock.mock_open() - mock_open.side_effect = [FileNotFoundError(), mock.DEFAULT] + mock_open.side_effect = [FileNotFoundError(), + mock.DEFAULT, + mock.DEFAULT] with mock.patch('homeassistant.config.open', mock_open, create=True): opened_file = mock_open.return_value # pylint: disable=no-member @@ -355,6 +358,7 @@ class TestConfig(unittest.TestCase): @mock.patch('homeassistant.config.shutil') @mock.patch('homeassistant.config.os') + @mock.patch('homeassistant.config.find_config_file', mock.Mock()) def test_migrate_file_on_upgrade(self, mock_os, mock_shutil): """Test migrate of config files on upgrade.""" ha_version = '0.7.0' @@ -381,6 +385,7 @@ class TestConfig(unittest.TestCase): @mock.patch('homeassistant.config.shutil') @mock.patch('homeassistant.config.os') + @mock.patch('homeassistant.config.find_config_file', mock.Mock()) def test_migrate_no_file_on_upgrade(self, mock_os, mock_shutil): """Test not migrating config files on upgrade.""" ha_version = '0.7.0'