|
@@ -11,7 +11,8 @@ from flask import Flask
|
|
|
from flask import send_from_directory
|
|
|
|
|
|
from pycs import app
|
|
|
-from pycs.database.Database import Database
|
|
|
+from pycs.database.Model import Model
|
|
|
+from pycs.database.LabelProvider import LabelProvider
|
|
|
from pycs.frontend.endpoints.ListJobs import ListJobs
|
|
|
from pycs.frontend.endpoints.ListLabelProviders import ListLabelProviders
|
|
|
from pycs.frontend.endpoints.ListModels import ListModels
|
|
@@ -39,8 +40,8 @@ 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.ListProjectCollections import ListProjectCollections
|
|
|
+from pycs.frontend.endpoints.projects.ListProjectFiles import ListProjectFiles
|
|
|
from pycs.frontend.endpoints.projects.RemoveProject import RemoveProject
|
|
|
from pycs.frontend.endpoints.results.ConfirmResult import ConfirmResult
|
|
|
from pycs.frontend.endpoints.results.CreateResult import CreateResult
|
|
@@ -64,7 +65,6 @@ class WebServer:
|
|
|
# pylint: disable=line-too-long
|
|
|
# pylint: disable=too-many-statements
|
|
|
def __init__(self, app, settings: dict):
|
|
|
- self.database = Database()
|
|
|
|
|
|
PRODUCTION = os.path.exists('webui/index.html')
|
|
|
|
|
@@ -104,19 +104,25 @@ class WebServer:
|
|
|
|
|
|
# create service objects
|
|
|
self.__sio = socketio.Server(cors_allowed_origins='*', async_mode='eventlet')
|
|
|
- self.__app = socketio.WSGIApp(self.__sio, app)
|
|
|
+ self.app = app
|
|
|
+ self.wsgi_app = socketio.WSGIApp(self.__sio, app)
|
|
|
|
|
|
# set access control header to allow requests from Vue.js development server
|
|
|
- @app.after_request
|
|
|
+ @self.app.after_request
|
|
|
def after_request(response):
|
|
|
# pylint: disable=unused-variable
|
|
|
response.headers['Access-Control-Allow-Origin'] = '*'
|
|
|
return response
|
|
|
|
|
|
# set json encoder so database objects are serialized correctly
|
|
|
- app.json_encoder = JSONEncoder
|
|
|
+ self.app.json_encoder = JSONEncoder
|
|
|
+
|
|
|
+ self.host = settings.host
|
|
|
+ self.port = settings.port
|
|
|
|
|
|
# create notification manager
|
|
|
+ jobs = JobRunner()
|
|
|
+ pipelines = PipelineCache(jobs)
|
|
|
notifications = NotificationManager(self.__sio)
|
|
|
|
|
|
jobs.on_create(notifications.create_job)
|
|
@@ -127,187 +133,199 @@ class WebServer:
|
|
|
|
|
|
self.define_routes(jobs, notifications, pipelines)
|
|
|
|
|
|
+ Model.discover("models/")
|
|
|
+ LabelProvider.discover("labels/")
|
|
|
+
|
|
|
|
|
|
def define_routes(self, jobs, notifications, pipelines):
|
|
|
|
|
|
# additional
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/folder',
|
|
|
view_func=FolderInformation.as_view('folder_information')
|
|
|
)
|
|
|
|
|
|
# jobs
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/jobs',
|
|
|
view_func=ListJobs.as_view('list_jobs', jobs)
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
- '/jobs/<identifier>/remove',
|
|
|
+ self.app.add_url_rule(
|
|
|
+ '/jobs/<int:job_id>/remove',
|
|
|
view_func=RemoveJob.as_view('remove_job', jobs)
|
|
|
)
|
|
|
|
|
|
# models
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/models',
|
|
|
- view_func=ListModels.as_view('list_models', self.database)
|
|
|
+ view_func=ListModels.as_view('list_models')
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
- '/projects/<int:identifier>/model',
|
|
|
- view_func=GetProjectModel.as_view('get_project_model', self.database)
|
|
|
+ self.app.add_url_rule(
|
|
|
+ '/projects/<int:project_id>/model',
|
|
|
+ view_func=GetProjectModel.as_view('get_project_model')
|
|
|
)
|
|
|
|
|
|
# labels
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/label_providers',
|
|
|
- view_func=ListLabelProviders.as_view('label_providers', self.database)
|
|
|
+ view_func=ListLabelProviders.as_view('label_providers')
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
- '/projects/<int:identifier>/labels',
|
|
|
- view_func=ListLabels.as_view('list_labels', self.database)
|
|
|
+ self.app.add_url_rule(
|
|
|
+ '/projects/<int:project_id>/labels',
|
|
|
+ view_func=ListLabels.as_view('list_labels')
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
- '/projects/<int:identifier>/labels/tree',
|
|
|
- view_func=ListLabelTree.as_view('list_label_tree', self.database)
|
|
|
+ self.app.add_url_rule(
|
|
|
+ '/projects/<int:project_id>/labels/tree',
|
|
|
+ view_func=ListLabelTree.as_view('list_label_tree')
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
- '/projects/<int:identifier>/labels',
|
|
|
- view_func=CreateLabel.as_view('create_label', self.database, notifications)
|
|
|
+ self.app.add_url_rule(
|
|
|
+ '/projects/<int:project_id>/labels',
|
|
|
+ view_func=CreateLabel.as_view('create_label', notifications)
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/projects/<int:project_id>/labels/<int:label_id>/remove',
|
|
|
- view_func=RemoveLabel.as_view('remove_label', self.database, notifications)
|
|
|
+ view_func=RemoveLabel.as_view('remove_label', notifications)
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/projects/<int:project_id>/labels/<int:label_id>/name',
|
|
|
- view_func=EditLabelName.as_view('edit_label_name', self.database, notifications)
|
|
|
+ view_func=EditLabelName.as_view('edit_label_name', notifications)
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/projects/<int:project_id>/labels/<int:label_id>/parent',
|
|
|
- view_func=EditLabelParent.as_view('edit_label_parent', self.database, notifications)
|
|
|
+ view_func=EditLabelParent.as_view('edit_label_parent', notifications)
|
|
|
)
|
|
|
|
|
|
# collections
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/projects/<int:project_id>/collections',
|
|
|
- view_func=ListCollections.as_view('list_collections', self.database)
|
|
|
+ view_func=ListProjectCollections.as_view('list_collections')
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/projects/<int:project_id>/data/<int:collection_id>/<int:start>/<int:length>',
|
|
|
- view_func=ListFiles.as_view('list_collection_files', self.database)
|
|
|
+ view_func=ListProjectFiles.as_view('list_collection_files')
|
|
|
)
|
|
|
|
|
|
# data
|
|
|
- app.add_url_rule(
|
|
|
- '/projects/<int:identifier>/data',
|
|
|
- view_func=UploadFile.as_view('upload_file', self.database, notifications)
|
|
|
+ self.app.add_url_rule(
|
|
|
+ '/projects/<int:project_id>/data',
|
|
|
+ view_func=UploadFile.as_view('upload_file', notifications)
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/projects/<int:project_id>/data/<int:start>/<int:length>',
|
|
|
- view_func=ListFiles.as_view('list_files', self.database)
|
|
|
+ view_func=ListProjectFiles.as_view('list_files')
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
- '/data/<int:identifier>/remove',
|
|
|
- view_func=RemoveFile.as_view('remove_file', self.database, notifications)
|
|
|
+ self.app.add_url_rule(
|
|
|
+ '/data/<int:file_id>/remove',
|
|
|
+ view_func=RemoveFile.as_view('remove_file', notifications)
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/data/<int:file_id>',
|
|
|
- view_func=GetFile.as_view('get_file', self.database)
|
|
|
+ view_func=GetFile.as_view('get_file')
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/data/<int:file_id>/<resolution>',
|
|
|
- view_func=GetResizedFile.as_view('get_resized_file', self.database)
|
|
|
+ view_func=GetResizedFile.as_view('get_resized_file')
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/data/<int:file_id>/<resolution>/<crop_box>',
|
|
|
view_func=GetCroppedFile.as_view('crop_result', database)
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/data/<int:file_id>/previous_next',
|
|
|
- view_func=GetPreviousAndNextFile.as_view('get_previous_and_next_file', self.database)
|
|
|
+ view_func=GetPreviousAndNextFile.as_view('get_previous_and_next_file')
|
|
|
)
|
|
|
|
|
|
# results
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/projects/<int:project_id>/results',
|
|
|
- view_func=GetProjectResults.as_view('get_project_results', self.database)
|
|
|
+ view_func=GetProjectResults.as_view('get_project_results')
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/data/<int:file_id>/results',
|
|
|
- view_func=GetResults.as_view('get_results', self.database)
|
|
|
+ view_func=GetResults.as_view('get_results')
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/data/<int:file_id>/results',
|
|
|
- view_func=CreateResult.as_view('create_result', self.database, notifications)
|
|
|
+ view_func=CreateResult.as_view('create_result', notifications)
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/data/<int:file_id>/reset',
|
|
|
- view_func=ResetResults.as_view('reset_results', self.database, notifications)
|
|
|
+ view_func=ResetResults.as_view('reset_results', notifications)
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/results/<int:result_id>/remove',
|
|
|
- view_func=RemoveResult.as_view('remove_result', self.database, notifications)
|
|
|
+ view_func=RemoveResult.as_view('remove_result', notifications)
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/results/<int:result_id>/confirm',
|
|
|
- view_func=ConfirmResult.as_view('confirm_result', self.database, notifications)
|
|
|
+ view_func=ConfirmResult.as_view('confirm_result', notifications)
|
|
|
+ )
|
|
|
+ self.app.add_url_rule(
|
|
|
+ '/results/<int:result_id>/crop',
|
|
|
+ view_func=ResultAsCrop.as_view('crop_result')
|
|
|
+ )
|
|
|
+ self.app.add_url_rule(
|
|
|
+ '/results/<int:result_id>/crop/<int:max_width>',
|
|
|
+ view_func=ResultAsCrop.as_view('crop_result_resized_by_width')
|
|
|
+ )
|
|
|
+ self.app.add_url_rule(
|
|
|
+ '/results/<int:result_id>/crop/<int:max_width>x<int:max_height>',
|
|
|
+ view_func=ResultAsCrop.as_view('crop_result_resized')
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/results/<int:result_id>/label',
|
|
|
- view_func=EditResultLabel.as_view('edit_result_label', self.database, notifications)
|
|
|
+ view_func=EditResultLabel.as_view('edit_result_label', notifications)
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/results/<int:result_id>/data',
|
|
|
- view_func=EditResultData.as_view('edit_result_data', self.database, notifications)
|
|
|
+ view_func=EditResultData.as_view('edit_result_data', notifications)
|
|
|
)
|
|
|
|
|
|
# projects
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/projects',
|
|
|
- view_func=ListProjects.as_view('list_projects', self.database)
|
|
|
+ view_func=ListProjects.as_view('list_projects')
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/projects',
|
|
|
- view_func=CreateProject.as_view('create_project', self.database, notifications, jobs)
|
|
|
+ view_func=CreateProject.as_view('create_project', notifications, jobs)
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
- '/projects/<int:identifier>/label_provider',
|
|
|
- view_func=ExecuteLabelProvider.as_view('execute_label_provider', self.database,
|
|
|
- notifications, jobs)
|
|
|
+ self.app.add_url_rule(
|
|
|
+ '/projects/<int:project_id>/label_provider',
|
|
|
+ view_func=ExecuteLabelProvider.as_view('execute_label_provider', notifications, jobs)
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
- '/projects/<int:identifier>/external_storage',
|
|
|
- view_func=ExecuteExternalStorage.as_view('execute_external_storage', self.database,
|
|
|
- notifications, jobs)
|
|
|
+ self.app.add_url_rule(
|
|
|
+ '/projects/<int:project_id>/external_storage',
|
|
|
+ view_func=ExecuteExternalStorage.as_view('execute_external_storage', notifications, jobs)
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
- '/projects/<int:identifier>/remove',
|
|
|
- view_func=RemoveProject.as_view('remove_project', self.database, notifications)
|
|
|
+ self.app.add_url_rule(
|
|
|
+ '/projects/<int:project_id>/remove',
|
|
|
+ view_func=RemoveProject.as_view('remove_project', notifications)
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
- '/projects/<int:identifier>/name',
|
|
|
- view_func=EditProjectName.as_view('edit_project_name', self.database, notifications)
|
|
|
+ self.app.add_url_rule(
|
|
|
+ '/projects/<int:project_id>/name',
|
|
|
+ view_func=EditProjectName.as_view('edit_project_name', notifications)
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
- '/projects/<int:identifier>/description',
|
|
|
- view_func=EditProjectDescription.as_view('edit_project_description', self.database,
|
|
|
- notifications)
|
|
|
+ self.app.add_url_rule(
|
|
|
+ '/projects/<int:project_id>/description',
|
|
|
+ view_func=EditProjectDescription.as_view('edit_project_description', notifications)
|
|
|
)
|
|
|
|
|
|
# pipelines
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/projects/<int:project_id>/pipelines/fit',
|
|
|
- view_func=FitModel.as_view('fit_model', self.database, jobs, pipelines)
|
|
|
+ view_func=FitModel.as_view('fit_model', jobs, pipelines)
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/projects/<int:project_id>/pipelines/predict',
|
|
|
- view_func=PredictModel.as_view('predict_model', self.database, notifications, jobs,
|
|
|
+ view_func=PredictModel.as_view('predict_model', notifications, jobs,
|
|
|
pipelines)
|
|
|
)
|
|
|
- app.add_url_rule(
|
|
|
+ self.app.add_url_rule(
|
|
|
'/data/<int:file_id>/predict',
|
|
|
- view_func=PredictFile.as_view('predict_file', self.database, notifications, jobs, pipelines)
|
|
|
+ view_func=PredictFile.as_view('predict_file', notifications, jobs, pipelines)
|
|
|
)
|
|
|
|
|
|
def run(self):
|
|
|
# finally start web server
|
|
|
- eventlet.wsgi.server(eventlet.listen((self.host, self.port)), app)
|
|
|
+ eventlet.wsgi.server(eventlet.listen((self.host, self.port)), self.wsgi_app)
|