├── message.json ├── pyproject.toml ├── lambda-mailer-policy-dev.json ├── lambda-mailer-policy-prod.json ├── LICENSE ├── zappa_settings.json ├── .gitignore ├── README.md ├── api.py └── poetry.lock /message.json: -------------------------------------------------------------------------------- 1 | { 2 | "email": "test@test.com", 3 | "budget": "75-100k", 4 | "name": "My name", 5 | "message": "This is an email with Unicode ❤ ☀ ☆ ☂ ☻ ♞ ☯ ☭ ☢" 6 | } 7 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "lambda-mailer" 3 | version = "0.1.0" 4 | description = "API to send emails using AWS lambda." 5 | license = "MIT" 6 | authors = ["Alan Descoins "] 7 | 8 | [tool.poetry.dependencies] 9 | python = "^3.8" 10 | boto3 = "^1.17.101" 11 | zappa = "^0.53.0" 12 | Flask = "1" 13 | 14 | [tool.poetry.dev-dependencies] 15 | ipdb = "^0.13.9" 16 | black = "^21.6b0" 17 | 18 | [build-system] 19 | requires = ["poetry-core>=1.0.0"] 20 | build-backend = "poetry.core.masonry.api" 21 | -------------------------------------------------------------------------------- /lambda-mailer-policy-dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Action": [ 7 | "logs:*" 8 | ], 9 | "Resource": "arn:aws:logs:*:*:*" 10 | }, 11 | { 12 | "Effect": "Allow", 13 | "Action": [ 14 | "lambda:InvokeFunction" 15 | ], 16 | "Resource": [ 17 | "*" 18 | ] 19 | }, 20 | { 21 | "Action": [ 22 | "ses:SendEmail" 23 | ], 24 | "Resource": "*", 25 | "Effect": "Allow" 26 | } 27 | ] 28 | } -------------------------------------------------------------------------------- /lambda-mailer-policy-prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Effect": "Allow", 6 | "Action": [ 7 | "logs:*" 8 | ], 9 | "Resource": "arn:aws:logs:*:*:*" 10 | }, 11 | { 12 | "Effect": "Allow", 13 | "Action": [ 14 | "lambda:InvokeFunction" 15 | ], 16 | "Resource": [ 17 | "*" 18 | ] 19 | }, 20 | { 21 | "Action": [ 22 | "ses:SendEmail" 23 | ], 24 | "Resource": "*", 25 | "Effect": "Allow" 26 | } 27 | ] 28 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Tryolabs. https://tryolabs.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /zappa_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "dev": { 3 | "app_function": "api.app", 4 | "aws_region": "us-west-2", 5 | "s3_bucket": "zappa-emailsender-dev-lambda", 6 | "attach_policy": "lambda-mailer-policy-dev.json", 7 | "method_header_types": [ 8 | "Content-Type", 9 | "Access-Control-Allow-Origin", 10 | "Access-Control-Allow-Headers", 11 | "Access-Control-Allow-Methods" 12 | ], 13 | "environment_variables": { 14 | "FROM_EMAIL": "hello@tryolabs.com", 15 | "DESTINATION_EMAIL": "alan@tryolabs.com" 16 | } 17 | }, 18 | "prod": { 19 | "app_function": "api.app", 20 | "aws_region": "us-west-2", 21 | "s3_bucket": "zappa-emailsender-prod-lambda", 22 | "attach_policy": "lambda-mailer-policy-prod.json", 23 | "method_header_types": [ 24 | "Content-Type", 25 | "Access-Control-Allow-Origin", 26 | "Access-Control-Allow-Headers", 27 | "Access-Control-Allow-Methods" 28 | ], 29 | "environment_variables": { 30 | "FROM_EMAIL": "hello@tryolabs.com", 31 | "DESTINATION_EMAIL": "hello@tryolabs.com" 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /.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 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | local_settings.py 55 | 56 | # Flask stuff: 57 | instance/ 58 | .webassets-cache 59 | 60 | # Scrapy stuff: 61 | .scrapy 62 | 63 | # Sphinx documentation 64 | docs/_build/ 65 | 66 | # PyBuilder 67 | target/ 68 | 69 | # Jupyter Notebook 70 | .ipynb_checkpoints 71 | 72 | # pyenv 73 | .python-version 74 | 75 | # celery beat schedule file 76 | celerybeat-schedule 77 | 78 | # dotenv 79 | .env 80 | 81 | # virtualenv 82 | .venv/ 83 | venv/ 84 | ENV/ 85 | 86 | # Spyder project settings 87 | .spyderproject 88 | 89 | # Rope project settings 90 | .ropeproject -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tryolabs Lambda mailer 2 | 3 | Uses [Zappa](https://github.com/Miserlou/Zappa) to deploy a serverless endpoint that receives a JSON and sends an email to a destination address. Made to support contact forms in our static website. 4 | 5 | ## Setup 6 | 7 | _Before you begin, make sure you have a valid AWS account and your [AWS credentials file](https://blogs.aws.amazon.com/security/post/Tx3D6U6WSFGOK2H/A-New-and-Standardized-Way-to-Manage-Credentials-in-the-AWS-SDKs) is properly installed._ 8 | 9 | Make sure you are in a virtualenv, and run: 10 | 11 | ``` 12 | $ pip install -r requirements.txt 13 | $ zappa deploy dev 14 | ``` 15 | 16 | To redeploy: 17 | 18 | $ zappa update dev 19 | 20 | To deploy the production version: 21 | 22 | $ zappa deploy prod 23 | 24 | 25 | ### Environment variables 26 | In the `zappa_settings.json` file, you can edit the environment variables for `dev` and `prod`: 27 | 28 | ```javascript 29 | { 30 | "dev": { 31 | ... 32 | "environment_variables": { 33 | "FROM_EMAIL": "alan@tryolabs.com", 34 | "DESTINATION_EMAIL": "alan@tryolabs.com" 35 | } 36 | }, 37 | ... 38 | } 39 | ``` 40 | 41 | ## Testing 42 | 43 | With [httpie](https://httpie.org/), invoke the endpoint0 with the `message.json` test file as payload: 44 | 45 | $ http < message.json 46 | 47 | 48 | ## License 49 | 50 | Copyright (c) 2016 [Tryolabs](https://tryolabs.com). 51 | 52 | Released under the MIT License (See LICENSE). 53 | -------------------------------------------------------------------------------- /api.py: -------------------------------------------------------------------------------- 1 | import boto3 2 | import os 3 | import re 4 | 5 | from botocore.exceptions import ClientError 6 | from flask import Flask, request, jsonify 7 | 8 | 9 | FROM_EMAIL = os.environ["FROM_EMAIL"] 10 | DESTINATION_EMAIL = os.environ["DESTINATION_EMAIL"] 11 | 12 | 13 | app = Flask(__name__) 14 | app.debug = False 15 | 16 | ses = boto3.client("ses") 17 | 18 | 19 | REQUIRED_FIELDS = ["name", "email", "message"] 20 | EMAIL_REGEXP = r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)" 21 | 22 | 23 | @app.after_request 24 | def after_request(response): 25 | response.headers.add("Access-Control-Allow-Origin", "*") 26 | response.headers.add("Access-Control-Allow-Headers", "Content-Type,Authorization") 27 | response.headers.add("Access-Control-Allow-Methods", "OPTIONS,POST") 28 | return response 29 | 30 | 31 | class InvalidUsage(Exception): 32 | pass 33 | 34 | 35 | @app.errorhandler(400) 36 | def handle_bad_request(error): 37 | return jsonify({"status": "error", "error": str(error)}), 400 38 | 39 | 40 | @app.errorhandler(InvalidUsage) 41 | def handle_invalid_usage(error): 42 | response = jsonify({"status": "error", "error": str(error)}) 43 | response.status_code = 400 44 | return response 45 | 46 | 47 | @app.errorhandler(ClientError) 48 | def handle_client_error(error): 49 | response = jsonify({"status": "error", "error": str(error)}) 50 | response.status_code = 500 51 | return response 52 | 53 | 54 | @app.route("/", methods=["POST"]) 55 | def index(): 56 | data = request.get_json(force=True) 57 | if not data: 58 | raise InvalidUsage("Request body cannot be empty.") 59 | 60 | for field in REQUIRED_FIELDS: 61 | value = data.get(field, None) 62 | if value is None: 63 | raise InvalidUsage('Request body needs a "{}" field.'.format(field)) 64 | if not value.strip(): 65 | raise InvalidUsage( 66 | 'The "{}" field cannot be empty or spaces.'.format(field) 67 | ) 68 | 69 | if not re.match(EMAIL_REGEXP, data["email"]): 70 | raise InvalidUsage('The "email" field needs to be a valid email address.') 71 | 72 | if "_important" in data: 73 | # Our code should have removed this field before POSTing. 74 | # This is probably triggered by a bot. 75 | return (jsonify({"status": "ok"}), 200) 76 | 77 | # Create a string with those fields that we do not recognize 78 | other_fields = set(data.keys()) - set(REQUIRED_FIELDS) 79 | str_other_fields = "\n".join( 80 | "{}: {}
".format(field, data[field]) 81 | for field in sorted(other_fields) 82 | ) 83 | 84 | subject = "Tryolabs contact form message from {} ({})".format( 85 | data["name"], data["email"] 86 | ) 87 | message = """name: {}
88 | email: {}
89 | {} 90 |

