Remove unused modules.

This commit is contained in:
2019-10-17 21:17:02 +02:00
parent ad3b216a0d
commit 632741ba46
18 changed files with 49 additions and 690 deletions

2
.gitignore vendored
View File

@@ -95,3 +95,5 @@ Screenshots/
typesheds/
*.db
*.env
estusshots/config/production.py

View File

@@ -1,31 +1,23 @@
import os
import logging
import sys
from flask import Flask
from flask_bootstrap import Bootstrap
from estusshots.config import config
def create_app():
app = Flask(__name__)
Bootstrap(app)
return app
if not config.SECRET_KEY:
logging.error(
"No secret key provided for app. Are the environment variables set correctly?"
)
sys.exit(1)
app = create_app()
app.config.from_pyfile("config/default.py")
config_path = f"config/{app.env}.py"
app.config.from_pyfile(config_path, silent=True)
logging.basicConfig(filename=config.LOG_PATH, level=logging.DEBUG)
logging.basicConfig(filename=app.config.get("LOG_PATH"), level=logging.DEBUG)
logging.info(f"Starting in working dir: {os.getcwd()}")
app.config.from_object(config)
import estusshots.views.drinks
import estusshots.views.enemies

View File

@@ -1,6 +0,0 @@
[Default]
ES_READ_PW = 123
ES_WRITE_PW = 1234
ES_SECRET_KEY = 1234
ES_DATABASE_PATH = ../databases/debug.db
ES_LOG_PATH = ../logs/debug.log

View File

@@ -1,16 +0,0 @@
from configparser import ConfigParser
class Config:
def __init__(self):
parser = ConfigParser()
parser.read("config.ini")
self.SECRET_KEY = parser.get("Default", "ES_SECRET_KEY")
self.WRITE_PW = parser.get("Default", "ES_WRITE_PW")
self.READ_PW = parser.get("Default", "ES_READ_PW")
self.DATABASE_PATH = parser.get("Default", "ES_DATABASE_PATH")
self.LOG_PATH = parser.get("Default", "ES_LOG_PATH")
config = Config()

View File

View File

@@ -0,0 +1,6 @@
READ_PW = None
WRITE_PW = None
SECRET_KEY = None
DATABASE_PATH = None
LOG_PATH = None

View File

@@ -0,0 +1,5 @@
READ_PW = "123"
WRITE_PW = "1234"
SECRET_KEY = "1234"
DATABASE_PATH = "../databases/test.db"
LOG_PATH = "../logs/debug.log"

View File

