reformat using Black

This commit is contained in:
Xevion
2020-03-09 01:49:32 -05:00
parent 4a6615f089
commit c3ccff10e8
3 changed files with 111 additions and 58 deletions

View File

@@ -1,6 +1,7 @@
# Main Flask and Flask configs # Main Flask and Flask configs
from flask import Flask from flask import Flask
from config import Config from config import Config
# Flask Extensions # Flask Extensions
from flask_sqlalchemy import SQLAlchemy from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate from flask_migrate import Migrate
@@ -14,7 +15,7 @@ app.config.from_object(Config)
app.url_map.strict_slashes = False app.url_map.strict_slashes = False
# App extension setup # App extension setup
login = LoginManager(app) login = LoginManager(app)
login.login_view = 'login' login.login_view = "login"
db = SQLAlchemy(app) db = SQLAlchemy(app)
migrate = Migrate(app, db) migrate = Migrate(app, db)
limiter = Limiter(app, key_func=get_remote_address, default_limits=["10 per second"]) limiter = Limiter(app, key_func=get_remote_address, default_limits=["10 per second"])

View File

@@ -4,32 +4,44 @@ import re
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from app import db, login from app import db, login
episodes = [5, 6, 22, 23, 14, 26, 24, 24, 24, 23] # Episode counts. Index 0 is for Webisodes. episodes = [
quotePattern = r'([\w\s\.\',-\[\]\d&\"#]+):(.+)' 5,
6,
22,
23,
14,
26,
24,
24,
24,
23,
] # Episode counts. Index 0 is for Webisodes.
quotePattern = r"([\w\s\.\',-\[\]\d&\"#]+):(.+)"
class Season(db.Model): class Season(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
episodes = db.relationship('Episode', backref='season', lazy='dynamic') episodes = db.relationship("Episode", backref="season", lazy="dynamic")
def __init__(self, **kwargs): def __init__(self, **kwargs):
assert 0 <= kwargs.get('id') <= 9, "Season ID must be 0-9 inclusive" assert 0 <= kwargs.get("id") <= 9, "Season ID must be 0-9 inclusive"
super(Season, self).__init__(**kwargs) super(Season, self).__init__(**kwargs)
def build(self, rebuild=False): def build(self, rebuild=False):
"""runs build operations on every Episode under this season""" """runs build operations on every Episode under this season"""
print(f'Running build() on Season {self.id}') print(f"Running build() on Season {self.id}")
for episode in range(1, episodes[self.id - 1] + 1): for episode in range(1, episodes[self.id - 1] + 1):
ep = Episode.query.filter_by(season_id=self.id, number=episode).first() ep = Episode.query.filter_by(season_id=self.id, number=episode).first()
if ep is None: if ep is None:
# Add the episode, then build # Add the episode, then build
print(f'Creating new Episode, Season {self.id}, Episode {episode}') print(f"Creating new Episode, Season {self.id}, Episode {episode}")
ep = Episode(season_id=self.id, number=episode) ep = Episode(season_id=self.id, number=episode)
db.session.add(ep) db.session.add(ep)
# I'm commiting early, which is a bit taboo, but I'm more worried about what the Episode object will need while building. # I'm commiting early, which is a bit taboo, but I'm more worried about what the Episode object will need while building.
db.session.commit() db.session.commit()
ep.build() ep.build()
else: else:
print(f'Rebuilding Season {self.id}, Episode {episode}') print(f"Rebuilding Season {self.id}, Episode {episode}")
if rebuild: if rebuild:
ep.build() ep.build()
pass pass
@@ -41,7 +53,8 @@ class Season(db.Model):
if Season.query.get(i) is None: if Season.query.get(i) is None:
s = Season(id=i) s = Season(id=i)
db.session.add(s) db.session.add(s)
if build: s.build() if build:
s.build()
db.session.commit() db.session.commit()
@staticmethod @staticmethod
@@ -60,42 +73,54 @@ class Season(db.Model):
"""returns a List of Characters under this Season, sorted by number of spoken lines""" """returns a List of Characters under this Season, sorted by number of spoken lines"""
pass pass
class Episode(db.Model): class Episode(db.Model):
"""represents a Episode with underlying Sections (representing a specific cutscene or area""" """represents a Episode with underlying Sections (representing a specific cutscene or area"""
id = db.Column(db.Integer, primary_key=True) # arbitrary ID, should NOT be relied on to determine episode number or correlating season
number = db.Column(db.Integer) # episode number id = db.Column(
season_id = db.Column(db.Integer, db.ForeignKey('season.id')) # correlating season number db.Integer, primary_key=True
) # arbitrary ID, should NOT be relied on to determine episode number or correlating season
number = db.Column(db.Integer) # episode number
season_id = db.Column(
db.Integer, db.ForeignKey("season.id")
) # correlating season number
built = db.Column(db.Boolean, default=False) built = db.Column(db.Boolean, default=False)
sections = db.relationship('Section', backref='episode', lazy='dynamic') # sections of quotes under this episode sections = db.relationship(
"Section", backref="episode", lazy="dynamic"
) # sections of quotes under this episode
def build(self): def build(self):
"""downloads, processes, and automatically creates Sections and Quotes""" """downloads, processes, and automatically creates Sections and Quotes"""
link = f'http://officequotes.net/no{self.season_id}-{str(self.number).zfill(2)}.php' link = f"http://officequotes.net/no{self.season_id}-{str(self.number).zfill(2)}.php"
data = requests.get(link).text data = requests.get(link).text
open('test.html', 'w+', encoding='utf-8').write(data) open("test.html", "w+", encoding="utf-8").write(data)
soup = BeautifulSoup(data, 'html.parser') soup = BeautifulSoup(data, "html.parser")
sections = soup.find_all(attrs={'class' : 'quote'}) sections = soup.find_all(attrs={"class": "quote"})
deleted = 0 deleted = 0
for section in sections: for section in sections:
isNewpeat = False isNewpeat = False
quotes = [] quotes = []
for quote in section.find_all('b'): for quote in section.find_all("b"):
if 'Newpeat' in quote.string: if "Newpeat" in quote.string:
quote = quote.next_sibling quote = quote.next_sibling
isNewpeat = True isNewpeat = True
if quote is None or quote.next_sibling is None: if quote is None or quote.next_sibling is None:
print('Quote is None or next sibling is None') print("Quote is None or next sibling is None")
continue continue
quotes.append(quote.string + quote.next_sibling.string) quotes.append(quote.string + quote.next_sibling.string)
if len(quotes) == 0: if len(quotes) == 0:
print(f'Section found with Zero quotes. Newpeat: {isNewpeat}') print(f"Section found with Zero quotes. Newpeat: {isNewpeat}")
continue continue
isDeletedScene = quotes[0].lower().startswith('deleted scene') isDeletedScene = quotes[0].lower().startswith("deleted scene")
if isDeletedScene: if isDeletedScene:
deleted += 1 deleted += 1
s = Section(episode_id=self.id, deleted=deleted if isDeletedScene else -1, newpeat=isNewpeat) s = Section(
episode_id=self.id,
deleted=deleted if isDeletedScene else -1,
newpeat=isNewpeat,
)
s.build(quotes[1:] if isDeletedScene else quotes) s.build(quotes[1:] if isDeletedScene else quotes)
db.session.add(s) db.session.add(s)
self.built = True self.built = True
@@ -109,7 +134,9 @@ class Episode(db.Model):
def clear(self): def clear(self):
"""delete all sections relevant to this episode in order to reprocess""" """delete all sections relevant to this episode in order to reprocess"""
sections = Section.query.filter_by(episode_id=self.id).all() sections = Section.query.filter_by(episode_id=self.id).all()
print(f'Clearing {len(sections)} Sections of Ep {self.number} Season {self.season_id}') print(
f"Clearing {len(sections)} Sections of Ep {self.number} Season {self.season_id}"
)
for section in sections: for section in sections:
section.clear(commit=False, delete=True) section.clear(commit=False, delete=True)
self.built = False self.built = False
@@ -123,50 +150,69 @@ class Episode(db.Model):
def __repr__(self): def __repr__(self):
sections = len(Section.query.filter_by(episode_id=self.id).all()) sections = len(Section.query.filter_by(episode_id=self.id).all())
return f'Episode(id={self.id} s={self.season_id} ep={self.number} sects=[{sections}...])' return f"Episode(id={self.id} s={self.season_id} ep={self.number} sects=[{sections}...])"
class Section(db.Model): class Section(db.Model):
"""represents a Section of Quotes, a specific scene with relevant dialog""" """represents a Section of Quotes, a specific scene with relevant dialog"""
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
episode_id = db.Column(db.Integer, db.ForeignKey('episode.id')) episode_id = db.Column(db.Integer, db.ForeignKey("episode.id"))
deleted = db.Column(db.Integer, default=-1) deleted = db.Column(db.Integer, default=-1)
newpeat = db.Column(db.Boolean, default=False) newpeat = db.Column(db.Boolean, default=False)
quotes = db.relationship('Quote', backref='section', lazy='dynamic') quotes = db.relationship("Quote", backref="section", lazy="dynamic")
def build(self, quotes, commit=False, reset=False): def build(self, quotes, commit=False, reset=False):
"""given an List of unformatted script quotes, automatically creates Quotes assigned to this Section""" """given an List of unformatted script quotes, automatically creates Quotes assigned to this Section"""
for i, quote in enumerate(quotes): for i, quote in enumerate(quotes):
if quote.lower().startswith('deleted scene'): if quote.lower().startswith("deleted scene"):
raise Exception(f'Deleted Scene Quote passed to Section Builder: "{quote}"') raise Exception(
f'Deleted Scene Quote passed to Section Builder: "{quote}"'
)
# match = re.match(quotePattern, quote) # match = re.match(quotePattern, quote)
# assert match != None, f"Quote '{quote}' could not be processed." # assert match != None, f"Quote '{quote}' could not be processed."
# q = Quote(section=self, speaker=match[1].strip(), text=match[2].strip()) # q = Quote(section=self, speaker=match[1].strip(), text=match[2].strip())
mark = quote.find(':') mark = quote.find(":")
q = Quote(section=self, speaker=quote[:mark], text=quote[mark + 1:], section_index=i) q = Quote(
section=self,
speaker=quote[:mark],
text=quote[mark + 1 :],
section_index=i,
)
db.session.add(q) db.session.add(q)
if commit: db.session.commit() if commit:
db.session.commit()
def clear(self, doprint=True, commit=True, delete=False): def clear(self, doprint=True, commit=True, delete=False):
"""delete all quotes relevant to this section""" """delete all quotes relevant to this section"""
quotes = Quote.query.filter_by(section_id=self.id).all() quotes = Quote.query.filter_by(section_id=self.id).all()
if doprint: print(f'Clearing {len(quotes)} quotes from Section ID {self.id}') if doprint:
print(f"Clearing {len(quotes)} quotes from Section ID {self.id}")
for quote in quotes: for quote in quotes:
db.session.delete(quote) db.session.delete(quote)
if delete: db.session.delete(self) if delete:
if commit: db.session.commit() db.session.delete(self)
if commit:
db.session.commit()
def __repr__(self): def __repr__(self):
season = Episode.query.get(self.episode_id).id season = Episode.query.get(self.episode_id).id
quotes = len(Quote.query.filter_by(section_id=self.id).all()) quotes = len(Quote.query.filter_by(section_id=self.id).all())
return f'Section(id={self.id} S-EP={season}/{self.episode_id} quotes=[{quotes}...])' return f"Section(id={self.id} S-EP={season}/{self.episode_id} quotes=[{quotes}...])"
class Quote(db.Model): class Quote(db.Model):
"""represents a specific quote by a specific speaker""" """represents a specific quote by a specific speaker"""
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
section_id = db.Column(db.Integer, db.ForeignKey('section.id')) # The section this quote belongs to. section_id = db.Column(
speaker = db.Column(db.String(32)) # The name of a character db.Integer, db.ForeignKey("section.id")
text = db.Column(db.String(512)) # The content of the Quote. Usually a sentence, sometimes more. ) # The section this quote belongs to.
section_index = db.Column(db.Integer) # The index of this quote in the section speaker = db.Column(db.String(32)) # The name of a character
text = db.Column(
db.String(512)
) # The content of the Quote. Usually a sentence, sometimes more.
section_index = db.Column(db.Integer) # The index of this quote in the section
def __repr__(self): def __repr__(self):
return f"Quote(speaker='{self.speaker}' text='{self.text[:50]}{'...' if len(self.text) > 51 else ''}')" return f"Quote(speaker='{self.speaker}' text='{self.text[:50]}{'...' if len(self.text) > 51 else ''}')"

