Fix TTS key by hashing options values too (#36813)

This commit is contained in:
Paulus Schoutsen 2020-06-15 04:33:26 -07:00 committed by GitHub
parent c96458c7e4
commit dfac9c5e03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 16 additions and 9 deletions

View File

@ -1,6 +1,5 @@
"""Provide functionality for TTS.""" """Provide functionality for TTS."""
import asyncio import asyncio
import ctypes
import functools as ft import functools as ft
import hashlib import hashlib
import io import io
@ -8,7 +7,7 @@ import logging
import mimetypes import mimetypes
import os import os
import re import re
from typing import Optional from typing import Dict, Optional
from aiohttp import web from aiohttp import web
import mutagen import mutagen
@ -212,6 +211,16 @@ async def async_setup(hass, config):
return True return True
def _hash_options(options: Dict) -> str:
"""Hashes an options dictionary."""
opts_hash = hashlib.blake2s(digest_size=5)
for key, value in sorted(options.items()):
opts_hash.update(str(key).encode())
opts_hash.update(str(value).encode())
return opts_hash.hexdigest()
class SpeechManager: class SpeechManager:
"""Representation of a speech store.""" """Representation of a speech store."""
@ -304,7 +313,7 @@ class SpeechManager:
] ]
if invalid_opts: if invalid_opts:
raise HomeAssistantError(f"Invalid options found: {invalid_opts}") raise HomeAssistantError(f"Invalid options found: {invalid_opts}")
options_key = ctypes.c_size_t(hash(frozenset(options))).value options_key = _hash_options(options)
else: else:
options_key = "-" options_key = "-"

View File

@ -1,6 +1,4 @@
"""The tests for the TTS component.""" """The tests for the TTS component."""
import ctypes
import pytest import pytest
import yarl import yarl
@ -265,11 +263,11 @@ async def test_setup_component_and_test_service_with_service_options(
"entity_id": "media_player.something", "entity_id": "media_player.something",
tts.ATTR_MESSAGE: "There is someone at the door.", tts.ATTR_MESSAGE: "There is someone at the door.",
tts.ATTR_LANGUAGE: "de", tts.ATTR_LANGUAGE: "de",
tts.ATTR_OPTIONS: {"voice": "alex"}, tts.ATTR_OPTIONS: {"voice": "alex", "age": 5},
}, },
blocking=True, blocking=True,
) )
opt_hash = ctypes.c_size_t(hash(frozenset({"voice": "alex"}))).value opt_hash = tts._hash_options({"voice": "alex", "age": 5})
assert len(calls) == 1 assert len(calls) == 1
assert calls[0].data[ATTR_MEDIA_CONTENT_TYPE] == MEDIA_TYPE_MUSIC assert calls[0].data[ATTR_MEDIA_CONTENT_TYPE] == MEDIA_TYPE_MUSIC
@ -306,7 +304,7 @@ async def test_setup_component_and_test_with_service_options_def(hass, empty_cac
}, },
blocking=True, blocking=True,
) )
opt_hash = ctypes.c_size_t(hash(frozenset({"voice": "alex"}))).value opt_hash = tts._hash_options({"voice": "alex"})
assert len(calls) == 1 assert len(calls) == 1
assert calls[0].data[ATTR_MEDIA_CONTENT_TYPE] == MEDIA_TYPE_MUSIC assert calls[0].data[ATTR_MEDIA_CONTENT_TYPE] == MEDIA_TYPE_MUSIC
@ -343,7 +341,7 @@ async def test_setup_component_and_test_service_with_service_options_wrong(
}, },
blocking=True, blocking=True,
) )
opt_hash = ctypes.c_size_t(hash(frozenset({"speed": 1}))).value opt_hash = tts._hash_options({"speed": 1})
assert len(calls) == 0 assert len(calls) == 0
await hass.async_block_till_done() await hass.async_block_till_done()