Commit 7f6fb900 authored by André Anjos's avatar André Anjos 💬

Merge branch '79_implement_missing_prototypes_handling' into 'master'

Implement missing prototypes handling

Closes #79

See merge request !74
parents 58489f6d e5b6cf6b
Pipeline #29970 passed with stages
in 20 minutes and 59 seconds
...@@ -56,6 +56,22 @@ from . import prototypes ...@@ -56,6 +56,22 @@ from . import prototypes
from beat.backend.python.database import Storage from beat.backend.python.database import Storage
from beat.backend.python.database import Database as BackendDatabase from beat.backend.python.database import Database as BackendDatabase
from beat.backend.python.protocoltemplate import Storage as PTStorage
def get_first_procotol_template(prefix):
pt_root_folder = os.path.join(prefix, PTStorage.asset_folder)
pts_available = os.listdir(pt_root_folder)
if not pts_available:
raise RuntimeError("Invalid prefix content, no protocol template available")
procotol_template_folder = pts_available[0]
protocol_template_versions = sorted(
os.listdir(os.path.join(pt_root_folder, procotol_template_folder))
)
version = protocol_template_versions[-1].split(".")[0]
return "{}/{}".format(procotol_template_folder, version)
class Database(BackendDatabase): class Database(BackendDatabase):
...@@ -132,8 +148,17 @@ class Database(BackendDatabase): ...@@ -132,8 +148,17 @@ class Database(BackendDatabase):
self.errors.append("Database declaration file not found: %s" % data) self.errors.append("Database declaration file not found: %s" % data)
return return
# this runs basic validation, including JSON loading if required # At this point, `data' can be a dictionary or ``None``
self.data, self.errors = schema.validate("database", data) if data is None: # loads the default declaration for a database
self.data, self.errors = prototypes.load("database")
self.data["protocols"][0]["template"] = get_first_procotol_template(
self.prefix
)
assert not self.errors, "\n * %s" % "\n *".join(self.errors) # nosec
else:
# this runs basic validation, including JSON loading if required
self.data, self.errors = schema.validate("database", data)
if self.errors: if self.errors:
return # don't proceed with the rest of validation return # don't proceed with the rest of validation
...@@ -148,7 +173,7 @@ class Database(BackendDatabase): ...@@ -148,7 +173,7 @@ class Database(BackendDatabase):
# At this point, `code' can be a string (or a binary blob) or ``None`` # At this point, `code' can be a string (or a binary blob) or ``None``
if code is None: # loads the default code for an algorithm if code is None: # loads the default code for an algorithm
self.code = prototypes.binary_load("view.py") self.code = prototypes.binary_load("database.py")
else: # just assign it - notice that in this case, no language is set else: # just assign it - notice that in this case, no language is set
self.code = code self.code = code
......
...@@ -52,7 +52,6 @@ from . import algorithm ...@@ -52,7 +52,6 @@ from . import algorithm
from . import schema from . import schema
from . import database from . import database
from . import toolchain from . import toolchain
from . import prototypes
from . import hash from . import hash
...@@ -233,12 +232,10 @@ class Experiment(object): ...@@ -233,12 +232,10 @@ class Experiment(object):
self.data = None self.data = None
self.errors = [] self.errors = []
if data is None: # loads prototype and validates it if data is None: # Invalid case
# There can't be a prototype for experiments they must be
experiment_data, self.errors = prototypes.load("experiment") # filled based on the toolchain and the content of the prefix
assert not self.errors, "\n * %s" % "\n *".join(self.errors) # nosec raise RuntimeError("Experiments can't have default implementation")
toolchain_data, self.errors = prototypes.load("toolchain")
assert not self.errors, "\n * %s" % "\n *".join(self.errors) # nosec
elif isinstance(data, (tuple, list)): # the user has passed a tuple elif isinstance(data, (tuple, list)): # the user has passed a tuple
......
{
"root_folder": "/tmp/foo/bar",
"protocols": [
{
"name": "foo",
"template": "bar/1",
"views": {
"foo": {
"view": "FooView"
}
}
}
],
"schema_version": 2
}
import numpy
from collections import namedtuple
from beat.backend.python.database import View
class FooView(View):
def setup(
self,
root_folder,
outputs,
parameters,
force_start_index=None,
force_end_index=None,
):
"""Initializes the database"""
return True
def index(self, root_folder, parameters):
"""Creates the data for the database indexation"""
Entry = namedtuple("Entry", ["out"])
return [Entry(42)]
def get(self, output, index):
"""Returns the data for the output based on the index content"""
obj = self.objs[index]
if output == "out":
return {"value": numpy.int32(obj.out)}
class View:
def setup(
self,
root_folder,
outputs,
parameters,
force_start_index=None,
force_end_index=None,
):
"""Initializes the database"""
return True
def done(self):
"""Should return ``True``, when data is finished"""
return True
def next(self):
"""Loads the next data block on ``outputs``"""
return True
...@@ -42,6 +42,17 @@ from . import prefix, tmp_prefix ...@@ -42,6 +42,17 @@ from . import prefix, tmp_prefix
from .utils import cleanup from .utils import cleanup
# ----------------------------------------------------------
@nose.tools.raises(RuntimeError)
def test_load_default_experiment_fails():
Experiment(prefix, data=None)
# ----------------------------------------------------------
def test_load_valid_experiment(): def test_load_valid_experiment():
experiment = Experiment(prefix, "user/integers_addition/1/integers_addition") experiment = Experiment(prefix, "user/integers_addition/1/integers_addition")
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment