diff --git a/homeassistant/components/tts/__init__.py b/homeassistant/components/tts/__init__.py index 6dc2e9b7d45..ebd7a1c8411 100644 --- a/homeassistant/components/tts/__init__.py +++ b/homeassistant/components/tts/__init__.py @@ -1,6 +1,5 @@ """Provide functionality for TTS.""" import asyncio -import ctypes import functools as ft import hashlib import io @@ -8,7 +7,7 @@ import logging import mimetypes import os import re -from typing import Optional +from typing import Dict, Optional from aiohttp import web import mutagen @@ -212,6 +211,16 @@ async def async_setup(hass, config): 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: """Representation of a speech store.""" @@ -304,7 +313,7 @@ class SpeechManager: ] if 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: options_key = "-" diff --git a/tests/components/tts/test_init.py b/tests/components/tts/test_init.py index 527fb559eb1..b4cb9c67af3 100644 --- a/tests/components/tts/test_init.py +++ b/tests/components/tts/test_init.py @@ -1,6 +1,4 @@ """The tests for the TTS component.""" -import ctypes - import pytest import yarl @@ -265,11 +263,11 @@ async def test_setup_component_and_test_service_with_service_options( "entity_id": "media_player.something", tts.ATTR_MESSAGE: "There is someone at the door.", tts.ATTR_LANGUAGE: "de", - tts.ATTR_OPTIONS: {"voice": "alex"}, + tts.ATTR_OPTIONS: {"voice": "alex", "age": 5}, }, 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 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, ) - opt_hash = ctypes.c_size_t(hash(frozenset({"voice": "alex"}))).value + opt_hash = tts._hash_options({"voice": "alex"}) assert len(calls) == 1 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, ) - opt_hash = ctypes.c_size_t(hash(frozenset({"speed": 1}))).value + opt_hash = tts._hash_options({"speed": 1}) assert len(calls) == 0 await hass.async_block_till_done()