Skip to content
Snippets Groups Projects
Commit 31bd792c authored by André Anjos's avatar André Anjos :speech_balloon:
Browse files

Merge branch 'implement_asset_model' into 'v2'

[backend] Implement AssetModel class

See merge request !40
parents 93e44552 c0613f52
No related branches found
No related tags found
1 merge request!40[backend] Implement AssetModel class
Pipeline #26090 passed
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
###############################################################################
# #
# Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/ #
# Contact: beat.support@idiap.ch #
# #
# This file is part of the beat.cmdline module of the BEAT platform. #
# #
# Commercial License Usage #
# Licensees holding valid commercial BEAT licenses may use this file in #
# accordance with the terms contained in a written agreement between you #
# and Idiap. For further information contact tto@idiap.ch #
# #
# Alternatively, this file may be used under the terms of the GNU Affero #
# Public License version 3 as published by the Free Software and appearing #
# in the file LICENSE.AGPL included in the packaging of this file. #
# The BEAT platform is distributed in the hope that it will be useful, but #
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY #
# or FITNESS FOR A PARTICULAR PURPOSE. #
# #
# You should have received a copy of the GNU Affero Public License along #
# with the BEAT platform. If not, see http://www.gnu.org/licenses/. #
# #
###############################################################################
# vim: set fileencoding=utf-8 :
###############################################################################
# #
# Copyright (c) 2019 Idiap Research Institute, http://www.idiap.ch/ #
# Contact: beat.support@idiap.ch #
# #
# This file is part of the beat.editor module of the BEAT platform. #
# #
# Commercial License Usage #
# Licensees holding valid commercial BEAT licenses may use this file in #
# accordance with the terms contained in a written agreement between you #
# and Idiap. For further information contact tto@idiap.ch #
# #
# Alternatively, this file may be used under the terms of the GNU Affero #
# Public License version 3 as published by the Free Software and appearing #
# in the file LICENSE.AGPL included in the packaging of this file. #
# The BEAT platform is distributed in the hope that it will be useful, but #
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY #
# or FITNESS FOR A PARTICULAR PURPOSE. #
# #
# You should have received a copy of the GNU Affero Public License along #
# with the BEAT platform. If not, see http://www.gnu.org/licenses/. #
# #
###############################################################################
import os
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtCore import pyqtProperty
from PyQt5.QtCore import Q_ENUMS
from PyQt5.QtCore import QStringListModel
class AssetType:
"""All possible assets available on the BEAT platform"""
Unknown = 0
Algorithm = 1
Database = 2
Dataformat = 3
Experiment = 4
Library = 5
Plotter = 6
Toolchain = 7
@classmethod
def path(cls, type_):
path = "unkown"
if type_ == cls.Algorithm:
path = "algorithms"
elif type_ == cls.Database:
path = "databases"
elif type_ == cls.Dataformat:
path = "dataformats"
elif type_ == cls.Experiment:
path = "experiments"
elif type_ == cls.Library:
path = "libraries"
elif type_ == cls.Plotter:
path = "plotters"
elif type_ == cls.Toolchain:
path = "toolchains"
return path
class AssetModel(QStringListModel, AssetType):
"""The asset model present a list of available asset from a given type"""
Q_ENUMS(AssetType)
assetTypeChanged = pyqtSignal(AssetType)
prefixPathChanged = pyqtSignal(str)
def __init__(self, parent=None):
"""Constructor"""
super(QStringListModel, self).__init__(parent)
self.__prefix_path = AssetType.Unknown
self.__asset_type = None
@pyqtSlot()
def reload(self):
"""Loads the content regarding the asset property from the prefix"""
if not self.__prefix_path or self.__asset_type == AssetType.Unknown:
return
asset_folder = os.path.join(
self.__prefix_path, AssetType.path(self.__asset_type)
)
asset_users = os.scandir(asset_folder)
latest_assets_list = []
for asset_user in asset_users:
for asset_folder in os.scandir(asset_user):
if self.asset_type == AssetType.Experiment:
for root, dirs, files in os.walk(asset_folder, topdown=False):
if dirs:
continue
anchor = "experiments/"
position = root.index(anchor) + len(anchor)
experiment_path = root[position:]
for json_file in [
file for file in files if file.endswith("json")
]:
latest_assets_list.append(
"{experiment_path}/{name}".format(
experiment_path=experiment_path,
name=json_file.split(".")[0],
)
)
else:
asset_items = os.scandir(asset_folder)
json_files = sorted(
[
item.name
for item in asset_items
if item.is_file() and item.name.endswith("json")
]
)
if json_files:
latest_assets_list.append(
"{user}/{name}/{version}".format(
user=asset_user.name,
name=asset_folder.name,
version=json_files[-1].split(".")[0],
)
)
self.setStringList(sorted(latest_assets_list))
def assetType(self):
"""Returns the asset type of this model
:return: Asset type of this model
"""
return self.__asset_type
def setAssetType(self, type_):
"""Set the asset type of this model
:param AssetType type_: Asset type this model should show
"""
if self.__asset_type == type_:
return
self.__asset_type = type_
self.reload()
self.assetTypeChanged.emit(type_)
asset_type = pyqtProperty(
AssetType, fget=assetType, fset=setAssetType, notify=assetTypeChanged
)
def prefixPath(self):
"""Returns the prefix path use by this model
:return: the prefix path used
"""
return self.__prefix_path
def setPrefixPath(self, path):
"""Set the prefix path use by this model
:param str path: Path to prefix
"""
if self.__prefix_path == path:
return
self.__prefix_path = path
self.reload()
self.prefixPathChanged.emit(path)
prefix_path = pyqtProperty(
str, fget=prefixPath, fset=setPrefixPath, notify=prefixPathChanged
)
# vim: set fileencoding=utf-8 :
###############################################################################
# #
# Copyright (c) 2019 Idiap Research Institute, http://www.idiap.ch/ #
# Contact: beat.support@idiap.ch #
# #
# This file is part of the beat.editor module of the BEAT platform. #
# #
# Commercial License Usage #
# Licensees holding valid commercial BEAT licenses may use this file in #
# accordance with the terms contained in a written agreement between you #
# and Idiap. For further information contact tto@idiap.ch #
# #
# Alternatively, this file may be used under the terms of the GNU Affero #
# Public License version 3 as published by the Free Software and appearing #
# in the file LICENSE.AGPL included in the packaging of this file. #
# The BEAT platform is distributed in the hope that it will be useful, but #
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY #
# or FITNESS FOR A PARTICULAR PURPOSE. #
# #
# You should have received a copy of the GNU Affero Public License along #
# with the BEAT platform. If not, see http://www.gnu.org/licenses/. #
# #
###############################################################################
import os
import sys
import tempfile
import pytest
import pkg_resources
import subprocess
import shutil
import importlib
if sys.platform == "darwin":
prefix_folder = tempfile.mkdtemp(prefix=__name__, suffix=".prefix", dir="/tmp")
else:
prefix_folder = tempfile.mkdtemp(prefix=__name__, suffix=".prefix")
prefix = os.path.join(prefix_folder, "prefix")
@pytest.fixture(scope="module")
def test_prefix():
prefixes = [
pkg_resources.resource_filename("beat.backend.python.test", "prefix"),
pkg_resources.resource_filename("beat.core.test", "prefix"),
]
for path in prefixes:
subprocess.check_call(["rsync", "-arz", path, prefix_folder])
yield prefix
shutil.rmtree(prefix_folder)
# Getting the prefix from beat.core triggers its setup_package but not the
# corresponding tear down, therefore trigger it manually
beat_core_test = importlib.import_module("beat.core.test")
teardown_package = getattr(beat_core_test, "teardown_package")
teardown_package()
# vim: set fileencoding=utf-8 :
###############################################################################
# #
# Copyright (c) 2019 Idiap Research Institute, http://www.idiap.ch/ #
# Contact: beat.support@idiap.ch #
# #
# This file is part of the beat.editor module of the BEAT platform. #
# #
# Commercial License Usage #
# Licensees holding valid commercial BEAT licenses may use this file in #
# accordance with the terms contained in a written agreement between you #
# and Idiap. For further information contact tto@idiap.ch #
# #
# Alternatively, this file may be used under the terms of the GNU Affero #
# Public License version 3 as published by the Free Software and appearing #
# in the file LICENSE.AGPL included in the packaging of this file. #
# The BEAT platform is distributed in the hope that it will be useful, but #
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY #
# or FITNESS FOR A PARTICULAR PURPOSE. #
# #
# You should have received a copy of the GNU Affero Public License along #
# with the BEAT platform. If not, see http://www.gnu.org/licenses/. #
# #
###############################################################################
from ..backend.assetmodel import AssetModel
class TestAssetModel:
"""Test that the mock editor works correctly"""
def test_model_load(self, qtbot, test_prefix):
model = AssetModel()
asset_type = AssetModel.Dataformat
with qtbot.waitSignals(
[model.assetTypeChanged, model.prefixPathChanged]
) as blocker:
model.asset_type = asset_type
model.prefix_path = test_prefix
assert blocker.all_signals_and_args[0].args[0] == asset_type
assert blocker.all_signals_and_args[1].args[0] == test_prefix
asset_list = model.stringList()
for item in asset_list:
assert len(item.split("/")) == 3
def test_experiment_model_load(self, qtbot, test_prefix):
model = AssetModel()
asset_type = AssetModel.Experiment
with qtbot.waitSignals(
[model.assetTypeChanged, model.prefixPathChanged]
) as blocker:
model.asset_type = asset_type
model.prefix_path = test_prefix
assert blocker.all_signals_and_args[0].args[0] == asset_type
assert blocker.all_signals_and_args[1].args[0] == test_prefix
asset_list = model.stringList()
for item in asset_list:
assert len(item.split("/")) == 5
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment