diff --git a/.env.example b/.env.example
index ead0006..f2db431 100644
--- a/.env.example
+++ b/.env.example
@@ -1,4 +1,4 @@
FLASK_ENV=development
-FLASK_APP=wsgi.py
-FLASK_DEBUG=True
-LESS_BIN=/usr/local/bin/lessc
\ No newline at end of file
+SECRET_KEY="HGuitfI&uf6i7r&ujHFc"
+FLASK_DEBUG=False
+LESS_BIN="/Users/myuser/.nvm/versions/node/v18.18.1/bin/lessc"
\ No newline at end of file
diff --git a/.github/workflows/pythonapp.yml b/.github/workflows/pythonapp.yml
new file mode 100644
index 0000000..f79bc01
--- /dev/null
+++ b/.github/workflows/pythonapp.yml
@@ -0,0 +1,34 @@
+# This workflow will install Python dependencies, run tests and lint with a single version of Python
+# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
+
+name: Python application
+
+on:
+ push:
+ branches: [master]
+ pull_request:
+ branches: [master]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-python@v5
+ with:
+ python-version: "3.10"
+ cache: "pip" # caching pip dependencies
+
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install flake8 pytest
+ if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
+
+ - name: Lint with flake8
+ run: |
+ # stop the build if there are Python syntax errors or undefined names
+ flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
+ # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
+ flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
diff --git a/.gitignore b/.gitignore
index 9b7cc96..95f6b8c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,7 +23,6 @@ wheels/
.installed.cfg
*.egg
MANIFEST
-dist/
# PyInstaller
# Usually these files are written by a python script from a static
@@ -107,4 +106,5 @@ venv.bak/
.DS_Store
# idea
+.vscode
.idea
diff --git a/Makefile b/Makefile
index ce889d3..2c28df0 100644
--- a/Makefile
+++ b/Makefile
@@ -1,58 +1,96 @@
-SRCPATH := $(CURDIR)
-PROJECTNAME := $(shell basename $(CURDIR))
+PROJECT_NAME := $(shell basename $CURDIR)
+VIRTUAL_ENV := $(CURDIR)/.venv
+LOCAL_PYTHON := $(VIRTUAL_ENV)/bin/python3
define HELP
-Manage $(PROJECTNAME). Usage:
+Manage $(PROJECT_NAME). Usage:
+
+make run - Run $(PROJECT_NAME) locally.
+make install - Create local virtualenv & install dependencies.
+make deploy - Set up project & run locally.
+make update - Update dependencies via Poetry and output resulting `requirements.txt`.
+make format - Run Python code formatter & sort dependencies.
+make lint - Check code formatting with flake8.
+make clean - Remove extraneous compiled files, caches, logs, etc.
-make run - Run $(PROJECTNAME).
-make deploy - Install requirements and run app for the first time.
-make update - Update pip dependencies via Python Poetry.
-make format - Format code with Python's `Black` library.
-make clean - Remove cached files and lock files.
endef
export HELP
-.PHONY: run deploy update format clean help
-
-
-requirements: .requirements.txt
-
-
-.requirements.txt: requirements.txt
- $(shell . .venv/bin/activate && pip install -r requirements.txt)
+.PHONY: run install deploy update format lint clean help
all help:
@echo "$$HELP"
+env: $(VIRTUAL_ENV)
+
+$(VIRTUAL_ENV):
+ if [ ! -d $(VIRTUAL_ENV) ]; then \
+ echo "Creating Python virtual env in \`${VIRTUAL_ENV}\`"; \
+ python3 -m venv $(VIRTUAL_ENV); \
+ fi
.PHONY: run
-run:
- $(shell . .venv/bin/activate && python3 wsgi.py)
+run: env
+ $(LOCAL_PYTHON) -m gunicorn -w 4 wsgi:app
+.PHONY: install
+install: env
+ $(LOCAL_PYTHON) -m pip install --upgrade pip setuptools wheel && \
+ $(LOCAL_PYTHON) -m pip install -r requirements.txt && \
+ npm i -g less && \
+ echo Installed dependencies in \`${VIRTUAL_ENV}\`;
.PHONY: deploy
deploy:
- $(shell . ./deploy.sh)
+ make install && \
+ make run
+.PHONY: test
+test: env
+ $(LOCAL_PYTHON) -m \
+ coverage run -m pytest -vv \
+ --disable-pytest-warnings && \
+ coverage html --title='Coverage Report' -d .reports && \
+ open .reports/index.html
.PHONY: update
-update:
- poetry shell && poetry update
- pip freeze > requirements.txt
- exit
-
+update: env
+ $(LOCAL_PYTHON) -m pip install --upgrade pip setuptools wheel && \
+ poetry update && \
+ poetry export -f requirements.txt --output requirements.txt --without-hashes && \
+ echo Installed dependencies in \`${VIRTUAL_ENV}\`;
.PHONY: format
-format: requirements
- $(shell . .venv/bin/activate)
- $(shell isort -rc ./)
- $(shell black ./)
+format: env
+ $(LOCAL_PYTHON) -m isort --multi-line=3 . && \
+ $(LOCAL_PYTHON) -m black .
+
+.PHONY: lint
+lint: env
+ $(LOCAL_PYTHON) -m flake8 . --count \
+ --select=E9,F63,F7,F82 \
+ --exclude .git,.github,__pycache__,.pytest_cache,.venv,logs,creds,.venv,docs,logs,.reports \
+ --show-source \
+ --statistics
.PHONY: clean
clean:
- find . -name '*.pyc' -delete
- find . -name '__pycache__' -delete
- find . -name 'poetry.lock' -delete
- find . -name 'Pipefile.lock' -delete
\ No newline at end of file
+ find . -name '.coverage' -delete && \
+ find . -name '*.pyc' -delete && \
+ find . -name '__pycache__' -delete && \
+ find . -name 'poetry.lock' -delete && \
+ find . -name '*.log' -delete && \
+ find . -name '.DS_Store' -delete && \
+ find . -name 'Pipfile' -delete && \
+ find . -name 'Pipfile.lock' -delete && \
+ find . -wholename '**/*.pyc' -delete && \
+ find . -wholename '**/*.html' -delete && \
+ find . -type d -wholename '__pycache__' -exec rm -rf {} + && \
+ find . -type d -wholename '.venv' -exec rm -rf {} + && \
+ find . -type d -wholename '.pytest_cache' -exec rm -rf {} + && \
+ find . -type d -wholename '**/.pytest_cache' -exec rm -rf {} + && \
+ find . -type d -wholename '**/*.log' -exec rm -rf {} + && \
+ find . -type d -wholename './.reports/*' -exec rm -rf {} + && \
+ find . -type d -wholename '**/.webassets-cache' -exec rm -rf {} +
\ No newline at end of file
diff --git a/Pipfile b/Pipfile
deleted file mode 100644
index b7d9154..0000000
--- a/Pipfile
+++ /dev/null
@@ -1,17 +0,0 @@
-[[source]]
-name = "pypi"
-url = "https://pypi.org/simple"
-verify_ssl = true
-
-[dev-packages]
-
-[packages]
-Flask = "*"
-Flask-Assets = "*"
-Python-Dotenv = "*"
-Lesscpy = "*"
-CSSMin = "*"
-JSMin = "*"
-
-[requires]
-python_version = "3.8"
diff --git a/Pipfile.lock b/Pipfile.lock
deleted file mode 100644
index cc72ea6..0000000
--- a/Pipfile.lock
+++ /dev/null
@@ -1,160 +0,0 @@
-{
- "_meta": {
- "hash": {
- "sha256": "e1b93329e37431bead2dd6e0bee7f79b1b04c24aa3e554d64e75a0d1a679c3a4"
- },
- "pipfile-spec": 6,
- "requires": {
- "python_version": "3.8"
- },
- "sources": [
- {
- "name": "pypi",
- "url": "https://pypi.org/simple",
- "verify_ssl": true
- }
- ]
- },
- "default": {
- "click": {
- "hashes": [
- "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a",
- "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"
- ],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
- "version": "==7.1.2"
- },
- "cssmin": {
- "hashes": [
- "sha256:e012f0cc8401efcf2620332339011564738ae32be8c84b2e43ce8beaec1067b6"
- ],
- "index": "pypi",
- "version": "==0.2.0"
- },
- "flask": {
- "hashes": [
- "sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060",
- "sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557"
- ],
- "index": "pypi",
- "version": "==1.1.2"
- },
- "flask-assets": {
- "hashes": [
- "sha256:1dfdea35e40744d46aada72831f7613d67bf38e8b20ccaaa9e91fdc37aa3b8c2",
- "sha256:2845bd3b479be9db8556801e7ebc2746ce2d9edb4e7b64a1c786ecbfc1e5867b"
- ],
- "index": "pypi",
- "version": "==2.0"
- },
- "itsdangerous": {
- "hashes": [
- "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19",
- "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"
- ],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==1.1.0"
- },
- "jinja2": {
- "hashes": [
- "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0",
- "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035"
- ],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
- "version": "==2.11.2"
- },
- "jsmin": {
- "hashes": [
- "sha256:b6df99b2cd1c75d9d342e4335b535789b8da9107ec748212706ef7bbe5c2553b"
- ],
- "index": "pypi",
- "version": "==2.2.2"
- },
- "lesscpy": {
- "hashes": [
- "sha256:7b664f60818a16afa8cc9f1dd6d9b17f944e0ce94e50787d76f81bc7a8648cce",
- "sha256:b0f2f853ee1dfb0891b147b57028057d5389510e079581e7b533d07dc0d95d3e"
- ],
- "index": "pypi",
- "version": "==0.14.0"
- },
- "markupsafe": {
- "hashes": [
- "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
- "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
- "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
- "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
- "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42",
- "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
- "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
- "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
- "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
- "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
- "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
- "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b",
- "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
- "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15",
- "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
- "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
- "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
- "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
- "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
- "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
- "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
- "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
- "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
- "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
- "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
- "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
- "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
- "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
- "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
- "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
- "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2",
- "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7",
- "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"
- ],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==1.1.1"
- },
- "ply": {
- "hashes": [
- "sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3",
- "sha256:096f9b8350b65ebd2fd1346b12452efe5b9607f7482813ffca50c22722a807ce"
- ],
- "version": "==3.11"
- },
- "python-dotenv": {
- "hashes": [
- "sha256:8c10c99a1b25d9a68058a1ad6f90381a62ba68230ca93966882a4dbc3bc9c33d",
- "sha256:c10863aee750ad720f4f43436565e4c1698798d763b63234fb5021b6c616e423"
- ],
- "index": "pypi",
- "version": "==0.14.0"
- },
- "six": {
- "hashes": [
- "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
- "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
- ],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==1.15.0"
- },
- "webassets": {
- "hashes": [
- "sha256:167132337677c8cedc9705090f6d48da3fb262c8e0b2773b29f3352f050181cd",
- "sha256:a31a55147752ba1b3dc07dee0ad8c8efff274464e08bbdb88c1fd59ffd552724"
- ],
- "version": "==2.0"
- },
- "werkzeug": {
- "hashes": [
- "sha256:2de2a5db0baeae7b2d2664949077c2ac63fbd16d98da0ff71837f7d1dea3fd43",
- "sha256:6c80b1e5ad3665290ea39320b91e1be1e0d5f60652b964a3070216de83d2e47c"
- ],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
- "version": "==1.0.1"
- }
- },
- "develop": {}
-}
diff --git a/README.md b/README.md
index 61df1e0..8d1fe19 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,9 @@
# Flask-Assets Tutorial
-![Python](https://img.shields.io/badge/Python-v3.8-blue.svg?logo=python&longCache=true&logoColor=white&colorB=5e81ac&style=flat-square&colorA=4c566a)
-![Flask](https://img.shields.io/badge/Flask-v1.1.1-blue.svg?longCache=true&logo=flask&style=flat-square&logoColor=white&colorB=5e81ac&colorA=4c566a)
-![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)
+![Python](https://img.shields.io/badge/Python-v3.10-blue.svg?logo=python&longCache=true&logoColor=white&colorB=5e81ac&style=flat-square&colorA=4c566a)
+![Flask](https://img.shields.io/badge/Flask-v3.0.0-blue.svg?longCache=true&logo=flask&style=flat-square&logoColor=white&colorB=5e81ac&colorA=4c566a)
+![Flask-Assets](https://img.shields.io/badge/Flask--Assets-v2.1.0-blue.svg?longCache=true&logo=flask&style=flat-square&logoColor=white&colorB=5e81ac&colorA=4c566a)
+![Gunicorn](https://img.shields.io/badge/Gunicorn-v21.2.0-blue.svg?longCache=true&logo=gunicorn&style=flat-square&logoColor=white&colorB=a3be8c&colorA=4c566a)
![GitHub Last Commit](https://img.shields.io/github/last-commit/google/skia.svg?style=flat-square&colorA=4c566a&colorB=a3be8c&logo=GitHub)
[![GitHub Issues](https://img.shields.io/github/issues/hackersandslackers/flask-assets-tutorial.svg?style=flat-square&colorA=4c566a&logo=GitHub&colorB=ebcb8b)](https://github.com/hackersandslackers/flask-assets-tutorial/issues)
[![GitHub Stars](https://img.shields.io/github/stars/hackersandslackers/flask-assets-tutorial.svg?style=flat-square&colorA=4c566a&logo=GitHub&colorB=ebcb8b)](https://github.com/hackersandslackers/flask-assets-tutorial/stargazers)
@@ -10,9 +11,12 @@
![Flask Assets Tutorial](https://github.com/hackersandslackers/flask-assets-tutorial/blob/master/.github/flask-assets@2x.jpg?raw=true)
-Build and code-split your frontend assets across Blueprints using Flask-Assets. Accompanying tutorial on Hackers and Slackers here: https://hackersandslackers.com/flask-assets/
+Build and code-split your frontend assets across Blueprints using Flask-Assets.
-# Getting Started
+* **Tutorial**: [https://hackersandslackers.com/flask-assets/](https://hackersandslackers.com/flask-assets/)
+* **Demo**: [https://flaskassets.hackersandslackers.app/](https://flaskassets.hackersandslackers.app/)
+
+## Getting Started
Get set up locally in two steps:
@@ -20,8 +24,8 @@ Get set up locally in two steps:
Replace the values in **.env.example** with your values and rename this file to **.env**:
-* `FLASK_APP`: Entry point of your application; should be `wsgi.py`.
-* `FLASK_ENV`: The environment in which run your application; either `development` or `production`.
+* `ENVIRONMENT`: The environment in which to run your application (either `development` or `production`).
+* `FLASK_DEBUG`: Set to `True` to enable Flask's debug mode (default to `False` in prod).
* `SECRET_KEY`: Randomly generated string of characters used to encrypt your app's data.
* `LESS_BIN`: Path to your local LESS installation via `which lessc`.
@@ -32,10 +36,10 @@ Replace the values in **.env.example** with your values and rename this file to
Get up and running with `make deploy`:
```shell
-$ git clone https://github.com/hackersandslackers/flask-assets-tutorial.git
-$ cd flask-assets-tutorial
-$ make deploy
-```
+git clone https://github.com/hackersandslackers/flask-assets-tutorial.git
+cd flask-assets-tutorial
+make deploy
+```
-----
diff --git a/config.py b/config.py
index 84380fa..cb1f62d 100644
--- a/config.py
+++ b/config.py
@@ -1,26 +1,29 @@
"""Flask configuration variables."""
from os import environ, path
+
from dotenv import load_dotenv
basedir = path.abspath(path.dirname(__file__))
-load_dotenv(path.join(basedir, '.env'))
+load_dotenv(path.join(basedir, ".env"))
class Config:
"""Set Flask configuration from .env file."""
# General Config
- SECRET_KEY = environ.get('SECRET_KEY')
- FLASK_APP = environ.get('FLASK_APP')
- FLASK_ENV = environ.get('FLASK_ENV')
+ ENVIRONMENT = environ.get("ENVIRONMENT")
+
+ # Flask Config
+ FLASK_APP = "wsgi.py"
+ SECRET_KEY = environ.get("SECRET_KEY")
+ FLASK_DEBUG = environ.get("FLASK_DEBUG")
# Flask-Assets
- LESS_BIN = environ.get('LESS_BIN')
+ LESS_BIN = environ.get("LESS_BIN")
ASSETS_DEBUG = True
LESS_RUN_IN_DEBUG = True
# Static Assets
- STATIC_FOLDER = 'static'
- TEMPLATES_FOLDER = 'templates'
+ STATIC_FOLDER = "static"
+ TEMPLATES_FOLDER = "templates"
COMPRESSOR_DEBUG = True
-
diff --git a/deploy.sh b/deploy.sh
deleted file mode 100644
index 038a8aa..0000000
--- a/deploy.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/bash
-
-if [ -d ".venv" ]
-then
- source .venv/bin/activate
- pip install -r requirements.txt
- python3 wsgi.py
-else
- python3 -m venv .venv
- source .venv/bin/activate
- python3 -m pip install --upgrade pip
- pip install -r requirements.txt
- python3 wsgi.py
-fi
diff --git a/flask_assets_tutorial/__init__.py b/flask_assets_tutorial/__init__.py
index f19b884..fefbe8d 100644
--- a/flask_assets_tutorial/__init__.py
+++ b/flask_assets_tutorial/__init__.py
@@ -6,7 +6,7 @@
def create_app():
"""Construct core Flask app."""
app = Flask(__name__, instance_relative_config=False)
- app.config.from_object('config.Config')
+ app.config.from_object("config.Config")
assets = Environment()
assets.init_app(app)
@@ -16,14 +16,15 @@ def create_app():
with app.app_context():
# Import parts of our flask_assets_tutorial
from .admin import admin_routes
+ from .assets import compile_static_assets, compile_stylesheet_bundles
from .main import main_routes
- from .assets import compile_static_assets
# Register Blueprints
- app.register_blueprint(admin_routes.admin_bp)
- app.register_blueprint(main_routes.main_bp)
+ app.register_blueprint(admin_routes.admin_blueprint)
+ app.register_blueprint(main_routes.main_blueprint)
# Compile static assets
+ compile_stylesheet_bundles(assets)
compile_static_assets(assets)
return app
diff --git a/flask_assets_tutorial/admin/admin_routes.py b/flask_assets_tutorial/admin/admin_routes.py
index 3fb6bed..88e7573 100644
--- a/flask_assets_tutorial/admin/admin_routes.py
+++ b/flask_assets_tutorial/admin/admin_routes.py
@@ -1,21 +1,15 @@
"""Routes for logged-in account pages."""
from flask import Blueprint, render_template
+admin_blueprint = Blueprint("admin_blueprint", __name__, template_folder="templates", static_folder="static")
-admin_bp = Blueprint(
- 'admin_bp',
- __name__,
- template_folder='templates',
- static_folder='static'
-)
-
-@admin_bp.route('/dashboard', methods=['GET'])
+@admin_blueprint.route("/dashboard", methods=["GET"])
def dashboard():
"""Admin dashboard route."""
return render_template(
- 'dashboard.jinja2',
- title='Admin Dashboard | Flask-Blueprint Tutorial',
- template='dashboard-static account',
- body="Account"
+ "dashboard.jinja2",
+ title="Admin Dashboard | Flask-Blueprint Tutorial",
+ template="dashboard-static account",
+ body="Account",
)
diff --git a/flask_assets_tutorial/assets.py b/flask_assets_tutorial/assets.py
index 35db170..35d2440 100644
--- a/flask_assets_tutorial/assets.py
+++ b/flask_assets_tutorial/assets.py
@@ -1,34 +1,46 @@
"""Compile static assets."""
from flask import current_app as app
-from flask_assets import Bundle
+from flask_assets import Bundle, Environment
-def compile_static_assets(assets):
- """Configure and build asset bundles."""
+def compile_stylesheet_bundles(assets: Environment):
+ """
+ Create minified CSS bundles from LESS styles.
+
+ :param Environment assets: Flask `environment` for static assets.
+ """
+ # Main Stylesheets Bundle
main_style_bundle = Bundle(
- 'src/less/*.less',
- 'main_bp/homepage.less',
- filters='less,cssmin',
- output='dist/css/landing.css',
- extra={'rel': 'stylesheet/css'}
- ) # Main Stylesheets Bundle
- main_js_bundle = Bundle(
- 'src/js/main.js',
- filters='jsmin',
- output='dist/js/main.min.js'
- ) # Main JavaScript Bundle
+ "src/less/*.less",
+ "main_blueprint/homepage.less",
+ filters="less,cssmin",
+ output="dist/css/landing.css",
+ extra={"rel": "stylesheet/css"},
+ )
+ # Admin Stylesheets Bundle
admin_style_bundle = Bundle(
- 'src/less/*.less',
- 'admin_bp/admin.less',
- filters='less,cssmin',
- output='dist/css/account.css',
- extra={'rel': 'stylesheet/css'}
- ) # Admin Stylesheets Bundle
- assets.register('main_styles', main_style_bundle)
- assets.register('main_js', main_js_bundle)
- assets.register('admin_styles', admin_style_bundle)
- if app.config['FLASK_ENV'] != 'production':
+ "src/less/*.less",
+ "admin_blueprint/admin.less",
+ filters="less,cssmin",
+ output="dist/css/account.css",
+ extra={"rel": "stylesheet/css"},
+ )
+ assets.register("main_styles", main_style_bundle)
+ assets.register("admin_styles", admin_style_bundle)
+ if app.config["ENVIRONMENT"] == "development":
main_style_bundle.build()
- main_js_bundle.build()
admin_style_bundle.build()
return assets
+
+
+def compile_static_assets(assets: Environment):
+ """
+ Create minified JS bundles from raw Javascript files.
+
+ :param Environment assets: Flask `environment` for static assets.
+ """
+ main_js_bundle = Bundle("src/js/main.js", filters="jsmin", output="dist/js/main.min.js") # Main JavaScript Bundle
+ assets.register("main_js", main_js_bundle)
+ if app.config["ENVIRONMENT"] != "production":
+ main_js_bundle.build()
+ return assets
diff --git a/flask_assets_tutorial/main/main_routes.py b/flask_assets_tutorial/main/main_routes.py
index 3bda3be..0b63925 100644
--- a/flask_assets_tutorial/main/main_routes.py
+++ b/flask_assets_tutorial/main/main_routes.py
@@ -1,43 +1,28 @@
"""Routes for main pages."""
from flask import Blueprint, render_template
+main_blueprint = Blueprint("main_blueprint", __name__, template_folder="templates", static_folder="static")
-main_bp = Blueprint(
- 'main_bp',
- __name__,
- template_folder='templates',
- static_folder='static'
-)
-
-@main_bp.route('/', methods=['GET'])
+@main_blueprint.route("/", methods=["GET"])
def home():
"""Homepage route."""
return render_template(
- 'index.jinja2',
- title='Home | Flask-Blueprint Tutorial',
- template='home-static main',
- body="Home"
+ "index.jinja2", title="Home | Flask-Blueprint Tutorial", template="home-static main", body="Home"
)
-@main_bp.route('/about', methods=['GET'])
+@main_blueprint.route("/about", methods=["GET"])
def about():
"""About page route."""
return render_template(
- 'index.jinja2',
- title='About | Flask-Blueprint Tutorial',
- template='about-static main',
- body="About"
+ "index.jinja2", title="About | Flask-Blueprint Tutorial", template="about-static main", body="About"
)
-@main_bp.route('/etc', methods=['GET'])
+@main_blueprint.route("/etc", methods=["GET"])
def etc():
"""Etc page route."""
return render_template(
- 'index.jinja2',
- title='Etc | Flask-Blueprint Tutorial',
- template='etc-static main',
- body="Etc"
+ "index.jinja2", title="Etc | Flask-Blueprint Tutorial", template="etc-static main", body="Etc"
)
diff --git a/flask_assets_tutorial/static/dist/css/account.css b/flask_assets_tutorial/static/dist/css/account.css
new file mode 100644
index 0000000..1e03221
--- /dev/null
+++ b/flask_assets_tutorial/static/dist/css/account.css
@@ -0,0 +1,123 @@
+nav {
+ background: #fff;
+ padding: 30px;
+ width: auto;
+ margin-bottom: 40px;
+ box-shadow: 0 0 5px #bec6cf;
+}
+nav .nav-wrapper {
+ max-width: 900px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ width: auto;
+ margin: 0 auto;
+}
+nav .nav-wrapper .left-nav {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+nav .nav-wrapper .left-nav img {
+ width: 30px;
+ margin-right: 40px;
+}
+nav .nav-wrapper .left-nav a {
+ margin-right: 20px;
+ font-weight: 400;
+}
+nav a {
+ color: #4d545d;
+ transition: all 0.2s ease-out;
+ text-decoration: none;
+}
+nav a:hover {
+ cursor: pointer;
+ opacity: 0.7;
+}
+body,
+html {
+ font-family: 'Poppins', sans-serif;
+ margin: 0;
+ padding: 0;
+ color: #2a2c2f;
+ background: #f0f0f0;
+ height: 100%;
+}
+ul {
+ list-style: none;
+ width: 50%;
+ border: 1px solid #e6e6e6;
+ padding: 10px;
+}
+ul li {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ border-bottom: 1px solid #ececec;
+ padding-bottom: 10px;
+ margin-bottom: 10px;
+}
+ul li:last-of-type {
+ border-bottom: none;
+ margin-bottom: 0;
+ padding-bottom: 0;
+}
+.container {
+ max-width: 847px;
+ margin: 0 auto;
+ min-height: 100%;
+ background: white;
+ padding: 40px;
+ box-shadow: 0 0 5px #bec6cf;
+}
+.container .attribute-value {
+ font-weight: 300;
+ font-size: 0.9em;
+}
+h1 {
+ margin-top: 0;
+}
+
+nav {
+ background: #fff;
+ padding: 30px;
+ width: auto;
+ margin-bottom: 40px;
+ box-shadow: 0 0 5px #bec6cf;
+}
+nav .nav-wrapper {
+ max-width: 900px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ width: auto;
+ margin: 0 auto;
+}
+nav .nav-wrapper .left-nav {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+nav .nav-wrapper .left-nav img {
+ width: 30px;
+ margin-right: 40px;
+}
+nav .nav-wrapper .left-nav a {
+ margin-right: 20px;
+ font-weight: 400;
+}
+nav a {
+ color: #4d545d;
+ transition: all 0.2s ease-out;
+ text-decoration: none;
+}
+nav a:hover {
+ cursor: pointer;
+ opacity: 0.7;
+}
+
+
+p {
+ width: 100%;
+}
diff --git a/flask_assets_tutorial/static/dist/css/landing.css b/flask_assets_tutorial/static/dist/css/landing.css
new file mode 100644
index 0000000..1e03221
--- /dev/null
+++ b/flask_assets_tutorial/static/dist/css/landing.css
@@ -0,0 +1,123 @@
+nav {
+ background: #fff;
+ padding: 30px;
+ width: auto;
+ margin-bottom: 40px;
+ box-shadow: 0 0 5px #bec6cf;
+}
+nav .nav-wrapper {
+ max-width: 900px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ width: auto;
+ margin: 0 auto;
+}
+nav .nav-wrapper .left-nav {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+nav .nav-wrapper .left-nav img {
+ width: 30px;
+ margin-right: 40px;
+}
+nav .nav-wrapper .left-nav a {
+ margin-right: 20px;
+ font-weight: 400;
+}
+nav a {
+ color: #4d545d;
+ transition: all 0.2s ease-out;
+ text-decoration: none;
+}
+nav a:hover {
+ cursor: pointer;
+ opacity: 0.7;
+}
+body,
+html {
+ font-family: 'Poppins', sans-serif;
+ margin: 0;
+ padding: 0;
+ color: #2a2c2f;
+ background: #f0f0f0;
+ height: 100%;
+}
+ul {
+ list-style: none;
+ width: 50%;
+ border: 1px solid #e6e6e6;
+ padding: 10px;
+}
+ul li {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ border-bottom: 1px solid #ececec;
+ padding-bottom: 10px;
+ margin-bottom: 10px;
+}
+ul li:last-of-type {
+ border-bottom: none;
+ margin-bottom: 0;
+ padding-bottom: 0;
+}
+.container {
+ max-width: 847px;
+ margin: 0 auto;
+ min-height: 100%;
+ background: white;
+ padding: 40px;
+ box-shadow: 0 0 5px #bec6cf;
+}
+.container .attribute-value {
+ font-weight: 300;
+ font-size: 0.9em;
+}
+h1 {
+ margin-top: 0;
+}
+
+nav {
+ background: #fff;
+ padding: 30px;
+ width: auto;
+ margin-bottom: 40px;
+ box-shadow: 0 0 5px #bec6cf;
+}
+nav .nav-wrapper {
+ max-width: 900px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ width: auto;
+ margin: 0 auto;
+}
+nav .nav-wrapper .left-nav {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+nav .nav-wrapper .left-nav img {
+ width: 30px;
+ margin-right: 40px;
+}
+nav .nav-wrapper .left-nav a {
+ margin-right: 20px;
+ font-weight: 400;
+}
+nav a {
+ color: #4d545d;
+ transition: all 0.2s ease-out;
+ text-decoration: none;
+}
+nav a:hover {
+ cursor: pointer;
+ opacity: 0.7;
+}
+
+
+p {
+ width: 100%;
+}
diff --git a/flask_assets_tutorial/static/img/favicon.png b/flask_assets_tutorial/static/dist/img/favicon.png
similarity index 100%
rename from flask_assets_tutorial/static/img/favicon.png
rename to flask_assets_tutorial/static/dist/img/favicon.png
diff --git a/flask_assets_tutorial/static/dist/img/favicon@2x.png b/flask_assets_tutorial/static/dist/img/favicon@2x.png
new file mode 100644
index 0000000..61bdc13
Binary files /dev/null and b/flask_assets_tutorial/static/dist/img/favicon@2x.png differ
diff --git a/flask_assets_tutorial/static/img/logo.png b/flask_assets_tutorial/static/dist/img/logo.png
similarity index 100%
rename from flask_assets_tutorial/static/img/logo.png
rename to flask_assets_tutorial/static/dist/img/logo.png
diff --git a/flask_assets_tutorial/static/dist/img/logo@2x.png b/flask_assets_tutorial/static/dist/img/logo@2x.png
new file mode 100644
index 0000000..61bdc13
Binary files /dev/null and b/flask_assets_tutorial/static/dist/img/logo@2x.png differ
diff --git a/flask_assets_tutorial/static/dist/js/main.min.js b/flask_assets_tutorial/static/dist/js/main.min.js
new file mode 100644
index 0000000..9785fa2
--- /dev/null
+++ b/flask_assets_tutorial/static/dist/js/main.min.js
@@ -0,0 +1 @@
+let alertbutton=document.querySelector('.alert button');if(alertbutton){alertbutton.addEventListener('click',function(event){if(!event.target===alertbutton)return;alertbutton.parentNode.style.display='none';event.preventDefault();},false);}
\ No newline at end of file
diff --git a/flask_assets_tutorial/templates/layout.jinja2 b/flask_assets_tutorial/templates/layout.jinja2
index d56e280..bdf5d9f 100644
--- a/flask_assets_tutorial/templates/layout.jinja2
+++ b/flask_assets_tutorial/templates/layout.jinja2
@@ -13,7 +13,7 @@
{% block content %}{% endblock %}
-
+ {# Scripts #}
{% block additionalscripts %}{% endblock %}
{% include 'analytics.jinja2' %}
diff --git a/flask_assets_tutorial/templates/meta.jinja2 b/flask_assets_tutorial/templates/meta.jinja2
index dd92305..2f28a5d 100644
--- a/flask_assets_tutorial/templates/meta.jinja2
+++ b/flask_assets_tutorial/templates/meta.jinja2
@@ -2,8 +2,16 @@
{{title}}
-
-
+
+
+
+
+
+
+
+
+
+
-
+
{% endblock %}
diff --git a/flask_assets_tutorial/templates/navigation-default.jinja2 b/flask_assets_tutorial/templates/navigation-default.jinja2
index f15d5f8..b918eba 100644
--- a/flask_assets_tutorial/templates/navigation-default.jinja2
+++ b/flask_assets_tutorial/templates/navigation-default.jinja2
@@ -1,13 +1,13 @@
\ No newline at end of file
diff --git a/flask_assets_tutorial/templates/navigation-loggedin.jinja2 b/flask_assets_tutorial/templates/navigation-loggedin.jinja2
index 36ed7a8..eeddc89 100644
--- a/flask_assets_tutorial/templates/navigation-loggedin.jinja2
+++ b/flask_assets_tutorial/templates/navigation-loggedin.jinja2
@@ -3,7 +3,7 @@
diff --git a/poetry.lock b/poetry.lock
index 140a669..21455ae 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,542 +1,475 @@
-[[package]]
-category = "dev"
-description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
-name = "appdirs"
-optional = false
-python-versions = "*"
-version = "1.4.4"
-
-[[package]]
-category = "dev"
-description = "Atomic file writes."
-marker = "sys_platform == \"win32\""
-name = "atomicwrites"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "1.4.0"
+# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
[[package]]
-category = "dev"
-description = "Classes Without Boilerplate"
-name = "attrs"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "20.2.0"
-
-[package.extras]
-dev = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "sphinx-rtd-theme", "pre-commit"]
-docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"]
-tests = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"]
-tests_no_zope = ["coverage (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"]
-
-[[package]]
-category = "dev"
-description = "The uncompromising code formatter."
name = "black"
+version = "23.12.0"
+description = "The uncompromising code formatter."
optional = false
-python-versions = ">=3.6"
-version = "20.8b1"
+python-versions = ">=3.8"
+files = [
+ {file = "black-23.12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:67f19562d367468ab59bd6c36a72b2c84bc2f16b59788690e02bbcb140a77175"},
+ {file = "black-23.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bbd75d9f28a7283b7426160ca21c5bd640ca7cd8ef6630b4754b6df9e2da8462"},
+ {file = "black-23.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:593596f699ca2dcbbbdfa59fcda7d8ad6604370c10228223cd6cf6ce1ce7ed7e"},
+ {file = "black-23.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:12d5f10cce8dc27202e9a252acd1c9a426c83f95496c959406c96b785a92bb7d"},
+ {file = "black-23.12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e73c5e3d37e5a3513d16b33305713237a234396ae56769b839d7c40759b8a41c"},
+ {file = "black-23.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ba09cae1657c4f8a8c9ff6cfd4a6baaf915bb4ef7d03acffe6a2f6585fa1bd01"},
+ {file = "black-23.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ace64c1a349c162d6da3cef91e3b0e78c4fc596ffde9413efa0525456148873d"},
+ {file = "black-23.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:72db37a2266b16d256b3ea88b9affcdd5c41a74db551ec3dd4609a59c17d25bf"},
+ {file = "black-23.12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fdf6f23c83078a6c8da2442f4d4eeb19c28ac2a6416da7671b72f0295c4a697b"},
+ {file = "black-23.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:39dda060b9b395a6b7bf9c5db28ac87b3c3f48d4fdff470fa8a94ab8271da47e"},
+ {file = "black-23.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7231670266ca5191a76cb838185d9be59cfa4f5dd401b7c1c70b993c58f6b1b5"},
+ {file = "black-23.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:193946e634e80bfb3aec41830f5d7431f8dd5b20d11d89be14b84a97c6b8bc75"},
+ {file = "black-23.12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bcf91b01ddd91a2fed9a8006d7baa94ccefe7e518556470cf40213bd3d44bbbc"},
+ {file = "black-23.12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:996650a89fe5892714ea4ea87bc45e41a59a1e01675c42c433a35b490e5aa3f0"},
+ {file = "black-23.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bdbff34c487239a63d86db0c9385b27cdd68b1bfa4e706aa74bb94a435403672"},
+ {file = "black-23.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:97af22278043a6a1272daca10a6f4d36c04dfa77e61cbaaf4482e08f3640e9f0"},
+ {file = "black-23.12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ead25c273adfad1095a8ad32afdb8304933efba56e3c1d31b0fee4143a1e424a"},
+ {file = "black-23.12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c71048345bdbced456cddf1622832276d98a710196b842407840ae8055ade6ee"},
+ {file = "black-23.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a832b6e00eef2c13b3239d514ea3b7d5cc3eaa03d0474eedcbbda59441ba5d"},
+ {file = "black-23.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:6a82a711d13e61840fb11a6dfecc7287f2424f1ca34765e70c909a35ffa7fb95"},
+ {file = "black-23.12.0-py3-none-any.whl", hash = "sha256:a7c07db8200b5315dc07e331dda4d889a56f6bf4db6a9c2a526fa3166a81614f"},
+ {file = "black-23.12.0.tar.gz", hash = "sha256:330a327b422aca0634ecd115985c1c7fd7bdb5b5a2ef8aa9888a82e2ebe9437a"},
+]
[package.dependencies]
-appdirs = "*"
-click = ">=7.1.2"
+click = ">=8.0.0"
mypy-extensions = ">=0.4.3"
-pathspec = ">=0.6,<1"
-regex = ">=2020.1.8"
-toml = ">=0.10.1"
-typed-ast = ">=1.4.0"
-typing-extensions = ">=3.7.4"
+packaging = ">=22.0"
+pathspec = ">=0.9.0"
+platformdirs = ">=2"
+tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
+typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""}
[package.extras]
colorama = ["colorama (>=0.4.3)"]
-d = ["aiohttp (>=3.3.2)", "aiohttp-cors"]
+d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"]
+jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
+uvloop = ["uvloop (>=0.15.2)"]
+
+[[package]]
+name = "blinker"
+version = "1.7.0"
+description = "Fast, simple object-to-object and broadcast signaling"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "blinker-1.7.0-py3-none-any.whl", hash = "sha256:c3f865d4d54db7abc53758a01601cf343fe55b84c1de4e3fa910e420b438d5b9"},
+ {file = "blinker-1.7.0.tar.gz", hash = "sha256:e6820ff6fa4e4d1d8e2747c2283749c3f547e4fee112b98555cdcdae32996182"},
+]
[[package]]
-category = "main"
-description = "Composable command line interface toolkit"
name = "click"
+version = "8.1.7"
+description = "Composable command line interface toolkit"
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-version = "7.1.2"
+python-versions = ">=3.7"
+files = [
+ {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
+ {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "platform_system == \"Windows\""}
[[package]]
-category = "dev"
-description = "Cross-platform colored terminal text."
-marker = "sys_platform == \"win32\""
name = "colorama"
+version = "0.4.6"
+description = "Cross-platform colored terminal text."
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-version = "0.4.4"
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
[[package]]
-category = "main"
-description = "A Python port of the YUI CSS compression algorithm."
name = "cssmin"
+version = "0.2.0"
+description = "A Python port of the YUI CSS compression algorithm."
optional = false
python-versions = "*"
-version = "0.2.0"
+files = [
+ {file = "cssmin-0.2.0.tar.gz", hash = "sha256:e012f0cc8401efcf2620332339011564738ae32be8c84b2e43ce8beaec1067b6"},
+]
+
+[[package]]
+name = "exceptiongroup"
+version = "1.2.0"
+description = "Backport of PEP 654 (exception groups)"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"},
+ {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"},
+]
+
+[package.extras]
+test = ["pytest (>=6)"]
[[package]]
-category = "main"
-description = "A simple framework for building complex web applications."
name = "flask"
+version = "3.0.0"
+description = "A simple framework for building complex web applications."
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-version = "1.1.2"
+python-versions = ">=3.8"
+files = [
+ {file = "flask-3.0.0-py3-none-any.whl", hash = "sha256:21128f47e4e3b9d597a3e8521a329bf56909b690fcc3fa3e477725aa81367638"},
+ {file = "flask-3.0.0.tar.gz", hash = "sha256:cfadcdb638b609361d29ec22360d6070a77d7463dcb3ab08d2c2f2f168845f58"},
+]
[package.dependencies]
-Jinja2 = ">=2.10.1"
-Werkzeug = ">=0.15"
-click = ">=5.1"
-itsdangerous = ">=0.24"
+blinker = ">=1.6.2"
+click = ">=8.1.3"
+itsdangerous = ">=2.1.2"
+Jinja2 = ">=3.1.2"
+Werkzeug = ">=3.0.0"
[package.extras]
-dev = ["pytest", "coverage", "tox", "sphinx", "pallets-sphinx-themes", "sphinxcontrib-log-cabinet", "sphinx-issues"]
-docs = ["sphinx", "pallets-sphinx-themes", "sphinxcontrib-log-cabinet", "sphinx-issues"]
+async = ["asgiref (>=3.2)"]
dotenv = ["python-dotenv"]
[[package]]
-category = "main"
-description = "Asset management for Flask, to compress and merge CSS and Javascript files."
name = "flask-assets"
+version = "2.1.0"
+description = "Asset management for Flask, to compress and merge CSS and Javascript files."
optional = false
python-versions = "*"
-version = "2.0"
+files = [
+ {file = "Flask-Assets-2.1.0.tar.gz", hash = "sha256:f84d6532ffe59c9ff352885e8740ff4da25c0bcfacd805f0a806815e44354813"},
+ {file = "Flask_Assets-2.1.0-py3-none-any.whl", hash = "sha256:a56c476b15f84701712cc3b4b4a001ebbe62b1dcbe81c23f96fbe6f261b75324"},
+]
[package.dependencies]
Flask = ">=0.8"
webassets = ">=2.0"
[[package]]
-category = "dev"
-description = "iniconfig: brain-dead simple config-ini parsing"
+name = "gunicorn"
+version = "21.2.0"
+description = "WSGI HTTP Server for UNIX"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "gunicorn-21.2.0-py3-none-any.whl", hash = "sha256:3213aa5e8c24949e792bcacfc176fef362e7aac80b76c56f6b5122bf350722f0"},
+ {file = "gunicorn-21.2.0.tar.gz", hash = "sha256:88ec8bff1d634f98e61b9f65bc4bf3cd918a90806c6f5c48bc5603849ec81033"},
+]
+
+[package.dependencies]
+packaging = "*"
+
+[package.extras]
+eventlet = ["eventlet (>=0.24.1)"]
+gevent = ["gevent (>=1.4.0)"]
+setproctitle = ["setproctitle"]
+tornado = ["tornado (>=0.2)"]
+
+[[package]]
name = "iniconfig"
+version = "2.0.0"
+description = "brain-dead simple config-ini parsing"
optional = false
-python-versions = "*"
-version = "1.1.1"
+python-versions = ">=3.7"
+files = [
+ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
+ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
+]
[[package]]
-category = "dev"
-description = "A Python utility / library to sort Python imports."
name = "isort"
+version = "5.13.2"
+description = "A Python utility / library to sort Python imports."
optional = false
-python-versions = ">=3.6,<4.0"
-version = "5.6.4"
+python-versions = ">=3.8.0"
+files = [
+ {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"},
+ {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"},
+]
[package.extras]
-colors = ["colorama (>=0.4.3,<0.5.0)"]
-pipfile_deprecated_finder = ["pipreqs", "requirementslib"]
-requirements_deprecated_finder = ["pipreqs", "pip-api"]
+colors = ["colorama (>=0.4.6)"]
[[package]]
-category = "main"
-description = "Various helpers to pass data to untrusted environments and back."
name = "itsdangerous"
+version = "2.1.2"
+description = "Safely pass data to untrusted environments and back."
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "1.1.0"
+python-versions = ">=3.7"
+files = [
+ {file = "itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44"},
+ {file = "itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"},
+]
[[package]]
-category = "main"
-description = "A very fast and expressive template engine."
name = "jinja2"
+version = "3.1.2"
+description = "A very fast and expressive template engine."
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-version = "2.11.2"
+python-versions = ">=3.7"
+files = [
+ {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
+ {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
+]
[package.dependencies]
-MarkupSafe = ">=0.23"
+MarkupSafe = ">=2.0"
[package.extras]
-i18n = ["Babel (>=0.8)"]
+i18n = ["Babel (>=2.7)"]
[[package]]
-category = "main"
-description = "JavaScript minifier."
name = "jsmin"
+version = "3.0.1"
+description = "JavaScript minifier."
optional = false
python-versions = "*"
-version = "2.2.2"
+files = [
+ {file = "jsmin-3.0.1.tar.gz", hash = "sha256:c0959a121ef94542e807a674142606f7e90214a2b3d1eb17300244bbb5cc2bfc"},
+]
[[package]]
-category = "main"
-description = "Python LESS compiler"
name = "lesscpy"
+version = "0.15.1"
+description = "Python LESS compiler"
optional = false
python-versions = "*"
-version = "0.14.0"
+files = [
+ {file = "lesscpy-0.15.1-py2.py3-none-any.whl", hash = "sha256:8d26e58ed4812b345c2896daea435a28cb3182f87ae3391157085255d4c37dff"},
+ {file = "lesscpy-0.15.1.tar.gz", hash = "sha256:1045d17a98f688646ca758dff254e6e9c03745648e051a081b0395c3b77c824c"},
+]
[package.dependencies]
ply = "*"
-six = "*"
[[package]]
-category = "main"
-description = "Safely add untrusted strings to HTML/XML markup."
name = "markupsafe"
+version = "2.1.3"
+description = "Safely add untrusted strings to HTML/XML markup."
optional = false
-python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
-version = "1.1.1"
+python-versions = ">=3.7"
+files = [
+ {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"},
+ {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"},
+ {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"},
+]
[[package]]
-category = "dev"
-description = "Experimental type system extensions for programs checked with the mypy typechecker."
name = "mypy-extensions"
+version = "1.0.0"
+description = "Type system extensions for programs checked with the mypy type checker."
optional = false
-python-versions = "*"
-version = "0.4.3"
+python-versions = ">=3.5"
+files = [
+ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
+ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
+]
[[package]]
-category = "dev"
-description = "Core utilities for Python packages"
name = "packaging"
+version = "23.2"
+description = "Core utilities for Python packages"
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "20.4"
-
-[package.dependencies]
-pyparsing = ">=2.0.2"
-six = "*"
+python-versions = ">=3.7"
+files = [
+ {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"},
+ {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"},
+]
[[package]]
-category = "dev"
-description = "Utility library for gitignore style pattern matching of file paths."
name = "pathspec"
+version = "0.12.1"
+description = "Utility library for gitignore style pattern matching of file paths."
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-version = "0.8.0"
+python-versions = ">=3.8"
+files = [
+ {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"},
+ {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"},
+]
[[package]]
-category = "dev"
-description = "plugin and hook calling mechanisms for python"
-name = "pluggy"
+name = "platformdirs"
+version = "4.1.0"
+description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "0.13.1"
+python-versions = ">=3.8"
+files = [
+ {file = "platformdirs-4.1.0-py3-none-any.whl", hash = "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380"},
+ {file = "platformdirs-4.1.0.tar.gz", hash = "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420"},
+]
[package.extras]
-dev = ["pre-commit", "tox"]
+docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"]
+test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"]
[[package]]
-category = "main"
-description = "Python Lex & Yacc"
-name = "ply"
+name = "pluggy"
+version = "1.3.0"
+description = "plugin and hook calling mechanisms for python"
optional = false
-python-versions = "*"
-version = "3.11"
+python-versions = ">=3.8"
+files = [
+ {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"},
+ {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"},
+]
-[[package]]
-category = "dev"
-description = "library with cross-python path, ini-parsing, io, code, log facilities"
-name = "py"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "1.9.0"
+[package.extras]
+dev = ["pre-commit", "tox"]
+testing = ["pytest", "pytest-benchmark"]
[[package]]
-category = "dev"
-description = "Python parsing module"
-name = "pyparsing"
+name = "ply"
+version = "3.11"
+description = "Python Lex & Yacc"
optional = false
-python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
-version = "2.4.7"
+python-versions = "*"
+files = [
+ {file = "ply-3.11-py2.py3-none-any.whl", hash = "sha256:096f9b8350b65ebd2fd1346b12452efe5b9607f7482813ffca50c22722a807ce"},
+ {file = "ply-3.11.tar.gz", hash = "sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3"},
+]
[[package]]
-category = "dev"
-description = "pytest: simple powerful testing with Python"
name = "pytest"
+version = "7.4.3"
+description = "pytest: simple powerful testing with Python"
optional = false
-python-versions = ">=3.5"
-version = "6.1.1"
+python-versions = ">=3.7"
+files = [
+ {file = "pytest-7.4.3-py3-none-any.whl", hash = "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac"},
+ {file = "pytest-7.4.3.tar.gz", hash = "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5"},
+]
[package.dependencies]
-atomicwrites = ">=1.0"
-attrs = ">=17.4.0"
-colorama = "*"
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
iniconfig = "*"
packaging = "*"
-pluggy = ">=0.12,<1.0"
-py = ">=1.8.2"
-toml = "*"
+pluggy = ">=0.12,<2.0"
+tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
[package.extras]
-checkqa_mypy = ["mypy (0.780)"]
-testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
+testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
[[package]]
-category = "main"
-description = "Add .env support to your django/flask apps in development and deployments"
name = "python-dotenv"
+version = "1.0.0"
+description = "Read key-value pairs from a .env file and set them as environment variables"
optional = false
-python-versions = "*"
-version = "0.14.0"
+python-versions = ">=3.8"
+files = [
+ {file = "python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba"},
+ {file = "python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a"},
+]
[package.extras]
cli = ["click (>=5.0)"]
[[package]]
-category = "dev"
-description = "Alternative regular expression module, to replace re."
-name = "regex"
-optional = false
-python-versions = "*"
-version = "2020.10.15"
-
-[[package]]
-category = "main"
-description = "Python 2 and 3 compatibility utilities"
-name = "six"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
-version = "1.15.0"
-
-[[package]]
-category = "dev"
-description = "Python Library for Tom's Obvious, Minimal Language"
-name = "toml"
-optional = false
-python-versions = "*"
-version = "0.10.1"
-
-[[package]]
-category = "dev"
-description = "a fork of Python 2 and 3 ast modules with type comment support"
-name = "typed-ast"
+name = "tomli"
+version = "2.0.1"
+description = "A lil' TOML parser"
optional = false
-python-versions = "*"
-version = "1.4.1"
+python-versions = ">=3.7"
+files = [
+ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
+ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
+]
[[package]]
-category = "dev"
-description = "Backported and Experimental Type Hints for Python 3.5+"
name = "typing-extensions"
+version = "4.9.0"
+description = "Backported and Experimental Type Hints for Python 3.8+"
optional = false
-python-versions = "*"
-version = "3.7.4.3"
+python-versions = ">=3.8"
+files = [
+ {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"},
+ {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"},
+]
[[package]]
-category = "main"
-description = "Media asset management for Python, with glue code for various web frameworks"
name = "webassets"
+version = "2.0"
+description = "Media asset management for Python, with glue code for various web frameworks"
optional = false
python-versions = "*"
-version = "2.0"
+files = [
+ {file = "webassets-2.0-py3-none-any.whl", hash = "sha256:a31a55147752ba1b3dc07dee0ad8c8efff274464e08bbdb88c1fd59ffd552724"},
+ {file = "webassets-2.0.tar.gz", hash = "sha256:167132337677c8cedc9705090f6d48da3fb262c8e0b2773b29f3352f050181cd"},
+]
[[package]]
-category = "main"
-description = "The comprehensive WSGI web application library."
name = "werkzeug"
+version = "3.0.1"
+description = "The comprehensive WSGI web application library."
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-version = "1.0.1"
+python-versions = ">=3.8"
+files = [
+ {file = "werkzeug-3.0.1-py3-none-any.whl", hash = "sha256:90a285dc0e42ad56b34e696398b8122ee4c681833fb35b8334a095d82c56da10"},
+ {file = "werkzeug-3.0.1.tar.gz", hash = "sha256:507e811ecea72b18a404947aded4b3390e1db8f826b494d76550ef45bb3b1dcc"},
+]
+
+[package.dependencies]
+MarkupSafe = ">=2.1.1"
[package.extras]
-dev = ["pytest", "pytest-timeout", "coverage", "tox", "sphinx", "pallets-sphinx-themes", "sphinx-issues"]
-watchdog = ["watchdog"]
+watchdog = ["watchdog (>=2.3)"]
[metadata]
-content-hash = "20f8860c331396cb79c1219d005baa4997b67a041d29febaab9c9478336ab439"
-python-versions = "^3.8"
-
-[metadata.files]
-appdirs = [
- {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
- {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
-]
-atomicwrites = [
- {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
- {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
-]
-attrs = [
- {file = "attrs-20.2.0-py2.py3-none-any.whl", hash = "sha256:fce7fc47dfc976152e82d53ff92fa0407700c21acd20886a13777a0d20e655dc"},
- {file = "attrs-20.2.0.tar.gz", hash = "sha256:26b54ddbbb9ee1d34d5d3668dd37d6cf74990ab23c828c2888dccdceee395594"},
-]
-black = [
- {file = "black-20.8b1.tar.gz", hash = "sha256:1c02557aa099101b9d21496f8a914e9ed2222ef70336404eeeac8edba836fbea"},
-]
-click = [
- {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"},
- {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"},
-]
-colorama = [
- {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
- {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
-]
-cssmin = [
- {file = "cssmin-0.2.0.tar.gz", hash = "sha256:e012f0cc8401efcf2620332339011564738ae32be8c84b2e43ce8beaec1067b6"},
-]
-flask = [
- {file = "Flask-1.1.2-py2.py3-none-any.whl", hash = "sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557"},
- {file = "Flask-1.1.2.tar.gz", hash = "sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060"},
-]
-flask-assets = [
- {file = "Flask-Assets-2.0.tar.gz", hash = "sha256:1dfdea35e40744d46aada72831f7613d67bf38e8b20ccaaa9e91fdc37aa3b8c2"},
- {file = "Flask_Assets-2.0-py3-none-any.whl", hash = "sha256:2845bd3b479be9db8556801e7ebc2746ce2d9edb4e7b64a1c786ecbfc1e5867b"},
-]
-iniconfig = [
- {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
- {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
-]
-isort = [
- {file = "isort-5.6.4-py3-none-any.whl", hash = "sha256:dcab1d98b469a12a1a624ead220584391648790275560e1a43e54c5dceae65e7"},
- {file = "isort-5.6.4.tar.gz", hash = "sha256:dcaeec1b5f0eca77faea2a35ab790b4f3680ff75590bfcb7145986905aab2f58"},
-]
-itsdangerous = [
- {file = "itsdangerous-1.1.0-py2.py3-none-any.whl", hash = "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"},
- {file = "itsdangerous-1.1.0.tar.gz", hash = "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19"},
-]
-jinja2 = [
- {file = "Jinja2-2.11.2-py2.py3-none-any.whl", hash = "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035"},
- {file = "Jinja2-2.11.2.tar.gz", hash = "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0"},
-]
-jsmin = [
- {file = "jsmin-2.2.2.tar.gz", hash = "sha256:b6df99b2cd1c75d9d342e4335b535789b8da9107ec748212706ef7bbe5c2553b"},
-]
-lesscpy = [
- {file = "lesscpy-0.14.0-py2.py3-none-any.whl", hash = "sha256:b0f2f853ee1dfb0891b147b57028057d5389510e079581e7b533d07dc0d95d3e"},
- {file = "lesscpy-0.14.0.tar.gz", hash = "sha256:7b664f60818a16afa8cc9f1dd6d9b17f944e0ce94e50787d76f81bc7a8648cce"},
-]
-markupsafe = [
- {file = "MarkupSafe-1.1.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161"},
- {file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"},
- {file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183"},
- {file = "MarkupSafe-1.1.1-cp27-cp27m-win32.whl", hash = "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b"},
- {file = "MarkupSafe-1.1.1-cp27-cp27m-win_amd64.whl", hash = "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e"},
- {file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f"},
- {file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1"},
- {file = "MarkupSafe-1.1.1-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5"},
- {file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1"},
- {file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735"},
- {file = "MarkupSafe-1.1.1-cp34-cp34m-win32.whl", hash = "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21"},
- {file = "MarkupSafe-1.1.1-cp34-cp34m-win_amd64.whl", hash = "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235"},
- {file = "MarkupSafe-1.1.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b"},
- {file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f"},
- {file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905"},
- {file = "MarkupSafe-1.1.1-cp35-cp35m-win32.whl", hash = "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1"},
- {file = "MarkupSafe-1.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d"},
- {file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff"},
- {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473"},
- {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e"},
- {file = "MarkupSafe-1.1.1-cp36-cp36m-win32.whl", hash = "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66"},
- {file = "MarkupSafe-1.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5"},
- {file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d"},
- {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e"},
- {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"},
- {file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"},
- {file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"},
- {file = "MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15"},
- {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2"},
- {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42"},
- {file = "MarkupSafe-1.1.1-cp38-cp38-win32.whl", hash = "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b"},
- {file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"},
- {file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"},
-]
-mypy-extensions = [
- {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
- {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
-]
-packaging = [
- {file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"},
- {file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"},
-]
-pathspec = [
- {file = "pathspec-0.8.0-py2.py3-none-any.whl", hash = "sha256:7d91249d21749788d07a2d0f94147accd8f845507400749ea19c1ec9054a12b0"},
- {file = "pathspec-0.8.0.tar.gz", hash = "sha256:da45173eb3a6f2a5a487efba21f050af2b41948be6ab52b6a1e3ff22bb8b7061"},
-]
-pluggy = [
- {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
- {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
-]
-ply = [
- {file = "ply-3.11-py2.py3-none-any.whl", hash = "sha256:096f9b8350b65ebd2fd1346b12452efe5b9607f7482813ffca50c22722a807ce"},
- {file = "ply-3.11.tar.gz", hash = "sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3"},
-]
-py = [
- {file = "py-1.9.0-py2.py3-none-any.whl", hash = "sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2"},
- {file = "py-1.9.0.tar.gz", hash = "sha256:9ca6883ce56b4e8da7e79ac18787889fa5206c79dcc67fb065376cd2fe03f342"},
-]
-pyparsing = [
- {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
- {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
-]
-pytest = [
- {file = "pytest-6.1.1-py3-none-any.whl", hash = "sha256:7a8190790c17d79a11f847fba0b004ee9a8122582ebff4729a082c109e81a4c9"},
- {file = "pytest-6.1.1.tar.gz", hash = "sha256:8f593023c1a0f916110285b6efd7f99db07d59546e3d8c36fc60e2ab05d3be92"},
-]
-python-dotenv = [
- {file = "python-dotenv-0.14.0.tar.gz", hash = "sha256:8c10c99a1b25d9a68058a1ad6f90381a62ba68230ca93966882a4dbc3bc9c33d"},
- {file = "python_dotenv-0.14.0-py2.py3-none-any.whl", hash = "sha256:c10863aee750ad720f4f43436565e4c1698798d763b63234fb5021b6c616e423"},
-]
-regex = [
- {file = "regex-2020.10.15-cp27-cp27m-win32.whl", hash = "sha256:e935a166a5f4c02afe3f7e4ce92ce5a786f75c6caa0c4ce09c922541d74b77e8"},
- {file = "regex-2020.10.15-cp27-cp27m-win_amd64.whl", hash = "sha256:d81be22d5d462b96a2aa5c512f741255ba182995efb0114e5a946fe254148df1"},
- {file = "regex-2020.10.15-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:6d4cdb6c20e752426b2e569128488c5046fb1b16b1beadaceea9815c36da0847"},
- {file = "regex-2020.10.15-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:25991861c6fef1e5fd0a01283cf5658c5e7f7aa644128e85243bc75304e91530"},
- {file = "regex-2020.10.15-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:6e9f72e0ee49f7d7be395bfa29e9533f0507a882e1e6bf302c0a204c65b742bf"},
- {file = "regex-2020.10.15-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:578ac6379e65eb8e6a85299b306c966c852712c834dc7eef0ba78d07a828f67b"},
- {file = "regex-2020.10.15-cp36-cp36m-win32.whl", hash = "sha256:65b6b018b07e9b3b6a05c2c3bb7710ed66132b4df41926c243887c4f1ff303d5"},
- {file = "regex-2020.10.15-cp36-cp36m-win_amd64.whl", hash = "sha256:2f60ba5c33f00ce9be29a140e6f812e39880df8ba9cb92ad333f0016dbc30306"},
- {file = "regex-2020.10.15-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:5d4a3221f37520bb337b64a0632716e61b26c8ae6aaffceeeb7ad69c009c404b"},
- {file = "regex-2020.10.15-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:26b85672275d8c7a9d4ff93dbc4954f5146efdb2ecec89ad1de49439984dea14"},
- {file = "regex-2020.10.15-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:828618f3c3439c5e6ef8621e7c885ca561bbaaba90ddbb6a7dfd9e1ec8341103"},
- {file = "regex-2020.10.15-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:aef23aed9d4017cc74d37f703d57ce254efb4c8a6a01905f40f539220348abf9"},
- {file = "regex-2020.10.15-cp37-cp37m-win32.whl", hash = "sha256:6c72adb85adecd4522a488a751e465842cdd2a5606b65464b9168bf029a54272"},
- {file = "regex-2020.10.15-cp37-cp37m-win_amd64.whl", hash = "sha256:ef3a55b16c6450574734db92e0a3aca283290889934a23f7498eaf417e3af9f0"},
- {file = "regex-2020.10.15-cp38-cp38-manylinux1_i686.whl", hash = "sha256:8958befc139ac4e3f16d44ec386c490ea2121ed8322f4956f83dd9cad8e9b922"},
- {file = "regex-2020.10.15-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:3dd952f3f8dc01b72c0cf05b3631e05c50ac65ddd2afdf26551638e97502107b"},
- {file = "regex-2020.10.15-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:608d6c05452c0e6cc49d4d7407b4767963f19c4d2230fa70b7201732eedc84f2"},
- {file = "regex-2020.10.15-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:02686a2f0b1a4be0facdd0d3ad4dc6c23acaa0f38fb5470d892ae88584ba705c"},
- {file = "regex-2020.10.15-cp38-cp38-win32.whl", hash = "sha256:137da580d1e6302484be3ef41d72cf5c3ad22a076070051b7449c0e13ab2c482"},
- {file = "regex-2020.10.15-cp38-cp38-win_amd64.whl", hash = "sha256:20cdd7e1736f4f61a5161aa30d05ac108ab8efc3133df5eb70fe1e6a23ea1ca6"},
- {file = "regex-2020.10.15-cp39-cp39-manylinux1_i686.whl", hash = "sha256:85b733a1ef2b2e7001aff0e204a842f50ad699c061856a214e48cfb16ace7d0c"},
- {file = "regex-2020.10.15-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:af1f5e997dd1ee71fb6eb4a0fb6921bf7a778f4b62f1f7ef0d7445ecce9155d6"},
- {file = "regex-2020.10.15-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:b5eeaf4b5ef38fab225429478caf71f44d4a0b44d39a1aa4d4422cda23a9821b"},
- {file = "regex-2020.10.15-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:aeac7c9397480450016bc4a840eefbfa8ca68afc1e90648aa6efbfe699e5d3bb"},
- {file = "regex-2020.10.15-cp39-cp39-win32.whl", hash = "sha256:698f8a5a2815e1663d9895830a063098ae2f8f2655ae4fdc5dfa2b1f52b90087"},
- {file = "regex-2020.10.15-cp39-cp39-win_amd64.whl", hash = "sha256:a51e51eecdac39a50ede4aeed86dbef4776e3b73347d31d6ad0bc9648ba36049"},
- {file = "regex-2020.10.15.tar.gz", hash = "sha256:d25f5cca0f3af6d425c9496953445bf5b288bb5b71afc2b8308ad194b714c159"},
-]
-six = [
- {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"},
- {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"},
-]
-toml = [
- {file = "toml-0.10.1-py2.py3-none-any.whl", hash = "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"},
- {file = "toml-0.10.1.tar.gz", hash = "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f"},
-]
-typed-ast = [
- {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3"},
- {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb"},
- {file = "typed_ast-1.4.1-cp35-cp35m-win32.whl", hash = "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919"},
- {file = "typed_ast-1.4.1-cp35-cp35m-win_amd64.whl", hash = "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01"},
- {file = "typed_ast-1.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75"},
- {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652"},
- {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"},
- {file = "typed_ast-1.4.1-cp36-cp36m-win32.whl", hash = "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1"},
- {file = "typed_ast-1.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa"},
- {file = "typed_ast-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614"},
- {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41"},
- {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b"},
- {file = "typed_ast-1.4.1-cp37-cp37m-win32.whl", hash = "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe"},
- {file = "typed_ast-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355"},
- {file = "typed_ast-1.4.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6"},
- {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907"},
- {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d"},
- {file = "typed_ast-1.4.1-cp38-cp38-win32.whl", hash = "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c"},
- {file = "typed_ast-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4"},
- {file = "typed_ast-1.4.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34"},
- {file = "typed_ast-1.4.1.tar.gz", hash = "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b"},
-]
-typing-extensions = [
- {file = "typing_extensions-3.7.4.3-py2-none-any.whl", hash = "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"},
- {file = "typing_extensions-3.7.4.3-py3-none-any.whl", hash = "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918"},
- {file = "typing_extensions-3.7.4.3.tar.gz", hash = "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c"},
-]
-webassets = [
- {file = "webassets-2.0-py3-none-any.whl", hash = "sha256:a31a55147752ba1b3dc07dee0ad8c8efff274464e08bbdb88c1fd59ffd552724"},
- {file = "webassets-2.0.tar.gz", hash = "sha256:167132337677c8cedc9705090f6d48da3fb262c8e0b2773b29f3352f050181cd"},
-]
-werkzeug = [
- {file = "Werkzeug-1.0.1-py2.py3-none-any.whl", hash = "sha256:2de2a5db0baeae7b2d2664949077c2ac63fbd16d98da0ff71837f7d1dea3fd43"},
- {file = "Werkzeug-1.0.1.tar.gz", hash = "sha256:6c80b1e5ad3665290ea39320b91e1be1e0d5f60652b964a3070216de83d2e47c"},
-]
+lock-version = "2.0"
+python-versions = ">=3.10,<4.0"
+content-hash = "1cefee7201afdf1c906904384c9dbee5da986795fd191749b2e1b573b07ab3cd"
diff --git a/pyproject.toml b/pyproject.toml
index b5ec753..d99fcfe 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[tool.poetry]
name = "flask_assets_tutorial"
-version = "0.1.0"
+version = "0.1.1"
description = "Flask application which compiles ands serves frontend assets with Flask-Assets."
authors = ["Todd Birchard "]
maintainers = ["Todd Birchard "]
@@ -9,27 +9,20 @@ readme = "README.md"
homepage = "https://hackersandslackers.com/flask-assets/"
repository = "https://github.com/hackersandslackers/flask-assets-tutorial/"
documentation = "https://hackersandslackers.com/flask-assets/"
-keywords = [
- "Flask",
- "Flask-Assets",
- "Bundles",
- "Frontend",
- "Tutorial"
-]
+keywords = ["Flask", "Flask-Assets", "Bundles", "Frontend", "Tutorial"]
[tool.poetry.dependencies]
-python = "^3.8"
+python = ">=3.10,<4.0"
flask = "*"
flask-assets = "*"
lesscpy = "*"
cssmin = "*"
jsmin = "*"
python-dotenv = "*"
-
-[tool.poetry.dev-dependencies]
pytest = "*"
-black = "^20.8b1"
-isort = "^5.6.4"
+black = "*"
+isort = "*"
+gunicorn = "*"
[tool.poetry.scripts]
run = "wsgi:app"
@@ -38,6 +31,18 @@ run = "wsgi:app"
issues = "https://github.com/hackersandslackers/flask-assets-tutorial/issues"
[build-system]
-requires = ["poetry>=0.12"]
+requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.masonry.api"
+[tool.black]
+line-length = 120
+target-version = ['py310']
+src_paths = ["flask_assets_tutorial", "config", "wsgi"]
+
+[tool.isort]
+profile = "black"
+multi_line_output = 3
+src_paths = ["flask_login_tutorial", "config", "wsgi"]
+
+[tool.pylint.'MESSAGES CONTROL']
+disable = "C0103,C0301,W0703,W0621"
diff --git a/requirements.txt b/requirements.txt
index 5d1444b..c221d39 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,30 +1,28 @@
-appdirs==1.4.4
-attrs==20.2.0
-black==20.8b1
-click==7.1.2
-cssmin==0.2.0
-Flask==1.1.2
-Flask-Assets==2.0
-iniconfig==1.1.1
-isort==5.6.4
-itsdangerous==1.1.0
-Jinja2==2.11.2
-jsmin==2.2.2
-lesscpy==0.14.0
-MarkupSafe==1.1.1
-mypy-extensions==0.4.3
-packaging==20.4
-pathspec==0.8.0
-pluggy==0.13.1
-ply==3.11
-py==1.9.0
-pyparsing==2.4.7
-pytest==6.1.1
-python-dotenv==0.14.0
-regex==2020.10.15
-six==1.15.0
-toml==0.10.1
-typed-ast==1.4.1
-typing-extensions==3.7.4.3
-webassets==2.0
-Werkzeug==1.0.1
+black==23.12.0 ; python_version >= "3.10" and python_version < "4.0"
+blinker==1.7.0 ; python_version >= "3.10" and python_version < "4.0"
+click==8.1.7 ; python_version >= "3.10" and python_version < "4.0"
+colorama==0.4.6 ; python_version >= "3.10" and python_version < "4.0" and (sys_platform == "win32" or platform_system == "Windows")
+cssmin==0.2.0 ; python_version >= "3.10" and python_version < "4.0"
+exceptiongroup==1.2.0 ; python_version >= "3.10" and python_version < "3.11"
+flask-assets==2.1.0 ; python_version >= "3.10" and python_version < "4.0"
+flask==3.0.0 ; python_version >= "3.10" and python_version < "4.0"
+gunicorn==21.2.0 ; python_version >= "3.10" and python_version < "4.0"
+iniconfig==2.0.0 ; python_version >= "3.10" and python_version < "4.0"
+isort==5.13.2 ; python_version >= "3.10" and python_version < "4.0"
+itsdangerous==2.1.2 ; python_version >= "3.10" and python_version < "4.0"
+jinja2==3.1.2 ; python_version >= "3.10" and python_version < "4.0"
+jsmin==3.0.1 ; python_version >= "3.10" and python_version < "4.0"
+lesscpy==0.15.1 ; python_version >= "3.10" and python_version < "4.0"
+markupsafe==2.1.3 ; python_version >= "3.10" and python_version < "4.0"
+mypy-extensions==1.0.0 ; python_version >= "3.10" and python_version < "4.0"
+packaging==23.2 ; python_version >= "3.10" and python_version < "4.0"
+pathspec==0.12.1 ; python_version >= "3.10" and python_version < "4.0"
+platformdirs==4.1.0 ; python_version >= "3.10" and python_version < "4.0"
+pluggy==1.3.0 ; python_version >= "3.10" and python_version < "4.0"
+ply==3.11 ; python_version >= "3.10" and python_version < "4.0"
+pytest==7.4.3 ; python_version >= "3.10" and python_version < "4.0"
+python-dotenv==1.0.0 ; python_version >= "3.10" and python_version < "4.0"
+tomli==2.0.1 ; python_version >= "3.10" and python_version < "3.11"
+typing-extensions==4.9.0 ; python_version >= "3.10" and python_version < "3.11"
+webassets==2.0 ; python_version >= "3.10" and python_version < "4.0"
+werkzeug==3.0.1 ; python_version >= "3.10" and python_version < "4.0"
diff --git a/start.sh b/start.sh
deleted file mode 100644
index 44d02b3..0000000
--- a/start.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-# start.sh
-
-export FLASK_APP=wsgi.py
-export FLASK_DEBUG=1
-export APP_CONFIG_FILE=config.py
-flask run
diff --git a/wsgi.py b/wsgi.py
index f63d530..0b48e33 100644
--- a/wsgi.py
+++ b/wsgi.py
@@ -2,6 +2,3 @@
from flask_assets_tutorial import create_app
app = create_app()
-
-if __name__ == "__main__":
- app.run(host='0.0.0.0')