Skip to content

Commit 3af12eb

Browse files
authored
Merge pull request #706 from simvue-io/v2.0
Create v2.0.0a1 release
2 parents 5313dae + 010abe5 commit 3af12eb

26 files changed

+797
-409
lines changed

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
# Change log
22

3+
## [v2.0.0-alpha1](https://github.com/simvue-io/client/releases/tag/v2.0.0a1) - 2025-02-19
4+
* Fixed `add_alerts` so that it now works with both IDs and names
5+
* Improved alert and folder deduplication methods to rely on 409 responses from server upon creation
6+
* Added `attach_to_run` option to create alerts methods so that alerts can be created without a run attached
7+
* Improved merging of local staging file and _staged dict using `deepmerge` - fixes bugs with tags, alerts and metadata in offline mode
8+
* Added `started`, `created` and `ended` timestamps to runs in offline mode
9+
* Remove all erronous server calls in offline mode
10+
* Fixed method to find simvue.toml config files, now just looks in cwd and home
11+
* Added run notification option to `run.init` so that users can now get emails upon their runs completing
12+
* Fixed artifact retrieval by run so that `category` parameter works correctly
13+
* Fixed bug where file artifacts wouldn't be saved correctly in offline mode if sender runs in different location to script
14+
* Fixed bug where DEBUG log messages were spamming to the console
15+
* Fixed link to run dashboard printed to the console by removing `/api`
16+
* Fixed bug where offline mode wouldn't work if no run name provided
17+
* Fixed bug where errors would be thrown if a traceback was logged as an event when a run was already terminated
18+
* Fixed hierarchical artifact retrieval to maintain directory structure
19+
* Loosened Numpy requirement to >2.0.0
20+
321
## [v2.0.0-alpha0](https://github.com/simvue-io/client/releases/tag/v2.0.0a0) - 2025-02-10
422

523
* Add support for defining Simvue run defaults using `tool.simvue` in a project `pyproject.toml` file.

CITATION.cff

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ keywords:
4242
- alerting
4343
- simulation
4444
license: Apache-2.0
45-
commit: 5aaebe682d7ec2f80fefc3eb2a8a26f5bdca1e0c
46-
version: 2.0.0a0
47-
date-released: '2025-02-11'
45+
commit: 124b2993d91dbff2e475aa972916b11e7bd02fa4
46+
version: 2.0.0a1
47+
date-released: '2025-02-19'
4848
references:
4949
- title: mlco2/codecarbon
5050
version: v2.8.2

poetry.lock

