├── example_project ├── __init__.py ├── project │ ├── __init__.py │ ├── urls.py │ ├── asgi.py │ └── settings.py └── manage.py ├── django_live_dashboard ├── __init__.py ├── urls.py ├── asgi.py ├── views.py ├── websocket.py ├── conf.py ├── middleware.py └── templates │ └── django_live_dashboard │ └── monitoring.html ├── .flake8 ├── django-live-dashboard-demo.gif ├── pyproject.toml ├── .gitignore ├── README.md └── poetry.lock /example_project/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example_project/project/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /django_live_dashboard/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = '0.1.0' 2 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 80 3 | select = C,E,F,W,B,B950 4 | ignore = E501,W503 -------------------------------------------------------------------------------- /django-live-dashboard-demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adamghill/django-live-dashboard/master/django-live-dashboard-demo.gif -------------------------------------------------------------------------------- /django_live_dashboard/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from .views import monitoring 4 | 5 | 6 | app_name = "django_live_dashboard" 7 | 8 | urlpatterns = (path("monitoring/", monitoring, name="monitoring"),) 9 | -------------------------------------------------------------------------------- /example_project/project/urls.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | from django.contrib import admin 3 | from django.contrib.staticfiles import views 4 | from django.urls import include, path, re_path 5 | from django_live_dashboard import urls 6 | 7 | 8 | urlpatterns = [path("admin/", admin.site.urls), path("", include(urls))] 9 | 10 | if settings.DEBUG: 11 | urlpatterns += (re_path(r"^static/(?P.*)$", views.serve),) 12 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "django-live-dashboard" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["Adam Hill "] 6 | 7 | [tool.poetry.dependencies] 8 | python = "^3.6" 9 | hiredis = "^1.0.1" 10 | aioredis = "^1.3.1" 11 | django = "^3.0.5" 12 | orjson = "^2.6.5" 13 | django-app-settings = "^0.7.0" 14 | python-box = "^4.2.2" 15 | redis = "^3.4.1" 16 | 17 | [tool.poetry.dev-dependencies] 18 | pytest = "^4.6" 19 | flake8 = "^3.7.9" 20 | black = "^19.10b0" 21 | uvicorn = "^0.11.3" 22 | hiredis = "^1.0.1" 23 | 24 | [build-system] 25 | requires = ["poetry>=0.12"] 26 | build-backend = "poetry.masonry.api" 27 | -------------------------------------------------------------------------------- /django_live_dashboard/asgi.py: -------------------------------------------------------------------------------- 1 | # -*- mode: python -*- 2 | # vi: set ft=python : 3 | import os 4 | 5 | from django.core.asgi import get_asgi_application 6 | from django_live_dashboard.websocket import websocket_application 7 | 8 | 9 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings") 10 | 11 | django_application = get_asgi_application() 12 | 13 | 14 | async def application(scope, receive, send): 15 | if scope["type"] == "http": 16 | await django_application(scope, receive, send) 17 | elif scope["type"] == "websocket": 18 | await websocket_application(scope, receive, send) 19 | else: 20 | raise NotImplementedError(f"Unknown scope type {scope['type']}") 21 | -------------------------------------------------------------------------------- /example_project/project/asgi.py: -------------------------------------------------------------------------------- 1 | # -*- mode: python -*- 2 | # vi: set ft=python : 3 | import os 4 | 5 | from django.core.asgi import get_asgi_application 6 | from django_live_dashboard.websocket import websocket_application 7 | 8 | 9 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "example_project.project.settings") 10 | 11 | django_application = get_asgi_application() 12 | 13 | 14 | async def application(scope, receive, send): 15 | if scope["type"] == "http": 16 | await django_application(scope, receive, send) 17 | elif scope["type"] == "websocket": 18 | await websocket_application(scope, receive, send) 19 | else: 20 | raise NotImplementedError(f"Unknown scope type {scope['type']}") 21 | -------------------------------------------------------------------------------- /example_project/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings") 9 | 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == "__main__": 22 | main() 23 | -------------------------------------------------------------------------------- /django_live_dashboard/views.py: -------------------------------------------------------------------------------- 1 | from django.contrib.admin.views.decorators import staff_member_required 2 | from django.shortcuts import render 3 | 4 | from box import Box 5 | 6 | from .conf import Settings 7 | 8 | 9 | @staff_member_required 10 | def monitoring(request): 11 | settings = Box(Settings().DJANGO_LIVE_DASHBOARD) 12 | 13 | return render( 14 | request, 15 | "django_live_dashboard/monitoring.html", 16 | { 17 | "pubsub_channel": settings.REDIS.PUBSUB_CHANNEL, 18 | "websocket_host": settings.WEBSOCKET_HOST, 19 | "refresh": settings.CHART.REFRESH, 20 | "delay": settings.CHART.DELAY, 21 | "duration": settings.CHART.DURATION, 22 | }, 23 | ) 24 | -------------------------------------------------------------------------------- /django_live_dashboard/websocket.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | import aioredis 4 | import orjson 5 | from box import Box 6 | 7 | from .conf import Settings 8 | 9 | 10 | async def reader(channel, send): 11 | while await channel.wait_message(): 12 | message = await channel.get_json() 13 | await send( 14 | {"type": "websocket.send", "text": orjson.dumps(message).decode("utf-8")} 15 | ) 16 | 17 | 18 | async def websocket_application(scope, receive, send): 19 | settings = Box(Settings().DJANGO_LIVE_DASHBOARD) 20 | redis_host = settings.REDIS.HOST 21 | redis_port = settings.REDIS.PORT 22 | pubsub_channel = settings.REDIS.PUBSUB_CHANNEL 23 | 24 | subscriber = await aioredis.create_redis(f"redis://{redis_host}:{redis_port}") 25 | response = await subscriber.subscribe(pubsub_channel) 26 | 27 | while True: 28 | event = await receive() 29 | channel = response[0] 30 | task = None 31 | 32 | if event["type"] == "websocket.connect": 33 | await send({"type": "websocket.accept"}) 34 | 35 | if event["type"] == "websocket.disconnect": 36 | await subscriber.unsubscribe(pubsub_channel) 37 | 38 | if task: 39 | await task 40 | 41 | subscriber.close() 42 | break 43 | 44 | if event["type"] == "websocket.receive": 45 | if event["text"] == pubsub_channel: 46 | task = asyncio.ensure_future(reader(channel, send)) 47 | -------------------------------------------------------------------------------- /django_live_dashboard/conf.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | 3 | import appsettings 4 | 5 | 6 | REDIS_DEFAULTS = { 7 | "HOST": "localhost", 8 | "PORT": 6379, 9 | "DB": 0, 10 | "PUBSUB_CHANNEL": "django_live_dashboard:stats", 11 | } 12 | CHART_DEFAULTS = {"REFRESH": 1000, "DELAY": 1000, "DURATION": 10000} 13 | 14 | 15 | class Settings(appsettings.AppSettings): 16 | DJANGO_LIVE_DASHBOARD = appsettings.NestedDictSetting( 17 | settings=dict( 18 | ENABLED=appsettings.BooleanSetting(default=False), 19 | WEBSOCKET_HOST=appsettings.StringSetting(default="localhost:8000"), 20 | TOTAL_TIME_CUTOFF=appsettings.FloatSetting(default=0.5), 21 | REDIS=appsettings.NestedDictSetting( 22 | settings=dict( 23 | HOST=appsettings.StringSetting(default=REDIS_DEFAULTS["HOST"]), 24 | PORT=appsettings.IntegerSetting(default=REDIS_DEFAULTS["PORT"]), 25 | DB=appsettings.IntegerSetting(default=REDIS_DEFAULTS["DB"]), 26 | PUBSUB_CHANNEL=appsettings.StringSetting( 27 | default=REDIS_DEFAULTS["PUBSUB_CHANNEL"] 28 | ), 29 | ), 30 | default=REDIS_DEFAULTS, 31 | ), 32 | CHART=appsettings.NestedDictSetting( 33 | settings=dict( 34 | REFRESH=appsettings.IntegerSetting( 35 | default=CHART_DEFAULTS["REFRESH"] 36 | ), 37 | DELAY=appsettings.IntegerSetting(default=CHART_DEFAULTS["DELAY"]), 38 | DURATION=appsettings.IntegerSetting( 39 | default=CHART_DEFAULTS["DURATION"] 40 | ), 41 | ), 42 | default=CHART_DEFAULTS, 43 | ), 44 | ), 45 | default={ 46 | "ENABLED": False, 47 | "WEBSOCKET_HOST": "localhost:8000", 48 | "TOTAL_TIME_CUTOFF": 0.5, 49 | "REDIS": REDIS_DEFAULTS, 50 | "CHART": CHART_DEFAULTS, 51 | }, 52 | ) 53 | -------------------------------------------------------------------------------- /example_project/project/settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 5 | SECRET_KEY = "px1xyx=o(p*9&a$(w1+59calf9%83@eaxsb^%%me02^$iriz=@" 6 | DEBUG = True 7 | ALLOWED_HOSTS = ["localhost", "127.0.0.1", "0.0.0.0"] 8 | 9 | INSTALLED_APPS = [ 10 | "django.contrib.admin", 11 | "django.contrib.auth", 12 | "django.contrib.contenttypes", 13 | "django.contrib.sessions", 14 | "django.contrib.messages", 15 | "django.contrib.staticfiles", 16 | "django_live_dashboard", 17 | ] 18 | 19 | MIDDLEWARE = [ 20 | "django_live_dashboard.middleware.DjangoLiveDashboardMiddleware", 21 | "django.middleware.security.SecurityMiddleware", 22 | "django.contrib.sessions.middleware.SessionMiddleware", 23 | "django.middleware.common.CommonMiddleware", 24 | "django.middleware.csrf.CsrfViewMiddleware", 25 | "django.contrib.auth.middleware.AuthenticationMiddleware", 26 | "django.contrib.messages.middleware.MessageMiddleware", 27 | "django.middleware.clickjacking.XFrameOptionsMiddleware", 28 | ] 29 | 30 | ROOT_URLCONF = "example_project.project.urls" 31 | 32 | TEMPLATES = [ 33 | { 34 | "BACKEND": "django.template.backends.django.DjangoTemplates", 35 | "DIRS": [], 36 | "APP_DIRS": True, 37 | "OPTIONS": { 38 | "context_processors": [ 39 | "django.template.context_processors.debug", 40 | "django.template.context_processors.request", 41 | "django.contrib.auth.context_processors.auth", 42 | "django.contrib.messages.context_processors.messages", 43 | ], 44 | }, 45 | }, 46 | ] 47 | 48 | DATABASES = { 49 | "default": { 50 | "ENGINE": "django.db.backends.sqlite3", 51 | "NAME": os.path.join(BASE_DIR, "db.sqlite3"), 52 | } 53 | } 54 | 55 | STATIC_URL = "/static/" 56 | 57 | DJANGO_LIVE_DASHBOARD = { 58 | "ENABLED": True, 59 | "WEBSOCKET_HOST": "localhost:8000", 60 | "TOTAL_TIME_CUTOFF": 0, 61 | "REDIS": { 62 | "HOST": "localhost", 63 | "PORT": 6379, 64 | "DB": 0, 65 | "PUBSUB_CHANNEL": "django_live_dashboard:stats", 66 | }, 67 | "CHART": {"REFRESH": 1000, "DELAY": 1000, "DURATION": 100000}, 68 | } 69 | -------------------------------------------------------------------------------- /django_live_dashboard/middleware.py: -------------------------------------------------------------------------------- 1 | from time import time 2 | 3 | from django.db import connection 4 | 5 | import orjson 6 | import redis 7 | from box import Box 8 | 9 | from .conf import Settings 10 | 11 | 12 | class DjangoLiveDashboardMiddleware: 13 | def __init__(self, get_response): 14 | self.get_response = get_response 15 | self.settings = Box(Settings().DJANGO_LIVE_DASHBOARD) 16 | 17 | if self.settings.ENABLED: 18 | redis_host = self.settings.REDIS.HOST 19 | redis_port = self.settings.REDIS.PORT 20 | redis_db = self.settings.REDIS.DB 21 | 22 | self.redis_connection = redis.Redis( 23 | host=redis_host, port=redis_port, db=redis_db, 24 | ) 25 | 26 | def __call__(self, request): 27 | if not self.settings.ENABLED: 28 | return self.get_response(request) 29 | 30 | # Get initial data 31 | start = time() 32 | initial_database_query_count = len(connection.queries) 33 | 34 | response = self.get_response(request) 35 | 36 | # Get data after the response has been created 37 | total_time = time() - start 38 | total_time_cutoff = self.settings.TOTAL_TIME_CUTOFF or 0 39 | 40 | if total_time > total_time_cutoff: 41 | database_queries = len(connection.queries) - initial_database_query_count 42 | database_time = 0.0 43 | 44 | if database_queries: 45 | database_time = sum( 46 | [ 47 | float(q["time"]) 48 | for q in connection.queries[initial_database_query_count:] 49 | ], 50 | ) 51 | 52 | python_time = total_time - database_time 53 | url = request.path 54 | 55 | stats = { 56 | "url": url, 57 | "totalTime": total_time, 58 | "pythonTime": python_time, 59 | "databaseTime": database_time, 60 | "databaseQueries": (database_queries - initial_database_query_count), 61 | } 62 | 63 | pubsub_channel = self.settings.REDIS.PUBSUB_CHANNEL 64 | self.redis_connection.publish(pubsub_channel, orjson.dumps(stats)) 65 | 66 | return response 67 | -------------------------------------------------------------------------------- /.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 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | 53 | # Translations 54 | *.mo 55 | *.pot 56 | 57 | # Django stuff: 58 | *.log 59 | local_settings.py 60 | db.sqlite3 61 | db.sqlite3-journal 62 | statics 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 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # celery beat schedule file 95 | celerybeat-schedule 96 | 97 | # SageMath parsed files 98 | *.sage.py 99 | 100 | # Environments 101 | .env 102 | .venv 103 | env/ 104 | venv/ 105 | ENV/ 106 | env.bak/ 107 | venv.bak/ 108 | 109 | # Spyder project settings 110 | .spyderproject 111 | .spyproject 112 | 113 | # Rope project settings 114 | .ropeproject 115 | 116 | # mkdocs documentation 117 | /site 118 | 119 | # mypy 120 | .mypy_cache/ 121 | .dmypy.json 122 | dmypy.json 123 | 124 | # Pyre type checker 125 | .pyre/ 126 | 127 | .DS_Store 128 | *.sublime-workspace 129 | media/ 130 | 131 | node_modules/ 132 | 133 | .autoenv*.zsh 134 | .dj-config.* 135 | 136 | .pytype 137 | .idea/ 138 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # django_live_dashboard 2 | 3 | Inspired by Phoenix's LiveView Dashboard. Uses `redis` pub-sub, chart.js, alpine.js, and websockets for streaming realtime updates of all current requests to a Django application. 4 | 5 | ![](https://github.com/adamghill/django-live-dashboard/blob/master/django-live-dashboard-demo.gif) 6 | 7 | # Requires 8 | 1. Python 3.6+ 9 | 1. Django 3.0+ 10 | 1. Django to be run via `ASGI` for websockets support 11 | 12 | # Install 13 | 1. `pip install django-live-dashboard` or `poetry add django-live-dashboard` 14 | 1. Update current `asgi.py` or use the `asgi.py` file in the repo as an example 15 | 1. Add `"django_live_dashboard",` to `INSTALLED_APPS` in settings file 16 | 1. Add `"django_live_dashboard.middleware.DjangoLiveDashboardMiddleware",` to beginning of the `MIDDLEWARE` list in settings file 17 | 1. Add `DJANGO_LIVE_DASHBOARD` configuration to settings file (see details below) 18 | 1. Add to default `urls.py`: `path("admin/", include(django_live_dashboard_urls))` 19 | 1. Run your server with something like `uvicorn project.asgi:application --port=8000` 20 | 21 | # Settings 22 | Configuration is in a `DJANGO_LIVE_DASHBOARD` setting. 23 | 24 | ## Example 25 | ```python 26 | DJANGO_LIVE_DASHBOARD = { 27 | "ENABLED": True, 28 | "WEBSOCKET_HOST": 'localhost:8000', 29 | "TOTAL_TIME_CUTOFF": 0.5, 30 | "REDIS": { 31 | "HOST": "localhost", 32 | "PORT": 6379, 33 | "DB": 0, 34 | "PUBSUB_CHANNEL": "django_live_dashboard:stats" 35 | }, 36 | "CHART": { 37 | "REFRESH": 1000, 38 | "DELAY": 1000, 39 | "DURATION": 100000, 40 | } 41 | } 42 | ``` 43 | 44 | ## ENABLED 45 | Whether any statistics should be logged. Defaults to `DEBUG`. 46 | 47 | ## WEBSOCKET_HOST 48 | The host that the websocket should listen to. Defaults to `localhost`. 49 | 50 | ## TOTAL_TIME_CUTOFF 51 | How long a request should take in seconds before getting logged. For example, if the value is 0.75, any request that takes longer than three quarters of a second will get graphed. Defaults to `0.5`. 52 | 53 | ## REDIS 54 | Redis configuration with standard `HOST`, `PORT`, and `DB` settings in a dictionary. 55 | 56 | ### HOST 57 | The host of the redis server. Defaults to `localhost`. 58 | 59 | ### PORT 60 | THe port of the redis server. Defaults to `6379`. 61 | 62 | ### DB 63 | The database of the redis server. Defaults to `0`. 64 | 65 | ## CHART 66 | Configuration for the streaming `chart.js` plugin. 67 | 68 | ### DELAY 69 | Delay in milliseconds of the `chart.js` which helps to make the drawing more fluid and smooth. Defaults to 1000. 70 | 71 | ### DURATION 72 | Time duration in milliseconds of how much data should be charted. Defaults to 100000. 73 | 74 | ### REFRESH 75 | How often the chart should try to refresh its data. Defaults to 1000. 76 | 77 | # Example Django project 78 | 79 | Found in the `example_project` directory in this repo. 80 | 81 | ## How to run 82 | 83 | 1. `redis-server` 84 | 1. `poetry install` 85 | 1. `poetry run example_project/manage.py migrate` 86 | 1. `poetry run example_project/manage.py createsuperuser` 87 | 1. `poetry run uvicorn example_project.project.asgi:application` 88 | 1. Go to http://localhost:8000/monitoring/ 89 | 1. Open up http://localhost:8000/admin/ in a new tab; go back to the first tab and you should see some updated information 90 | -------------------------------------------------------------------------------- /django_live_dashboard/templates/django_live_dashboard/monitoring.html: -------------------------------------------------------------------------------- 1 | {% extends 'admin/base_site.html' %} 2 | 3 | {% block extrahead %} 4 | 5 | 6 | 8 | 9 | {% endblock extrahead %} 10 | 11 | {% block content %} 12 |
13 |
14 |
15 | 20 | 25 | 30 |
31 |
32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | 48 | 49 |
50 | {% endblock %} 51 | 52 | {% block footer %} 53 | {{ block.super }} 54 | 265 | {% endblock %} -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | category = "main" 3 | description = "asyncio (PEP 3156) Redis support" 4 | name = "aioredis" 5 | optional = false 6 | python-versions = "*" 7 | version = "1.3.1" 8 | 9 | [package.dependencies] 10 | async-timeout = "*" 11 | hiredis = "*" 12 | 13 | [[package]] 14 | category = "dev" 15 | description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." 16 | name = "appdirs" 17 | optional = false 18 | python-versions = "*" 19 | version = "1.4.3" 20 | 21 | [[package]] 22 | category = "main" 23 | description = "ASGI specs, helper code, and adapters" 24 | name = "asgiref" 25 | optional = false 26 | python-versions = ">=3.5" 27 | version = "3.2.7" 28 | 29 | [package.extras] 30 | tests = ["pytest (>=4.3.0,<4.4.0)", "pytest-asyncio (>=0.10.0,<0.11.0)"] 31 | 32 | [[package]] 33 | category = "main" 34 | description = "Timeout context manager for asyncio programs" 35 | name = "async-timeout" 36 | optional = false 37 | python-versions = "*" 38 | version = "2.0.1" 39 | 40 | [[package]] 41 | category = "dev" 42 | description = "Atomic file writes." 43 | name = "atomicwrites" 44 | optional = false 45 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 46 | version = "1.3.0" 47 | 48 | [[package]] 49 | category = "dev" 50 | description = "Classes Without Boilerplate" 51 | name = "attrs" 52 | optional = false 53 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 54 | version = "19.3.0" 55 | 56 | [package.extras] 57 | azure-pipelines = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "pytest-azurepipelines"] 58 | dev = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "pre-commit"] 59 | docs = ["sphinx", "zope.interface"] 60 | tests = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] 61 | 62 | [[package]] 63 | category = "dev" 64 | description = "The uncompromising code formatter." 65 | name = "black" 66 | optional = false 67 | python-versions = ">=3.6" 68 | version = "19.10b0" 69 | 70 | [package.dependencies] 71 | appdirs = "*" 72 | attrs = ">=18.1.0" 73 | click = ">=6.5" 74 | pathspec = ">=0.6,<1" 75 | regex = "*" 76 | toml = ">=0.9.4" 77 | typed-ast = ">=1.4.0" 78 | 79 | [package.extras] 80 | d = ["aiohttp (>=3.3.2)", "aiohttp-cors"] 81 | 82 | [[package]] 83 | category = "dev" 84 | description = "Composable command line interface toolkit" 85 | name = "click" 86 | optional = false 87 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 88 | version = "7.1.1" 89 | 90 | [[package]] 91 | category = "dev" 92 | description = "Cross-platform colored terminal text." 93 | marker = "sys_platform == \"win32\" and python_version != \"3.4\"" 94 | name = "colorama" 95 | optional = false 96 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 97 | version = "0.4.3" 98 | 99 | [[package]] 100 | category = "main" 101 | description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design." 102 | name = "django" 103 | optional = false 104 | python-versions = ">=3.6" 105 | version = "3.0.5" 106 | 107 | [package.dependencies] 108 | asgiref = ">=3.2,<4.0" 109 | pytz = "*" 110 | sqlparse = ">=0.2.2" 111 | 112 | [package.extras] 113 | argon2 = ["argon2-cffi (>=16.1.0)"] 114 | bcrypt = ["bcrypt"] 115 | 116 | [[package]] 117 | category = "main" 118 | description = "Application settings helper for Django apps." 119 | name = "django-app-settings" 120 | optional = false 121 | python-versions = "~=3.5" 122 | version = "0.7.0" 123 | 124 | [package.dependencies] 125 | Django = "*" 126 | 127 | [[package]] 128 | category = "dev" 129 | description = "Discover and load entry points from installed packages." 130 | name = "entrypoints" 131 | optional = false 132 | python-versions = ">=2.7" 133 | version = "0.3" 134 | 135 | [[package]] 136 | category = "dev" 137 | description = "the modular source code checker: pep8, pyflakes and co" 138 | name = "flake8" 139 | optional = false 140 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 141 | version = "3.7.9" 142 | 143 | [package.dependencies] 144 | entrypoints = ">=0.3.0,<0.4.0" 145 | mccabe = ">=0.6.0,<0.7.0" 146 | pycodestyle = ">=2.5.0,<2.6.0" 147 | pyflakes = ">=2.1.0,<2.2.0" 148 | 149 | [[package]] 150 | category = "dev" 151 | description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" 152 | name = "h11" 153 | optional = false 154 | python-versions = "*" 155 | version = "0.9.0" 156 | 157 | [[package]] 158 | category = "main" 159 | description = "Python wrapper for hiredis" 160 | name = "hiredis" 161 | optional = false 162 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 163 | version = "1.0.1" 164 | 165 | [[package]] 166 | category = "dev" 167 | description = "A collection of framework independent HTTP protocol utils." 168 | marker = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"" 169 | name = "httptools" 170 | optional = false 171 | python-versions = "*" 172 | version = "0.1.1" 173 | 174 | [package.extras] 175 | test = ["Cython (0.29.14)"] 176 | 177 | [[package]] 178 | category = "dev" 179 | description = "Read metadata from Python packages" 180 | marker = "python_version < \"3.8\"" 181 | name = "importlib-metadata" 182 | optional = false 183 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" 184 | version = "1.6.0" 185 | 186 | [package.dependencies] 187 | zipp = ">=0.5" 188 | 189 | [package.extras] 190 | docs = ["sphinx", "rst.linker"] 191 | testing = ["packaging", "importlib-resources"] 192 | 193 | [[package]] 194 | category = "dev" 195 | description = "McCabe checker, plugin for flake8" 196 | name = "mccabe" 197 | optional = false 198 | python-versions = "*" 199 | version = "0.6.1" 200 | 201 | [[package]] 202 | category = "dev" 203 | description = "More routines for operating on iterables, beyond itertools" 204 | marker = "python_version > \"2.7\"" 205 | name = "more-itertools" 206 | optional = false 207 | python-versions = "*" 208 | version = "5.0.0" 209 | 210 | [package.dependencies] 211 | six = ">=1.0.0,<2.0.0" 212 | 213 | [[package]] 214 | category = "main" 215 | description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" 216 | name = "orjson" 217 | optional = false 218 | python-versions = ">=3.6" 219 | version = "2.6.5" 220 | 221 | [[package]] 222 | category = "dev" 223 | description = "Core utilities for Python packages" 224 | name = "packaging" 225 | optional = false 226 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 227 | version = "20.3" 228 | 229 | [package.dependencies] 230 | pyparsing = ">=2.0.2" 231 | six = "*" 232 | 233 | [[package]] 234 | category = "dev" 235 | description = "Utility library for gitignore style pattern matching of file paths." 236 | name = "pathspec" 237 | optional = false 238 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 239 | version = "0.8.0" 240 | 241 | [[package]] 242 | category = "dev" 243 | description = "plugin and hook calling mechanisms for python" 244 | name = "pluggy" 245 | optional = false 246 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 247 | version = "0.13.1" 248 | 249 | [package.dependencies] 250 | [package.dependencies.importlib-metadata] 251 | python = "<3.8" 252 | version = ">=0.12" 253 | 254 | [package.extras] 255 | dev = ["pre-commit", "tox"] 256 | 257 | [[package]] 258 | category = "dev" 259 | description = "library with cross-python path, ini-parsing, io, code, log facilities" 260 | name = "py" 261 | optional = false 262 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 263 | version = "1.8.1" 264 | 265 | [[package]] 266 | category = "dev" 267 | description = "Python style guide checker" 268 | name = "pycodestyle" 269 | optional = false 270 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 271 | version = "2.5.0" 272 | 273 | [[package]] 274 | category = "dev" 275 | description = "passive checker of Python programs" 276 | name = "pyflakes" 277 | optional = false 278 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 279 | version = "2.1.1" 280 | 281 | [[package]] 282 | category = "dev" 283 | description = "Python parsing module" 284 | name = "pyparsing" 285 | optional = false 286 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 287 | version = "2.4.7" 288 | 289 | [[package]] 290 | category = "dev" 291 | description = "pytest: simple powerful testing with Python" 292 | name = "pytest" 293 | optional = false 294 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" 295 | version = "4.6.9" 296 | 297 | [package.dependencies] 298 | atomicwrites = ">=1.0" 299 | attrs = ">=17.4.0" 300 | packaging = "*" 301 | pluggy = ">=0.12,<1.0" 302 | py = ">=1.5.0" 303 | six = ">=1.10.0" 304 | wcwidth = "*" 305 | 306 | [package.dependencies.colorama] 307 | python = "<3.4.0 || >=3.5.0" 308 | version = "*" 309 | 310 | [package.dependencies.importlib-metadata] 311 | python = "<3.8" 312 | version = ">=0.12" 313 | 314 | [package.dependencies.more-itertools] 315 | python = ">=2.8" 316 | version = ">=4.0.0" 317 | 318 | [package.extras] 319 | testing = ["argcomplete", "hypothesis (>=3.56)", "nose", "requests", "mock"] 320 | 321 | [[package]] 322 | category = "main" 323 | description = "Advanced Python dictionaries with dot notation access" 324 | name = "python-box" 325 | optional = false 326 | python-versions = ">=3.6" 327 | version = "4.2.2" 328 | 329 | [package.dependencies] 330 | "ruamel.yaml" = "*" 331 | toml = "*" 332 | 333 | [[package]] 334 | category = "main" 335 | description = "World timezone definitions, modern and historical" 336 | name = "pytz" 337 | optional = false 338 | python-versions = "*" 339 | version = "2019.3" 340 | 341 | [[package]] 342 | category = "main" 343 | description = "Python client for Redis key-value store" 344 | name = "redis" 345 | optional = false 346 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 347 | version = "3.4.1" 348 | 349 | [package.extras] 350 | hiredis = ["hiredis (>=0.1.3)"] 351 | 352 | [[package]] 353 | category = "dev" 354 | description = "Alternative regular expression module, to replace re." 355 | name = "regex" 356 | optional = false 357 | python-versions = "*" 358 | version = "2020.4.4" 359 | 360 | [[package]] 361 | category = "main" 362 | description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" 363 | name = "ruamel.yaml" 364 | optional = false 365 | python-versions = "*" 366 | version = "0.16.10" 367 | 368 | [package.dependencies] 369 | [package.dependencies."ruamel.yaml.clib"] 370 | python = "<3.9" 371 | version = ">=0.1.2" 372 | 373 | [package.extras] 374 | docs = ["ryd"] 375 | jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] 376 | 377 | [[package]] 378 | category = "main" 379 | description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" 380 | marker = "platform_python_implementation == \"CPython\" and python_version < \"3.9\"" 381 | name = "ruamel.yaml.clib" 382 | optional = false 383 | python-versions = "*" 384 | version = "0.2.0" 385 | 386 | [[package]] 387 | category = "dev" 388 | description = "Python 2 and 3 compatibility utilities" 389 | name = "six" 390 | optional = false 391 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 392 | version = "1.14.0" 393 | 394 | [[package]] 395 | category = "main" 396 | description = "Non-validating SQL parser" 397 | name = "sqlparse" 398 | optional = false 399 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 400 | version = "0.3.1" 401 | 402 | [[package]] 403 | category = "main" 404 | description = "Python Library for Tom's Obvious, Minimal Language" 405 | name = "toml" 406 | optional = false 407 | python-versions = "*" 408 | version = "0.10.0" 409 | 410 | [[package]] 411 | category = "dev" 412 | description = "a fork of Python 2 and 3 ast modules with type comment support" 413 | name = "typed-ast" 414 | optional = false 415 | python-versions = "*" 416 | version = "1.4.1" 417 | 418 | [[package]] 419 | category = "dev" 420 | description = "The lightning-fast ASGI server." 421 | name = "uvicorn" 422 | optional = false 423 | python-versions = "*" 424 | version = "0.11.3" 425 | 426 | [package.dependencies] 427 | click = ">=7.0.0,<8.0.0" 428 | h11 = ">=0.8,<0.10" 429 | httptools = ">=0.1.0,<0.2.0" 430 | uvloop = ">=0.14.0" 431 | websockets = ">=8.0.0,<9.0.0" 432 | 433 | [[package]] 434 | category = "dev" 435 | description = "Fast implementation of asyncio event loop on top of libuv" 436 | marker = "sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"" 437 | name = "uvloop" 438 | optional = false 439 | python-versions = "*" 440 | version = "0.14.0" 441 | 442 | [[package]] 443 | category = "dev" 444 | description = "Measures number of Terminal column cells of wide-character codes" 445 | name = "wcwidth" 446 | optional = false 447 | python-versions = "*" 448 | version = "0.1.9" 449 | 450 | [[package]] 451 | category = "dev" 452 | description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" 453 | name = "websockets" 454 | optional = false 455 | python-versions = ">=3.6" 456 | version = "8.0.2" 457 | 458 | [[package]] 459 | category = "dev" 460 | description = "Backport of pathlib-compatible object wrapper for zip files" 461 | marker = "python_version < \"3.8\"" 462 | name = "zipp" 463 | optional = false 464 | python-versions = ">=2.7" 465 | version = "1.2.0" 466 | 467 | [package.extras] 468 | docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] 469 | testing = ["pathlib2", "unittest2", "jaraco.itertools", "func-timeout"] 470 | 471 | [metadata] 472 | content-hash = "a17ab7dc839767c2e68598e177c2ade519a4da2e1de5d784b175370f1197dd14" 473 | python-versions = "^3.6" 474 | 475 | [metadata.files] 476 | aioredis = [ 477 | {file = "aioredis-1.3.1-py3-none-any.whl", hash = "sha256:b61808d7e97b7cd5a92ed574937a079c9387fdadd22bfbfa7ad2fd319ecc26e3"}, 478 | {file = "aioredis-1.3.1.tar.gz", hash = "sha256:15f8af30b044c771aee6787e5ec24694c048184c7b9e54c3b60c750a4b93273a"}, 479 | ] 480 | appdirs = [ 481 | {file = "appdirs-1.4.3-py2.py3-none-any.whl", hash = "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e"}, 482 | {file = "appdirs-1.4.3.tar.gz", hash = "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92"}, 483 | ] 484 | asgiref = [ 485 | {file = "asgiref-3.2.7-py2.py3-none-any.whl", hash = "sha256:9ca8b952a0a9afa61d30aa6d3d9b570bb3fd6bafcf7ec9e6bed43b936133db1c"}, 486 | {file = "asgiref-3.2.7.tar.gz", hash = "sha256:8036f90603c54e93521e5777b2b9a39ba1bad05773fcf2d208f0299d1df58ce5"}, 487 | ] 488 | async-timeout = [ 489 | {file = "async-timeout-2.0.1.tar.gz", hash = "sha256:00cff4d2dce744607335cba84e9929c3165632da2d27970dbc55802a0c7873d0"}, 490 | {file = "async_timeout-2.0.1-py3-none-any.whl", hash = "sha256:9093db5b8ddbe4b8f6885d1a6e0ad84ae3155464cbf6877c387605244c285f3c"}, 491 | ] 492 | atomicwrites = [ 493 | {file = "atomicwrites-1.3.0-py2.py3-none-any.whl", hash = "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4"}, 494 | {file = "atomicwrites-1.3.0.tar.gz", hash = "sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6"}, 495 | ] 496 | attrs = [ 497 | {file = "attrs-19.3.0-py2.py3-none-any.whl", hash = "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c"}, 498 | {file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"}, 499 | ] 500 | black = [ 501 | {file = "black-19.10b0-py36-none-any.whl", hash = "sha256:1b30e59be925fafc1ee4565e5e08abef6b03fe455102883820fe5ee2e4734e0b"}, 502 | {file = "black-19.10b0.tar.gz", hash = "sha256:c2edb73a08e9e0e6f65a0e6af18b059b8b1cdd5bef997d7a0b181df93dc81539"}, 503 | ] 504 | click = [ 505 | {file = "click-7.1.1-py2.py3-none-any.whl", hash = "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a"}, 506 | {file = "click-7.1.1.tar.gz", hash = "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc"}, 507 | ] 508 | colorama = [ 509 | {file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"}, 510 | {file = "colorama-0.4.3.tar.gz", hash = "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"}, 511 | ] 512 | django = [ 513 | {file = "Django-3.0.5-py3-none-any.whl", hash = "sha256:642d8eceab321ca743ae71e0f985ff8fdca59f07aab3a9fb362c617d23e33a76"}, 514 | {file = "Django-3.0.5.tar.gz", hash = "sha256:d4666c2edefa38c5ede0ec1655424c56dc47ceb04b6d8d62a7eac09db89545c1"}, 515 | ] 516 | django-app-settings = [ 517 | {file = "django-app-settings-0.7.0.tar.gz", hash = "sha256:d7747794620086059ad07d0b80ee93ed59c0294ad1b297c043499a433a9cf218"}, 518 | ] 519 | entrypoints = [ 520 | {file = "entrypoints-0.3-py2.py3-none-any.whl", hash = "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19"}, 521 | {file = "entrypoints-0.3.tar.gz", hash = "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"}, 522 | ] 523 | flake8 = [ 524 | {file = "flake8-3.7.9-py2.py3-none-any.whl", hash = "sha256:49356e766643ad15072a789a20915d3c91dc89fd313ccd71802303fd67e4deca"}, 525 | {file = "flake8-3.7.9.tar.gz", hash = "sha256:45681a117ecc81e870cbf1262835ae4af5e7a8b08e40b944a8a6e6b895914cfb"}, 526 | ] 527 | h11 = [ 528 | {file = "h11-0.9.0-py2.py3-none-any.whl", hash = "sha256:4bc6d6a1238b7615b266ada57e0618568066f57dd6fa967d1290ec9309b2f2f1"}, 529 | {file = "h11-0.9.0.tar.gz", hash = "sha256:33d4bca7be0fa039f4e84d50ab00531047e53d6ee8ffbc83501ea602c169cae1"}, 530 | ] 531 | hiredis = [ 532 | {file = "hiredis-1.0.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:38437a681f17c975fd22349e72c29bc643f8e7eb2d6dc5df419eac59afa4d7ce"}, 533 | {file = "hiredis-1.0.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:102f9b9dc6ed57feb3a7c9bdf7e71cb7c278fe8df1edfcfe896bc3e0c2be9447"}, 534 | {file = "hiredis-1.0.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:dbaef9a21a4f10bc281684ee4124f169e62bb533c2a92b55f8c06f64f9af7b8f"}, 535 | {file = "hiredis-1.0.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:03ed34a13316d0c34213c4fd46e0fa3a5299073f4d4f08e93fed8c2108b399b3"}, 536 | {file = "hiredis-1.0.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:d6456afeddba036def1a36d8a2758eca53202308d83db20ab5d0b66590919627"}, 537 | {file = "hiredis-1.0.1-cp27-cp27m-win32.whl", hash = "sha256:4a60e71625a2d78d8ab84dfb2fa2cfd9458c964b6e6c04fea76d9ade153fb371"}, 538 | {file = "hiredis-1.0.1-cp27-cp27m-win_amd64.whl", hash = "sha256:091eb38fbf968d1c5b703e412bbbd25f43a7967d8400842cee33a5a07b33c27b"}, 539 | {file = "hiredis-1.0.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:75c65c3850e89e9daa68d1b9bedd5806f177d60aa5a7b0953b4829481cfc1f72"}, 540 | {file = "hiredis-1.0.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:fa2dc05b87d97acc1c6ae63f3e0f39eae5246565232484b08db6bf2dc1580678"}, 541 | {file = "hiredis-1.0.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:74b364b3f06c9cf0a53f7df611045bc9437ed972a283fa1f0b12537236d23ddc"}, 542 | {file = "hiredis-1.0.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:9afeb88c67bbc663b9f27385c496da056d06ad87f55df6e393e1516cfecb0461"}, 543 | {file = "hiredis-1.0.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:040436e91df5143aff9e0debb49530d0b17a6bd52200ce568621c31ef581b10d"}, 544 | {file = "hiredis-1.0.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2b4b392c7e3082860c8371fab3ae762139090f9115819e12d9f56060f9ede05d"}, 545 | {file = "hiredis-1.0.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:936aa565e673536e8a211e43ec43197406f24cd1f290138bd143765079c8ba00"}, 546 | {file = "hiredis-1.0.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:48c627581ad4ef60adbac980981407939acf13a0e18f093502c7b542223c4f19"}, 547 | {file = "hiredis-1.0.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:9d62cc7880110e4f83b0a51d218f465d3095e2751fbddd34e553dbd106a929ff"}, 548 | {file = "hiredis-1.0.1-cp35-cp35m-win32.whl", hash = "sha256:8113a7d5e87ecf57cd4ae263cc9e429adb9a3e59f5a7768da5d3312a8d0a051a"}, 549 | {file = "hiredis-1.0.1-cp35-cp35m-win_amd64.whl", hash = "sha256:fe7d6ce9f6a5fbe24f09d95ea93e9c7271abc4e1565da511e1449b107b4d7848"}, 550 | {file = "hiredis-1.0.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:efc98b14ee3a8595e40b1425e8d42f5fd26f11a7b215a81ef9259068931754f4"}, 551 | {file = "hiredis-1.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:01ff0900134166961c9e339df77c33b72f7edc5cb41739f0babcd9faa345926e"}, 552 | {file = "hiredis-1.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d0caf98dfb8af395d6732bd16561c0a2458851bea522e39f12f04802dbf6f502"}, 553 | {file = "hiredis-1.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:ae2ee0992f8de249715435942137843a93db204dd7db1e7cc9bdc5a8436443e8"}, 554 | {file = "hiredis-1.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:4414a96c212e732723b5c3d7c04d386ebbb2ec359e1de646322cbc3f875cbd0d"}, 555 | {file = "hiredis-1.0.1-cp36-cp36m-win32.whl", hash = "sha256:7f052de8bf744730a9120dbdc67bfeb7605a01f69fb8e7ba5c475af33c24e145"}, 556 | {file = "hiredis-1.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:2fa65a9df683bca72073cd77709ddeb289ea2b114d3775d225fbbcc5faf808c5"}, 557 | {file = "hiredis-1.0.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:585ace09f434e43d8a8dbeb366865b1a044d7c06319b3c7372a0a00e63b860f4"}, 558 | {file = "hiredis-1.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:bcbf9379c553b5facc6c04c1e5569b44b38ff16bcbf354676287698d61ee0c92"}, 559 | {file = "hiredis-1.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:3b3428fa3cf1ee178807b52c9bee8950ab94cd4eaa9bfae8c1bbae3c49501d34"}, 560 | {file = "hiredis-1.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:cbccbda6f1c62ab460449d9c85fdf24d0d32a6bf45176581151e53cc26a5d910"}, 561 | {file = "hiredis-1.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:2c9cc0b986397b833073f466e6b9e9c70d1d4dc2c2c1b3e9cae3a23102ff296c"}, 562 | {file = "hiredis-1.0.1-cp37-cp37m-win32.whl", hash = "sha256:84857ce239eb8ed191ac78e77ff65d52902f00f30f4ee83bf80eb71da73b70e6"}, 563 | {file = "hiredis-1.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:b36842d7cf32929d568f37ec5b3173b72b2ec6572dec4d6be6ce774762215aee"}, 564 | {file = "hiredis-1.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3dd8c2fae7f5494978facb0e93297dd627b1a3f536f3b070cf0a7d9157a07dcb"}, 565 | {file = "hiredis-1.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:01b577f84c20ecc9c07fc4c184231b08e3c3942de096fa99978e053de231c423"}, 566 | {file = "hiredis-1.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:a1fadd062fc8d647ff39220c57ea2b48c99bb73f18223828ec97f88fc27e7898"}, 567 | {file = "hiredis-1.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:dce84916c09aaece006272b37234ae84a8ed13abb3a4d341a23933b8701abfb5"}, 568 | {file = "hiredis-1.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:8644a48ddc4a40b3e3a6b9443f396c2ee353afb2d45656c4fc68d04a82e8e3f7"}, 569 | {file = "hiredis-1.0.1-cp38-cp38-win32.whl", hash = "sha256:eb8c9c8b9869539d58d60ff4a28373a22514d40495911451343971cb4835b7a9"}, 570 | {file = "hiredis-1.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:a7754a783b1e5d6f627c19d099b178059c62f782ab62b4d8ba165b9fbc2ee34c"}, 571 | {file = "hiredis-1.0.1.tar.gz", hash = "sha256:aa59dd63bb3f736de4fc2d080114429d5d369dfb3265f771778e8349d67a97a4"}, 572 | ] 573 | httptools = [ 574 | {file = "httptools-0.1.1-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:a2719e1d7a84bb131c4f1e0cb79705034b48de6ae486eb5297a139d6a3296dce"}, 575 | {file = "httptools-0.1.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:fa3cd71e31436911a44620473e873a256851e1f53dee56669dae403ba41756a4"}, 576 | {file = "httptools-0.1.1-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:86c6acd66765a934e8730bf0e9dfaac6fdcf2a4334212bd4a0a1c78f16475ca6"}, 577 | {file = "httptools-0.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:bc3114b9edbca5a1eb7ae7db698c669eb53eb8afbbebdde116c174925260849c"}, 578 | {file = "httptools-0.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:ac0aa11e99454b6a66989aa2d44bca41d4e0f968e395a0a8f164b401fefe359a"}, 579 | {file = "httptools-0.1.1-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:96da81e1992be8ac2fd5597bf0283d832287e20cb3cfde8996d2b00356d4e17f"}, 580 | {file = "httptools-0.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:56b6393c6ac7abe632f2294da53f30d279130a92e8ae39d8d14ee2e1b05ad1f2"}, 581 | {file = "httptools-0.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:96eb359252aeed57ea5c7b3d79839aaa0382c9d3149f7d24dd7172b1bcecb009"}, 582 | {file = "httptools-0.1.1-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:fea04e126014169384dee76a153d4573d90d0cbd1d12185da089f73c78390437"}, 583 | {file = "httptools-0.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:3592e854424ec94bd17dc3e0c96a64e459ec4147e6d53c0a42d0ebcef9cb9c5d"}, 584 | {file = "httptools-0.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:0a4b1b2012b28e68306575ad14ad5e9120b34fccd02a81eb08838d7e3bbb48be"}, 585 | {file = "httptools-0.1.1.tar.gz", hash = "sha256:41b573cf33f64a8f8f3400d0a7faf48e1888582b6f6e02b82b9bd4f0bf7497ce"}, 586 | ] 587 | importlib-metadata = [ 588 | {file = "importlib_metadata-1.6.0-py2.py3-none-any.whl", hash = "sha256:2a688cbaa90e0cc587f1df48bdc97a6eadccdcd9c35fb3f976a09e3b5016d90f"}, 589 | {file = "importlib_metadata-1.6.0.tar.gz", hash = "sha256:34513a8a0c4962bc66d35b359558fd8a5e10cd472d37aec5f66858addef32c1e"}, 590 | ] 591 | mccabe = [ 592 | {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, 593 | {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, 594 | ] 595 | more-itertools = [ 596 | {file = "more-itertools-5.0.0.tar.gz", hash = "sha256:38a936c0a6d98a38bcc2d03fdaaedaba9f412879461dd2ceff8d37564d6522e4"}, 597 | {file = "more_itertools-5.0.0-py2-none-any.whl", hash = "sha256:c0a5785b1109a6bd7fac76d6837fd1feca158e54e521ccd2ae8bfe393cc9d4fc"}, 598 | {file = "more_itertools-5.0.0-py3-none-any.whl", hash = "sha256:fe7a7cae1ccb57d33952113ff4fa1bc5f879963600ed74918f1236e212ee50b9"}, 599 | ] 600 | orjson = [ 601 | {file = "orjson-2.6.5-cp36-cp36m-macosx_10_7_x86_64.whl", hash = "sha256:2b73518e036fcaabc03f88c951350d971493346f55cdc7368c10a13ff62a4f6f"}, 602 | {file = "orjson-2.6.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2f2b6a425b43174ea4a34dcee67e6c07f6df88baaf7098d1f41bf3e9eb996b00"}, 603 | {file = "orjson-2.6.5-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:2a2e5f0dca7203f8779c20c3c0c5246bbeb62d48a72fa81d30fdae6508acb48f"}, 604 | {file = "orjson-2.6.5-cp36-none-win_amd64.whl", hash = "sha256:1393d45a08799f5058aa92e480f8da42e06a288af41bfc58fb48b37a66d711d5"}, 605 | {file = "orjson-2.6.5-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:dae4c6d25f09069127deb3866c8f22f9b25530df7ac93ae57068b9c10557d106"}, 606 | {file = "orjson-2.6.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:b424eab367173bf9d56ef5242371dc1258bf573dcb4517291ec3b1e4e8020abc"}, 607 | {file = "orjson-2.6.5-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b10bda292e91df63c2ced92c0bdd4d74615acaf58b1f3742a19a82e84a1cb4ee"}, 608 | {file = "orjson-2.6.5-cp37-none-win_amd64.whl", hash = "sha256:211d03974a2141e1a52fc1c284ffbbf3c37e9d5c6dd9303aa0817158f800092c"}, 609 | {file = "orjson-2.6.5-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:411d3823f6b9cbb43a43942f0bc263720ad7c94d0c68d258cfbf76a0f3c0ce0d"}, 610 | {file = "orjson-2.6.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:dd9a62914fabe387cc3c8ff50c9ffd6a7009b422cea270c1527d98b87034ed01"}, 611 | {file = "orjson-2.6.5-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:a889288e111dbb36c740911232ccee97c86f25c70e7a666daca94c5b1f70d7f7"}, 612 | {file = "orjson-2.6.5-cp38-none-win_amd64.whl", hash = "sha256:c7d64e3452396af7810efe9fcb0a33c269a4b20e569e51ec9d1522ab4b6aa97b"}, 613 | {file = "orjson-2.6.5-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b15831f847ecae767aed19e0365aefb5315a7834410ab6c59e046f0d199e1593"}, 614 | {file = "orjson-2.6.5-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:9f817e770cf4cf919cba6950a47f1b19e3c201dc02a2176821c9c63eff41ad86"}, 615 | {file = "orjson-2.6.5.tar.gz", hash = "sha256:89c853658e3dab6e553205159c809f84fd8a69886fe0ef7e4e5eeac407254926"}, 616 | ] 617 | packaging = [ 618 | {file = "packaging-20.3-py2.py3-none-any.whl", hash = "sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752"}, 619 | {file = "packaging-20.3.tar.gz", hash = "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3"}, 620 | ] 621 | pathspec = [ 622 | {file = "pathspec-0.8.0-py2.py3-none-any.whl", hash = "sha256:7d91249d21749788d07a2d0f94147accd8f845507400749ea19c1ec9054a12b0"}, 623 | {file = "pathspec-0.8.0.tar.gz", hash = "sha256:da45173eb3a6f2a5a487efba21f050af2b41948be6ab52b6a1e3ff22bb8b7061"}, 624 | ] 625 | pluggy = [ 626 | {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, 627 | {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, 628 | ] 629 | py = [ 630 | {file = "py-1.8.1-py2.py3-none-any.whl", hash = "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0"}, 631 | {file = "py-1.8.1.tar.gz", hash = "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa"}, 632 | ] 633 | pycodestyle = [ 634 | {file = "pycodestyle-2.5.0-py2.py3-none-any.whl", hash = "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56"}, 635 | {file = "pycodestyle-2.5.0.tar.gz", hash = "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c"}, 636 | ] 637 | pyflakes = [ 638 | {file = "pyflakes-2.1.1-py2.py3-none-any.whl", hash = "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0"}, 639 | {file = "pyflakes-2.1.1.tar.gz", hash = "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2"}, 640 | ] 641 | pyparsing = [ 642 | {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, 643 | {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, 644 | ] 645 | pytest = [ 646 | {file = "pytest-4.6.9-py2.py3-none-any.whl", hash = "sha256:c77a5f30a90e0ce24db9eaa14ddfd38d4afb5ea159309bdd2dae55b931bc9324"}, 647 | {file = "pytest-4.6.9.tar.gz", hash = "sha256:19e8f75eac01dd3f211edd465b39efbcbdc8fc5f7866d7dd49fedb30d8adf339"}, 648 | ] 649 | python-box = [ 650 | {file = "python-box-4.2.2.tar.gz", hash = "sha256:5168fcd5572ec1e97754a636a9a93abef5d7f300cd5f1906927feb19839e7068"}, 651 | {file = "python_box-4.2.2-py3-none-any.whl", hash = "sha256:b47cac911e9d8f2ba6551fdb29d3e70a394b67691758baa114d4fcd9c0f1b1f8"}, 652 | ] 653 | pytz = [ 654 | {file = "pytz-2019.3-py2.py3-none-any.whl", hash = "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d"}, 655 | {file = "pytz-2019.3.tar.gz", hash = "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"}, 656 | ] 657 | redis = [ 658 | {file = "redis-3.4.1-py2.py3-none-any.whl", hash = "sha256:b205cffd05ebfd0a468db74f0eedbff8df1a7bfc47521516ade4692991bb0833"}, 659 | {file = "redis-3.4.1.tar.gz", hash = "sha256:0dcfb335921b88a850d461dc255ff4708294943322bd55de6cfd68972490ca1f"}, 660 | ] 661 | regex = [ 662 | {file = "regex-2020.4.4-cp27-cp27m-win32.whl", hash = "sha256:90742c6ff121a9c5b261b9b215cb476eea97df98ea82037ec8ac95d1be7a034f"}, 663 | {file = "regex-2020.4.4-cp27-cp27m-win_amd64.whl", hash = "sha256:24f4f4062eb16c5bbfff6a22312e8eab92c2c99c51a02e39b4eae54ce8255cd1"}, 664 | {file = "regex-2020.4.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:08119f707f0ebf2da60d2f24c2f39ca616277bb67ef6c92b72cbf90cbe3a556b"}, 665 | {file = "regex-2020.4.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:c9423a150d3a4fc0f3f2aae897a59919acd293f4cb397429b120a5fcd96ea3db"}, 666 | {file = "regex-2020.4.4-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:c087bff162158536387c53647411db09b6ee3f9603c334c90943e97b1052a156"}, 667 | {file = "regex-2020.4.4-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:1cbe0fa0b7f673400eb29e9ef41d4f53638f65f9a2143854de6b1ce2899185c3"}, 668 | {file = "regex-2020.4.4-cp36-cp36m-win32.whl", hash = "sha256:0ce9537396d8f556bcfc317c65b6a0705320701e5ce511f05fc04421ba05b8a8"}, 669 | {file = "regex-2020.4.4-cp36-cp36m-win_amd64.whl", hash = "sha256:7e1037073b1b7053ee74c3c6c0ada80f3501ec29d5f46e42669378eae6d4405a"}, 670 | {file = "regex-2020.4.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:4385f12aa289d79419fede43f979e372f527892ac44a541b5446617e4406c468"}, 671 | {file = "regex-2020.4.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:a58dd45cb865be0ce1d5ecc4cfc85cd8c6867bea66733623e54bd95131f473b6"}, 672 | {file = "regex-2020.4.4-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:ccccdd84912875e34c5ad2d06e1989d890d43af6c2242c6fcfa51556997af6cd"}, 673 | {file = "regex-2020.4.4-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:ea4adf02d23b437684cd388d557bf76e3afa72f7fed5bbc013482cc00c816948"}, 674 | {file = "regex-2020.4.4-cp37-cp37m-win32.whl", hash = "sha256:2294f8b70e058a2553cd009df003a20802ef75b3c629506be20687df0908177e"}, 675 | {file = "regex-2020.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:e91ba11da11cf770f389e47c3f5c30473e6d85e06d7fd9dcba0017d2867aab4a"}, 676 | {file = "regex-2020.4.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5635cd1ed0a12b4c42cce18a8d2fb53ff13ff537f09de5fd791e97de27b6400e"}, 677 | {file = "regex-2020.4.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:23069d9c07e115537f37270d1d5faea3e0bdded8279081c4d4d607a2ad393683"}, 678 | {file = "regex-2020.4.4-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:c162a21e0da33eb3d31a3ac17a51db5e634fc347f650d271f0305d96601dc15b"}, 679 | {file = "regex-2020.4.4-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:fb95debbd1a824b2c4376932f2216cc186912e389bdb0e27147778cf6acb3f89"}, 680 | {file = "regex-2020.4.4-cp38-cp38-win32.whl", hash = "sha256:2a3bf8b48f8e37c3a40bb3f854bf0121c194e69a650b209628d951190b862de3"}, 681 | {file = "regex-2020.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:5bfed051dbff32fd8945eccca70f5e22b55e4148d2a8a45141a3b053d6455ae3"}, 682 | {file = "regex-2020.4.4.tar.gz", hash = "sha256:295badf61a51add2d428a46b8580309c520d8b26e769868b922750cf3ce67142"}, 683 | ] 684 | "ruamel.yaml" = [ 685 | {file = "ruamel.yaml-0.16.10-py2.py3-none-any.whl", hash = "sha256:0962fd7999e064c4865f96fb1e23079075f4a2a14849bcdc5cdba53a24f9759b"}, 686 | {file = "ruamel.yaml-0.16.10.tar.gz", hash = "sha256:099c644a778bf72ffa00524f78dd0b6476bca94a1da344130f4bf3381ce5b954"}, 687 | ] 688 | "ruamel.yaml.clib" = [ 689 | {file = "ruamel.yaml.clib-0.2.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:9c6d040d0396c28d3eaaa6cb20152cb3b2f15adf35a0304f4f40a3cf9f1d2448"}, 690 | {file = "ruamel.yaml.clib-0.2.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:4d55386129291b96483edcb93b381470f7cd69f97585829b048a3d758d31210a"}, 691 | {file = "ruamel.yaml.clib-0.2.0-cp27-cp27m-win32.whl", hash = "sha256:8073c8b92b06b572e4057b583c3d01674ceaf32167801fe545a087d7a1e8bf52"}, 692 | {file = "ruamel.yaml.clib-0.2.0-cp27-cp27m-win_amd64.whl", hash = "sha256:615b0396a7fad02d1f9a0dcf9f01202bf9caefee6265198f252c865f4227fcc6"}, 693 | {file = "ruamel.yaml.clib-0.2.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:a0ff786d2a7dbe55f9544b3f6ebbcc495d7e730df92a08434604f6f470b899c5"}, 694 | {file = "ruamel.yaml.clib-0.2.0-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:ea4362548ee0cbc266949d8a441238d9ad3600ca9910c3fe4e82ee3a50706973"}, 695 | {file = "ruamel.yaml.clib-0.2.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:77556a7aa190be9a2bd83b7ee075d3df5f3c5016d395613671487e79b082d784"}, 696 | {file = "ruamel.yaml.clib-0.2.0-cp35-cp35m-win32.whl", hash = "sha256:392b7c371312abf27fb549ec2d5e0092f7ef6e6c9f767bfb13e83cb903aca0fd"}, 697 | {file = "ruamel.yaml.clib-0.2.0-cp35-cp35m-win_amd64.whl", hash = "sha256:ed5b3698a2bb241b7f5cbbe277eaa7fe48b07a58784fba4f75224fd066d253ad"}, 698 | {file = "ruamel.yaml.clib-0.2.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:7aee724e1ff424757b5bd8f6c5bbdb033a570b2b4683b17ace4dbe61a99a657b"}, 699 | {file = "ruamel.yaml.clib-0.2.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d0d3ac228c9bbab08134b4004d748cf9f8743504875b3603b3afbb97e3472947"}, 700 | {file = "ruamel.yaml.clib-0.2.0-cp36-cp36m-win32.whl", hash = "sha256:f9dcc1ae73f36e8059589b601e8e4776b9976effd76c21ad6a855a74318efd6e"}, 701 | {file = "ruamel.yaml.clib-0.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:1e77424825caba5553bbade750cec2277ef130647d685c2b38f68bc03453bac6"}, 702 | {file = "ruamel.yaml.clib-0.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d10e9dd744cf85c219bf747c75194b624cc7a94f0c80ead624b06bfa9f61d3bc"}, 703 | {file = "ruamel.yaml.clib-0.2.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:550168c02d8de52ee58c3d8a8193d5a8a9491a5e7b2462d27ac5bf63717574c9"}, 704 | {file = "ruamel.yaml.clib-0.2.0-cp37-cp37m-win32.whl", hash = "sha256:57933a6986a3036257ad7bf283529e7c19c2810ff24c86f4a0cfeb49d2099919"}, 705 | {file = "ruamel.yaml.clib-0.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:b1b7fcee6aedcdc7e62c3a73f238b3d080c7ba6650cd808bce8d7761ec484070"}, 706 | {file = "ruamel.yaml.clib-0.2.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:be018933c2f4ee7de55e7bd7d0d801b3dfb09d21dad0cce8a97995fd3e44be30"}, 707 | {file = "ruamel.yaml.clib-0.2.0.tar.gz", hash = "sha256:b66832ea8077d9b3f6e311c4a53d06273db5dc2db6e8a908550f3c14d67e718c"}, 708 | ] 709 | six = [ 710 | {file = "six-1.14.0-py2.py3-none-any.whl", hash = "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"}, 711 | {file = "six-1.14.0.tar.gz", hash = "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a"}, 712 | ] 713 | sqlparse = [ 714 | {file = "sqlparse-0.3.1-py2.py3-none-any.whl", hash = "sha256:022fb9c87b524d1f7862b3037e541f68597a730a8843245c349fc93e1643dc4e"}, 715 | {file = "sqlparse-0.3.1.tar.gz", hash = "sha256:e162203737712307dfe78860cc56c8da8a852ab2ee33750e33aeadf38d12c548"}, 716 | ] 717 | toml = [ 718 | {file = "toml-0.10.0-py2.7.egg", hash = "sha256:f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"}, 719 | {file = "toml-0.10.0-py2.py3-none-any.whl", hash = "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"}, 720 | {file = "toml-0.10.0.tar.gz", hash = "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c"}, 721 | ] 722 | typed-ast = [ 723 | {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3"}, 724 | {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb"}, 725 | {file = "typed_ast-1.4.1-cp35-cp35m-win32.whl", hash = "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919"}, 726 | {file = "typed_ast-1.4.1-cp35-cp35m-win_amd64.whl", hash = "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01"}, 727 | {file = "typed_ast-1.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75"}, 728 | {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652"}, 729 | {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"}, 730 | {file = "typed_ast-1.4.1-cp36-cp36m-win32.whl", hash = "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1"}, 731 | {file = "typed_ast-1.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa"}, 732 | {file = "typed_ast-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614"}, 733 | {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41"}, 734 | {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b"}, 735 | {file = "typed_ast-1.4.1-cp37-cp37m-win32.whl", hash = "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe"}, 736 | {file = "typed_ast-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355"}, 737 | {file = "typed_ast-1.4.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6"}, 738 | {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907"}, 739 | {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d"}, 740 | {file = "typed_ast-1.4.1-cp38-cp38-win32.whl", hash = "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c"}, 741 | {file = "typed_ast-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4"}, 742 | {file = "typed_ast-1.4.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34"}, 743 | {file = "typed_ast-1.4.1.tar.gz", hash = "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b"}, 744 | ] 745 | uvicorn = [ 746 | {file = "uvicorn-0.11.3-py3-none-any.whl", hash = "sha256:0f58170165c4495f563d8224b2f415a0829af0412baa034d6f777904613087fd"}, 747 | {file = "uvicorn-0.11.3.tar.gz", hash = "sha256:6fdaf8e53bf1b2ddf0fe9ed06079b5348d7d1d87b3365fe2549e6de0d49e631c"}, 748 | ] 749 | uvloop = [ 750 | {file = "uvloop-0.14.0-cp35-cp35m-macosx_10_11_x86_64.whl", hash = "sha256:08b109f0213af392150e2fe6f81d33261bb5ce968a288eb698aad4f46eb711bd"}, 751 | {file = "uvloop-0.14.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:4544dcf77d74f3a84f03dd6278174575c44c67d7165d4c42c71db3fdc3860726"}, 752 | {file = "uvloop-0.14.0-cp36-cp36m-macosx_10_11_x86_64.whl", hash = "sha256:b4f591aa4b3fa7f32fb51e2ee9fea1b495eb75b0b3c8d0ca52514ad675ae63f7"}, 753 | {file = "uvloop-0.14.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:f07909cd9fc08c52d294b1570bba92186181ca01fe3dc9ffba68955273dd7362"}, 754 | {file = "uvloop-0.14.0-cp37-cp37m-macosx_10_11_x86_64.whl", hash = "sha256:afd5513c0ae414ec71d24f6f123614a80f3d27ca655a4fcf6cabe50994cc1891"}, 755 | {file = "uvloop-0.14.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:e7514d7a48c063226b7d06617cbb12a14278d4323a065a8d46a7962686ce2e95"}, 756 | {file = "uvloop-0.14.0-cp38-cp38-macosx_10_11_x86_64.whl", hash = "sha256:bcac356d62edd330080aed082e78d4b580ff260a677508718f88016333e2c9c5"}, 757 | {file = "uvloop-0.14.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4315d2ec3ca393dd5bc0b0089d23101276778c304d42faff5dc4579cb6caef09"}, 758 | {file = "uvloop-0.14.0.tar.gz", hash = "sha256:123ac9c0c7dd71464f58f1b4ee0bbd81285d96cdda8bc3519281b8973e3a461e"}, 759 | ] 760 | wcwidth = [ 761 | {file = "wcwidth-0.1.9-py2.py3-none-any.whl", hash = "sha256:cafe2186b3c009a04067022ce1dcd79cb38d8d65ee4f4791b8888d6599d1bbe1"}, 762 | {file = "wcwidth-0.1.9.tar.gz", hash = "sha256:ee73862862a156bf77ff92b09034fc4825dd3af9cf81bc5b360668d425f3c5f1"}, 763 | ] 764 | websockets = [ 765 | {file = "websockets-8.0.2-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:e906128532a14b9d264a43eb48f9b3080d53a9bda819ab45bf56b8039dc606ac"}, 766 | {file = "websockets-8.0.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:83e63aa73331b9ca21af61df8f115fb5fbcba3f281bee650a4ad16a40cd1ef15"}, 767 | {file = "websockets-8.0.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:e9102043a81cdc8b7c8032ff4bce39f6229e4ac39cb2010946c912eeb84e2cb6"}, 768 | {file = "websockets-8.0.2-cp36-cp36m-win32.whl", hash = "sha256:8d7a20a2f97f1e98c765651d9fb9437201a9ccc2c70e94b0270f1c5ef29667a3"}, 769 | {file = "websockets-8.0.2-cp36-cp36m-win_amd64.whl", hash = "sha256:c82e286555f839846ef4f0fdd6910769a577952e1e26aa8ee7a6f45f040e3c2b"}, 770 | {file = "websockets-8.0.2-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:73ce69217e4655783ec72ce11c151053fcbd5b837cc39de7999e19605182e28a"}, 771 | {file = "websockets-8.0.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:8c77f7d182a6ea2a9d09c2612059f3ad859a90243e899617137ee3f6b7f2b584"}, 772 | {file = "websockets-8.0.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:a7affaeffbc5d55681934c16bb6b8fc82bb75b175e7fd4dcca798c938bde8dda"}, 773 | {file = "websockets-8.0.2-cp37-cp37m-win32.whl", hash = "sha256:f5cb2683367e32da6a256b60929a3af9c29c212b5091cf5bace9358d03011bf5"}, 774 | {file = "websockets-8.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:049e694abe33f8a1d99969fee7bfc0ae6761f7fd5f297c58ea933b27dd6805f2"}, 775 | {file = "websockets-8.0.2.tar.gz", hash = "sha256:882a7266fa867a2ebb2c0baaa0f9159cabf131cf18c1b4270d79ad42f9208dc5"}, 776 | ] 777 | zipp = [ 778 | {file = "zipp-1.2.0-py2.py3-none-any.whl", hash = "sha256:e0d9e63797e483a30d27e09fffd308c59a700d365ec34e93cc100844168bf921"}, 779 | {file = "zipp-1.2.0.tar.gz", hash = "sha256:c70410551488251b0fee67b460fb9a536af8d6f9f008ad10ac51f615b6a521b1"}, 780 | ] 781 | --------------------------------------------------------------------------------