View File

@@ -2,24 +2,30 @@ from flask import send_from_directory, redirect, url_for, render_template, reque
from app.models import Season, Episode from app.models import Season, Episode
from app import app from app import app
@app.route('/')
@app.route("/")
def index(): def index():
return render_template('view.html', seasons=Season.query.all()) return render_template("view.html", seasons=Season.query.all())
@app.route('/season/<season>/')
@app.route("/season/<season>/")
def viewSeason(season): def viewSeason(season):
return render_template('season.html', season=Season.query.filter_by(id=season).first_or_404()) return render_template(
"season.html", season=Season.query.filter_by(id=season).first_or_404()
)
@app.route('/season/<season>/<episode>/')
@app.route("/season/<season>/<episode>/")
def viewEpisode(season, episode): def viewEpisode(season, episode):
e = Episode.query.filter_by(season_id=season, number=episode).first_or_404() e = Episode.query.filter_by(season_id=season, number=episode).first_or_404()
if not e.built: if not e.built:
print('Rebuilding') print("Rebuilding")
e.build() e.build()
return render_template('episode.html', episode=e) return render_template("episode.html", episode=e)
@app.route('/season/<season>/<episode>/rebuild')
@app.route("/season/<season>/<episode>/rebuild")
def rebuildEpisode(season, episode): def rebuildEpisode(season, episode):
e = Episode.query.filter_by(season_id=season, number=episode).first_or_404() e = Episode.query.filter_by(season_id=season, number=episode).first_or_404()
e.rebuild() e.rebuild()
return redirect(url_for('viewEpisode', season=season, episode=episode)) return redirect(url_for("viewEpisode", season=season, episode=episode))