Setup application factory and dev/prod files.

Also some style fixes in there.
This commit is contained in:
Luke Murphy 2018-11-18 11:13:56 +01:00
parent 2399a25ce9
commit b20e880db3
No known key found for this signature in database
GPG Key ID: 5E2EF5A63E3718CC
11 changed files with 176 additions and 84 deletions

8
dev.py Normal file
View File

@ -0,0 +1,8 @@
"""Expose a development application."""
from xppl.app import create_app
from xppl.socketio import socketio
app = create_app('xppl.config.Development')
socketio.run(app)

3
run.py
View File

@ -1,3 +0,0 @@
from xppl import app, socketio
socketio.run(app, host='0.0.0.0', port=8080)

5
wsgi.py Normal file
View File

@ -0,0 +1,5 @@
"""Expose a production application."""
from xppl.app import create_app
app = create_app('xppl.config.Production')

View File

@ -1,37 +0,0 @@
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 sqlalchemy.dialects import registry
registry.register(
'rqlite.pyrqlite',
'sqlalchemy_rqlite.pyrqlite',
'dialect'
)
BASEDIR = os.path.abspath(os.path.dirname(__file__))
UPLOAD_FOLDER = os.path.join(BASEDIR, 'uploads')
UPLOAD_FOLDER_COVER = os.path.join(BASEDIR, 'cover')
load_dotenv(find_dotenv())
app = Flask(__name__)
app.config['SECRET_KEY'] = 'super secret key'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['SQLALCHEMY_DATABASE_URI'] = 'rqlite+pyrqlite://localhost:4001/'
app.config['DEBUG'] = True
app.config['PORT'] = 80
db = SQLAlchemy(app)
light = not os.path.isdir(UPLOAD_FOLDER)
DOMAIN = environ.get('DOMAIN')
socketio = SocketIO(app)
app.config.from_object(__name__)
from xppl import views # noqa

57
xppl/app.py Normal file
View File

@ -0,0 +1,57 @@
"""Main application factory."""
from dotenv import find_dotenv, load_dotenv
from flask import Flask
from sqlalchemy.dialects import registry
def create_app(config):
app = Flask(__name__.split('.')[0])
app.config.from_object(config)
configure_dotenv()
configure_pyrqlite()
configure_socketio(app)
configure_sqlalchemy(app)
with app.app_context():
from xppl import views # noqa
return app
def configure_pyrqlite():
"""Configure PyRQLite."""
registry.register(
'rqlite.pyrqlite',
'sqlalchemy_rqlite.pyrqlite',
'dialect'
)
def configure_dotenv():
"""Configure the environment."""
load_dotenv(find_dotenv())
def configure_sqlalchemy(app):
"""Configure SQLAlchemy."""
from xppl.database import db
from xppl.models import ( # noqa
Book, Author, Instance,
Potential, UserIns, Chat,
Stack,
)
db.init_app(app)
with app.app_context():
db.create_all()
def configure_socketio(app):
"""Configure SocketIO."""
from xppl.socketio import socketio
socketio.init_app(app)

32
xppl/config.py Normal file
View File

@ -0,0 +1,32 @@
"""The Application settings."""
from os.path import abspath, dirname, isdir, join
class Base():
"""The base configuration."""
BASEDIR = abspath(dirname(__file__))
UPLOAD_FOLDER_COVER = join(BASEDIR, 'cover')
UPLOAD_FOLDER = join(BASEDIR, 'uploads')
LIGHT = isdir(UPLOAD_FOLDER)
DEBUG = False
TESTING = False
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_DATABASE_URI = 'rqlite+pyrqlite://localhost:4001/'
class Production(Base):
"""The production configuration."""
ENV = 'production'
DOMAIN = 'https://book.vvvvvvaria.org'
class Development(Base):
"""The development configuration."""
ENV = 'development'
DEBUG = True
TESTING = True
DOMAIN = 'http://localhost'

5
xppl/database.py Normal file
View File

@ -0,0 +1,5 @@
"""Database initialisation."""
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()

View File