@@ -1,306 +0,0 @@
import sqlite3
import logging as log
from typing import Sequence
from flask import g
from estusshots import models
from estusshots.config import config
class DataBaseError(Exception):
"""General exception class for SQL errors"""
def connect_db():
"""Create a new sqlite3 connection and register it in 'g._database'"""
db = getattr(g, "_database", None)
if db is None:
log.info(f"Connecting {config.DATABASE_PATH}")
db = g._database = sqlite3.connect(config.DATABASE_PATH)
db.row_factory = sqlite3.Row
return db
def query_db(query, args=(), one=False, cls=None):
"""Runs an SQL query on an new database connection, returning the fetched rv"""
log.debug(f"Running query ({query}) with arguments ({args})")
cur = connect_db().execute(query, args)
rv = cur.fetchall()
cur.close()
if cls:
rv = [cls(**row) for row in rv]
return (rv[0] if rv else None) if one else rv
def update_db(query, args=(), return_key: bool = False):
"""
Runs an changing query on the database
Returns either False if no error has occurred, or an sqlite3 Exception
:param query: An SQL query string
:param args: Tuple for inserting into a row
:param return_key: Changes return behavior of the function:
If used function will return last row id.
Exceptions will be raised instead of returned.
"""
log.debug(f"Running query ({query}) with arguments ({args})")
with connect_db() as con:
cur = con.cursor()
multi_args = any(isinstance(i, tuple) for i in args)
try:
if multi_args:
cur.executemany(query, args)
else:
cur.execute(query, args)
except sqlite3.Error as err:
if not return_key:
return err
raise
else:
con.commit()
return cur.lastrowid if return_key else False
def init_db():
"""Initialize the database from the 'schema.sql' script file"""
file_name = "schema.sql"
print(f'Creating database from file: "{file_name}"')
with connect_db() as conn:
with open(file_name, "r") as f:
try:
conn.cursor().executescript(f.read())
except sqlite3.OperationalError as err:
log.error(f"Cannot create database: {err}")
conn.commit()
def save_player_query(player):
if not player.id:
sql = "insert into player values (?, ?, ?, ?, ?)"
args = (None, player.real_name, player.alias, player.hex_id, player.anon)
else:
sql = (
"update player " "set real_name=?, alias=?, hex_id=?, anon=? " "where id==?"
)
args = (player.real_name, player.alias, player.hex_id, player.anon, player.id)
return sql, args
def save_player(player):
sql, args = save_player_query(player)
return update_db(sql, args)
def load_players(id=None):
sql = "select * from player"
args = ()
if id:
sql += " where player.id = ?"
args = (id,)
sql += " order by player.id"
return sql, args
def load_drinks(id=None):
sql = "select * from drink"
args = ()
if id:
sql += " where drink.id = ?"
args = (id,)
sql += " order by drink.id"
return sql, args
def save_drink_query(drink):
if not drink.id:
sql = "insert into drink values (?, ?, ?)"
args = (None, drink.name, drink.vol)
else:
sql = "update drink " \
"set name=?, vol=? " \
"where id==?"
args = (drink.name, drink.vol, drink.id)
return sql, args
def save_drink(drink):
sql, args = save_drink_query(drink)
return update_db(sql, args)
def load_enemies(id=None):
sql = "select * from enemy"
args = ()
if id:
sql += " where enemy.id = ?"
args = (id,)
sql += " order by enemy.id"
return sql, args
def load_enemies_for_season(season_id: int):
sql = "select * from enemy " \
"where season_id = ? or season_id = 'None'" \
"order by enemy.id"
args = (season_id, )
return sql, args
def save_enemy(enemy: models.Enemy):
if not enemy.id:
sql = "insert into enemy values (?, ?, ?, ?)"
args = (None, enemy.name, enemy.boss, enemy.season_id)
else:
sql = "update enemy " \
"set name=?, boss=?, season_id=? " \
"where id==?"
args = (enemy.name, enemy.boss, enemy.season_id, enemy.id)
return sql, args
def save_season_query(season: models.Season):
if not season.id:
sql = "insert into season values (?, ?, ?, ?, ?, ?)"
args = (
None,
season.game,
season.description,
season.start,
season.end,
season.code,
)
else:
sql = (
"update season "
"set game=?, description=?, start=?, end=?, code=? "
"where id==?"
)
args = (
season.game,
season.description,
season.start,
season.end,
season.code,
season.id,
)
return sql, args
def load_season(id=None):
sql = "select * from season"
args = ()
if id:
sql += " where season.id = ?"
args = (id,)
sql += " order by season.code"
return sql, args
def load_episode(episode_id: int = None):
sql = "select * from episode"
args = ()
if episode_id:
sql += " where episode.id = ?"
args = (episode_id,)
sql += " order by episode.code"
return sql, args
def load_episodes(season_id: int = None):
sql = "select * from episode"
args = ()
if season_id:
sql += " where episode.season_id = ?"
args = (season_id,)
sql += " order by episode.code"
return sql, args
def load_episode_player_links(episode_id: int):
sql = "select * from episode_player where episode_id = ?"
args = (episode_id,)
return sql, args
def load_episode_players(episode_id: int):
sql = (
"select player.* "
"from player "
"left join episode_player ep on player.id = ep.player_id "
"where ep.episode_id = ?"
)
args = (episode_id,)
return sql, args
def save_episode_players(episode_id: int, player_ids: Sequence[int]):
sql = "insert into episode_player values (?, ?, ?)"
args = tuple((None, episode_id, i) for i in player_ids)
return sql, args
def remove_episode_player(episode_id: int, player_ids: Sequence[int]):
sql = "delete from episode_player " "where episode_id = ? and player_id = ?"
args = tuple((episode_id, pid) for pid in player_ids)
return sql, args
def save_episode(episode: models.Episode):
if not episode.id:
sql = "insert into episode values (?, ?, ?, ?, ?, ?, ?)"
args = (
None,
episode.season_id,
episode.title,
episode.date,
episode.start.timestamp(),
episode.end.timestamp(),
episode.code,
)
else:
sql = (
"update episode "
"set season_id=?, title=?, date=?, start=?, end=?, code=?"
"where id==?"
)
args = (
episode.season_id,
episode.title,
episode.date,
episode.start.timestamp(),
episode.end.timestamp(),
episode.code,
episode.id,
)
return sql, args
def save_event(event: models.Event):
args = [
None,
event.episode_id,
event.player_id,
event.enemy_id,
event.type.name,
event.time.timestamp(),
event.comment,
]
if not event.event_id:
sql = "insert into event values (?, ?, ?, ?, ?, ?, ?)"
else:
sql = (
"where id==? "
"update event "
"set episode_id=?, player_id=?, enemy_id=?, type=?, time=?, comment=?"
)
args[0] = event.event_id
return sql, args
def load_events(episode_id: int):
sql = "select * from event where episode_id = ?"
args = (episode_id,)
return sql, args

