Skip to content

Commit dde9a07

Browse files
committed
Merge remote-tracking branch 'origin/main'
2 parents 4058b59 + 46925cb commit dde9a07

File tree

753 files changed

+82557
-100380
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

753 files changed

+82557
-100380
lines changed

code/code_with_me/podcast/program.py

+5-9
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,23 @@ def main():
55
show_header()
66

77
service.download_info()
8-
print("Working with total of {} episodes".format(service.get_latest_show_id()))
8+
print('Working with total of {} episodes'.format(service.get_latest_show_id()))
99
display_results()
1010

1111

1212
def show_header():
13-
print("Welcome to the talk python info downloader.")
14-
print("Code with me version.")
13+
print('Welcome to the talk python info downloader.')
14+
print('Code with me version.')
1515
print()
1616

1717

1818
def display_results():
19-
# This is updated since the video recording.
20-
# We had to trim back the episode list, so I changed
21-
# this code to use the moving numbers from the RSS feed
22-
# as they change over time.
23-
start = service.get_min_show_id()
2419
end = service.get_latest_show_id()
20+
start = max(1, end - 20)
2521

2622
for show_id in range(start, end):
2723
info = service.get_episode(show_id)
28-
print("{}. {}".format(info.show_id, info.title))
24+
print('{}. {}'.format(info.show_id, info.title))
2925

3026

3127
if __name__ == '__main__':

code/code_with_me/podcast/service.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,23 @@
88

99

1010
def download_info():
11-
url = 'https://pythonbytes.fm/episodes/rss'
11+
url = 'https://talkpython.fm/episodes/rss'
1212

1313
resp = requests.get(url)
1414
resp.raise_for_status()
1515

1616
dom = ElementTree.fromstring(resp.text)
1717

1818
items = dom.findall('channel/item')
19+
# Probably right here, smell, smell
1920
episode_count = len(items)
2021

2122
for idx, item in enumerate(items):
2223
episode = Episode(
2324
item.find('title').text,
2425
item.find('link').text,
2526
item.find('pubDate').text,
26-
episode_count - idx
27+
episode_count - idx + 1
2728
)
2829
episode_data[episode.show_id] = episode
2930

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
Manufacturer,Model,Engine (cc),Category
2+
BMW,R1150GS,1130,Heavyweight
3+
BMW,R1200GS,1170,Heavyweight
4+
BMW,R1250GS,1254,Heavyweight
5+
BMW,F650GS/G650GS,652,Middleweight
6+
BMW,F800GS,798,Middleweight
7+
BMW,F850GS,853,Middleweight
8+
BMW,G310GS,313,Lightweight
9+
Kawasaki,KLR650,652,Lightweight
10+
Kawasaki,Versys 650,649,Middleweight
11+
Kawasaki,Versys 1000,1043,Heavyweight
12+
Kawasaki,Versys-X 300,296,Lightweight
13+
Suzuki,V-Strom 1000,996,Heavyweight
14+
Suzuki,V-Strom 650,645,Middleweight
15+
Suzuki,V-Strom 800DE,776,Middleweight
16+
Honda,XR650L,644,Lightweight
17+
Honda,Africa Twin 1000 (CRF1000L),998,Heavyweight
18+
Honda,Africa Twin 1100 (CRF1100L),1084,Heavyweight
19+
Honda,CB500X,471,Lightweight
20+
Honda,NC700X,670,Middleweight
21+
Honda,XL750 Transalp,755,Middleweight
22+
Honda,CRF300L Rally,286,Lightweight
23+
Yamaha,Super Tenere 1200,1199,Heavyweight
24+
Yamaha,Tenere,689,Middleweight
25+
Triumph,Tiger 955i,955,Heavyweight
26+
Triumph,Tiger 1050,1050,Heavyweight
27+
Triumph,Tiger 800,799,Middleweight
28+
Triumph,Tiger 900,888,Middleweight
29+
Triumph,Tiger 1200,1215,Heavyweight
30+
Ducati,Multistrada 1100,1078,Heavyweight
31+
Ducati,Multistrada 1260,1262,Heavyweight
32+
Ducati,Multistrada V4,1158,Heavyweight
33+
Ducati,Multistrada 950/V2,937,Middleweight
34+
Ducati,DesertX,937,Middleweight
35+
KTM,640 Adventure,625,Lightweight
36+
KTM,950 Adventure,942,Heavyweight
37+
KTM,990 Adventure,999,Heavyweight
38+
KTM,1190 Adventure,1195,Heavyweight
39+
KTM,1290 Super Adventure,1301,Heavyweight
40+
KTM,790 Adventure,799,Middleweight
41+
KTM,890 Adventure,889,Middleweight
42+
KTM,390 Adventure,373,Lightweight
43+
Aprilia,Caponord 1000,998,Heavyweight
44+
Aprilia,Caponord 1200,1197,Heavyweight
45+
Aprilia,Tuareg 660,659,Middleweight
46+
Moto Guzzi,Stelvio 1200,1151,Heavyweight
47+
Moto Guzzi,V85 TT,853,Middleweight
48+
Buell/Harley,Buell Ulysses XB12X,1203,Heavyweight
49+
Harley-Davidson,Pan America 1250,1252,Heavyweight
50+
Zero,DSR/X (electric),0,Heavyweight

