Skip to content
Merged
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
long_description_content_type="text/markdown",
url="https://simvue.io",
platforms=["any"],
install_requires=["requests", "msgpack", "tenacity", "pyjwt", "psutil"],
install_requires=["requests", "msgpack", "tenacity", "pyjwt", "psutil", "pydantic"],
package_dir={'': '.'},
packages=["simvue"],
package_data={"": ["README.md"]},
Expand Down
1 change: 1 addition & 0 deletions simvue/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from simvue.run import Run
from simvue.client import Client
from simvue.handler import Handler
from simvue.models import RunInput
__version__ = '0.7.1'
17 changes: 17 additions & 0 deletions simvue/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from datetime import datetime

import re
from pydantic import BaseModel, constr
from typing import Optional, List, Dict, Union
from enum import Enum

FolderStrRegex = constr(regex=r"^/.*")

# Pydantic class to validate run.init()
class RunInput(BaseModel):
name: Optional[str]
metadata: Optional[Dict[str, Union[str, int, float, None]]]
tags: Optional[List[str]]
description: Optional[str]
folder: FolderStrRegex
status: Optional[str]
17 changes: 8 additions & 9 deletions simvue/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@

from .worker import Worker
from .simvue import Simvue
from .models import RunInput
from .utilities import get_auth, get_expiry
from pydantic import ValidationError

INIT_MISSING = 'initialize a run using init() first'
QUEUE_SIZE = 10000
Expand Down Expand Up @@ -226,12 +228,6 @@ def init(self, name=None, metadata={}, tags=[], description=None, folder='/', ru
if not re.match(r'^[a-zA-Z0-9\-\_\s\/\.:]+$', name):
self._error('specified name is invalid')

if not isinstance(tags, list):
self._error('tags must be a list')

if not isinstance(metadata, dict):
self._error('metadata must be a dict')

self._name = name

if running:
Expand All @@ -252,16 +248,19 @@ def init(self, name=None, metadata={}, tags=[], description=None, folder='/', ru
if description:
data['description'] = description

if not folder.startswith('/'):
self._error('the folder must begin with /')

data['folder'] = folder

if self._status == 'running':
data['system'] = get_system()

self._check_token()

# compare with pydantic RunInput model
try:
runinput = RunInput(**data)
except ValidationError as e:
self._error(e)

self._simvue = Simvue(self._name, self._uuid, self._mode, self._suppress_errors)
name = self._simvue.create_run(data)

Expand Down
58 changes: 58 additions & 0 deletions tests/unit/test_simvue.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,61 @@ def test_suppress_errors():

with pytest.raises(RuntimeError, match="suppress_errors must be boolean"):
run.config(suppress_errors=200)

def test_run_init_metadata():
"""
Check that run.init throws an exception if tuples are passed into metadata dictionary
"""
os.environ["SIMVUE_TOKEN"] = "test"
os.environ["SIMVUE_URL"] = "https://simvue.io"

x1_lower = 2,
x1_upper = 6,

run = Run(mode='offline')

with pytest.raises(RuntimeError) as exc_info:
run.init(metadata={'dataset.x1_lower': x1_lower, 'dataset.x1_upper': x1_upper},
description="A test to validate inputs passed into metadata dictionary"
)

assert exc_info.match(r"value is not a valid integer")

def test_run_init_tags():
"""
Check that run.init throws an exception if tags are not a list
"""
os.environ["SIMVUE_TOKEN"] = "test"
os.environ["SIMVUE_URL"] = "https://simvue.io"

x1_lower = 2
x1_upper = 6

run = Run(mode='offline')

with pytest.raises(RuntimeError) as exc_info:
run.init(metadata={'dataset.x1_lower': x1_lower, 'dataset.x1_upper': x1_upper}, tags=1,
description="A test to validate tag inputs passed into run.init"
)

assert exc_info.match(r"value is not a valid list")

def test_run_init_folder():
"""
Check that run.init throws an exception if folder input is not specified correctly
"""
os.environ["SIMVUE_TOKEN"] = "test"
os.environ["SIMVUE_URL"] = "https://simvue.io"

x1_lower = 2
x1_upper = 6

run = Run(mode='offline')

with pytest.raises(RuntimeError) as exc_info:
run.init(metadata={'dataset.x1_lower': x1_lower, 'dataset.x1_upper': x1_upper}, tags=[1,2,3], folder='test_folder',
description="A test to validate folder input passed into run.init"
)

assert exc_info.match(r"string does not match regex")