diff --git a/beat/web/libraries/models.py b/beat/web/libraries/models.py index 6e85a6cc010f5a00529f0f2d62c7158e6ecb9973..436e5878754446ea690f14ceb5a776d327e76ca7 100644 --- a/beat/web/libraries/models.py +++ b/beat/web/libraries/models.py @@ -43,18 +43,20 @@ import simplejson import collections -#---------------------------------------------------------- +# ---------------------------------------------------------- def validate_library(declaration): """Validates the declaration of a library code, returns wrapper""" if not declaration: - raise SyntaxError('Library declaration cannot be empty') + raise SyntaxError("Library declaration cannot be empty") - if not(isinstance(declaration, dict)): + if not (isinstance(declaration, dict)): try: - declaration_dict = simplejson.loads(declaration, object_pairs_hook=collections.OrderedDict) + declaration_dict = simplejson.loads( + declaration, object_pairs_hook=collections.OrderedDict + ) except Exception as e: raise SyntaxError(str(e)) else: @@ -63,111 +65,122 @@ def validate_library(declaration): library = beat.core.library.Library(settings.PREFIX, declaration_dict) if not library.valid: - raise SyntaxError('\n * %s' % '\n * '.join(library.errors)) + raise SyntaxError("\n * %s" % "\n * ".join(library.errors)) return library -#---------------------------------------------------------- +# ---------------------------------------------------------- class LibraryStorage(OverwriteStorage): - def __init__(self, *args, **kwargs): - kwargs['location'] = settings.LIBRARIES_ROOT + kwargs["location"] = settings.LIBRARIES_ROOT super(LibraryStorage, self).__init__(*args, **kwargs) -#---------------------------------------------------------- +# ---------------------------------------------------------- class LibraryManager(CodeManager): - - def create_library(self, author, name, short_description='', - description='', declaration=None, code=None, version=1, - previous_version=None, fork_of=None): + def create_library( + self, + author, + name, + short_description="", + description="", + declaration=None, + code=None, + version=1, + previous_version=None, + fork_of=None, + ): default = beat.core.library.Library(settings.PREFIX, data=None) - return self.create_code(author, name, default, short_description, - description, declaration, code, version, - previous_version, fork_of) + return self.create_code( + author, + name, + default, + short_description, + description, + declaration, + code, + version, + previous_version, + fork_of, + ) -#---------------------------------------------------------- +# ---------------------------------------------------------- class Library(Code): - #_____ Fields __________ + # _____ Fields __________ declaration_file = models.FileField( storage=LibraryStorage(), upload_to=get_contribution_declaration_filename, - blank=True, null=True, + blank=True, + null=True, max_length=200, - db_column='declaration' + db_column="declaration", ) description_file = models.FileField( storage=LibraryStorage(), upload_to=get_contribution_description_filename, - blank=True, null=True, + blank=True, + null=True, max_length=200, - db_column='description' + db_column="description", ) source_code_file = models.FileField( storage=LibraryStorage(), upload_to=get_contribution_source_code_filename, - blank=True, null=True, + blank=True, + null=True, max_length=200, - db_column='source_code' + db_column="source_code", ) # Read-only parameters that are updated at every save(), if required - referenced_libraries = models.ManyToManyField('self', - blank=True, related_name='referencing', - symmetrical=False) + referenced_libraries = models.ManyToManyField( + "self", blank=True, related_name="referencing", symmetrical=False + ) objects = LibraryManager() - - #_____ Meta parameters __________ + # _____ Meta parameters __________ class Meta(Code.Meta): - verbose_name_plural = 'libraries' + verbose_name_plural = "libraries" - - #_____ Utilities __________ + # _____ Utilities __________ def get_absolute_url(self): return reverse( - 'libraries:view', - args=(self.author.username, self.name, self.version,), + "libraries:view", args=(self.author.username, self.name, self.version) ) - def get_api_update_url(self): - '''Returns the endpoint to update this object''' + """Returns the endpoint to update this object""" return reverse( - 'api_libraries:object', - args=(self.author.username, self.name, self.version,), + "api_libraries:object", args=(self.author.username, self.name, self.version) ) - def get_api_share_url(self): - '''Returns the endpoint to share this object''' + """Returns the endpoint to share this object""" return reverse( - 'api_libraries:share', - args=(self.author.username, self.name, self.version,), + "api_libraries:share", args=(self.author.username, self.name, self.version) ) - - #_____ Overrides __________ + # _____ Overrides __________ def save(self, *args, **kwargs): wrapper = self._save_preprocessing() @@ -179,50 +192,47 @@ class Library(Code): if wrapper.uses is not None: for l in set(wrapper.uses.values()): s = beat.core.library.Storage(settings.PREFIX, l) - library = Library.objects.get(author__username=s.username, - name=s.name, - version=s.version, - ) + library = Library.objects.get( + author__username=s.username, name=s.name, version=s.version + ) self.referenced_libraries.add(library) - - #_____ Methods __________ + # _____ Methods __________ def validate(self, declaration): return validate_library(declaration) - def modifiable(self): """Can modify if nobody points at me""" - return super(Library, self).modifiable() and ((self.referencing.count() + self.used_by_algorithms.count()) == 0) - + return super(Library, self).modifiable() and ( + (self.referencing.count() + self.used_by_algorithms.count()) == 0 + ) def deletable(self): """Can delete if nobody points at me""" - return super(Library, self).deletable() and ((self.referencing.count() + self.used_by_algorithms.count()) == 0) - + return super(Library, self).deletable() and ( + (self.referencing.count() + self.used_by_algorithms.count()) == 0 + ) def valid(self): - return True # A library (at least for now) is always implemented in Python, - # thus always valid + return True # A library (at least for now) is always implemented in Python, + # thus always valid def core(self): return validate_library(self.declaration) - def uses(self): return self.core().uses - def environments(self): - '''Calculates environment usage for this library + """Calculates environment usage for this library Returns: list: mapping environment to usage counts, determining how many times - a given algorithm has been successfuly used on that environment + a given algorithm has been successfully used on that environment - ''' + """ from django.db.models import Count, Q from ..experiments.models import Block @@ -230,18 +240,25 @@ class Library(Code): from ..backend.models import Environment # Tries to figure through a maximum if using algorithms have been - # successfuly used inside an environment. + # 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 algorithm/environment relationship!) - envs = Environment.objects.filter(blocks__in=Block.objects.filter( \ - algorithm__in=self.used_by_algorithms.all()).filter( \ - Q(experiment__status=Experiment.DONE) | \ - ((~Q(experiment__status=Experiment.DONE)) & Q(status=Block.DONE)) - )).annotate(itemcount=Count('id')).order_by('-creation_date' \ - ).distinct() + envs = ( + Environment.objects.filter( + blocks__in=Block.objects.filter( + algorithm__in=self.used_by_algorithms.all() + ).filter( + Q(experiment__status=Experiment.DONE) + | ((~Q(experiment__status=Experiment.DONE)) & Q(status=Block.DONE)) + ) + ) + .annotate(itemcount=Count("id")) + .order_by("-creation_date") + .distinct() + ) return [(k, k.itemcount) for k in envs]