From a9dcd804ed094cdf73a3444aa3c86e8bb36cb494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Zar=C4=99bski?= Date: Tue, 26 Mar 2024 14:35:37 +0000 Subject: [PATCH 1/2] Added decorator to prevent pre-mature Run function calls --- simvue/run.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/simvue/run.py b/simvue/run.py index fee5054a..fccf679e 100644 --- a/simvue/run.py +++ b/simvue/run.py @@ -175,6 +175,20 @@ def validate_timestamp(timestamp): return True +def check_run_initialised( + function: typing.Callable[..., typing.Any], +) -> typing.Callable[..., typing.Any]: + def _wrapper(self: "Run", *args: typing.Any, **kwargs: typing.Any) -> typing.Any: + if not self._simvue: + raise RuntimeError( + "Simvue Run must be initialised before calling " + f"'{function.__name__}'" + ) + return function(self, *args, **kwargs) + + return _wrapper + + class Run(object): """ Track simulation details based on token and URL @@ -184,6 +198,7 @@ def __init__(self, mode="online"): self._uuid = str(uuid.uuid4()) self._mode = mode self._name = None + self._worker = None self._executor = Executor(self) self._id = None self._suppress_errors = False @@ -595,6 +610,7 @@ def config( if storage_id: self._storage_id = storage_id + @check_run_initialised def update_metadata(self, metadata): """ Add/update metadata @@ -635,6 +651,7 @@ def update_tags(self, tags): return False + @check_run_initialised def log_event(self, message, timestamp=None): """ Write event @@ -671,6 +688,7 @@ def log_event(self, message, timestamp=None): return True + @check_run_initialised def log_metrics(self, metrics, step=None, time=None, timestamp=None): """ Write metrics @@ -721,6 +739,7 @@ def log_metrics(self, metrics, step=None, time=None, timestamp=None): return True + @check_run_initialised def save( self, filename, @@ -823,6 +842,7 @@ def save( return True + @check_run_initialised def save_directory(self, directory, category, filetype=None, preserve_path=False): """ Upload a whole directory @@ -854,6 +874,7 @@ def save_directory(self, directory, category, filetype=None, preserve_path=False return True + @check_run_initialised def save_all(self, items, category, filetype=None, preserve_path=False): """ Save the list of files and/or directories @@ -869,6 +890,7 @@ def save_all(self, items, category, filetype=None, preserve_path=False): else: self._error(f"{item}: No such file or directory") + @check_run_initialised def set_status(self, status): """ Set run status @@ -915,6 +937,7 @@ def close(self): self._shutdown_event.set() + @check_run_initialised def set_folder_details(self, path, metadata={}, tags=[], description=None): """ Add metadata to the specified folder @@ -954,6 +977,7 @@ def set_folder_details(self, path, metadata={}, tags=[], description=None): return False + @check_run_initialised def add_alerts(self, ids=None, names=None): """ Add one or more existing alerts by name or id @@ -980,6 +1004,7 @@ def add_alerts(self, ids=None, names=None): return False + @check_run_initialised def add_alert( self, name, @@ -1086,6 +1111,7 @@ def add_alert( return False + @check_run_initialised def log_alert(self, name, state): """ Set the state of an alert From 4f555874b9d142d4a3b5ac6dcf441c096e3d7628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20Zar=C4=99bski?= Date: Fri, 19 Apr 2024 10:01:18 +0100 Subject: [PATCH 2/2] Added init check decorator test --- simvue/run.py | 2 ++ tests/refactor/test_run_class.py | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/simvue/run.py b/simvue/run.py index 455ca952..b5e8e124 100644 --- a/simvue/run.py +++ b/simvue/run.py @@ -71,6 +71,8 @@ def _wrapper(self: "Run", *args: typing.Any, **kwargs: typing.Any) -> typing.Any ) return function(self, *args, **kwargs) + _wrapper.__name__ = f"{function.__name__}__init_locked" + return _wrapper diff --git a/tests/refactor/test_run_class.py b/tests/refactor/test_run_class.py index d5cd6b57..fb4a60dd 100644 --- a/tests/refactor/test_run_class.py +++ b/tests/refactor/test_run_class.py @@ -6,6 +6,7 @@ import uuid import concurrent.futures import random +import inspect import simvue.run as sv_run import simvue.client as sv_cl @@ -14,6 +15,16 @@ from .conftest import CountingLogHandler +@pytest.mark.run +def test_check_run_initialised_decorator() -> None: + with sv_run.Run(mode="offline") as run: + for method_name, method in inspect.getmembers(run, inspect.ismethod): + if not method.__name__.endswith("init_locked"): + continue + with pytest.raises(RuntimeError) as e: + getattr(run, method_name)() + assert "Simvue Run must be initialised" in str(e.value) + @pytest.mark.run @pytest.mark.parametrize("overload_buffer", (True, False), ids=("overload", "normal")) def test_log_metrics(