@ -1,4 +1,3 @@
from xppl.models import Author
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from wtforms import FieldList, FileField from wtforms import FieldList, FileField
from wtforms import Form as NoCsrfForm from wtforms import Form as NoCsrfForm
@ -6,6 +5,7 @@ from wtforms import validators
from wtforms.fields import FormField, SelectField, StringField, SubmitField from wtforms.fields import FormField, SelectField, StringField, SubmitField
from wtforms.fields.html5 import DecimalRangeField from wtforms.fields.html5 import DecimalRangeField
from wtforms.validators import DataRequired, InputRequired from wtforms.validators import DataRequired, InputRequired
from xppl.models import Author
# - - - Forms - - - # - - - Forms - - -

View File

@ -1,8 +1,8 @@
import datetime import datetime
from xppl import db
from marshmallow import Schema, ValidationError, fields from marshmallow import Schema, ValidationError, fields
from sqlalchemy import Column, DateTime from sqlalchemy import Column, DateTime
from xppl.database import db
authors = db.Table( authors = db.Table(

5
xppl/socketio.py Normal file
View File

@ -0,0 +1,5 @@
"""SocketIO initialisation."""
from flask_socketio import SocketIO
socketio = SocketIO()

View File

@ -8,7 +8,8 @@ from functools import wraps
from urllib.parse import quote as urlquote from urllib.parse import quote as urlquote
import autocomplete import autocomplete
from xppl import DOMAIN, app, db, light, socketio from xppl.database import db
from xppl.socketio import socketio
from xppl.cover import get_cover from xppl.cover import get_cover
from xppl.extractText import extract_text from xppl.extractText import extract_text
from xppl.forms import ( from xppl.forms import (
@ -24,7 +25,7 @@ from xppl.models import (
from flask import ( from flask import (
Response, abort, flash, jsonify, redirect, Response, abort, flash, jsonify, redirect,
render_template, request, send_from_directory, render_template, request, send_from_directory,
url_for url_for, current_app as app
) )
from flask_socketio import emit from flask_socketio import emit
from flask_weasyprint import HTML, render_pdf from flask_weasyprint import HTML, render_pdf
@ -32,7 +33,6 @@ from sqlalchemy.inspection import inspect
from sqlalchemy.sql.expression import func from sqlalchemy.sql.expression import func
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
# import sqlite3
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'epub', 'chm', 'mobi']) ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'epub', 'chm', 'mobi'])
author_schema = AuthorSchema() author_schema = AuthorSchema()
@ -46,8 +46,9 @@ chats_schema = ChatSchema(many=True)
def allowed_file(filename): def allowed_file(filename):
return '.' in filename and \ extension = filename.rsplit('.', 1)[1].lower()
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS return '.' in filename and extension in ALLOWED_EXTENSIONS
### ###
# Routing for your application. # Routing for your application.
### ###
@ -56,7 +57,7 @@ def allowed_file(filename):
def check_light(func): def check_light(func):
@wraps(func) @wraps(func)
def decorated_function(*args, **kwargs): def decorated_function(*args, **kwargs):
if not light: if not app.config['LIGHT']:
return func(*args, **kwargs) return func(*args, **kwargs)
else: else:
flash("Your account has expired. Update your billing info.") flash("Your account has expired. Update your billing info.")
@ -67,8 +68,6 @@ def check_light(func):
@app.route('/', methods=['POST', 'GET']) @app.route('/', methods=['POST', 'GET'])
def home(): def home():
print("/////////////")
print(light)
chat_messages = db.session.query(Chat).all() chat_messages = db.session.query(Chat).all()
username = 'librarian' username = 'librarian'
server = request.host server = request.host
@ -79,13 +78,13 @@ def home():
return render_template( return render_template(
'home.html', 'home.html',
domain=DOMAIN, domain=app.config['DOMAIN'],
chat=chat_messages, chat=chat_messages,
channel=1, channel=1,
username=username, username=username,
client=client, client=client,
server=server, server=server,
light=light light=app.config['LIGHT'],
) )
@ -97,7 +96,7 @@ def hello(name):
@app.route('/about/') @app.route('/about/')
def about(): def about():
"""Render the website's about page.""" """Render the website's about page."""
return render_template('about.html', light=light) return render_template('about.html', light=app.config['LIGHT'])
@app.route('/uploads/<filename>') @app.route('/uploads/<filename>')
@ -124,7 +123,7 @@ def annotations():
'annotations.html', 'annotations.html',
annot=annot, annot=annot,
books=books, books=books,
light=light light=app.config['LIGHT']
) )
@ -133,7 +132,11 @@ def annotations():
def annotations_pdf(): def annotations_pdf():
annot = get_annotations() annot = get_annotations()
# Make a PDF straight from HTML in a string. # Make a PDF straight from HTML in a string.
html = render_template(('annotations.html'), annot=annot, light=light) html = render_template(
'annotations.html',
annot=annot,
light=app.config['LIGHT'],
)
return render_pdf(HTML(string=html)) return render_pdf(HTML(string=html))
@ -179,7 +182,6 @@ def scape():
if request.method == 'POST': if request.method == 'POST':
data = request.form data = request.form
book = Book.query.get(data['id']) book = Book.query.get(data['id'])
print(book.scapeX)
book.scapeX = data['x'] book.scapeX = data['x']
book.scapeY = data['y'] book.scapeY = data['y']
db.session.commit() db.session.commit()
@ -207,7 +209,11 @@ def scape_new():
@app.route('/books_grid') @app.route('/books_grid')
def show_books_grid(): def show_books_grid():
books = db.session.query(Book).all() books = db.session.query(Book).all()
return render_template('show_books_grid.html', books=books, light=light) return render_template(
'show_books_grid.html',
books=books,
light=app.config['LIGHT']
)
@app.route('/books/<int:id>') @app.route('/books/<int:id>')
@ -236,7 +242,11 @@ def show_book_by_id(id):
db.session.add(user_info) db.session.add(user_info)
db.session.commit() db.session.commit()
if not book: if not book:
return render_template('red_link.html', id=id, light=light) return render_template(
'red_link.html',
id=id,
light=app.config['LIGHT']
)
else: else:
return render_template( return render_template(
'show_book_detail.html', 'show_book_detail.html',
@ -247,7 +257,7 @@ def show_book_by_id(id):
name=name, name=name,
annot=annot, annot=annot,
res=res, res=res,
light=light light=app.config['LIGHT']
) )
@ -359,7 +369,7 @@ def edit_book_by_id(id):
'edit_book_detail.html', 'edit_book_detail.html',
book=book_to_edit, book=book_to_edit,
form=user_form, form=user_form,
light=light light=app.config['LIGHT']
) )
@ -505,7 +515,7 @@ def add_book():
books_potential=books_potential, books_potential=books_potential,
earliest=earliest, earliest=earliest,
latest=latest, latest=latest,
light=light light=app.config['LIGHT']
) )
@ -530,7 +540,7 @@ def show_author_by_id(id):
return render_template( return render_template(
'show_author_detail.html', 'show_author_detail.html',
author=author, author=author,
light=light light=app.config['LIGHT']
) )
@ -545,7 +555,11 @@ def edit_author_by_id(id):
@app.route('/stacks') @app.route('/stacks')
def show_stacks(): def show_stacks():
stacks = db.session.query(Stack).all() stacks = db.session.query(Stack).all()
return render_template('show_stacks.html', stacks=stacks, light=light) return render_template(
'show_stacks.html',
stacks=stacks,
light=app.config['LIGHT']
)
@app.route('/stacks/add_stack', methods=['POST', 'GET']) @app.route('/stacks/add_stack', methods=['POST', 'GET'])
@ -569,7 +583,7 @@ def add_stack():
'add_stack.html', 'add_stack.html',
stacks=stacks, stacks=stacks,
form=form, form=form,
light=light light=app.config['LIGHT']
) )
@ -589,13 +603,13 @@ def show_stack_by_id(id, is_tab=False):
return render_template( return render_template(
'show_stack_detail.html', 'show_stack_detail.html',
stack=stack, stack=stack,
light=light light=app.config['LIGHT']
) )
else: else:
return render_template( return render_template(
'show_stack_detail_tab.html', 'show_stack_detail_tab.html',
stack=stack, stack=stack,
light=light light=app.config['LIGHT']
) )
@ -629,7 +643,7 @@ def edit_stack_by_id(id):
'edit_stack_detail.html', 'edit_stack_detail.html',
stack=stack, stack=stack,
form=form, form=form,
light=light light=app.config['LIGHT']
) )
@ -672,7 +686,7 @@ def show_instances():
return render_template( return render_template(
'show_instances.html', 'show_instances.html',
instances=instances, instances=instances,
light=light light=app.config['LIGHT']
) )
@ -685,10 +699,18 @@ def remove_from_stack(bookid, stackid):
book = Book.query.get(bookid) book = Book.query.get(bookid)
stack = Stack.query.get(stackid) stack = Stack.query.get(stackid)
if book not in stack.books: if book not in stack.books:
return render_template('show_book_detail.html', book=book, light=light) return render_template(
'show_book_detail.html',
book=book,
light=app.config['LIGHT']
)
stack.books.remove(book) stack.books.remove(book)
db.session.commit() db.session.commit()
return render_template('show_book_detail.html', book=book, light=light) return render_template(
'show_book_detail.html',
book=book,
light=app.config['LIGHT']
)
# Search # Search
@ -710,7 +732,7 @@ def show_books():
'show_books_grid.html', 'show_books_grid.html',
books=books, books=books,
form=search, form=search,
light=light light=app.config['LIGHT']
) )
if search.listview.data: if search.listview.data:
@ -720,7 +742,7 @@ def show_books():
'show_books.html', 'show_books.html',
books=books, books=books,
form=search, form=search,
light=light light=app.config['LIGHT']
) )
if request.method == 'POST': if request.method == 'POST':
@ -750,7 +772,7 @@ def show_books():
'show_books.html', 'show_books.html',
books=books, books=books,
form=search, form=search,
light=light light=app.config['LIGHT']
) )
@ -823,7 +845,7 @@ def search_results(searchtype, query, viewby):
form=upload_form, form=upload_form,
title=query, title=query,
books=books, books=books,
light=light light=app.config['LIGHT']
) )
count = results.count() count = results.count()
@ -844,7 +866,7 @@ def search_results(searchtype, query, viewby):
count=count, count=count,
whole=whole, whole=whole,
percentage=percentage, percentage=percentage,
light=light light=app.config['LIGHT']
) )
if search.grid.data: if search.grid.data:
@ -859,7 +881,7 @@ def search_results(searchtype, query, viewby):
count=count, count=count,
whole=whole, whole=whole,
percentage=percentage, percentage=percentage,
light=light light=app.config['LIGHT']
) )
if request.method == 'POST': if request.method == 'POST':
@ -907,7 +929,7 @@ def search_results(searchtype, query, viewby):
count=count, count=count,
whole=whole, whole=whole,
percentage=percentage, percentage=percentage,
light=light light=app.config['LIGHT']
) )
else: else:
@ -921,7 +943,7 @@ def search_results(searchtype, query, viewby):
count=count, count=count,
whole=whole, whole=whole,
percentage=percentage, percentage=percentage,
light=light light=app.config['LIGHT']
) )
@ -981,7 +1003,7 @@ def add_to_stack(id):
stacks=stacks, stacks=stacks,
book=book, book=book,
add_form=add_form, add_form=add_form,
light=light light=app.config['LIGHT']
) )
else: else:
stack = Stack.query.get(int(add_form.select_stack.data)) stack = Stack.query.get(int(add_form.select_stack.data))
@ -991,7 +1013,7 @@ def add_to_stack(id):
return render_template( return render_template(
'show_stack_detail.html', 'show_stack_detail.html',
stack=stack, stack=stack,
light=light light=app.config['LIGHT']
) )
@ -1023,7 +1045,6 @@ def export_csv():
for book in Book.query.order_by("title"): for book in Book.query.order_by("title"):
row = {} row = {}
for col in fieldnames: for col in fieldnames:
print(getattr(book, col))
row[col] = getattr(book, col) row[col] = getattr(book, col)
for col in referred_classes: for col in referred_classes:
subattr = [] subattr = []
@ -1128,7 +1149,7 @@ def import_csv():
return render_template( return render_template(
'import_csv.html', 'import_csv.html',
numberadded=numberadded, numberadded=numberadded,
light=light light=app.config['LIGHT']
) )
@ -1140,7 +1161,6 @@ def empty_catalogue():
if (str(table) == "books" if (str(table) == "books"
or str(table) == "authors" or str(table) == "authors"
or str(table) == "books_authors"): or str(table) == "books_authors"):
print('Clear table %s' % table)
db.session.execute(table.delete()) db.session.execute(table.delete())
db.create_all() db.create_all()
db.session.commit() db.session.commit()
@ -1193,7 +1213,7 @@ def add_header(response):
@app.errorhandler(404) @app.errorhandler(404)
def page_not_found(error): def page_not_found(error):
"""Custom 404 page.""" """Custom 404 page."""
return render_template('404.html', light=light), 404 return render_template('404.html', light=app.config['LIGHT']), 404
# SOCKET for the chat # SOCKET for the chat