Skip to content

Commit 67f6a4b

Browse files
committed
Upgrade to Python3.10
1 parent dab7f46 commit 67f6a4b

22 files changed

+1064
-909
lines changed

.env.example

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
FLASK_ENV=development
1+
FLASK_ENV=production
2+
FLASK_DEBUG=False
23
SECRET_KEY=randomstringofcharacters
4+
35
LESS_BIN=/usr/local/bin/lessc
6+
COMPRESSOR_DEBUG=False
47
ASSETS_DEBUG=False
5-
LESS_RUN_IN_DEBUG=False
6-
COMPRESSOR_DEBUG=True
8+
LESS_RUN_IN_DEBUG=False

.flake8

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[flake8]
2+
select = E9,F63,F7,F82
3+
exclude = .git,.github,__pycache__,.pytest_cache,.venv,logs,creds
4+
max-line-length = 120

Makefile

+40-50
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
PROJECT_NAME := $(shell basename $CURDIR)
2-
VIRTUAL_ENVIRONMENT := $(CURDIR)/.venv
3-
LOCAL_PYTHON := $(VIRTUAL_ENVIRONMENT)/bin/python3
2+
VIRTUAL_ENV := $(CURDIR)/.venv
3+
LOCAL_PYTHON := $(VIRTUAL_ENV)/bin/python3
44

55
define HELP
66
Manage $(PROJECT_NAME). Usage:
@@ -19,63 +19,52 @@ export HELP
1919

2020
.PHONY: run install deploy update format lint clean help
2121

22-
2322
all help:
2423
@echo "$$HELP"
2524

25+
env: $(VIRTUAL_ENV)
2626

27-
env: $(VIRTUAL_ENVIRONMENT)
28-
29-
30-
$(VIRTUAL_ENVIRONMENT):
31-
if [ -d $(VIRTUAL_ENVIRONMENT) ]; then \
32-
@echo "Creating Python virtual environment..." && \
33-
python3 -m venv $(VIRTUAL_ENVIRONMENT) && \
27+
$(VIRTUAL_ENV):
28+
if [ ! -d $(VIRTUAL_ENV) ]; then \
29+
echo "Creating Python virtual env in \`${VIRTUAL_ENV}\`"; \
30+
python3 -m venv $(VIRTUAL_ENV); \
3431
fi
3532

36-
3733
.PHONY: run
3834
run: env
39-
$(shell python3 -m wsgi.py)
40-
35+
$(LOCAL_PYTHON) -m main
4136

4237
.PHONY: install
43-
install:
44-
if [ ! -d "./.venv" ]; then python3 -m venv $(VIRTUAL_ENVIRONMENT); fi
45-
$(shell . .venv/bin/activate)
46-
$(LOCAL_PYTHON) -m pip install --upgrade pip setuptools wheel
47-
$(LOCAL_PYTHON) -m pip install -r requirements.txt
48-
38+
install: env
39+
$(LOCAL_PYTHON) -m pip install --upgrade pip setuptools wheel && \
40+
$(LOCAL_PYTHON) -m pip install -r requirements.txt && \
41+
npm i -g less && \
42+
echo Installed dependencies in \`${VIRTUAL_ENV}\`;
4943

5044
.PHONY: deploy
5145
deploy:
52-
make clean
53-
make install
46+
make install && \
5447
make run
5548

56-
5749
.PHONY: test
5850
test: env
5951
$(LOCAL_PYTHON) -m \
60-
coverage run -m pytest -v \
61-
--disable-pytest-warnings \
62-
&& coverage html --title='Coverage Report' -d .reports \
63-
&& open .reports/index.html
64-
52+
coverage run -m pytest -vv \
53+
--disable-pytest-warnings && \
54+
coverage html --title='Coverage Report' -d .reports && \
55+
open .reports/index.html
6556

6657
.PHONY: update
67-
update:
68-
if [ ! -d "./.venv" ]; then python3 -m venv $(VIRTUAL_ENVIRONMENT); fi
69-
$(LOCAL_PYTHON) -m pip install --upgrade pip setuptools wheel
70-
poetry update
71-
poetry export -f requirements.txt --output requirements.txt --without-hashes
72-
58+
update: env
59+
$(LOCAL_PYTHON) -m pip install --upgrade pip setuptools wheel && \
60+
poetry update && \
61+
poetry export -f requirements.txt --output requirements.txt --without-hashes && \
62+
echo Installed dependencies in \`${VIRTUAL_ENV}\`;
7363

7464
.PHONY: format
7565
format: env
76-
isort --multi-line=3 .
77-
black .
78-
66+
$(LOCAL_PYTHON) -m isort --multi-line=3 . && \
67+
$(LOCAL_PYTHON) -m black .
7968

8069
.PHONY: lint
8170
lint: env
@@ -85,19 +74,20 @@ lint: env
8574
--show-source \
8675
--statistics
8776

88-
8977
.PHONY: clean
9078
clean:
91-
find . -name '*.pyc' -delete
92-
find . -name '__pycache__' -delete
93-
find . -name 'poetry.lock' -delete
94-
find . -name 'Pipefile.lock' -delete
95-
find . -name '*.log' -delete
96-
find . -name '.coverage' -delete
97-
find . -wholename 'logs/*.json' -delete
98-
find . -wholename '*/.pytest_cache' -delete
99-
find . -wholename '**/.pytest_cache' -delete
100-
find . -wholename './logs/*.json' -delete
101-
find . -wholename '.webassets-cache/*' -delete
102-
find . -wholename './logs' -delete
103-
find . -wholename './.reports' -delete
79+
find . -name '.coverage' -delete && \
80+
find . -name '*.pyc' -delete \
81+
find . -name '__pycache__' -delete \
82+
find . -name 'poetry.lock' -delete \
83+
find . -name '*.log' -delete \
84+
find . -name '.DS_Store' -delete \
85+
find . -wholename '**/*.pyc' -delete && \
86+
find . -wholename '**/*.html' -delete && \
87+
find . -type d -wholename '__pycache__' -exec rm -rf {} + && \
88+
find . -type d -wholename '.venv' -exec rm -rf {} + && \
89+
find . -type d -wholename '.pytest_cache' -exec rm -rf {} + && \
90+
find . -type d -wholename '**/.pytest_cache' -exec rm -rf {} + && \
91+
find . -type d -wholename '**/*.log' -exec rm -rf {} + && \
92+
find . -type d -wholename './.reports/*' -exec rm -rf {} + && \
93+
find . -type d -wholename '**/.webassets-cache' -exec rm -rf {} +

README.md

+7-8
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# Plotly Dash Flask Tutorial
22

3-
![Python](https://img.shields.io/badge/Python-^3.9-blue.svg?logo=python&longCache=true&logoColor=white&colorB=5e81ac&style=flat-square&colorA=4c566a)
4-
![Flask](https://img.shields.io/badge/Flask^2.0.0-blue.svg?longCache=true&logo=flask&style=flat-square&logoColor=white&colorB=5e81ac&colorA=4c566a)
3+
![Python](https://img.shields.io/badge/Python-^3.10-blue.svg?logo=python&longCache=true&logoColor=white&colorB=5e81ac&style=flat-square&colorA=4c566a)
4+
![Flask](https://img.shields.io/badge/Flask^2.2.5-blue.svg?longCache=true&logo=flask&style=flat-square&logoColor=white&colorB=5e81ac&colorA=4c566a)
55
![Flask-Assets](https://img.shields.io/badge/Flask--Assets-v2.0-blue.svg?longCache=true&logo=flask&style=flat-square&logoColor=white&colorB=5e81ac&colorA=4c566a)
6-
![Pandas](https://img.shields.io/badge/Pandas-v^1.4.0-blue.svg?longCache=true&logo=python&longCache=true&style=flat-square&logoColor=white&colorB=5e81ac&colorA=4c566a)
7-
![Dash](https://img.shields.io/badge/Dash-v^2.0.0-blue.svg?longCache=true&logo=python&longCache=true&style=flat-square&logoColor=white&colorB=5e81ac&colorA=4c566a)
8-
![Plotly](https://img.shields.io/badge/Plotly-v^5.8.0-blue.svg?longCache=true&logo=python&longCache=true&style=flat-square&logoColor=white&colorB=5e81ac&colorA=4c566a)
6+
![Pandas](https://img.shields.io/badge/Pandas-v^2.1.0-blue.svg?longCache=true&logo=python&longCache=true&style=flat-square&logoColor=white&colorB=5e81ac&colorA=4c566a)
7+
![Dash](https://img.shields.io/badge/Dash-v^2.13.0-blue.svg?longCache=true&logo=python&longCache=true&style=flat-square&logoColor=white&colorB=5e81ac&colorA=4c566a)
8+
![Plotly](https://img.shields.io/badge/Plotly-v^5.16.1-blue.svg?longCache=true&logo=python&longCache=true&style=flat-square&logoColor=white&colorB=5e81ac&colorA=4c566a)
99
![GitHub Last Commit](https://img.shields.io/github/last-commit/google/skia.svg?style=flat-square&colorA=4c566a&colorB=a3be8c)
1010
[![GitHub Issues](https://img.shields.io/github/issues/toddbirchard/plotlydash-flask-tutorial.svg?style=flat-square&colorA=4c566a&colorB=ebcb8b)](https://github.com/toddbirchard/plotlydash-flask-tutorial/issues)
1111
[![GitHub Stars](https://img.shields.io/github/stars/toddbirchard/plotlydash-flask-tutorial.svg?style=flat-square&colorB=ebcb8b&colorA=4c566a)](https://github.com/toddbirchard/plotlydash-flask-tutorial/stargazers)
@@ -18,7 +18,7 @@ Make Plotly Dash part of your Flask Application by following this example.
1818
* **Tutorial**: https://hackersandslackers.com/plotly-dash-with-flask/
1919
* **Demo**: https://plotlydashflask.hackersandslackers.app/
2020

21-
# Getting Started
21+
## Getting Started
2222

2323
Get set up locally in two steps:
2424

@@ -33,7 +33,6 @@ Replace the values in **.env.example** with your values and rename this file to
3333
* `LESS_RUN_IN_DEBUG` *(optional)*: Debug LESS while in `development`.
3434
* `COMPRESSOR_DEBUG` *(optional)*: Debug asset compression while in `development`.
3535

36-
3736
*Remember never to commit secrets saved in .env files to Github.*
3837

3938
### Installation
@@ -44,7 +43,7 @@ Get up and running with `make deploy`:
4443
$ git clone https://github.com/hackersandslackers/plotlydash-flask-tutorial.git
4544
$ cd dashboard-flask-tutorial
4645
$ make deploy
47-
```
46+
```
4847

4948
-----
5049

config.py

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
"""Flask config."""
22
from os import environ, path
33

4-
from dotenv import load_dotenv
5-
64
BASE_DIR = path.abspath(path.dirname(__file__))
7-
load_dotenv(path.join(BASE_DIR, ".env"))
85

96

107
class Config:
118
"""Flask configuration variables."""
129

1310
# General Config
14-
FLASK_APP = "wsgi.py"
15-
FLASK_ENV = environ.get("FLASK_ENV")
11+
ENVIRONMENT = environ.get("ENVIRONMENT")
12+
FLASK_APP = "main.py"
13+
FLASK_DEBUG = environ.get("FLASK_DEBUG")
1614
SECRET_KEY = environ.get("SECRET_KEY")
1715

1816
# Assets
File renamed without changes.

wsgi.py renamed to main.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
app = init_app()
55

66
if __name__ == "__main__":
7-
app.run(host="0.0.0.0")
7+
app.run(host="0.0.0.0", port=8083, debug=True, load_dotenv=True)

plotly_flask_tutorial/assets.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ def compile_static_assets(assets):
1919
extra={"rel": "stylesheet/less"},
2020
)
2121
assets.register("less_all", less_bundle)
22-
if app.config["FLASK_ENV"] == "development":
22+
if app.config["ENVIRONMENT"] == "development":
2323
less_bundle.build()
2424
return assets

plotly_flask_tutorial/dashboard/__init__.py

+24-13
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
"""Instantiate a Dash app."""
22
import dash
3-
from dash import dash_table
4-
from dash import dcc
5-
from dash import html
3+
from dash import dcc, html
4+
from dash.dash_table import DataTable
5+
from flask import Flask
6+
from pandas import DataFrame
67

78
from .data import create_dataframe
89
from .layout import html_layout
910

1011

11-
def init_dashboard(server):
12-
"""Create a Plotly Dash dashboard."""
13-
dash_app = dash.Dash(
14-
server=server,
12+
def init_dashboard(app: Flask):
13+
"""
14+
Create a Plotly Dash dashboard within a running Flask app.
15+
16+
:param Flask app: Top-level Flask application.
17+
"""
18+
dash_module = dash.Dash(
19+
server=app,
1520
routes_pathname_prefix="/dashapp/",
1621
external_stylesheets=[
1722
"/static/dist/css/styles.css",
@@ -23,10 +28,10 @@ def init_dashboard(server):
2328
df = create_dataframe()
2429

2530
# Custom HTML layout
26-
dash_app.index_string = html_layout
31+
dash_module.index_string = html_layout
2732

2833
# Create Layout
29-
dash_app.layout = html.Div(
34+
dash_module.layout = html.Div(
3035
children=[
3136
dcc.Graph(
3237
id="histogram-graph",
@@ -51,12 +56,18 @@ def init_dashboard(server):
5156
],
5257
id="dash-container",
5358
)
54-
return dash_app.server
59+
return dash_module.server
60+
61+
62+
def create_data_table(df: DataFrame) -> DataTable:
63+
"""
64+
Create Dash DataTable object from Pandas DataFrame.
5565
66+
:param DataFrame df: Pandas DataFrame from which to build a Dash table.
5667
57-
def create_data_table(df):
58-
"""Create Dash datatable from Pandas DataFrame."""
59-
table = dash_table.DataTable(
68+
:returns: DataTable
69+
"""
70+
table = DataTable(
6071
id="database-table",
6172
columns=[{"name": i, "id": i} for i in df.columns],
6273
data=df.to_dict("records"),

plotly_flask_tutorial/dashboard/data.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
"""Prepare data for Plotly Dash."""
22
import numpy as np
33
import pandas as pd
4+
from pandas import DataFrame
45

56

6-
def create_dataframe():
7+
def create_dataframe() -> DataFrame:
78
"""Create Pandas DataFrame from local CSV."""
8-
df = pd.read_csv("data/311-calls.csv", parse_dates=["created"])
9+
df = pd.read_csv("data/calls.csv", parse_dates=["created"])
910
df["created"] = df["created"].dt.date
1011
df.drop(columns=["incident_zip"], inplace=True)
1112
num_complaints = df["complaint_type"].value_counts()

plotly_flask_tutorial/dashboard/layout.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<header>
1414
<div class="nav-wrapper">
1515
<a href="/">
16-
<img src="/static/img/logo.png" class="logo" />
16+
<img src="/static/img/logo@2x.png" class="logo" />
1717
<h1>Plotly Dash Flask Tutorial</h1>
1818
</a>
1919
<nav>

plotly_flask_tutorial/routes.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
"""Routes for parent Flask app."""
22
from flask import current_app as app
3-
from flask import render_template
3+
from flask import render_template, request
44

55

66
@app.route("/")
77
def home():
8-
"""Landing page."""
8+
"""Home page of Flask Application."""
99
return render_template(
1010
"index.jinja2",
1111
title="Plotly Dash Flask Tutorial",
1212
description="Embed Plotly Dash into your Flask applications.",
1313
template="home-template",
1414
body="This is a homepage served with Flask.",
15+
base_url=request.base_url,
1516
)

0 commit comments

Comments
 (0)