91 | {} 92 |

93 | """.format( 94 | data["name"], 95 | data["email"], 96 | str_other_fields, 97 | data["message"].replace("\n", "
"), 98 | ) 99 | 100 | response = ses.send_email( 101 | Source=FROM_EMAIL, 102 | Destination={ 103 | "ToAddresses": [DESTINATION_EMAIL], 104 | }, 105 | Message={ 106 | "Subject": {"Data": subject, "Charset": "utf-8"}, 107 | "Body": {"Html": {"Data": message, "Charset": "utf-8"}}, 108 | }, 109 | ReplyToAddresses=[data["email"]], 110 | ReturnPath=FROM_EMAIL, 111 | ) 112 | 113 | if response["ResponseMetadata"]["HTTPStatusCode"] != 200: 114 | return ( 115 | jsonify( 116 | { 117 | "status": "error", 118 | "error": "SES responded with {}".format( 119 | response["ResponseMetadata"]["HTTPStatusCode"] 120 | ), 121 | } 122 | ), 123 | 500, 124 | ) 125 | 126 | return jsonify({"status": "ok"}), 200 127 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "appdirs" 3 | version = "1.4.4" 4 | description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." 5 | category = "dev" 6 | optional = false 7 | python-versions = "*" 8 | 9 | [[package]] 10 | name = "appnope" 11 | version = "0.1.2" 12 | description = "Disable App Nap on macOS >= 10.9" 13 | category = "dev" 14 | optional = false 15 | python-versions = "*" 16 | 17 | [[package]] 18 | name = "argcomplete" 19 | version = "1.12.3" 20 | description = "Bash tab completion for argparse" 21 | category = "main" 22 | optional = false 23 | python-versions = "*" 24 | 25 | [package.extras] 26 | test = ["coverage", "flake8", "pexpect", "wheel"] 27 | 28 | [[package]] 29 | name = "backcall" 30 | version = "0.2.0" 31 | description = "Specifications for callback functions passed in to an API" 32 | category = "dev" 33 | optional = false 34 | python-versions = "*" 35 | 36 | [[package]] 37 | name = "black" 38 | version = "21.6b0" 39 | description = "The uncompromising code formatter." 40 | category = "dev" 41 | optional = false 42 | python-versions = ">=3.6.2" 43 | 44 | [package.dependencies] 45 | appdirs = "*" 46 | click = ">=7.1.2" 47 | mypy-extensions = ">=0.4.3" 48 | pathspec = ">=0.8.1,<1" 49 | regex = ">=2020.1.8" 50 | toml = ">=0.10.1" 51 | 52 | [package.extras] 53 | colorama = ["colorama (>=0.4.3)"] 54 | d = ["aiohttp (>=3.6.0)", "aiohttp-cors (>=0.4.0)"] 55 | python2 = ["typed-ast (>=1.4.2)"] 56 | uvloop = ["uvloop (>=0.15.2)"] 57 | 58 | [[package]] 59 | name = "boto3" 60 | version = "1.17.101" 61 | description = "The AWS SDK for Python" 62 | category = "main" 63 | optional = false 64 | python-versions = ">= 2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" 65 | 66 | [package.dependencies] 67 | botocore = ">=1.20.101,<1.21.0" 68 | jmespath = ">=0.7.1,<1.0.0" 69 | s3transfer = ">=0.4.0,<0.5.0" 70 | 71 | [[package]] 72 | name = "botocore" 73 | version = "1.20.101" 74 | description = "Low-level, data-driven core of boto 3." 75 | category = "main" 76 | optional = false 77 | python-versions = ">= 2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" 78 | 79 | [package.dependencies] 80 | jmespath = ">=0.7.1,<1.0.0" 81 | python-dateutil = ">=2.1,<3.0.0" 82 | urllib3 = ">=1.25.4,<1.27" 83 | 84 | [package.extras] 85 | crt = ["awscrt (==0.11.24)"] 86 | 87 | [[package]] 88 | name = "certifi" 89 | version = "2021.5.30" 90 | description = "Python package for providing Mozilla's CA Bundle." 91 | category = "main" 92 | optional = false 93 | python-versions = "*" 94 | 95 | [[package]] 96 | name = "cfn-flip" 97 | version = "1.2.3" 98 | description = "Convert AWS CloudFormation templates between JSON and YAML formats" 99 | category = "main" 100 | optional = false 101 | python-versions = "*" 102 | 103 | [package.dependencies] 104 | Click = "*" 105 | PyYAML = ">=4.1" 106 | six = "*" 107 | 108 | [[package]] 109 | name = "chardet" 110 | version = "4.0.0" 111 | description = "Universal encoding detector for Python 2 and 3" 112 | category = "main" 113 | optional = false 114 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 115 | 116 | [[package]] 117 | name = "click" 118 | version = "8.0.1" 119 | description = "Composable command line interface toolkit" 120 | category = "main" 121 | optional = false 122 | python-versions = ">=3.6" 123 | 124 | [package.dependencies] 125 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 126 | 127 | [[package]] 128 | name = "colorama" 129 | version = "0.4.4" 130 | description = "Cross-platform colored terminal text." 131 | category = "main" 132 | optional = false 133 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 134 | 135 | [[package]] 136 | name = "decorator" 137 | version = "5.0.9" 138 | description = "Decorators for Humans" 139 | category = "dev" 140 | optional = false 141 | python-versions = ">=3.5" 142 | 143 | [[package]] 144 | name = "durationpy" 145 | version = "0.5" 146 | description = "Module for converting between datetime.timedelta and Go's Duration strings." 147 | category = "main" 148 | optional = false 149 | python-versions = "*" 150 | 151 | [[package]] 152 | name = "flask" 153 | version = "1.0" 154 | description = "A simple framework for building complex web applications." 155 | category = "main" 156 | optional = false 157 | python-versions = "*" 158 | 159 | [package.dependencies] 160 | click = ">=5.1" 161 | itsdangerous = ">=0.24" 162 | Jinja2 = ">=2.10" 163 | Werkzeug = ">=0.14" 164 | 165 | [package.extras] 166 | dev = ["pytest (>=3)", "coverage", "tox", "sphinx", "pallets-sphinx-themes", "sphinxcontrib-log-cabinet"] 167 | docs = ["sphinx", "pallets-sphinx-themes", "sphinxcontrib-log-cabinet"] 168 | dotenv = ["python-dotenv"] 169 | 170 | [[package]] 171 | name = "future" 172 | version = "0.18.2" 173 | description = "Clean single-source support for Python 3 and 2" 174 | category = "main" 175 | optional = false 176 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 177 | 178 | [[package]] 179 | name = "hjson" 180 | version = "3.0.2" 181 | description = "Hjson, a user interface for JSON." 182 | category = "main" 183 | optional = false 184 | python-versions = "*" 185 | 186 | [[package]] 187 | name = "idna" 188 | version = "2.10" 189 | description = "Internationalized Domain Names in Applications (IDNA)" 190 | category = "main" 191 | optional = false 192 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 193 | 194 | [[package]] 195 | name = "ipdb" 196 | version = "0.13.9" 197 | description = "IPython-enabled pdb" 198 | category = "dev" 199 | optional = false 200 | python-versions = ">=2.7" 201 | 202 | [package.dependencies] 203 | decorator = {version = "*", markers = "python_version > \"3.6\""} 204 | ipython = {version = ">=7.17.0", markers = "python_version > \"3.6\""} 205 | toml = {version = ">=0.10.2", markers = "python_version > \"3.6\""} 206 | 207 | [[package]] 208 | name = "ipython" 209 | version = "7.25.0" 210 | description = "IPython: Productive Interactive Computing" 211 | category = "dev" 212 | optional = false 213 | python-versions = ">=3.7" 214 | 215 | [package.dependencies] 216 | appnope = {version = "*", markers = "sys_platform == \"darwin\""} 217 | backcall = "*" 218 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 219 | decorator = "*" 220 | jedi = ">=0.16" 221 | matplotlib-inline = "*" 222 | pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} 223 | pickleshare = "*" 224 | prompt-toolkit = ">=2.0.0,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.1.0" 225 | pygments = "*" 226 | traitlets = ">=4.2" 227 | 228 | [package.extras] 229 | all = ["Sphinx (>=1.3)", "ipykernel", "ipyparallel", "ipywidgets", "nbconvert", "nbformat", "nose (>=0.10.1)", "notebook", "numpy (>=1.17)", "pygments", "qtconsole", "requests", "testpath"] 230 | doc = ["Sphinx (>=1.3)"] 231 | kernel = ["ipykernel"] 232 | nbconvert = ["nbconvert"] 233 | nbformat = ["nbformat"] 234 | notebook = ["notebook", "ipywidgets"] 235 | parallel = ["ipyparallel"] 236 | qtconsole = ["qtconsole"] 237 | test = ["nose (>=0.10.1)", "requests", "testpath", "pygments", "nbformat", "ipykernel", "numpy (>=1.17)"] 238 | 239 | [[package]] 240 | name = "ipython-genutils" 241 | version = "0.2.0" 242 | description = "Vestigial utilities from IPython" 243 | category = "dev" 244 | optional = false 245 | python-versions = "*" 246 | 247 | [[package]] 248 | name = "itsdangerous" 249 | version = "2.0.1" 250 | description = "Safely pass data to untrusted environments and back." 251 | category = "main" 252 | optional = false 253 | python-versions = ">=3.6" 254 | 255 | [[package]] 256 | name = "jedi" 257 | version = "0.18.0" 258 | description = "An autocompletion tool for Python that can be used for text editors." 259 | category = "dev" 260 | optional = false 261 | python-versions = ">=3.6" 262 | 263 | [package.dependencies] 264 | parso = ">=0.8.0,<0.9.0" 265 | 266 | [package.extras] 267 | qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] 268 | testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<6.0.0)"] 269 | 270 | [[package]] 271 | name = "jinja2" 272 | version = "3.0.1" 273 | description = "A very fast and expressive template engine." 274 | category = "main" 275 | optional = false 276 | python-versions = ">=3.6" 277 | 278 | [package.dependencies] 279 | MarkupSafe = ">=2.0" 280 | 281 | [package.extras] 282 | i18n = ["Babel (>=2.7)"] 283 | 284 | [[package]] 285 | name = "jmespath" 286 | version = "0.10.0" 287 | description = "JSON Matching Expressions" 288 | category = "main" 289 | optional = false 290 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 291 | 292 | [[package]] 293 | name = "kappa" 294 | version = "0.6.0" 295 | description = "A CLI tool for AWS Lambda developers" 296 | category = "main" 297 | optional = false 298 | python-versions = "*" 299 | 300 | [package.dependencies] 301 | boto3 = ">=1.2.3" 302 | click = ">=5.1" 303 | placebo = ">=0.8.1" 304 | PyYAML = ">=3.11" 305 | 306 | [[package]] 307 | name = "markupsafe" 308 | version = "2.0.1" 309 | description = "Safely add untrusted strings to HTML/XML markup." 310 | category = "main" 311 | optional = false 312 | python-versions = ">=3.6" 313 | 314 | [[package]] 315 | name = "matplotlib-inline" 316 | version = "0.1.2" 317 | description = "Inline Matplotlib backend for Jupyter" 318 | category = "dev" 319 | optional = false 320 | python-versions = ">=3.5" 321 | 322 | [package.dependencies] 323 | traitlets = "*" 324 | 325 | [[package]] 326 | name = "mypy-extensions" 327 | version = "0.4.3" 328 | description = "Experimental type system extensions for programs checked with the mypy typechecker." 329 | category = "dev" 330 | optional = false 331 | python-versions = "*" 332 | 333 | [[package]] 334 | name = "parso" 335 | version = "0.8.2" 336 | description = "A Python Parser" 337 | category = "dev" 338 | optional = false 339 | python-versions = ">=3.6" 340 | 341 | [package.extras] 342 | qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] 343 | testing = ["docopt", "pytest (<6.0.0)"] 344 | 345 | [[package]] 346 | name = "pathspec" 347 | version = "0.8.1" 348 | description = "Utility library for gitignore style pattern matching of file paths." 349 | category = "dev" 350 | optional = false 351 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 352 | 353 | [[package]] 354 | name = "pep517" 355 | version = "0.10.0" 356 | description = "Wrappers to build Python packages using PEP 517 hooks" 357 | category = "main" 358 | optional = false 359 | python-versions = "*" 360 | 361 | [package.dependencies] 362 | toml = "*" 363 | 364 | [[package]] 365 | name = "pexpect" 366 | version = "4.8.0" 367 | description = "Pexpect allows easy control of interactive console applications." 368 | category = "dev" 369 | optional = false 370 | python-versions = "*" 371 | 372 | [package.dependencies] 373 | ptyprocess = ">=0.5" 374 | 375 | [[package]] 376 | name = "pickleshare" 377 | version = "0.7.5" 378 | description = "Tiny 'shelve'-like database with concurrency support" 379 | category = "dev" 380 | optional = false 381 | python-versions = "*" 382 | 383 | [[package]] 384 | name = "pip-tools" 385 | version = "6.2.0" 386 | description = "pip-tools keeps your pinned dependencies fresh." 387 | category = "main" 388 | optional = false 389 | python-versions = ">=3.6" 390 | 391 | [package.dependencies] 392 | click = ">=7" 393 | pep517 = "*" 394 | 395 | [package.extras] 396 | coverage = ["pytest-cov"] 397 | testing = ["pytest", "pytest-rerunfailures", "pytest-xdist"] 398 | 399 | [[package]] 400 | name = "placebo" 401 | version = "0.9.0" 402 | description = "Make boto3 calls that look real but have no effect" 403 | category = "main" 404 | optional = false 405 | python-versions = "*" 406 | 407 | [[package]] 408 | name = "prompt-toolkit" 409 | version = "3.0.19" 410 | description = "Library for building powerful interactive command lines in Python" 411 | category = "dev" 412 | optional = false 413 | python-versions = ">=3.6.1" 414 | 415 | [package.dependencies] 416 | wcwidth = "*" 417 | 418 | [[package]] 419 | name = "ptyprocess" 420 | version = "0.7.0" 421 | description = "Run a subprocess in a pseudo terminal" 422 | category = "dev" 423 | optional = false 424 | python-versions = "*" 425 | 426 | [[package]] 427 | name = "pygments" 428 | version = "2.9.0" 429 | description = "Pygments is a syntax highlighting package written in Python." 430 | category = "dev" 431 | optional = false 432 | python-versions = ">=3.5" 433 | 434 | [[package]] 435 | name = "python-dateutil" 436 | version = "2.8.1" 437 | description = "Extensions to the standard Python datetime module" 438 | category = "main" 439 | optional = false 440 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" 441 | 442 | [package.dependencies] 443 | six = ">=1.5" 444 | 445 | [[package]] 446 | name = "python-slugify" 447 | version = "5.0.2" 448 | description = "A Python Slugify application that handles Unicode" 449 | category = "main" 450 | optional = false 451 | python-versions = ">=3.6" 452 | 453 | [package.dependencies] 454 | text-unidecode = ">=1.3" 455 | 456 | [package.extras] 457 | unidecode = ["Unidecode (>=1.1.1)"] 458 | 459 | [[package]] 460 | name = "pyyaml" 461 | version = "5.4.1" 462 | description = "YAML parser and emitter for Python" 463 | category = "main" 464 | optional = false 465 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" 466 | 467 | [[package]] 468 | name = "regex" 469 | version = "2021.4.4" 470 | description = "Alternative regular expression module, to replace re." 471 | category = "dev" 472 | optional = false 473 | python-versions = "*" 474 | 475 | [[package]] 476 | name = "requests" 477 | version = "2.25.1" 478 | description = "Python HTTP for Humans." 479 | category = "main" 480 | optional = false 481 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 482 | 483 | [package.dependencies] 484 | certifi = ">=2017.4.17" 485 | chardet = ">=3.0.2,<5" 486 | idna = ">=2.5,<3" 487 | urllib3 = ">=1.21.1,<1.27" 488 | 489 | [package.extras] 490 | security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] 491 | socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] 492 | 493 | [[package]] 494 | name = "s3transfer" 495 | version = "0.4.2" 496 | description = "An Amazon S3 Transfer Manager" 497 | category = "main" 498 | optional = false 499 | python-versions = "*" 500 | 501 | [package.dependencies] 502 | botocore = ">=1.12.36,<2.0a.0" 503 | 504 | [package.extras] 505 | crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"] 506 | 507 | [[package]] 508 | name = "six" 509 | version = "1.16.0" 510 | description = "Python 2 and 3 compatibility utilities" 511 | category = "main" 512 | optional = false 513 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 514 | 515 | [[package]] 516 | name = "text-unidecode" 517 | version = "1.3" 518 | description = "The most basic Text::Unidecode port" 519 | category = "main" 520 | optional = false 521 | python-versions = "*" 522 | 523 | [[package]] 524 | name = "toml" 525 | version = "0.10.2" 526 | description = "Python Library for Tom's Obvious, Minimal Language" 527 | category = "main" 528 | optional = false 529 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 530 | 531 | [[package]] 532 | name = "tqdm" 533 | version = "4.61.1" 534 | description = "Fast, Extensible Progress Meter" 535 | category = "main" 536 | optional = false 537 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" 538 | 539 | [package.extras] 540 | dev = ["py-make (>=0.1.0)", "twine", "wheel"] 541 | notebook = ["ipywidgets (>=6)"] 542 | telegram = ["requests"] 543 | 544 | [[package]] 545 | name = "traitlets" 546 | version = "5.0.5" 547 | description = "Traitlets Python configuration system" 548 | category = "dev" 549 | optional = false 550 | python-versions = ">=3.7" 551 | 552 | [package.dependencies] 553 | ipython-genutils = "*" 554 | 555 | [package.extras] 556 | test = ["pytest"] 557 | 558 | [[package]] 559 | name = "troposphere" 560 | version = "2.7.1" 561 | description = "AWS CloudFormation creation library" 562 | category = "main" 563 | optional = false 564 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 565 | 566 | [package.dependencies] 567 | cfn_flip = ">=1.0.2" 568 | 569 | [package.extras] 570 | policy = ["awacs (>=0.8)"] 571 | 572 | [[package]] 573 | name = "urllib3" 574 | version = "1.26.6" 575 | description = "HTTP library with thread-safe connection pooling, file post, and more." 576 | category = "main" 577 | optional = false 578 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" 579 | 580 | [package.extras] 581 | brotli = ["brotlipy (>=0.6.0)"] 582 | secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] 583 | socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] 584 | 585 | [[package]] 586 | name = "wcwidth" 587 | version = "0.2.5" 588 | description = "Measures the displayed width of unicode strings in a terminal" 589 | category = "dev" 590 | optional = false 591 | python-versions = "*" 592 | 593 | [[package]] 594 | name = "werkzeug" 595 | version = "0.16.1" 596 | description = "The comprehensive WSGI web application library." 597 | category = "main" 598 | optional = false 599 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 600 | 601 | [package.extras] 602 | dev = ["pytest", "coverage", "tox", "sphinx", "pallets-sphinx-themes", "sphinx-issues"] 603 | termcolor = ["termcolor"] 604 | watchdog = ["watchdog"] 605 | 606 | [[package]] 607 | name = "wsgi-request-logger" 608 | version = "0.4.6" 609 | description = "Apache-like combined logging for WSGI Web Applications" 610 | category = "main" 611 | optional = false 612 | python-versions = "*" 613 | 614 | [[package]] 615 | name = "zappa" 616 | version = "0.53.0" 617 | description = "Server-less Python Web Services for AWS Lambda and API Gateway" 618 | category = "main" 619 | optional = false 620 | python-versions = "*" 621 | 622 | [package.dependencies] 623 | argcomplete = "*" 624 | boto3 = ">=1.17.28" 625 | durationpy = "*" 626 | future = "*" 627 | hjson = "*" 628 | jmespath = "*" 629 | kappa = "0.6.0" 630 | pip-tools = "*" 631 | python-dateutil = "*" 632 | python-slugify = "*" 633 | PyYAML = "*" 634 | requests = ">=2.20.0" 635 | six = "*" 636 | toml = "*" 637 | tqdm = "*" 638 | troposphere = "*" 639 | Werkzeug = "<1.0" 640 | wsgi-request-logger = "*" 641 | 642 | [metadata] 643 | lock-version = "1.1" 644 | python-versions = "^3.8" 645 | content-hash = "9d1851a4c5cbe6aa6aecc6d96ed8569a1fb6d72d30922138eee0d3e91a01d974" 646 | 647 | [metadata.files] 648 | appdirs = [ 649 | {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, 650 | {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, 651 | ] 652 | appnope = [ 653 | {file = "appnope-0.1.2-py2.py3-none-any.whl", hash = "sha256:93aa393e9d6c54c5cd570ccadd8edad61ea0c4b9ea7a01409020c9aa019eb442"}, 654 | {file = "appnope-0.1.2.tar.gz", hash = "sha256:dd83cd4b5b460958838f6eb3000c660b1f9caf2a5b1de4264e941512f603258a"}, 655 | ] 656 | argcomplete = [ 657 | {file = "argcomplete-1.12.3-py2.py3-none-any.whl", hash = "sha256:291f0beca7fd49ce285d2f10e4c1c77e9460cf823eef2de54df0c0fec88b0d81"}, 658 | {file = "argcomplete-1.12.3.tar.gz", hash = "sha256:2c7dbffd8c045ea534921e63b0be6fe65e88599990d8dc408ac8c542b72a5445"}, 659 | ] 660 | backcall = [ 661 | {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, 662 | {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, 663 | ] 664 | black = [ 665 | {file = "black-21.6b0-py3-none-any.whl", hash = "sha256:dfb8c5a069012b2ab1e972e7b908f5fb42b6bbabcba0a788b86dc05067c7d9c7"}, 666 | {file = "black-21.6b0.tar.gz", hash = "sha256:dc132348a88d103016726fe360cb9ede02cecf99b76e3660ce6c596be132ce04"}, 667 | ] 668 | boto3 = [ 669 | {file = "boto3-1.17.101-py2.py3-none-any.whl", hash = "sha256:a9beeb6f1be835ced95e90e93e5ac35b972a0fc35b71e6a1edc01abdc87932d4"}, 670 | {file = "boto3-1.17.101.tar.gz", hash = "sha256:77ebaa3645ae153978a0f2c492502fef3804fe0e693abc7dc74620e4884afe67"}, 671 | ] 672 | botocore = [ 673 | {file = "botocore-1.20.101-py2.py3-none-any.whl", hash = "sha256:2c56644dc1fdfc3f7cc5c690371d0770d8e6b9edb3f4e15f206e5bc27422dcd6"}, 674 | {file = "botocore-1.20.101.tar.gz", hash = "sha256:f7a44fab1a3739ca54e7f72e8625b71574f8218f05349e59d3b871c887444edd"}, 675 | ] 676 | certifi = [ 677 | {file = "certifi-2021.5.30-py2.py3-none-any.whl", hash = "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"}, 678 | {file = "certifi-2021.5.30.tar.gz", hash = "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee"}, 679 | ] 680 | cfn-flip = [ 681 | {file = "cfn_flip-1.2.3.tar.gz", hash = "sha256:2bed32a1f4dca26dc64178d52511fd4ef778b5ccbcf32559cac884ace75bde6a"}, 682 | ] 683 | chardet = [ 684 | {file = "chardet-4.0.0-py2.py3-none-any.whl", hash = "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"}, 685 | {file = "chardet-4.0.0.tar.gz", hash = "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"}, 686 | ] 687 | click = [ 688 | {file = "click-8.0.1-py3-none-any.whl", hash = "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"}, 689 | {file = "click-8.0.1.tar.gz", hash = "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a"}, 690 | ] 691 | colorama = [ 692 | {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, 693 | {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, 694 | ] 695 | decorator = [ 696 | {file = "decorator-5.0.9-py3-none-any.whl", hash = "sha256:6e5c199c16f7a9f0e3a61a4a54b3d27e7dad0dbdde92b944426cb20914376323"}, 697 | {file = "decorator-5.0.9.tar.gz", hash = "sha256:72ecfba4320a893c53f9706bebb2d55c270c1e51a28789361aa93e4a21319ed5"}, 698 | ] 699 | durationpy = [ 700 | {file = "durationpy-0.5.tar.gz", hash = "sha256:5ef9416b527b50d722f34655becfb75e49228eb82f87b855ed1911b3314b5408"}, 701 | ] 702 | flask = [ 703 | {file = "Flask-1.0-py2.py3-none-any.whl", hash = "sha256:b1883637bbee4dc7bc98d900792d0a304d609fce0f5bd9ca91d1b6457e5918dd"}, 704 | {file = "Flask-1.0.tar.gz", hash = "sha256:7fab1062d11dd0038434e790d18c5b9133fd9e6b7257d707c4578ccc1e38b67c"}, 705 | ] 706 | future = [ 707 | {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"}, 708 | ] 709 | hjson = [ 710 | {file = "hjson-3.0.2-py3-none-any.whl", hash = "sha256:5546438bf4e1b52bc964c6a47c4ed10fa5fba8a1b264e22efa893e333baad2db"}, 711 | {file = "hjson-3.0.2.tar.gz", hash = "sha256:2838fd7200e5839ea4516ece953f3a19892c41089f0d933ba3f68e596aacfcd5"}, 712 | ] 713 | idna = [ 714 | {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, 715 | {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, 716 | ] 717 | ipdb = [ 718 | {file = "ipdb-0.13.9.tar.gz", hash = "sha256:951bd9a64731c444fd907a5ce268543020086a697f6be08f7cc2c9a752a278c5"}, 719 | ] 720 | ipython = [ 721 | {file = "ipython-7.25.0-py3-none-any.whl", hash = "sha256:aa21412f2b04ad1a652e30564fff6b4de04726ce875eab222c8430edc6db383a"}, 722 | {file = "ipython-7.25.0.tar.gz", hash = "sha256:54bbd1fe3882457aaf28ae060a5ccdef97f212a741754e420028d4ec5c2291dc"}, 723 | ] 724 | ipython-genutils = [ 725 | {file = "ipython_genutils-0.2.0-py2.py3-none-any.whl", hash = "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8"}, 726 | {file = "ipython_genutils-0.2.0.tar.gz", hash = "sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8"}, 727 | ] 728 | itsdangerous = [ 729 | {file = "itsdangerous-2.0.1-py3-none-any.whl", hash = "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c"}, 730 | {file = "itsdangerous-2.0.1.tar.gz", hash = "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"}, 731 | ] 732 | jedi = [ 733 | {file = "jedi-0.18.0-py2.py3-none-any.whl", hash = "sha256:18456d83f65f400ab0c2d3319e48520420ef43b23a086fdc05dff34132f0fb93"}, 734 | {file = "jedi-0.18.0.tar.gz", hash = "sha256:92550a404bad8afed881a137ec9a461fed49eca661414be45059329614ed0707"}, 735 | ] 736 | jinja2 = [ 737 | {file = "Jinja2-3.0.1-py3-none-any.whl", hash = "sha256:1f06f2da51e7b56b8f238affdd6b4e2c61e39598a378cc49345bc1bd42a978a4"}, 738 | {file = "Jinja2-3.0.1.tar.gz", hash = "sha256:703f484b47a6af502e743c9122595cc812b0271f661722403114f71a79d0f5a4"}, 739 | ] 740 | jmespath = [ 741 | {file = "jmespath-0.10.0-py2.py3-none-any.whl", hash = "sha256:cdf6525904cc597730141d61b36f2e4b8ecc257c420fa2f4549bac2c2d0cb72f"}, 742 | {file = "jmespath-0.10.0.tar.gz", hash = "sha256:b85d0567b8666149a93172712e68920734333c0ce7e89b78b3e987f71e5ed4f9"}, 743 | ] 744 | kappa = [ 745 | {file = "kappa-0.6.0-py2-none-any.whl", hash = "sha256:4d6b7b3accce4a0aaaac92b36237a6304f0f2fffbbe3caea3f7c9f52d12c9989"}, 746 | {file = "kappa-0.6.0.tar.gz", hash = "sha256:4b5b372872f25d619e427e04282551048dc975a107385b076b3ffc6406a15833"}, 747 | ] 748 | markupsafe = [ 749 | {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, 750 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, 751 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, 752 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, 753 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, 754 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, 755 | {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, 756 | {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, 757 | {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, 758 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"}, 759 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"}, 760 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, 761 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, 762 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, 763 | {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, 764 | {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, 765 | {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, 766 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, 767 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, 768 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, 769 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, 770 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, 771 | {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, 772 | {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, 773 | {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, 774 | {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"}, 775 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"}, 776 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"}, 777 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, 778 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, 779 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, 780 | {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, 781 | {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, 782 | {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, 783 | ] 784 | matplotlib-inline = [ 785 | {file = "matplotlib-inline-0.1.2.tar.gz", hash = "sha256:f41d5ff73c9f5385775d5c0bc13b424535c8402fe70ea8210f93e11f3683993e"}, 786 | {file = "matplotlib_inline-0.1.2-py3-none-any.whl", hash = "sha256:5cf1176f554abb4fa98cb362aa2b55c500147e4bdbb07e3fda359143e1da0811"}, 787 | ] 788 | mypy-extensions = [ 789 | {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, 790 | {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, 791 | ] 792 | parso = [ 793 | {file = "parso-0.8.2-py2.py3-none-any.whl", hash = "sha256:a8c4922db71e4fdb90e0d0bc6e50f9b273d3397925e5e60a717e719201778d22"}, 794 | {file = "parso-0.8.2.tar.gz", hash = "sha256:12b83492c6239ce32ff5eed6d3639d6a536170723c6f3f1506869f1ace413398"}, 795 | ] 796 | pathspec = [ 797 | {file = "pathspec-0.8.1-py2.py3-none-any.whl", hash = "sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d"}, 798 | {file = "pathspec-0.8.1.tar.gz", hash = "sha256:86379d6b86d75816baba717e64b1a3a3469deb93bb76d613c9ce79edc5cb68fd"}, 799 | ] 800 | pep517 = [ 801 | {file = "pep517-0.10.0-py2.py3-none-any.whl", hash = "sha256:eba39d201ef937584ad3343df3581069085bacc95454c80188291d5b3ac7a249"}, 802 | {file = "pep517-0.10.0.tar.gz", hash = "sha256:ac59f3f6b9726a49e15a649474539442cf76e0697e39df4869d25e68e880931b"}, 803 | ] 804 | pexpect = [ 805 | {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, 806 | {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, 807 | ] 808 | pickleshare = [ 809 | {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, 810 | {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, 811 | ] 812 | pip-tools = [ 813 | {file = "pip-tools-6.2.0.tar.gz", hash = "sha256:9ed38c73da4993e531694ea151f77048b4dbf2ba7b94c4a569daa39568cc6564"}, 814 | {file = "pip_tools-6.2.0-py3-none-any.whl", hash = "sha256:77727ef7457d1865e61fe34c2b1439f9b971b570cc232616a22ce82ab89d357d"}, 815 | ] 816 | placebo = [ 817 | {file = "placebo-0.9.0.tar.gz", hash = "sha256:03157f8527bbc2965b71b88f4a139ef8038618b346787f20d63e3c5da541b047"}, 818 | ] 819 | prompt-toolkit = [ 820 | {file = "prompt_toolkit-3.0.19-py3-none-any.whl", hash = "sha256:7089d8d2938043508aa9420ec18ce0922885304cddae87fb96eebca942299f88"}, 821 | {file = "prompt_toolkit-3.0.19.tar.gz", hash = "sha256:08360ee3a3148bdb5163621709ee322ec34fc4375099afa4bbf751e9b7b7fa4f"}, 822 | ] 823 | ptyprocess = [ 824 | {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, 825 | {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, 826 | ] 827 | pygments = [ 828 | {file = "Pygments-2.9.0-py3-none-any.whl", hash = "sha256:d66e804411278594d764fc69ec36ec13d9ae9147193a1740cd34d272ca383b8e"}, 829 | {file = "Pygments-2.9.0.tar.gz", hash = "sha256:a18f47b506a429f6f4b9df81bb02beab9ca21d0a5fee38ed15aef65f0545519f"}, 830 | ] 831 | python-dateutil = [ 832 | {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, 833 | {file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"}, 834 | ] 835 | python-slugify = [ 836 | {file = "python-slugify-5.0.2.tar.gz", hash = "sha256:f13383a0b9fcbe649a1892b9c8eb4f8eab1d6d84b84bb7a624317afa98159cab"}, 837 | {file = "python_slugify-5.0.2-py2.py3-none-any.whl", hash = "sha256:6d8c5df75cd4a7c3a2d21e257633de53f52ab0265cd2d1dc62a730e8194a7380"}, 838 | ] 839 | pyyaml = [ 840 | {file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"}, 841 | {file = "PyYAML-5.4.1-cp27-cp27m-win32.whl", hash = "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393"}, 842 | {file = "PyYAML-5.4.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8"}, 843 | {file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"}, 844 | {file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"}, 845 | {file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"}, 846 | {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347"}, 847 | {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541"}, 848 | {file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"}, 849 | {file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"}, 850 | {file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"}, 851 | {file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"}, 852 | {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa"}, 853 | {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"}, 854 | {file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"}, 855 | {file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"}, 856 | {file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"}, 857 | {file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"}, 858 | {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247"}, 859 | {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc"}, 860 | {file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"}, 861 | {file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"}, 862 | {file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"}, 863 | {file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"}, 864 | {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122"}, 865 | {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6"}, 866 | {file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"}, 867 | {file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"}, 868 | {file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"}, 869 | ] 870 | regex = [ 871 | {file = "regex-2021.4.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:619d71c59a78b84d7f18891fe914446d07edd48dc8328c8e149cbe0929b4e000"}, 872 | {file = "regex-2021.4.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:47bf5bf60cf04d72bf6055ae5927a0bd9016096bf3d742fa50d9bf9f45aa0711"}, 873 | {file = "regex-2021.4.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:281d2fd05555079448537fe108d79eb031b403dac622621c78944c235f3fcf11"}, 874 | {file = "regex-2021.4.4-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:bd28bc2e3a772acbb07787c6308e00d9626ff89e3bfcdebe87fa5afbfdedf968"}, 875 | {file = "regex-2021.4.4-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:7c2a1af393fcc09e898beba5dd59196edaa3116191cc7257f9224beaed3e1aa0"}, 876 | {file = "regex-2021.4.4-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c38c71df845e2aabb7fb0b920d11a1b5ac8526005e533a8920aea97efb8ec6a4"}, 877 | {file = "regex-2021.4.4-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:96fcd1888ab4d03adfc9303a7b3c0bd78c5412b2bfbe76db5b56d9eae004907a"}, 878 | {file = "regex-2021.4.4-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:ade17eb5d643b7fead300a1641e9f45401c98eee23763e9ed66a43f92f20b4a7"}, 879 | {file = "regex-2021.4.4-cp36-cp36m-win32.whl", hash = "sha256:e8e5b509d5c2ff12f8418006d5a90e9436766133b564db0abaec92fd27fcee29"}, 880 | {file = "regex-2021.4.4-cp36-cp36m-win_amd64.whl", hash = "sha256:11d773d75fa650cd36f68d7ca936e3c7afaae41b863b8c387a22aaa78d3c5c79"}, 881 | {file = "regex-2021.4.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d3029c340cfbb3ac0a71798100ccc13b97dddf373a4ae56b6a72cf70dfd53bc8"}, 882 | {file = "regex-2021.4.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:18c071c3eb09c30a264879f0d310d37fe5d3a3111662438889ae2eb6fc570c31"}, 883 | {file = "regex-2021.4.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:4c557a7b470908b1712fe27fb1ef20772b78079808c87d20a90d051660b1d69a"}, 884 | {file = "regex-2021.4.4-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:01afaf2ec48e196ba91b37451aa353cb7eda77efe518e481707e0515025f0cd5"}, 885 | {file = "regex-2021.4.4-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:3a9cd17e6e5c7eb328517969e0cb0c3d31fd329298dd0c04af99ebf42e904f82"}, 886 | {file = "regex-2021.4.4-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:90f11ff637fe8798933fb29f5ae1148c978cccb0452005bf4c69e13db951e765"}, 887 | {file = "regex-2021.4.4-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:919859aa909429fb5aa9cf8807f6045592c85ef56fdd30a9a3747e513db2536e"}, 888 | {file = "regex-2021.4.4-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:339456e7d8c06dd36a22e451d58ef72cef293112b559010db3d054d5560ef439"}, 889 | {file = "regex-2021.4.4-cp37-cp37m-win32.whl", hash = "sha256:67bdb9702427ceddc6ef3dc382455e90f785af4c13d495f9626861763ee13f9d"}, 890 | {file = "regex-2021.4.4-cp37-cp37m-win_amd64.whl", hash = "sha256:32e65442138b7b76dd8173ffa2cf67356b7bc1768851dded39a7a13bf9223da3"}, 891 | {file = "regex-2021.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1e1c20e29358165242928c2de1482fb2cf4ea54a6a6dea2bd7a0e0d8ee321500"}, 892 | {file = "regex-2021.4.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:314d66636c494ed9c148a42731b3834496cc9a2c4251b1661e40936814542b14"}, 893 | {file = "regex-2021.4.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:6d1b01031dedf2503631d0903cb563743f397ccaf6607a5e3b19a3d76fc10480"}, 894 | {file = "regex-2021.4.4-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:741a9647fcf2e45f3a1cf0e24f5e17febf3efe8d4ba1281dcc3aa0459ef424dc"}, 895 | {file = "regex-2021.4.4-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:4c46e22a0933dd783467cf32b3516299fb98cfebd895817d685130cc50cd1093"}, 896 | {file = "regex-2021.4.4-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:e512d8ef5ad7b898cdb2d8ee1cb09a8339e4f8be706d27eaa180c2f177248a10"}, 897 | {file = "regex-2021.4.4-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:980d7be47c84979d9136328d882f67ec5e50008681d94ecc8afa8a65ed1f4a6f"}, 898 | {file = "regex-2021.4.4-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:ce15b6d103daff8e9fee13cf7f0add05245a05d866e73926c358e871221eae87"}, 899 | {file = "regex-2021.4.4-cp38-cp38-win32.whl", hash = "sha256:a91aa8619b23b79bcbeb37abe286f2f408d2f2d6f29a17237afda55bb54e7aac"}, 900 | {file = "regex-2021.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:c0502c0fadef0d23b128605d69b58edb2c681c25d44574fc673b0e52dce71ee2"}, 901 | {file = "regex-2021.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:598585c9f0af8374c28edd609eb291b5726d7cbce16be6a8b95aa074d252ee17"}, 902 | {file = "regex-2021.4.4-cp39-cp39-manylinux1_i686.whl", hash = "sha256:ee54ff27bf0afaf4c3b3a62bcd016c12c3fdb4ec4f413391a90bd38bc3624605"}, 903 | {file = "regex-2021.4.4-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7d9884d86dd4dd489e981d94a65cd30d6f07203d90e98f6f657f05170f6324c9"}, 904 | {file = "regex-2021.4.4-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:bf5824bfac591ddb2c1f0a5f4ab72da28994548c708d2191e3b87dd207eb3ad7"}, 905 | {file = "regex-2021.4.4-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:563085e55b0d4fb8f746f6a335893bda5c2cef43b2f0258fe1020ab1dd874df8"}, 906 | {file = "regex-2021.4.4-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b9c3db21af35e3b3c05764461b262d6f05bbca08a71a7849fd79d47ba7bc33ed"}, 907 | {file = "regex-2021.4.4-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:3916d08be28a1149fb97f7728fca1f7c15d309a9f9682d89d79db75d5e52091c"}, 908 | {file = "regex-2021.4.4-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:fd45ff9293d9274c5008a2054ecef86a9bfe819a67c7be1afb65e69b405b3042"}, 909 | {file = "regex-2021.4.4-cp39-cp39-win32.whl", hash = "sha256:fa4537fb4a98fe8fde99626e4681cc644bdcf2a795038533f9f711513a862ae6"}, 910 | {file = "regex-2021.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:97f29f57d5b84e73fbaf99ab3e26134e6687348e95ef6b48cfd2c06807005a07"}, 911 | {file = "regex-2021.4.4.tar.gz", hash = "sha256:52ba3d3f9b942c49d7e4bc105bb28551c44065f139a65062ab7912bef10c9afb"}, 912 | ] 913 | requests = [ 914 | {file = "requests-2.25.1-py2.py3-none-any.whl", hash = "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"}, 915 | {file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"}, 916 | ] 917 | s3transfer = [ 918 | {file = "s3transfer-0.4.2-py2.py3-none-any.whl", hash = "sha256:9b3752887a2880690ce628bc263d6d13a3864083aeacff4890c1c9839a5eb0bc"}, 919 | {file = "s3transfer-0.4.2.tar.gz", hash = "sha256:cb022f4b16551edebbb31a377d3f09600dbada7363d8c5db7976e7f47732e1b2"}, 920 | ] 921 | six = [ 922 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, 923 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, 924 | ] 925 | text-unidecode = [ 926 | {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"}, 927 | {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, 928 | ] 929 | toml = [ 930 | {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, 931 | {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, 932 | ] 933 | tqdm = [ 934 | {file = "tqdm-4.61.1-py2.py3-none-any.whl", hash = "sha256:aa0c29f03f298951ac6318f7c8ce584e48fa22ec26396e6411e43d038243bdb2"}, 935 | {file = "tqdm-4.61.1.tar.gz", hash = "sha256:24be966933e942be5f074c29755a95b315c69a91f839a29139bf26ffffe2d3fd"}, 936 | ] 937 | traitlets = [ 938 | {file = "traitlets-5.0.5-py3-none-any.whl", hash = "sha256:69ff3f9d5351f31a7ad80443c2674b7099df13cc41fc5fa6e2f6d3b0330b0426"}, 939 | {file = "traitlets-5.0.5.tar.gz", hash = "sha256:178f4ce988f69189f7e523337a3e11d91c786ded9360174a3d9ca83e79bc5396"}, 940 | ] 941 | troposphere = [ 942 | {file = "troposphere-2.7.1.tar.gz", hash = "sha256:ea2e5f2f82c224eaa1414a008b1939aae124c3e3e1dd993301968f155b333bd7"}, 943 | ] 944 | urllib3 = [ 945 | {file = "urllib3-1.26.6-py2.py3-none-any.whl", hash = "sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4"}, 946 | {file = "urllib3-1.26.6.tar.gz", hash = "sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f"}, 947 | ] 948 | wcwidth = [ 949 | {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, 950 | {file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"}, 951 | ] 952 | werkzeug = [ 953 | {file = "Werkzeug-0.16.1-py2.py3-none-any.whl", hash = "sha256:1e0dedc2acb1f46827daa2e399c1485c8fa17c0d8e70b6b875b4e7f54bf408d2"}, 954 | {file = "Werkzeug-0.16.1.tar.gz", hash = "sha256:b353856d37dec59d6511359f97f6a4b2468442e454bd1c98298ddce53cac1f04"}, 955 | ] 956 | wsgi-request-logger = [ 957 | {file = "wsgi-request-logger-0.4.6.tar.gz", hash = "sha256:445d7ec52799562f812006394d0b4a7064b37084c6ea6bd74ea7a2136c97ed83"}, 958 | ] 959 | zappa = [ 960 | {file = "zappa-0.53.0-py3-none-any.whl", hash = "sha256:46a0afc1218de17bf713a8f4cfcb4dde2ba0466d18088918b9d2bc22ec6f9434"}, 961 | {file = "zappa-0.53.0.tar.gz", hash = "sha256:a3623197a1dd30faa028f62fda1b7ba5dcbb643bc6ac43ad4cffdfd89a3b85c8"}, 962 | ] 963 | --------------------------------------------------------------------------------