├── src ├── __init__.py ├── models │ └── message.py ├── controllers │ ├── __init__.py │ ├── messages.py │ ├── home.py │ └── status.py ├── extensions.py ├── app.py ├── config.py ├── worker.py └── tasks │ └── long_task.py ├── setup.cfg ├── .env.example ├── .vscode └── settings.json ├── pyproject.toml ├── README.md ├── .gitignore └── poetry.lock /src/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 88 3 | ignore = W503 4 | filename = src/*.py 5 | 6 | [pydocstyle] 7 | ignore = D10,D203,D213 8 | match-dir='src/.*' 9 | -------------------------------------------------------------------------------- /src/models/message.py: -------------------------------------------------------------------------------- 1 | from src.extensions import db 2 | 3 | 4 | class Message(db.Model): 5 | id = db.Column(db.Integer, primary_key=True) 6 | text = db.Column(db.Unicode(200), nullable=False) 7 | -------------------------------------------------------------------------------- /src/controllers/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | 3 | from .home import home 4 | from .messages import messages 5 | from .status import status 6 | 7 | 8 | def register_blueprints(app: Flask) -> None: 9 | app.register_blueprint(home) 10 | app.register_blueprint(messages) 11 | app.register_blueprint(status) 12 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | export FLASK_ENV="development" 2 | export FLASK_APP="src.app:create_app" 3 | export SECRET_KEY="change_me" 4 | 5 | export DATABASE_URL="postgresql+psycopg2://postgres:postgres@localhost:5432/celery" 6 | 7 | export CELERY_TIMEZONE="Europe/Berlin" 8 | export CELERY_BROKER_URL="redis://localhost:6379/0" 9 | export CELERY_RESULT_BACKEND="redis://localhost:6379/0" 10 | -------------------------------------------------------------------------------- /src/extensions.py: -------------------------------------------------------------------------------- 1 | from celery import Celery 2 | from flask_sqlalchemy import SQLAlchemy 3 | 4 | db = SQLAlchemy() 5 | celery = Celery() 6 | 7 | 8 | def register_extensions(app, worker=False): 9 | db.init_app(app) 10 | 11 | # load celery config 12 | celery.config_from_object(app.config) 13 | 14 | if not worker: 15 | # register celery irrelevant extensions 16 | pass 17 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.formatting.provider": "black", 3 | "python.linting.flake8Enabled": true, 4 | "python.linting.pydocstyleEnabled": true, 5 | "python.linting.mypyEnabled": true, 6 | "[python]": { 7 | "editor.formatOnSave": true, 8 | "editor.rulers": [88, 100], 9 | "editor.detectIndentation": false, 10 | "editor.insertSpaces": true, 11 | "editor.tabSize": 4 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/controllers/messages.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | from flask import jsonify 3 | 4 | from src.extensions import db 5 | from src.models.message import Message 6 | 7 | messages = Blueprint("messages", __name__, url_prefix="/messages") 8 | 9 | 10 | @messages.route("/") 11 | def index(): 12 | messages = Message.query.all() 13 | if not messages: 14 | message = Message(text="Hello World") 15 | db.session.add(message) 16 | db.session.commit() 17 | messages.append(message) 18 | 19 | return jsonify([message.text for message in messages]) 20 | -------------------------------------------------------------------------------- /src/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | 3 | from src.config import config 4 | from src.extensions import register_extensions 5 | from src.controllers import register_blueprints 6 | 7 | 8 | def create_app(): 9 | app = Flask(__name__) 10 | app.config.from_object(config) 11 | app.url_map.strict_slashes = False 12 | 13 | register_extensions(app) 14 | register_blueprints(app) 15 | 16 | return app 17 | 18 | 19 | def create_worker_app(): 20 | """Minimal App without routes for celery worker.""" 21 | app = Flask(__name__) 22 | app.config.from_object(config) 23 | 24 | register_extensions(app, worker=True) 25 | 26 | return app 27 | -------------------------------------------------------------------------------- /src/controllers/home.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from datetime import timedelta 3 | 4 | from flask import url_for 5 | from flask import Blueprint 6 | from flask import jsonify 7 | 8 | from src.extensions import db 9 | from src.tasks.long_task import long_task 10 | 11 | home = Blueprint("home", __name__) 12 | 13 | 14 | @home.before_app_first_request 15 | def init_db(): 16 | db.create_all() 17 | 18 | 19 | @home.route("/") 20 | def index(): 21 | """Add a new task and start running it after 10 seconds.""" 22 | eta = datetime.utcnow() + timedelta(seconds=10) 23 | task = long_task.apply_async(eta=eta) 24 | return ( 25 | jsonify( 26 | {"_links": {"task": url_for("status.get", task_id=task.id, _external=True)}} 27 | ), 28 | 202, 29 | ) 30 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "flask-celery-example" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["nebularazer "] 6 | license = "MIT" 7 | 8 | [tool.poetry.dependencies] 9 | python = "~3.8" 10 | flask = "^1.1.2" 11 | celery = "^4.4.7" 12 | redis = "^3.5.3" 13 | psycopg2-binary = "^2.8.5" 14 | flask-sqlalchemy = "^2.4.4" 15 | 16 | [tool.poetry.dev-dependencies] 17 | ipython = "^7.17.0" 18 | black = "^19.10b0" 19 | python-dotenv = "^0.14.0" 20 | flake8 = "^3.8.3" 21 | mypy = "^0.782" 22 | pydocstyle = "^5.0.2" 23 | 24 | [tool.black] 25 | skip-string-normalization = false 26 | line-length = 88 27 | target-version = ['py37'] 28 | include = '\.pyi?$' 29 | exclude = ''' 30 | /( 31 | \.eggs # exclude a few common directories in the 32 | | \.git # root of the project 33 | | \.hg 34 | | \.mypy_cache 35 | | \.tox 36 | | \.venv 37 | | _build 38 | | buck-out 39 | | build 40 | | dist 41 | )/ 42 | ''' 43 | 44 | [build-system] 45 | requires = ["poetry>=0.12"] 46 | build-backend = "poetry.masonry.api" 47 | -------------------------------------------------------------------------------- /src/controllers/status.py: -------------------------------------------------------------------------------- 1 | from flask import jsonify 2 | from flask import Blueprint 3 | from celery.result import AsyncResult 4 | 5 | status = Blueprint("status", __name__, url_prefix="/status") 6 | 7 | 8 | @status.route("//", methods=["GET"]) 9 | def get(task_id): 10 | task = AsyncResult(task_id) 11 | if task.state == "PENDING": 12 | # job did not start yet 13 | response = {"state": task.state, "status": "Pending..."} 14 | elif task.state != "FAILURE": 15 | response = { 16 | "state": task.state, 17 | "current": task.info.get("current", 0), 18 | "total": task.info.get("total", 1), 19 | "status": task.info.get("status", ""), 20 | } 21 | if "result" in task.info: 22 | response["result"] = task.info["result"] 23 | else: 24 | # something went wrong in the background job 25 | response = { 26 | "state": task.state, 27 | "current": 1, 28 | "total": 1, 29 | "status": str(task.info), # this is the exception raised 30 | } 31 | return jsonify(response) 32 | -------------------------------------------------------------------------------- /src/config.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | BASEDIR = os.path.abspath(os.path.dirname(__name__)) 4 | SQLITE_DB = "sqlite:///" + os.path.join(BASEDIR, "db.sqlite") 5 | 6 | 7 | class Config(object): 8 | DEBUG = False 9 | SECRET_KEY = os.getenv("SECRET_KEY", os.urandom(16).hex()) 10 | 11 | SQLALCHEMY_TRACK_MODIFICATIONS = False 12 | SQLALCHEMY_DATABASE_URI = os.getenv("DATABASE_URL", SQLITE_DB) 13 | 14 | CELERY_TIMEZONE = os.getenv("CELERY_TIMEZONE", "Europe/Berlin") 15 | BROKER_URL = os.getenv("BROKER_URL", "redis://localhost:6379/0") 16 | CELERY_RESULT_BACKEND = os.getenv( 17 | "CELERY_RESULT_BACKEND", "redis://localhost:6379/0" 18 | ) 19 | CELERY_SEND_SENT_EVENT = True 20 | 21 | 22 | class DevelopmentConfig(Config): 23 | DEBUG = True 24 | SQLALCHEMY_DATABASE_URI = ( 25 | "postgresql+psycopg2://postgres:postgres@localhost:5432/celery" 26 | ) 27 | 28 | 29 | class ProductionConfig(Config): 30 | pass 31 | 32 | 33 | # return active config 34 | available_configs = dict(development=DevelopmentConfig, production=ProductionConfig) 35 | selected_config = os.getenv("FLASK_ENV", "production") 36 | config = available_configs.get(selected_config, "production") 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # flask-celery-example 2 | 3 | An example to run flask with celery including: 4 | 5 | - app factory setup 6 | - send a long running task from flask app 7 | - send periodic tasks with celery beat 8 | 9 | based on [flask-celery-example by Miguel Grinberg](https://github.com/miguelgrinberg/flask-celery-example) and his [bloc article](http://blog.miguelgrinberg.com/post/using-celery-with-flask) 10 | 11 | 12 | # endpoints 13 | - / adds a task to the queue and schedule it to start in 10 seconds 14 | - /message - shows messages in the database (revered every 10 seconds by celery task) 15 | - /status/ - show the status of the long running task 16 | 17 | 18 | # installation 19 | 20 | ## install dependencies with [poetry](https://python-poetry.org/) 21 | ``` bash 22 | poetry install 23 | poetry shell 24 | ``` 25 | 26 | ## start redis backend (using docker) 27 | ``` bash 28 | docker run -d --name redis -p 6379:6379 redis 29 | ``` 30 | 31 | ## run celery worker 32 | ``` 33 | source .env 34 | celery -A src.worker:celery worker --loglevel=DEBUG 35 | ``` 36 | 37 | ## run celery beat for periodic tasks 38 | ``` 39 | source .env 40 | celery -A src.worker:celery beat --loglevel=INFO 41 | ``` 42 | 43 | ## run flask app 44 | ``` bash 45 | source .env 46 | # check the available routes 47 | flask routes 48 | # start flask development server 49 | flask run 50 | ``` 51 | -------------------------------------------------------------------------------- /src/worker.py: -------------------------------------------------------------------------------- 1 | from celery import Celery 2 | from celery.schedules import crontab 3 | 4 | from src.app import create_worker_app 5 | from src.tasks.long_task import log 6 | from src.tasks.long_task import reverse_messages 7 | 8 | 9 | def create_celery(app): 10 | celery = Celery( 11 | app.import_name, 12 | backend=app.config["CELERY_RESULT_BACKEND"], 13 | broker=app.config["BROKER_URL"], 14 | ) 15 | celery.conf.update(app.config) 16 | TaskBase = celery.Task 17 | 18 | class ContextTask(TaskBase): 19 | abstract = True 20 | 21 | def __call__(self, *args, **kwargs): 22 | with app.app_context(): 23 | return TaskBase.__call__(self, *args, **kwargs) 24 | 25 | celery.Task = ContextTask 26 | return celery 27 | 28 | 29 | flask_app = create_worker_app() 30 | celery = create_celery(flask_app) 31 | 32 | 33 | @celery.on_after_configure.connect 34 | def setup_periodic_tasks(sender, **kwargs): 35 | # Calls reverse_messages every 10 seconds. 36 | sender.add_periodic_task(10.0, reverse_messages, name="reverse every 10") 37 | 38 | # Calls log('Logging Stuff') every 30 seconds 39 | sender.add_periodic_task(30.0, log.s(("Logging Stuff")), name="Log every 30") 40 | 41 | # Executes every Monday morning at 7:30 a.m. 42 | sender.add_periodic_task( 43 | crontab(hour=7, minute=30, day_of_week=1), log.s("Monday morning log!"), 44 | ) 45 | -------------------------------------------------------------------------------- /src/tasks/long_task.py: -------------------------------------------------------------------------------- 1 | import random 2 | import time 3 | 4 | from celery.signals import task_postrun 5 | from celery.utils.log import get_task_logger 6 | 7 | from src.extensions import db 8 | from src.extensions import celery 9 | from src.models.message import Message 10 | 11 | logger = get_task_logger(__name__) 12 | 13 | 14 | @celery.task(bind=True) 15 | def long_task(self): 16 | """Background task that runs a long function with progress reports.""" 17 | verb = ["Starting up", "Booting", "Repairing", "Loading", "Checking"] 18 | adjective = ["master", "radiant", "silent", "harmonic", "fast"] 19 | noun = ["solar array", "particle reshaper", "cosmic ray", "orbiter", "bit"] 20 | message = "" 21 | total = random.randint(10, 50) 22 | for i in range(total): 23 | if not message or random.random() < 0.25: 24 | message = "{0} {1} {2}...".format( 25 | random.choice(verb), random.choice(adjective), random.choice(noun) 26 | ) 27 | self.update_state( 28 | state="PROGRESS", meta={"current": i, "total": total, "status": message} 29 | ) 30 | time.sleep(1) 31 | return {"current": 100, "total": 100, "status": "Task completed!", "result": 42} 32 | 33 | 34 | @celery.task 35 | def log(message): 36 | logger.debug(message) 37 | logger.info(message) 38 | logger.warning(message) 39 | logger.error(message) 40 | logger.critical(message) 41 | 42 | 43 | @celery.task 44 | def reverse_messages(): 45 | """Reverse all messages in DB.""" 46 | for message in Message.query.all(): 47 | words = message.text.split() 48 | message.text = " ".join(reversed(words)) 49 | db.session.commit() 50 | 51 | 52 | @task_postrun.connect 53 | def close_session(*args, **kwargs): 54 | # Flask SQLAlchemy will automatically create new sessions for you from 55 | # a scoped session factory, given that we are maintaining the same app 56 | # context, this ensures tasks have a fresh session (e.g. session errors 57 | # won't propagate across tasks) 58 | db.session.remove() 59 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 98 | __pypackages__/ 99 | 100 | # Celery stuff 101 | celerybeat-schedule 102 | celerybeat.pid 103 | 104 | # SageMath parsed files 105 | *.sage.py 106 | 107 | # Environments 108 | .env 109 | .venv 110 | env/ 111 | venv/ 112 | ENV/ 113 | env.bak/ 114 | venv.bak/ 115 | 116 | # Spyder project settings 117 | .spyderproject 118 | .spyproject 119 | 120 | # Rope project settings 121 | .ropeproject 122 | 123 | # mkdocs documentation 124 | /site 125 | 126 | # mypy 127 | .mypy_cache/ 128 | .dmypy.json 129 | dmypy.json 130 | 131 | # Pyre type checker 132 | .pyre/ 133 | 134 | # pytype static type analyzer 135 | .pytype/ 136 | 137 | # Cython debug symbols 138 | cython_debug/ 139 | 140 | # Misc 141 | db.sqlite 142 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | category = "main" 3 | description = "Low-level AMQP client for Python (fork of amqplib)." 4 | name = "amqp" 5 | optional = false 6 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 7 | version = "2.6.1" 8 | 9 | [package.dependencies] 10 | vine = ">=1.1.3,<5.0.0a1" 11 | 12 | [[package]] 13 | category = "dev" 14 | description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." 15 | name = "appdirs" 16 | optional = false 17 | python-versions = "*" 18 | version = "1.4.4" 19 | 20 | [[package]] 21 | category = "dev" 22 | description = "Disable App Nap on OS X 10.9" 23 | marker = "sys_platform == \"darwin\"" 24 | name = "appnope" 25 | optional = false 26 | python-versions = "*" 27 | version = "0.1.0" 28 | 29 | [[package]] 30 | category = "dev" 31 | description = "Classes Without Boilerplate" 32 | name = "attrs" 33 | optional = false 34 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 35 | version = "19.3.0" 36 | 37 | [package.extras] 38 | azure-pipelines = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "pytest-azurepipelines"] 39 | dev = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "pre-commit"] 40 | docs = ["sphinx", "zope.interface"] 41 | tests = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] 42 | 43 | [[package]] 44 | category = "dev" 45 | description = "Specifications for callback functions passed in to an API" 46 | name = "backcall" 47 | optional = false 48 | python-versions = "*" 49 | version = "0.2.0" 50 | 51 | [[package]] 52 | category = "main" 53 | description = "Python multiprocessing fork with improvements and bugfixes" 54 | name = "billiard" 55 | optional = false 56 | python-versions = "*" 57 | version = "3.6.3.0" 58 | 59 | [[package]] 60 | category = "dev" 61 | description = "The uncompromising code formatter." 62 | name = "black" 63 | optional = false 64 | python-versions = ">=3.6" 65 | version = "19.10b0" 66 | 67 | [package.dependencies] 68 | appdirs = "*" 69 | attrs = ">=18.1.0" 70 | click = ">=6.5" 71 | pathspec = ">=0.6,<1" 72 | regex = "*" 73 | toml = ">=0.9.4" 74 | typed-ast = ">=1.4.0" 75 | 76 | [package.extras] 77 | d = ["aiohttp (>=3.3.2)", "aiohttp-cors"] 78 | 79 | [[package]] 80 | category = "main" 81 | description = "Distributed Task Queue." 82 | name = "celery" 83 | optional = false 84 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 85 | version = "4.4.7" 86 | 87 | [package.dependencies] 88 | billiard = ">=3.6.3.0,<4.0" 89 | kombu = ">=4.6.10,<4.7" 90 | pytz = ">0.0-dev" 91 | vine = "1.3.0" 92 | 93 | [package.extras] 94 | arangodb = ["pyArango (>=1.3.2)"] 95 | auth = ["cryptography"] 96 | azureblockblob = ["azure-storage (0.36.0)", "azure-common (1.1.5)", "azure-storage-common (1.1.0)"] 97 | brotli = ["brotli (>=1.0.0)", "brotlipy (>=0.7.0)"] 98 | cassandra = ["cassandra-driver (<3.21.0)"] 99 | consul = ["python-consul"] 100 | cosmosdbsql = ["pydocumentdb (2.3.2)"] 101 | couchbase = ["couchbase-cffi (<3.0.0)", "couchbase (<3.0.0)"] 102 | couchdb = ["pycouchdb"] 103 | django = ["Django (>=1.11)"] 104 | dynamodb = ["boto3 (>=1.9.178)"] 105 | elasticsearch = ["elasticsearch"] 106 | eventlet = ["eventlet (>=0.24.1)"] 107 | gevent = ["gevent"] 108 | librabbitmq = ["librabbitmq (>=1.5.0)"] 109 | lzma = ["backports.lzma"] 110 | memcache = ["pylibmc"] 111 | mongodb = ["pymongo (>=3.3.0)"] 112 | msgpack = ["msgpack"] 113 | pymemcache = ["python-memcached"] 114 | pyro = ["pyro4"] 115 | redis = ["redis (>=3.2.0)"] 116 | riak = ["riak (>=2.0)"] 117 | s3 = ["boto3 (>=1.9.125)"] 118 | slmq = ["softlayer-messaging (>=1.0.3)"] 119 | solar = ["ephem"] 120 | sqlalchemy = ["sqlalchemy"] 121 | sqs = ["boto3 (>=1.9.125)", "pycurl (7.43.0.5)"] 122 | tblib = ["tblib (>=1.3.0)", "tblib (>=1.5.0)"] 123 | yaml = ["PyYAML (>=3.10)"] 124 | zookeeper = ["kazoo (>=1.3.1)"] 125 | zstd = ["zstandard"] 126 | 127 | [[package]] 128 | category = "main" 129 | description = "Composable command line interface toolkit" 130 | name = "click" 131 | optional = false 132 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 133 | version = "7.1.2" 134 | 135 | [[package]] 136 | category = "dev" 137 | description = "Cross-platform colored terminal text." 138 | marker = "sys_platform == \"win32\"" 139 | name = "colorama" 140 | optional = false 141 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 142 | version = "0.4.3" 143 | 144 | [[package]] 145 | category = "dev" 146 | description = "Decorators for Humans" 147 | name = "decorator" 148 | optional = false 149 | python-versions = ">=2.6, !=3.0.*, !=3.1.*" 150 | version = "4.4.2" 151 | 152 | [[package]] 153 | category = "dev" 154 | description = "the modular source code checker: pep8 pyflakes and co" 155 | name = "flake8" 156 | optional = false 157 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" 158 | version = "3.8.3" 159 | 160 | [package.dependencies] 161 | mccabe = ">=0.6.0,<0.7.0" 162 | pycodestyle = ">=2.6.0a1,<2.7.0" 163 | pyflakes = ">=2.2.0,<2.3.0" 164 | 165 | [[package]] 166 | category = "main" 167 | description = "A simple framework for building complex web applications." 168 | name = "flask" 169 | optional = false 170 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 171 | version = "1.1.2" 172 | 173 | [package.dependencies] 174 | Jinja2 = ">=2.10.1" 175 | Werkzeug = ">=0.15" 176 | click = ">=5.1" 177 | itsdangerous = ">=0.24" 178 | 179 | [package.extras] 180 | dev = ["pytest", "coverage", "tox", "sphinx", "pallets-sphinx-themes", "sphinxcontrib-log-cabinet", "sphinx-issues"] 181 | docs = ["sphinx", "pallets-sphinx-themes", "sphinxcontrib-log-cabinet", "sphinx-issues"] 182 | dotenv = ["python-dotenv"] 183 | 184 | [[package]] 185 | category = "main" 186 | description = "Adds SQLAlchemy support to your Flask application." 187 | name = "flask-sqlalchemy" 188 | optional = false 189 | python-versions = ">= 2.7, != 3.0.*, != 3.1.*, != 3.2.*, != 3.3.*" 190 | version = "2.4.4" 191 | 192 | [package.dependencies] 193 | Flask = ">=0.10" 194 | SQLAlchemy = ">=0.8.0" 195 | 196 | [[package]] 197 | category = "dev" 198 | description = "IPython: Productive Interactive Computing" 199 | name = "ipython" 200 | optional = false 201 | python-versions = ">=3.7" 202 | version = "7.17.0" 203 | 204 | [package.dependencies] 205 | appnope = "*" 206 | backcall = "*" 207 | colorama = "*" 208 | decorator = "*" 209 | jedi = ">=0.10" 210 | pexpect = "*" 211 | pickleshare = "*" 212 | prompt-toolkit = ">=2.0.0,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.1.0" 213 | pygments = "*" 214 | setuptools = ">=18.5" 215 | traitlets = ">=4.2" 216 | 217 | [package.extras] 218 | all = ["Sphinx (>=1.3)", "ipykernel", "ipyparallel", "ipywidgets", "nbconvert", "nbformat", "nose (>=0.10.1)", "notebook", "numpy (>=1.14)", "pygments", "qtconsole", "requests", "testpath"] 219 | doc = ["Sphinx (>=1.3)"] 220 | kernel = ["ipykernel"] 221 | nbconvert = ["nbconvert"] 222 | nbformat = ["nbformat"] 223 | notebook = ["notebook", "ipywidgets"] 224 | parallel = ["ipyparallel"] 225 | qtconsole = ["qtconsole"] 226 | test = ["nose (>=0.10.1)", "requests", "testpath", "pygments", "nbformat", "ipykernel", "numpy (>=1.14)"] 227 | 228 | [[package]] 229 | category = "dev" 230 | description = "Vestigial utilities from IPython" 231 | name = "ipython-genutils" 232 | optional = false 233 | python-versions = "*" 234 | version = "0.2.0" 235 | 236 | [[package]] 237 | category = "main" 238 | description = "Various helpers to pass data to untrusted environments and back." 239 | name = "itsdangerous" 240 | optional = false 241 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 242 | version = "1.1.0" 243 | 244 | [[package]] 245 | category = "dev" 246 | description = "An autocompletion tool for Python that can be used for text editors." 247 | name = "jedi" 248 | optional = false 249 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 250 | version = "0.17.2" 251 | 252 | [package.dependencies] 253 | parso = ">=0.7.0,<0.8.0" 254 | 255 | [package.extras] 256 | qa = ["flake8 (3.7.9)"] 257 | testing = ["Django (<3.1)", "colorama", "docopt", "pytest (>=3.9.0,<5.0.0)"] 258 | 259 | [[package]] 260 | category = "main" 261 | description = "A very fast and expressive template engine." 262 | name = "jinja2" 263 | optional = false 264 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 265 | version = "2.11.2" 266 | 267 | [package.dependencies] 268 | MarkupSafe = ">=0.23" 269 | 270 | [package.extras] 271 | i18n = ["Babel (>=0.8)"] 272 | 273 | [[package]] 274 | category = "main" 275 | description = "Messaging library for Python." 276 | name = "kombu" 277 | optional = false 278 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 279 | version = "4.6.11" 280 | 281 | [package.dependencies] 282 | amqp = ">=2.6.0,<2.7" 283 | 284 | [package.extras] 285 | azureservicebus = ["azure-servicebus (>=0.21.1)"] 286 | azurestoragequeues = ["azure-storage-queue"] 287 | consul = ["python-consul (>=0.6.0)"] 288 | librabbitmq = ["librabbitmq (>=1.5.2)"] 289 | mongodb = ["pymongo (>=3.3.0)"] 290 | msgpack = ["msgpack"] 291 | pyro = ["pyro4"] 292 | qpid = ["qpid-python (>=0.26)", "qpid-tools (>=0.26)"] 293 | redis = ["redis (>=3.3.11)"] 294 | slmq = ["softlayer-messaging (>=1.0.3)"] 295 | sqlalchemy = ["sqlalchemy"] 296 | sqs = ["boto3 (>=1.4.4)", "pycurl (7.43.0.2)"] 297 | yaml = ["PyYAML (>=3.10)"] 298 | zookeeper = ["kazoo (>=1.3.1)"] 299 | 300 | [[package]] 301 | category = "main" 302 | description = "Safely add untrusted strings to HTML/XML markup." 303 | name = "markupsafe" 304 | optional = false 305 | python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" 306 | version = "1.1.1" 307 | 308 | [[package]] 309 | category = "dev" 310 | description = "McCabe checker, plugin for flake8" 311 | name = "mccabe" 312 | optional = false 313 | python-versions = "*" 314 | version = "0.6.1" 315 | 316 | [[package]] 317 | category = "dev" 318 | description = "Optional static typing for Python" 319 | name = "mypy" 320 | optional = false 321 | python-versions = ">=3.5" 322 | version = "0.782" 323 | 324 | [package.dependencies] 325 | mypy-extensions = ">=0.4.3,<0.5.0" 326 | typed-ast = ">=1.4.0,<1.5.0" 327 | typing-extensions = ">=3.7.4" 328 | 329 | [package.extras] 330 | dmypy = ["psutil (>=4.0)"] 331 | 332 | [[package]] 333 | category = "dev" 334 | description = "Experimental type system extensions for programs checked with the mypy typechecker." 335 | name = "mypy-extensions" 336 | optional = false 337 | python-versions = "*" 338 | version = "0.4.3" 339 | 340 | [[package]] 341 | category = "dev" 342 | description = "A Python Parser" 343 | name = "parso" 344 | optional = false 345 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 346 | version = "0.7.1" 347 | 348 | [package.extras] 349 | testing = ["docopt", "pytest (>=3.0.7)"] 350 | 351 | [[package]] 352 | category = "dev" 353 | description = "Utility library for gitignore style pattern matching of file paths." 354 | name = "pathspec" 355 | optional = false 356 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 357 | version = "0.8.0" 358 | 359 | [[package]] 360 | category = "dev" 361 | description = "Pexpect allows easy control of interactive console applications." 362 | marker = "sys_platform != \"win32\"" 363 | name = "pexpect" 364 | optional = false 365 | python-versions = "*" 366 | version = "4.8.0" 367 | 368 | [package.dependencies] 369 | ptyprocess = ">=0.5" 370 | 371 | [[package]] 372 | category = "dev" 373 | description = "Tiny 'shelve'-like database with concurrency support" 374 | name = "pickleshare" 375 | optional = false 376 | python-versions = "*" 377 | version = "0.7.5" 378 | 379 | [[package]] 380 | category = "dev" 381 | description = "Library for building powerful interactive command lines in Python" 382 | name = "prompt-toolkit" 383 | optional = false 384 | python-versions = ">=3.6.1" 385 | version = "3.0.6" 386 | 387 | [package.dependencies] 388 | wcwidth = "*" 389 | 390 | [[package]] 391 | category = "main" 392 | description = "psycopg2 - Python-PostgreSQL Database Adapter" 393 | name = "psycopg2-binary" 394 | optional = false 395 | python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" 396 | version = "2.8.5" 397 | 398 | [[package]] 399 | category = "dev" 400 | description = "Run a subprocess in a pseudo terminal" 401 | marker = "sys_platform != \"win32\"" 402 | name = "ptyprocess" 403 | optional = false 404 | python-versions = "*" 405 | version = "0.6.0" 406 | 407 | [[package]] 408 | category = "dev" 409 | description = "Python style guide checker" 410 | name = "pycodestyle" 411 | optional = false 412 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 413 | version = "2.6.0" 414 | 415 | [[package]] 416 | category = "dev" 417 | description = "Python docstring style checker" 418 | name = "pydocstyle" 419 | optional = false 420 | python-versions = ">=3.5" 421 | version = "5.0.2" 422 | 423 | [package.dependencies] 424 | snowballstemmer = "*" 425 | 426 | [[package]] 427 | category = "dev" 428 | description = "passive checker of Python programs" 429 | name = "pyflakes" 430 | optional = false 431 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 432 | version = "2.2.0" 433 | 434 | [[package]] 435 | category = "dev" 436 | description = "Pygments is a syntax highlighting package written in Python." 437 | name = "pygments" 438 | optional = false 439 | python-versions = ">=3.5" 440 | version = "2.6.1" 441 | 442 | [[package]] 443 | category = "dev" 444 | description = "Add .env support to your django/flask apps in development and deployments" 445 | name = "python-dotenv" 446 | optional = false 447 | python-versions = "*" 448 | version = "0.14.0" 449 | 450 | [package.extras] 451 | cli = ["click (>=5.0)"] 452 | 453 | [[package]] 454 | category = "main" 455 | description = "World timezone definitions, modern and historical" 456 | name = "pytz" 457 | optional = false 458 | python-versions = "*" 459 | version = "2020.1" 460 | 461 | [[package]] 462 | category = "main" 463 | description = "Python client for Redis key-value store" 464 | name = "redis" 465 | optional = false 466 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 467 | version = "3.5.3" 468 | 469 | [package.extras] 470 | hiredis = ["hiredis (>=0.1.3)"] 471 | 472 | [[package]] 473 | category = "dev" 474 | description = "Alternative regular expression module, to replace re." 475 | name = "regex" 476 | optional = false 477 | python-versions = "*" 478 | version = "2020.7.14" 479 | 480 | [[package]] 481 | category = "dev" 482 | description = "Python 2 and 3 compatibility utilities" 483 | name = "six" 484 | optional = false 485 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 486 | version = "1.15.0" 487 | 488 | [[package]] 489 | category = "dev" 490 | description = "This package provides 26 stemmers for 25 languages generated from Snowball algorithms." 491 | name = "snowballstemmer" 492 | optional = false 493 | python-versions = "*" 494 | version = "2.0.0" 495 | 496 | [[package]] 497 | category = "main" 498 | description = "Database Abstraction Library" 499 | name = "sqlalchemy" 500 | optional = false 501 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 502 | version = "1.3.18" 503 | 504 | [package.extras] 505 | mssql = ["pyodbc"] 506 | mssql_pymssql = ["pymssql"] 507 | mssql_pyodbc = ["pyodbc"] 508 | mysql = ["mysqlclient"] 509 | oracle = ["cx-oracle"] 510 | postgresql = ["psycopg2"] 511 | postgresql_pg8000 = ["pg8000"] 512 | postgresql_psycopg2binary = ["psycopg2-binary"] 513 | postgresql_psycopg2cffi = ["psycopg2cffi"] 514 | pymysql = ["pymysql"] 515 | 516 | [[package]] 517 | category = "dev" 518 | description = "Python Library for Tom's Obvious, Minimal Language" 519 | name = "toml" 520 | optional = false 521 | python-versions = "*" 522 | version = "0.10.1" 523 | 524 | [[package]] 525 | category = "dev" 526 | description = "Traitlets Python config system" 527 | name = "traitlets" 528 | optional = false 529 | python-versions = "*" 530 | version = "4.3.3" 531 | 532 | [package.dependencies] 533 | decorator = "*" 534 | ipython-genutils = "*" 535 | six = "*" 536 | 537 | [package.extras] 538 | test = ["pytest", "mock"] 539 | 540 | [[package]] 541 | category = "dev" 542 | description = "a fork of Python 2 and 3 ast modules with type comment support" 543 | name = "typed-ast" 544 | optional = false 545 | python-versions = "*" 546 | version = "1.4.1" 547 | 548 | [[package]] 549 | category = "dev" 550 | description = "Backported and Experimental Type Hints for Python 3.5+" 551 | name = "typing-extensions" 552 | optional = false 553 | python-versions = "*" 554 | version = "3.7.4.2" 555 | 556 | [[package]] 557 | category = "main" 558 | description = "Promises, promises, promises." 559 | name = "vine" 560 | optional = false 561 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 562 | version = "1.3.0" 563 | 564 | [[package]] 565 | category = "dev" 566 | description = "Measures the displayed width of unicode strings in a terminal" 567 | name = "wcwidth" 568 | optional = false 569 | python-versions = "*" 570 | version = "0.2.5" 571 | 572 | [[package]] 573 | category = "main" 574 | description = "The comprehensive WSGI web application library." 575 | name = "werkzeug" 576 | optional = false 577 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 578 | version = "1.0.1" 579 | 580 | [package.extras] 581 | dev = ["pytest", "pytest-timeout", "coverage", "tox", "sphinx", "pallets-sphinx-themes", "sphinx-issues"] 582 | watchdog = ["watchdog"] 583 | 584 | [metadata] 585 | content-hash = "3b9cf9ef4fed5c0d3cec2bf0aa7fa8bebb2f79c116db49d83bc990cc22f81a78" 586 | python-versions = "~3.8" 587 | 588 | [metadata.files] 589 | amqp = [ 590 | {file = "amqp-2.6.1-py2.py3-none-any.whl", hash = "sha256:aa7f313fb887c91f15474c1229907a04dac0b8135822d6603437803424c0aa59"}, 591 | {file = "amqp-2.6.1.tar.gz", hash = "sha256:70cdb10628468ff14e57ec2f751c7aa9e48e7e3651cfd62d431213c0c4e58f21"}, 592 | ] 593 | appdirs = [ 594 | {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, 595 | {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, 596 | ] 597 | appnope = [ 598 | {file = "appnope-0.1.0-py2.py3-none-any.whl", hash = "sha256:5b26757dc6f79a3b7dc9fab95359328d5747fcb2409d331ea66d0272b90ab2a0"}, 599 | {file = "appnope-0.1.0.tar.gz", hash = "sha256:8b995ffe925347a2138d7ac0fe77155e4311a0ea6d6da4f5128fe4b3cbe5ed71"}, 600 | ] 601 | attrs = [ 602 | {file = "attrs-19.3.0-py2.py3-none-any.whl", hash = "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c"}, 603 | {file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"}, 604 | ] 605 | backcall = [ 606 | {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, 607 | {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, 608 | ] 609 | billiard = [ 610 | {file = "billiard-3.6.3.0-py3-none-any.whl", hash = "sha256:bff575450859a6e0fbc2f9877d9b715b0bbc07c3565bb7ed2280526a0cdf5ede"}, 611 | {file = "billiard-3.6.3.0.tar.gz", hash = "sha256:d91725ce6425f33a97dfa72fb6bfef0e47d4652acd98a032bd1a7fbf06d5fa6a"}, 612 | ] 613 | black = [ 614 | {file = "black-19.10b0-py36-none-any.whl", hash = "sha256:1b30e59be925fafc1ee4565e5e08abef6b03fe455102883820fe5ee2e4734e0b"}, 615 | {file = "black-19.10b0.tar.gz", hash = "sha256:c2edb73a08e9e0e6f65a0e6af18b059b8b1cdd5bef997d7a0b181df93dc81539"}, 616 | ] 617 | celery = [ 618 | {file = "celery-4.4.7-py2.py3-none-any.whl", hash = "sha256:a92e1d56e650781fb747032a3997d16236d037c8199eacd5217d1a72893bca45"}, 619 | {file = "celery-4.4.7.tar.gz", hash = "sha256:d220b13a8ed57c78149acf82c006785356071844afe0b27012a4991d44026f9f"}, 620 | ] 621 | click = [ 622 | {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, 623 | {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, 624 | ] 625 | colorama = [ 626 | {file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"}, 627 | {file = "colorama-0.4.3.tar.gz", hash = "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"}, 628 | ] 629 | decorator = [ 630 | {file = "decorator-4.4.2-py2.py3-none-any.whl", hash = "sha256:41fa54c2a0cc4ba648be4fd43cff00aedf5b9465c9bf18d64325bc225f08f760"}, 631 | {file = "decorator-4.4.2.tar.gz", hash = "sha256:e3a62f0520172440ca0dcc823749319382e377f37f140a0b99ef45fecb84bfe7"}, 632 | ] 633 | flake8 = [ 634 | {file = "flake8-3.8.3-py2.py3-none-any.whl", hash = "sha256:15e351d19611c887e482fb960eae4d44845013cc142d42896e9862f775d8cf5c"}, 635 | {file = "flake8-3.8.3.tar.gz", hash = "sha256:f04b9fcbac03b0a3e58c0ab3a0ecc462e023a9faf046d57794184028123aa208"}, 636 | ] 637 | flask = [ 638 | {file = "Flask-1.1.2-py2.py3-none-any.whl", hash = "sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557"}, 639 | {file = "Flask-1.1.2.tar.gz", hash = "sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060"}, 640 | ] 641 | flask-sqlalchemy = [ 642 | {file = "Flask-SQLAlchemy-2.4.4.tar.gz", hash = "sha256:bfc7150eaf809b1c283879302f04c42791136060c6eeb12c0c6674fb1291fae5"}, 643 | {file = "Flask_SQLAlchemy-2.4.4-py2.py3-none-any.whl", hash = "sha256:05b31d2034dd3f2a685cbbae4cfc4ed906b2a733cff7964ada450fd5e462b84e"}, 644 | ] 645 | ipython = [ 646 | {file = "ipython-7.17.0-py3-none-any.whl", hash = "sha256:5a8f159ca8b22b9a0a1f2a28befe5ad2b703339afb58c2ffe0d7c8d7a3af5999"}, 647 | {file = "ipython-7.17.0.tar.gz", hash = "sha256:b70974aaa2674b05eb86a910c02ed09956a33f2dd6c71afc60f0b128a77e7f28"}, 648 | ] 649 | ipython-genutils = [ 650 | {file = "ipython_genutils-0.2.0-py2.py3-none-any.whl", hash = "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8"}, 651 | {file = "ipython_genutils-0.2.0.tar.gz", hash = "sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8"}, 652 | ] 653 | itsdangerous = [ 654 | {file = "itsdangerous-1.1.0-py2.py3-none-any.whl", hash = "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"}, 655 | {file = "itsdangerous-1.1.0.tar.gz", hash = "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19"}, 656 | ] 657 | jedi = [ 658 | {file = "jedi-0.17.2-py2.py3-none-any.whl", hash = "sha256:98cc583fa0f2f8304968199b01b6b4b94f469a1f4a74c1560506ca2a211378b5"}, 659 | {file = "jedi-0.17.2.tar.gz", hash = "sha256:86ed7d9b750603e4ba582ea8edc678657fb4007894a12bcf6f4bb97892f31d20"}, 660 | ] 661 | jinja2 = [ 662 | {file = "Jinja2-2.11.2-py2.py3-none-any.whl", hash = "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035"}, 663 | {file = "Jinja2-2.11.2.tar.gz", hash = "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0"}, 664 | ] 665 | kombu = [ 666 | {file = "kombu-4.6.11-py2.py3-none-any.whl", hash = "sha256:be48cdffb54a2194d93ad6533d73f69408486483d189fe9f5990ee24255b0e0a"}, 667 | {file = "kombu-4.6.11.tar.gz", hash = "sha256:ca1b45faac8c0b18493d02a8571792f3c40291cf2bcf1f55afed3d8f3aa7ba74"}, 668 | ] 669 | markupsafe = [ 670 | {file = "MarkupSafe-1.1.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161"}, 671 | {file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"}, 672 | {file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183"}, 673 | {file = "MarkupSafe-1.1.1-cp27-cp27m-win32.whl", hash = "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b"}, 674 | {file = "MarkupSafe-1.1.1-cp27-cp27m-win_amd64.whl", hash = "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e"}, 675 | {file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f"}, 676 | {file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1"}, 677 | {file = "MarkupSafe-1.1.1-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5"}, 678 | {file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1"}, 679 | {file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735"}, 680 | {file = "MarkupSafe-1.1.1-cp34-cp34m-win32.whl", hash = "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21"}, 681 | {file = "MarkupSafe-1.1.1-cp34-cp34m-win_amd64.whl", hash = "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235"}, 682 | {file = "MarkupSafe-1.1.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b"}, 683 | {file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f"}, 684 | {file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905"}, 685 | {file = "MarkupSafe-1.1.1-cp35-cp35m-win32.whl", hash = "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1"}, 686 | {file = "MarkupSafe-1.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d"}, 687 | {file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff"}, 688 | {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473"}, 689 | {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e"}, 690 | {file = "MarkupSafe-1.1.1-cp36-cp36m-win32.whl", hash = "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66"}, 691 | {file = "MarkupSafe-1.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5"}, 692 | {file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d"}, 693 | {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e"}, 694 | {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"}, 695 | {file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"}, 696 | {file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"}, 697 | {file = "MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15"}, 698 | {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2"}, 699 | {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42"}, 700 | {file = "MarkupSafe-1.1.1-cp38-cp38-win32.whl", hash = "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b"}, 701 | {file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"}, 702 | {file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"}, 703 | ] 704 | mccabe = [ 705 | {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, 706 | {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, 707 | ] 708 | mypy = [ 709 | {file = "mypy-0.782-cp35-cp35m-macosx_10_6_x86_64.whl", hash = "sha256:2c6cde8aa3426c1682d35190b59b71f661237d74b053822ea3d748e2c9578a7c"}, 710 | {file = "mypy-0.782-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9c7a9a7ceb2871ba4bac1cf7217a7dd9ccd44c27c2950edbc6dc08530f32ad4e"}, 711 | {file = "mypy-0.782-cp35-cp35m-win_amd64.whl", hash = "sha256:c05b9e4fb1d8a41d41dec8786c94f3b95d3c5f528298d769eb8e73d293abc48d"}, 712 | {file = "mypy-0.782-cp36-cp36m-macosx_10_6_x86_64.whl", hash = "sha256:6731603dfe0ce4352c555c6284c6db0dc935b685e9ce2e4cf220abe1e14386fd"}, 713 | {file = "mypy-0.782-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:f05644db6779387ccdb468cc47a44b4356fc2ffa9287135d05b70a98dc83b89a"}, 714 | {file = "mypy-0.782-cp36-cp36m-win_amd64.whl", hash = "sha256:b7fbfabdbcc78c4f6fc4712544b9b0d6bf171069c6e0e3cb82440dd10ced3406"}, 715 | {file = "mypy-0.782-cp37-cp37m-macosx_10_6_x86_64.whl", hash = "sha256:3fdda71c067d3ddfb21da4b80e2686b71e9e5c72cca65fa216d207a358827f86"}, 716 | {file = "mypy-0.782-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d7df6eddb6054d21ca4d3c6249cae5578cb4602951fd2b6ee2f5510ffb098707"}, 717 | {file = "mypy-0.782-cp37-cp37m-win_amd64.whl", hash = "sha256:a4a2cbcfc4cbf45cd126f531dedda8485671545b43107ded25ce952aac6fb308"}, 718 | {file = "mypy-0.782-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6bb93479caa6619d21d6e7160c552c1193f6952f0668cdda2f851156e85186fc"}, 719 | {file = "mypy-0.782-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:81c7908b94239c4010e16642c9102bfc958ab14e36048fa77d0be3289dda76ea"}, 720 | {file = "mypy-0.782-cp38-cp38-win_amd64.whl", hash = "sha256:5dd13ff1f2a97f94540fd37a49e5d255950ebcdf446fb597463a40d0df3fac8b"}, 721 | {file = "mypy-0.782-py3-none-any.whl", hash = "sha256:e0b61738ab504e656d1fe4ff0c0601387a5489ca122d55390ade31f9ca0e252d"}, 722 | {file = "mypy-0.782.tar.gz", hash = "sha256:eff7d4a85e9eea55afa34888dfeaccde99e7520b51f867ac28a48492c0b1130c"}, 723 | ] 724 | mypy-extensions = [ 725 | {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, 726 | {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, 727 | ] 728 | parso = [ 729 | {file = "parso-0.7.1-py2.py3-none-any.whl", hash = "sha256:97218d9159b2520ff45eb78028ba8b50d2bc61dcc062a9682666f2dc4bd331ea"}, 730 | {file = "parso-0.7.1.tar.gz", hash = "sha256:caba44724b994a8a5e086460bb212abc5a8bc46951bf4a9a1210745953622eb9"}, 731 | ] 732 | pathspec = [ 733 | {file = "pathspec-0.8.0-py2.py3-none-any.whl", hash = "sha256:7d91249d21749788d07a2d0f94147accd8f845507400749ea19c1ec9054a12b0"}, 734 | {file = "pathspec-0.8.0.tar.gz", hash = "sha256:da45173eb3a6f2a5a487efba21f050af2b41948be6ab52b6a1e3ff22bb8b7061"}, 735 | ] 736 | pexpect = [ 737 | {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, 738 | {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, 739 | ] 740 | pickleshare = [ 741 | {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, 742 | {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, 743 | ] 744 | prompt-toolkit = [ 745 | {file = "prompt_toolkit-3.0.6-py3-none-any.whl", hash = "sha256:683397077a64cd1f750b71c05afcfc6612a7300cb6932666531e5a54f38ea564"}, 746 | {file = "prompt_toolkit-3.0.6.tar.gz", hash = "sha256:7630ab85a23302839a0f26b31cc24f518e6155dea1ed395ea61b42c45941b6a6"}, 747 | ] 748 | psycopg2-binary = [ 749 | {file = "psycopg2-binary-2.8.5.tar.gz", hash = "sha256:ccdc6a87f32b491129ada4b87a43b1895cf2c20fdb7f98ad979647506ffc41b6"}, 750 | {file = "psycopg2_binary-2.8.5-cp27-cp27m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:96d3038f5bd061401996614f65d27a4ecb62d843eb4f48e212e6d129171a721f"}, 751 | {file = "psycopg2_binary-2.8.5-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:08507efbe532029adee21b8d4c999170a83760d38249936038bd0602327029b5"}, 752 | {file = "psycopg2_binary-2.8.5-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:b9a8b391c2b0321e0cd7ec6b4cfcc3dd6349347bd1207d48bcb752aa6c553a66"}, 753 | {file = "psycopg2_binary-2.8.5-cp27-cp27m-win32.whl", hash = "sha256:3286541b9d85a340ee4ed42732d15fc1bb441dc500c97243a768154ab8505bb5"}, 754 | {file = "psycopg2_binary-2.8.5-cp27-cp27m-win_amd64.whl", hash = "sha256:008da3ab51adc70a5f1cfbbe5db3a22607ab030eb44bcecf517ad11a0c2b3cac"}, 755 | {file = "psycopg2_binary-2.8.5-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:ba13346ff6d3eb2dca0b6fa0d8a9d999eff3dcd9b55f3a890f12b0b6362b2b38"}, 756 | {file = "psycopg2_binary-2.8.5-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:c8830b7d5f16fd79d39b21e3d94f247219036b29b30c8270314c46bf8b732389"}, 757 | {file = "psycopg2_binary-2.8.5-cp34-cp34m-win32.whl", hash = "sha256:51f7823f1b087d2020d8e8c9e6687473d3d239ba9afc162d9b2ab6e80b53f9f9"}, 758 | {file = "psycopg2_binary-2.8.5-cp34-cp34m-win_amd64.whl", hash = "sha256:107d9be3b614e52a192719c6bf32e8813030020ea1d1215daa86ded9a24d8b04"}, 759 | {file = "psycopg2_binary-2.8.5-cp35-cp35m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:930315ac53dc65cbf52ab6b6d27422611f5fb461d763c531db229c7e1af6c0b3"}, 760 | {file = "psycopg2_binary-2.8.5-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:6bb2dd006a46a4a4ce95201f836194eb6a1e863f69ee5bab506673e0ca767057"}, 761 | {file = "psycopg2_binary-2.8.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:3939cf75fc89c5e9ed836e228c4a63604dff95ad19aed2bbf71d5d04c15ed5ce"}, 762 | {file = "psycopg2_binary-2.8.5-cp35-cp35m-win32.whl", hash = "sha256:a20299ee0ea2f9cca494396ac472d6e636745652a64a418b39522c120fd0a0a4"}, 763 | {file = "psycopg2_binary-2.8.5-cp35-cp35m-win_amd64.whl", hash = "sha256:cc30cb900f42c8a246e2cb76539d9726f407330bc244ca7729c41a44e8d807fb"}, 764 | {file = "psycopg2_binary-2.8.5-cp36-cp36m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:40abc319f7f26c042a11658bf3dd3b0b3bceccf883ec1c565d5c909a90204434"}, 765 | {file = "psycopg2_binary-2.8.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:702f09d8f77dc4794651f650828791af82f7c2efd8c91ae79e3d9fe4bb7d4c98"}, 766 | {file = "psycopg2_binary-2.8.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d1a8b01f6a964fec702d6b6dac1f91f2b9f9fe41b310cbb16c7ef1fac82df06d"}, 767 | {file = "psycopg2_binary-2.8.5-cp36-cp36m-win32.whl", hash = "sha256:17a0ea0b0eabf07035e5e0d520dabc7950aeb15a17c6d36128ba99b2721b25b1"}, 768 | {file = "psycopg2_binary-2.8.5-cp36-cp36m-win_amd64.whl", hash = "sha256:e004db88e5a75e5fdab1620fb9f90c9598c2a195a594225ac4ed2a6f1c23e162"}, 769 | {file = "psycopg2_binary-2.8.5-cp37-cp37m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:a34826d6465c2e2bbe9d0605f944f19d2480589f89863ed5f091943be27c9de4"}, 770 | {file = "psycopg2_binary-2.8.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:cac918cd7c4c498a60f5d2a61d4f0a6091c2c9490d81bc805c963444032d0dab"}, 771 | {file = "psycopg2_binary-2.8.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:7b832d76cc65c092abd9505cc670c4e3421fd136fb6ea5b94efbe4c146572505"}, 772 | {file = "psycopg2_binary-2.8.5-cp37-cp37m-win32.whl", hash = "sha256:bb0608694a91db1e230b4a314e8ed00ad07ed0c518f9a69b83af2717e31291a3"}, 773 | {file = "psycopg2_binary-2.8.5-cp37-cp37m-win_amd64.whl", hash = "sha256:eb2f43ae3037f1ef5e19339c41cf56947021ac892f668765cd65f8ab9814192e"}, 774 | {file = "psycopg2_binary-2.8.5-cp38-cp38-macosx_10_9_x86_64.macosx_10_9_intel.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:07cf82c870ec2d2ce94d18e70c13323c89f2f2a2628cbf1feee700630be2519a"}, 775 | {file = "psycopg2_binary-2.8.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:a69970ee896e21db4c57e398646af9edc71c003bc52a3cc77fb150240fefd266"}, 776 | {file = "psycopg2_binary-2.8.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7036ccf715925251fac969f4da9ad37e4b7e211b1e920860148a10c0de963522"}, 777 | {file = "psycopg2_binary-2.8.5-cp38-cp38-win32.whl", hash = "sha256:8f74e631b67482d504d7e9cf364071fc5d54c28e79a093ff402d5f8f81e23bfa"}, 778 | {file = "psycopg2_binary-2.8.5-cp38-cp38-win_amd64.whl", hash = "sha256:fa466306fcf6b39b8a61d003123d442b23707d635a5cb05ac4e1b62cc79105cd"}, 779 | ] 780 | ptyprocess = [ 781 | {file = "ptyprocess-0.6.0-py2.py3-none-any.whl", hash = "sha256:d7cc528d76e76342423ca640335bd3633420dc1366f258cb31d05e865ef5ca1f"}, 782 | {file = "ptyprocess-0.6.0.tar.gz", hash = "sha256:923f299cc5ad920c68f2bc0bc98b75b9f838b93b599941a6b63ddbc2476394c0"}, 783 | ] 784 | pycodestyle = [ 785 | {file = "pycodestyle-2.6.0-py2.py3-none-any.whl", hash = "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367"}, 786 | {file = "pycodestyle-2.6.0.tar.gz", hash = "sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e"}, 787 | ] 788 | pydocstyle = [ 789 | {file = "pydocstyle-5.0.2-py3-none-any.whl", hash = "sha256:da7831660b7355307b32778c4a0dbfb137d89254ef31a2b2978f50fc0b4d7586"}, 790 | {file = "pydocstyle-5.0.2.tar.gz", hash = "sha256:f4f5d210610c2d153fae39093d44224c17429e2ad7da12a8b419aba5c2f614b5"}, 791 | ] 792 | pyflakes = [ 793 | {file = "pyflakes-2.2.0-py2.py3-none-any.whl", hash = "sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92"}, 794 | {file = "pyflakes-2.2.0.tar.gz", hash = "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8"}, 795 | ] 796 | pygments = [ 797 | {file = "Pygments-2.6.1-py3-none-any.whl", hash = "sha256:ff7a40b4860b727ab48fad6360eb351cc1b33cbf9b15a0f689ca5353e9463324"}, 798 | {file = "Pygments-2.6.1.tar.gz", hash = "sha256:647344a061c249a3b74e230c739f434d7ea4d8b1d5f3721bc0f3558049b38f44"}, 799 | ] 800 | python-dotenv = [ 801 | {file = "python-dotenv-0.14.0.tar.gz", hash = "sha256:8c10c99a1b25d9a68058a1ad6f90381a62ba68230ca93966882a4dbc3bc9c33d"}, 802 | {file = "python_dotenv-0.14.0-py2.py3-none-any.whl", hash = "sha256:c10863aee750ad720f4f43436565e4c1698798d763b63234fb5021b6c616e423"}, 803 | ] 804 | pytz = [ 805 | {file = "pytz-2020.1-py2.py3-none-any.whl", hash = "sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed"}, 806 | {file = "pytz-2020.1.tar.gz", hash = "sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"}, 807 | ] 808 | redis = [ 809 | {file = "redis-3.5.3-py2.py3-none-any.whl", hash = "sha256:432b788c4530cfe16d8d943a09d40ca6c16149727e4afe8c2c9d5580c59d9f24"}, 810 | {file = "redis-3.5.3.tar.gz", hash = "sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2"}, 811 | ] 812 | regex = [ 813 | {file = "regex-2020.7.14-cp27-cp27m-win32.whl", hash = "sha256:e46d13f38cfcbb79bfdb2964b0fe12561fe633caf964a77a5f8d4e45fe5d2ef7"}, 814 | {file = "regex-2020.7.14-cp27-cp27m-win_amd64.whl", hash = "sha256:6961548bba529cac7c07af2fd4d527c5b91bb8fe18995fed6044ac22b3d14644"}, 815 | {file = "regex-2020.7.14-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c50a724d136ec10d920661f1442e4a8b010a4fe5aebd65e0c2241ea41dbe93dc"}, 816 | {file = "regex-2020.7.14-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8a51f2c6d1f884e98846a0a9021ff6861bdb98457879f412fdc2b42d14494067"}, 817 | {file = "regex-2020.7.14-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:9c568495e35599625f7b999774e29e8d6b01a6fb684d77dee1f56d41b11b40cd"}, 818 | {file = "regex-2020.7.14-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:51178c738d559a2d1071ce0b0f56e57eb315bcf8f7d4cf127674b533e3101f88"}, 819 | {file = "regex-2020.7.14-cp36-cp36m-win32.whl", hash = "sha256:9eddaafb3c48e0900690c1727fba226c4804b8e6127ea409689c3bb492d06de4"}, 820 | {file = "regex-2020.7.14-cp36-cp36m-win_amd64.whl", hash = "sha256:14a53646369157baa0499513f96091eb70382eb50b2c82393d17d7ec81b7b85f"}, 821 | {file = "regex-2020.7.14-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:1269fef3167bb52631ad4fa7dd27bf635d5a0790b8e6222065d42e91bede4162"}, 822 | {file = "regex-2020.7.14-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d0a5095d52b90ff38592bbdc2644f17c6d495762edf47d876049cfd2968fbccf"}, 823 | {file = "regex-2020.7.14-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:4c037fd14c5f4e308b8370b447b469ca10e69427966527edcab07f52d88388f7"}, 824 | {file = "regex-2020.7.14-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:bc3d98f621898b4a9bc7fecc00513eec8f40b5b83913d74ccb445f037d58cd89"}, 825 | {file = "regex-2020.7.14-cp37-cp37m-win32.whl", hash = "sha256:46bac5ca10fb748d6c55843a931855e2727a7a22584f302dd9bb1506e69f83f6"}, 826 | {file = "regex-2020.7.14-cp37-cp37m-win_amd64.whl", hash = "sha256:0dc64ee3f33cd7899f79a8d788abfbec168410be356ed9bd30bbd3f0a23a7204"}, 827 | {file = "regex-2020.7.14-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5ea81ea3dbd6767873c611687141ec7b06ed8bab43f68fad5b7be184a920dc99"}, 828 | {file = "regex-2020.7.14-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:bbb332d45b32df41200380fff14712cb6093b61bd142272a10b16778c418e98e"}, 829 | {file = "regex-2020.7.14-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:c11d6033115dc4887c456565303f540c44197f4fc1a2bfb192224a301534888e"}, 830 | {file = "regex-2020.7.14-cp38-cp38-win32.whl", hash = "sha256:d6cff2276e502b86a25fd10c2a96973fdb45c7a977dca2138d661417f3728341"}, 831 | {file = "regex-2020.7.14-cp38-cp38-win_amd64.whl", hash = "sha256:7a2dd66d2d4df34fa82c9dc85657c5e019b87932019947faece7983f2089a840"}, 832 | {file = "regex-2020.7.14.tar.gz", hash = "sha256:3a3af27a8d23143c49a3420efe5b3f8cf1a48c6fc8bc6856b03f638abc1833bb"}, 833 | ] 834 | six = [ 835 | {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"}, 836 | {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, 837 | ] 838 | snowballstemmer = [ 839 | {file = "snowballstemmer-2.0.0-py2.py3-none-any.whl", hash = "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0"}, 840 | {file = "snowballstemmer-2.0.0.tar.gz", hash = "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52"}, 841 | ] 842 | sqlalchemy = [ 843 | {file = "SQLAlchemy-1.3.18-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:f11c2437fb5f812d020932119ba02d9e2bc29a6eca01a055233a8b449e3e1e7d"}, 844 | {file = "SQLAlchemy-1.3.18-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:0ec575db1b54909750332c2e335c2bb11257883914a03bc5a3306a4488ecc772"}, 845 | {file = "SQLAlchemy-1.3.18-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:f57be5673e12763dd400fea568608700a63ce1c6bd5bdbc3cc3a2c5fdb045274"}, 846 | {file = "SQLAlchemy-1.3.18-cp27-cp27m-win32.whl", hash = "sha256:8cac7bb373a5f1423e28de3fd5fc8063b9c8ffe8957dc1b1a59cb90453db6da1"}, 847 | {file = "SQLAlchemy-1.3.18-cp27-cp27m-win_amd64.whl", hash = "sha256:adad60eea2c4c2a1875eb6305a0b6e61a83163f8e233586a4d6a55221ef984fe"}, 848 | {file = "SQLAlchemy-1.3.18-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:57aa843b783179ab72e863512e14bdcba186641daf69e4e3a5761d705dcc35b1"}, 849 | {file = "SQLAlchemy-1.3.18-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:621f58cd921cd71ba6215c42954ffaa8a918eecd8c535d97befa1a8acad986dd"}, 850 | {file = "SQLAlchemy-1.3.18-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:fc728ece3d5c772c196fd338a99798e7efac7a04f9cb6416299a3638ee9a94cd"}, 851 | {file = "SQLAlchemy-1.3.18-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:736d41cfebedecc6f159fc4ac0769dc89528a989471dc1d378ba07d29a60ba1c"}, 852 | {file = "SQLAlchemy-1.3.18-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:427273b08efc16a85aa2b39892817e78e3ed074fcb89b2a51c4979bae7e7ba98"}, 853 | {file = "SQLAlchemy-1.3.18-cp35-cp35m-win32.whl", hash = "sha256:cbe1324ef52ff26ccde2cb84b8593c8bf930069dfc06c1e616f1bfd4e47f48a3"}, 854 | {file = "SQLAlchemy-1.3.18-cp35-cp35m-win_amd64.whl", hash = "sha256:8fd452dc3d49b3cc54483e033de6c006c304432e6f84b74d7b2c68afa2569ae5"}, 855 | {file = "SQLAlchemy-1.3.18-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:e89e0d9e106f8a9180a4ca92a6adde60c58b1b0299e1b43bd5e0312f535fbf33"}, 856 | {file = "SQLAlchemy-1.3.18-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:6ac2558631a81b85e7fb7a44e5035347938b0a73f5fdc27a8566777d0792a6a4"}, 857 | {file = "SQLAlchemy-1.3.18-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:87fad64529cde4f1914a5b9c383628e1a8f9e3930304c09cf22c2ae118a1280e"}, 858 | {file = "SQLAlchemy-1.3.18-cp36-cp36m-win32.whl", hash = "sha256:e4624d7edb2576cd72bb83636cd71c8ce544d8e272f308bd80885056972ca299"}, 859 | {file = "SQLAlchemy-1.3.18-cp36-cp36m-win_amd64.whl", hash = "sha256:89494df7f93b1836cae210c42864b292f9b31eeabca4810193761990dc689cce"}, 860 | {file = "SQLAlchemy-1.3.18-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:716754d0b5490bdcf68e1e4925edc02ac07209883314ad01a137642ddb2056f1"}, 861 | {file = "SQLAlchemy-1.3.18-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:50c4ee32f0e1581828843267d8de35c3298e86ceecd5e9017dc45788be70a864"}, 862 | {file = "SQLAlchemy-1.3.18-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:d98bc827a1293ae767c8f2f18be3bb5151fd37ddcd7da2a5f9581baeeb7a3fa1"}, 863 | {file = "SQLAlchemy-1.3.18-cp37-cp37m-win32.whl", hash = "sha256:0942a3a0df3f6131580eddd26d99071b48cfe5aaf3eab2783076fbc5a1c1882e"}, 864 | {file = "SQLAlchemy-1.3.18-cp37-cp37m-win_amd64.whl", hash = "sha256:16593fd748944726540cd20f7e83afec816c2ac96b082e26ae226e8f7e9688cf"}, 865 | {file = "SQLAlchemy-1.3.18-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:c26f95e7609b821b5f08a72dab929baa0d685406b953efd7c89423a511d5c413"}, 866 | {file = "SQLAlchemy-1.3.18-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:512a85c3c8c3995cc91af3e90f38f460da5d3cade8dc3a229c8e0879037547c9"}, 867 | {file = "SQLAlchemy-1.3.18-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:d05c4adae06bd0c7f696ae3ec8d993ed8ffcc4e11a76b1b35a5af8a099bd2284"}, 868 | {file = "SQLAlchemy-1.3.18-cp38-cp38-win32.whl", hash = "sha256:109581ccc8915001e8037b73c29590e78ce74be49ca0a3630a23831f9e3ed6c7"}, 869 | {file = "SQLAlchemy-1.3.18-cp38-cp38-win_amd64.whl", hash = "sha256:8619b86cb68b185a778635be5b3e6018623c0761dde4df2f112896424aa27bd8"}, 870 | {file = "SQLAlchemy-1.3.18.tar.gz", hash = "sha256:da2fb75f64792c1fc64c82313a00c728a7c301efe6a60b7a9fe35b16b4368ce7"}, 871 | ] 872 | toml = [ 873 | {file = "toml-0.10.1-py2.py3-none-any.whl", hash = "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"}, 874 | {file = "toml-0.10.1.tar.gz", hash = "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f"}, 875 | ] 876 | traitlets = [ 877 | {file = "traitlets-4.3.3-py2.py3-none-any.whl", hash = "sha256:70b4c6a1d9019d7b4f6846832288f86998aa3b9207c6821f3578a6a6a467fe44"}, 878 | {file = "traitlets-4.3.3.tar.gz", hash = "sha256:d023ee369ddd2763310e4c3eae1ff649689440d4ae59d7485eb4cfbbe3e359f7"}, 879 | ] 880 | typed-ast = [ 881 | {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3"}, 882 | {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb"}, 883 | {file = "typed_ast-1.4.1-cp35-cp35m-win32.whl", hash = "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919"}, 884 | {file = "typed_ast-1.4.1-cp35-cp35m-win_amd64.whl", hash = "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01"}, 885 | {file = "typed_ast-1.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75"}, 886 | {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652"}, 887 | {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"}, 888 | {file = "typed_ast-1.4.1-cp36-cp36m-win32.whl", hash = "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1"}, 889 | {file = "typed_ast-1.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa"}, 890 | {file = "typed_ast-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614"}, 891 | {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41"}, 892 | {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b"}, 893 | {file = "typed_ast-1.4.1-cp37-cp37m-win32.whl", hash = "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe"}, 894 | {file = "typed_ast-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355"}, 895 | {file = "typed_ast-1.4.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6"}, 896 | {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907"}, 897 | {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d"}, 898 | {file = "typed_ast-1.4.1-cp38-cp38-win32.whl", hash = "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c"}, 899 | {file = "typed_ast-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4"}, 900 | {file = "typed_ast-1.4.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34"}, 901 | {file = "typed_ast-1.4.1.tar.gz", hash = "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b"}, 902 | ] 903 | typing-extensions = [ 904 | {file = "typing_extensions-3.7.4.2-py2-none-any.whl", hash = "sha256:f8d2bd89d25bc39dabe7d23df520442fa1d8969b82544370e03d88b5a591c392"}, 905 | {file = "typing_extensions-3.7.4.2-py3-none-any.whl", hash = "sha256:6e95524d8a547a91e08f404ae485bbb71962de46967e1b71a0cb89af24e761c5"}, 906 | {file = "typing_extensions-3.7.4.2.tar.gz", hash = "sha256:79ee589a3caca649a9bfd2a8de4709837400dfa00b6cc81962a1e6a1815969ae"}, 907 | ] 908 | vine = [ 909 | {file = "vine-1.3.0-py2.py3-none-any.whl", hash = "sha256:ea4947cc56d1fd6f2095c8d543ee25dad966f78692528e68b4fada11ba3f98af"}, 910 | {file = "vine-1.3.0.tar.gz", hash = "sha256:133ee6d7a9016f177ddeaf191c1f58421a1dcc6ee9a42c58b34bed40e1d2cd87"}, 911 | ] 912 | wcwidth = [ 913 | {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, 914 | {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, 915 | ] 916 | werkzeug = [ 917 | {file = "Werkzeug-1.0.1-py2.py3-none-any.whl", hash = "sha256:2de2a5db0baeae7b2d2664949077c2ac63fbd16d98da0ff71837f7d1dea3fd43"}, 918 | {file = "Werkzeug-1.0.1.tar.gz", hash = "sha256:6c80b1e5ad3665290ea39320b91e1be1e0d5f60652b964a3070216de83d2e47c"}, 919 | ] 920 | --------------------------------------------------------------------------------