diff --git a/test/user_dict/test_user_dict.py b/test/user_dict/test_user_dict.py index cb938a689..ad0e4c5dc 100644 --- a/test/user_dict/test_user_dict.py +++ b/test/user_dict/test_user_dict.py @@ -4,7 +4,6 @@ from tempfile import TemporaryDirectory from unittest import TestCase -from fastapi import HTTPException from pyopenjtalk import g2p, unset_user_dict from voicevox_engine.model import UserDictWord, WordTypes @@ -13,6 +12,7 @@ part_of_speech_data, ) from voicevox_engine.user_dict.user_dict import ( + UserDictInputError, _create_word, apply_word, delete_word, @@ -163,7 +163,7 @@ def test_rewrite_word_invalid_id(self) -> None: json.dumps(valid_dict_dict_json, ensure_ascii=False), encoding="utf-8" ) self.assertRaises( - HTTPException, + UserDictInputError, rewrite_word, word_uuid="c2be4dc5-d07d-4767-8be1-04a1bb3f05a9", surface="test2", @@ -200,7 +200,7 @@ def test_delete_word_invalid_id(self) -> None: json.dumps(valid_dict_dict_json, ensure_ascii=False), encoding="utf-8" ) self.assertRaises( - HTTPException, + UserDictInputError, delete_word, word_uuid="c2be4dc5-d07d-4767-8be1-04a1bb3f05a9", user_dict_path=user_dict_path, diff --git a/voicevox_engine/app/routers/user_dict.py b/voicevox_engine/app/routers/user_dict.py index 496b51eed..8bfa7fd82 100644 --- a/voicevox_engine/app/routers/user_dict.py +++ b/voicevox_engine/app/routers/user_dict.py @@ -11,6 +11,7 @@ from voicevox_engine.model import UserDictWord, WordTypes from voicevox_engine.user_dict.part_of_speech_data import MAX_PRIORITY, MIN_PRIORITY from voicevox_engine.user_dict.user_dict import ( + UserDictInputError, apply_word, delete_word, import_user_dict, @@ -38,10 +39,12 @@ def get_user_dict_words() -> dict[str, UserDictWord]: """ try: return read_dict() + except UserDictInputError as err: + raise HTTPException(status_code=422, detail=str(err)) except Exception: traceback.print_exc() raise HTTPException( - status_code=422, detail="辞書の読み込みに失敗しました。" + status_code=500, detail="辞書の読み込みに失敗しました。" ) @router.post( @@ -87,10 +90,12 @@ def add_user_dict_word( raise HTTPException( status_code=422, detail="パラメータに誤りがあります。\n" + str(e) ) + except UserDictInputError as err: + raise HTTPException(status_code=422, detail=str(err)) except Exception: traceback.print_exc() raise HTTPException( - status_code=422, detail="ユーザー辞書への追加に失敗しました。" + status_code=500, detail="ユーザー辞書への追加に失敗しました。" ) @router.put( @@ -134,16 +139,16 @@ def rewrite_user_dict_word( priority=priority, ) return Response(status_code=204) - except HTTPException: - raise except ValidationError as e: raise HTTPException( status_code=422, detail="パラメータに誤りがあります。\n" + str(e) ) + except UserDictInputError as err: + raise HTTPException(status_code=422, detail=str(err)) except Exception: traceback.print_exc() raise HTTPException( - status_code=422, detail="ユーザー辞書の更新に失敗しました。" + status_code=500, detail="ユーザー辞書の更新に失敗しました。" ) @router.delete( @@ -161,12 +166,12 @@ def delete_user_dict_word( try: delete_word(word_uuid=word_uuid) return Response(status_code=204) - except HTTPException: - raise + except UserDictInputError as err: + raise HTTPException(status_code=422, detail=str(err)) except Exception: traceback.print_exc() raise HTTPException( - status_code=422, detail="ユーザー辞書の更新に失敗しました。" + status_code=500, detail="ユーザー辞書の更新に失敗しました。" ) @router.post( @@ -190,10 +195,12 @@ def import_user_dict_words( try: import_user_dict(dict_data=import_dict_data, override=override) return Response(status_code=204) + except UserDictInputError as err: + raise HTTPException(status_code=422, detail=str(err)) except Exception: traceback.print_exc() raise HTTPException( - status_code=422, detail="ユーザー辞書のインポートに失敗しました。" + status_code=500, detail="ユーザー辞書のインポートに失敗しました。" ) return router diff --git a/voicevox_engine/user_dict/user_dict.py b/voicevox_engine/user_dict/user_dict.py index cf31de6ef..3d4092ad9 100644 --- a/voicevox_engine/user_dict/user_dict.py +++ b/voicevox_engine/user_dict/user_dict.py @@ -8,13 +8,19 @@ import numpy as np import pyopenjtalk -from fastapi import HTTPException from ..model import UserDictWord, WordTypes from ..utility.mutex_utility import mutex_wrapper from ..utility.path_utility import engine_root, get_save_dir from .part_of_speech_data import MAX_PRIORITY, MIN_PRIORITY, part_of_speech_data + +class UserDictInputError(Exception): + """受け入れ不可能な入力値に起因するエラー""" + + pass + + root_dir = engine_root() save_dir = get_save_dir() @@ -212,11 +218,11 @@ def _create_word( if word_type is None: word_type = WordTypes.PROPER_NOUN if word_type not in part_of_speech_data.keys(): - raise HTTPException(status_code=422, detail="不明な品詞です") + raise UserDictInputError("不明な品詞です") if priority is None: priority = 5 if not MIN_PRIORITY <= priority <= MAX_PRIORITY: - raise HTTPException(status_code=422, detail="優先度の値が無効です") + raise UserDictInputError("優先度の値が無効です") pos_detail = part_of_speech_data[word_type] return UserDictWord( surface=surface, @@ -330,9 +336,7 @@ def rewrite_word( # 既存単語の上書きによる辞書データの更新 user_dict = read_dict(user_dict_path=user_dict_path) if word_uuid not in user_dict: - raise HTTPException( - status_code=422, detail="UUIDに該当するワードが見つかりませんでした" - ) + raise UserDictInputError("UUIDに該当するワードが見つかりませんでした") user_dict[word_uuid] = word # 更新された辞書データの保存と適用 @@ -359,9 +363,7 @@ def delete_word( # 既存単語の削除による辞書データの更新 user_dict = read_dict(user_dict_path=user_dict_path) if word_uuid not in user_dict: - raise HTTPException( - status_code=422, detail="IDに該当するワードが見つかりませんでした" - ) + raise UserDictInputError("IDに該当するワードが見つかりませんでした") del user_dict[word_uuid] # 更新された辞書データの保存と適用 @@ -438,7 +440,7 @@ def _search_cost_candidates(context_id: int) -> List[int]: for value in part_of_speech_data.values(): if value.context_id == context_id: return value.cost_candidates - raise HTTPException(status_code=422, detail="品詞IDが不正です") + raise UserDictInputError("品詞IDが不正です") def _cost2priority(context_id: int, cost: int) -> int: