Skip to content

Commit 38b425d

Browse files
committed
Factorize deletion test
1 parent 6451472 commit 38b425d

File tree

2 files changed

+54
-34
lines changed

2 files changed

+54
-34
lines changed

skore-local-project/src/skore_local_project/project.py

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import io
66
import os
7+
from functools import wraps
78
from pathlib import Path
89
from types import SimpleNamespace
910
from typing import TYPE_CHECKING
@@ -40,6 +41,21 @@ class Metadata(TypedDict): # noqa: D101
4041
predict_time_mean: float | None
4142

4243

44+
def ensure_project_is_not_deleted(method):
45+
"""Ensure project is not deleted, before executing any other operation."""
46+
47+
@wraps(method)
48+
def wrapper(self, *args, **kwargs):
49+
if self.name not in self._Project__projects_storage:
50+
raise RuntimeError(
51+
f"Skore could not proceed because {repr(self)} does not exist anymore."
52+
)
53+
54+
return method(self, *args, **kwargs)
55+
56+
return wrapper
57+
58+
4359
class Project:
4460
r"""
4561
API to manage a collection of key-report pairs persisted in a local storage.
@@ -173,6 +189,7 @@ def pickle(report: EstimatorReport | CrossValidationReport) -> tuple[str, bytes]
173189

174190
return pickle_hash, pickle_bytes
175191

192+
@ensure_project_is_not_deleted
176193
def put(self, key: str, report: EstimatorReport | CrossValidationReport):
177194
"""
178195
Put a key-report pair to the local project.
@@ -207,12 +224,6 @@ def put(self, key: str, report: EstimatorReport | CrossValidationReport):
207224
f"ort` (found '{type(report)}')"
208225
)
209226

210-
if self.name not in self.__projects_storage:
211-
raise RuntimeError(
212-
f"Bad condition: {repr(self)} does not exist anymore, "
213-
f"it had to be removed."
214-
)
215-
216227
pickle_hash, pickle_bytes = Project.pickle(report)
217228

218229
if pickle_hash not in self.__artifacts_storage:
@@ -228,6 +239,7 @@ def put(self, key: str, report: EstimatorReport | CrossValidationReport):
228239
)
229240
)
230241

242+
@ensure_project_is_not_deleted
231243
def get(self, id: str) -> EstimatorReport:
232244
"""Get a persisted report by its id."""
233245
if id in self.__artifacts_storage:
@@ -236,14 +248,9 @@ def get(self, id: str) -> EstimatorReport:
236248

237249
raise KeyError(id)
238250

251+
@ensure_project_is_not_deleted
239252
def summarize(self) -> list[Metadata]:
240253
"""Obtain metadata/metrics for all persisted reports in insertion order."""
241-
if self.name not in self.__projects_storage:
242-
raise RuntimeError(
243-
f"Bad condition: {repr(self)} does not exist anymore, "
244-
f"it had to be removed."
245-
)
246-
247254
return [
248255
{
249256
"id": value["artifact_id"],
@@ -272,11 +279,6 @@ def summarize(self) -> list[Metadata]:
272279
@property
273280
def reports(self):
274281
"""Accessor for interaction with the persisted reports."""
275-
if self.name not in self.__projects_storage:
276-
raise RuntimeError(
277-
f"Bad condition: {repr(self)} does not exist anymore, "
278-
f"it had to be removed."
279-
)
280282

281283
def get(id: str) -> EstimatorReport:
282284
"""

skore-local-project/tests/unit/test_project.py

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -192,8 +192,9 @@ def test_put_exception(self, tmp_path, regression):
192192
with raises(
193193
RuntimeError,
194194
match=re.escape(
195-
f"Bad condition: {repr(project)} does not exist anymore, "
196-
f"it had to be removed.",
195+
f"Skore could not proceed because "
196+
f"Project(mode='local', name='<project>', workspace='{tmp_path}') "
197+
f"does not exist anymore."
197198
),
198199
):
199200
project.put("<key>", regression)
@@ -287,21 +288,6 @@ def test_reports(self, tmp_path):
287288
assert hasattr(project.reports, "get")
288289
assert hasattr(project.reports, "metadata")
289290

290-
def test_reports_exception(self, tmp_path):
291-
import re
292-
293-
project = Project("<project>", workspace=tmp_path)
294-
Project.delete("<project>", workspace=tmp_path)
295-
296-
with raises(
297-
RuntimeError,
298-
match=re.escape(
299-
f"Bad condition: {repr(project)} does not exist anymore, "
300-
f"it had to be removed.",
301-
),
302-
):
303-
project.reports # noqa: B018
304-
305291
def test_reports_get(self, tmp_path, regression):
306292
project = Project("<project>", workspace=tmp_path)
307293
project.put("<key>", regression)
@@ -315,6 +301,22 @@ def test_reports_get(self, tmp_path, regression):
315301
assert report.estimator_name_ == regression.estimator_name_
316302
assert report._ml_task == regression._ml_task
317303

304+
def test_reports_get_exception(self, tmp_path, regression):
305+
import re
306+
307+
project = Project("<project>", workspace=tmp_path)
308+
Project.delete("<project>", workspace=tmp_path)
309+
310+
with raises(
311+
RuntimeError,
312+
match=re.escape(
313+
f"Skore could not proceed because "
314+
f"Project(mode='local', name='<project>', workspace='{tmp_path}') "
315+
f"does not exist anymore."
316+
),
317+
):
318+
project.reports.get(None)
319+
318320
def test_reports_metadata(self, tmp_path, Datetime, regression, cv_regression):
319321
project = Project("<project>", workspace=tmp_path)
320322

@@ -389,6 +391,22 @@ def test_reports_metadata(self, tmp_path, Datetime, regression, cv_regression):
389391
},
390392
]
391393

394+
def test_reports_metadata_exception(self, tmp_path, regression):
395+
import re
396+
397+
project = Project("<project>", workspace=tmp_path)
398+
Project.delete("<project>", workspace=tmp_path)
399+
400+
with raises(
401+
RuntimeError,
402+
match=re.escape(
403+
f"Skore could not proceed because "
404+
f"Project(mode='local', name='<project>', workspace='{tmp_path}') "
405+
f"does not exist anymore."
406+
),
407+
):
408+
project.reports.metadata()
409+
392410
def test_delete(self, tmp_path, binary_classification, regression):
393411
project1 = Project("<project1>", workspace=tmp_path)
394412
project1.put("<project1-key1>", binary_classification)

0 commit comments

Comments
 (0)