Repository: VOICEVOX/voicevox_engine (Python)

Issue:
pyproject.tomlのtool.ruff.lintのselectにUPを追加する

## 内容

ruffのルールにおいて、Pythonのバージョンアップに合わせた正しい書き方を促す「UP」チェックの追加したいです。

UPルール
https://docs.astral.sh/ruff/rules/#pyupgrade-up

huggingfaceとかfastapiとかも採用しているし、新しい書き方と古い書き方がまじるのはなんかあれなので、適用したいなーと･･･！

### Pros 良くなる点

- 最新の推奨書式に準拠したコードになる
- 古い書き方や非推奨の記法が明確に検出される

### Cons 悪くなる点

特になし

### 実現方法

- pyproject.toml内の設定にUPを追加
- `ruff --fix`で自動修正
- 残ったエラーは個別に対応


## その他

関連

- https://github.com/VOICEVOX/voicevox_engine/pull/1563



Fix (patch):
diff --git a/pyproject.toml b/pyproject.toml
index 14d601f73..afa49b12c 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -2,7 +2,7 @@
 target-version = "py311"
 
 [tool.ruff.lint]
-select = ["E", "F", "B", "I", "W"]
+select = ["E", "F", "B", "I", "W", "UP"]
 ignore = [
   "E501", # line-too-long
   "B9"    # TODO: 一時期に除外、あとで有効化する
diff --git a/tools/make_docs.py b/tools/make_docs.py
index 68e220e0d..bd9f4be9f 100644
--- a/tools/make_docs.py
+++ b/tools/make_docs.py
@@ -18,8 +18,7 @@
 def generate_api_docs_html(schema: str) -> str:
     """OpenAPI schema から API ドキュメント HTML を生成する"""
 
-    return (
-        """<!DOCTYPE html>
+    return f"""<!DOCTYPE html>
 <html lang="ja">
 <head>
     <title>voicevox_engine API Document</title>
@@ -30,12 +29,10 @@ def generate_api_docs_html(schema: str) -> str:
     <div id="redoc-container"></div>
     <script src="https://cdn.jsdelivr.net/npm/redoc/bundles/redoc.standalone.js"></script>
     <script>
-        Redoc.init(%s, {"hideHostname": true}, document.getElementById("redoc-container"));
+        Redoc.init({schema}, {"hideHostname": true}, document.getElementById("redoc-container"));
     </script>
 </body>
 </html>"""
-        % schema
-    )
 
 
 if __name__ == "__main__":
diff --git a/voicevox_engine/app/dependencies.py b/voicevox_engine/app/dependencies.py
index 904682d9d..30fb61762 100644
--- a/voicevox_engine/app/dependencies.py
+++ b/voicevox_engine/app/dependencies.py
@@ -1,6 +1,7 @@
 """FastAPI dependencies"""
 
-from typing import Any, Callable, Coroutine, TypeAlias
+from collections.abc import Callable, Coroutine
+from typing import Any, TypeAlias
 
 from fastapi import HTTPException
 
diff --git a/voicevox_engine/app/routers/tts_pipeline.py b/voicevox_engine/app/routers/tts_pipeline.py
index a2a65b1d0..4c4335edf 100644
--- a/voicevox_engine/app/routers/tts_pipeline.py
+++ b/voicevox_engine/app/routers/tts_pipeline.py
@@ -52,10 +52,7 @@ class ParseKanaBadRequest(BaseModel):
         description="エラー名\n\n"
         "|name|description|\n|---|---|\n"
         + "\n".join(
-            [
-                "| {} | {} |".format(err.name, err.value)
-                for err in list(ParseKanaErrorCode)
-            ]
+            [f"| {err.name} | {err.value} |" for err in list(ParseKanaErrorCode)]
         ),
     )
     error_args: dict[str, str] = Field(description="エラーを起こした箇所")
diff --git a/voicevox_engine/metas/MetasStore.py b/voicevox_engine/metas/MetasStore.py
index b8bd35678..bd8e97b2a 100644
--- a/voicevox_engine/metas/MetasStore.py
+++ b/voicevox_engine/metas/MetasStore.py
@@ -1,8 +1,9 @@
 """キャラクター情報とキャラクターメタ情報の管理"""
 
+from collections.abc import Callable
 from dataclasses import dataclass
 from pathlib import Path
-from typing import Callable, Final, Literal, TypeAlias
+from typing import Final, Literal, TypeAlias
 
 from fastapi import HTTPException
 from pydantic import BaseModel, Field
diff --git a/voicevox_engine/preset/preset_manager.py b/voicevox_engine/preset/preset_manager.py
index 74991dc48..e5e08129c 100644
--- a/voicevox_engine/preset/preset_manager.py
+++ b/voicevox_engine/preset/preset_manager.py
@@ -63,7 +63,7 @@ def _refresh_cache(self) -> None:
                 return
 
             # データベースの読み込み
-            with open(self.preset_path, mode="r", encoding="utf-8") as f:
+            with open(self.preset_path, encoding="utf-8") as f:
                 obj = yaml.safe_load(f)
         except OSError:
             raise PresetInternalError("プリセットの読み込みに失敗しました")
diff --git a/voicevox_engine/tts_pipeline/text_analyzer.py b/voicevox_engine/tts_pipeline/text_analyzer.py
index aac169c38..a15936fa2 100644
--- a/voicevox_engine/tts_pipeline/text_analyzer.py
+++ b/voicevox_engine/tts_pipeline/text_analyzer.py
@@ -1,9 +1,10 @@
 """テキスト解析"""
 
 import re
+from collections.abc import Callable
 from dataclasses import dataclass
 from itertools import chain
-from typing import Any, Callable, Final, Literal, Self, TypeGuard
+from typing import Any, Final, Literal, Self, TypeGuard
 
 import pyopenjtalk
 
diff --git a/voicevox_engine/user_dict/model.py b/voicevox_engine/user_dict/model.py
index 8ae1c1e2d..ad169e053 100644
--- a/voicevox_engine/user_dict/model.py
+++ b/voicevox_engine/user_dict/model.py
@@ -6,11 +6,10 @@
 
 from enum import Enum
 from re import findall, fullmatch
-from typing import Self
+from typing import Annotated, Self
 
 from pydantic import AfterValidator, BaseModel, ConfigDict, Field, model_validator
 from pydantic.json_schema import SkipJsonSchema
-from typing_extensions import Annotated
 
 
 class WordTypes(str, Enum):
@@ -130,8 +129,6 @@ def check_mora_count_and_accent_type(self) -> Self:
 
         if not 0 <= self.accent_type <= self.mora_count:
             raise ValueError(
-                "誤ったアクセント型です({})。 expect: 0 <= accent_type <= {}".format(
-                    self.accent_type, self.mora_count
-                )
+                f"誤ったアクセント型です({self.accent_type})。 expect: 0 <= accent_type <= {self.mora_count}"
             )
         return self