Spaces:
Build error
Build error
from pathlib import Path | |
from typing import List | |
import yaml | |
from pydantic import ValidationError, parse_obj_as | |
from .Preset import Preset | |
from .PresetError import PresetError | |
class PresetManager: | |
def __init__( | |
self, | |
preset_path: Path, | |
): | |
self.presets = [] | |
self.last_modified_time = 0 | |
self.preset_path = preset_path | |
def load_presets(self): | |
""" | |
プリセットのYAMLファイルを読み込む | |
Returns | |
------- | |
ret: List[Preset] | |
プリセットのリスト | |
""" | |
# 設定ファイルのタイムスタンプを確認 | |
try: | |
_last_modified_time = self.preset_path.stat().st_mtime | |
if _last_modified_time == self.last_modified_time: | |
return self.presets | |
except OSError: | |
raise PresetError("プリセットの設定ファイルが見つかりません") | |
with open(self.preset_path, mode="r", encoding="utf-8") as f: | |
obj = yaml.safe_load(f) | |
if obj is None: | |
raise PresetError("プリセットの設定ファイルが空の内容です") | |
try: | |
_presets = parse_obj_as(List[Preset], obj) | |
except ValidationError: | |
raise PresetError("プリセットの設定ファイルにミスがあります") | |
# idが一意か確認 | |
if len([preset.id for preset in _presets]) != len( | |
{preset.id for preset in _presets} | |
): | |
raise PresetError("プリセットのidに重複があります") | |
self.presets = _presets | |
self.last_modified_time = _last_modified_time | |
return self.presets | |
def add_preset(self, preset: Preset): | |
""" | |
YAMLファイルに新規のプリセットを追加する | |
Parameters | |
---------- | |
preset : Preset | |
追加するプリセットを渡す | |
Returns | |
------- | |
ret: int | |
追加したプリセットのプリセットID | |
""" | |
# 手動でファイルが更新されているかも知れないので、最新のYAMLファイルを読み直す | |
self.load_presets() | |
# IDが0未満、または存在するIDなら新しいIDを決定し、配列に追加 | |
if preset.id < 0 or preset.id in {preset.id for preset in self.presets}: | |
preset.id = max([preset.id for preset in self.presets]) + 1 | |
self.presets.append(preset) | |
# ファイルに書き込み | |
try: | |
with open(self.preset_path, mode="w", encoding="utf-8") as f: | |
yaml.safe_dump( | |
[preset.dict() for preset in self.presets], | |
f, | |
allow_unicode=True, | |
sort_keys=False, | |
) | |
except Exception as err: | |
self.presets.pop() | |
if isinstance(err, FileNotFoundError): | |
raise PresetError("プリセットの設定ファイルに書き込み失敗しました") | |
else: | |
raise err | |
return preset.id | |
def update_preset(self, preset: Preset): | |
""" | |
YAMLファイルのプリセットを更新する | |
Parameters | |
---------- | |
preset : Preset | |
更新するプリセットを渡す | |
Returns | |
------- | |
ret: int | |
更新したプリセットのプリセットID | |
""" | |
# 手動でファイルが更新されているかも知れないので、最新のYAMLファイルを読み直す | |
self.load_presets() | |
# IDが存在するか探索 | |
prev_preset = (-1, None) | |
for i in range(len(self.presets)): | |
if self.presets[i].id == preset.id: | |
prev_preset = (i, self.presets[i]) | |
self.presets[i] = preset | |
break | |
else: | |
raise PresetError("更新先のプリセットが存在しません") | |
# ファイルに書き込み | |
try: | |
with open(self.preset_path, mode="w", encoding="utf-8") as f: | |
yaml.safe_dump( | |
[preset.dict() for preset in self.presets], | |
f, | |
allow_unicode=True, | |
sort_keys=False, | |
) | |
except Exception as err: | |
if prev_preset != (-1, None): | |
self.presets[prev_preset[0]] = prev_preset[1] | |
if isinstance(err, FileNotFoundError): | |
raise PresetError("プリセットの設定ファイルに書き込み失敗しました") | |
else: | |
raise err | |
return preset.id | |
def delete_preset(self, id: int): | |
""" | |
YAMLファイルのプリセットを削除する | |
Parameters | |
---------- | |
id: int | |
削除するプリセットのプリセットIDを渡す | |
Returns | |
------- | |
ret: int | |
削除したプリセットのプリセットID | |
""" | |
# 手動でファイルが更新されているかも知れないので、最新のYAMLファイルを読み直す | |
self.load_presets() | |
# IDが存在するか探索 | |
buf = None | |
buf_index = -1 | |
for i in range(len(self.presets)): | |
if self.presets[i].id == id: | |
buf = self.presets.pop(i) | |
buf_index = i | |
break | |
else: | |
raise PresetError("削除対象のプリセットが存在しません") | |
# ファイルに書き込み | |
try: | |
with open(self.preset_path, mode="w", encoding="utf-8") as f: | |
yaml.safe_dump( | |
[preset.dict() for preset in self.presets], | |
f, | |
allow_unicode=True, | |
sort_keys=False, | |
) | |
except FileNotFoundError: | |
self.presets.insert(buf_index, buf) | |
raise PresetError("プリセットの設定ファイルに書き込み失敗しました") | |
return id | |