From 5f4b5f3993c7dc4a04b100ef5efbdb183c1ef2ad Mon Sep 17 00:00:00 2001 From: Luke Murphy Date: Sat, 17 Nov 2018 20:04:02 +0100 Subject: [PATCH] Run the style checker over the source. --- app/__init__.py | 19 +- app/cover.py | 36 +-- app/extractText.py | 12 +- app/forms.py | 54 +++- app/getannot.py | 136 +++++---- app/models.py | 112 +++++-- app/test.txt | 0 app/views.py | 732 ++++++++++++++++++++++++++++++++------------- 8 files changed, 751 insertions(+), 350 deletions(-) delete mode 100644 app/test.txt diff --git a/app/__init__.py b/app/__init__.py index 8a69b1f..40711cf 100755 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,14 +1,11 @@ +import os +from os import environ + +from dotenv import find_dotenv, load_dotenv from flask import Flask +from flask_socketio import SocketIO from flask_sqlalchemy import SQLAlchemy -from marshmallow import Schema, fields, ValidationError, pre_load -from flask_socketio import SocketIO, emit -from os import environ -from dotenv import load_dotenv, find_dotenv -import os -import click -from werkzeug.utils import secure_filename from sqlalchemy.dialects import registry -# import flask_whooshalchemyplus not using whoosh anymore registry.register("rqlite.pyrqlite", "sqlalchemy_rqlite.pyrqlite", "dialect") @@ -16,23 +13,21 @@ basedir = os.path.abspath(os.path.dirname(__file__)) UPLOAD_FOLDER = os.path.join(basedir, 'uploads') UPLOAD_FOLDER_COVER = os.path.join(basedir, 'cover') -#ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif']) + load_dotenv(find_dotenv()) app = Flask(__name__) app.config['SECRET_KEY'] = 'super secret key' -#app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/mydatabase.db' app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER app.config['SQLALCHEMY_DATABASE_URI'] = 'rqlite+pyrqlite://localhost:4001/' app.config['DEBUG'] = True app.config['PORT'] = 80 -#app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'mydatabase.db') db = SQLAlchemy(app) light = not os.path.isdir(UPLOAD_FOLDER) DOMAIN = environ.get('DOMAIN') socketio = SocketIO(app) app.config.from_object(__name__) -from app import views +from app import views # noqa diff --git a/app/cover.py b/app/cover.py index 5847e0b..2da1bb0 100755 --- a/app/cover.py +++ b/app/cover.py @@ -1,11 +1,11 @@ +import io + import PyPDF2 -from wand.image import Image from wand.color import Color -import io -import os +from wand.image import Image -def pdf_page_to_png(src_pdf, pagenum = 0, resolution = 72,): +def pdf_page_to_png(src_pdf, pagenum=0, resolution=72): """ Returns specified PDF page as wand.image.Image png. :param PyPDF2.PdfFileReader src_pdf: PDF from which to take pages. @@ -19,7 +19,7 @@ def pdf_page_to_png(src_pdf, pagenum = 0, resolution = 72,): dst_pdf.write(pdf_bytes) pdf_bytes.seek(0) - img = Image(file = pdf_bytes, resolution = resolution) + img = Image(file=pdf_bytes, resolution=resolution) img.background_color = Color('white') img.alpha_channel = 'remove' img.convert("jpeg") @@ -32,36 +32,32 @@ def get_cover(file_path, filename): # ==== print(file_path) src_filename = file_path + try: src_pdf = PyPDF2.PdfFileReader(open(src_filename, "rb")) - except: + except Exception: print("couln't open PDF") - return None; + return + if src_pdf.isEncrypted: try: src_pdf.decrypt('') - except: + except Exception: print("couln't decrypt") - return None; - # What follows is a lookup table of page numbers within sample_log.pdf and the corresponding filenames. + return + + # What follows is a lookup table of page numbers within sample_log.pdf and + # the corresponding filenames. pages = [{"pagenum": 0, "filename": filename}] # Convert each page to a png image. for page in pages: big_filename = "app/cover/"+page["filename"] + "_cover.jpeg" - #small_filename = "app/cover/"+page["filename"] + "cover_small" + ".jpeg" - img = pdf_page_to_png(src_pdf, pagenum = page["pagenum"], resolution = 130) - #img.save(filename = big_filename) + img = pdf_page_to_png(src_pdf, pagenum=page["pagenum"], resolution=130) # Ensmallen img.transform("", "250") - img.save(filename = big_filename) + img.save(filename=big_filename) return page["filename"] + "_cover.jpeg" - -#--- -#epub -#https://ebooks.stackexchange.com/questions/6517/command-line-extraction-of-metadata-title-author-from-epub-file -#https://hackage.haskell.org/package/epub-tools -#http://stackoverflow.com/questions/9751475/extract-cover-image-from-chm-and-epub-files diff --git a/app/extractText.py b/app/extractText.py index e3e435f..91f6987 100644 --- a/app/extractText.py +++ b/app/extractText.py @@ -2,22 +2,22 @@ import PyPDF2 def get_text(file_path, filename): - read_pdf =file_path + read_pdf = file_path + write_txt = "app/uploads/" + filename + '.txt' - with open(read_pdf,'rb') as pdf_file, open("app/uploads/"+filename+'.txt', 'w') as text_file: + with open(read_pdf, 'rb') as pdf_file, open(write_txt, 'w') as text_file: read_pdf = PyPDF2.PdfFileReader(pdf_file) number_of_pages = read_pdf.getNumPages() - for page_number in range(number_of_pages): # use xrange in Py2 + for page_number in range(number_of_pages): page = read_pdf.getPage(page_number) page_content = page.extractText() text_file.write(page_content) - def extract_text(file_path, filename): try: get_text(file_path, filename) - except: - with open(filename+'.txt', 'w') as text_file: + except Exception: + with open(filename + '.txt', 'w') as text_file: page_content = "" text_file.write(page_content) diff --git a/app/forms.py b/app/forms.py index 6083f5a..58feb96 100755 --- a/app/forms.py +++ b/app/forms.py @@ -1,11 +1,11 @@ +from app.models import Author from flask_wtf import FlaskForm -from wtforms import StringField, FileField, validators -from wtforms.validators import InputRequired, DataRequired -from wtforms import FieldList +from wtforms import FieldList, FileField from wtforms import Form as NoCsrfForm -from wtforms.fields import StringField, FormField, SubmitField, SelectField, RadioField -from app.models import Book, BookSchema, Author, Stack, StackSchema +from wtforms import validators +from wtforms.fields import FormField, SelectField, StringField, SubmitField from wtforms.fields.html5 import DecimalRangeField +from wtforms.validators import DataRequired, InputRequired # - - - Forms - - - @@ -13,11 +13,19 @@ class AuthorForm(NoCsrfForm): # this forms is never exposed so we can user the non CSRF version author_name = StringField('Author Name', validators=[DataRequired()]) + class UploadForm(FlaskForm): title = StringField('title', validators=[InputRequired()]) - author = FieldList(FormField(AuthorForm, default=lambda: Author()), min_entries=1) + author = FieldList( + FormField(AuthorForm, default=lambda: Author()), + min_entries=1 + ) category = StringField('category', validators=[InputRequired()]) - year_published = StringField('year published', [validators.Length(max=4)],default=None) + year_published = StringField( + 'year published', + [validators.Length(max=4)], + default=None + ) file = FileField() upload = SubmitField(label='Upload') wish = SubmitField(label='''I don't have the file, but wish I did.''') @@ -26,7 +34,7 @@ class UploadForm(FlaskForm): diversity = DecimalRangeField('diversity', default=0) gender = DecimalRangeField('gender', default=50) choices = [('Student', 'Student'), - ('Librarian', 'Librarian'), + ('Librarian', 'Librarian'), ('Pirate', 'Pirate'), ('Teacher', 'Teacher'), ('Institution', 'Institution'), @@ -37,16 +45,23 @@ class UploadForm(FlaskForm): class EditForm(FlaskForm): title = StringField('title', validators=[InputRequired()]) - author = FieldList(FormField(AuthorForm, default=lambda: Author()), min_entries=1) + author = FieldList( + FormField(AuthorForm, default=lambda: Author()), + min_entries=1 + ) category = StringField('category', validators=[InputRequired()]) - year_published = StringField('year published', [validators.Length(max=4)],default=None) + year_published = StringField( + 'year published', + [validators.Length(max=4)], + default=None + ) file = FileField() message = StringField('message') sameness = DecimalRangeField('sameness', default=0) diversity = DecimalRangeField('diversity', default=0) gender = DecimalRangeField('gender', default=50) choices = [('Student', 'Student'), - ('Librarian', 'Librarian'), + ('Librarian', 'Librarian'), ('Pirate', 'Pirate'), ('Teacher', 'Teacher'), ('Institution', 'Institution'), @@ -54,26 +69,37 @@ class EditForm(FlaskForm): ('None of the above', 'None of the above')] who = SelectField('', choices=choices, default='Student') + class ChatForm(FlaskForm): message = StringField('message', validators=[InputRequired()]) send = SubmitField(label='Send') + class StackForm(FlaskForm): stack_name = StringField('Stack', validators=[InputRequired()]) - stack_description = StringField('Description', validators=[InputRequired()]) + stack_description = StringField( + 'Description', + validators=[InputRequired()] + ) stack_author = StringField('Who made this', validators=[InputRequired()]) create = SubmitField(label='Create') + class AddtoStackForm(FlaskForm): select_stack = SelectField('Stacks', validators=[InputRequired()]) + class EditStackForm(FlaskForm): edit_stack_name = StringField('Stack', validators=[InputRequired()]) - edit_stack_description = StringField('Description', validators=[InputRequired()]) + edit_stack_description = StringField( + 'Description', + validators=[InputRequired()] + ) + class SearchForm(FlaskForm): choices = [('All', 'All'), - ('Title', 'Title'), + ('Title', 'Title'), ('Author', 'Author'), ('Category', 'Category'), ('Stack', 'Stack'), diff --git a/app/getannot.py b/app/getannot.py index 55420c1..1644f03 100644 --- a/app/getannot.py +++ b/app/getannot.py @@ -1,61 +1,87 @@ -from flask import request -import requests import json +import requests + +from flask import request + + def get_annotations(): - KEY = "6879-n8AksBoSB7kYoQ3eEwzpEr3nFQEmSp3XN-0PcKL_Sik" - - #a dictionary containing necessary http headers - headers = { - "Host": "hypothes.is", - "Accept": "application/json", - "Authorization": "Bearer %s" % KEY - } - - base_url = "https://hypothes.is/api/search?user=xpub@hypothes.is" - - search_url = "".join([base_url]) - - r = requests.get(search_url, headers=headers) - #data is a python dictionary - data = json.loads(r.text) - server = request.host - for row in data['rows']: - row['uri']= row['uri'].replace('http://' + server+'/uploads/','') - return data - - -def get_annot_results(annot,name): - res=[] - annot=get_annotations() - for item in annot['rows']: - if 'selector' in item['target'][0]: - if len(item['target'][0]['selector'])>2: - if name in item['text'] or name in item['target'][0]['selector'][2]['exact']: - data={'text': item['text'],'extract':item['target'][0]['selector'][2]['exact'],'title':item['document']['title'], 'url':item['uri']} - res.append(data) - else: - if name in item['text'] or name in item['target'][0]['selector'][1]['exact']: - data={'text': item['text'],'extract':item['target'][0]['selector'][1]['exact'],'title':item['document']['title'], 'url':item['uri']} - res.append(data) - return res - -def get_annot_book(annot,name): - res=[] - server = request.host - for item in annot['rows']: - if 'selector' in item['target'][0]: - if len(item['target'][0]['selector'])>2: - string=item['uri'] - if name==string.replace('http://' + server+'/uploads/',''): - data={'text': item['text'],'extract':item['target'][0]['selector'][2]['exact'],'title':item['document']['title'], 'url':item['uri']} - res.append(data) - else: - string=item['uri'] - if name==string.replace('http://' + server+'/uploads/',''): - data={'text': item['text'],'extract':item['target'][0]['selector'][1]['exact'],'title':item['document']['title'], 'url':item['uri']} - res.append(data) - return res + # TODO(decentral1se): remove this from the source + KEY = "6879-n8AksBoSB7kYoQ3eEwzpEr3nFQEmSp3XN-0PcKL_Sik" + + # a dictionary containing necessary http headers + headers = { + "Host": "hypothes.is", + "Accept": "application/json", + "Authorization": "Bearer %s" % KEY + } + + base_url = "https://hypothes.is/api/search?user=xpub@hypothes.is" + + search_url = "".join([base_url]) + + r = requests.get(search_url, headers=headers) + + # data is a python dictionary + data = json.loads(r.text) + server = request.host + + for row in data['rows']: + row['uri'] = row['uri'].replace( + 'http://' + server + '/uploads/', + '' + ) + + return data + +def get_annot_results(annot, name): + res = [] + annot = get_annotations() + for item in annot['rows']: + if 'selector' in item['target'][0]: + if len(item['target'][0]['selector']) > 2: + exact_second = item['target'][0]['selector'][2]['exact'] + if name in item['text'] or name in exact_second: + data = { + 'text': item['text'], + 'extract': item['target'][0]['selector'][2]['exact'], + 'title': item['document']['title'], 'url': item['uri'] + } + res.append(data) + else: + exact_first = item['target'][0]['selector'][1]['exact'] + if name in item['text'] or name in exact_first: + data = { + 'text': item['text'], + 'extract': item['target'][0]['selector'][1]['exact'], + 'title': item['document']['title'], 'url': item['uri'] + } + res.append(data) + return res +def get_annot_book(annot, name): + res = [] + server = request.host + for item in annot['rows']: + if 'selector' in item['target'][0]: + if len(item['target'][0]['selector']) > 2: + string = item['uri'] + if name == string.replace('http://' + server+'/uploads/', ''): + data = { + 'text': item['text'], + 'extract': item['target'][0]['selector'][2]['exact'], + 'title': item['document']['title'], 'url': item['uri'] + } + res.append(data) + else: + string = item['uri'] + if name == string.replace('http://' + server+'/uploads/', ''): + data = { + 'text': item['text'], + 'extract': item['target'][0]['selector'][1]['exact'], + 'title': item['document']['title'], 'url': item['uri'] + } + res.append(data) + return res diff --git a/app/models.py b/app/models.py index 076ca22..ec48471 100755 --- a/app/models.py +++ b/app/models.py @@ -1,54 +1,99 @@ -from app import db -from marshmallow import Schema, fields, ValidationError, pre_load import datetime -from sqlalchemy import Column, Integer, DateTime -import flask_whooshalchemyplus - -authors = db.Table('books_authors', - db.Column('book_id', db.Integer, db.ForeignKey('books.id'), primary_key=True), - db.Column('author_id', db.Integer, db.ForeignKey('authors.id'), primary_key=True) +from app import db +from marshmallow import Schema, ValidationError, fields +from sqlalchemy import Column, DateTime + + +authors = db.Table( + 'books_authors', + db.Column( + 'book_id', + db.Integer, + db.ForeignKey('books.id'), + primary_key=True + ), + db.Column( + 'author_id', + db.Integer, + db.ForeignKey('authors.id'), + primary_key=True + ) ) -stacks = db.Table('books_stacks', - db.Column('book_id', db.Integer, db.ForeignKey('books.id'), primary_key=True), - db.Column('stack_id', db.Integer, db.ForeignKey('stacks.id'), primary_key=True) +stacks = db.Table( + 'books_stacks', + db.Column( + 'book_id', + db.Integer, + db.ForeignKey('books.id'), + primary_key=True + ), + db.Column( + 'stack_id', + db.Integer, + db.ForeignKey('stacks.id'), + primary_key=True + ) ) -instances = db.Table('books_instances', - db.Column('book_id', db.Integer, db.ForeignKey('books.id'), primary_key=True), - db.Column('instance_id', db.Integer, db.ForeignKey('instances.id'), primary_key=True) +instances = db.Table( + 'books_instances', + db.Column( + 'book_id', + db.Integer, + db.ForeignKey('books.id'), + primary_key=True + ), + db.Column( + 'instance_id', + db.Integer, + db.ForeignKey('instances.id'), + primary_key=True + ) ) + class Book(db.Model): __tablename__ = 'books' - id = db.Column(db.Integer, primary_key = True) + id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(255)) file = db.Column(db.String(255)) cover = db.Column(db.String(255)) fileformat = db.Column(db.String(255)) category = db.Column(db.String(255)) - year_published = db.Column(db.Numeric(4,0)) + year_published = db.Column(db.Numeric(4, 0)) description = db.Column(db.String(2500)) html = db.Column(db.String(255)) - downloads = db.Column(db.Numeric(100,0)) - authors = db.relationship('Author', secondary=authors,cascade="delete", lazy='subquery', - backref=db.backref('books', lazy=True),passive_deletes=True) - stacks = db.relationship('Stack', secondary=stacks, lazy='subquery', - backref=db.backref('books', lazy=True)) - instances = db.relationship('Instance', secondary=instances, lazy='subquery', - backref=db.backref('books', lazy=True)) - scapeX = db.Column(db.Numeric(10,2)) - scapeY = db.Column(db.Numeric(10,2)) + downloads = db.Column(db.Numeric(100, 0)) + authors = db.relationship( + 'Author', + secondary=authors, + cascade="delete", + lazy='subquery', + backref=db.backref('books', lazy=True), + passive_deletes=True + ) + stacks = db.relationship( + 'Stack', secondary=stacks, lazy='subquery', + backref=db.backref('books', lazy=True) + ) + instances = db.relationship( + 'Instance', secondary=instances, lazy='subquery', + backref=db.backref('books', lazy=True) + ) + scapeX = db.Column(db.Numeric(10, 2)) + scapeY = db.Column(db.Numeric(10, 2)) message = db.Column(db.String(1000)) sameness = db.Column(db.Numeric()) diversity = db.Column(db.Numeric()) gender = db.Column(db.Numeric()) who = db.Column(db.String(255)) - - def __init__(self, title, file, cover, fileformat, category, year_published, message, sameness, diversity, gender, who): + def __init__(self, title, file, cover, fileformat, + category, year_published, message, + sameness, diversity, gender, who): self.title = title self.file = file self.cover = cover @@ -64,7 +109,6 @@ class Book(db.Model): self.gender = gender self.who = who - def __repr__(self): return '' % self.title @@ -81,6 +125,7 @@ class Author(db.Model): def __init__(self, author_name): self.author_name = author_name + class Instance(db.Model): __tablename__ = 'instances' @@ -106,6 +151,7 @@ class UserIns(db.Model): self.title = title self.info = info + class Chat(db.Model): __tablename__ = 'chat' @@ -117,14 +163,15 @@ class Chat(db.Model): self.message = message self.time = datetime.datetime.now() + class Stack(db.Model): __tablename__ = 'stacks' - id = db.Column(db.Integer, primary_key = True) + + id = db.Column(db.Integer, primary_key=True) stack_name = db.Column(db.String(50)) stack_description = db.Column(db.String(1000)) stack_author = db.Column(db.String(255)) - def __init__(self, stack_name, stack_description, stack_author): self.stack_name = stack_name self.stack_description = stack_description @@ -136,7 +183,7 @@ class Stack(db.Model): class Potential(db.Model): __tablename__ = 'potential' - id = db.Column(db.Integer, primary_key = True) + id = db.Column(db.Integer, primary_key=True) ptitle = db.Column(db.String(50)) time = db.Column(DateTime, default=datetime.datetime.now()) @@ -149,16 +196,19 @@ class AuthorSchema(Schema): id = fields.Int(dump_only=True) author_name = fields.Str() + class StackSchema(Schema): id = fields.Int(dump_only=True) stack_name = fields.Str() stack_description = fields.Str() + class ChatSchema(Schema): id = fields.Int(dump_only=True) message = fields.Str() time = fields.DateTime() + class BookSchema(Schema): id = fields.Int(dump_only=True) title = fields.Str() diff --git a/app/test.txt b/app/test.txt deleted file mode 100644 index e69de29..0000000 diff --git a/app/views.py b/app/views.py index e20ad53..01e0862 100755 --- a/app/views.py +++ b/app/views.py @@ -1,35 +1,35 @@ -""" -Flask Documentation: http://flask.pocoo.org/docs/ -Jinja2 Documentation: http://jinja.pocoo.org/2/documentation/ -Werkzeug Documentation: http://werkzeug.pocoo.org/documentation/ -This file creates your application. -""" - -from app import app, db, socketio, DOMAIN, light -from flask import Flask, Response, session, render_template, request, redirect, url_for, flash, send_from_directory, jsonify, abort -from flask_weasyprint import HTML, render_pdf +import codecs +import datetime +import io import json -from functools import wraps import os -from sqlalchemy.sql.expression import func, select -from sqlalchemy.sql import except_ -from app.forms import UploadForm, EditForm, SearchForm, ChatForm, StackForm, AddtoStackForm, EditStackForm -from app.models import Book, BookSchema, Author, AuthorSchema, Stack, StackSchema, UserIns, Chat, ChatSchema, Instance, Potential -from app.cover import get_cover -from app.getannot import get_annotations, get_annot_results, get_annot_book +from csv import DictReader, DictWriter +from functools import wraps from urllib.parse import quote as urlquote + +import autocomplete +from app import DOMAIN, app, db, light, socketio +from app.cover import get_cover from app.extractText import extract_text -from os import environ -from flask_socketio import SocketIO, emit -from weasyprint import HTML -import datetime -import time -from csv import DictWriter, DictReader -import io +from app.forms import ( + AddtoStackForm, EditForm, EditStackForm, + SearchForm, StackForm, UploadForm +) +from app.getannot import get_annot_book, get_annot_results, get_annotations +from app.models import ( + Author, AuthorSchema, Book, BookSchema, Chat, + ChatSchema, Instance, Potential, Stack, StackSchema, + UserIns +) +from flask import ( + Response, abort, flash, jsonify, redirect, + render_template, request, send_from_directory, + url_for +) +from flask_socketio import emit +from flask_weasyprint import HTML, render_pdf from sqlalchemy.inspection import inspect -import autocomplete -from autocomplete import models -import sys +from sqlalchemy.sql.expression import func from werkzeug.utils import secure_filename # import sqlite3 @@ -44,6 +44,7 @@ stacks_schema = StackSchema(many=True) chat_schema = ChatSchema() chats_schema = ChatSchema(many=True) + def allowed_file(filename): return '.' in filename and \ filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS @@ -52,7 +53,6 @@ def allowed_file(filename): ### - def check_light(func): @wraps(func) def decorated_function(*args, **kwargs): @@ -65,30 +65,41 @@ def check_light(func): return decorated_function -@app.route('/', methods= ['POST','GET']) +@app.route('/', methods=['POST', 'GET']) def home(): print("/////////////") print(light) - chat_form = ChatForm() chat_messages = db.session.query(Chat).all() username = 'librarian' server = request.host if request.environ.get('HTTP_X_FORWARDED_FOR') is None: - client =request.environ['REMOTE_ADDR'] + client = request.environ['REMOTE_ADDR'] else: client = request.environ['HTTP_X_FORWARDED_FOR'] - return render_template('home.html',domain=DOMAIN,chat=chat_messages, channel = 1, username=username, client=client, server=server, light=light) + return render_template( + 'home.html', + domain=DOMAIN, + chat=chat_messages, + channel=1, + username=username, + client=client, + server=server, + light=light + ) + @app.route('/hello/<name>') def hello(name): return "Hello " + name + @app.route('/about/') def about(): """Render the website's about page.""" return render_template('about.html', light=light) + @app.route('/uploads/<filename>') @check_light def uploaded_file(filename): @@ -102,18 +113,20 @@ def uploaded_file(filename): return send_from_directory(app.config['UPLOAD_FOLDER'], filename) + # annotations @app.route('/annotations') def annotations(): """Render annotations page.""" books = db.session.query(Book).all() - # books = db.session.query(Book).order_by(Book.title) - # id = book.id - server = request.host - rstr=('http://' + server+'/uploads/','') annot = get_annotations() - print(annot) - return render_template('annotations.html', annot=annot, books=books, light=light) + return render_template( + 'annotations.html', + annot=annot, + books=books, + light=light + ) + # PDF from annotations @app.route('/annotations.pdf') @@ -123,38 +136,44 @@ def annotations_pdf(): html = render_template(('annotations.html'), annot=annot, light=light) return render_pdf(HTML(string=html)) -# @app.route('/myannotations.pdf') -# def myannotations_pdf(): -# books = db.session.query(Book).all() -# name=str(request.args.get('query')) -# annot = get_annotations() -# res = get_annot_results(annot,name) -# # Make a PDF straight from HTML in a string. -# html = render_template('results_annot.html', name=name, annot=annot, res=res, books=books) -# return render_pdf(HTML(string=html)) - @app.route('/viewpdf/<filename>') def viewtestfile1_file(filename): - return redirect("/static/viewer/web/viewer.html?file=%2Fuploads%2F"+urlquote(filename)) + return redirect(( + "/static/viewer/web/viewer.html?file=%2Fuploads%2F" + + + urlquote(filename) + )) + @app.route('/cover/<filename>') def uploaded_file_cover(filename): return send_from_directory(app.config['UPLOAD_FOLDER_COVER'], filename) + @app.route('/updates', methods=['POST', 'GET']) def get_updates(): userin = UserIns.query.filter_by(title="lastViewed").first() allbooks = db.session.query(Book).all() - id = len(allbooks) latest_upload = allbooks[-1] - return "This is the XPPL ~ Library XPUB ~ Updates / / / / / / / Last viewed: " + userin.info + " / / / / / / / " + str(len(allbooks)) + " Books online "+ " / / / / / / / " + "Latest entry: " + latest_upload.title + return ( + "This is the XPPL ~ Library XPUB ~ Updates / / / / / / / Last viewed: " + + userin.info + + " / / / / / / / " + + str(len(allbooks)) + + " Books online " + + " / / / / / / / " + + "Latest entry: " + + latest_upload.title + ) + @app.route('/volumetric_catalog', methods=['GET']) def volumetric_catalog(): return render_template('volumetric_catalog/index.html') + @app.route('/scape', methods=['POST', 'GET']) def scape(): if request.method == 'POST': @@ -164,7 +183,7 @@ def scape(): book.scapeX = data['x'] book.scapeY = data['y'] db.session.commit() - books = db.session.query(Book).all() # or you could have used User.query.all() + books = db.session.query(Book).all() all_instances = db.session.query(Instance).all() instances = [] for instance in all_instances: @@ -179,18 +198,18 @@ def scape(): instances.append(instance) return render_template('scape.html', books=books, instances=instances) + @app.route('/scape_new', methods=['POST', 'GET']) def scape_new(): return render_template('scape_new.html') + @app.route('/books_grid') def show_books_grid(): - books = db.session.query(Book).all() # or you could have used User.query.all() + books = db.session.query(Book).all() return render_template('show_books_grid.html', books=books, light=light) - - @app.route('/books/<int:id>') def show_book_by_id(id): book = Book.query.get(id) @@ -204,14 +223,12 @@ def show_book_by_id(id): if id == edge: nextbook = None - name= book.file + name = book.file annot = get_annotations() - res = get_annot_book(annot,name) - - + res = get_annot_book(annot, name) userin = UserIns.query.filter_by(title="lastViewed").first() - if userin != None: + if userin is not None: userin.info = book.title db.session.commit() else: @@ -221,10 +238,17 @@ def show_book_by_id(id): if not book: return render_template('red_link.html', id=id, light=light) else: - return render_template('show_book_detail.html', book=book, previousbook = previousbook, nextbook = nextbook, all_instances=all_instances, name=name, annot=annot, res=res, light=light) - - - + return render_template( + 'show_book_detail.html', + book=book, + previousbook=previousbook, + nextbook=nextbook, + all_instances=all_instances, + name=name, + annot=annot, + res=res, + light=light + ) @app.route('/books/<int:id>/delete', methods=['POST', 'GET']) @@ -233,20 +257,29 @@ def remove_book_by_id(id): book_to_edit = Book.query.filter_by(id=id).first() title = book_to_edit.title Book.query.filter_by(id=id).delete() - #author_table = Author.query.filter_by(book_id=book_to_edit.id).delete() db.session.commit() flash("%s deleted from library" % (title)) return redirect(url_for('show_books')) + @app.route('/books/<int:id>/edit', methods=['POST', 'GET']) @check_light def edit_book_by_id(id): book_to_edit = Book.query.filter_by(id=id).first() - user_form = EditForm(title = book_to_edit.title, author =book_to_edit.authors, category = book_to_edit.category, year_published= book_to_edit.year_published, message= book_to_edit.message, sameness=book_to_edit.sameness, gender=book_to_edit.gender, diversity=book_to_edit.diversity, who=book_to_edit.who) + user_form = EditForm( + title=book_to_edit.title, + author=book_to_edit.authors, + category=book_to_edit.category, + year_published=book_to_edit.year_published, + message=book_to_edit.message, + sameness=book_to_edit.sameness, + gender=book_to_edit.gender, + diversity=book_to_edit.diversity, + who=book_to_edit.who + ) if request.method == 'POST': if user_form.validate_on_submit(): - # on submit, check fields title = user_form.title.data input_authors = user_form.author.data category = user_form.category.data @@ -257,8 +290,9 @@ def edit_book_by_id(id): diversity = user_form.diversity.data who = user_form.who.data - if year_published=="": + if year_published == "": year_published = None + book = Book.query.filter_by(id=id).first() book.title = title book.category = category @@ -269,18 +303,23 @@ def edit_book_by_id(id): book.diversity = diversity book.who = who - #authors update book.authors.clear() for i, author in enumerate(input_authors): author_name = author.get("author_name") if author_name: - a = db.session.query(Author).filter_by(author_name=author_name).first() - if a == None: + a = ( + db.session.query(Author) + .filter_by(author_name=author_name).first() + ) + if a is None: a = Author(author_name=author_name) db.session.add(a) book.authors.append(a) i = Instance(request.host, "edit") - existing_ip = db.session.query(Instance).filter_by(ip=request.host).first() + existing_ip = ( + db.session.query(Instance) + .filter_by(ip=request.host).first() + ) if existing_ip: i.name = existing_ip.name book.instances.append(i) @@ -292,18 +331,22 @@ def edit_book_by_id(id): flash('No selected file') return redirect(request.url) if file and allowed_file(file.filename): - allbooks = db.session.query(Book).all() id = book.id filename = str(id) + "_" + secure_filename(file.filename) - fullpath = os.path.join(app.config['UPLOAD_FOLDER'], filename) + fullpath = os.path.join( + app.config['UPLOAD_FOLDER'], + filename + ) name, file_extension = os.path.splitext(filename) file.save(fullpath) book.cover = "" + try: get_cover(fullpath, name) - except: + except Exception: print("couldn't get cover") + book.file = filename else: flash('allowed file formats: %s' % ALLOWED_EXTENSIONS) @@ -312,7 +355,12 @@ def edit_book_by_id(id): flash("%s updated" % (title)) return redirect(url_for('show_book_by_id', id=id)) - return render_template('edit_book_detail.html', book=book_to_edit, form=user_form, light=light) + return render_template( + 'edit_book_detail.html', + book=book_to_edit, + form=user_form, + light=light + ) @app.route('/add-book', methods=['POST', 'GET']) @@ -324,16 +372,21 @@ def add_book(): allauthors = db.session.query(Author).all() authors_all = len(allauthors) stacks_all = [s.stack_name for s in db.session.query(Stack.stack_name)] - categories = [r.category for r in db.session.query(Book.category).distinct()] - allpotential = db.session.query(Book).filter(Book.file.contains('potential.pdf')).all() + categories = [ + r.category for r in + db.session.query(Book.category).distinct() + ] + allpotential = ( + db.session.query(Book) + .filter(Book.file.contains('potential.pdf')) + .all() + ) books_potential = len(allpotential) earliest = db.session.query(func.min(Book.year_published)).scalar() latest = db.session.query(func.max(Book.year_published)).scalar() - if request.method == 'POST': if upload_form.validate_on_submit(): - #get data from form title = upload_form.title.data authors = upload_form.author.data category = upload_form.category.data @@ -344,10 +397,10 @@ def add_book(): diversity = upload_form.diversity.data who = upload_form.who.data - if year_published=="": + if year_published == "": year_published = None - #if upload with file + # if upload with file if upload_form.upload.data: # check if the post request has the file part if 'file' not in request.files: @@ -364,46 +417,75 @@ def add_book(): id = len(allbooks)+1 filename = str(id) + "_" + secure_filename(file.filename) - fullpath = os.path.join(app.config['UPLOAD_FOLDER'], filename) + fullpath = os.path.join( + app.config['UPLOAD_FOLDER'], + filename + ) name, file_extension = os.path.splitext(filename) file.save(fullpath) + try: cover = get_cover(fullpath, name) - except: + except Exception: cover = '' extract_text(fullpath, name) else: flash('allowed file formats: %s' % ALLOWED_EXTENSIONS) - #if upload without file -> wishform, with potential PDF + # if upload without file -> wishform, with potential PDF if upload_form.wish.data: - #pdf generator + # pdf generator filename = 'potential.pdf' file_extension = '.pdf' - cover= 'default_cover.gif' + cover = 'default_cover.gif' ptitle = upload_form.title.data pbook = Potential(ptitle) db.session.add(pbook) db.session.commit() pbooks = Potential.query.all() - template = 'app/templates/potential_pdf.html' - html_string = render_template('potential_pdf.html', pbooks = pbooks) + html_string = render_template( + 'potential_pdf.html', + pbooks=pbooks + ) html = HTML(string=html_string) - html.write_pdf(target='app/uploads/potential.pdf'); + html.write_pdf(target='app/uploads/potential.pdf') + + book = Book( + title, + filename, + cover, + file_extension, + category, + year_published, + message, + sameness, + diversity, + gender, + who + ) - book = Book(title, filename, cover, file_extension, category, year_published, message, sameness, diversity, gender, who) db.session.add(book) + for author in authors: author_name = author.get("author_name") if author_name: - a = db.session.query(Author).filter_by(author_name=author_name).first() - if a == None: + a = ( + db.session.query(Author) + .filter_by(author_name=author_name) + .first() + ) + if a is None: a = Author(author_name=author_name) db.session.add(a) book.authors.append(a) i = Instance(request.host, "add") - existing_ip = db.session.query(Instance).filter_by(ip=request.host).first() + existing_ip = ( + db.session + .query(Instance) + .filter_by(ip=request.host) + .first() + ) if existing_ip: i.name = existing_ip.name book.instances.append(i) @@ -413,7 +495,18 @@ def add_book(): return redirect(url_for('show_books')) flash_errors(upload_form) - return render_template('add_book.html', form=upload_form, books_all=books_all, authors_all=authors_all, categories=categories, stacks_all=stacks_all, books_potential=books_potential, earliest=earliest, latest=latest, light=light) + return render_template( + 'add_book.html', + form=upload_form, + books_all=books_all, + authors_all=authors_all, + categories=categories, + stacks_all=stacks_all, + books_potential=books_potential, + earliest=earliest, + latest=latest, + light=light + ) # Flash errors from the form if validation fails @@ -425,15 +518,20 @@ def flash_errors(form): error )) -#Authors +# Authors + @app.route('/authors/<int:id>') def show_author_by_id(id): author = Author.query.get(id) if not author: - abort (404) + abort(404) else: - return render_template('show_author_detail.html', author=author, light=light) + return render_template( + 'show_author_detail.html', + author=author, + light=light + ) @app.route('/authors/<int:id>/edit', methods=['POST', 'GET']) @@ -441,13 +539,15 @@ def show_author_by_id(id): def edit_author_by_id(id): return "Ask the programmer." -##stacks +# Stacks + @app.route('/stacks') def show_stacks(): stacks = db.session.query(Stack).all() return render_template('show_stacks.html', stacks=stacks, light=light) + @app.route('/stacks/add_stack', methods=['POST', 'GET']) @check_light def add_stack(): @@ -465,7 +565,13 @@ def add_stack(): stacks = db.session.query(Stack).all() return redirect(url_for('show_stacks')) flash("%s stack created" % (stack_name)) - return render_template('add_stack.html', stacks=stacks, form=form, light=light) + return render_template( + 'add_stack.html', + stacks=stacks, + form=form, + light=light + ) + @app.route('/stacks/tab/<int:id>', methods=['POST', 'GET']) def show_stack_in_tab(id): @@ -474,15 +580,24 @@ def show_stack_in_tab(id): @app.route('/stacks/<int:id>', methods=['POST', 'GET']) def show_stack_by_id(id, is_tab=False): - stack = Stack.query.get(id) + if not stack: - return render_template('add_stack.html', stacks=stacks, form=form, light=light) + abort(404) + + if not is_tab: + return render_template( + 'show_stack_detail.html', + stack=stack, + light=light + ) else: - if is_tab == False: - return render_template('show_stack_detail.html', stack=stack, light=light) - else: - return render_template('show_stack_detail_tab.html', stack=stack, light=light) + return render_template( + 'show_stack_detail_tab.html', + stack=stack, + light=light + ) + @app.route('/stacks/<int:id>/delete', methods=['POST', 'GET']) @check_light @@ -491,11 +606,15 @@ def remove_stack_by_id(id): db.session.commit() return redirect(url_for('show_stacks')) + @app.route('/stacks/<int:id>/edit', methods=['POST', 'GET']) @check_light def edit_stack_by_id(id): stack = Stack.query.filter_by(id=id).first() - form = EditStackForm(edit_stack_name = stack.stack_name, edit_stack_description = stack.stack_description) + form = EditStackForm( + edit_stack_name=stack.stack_name, + edit_stack_description=stack.stack_description + ) if request.method == 'POST': if form.validate_on_submit(): @@ -505,7 +624,14 @@ def edit_stack_by_id(id): stack.stack_description = stack_description db.session.commit() return redirect(url_for('show_stack_by_id', id=id)) - return render_template('edit_stack_detail.html', stack=stack, form=form, light=light) + + return render_template( + 'edit_stack_detail.html', + stack=stack, + form=form, + light=light + ) + @app.route('/instances', methods=['POST', 'GET']) @check_light @@ -531,15 +657,29 @@ def show_instances(): if i == 1: name = itm - all_instances = db.session.query(Instance).filter_by(name=oldname).all() + all_instances = ( + db.session + .query(Instance) + .filter_by(name=oldname) + .all() + ) + for instance in all_instances: instance.name = name - print(oldname) - print(name) + db.session.commit() - return render_template('show_instances.html', instances=instances, light=light) -@app.route('/stacks/<int:stackid>/remove/<int:bookid>', methods=['POST', 'GET']) + return render_template( + 'show_instances.html', + instances=instances, + light=light + ) + + +@app.route( + '/stacks/<int:stackid>/remove/<int:bookid>', + methods=['POST', 'GET'] +) @check_light def remove_from_stack(bookid, stackid): book = Book.query.get(bookid) @@ -550,11 +690,13 @@ def remove_from_stack(bookid, stackid): db.session.commit() return render_template('show_book_detail.html', book=book, light=light) -## search +# Search + + view = ['1'] -@app.route('/books', methods= ['POST','GET']) +@app.route('/books', methods=['POST', 'GET']) def show_books(): books = db.session.query(Book).order_by(Book.title) search = SearchForm(request.form) @@ -564,64 +706,125 @@ def show_books(): if search.grid.data: viewby = '2' view.append('2') - return render_template ('show_books_grid.html', books=books, form=search, light=light) + return render_template( + 'show_books_grid.html', + books=books, + form=search, + light=light + ) if search.listview.data: viewby = '1' view.append('1') - return render_template ('show_books.html', books=books, form=search, light=light) + return render_template( + 'show_books.html', + books=books, + form=search, + light=light + ) if request.method == 'POST': newmsg = 'searched for: ' + search.search.data socketio.emit('channel-' + str(1), { - 'username': 'Search form', - 'text': search.search.data, - 'time': str(datetime.datetime.now().strftime("%d.%m.%Y %H:%M"))}, broadcast=True) - # Save message + 'username': 'Search form', + 'text': search.search.data, + 'time': str(datetime.datetime.now().strftime("%d.%m.%Y %H:%M")) + }, broadcast=True) + my_new_chat = Chat(message=newmsg) db.session.add(my_new_chat) + try: db.session.commit() - except: + except Exception: db.session.rollback() - return redirect((url_for('search_results', searchtype=search.select.data, query=search.search.data, viewby=viewby))) - return render_template('show_books.html', books=books, form=search, light=light) + return redirect((url_for( + 'search_results', + searchtype=search.select.data, + query=search.search.data, + viewby=viewby + ))) + + return render_template( + 'show_books.html', + books=books, + form=search, + light=light + ) + @app.route('/search/<searchtype>/<viewby>/<query>', methods=['POST', 'GET']) def search_results(searchtype, query, viewby): search = SearchForm(request.form, search=query) - results=Book.query.filter(Book.title.contains(query)).order_by(Book.title) + results = ( + Book.query + .filter(Book.title.contains(query)) + .order_by(Book.title) + ) allbooks = set(Book.query.all()) viewby = view[-1] if searchtype == 'Title': - results=Book.query.filter(Book.title.contains(query)).order_by(Book.title) + results = ( + Book.query + .filter(Book.title.contains(query)) + .order_by(Book.title) + ) if searchtype == 'Category': - results=Book.query.filter(Book.category.contains(query)).order_by(Book.title) - - if searchtype== 'Author': - results=db.session.query(Book).join(Book.authors).filter(Author.author_name.contains(query)).order_by(Book.title) - - if searchtype== 'Stack': - results=db.session.query(Book).join(Book.stacks).filter(Stack.stack_name.contains(query)).order_by(Book.title) - - if searchtype== 'Outliers': - results=Book.query.filter(Book.sameness > 50).order_by(Book.title) - - if searchtype== 'All': - # results=Book.query.whoosh_search(query) - results=Book.query.filter(Book.title.contains(query)) - results=results.union(Book.query.filter(Book.category.contains(query))) - results=results.union(Book.query.filter(Book.year_published.contains(query))) - results=results.union(db.session.query(Book).join(Book.authors).filter(Author.author_name.contains(query))) - results=results.union(db.session.query(Book).join(Book.stacks).filter(Stack.stack_name.contains(query))).order_by(Book.title) + results = ( + Book.query + .filter(Book.category.contains(query)) + .order_by(Book.title) + ) + + if searchtype == 'Author': + results = ( + db.session.query(Book) + .join(Book.authors) + .filter(Author.author_name.contains(query)) + .order_by(Book.title) + ) + + if searchtype == 'Stack': + results = ( + db.session.query(Book) + .join(Book.stacks) + .filter(Stack.stack_name.contains(query)) + .order_by(Book.title) + ) + + if searchtype == 'Outliers': + results = Book.query.filter(Book.sameness > 50).order_by(Book.title) + + if searchtype == 'All': + results = ( + Book.query.filter(Book.title.contains(query)) + .union(Book.query.filter(Book.category.contains(query))) + .union(Book.query.filter(Book.year_published.contains(query))) + .union( + db.session.query(Book) + .join(Book.authors) + .filter(Author.author_name.contains(query)) + ) + .union( + db.session.query(Book) + .join(Book.stacks) + .filter(Stack.stack_name.contains(query)) + ).order_by(Book.title) + ) if results.count() == 0: books = Book.query.filter(Book.file.like('potential.pdf')) - upload_form = UploadForm(title= query, author='') - return render_template('red_link.html', form=upload_form, title=query, books=books, light=light) + upload_form = UploadForm(title=query, author='') + return render_template( + 'red_link.html', + form=upload_form, + title=query, + books=books, + light=light + ) count = results.count() whole = Book.query.count() @@ -631,103 +834,191 @@ def search_results(searchtype, query, viewby): if search.listview.data: view.append('1') - return render_template('results.html', books=results, form=search, query=query, books_all=books_all, searchtype=search.select.data, count = count, whole = whole, percentage = percentage, light=light) + return render_template( + 'results.html', + books=results, + form=search, + query=query, + books_all=books_all, + searchtype=search.select.data, + count=count, + whole=whole, + percentage=percentage, + light=light + ) if search.grid.data: view.append('2') - return render_template('results_grid.html', books=results, form=search, query=query, books_all=books_all, searchtype=search.select.data, count = count, whole = whole, percentage = percentage, light=light) + return render_template( + 'results_grid.html', + books=results, + form=search, + query=query, + books_all=books_all, + searchtype=search.select.data, + count=count, + whole=whole, + percentage=percentage, + light=light + ) if request.method == 'POST': newmsg = 'searched for: ' + search.search.data socketio.emit('channel-' + str(1), { - 'username': 'Search form', - 'text': search.search.data, - 'time': str(datetime.datetime.now().strftime("%d.%m.%Y %H:%M"))}, broadcast=True) - # Save message + 'username': 'Search form', + 'text': search.search.data, + 'time': str(datetime.datetime.now().strftime("%d.%m.%Y %H:%M")) + }, broadcast=True) + my_new_chat = Chat(message=newmsg) db.session.add(my_new_chat) + try: db.session.commit() - except: + except Exception: db.session.rollback() query = search.search.data results = [] + if viewby == '1': - print (view[-1]) - return redirect((url_for('search_results', searchtype=search.select.data, query=search.search.data, viewby=viewby))) + return redirect((url_for( + 'search_results', + searchtype=search.select.data, + query=search.search.data, + viewby=viewby + ))) else: - return redirect((url_for('search_results', searchtype=search.select.data, query=search.search.data, viewby=viewby))) + return redirect((url_for( + 'search_results', + searchtype=search.select.data, + query=search.search.data, + viewby=viewby + ))) if viewby == '2': - return render_template('results_grid.html', form=search, books=results, books_all=books_all, searchtype=search.select.data, query=query, count = count, whole = whole, percentage = percentage, light=light) + return render_template( + 'results_grid.html', + form=search, + books=results, + books_all=books_all, + searchtype=search.select.data, + query=query, + count=count, + whole=whole, + percentage=percentage, + light=light + ) else: - return render_template('results.html', form=search, books=results, books_all=books_all, searchtype=search.select.data, query=query, count = count, whole = whole, percentage = percentage, light=light) + return render_template( + 'results.html', + form=search, + books=results, + books_all=books_all, + searchtype=search.select.data, + query=query, + count=count, + whole=whole, + percentage=percentage, + light=light + ) + autocomplete_suggestions = [] autocomplete.load() + @app.route('/autocomplete_suggestions', methods=['GET', 'POST']) def autocomplete_search(): if request.method == 'GET': - #query = request.form['search'] query = request.args.get('q') query_tokenized = query.split() - #print(query_tokenized) word_1 = query_tokenized[-2] word_2 = query_tokenized[-1] - #print(word_1) - #print(word_2) - autocomplete_output = autocomplete.predict(word_1 , word_2) + autocomplete_output = autocomplete.predict(word_1, word_2) autocomplete_suggestions.clear() for suggestion, score in autocomplete_output: autocomplete_suggestions.append(suggestion) - return Response(json.dumps(autocomplete_suggestions), mimetype='application/json') + return Response( + json.dumps(autocomplete_suggestions), + mimetype='application/json' + ) + @app.route('/search_annot', methods=['POST', 'GET']) def search_annot(): books = db.session.query(Book).all() - name=str(request.args.get('query')) + name = str(request.args.get('query')) annot = get_annotations() - res = get_annot_results(annot,name) - return render_template('results_annot.html', name=name, annot=annot, res=res, books=books) + res = get_annot_results(annot, name) + return render_template( + 'results_annot.html', + name=name, + annot=annot, + res=res, + books=books + ) -## STACKS! +# STACKS! @app.route('/add_to_stack/<int:id>', methods=['GET', 'POST']) @check_light def add_to_stack(id): stacks = db.session.query(Stack).all() add_form = AddtoStackForm(request.form) - add_form.select_stack.choices = [(stack.id, stack.stack_name) for stack in stacks] + add_form.select_stack.choices = [ + (stack.id, stack.stack_name) + for stack in stacks + ] if request.method == 'GET': book = Book.query.get(id) - return render_template('add_to_stacks.html', id=id, stacks=stacks, book=book, add_form=add_form, light=light) + return render_template( + 'add_to_stacks.html', + id=id, + stacks=stacks, + book=book, + add_form=add_form, + light=light + ) else: stack = Stack.query.get(int(add_form.select_stack.data)) book = Book.query.get(id) stack.books.append(book) db.session.commit() - return render_template('show_stack_detail.html', stack=stack, light=light) + return render_template( + 'show_stack_detail.html', + stack=stack, + light=light + ) @app.route('/export/csv', methods=['GET']) @check_light def export_csv(): output = io.StringIO() - #fieldnames = ['title', 'authors', 'file', 'fileformat', 'category', 'year_published', 'description' ] fields = Book.__mapper__.columns fieldnames = [] + for columns in fields: fieldnames.append(columns.name) + i = inspect(Book) + referred_classes = [r.mapper.class_ for r in i.relationships] - referred_classes_tablenames = [r.mapper.class_.__tablename__ for r in i.relationships] - print(fieldnames+referred_classes_tablenames) - csv = DictWriter(output,fieldnames+referred_classes_tablenames) + + referred_classes_tablenames = [ + r.mapper.class_.__tablename__ + for r in i.relationships + ] + + csv = DictWriter( + output, + fieldnames + referred_classes_tablenames + ) + csv.writeheader() for book in Book.query.order_by("title"): row = {} @@ -744,13 +1035,14 @@ def export_csv(): subattr.append(this) row[col.__tablename__] = " | ".join(subattr) csv.writerow(row) - #print(row) + resp = Response(output.getvalue(), mimetype="text/csv") resp.headers["Content-Disposition"] = "attachment;filename=export.csv" + return resp -import codecs -@app.route('/import/csv', methods= ['POST','GET']) + +@app.route('/import/csv', methods=['POST', 'GET']) @check_light def import_csv(): if request.method == 'POST': @@ -760,9 +1052,12 @@ def import_csv(): else: file = request.files['file'] for row in DictReader(codecs.iterdecode(file, 'utf-8')): - numberadded = 0; - book = db.session.query(Book).filter(Book.title==row['title']).first() - #book = Book.query.filter_by(title=row['title']).first() + numberadded = 0 + book = ( + db.session.query(Book) + .filter(Book.title == row['title']) + .first() + ) if book: print("allreadyexists") else: @@ -776,26 +1071,39 @@ def import_csv(): db.session.add(pbook) db.session.commit() pbooks = Potential.query.all() - template = 'app/templates/potential_pdf.html' - html_string = render_template('potential_pdf.html', pbooks = pbooks) + html_string = render_template( + 'potential_pdf.html', + pbooks=pbooks + ) html = HTML(string=html_string) html.write_pdf(target='app/uploads/potential.pdf') else: - fullpath = os.path.join(app.config['UPLOAD_FOLDER'], row['file']) + fullpath = os.path.join( + app.config['UPLOAD_FOLDER'], row['file'] + ) name, file_extension = os.path.splitext(row['file']) - print ('get_cover', fullpath, name) + try: cover = get_cover(fullpath, name) - except: + except Exception: print("couldn't get cover") + file = row['file'] if row['year_published']: year_published = int(row['year_published']) else: - year_published = None; - book = Book(row['title'], file, cover, row['fileformat'], row['category'],year_published, None, None, None, None, None) + year_published = None + book = Book( + row['title'], + file, + cover, + row['fileformat'], + row['category'], + year_published, + None, None, None, None, None + ) if row['scapeX']: book.scapeX = float(row['scapeX']) if row['scapeY']: @@ -807,21 +1115,31 @@ def import_csv(): authors = [x.strip() for x in authors] for author in authors: if author: - a = db.session.query(Author).filter_by(author_name=author).first() - if a == None: + a = ( + db.session.query(Author) + .filter_by(author_name=author) + .first() + ) + if a is None: a = Author(author_name=author) db.session.add(a) book.authors.append(a) db.session.commit() - return render_template('import_csv.html', numberadded=numberadded, light=light) + return render_template( + 'import_csv.html', + numberadded=numberadded, + light=light + ) -@app.route('/emptycataloguexpubxpubfuck', methods= ['POST','GET']) +@app.route('/emptycataloguexpubxpubfuck', methods=['POST', 'GET']) @check_light def empty_catalogue(): meta = db.metadata for table in reversed(meta.sorted_tables): - if str(table) == "books" or str(table) == "authors" or str(table) == "books_authors": + if (str(table) == "books" + or str(table) == "authors" + or str(table) == "books_authors"): print('Clear table %s' % table) db.session.execute(table.delete()) db.create_all() @@ -832,13 +1150,14 @@ def empty_catalogue(): # The API ### + @app.route('/api/books', methods=['GET']) def get_books(): books = Book.query.all() data = books_schema.dump(books) - #print(errors) return jsonify({'books': data}) + @app.route('/api/books/<int:id>', methods=['GET']) def get_book_by_id(id): book = Book.query.get(id) @@ -846,22 +1165,20 @@ def get_book_by_id(id): if not data: return jsonify({"message": "Book could not be found."}), 400 else: - return jsonify({'book': data }) + return jsonify({'book': data}) + @app.route('/api/chats', methods=['GET']) def get_chat(): chats = Chat.query.all() data = chats_schema.dump(chats) - #print(errors) return jsonify({'chat': data}) - ### # The functions below should be applicable to all Flask apps. ### - @app.after_request def add_header(response): """ @@ -879,32 +1196,23 @@ def page_not_found(error): return render_template('404.html', light=light), 404 -### SOCKET for the chat +# SOCKET for the chat @socketio.on('new_message') def new_message(message): - # Send message to all users - # print("new message") - # channel is always 1 now, but might be interesting for further development emit('channel-' + str(message['channel']), { 'username': message['username'], 'text': message['text'], 'time': str(datetime.datetime.now().strftime("%d.%m.%Y %H:%M")) - }, - broadcast=True - ) - # Save message - my_new_chat = Chat( - message=message['text'] - ) + }, broadcast=True) + my_new_chat = Chat(message=message['text']) db.session.add(my_new_chat) try: db.session.commit() - except: + except Exception: db.session.rollback() if __name__ == '__main__': - # socketio.run(app) - app.run(debug=True,host="0.0.0.0",port="8080") + app.run(debug=True, host='0.0.0.0', port='8080')