6
0
Dimitri Korsch 3 жил өмнө
parent
commit
1c2865bb0a

+ 22 - 2
pycs/database/Collection.py

@@ -1,5 +1,6 @@
-from contextlib import closing
-from typing import Iterator
+from __future__ import annotations
+
+from typing import List
 
 from pycs import db
 from pycs.database.base import NamedBaseModel
@@ -55,3 +56,22 @@ class Collection(NamedBaseModel):
         from pycs.database.File import File
         return self.files.order_by(File.id).offset(offset).limit(limit)
 
+
+    @staticmethod
+    def update_autoselect(collections: List[Collection]) -> List[Collection]:
+        """ disable autoselect if there are no elements in the collection """
+
+        found = False
+
+        for collection in collections:
+            if not collection.autoselect:
+                continue
+
+            if found:
+                collection.autoselect = False
+
+            elif collection.count_files() == 0:
+                collection.autoselect = False
+                found = True
+
+        return collections

+ 0 - 15
pycs/database/Project.py

@@ -249,19 +249,4 @@ class Project(NamedBaseModel):
         """
         return self._files_without_results().all()
 
-    def files_without_collection(self, offset: int = 0, limit: int = -1) -> T.Iterator[File]:
-        """
-        get an iterator of files without not associated with any collection
-
-        :return: list of files
-        """
-        return self.get_files(offset, limit).filter(File.collection_id == None)
-
 
-    def count_files_without_collection(self) -> int:
-        """
-        count files associated with this project but with no collection
-
-        :return: count
-        """
-        return self.files_without_collection().count()

+ 18 - 13
pycs/frontend/WebServer.py

@@ -1,5 +1,5 @@
-import os
 import glob
+import os
 import threading
 
 from logging.config import dictConfig
@@ -9,12 +9,18 @@ from flask_socketio import SocketIO
 from logging import config
 
 from pycs import app
+
+from pycs.database.Collection import Collection
 from pycs.database.Database import Database
+from pycs.database.LabelProvider import LabelProvider
+from pycs.database.Label import Label
+from pycs.database.Model import Model
+from pycs.database.Project import Project
+from pycs.database.Result import Result
+
 from pycs.frontend.endpoints.ListJobs import ListJobs
-from pycs.frontend.endpoints.ListLabelProviders import ListLabelProviders
-from pycs.frontend.endpoints.ListModels import ListModels
-from pycs.frontend.endpoints.ListProjects import ListProjects
 from pycs.frontend.endpoints.additional.FolderInformation import FolderInformation
+from pycs.frontend.endpoints.base import ListView
 from pycs.frontend.endpoints.data.GetFile import GetFile
 from pycs.frontend.endpoints.data.GetPreviousAndNextFile import GetPreviousAndNextFile
 from pycs.frontend.endpoints.data.GetResizedFile import GetResizedFile
@@ -24,7 +30,6 @@ from pycs.frontend.endpoints.jobs.RemoveJob import RemoveJob
 from pycs.frontend.endpoints.labels.CreateLabel import CreateLabel
 from pycs.frontend.endpoints.labels.EditLabelName import EditLabelName
 from pycs.frontend.endpoints.labels.EditLabelParent import EditLabelParent
-from pycs.frontend.endpoints.labels.ListLabels import ListLabels
 from pycs.frontend.endpoints.labels.RemoveLabel import RemoveLabel
 from pycs.frontend.endpoints.pipelines.FitModel import FitModel
 from pycs.frontend.endpoints.pipelines.PredictFile import PredictFile
@@ -35,7 +40,6 @@ from pycs.frontend.endpoints.projects.EditProjectName import EditProjectName
 from pycs.frontend.endpoints.projects.ExecuteExternalStorage import ExecuteExternalStorage
 from pycs.frontend.endpoints.projects.ExecuteLabelProvider import ExecuteLabelProvider
 from pycs.frontend.endpoints.projects.GetProjectModel import GetProjectModel
-from pycs.frontend.endpoints.projects.ListCollections import ListCollections
 from pycs.frontend.endpoints.projects.ListFiles import ListFiles
 from pycs.frontend.endpoints.projects.RemoveProject import RemoveProject
 from pycs.frontend.endpoints.results.ConfirmResult import ConfirmResult
@@ -189,7 +193,7 @@ class WebServer:
         # models
         self.app.add_url_rule(
             '/models',
-            view_func=ListModels.as_view('list_models')
+            view_func=ListView.as_view('list_models', model_cls=Model)
         )
         self.app.add_url_rule(
             '/projects/<int:identifier>/model',
@@ -199,11 +203,11 @@ class WebServer:
         # labels
         self.app.add_url_rule(
             '/label_providers',
-            view_func=ListLabelProviders.as_view('label_providers')
+            view_func=ListView.as_view('label_providers', model_cls=LabelProvider)
         )
         self.app.add_url_rule(
-            '/projects/<int:identifier>/labels',
-            view_func=ListLabels.as_view('list_labels')
+            '/projects/<int:project_id>/labels',
+            view_func=ListView.as_view('list_labels', model_cls=Label)
         )
         self.app.add_url_rule(
             '/projects/<int:identifier>/labels',
@@ -225,7 +229,8 @@ class WebServer:
         # collections
         self.app.add_url_rule(
             '/projects/<int:project_id>/collections',
-            view_func=ListCollections.as_view('list_collections')
+            view_func=ListView.as_view('list_collections',
+                model_cls=Collection, post_process=Collection.update_autoselect)
         )
         self.app.add_url_rule(
             '/projects/<int:project_id>/data/<int:collection_id>/<int:start>/<int:length>',
@@ -265,7 +270,7 @@ class WebServer:
         )
         self.app.add_url_rule(
             '/data/<int:file_id>/results',
-            view_func=GetResults.as_view('get_results')
+            view_func=ListView.as_view('get_results', model_cls=Result)
         )
         self.app.add_url_rule(
             '/data/<int:file_id>/results',
@@ -295,7 +300,7 @@ class WebServer:
         # projects
         self.app.add_url_rule(
             '/projects',
-            view_func=ListProjects.as_view('list_projects')
+            view_func=ListView.as_view('list_projects', model_cls=Project)
         )
         self.app.add_url_rule(
             '/projects',

+ 0 - 15
pycs/frontend/endpoints/ListLabelProviders.py

@@ -1,15 +0,0 @@
-from flask import jsonify
-from flask.views import View
-
-from pycs.database.LabelProvider import LabelProvider
-
-
-class ListLabelProviders(View):
-    """
-    returns a list of all available label providers
-    """
-    # pylint: disable=arguments-differ
-    methods = ['GET']
-
-    def dispatch_request(self):
-        return jsonify(LabelProvider.query.all())

+ 0 - 15
pycs/frontend/endpoints/ListModels.py

@@ -1,15 +0,0 @@
-from flask import jsonify
-from flask.views import View
-
-from pycs.database.Model import Model
-
-
-class ListModels(View):
-    """
-    get a list of all available models
-    """
-    # pylint: disable=arguments-differ
-    methods = ['GET']
-
-    def dispatch_request(self):
-        return jsonify(Model.query.all())

+ 0 - 15
pycs/frontend/endpoints/ListProjects.py

@@ -1,15 +0,0 @@
-from flask import jsonify
-from flask.views import View
-
-from pycs.database.Project import Project
-
-
-class ListProjects(View):
-    """
-    get a list of all available projects
-    """
-    # pylint: disable=arguments-differ
-    methods = ['GET']
-
-    def dispatch_request(self):
-        return jsonify(Project.query.all())

+ 35 - 0
pycs/frontend/endpoints/base.py

@@ -0,0 +1,35 @@
+from flask import jsonify
+from flask.views import View
+from typing import Callable
+from typing import Optional
+
+class ListView(View):
+    """
+        View that returns a list of instances of a certain class
+    """
+
+    # pylint: disable=arguments-differ
+    methods = ['GET']
+    model = None
+
+    def __init__(self, model_cls: Optional = None, post_process: Optional[Callable] = None):
+        self._cls = model_cls or self.model
+        self._post_process = post_process
+
+    def dispatch_request(self, **kwargs):
+        objects = self.get_objects(**kwargs)
+        objects = self.post_process(objects)
+        return jsonify(objects)
+
+    def get_objects(self, **kwargs):
+        query = self._list_query(**kwargs)
+        return self._cls.query.filter_by(**query).all()
+
+    def _list_query(self, **kwargs) -> dict:
+        return kwargs
+
+    def post_process(self, objects):
+        if self._post_process is None or not callable(self._post_process):
+            return objects
+
+        return self._post_process(objects)

+ 0 - 20
pycs/frontend/endpoints/labels/ListLabels.py

@@ -1,20 +0,0 @@
-from flask import abort, jsonify
-from flask.views import View
-
-from pycs.database.Project import Project
-
-
-class ListLabels(View):
-    """
-    return a list of labels for a given project
-    """
-    # pylint: disable=arguments-differ
-    methods = ['GET']
-
-    def dispatch_request(self, identifier):
-        # find project
-        project = Project.query.get(identifier)
-        if project is None:
-            abort(404)
-
-        return jsonify(project.labels.all())

+ 0 - 33
pycs/frontend/endpoints/projects/ListCollections.py

@@ -1,33 +0,0 @@
-from flask import abort
-from flask import jsonify
-from flask.views import View
-
-from pycs.database.Collection import Collection
-
-
-class ListCollections(View):
-    """
-    return a list of collections for a given project
-    """
-    # pylint: disable=arguments-differ
-    methods = ['GET']
-
-    def dispatch_request(self, project_id: int):
-
-        # get collection list
-        collections = Collection.query.filter_by(project_id=project_id).all()
-
-        # disable autoselect if there are no elements in the collection
-        found = False
-
-        for collection in collections:
-            if collection.autoselect:
-                if found:
-                    collection.autoselect = False
-
-                elif collection.count_files() == 0:
-                    collection.autoselect = False
-                    found = True
-
-        # return files
-        return jsonify(collections)

+ 23 - 31
pycs/frontend/endpoints/projects/ListFiles.py

@@ -2,41 +2,33 @@ from flask import abort
 from flask import jsonify
 from flask.views import View
 
-from pycs.database.Project import Project
+from pycs.database.File import File
+from pycs.frontend.endpoints.base import ListView
 
-
-class ListFiles(View):
+class ListFiles(ListView):
     """
     return a list of files for a given project
