mirror of
				https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
				synced 2025-11-04 04:12:45 +00:00 
			
		
		
		
	Merge branch 'contributors-update' into development
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -39,3 +39,4 @@ __pycache__
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# Virtual environment
 | 
					# Virtual environment
 | 
				
			||||||
venv
 | 
					venv
 | 
				
			||||||
 | 
					.idea
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										58
									
								
								app/contributions/forms.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								app/contributions/forms.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
				
			|||||||
 | 
					from flask_wtf import FlaskForm
 | 
				
			||||||
 | 
					from flask_wtf.file import FileField, FileRequired
 | 
				
			||||||
 | 
					from wtforms import (
 | 
				
			||||||
 | 
					    BooleanField,
 | 
				
			||||||
 | 
					    StringField,
 | 
				
			||||||
 | 
					    SubmitField,
 | 
				
			||||||
 | 
					    SelectMultipleField,
 | 
				
			||||||
 | 
					    IntegerField
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					from wtforms.validators import InputRequired, Length
 | 
				
			||||||
 | 
					from app.services import SERVICES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ContributionForm(FlaskForm):
 | 
				
			||||||
 | 
					    title = StringField(
 | 
				
			||||||
 | 
					        'Title',
 | 
				
			||||||
 | 
					        validators=[InputRequired(), Length(max=64)]
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    description = StringField(
 | 
				
			||||||
 | 
					        'Description',
 | 
				
			||||||
 | 
					        validators=[InputRequired(), Length(max=255)]
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    version = StringField(
 | 
				
			||||||
 | 
					        'Version',
 | 
				
			||||||
 | 
					        validators=[InputRequired(), Length(max=16)]
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    compatible_service_versions = SelectMultipleField(
 | 
				
			||||||
 | 
					        'Compatible service versions'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    publisher = StringField(
 | 
				
			||||||
 | 
					        'Publisher',
 | 
				
			||||||
 | 
					        validators=[InputRequired(), Length(max=128)]
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    publisher_url = StringField(
 | 
				
			||||||
 | 
					        'Publisher URL',
 | 
				
			||||||
 | 
					        validators=[InputRequired(), Length(max=512)]
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    publishing_url = StringField(
 | 
				
			||||||
 | 
					        'Publishing URL',
 | 
				
			||||||
 | 
					        validators=[InputRequired(), Length(max=512)]
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    publishing_year = IntegerField(
 | 
				
			||||||
 | 
					        'Publishing year',
 | 
				
			||||||
 | 
					        validators=[InputRequired()]
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    shared = BooleanField('Shared', validators=[InputRequired()])
 | 
				
			||||||
 | 
					    model_file = FileField('File',validators=[FileRequired()])
 | 
				
			||||||
 | 
					    submit = SubmitField()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, *args, **kwargs):
 | 
				
			||||||
 | 
					        service_manifest = SERVICES['tesseract-ocr-pipeline']
 | 
				
			||||||
 | 
					        super().__init__(*args, **kwargs)
 | 
				
			||||||
 | 
					        self.compatible_service_versions.choices = [('', 'Choose your option')]
 | 
				
			||||||
 | 
					        self.compatible_service_versions.choices += [
 | 
				
			||||||
 | 
					            (x, x) for x in service_manifest['versions'].keys()
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					        self.compatible_service_versions.default = ''
 | 
				
			||||||
@@ -1,7 +1,10 @@
 | 
				
			|||||||
 | 
					from flask import abort, flash, Markup, render_template, url_for
 | 
				
			||||||
from flask_login import login_required
 | 
					from flask_login import login_required
 | 
				
			||||||
 | 
					from app import db
 | 
				
			||||||
from app.decorators import permission_required
 | 
					from app.decorators import permission_required
 | 
				
			||||||
from app.models import Permission
 | 
					from app.models import TesseractOCRModel, Permission
 | 
				
			||||||
from . import bp
 | 
					from . import bp
 | 
				
			||||||
 | 
					from .forms import ContributionForm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@bp.before_request
 | 
					@bp.before_request
 | 
				
			||||||
@@ -14,3 +17,38 @@ def before_request():
 | 
				
			|||||||
@bp.route('')
 | 
					@bp.route('')
 | 
				
			||||||
def contributions():
 | 
					def contributions():
 | 
				
			||||||
    pass
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@bp.route('/tesseract-ocr-pipeline-models', methods=['GET', 'POST'])
 | 
				
			||||||
 | 
					def tesseract_ocr_pipeline_models():
 | 
				
			||||||
 | 
					    form = ContributionForm(
 | 
				
			||||||
 | 
					        prefix='contribute-tesseract-ocr-pipeline-model-form'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    if form.is_submitted():
 | 
				
			||||||
 | 
					        if not form.validate():
 | 
				
			||||||
 | 
					            response = {'errors': form.errors}
 | 
				
			||||||
 | 
					            return response, 400
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            tesseract_ocr_model = TesseractOCRModel.create(
 | 
				
			||||||
 | 
					                form.file.data,
 | 
				
			||||||
 | 
					                compatible_service_versions=form.compatible_service_versions.data,
 | 
				
			||||||
 | 
					                description=form.description.data,
 | 
				
			||||||
 | 
					                publisher=form.publisher.data,
 | 
				
			||||||
 | 
					                publisher_url=form.publisher_url.data,
 | 
				
			||||||
 | 
					                publishing_url=form.publishing_url.data,
 | 
				
			||||||
 | 
					                publishing_year=form.publishing_year.data,
 | 
				
			||||||
 | 
					                shared=form.shared.data,
 | 
				
			||||||
 | 
					                title=form.title.data,
 | 
				
			||||||
 | 
					                version=form.version.data
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        except OSError:
 | 
				
			||||||
 | 
					            abort(500)
 | 
				
			||||||
 | 
					        db.session.commit()
 | 
				
			||||||
 | 
					        message = Markup(f'Model "{tesseract_ocr_model.title}" created')
 | 
				
			||||||
 | 
					        flash(message)
 | 
				
			||||||
 | 
					        return {}, 201, {'Location': url_for('contributions.contributions')}
 | 
				
			||||||
 | 
					    return render_template(
 | 
				
			||||||
 | 
					        'contributions/contribute.html.j2',
 | 
				
			||||||
 | 
					        form=form,
 | 
				
			||||||
 | 
					        title='Contribution'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -620,6 +620,55 @@ class TesseractOCRPipelineModel(FileMixin, HashidMixin, db.Model):
 | 
				
			|||||||
            _json['user'] = self.user.to_json(backrefs=True)
 | 
					            _json['user'] = self.user.to_json(backrefs=True)
 | 
				
			||||||
        return _json
 | 
					        return _json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @staticmethod
 | 
				
			||||||
 | 
					    def create(model_file, **kwargs):  # ??? Ist das so richtig? übergeben wir das form? Im anderen Fall ist das nicht so .. aber was soll hier überhaupt rein?
 | 
				
			||||||
 | 
					        filename = kwargs.get('filename', model_file.filename)
 | 
				
			||||||
 | 
					        mimetype = kwargs.get('mimetype', model_file.mimetype)
 | 
				
			||||||
 | 
					        tesseract_ocr_model = TesseractOCRModel(
 | 
				
			||||||
 | 
					            filename=secure_filename(filename),
 | 
				
			||||||
 | 
					            mimetype=mimetype,
 | 
				
			||||||
 | 
					            **kwargs
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        db.session.add(tesseract_ocr_model)
 | 
				
			||||||
 | 
					        db.session.flush(objects=[tesseract_ocr_model])
 | 
				
			||||||
 | 
					        db.session.refresh(tesseract_ocr_model)
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            # ??? Woher soll file kommen? Wir haben der methode das ganze form übergeben.
 | 
				
			||||||
 | 
					            # filename = form.file.data.filename
 | 
				
			||||||
 | 
					            model_file.save(tesseract_ocr_model.path)
 | 
				
			||||||
 | 
					        except OSError as e:
 | 
				
			||||||
 | 
					            current_app.logger.error(e)
 | 
				
			||||||
 | 
					            db.session.rollback()
 | 
				
			||||||
 | 
					            raise e
 | 
				
			||||||
 | 
					        return tesseract_ocr_model
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Kann man das so committen?
 | 
				
			||||||
 | 
					        # db.session.add(model)
 | 
				
			||||||
 | 
					        # db.session.flush(objects=[model])
 | 
				
			||||||
 | 
					        # db.session.refresh(model)
 | 
				
			||||||
 | 
					        # model.filename = f'{model.id}.traineddata'
 | 
				
			||||||
 | 
					        # r = requests.get(m['url'], stream=True)
 | 
				
			||||||
 | 
					        # pbar = tqdm(
 | 
				
			||||||
 | 
					        #     desc=f'{model.title} ({model.filename})',
 | 
				
			||||||
 | 
					        #     unit="B",
 | 
				
			||||||
 | 
					        #     unit_scale=True,
 | 
				
			||||||
 | 
					        #     unit_divisor=1024,
 | 
				
			||||||
 | 
					        #     total=int(r.headers['Content-Length'])
 | 
				
			||||||
 | 
					        # )
 | 
				
			||||||
 | 
					        # pbar.clear()
 | 
				
			||||||
 | 
					        # with open(model.path, 'wb') as f:
 | 
				
			||||||
 | 
					        #     for chunk in r.iter_content(chunk_size=1024):
 | 
				
			||||||
 | 
					        #         if chunk:  # filter out keep-alive new chunks
 | 
				
			||||||
 | 
					        #             pbar.update(len(chunk))
 | 
				
			||||||
 | 
					        #             f.write(chunk)
 | 
				
			||||||
 | 
					        #     pbar.close()
 | 
				
			||||||
 | 
					        #
 | 
				
			||||||
 | 
					        # db.session.commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SpaCyNLPPipelineModel(FileMixin, HashidMixin, db.Model):
 | 
					class SpaCyNLPPipelineModel(FileMixin, HashidMixin, db.Model):
 | 
				
			||||||
    __tablename__ = 'spacy_nlp_pipeline_models'
 | 
					    __tablename__ = 'spacy_nlp_pipeline_models'
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										32
									
								
								app/templates/contributions/contribute.html.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								app/templates/contributions/contribute.html.j2
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
				
			|||||||
 | 
					{% extends "base.html.j2" %}
 | 
				
			||||||
 | 
					{% import "materialize/wtf.html.j2" as wtf %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block page_content %}
 | 
				
			||||||
 | 
					<div class="container">
 | 
				
			||||||
 | 
					  <div class="row">
 | 
				
			||||||
 | 
					    <div class="col s12 m8 offset-m2">
 | 
				
			||||||
 | 
					      <h1 id="title">{{ title }}</h1>
 | 
				
			||||||
 | 
					      <p>
 | 
				
			||||||
 | 
					        In order to add a new model, please fill in the form below.
 | 
				
			||||||
 | 
					      </p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      <form method="POST">
 | 
				
			||||||
 | 
					        <div class="card-panel">
 | 
				
			||||||
 | 
					          {{ form.hidden_tag() }}
 | 
				
			||||||
 | 
					          {{ wtf.render_field(form.title) }}
 | 
				
			||||||
 | 
					          {{ wtf.render_field(form.description) }}
 | 
				
			||||||
 | 
					          {{ wtf.render_field(form.publisher) }}
 | 
				
			||||||
 | 
					          {{ wtf.render_field(form.publisher_url) }}
 | 
				
			||||||
 | 
					          {{ wtf.render_field(form.publishing_url) }}
 | 
				
			||||||
 | 
					          {{ wtf.render_field(form.publishing_year) }}
 | 
				
			||||||
 | 
					          {{ wtf.render_field(form.shared) }}
 | 
				
			||||||
 | 
					          {{ wtf.render_field(form.version) }}
 | 
				
			||||||
 | 
					          {{ wtf.render_field(form.compatible_service_versions) }}
 | 
				
			||||||
 | 
					          {{ wtf.render_field(form.submit, class_='width-100', material_icon='send') }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </form>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					{% endblock page_content %}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user