Skip to content

Commit 8bbcdf0

Browse files
committed
Support namespaces root query/update APIs
1 parent 42a355a commit 8bbcdf0

File tree

3 files changed

+68
-10
lines changed

3 files changed

+68
-10
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,4 +178,6 @@ models/**
178178
!models/pretrained/
179179
!models/pretrained/.gitkeep
180180

181-
tb_logs/
181+
tb_logs/
182+
.namespaces_root.metadata.json
183+
easevoice_trainer_namespaces/

src/rest/rest.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,18 @@ def _register_routes(self):
171171
status_code=204, # No body in response
172172
summary="Delete a namespace",
173173
)
174+
self.router.add_api_route(
175+
path="/namespaces-root",
176+
endpoint=self.get_namespaces_root,
177+
methods=["GET"],
178+
summary="Get namespaces root directory",
179+
)
180+
self.router.add_api_route(
181+
path="/namespaces-root",
182+
endpoint=self.set_namespaces_root,
183+
methods=["POST"],
184+
summary="Set namespaces root directory",
185+
)
174186

175187
async def list_namespaces(self):
176188
"""List all namespaces."""
@@ -202,6 +214,17 @@ async def remove_namespace(self, name: str):
202214
except ValueError as e:
203215
raise HTTPException(status_code=404, detail=str(e))
204216

217+
async def get_namespaces_root(self):
218+
"""Get namespaces root directory."""
219+
return self.namespace_service.get_namespaces_root_metadata()
220+
221+
async def set_namespaces_root(self, request: dict):
222+
"""Set namespaces root directory."""
223+
try:
224+
self.namespace_service.set_namespaces_root(request["namespaces-root"])
225+
except ValueError as e:
226+
raise HTTPException(status_code=400, detail=str(e))
227+
205228

206229
class FileAPI:
207230
"""Encapsulated API logic for file operations."""

src/service/namespace.py

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
2+
import logging
23
import json
34
import shutil
45
from datetime import datetime, timezone
@@ -8,15 +9,47 @@ class NamespaceService:
89
"""Manages namespaces on the filesystem."""
910

1011
def __init__(self, base_dir: Optional[str] = None):
11-
self.base_dir = base_dir or os.path.join(os.path.expanduser("~"), "easevoice_trainer_namespaces")
12-
os.makedirs(self.base_dir, exist_ok=True)
12+
ns_root = os.getenv("EASEVOICE_TRAINER_NAMESPACES_ROOT", os.path.join(os.getcwd(), "easevoice_trainer_namespaces"))
13+
14+
# Fixed path to the metadata file for the namespaces root.
15+
self.ns_root_metadata_path = os.path.join(os.getcwd(), ".namespaces_root.metadata.json")
16+
17+
# Create the default namespace root anyway in the beginning.
18+
self.ns_root = ns_root
19+
os.makedirs(self.ns_root, exist_ok=True)
20+
21+
# The first time saving does not count as a set-once operation.
22+
self._save_ns_root_metadata(setOnce=False)
23+
24+
def _save_ns_root_metadata(self, setOnce: bool):
25+
with open(self.ns_root_metadata_path, "w") as f:
26+
json.dump({
27+
"namespaces-root": self.ns_root,
28+
"setOnce": setOnce,
29+
}, f)
30+
31+
def get_namespaces_root_metadata(self) -> str:
32+
with open(self.ns_root_metadata_path, "r") as f:
33+
return json.load(f)
34+
35+
def set_namespaces_root(self, ns_root: str):
36+
if os.path.exists(self.ns_root_metadata_path):
37+
with open(self.ns_root_metadata_path, "r") as f:
38+
metadata = json.load(f)
39+
if metadata["setOnce"]:
40+
logging.warning("change namespaces root %s to %s while setOnce is true", self.ns_root, ns_root)
41+
42+
self.ns_root = ns_root
43+
os.makedirs(self.ns_root, exist_ok=True)
44+
45+
self._save_ns_root_metadata(setOnce=True)
1346

1447
def _namespace_metadata_path(self, name: str) -> str:
15-
return os.path.join(self.base_dir, name, ".metadata.json")
48+
return os.path.join(self.ns_root, name, ".metadata.json")
1649

1750
def create_namespace(self, name: str) -> dict:
1851
"""Create a new namespace, raising FileExistsError if it already exists."""
19-
home_path = os.path.join(self.base_dir, name)
52+
home_path = os.path.join(self.ns_root, name)
2053
if os.path.exists(home_path):
2154
raise FileExistsError("Namespace already exists")
2255

@@ -33,8 +66,8 @@ def create_namespace(self, name: str) -> dict:
3366
def get_namespaces(self) -> List[dict]:
3467
"""List all namespaces."""
3568
namespaces = []
36-
for name in os.listdir(self.base_dir):
37-
namespace_path = os.path.join(self.base_dir, name)
69+
for name in os.listdir(self.ns_root):
70+
namespace_path = os.path.join(self.ns_root, name)
3871
if os.path.isdir(namespace_path):
3972
try:
4073
namespaces.append(self._load_namespace_metadata(name))
@@ -44,8 +77,8 @@ def get_namespaces(self) -> List[dict]:
4477

4578
def update_namespace(self, old_name: str, new_name: str) -> dict:
4679
"""Rename a namespace, raising FileExistsError if the new name is taken."""
47-
old_home_path = os.path.join(self.base_dir, old_name)
48-
new_home_path = os.path.join(self.base_dir, new_name)
80+
old_home_path = os.path.join(self.ns_root, old_name)
81+
new_home_path = os.path.join(self.ns_root, new_name)
4982

5083
if not os.path.exists(old_home_path):
5184
raise ValueError("Namespace not found")
@@ -64,7 +97,7 @@ def update_namespace(self, old_name: str, new_name: str) -> dict:
6497

6598
def delete_namespace(self, name: str):
6699
"""Delete a namespace, raising ValueError if it does not exist."""
67-
home_path = os.path.join(self.base_dir, name)
100+
home_path = os.path.join(self.ns_root, name)
68101
if not os.path.exists(home_path):
69102
raise ValueError("Namespace not found")
70103

0 commit comments

Comments
 (0)