mirror of
				https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
				synced 2025-11-04 12:22:47 +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
 | 
			
		||||
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 app import db
 | 
			
		||||
from app.decorators import permission_required
 | 
			
		||||
from app.models import Permission
 | 
			
		||||
from app.models import TesseractOCRModel, Permission
 | 
			
		||||
from . import bp
 | 
			
		||||
from .forms import ContributionForm
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@bp.before_request
 | 
			
		||||
@@ -14,3 +17,38 @@ def before_request():
 | 
			
		||||
@bp.route('')
 | 
			
		||||
def contributions():
 | 
			
		||||
    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)
 | 
			
		||||
        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):
 | 
			
		||||
    __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