Skip to content

Commit

Permalink
Starter code for chapter 7, infinite scroll.
Browse files Browse the repository at this point in the history
  • Loading branch information
mikeckennedy committed Sep 21, 2021
1 parent 36d0869 commit f2b32b9
Show file tree
Hide file tree
Showing 140 changed files with 50,488 additions and 0 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

55 changes: 55 additions & 0 deletions code/ch7_infinite_scroll/ch7_final_video_collector/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import sys

import flask
import jinja_partials

from services import video_service

app = flask.Flask("app")


def configure():
print("Configuring Flask app:")

register_template_ops()
print("Registered template helpers")

register_blueprints()
print("Registered blueprints")

setup_db()
print("DB setup completed.")
print("", flush=True)


def register_template_ops():
jinja_partials.register_extensions(app)
helpers = {
'len': len,
'isinstance': isinstance,
'str': str,
'type': type
}
app.jinja_env.globals.update(**helpers)


def register_blueprints():
from views import home
from views import videos
from views import feed

app.register_blueprint(home.blueprint)
app.register_blueprint(videos.blueprint)
app.register_blueprint(feed.blueprint)


def setup_db():
video_service.load_data()


if __name__ == '__main__':
configure()
being_debugged = sys.gettrace() is not None
app.run(debug=being_debugged)
else:
configure()
256 changes: 256 additions & 0 deletions code/ch7_infinite_scroll/ch7_final_video_collector/db/videos.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
[
{
"category": "Python",
"image": "python.jpg",
"videos": [
{
"id": "rDYKZG6Fn8o",
"title": "Go Python, Go!",
"url": "https://www.youtube.com/watch?v=rDYKZG6Fn8o",
"author": "Python Bytes",
"views": 347
},
{
"id": "QltSJUlHbpw",
"title": "A Space Filled Episode with Dr. Becky",
"url": "https://www.youtube.com/watch?v=QltSJUlHbpw",
"author": "Python Bytes",
"views": 365
},
{
"id": "4wjqsPtj2QY",
"title": "HTMX - Clean Dynamic HTML Pages",
"url": "https://www.youtube.com/watch?v=4wjqsPtj2QY",
"author": "Talk Python",
"views": 756
},
{
"id": "cfrUF-UGehk",
"title": "Python and Flask at the US Federal Election Commission",
"url": "https://www.youtube.com/watch?v=cfrUF-UGehk",
"author": "Talk Python",
"views": 511
},
{
"id": "36yw8VC3KU8",
"title": "PyCon: Let's talk Databases in Python: SQLAlchemy and Alembic",
"url": "https://www.youtube.com/watch?v=36yw8VC3KU8",
"author": "Hannah Stepanek",
"views": 10302
},
{
"id": "pvaIi0l1GME",
"title": "What we learned from Papermill to operationalize notebooks",
"url": "https://www.youtube.com/watch?v=pvaIi0l1GME",
"author": "Alan Yu and Vasu Bhog",
"views": 789
},
{
"id": "PnxlHfGdihI",
"title": "A Python Developer Explores Apple's M1",
"url": "https://www.youtube.com/watch?v=PnxlHfGdihI",
"author": "Michael Kennedy",
"views": 4654
}
]
},
{
"category": "Apple",
"image": "apple.jpg",
"videos": [
{
"id": "R5BQ6yhhRJc",
"title": "Andy's Pick & Pull - WWDC 2021",
"url": "https://www.youtube.com/watch?v=R5BQ6yhhRJc",
"author": "MacBreak Weekly",
"views": 13720
},
{
"id": "PnxlHfGdihI",
"title": "A Python Developer Explores Apple's M1",
"url": "https://www.youtube.com/watch?v=PnxlHfGdihI",
"author": "Michael Kennedy",
"views": 4654
},
{
"id": "YisUywtzZK0",
"title": "How Apple Private Relay Kills Data Profiling",
"url": "https://www.youtube.com/watch?v=YisUywtzZK0",
"author": "Rene Ritchie",
"views": 65245
},
{
"id": "vg0AF166eVI",
"title": "Why the M1 Mac is SO FAST — Apple Silicon Explained!",
"url": "https://www.youtube.com/watch?v=vg0AF166eVI",
"author": "Rene Ritchie",
"views": 523014
},
{
"id": "0TD96VTf0Xs",
"title": "WWDC 2021",
"url": "https://www.youtube.com/watch?v=0TD96VTf0Xs",
"author": "Apple",
"views": 6655103
},
{
"id": "4ecN7yGcqcQ",
"title": "M1 iMac Unboxing and Review!",
"url": "https://www.youtube.com/watch?v=4ecN7yGcqcQ",
"author": "iJustine",
"views": 623042
}
]
},
{
"category": "JavaScript",
"image": "javascript.jpg",
"videos": [
{
"id": "4wjqsPtj2QY",
"title": "HTMX - Clean Dynamic HTML Pages",
"url": "https://www.youtube.com/watch?v=4wjqsPtj2QY",
"author": "Talk Python",
"views": 756
},
{
"id": "qZXt1Aom3Cs",
"title": "Vue JS Crash Course 2021",
"url": "https://www.youtube.com/watch?v=qZXt1Aom3Cs",
"author": "Traversy Media",
"views": 265783
},
{
"id": "OrxmtDw4pVI",
"title": "Vue.js: The Documentary",
"url": "https://www.youtube.com/watch?v=OrxmtDw4pVI",
"author": "Honeypot",
"views": 932606
},
{
"id": "m_F8wSZT3QY",
"title": "Wat - JavaScript misadventures",
"url": "https://www.youtube.com/watch?v=3se2-thqf-A",
"author": "Gary Bernhardt",
"views": 866
},
{
"id": "ahCwqrYpIuM",
"title": "TypeScript - The Basics",
"url": "https://www.youtube.com/watch?v=ahCwqrYpIuM",
"author": "Fireship",
"views": 772764
}
]
},
{
"category": "EVs",
"image": "ev.jpg",
"videos": [
{
"id": "6RhtiPefVzM",
"title": "Are Electric Cars Worse For The Environment? Myth Busted",
"url": "https://www.youtube.com/watch?v=6RhtiPefVzM",
"author": "Engineering Explained",
"views": 1753659
},
{
"id": "QMfxJEfb4lw",
"title": "Rivian - Electric Adventure Vehicle",
"url": "https://www.youtube.com/watch?v=QMfxJEfb4lw",
"author": "Fully Charged Show",
"views": 4029696
},
{
"id": "A6RsmzCYB3I",
"title": "New Hyundai Ioniq 5 full review - the 300-mile Tesla EV rival styled by Minecraft",
"url": "https://www.youtube.com/watch?v=A6RsmzCYB3I",
"author": "The Late Brake Show",
"views": 938994
},
{
"id": "QHOPFp1o3d0",
"title": "Bolt: Best Non Tesla Electric Car?",
"url": "https://www.youtube.com/watch?v=QHOPFp1o3d0",
"author": "TheStraightPipes",
"views": 512330
},
{
"id": "3iRHYIwjFKw",
"title": "Tesla Full Self Driving Beta Test Drive",
"url": "https://www.youtube.com/watch?v=3iRHYIwjFKw",
"author": "Tesla Raj",
"views": 367345
},
{
"id": "KOWz9-5T9pE",
"title": "Formula E: 2021 Puebla E-Prix | Round 8",
"url": "https://www.youtube.com/watch?v=KOWz9-5T9pE",
"author": "ABB Formula E",
"views": 43975
}
]
},
{
"category": "Racing",
"image": "racing.jpg",
"videos": [
{
"id": "tvcuGoVhpxw",
"title": "How to Trail Brake: A Step-by-Step Guide",
"url": "https://www.youtube.com/watch?v=tvcuGoVhpxw",
"author": "Driver61",
"views": 210861
},
{
"id": "eUdaWbr1KB4",
"title": "Trail Braking: 5 Mistakes DESTROYING Your Lap Time",
"url": "https://www.youtube.com/watch?v=eUdaWbr1KB4",
"author": "Driver61",
"views": 581747
},
{
"id": "F5igCWjmeAU",
"title": "My Very First Start in IndyCar",
"url": "https://www.youtube.com/watch?v=F5igCWjmeAU",
"author": "Romain Grosjean",
"views": 960145
},
{
"id": "KOWz9-5T9pE",
"title": "Formula E: 2021 Puebla E-Prix | Round 8",
"url": "https://www.youtube.com/watch?v=KOWz9-5T9pE",
"author": "ABB Formula E",
"views": 43975
},
{
"id": "EU73gjQJXU4",
"title": "IndyCar - Road America 2021 Highlights",
"url": "https://www.youtube.com/watch?v=EU73gjQJXU4",
"author": "Motorsports on NBC",
"views": 43295
},
{
"id": "9i2iA0R6IdA",
"title": "The First Corner: Do's and Don'ts",
"url": "https://www.youtube.com/watch?v=9i2iA0R6IdA",
"author": "Driver61",
"views": 46432
},
{
"id": "X0WuN3poyVs",
"title": "Biggest Sim Racing Tips (sim driver analysis)",
"url": "https://www.youtube.com/watch?v=X0WuN3poyVs",
"author": "Driver61",
"views": 78817
},
{
"id": "2wzy3HiW7SE",
"title": "CAN YOU TELL THIS ISN'T REAL? - Corvette C8.R - Nordschleife",
"url": "https://www.youtube.com/watch?v=2wzy3HiW7SE",
"author": "Boosted Media",
"views": 60007
}
]
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import flask
from werkzeug.datastructures import MultiDict


class RequestDictionary(dict):
def __init__(self, *args, default_val=None, **kwargs):
self.default_val = default_val
super().__init__(*args, **kwargs)

def __getattr__(self, key):
return self.get(key, self.default_val)


def create(default_val=None, **route_args) -> RequestDictionary:
request = flask.request

# Adding this retro actively. Some folks are experiencing issues where they
# are getting a list rather than plain dict. I think it's from multiple
# entries in the multidict. This should fix it.
args = request.args
if isinstance(request.args, MultiDict):
args = request.args.to_dict()

form = request.form
if isinstance(request.args, MultiDict):
form = request.form.to_dict()

data = {
**args, # The key/value pairs in the URL query string
**request.headers, # Header values
**form, # The key/value pairs in the body, from a HTML post form
**route_args # And additional arguments the method access, if they want them merged.
}

return RequestDictionary(data, default_val=default_val)
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from functools import wraps

import flask
import werkzeug
import werkzeug.wrappers


def response(*, mimetype: str = None, template_file: str = None):
def response_inner(f):

@wraps(f)
def view_method(*args, **kwargs):
response_val = f(*args, **kwargs)

if isinstance(response_val, werkzeug.wrappers.Response):
return response_val

if isinstance(response_val, flask.Response):
return response_val

if isinstance(response_val, dict):
model = dict(response_val)
else:
model = dict()

if template_file and not isinstance(response_val, dict):
raise Exception(
"Invalid return type {}, we expected a dict as the return value.".format(type(response_val)))

if template_file:
response_val = flask.render_template(template_file, **response_val)

resp = flask.make_response(response_val)
resp.model = model
if mimetype:
resp.mimetype = mimetype

return resp

return view_method

return response_inner
Loading

0 comments on commit f2b32b9

Please sign in to comment.