diff options
author | Galen Guyer <galen@galenguyer.com> | 2020-10-31 11:58:32 -0400 |
---|---|---|
committer | Galen Guyer <galen@galenguyer.com> | 2020-10-31 11:59:58 -0400 |
commit | 1009968ea0ca43ef1b1bc421f7694f1f70707948 (patch) | |
tree | f40c80a45095782290fb1af52bd7e683d6a74710 |
Initial commit
-rw-r--r-- | .gitignore | 132 | ||||
-rw-r--r-- | .pylintrc | 6 | ||||
-rw-r--r-- | .travis.yml | 12 | ||||
-rw-r--r-- | Dockerfile | 16 | ||||
-rw-r--r-- | LICENCE.txt | 19 | ||||
-rw-r--r-- | README.md | 27 | ||||
-rw-r--r-- | config.env.py | 17 | ||||
-rw-r--r-- | demo/__init__.py | 20 | ||||
-rw-r--r-- | requirements.txt | 4 | ||||
-rw-r--r-- | wsgi.py | 8 |
10 files changed, 261 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..68504eb --- /dev/null +++ b/.gitignore @@ -0,0 +1,132 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# Don't commit secrets! +config.py diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..3660be0 --- /dev/null +++ b/.pylintrc @@ -0,0 +1,6 @@ +[MASTER] +persistent = yes +load-plugins = pylint_quotes + +[FORMAT] +output-format = colorized diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..7e891f8 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +language: python +python: + - "3.8" +services: + - "docker" + +install: + - "pip install -r requirements.txt" +script: + - "pylint demo" + - "docker build -t demo ." + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..194a42a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM python:3.8-alpine +MAINTAINER Galen Guyer <galen@galenguyer.com> + +RUN mkdir /opt/demo + +ADD requirements.txt /opt/demo + +WORKDIR /opt/demo + +RUN pip install -r requirements.txt + +ADD . /opt/demo + +RUN ln -sf /usr/share/zoneinfo/America/New_York /etc/localtime + +CMD ["gunicorn", "demo:APP", "--bind=0.0.0.0:8080", "--access-logfile=-"] diff --git a/LICENCE.txt b/LICENCE.txt new file mode 100644 index 0000000..4457e5d --- /dev/null +++ b/LICENCE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2020 Galen Guyer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7919b4f --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# Flask wsgi bootstrap/demo + +This demo shows the use of gunicorn with flask. Original credit goes to [Max Meinhold](https://github.com/mxmeinhold/flask-gunicorn-demo). +It includes a basic Dockerfile, a linting demonstration using Pylint, and a Travis CI configuration for running linting. + +This is not an in depth guide in how these tools work, but a basic starting point and reference. + +Make sure to change my name and email if you use this template, especially in the license. + + +## Setup +Locally running this application should be pretty simple. + +1. (optional) Use a virtualenv + * Why use a venv? It isolates your dependencies and helps prevent version conflicts with other projects or system dependencies. + 1. `python3 -m venv venv` will create a venv in a directory named venv + 2. `source ./venv/bin/activate` will activate the venv +2. Install dependencies + * `pip install -r requirements.txt` +3. Run the app + * `gunicorn demo:APP --bind=localhost:5000` +4. Visit localhost:5000 in your web browser. + +## Linting +This demo uses pylint. +Travis CI will automatically run pylint on commits and PRs, but you can also run pylint manually, using `pylint demo`. +The pylint_quotes plugin is loaded by [the pylintrc](./.pylintrc) and will ensure standardised quotation mark formats. diff --git a/config.env.py b/config.env.py new file mode 100644 index 0000000..e996ffa --- /dev/null +++ b/config.env.py @@ -0,0 +1,17 @@ +import secrets +import os + +# Values in this file are loaded into the flask app instance, `demo.APP` in this +# demo. This file sources values from the environment if they exist, otherwise a +# set of defaults are used. This is useful for keeping secrets secret, as well +# as facilitating configuration in a container. Defaults may be overriden either +# by defining the environment variables, or by creating a `config.py` file that +# contains locally set secrets or config values. + + +# Defaults for flask configuration +IP = os.environ.get('IP', '127.0.0.1') +PORT = os.environ.get('PORT', 5000) +SERVER_NAME = os.environ.get('SERVER_NAME', 'localhost:5000') +SECRET_KEY = os.environ.get('SESSION_KEY', default=''.join(secrets.token_hex(16))) + diff --git a/demo/__init__.py b/demo/__init__.py new file mode 100644 index 0000000..86af046 --- /dev/null +++ b/demo/__init__.py @@ -0,0 +1,20 @@ +""" A small flask Hello World """ + +import os +import subprocess + +from flask import Flask, jsonify + +APP = Flask(__name__) + +# Load file based configuration overrides if present +if os.path.exists(os.path.join(os.getcwd(), 'config.py')): + APP.config.from_pyfile(os.path.join(os.getcwd(), 'config.py')) +else: + APP.config.from_pyfile(os.path.join(os.getcwd(), 'config.env.py')) + +APP.secret_key = APP.config['SECRET_KEY'] + +@APP.route('/') +def _index(): + return jsonify(status=200, response="OK") diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7b7f48f --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +Flask==1.1.2 +gunicorn==20.0.4 +pylint==2.6.0 +pylint-quotes==0.2.1 @@ -0,0 +1,8 @@ +""" +Primary entry point for the app +""" + +from demo import APP + +if __name__ == "__main__": + APP.run(host=APP.config["IP"], port=int(APP.config["PORT"])) |