Use enums where appropriate. This commit includes new migrations that are NOT compatible with older nopaque instances

This commit is contained in:
Patrick Jentsch
2022-02-08 12:26:20 +01:00
parent fe938c0ca2
commit df6ab3991c
110 changed files with 1389 additions and 2301 deletions

View File

@ -1,6 +1,6 @@
from app import db, hashids, socketio
from app.decorators import socketio_login_required
from app.models import Corpus
from app.models import Corpus, CorpusStatus
from flask import session
from flask_login import current_user
from flask_socketio import ConnectionRefusedError
@ -65,7 +65,12 @@ def connect(auth):
if not (corpus.user == current_user or current_user.is_administrator()):
# return {'code': 403, 'msg': 'Forbidden'}
raise ConnectionRefusedError('Forbidden')
if corpus.status not in ['prepared', 'start analysis', 'analysing', 'stop analysis']:
if corpus.status not in [
CorpusStatus.BUILT,
CorpusStatus.STARTING_ANALYSIS_SESSION,
CorpusStatus.RUNNING_ANALYSIS_SESSION,
CorpusStatus.CANCELING_ANALYSIS_SESSION
]:
# return {'code': 424, 'msg': 'Failed Dependency'}
raise ConnectionRefusedError('Failed Dependency')
if corpus.num_analysis_sessions is None:
@ -74,7 +79,7 @@ def connect(auth):
corpus.num_analysis_sessions = Corpus.num_analysis_sessions + 1
db.session.commit()
retry_counter = 20
while corpus.status != 'analysing':
while corpus.status != CorpusStatus.RUNNING_ANALYSIS_SESSION:
if retry_counter == 0:
corpus.num_analysis_sessions = Corpus.num_analysis_sessions - 1
db.session.commit()

View File

@ -1,7 +1,12 @@
from flask_wtf import FlaskForm
from werkzeug.utils import secure_filename
from wtforms import (FileField, StringField, SubmitField,
ValidationError, IntegerField)
from wtforms import (
FileField,
StringField,
SubmitField,
ValidationError,
IntegerField
)
from wtforms.validators import DataRequired, Length

View File

@ -58,7 +58,7 @@ def add_query_result():
query_result_file_content.pop('cpos_lookup')
query_result.query_metadata = query_result_file_content
db.session.commit()
flash('Query result added!', 'result')
flash('Query result added', 'result')
return make_response({'redirect_url': url_for('.query_result', query_result_id=query_result.id)}, 201) # noqa
return render_template('corpora/query_results/add_query_result.html.j2',
form=form, title='Add query result')
@ -117,7 +117,7 @@ def delete_query_result(query_result_id):
if not (query_result.user == current_user
or current_user.is_administrator()):
abort(403)
flash(f'Query result "{query_result}" marked for deletion!', 'result')
flash(f'Query result "{query_result}" marked for deletion', 'result')
tasks.delete_query_result(query_result_id)
return redirect(url_for('services.service', service="corpus_analysis"))

View File

@ -0,0 +1,13 @@
from .. import db
from ..decorators import background
from ..models import QueryResult
@background
def delete_query_result(query_result_id, *args, **kwargs):
with kwargs['app'].app_context():
query_result = QueryResult.query.get(query_result_id)
if query_result is None:
raise Exception(f'QueryResult {query_result_id} not found')
query_result.delete()
db.session.commit()

View File

