Skip to content

Commit df1ff98

Browse files
authored
feat(api): delete project & experiment (#1138)
1 parent 5f9b57d commit df1ff98

File tree

6 files changed

+102
-1
lines changed

6 files changed

+102
-1
lines changed

swanlab/api/base.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def get_logger(log_level: str = "info") -> SwanLog:
3232

3333
def handle_response(resp: requests.Response) -> ApiResponse:
3434
try:
35-
data = resp.json()
35+
data = resp.json() if resp.content else {}
3636
except (json.decoder.JSONDecodeError, requests.JSONDecodeError):
3737
return ApiResponse[str](
3838
code=resp.status_code,
@@ -126,6 +126,11 @@ def post(self, url: str, data: Union[dict, list], params: dict) -> ApiResponse:
126126
resp = self.__session.post(self.base_url + url, json=data, params=params)
127127
return handle_response(resp)
128128

129+
def delete(self, url: str, params: dict) -> ApiResponse:
130+
self.__before_request()
131+
resp = self.__session.delete(self.base_url + url, params=params)
132+
return handle_response(resp)
133+
129134
class OpenApiService:
130135
def __init__(self, http: ApiHTTP):
131136
self.http: ApiHTTP = http

swanlab/api/experiment.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,22 @@ def get_experiment(
5252
resp.data = ExperimentAPI.parse(resp.data)
5353
return resp
5454

55+
def delete_experiment(
56+
self,
57+
username: str,
58+
projname: str,
59+
exp_id: str
60+
):
61+
"""
62+
删除实验
63+
64+
Args:
65+
username (str): 工作空间名
66+
projname (str): 项目名
67+
exp_id (str): 实验CUID
68+
"""
69+
return self.http.delete(f"/project/{username}/{projname}/runs/{exp_id}", params={})
70+
5571
def list_experiments(
5672
self,
5773
username: str,

swanlab/api/main.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,30 @@ def get_experiment(
8484
username=username if username else self.http.username, projname=project, exp_id=exp_id
8585
)
8686

87+
def delete_experiment(
88+
self,
89+
project: str,
90+
exp_id: str,
91+
username: str = ""
92+
) -> ApiResponse[None]:
93+
"""
94+
删除实验
95+
96+
Args:
97+
project (str): 项目名
98+
exp_id (str): 实验CUID
99+
username (str): 工作空间名, 默认为用户个人空间
100+
101+
Returns:
102+
ApiResponse[None]:
103+
- code (int): HTTP 状态码
104+
- errmsg (str): 错误信息, 仅在请求有错误时非空
105+
- data (None): 无数据返回
106+
"""
107+
return self.experiment.delete_experiment(
108+
username=username if username else self.http.username, projname=project, exp_id=exp_id
109+
)
110+
87111
def list_experiments(
88112
self,
89113
project: str,
@@ -109,6 +133,28 @@ def list_experiments(
109133
username=username if username else self.http.username
110134
)
111135

136+
def delete_project(
137+
self,
138+
project: str,
139+
username: str = ""
140+
) -> ApiResponse[None]:
141+
"""
142+
删除一个项目
143+
144+
Args:
145+
project (str): 项目名
146+
username (str): 工作空间名, 默认为用户个人空间
147+
148+
Returns:
149+
ApiResponse[None]:
150+
- code (int): HTTP 状态码
151+
- errmsg (str): 错误信息, 仅在请求有错误时非空
152+
- data (None): 无数据返回
153+
"""
154+
return self.project.delete_project(
155+
username=username if username else self.http.username, project=project
156+
)
157+
112158
def list_projects(
113159
self,
114160
username: str = "",

swanlab/api/project.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,18 @@ def parse(cls, body: dict, detail=True) -> Project:
3535
project_parser["count"] = body.get("_count") or {}
3636
return Project.model_validate(project_parser)
3737

38+
def delete_project(
39+
self, username: str, project: str
40+
) -> ApiResponse[None]:
41+
"""
42+
删除一个项目
43+
44+
Args:
45+
username (str): 工作空间名
46+
project (str): 项目名
47+
"""
48+
return self.http.delete(f"/project/{username}/{project}", params={})
49+
3850
def list_projects(
3951
self, username: str, detail = True, page: int = 1, size: int = 10
4052
) -> ApiResponse[Pagination[Project]]:

test/unit/api/test_experiment.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,14 @@ def test_get_summary():
5151
assert isinstance(res, ApiResponse)
5252
if res.code == 200:
5353
assert isinstance(res.data, dict)
54+
55+
@pytest.mark.skipif(T.is_skip_cloud_test, reason="skip cloud test")
56+
def test_delete_experiment():
57+
"""
58+
删除一个实验
59+
"""
60+
api = OpenApi()
61+
exp_cuid = "test_cuid"
62+
res = api.delete_experiment(project="test_project", exp_id=exp_cuid)
63+
assert isinstance(res, ApiResponse)
64+
assert res.code in [204, 404]

test/unit/api/test_project.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,14 @@ def test_list_projects():
2727
assert isinstance(resp.data, list)
2828
for item in resp.data:
2929
assert isinstance(item, Project)
30+
31+
@pytest.mark.skipif(T.is_skip_cloud_test, reason="skip cloud test")
32+
def test_delete_project():
33+
"""
34+
测试删除一个项目
35+
"""
36+
api = OpenApi()
37+
project_name = "test_project"
38+
resp = api.delete_project(project=project_name)
39+
assert isinstance(resp, ApiResponse)
40+
assert resp.code in [204, 404]

0 commit comments

Comments
 (0)