-
Notifications
You must be signed in to change notification settings - Fork 27
/
QA.py
128 lines (96 loc) · 5.01 KB
/
QA.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import os
import shutil
import logging
from logging import config
from multiprocessing import Pool
from flask import Flask
from flask_restless import APIManager, ProcessingException
import QA_db
from QA_api import api,delete_image
from QA_config import config, get_database_uri
from QA_db import db, Image, Project, Roi, Job
from QA_html import html
def add_project(**kw):
projectid = kw['result']['name']
# Check if the project folder exists
if not os.path.isdir("projects"):
os.mkdir("projects")
if not os.path.isdir(os.path.join("projects", projectid)):
# Create new project under root, add sub-folders
os.mkdir(os.path.join("projects", projectid))
os.mkdir(os.path.join("projects", projectid, "models"))
os.mkdir(os.path.join("projects", projectid, "pred"))
os.mkdir(os.path.join("projects", projectid, "mask"))
os.mkdir(os.path.join("projects", projectid, "patches"))
os.mkdir(os.path.join("projects", projectid, "roi"))
os.mkdir(os.path.join("projects", projectid, "roi_mask"))
os.mkdir(os.path.join("projects", projectid, "superpixels"))
os.mkdir(os.path.join("projects", projectid, "superpixels_boundary"))
return kw
def delete_project(instance_id=None, **kw): # should really be a postprocess but no instance ID is available
# Delete all images in the project, this function removes the relational foreign keys as well
proj = Project.query.filter_by(id=instance_id).first()
selected_images = db.session.query(Image).filter_by(projId=proj.id)
for selected_image in selected_images:
delete_image(proj.name, selected_image.name)
#delete jobs
selected_Jobs = db.session.query(Job).filter_by(projId=proj.id)
selected_Jobs.delete()
# Check if the project folder exists
shutil.rmtree(os.path.join("projects", proj.name), ignore_errors=True)
pass
# For the preprocessor to raise an exception if a duplicate project name is posted.
def check_existing_project(data):
project_name = data['name']
proj = Project.query.filter_by(name=project_name).first()
if proj is not None:
raise ProcessingException(description=f'Project {project_name} already exists.', code=400)
# Create the Flask-Restless API manager
app = Flask(__name__)
app.debug = True
app.logger_name='flask'
app.register_blueprint(api)
app.register_blueprint(html)
app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 0
app.config['SQLALCHEMY_DATABASE_URI'] = get_database_uri()
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_ECHO'] = config.getboolean('sqlalchemy', 'echo', fallback=False)
APP_ROOT = os.path.dirname(os.path.abspath('__file__'))
if __name__ == '__main__': #This seems like the correct place to do this
# load logging config
logging.config.fileConfig('./config/logging.ini')
app.logger.info('Initializing database')
db.app = app
db.init_app(app)
db.create_all()
db.engine.connect().execute('pragma journal_mode=wal;')
if config.getboolean('sqlalchemy', 'delete_old_jobs_at_start', fallback=True):
jobid_tables = db.session.execute("SELECT name FROM sqlite_master WHERE type='table' and name like 'jobid_%' ORDER BY name").fetchall()
for jobid_table in jobid_tables:
app.logger.info(f'Dropping jobid_table {jobid_table[0]}')
db.session.execute(f"DROP TABLE IF EXISTS {jobid_table[0]}")
db.session.commit()
# ----
app.logger.info('Clearing stale jobs')
if config.getboolean('flask', 'clear_stale_jobs_at_start', fallback=True):
njobs = QA_db.clear_stale_jobs() # <-- clear old queued jobs from last session
db.session.commit()
app.logger.info(f'Deleted {njobs} queued jobs.')
# ----
app.apimanager = APIManager(app, flask_sqlalchemy_db=db)
# Create API endpoints, which will be available at /api/<tablename> by default
app.apimanager.create_api(Project, methods=['GET', 'POST', 'DELETE', 'PUT'], url_prefix='/api/db',
results_per_page=0, max_results_per_page=0,
preprocessors={'DELETE_SINGLE': [delete_project], 'POST': [check_existing_project]},
postprocessors={'POST': [add_project]})
app.apimanager.create_api(Image, methods=['GET', 'POST', 'DELETE', 'PUT'], url_prefix='/api/db',
results_per_page=0, max_results_per_page=0,)
app.apimanager.create_api(Roi, methods=['GET', 'POST', 'DELETE', 'PUT'], url_prefix='/api/db',
results_per_page=0, max_results_per_page=0,)
app.apimanager.create_api(Job, methods=['GET', 'POST', 'DELETE', 'PUT'], url_prefix='/api/db',
results_per_page=0, max_results_per_page=0,)
app.logger.info('Starting up worker pool.')
QA_db._pool = Pool(processes=config.getint('pooling', 'npoolthread', fallback=4))
app.run(host='0.0.0.0', port=config.getint('flask', 'port', fallback=5555), debug=config.getboolean('flask', 'debug', fallback = False))
QA_db._pool.close()
QA_db._pool.join()