View File

@@ -1,3 +1,6 @@
from typing import Dict, List
from dataclasses import dataclass
from flask_wtf import FlaskForm
from wtforms import (
DateField,
@@ -17,6 +20,13 @@ from wtforms.validators import DataRequired, Optional
from estusshots import choices
@dataclass
class GenericFormModel:
page_title: str
form_title: str
post_url: str
errors: Dict[str, List[str]] = None
class SeasonForm(FlaskForm):
season_id = HiddenField("Season ID", render_kw={"readonly": True})
code = StringField("Season Code", validators=[DataRequired()])

View File

@@ -1,189 +0,0 @@
import datetime
import enum
from numbers import Rational
from typing import Dict, List, Union, Optional
from dataclasses import dataclass
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from estusshots import forms, util
class EventType(enum.Enum):
Pause = 0
Death = 1
Victory = 2
@dataclass
class GenericFormModel:
page_title: str
form_title: str
post_url: str
errors: Dict[str, List[str]] = None
@dataclass
class Player:
id: int
real_name: str
alias: str
hex_id: str
anon: bool = False
@property
def name(self) -> str:
return self.real_name if self.real_name and not self.anon else self.alias
@classmethod
def from_form(cls, form: "forms.PlayerForm"):
id = int(form.player_id.data) if form.player_id.data else None
real_name = str(form.real_name.data) if form.real_name.data else None
alias = str(form.alias.data)
hex_id = str(form.hex_id.data) if form.hex_id.data else None
anon = bool(form.anonymize.data)
return cls(id=id, real_name=real_name, alias=alias, hex_id=hex_id, anon=anon)
@dataclass
class Drink:
id: int
name: str
vol: float
@classmethod
def from_form(cls, form: "forms.DrinkForm"):
id = int(form.drink_id.data) if form.drink_id.data else None
name = str(form.name.data)
vol = float(form.vol.data)
self = cls(id=id, name=name, vol=vol)
return self
@dataclass
class Enemy:
id: int
name: str
boss: bool
season_id: int
@classmethod
def from_form(cls, form: "forms.EnemyForm"):
id = int(form.enemy_id.data) if form.enemy_id.data else None
name = str(form.name.data)
boss = bool(form.is_boss.data)
season = int(form.season_id.data)
self = cls(id=id, name=name, boss=boss, season_id=season)
return self
@dataclass
class Season:
id: int
game: str
description: str
start: datetime.date
end: datetime.date
code: str
def __post_init__(self):
try:
self.start = datetime.datetime.strptime(self.start, "%Y-%m-%d").date()
except Exception:
pass
try:
self.end = datetime.datetime.strptime(self.end, "%Y-%m-%d").date()
except Exception:
pass
@classmethod
def from_form(cls, form: "forms.SeasonForm"):
season_id = int(form.season_id.data) if form.season_id.data else None
code = str(form.code.data)
game = str(form.game_name.data)
description = str(form.description.data) if form.description.data else None
start = form.start.data
end = form.end.data
self = cls(season_id, game, description, start, end, code)
return self
@dataclass
class Episode:
id: int
season_id: int
title: str
date: Union[datetime.date, Rational]
start: Union[datetime.datetime, Rational]
end: Union[datetime.datetime, Rational]
code: str
@property
def playtime(self):
return self.end - self.start
def __post_init__(self):
if isinstance(self.date, str):
self.date = datetime.datetime.strptime(self.date, util.DATE_FMT).date()
if isinstance(self.start, Rational):
self.start = datetime.datetime.fromtimestamp(self.start)
if isinstance(self.end, Rational):
self.end = datetime.datetime.fromtimestamp(self.end)
@classmethod
def from_form(cls, form: "forms.EpisodeForm"):
episode_id = int(form.episode_id.data) if form.episode_id.data else None
season_id = int(form.season_id.data)
code = str(form.code.data)
title = str(form.title.data)
date = form.date.data
start = util.combine_datetime(date, form.start.data)
end = util.combine_datetime(date, form.end.data)
if end < start:
end = end + datetime.timedelta(days=1)
return cls(episode_id, season_id, title, date, start, end, code)
@dataclass
class Penalty:
penalty_id: int
player_id: int
drink_id: int
@dataclass
class Event:
event_id: int
episode_id: int
type: EventType
time: datetime.datetime
comment: str
player_id: Optional[int]
enemy_id: Optional[int]
penalties: List[Penalty]
@classmethod
def from_form(cls, form: "forms.EventForm"):
event_id = int(form.event_id.data) if form.event_id.data else None
episode_id = int(form.episode_id.data)
event_type = EventType(form.event_type.data)
time = util.combine_datetime(datetime.datetime.today(), form.time.data)
comment = str(form.comment.data) if form.comment.data else None
player_id = int(form.player.data) if form.player.data else None
enemy_id = int(form.enemy.data) if form.enemy.data else None
penalties = []
for entry in form.penalties:
penalties.append(Penalty(
penalty_id=int(entry.penalty_id.data) if entry.penalty_id.data else None,
player_id=int(entry.player_id.data),
drink_id=int(entry.drink.data)
))
return cls(event_id, episode_id, event_type, time, comment, player_id, enemy_id,
penalties)

View File

@@ -7,9 +7,10 @@ from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, Boolean, Float, Enum, Date, Time
from sqlalchemy.orm import sessionmaker, relationship
from estusshots import util, forms
from estusshots import util, forms, app
engine = create_engine('sqlite:///../databases/test.db')
connection = f"sqlite:///{app.config.get('DATABASE_PATH')}"
engine = create_engine(connection)
Base = declarative_base()
player_episode = Table(

View File

@@ -1,133 +0,0 @@
create table if not exists season
(
id integer not null
constraint season_pk
primary key autoincrement,
game text,
description text,
start text,
end text,
code text not null
);
create unique index if not exists season_id_uindex
on season (id);
create table if not exists player
(
id integer not null
constraint player_pk
primary key autoincrement,
real_name text,
alias text not null,
hex_id text,
anon integer not null
);
create unique index if not exists player_id_uindex
on player (id);
create table if not exists drink
(
id integer not null
constraint drink_pk
primary key autoincrement,
name text not null,
vol real not null
);
create unique index if not exists drink_id_uindex
on drink (id);
create table if not exists enemy
(
id integer not null
constraint enemy_pk
primary key autoincrement,
name text not null,
boss integer not null,
season_id integer,
foreign key (season_id) references season(id)
);
create unique index if not exists enemy_id_uindex
on enemy (id);
create table if not exists episode
(
id integer not null
constraint episode_pk
primary key autoincrement,
season_id integer not null
constraint episode_season_id_fk
references season,
title text not null,
date text not null,
start timestamp not null,
end timestamp not null,
code text not null default 'EXX'
);
create unique index if not exists episode_id_uindex
on episode (id);
create table if not exists episode_player
(
link_id integer not null
constraint episode_player_pk
primary key autoincrement,
episode_id integer not null
references episode,
player_id integer not null
references player
);
create table if not exists penalty
(
id integer not null
constraint penalty_pk
primary key autoincrement,
episode_id integer not null
references episode,
drink_id integer not null
references drink
);
create unique index if not exists penalty_id_uindex
on penalty (id);
create table if not exists event
(
id integer not null
constraint event_pk
primary key autoincrement,
episode_id integer not null
constraint event_episode_id_fk
references season,
player_id integer not null
constraint event_player_id_fk
references player,
enemy_id integer
references enemy,
type text not null,
time timestamp not null,
comment text
);
create unique index if not exists event_id_uindex
on event (id);
create table if not exists event_penalty
(
link_id integer not null
constraint event_punishment_pk
primary key autoincrement,
event_id integer not null
references event,
punishment_id integer not null
references punishment
);

View File

@@ -3,7 +3,7 @@ from datetime import datetime, time, date, timedelta
from flask import g, session, redirect
from estusshots import config, app, db
from estusshots import app
TIME_FMT = "%H:%M"
DATE_FMT = "%Y-%m-%d"
@@ -69,9 +69,9 @@ def combine_datetime(date: datetime.date, time: datetime.time):
def get_user_type(password):
# TODO password hashing?
if password == config.WRITE_PW:
if password == app.config.get("WRITE_PW"):
return "editor"
if password == config.READ_PW:
if password == app.config.get("READ_PW"):
return "readonly"
return False
@@ -109,12 +109,6 @@ def format_timedelta(value):
return timedelta_to_str(value)
@app.cli.command("initdb")
def init_db_command():
"""Initializes the database."""
db.init_db()
@app.teardown_appcontext
def close_connection(exception):
db = getattr(g, "_database", None)

View File

@@ -1,7 +1,7 @@
from flask import render_template, redirect
from estusshots import app
from estusshots import forms, models, orm
from estusshots import forms, orm
from estusshots.util import authorize
from estusshots.orm import Drink
@@ -29,7 +29,7 @@ def drink_edit(drink_id: int):
form.name.data = drink.name
form.vol.data = drink.vol
model = models.GenericFormModel(
model = forms.GenericFormModel(
page_title="Edit Drink",
form_title=f'Edit Drink "{drink.name}"',
post_url="/drink/save",
@@ -42,7 +42,7 @@ def drink_edit(drink_id: int):
@authorize
def new_drink():
form = forms.DrinkForm()
model = models.GenericFormModel(
model = forms.GenericFormModel(
page_title="New Drink",
form_title=f"Create a new Drink",
post_url="/drink/save",
@@ -66,7 +66,7 @@ def drink_save():
err = db.commit()
return redirect("/drink")
model = models.GenericFormModel(
model = forms.GenericFormModel(
page_title="Drinks", form_title="Edit Drink", post_url="/drink/save"
)
return render_template("generic_form.html", model=model, form=form)

View File

@@ -1,7 +1,6 @@
from flask import render_template, request, redirect, url_for
from estusshots import app
from estusshots import forms, models, orm
from estusshots import app, forms, orm
from estusshots.util import authorize
from estusshots.orm import Enemy
from sqlalchemy.orm import subqueryload
@@ -25,7 +24,7 @@ def enemy_new():
form.season_id.process_data(request.args['preselect'])
form.is_boss.data = True
model = models.GenericFormModel(
model = forms.GenericFormModel(
page_title="Enemies",
form_title="Create a new Enemy",
post_url=f"/enemy/null/edit",
@@ -36,7 +35,7 @@ def enemy_new():
@app.route("/enemy/<enemy_id>/edit", methods=["GET", "POST"])
@authorize
def enemy_edit(enemy_id: int):
model = models.GenericFormModel(
model = forms.GenericFormModel(
page_title="Enemies",
form_title="Edit Enemy",
post_url=f"/enemy/{enemy_id}/edit",

View File

@@ -1,7 +1,7 @@
from flask import render_template, request, redirect, url_for
from estusshots import app
from estusshots import forms, models, orm
from estusshots import forms, orm
from estusshots.util import authorize
from estusshots.orm import Season, Episode, Player
@@ -37,7 +37,7 @@ def episode_list(season_id: int):
@app.route("/season/<season_id>/episode/new", methods=["GET"])
@authorize
def episode_new(season_id: int):
model = models.GenericFormModel(
model = forms.GenericFormModel(
page_title="New Episode",
form_title="Create New Episode",
post_url=f"/season/{season_id}/episode/null/edit",
@@ -50,7 +50,7 @@ def episode_new(season_id: int):
@app.route("/season/<season_id>/episode/<episode_id>/edit", methods=["GET", "POST"])
@authorize
def episode_edit(season_id: int, episode_id: int):
model = models.GenericFormModel(
model = forms.GenericFormModel(
page_title="Edit Episode",
form_title="Edit Episode",
post_url=f"/season/{season_id}/episode/{episode_id}/edit",

View File

@@ -1,7 +1,7 @@
from flask import render_template, request, redirect
from estusshots import app
from estusshots import forms, models, orm
from estusshots import forms, orm
from estusshots.util import authorize
from estusshots.orm import Player
@@ -10,7 +10,7 @@ from estusshots.orm import Player
@authorize
def player_new():
form = forms.PlayerForm()
model = models.GenericFormModel(
model = forms.GenericFormModel(
page_title="Players",
form_title="Create a new Player",
post_url="/player/null/edit",
@@ -21,7 +21,7 @@ def player_new():
@app.route("/player/<player_id>/edit", methods=["GET", "POST"])
@authorize
def player_edit(player_id: int):
model = models.GenericFormModel(
model = forms.GenericFormModel(
page_title="Players",
form_title=f"Edit Player",
post_url=f"/player/{player_id}/edit",

View File

@@ -1,7 +1,7 @@
from flask import render_template, request, redirect, url_for
from estusshots import app
from estusshots import forms, models, orm
from estusshots import forms, orm
from estusshots.util import authorize
from estusshots.orm import Season
@@ -28,7 +28,7 @@ def season_list():
@authorize
def season_new():
form = forms.SeasonForm()
model = models.GenericFormModel(
model = forms.GenericFormModel(
page_title="New Season",
form_title="Create New Season",
post_url="/season/edit/null",