demos/adv_analysis_project/adv_notebook.ipynb

+214
Large diffs are not rendered by default.
+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#%% md
2+
# # Adventure Motorcycle Segment
3+
#%%
4+
import pandas as pd
5+
import matplotlib.pyplot as plt
6+
#%%
7+
df = pd.read_csv('adv-moto-data.csv')
8+
# df
9+
#%%
10+
df.groupby('Category')['Engine (cc)'].mean().astype(int)
11+
#%% md
12+
# ## Let's visualize our data
13+
#%% md
14+
# ### Plotting engine size
15+
#%%
16+
# Map categories to colors
17+
colors = {'Heavyweight': 'red', 'Middleweight': 'blue', 'Lightweight': 'green'}
18+
df['Color'] = df['Category'].map(colors)
19+
20+
plt.figure(figsize=(12, 8))
21+
22+
# Use df.index for the x-axis and 'Engine (cc)' for the y-axis.
23+
# The marker size is proportional to engine size, scaled down by a factor.
24+
scaling_factor = 0.5
25+
plt.scatter(
26+
df.index,
27+
df['Engine (cc)'],
28+
s=df['Engine (cc)'] * scaling_factor,
29+
color=df['Color'],
30+
alpha=0.6
31+
)
32+
33+
# Annotate each point with the model name, offset slightly above the marker
34+
for i, row in df.iterrows():
35+
plt.annotate(
36+
row['Model'],
37+
(i, row['Engine (cc)']),
38+
textcoords="offset points",
39+
xytext=(0, -14), # Offset label by 10 points below the marker
40+
ha='center',
41+
va='top', # Align text so that its top is at the offset position
42+
fontsize=8
43+
)
44+
45+
plt.xlabel('Model Index')
46+
plt.ylabel('Engine (cc)')
47+
plt.title('Engine Size by Model with Category Color')
48+
plt.show()
49+
#%% md
50+
# ## Visualizing Engine Size by Category
51+
#%%
52+
# Compute the average engine size by category
53+
avg_engine_size = df.groupby('Category')['Engine (cc)'].mean()
54+
55+
# Define colors for each category
56+
colors = {'Heavyweight': 'red', 'Middleweight': 'blue', 'Lightweight': 'green'}
57+
58+
# Create the bar plot
59+
plt.figure(figsize=(10, 3))
60+
plt.bar(avg_engine_size.index, avg_engine_size.values,
61+
color=[colors[cat] for cat in avg_engine_size.index])
62+
plt.xlabel('Category')
63+
plt.ylabel('Average Engine Size (cc)')
64+
plt.title('Average Engine Size by Category')
65+
plt.show()
66+
#%%
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2019 Talk Python
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Data-driven web apps with
2+
3+
Course demo code and other hand-out materials for our data driven web apps in Flask course. Visit the full course page at **[training.talkpython.fm](https://training.talkpython.fm/courses/explore_flask/building-data-driven-web-applications-in-python-with-flask-sqlalchemy-and-bootstrap)**
4+
5+
[![](readme_materials/flask-data-web-apps.jpg)](https://training.talkpython.fm/courses/explore_flask/building-data-driven-web-applications-in-python-with-flask-sqlalchemy-and-bootstrap)
6+
7+
## Course Summary
8+
9+
One of the areas Python really shines is in building clean and powerful web applications. Once you know the language basics, this course will teach you everything you need to build data-driven, modern web applications in Python with the Flask web framework.
10+
11+
## What's this course about and how is it different?
12+
13+
**Full stack web development is exactly what you need to build true data-driven web applications in Python**. Yet these courses can be confusing and overwhelming due to the many technologies involved (Python, SQL, CSS, etc).
14+
15+
We have taken great care to build a course that is **just real enough to give you what you need without anything extra**. We build a replica of a popular web application, Python's own packaging index over at pypi.org.
16+
17+
While building our replica PyPI, you will learn:
18+
19+
* Learn about the different major Python web frameworks
20+
* Create a Flask-based website from scratch using the CLI and PyCharm
21+
* Work with dynamic HTML templates
22+
* Map URLs to view methods using routing
23+
* Make advanced use of routing to build a full custom CMS in 8 minutes
24+
* Take advantage of bootstrap to build well designed sites
25+
* Map data to and from Python using classes with SQLAlchemy
26+
* Learn how Alembic can help our database evolve as our models change
27+
* Accept user input with HTML forms
28+
* Add client and server-side validation
29+
* Overcome the special challenges of testing web apps (databases, frameworks, etc)
30+
* Deploy our web application to a fresh Linux machine (virtual, cloud-based)
31+
* Leverage our design patterns to convert our app to another data model (MongoDB edition)
32+
33+
## Who is this course for?
34+
35+
This course is for **anyone who wants to create Python-based web applications using the Flask web framework**. In fact, you'll learn a lot of web skills that will translate across frameworks as well.
36+
37+
We do assume that you have basic Python language skills and can read HTML and CSS. But most advanced uses of the language or CSS are explained in the course.
38+
39+
## Is this course based on Python 3 or Python 2?
40+
41+
This course is **based upon Python 3**. With Python 2 going unsupported in 2020, we believe that it would be ill-advised to teach or learn Python 2.
42+
43+
## The time to act is now
44+
45+
This **data-driven web apps with Python and Flask** course is just what you need to build that fast, custom web application that can help you create your next great idea or just solve a business problem by deploying it behind your firewall.
46+
47+
Take the course over at **[training.talkpython.fm](https://training.talkpython.fm/courses/explore_flask/building-data-driven-web-applications-in-python-with-flask-sqlalchemy-and-bootstrap)**.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# A generic, single database configuration.
2+
3+
[alembic]
4+
# path to migration scripts
5+
script_location = alembic
6+
7+
# template used to generate migration files
8+
# file_template = %%(rev)s_%%(slug)s
9+
10+
# timezone to use when rendering the date
11+
# within the migration file as well as the filename.
12+
# string value is passed to dateutil.tz.gettz()
13+
# leave blank for localtime
14+
# timezone =
15+
16+
# max length of characters to apply to the
17+
# "slug" field
18+
# truncate_slug_length = 40
19+
20+
# set to 'true' to run the environment during
21+
# the 'revision' command, regardless of autogenerate
22+
# revision_environment = false
23+
24+
# set to 'true' to allow .pyc and .pyo files without
25+
# a source .py file to be detected as revisions in the
26+
# versions/ directory
27+
# sourceless = false
28+
29+
# version location specification; this defaults
30+
# to alembic/versions. When using multiple version
31+
# directories, initial revisions must be specified with --version-path
32+
# version_locations = %(here)s/bar %(here)s/bat alembic/versions
33+
34+
# the output encoding used when revision files
35+
# are written from script.py.mako
36+
# output_encoding = utf-8
37+
38+
sqlalchemy.url = sqlite:///./pypi_org/db/pypi.sqlite
39+
40+
41+
# Logging configuration
42+
[loggers]
43+
keys = root,sqlalchemy,alembic
44+
45+
[handlers]
46+
keys = console
47+
48+
[formatters]
49+
keys = generic
50+
51+
[logger_root]
52+
level = WARN
53+
handlers = console
54+
qualname =
55+
56+
[logger_sqlalchemy]
57+
level = WARN
58+
handlers =
59+
qualname = sqlalchemy.engine
60+
61+
[logger_alembic]
62+
level = INFO
63+
handlers =
64+
qualname = alembic
65+
66+
[handler_console]
67+
class = StreamHandler
68+
args = (sys.stderr,)
69+
level = NOTSET
70+
formatter = generic
71+
72+
[formatter_generic]
73+
format = %(levelname)-5.5s [%(name)s] %(message)s
74+
datefmt = %H:%M:%S
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Generic single-database configuration.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from alembic import op
2+
from sqlalchemy import engine_from_config
3+
from sqlalchemy.engine import reflection
4+
5+
6+
def table_has_column(table, column):
7+
config = op.get_context().config
8+
engine = engine_from_config(config.get_section(config.config_ini_section), prefix='sqlalchemy.')
9+
insp = reflection.Inspector.from_engine(engine)
10+
has_column = False
11+
for col in insp.get_columns(table):
12+
if column not in col['name']:
13+
continue
14+
has_column = True
15+
return has_column

0 commit comments

Comments
 (0)