#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
###############################################################################
# #
# Copyright (c) 2017 Idiap Research Institute, http://www.idiap.ch/ #
# Contact: beat.support@idiap.ch #
# #
# This file is part of the beat.web 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 django.db import models
from django.db.models import Count
from django.db.models import Q
from django.urls import reverse
from ...code.models import Code
from ...common.models import Shareable
from ...common.models import ShareableManager
from ...common.texts import Messages
# ----------------------------------------------------------
[docs]class EnvironmentManager(ShareableManager):
[docs] def get_by_natural_key(self, name, version):
return self.get(name=name, version=version)
[docs] def get_by_fullname(self, fullname):
name, version = fullname.rsplit(" ", 1)
return self.get_by_natural_key(name, version[1:-1])
[docs] def use_count(self, block_list):
"""Returns a list of environments used for the blocks in that list with
how many times each has been used.
Parameters:
block_list (Block) : list of blocks to analyze.
Returns:
list: annotated environments with the number of time they have been
used for blocks that are done.
"""
from ...experiments.models import Block
from ...experiments.models import Experiment
# Tries to figure through a maximum if blocks in the list have been
# successfully used inside an environment.
# Case 1) The block is part of an experiment that was successful
# Case 2) The block is part of an experiment that is not successful
# (failed or other), but it is CACHED (if not cached, then we can't
# attest anything about the block/environment relationship!)
return (
self.filter(
blocks__in=block_list.filter(
Q(experiment__status=Experiment.DONE)
| ((~Q(experiment__status=Experiment.DONE)) & Q(status=Block.DONE))
)
)
.annotate(use_count=Count("id"))
.order_by("-creation_date")
.distinct()
)
# ----------------------------------------------------------
[docs]class Environment(Shareable):
"""Defines a software environment to run algorithms"""
name = models.CharField(max_length=200, help_text=Messages["name"])
version = models.CharField(
max_length=20,
help_text="Free-style version for this environment (normally read from the Worker/Scheduler available environments)",
)
short_description = models.CharField(
max_length=100, default="", blank=True, help_text=Messages["short_description"]
)
description = models.TextField(
default="", blank=True, help_text=Messages["description"]
)
creation_date = models.DateTimeField("Creation date", auto_now_add=True)
active = models.BooleanField(
default=True, help_text="If this environment can be used in experiments"
)
previous_version = models.ForeignKey(
"self",
related_name="next_versions",
null=True,
blank=True,
on_delete=models.SET_NULL,
)
objects = EnvironmentManager()
# _____ Meta parameters __________
class Meta:
unique_together = ("name", "version")
# _____ Overrides __________
def __str__(self):
return self.fullname()
[docs] def natural_key(self):
return (self.name, self.version)
# _____ Utilities __________
[docs] def fullname(self):
return "%s (%s)" % (self.name, self.version)
[docs] def get_absolute_url(self):
return reverse("backend:view-environment", args=(self.name, self.version))
[docs] def get_admin_change_url(self):
return reverse("admin:backend_environment_change", args=(self.id,))
[docs] def queues_for(self, user):
"""Returns all queues associated to this environment for which the user
has the 'can_access' permission"""
return [q for q in self.queues.all() if user.has_perm("backend.can_access", q)]
[docs] def as_dict(self):
"""Returns a representation as a dictionary"""
return dict(
name=self.name,
version=self.version,
short_description=self.short_description,
description=self.description,
)
# ----------------------------------------------------------
[docs]class EnvironmentLanguage(models.Model):
environment = models.ForeignKey(
Environment, related_name="languages", on_delete=models.CASCADE
)
language = models.CharField(
max_length=1, choices=Code.CODE_LANGUAGE, default=Code.PYTHON
)