From 5fcd68bad83b3c7dff651b6c0d129137d9ada6f7 Mon Sep 17 00:00:00 2001 From: tarepan Date: Mon, 6 May 2024 04:29:36 +0900 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3:=20=E3=83=97=E3=83=AA?= =?UTF-8?q?=E3=82=BB=E3=83=83=E3=83=88=E3=81=AE=E4=B8=80=E5=BE=8B=20`500`?= =?UTF-8?q?=20=E3=82=A8=E3=83=A9=E3=83=BC=E3=82=92=E8=A9=B3=E7=B4=B0?= =?UTF-8?q?=E5=8C=96=E3=81=97=20`422`=20=E5=8C=96=E3=81=97=E3=81=A6?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3=20(#1162)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: プリセット関連エラーを詳細化し500バグを修正 * fix: lint * fix: lint * Update voicevox_engine/preset/PresetError.py Co-authored-by: Hiroshiba * fix: `PresetInternalError` docstring をドメイン内の事象に関する記述へ修正 * fix: `PresetInternalError` docstring を明確化 --------- Co-authored-by: Hiroshiba --- test/preset/test_preset.py | 32 ++++++++++++--------- voicevox_engine/app/routers/preset.py | 18 ++++++++---- voicevox_engine/app/routers/tts_pipeline.py | 6 ++-- voicevox_engine/preset/PresetError.py | 13 ++++++++- voicevox_engine/preset/PresetManager.py | 20 ++++++------- 5 files changed, 58 insertions(+), 31 deletions(-) diff --git a/test/preset/test_preset.py b/test/preset/test_preset.py index 88223fc5f..d7600189f 100644 --- a/test/preset/test_preset.py +++ b/test/preset/test_preset.py @@ -5,7 +5,7 @@ from unittest import TestCase from voicevox_engine.preset.Preset import Preset -from voicevox_engine.preset.PresetError import PresetError +from voicevox_engine.preset.PresetError import PresetInputError, PresetInternalError from voicevox_engine.preset.PresetManager import PresetManager presets_test_1_yaml_path = Path("test/preset/presets-test-1.yaml") @@ -37,26 +37,28 @@ def test_validation_same(self) -> None: def test_validation_2(self) -> None: preset_manager = PresetManager(preset_path=presets_test_2_yaml_path) with self.assertRaises( - PresetError, msg="プリセットの設定ファイルにミスがあります" + PresetInternalError, msg="プリセットの設定ファイルにミスがあります" ): preset_manager.load_presets() def test_preset_id(self) -> None: preset_manager = PresetManager(preset_path=presets_test_3_yaml_path) - with self.assertRaises(PresetError, msg="プリセットのidに重複があります"): + with self.assertRaises( + PresetInternalError, msg="プリセットのidに重複があります" + ): preset_manager.load_presets() def test_empty_file(self) -> None: preset_manager = PresetManager(preset_path=presets_test_4_yaml_path) with self.assertRaises( - PresetError, msg="プリセットの設定ファイルが空の内容です" + PresetInternalError, msg="プリセットの設定ファイルが空の内容です" ): preset_manager.load_presets() def test_not_exist_file(self) -> None: preset_manager = PresetManager(preset_path=Path("test/presets-dummy.yaml")) with self.assertRaises( - PresetError, msg="プリセットの設定ファイルが見つかりません" + PresetInternalError, msg="プリセットの設定ファイルが見つかりません" ): preset_manager.load_presets() @@ -89,7 +91,7 @@ def test_add_preset(self) -> None: def test_add_preset_load_failure(self) -> None: preset_manager = PresetManager(preset_path=presets_test_2_yaml_path) with self.assertRaises( - PresetError, msg="プリセットの設定ファイルにミスがあります" + PresetInternalError, msg="プリセットの設定ファイルにミスがあります" ): preset_manager.add_preset( Preset( @@ -182,7 +184,7 @@ def test_add_preset_write_failure(self) -> None: preset_manager._refresh_cache = lambda: None # type:ignore[method-assign] preset_manager.preset_path = "" # type: ignore[assignment] with self.assertRaises( - PresetError, msg="プリセットの設定ファイルに書き込み失敗しました" + PresetInternalError, msg="プリセットの設定ファイルが見つかりません" ): preset_manager.add_preset(preset) self.assertEqual(len(preset_manager.presets), 2) @@ -217,7 +219,7 @@ def test_update_preset(self) -> None: def test_update_preset_load_failure(self) -> None: preset_manager = PresetManager(preset_path=presets_test_2_yaml_path) with self.assertRaises( - PresetError, msg="プリセットの設定ファイルにミスがあります" + PresetInternalError, msg="プリセットの設定ファイルにミスがあります" ): preset_manager.update_preset( Preset( @@ -254,7 +256,9 @@ def test_update_preset_not_found(self) -> None: "postPhonemeLength": 0.1, } ) - with self.assertRaises(PresetError, msg="更新先のプリセットが存在しません"): + with self.assertRaises( + PresetInputError, msg="更新先のプリセットが存在しません" + ): preset_manager.update_preset(preset) self.assertEqual(len(preset_manager.presets), 2) remove(temp_path) @@ -281,7 +285,7 @@ def test_update_preset_write_failure(self) -> None: preset_manager._refresh_cache = lambda: None # type:ignore[method-assign] preset_manager.preset_path = "" # type: ignore[assignment] with self.assertRaises( - PresetError, msg="プリセットの設定ファイルに書き込み失敗しました" + PresetInternalError, msg="プリセットの設定ファイルが見つかりません" ): preset_manager.update_preset(preset) self.assertEqual(len(preset_manager.presets), 2) @@ -300,7 +304,7 @@ def test_delete_preset(self) -> None: def test_delete_preset_load_failure(self) -> None: preset_manager = PresetManager(preset_path=presets_test_2_yaml_path) with self.assertRaises( - PresetError, msg="プリセットの設定ファイルにミスがあります" + PresetInternalError, msg="プリセットの設定ファイルにミスがあります" ): preset_manager.delete_preset(10) @@ -308,7 +312,9 @@ def test_delete_preset_not_found(self) -> None: temp_path = self.tmp_dir_path / "presets-test-temp.yaml" copyfile(presets_test_1_yaml_path, temp_path) preset_manager = PresetManager(preset_path=temp_path) - with self.assertRaises(PresetError, msg="削除対象のプリセットが存在しません"): + with self.assertRaises( + PresetInputError, msg="削除対象のプリセットが存在しません" + ): preset_manager.delete_preset(10) self.assertEqual(len(preset_manager.presets), 2) remove(temp_path) @@ -321,7 +327,7 @@ def test_delete_preset_write_failure(self) -> None: preset_manager._refresh_cache = lambda: None # type:ignore[method-assign] preset_manager.preset_path = "" # type: ignore[assignment] with self.assertRaises( - PresetError, msg="プリセットの設定ファイルに書き込み失敗しました" + PresetInternalError, msg="プリセットの設定ファイルが見つかりません" ): preset_manager.delete_preset(1) self.assertEqual(len(preset_manager.presets), 2) diff --git a/voicevox_engine/app/routers/preset.py b/voicevox_engine/app/routers/preset.py index 98a57bfe4..060ae9620 100644 --- a/voicevox_engine/app/routers/preset.py +++ b/voicevox_engine/app/routers/preset.py @@ -5,7 +5,7 @@ from fastapi import APIRouter, Body, Depends, HTTPException, Query, Response from voicevox_engine.preset.Preset import Preset -from voicevox_engine.preset.PresetError import PresetError +from voicevox_engine.preset.PresetError import PresetInputError, PresetInternalError from voicevox_engine.preset.PresetManager import PresetManager from ..dependencies import check_disabled_mutable_api @@ -27,8 +27,10 @@ def get_presets() -> list[Preset]: """ try: presets = preset_manager.load_presets() - except PresetError as err: + except PresetInputError as err: raise HTTPException(status_code=422, detail=str(err)) + except PresetInternalError as err: + raise HTTPException(status_code=500, detail=str(err)) return presets @router.post( @@ -51,8 +53,10 @@ def add_preset( """ try: id = preset_manager.add_preset(preset) - except PresetError as err: + except PresetInputError as err: raise HTTPException(status_code=422, detail=str(err)) + except PresetInternalError as err: + raise HTTPException(status_code=500, detail=str(err)) return id @router.post( @@ -75,8 +79,10 @@ def update_preset( """ try: id = preset_manager.update_preset(preset) - except PresetError as err: + except PresetInputError as err: raise HTTPException(status_code=422, detail=str(err)) + except PresetInternalError as err: + raise HTTPException(status_code=500, detail=str(err)) return id @router.post( @@ -93,8 +99,10 @@ def delete_preset( """ try: preset_manager.delete_preset(id) - except PresetError as err: + except PresetInputError as err: raise HTTPException(status_code=422, detail=str(err)) + except PresetInternalError as err: + raise HTTPException(status_code=500, detail=str(err)) return Response(status_code=204) return router diff --git a/voicevox_engine/app/routers/tts_pipeline.py b/voicevox_engine/app/routers/tts_pipeline.py index f5bb5f567..ac01f29a1 100644 --- a/voicevox_engine/app/routers/tts_pipeline.py +++ b/voicevox_engine/app/routers/tts_pipeline.py @@ -20,7 +20,7 @@ ParseKanaError, Score, ) -from voicevox_engine.preset.PresetError import PresetError +from voicevox_engine.preset.PresetError import PresetInputError, PresetInternalError from voicevox_engine.preset.PresetManager import PresetManager from voicevox_engine.tts_pipeline.kana_converter import create_kana, parse_kana from voicevox_engine.tts_pipeline.tts_engine import TTSEngine @@ -88,8 +88,10 @@ def audio_query_from_preset( core = get_core(core_version) try: presets = preset_manager.load_presets() - except PresetError as err: + except PresetInputError as err: raise HTTPException(status_code=422, detail=str(err)) + except PresetInternalError as err: + raise HTTPException(status_code=500, detail=str(err)) for preset in presets: if preset.id == preset_id: selected_preset = preset diff --git a/voicevox_engine/preset/PresetError.py b/voicevox_engine/preset/PresetError.py index 6f5f802f5..add7acf05 100644 --- a/voicevox_engine/preset/PresetError.py +++ b/voicevox_engine/preset/PresetError.py @@ -1,2 +1,13 @@ -class PresetError(Exception): +"""プリセットに関するエラー""" + + +class PresetInputError(Exception): + """受け入れ不可能な入力値に起因するエラー""" + + pass + + +class PresetInternalError(Exception): + """プリセットマネージャーに起因するエラー""" + pass diff --git a/voicevox_engine/preset/PresetManager.py b/voicevox_engine/preset/PresetManager.py index 2b5c24e65..7421c9585 100644 --- a/voicevox_engine/preset/PresetManager.py +++ b/voicevox_engine/preset/PresetManager.py @@ -5,7 +5,7 @@ from pydantic import ValidationError, parse_obj_as from .Preset import Preset -from .PresetError import PresetError +from .PresetError import PresetInputError, PresetInternalError class PresetManager: @@ -32,23 +32,23 @@ def _refresh_cache(self) -> None: # 更新無し return except OSError: - raise PresetError("プリセットの設定ファイルが見つかりません") + raise PresetInternalError("プリセットの設定ファイルが見つかりません") # データベースの読み込み with open(self.preset_path, mode="r", encoding="utf-8") as f: obj = yaml.safe_load(f) if obj is None: - raise PresetError("プリセットの設定ファイルが空の内容です") + raise PresetInternalError("プリセットの設定ファイルが空の内容です") try: _presets = parse_obj_as(List[Preset], obj) except ValidationError: - raise PresetError("プリセットの設定ファイルにミスがあります") + raise PresetInternalError("プリセットの設定ファイルにミスがあります") # 全idの一意性をバリデーション if len([preset.id for preset in _presets]) != len( {preset.id for preset in _presets} ): - raise PresetError("プリセットのidに重複があります") + raise PresetInternalError("プリセットのidに重複があります") # キャッシュを更新する self.presets = _presets @@ -72,7 +72,7 @@ def add_preset(self, preset: Preset) -> int: except Exception as err: self.presets.pop() if isinstance(err, FileNotFoundError): - raise PresetError("プリセットの設定ファイルに書き込み失敗しました") + raise PresetInternalError("プリセットの設定ファイルが見つかりません") else: raise err @@ -100,7 +100,7 @@ def update_preset(self, preset: Preset) -> int: self.presets[i] = preset break else: - raise PresetError("更新先のプリセットが存在しません") + raise PresetInputError("更新先のプリセットが存在しません") # 変更の反映。失敗時はリバート。 try: @@ -108,7 +108,7 @@ def update_preset(self, preset: Preset) -> int: except Exception as err: self.presets[prev_preset[0]] = prev_preset[1] if isinstance(err, FileNotFoundError): - raise PresetError("プリセットの設定ファイルに書き込み失敗しました") + raise PresetInternalError("プリセットの設定ファイルが見つかりません") else: raise err @@ -129,14 +129,14 @@ def delete_preset(self, id: int) -> int: buf_index = i break else: - raise PresetError("削除対象のプリセットが存在しません") + raise PresetInputError("削除対象のプリセットが存在しません") # 変更の反映。失敗時はリバート。 try: self._write_on_file() except FileNotFoundError: self.presets.insert(buf_index, buf) - raise PresetError("プリセットの設定ファイルに書き込み失敗しました") + raise PresetInternalError("プリセットの設定ファイルが見つかりません") return id