diff --git a/.gitignore b/.gitignore index 70a8aa797..bfcae394d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,6 @@ ## Artifact of generating licenses /licenses.json licenses_venv/ -## Presets -presets.yaml # Copied from `https://github.com/github/gitignore/blob/main/Python.gitignore` @2022-01-10 # Byte-compiled / optimized / DLL files diff --git a/README.md b/README.md index a72747886..e16c9fad8 100644 --- a/README.md +++ b/README.md @@ -249,7 +249,7 @@ curl -s -X DELETE "127.0.0.1:50021/user_dict_word/$word_uuid" ### プリセット機能について -`presets.yaml`を編集することでキャラクターや話速などのプリセットを使うことができます。 +ユーザーディレクトリにある`presets.yaml`を編集することでキャラクターや話速などのプリセットを使うことができます。 ```bash echo -n "プリセットをうまく活用すれば、サードパーティ間で同じ設定を使うことができます" >text.txt @@ -442,7 +442,7 @@ options: --setting_file SETTING_FILE 設定ファイルを指定できます。 --preset_file PRESET_FILE - プリセットファイルを指定できます。指定がない場合、環境変数 VV_PRESET_FILE、実行ファイルのディレクトリのpresets.yamlを順に探します。 + プリセットファイルを指定できます。指定がない場合、環境変数 VV_PRESET_FILE、ユーザーディレクトリのpresets.yamlを順に探します。 --disable_mutable_api 辞書登録や設定変更など、エンジンの静的なデータを変更するAPIを無効化します。指定しない場合、代わりに環境変数 VV_DISABLE_MUTABLE_API の値が使われます。VV_DISABLE_MUTABLE_API の値が1の場合は無効化で、0または空文字、値がない場合は無視されます。 ``` diff --git a/run.py b/run.py index b17d29cae..bfbcd6a88 100644 --- a/run.py +++ b/run.py @@ -275,7 +275,7 @@ def read_cli_arguments(envs: Envs) -> CLIArgs: default=None, help=( "プリセットファイルを指定できます。" - "指定がない場合、環境変数 VV_PRESET_FILE、実行ファイルのディレクトリのpresets.yamlを順に探します。" + "指定がない場合、環境変数 VV_PRESET_FILE、ユーザーディレクトリのpresets.yamlを順に探します。" ), ) @@ -360,7 +360,7 @@ def main() -> None: env_preset_path = Path(envs.env_preset_path) else: env_preset_path = None - default_preset_path = engine_root() / "presets.yaml" + default_preset_path = get_save_dir() / "presets.yaml" preset_path = select_first_not_none( [args.preset_file, env_preset_path, default_preset_path] ) diff --git a/test/benchmark/engine_preparation.py b/test/benchmark/engine_preparation.py index 21140ffd5..6000ac313 100644 --- a/test/benchmark/engine_preparation.py +++ b/test/benchmark/engine_preparation.py @@ -24,7 +24,7 @@ def _generate_engine_fake_server(root_dir: Path) -> TestClient: ) tts_engines = make_tts_engines_from_cores(core_manager) setting_loader = SettingHandler(Path("./not_exist.yaml")) - preset_manager = PresetManager(Path("./presets.yaml")) + preset_manager = PresetManager(get_save_dir() / "presets.yaml") user_dict = UserDictionary() engine_manifest = load_manifest(engine_manifest_path()) library_manager = LibraryManager( diff --git a/test/unit/preset/test_preset.py b/test/unit/preset/test_preset.py index 995f81d29..b76a976bc 100644 --- a/test/unit/preset/test_preset.py +++ b/test/unit/preset/test_preset.py @@ -1,4 +1,4 @@ -from os import remove +from os import environ, remove from pathlib import Path from shutil import copyfile @@ -10,6 +10,7 @@ PresetInternalError, PresetManager, ) +from voicevox_engine.utility.path_utility import engine_root presets_test_1_yaml_path = Path("test/unit/preset/presets-test-1.yaml") presets_test_2_yaml_path = Path("test/unit/preset/presets-test-2.yaml") @@ -350,3 +351,21 @@ def test_delete_preset_write_failure(tmp_path: Path) -> None: preset_manager.delete_preset(1) assert len(preset_manager.presets) == 2 remove(preset_path) + + +# テストのためにエンジン直下にファイルを作るため、念のためActions上のみで実行 +@pytest.mark.skipif(not environ.get("CI", False), reason="runs only on Github Actions") +def test_migrate_default_preset_path(tmp_path: Path) -> None: + preset_path = tmp_path / "presets.yaml" + old_preset_path = engine_root() / "presets.yaml" + assert not preset_path.exists() + copyfile(presets_test_1_yaml_path, old_preset_path) + old_preset_manager = PresetManager(preset_path=preset_path) + migrated_presets = old_preset_manager.load_presets() + if old_preset_path.exists(): + remove(old_preset_path) + raise AssertionError("The old preset file exists.") + preset_manager = PresetManager(preset_path=presets_test_1_yaml_path) + presets = preset_manager.load_presets() + assert migrated_presets == presets + remove(preset_path) diff --git a/tools/make_docs.py b/tools/make_docs.py index e9483d0f0..68e220e0d 100644 --- a/tools/make_docs.py +++ b/tools/make_docs.py @@ -12,11 +12,7 @@ from voicevox_engine.setting.setting_manager import USER_SETTING_PATH, SettingHandler from voicevox_engine.tts_pipeline.tts_engine import TTSEngineManager from voicevox_engine.user_dict.user_dict_manager import UserDictionary -from voicevox_engine.utility.path_utility import ( - engine_manifest_path, - engine_root, - get_save_dir, -) +from voicevox_engine.utility.path_utility import engine_manifest_path, get_save_dir def generate_api_docs_html(schema: str) -> str: @@ -47,7 +43,7 @@ def generate_api_docs_html(schema: str) -> str: core_manager.register_core(CoreAdapter(MockCoreWrapper()), "mock") tts_engines = TTSEngineManager() tts_engines.register_engine(MockTTSEngine(), "mock") - preset_path = engine_root() / "presets.yaml" + preset_path = get_save_dir() / "presets.yaml" engine_manifest = load_manifest(engine_manifest_path()) library_manager = LibraryManager( get_save_dir() / "installed_libraries", diff --git a/voicevox_engine/preset/preset_manager.py b/voicevox_engine/preset/preset_manager.py index eac2f2583..74991dc48 100644 --- a/voicevox_engine/preset/preset_manager.py +++ b/voicevox_engine/preset/preset_manager.py @@ -1,10 +1,13 @@ """プリセット関連の処理""" +import shutil +import warnings from pathlib import Path import yaml from pydantic import TypeAdapter, ValidationError +from ..utility.path_utility import engine_root from .model import Preset @@ -35,7 +38,19 @@ def __init__(self, preset_path: Path): self.last_modified_time = 0.0 self.preset_path = preset_path if not self.preset_path.exists(): - self.preset_path.write_text("[]") + # エンジンのディレクトリ内に`presets.yaml`があった場合、マイグレーションする + old_preset_path = engine_root() / "presets.yaml" + if old_preset_path.exists(): + try: + shutil.move(old_preset_path, self.preset_path) + except OSError: + warnings.warn( + "プリセットファイルのマイグレーションに失敗しました", + stacklevel=1, + ) + self.preset_path.write_text("[]") + else: + self.preset_path.write_text("[]") def _refresh_cache(self) -> None: """プリセットの設定ファイルの最新状態をキャッシュへ反映する"""