Skip to content

Commit 432f6db

Browse files
authored
Merge pull request #91 from simvue-io/save_files_in_created_state
Allow files to be saved & metadata/tags to be updated for runs in the created state
2 parents 439c809 + 554b75a commit 432f6db

8 files changed

+186
-11
lines changed

CHANGELOG.md

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

3+
## v0.13.3
4+
5+
* Allow files (`input` and `code` only) to be saved for runs in the `created` state.
6+
* Allow metadata and tags to be updated for runs in the `created` state.
7+
38
## v0.13.2
49

510
* Added `plot_metrics` method to the `Client` class to simplify plotting metrics.

simvue/run.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -389,10 +389,6 @@ def update_metadata(self, metadata):
389389
self._error(INIT_MISSING)
390390
return False
391391

392-
if not self._active:
393-
self._error('Run is not active')
394-
return False
395-
396392
if not isinstance(metadata, dict):
397393
self._error('metadata must be a dict')
398394
return False
@@ -415,10 +411,6 @@ def update_tags(self, tags):
415411
self._error(INIT_MISSING)
416412
return False
417413

418-
if not self._active:
419-
self._error('Run is not active')
420-
return False
421-
422414
data = {'name': self._name, 'tags': tags}
423415

424416
if self._simvue.update(data):
@@ -525,8 +517,8 @@ def save(self, filename, category, filetype=None, preserve_path=False, name=None
525517
self._error(INIT_MISSING)
526518
return False
527519

528-
if not self._active:
529-
self._error('Run is not active')
520+
if self._status == 'created' and category == 'output':
521+
self._error("Cannot upload output files for runs in the created state")
530522
return False
531523

532524
is_file = False

simvue/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '0.13.2'
1+
__version__ = '0.13.3'
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import configparser
2+
import filecmp
3+
import os
4+
import shutil
5+
import time
6+
import unittest
7+
import uuid
8+
from simvue import Run, Client
9+
from simvue.sender import sender
10+
11+
import common
12+
13+
class TestArtifactsCreatedState(unittest.TestCase):
14+
def test_artifact_code_created(self):
15+
"""
16+
Create a run & an artifact of type 'code' & check it can be downloaded for
17+
a run left in the created state
18+
"""
19+
run = Run()
20+
run.init(common.RUNNAME1, folder=common.FOLDER, running=False)
21+
22+
content = str(uuid.uuid4())
23+
with open(common.FILENAME1, 'w') as fh:
24+
fh.write(content)
25+
run.save(common.FILENAME1, 'code')
26+
27+
shutil.rmtree('./test', ignore_errors=True)
28+
os.mkdir('./test')
29+
30+
client = Client()
31+
client.get_artifact_as_file(common.RUNNAME1, common.FILENAME1, './test')
32+
33+
self.assertTrue(filecmp.cmp(common.FILENAME1, './test/%s' % common.FILENAME1))
34+
35+
runs = client.delete_runs(common.FOLDER)
36+
self.assertEqual(len(runs), 1)
37+
38+
shutil.rmtree('./test', ignore_errors=True)
39+
os.remove(common.FILENAME1)
40+
41+
if __name__ == '__main__':
42+
unittest.main()
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import configparser
2+
import filecmp
3+
import os
4+
import shutil
5+
import time
6+
import unittest
7+
import uuid
8+
from simvue import Run, Client
9+
from simvue.sender import sender
10+
11+
import common
12+
13+
class TestArtifactsCreated(unittest.TestCase):
14+
def test_artifact_input_created(self):
15+
"""
16+
Create a run & an artifact of type 'input' & check it can be downloaded
17+
for runs in the created state
18+
"""
19+
run = Run()
20+
run.init(common.RUNNAME2, folder=common.FOLDER, running=False)
21+
22+
content = str(uuid.uuid4())
23+
with open(common.FILENAME2, 'w') as fh:
24+
fh.write(content)
25+
run.save(common.FILENAME2, 'input')
26+
27+
shutil.rmtree('./test', ignore_errors=True)
28+
os.mkdir('./test')
29+
30+
client = Client()
31+
client.get_artifact_as_file(common.RUNNAME2, common.FILENAME2, './test')
32+
33+
self.assertTrue(filecmp.cmp(common.FILENAME2, './test/%s' % common.FILENAME2))
34+
35+
runs = client.delete_runs(common.FOLDER)
36+
self.assertEqual(len(runs), 1)
37+
38+
shutil.rmtree('./test', ignore_errors=True)
39+
os.remove(common.FILENAME2)
40+
41+
if __name__ == '__main__':
42+
unittest.main()
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import configparser
2+
import filecmp
3+
import os
4+
import shutil
5+
import time
6+
import unittest
7+
import uuid
8+
from simvue import Run, Client
9+
10+
import common
11+
12+
class TestArtifactsOutputCreated(unittest.TestCase):
13+
def test_artifact_output_created(self):
14+
"""
15+
Create a run in the created state and check that an output file
16+
cannot be saved.
17+
"""
18+
run = Run()
19+
run.init(common.RUNNAME3, folder=common.FOLDER, running=False)
20+
21+
content = str(uuid.uuid4())
22+
with open(common.FILENAME3, 'w') as fh:
23+
fh.write(content)
24+
25+
with self.assertRaises(Exception) as context:
26+
run.save(common.FILENAME3, 'output')
27+
28+
self.assertTrue('Cannot upload output files for runs in the created state' in str(context.exception))
29+
30+
client = Client()
31+
runs = client.delete_runs(common.FOLDER)
32+
self.assertEqual(len(runs), 1)
33+
34+
os.remove(common.FILENAME3)
35+
36+
if __name__ == '__main__':
37+
unittest.main()
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import unittest
2+
import uuid
3+
from simvue import Run, Client
4+
5+
import common
6+
7+
class TestRunMetadataUpdatedCreated(unittest.TestCase):
8+
def test_run_metadata_update_created(self):
9+
"""
10+
Check metadata can be updated & retrieved
11+
"""
12+
name = 'test-%s' % str(uuid.uuid4())
13+
metadata = {'a': 'string', 'b': 1, 'c': 2.5}
14+
run = Run()
15+
run.init(name, metadata=metadata, folder=common.FOLDER, running=False)
16+
run.update_metadata({'b': 2})
17+
18+
metadata['b'] = 2
19+
20+
client = Client()
21+
data = client.get_run(name, metadata=True)
22+
self.assertEqual(data['metadata'], metadata)
23+
24+
runs = client.delete_runs(common.FOLDER)
25+
self.assertEqual(len(runs), 1)
26+
27+
if __name__ == '__main__':
28+
unittest.main()
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import unittest
2+
import uuid
3+
from simvue import Run, Client
4+
5+
import common
6+
7+
class TestRunUpdateTagsCreated(unittest.TestCase):
8+
def test_run_tags_update_created(self):
9+
"""
10+
Check tags can be updated & retrieved for a run in the
11+
created state
12+
"""
13+
name = 'test-%s' % str(uuid.uuid4())
14+
tags = ['a1']
15+
run = Run()
16+
run.init(name, tags=tags, folder=common.FOLDER, running=False)
17+
run.update_tags(['b2'])
18+
19+
tags.append('b2')
20+
21+
client = Client()
22+
data = client.get_run(name, tags=True)
23+
self.assertEqual(tags, data['tags'])
24+
25+
runs = client.delete_runs(common.FOLDER)
26+
self.assertEqual(len(runs), 1)
27+
28+
if __name__ == '__main__':
29+
unittest.main()

0 commit comments

Comments
 (0)