+    with offset and limit parameters
     """
     # pylint: disable=arguments-differ
     methods = ['GET']
+    model = File
+
+    def get_objects(self, project_id: int, start: int, length: int, collection_id: int = None):
+        # find project files
+
+        files = File.query.filter_by(project_id=project_id)
+
+        if collection_id == 0:
+            # files without a collection
+            files = files.filter(File.collection_id == None)
+
+        elif collection_id is not None:
+            # files of a collection
+            files = files.filter(File.collection_id == collection_id)
+
+        count = files.count()
+        files = files.order_by(File.id).offset(start).limit(length).all()
+
+        return dict(count=count, files=files)
 
-    def dispatch_request(self, project_id: int, start: int, length: int, collection_id: int = None):
-        # find project
-        project = Project.query.get(project_id)
-        if project is None:
-            return abort(404)
-
-        # get count and files
-        if collection_id is None:
-            count = project.count_files()
-            files = list(project.get_files(start, length))
-
-        elif collection_id == 0:
-            count = project.count_files_without_collection()
-            files = list(project.files_without_collection(start, length))
-
-        else:
-            collection = project.collection(collection_id)
-            if collection is None:
-                return abort(404)
-
-            count = collection.count_files()
-            files = list(collection.files(start, length))
-
-        # return files
-        return jsonify({
-            'count': count,
-            'files': files
-        })