@ -1,19 +1,31 @@
from flask import (abort, current_app, flash, make_response, redirect,
render_template, url_for, send_from_directory)
from app import db
from app.models import Corpus, CorpusFile, CorpusStatus
from flask import (
abort,
current_app,
flash,
make_response,
redirect,
render_template,
url_for,
send_from_directory
)
from flask_login import current_user, login_required
from werkzeug.utils import secure_filename
from zipfile import ZipFile
from . import bp
from . import tasks
from .forms import (AddCorpusFileForm, AddCorpusForm, EditCorpusFileForm,
ImportCorpusForm)
from .. import db
from ..models import Corpus, CorpusFile
from .forms import (
AddCorpusFileForm,
AddCorpusForm,
EditCorpusFileForm,
ImportCorpusForm
)
from .import_corpus import check_zip_contents
import os
import shutil
import glob
import xml.etree.ElementTree as ET
from zipfile import ZipFile
from .import_corpus import check_zip_contents
@bp.route('/add', methods=['GET', 'POST'])
@ -34,10 +46,10 @@ def add_corpus():
except OSError as e:
current_app.logger.error(e)
db.session.rollback()
flash('Internal Server Error', 'error')
flash('Internal Server Error', category='error')
abort(500)
db.session.commit()
flash(f'Corpus "{corpus.title}" added', 'corpus')
flash(f'Corpus "{corpus.title}" added', category='corpus')
return redirect(url_for('.corpus', corpus_id=corpus.id))
return render_template(
'corpora/add_corpus.html.j2',
@ -46,6 +58,21 @@ def add_corpus():
)
@bp.route('/<hashid:corpus_id>/export')
@login_required
def export_corpus(corpus_id):
abort(503)
corpus = Corpus.query.get_or_404(corpus_id)
if not (corpus.user == current_user or current_user.is_administrator()):
abort(403)
return send_from_directory(
as_attachment=True,
directory=os.path.join(corpus.user.path, 'corpora'),
filename=corpus.archive_file,
mimetype='zip'
)
@bp.route('/import', methods=['GET', 'POST'])
@login_required
def import_corpus():
@ -65,11 +92,10 @@ def import_corpus():
try:
os.makedirs(corpus.path)
except OSError as e:
current_app.logger.error(f'Could not import corpus: {e}')
current_app.logger.error(e)
db.session.rollback()
flash('Internal Server Error', 'error')
return make_response(
{'redirect_url': url_for('.import_corpus')}, 500)
flash('Internal Server Error', category='error')
return make_response({'redirect_url': url_for('.import_corpus')}, 500) # noqa
# Upload zip
archive_file = os.path.join(corpus.path, form.file.data.filename)
form.file.data.save(archive_file)
@ -102,20 +128,25 @@ def import_corpus():
)
db.session.add(corpus_file)
# finish import and redirect to imported corpus
corpus.status = 'prepared'
corpus.status = CorpusStatus.BUILT
db.session.commit()
os.remove(archive_file)
flash(f'Corpus "{corpus.title}" imported!', 'corpus')
flash(f'Corpus "{corpus.title}" imported', 'corpus')
return make_response(
{'redirect_url': url_for('.corpus', corpus_id=corpus.id)}, 201)
else:
# If imported zip is not valid delete corpus and give feedback
flash('Can not import corpus "{}" not imported: Invalid archive file!', 'error') # noqa
flash(
f'Can\'t import corpus "{corpus.title}": Invalid archive file',
category='error'
)
tasks.delete_corpus(corpus.id)
return make_response(
{'redirect_url': url_for('.import_corpus')}, 201)
return render_template('corpora/import_corpus.html.j2', form=form,
title='Import Corpus')
return make_response({'redirect_url': url_for('.import_corpus')}, 201) # noqa
return render_template(
'corpora/import_corpus.html.j2',
form=form,
title='Import Corpus'
)
@bp.route('/<hashid:corpus_id>')
@ -124,9 +155,11 @@ def corpus(corpus_id):
corpus = Corpus.query.get_or_404(corpus_id)
if not (corpus.user == current_user or current_user.is_administrator()):
abort(403)
corpus_files = [corpus_file.to_dict() for corpus_file in corpus.files]
return render_template('corpora/corpus.html.j2', corpus=corpus,
corpus_files=corpus_files, title='Corpus')
return render_template(
'corpora/corpus.html.j2',
corpus=corpus,
title='Corpus'
)
@bp.route('/<hashid:corpus_id>/analyse')
@ -140,28 +173,13 @@ def analyse_corpus(corpus_id):
)
@bp.route('/<hashid:corpus_id>/download')
@login_required
def download_corpus(corpus_id):
abort(503)
corpus = Corpus.query.get_or_404(corpus_id)
if not (corpus.user == current_user or current_user.is_administrator()):
abort(403)
return send_from_directory(
as_attachment=True,
directory=os.path.join(corpus.user.path, 'corpora'),
filename=corpus.archive_file,
mimetype='zip'
)
@bp.route('/<hashid:corpus_id>/delete')
@login_required
def delete_corpus(corpus_id):
corpus = Corpus.query.get_or_404(corpus_id)
if not (corpus.user == current_user or current_user.is_administrator()):
abort(403)
flash(f'Corpus "{corpus.title}" marked for deletion!', 'corpus')
flash(f'Corpus "{corpus.title}" marked for deletion', 'corpus')
tasks.delete_corpus(corpus_id)
return redirect(url_for('main.dashboard'))
@ -203,11 +221,11 @@ def add_corpus_file(corpus_id):
except OSError as e:
current_app.logger.error(e)
db.session.rollback()
flash('Internal Server Error', 'error')
flash('Internal Server Error', category='error')
return make_response({'redirect_url': url_for('.add_corpus_file', corpus_id=corpus.id)}, 500) # noqa
corpus.status = 'unprepared'
corpus.status = CorpusStatus.UNPREPARED
db.session.commit()
flash(f'Corpus file "{corpus_file.title}" added!', 'corpus')
flash(f'Corpus file "{corpus_file.filename}" added', category='corpus')
return make_response({'redirect_url': url_for('.corpus', corpus_id=corpus.id)}, 201) # noqa
return render_template(
'corpora/add_corpus_file.html.j2',
@ -220,14 +238,19 @@ def add_corpus_file(corpus_id):
@bp.route('/<hashid:corpus_id>/files/<hashid:corpus_file_id>/delete')
@login_required
def delete_corpus_file(corpus_id, corpus_file_id):
corpus_file = CorpusFile.query.get_or_404(corpus_file_id)
if not corpus_file.corpus_id == corpus_id:
abort(404)
if not (corpus_file.corpus.user == current_user
or current_user.is_administrator()):
corpus_file = CorpusFile.query.filter(
CorpusFile.corpus_id == corpus_id,
CorpusFile.id == corpus_file_id
).first_or_404()
if not (
corpus_file.corpus.user == current_user
or current_user.is_administrator()
):
abort(403)
flash(
f'Corpus file "{corpus_file.filename}" marked for deletion!', 'corpus')
f'Corpus file "{corpus_file.filename}" marked for deletion',
category='corpus'
)
tasks.delete_corpus_file(corpus_file_id)
return redirect(url_for('.corpus', corpus_id=corpus_id))
@ -235,26 +258,34 @@ def delete_corpus_file(corpus_id, corpus_file_id):
@bp.route('/<hashid:corpus_id>/files/<hashid:corpus_file_id>/download')
@login_required
def download_corpus_file(corpus_id, corpus_file_id):
corpus_file = CorpusFile.query.get_or_404(corpus_file_id)
if not corpus_file.corpus_id == corpus_id:
abort(404)
if not (corpus_file.corpus.user == current_user
or current_user.is_administrator()):
corpus_file = CorpusFile.query.filter(
CorpusFile.corpus_id == corpus_id,
CorpusFile.id == corpus_file_id
).first_or_404()
if not (
corpus_file.corpus.user == current_user
or current_user.is_administrator()
):
abort(403)
return send_from_directory(as_attachment=True,
directory=os.path.dirname(corpus_file.path),
filename=corpus_file.filename)
return send_from_directory(
as_attachment=True,
directory=os.path.dirname(corpus_file.path),
filename=corpus_file.filename
)
@bp.route('/<hashid:corpus_id>/files/<hashid:corpus_file_id>', methods=['GET', 'POST'])
@bp.route('/<hashid:corpus_id>/files/<hashid:corpus_file_id>', methods=['GET', 'POST']) # noqa
@login_required
def corpus_file(corpus_id, corpus_file_id):
corpus = Corpus.query.get_or_404(corpus_id)
if not (corpus.user == current_user or current_user.is_administrator()):
corpus_file = CorpusFile.query.filter(
CorpusFile.corpus_id == corpus_id,
CorpusFile.id == corpus_file_id
).first_or_404()
if not (
corpus_file.corpus.user == current_user
or current_user.is_administrator()
):
abort(403)
corpus_file = CorpusFile.query.get_or_404(corpus_file_id)
if corpus_file.corpus != corpus:
abort(404)
form = EditCorpusFileForm(prefix='edit-corpus-file-form')
if form.validate_on_submit():
corpus_file.address = form.address.data
@ -269,9 +300,9 @@ def corpus_file(corpus_id, corpus_file_id):
corpus_file.publishing_year = form.publishing_year.data
corpus_file.school = form.school.data
corpus_file.title = form.title.data
corpus.status = 'unprepared'
corpus_file.corpus.status = CorpusStatus.UNPREPARED
db.session.commit()
flash(f'Corpus file "{corpus_file.filename}" edited!', 'corpus')
flash(f'Corpus file "{corpus_file.filename}" edited', category='corpus') # noqa
return redirect(url_for('.corpus', corpus_id=corpus_id))
# If no form is submitted or valid, fill out fields with current values
form.address.data = corpus_file.address
@ -286,9 +317,13 @@ def corpus_file(corpus_id, corpus_file_id):
form.publishing_year.data = corpus_file.publishing_year
form.school.data = corpus_file.school
form.title.data = corpus_file.title
return render_template('corpora/corpus_file.html.j2', corpus=corpus,
corpus_file=corpus_file, form=form,
title='Edit corpus file')
return render_template(
'corpora/corpus_file.html.j2',
corpus=corpus,
corpus_file=corpus_file,
form=form,
title='Edit corpus file'
)
@bp.route('/<hashid:corpus_id>/build')
@ -299,7 +334,13 @@ def build_corpus(corpus_id):
abort(403)
if corpus.files.all():
tasks.build_corpus(corpus_id)
flash(f'Corpus "{corpus.title}" marked for building!', 'corpus')
flash(
f'Corpus "{corpus.title}" marked for building',
category='corpus'
)
else:
flash(f'Can\'t build corpus "{corpus.title}": No corpus file(s)!', 'error') # noqa
flash(
f'Can\'t build corpus "{corpus.title}": No corpus file(s)',
category='error'
)
return redirect(url_for('.corpus', corpus_id=corpus_id))

View File

@ -1,6 +1,6 @@
from .. import db
from ..decorators import background
from ..models import Corpus, CorpusFile, QueryResult
from app import db
from app.decorators import background
from app.models import Corpus, CorpusFile
@background
@ -32,13 +32,3 @@ def delete_corpus_file(corpus_file_id, *args, **kwargs):
raise Exception(f'Corpus file {corpus_file_id} not found')
corpus_file.delete()
db.session.commit()
@background
def delete_query_result(query_result_id, *args, **kwargs):
with kwargs['app'].app_context():
query_result = QueryResult.query.get(query_result_id)
if query_result is None:
raise Exception(f'QueryResult {query_result_id} not found')
query_result.delete()
db.session.commit()