Lines changed: 243 additions & 224 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "simvue"
3-
version = "2.0.0a0"
3+
version = "2.0.0a1"
44
description = "Simulation tracking and monitoring"
55
authors = [
66
{name = "Simvue Development Team", email = "[email protected]"}
@@ -46,13 +46,14 @@ dependencies = [
4646
"humanfriendly (>=10.0,<11.0)",
4747
"randomname (>=0.2.1,<0.3.0)",
4848
"codecarbon (>=2.8.3,<3.0.0)",
49-
"numpy (>=2.2.2,<3.0.0)",
49+
"numpy (>=2.0.0,<3.0.0)",
5050
"flatdict (>=4.0.1,<5.0.0)",
5151
"semver (>=3.0.4,<4.0.0)",
5252
"email-validator (>=2.2.0,<3.0.0)",
5353
"psutil (>=6.1.1,<7.0.0)",
5454
"tenacity (>=9.0.0,<10.0.0)",
5555
"typing-extensions (>=4.12.2,<5.0.0) ; python_version < \"3.11\"",
56+
"deepmerge (>=2.0,<3.0)",
5657
]
5758

5859
[project.urls]

simvue/api/objects/alert/events.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ def new(
8787
_offline=offline,
8888
)
8989
_alert._staging |= _alert_definition
90+
_alert._params = {"deduplicate": True}
9091
return _alert
9192

9293

simvue/api/objects/alert/metrics.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ def new(
105105
_offline=offline,
106106
)
107107
_alert._staging |= _alert_definition
108+
_alert._params = {"deduplicate": True}
109+
108110
return _alert
109111

110112

@@ -194,6 +196,7 @@ def new(
194196
_offline=offline,
195197
)
196198
_alert._staging |= _alert_definition
199+
_alert._params = {"deduplicate": True}
197200
return _alert
198201

199202

simvue/api/objects/alert/user.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def new(
5757
whether this alert should be created locally, default is False
5858
5959
"""
60-
return UserAlert(
60+
_alert = UserAlert(
6161
name=name,
6262
description=description,
6363
notification=notification,
@@ -66,6 +66,8 @@ def new(
6666
_read_only=False,
6767
_offline=offline,
6868
)
69+
_alert._params = {"deduplicate": True}
70+
return _alert
6971

7072
@classmethod
7173
def get(

simvue/api/objects/artifact/base.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ def _upload(self, file: io.BytesIO) -> None:
9797
_response = sv_post(
9898
url=_url,
9999
headers={},
100+
params={},
100101
is_json=False,
101102
files={"file": file},
102103
data=self._init_data.get("fields"),

simvue/api/objects/artifact/fetch.py

Lines changed: 60 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,62 @@ def __new__(cls, identifier: str | None = None, **kwargs):
2323
else:
2424
return ObjectArtifact(identifier=identifier, **kwargs)
2525

26+
@classmethod
27+
def from_run(
28+
cls,
29+
run_id: str,
30+
category: typing.Literal["input", "output", "code"] | None = None,
31+
**kwargs,
32+
) -> typing.Generator[tuple[str, FileArtifact | ObjectArtifact], None, None]:
33+
"""Return artifacts associated with a given run.
34+
35+
Parameters
36+
----------
37+
run_id : str
38+
The ID of the run to retriece artifacts from
39+
category : typing.Literal["input", "output", "code"] | None, optional
40+
The category of artifacts to return, by default all artifacts are returned
41+
42+
Returns
43+
-------
44+
typing.Generator[tuple[str, FileArtifact | ObjectArtifact], None, None]
45+
The artifacts
46+
47+
Yields
48+
------
49+
Iterator[typing.Generator[tuple[str, FileArtifact | ObjectArtifact], None, None]]
50+
identifier for artifact
51+
the artifact itself as a class instance
52+
53+
Raises
54+
------
55+
ObjectNotFoundError
56+
Raised if artifacts could not be found for that run
57+
"""
58+
_temp = ArtifactBase(**kwargs)
59+
_url = URL(_temp._user_config.server.url) / f"runs/{run_id}/artifacts"
60+
_response = sv_get(
61+
url=f"{_url}", params={"category": category}, headers=_temp._headers
62+
)
63+
_json_response = get_json_from_response(
64+
expected_type=list,
65+
response=_response,
66+
expected_status=[http.HTTPStatus.OK, http.HTTPStatus.NOT_FOUND],
67+
scenario=f"Retrieval of artifacts for run '{run_id}'",
68+
)
69+
70+
if _response.status_code == http.HTTPStatus.NOT_FOUND or not _json_response:
71+
raise ObjectNotFoundError(
72+
_temp._label, category, extra=f"for run '{run_id}'"
73+
)
74+
75+
for _entry in _json_response:
76+
_id = _entry.pop("id")
77+
yield (
78+
_id,
79+
Artifact(_local=True, _read_only=True, identifier=_id, **_entry),
80+
)
81+
2682
@classmethod
2783
def from_name(
2884
cls, run_id: str, name: str, **kwargs
@@ -99,21 +155,9 @@ def get(
99155
if (_data := _json_response.get("data")) is None:
100156
raise RuntimeError(f"Expected key 'data' for retrieval of {_label}s")
101157

102-
_out_dict: dict[str, FileArtifact | ObjectArtifact] = {}
103-
104158
for _entry in _data:
105159
_id = _entry.pop("id")
106-
if _entry["original_path"]:
107-
yield (
108-
_id,
109-
FileArtifact(
110-
_local=True, _read_only=True, identifier=_id, **_entry
111-
),
112-
)
113-
else:
114-
yield (
115-
_id,
116-
ObjectArtifact(
117-
_local=True, _read_only=True, identifier=_id, **_entry
118-
),
119-
)
160+
yield (
161+
_id,
162+
Artifact(_local=True, _read_only=True, identifier=_id, **_entry),
163+
)

simvue/api/objects/artifact/file.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,15 @@ def new(
5252

5353
if _mime_type not in get_mimetypes():
5454
raise ValueError(f"Invalid MIME type '{mime_type}' specified")
55-
file_path = pathlib.Path(file_path)
56-
_file_size = file_path.stat().st_size
57-
_file_orig_path = file_path.expanduser().absolute()
58-
_file_checksum = calculate_sha256(f"{file_path}", is_file=True)
5955

60-
kwargs.pop("original_path", None)
61-
kwargs.pop("size", None)
62-
kwargs.pop("checksum", None)
56+
if _file_orig_path := kwargs.pop("original_path", None):
57+
_file_size = kwargs.pop("size")
58+
_file_checksum = kwargs.pop("checksum")
59+
else:
60+
file_path = pathlib.Path(file_path)
61+
_file_size = file_path.stat().st_size
62+
_file_orig_path = file_path.expanduser().absolute()
63+
_file_checksum = calculate_sha256(f"{file_path}", is_file=True)
6364

6465
_artifact = FileArtifact(
6566
name=name,

0 commit comments

Comments
 (0)