diff --git a/.github/workflows/test-ubuntu.yml b/.github/workflows/test-ubuntu.yml index 2f41013..a6abfd0 100644 --- a/.github/workflows/test-ubuntu.yml +++ b/.github/workflows/test-ubuntu.yml @@ -10,11 +10,7 @@ on: jobs: build: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-20.04, ubuntu-18.04] - python_version: [3.7, 3.8, 3.9] + runs-on: ubuntu-20.04 services: postgres: image: kartoza/postgis:12.1 @@ -43,16 +39,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python_version }} + - name: Set up Python 3.10 uses: actions/setup-python@v2 with: - python-version: ${{ matrix.python_version }} - - # From https://github.com/python-poetry/poetry/actions - - name: Get full python version - id: full-python-version - run: | - echo ::set-output name=version::$(python -c "import sys; print('-'.join(str(v) for v in sys.version_info[:3]))") + python-version: '3.10' - name: Install and set up Poetry run: | @@ -64,7 +54,7 @@ jobs: uses: actions/cache@v2 with: path: .venv - key: venv-${{ runner.os }}-${{ steps.full-python-version.outputs.version }}-${{ hashFiles('**/poetry.lock') }} + key: venv-3.10-${{ hashFiles('**/poetry.lock') }} - name: Install dependencies run: | @@ -77,29 +67,25 @@ jobs: - name: Install osmium run: | - sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 648ACFD622F3D138 - sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 04EE7237B7D453EC - sudo add-apt-repository 'deb http://ftp.debian.org/debian sid main' sudo apt-get update sudo apt-get install -y -qq osmium-tool osmctools echo $(osmium --version) - - name: yapf linting + - name: linting run: | source .venv/bin/activate - yapf -r -vv --diff -p tests routing_packager_app config.py http_app.py gunicorn.py + pre-commit run --all-files - - name: pytest + - name: pytest and coverage run: | source .venv/bin/activate sudo python -m smtpd -n -c DebuggingServer localhost:1025 & sudo docker volume create routing-packager_packages --driver local --opt type=none --opt device=$PWD --opt o=bind pytest --cov=routing_packager_app --ignore=tests/test_tasks.py + coverage lcov --include "routing_packager_app/*" - name: coveralls - run: | - source .venv/bin/activate - coveralls - - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + path-to-lcov: ./coverage.lcov \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1f3e5fc..1f83e83 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,11 @@ repos: -- repo: https://github.com/pre-commit/mirrors-yapf - rev: v0.30.0 # Use the sha / tag you want to point at +- repo: https://github.com/psf/black + rev: 22.3.0 hooks: - - id: yapf \ No newline at end of file + - id: black + language_version: python3 + args: [routing_packager_app, tests] +- repo: https://github.com/pycqa/flake8 + rev: 4.0.1 # pick a git hash / tag to point to + hooks: + - id: flake8 diff --git a/Dockerfile b/Dockerfile index e2a5692..7bb1344 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ #--- BEGIN Usual Python stuff --- -FROM python:3.9-slim-buster +FROM python:3.10-slim-bullseye LABEL maintainer=nils@gis-ops.com # Install poetry @@ -21,14 +21,17 @@ RUN apt-get update -y > /dev/null && \ RUN apt-get update -y > /dev/null && \ apt-get install -y --fix-missing \ software-properties-common \ - gnupg-agent \ + apt-transport-https \ + ca-certificates \ + curl \ + gnupg \ + lsb-release \ nano \ jq \ cron -o APT::Immediate-Configure=0 > /dev/null && \ # install docker & osmium curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - && \ add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" && \ - add-apt-repository 'deb http://ftp.debian.org/debian sid main' && \ apt-get update -y > /dev/null && \ apt-get install -y docker-ce docker-ce-cli containerd.io osmium-tool osmctools > /dev/null && \ systemctl enable docker diff --git a/config.py b/config.py index f8d3af5..a817c31 100644 --- a/config.py +++ b/config.py @@ -3,60 +3,62 @@ from distutils.util import strtobool basedir = os.path.abspath(os.path.dirname(__file__)) -load_dotenv(os.path.join(basedir, '.env')) +load_dotenv(os.path.join(basedir, ".env")) def _get_list_var(var): out = [] if var: - out.extend(var.split(',')) + out.extend(var.split(",")) return out class BaseConfig(object): ### FLASK ### - SECRET_KEY = os.getenv( - 'SECRET_KEY' - ) or ';LarIGI&FjWhKNSe=%3|W;=DFDqOdx+~-rBS+K=p8#t#9E+;{e$' + SECRET_KEY = ( + os.getenv("SECRET_KEY") or ";LarIGI&FjWhKNSe=%3|W;=DFDqOdx+~-rBS+K=p8#t#9E+;{e$" + ) ERROR_INCLUDE_MESSAGE = False # No default "message" field in error responses RESTX_MASK_SWAGGER = False # No default MASK header in Swagger SQLALCHEMY_TRACK_MODIFICATIONS = False ### APP ### - ADMIN_EMAIL = os.getenv('ADMIN_EMAIL') or 'admin@example.org' - ADMIN_PASS = os.getenv('ADMIN_PASSWORD') or 'admin' + ADMIN_EMAIL = os.getenv("ADMIN_EMAIL") or "admin@example.org" + ADMIN_PASS = os.getenv("ADMIN_PASSWORD") or "admin" - DATA_DIR = os.getenv('DATA_DIR') or os.path.join(basedir, 'data') + DATA_DIR = os.getenv("DATA_DIR") or os.path.join(basedir, "data") # if we're inside a docker container, we need to reference the fixed directory instead # Watch out for CI, also runs within docker - if os.path.isdir('/app/data') and not os.getenv('CI', None): - DATA_DIR = '/app/data' + if os.path.isdir("/app/data") and not os.getenv("CI", None): + DATA_DIR = "/app/data" - ENABLED_PROVIDERS = _get_list_var(os.getenv('ENABLED_PROVIDERS')) or ['osm'] - ENABLED_ROUTERS = _get_list_var(os.getenv('ENABLED_ROUTERS')) or ['valhalla'] - VALHALLA_IMAGE = os.getenv('VALHALLA_IMAGE') or 'gisops/valhalla:latest' - OSRM_IMAGE = os.getenv('OSRM_IMAGE') or 'osrm/osrm-backend:latest' - ORS_IMAGE = os.getenv('ORS_IMAGE') or 'openrouteservice/openrouteservice:latest' - GRAPHHOPPER_IMAGE = os.getenv('GRAPHHOPPER_IMAGE') or 'graphhopper/graphhopper:latest' + ENABLED_PROVIDERS = _get_list_var(os.getenv("ENABLED_PROVIDERS")) or ["osm"] + ENABLED_ROUTERS = _get_list_var(os.getenv("ENABLED_ROUTERS")) or ["valhalla"] + VALHALLA_IMAGE = os.getenv("VALHALLA_IMAGE") or "gisops/valhalla:latest" + OSRM_IMAGE = os.getenv("OSRM_IMAGE") or "osrm/osrm-backend:latest" + ORS_IMAGE = os.getenv("ORS_IMAGE") or "openrouteservice/openrouteservice:latest" + GRAPHHOPPER_IMAGE = os.getenv("GRAPHHOPPER_IMAGE") or "graphhopper/graphhopper:latest" ### DATABASES ### - POSTGRES_HOST = os.getenv('POSTGRES_HOST') or 'localhost' - POSTGRES_PORT = int(os.getenv('POSTGRES_PORT', int())) or 5432 - POSTGRES_DB = os.getenv('POSTGRES_DB') or 'gis' - POSTGRES_USER = os.getenv('POSTGRES_USER') or 'docker' - POSTGRES_PASS = os.getenv('POSTGRES_PASS') or 'docker' - SQLALCHEMY_DATABASE_URI = os.getenv('POSTGRES_URL') or \ - f'postgresql://{POSTGRES_USER}:{POSTGRES_PASS}@{POSTGRES_HOST}:{POSTGRES_PORT}/{POSTGRES_DB}' - REDIS_URL = os.getenv('REDIS_URL') or f'redis://localhost:6379/0' + POSTGRES_HOST = os.getenv("POSTGRES_HOST") or "localhost" + POSTGRES_PORT = int(os.getenv("POSTGRES_PORT", int())) or 5432 + POSTGRES_DB = os.getenv("POSTGRES_DB") or "gis" + POSTGRES_USER = os.getenv("POSTGRES_USER") or "docker" + POSTGRES_PASS = os.getenv("POSTGRES_PASS") or "docker" + SQLALCHEMY_DATABASE_URI = ( + os.getenv("POSTGRES_URL") + or f"postgresql://{POSTGRES_USER}:{POSTGRES_PASS}@{POSTGRES_HOST}:{POSTGRES_PORT}/{POSTGRES_DB}" + ) + REDIS_URL = os.getenv("REDIS_URL") or "redis://localhost:6379/0" ### SMTP ### - SMTP_HOST = os.getenv('SMTP_HOST') or 'localhost' - SMTP_PORT = int(os.getenv('SMTP_PORT', int())) or 1025 - SMTP_FROM = os.getenv('SMTP_FROM') or 'valhalla@kadas.org' - SMTP_USER = os.getenv('SMTP_USER') - SMTP_PASS = os.getenv('SMTP_PASS') - SMTP_SECURE = bool(strtobool(os.getenv('SMTP_SECURE', 'False'))) or False + SMTP_HOST = os.getenv("SMTP_HOST") or "localhost" + SMTP_PORT = int(os.getenv("SMTP_PORT", int())) or 1025 + SMTP_FROM = os.getenv("SMTP_FROM") or "valhalla@kadas.org" + SMTP_USER = os.getenv("SMTP_USER") + SMTP_PASS = os.getenv("SMTP_PASS") + SMTP_SECURE = bool(strtobool(os.getenv("SMTP_SECURE", "False"))) or False class DevConfig(BaseConfig): @@ -71,22 +73,24 @@ class TestingConfig(BaseConfig): TESTING = True FLASK_DEBUG = 0 - POSTGRES_HOST = os.getenv('POSTGRES_HOST') or 'localhost' - POSTGRES_PORT = os.getenv('POSTGRES_PORT') or '5432' - POSTGRES_DB_TEST = os.getenv('POSTGRES_DB_TEST') or 'gis_test' - POSTGRES_USER = os.getenv('POSTGRES_USER') or 'admin' - POSTGRES_PASS = os.getenv('POSTGRES_PASS') or 'admin' + POSTGRES_HOST = os.getenv("POSTGRES_HOST") or "localhost" + POSTGRES_PORT = os.getenv("POSTGRES_PORT") or "5432" + POSTGRES_DB_TEST = os.getenv("POSTGRES_DB_TEST") or "gis_test" + POSTGRES_USER = os.getenv("POSTGRES_USER") or "admin" + POSTGRES_PASS = os.getenv("POSTGRES_PASS") or "admin" - SQLALCHEMY_DATABASE_URI = os.getenv('POSTGRES_TEST_URL') or \ - f'postgresql://{POSTGRES_USER}:{POSTGRES_PASS}@{POSTGRES_HOST}:{POSTGRES_PORT}/{POSTGRES_DB_TEST}' + SQLALCHEMY_DATABASE_URI = ( + os.getenv("POSTGRES_TEST_URL") + or f"postgresql://{POSTGRES_USER}:{POSTGRES_PASS}@{POSTGRES_HOST}:{POSTGRES_PORT}/{POSTGRES_DB_TEST}" + ) - DATA_DIR = os.path.join(basedir, 'tests', 'data') - OSM_PBF_PATH = os.path.join(basedir, 'tests', 'data', 'andorra-200827.osm.pbf') - TOMTOM_PBF_PATH = os.path.join(basedir, 'tests', 'data', 'liechtenstein-201109.tomtom.pbf') - HERE_PBF_PATH = os.path.join(basedir, 'tests', 'data', 'liechtenstein-201109.here.pbf') + DATA_DIR = os.path.join(basedir, "tests", "data") + OSM_PBF_PATH = os.path.join(basedir, "tests", "data", "andorra-200827.osm.pbf") + TOMTOM_PBF_PATH = os.path.join(basedir, "tests", "data", "liechtenstein-201109.tomtom.pbf") + HERE_PBF_PATH = os.path.join(basedir, "tests", "data", "liechtenstein-201109.here.pbf") - ENABLED_ROUTERS = _get_list_var('valhalla') - ENABLED_PROVIDERS = _get_list_var('osm,tomtom,here') + ENABLED_ROUTERS = _get_list_var("valhalla") + ENABLED_PROVIDERS = _get_list_var("osm,tomtom,here") - ADMIN_EMAIL = 'admin@example.org' - ADMIN_PASS = 'admin' + ADMIN_EMAIL = "admin@example.org" + ADMIN_PASS = "admin" diff --git a/gunicorn.py b/gunicorn.py index 7fab275..c2a80b4 100644 --- a/gunicorn.py +++ b/gunicorn.py @@ -1,7 +1,7 @@ bind = "0.0.0.0:5000" # Generally we recommend (2 x $num_cores) + 1 as the number of workers to start off with workers = 5 -worker_class = 'gevent' +worker_class = "gevent" worker_connections = 10 timeout = 30 keepalive = 2 diff --git a/http_app.py b/http_app.py index 89e79b7..cea1435 100644 --- a/http_app.py +++ b/http_app.py @@ -7,4 +7,4 @@ @app.shell_context_processor def make_shell_context(): - return {'db': db, 'User': User, 'Job': Job} + return {"db": db, "User": User, "Job": Job} diff --git a/poetry.lock b/poetry.lock index 0d6963b..50805b2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,17 +1,3 @@ -[[package]] -name = "alembic" -version = "1.6.5" -description = "A database migration tool for SQLAlchemy." -category = "main" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" - -[package.dependencies] -Mako = "*" -python-dateutil = "*" -python-editor = ">=0.3" -SQLAlchemy = ">=1.3.0" - [[package]] name = "aniso8601" version = "9.0.1" @@ -23,6 +9,14 @@ python-versions = "*" [package.extras] dev = ["black", "coverage", "isort", "pre-commit", "pyenchant", "pylint"] +[[package]] +name = "async-timeout" +version = "4.0.2" +description = "Timeout context manager for asyncio programs" +category = "main" +optional = false +python-versions = ">=3.6" + [[package]] name = "atomicwrites" version = "1.4.0" @@ -33,36 +27,21 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "attrs" -version = "21.2.0" +version = "21.4.0" description = "Classes Without Boilerplate" category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit"] +dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"] -tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"] - -[[package]] -name = "backports.entry-points-selectable" -version = "1.1.0" -description = "Compatibility shim providing selectable entry points for older implementations" -category = "dev" -optional = false -python-versions = ">=2.7" - -[package.dependencies] -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} - -[package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=4.6)", "pytest-flake8", "pytest-cov", "pytest-black (>=0.3.7)", "pytest-mypy", "pytest-checkdocs (>=2.4)", "pytest-enabler (>=1.0.1)"] +tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] +tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"] [[package]] name = "certifi" -version = "2021.5.30" +version = "2021.10.8" description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false @@ -70,7 +49,7 @@ python-versions = "*" [[package]] name = "cffi" -version = "1.14.6" +version = "1.15.0" description = "Foreign Function Interface for Python calling C code." category = "main" optional = false @@ -81,7 +60,7 @@ pycparser = "*" [[package]] name = "cfgv" -version = "3.3.0" +version = "3.3.1" description = "Validate configuration and produce human readable error messages." category = "dev" optional = false @@ -89,7 +68,7 @@ python-versions = ">=3.6.1" [[package]] name = "charset-normalizer" -version = "2.0.3" +version = "2.0.12" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "main" optional = false @@ -100,50 +79,70 @@ unicode_backport = ["unicodedata2"] [[package]] name = "click" -version = "7.1.2" +version = "8.1.2" description = "Composable command line interface toolkit" category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.7" + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "colorama" version = "0.4.4" description = "Cross-platform colored terminal text." -category = "dev" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "coverage" -version = "5.5" +version = "6.3.2" description = "Code coverage measurement for Python" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +python-versions = ">=3.7" + +[package.dependencies] +tomli = {version = "*", optional = true, markers = "extra == \"toml\""} [package.extras] -toml = ["toml"] +toml = ["tomli"] [[package]] name = "coveralls" -version = "2.2.0" +version = "3.3.1" description = "Show coverage stats online via coveralls.io" category = "dev" optional = false python-versions = ">= 3.5" [package.dependencies] -coverage = ">=4.1,<6.0" +coverage = ">=4.1,<6.0.0 || >6.1,<6.1.1 || >6.1.1,<7.0" docopt = ">=0.6.1" requests = ">=1.0.0" [package.extras] yaml = ["PyYAML (>=3.10)"] +[[package]] +name = "deprecated" +version = "1.2.13" +description = "Python @deprecated decorator to deprecate old python classes, functions or methods." +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" + +[package.dependencies] +wrapt = ">=1.10,<2" + +[package.extras] +dev = ["tox", "bump2version (<1)", "sphinx (<2)", "importlib-metadata (<3)", "importlib-resources (<4)", "configparser (<5)", "sphinxcontrib-websupport (<2)", "zipp (<2)", "PyTest (<5)", "PyTest-Cov (<2.6)", "pytest", "pytest-cov"] + [[package]] name = "distlib" -version = "0.3.2" +version = "0.3.4" description = "Distribution utilities" category = "dev" optional = false @@ -151,21 +150,20 @@ python-versions = "*" [[package]] name = "docker" -version = "4.4.4" +version = "5.0.3" description = "A Python library for the Docker Engine API." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.6" [package.dependencies] pywin32 = {version = "227", markers = "sys_platform == \"win32\""} requests = ">=2.14.2,<2.18.0 || >2.18.0" -six = ">=1.4.0" websocket-client = ">=0.32.0" [package.extras] ssh = ["paramiko (>=2.4.2)"] -tls = ["pyOpenSSL (>=17.5.0)", "cryptography (>=1.3.4)", "idna (>=2.0.0)"] +tls = ["pyOpenSSL (>=17.5.0)", "cryptography (>=3.4.7)", "idna (>=2.0.0)"] [[package]] name = "docopt" @@ -177,29 +175,33 @@ python-versions = "*" [[package]] name = "filelock" -version = "3.0.12" +version = "3.6.0" description = "A platform independent file lock." category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.7" + +[package.extras] +docs = ["furo (>=2021.8.17b43)", "sphinx (>=4.1)", "sphinx-autodoc-typehints (>=1.12)"] +testing = ["covdefaults (>=1.2.0)", "coverage (>=4)", "pytest (>=4)", "pytest-cov", "pytest-timeout (>=1.4.2)"] [[package]] name = "flask" -version = "1.1.4" +version = "2.1.1" description = "A simple framework for building complex web applications." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.7" [package.dependencies] -click = ">=5.1,<8.0" -itsdangerous = ">=0.24,<2.0" -Jinja2 = ">=2.10.1,<3.0" -Werkzeug = ">=0.15,<2.0" +click = ">=8.0" +importlib-metadata = {version = ">=3.6.0", markers = "python_version < \"3.10\""} +itsdangerous = ">=2.0" +Jinja2 = ">=3.0" +Werkzeug = ">=2.0" [package.extras] -dev = ["pytest", "coverage", "tox", "sphinx", "pallets-sphinx-themes", "sphinxcontrib-log-cabinet", "sphinx-issues"] -docs = ["sphinx", "pallets-sphinx-themes", "sphinxcontrib-log-cabinet", "sphinx-issues"] +async = ["asgiref (>=3.2)"] dotenv = ["python-dotenv"] [[package]] @@ -216,49 +218,43 @@ Six = "*" [[package]] name = "flask-httpauth" -version = "4.4.0" -description = "Basic and Digest HTTP authentication for Flask routes" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -Flask = "*" - -[[package]] -name = "flask-migrate" -version = "2.7.0" -description = "SQLAlchemy database migrations for Flask applications using Alembic" +version = "4.5.0" +description = "HTTP authentication for Flask routes" category = "main" optional = false python-versions = "*" [package.dependencies] -alembic = ">=0.7" -Flask = ">=0.9" -Flask-SQLAlchemy = ">=1.0" +flask = "*" [[package]] name = "flask-restx" -version = "0.2.0" +version = "0.5.2.dev0" description = "Fully featured framework for fast, easy and documented API development with Flask" category = "main" optional = false python-versions = "*" +develop = false [package.dependencies] -aniso8601 = ">=0.82" -Flask = ">=0.8" +aniso8601 = {version = ">=0.82", markers = "python_version >= \"3.5\""} +Flask = ">=0.8,<2.0.0 || >2.0.0" jsonschema = "*" pytz = "*" six = ">=1.3.0" -werkzeug = "*" +werkzeug = "!=2.0.0" [package.extras] -dev = ["blinker", "Faker (==2.0.0)", "mock (==3.0.5)", "pytest-benchmark (==3.2.2)", "pytest-cov (==2.7.1)", "pytest-flask (==0.15.1)", "pytest-mock (==1.10.4)", "pytest-profiling (==1.7.0)", "tzlocal", "invoke (==1.3.0)", "readme-renderer (==24.0)", "twine (==1.15.0)", "tox (==3.13.2)", "pytest (==4.6.5)", "pytest (==5.4.1)", "ossaudit", "black (==19.10b0)"] +dev = ["blinker", "Faker (==2.0.0)", "mock (==3.0.5)", "pytest-benchmark (==3.2.2)", "pytest-cov (==2.7.1)", "pytest-flask (==0.15.1)", "pytest-mock (==1.10.4)", "pytest-profiling (==1.7.0)", "tzlocal", "invoke (==1.3.0)", "readme-renderer (==24.0)", "twine (==1.15.0)", "tox", "pytest (==4.6.5)", "pytest (==5.4.1)", "ossaudit", "black"] doc = ["alabaster (==0.7.12)", "Sphinx (==2.1.2)", "sphinx-issues (==1.2.0)"] test = ["blinker", "Faker (==2.0.0)", "mock (==3.0.5)", "pytest-benchmark (==3.2.2)", "pytest-cov (==2.7.1)", "pytest-flask (==0.15.1)", "pytest-mock (==1.10.4)", "pytest-profiling (==1.7.0)", "tzlocal", "invoke (==1.3.0)", "readme-renderer (==24.0)", "twine (==1.15.0)", "pytest (==4.6.5)", "pytest (==5.4.1)", "ossaudit"] +[package.source] +type = "git" +url = "https://github.com/stacywsmith/flask-restx.git" +reference = "041b1f074a32891c2359607b349bbc9d1ee4b374" +resolved_reference = "041b1f074a32891c2359607b349bbc9d1ee4b374" + [[package]] name = "flask-sqlalchemy" version = "2.5.1" @@ -273,39 +269,40 @@ SQLAlchemy = ">=0.8.0" [[package]] name = "geoalchemy2" -version = "0.8.5" +version = "0.11.1" description = "Using SQLAlchemy with Spatial Databases" category = "main" optional = false -python-versions = "*" +python-versions = ">=3.6" [package.dependencies] +packaging = "*" SQLAlchemy = ">=1.1" [[package]] name = "gevent" -version = "20.12.1" +version = "21.12.0" description = "Coroutine-based network library" category = "main" optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5" [package.dependencies] cffi = {version = ">=1.12.2", markers = "platform_python_implementation == \"CPython\" and sys_platform == \"win32\""} -greenlet = {version = ">=0.4.17,<2.0", markers = "platform_python_implementation == \"CPython\""} +greenlet = {version = ">=1.1.0,<2.0", markers = "platform_python_implementation == \"CPython\""} "zope.event" = "*" "zope.interface" = "*" [package.extras] dnspython = ["dnspython (>=1.16.0,<2.0)", "idna"] -docs = ["repoze.sphinx.autointerface", "sphinxcontrib-programoutput"] +docs = ["repoze.sphinx.autointerface", "sphinxcontrib-programoutput", "zope.schema"] monitor = ["psutil (>=5.7.0)"] -recommended = ["dnspython (>=1.16.0,<2.0)", "idna", "cffi (>=1.12.2)", "selectors2", "backports.socketpair", "psutil (>=5.7.0)"] -test = ["dnspython (>=1.16.0,<2.0)", "idna", "requests", "objgraph", "cffi (>=1.12.2)", "selectors2", "futures", "mock", "backports.socketpair", "contextvars (==2.4)", "coverage (>=5.0)", "coveralls (>=1.7.0)", "psutil (>=5.7.0)"] +recommended = ["cffi (>=1.12.2)", "dnspython (>=1.16.0,<2.0)", "idna", "selectors2", "backports.socketpair", "psutil (>=5.7.0)"] +test = ["requests", "objgraph", "cffi (>=1.12.2)", "dnspython (>=1.16.0,<2.0)", "idna", "selectors2", "futures", "mock", "backports.socketpair", "contextvars (==2.4)", "coverage (>=5.0)", "coveralls (>=1.7.0)", "psutil (>=5.7.0)"] [[package]] name = "greenlet" -version = "1.1.0" +version = "1.1.2" description = "Lightweight in-process concurrent programming" category = "main" optional = false @@ -330,18 +327,18 @@ tornado = ["tornado (>=0.2)"] [[package]] name = "identify" -version = "2.2.11" +version = "2.4.12" description = "File identification library for Python" category = "dev" optional = false -python-versions = ">=3.6.1" +python-versions = ">=3.7" [package.extras] -license = ["editdistance-s"] +license = ["ukkonen"] [[package]] name = "idna" -version = "3.2" +version = "3.3" description = "Internationalized Domain Names in Applications (IDNA)" category = "main" optional = false @@ -349,35 +346,34 @@ python-versions = ">=3.5" [[package]] name = "importlib-metadata" -version = "4.6.1" +version = "4.11.3" description = "Read metadata from Python packages" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] -typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""} zipp = ">=0.5" [package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] +docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] perf = ["ipython"] -testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"] [[package]] name = "importlib-resources" -version = "5.2.0" +version = "5.6.0" description = "Read resources from Python packages" -category = "dev" +category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} [package.extras] -docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-black (>=0.3.7)", "pytest-mypy"] +docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"] [[package]] name = "iniconfig" @@ -389,66 +385,50 @@ python-versions = "*" [[package]] name = "itsdangerous" -version = "1.1.0" -description = "Various helpers to pass data to untrusted environments and back." +version = "2.1.2" +description = "Safely pass data to untrusted environments and back." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=3.7" [[package]] name = "jinja2" -version = "2.11.3" +version = "3.1.1" description = "A very fast and expressive template engine." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.7" [package.dependencies] -MarkupSafe = ">=0.23" +MarkupSafe = ">=2.0" [package.extras] -i18n = ["Babel (>=0.8)"] +i18n = ["Babel (>=2.7)"] [[package]] name = "jsonschema" -version = "3.2.0" +version = "4.4.0" description = "An implementation of JSON Schema validation for Python" category = "main" optional = false -python-versions = "*" +python-versions = ">=3.7" [package.dependencies] attrs = ">=17.4.0" -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} -pyrsistent = ">=0.14.0" -six = ">=1.11.0" +importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} +pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" [package.extras] -format = ["idna", "jsonpointer (>1.13)", "rfc3987", "strict-rfc3339", "webcolors"] -format_nongpl = ["idna", "jsonpointer (>1.13)", "webcolors", "rfc3986-validator (>0.1.0)", "rfc3339-validator"] - -[[package]] -name = "mako" -version = "1.1.4" -description = "A super-fast templating language that borrows the best ideas from the existing templating languages." -category = "main" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.dependencies] -MarkupSafe = ">=0.9.2" - -[package.extras] -babel = ["babel"] -lingua = ["lingua"] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format_nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] [[package]] name = "markupsafe" -version = "2.0.1" +version = "2.1.1" description = "Safely add untrusted strings to HTML/XML markup." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "nodeenv" @@ -460,22 +440,25 @@ python-versions = "*" [[package]] name = "osmium" -version = "3.1.3" +version = "3.3.0" description = "Python bindings for libosmium, the data processing library for OSM data" category = "main" optional = false -python-versions = ">=3.4" +python-versions = ">=3.5" + +[package.dependencies] +requests = "*" [[package]] name = "packaging" -version = "21.0" +version = "21.3" description = "Core utilities for Python packages" -category = "dev" +category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -pyparsing = ">=2.0.2" +pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" [[package]] name = "passlib" @@ -493,11 +476,11 @@ totp = ["cryptography"] [[package]] name = "platformdirs" -version = "2.1.0" +version = "2.5.1" description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.extras] docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] @@ -505,21 +488,19 @@ test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock [[package]] name = "pluggy" -version = "0.13.1" +version = "1.0.0" description = "plugin and hook calling mechanisms for python" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - -[package.dependencies] -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} +python-versions = ">=3.6" [package.extras] dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" -version = "2.13.0" +version = "2.17.0" description = "A framework for managing and maintaining multi-language pre-commit hooks." category = "dev" optional = false @@ -528,8 +509,6 @@ python-versions = ">=3.6.1" [package.dependencies] cfgv = ">=2.0.0" identify = ">=1.0.0" -importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} -importlib-resources = {version = "*", markers = "python_version < \"3.7\""} nodeenv = ">=0.11.1" pyyaml = ">=5.1" toml = "*" @@ -537,7 +516,7 @@ virtualenv = ">=20.0.8" [[package]] name = "psycopg2-binary" -version = "2.9.1" +version = "2.9.3" description = "psycopg2 - Python-PostgreSQL Database Adapter" category = "main" optional = false @@ -545,15 +524,15 @@ python-versions = ">=3.6" [[package]] name = "py" -version = "1.10.0" +version = "1.11.0" description = "library with cross-python path, ini-parsing, io, code, log facilities" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [[package]] name = "pycparser" -version = "2.20" +version = "2.21" description = "C parser in Python" category = "main" optional = false @@ -561,102 +540,84 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pyparsing" -version = "2.4.7" +version = "3.0.7" description = "Python parsing module" -category = "dev" +category = "main" optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +python-versions = ">=3.6" + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] [[package]] name = "pyproj" -version = "3.0.1" +version = "3.3.0" description = "Python interface to PROJ (cartographic projections and coordinate transformations library)" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" [package.dependencies] certifi = "*" [[package]] name = "pyrsistent" -version = "0.18.0" +version = "0.18.1" description = "Persistent/Functional/Immutable data structures" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [[package]] name = "pytest" -version = "6.2.4" +version = "7.1.1" description = "pytest: simple powerful testing with Python" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} iniconfig = "*" packaging = "*" -pluggy = ">=0.12,<1.0.0a1" +pluggy = ">=0.12,<2.0" py = ">=1.8.2" -toml = "*" +tomli = ">=1.0.0" [package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] +testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] [[package]] name = "pytest-cov" -version = "2.12.1" +version = "3.0.0" description = "Pytest plugin for measuring coverage." category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.6" [package.dependencies] -coverage = ">=5.2.1" +coverage = {version = ">=5.2.1", extras = ["toml"]} pytest = ">=4.6" -toml = "*" [package.extras] testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"] -[[package]] -name = "python-dateutil" -version = "2.8.2" -description = "Extensions to the standard Python datetime module" -category = "main" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" - -[package.dependencies] -six = ">=1.5" - [[package]] name = "python-dotenv" -version = "0.14.0" -description = "Add .env support to your django/flask apps in development and deployments" +version = "0.20.0" +description = "Read key-value pairs from a .env file and set them as environment variables" category = "main" optional = false -python-versions = "*" +python-versions = ">=3.5" [package.extras] cli = ["click (>=5.0)"] -[[package]] -name = "python-editor" -version = "1.0.4" -description = "Programmatically open an editor, capture the result." -category = "main" -optional = false -python-versions = "*" - [[package]] name = "pytz" -version = "2021.1" +version = "2022.1" description = "World timezone definitions, modern and historical" category = "main" optional = false @@ -672,26 +633,32 @@ python-versions = "*" [[package]] name = "pyyaml" -version = "5.4.1" +version = "6.0" description = "YAML parser and emitter for Python" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.6" [[package]] name = "redis" -version = "3.5.3" -description = "Python client for Redis key-value store" +version = "4.2.1" +description = "Python client for Redis database and key-value store" category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.6" + +[package.dependencies] +async-timeout = ">=4.0.2" +deprecated = ">=1.2.3" +packaging = ">=20.4" [package.extras] -hiredis = ["hiredis (>=0.1.3)"] +hiredis = ["hiredis (>=1.0.0)"] +ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"] [[package]] name = "requests" -version = "2.26.0" +version = "2.27.1" description = "Python HTTP for Humans." category = "main" optional = false @@ -709,7 +676,7 @@ use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"] [[package]] name = "rq" -version = "1.9.0" +version = "1.10.1" description = "RQ is a simple, lightweight, library for creating background jobs, and processing them." category = "main" optional = false @@ -721,14 +688,14 @@ redis = ">=3.5.0" [[package]] name = "shapely" -version = "1.7.1" +version = "1.8.1.post1" description = "Geometric objects, predicates, and operations" category = "main" optional = false -python-versions = "*" +python-versions = ">=3.6" [package.extras] -all = ["numpy", "pytest", "pytest-cov"] +all = ["pytest", "pytest-cov", "numpy"] test = ["pytest", "pytest-cov"] vectorized = ["numpy"] @@ -742,38 +709,49 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "sqlalchemy" -version = "1.3.24" +version = "1.4.34" description = "Database Abstraction Library" category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" + +[package.dependencies] +greenlet = {version = "!=0.4.17", markers = "python_version >= \"3\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\")"} [package.extras] +aiomysql = ["greenlet (!=0.4.17)", "aiomysql"] +aiosqlite = ["typing_extensions (!=3.10.0.1)", "greenlet (!=0.4.17)", "aiosqlite"] +asyncio = ["greenlet (!=0.4.17)"] +asyncmy = ["greenlet (!=0.4.17)", "asyncmy (>=0.2.3,!=0.2.4)"] +mariadb_connector = ["mariadb (>=1.0.1)"] mssql = ["pyodbc"] mssql_pymssql = ["pymssql"] mssql_pyodbc = ["pyodbc"] -mysql = ["mysqlclient"] -oracle = ["cx-oracle"] -postgresql = ["psycopg2"] -postgresql_pg8000 = ["pg8000 (<1.16.6)"] +mypy = ["sqlalchemy2-stubs", "mypy (>=0.910)"] +mysql = ["mysqlclient (>=1.4.0,<2)", "mysqlclient (>=1.4.0)"] +mysql_connector = ["mysql-connector-python"] +oracle = ["cx_oracle (>=7,<8)", "cx_oracle (>=7)"] +postgresql = ["psycopg2 (>=2.7)"] +postgresql_asyncpg = ["greenlet (!=0.4.17)", "asyncpg"] +postgresql_pg8000 = ["pg8000 (>=1.16.6)"] postgresql_psycopg2binary = ["psycopg2-binary"] postgresql_psycopg2cffi = ["psycopg2cffi"] pymysql = ["pymysql (<1)", "pymysql"] +sqlcipher = ["sqlcipher3-binary"] [[package]] name = "sqlalchemy-utils" -version = "0.36.8" +version = "0.38.2" description = "Various utility functions for SQLAlchemy." category = "main" optional = false -python-versions = "*" +python-versions = "~=3.4" [package.dependencies] six = "*" SQLAlchemy = ">=1.0" [package.extras] -anyjson = ["anyjson (>=0.3.3)"] arrow = ["arrow (>=0.3.4)"] babel = ["Babel (>=1.3)"] color = ["colour (>=0.0.4)"] @@ -782,8 +760,8 @@ intervals = ["intervals (>=0.7.1)"] password = ["passlib (>=1.6,<2.0)"] pendulum = ["pendulum (>=2.0.5)"] phone = ["phonenumbers (>=5.9.2)"] -test = ["pytest (>=2.7.1)", "Pygments (>=1.2)", "Jinja2 (>=2.3)", "docutils (>=0.10)", "flexmock (>=0.9.7)", "mock (==2.0.0)", "psycopg2 (>=2.5.1)", "psycopg2cffi (>=2.8.1)", "pg8000 (>=1.12.4)", "pytz (>=2014.2)", "python-dateutil (>=2.6)", "pymysql", "flake8 (>=2.4.0)", "isort (>=4.2.2)", "pyodbc"] -test_all = ["anyjson (>=0.3.3)", "arrow (>=0.3.4)", "Babel (>=1.3)", "colour (>=0.0.4)", "cryptography (>=0.6)", "intervals (>=0.7.1)", "passlib (>=1.6,<2.0)", "pendulum (>=2.0.5)", "phonenumbers (>=5.9.2)", "pytest (>=2.7.1)", "Pygments (>=1.2)", "Jinja2 (>=2.3)", "docutils (>=0.10)", "flexmock (>=0.9.7)", "mock (==2.0.0)", "psycopg2 (>=2.5.1)", "psycopg2cffi (>=2.8.1)", "pg8000 (>=1.12.4)", "pytz (>=2014.2)", "python-dateutil (>=2.6)", "pymysql", "flake8 (>=2.4.0)", "isort (>=4.2.2)", "pyodbc", "python-dateutil", "furl (>=0.4.1)"] +test = ["pytest (>=2.7.1)", "Pygments (>=1.2)", "Jinja2 (>=2.3)", "docutils (>=0.10)", "flexmock (>=0.9.7)", "mock (==2.0.0)", "psycopg2 (>=2.5.1)", "psycopg2cffi (>=2.8.1)", "pg8000 (>=1.12.4)", "pytz (>=2014.2)", "python-dateutil (>=2.6)", "pymysql", "flake8 (>=2.4.0)", "isort (>=4.2.2)", "pyodbc", "backports.zoneinfo"] +test_all = ["Babel (>=1.3)", "Jinja2 (>=2.3)", "Pygments (>=1.2)", "arrow (>=0.3.4)", "colour (>=0.0.4)", "cryptography (>=0.6)", "docutils (>=0.10)", "flake8 (>=2.4.0)", "flexmock (>=0.9.7)", "furl (>=0.4.1)", "intervals (>=0.7.1)", "isort (>=4.2.2)", "mock (==2.0.0)", "passlib (>=1.6,<2.0)", "pendulum (>=2.0.5)", "pg8000 (>=1.12.4)", "phonenumbers (>=5.9.2)", "psycopg2 (>=2.5.1)", "psycopg2cffi (>=2.8.1)", "pymysql", "pyodbc", "pytest (>=2.7.1)", "python-dateutil", "python-dateutil (>=2.6)", "pytz (>=2014.2)", "backports.zoneinfo"] timezone = ["python-dateutil"] url = ["furl (>=0.4.1)"] @@ -796,86 +774,87 @@ optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] -name = "typing-extensions" -version = "3.10.0.0" -description = "Backported and Experimental Type Hints for Python 3.5+" -category = "main" +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.7" [[package]] name = "urllib3" -version = "1.26.6" +version = "1.26.9" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" [package.extras] -brotli = ["brotlipy (>=0.6.0)"] +brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "virtualenv" -version = "20.6.0" +version = "20.14.0" description = "Virtual Python Environment builder" category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [package.dependencies] -"backports.entry-points-selectable" = ">=1.0.4" distlib = ">=0.3.1,<1" -filelock = ">=3.0.0,<4" -importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} -importlib-resources = {version = ">=1.0", markers = "python_version < \"3.7\""} +filelock = ">=3.2,<4" platformdirs = ">=2,<3" six = ">=1.9.0,<2" [package.extras] -docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=19.9.0rc1)"] -testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)", "xonsh (>=0.9.16)"] +docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"] +testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"] [[package]] name = "websocket-client" -version = "1.1.0" +version = "1.3.2" description = "WebSocket client for Python with low level API options" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" + +[package.extras] +docs = ["Sphinx (>=3.4)", "sphinx-rtd-theme (>=0.5)"] +optional = ["python-socks", "wsaccel"] +test = ["websockets"] [[package]] name = "werkzeug" -version = "1.0.1" +version = "2.1.0" description = "The comprehensive WSGI web application library." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.7" [package.extras] -dev = ["pytest", "pytest-timeout", "coverage", "tox", "sphinx", "pallets-sphinx-themes", "sphinx-issues"] watchdog = ["watchdog"] [[package]] -name = "yapf" -version = "0.30.0" -description = "A formatter for Python code." -category = "dev" +name = "wrapt" +version = "1.14.0" +description = "Module for decorators, wrappers and monkey patching." +category = "main" optional = false -python-versions = "*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [[package]] name = "zipp" -version = "3.5.0" +version = "3.7.0" description = "Backport of pathlib-compatible object wrapper for zip files" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.extras] docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"] -testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] +testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] [[package]] name = "zope.event" @@ -904,510 +883,528 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] [metadata] lock-version = "1.1" -python-versions = "^3.6.1" -content-hash = "1c7957c682d518c69301ee435b9c1109cd4605e0e50d69e9e49ee0f136bb4f24" +python-versions = "^3.8" +content-hash = "79d860c6e060de9d14e83233f85ac81a7c757528c61c0f99c3baa290123ce18e" [metadata.files] -alembic = [ - {file = "alembic-1.6.5-py2.py3-none-any.whl", hash = "sha256:e78be5b919f5bb184e3e0e2dd1ca986f2362e29a2bc933c446fe89f39dbe4e9c"}, - {file = "alembic-1.6.5.tar.gz", hash = "sha256:a21fedebb3fb8f6bbbba51a11114f08c78709377051384c9c5ead5705ee93a51"}, -] aniso8601 = [ {file = "aniso8601-9.0.1-py2.py3-none-any.whl", hash = "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f"}, {file = "aniso8601-9.0.1.tar.gz", hash = "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973"}, ] +async-timeout = [ + {file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"}, + {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"}, +] atomicwrites = [ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, ] attrs = [ - {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, - {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, -] -"backports.entry-points-selectable" = [ - {file = "backports.entry_points_selectable-1.1.0-py2.py3-none-any.whl", hash = "sha256:a6d9a871cde5e15b4c4a53e3d43ba890cc6861ec1332c9c2428c92f977192acc"}, - {file = "backports.entry_points_selectable-1.1.0.tar.gz", hash = "sha256:988468260ec1c196dab6ae1149260e2f5472c9110334e5d51adcb77867361f6a"}, + {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, + {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, ] certifi = [ - {file = "certifi-2021.5.30-py2.py3-none-any.whl", hash = "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"}, - {file = "certifi-2021.5.30.tar.gz", hash = "sha256:2bbf76fd432960138b3ef6dda3dde0544f27cbf8546c458e60baf371917ba9ee"}, + {file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"}, + {file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"}, ] cffi = [ - {file = "cffi-1.14.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:22b9c3c320171c108e903d61a3723b51e37aaa8c81255b5e7ce102775bd01e2c"}, - {file = "cffi-1.14.6-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:f0c5d1acbfca6ebdd6b1e3eded8d261affb6ddcf2186205518f1428b8569bb99"}, - {file = "cffi-1.14.6-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:99f27fefe34c37ba9875f224a8f36e31d744d8083e00f520f133cab79ad5e819"}, - {file = "cffi-1.14.6-cp27-cp27m-win32.whl", hash = "sha256:55af55e32ae468e9946f741a5d51f9896da6b9bf0bbdd326843fec05c730eb20"}, - {file = "cffi-1.14.6-cp27-cp27m-win_amd64.whl", hash = "sha256:7bcac9a2b4fdbed2c16fa5681356d7121ecabf041f18d97ed5b8e0dd38a80224"}, - {file = "cffi-1.14.6-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:ed38b924ce794e505647f7c331b22a693bee1538fdf46b0222c4717b42f744e7"}, - {file = "cffi-1.14.6-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e22dcb48709fc51a7b58a927391b23ab37eb3737a98ac4338e2448bef8559b33"}, - {file = "cffi-1.14.6-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:aedb15f0a5a5949ecb129a82b72b19df97bbbca024081ed2ef88bd5c0a610534"}, - {file = "cffi-1.14.6-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:48916e459c54c4a70e52745639f1db524542140433599e13911b2f329834276a"}, - {file = "cffi-1.14.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f627688813d0a4140153ff532537fbe4afea5a3dffce1f9deb7f91f848a832b5"}, - {file = "cffi-1.14.6-cp35-cp35m-win32.whl", hash = "sha256:f0010c6f9d1a4011e429109fda55a225921e3206e7f62a0c22a35344bfd13cca"}, - {file = "cffi-1.14.6-cp35-cp35m-win_amd64.whl", hash = "sha256:57e555a9feb4a8460415f1aac331a2dc833b1115284f7ded7278b54afc5bd218"}, - {file = "cffi-1.14.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e8c6a99be100371dbb046880e7a282152aa5d6127ae01783e37662ef73850d8f"}, - {file = "cffi-1.14.6-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:19ca0dbdeda3b2615421d54bef8985f72af6e0c47082a8d26122adac81a95872"}, - {file = "cffi-1.14.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d950695ae4381ecd856bcaf2b1e866720e4ab9a1498cba61c602e56630ca7195"}, - {file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9dc245e3ac69c92ee4c167fbdd7428ec1956d4e754223124991ef29eb57a09d"}, - {file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a8661b2ce9694ca01c529bfa204dbb144b275a31685a075ce123f12331be790b"}, - {file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b315d709717a99f4b27b59b021e6207c64620790ca3e0bde636a6c7f14618abb"}, - {file = "cffi-1.14.6-cp36-cp36m-win32.whl", hash = "sha256:80b06212075346b5546b0417b9f2bf467fea3bfe7352f781ffc05a8ab24ba14a"}, - {file = "cffi-1.14.6-cp36-cp36m-win_amd64.whl", hash = "sha256:a9da7010cec5a12193d1af9872a00888f396aba3dc79186604a09ea3ee7c029e"}, - {file = "cffi-1.14.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4373612d59c404baeb7cbd788a18b2b2a8331abcc84c3ba40051fcd18b17a4d5"}, - {file = "cffi-1.14.6-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f10afb1004f102c7868ebfe91c28f4a712227fe4cb24974350ace1f90e1febbf"}, - {file = "cffi-1.14.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fd4305f86f53dfd8cd3522269ed7fc34856a8ee3709a5e28b2836b2db9d4cd69"}, - {file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d6169cb3c6c2ad50db5b868db6491a790300ade1ed5d1da29289d73bbe40b56"}, - {file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d4b68e216fc65e9fe4f524c177b54964af043dde734807586cf5435af84045c"}, - {file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33791e8a2dc2953f28b8d8d300dde42dd929ac28f974c4b4c6272cb2955cb762"}, - {file = "cffi-1.14.6-cp37-cp37m-win32.whl", hash = "sha256:0c0591bee64e438883b0c92a7bed78f6290d40bf02e54c5bf0978eaf36061771"}, - {file = "cffi-1.14.6-cp37-cp37m-win_amd64.whl", hash = "sha256:8eb687582ed7cd8c4bdbff3df6c0da443eb89c3c72e6e5dcdd9c81729712791a"}, - {file = "cffi-1.14.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba6f2b3f452e150945d58f4badd92310449876c4c954836cfb1803bdd7b422f0"}, - {file = "cffi-1.14.6-cp38-cp38-manylinux1_i686.whl", hash = "sha256:64fda793737bc4037521d4899be780534b9aea552eb673b9833b01f945904c2e"}, - {file = "cffi-1.14.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:9f3e33c28cd39d1b655ed1ba7247133b6f7fc16fa16887b120c0c670e35ce346"}, - {file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26bb2549b72708c833f5abe62b756176022a7b9a7f689b571e74c8478ead51dc"}, - {file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb687a11f0a7a1839719edd80f41e459cc5366857ecbed383ff376c4e3cc6afd"}, - {file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2ad4d668a5c0645d281dcd17aff2be3212bc109b33814bbb15c4939f44181cc"}, - {file = "cffi-1.14.6-cp38-cp38-win32.whl", hash = "sha256:487d63e1454627c8e47dd230025780e91869cfba4c753a74fda196a1f6ad6548"}, - {file = "cffi-1.14.6-cp38-cp38-win_amd64.whl", hash = "sha256:c33d18eb6e6bc36f09d793c0dc58b0211fccc6ae5149b808da4a62660678b156"}, - {file = "cffi-1.14.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:06c54a68935738d206570b20da5ef2b6b6d92b38ef3ec45c5422c0ebaf338d4d"}, - {file = "cffi-1.14.6-cp39-cp39-manylinux1_i686.whl", hash = "sha256:f174135f5609428cc6e1b9090f9268f5c8935fddb1b25ccb8255a2d50de6789e"}, - {file = "cffi-1.14.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f3ebe6e73c319340830a9b2825d32eb6d8475c1dac020b4f0aa774ee3b898d1c"}, - {file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c8d896becff2fa653dc4438b54a5a25a971d1f4110b32bd3068db3722c80202"}, - {file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4922cd707b25e623b902c86188aca466d3620892db76c0bdd7b99a3d5e61d35f"}, - {file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c9e005e9bd57bc987764c32a1bee4364c44fdc11a3cc20a40b93b444984f2b87"}, - {file = "cffi-1.14.6-cp39-cp39-win32.whl", hash = "sha256:eb9e2a346c5238a30a746893f23a9535e700f8192a68c07c0258e7ece6ff3728"}, - {file = "cffi-1.14.6-cp39-cp39-win_amd64.whl", hash = "sha256:818014c754cd3dba7229c0f5884396264d51ffb87ec86e927ef0be140bfdb0d2"}, - {file = "cffi-1.14.6.tar.gz", hash = "sha256:c9a875ce9d7fe32887784274dd533c57909b7b1dcadcc128a2ac21331a9765dd"}, + {file = "cffi-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962"}, + {file = "cffi-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:23cfe892bd5dd8941608f93348c0737e369e51c100d03718f108bf1add7bd6d0"}, + {file = "cffi-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:41d45de54cd277a7878919867c0f08b0cf817605e4eb94093e7516505d3c8d14"}, + {file = "cffi-1.15.0-cp27-cp27m-win32.whl", hash = "sha256:4a306fa632e8f0928956a41fa8e1d6243c71e7eb59ffbd165fc0b41e316b2474"}, + {file = "cffi-1.15.0-cp27-cp27m-win_amd64.whl", hash = "sha256:e7022a66d9b55e93e1a845d8c9eba2a1bebd4966cd8bfc25d9cd07d515b33fa6"}, + {file = "cffi-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:14cd121ea63ecdae71efa69c15c5543a4b5fbcd0bbe2aad864baca0063cecf27"}, + {file = "cffi-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d4d692a89c5cf08a8557fdeb329b82e7bf609aadfaed6c0d79f5a449a3c7c023"}, + {file = "cffi-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2"}, + {file = "cffi-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:91ec59c33514b7c7559a6acda53bbfe1b283949c34fe7440bcf917f96ac0723e"}, + {file = "cffi-1.15.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f5c7150ad32ba43a07c4479f40241756145a1f03b43480e058cfd862bf5041c7"}, + {file = "cffi-1.15.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3"}, + {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abb9a20a72ac4e0fdb50dae135ba5e77880518e742077ced47eb1499e29a443c"}, + {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a5263e363c27b653a90078143adb3d076c1a748ec9ecc78ea2fb916f9b861962"}, + {file = "cffi-1.15.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f54a64f8b0c8ff0b64d18aa76675262e1700f3995182267998c31ae974fbc382"}, + {file = "cffi-1.15.0-cp310-cp310-win32.whl", hash = "sha256:c21c9e3896c23007803a875460fb786118f0cdd4434359577ea25eb556e34c55"}, + {file = "cffi-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0"}, + {file = "cffi-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:64d4ec9f448dfe041705426000cc13e34e6e5bb13736e9fd62e34a0b0c41566e"}, + {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2756c88cbb94231c7a147402476be2c4df2f6078099a6f4a480d239a8817ae39"}, + {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b96a311ac60a3f6be21d2572e46ce67f09abcf4d09344c49274eb9e0bf345fc"}, + {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75e4024375654472cc27e91cbe9eaa08567f7fbdf822638be2814ce059f58032"}, + {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:59888172256cac5629e60e72e86598027aca6bf01fa2465bdb676d37636573e8"}, + {file = "cffi-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:27c219baf94952ae9d50ec19651a687b826792055353d07648a5695413e0c605"}, + {file = "cffi-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:4958391dbd6249d7ad855b9ca88fae690783a6be9e86df65865058ed81fc860e"}, + {file = "cffi-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:f6f824dc3bce0edab5f427efcfb1d63ee75b6fcb7282900ccaf925be84efb0fc"}, + {file = "cffi-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:06c48159c1abed75c2e721b1715c379fa3200c7784271b3c46df01383b593636"}, + {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c2051981a968d7de9dd2d7b87bcb9c939c74a34626a6e2f8181455dd49ed69e4"}, + {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:fd8a250edc26254fe5b33be00402e6d287f562b6a5b2152dec302fa15bb3e997"}, + {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91d77d2a782be4274da750752bb1650a97bfd8f291022b379bb8e01c66b4e96b"}, + {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:45db3a33139e9c8f7c09234b5784a5e33d31fd6907800b316decad50af323ff2"}, + {file = "cffi-1.15.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:263cc3d821c4ab2213cbe8cd8b355a7f72a8324577dc865ef98487c1aeee2bc7"}, + {file = "cffi-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:17771976e82e9f94976180f76468546834d22a7cc404b17c22df2a2c81db0c66"}, + {file = "cffi-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:3415c89f9204ee60cd09b235810be700e993e343a408693e80ce7f6a40108029"}, + {file = "cffi-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4238e6dab5d6a8ba812de994bbb0a79bddbdf80994e4ce802b6f6f3142fcc880"}, + {file = "cffi-1.15.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0808014eb713677ec1292301ea4c81ad277b6cdf2fdd90fd540af98c0b101d20"}, + {file = "cffi-1.15.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:57e9ac9ccc3101fac9d6014fba037473e4358ef4e89f8e181f8951a2c0162024"}, + {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b6c2ea03845c9f501ed1313e78de148cd3f6cad741a75d43a29b43da27f2e1e"}, + {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10dffb601ccfb65262a27233ac273d552ddc4d8ae1bf93b21c94b8511bffe728"}, + {file = "cffi-1.15.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:786902fb9ba7433aae840e0ed609f45c7bcd4e225ebb9c753aa39725bb3e6ad6"}, + {file = "cffi-1.15.0-cp38-cp38-win32.whl", hash = "sha256:da5db4e883f1ce37f55c667e5c0de439df76ac4cb55964655906306918e7363c"}, + {file = "cffi-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:181dee03b1170ff1969489acf1c26533710231c58f95534e3edac87fff06c443"}, + {file = "cffi-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a"}, + {file = "cffi-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37"}, + {file = "cffi-1.15.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a"}, + {file = "cffi-1.15.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e"}, + {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796"}, + {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df"}, + {file = "cffi-1.15.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8"}, + {file = "cffi-1.15.0-cp39-cp39-win32.whl", hash = "sha256:2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a"}, + {file = "cffi-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139"}, + {file = "cffi-1.15.0.tar.gz", hash = "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954"}, ] cfgv = [ - {file = "cfgv-3.3.0-py2.py3-none-any.whl", hash = "sha256:b449c9c6118fe8cca7fa5e00b9ec60ba08145d281d52164230a69211c5d597a1"}, - {file = "cfgv-3.3.0.tar.gz", hash = "sha256:9e600479b3b99e8af981ecdfc80a0296104ee610cab48a5ae4ffd0b668650eb1"}, + {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"}, + {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"}, ] charset-normalizer = [ - {file = "charset-normalizer-2.0.3.tar.gz", hash = "sha256:c46c3ace2d744cfbdebceaa3c19ae691f53ae621b39fd7570f59d14fb7f2fd12"}, - {file = "charset_normalizer-2.0.3-py3-none-any.whl", hash = "sha256:88fce3fa5b1a84fdcb3f603d889f723d1dd89b26059d0123ca435570e848d5e1"}, + {file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"}, + {file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"}, ] click = [ - {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, - {file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"}, + {file = "click-8.1.2-py3-none-any.whl", hash = "sha256:24e1a4a9ec5bf6299411369b208c1df2188d9eb8d916302fe6bf03faed227f1e"}, + {file = "click-8.1.2.tar.gz", hash = "sha256:479707fe14d9ec9a0757618b7a100a0ae4c4e236fac5b7f80ca68028141a1a72"}, ] colorama = [ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, ] coverage = [ - {file = "coverage-5.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf"}, - {file = "coverage-5.5-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:b7895207b4c843c76a25ab8c1e866261bcfe27bfaa20c192de5190121770672b"}, - {file = "coverage-5.5-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:c2723d347ab06e7ddad1a58b2a821218239249a9e4365eaff6649d31180c1669"}, - {file = "coverage-5.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:900fbf7759501bc7807fd6638c947d7a831fc9fdf742dc10f02956ff7220fa90"}, - {file = "coverage-5.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:004d1880bed2d97151facef49f08e255a20ceb6f9432df75f4eef018fdd5a78c"}, - {file = "coverage-5.5-cp27-cp27m-win32.whl", hash = "sha256:06191eb60f8d8a5bc046f3799f8a07a2d7aefb9504b0209aff0b47298333302a"}, - {file = "coverage-5.5-cp27-cp27m-win_amd64.whl", hash = "sha256:7501140f755b725495941b43347ba8a2777407fc7f250d4f5a7d2a1050ba8e82"}, - {file = "coverage-5.5-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:372da284cfd642d8e08ef606917846fa2ee350f64994bebfbd3afb0040436905"}, - {file = "coverage-5.5-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:8963a499849a1fc54b35b1c9f162f4108017b2e6db2c46c1bed93a72262ed083"}, - {file = "coverage-5.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:869a64f53488f40fa5b5b9dcb9e9b2962a66a87dab37790f3fcfb5144b996ef5"}, - {file = "coverage-5.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:4a7697d8cb0f27399b0e393c0b90f0f1e40c82023ea4d45d22bce7032a5d7b81"}, - {file = "coverage-5.5-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:8d0a0725ad7c1a0bcd8d1b437e191107d457e2ec1084b9f190630a4fb1af78e6"}, - {file = "coverage-5.5-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:51cb9476a3987c8967ebab3f0fe144819781fca264f57f89760037a2ea191cb0"}, - {file = "coverage-5.5-cp310-cp310-win_amd64.whl", hash = "sha256:c0891a6a97b09c1f3e073a890514d5012eb256845c451bd48f7968ef939bf4ae"}, - {file = "coverage-5.5-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:3487286bc29a5aa4b93a072e9592f22254291ce96a9fbc5251f566b6b7343cdb"}, - {file = "coverage-5.5-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:deee1077aae10d8fa88cb02c845cfba9b62c55e1183f52f6ae6a2df6a2187160"}, - {file = "coverage-5.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f11642dddbb0253cc8853254301b51390ba0081750a8ac03f20ea8103f0c56b6"}, - {file = "coverage-5.5-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:6c90e11318f0d3c436a42409f2749ee1a115cd8b067d7f14c148f1ce5574d701"}, - {file = "coverage-5.5-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:30c77c1dc9f253283e34c27935fded5015f7d1abe83bc7821680ac444eaf7793"}, - {file = "coverage-5.5-cp35-cp35m-win32.whl", hash = "sha256:9a1ef3b66e38ef8618ce5fdc7bea3d9f45f3624e2a66295eea5e57966c85909e"}, - {file = "coverage-5.5-cp35-cp35m-win_amd64.whl", hash = "sha256:972c85d205b51e30e59525694670de6a8a89691186012535f9d7dbaa230e42c3"}, - {file = "coverage-5.5-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:af0e781009aaf59e25c5a678122391cb0f345ac0ec272c7961dc5455e1c40066"}, - {file = "coverage-5.5-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:74d881fc777ebb11c63736622b60cb9e4aee5cace591ce274fb69e582a12a61a"}, - {file = "coverage-5.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:92b017ce34b68a7d67bd6d117e6d443a9bf63a2ecf8567bb3d8c6c7bc5014465"}, - {file = "coverage-5.5-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:d636598c8305e1f90b439dbf4f66437de4a5e3c31fdf47ad29542478c8508bbb"}, - {file = "coverage-5.5-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:41179b8a845742d1eb60449bdb2992196e211341818565abded11cfa90efb821"}, - {file = "coverage-5.5-cp36-cp36m-win32.whl", hash = "sha256:040af6c32813fa3eae5305d53f18875bedd079960822ef8ec067a66dd8afcd45"}, - {file = "coverage-5.5-cp36-cp36m-win_amd64.whl", hash = "sha256:5fec2d43a2cc6965edc0bb9e83e1e4b557f76f843a77a2496cbe719583ce8184"}, - {file = "coverage-5.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:18ba8bbede96a2c3dde7b868de9dcbd55670690af0988713f0603f037848418a"}, - {file = "coverage-5.5-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:2910f4d36a6a9b4214bb7038d537f015346f413a975d57ca6b43bf23d6563b53"}, - {file = "coverage-5.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:f0b278ce10936db1a37e6954e15a3730bea96a0997c26d7fee88e6c396c2086d"}, - {file = "coverage-5.5-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:796c9c3c79747146ebd278dbe1e5c5c05dd6b10cc3bcb8389dfdf844f3ead638"}, - {file = "coverage-5.5-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:53194af30d5bad77fcba80e23a1441c71abfb3e01192034f8246e0d8f99528f3"}, - {file = "coverage-5.5-cp37-cp37m-win32.whl", hash = "sha256:184a47bbe0aa6400ed2d41d8e9ed868b8205046518c52464fde713ea06e3a74a"}, - {file = "coverage-5.5-cp37-cp37m-win_amd64.whl", hash = "sha256:2949cad1c5208b8298d5686d5a85b66aae46d73eec2c3e08c817dd3513e5848a"}, - {file = "coverage-5.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:217658ec7187497e3f3ebd901afdca1af062b42cfe3e0dafea4cced3983739f6"}, - {file = "coverage-5.5-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1aa846f56c3d49205c952d8318e76ccc2ae23303351d9270ab220004c580cfe2"}, - {file = "coverage-5.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:24d4a7de75446be83244eabbff746d66b9240ae020ced65d060815fac3423759"}, - {file = "coverage-5.5-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d1f8bf7b90ba55699b3a5e44930e93ff0189aa27186e96071fac7dd0d06a1873"}, - {file = "coverage-5.5-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:970284a88b99673ccb2e4e334cfb38a10aab7cd44f7457564d11898a74b62d0a"}, - {file = "coverage-5.5-cp38-cp38-win32.whl", hash = "sha256:01d84219b5cdbfc8122223b39a954820929497a1cb1422824bb86b07b74594b6"}, - {file = "coverage-5.5-cp38-cp38-win_amd64.whl", hash = "sha256:2e0d881ad471768bf6e6c2bf905d183543f10098e3b3640fc029509530091502"}, - {file = "coverage-5.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d1f9ce122f83b2305592c11d64f181b87153fc2c2bbd3bb4a3dde8303cfb1a6b"}, - {file = "coverage-5.5-cp39-cp39-manylinux1_i686.whl", hash = "sha256:13c4ee887eca0f4c5a247b75398d4114c37882658300e153113dafb1d76de529"}, - {file = "coverage-5.5-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:52596d3d0e8bdf3af43db3e9ba8dcdaac724ba7b5ca3f6358529d56f7a166f8b"}, - {file = "coverage-5.5-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:2cafbbb3af0733db200c9b5f798d18953b1a304d3f86a938367de1567f4b5bff"}, - {file = "coverage-5.5-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:44d654437b8ddd9eee7d1eaee28b7219bec228520ff809af170488fd2fed3e2b"}, - {file = "coverage-5.5-cp39-cp39-win32.whl", hash = "sha256:d314ed732c25d29775e84a960c3c60808b682c08d86602ec2c3008e1202e3bb6"}, - {file = "coverage-5.5-cp39-cp39-win_amd64.whl", hash = "sha256:13034c4409db851670bc9acd836243aeee299949bd5673e11844befcb0149f03"}, - {file = "coverage-5.5-pp36-none-any.whl", hash = "sha256:f030f8873312a16414c0d8e1a1ddff2d3235655a2174e3648b4fa66b3f2f1079"}, - {file = "coverage-5.5-pp37-none-any.whl", hash = "sha256:2a3859cb82dcbda1cfd3e6f71c27081d18aa251d20a17d87d26d4cd216fb0af4"}, - {file = "coverage-5.5.tar.gz", hash = "sha256:ebe78fe9a0e874362175b02371bdfbee64d8edc42a044253ddf4ee7d3c15212c"}, + {file = "coverage-6.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9b27d894748475fa858f9597c0ee1d4829f44683f3813633aaf94b19cb5453cf"}, + {file = "coverage-6.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37d1141ad6b2466a7b53a22e08fe76994c2d35a5b6b469590424a9953155afac"}, + {file = "coverage-6.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9987b0354b06d4df0f4d3e0ec1ae76d7ce7cbca9a2f98c25041eb79eec766f1"}, + {file = "coverage-6.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:26e2deacd414fc2f97dd9f7676ee3eaecd299ca751412d89f40bc01557a6b1b4"}, + {file = "coverage-6.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4dd8bafa458b5c7d061540f1ee9f18025a68e2d8471b3e858a9dad47c8d41903"}, + {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:46191097ebc381fbf89bdce207a6c107ac4ec0890d8d20f3360345ff5976155c"}, + {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6f89d05e028d274ce4fa1a86887b071ae1755082ef94a6740238cd7a8178804f"}, + {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:58303469e9a272b4abdb9e302a780072c0633cdcc0165db7eec0f9e32f901e05"}, + {file = "coverage-6.3.2-cp310-cp310-win32.whl", hash = "sha256:2fea046bfb455510e05be95e879f0e768d45c10c11509e20e06d8fcaa31d9e39"}, + {file = "coverage-6.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:a2a8b8bcc399edb4347a5ca8b9b87e7524c0967b335fbb08a83c8421489ddee1"}, + {file = "coverage-6.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f1555ea6d6da108e1999b2463ea1003fe03f29213e459145e70edbaf3e004aaa"}, + {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5f4e1edcf57ce94e5475fe09e5afa3e3145081318e5fd1a43a6b4539a97e518"}, + {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a15dc0a14008f1da3d1ebd44bdda3e357dbabdf5a0b5034d38fcde0b5c234b7"}, + {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21b7745788866028adeb1e0eca3bf1101109e2dc58456cb49d2d9b99a8c516e6"}, + {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8ce257cac556cb03be4a248d92ed36904a59a4a5ff55a994e92214cde15c5bad"}, + {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b0be84e5a6209858a1d3e8d1806c46214e867ce1b0fd32e4ea03f4bd8b2e3359"}, + {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:acf53bc2cf7282ab9b8ba346746afe703474004d9e566ad164c91a7a59f188a4"}, + {file = "coverage-6.3.2-cp37-cp37m-win32.whl", hash = "sha256:8bdde1177f2311ee552f47ae6e5aa7750c0e3291ca6b75f71f7ffe1f1dab3dca"}, + {file = "coverage-6.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b31651d018b23ec463e95cf10070d0b2c548aa950a03d0b559eaa11c7e5a6fa3"}, + {file = "coverage-6.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:07e6db90cd9686c767dcc593dff16c8c09f9814f5e9c51034066cad3373b914d"}, + {file = "coverage-6.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c6dbb42f3ad25760010c45191e9757e7dce981cbfb90e42feef301d71540059"}, + {file = "coverage-6.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c76aeef1b95aff3905fb2ae2d96e319caca5b76fa41d3470b19d4e4a3a313512"}, + {file = "coverage-6.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cf5cfcb1521dc3255d845d9dca3ff204b3229401994ef8d1984b32746bb45ca"}, + {file = "coverage-6.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fbbdc8d55990eac1b0919ca69eb5a988a802b854488c34b8f37f3e2025fa90d"}, + {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ec6bc7fe73a938933d4178c9b23c4e0568e43e220aef9472c4f6044bfc6dd0f0"}, + {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:9baff2a45ae1f17c8078452e9e5962e518eab705e50a0aa8083733ea7d45f3a6"}, + {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd9e830e9d8d89b20ab1e5af09b32d33e1a08ef4c4e14411e559556fd788e6b2"}, + {file = "coverage-6.3.2-cp38-cp38-win32.whl", hash = "sha256:f7331dbf301b7289013175087636bbaf5b2405e57259dd2c42fdcc9fcc47325e"}, + {file = "coverage-6.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:68353fe7cdf91f109fc7d474461b46e7f1f14e533e911a2a2cbb8b0fc8613cf1"}, + {file = "coverage-6.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b78e5afb39941572209f71866aa0b206c12f0109835aa0d601e41552f9b3e620"}, + {file = "coverage-6.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4e21876082ed887baed0146fe222f861b5815455ada3b33b890f4105d806128d"}, + {file = "coverage-6.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34626a7eee2a3da12af0507780bb51eb52dca0e1751fd1471d0810539cefb536"}, + {file = "coverage-6.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ebf730d2381158ecf3dfd4453fbca0613e16eaa547b4170e2450c9707665ce7"}, + {file = "coverage-6.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd6fe30bd519694b356cbfcaca9bd5c1737cddd20778c6a581ae20dc8c04def2"}, + {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:96f8a1cb43ca1422f36492bebe63312d396491a9165ed3b9231e778d43a7fca4"}, + {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:dd035edafefee4d573140a76fdc785dc38829fe5a455c4bb12bac8c20cfc3d69"}, + {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5ca5aeb4344b30d0bec47481536b8ba1181d50dbe783b0e4ad03c95dc1296684"}, + {file = "coverage-6.3.2-cp39-cp39-win32.whl", hash = "sha256:f5fa5803f47e095d7ad8443d28b01d48c0359484fec1b9d8606d0e3282084bc4"}, + {file = "coverage-6.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:9548f10d8be799551eb3a9c74bbf2b4934ddb330e08a73320123c07f95cc2d92"}, + {file = "coverage-6.3.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:18d520c6860515a771708937d2f78f63cc47ab3b80cb78e86573b0a760161faf"}, + {file = "coverage-6.3.2.tar.gz", hash = "sha256:03e2a7826086b91ef345ff18742ee9fc47a6839ccd517061ef8fa1976e652ce9"}, ] coveralls = [ - {file = "coveralls-2.2.0-py2.py3-none-any.whl", hash = "sha256:2301a19500b06649d2ec4f2858f9c69638d7699a4c63027c5d53daba666147cc"}, - {file = "coveralls-2.2.0.tar.gz", hash = "sha256:b990ba1f7bc4288e63340be0433698c1efe8217f78c689d254c2540af3d38617"}, + {file = "coveralls-3.3.1-py2.py3-none-any.whl", hash = "sha256:f42015f31d386b351d4226389b387ae173207058832fbf5c8ec4b40e27b16026"}, + {file = "coveralls-3.3.1.tar.gz", hash = "sha256:b32a8bb5d2df585207c119d6c01567b81fba690c9c10a753bfe27a335bfc43ea"}, +] +deprecated = [ + {file = "Deprecated-1.2.13-py2.py3-none-any.whl", hash = "sha256:64756e3e14c8c5eea9795d93c524551432a0be75629f8f29e67ab8caf076c76d"}, + {file = "Deprecated-1.2.13.tar.gz", hash = "sha256:43ac5335da90c31c24ba028af536a91d41d53f9e6901ddb021bcc572ce44e38d"}, ] distlib = [ - {file = "distlib-0.3.2-py2.py3-none-any.whl", hash = "sha256:23e223426b28491b1ced97dc3bbe183027419dfc7982b4fa2f05d5f3ff10711c"}, - {file = "distlib-0.3.2.zip", hash = "sha256:106fef6dc37dd8c0e2c0a60d3fca3e77460a48907f335fa28420463a6f799736"}, + {file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"}, + {file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"}, ] docker = [ - {file = "docker-4.4.4-py2.py3-none-any.whl", hash = "sha256:f3607d5695be025fa405a12aca2e5df702a57db63790c73b927eb6a94aac60af"}, - {file = "docker-4.4.4.tar.gz", hash = "sha256:d3393c878f575d3a9ca3b94471a3c89a6d960b35feb92f033c0de36cc9d934db"}, + {file = "docker-5.0.3-py2.py3-none-any.whl", hash = "sha256:7a79bb439e3df59d0a72621775d600bc8bc8b422d285824cb37103eab91d1ce0"}, + {file = "docker-5.0.3.tar.gz", hash = "sha256:d916a26b62970e7c2f554110ed6af04c7ccff8e9f81ad17d0d40c75637e227fb"}, ] docopt = [ {file = "docopt-0.6.2.tar.gz", hash = "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"}, ] filelock = [ - {file = "filelock-3.0.12-py3-none-any.whl", hash = "sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836"}, - {file = "filelock-3.0.12.tar.gz", hash = "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59"}, + {file = "filelock-3.6.0-py3-none-any.whl", hash = "sha256:f8314284bfffbdcfa0ff3d7992b023d4c628ced6feb957351d4c48d059f56bc0"}, + {file = "filelock-3.6.0.tar.gz", hash = "sha256:9cd540a9352e432c7246a48fe4e8712b10acb1df2ad1f30e8c070b82ae1fed85"}, ] flask = [ - {file = "Flask-1.1.4-py2.py3-none-any.whl", hash = "sha256:c34f04500f2cbbea882b1acb02002ad6fe6b7ffa64a6164577995657f50aed22"}, - {file = "Flask-1.1.4.tar.gz", hash = "sha256:0fbeb6180d383a9186d0d6ed954e0042ad9f18e0e8de088b2b419d526927d196"}, + {file = "Flask-2.1.1-py3-none-any.whl", hash = "sha256:8a4cf32d904cf5621db9f0c9fbcd7efabf3003f22a04e4d0ce790c7137ec5264"}, + {file = "Flask-2.1.1.tar.gz", hash = "sha256:a8c9bd3e558ec99646d177a9739c41df1ded0629480b4c8d2975412f3c9519c8"}, ] flask-cors = [ {file = "Flask-Cors-3.0.10.tar.gz", hash = "sha256:b60839393f3b84a0f3746f6cdca56c1ad7426aa738b70d6c61375857823181de"}, {file = "Flask_Cors-3.0.10-py2.py3-none-any.whl", hash = "sha256:74efc975af1194fc7891ff5cd85b0f7478be4f7f59fe158102e91abb72bb4438"}, ] flask-httpauth = [ - {file = "Flask-HTTPAuth-4.4.0.tar.gz", hash = "sha256:bcaaa7a35a3cba0b2eafd4f113b3016bf70eb78087456d96484c3c18928b813a"}, - {file = "Flask_HTTPAuth-4.4.0-py2.py3-none-any.whl", hash = "sha256:d9131122cdc5709dda63790f6e9b3142d8101447d424b0b95ffd4ee279f49539"}, -] -flask-migrate = [ - {file = "Flask-Migrate-2.7.0.tar.gz", hash = "sha256:ae2f05671588762dd83a21d8b18c51fe355e86783e24594995ff8d7380dffe38"}, - {file = "Flask_Migrate-2.7.0-py2.py3-none-any.whl", hash = "sha256:26871836a4e46d2d590cf8e558c6d60039e1c003079b240689d845726b6b57c0"}, -] -flask-restx = [ - {file = "flask-restx-0.2.0.tar.gz", hash = "sha256:ca87a1808333f4ec5a50a5740b44e6cd3879a4b940d559df3996877ec4a2f2a5"}, - {file = "flask_restx-0.2.0-py2.py3-none-any.whl", hash = "sha256:a1653da19ca0b5e5c2ea59bd5f4639a7749e6a9b882f459de1814ed37872253b"}, + {file = "Flask-HTTPAuth-4.5.0.tar.gz", hash = "sha256:395040fda2854df800d15e84bc4a81a5f32f1d4a5e91eee554936f36f330aa29"}, + {file = "Flask_HTTPAuth-4.5.0-py3-none-any.whl", hash = "sha256:e16067ba3378ea366edf8de4b9d55f38c0a0cbddefcc0f777a54b3fce1d99392"}, ] +flask-restx = [] flask-sqlalchemy = [ {file = "Flask-SQLAlchemy-2.5.1.tar.gz", hash = "sha256:2bda44b43e7cacb15d4e05ff3cc1f8bc97936cc464623424102bfc2c35e95912"}, {file = "Flask_SQLAlchemy-2.5.1-py2.py3-none-any.whl", hash = "sha256:f12c3d4cc5cc7fdcc148b9527ea05671718c3ea45d50c7e732cceb33f574b390"}, ] geoalchemy2 = [ - {file = "GeoAlchemy2-0.8.5-py2.py3-none-any.whl", hash = "sha256:56dff13365ac2ea5ab828a697e240984f7ac448a32a3feba25356b4aa8e24d34"}, - {file = "GeoAlchemy2-0.8.5.tar.gz", hash = "sha256:567e105e6b0d5fd94a5a869d358b0c47956570bb3f3d19e98086344b1abefed8"}, + {file = "GeoAlchemy2-0.11.1-py2.py3-none-any.whl", hash = "sha256:43ce38a5387c9b380b4c9d20d720c3d8cf1752ca4f5f18aa88041be11f6948a3"}, + {file = "GeoAlchemy2-0.11.1.tar.gz", hash = "sha256:f92a0faddb5b74384dbbf3c7000433358ce8e07a180fe1d6c2843eaa0437ff08"}, ] gevent = [ - {file = "gevent-20.12.1-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:0f9fa230c5878704b9e286ad5038bac3b70d293bf10e9efa8b2ae1d7d80e7e08"}, - {file = "gevent-20.12.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:f020bfb34d57caa10029111be776524c378a4aac8417bc6fb1154b05e00fc220"}, - {file = "gevent-20.12.1-cp27-cp27m-win32.whl", hash = "sha256:e233ae153b586b61e492806d4cd1be2217de7441922c02053b67de14800bce96"}, - {file = "gevent-20.12.1-cp27-cp27m-win_amd64.whl", hash = "sha256:2d05f38a5ef1ebb7ceb692897674b11ba603914524765b989c65c020c7b08360"}, - {file = "gevent-20.12.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:ffa1be13963db6aa55c50d2fd4a656c82f53a03a47e37aaa69e79a488123538d"}, - {file = "gevent-20.12.1-cp35-cp35m-win32.whl", hash = "sha256:caec00914e8f21b2c77a29bbc2ef3abfeadf7515656e5451dfb14c2064733998"}, - {file = "gevent-20.12.1-cp35-cp35m-win_amd64.whl", hash = "sha256:19bd3fe60dec45fe6420b7772496950215f1b36701905876ba1644b6b2064163"}, - {file = "gevent-20.12.1-cp36-cp36m-win32.whl", hash = "sha256:9d001fc899db6e140110ae7484e58cd74b0dfa5cee021a0347f00bb441ac78bd"}, - {file = "gevent-20.12.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b57586ad3fedf13d351d2559b70d6fe593c50400315d52bb3c072285da60fa37"}, - {file = "gevent-20.12.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:69ddc1767a02f68e71d5e0d3215aa4d28872187715627f71ff0eadd7b7a5e7f4"}, - {file = "gevent-20.12.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:89c583744f91052ae987356660f5ed0b8fc59a1230b051d6ccc10d37a155fe01"}, - {file = "gevent-20.12.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:f3faf1834464f1b0731aa6346cd9f41029fa9e208d6ecbce4a736c19562c86aa"}, - {file = "gevent-20.12.1-cp37-cp37m-win32.whl", hash = "sha256:4baecba0fd614e14dc1f3f8c35616cb248cdb893de576150ed1fc7fc66b8ba3d"}, - {file = "gevent-20.12.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4b0a5626c4e534d184cdf00d66f06de3885beafaaa5f7b98d47186ea175629a1"}, - {file = "gevent-20.12.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:81e38ed46e21e0b00b930efce1a1ff46c7722ad83d84052f71a757f23cbed1c0"}, - {file = "gevent-20.12.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:895c76a89907d9d37fdfaf5321cb0fff0cba396f003bedb4f5fc13836da6f250"}, - {file = "gevent-20.12.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:c3706a620e167c4bd007f16f113928324c4e07a7bae11d6d18d65f82abcd7a58"}, - {file = "gevent-20.12.1-cp38-cp38-win32.whl", hash = "sha256:ba244028225ff8d3a58f344fcd16ab05b0e3642b34d81f51f7fa3c70761f6c34"}, - {file = "gevent-20.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:c570a2e3100f758a5c2f9b993ecf870ee784390e44e1a292c361d6b32fb3ad4c"}, - {file = "gevent-20.12.1-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:f857adbe1bf41e620d86173a53100f4ec328eba3089069a4815b3d9f4229dee8"}, - {file = "gevent-20.12.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:bf946a99e364ebcc95b82c794d5d1a67f13115adbefab7b9e12791f13184cfd5"}, - {file = "gevent-20.12.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:60799fd7dcbb622f8435eb12436d48a8d27f8e7b3d23631e32ccc04ddd2097c2"}, - {file = "gevent-20.12.1-pp27-pypy_73-win32.whl", hash = "sha256:7a808c63f065a303bbbe87c5c0754e06abb1e23e18752f418dce1eb3189cb43d"}, - {file = "gevent-20.12.1.tar.gz", hash = "sha256:99b68765767bb3e2244a66b012883899a6f17c23b6dc1cd80b793df341e15f08"}, + {file = "gevent-21.12.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:2afa3f3ad528155433f6ac8bd64fa5cc303855b97004416ec719a6b1ca179481"}, + {file = "gevent-21.12.0-cp27-cp27m-win32.whl", hash = "sha256:177f93a3a90f46a5009e0841fef561601e5c637ba4332ab8572edd96af650101"}, + {file = "gevent-21.12.0-cp27-cp27m-win_amd64.whl", hash = "sha256:a5ad4ed8afa0a71e1927623589f06a9b5e8b5e77810be3125cb4d93050d3fd1f"}, + {file = "gevent-21.12.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:eae3c46f9484eaacd67ffcdf4eaf6ca830f587edd543613b0f5c4eb3c11d052d"}, + {file = "gevent-21.12.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e1899b921219fc8959ff9afb94dae36be82e0769ed13d330a393594d478a0b3a"}, + {file = "gevent-21.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c21cb5c9f4e14d75b3fe0b143ec875d7dbd1495fad6d49704b00e57e781ee0f"}, + {file = "gevent-21.12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:542ae891e2aa217d2cf6d8446538fcd2f3263a40eec123b970b899bac391c47a"}, + {file = "gevent-21.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:0082d8a5d23c35812ce0e716a91ede597f6dd2c5ff508a02a998f73598c59397"}, + {file = "gevent-21.12.0-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:da8d2d51a49b2a5beb02ad619ca9ddbef806ef4870ba04e5ac7b8b41a5b61db3"}, + {file = "gevent-21.12.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cfff82f05f14b7f5d9ed53ccb7a609ae8604df522bb05c971bca78ec9d8b2b9"}, + {file = "gevent-21.12.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:7909780f0cf18a1fc32aafd8c8e130cdd93c6e285b11263f7f2d1a0f3678bc50"}, + {file = "gevent-21.12.0-cp36-cp36m-win32.whl", hash = "sha256:bb5cb8db753469c7a9a0b8a972d2660fe851aa06eee699a1ca42988afb0aaa02"}, + {file = "gevent-21.12.0-cp36-cp36m-win_amd64.whl", hash = "sha256:c43f081cbca41d27fd8fef9c6a32cf83cb979345b20abc07bf68df165cdadb24"}, + {file = "gevent-21.12.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:74fc1ef16b86616cfddcc74f7292642b0f72dde4dd95aebf4c45bb236744be54"}, + {file = "gevent-21.12.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cc2fef0f98ee180704cf95ec84f2bc2d86c6c3711bb6b6740d74e0afe708b62c"}, + {file = "gevent-21.12.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08b4c17064e28f4eb85604486abc89f442c7407d2aed249cf54544ce5c9baee6"}, + {file = "gevent-21.12.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:973749bacb7bc4f4181a8fb2a7e0e2ff44038de56d08e856dd54a5ac1d7331b4"}, + {file = "gevent-21.12.0-cp37-cp37m-win32.whl", hash = "sha256:6a02a88723ed3f0fd92cbf1df3c4cd2fbd87d82b0a4bac3e36a8875923115214"}, + {file = "gevent-21.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:f289fae643a3f1c3b909d6b033e6921b05234a4907e9c9c8c3f1fe403e6ac452"}, + {file = "gevent-21.12.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:3baeeccc4791ba3f8db27179dff11855a8f9210ddd754f6c9b48e0d2561c2aea"}, + {file = "gevent-21.12.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:05c5e8a50cd6868dd36536c92fb4468d18090e801bd63611593c0717bab63692"}, + {file = "gevent-21.12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d86438ede1cbe0fde6ef4cc3f72bf2f1ecc9630d8b633ff344a3aeeca272cdd"}, + {file = "gevent-21.12.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:01928770972181ad8866ee37ea3504f1824587b188fcab782ef1619ce7538766"}, + {file = "gevent-21.12.0-cp38-cp38-win32.whl", hash = "sha256:3c012c73e6c61f13c75e3a4869dbe6a2ffa025f103421a6de9c85e627e7477b1"}, + {file = "gevent-21.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:b7709c64afa8bb3000c28bb91ec42c79594a7cb0f322e20427d57f9762366a5b"}, + {file = "gevent-21.12.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:ec21f9eaaa6a7b1e62da786132d6788675b314f25f98d9541f1bf00584ed4749"}, + {file = "gevent-21.12.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:22ce1f38fdfe2149ffe8ec2131ca45281791c1e464db34b3b4321ae9d8d2efbb"}, + {file = "gevent-21.12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ccffcf708094564e442ac6fde46f0ae9e40015cb69d995f4b39cc29a7643881"}, + {file = "gevent-21.12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:24d3550fbaeef5fddd794819c2853bca45a86c3d64a056a2c268d981518220d1"}, + {file = "gevent-21.12.0-cp39-cp39-win32.whl", hash = "sha256:2bcec9f80196c751fdcf389ca9f7141e7b0db960d8465ed79be5e685bfcad682"}, + {file = "gevent-21.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:3dad62f55fad839d498c801e139481348991cee6e1c7706041b5fe096cb6a279"}, + {file = "gevent-21.12.0-pp27-pypy_73-win_amd64.whl", hash = "sha256:9f9652d1e4062d4b5b5a0a49ff679fa890430b5f76969d35dccb2df114c55e0f"}, + {file = "gevent-21.12.0.tar.gz", hash = "sha256:f48b64578c367b91fa793bf8eaaaf4995cb93c8bc45860e473bf868070ad094e"}, ] greenlet = [ - {file = "greenlet-1.1.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:60848099b76467ef09b62b0f4512e7e6f0a2c977357a036de602b653667f5f4c"}, - {file = "greenlet-1.1.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:f42ad188466d946f1b3afc0a9e1a266ac8926461ee0786c06baac6bd71f8a6f3"}, - {file = "greenlet-1.1.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:76ed710b4e953fc31c663b079d317c18f40235ba2e3d55f70ff80794f7b57922"}, - {file = "greenlet-1.1.0-cp27-cp27m-win32.whl", hash = "sha256:b33b51ab057f8a20b497ffafdb1e79256db0c03ef4f5e3d52e7497200e11f821"}, - {file = "greenlet-1.1.0-cp27-cp27m-win_amd64.whl", hash = "sha256:ed1377feed808c9c1139bdb6a61bcbf030c236dd288d6fca71ac26906ab03ba6"}, - {file = "greenlet-1.1.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:da862b8f7de577bc421323714f63276acb2f759ab8c5e33335509f0b89e06b8f"}, - {file = "greenlet-1.1.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:5f75e7f237428755d00e7460239a2482fa7e3970db56c8935bd60da3f0733e56"}, - {file = "greenlet-1.1.0-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:258f9612aba0d06785143ee1cbf2d7361801c95489c0bd10c69d163ec5254a16"}, - {file = "greenlet-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d928e2e3c3906e0a29b43dc26d9b3d6e36921eee276786c4e7ad9ff5665c78a"}, - {file = "greenlet-1.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cc407b68e0a874e7ece60f6639df46309376882152345508be94da608cc0b831"}, - {file = "greenlet-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c557c809eeee215b87e8a7cbfb2d783fb5598a78342c29ade561440abae7d22"}, - {file = "greenlet-1.1.0-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:3d13da093d44dee7535b91049e44dd2b5540c2a0e15df168404d3dd2626e0ec5"}, - {file = "greenlet-1.1.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:b3090631fecdf7e983d183d0fad7ea72cfb12fa9212461a9b708ff7907ffff47"}, - {file = "greenlet-1.1.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:06ecb43b04480e6bafc45cb1b4b67c785e183ce12c079473359e04a709333b08"}, - {file = "greenlet-1.1.0-cp35-cp35m-win32.whl", hash = "sha256:944fbdd540712d5377a8795c840a97ff71e7f3221d3fddc98769a15a87b36131"}, - {file = "greenlet-1.1.0-cp35-cp35m-win_amd64.whl", hash = "sha256:c767458511a59f6f597bfb0032a1c82a52c29ae228c2c0a6865cfeaeaac4c5f5"}, - {file = "greenlet-1.1.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:2325123ff3a8ecc10ca76f062445efef13b6cf5a23389e2df3c02a4a527b89bc"}, - {file = "greenlet-1.1.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:598bcfd841e0b1d88e32e6a5ea48348a2c726461b05ff057c1b8692be9443c6e"}, - {file = "greenlet-1.1.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:be9768e56f92d1d7cd94185bab5856f3c5589a50d221c166cc2ad5eb134bd1dc"}, - {file = "greenlet-1.1.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfe7eac0d253915116ed0cd160a15a88981a1d194c1ef151e862a5c7d2f853d3"}, - {file = "greenlet-1.1.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a6b035aa2c5fcf3dbbf0e3a8a5bc75286fc2d4e6f9cfa738788b433ec894919"}, - {file = "greenlet-1.1.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca1c4a569232c063615f9e70ff9a1e2fee8c66a6fb5caf0f5e8b21a396deec3e"}, - {file = "greenlet-1.1.0-cp36-cp36m-win32.whl", hash = "sha256:3096286a6072553b5dbd5efbefc22297e9d06a05ac14ba017233fedaed7584a8"}, - {file = "greenlet-1.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:c35872b2916ab5a240d52a94314c963476c989814ba9b519bc842e5b61b464bb"}, - {file = "greenlet-1.1.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:b97c9a144bbeec7039cca44df117efcbeed7209543f5695201cacf05ba3b5857"}, - {file = "greenlet-1.1.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:16183fa53bc1a037c38d75fdc59d6208181fa28024a12a7f64bb0884434c91ea"}, - {file = "greenlet-1.1.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6b1d08f2e7f2048d77343279c4d4faa7aef168b3e36039cba1917fffb781a8ed"}, - {file = "greenlet-1.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14927b15c953f8f2d2a8dffa224aa78d7759ef95284d4c39e1745cf36e8cdd2c"}, - {file = "greenlet-1.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bdcff4b9051fb1aa4bba4fceff6a5f770c6be436408efd99b76fc827f2a9319"}, - {file = "greenlet-1.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c70c7dd733a4c56838d1f1781e769081a25fade879510c5b5f0df76956abfa05"}, - {file = "greenlet-1.1.0-cp37-cp37m-win32.whl", hash = "sha256:0de64d419b1cb1bfd4ea544bedea4b535ef3ae1e150b0f2609da14bbf48a4a5f"}, - {file = "greenlet-1.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:8833e27949ea32d27f7e96930fa29404dd4f2feb13cce483daf52e8842ec246a"}, - {file = "greenlet-1.1.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:c1580087ab493c6b43e66f2bdd165d9e3c1e86ef83f6c2c44a29f2869d2c5bd5"}, - {file = "greenlet-1.1.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:ad80bb338cf9f8129c049837a42a43451fc7c8b57ad56f8e6d32e7697b115505"}, - {file = "greenlet-1.1.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:a9017ff5fc2522e45562882ff481128631bf35da444775bc2776ac5c61d8bcae"}, - {file = "greenlet-1.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7920e3eccd26b7f4c661b746002f5ec5f0928076bd738d38d894bb359ce51927"}, - {file = "greenlet-1.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:408071b64e52192869129a205e5b463abda36eff0cebb19d6e63369440e4dc99"}, - {file = "greenlet-1.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be13a18cec649ebaab835dff269e914679ef329204704869f2f167b2c163a9da"}, - {file = "greenlet-1.1.0-cp38-cp38-win32.whl", hash = "sha256:22002259e5b7828b05600a762579fa2f8b33373ad95a0ee57b4d6109d0e589ad"}, - {file = "greenlet-1.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:206295d270f702bc27dbdbd7651e8ebe42d319139e0d90217b2074309a200da8"}, - {file = "greenlet-1.1.0-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:096cb0217d1505826ba3d723e8981096f2622cde1eb91af9ed89a17c10aa1f3e"}, - {file = "greenlet-1.1.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:03f28a5ea20201e70ab70518d151116ce939b412961c33827519ce620957d44c"}, - {file = "greenlet-1.1.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:7db68f15486d412b8e2cfcd584bf3b3a000911d25779d081cbbae76d71bd1a7e"}, - {file = "greenlet-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70bd1bb271e9429e2793902dfd194b653221904a07cbf207c3139e2672d17959"}, - {file = "greenlet-1.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f92731609d6625e1cc26ff5757db4d32b6b810d2a3363b0ff94ff573e5901f6f"}, - {file = "greenlet-1.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06d7ac89e6094a0a8f8dc46aa61898e9e1aec79b0f8b47b2400dd51a44dbc832"}, - {file = "greenlet-1.1.0-cp39-cp39-win32.whl", hash = "sha256:adb94a28225005890d4cf73648b5131e885c7b4b17bc762779f061844aabcc11"}, - {file = "greenlet-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:aa4230234d02e6f32f189fd40b59d5a968fe77e80f59c9c933384fe8ba535535"}, - {file = "greenlet-1.1.0.tar.gz", hash = "sha256:c87df8ae3f01ffb4483c796fe1b15232ce2b219f0b18126948616224d3f658ee"}, + {file = "greenlet-1.1.2-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:58df5c2a0e293bf665a51f8a100d3e9956febfbf1d9aaf8c0677cf70218910c6"}, + {file = "greenlet-1.1.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:aec52725173bd3a7b56fe91bc56eccb26fbdff1386ef123abb63c84c5b43b63a"}, + {file = "greenlet-1.1.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:833e1551925ed51e6b44c800e71e77dacd7e49181fdc9ac9a0bf3714d515785d"}, + {file = "greenlet-1.1.2-cp27-cp27m-win32.whl", hash = "sha256:aa5b467f15e78b82257319aebc78dd2915e4c1436c3c0d1ad6f53e47ba6e2713"}, + {file = "greenlet-1.1.2-cp27-cp27m-win_amd64.whl", hash = "sha256:40b951f601af999a8bf2ce8c71e8aaa4e8c6f78ff8afae7b808aae2dc50d4c40"}, + {file = "greenlet-1.1.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:95e69877983ea39b7303570fa6760f81a3eec23d0e3ab2021b7144b94d06202d"}, + {file = "greenlet-1.1.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:356b3576ad078c89a6107caa9c50cc14e98e3a6c4874a37c3e0273e4baf33de8"}, + {file = "greenlet-1.1.2-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:8639cadfda96737427330a094476d4c7a56ac03de7265622fcf4cfe57c8ae18d"}, + {file = "greenlet-1.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97e5306482182170ade15c4b0d8386ded995a07d7cc2ca8f27958d34d6736497"}, + {file = "greenlet-1.1.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e6a36bb9474218c7a5b27ae476035497a6990e21d04c279884eb10d9b290f1b1"}, + {file = "greenlet-1.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abb7a75ed8b968f3061327c433a0fbd17b729947b400747c334a9c29a9af6c58"}, + {file = "greenlet-1.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b336501a05e13b616ef81ce329c0e09ac5ed8c732d9ba7e3e983fcc1a9e86965"}, + {file = "greenlet-1.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:14d4f3cd4e8b524ae9b8aa567858beed70c392fdec26dbdb0a8a418392e71708"}, + {file = "greenlet-1.1.2-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:17ff94e7a83aa8671a25bf5b59326ec26da379ace2ebc4411d690d80a7fbcf23"}, + {file = "greenlet-1.1.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9f3cba480d3deb69f6ee2c1825060177a22c7826431458c697df88e6aeb3caee"}, + {file = "greenlet-1.1.2-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:fa877ca7f6b48054f847b61d6fa7bed5cebb663ebc55e018fda12db09dcc664c"}, + {file = "greenlet-1.1.2-cp35-cp35m-win32.whl", hash = "sha256:7cbd7574ce8e138bda9df4efc6bf2ab8572c9aff640d8ecfece1b006b68da963"}, + {file = "greenlet-1.1.2-cp35-cp35m-win_amd64.whl", hash = "sha256:903bbd302a2378f984aef528f76d4c9b1748f318fe1294961c072bdc7f2ffa3e"}, + {file = "greenlet-1.1.2-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:049fe7579230e44daef03a259faa24511d10ebfa44f69411d99e6a184fe68073"}, + {file = "greenlet-1.1.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:dd0b1e9e891f69e7675ba5c92e28b90eaa045f6ab134ffe70b52e948aa175b3c"}, + {file = "greenlet-1.1.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:7418b6bfc7fe3331541b84bb2141c9baf1ec7132a7ecd9f375912eca810e714e"}, + {file = "greenlet-1.1.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9d29ca8a77117315101425ec7ec2a47a22ccf59f5593378fc4077ac5b754fce"}, + {file = "greenlet-1.1.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:21915eb821a6b3d9d8eefdaf57d6c345b970ad722f856cd71739493ce003ad08"}, + {file = "greenlet-1.1.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eff9d20417ff9dcb0d25e2defc2574d10b491bf2e693b4e491914738b7908168"}, + {file = "greenlet-1.1.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b8c008de9d0daba7b6666aa5bbfdc23dcd78cafc33997c9b7741ff6353bafb7f"}, + {file = "greenlet-1.1.2-cp36-cp36m-win32.whl", hash = "sha256:32ca72bbc673adbcfecb935bb3fb1b74e663d10a4b241aaa2f5a75fe1d1f90aa"}, + {file = "greenlet-1.1.2-cp36-cp36m-win_amd64.whl", hash = "sha256:f0214eb2a23b85528310dad848ad2ac58e735612929c8072f6093f3585fd342d"}, + {file = "greenlet-1.1.2-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:b92e29e58bef6d9cfd340c72b04d74c4b4e9f70c9fa7c78b674d1fec18896dc4"}, + {file = "greenlet-1.1.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fdcec0b8399108577ec290f55551d926d9a1fa6cad45882093a7a07ac5ec147b"}, + {file = "greenlet-1.1.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:93f81b134a165cc17123626ab8da2e30c0455441d4ab5576eed73a64c025b25c"}, + {file = "greenlet-1.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e12bdc622676ce47ae9abbf455c189e442afdde8818d9da983085df6312e7a1"}, + {file = "greenlet-1.1.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c790abda465726cfb8bb08bd4ca9a5d0a7bd77c7ac1ca1b839ad823b948ea28"}, + {file = "greenlet-1.1.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f276df9830dba7a333544bd41070e8175762a7ac20350786b322b714b0e654f5"}, + {file = "greenlet-1.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c5d5b35f789a030ebb95bff352f1d27a93d81069f2adb3182d99882e095cefe"}, + {file = "greenlet-1.1.2-cp37-cp37m-win32.whl", hash = "sha256:64e6175c2e53195278d7388c454e0b30997573f3f4bd63697f88d855f7a6a1fc"}, + {file = "greenlet-1.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b11548073a2213d950c3f671aa88e6f83cda6e2fb97a8b6317b1b5b33d850e06"}, + {file = "greenlet-1.1.2-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:9633b3034d3d901f0a46b7939f8c4d64427dfba6bbc5a36b1a67364cf148a1b0"}, + {file = "greenlet-1.1.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:eb6ea6da4c787111adf40f697b4e58732ee0942b5d3bd8f435277643329ba627"}, + {file = "greenlet-1.1.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:f3acda1924472472ddd60c29e5b9db0cec629fbe3c5c5accb74d6d6d14773478"}, + {file = "greenlet-1.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e859fcb4cbe93504ea18008d1df98dee4f7766db66c435e4882ab35cf70cac43"}, + {file = "greenlet-1.1.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:00e44c8afdbe5467e4f7b5851be223be68adb4272f44696ee71fe46b7036a711"}, + {file = "greenlet-1.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec8c433b3ab0419100bd45b47c9c8551248a5aee30ca5e9d399a0b57ac04651b"}, + {file = "greenlet-1.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2bde6792f313f4e918caabc46532aa64aa27a0db05d75b20edfc5c6f46479de2"}, + {file = "greenlet-1.1.2-cp38-cp38-win32.whl", hash = "sha256:288c6a76705dc54fba69fbcb59904ae4ad768b4c768839b8ca5fdadec6dd8cfd"}, + {file = "greenlet-1.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:8d2f1fb53a421b410751887eb4ff21386d119ef9cde3797bf5e7ed49fb51a3b3"}, + {file = "greenlet-1.1.2-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:166eac03e48784a6a6e0e5f041cfebb1ab400b394db188c48b3a84737f505b67"}, + {file = "greenlet-1.1.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:572e1787d1460da79590bf44304abbc0a2da944ea64ec549188fa84d89bba7ab"}, + {file = "greenlet-1.1.2-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:be5f425ff1f5f4b3c1e33ad64ab994eed12fc284a6ea71c5243fd564502ecbe5"}, + {file = "greenlet-1.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1692f7d6bc45e3200844be0dba153612103db241691088626a33ff1f24a0d88"}, + {file = "greenlet-1.1.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7227b47e73dedaa513cdebb98469705ef0d66eb5a1250144468e9c3097d6b59b"}, + {file = "greenlet-1.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ff61ff178250f9bb3cd89752df0f1dd0e27316a8bd1465351652b1b4a4cdfd3"}, + {file = "greenlet-1.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0051c6f1f27cb756ffc0ffbac7d2cd48cb0362ac1736871399a739b2885134d3"}, + {file = "greenlet-1.1.2-cp39-cp39-win32.whl", hash = "sha256:f70a9e237bb792c7cc7e44c531fd48f5897961701cdaa06cf22fc14965c496cf"}, + {file = "greenlet-1.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:013d61294b6cd8fe3242932c1c5e36e5d1db2c8afb58606c5a67efce62c1f5fd"}, + {file = "greenlet-1.1.2.tar.gz", hash = "sha256:e30f5ea4ae2346e62cedde8794a56858a67b878dd79f7df76a0767e356b1744a"}, ] gunicorn = [ {file = "gunicorn-20.1.0-py3-none-any.whl", hash = "sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e"}, {file = "gunicorn-20.1.0.tar.gz", hash = "sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8"}, ] identify = [ - {file = "identify-2.2.11-py2.py3-none-any.whl", hash = "sha256:7abaecbb414e385752e8ce02d8c494f4fbc780c975074b46172598a28f1ab839"}, - {file = "identify-2.2.11.tar.gz", hash = "sha256:a0e700637abcbd1caae58e0463861250095dfe330a8371733a471af706a4a29a"}, + {file = "identify-2.4.12-py2.py3-none-any.whl", hash = "sha256:5f06b14366bd1facb88b00540a1de05b69b310cbc2654db3c7e07fa3a4339323"}, + {file = "identify-2.4.12.tar.gz", hash = "sha256:3f3244a559290e7d3deb9e9adc7b33594c1bc85a9dd82e0f1be519bf12a1ec17"}, ] idna = [ - {file = "idna-3.2-py3-none-any.whl", hash = "sha256:14475042e284991034cb48e06f6851428fb14c4dc953acd9be9a5e95c7b6dd7a"}, - {file = "idna-3.2.tar.gz", hash = "sha256:467fbad99067910785144ce333826c71fb0e63a425657295239737f7ecd125f3"}, + {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, + {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, ] importlib-metadata = [ - {file = "importlib_metadata-4.6.1-py3-none-any.whl", hash = "sha256:9f55f560e116f8643ecf2922d9cd3e1c7e8d52e683178fecd9d08f6aa357e11e"}, - {file = "importlib_metadata-4.6.1.tar.gz", hash = "sha256:079ada16b7fc30dfbb5d13399a5113110dab1aa7c2bc62f66af75f0b717c8cac"}, + {file = "importlib_metadata-4.11.3-py3-none-any.whl", hash = "sha256:1208431ca90a8cca1a6b8af391bb53c1a2db74e5d1cef6ddced95d4b2062edc6"}, + {file = "importlib_metadata-4.11.3.tar.gz", hash = "sha256:ea4c597ebf37142f827b8f39299579e31685c31d3a438b59f469406afd0f2539"}, ] importlib-resources = [ - {file = "importlib_resources-5.2.0-py3-none-any.whl", hash = "sha256:a0143290bef3cbc99de9e40176e4987780939a955b8632f02ce6c935f42e9bfc"}, - {file = "importlib_resources-5.2.0.tar.gz", hash = "sha256:22a2c42d8c6a1d30aa8a0e1f57293725bfd5c013d562585e46aff469e0ff78b3"}, + {file = "importlib_resources-5.6.0-py3-none-any.whl", hash = "sha256:a9dd72f6cc106aeb50f6e66b86b69b454766dd6e39b69ac68450253058706bcc"}, + {file = "importlib_resources-5.6.0.tar.gz", hash = "sha256:1b93238cbf23b4cde34240dd8321d99e9bf2eb4bc91c0c99b2886283e7baad85"}, ] iniconfig = [ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, ] itsdangerous = [ - {file = "itsdangerous-1.1.0-py2.py3-none-any.whl", hash = "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"}, - {file = "itsdangerous-1.1.0.tar.gz", hash = "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19"}, + {file = "itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44"}, + {file = "itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"}, ] jinja2 = [ - {file = "Jinja2-2.11.3-py2.py3-none-any.whl", hash = "sha256:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419"}, - {file = "Jinja2-2.11.3.tar.gz", hash = "sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6"}, + {file = "Jinja2-3.1.1-py3-none-any.whl", hash = "sha256:539835f51a74a69f41b848a9645dbdc35b4f20a3b601e2d9a7e22947b15ff119"}, + {file = "Jinja2-3.1.1.tar.gz", hash = "sha256:640bed4bb501cbd17194b3cace1dc2126f5b619cf068a726b98192a0fde74ae9"}, ] jsonschema = [ - {file = "jsonschema-3.2.0-py2.py3-none-any.whl", hash = "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163"}, - {file = "jsonschema-3.2.0.tar.gz", hash = "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"}, -] -mako = [ - {file = "Mako-1.1.4.tar.gz", hash = "sha256:17831f0b7087c313c0ffae2bcbbd3c1d5ba9eeac9c38f2eb7b50e8c99fe9d5ab"}, + {file = "jsonschema-4.4.0-py3-none-any.whl", hash = "sha256:77281a1f71684953ee8b3d488371b162419767973789272434bbc3f29d9c8823"}, + {file = "jsonschema-4.4.0.tar.gz", hash = "sha256:636694eb41b3535ed608fe04129f26542b59ed99808b4f688aa32dcf55317a83"}, ] markupsafe = [ - {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, - {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, - {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, - {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, - {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, - {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"}, + {file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"}, + {file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"}, + {file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"}, + {file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"}, + {file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"}, ] nodeenv = [ {file = "nodeenv-1.6.0-py2.py3-none-any.whl", hash = "sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7"}, {file = "nodeenv-1.6.0.tar.gz", hash = "sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b"}, ] osmium = [ - {file = "osmium-3.1.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:08136f5b1b7b522cf450e0da6aa9dd1f93cc47bd8216843c3ef9293cb52aef35"}, - {file = "osmium-3.1.3-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:e345f3da191367e7108f0a25d7913e21ce2e946c1cc672e33623aef829ed3926"}, - {file = "osmium-3.1.3-cp36-cp36m-win_amd64.whl", hash = "sha256:b55711e3aaef39e8261a29e651ffada1be8b53fc3fe0bed8fe241327132713b1"}, - {file = "osmium-3.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d08d5ccd8308318fc05cc0d1bd66ea8239ed3498f93973b31b3b37a7b7f783e0"}, - {file = "osmium-3.1.3-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:7609b0b95b770fb4ba67aa96da3c8cf34cad8340935a4488963f541882ffede8"}, - {file = "osmium-3.1.3-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:8126fdabbb8d64c454a8939c3a2b1262cef1f79ad467821f88b478c029e7db71"}, - {file = "osmium-3.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:1bdc6e6a4303f91a524126210e2b28066192259f9aa6a8bf2038c67e7f916e5f"}, - {file = "osmium-3.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cc6d3096a6581f1c71d01987362fe8fc6d8788169ed859555e3d679d88cfc59d"}, - {file = "osmium-3.1.3-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:098b1cff3b815619e6173cee158bdd1d6c0a30690f51d1bdd3fffc55208e535a"}, - {file = "osmium-3.1.3-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:d8878d85b56cf07a016e111cee5a5ee6400d97ff820ba3a94bfdc6380e127d05"}, - {file = "osmium-3.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:81df4393802ed7d93d296773b4e2d03a799b2fee6244f31f0f92528d53301428"}, - {file = "osmium-3.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b050a63226de2927a8b1127c95f28b3598e75c49a23089bf4f76e44f9ada27da"}, - {file = "osmium-3.1.3-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:26a89d8a22679aaf707a338b9648e4368a4a08b44b3c0dafac5c154eaf3dc2b5"}, - {file = "osmium-3.1.3-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:8b8ea3e5dfe6c487edc04f930a78fb46c20f989284c860d62ca3daa416c3b3a7"}, - {file = "osmium-3.1.3.tar.gz", hash = "sha256:bdcbbb5e4f12de10aab9c209b4d436eafaf75bd30a91b81039b5dc3d22771465"}, + {file = "osmium-3.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:09840ae1b922e7a8f852c1767299b4ec5549f9bd27160a6556af3c06477a765b"}, + {file = "osmium-3.3.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:126cdf85894986d11c1da56e891d8ad26a94c6caa75eb73ccab21756e4ebadf2"}, + {file = "osmium-3.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:eadb3fa6786bd7affdfe72d53bd1f11e507bc0262107c1fc5d72a0336118099d"}, + {file = "osmium-3.3.0-cp35-cp35m-win_amd64.whl", hash = "sha256:8faab62b80e178ac3fa0b577550cd4b932ef7442b920a6b08c6d817e05c89b8a"}, + {file = "osmium-3.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:14763966e9c164d7e7a271bd64b3c7ef2199e7b83660854ca5d6d826f5241b38"}, + {file = "osmium-3.3.0-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:201cf31eb28303a6f598a6bbef634536bf67bc3f174a7e71a8f7e03a007856d5"}, + {file = "osmium-3.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:4f49241f06160ee802188c69112175ad29417fe1d72cfaf37790cf90d96e8376"}, + {file = "osmium-3.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:be0bf64d4f9084ea487bf7ee7e698dc49dc5fc0346f9dd93380da7056637ecd0"}, + {file = "osmium-3.3.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:30732f29d120eb78bcbe6be9522ff0ca9e5f23c2eb791c24d90e75ab5321a64f"}, + {file = "osmium-3.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f53c81a0f77bbb13b4d03566ada1de83e27b894ff0354aff4d87905c0545d62"}, + {file = "osmium-3.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b65f9932c21af0638daaa12d891cd043ffba448ecf654265152009c9ca496fa9"}, + {file = "osmium-3.3.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:df485130567a86167d5d7e7c8d0990a1d414e767dc95719a13abcd88a0c983f0"}, + {file = "osmium-3.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:dd44ffe3bcfb6dfba61d2699063c742cc2d8209173efda5068b0955e19ab1358"}, + {file = "osmium-3.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7ee86ef1a92bee85a22f3247e695310cff9866dabe8acc7c729f0f97c47c27a0"}, + {file = "osmium-3.3.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f2f228a25c774509feaf8515742f71255d1c8a1b84754c5c4ca00e71dfd46380"}, + {file = "osmium-3.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:44d3e0bf4dce4dbe68c913c8667cef4a8e8eadd853038ec5e4ca397fba4604ca"}, + {file = "osmium-3.3.0.tar.gz", hash = "sha256:e2d7a5e187436d22efe77539becb8f8a7ea7a874f0dae51c2bde0990ef3426ea"}, ] packaging = [ - {file = "packaging-21.0-py3-none-any.whl", hash = "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14"}, - {file = "packaging-21.0.tar.gz", hash = "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7"}, + {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, + {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, ] passlib = [ {file = "passlib-1.7.4-py2.py3-none-any.whl", hash = "sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1"}, {file = "passlib-1.7.4.tar.gz", hash = "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04"}, ] platformdirs = [ - {file = "platformdirs-2.1.0-py3-none-any.whl", hash = "sha256:b2b30ae52404f93e2024e85bba29329b85715d6b2f18ffe90ecd25a5c67553df"}, - {file = "platformdirs-2.1.0.tar.gz", hash = "sha256:1964be5aba107a7ccb7de0e6f1f1bfde0dee51641f0e733028121f8e02e2e16b"}, + {file = "platformdirs-2.5.1-py3-none-any.whl", hash = "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227"}, + {file = "platformdirs-2.5.1.tar.gz", hash = "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d"}, ] pluggy = [ - {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, - {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, + {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, + {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, ] pre-commit = [ - {file = "pre_commit-2.13.0-py2.py3-none-any.whl", hash = "sha256:b679d0fddd5b9d6d98783ae5f10fd0c4c59954f375b70a58cbe1ce9bcf9809a4"}, - {file = "pre_commit-2.13.0.tar.gz", hash = "sha256:764972c60693dc668ba8e86eb29654ec3144501310f7198742a767bec385a378"}, + {file = "pre_commit-2.17.0-py2.py3-none-any.whl", hash = "sha256:725fa7459782d7bec5ead072810e47351de01709be838c2ce1726b9591dad616"}, + {file = "pre_commit-2.17.0.tar.gz", hash = "sha256:c1a8040ff15ad3d648c70cc3e55b93e4d2d5b687320955505587fd79bbaed06a"}, ] psycopg2-binary = [ - {file = "psycopg2-binary-2.9.1.tar.gz", hash = "sha256:b0221ca5a9837e040ebf61f48899926b5783668b7807419e4adae8175a31f773"}, - {file = "psycopg2_binary-2.9.1-cp36-cp36m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:c250a7ec489b652c892e4f0a5d122cc14c3780f9f643e1a326754aedf82d9a76"}, - {file = "psycopg2_binary-2.9.1-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aef9aee84ec78af51107181d02fe8773b100b01c5dfde351184ad9223eab3698"}, - {file = "psycopg2_binary-2.9.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:123c3fb684e9abfc47218d3784c7b4c47c8587951ea4dd5bc38b6636ac57f616"}, - {file = "psycopg2_binary-2.9.1-cp36-cp36m-manylinux_2_24_aarch64.whl", hash = "sha256:995fc41ebda5a7a663a254a1dcac52638c3e847f48307b5416ee373da15075d7"}, - {file = "psycopg2_binary-2.9.1-cp36-cp36m-manylinux_2_24_ppc64le.whl", hash = "sha256:fbb42a541b1093385a2d8c7eec94d26d30437d0e77c1d25dae1dcc46741a385e"}, - {file = "psycopg2_binary-2.9.1-cp36-cp36m-win32.whl", hash = "sha256:20f1ab44d8c352074e2d7ca67dc00843067788791be373e67a0911998787ce7d"}, - {file = "psycopg2_binary-2.9.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f6fac64a38f6768e7bc7b035b9e10d8a538a9fadce06b983fb3e6fa55ac5f5ce"}, - {file = "psycopg2_binary-2.9.1-cp37-cp37m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:1e3a362790edc0a365385b1ac4cc0acc429a0c0d662d829a50b6ce743ae61b5a"}, - {file = "psycopg2_binary-2.9.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f8559617b1fcf59a9aedba2c9838b5b6aa211ffedecabca412b92a1ff75aac1a"}, - {file = "psycopg2_binary-2.9.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a36c7eb6152ba5467fb264d73844877be8b0847874d4822b7cf2d3c0cb8cdcb0"}, - {file = "psycopg2_binary-2.9.1-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:2f62c207d1740b0bde5c4e949f857b044818f734a3d57f1d0d0edc65050532ed"}, - {file = "psycopg2_binary-2.9.1-cp37-cp37m-manylinux_2_24_ppc64le.whl", hash = "sha256:cfc523edecddaef56f6740d7de1ce24a2fdf94fd5e704091856a201872e37f9f"}, - {file = "psycopg2_binary-2.9.1-cp37-cp37m-win32.whl", hash = "sha256:1e85b74cbbb3056e3656f1cc4781294df03383127a8114cbc6531e8b8367bf1e"}, - {file = "psycopg2_binary-2.9.1-cp37-cp37m-win_amd64.whl", hash = "sha256:1473c0215b0613dd938db54a653f68251a45a78b05f6fc21af4326f40e8360a2"}, - {file = "psycopg2_binary-2.9.1-cp38-cp38-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:35c4310f8febe41f442d3c65066ca93cccefd75013df3d8c736c5b93ec288140"}, - {file = "psycopg2_binary-2.9.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c13d72ed6af7fd2c8acbd95661cf9477f94e381fce0792c04981a8283b52917"}, - {file = "psycopg2_binary-2.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14db1752acdd2187d99cb2ca0a1a6dfe57fc65c3281e0f20e597aac8d2a5bd90"}, - {file = "psycopg2_binary-2.9.1-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:aed4a9a7e3221b3e252c39d0bf794c438dc5453bc2963e8befe9d4cd324dff72"}, - {file = "psycopg2_binary-2.9.1-cp38-cp38-manylinux_2_24_ppc64le.whl", hash = "sha256:da113b70f6ec40e7d81b43d1b139b9db6a05727ab8be1ee559f3a69854a69d34"}, - {file = "psycopg2_binary-2.9.1-cp38-cp38-win32.whl", hash = "sha256:4235f9d5ddcab0b8dbd723dca56ea2922b485ea00e1dafacf33b0c7e840b3d32"}, - {file = "psycopg2_binary-2.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:988b47ac70d204aed01589ed342303da7c4d84b56c2f4c4b8b00deda123372bf"}, - {file = "psycopg2_binary-2.9.1-cp39-cp39-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:7360647ea04db2e7dff1648d1da825c8cf68dc5fbd80b8fb5b3ee9f068dcd21a"}, - {file = "psycopg2_binary-2.9.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca86db5b561b894f9e5f115d6a159fff2a2570a652e07889d8a383b5fae66eb4"}, - {file = "psycopg2_binary-2.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ced67f1e34e1a450cdb48eb53ca73b60aa0af21c46b9b35ac3e581cf9f00e31"}, - {file = "psycopg2_binary-2.9.1-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:0f2e04bd2a2ab54fa44ee67fe2d002bb90cee1c0f1cc0ebc3148af7b02034cbd"}, - {file = "psycopg2_binary-2.9.1-cp39-cp39-manylinux_2_24_ppc64le.whl", hash = "sha256:3242b9619de955ab44581a03a64bdd7d5e470cc4183e8fcadd85ab9d3756ce7a"}, - {file = "psycopg2_binary-2.9.1-cp39-cp39-win32.whl", hash = "sha256:0b7dae87f0b729922e06f85f667de7bf16455d411971b2043bbd9577af9d1975"}, - {file = "psycopg2_binary-2.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:b4d7679a08fea64573c969f6994a2631908bb2c0e69a7235648642f3d2e39a68"}, + {file = "psycopg2-binary-2.9.3.tar.gz", hash = "sha256:761df5313dc15da1502b21453642d7599d26be88bff659382f8f9747c7ebea4e"}, + {file = "psycopg2_binary-2.9.3-cp310-cp310-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:539b28661b71da7c0e428692438efbcd048ca21ea81af618d845e06ebfd29478"}, + {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e82d38390a03da28c7985b394ec3f56873174e2c88130e6966cb1c946508e65"}, + {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57804fc02ca3ce0dbfbef35c4b3a4a774da66d66ea20f4bda601294ad2ea6092"}, + {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:083a55275f09a62b8ca4902dd11f4b33075b743cf0d360419e2051a8a5d5ff76"}, + {file = "psycopg2_binary-2.9.3-cp310-cp310-manylinux_2_24_ppc64le.whl", hash = "sha256:0a29729145aaaf1ad8bafe663131890e2111f13416b60e460dae0a96af5905c9"}, + {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3a79d622f5206d695d7824cbf609a4f5b88ea6d6dab5f7c147fc6d333a8787e4"}, + {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:090f3348c0ab2cceb6dfbe6bf721ef61262ddf518cd6cc6ecc7d334996d64efa"}, + {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a9e1f75f96ea388fbcef36c70640c4efbe4650658f3d6a2967b4cc70e907352e"}, + {file = "psycopg2_binary-2.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c3ae8e75eb7160851e59adc77b3a19a976e50622e44fd4fd47b8b18208189d42"}, + {file = "psycopg2_binary-2.9.3-cp310-cp310-win32.whl", hash = "sha256:7b1e9b80afca7b7a386ef087db614faebbf8839b7f4db5eb107d0f1a53225029"}, + {file = "psycopg2_binary-2.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:8b344adbb9a862de0c635f4f0425b7958bf5a4b927c8594e6e8d261775796d53"}, + {file = "psycopg2_binary-2.9.3-cp36-cp36m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:e847774f8ffd5b398a75bc1c18fbb56564cda3d629fe68fd81971fece2d3c67e"}, + {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68641a34023d306be959101b345732360fc2ea4938982309b786f7be1b43a4a1"}, + {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3303f8807f342641851578ee7ed1f3efc9802d00a6f83c101d21c608cb864460"}, + {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_24_aarch64.whl", hash = "sha256:e3699852e22aa68c10de06524a3721ade969abf382da95884e6a10ff798f9281"}, + {file = "psycopg2_binary-2.9.3-cp36-cp36m-manylinux_2_24_ppc64le.whl", hash = "sha256:526ea0378246d9b080148f2d6681229f4b5964543c170dd10bf4faaab6e0d27f"}, + {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:b1c8068513f5b158cf7e29c43a77eb34b407db29aca749d3eb9293ee0d3103ca"}, + {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:15803fa813ea05bef089fa78835118b5434204f3a17cb9f1e5dbfd0b9deea5af"}, + {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:152f09f57417b831418304c7f30d727dc83a12761627bb826951692cc6491e57"}, + {file = "psycopg2_binary-2.9.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:404224e5fef3b193f892abdbf8961ce20e0b6642886cfe1fe1923f41aaa75c9d"}, + {file = "psycopg2_binary-2.9.3-cp36-cp36m-win32.whl", hash = "sha256:1f6b813106a3abdf7b03640d36e24669234120c72e91d5cbaeb87c5f7c36c65b"}, + {file = "psycopg2_binary-2.9.3-cp36-cp36m-win_amd64.whl", hash = "sha256:2d872e3c9d5d075a2e104540965a1cf898b52274a5923936e5bfddb58c59c7c2"}, + {file = "psycopg2_binary-2.9.3-cp37-cp37m-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:10bb90fb4d523a2aa67773d4ff2b833ec00857f5912bafcfd5f5414e45280fb1"}, + {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:874a52ecab70af13e899f7847b3e074eeb16ebac5615665db33bce8a1009cf33"}, + {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a29b3ca4ec9defec6d42bf5feb36bb5817ba3c0230dd83b4edf4bf02684cd0ae"}, + {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:12b11322ea00ad8db8c46f18b7dfc47ae215e4df55b46c67a94b4effbaec7094"}, + {file = "psycopg2_binary-2.9.3-cp37-cp37m-manylinux_2_24_ppc64le.whl", hash = "sha256:53293533fcbb94c202b7c800a12c873cfe24599656b341f56e71dd2b557be063"}, + {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c381bda330ddf2fccbafab789d83ebc6c53db126e4383e73794c74eedce855ef"}, + {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9d29409b625a143649d03d0fd7b57e4b92e0ecad9726ba682244b73be91d2fdb"}, + {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:183a517a3a63503f70f808b58bfbf962f23d73b6dccddae5aa56152ef2bcb232"}, + {file = "psycopg2_binary-2.9.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:15c4e4cfa45f5a60599d9cec5f46cd7b1b29d86a6390ec23e8eebaae84e64554"}, + {file = "psycopg2_binary-2.9.3-cp37-cp37m-win32.whl", hash = "sha256:adf20d9a67e0b6393eac162eb81fb10bc9130a80540f4df7e7355c2dd4af9fba"}, + {file = "psycopg2_binary-2.9.3-cp37-cp37m-win_amd64.whl", hash = "sha256:2f9ffd643bc7349eeb664eba8864d9e01f057880f510e4681ba40a6532f93c71"}, + {file = "psycopg2_binary-2.9.3-cp38-cp38-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:def68d7c21984b0f8218e8a15d514f714d96904265164f75f8d3a70f9c295667"}, + {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dffc08ca91c9ac09008870c9eb77b00a46b3378719584059c034b8945e26b272"}, + {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:280b0bb5cbfe8039205c7981cceb006156a675362a00fe29b16fbc264e242834"}, + {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:af9813db73395fb1fc211bac696faea4ca9ef53f32dc0cfa27e4e7cf766dcf24"}, + {file = "psycopg2_binary-2.9.3-cp38-cp38-manylinux_2_24_ppc64le.whl", hash = "sha256:63638d875be8c2784cfc952c9ac34e2b50e43f9f0a0660b65e2a87d656b3116c"}, + {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ffb7a888a047696e7f8240d649b43fb3644f14f0ee229077e7f6b9f9081635bd"}, + {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:0c9d5450c566c80c396b7402895c4369a410cab5a82707b11aee1e624da7d004"}, + {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:d1c1b569ecafe3a69380a94e6ae09a4789bbb23666f3d3a08d06bbd2451f5ef1"}, + {file = "psycopg2_binary-2.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8fc53f9af09426a61db9ba357865c77f26076d48669f2e1bb24d85a22fb52307"}, + {file = "psycopg2_binary-2.9.3-cp38-cp38-win32.whl", hash = "sha256:6472a178e291b59e7f16ab49ec8b4f3bdada0a879c68d3817ff0963e722a82ce"}, + {file = "psycopg2_binary-2.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:35168209c9d51b145e459e05c31a9eaeffa9a6b0fd61689b48e07464ffd1a83e"}, + {file = "psycopg2_binary-2.9.3-cp39-cp39-macosx_10_14_x86_64.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:47133f3f872faf28c1e87d4357220e809dfd3fa7c64295a4a148bcd1e6e34ec9"}, + {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:91920527dea30175cc02a1099f331aa8c1ba39bf8b7762b7b56cbf54bc5cce42"}, + {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:887dd9aac71765ac0d0bac1d0d4b4f2c99d5f5c1382d8b770404f0f3d0ce8a39"}, + {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:1f14c8b0942714eb3c74e1e71700cbbcb415acbc311c730370e70c578a44a25c"}, + {file = "psycopg2_binary-2.9.3-cp39-cp39-manylinux_2_24_ppc64le.whl", hash = "sha256:7af0dd86ddb2f8af5da57a976d27cd2cd15510518d582b478fbb2292428710b4"}, + {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:93cd1967a18aa0edd4b95b1dfd554cf15af657cb606280996d393dadc88c3c35"}, + {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bda845b664bb6c91446ca9609fc69f7db6c334ec5e4adc87571c34e4f47b7ddb"}, + {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:01310cf4cf26db9aea5158c217caa92d291f0500051a6469ac52166e1a16f5b7"}, + {file = "psycopg2_binary-2.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:99485cab9ba0fa9b84f1f9e1fef106f44a46ef6afdeec8885e0b88d0772b49e8"}, + {file = "psycopg2_binary-2.9.3-cp39-cp39-win32.whl", hash = "sha256:46f0e0a6b5fa5851bbd9ab1bc805eef362d3a230fbdfbc209f4a236d0a7a990d"}, + {file = "psycopg2_binary-2.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:accfe7e982411da3178ec690baaceaad3c278652998b2c45828aaac66cd8285f"}, ] py = [ - {file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"}, - {file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"}, + {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, + {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, ] pycparser = [ - {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, - {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, + {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, + {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] pyparsing = [ - {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, - {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, + {file = "pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"}, + {file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"}, ] pyproj = [ - {file = "pyproj-3.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f942a976ea3de6a519cf48be30a12f465e44d0ac0c38a0d820ab3acfcc0a48a6"}, - {file = "pyproj-3.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:09db64a8088b23f001e574d92bcc3080bf7de44ddca152d0282a2b50c918a64a"}, - {file = "pyproj-3.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:cba99e171d744969e13a865ad28fa9c949c4400b0e9c431a802cdd804f52f632"}, - {file = "pyproj-3.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:81c06df20d09d621e52791c19ce3c880695fb430061e59c2472fa5467e890391"}, - {file = "pyproj-3.0.1-cp36-cp36m-win32.whl", hash = "sha256:3e7e851e6d58c16ac2cd920a1bacb7fbb24758a6fcd7f234d594a88ebae04ec9"}, - {file = "pyproj-3.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:aa0a2981b25145523ca17a643c5be077fe13e514fdca9b6d1c412a95d723a5a5"}, - {file = "pyproj-3.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:708d6e01b9ff3d6dc62a5ad2d2ba1264a863eaa657c1a9bf713a10cc35d34553"}, - {file = "pyproj-3.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:36ba436675f9dea4ab3db7d9a32d3ff11c2fbb4d6690a83454d2f3c5c0b54041"}, - {file = "pyproj-3.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:489a96da87d8846c34c90da90e637544e4f4f50a13589b5aac54297f5ee1b01d"}, - {file = "pyproj-3.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:4a333f3e46fe8b2eb4647a3daa3a2cec52ddc6c107c653b45880526114942ee8"}, - {file = "pyproj-3.0.1-cp37-cp37m-win32.whl", hash = "sha256:9e2ef75401f17062166d3fe53c555cd62c9577697a2f5ded916b23c54e5db497"}, - {file = "pyproj-3.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7bfaa34e8bb0510d4380310374deecd9e4328b9cf556925cfb45b5a94d5bbdbe"}, - {file = "pyproj-3.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9666d01faf4e758ac68f2c16695c90de49c3170e3760988bf76a34aae11f4e15"}, - {file = "pyproj-3.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:c658afc8a6115b58b02aa53d27bf2a67c1b00b55067edb1b7711c6c7391cfaa9"}, - {file = "pyproj-3.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:fee7517bd389a1db7b8bebb18838d04dedca9eaacda01d353d98f5ee421f263e"}, - {file = "pyproj-3.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:86ef2fcd584a3222bf73e2befc24b2badd139b3371f4a1e88649978ef7649540"}, - {file = "pyproj-3.0.1-cp38-cp38-win32.whl", hash = "sha256:d27d40ec541ef69a5107bfcd85f40170e9e122ceb6315ce508cd44d199983d41"}, - {file = "pyproj-3.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:bc70b6adcfa713d89bc561673cb57af5fb3a1718cd7d57ec537430cd1007a864"}, - {file = "pyproj-3.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b845510255f9580d7e226dd3321a51c468cefb7be24e46415caf67caa4287c4"}, - {file = "pyproj-3.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:7ae8e7052f18fde1884574da449010e94fa205ad27aeeaa34a097f49a1ed6a2b"}, - {file = "pyproj-3.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:a3805e026a5547be205a5e322c08e3069f0a48c63bbd53dbc7a8e3499bc66d58"}, - {file = "pyproj-3.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:1be7d54900eb7e2d1e637319080b3a047c70d1fb2f3c12d3400c0fa8a90cf440"}, - {file = "pyproj-3.0.1-cp39-cp39-win32.whl", hash = "sha256:09bead60769e69b592e8cb3ac51b5215f75e9bb9c213ce575031961deb48d6da"}, - {file = "pyproj-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:a3a8ab19232bf4f4bb2590536538881b7bd0c07df23e0c2a792402ca2476c197"}, - {file = "pyproj-3.0.1.tar.gz", hash = "sha256:bfbac35490dd17f706700673506eeb8170f8a2a63fb5878171d4e6eef242d141"}, + {file = "pyproj-3.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2c41c9b7b5e1a1b0acc2b7b2f5de65b226f7b96c870888e4f679ff96322b1ed0"}, + {file = "pyproj-3.3.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0e1fd560b509b722db6566fa9685252f25640e93464d09e13d5190ed7ab491ba"}, + {file = "pyproj-3.3.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277072176a17471c0b1d25d6cae75401d81e9b50ea625ba546f5b79acd757dfc"}, + {file = "pyproj-3.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eca8ecf2b6b3225d93c723e6a2f51143d9195ac407f69e979363cdde344b93bb"}, + {file = "pyproj-3.3.0-cp310-cp310-win32.whl", hash = "sha256:4d2fc49c73d9f34e932bf37926d56916ba1b6f2f693cd4d8cc1d0d9eacc0e537"}, + {file = "pyproj-3.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:ce1adec823738e2d7c6af019fc38f58b4204bacfc782e4430373578c672f3833"}, + {file = "pyproj-3.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e70a1ea6f198cace1a492397bdd0a46e640201120973293d6c48031e370d6a87"}, + {file = "pyproj-3.3.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:99f171da5f885efeec8d7fb2e2557175ffa8834eeb488842b1f52ac78a9a98e5"}, + {file = "pyproj-3.3.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3d28b84913cd849832a8f154c0e0c2ee4618057f7389ee68bfdb2145e7ed78cc"}, + {file = "pyproj-3.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab4baf781721640659db83a6b4da636fc403008f4978c668275754284c946778"}, + {file = "pyproj-3.3.0-cp38-cp38-win32.whl", hash = "sha256:4125e6704751d0e82d8d912d9851da097e8d38599d4c45f9944faaeb21771938"}, + {file = "pyproj-3.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:b15e199c1da8fd132e11dfa68d8cf65d4812dedabc776b308df778ecd0d07658"}, + {file = "pyproj-3.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fcceb6736085bf19291b707bc67c8cebe05330bd02268e9b8eba6d28a1905fce"}, + {file = "pyproj-3.3.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:dbf479bd481774ad217e9db5674868eee8f01dfe3868f61753328895ae7da61a"}, + {file = "pyproj-3.3.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:067a5c6099949edd66e9a10b139af4e2f65ebadb9f59583923a1d3feefac749a"}, + {file = "pyproj-3.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:235b52d8700ffb6be1f3638b1e25d83a9c13edcdb793236d8a98fd39227c5c27"}, + {file = "pyproj-3.3.0-cp39-cp39-win32.whl", hash = "sha256:44b5590c0b8dd002154916e170ef88f57abf91005b34bcb23faef97abb4d42c2"}, + {file = "pyproj-3.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:b48dd9e5736957707fce1d9253fb0772bcf80480198c7790e21fed73fee61240"}, + {file = "pyproj-3.3.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5a105bfe37c78416d2641cd5d3368c99057d041f15f8d51ea3898953b21395c9"}, + {file = "pyproj-3.3.0.tar.gz", hash = "sha256:ce8bfbc212729e9a643f5f5d77f7a93394e032eda1e2d8799ae902d08add747e"}, ] pyrsistent = [ - {file = "pyrsistent-0.18.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f4c8cabb46ff8e5d61f56a037974228e978f26bfefce4f61a4b1ac0ba7a2ab72"}, - {file = "pyrsistent-0.18.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:da6e5e818d18459fa46fac0a4a4e543507fe1110e808101277c5a2b5bab0cd2d"}, - {file = "pyrsistent-0.18.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:5e4395bbf841693eaebaa5bb5c8f5cdbb1d139e07c975c682ec4e4f8126e03d2"}, - {file = "pyrsistent-0.18.0-cp36-cp36m-win32.whl", hash = "sha256:527be2bfa8dc80f6f8ddd65242ba476a6c4fb4e3aedbf281dfbac1b1ed4165b1"}, - {file = "pyrsistent-0.18.0-cp36-cp36m-win_amd64.whl", hash = "sha256:2aaf19dc8ce517a8653746d98e962ef480ff34b6bc563fc067be6401ffb457c7"}, - {file = "pyrsistent-0.18.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58a70d93fb79dc585b21f9d72487b929a6fe58da0754fa4cb9f279bb92369396"}, - {file = "pyrsistent-0.18.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:4916c10896721e472ee12c95cdc2891ce5890898d2f9907b1b4ae0f53588b710"}, - {file = "pyrsistent-0.18.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:73ff61b1411e3fb0ba144b8f08d6749749775fe89688093e1efef9839d2dcc35"}, - {file = "pyrsistent-0.18.0-cp37-cp37m-win32.whl", hash = "sha256:b29b869cf58412ca5738d23691e96d8aff535e17390128a1a52717c9a109da4f"}, - {file = "pyrsistent-0.18.0-cp37-cp37m-win_amd64.whl", hash = "sha256:097b96f129dd36a8c9e33594e7ebb151b1515eb52cceb08474c10a5479e799f2"}, - {file = "pyrsistent-0.18.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:772e94c2c6864f2cd2ffbe58bb3bdefbe2a32afa0acb1a77e472aac831f83427"}, - {file = "pyrsistent-0.18.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:c1a9ff320fa699337e05edcaae79ef8c2880b52720bc031b219e5b5008ebbdef"}, - {file = "pyrsistent-0.18.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cd3caef37a415fd0dae6148a1b6957a8c5f275a62cca02e18474608cb263640c"}, - {file = "pyrsistent-0.18.0-cp38-cp38-win32.whl", hash = "sha256:e79d94ca58fcafef6395f6352383fa1a76922268fa02caa2272fff501c2fdc78"}, - {file = "pyrsistent-0.18.0-cp38-cp38-win_amd64.whl", hash = "sha256:a0c772d791c38bbc77be659af29bb14c38ced151433592e326361610250c605b"}, - {file = "pyrsistent-0.18.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d5ec194c9c573aafaceebf05fc400656722793dac57f254cd4741f3c27ae57b4"}, - {file = "pyrsistent-0.18.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:6b5eed00e597b5b5773b4ca30bd48a5774ef1e96f2a45d105db5b4ebb4bca680"}, - {file = "pyrsistent-0.18.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:48578680353f41dca1ca3dc48629fb77dfc745128b56fc01096b2530c13fd426"}, - {file = "pyrsistent-0.18.0-cp39-cp39-win32.whl", hash = "sha256:f3ef98d7b76da5eb19c37fda834d50262ff9167c65658d1d8f974d2e4d90676b"}, - {file = "pyrsistent-0.18.0-cp39-cp39-win_amd64.whl", hash = "sha256:404e1f1d254d314d55adb8d87f4f465c8693d6f902f67eb6ef5b4526dc58e6ea"}, - {file = "pyrsistent-0.18.0.tar.gz", hash = "sha256:773c781216f8c2900b42a7b638d5b517bb134ae1acbebe4d1e8f1f41ea60eb4b"}, + {file = "pyrsistent-0.18.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:df46c854f490f81210870e509818b729db4488e1f30f2a1ce1698b2295a878d1"}, + {file = "pyrsistent-0.18.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d45866ececf4a5fff8742c25722da6d4c9e180daa7b405dc0a2a2790d668c26"}, + {file = "pyrsistent-0.18.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4ed6784ceac462a7d6fcb7e9b663e93b9a6fb373b7f43594f9ff68875788e01e"}, + {file = "pyrsistent-0.18.1-cp310-cp310-win32.whl", hash = "sha256:e4f3149fd5eb9b285d6bfb54d2e5173f6a116fe19172686797c056672689daf6"}, + {file = "pyrsistent-0.18.1-cp310-cp310-win_amd64.whl", hash = "sha256:636ce2dc235046ccd3d8c56a7ad54e99d5c1cd0ef07d9ae847306c91d11b5fec"}, + {file = "pyrsistent-0.18.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e92a52c166426efbe0d1ec1332ee9119b6d32fc1f0bbfd55d5c1088070e7fc1b"}, + {file = "pyrsistent-0.18.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7a096646eab884bf8bed965bad63ea327e0d0c38989fc83c5ea7b8a87037bfc"}, + {file = "pyrsistent-0.18.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cdfd2c361b8a8e5d9499b9082b501c452ade8bbf42aef97ea04854f4a3f43b22"}, + {file = "pyrsistent-0.18.1-cp37-cp37m-win32.whl", hash = "sha256:7ec335fc998faa4febe75cc5268a9eac0478b3f681602c1f27befaf2a1abe1d8"}, + {file = "pyrsistent-0.18.1-cp37-cp37m-win_amd64.whl", hash = "sha256:6455fc599df93d1f60e1c5c4fe471499f08d190d57eca040c0ea182301321286"}, + {file = "pyrsistent-0.18.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fd8da6d0124efa2f67d86fa70c851022f87c98e205f0594e1fae044e7119a5a6"}, + {file = "pyrsistent-0.18.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bfe2388663fd18bd8ce7db2c91c7400bf3e1a9e8bd7d63bf7e77d39051b85ec"}, + {file = "pyrsistent-0.18.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e3e1fcc45199df76053026a51cc59ab2ea3fc7c094c6627e93b7b44cdae2c8c"}, + {file = "pyrsistent-0.18.1-cp38-cp38-win32.whl", hash = "sha256:b568f35ad53a7b07ed9b1b2bae09eb15cdd671a5ba5d2c66caee40dbf91c68ca"}, + {file = "pyrsistent-0.18.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1b96547410f76078eaf66d282ddca2e4baae8964364abb4f4dcdde855cd123a"}, + {file = "pyrsistent-0.18.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f87cc2863ef33c709e237d4b5f4502a62a00fab450c9e020892e8e2ede5847f5"}, + {file = "pyrsistent-0.18.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bc66318fb7ee012071b2792024564973ecc80e9522842eb4e17743604b5e045"}, + {file = "pyrsistent-0.18.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:914474c9f1d93080338ace89cb2acee74f4f666fb0424896fcfb8d86058bf17c"}, + {file = "pyrsistent-0.18.1-cp39-cp39-win32.whl", hash = "sha256:1b34eedd6812bf4d33814fca1b66005805d3640ce53140ab8bbb1e2651b0d9bc"}, + {file = "pyrsistent-0.18.1-cp39-cp39-win_amd64.whl", hash = "sha256:e24a828f57e0c337c8d8bb9f6b12f09dfdf0273da25fda9e314f0b684b415a07"}, + {file = "pyrsistent-0.18.1.tar.gz", hash = "sha256:d4d61f8b993a7255ba714df3aca52700f8125289f84f704cf80916517c46eb96"}, ] pytest = [ - {file = "pytest-6.2.4-py3-none-any.whl", hash = "sha256:91ef2131a9bd6be8f76f1f08eac5c5317221d6ad1e143ae03894b862e8976890"}, - {file = "pytest-6.2.4.tar.gz", hash = "sha256:50bcad0a0b9c5a72c8e4e7c9855a3ad496ca6a881a3641b4260605450772c54b"}, + {file = "pytest-7.1.1-py3-none-any.whl", hash = "sha256:92f723789a8fdd7180b6b06483874feca4c48a5c76968e03bb3e7f806a1869ea"}, + {file = "pytest-7.1.1.tar.gz", hash = "sha256:841132caef6b1ad17a9afde46dc4f6cfa59a05f9555aae5151f73bdf2820ca63"}, ] pytest-cov = [ - {file = "pytest-cov-2.12.1.tar.gz", hash = "sha256:261ceeb8c227b726249b376b8526b600f38667ee314f910353fa318caa01f4d7"}, - {file = "pytest_cov-2.12.1-py2.py3-none-any.whl", hash = "sha256:261bb9e47e65bd099c89c3edf92972865210c36813f80ede5277dceb77a4a62a"}, -] -python-dateutil = [ - {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, - {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, + {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"}, + {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"}, ] python-dotenv = [ - {file = "python-dotenv-0.14.0.tar.gz", hash = "sha256:8c10c99a1b25d9a68058a1ad6f90381a62ba68230ca93966882a4dbc3bc9c33d"}, - {file = "python_dotenv-0.14.0-py2.py3-none-any.whl", hash = "sha256:c10863aee750ad720f4f43436565e4c1698798d763b63234fb5021b6c616e423"}, -] -python-editor = [ - {file = "python-editor-1.0.4.tar.gz", hash = "sha256:51fda6bcc5ddbbb7063b2af7509e43bd84bfc32a4ff71349ec7847713882327b"}, - {file = "python_editor-1.0.4-py2-none-any.whl", hash = "sha256:5f98b069316ea1c2ed3f67e7f5df6c0d8f10b689964a4a811ff64f0106819ec8"}, - {file = "python_editor-1.0.4-py2.7.egg", hash = "sha256:ea87e17f6ec459e780e4221f295411462e0d0810858e055fc514684350a2f522"}, - {file = "python_editor-1.0.4-py3-none-any.whl", hash = "sha256:1bf6e860a8ad52a14c3ee1252d5dc25b2030618ed80c022598f00176adc8367d"}, - {file = "python_editor-1.0.4-py3.5.egg", hash = "sha256:c3da2053dbab6b29c94e43c486ff67206eafbe7eb52dbec7390b5e2fb05aac77"}, + {file = "python-dotenv-0.20.0.tar.gz", hash = "sha256:b7e3b04a59693c42c36f9ab1cc2acc46fa5df8c78e178fc33a8d4cd05c8d498f"}, + {file = "python_dotenv-0.20.0-py3-none-any.whl", hash = "sha256:d92a187be61fe482e4fd675b6d52200e7be63a12b724abbf931a40ce4fa92938"}, ] pytz = [ - {file = "pytz-2021.1-py2.py3-none-any.whl", hash = "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"}, - {file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"}, + {file = "pytz-2022.1-py2.py3-none-any.whl", hash = "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"}, + {file = "pytz-2022.1.tar.gz", hash = "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7"}, ] pywin32 = [ {file = "pywin32-227-cp27-cp27m-win32.whl", hash = "sha256:371fcc39416d736401f0274dd64c2302728c9e034808e37381b5e1b22be4a6b0"}, @@ -1424,135 +1421,219 @@ pywin32 = [ {file = "pywin32-227-cp39-cp39-win_amd64.whl", hash = "sha256:f27cec5e7f588c3d1051651830ecc00294f90728d19c3bf6916e6dba93ea357c"}, ] pyyaml = [ - {file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"}, - {file = "PyYAML-5.4.1-cp27-cp27m-win32.whl", hash = "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393"}, - {file = "PyYAML-5.4.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8"}, - {file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"}, - {file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"}, - {file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"}, - {file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"}, - {file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"}, - {file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"}, - {file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"}, - {file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"}, - {file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"}, - {file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"}, - {file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"}, - {file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"}, - {file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"}, - {file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"}, - {file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"}, - {file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"}, - {file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"}, - {file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"}, + {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"}, + {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"}, + {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, + {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, + {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, + {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, + {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"}, + {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"}, + {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"}, + {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"}, + {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"}, + {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"}, + {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"}, + {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"}, + {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"}, + {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"}, + {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"}, + {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"}, + {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"}, + {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"}, + {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, + {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, ] redis = [ - {file = "redis-3.5.3-py2.py3-none-any.whl", hash = "sha256:432b788c4530cfe16d8d943a09d40ca6c16149727e4afe8c2c9d5580c59d9f24"}, - {file = "redis-3.5.3.tar.gz", hash = "sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2"}, + {file = "redis-4.2.1-py3-none-any.whl", hash = "sha256:69d05fac17bf3f43937afbb775c536eb516bd21355a4f17d59a966f4a531ce71"}, + {file = "redis-4.2.1.tar.gz", hash = "sha256:fe45513881229dbee610620b9e0817b1f48c47ba635870320fd44a712204bbdd"}, ] requests = [ - {file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"}, - {file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"}, + {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"}, + {file = "requests-2.27.1.tar.gz", hash = "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61"}, ] rq = [ - {file = "rq-1.9.0-py2.py3-none-any.whl", hash = "sha256:7af1e9706dbe6f1eac16dffacd8271ec27c1369950941f14dab6bb08a62979d7"}, - {file = "rq-1.9.0.tar.gz", hash = "sha256:bdfef943de838955e474cfd0e25b9b8c53ed4b9c361fe4bb11cf56d17a87acc5"}, + {file = "rq-1.10.1-py2.py3-none-any.whl", hash = "sha256:92f4cf38b2364c1697b541e77c0fe62b7e5242fa864324f262be126ee2a07e3a"}, + {file = "rq-1.10.1.tar.gz", hash = "sha256:62d06b44c3acfa5d1933c5a4ec3fbc2484144a8af60e318d0b8447c5236271e2"}, ] shapely = [ - {file = "Shapely-1.7.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:4c10f317e379cc404f8fc510cd9982d5d3e7ba13a9cfd39aa251d894c6366798"}, - {file = "Shapely-1.7.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:17df66e87d0fe0193910aeaa938c99f0b04f67b430edb8adae01e7be557b141b"}, - {file = "Shapely-1.7.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:da38ed3d65b8091447dc3717e5218cc336d20303b77b0634b261bc5c1aa2bae8"}, - {file = "Shapely-1.7.1-cp35-cp35m-win32.whl", hash = "sha256:8e7659dd994792a0aad8fb80439f59055a21163e236faf2f9823beb63a380e19"}, - {file = "Shapely-1.7.1-cp35-cp35m-win_amd64.whl", hash = "sha256:791477edb422692e7dc351c5ed6530eb0e949a31b45569946619a0d9cd5f53cb"}, - {file = "Shapely-1.7.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e3afccf0437edc108eef1e2bb9cc4c7073e7705924eb4cd0bf7715cd1ef0ce1b"}, - {file = "Shapely-1.7.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8f15b6ce67dcc05b61f19c689b60f3fe58550ba994290ff8332f711f5aaa9840"}, - {file = "Shapely-1.7.1-cp36-cp36m-win32.whl", hash = "sha256:60e5b2282619249dbe8dc5266d781cc7d7fb1b27fa49f8241f2167672ad26719"}, - {file = "Shapely-1.7.1-cp36-cp36m-win_amd64.whl", hash = "sha256:de618e67b64a51a0768d26a9963ecd7d338a2cf6e9e7582d2385f88ad005b3d1"}, - {file = "Shapely-1.7.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:182716ffb500d114b5d1b75d7fd9d14b7d3414cef3c38c0490534cc9ce20981a"}, - {file = "Shapely-1.7.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:4f3c59f6dbf86a9fc293546de492f5e07344e045f9333f3a753f2dda903c45d1"}, - {file = "Shapely-1.7.1-cp37-cp37m-win32.whl", hash = "sha256:6871acba8fbe744efa4f9f34e726d070bfbf9bffb356a8f6d64557846324232b"}, - {file = "Shapely-1.7.1-cp37-cp37m-win_amd64.whl", hash = "sha256:35be1c5d869966569d3dfd4ec31832d7c780e9df760e1fe52131105685941891"}, - {file = "Shapely-1.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:052eb5b9ba756808a7825e8a8020fb146ec489dd5c919e7d139014775411e688"}, - {file = "Shapely-1.7.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:90a3e2ae0d6d7d50ff2370ba168fbd416a53e7d8448410758c5d6a5920646c1d"}, - {file = "Shapely-1.7.1-cp38-cp38-win32.whl", hash = "sha256:a3774516c8a83abfd1ddffb8b6ec1b0935d7fe6ea0ff5c31a18bfdae567b4eba"}, - {file = "Shapely-1.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:6593026cd3f5daaea12bcc51ae5c979318070fefee210e7990cb8ac2364e79a1"}, - {file = "Shapely-1.7.1.tar.gz", hash = "sha256:1641724c1055459a7e2b8bbe47ba25bdc89554582e62aec23cb3f3ca25f9b129"}, + {file = "Shapely-1.8.1.post1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0ca96a3314b7a38a3bb385531469de1fcf2b2c2979ec2aa4f37b4c70632cf1ad"}, + {file = "Shapely-1.8.1.post1-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:493902923fdd135316161a4ece5294ba3ce81accaa54540d2af3b93f7231143a"}, + {file = "Shapely-1.8.1.post1-cp310-cp310-win_amd64.whl", hash = "sha256:b82fc74d5efb11a71283c4ed69b4e036997cc70db4b73c646207ddf0476ade44"}, + {file = "Shapely-1.8.1.post1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:89bc5f3abc1ccbc7682c2e1664153c4f8f125fa9c24bff4abca48685739d5636"}, + {file = "Shapely-1.8.1.post1-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:44cb895b1710f7559c28d69dfa08cafe4f58cd4b7a87091a55bdf6711ad9ad66"}, + {file = "Shapely-1.8.1.post1-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:437fff3b6274be26ffa3e450de711ee01e436324b5a405952add2146227e3eb5"}, + {file = "Shapely-1.8.1.post1-cp36-cp36m-win32.whl", hash = "sha256:dc0f46212f84c57d13189fc33cf61e13eee292704d7652e931e4b51c54b0c73c"}, + {file = "Shapely-1.8.1.post1-cp36-cp36m-win_amd64.whl", hash = "sha256:9248aad099ecf228fbdd877b0c668823dd83c48798cf04d49a1be75167e3a7ce"}, + {file = "Shapely-1.8.1.post1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:bab5ff7c576588acccd665ecce2a0fe7b47d4ce0398f2d5c1e5b2e27d09398d2"}, + {file = "Shapely-1.8.1.post1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2381ce0aff67d569eb509bcc051264aa5fbdc1fdd54f4c09963d0e09f16a8f1b"}, + {file = "Shapely-1.8.1.post1-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b4d35e72022b2dbf152d476b0362596011c674ff68be9fc8f2e68e71d86502ca"}, + {file = "Shapely-1.8.1.post1-cp37-cp37m-win32.whl", hash = "sha256:5a420e7112b55a1587412a5b03ebf59e302ddd354da68516d3721718f6b8a7c5"}, + {file = "Shapely-1.8.1.post1-cp37-cp37m-win_amd64.whl", hash = "sha256:c4c366e18edf91196a399f8f0f046f93516002e6d8af0b57c23e7c7d91944b16"}, + {file = "Shapely-1.8.1.post1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2020fda37c708d44a613c020cea09e81e476f96866f348afc2601e66c0e71db1"}, + {file = "Shapely-1.8.1.post1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:69d5352fb977655c85d2f40a05ae24fc5053cccee77d0a8b1f773e54804e723e"}, + {file = "Shapely-1.8.1.post1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:83f3c8191d30ae0e3dd557434c48ca591d75342d5a3f42fc5148ec42796be624"}, + {file = "Shapely-1.8.1.post1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3e792635e92c9aacd1452a589a4fa2970114b6a9b1165e09655481f6e58970f5"}, + {file = "Shapely-1.8.1.post1-cp38-cp38-win32.whl", hash = "sha256:8cf7331f61780506976fe2175e069d898e1b04ace73be21aad55c3ee92e58e3a"}, + {file = "Shapely-1.8.1.post1-cp38-cp38-win_amd64.whl", hash = "sha256:f109064bdb0753a6bac6238538cfeeb4a09739e2d556036b343b2eabeb9520b2"}, + {file = "Shapely-1.8.1.post1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:aea1e87450adffba3d04ccbaa790df719bb7aa23b05ac797ad16be236a5d0db8"}, + {file = "Shapely-1.8.1.post1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3a3602ba2e7715ddd5d4114173dec83d3181bfb2497e8589676c284aa739fd67"}, + {file = "Shapely-1.8.1.post1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:679789d774cfe09ca05118cab78c0a6a42985b3ed23bc93606272a4509b4df28"}, + {file = "Shapely-1.8.1.post1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:363df36370f28fdc7789857929f6ff27e659f64087b4c89f7a47ed43bd3bfe4d"}, + {file = "Shapely-1.8.1.post1-cp39-cp39-win32.whl", hash = "sha256:bc6063875182515d3888180cc4cbdbaa6443e4a4386c4bb25499e9875b75dcac"}, + {file = "Shapely-1.8.1.post1-cp39-cp39-win_amd64.whl", hash = "sha256:54aeb2a57978ce731fd52289d0e1deee7c232d41aed53091f38776378f644184"}, + {file = "Shapely-1.8.1.post1.tar.gz", hash = "sha256:93ff06ff05fbe2be843b93c7b1ad8292e56e665ba01b4708f75ae8a757972e9f"}, ] six = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] sqlalchemy = [ - {file = "SQLAlchemy-1.3.24-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:87a2725ad7d41cd7376373c15fd8bf674e9c33ca56d0b8036add2d634dba372e"}, - {file = "SQLAlchemy-1.3.24-cp27-cp27m-win32.whl", hash = "sha256:f597a243b8550a3a0b15122b14e49d8a7e622ba1c9d29776af741f1845478d79"}, - {file = "SQLAlchemy-1.3.24-cp27-cp27m-win_amd64.whl", hash = "sha256:fc4cddb0b474b12ed7bdce6be1b9edc65352e8ce66bc10ff8cbbfb3d4047dbf4"}, - {file = "SQLAlchemy-1.3.24-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:f1149d6e5c49d069163e58a3196865e4321bad1803d7886e07d8710de392c548"}, - {file = "SQLAlchemy-1.3.24-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:14f0eb5db872c231b20c18b1e5806352723a3a89fb4254af3b3e14f22eaaec75"}, - {file = "SQLAlchemy-1.3.24-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:e98d09f487267f1e8d1179bf3b9d7709b30a916491997137dd24d6ae44d18d79"}, - {file = "SQLAlchemy-1.3.24-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:fc1f2a5a5963e2e73bac4926bdaf7790c4d7d77e8fc0590817880e22dd9d0b8b"}, - {file = "SQLAlchemy-1.3.24-cp35-cp35m-win32.whl", hash = "sha256:f3c5c52f7cb8b84bfaaf22d82cb9e6e9a8297f7c2ed14d806a0f5e4d22e83fb7"}, - {file = "SQLAlchemy-1.3.24-cp35-cp35m-win_amd64.whl", hash = "sha256:0352db1befcbed2f9282e72843f1963860bf0e0472a4fa5cf8ee084318e0e6ab"}, - {file = "SQLAlchemy-1.3.24-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:2ed6343b625b16bcb63c5b10523fd15ed8934e1ed0f772c534985e9f5e73d894"}, - {file = "SQLAlchemy-1.3.24-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:34fcec18f6e4b24b4a5f6185205a04f1eab1e56f8f1d028a2a03694ebcc2ddd4"}, - {file = "SQLAlchemy-1.3.24-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:e47e257ba5934550d7235665eee6c911dc7178419b614ba9e1fbb1ce6325b14f"}, - {file = "SQLAlchemy-1.3.24-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:816de75418ea0953b5eb7b8a74933ee5a46719491cd2b16f718afc4b291a9658"}, - {file = "SQLAlchemy-1.3.24-cp36-cp36m-win32.whl", hash = "sha256:26155ea7a243cbf23287f390dba13d7927ffa1586d3208e0e8d615d0c506f996"}, - {file = "SQLAlchemy-1.3.24-cp36-cp36m-win_amd64.whl", hash = "sha256:f03bd97650d2e42710fbe4cf8a59fae657f191df851fc9fc683ecef10746a375"}, - {file = "SQLAlchemy-1.3.24-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:a006d05d9aa052657ee3e4dc92544faae5fcbaafc6128217310945610d862d39"}, - {file = "SQLAlchemy-1.3.24-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:1e2f89d2e5e3c7a88e25a3b0e43626dba8db2aa700253023b82e630d12b37109"}, - {file = "SQLAlchemy-1.3.24-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:0d5d862b1cfbec5028ce1ecac06a3b42bc7703eb80e4b53fceb2738724311443"}, - {file = "SQLAlchemy-1.3.24-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:0172423a27fbcae3751ef016663b72e1a516777de324a76e30efa170dbd3dd2d"}, - {file = "SQLAlchemy-1.3.24-cp37-cp37m-win32.whl", hash = "sha256:d37843fb8df90376e9e91336724d78a32b988d3d20ab6656da4eb8ee3a45b63c"}, - {file = "SQLAlchemy-1.3.24-cp37-cp37m-win_amd64.whl", hash = "sha256:c10ff6112d119f82b1618b6dc28126798481b9355d8748b64b9b55051eb4f01b"}, - {file = "SQLAlchemy-1.3.24-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:861e459b0e97673af6cc5e7f597035c2e3acdfb2608132665406cded25ba64c7"}, - {file = "SQLAlchemy-1.3.24-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:5de2464c254380d8a6c20a2746614d5a436260be1507491442cf1088e59430d2"}, - {file = "SQLAlchemy-1.3.24-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:d375d8ccd3cebae8d90270f7aa8532fe05908f79e78ae489068f3b4eee5994e8"}, - {file = "SQLAlchemy-1.3.24-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:014ea143572fee1c18322b7908140ad23b3994036ef4c0d630110faf942652f8"}, - {file = "SQLAlchemy-1.3.24-cp38-cp38-win32.whl", hash = "sha256:6607ae6cd3a07f8a4c3198ffbf256c261661965742e2b5265a77cd5c679c9bba"}, - {file = "SQLAlchemy-1.3.24-cp38-cp38-win_amd64.whl", hash = "sha256:fcb251305fa24a490b6a9ee2180e5f8252915fb778d3dafc70f9cc3f863827b9"}, - {file = "SQLAlchemy-1.3.24-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:01aa5f803db724447c1d423ed583e42bf5264c597fd55e4add4301f163b0be48"}, - {file = "SQLAlchemy-1.3.24-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:4d0e3515ef98aa4f0dc289ff2eebb0ece6260bbf37c2ea2022aad63797eacf60"}, - {file = "SQLAlchemy-1.3.24-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:bce28277f308db43a6b4965734366f533b3ff009571ec7ffa583cb77539b84d6"}, - {file = "SQLAlchemy-1.3.24-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:8110e6c414d3efc574543109ee618fe2c1f96fa31833a1ff36cc34e968c4f233"}, - {file = "SQLAlchemy-1.3.24-cp39-cp39-win32.whl", hash = "sha256:ee5f5188edb20a29c1cc4a039b074fdc5575337c9a68f3063449ab47757bb064"}, - {file = "SQLAlchemy-1.3.24-cp39-cp39-win_amd64.whl", hash = "sha256:09083c2487ca3c0865dc588e07aeaa25416da3d95f7482c07e92f47e080aa17b"}, - {file = "SQLAlchemy-1.3.24.tar.gz", hash = "sha256:ebbb777cbf9312359b897bf81ba00dae0f5cb69fba2a18265dcc18a6f5ef7519"}, + {file = "SQLAlchemy-1.4.34-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:c025d45318b73c0601cca451532556cbab532b2742839ebb8cb58f9ebf06811e"}, + {file = "SQLAlchemy-1.4.34-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cd5cffd1dd753828f1069f33062f3896e51c990acd957c264f40e051b3e19887"}, + {file = "SQLAlchemy-1.4.34-cp27-cp27m-win32.whl", hash = "sha256:a47bf6b7ca6c28e4f4e262fabcf5be6b907af81be36de77839c9eeda2cdf3bb3"}, + {file = "SQLAlchemy-1.4.34-cp27-cp27m-win_amd64.whl", hash = "sha256:c9218e3519398129e364121e0d89823e6ba2a2b77c28bfc661face0829c41433"}, + {file = "SQLAlchemy-1.4.34-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7ee14a7f9f76d1ef9d5e5b760c9252617c839b87eee04d1ce8325ac66ae155c4"}, + {file = "SQLAlchemy-1.4.34-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:4414ace6e3a5e39523e55a5d9f3b215699b2ead4ff91fca98f1b659b7ab2d92a"}, + {file = "SQLAlchemy-1.4.34-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a6cfd468f54d65324fd3847cfd0148b0610efa6a43e5f5fcc89f455696ae9e7"}, + {file = "SQLAlchemy-1.4.34-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:27a42894a2751e438eaed12fc0dcfe741ff2f66c14760d081222c5adc5460064"}, + {file = "SQLAlchemy-1.4.34-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:671f61c3db4595b0e86cc4b30f675a7c0206d9ce99f041b4f6761c7ddd1e0074"}, + {file = "SQLAlchemy-1.4.34-cp310-cp310-win32.whl", hash = "sha256:3ebb97ed96f4506e2f212e1fcf0ec07a103bb194938627660a5acb4d9feae49c"}, + {file = "SQLAlchemy-1.4.34-cp310-cp310-win_amd64.whl", hash = "sha256:d8efcaa709ea8e7c08c3d3e7639c39b36083f5a995f397f9e6eedf5f5e4e4946"}, + {file = "SQLAlchemy-1.4.34-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:a4fb5c6ee84a6bba4ff6f9f5379f0b3a0ffe9de7ba5a0945659b3da8d519709b"}, + {file = "SQLAlchemy-1.4.34-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07f4dab2deb6d34618a2ccfff3971a85923ad7c3a9a45401818870fc51d3f0cc"}, + {file = "SQLAlchemy-1.4.34-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:67c1c27c48875afc950bee5ee24582794f20b545e64e4f9ca94071a9b514d6ed"}, + {file = "SQLAlchemy-1.4.34-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:954ea8c527c4322afb6885944904714893af81fe9167e421273770991bf08a4a"}, + {file = "SQLAlchemy-1.4.34-cp36-cp36m-win32.whl", hash = "sha256:2a3e4dc7c452ba3c0f3175ad5a8e0ba49c2b0570a8d07272cf50844c8d78e74f"}, + {file = "SQLAlchemy-1.4.34-cp36-cp36m-win_amd64.whl", hash = "sha256:f47996b1810894f766c9ee689607077c6c0e0fd6761e04c12ba13efb56d50c1d"}, + {file = "SQLAlchemy-1.4.34-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:b34bbc683789559f1bc9bb685fc162e0956dbbdfbe2fbd6755a9f5982c113610"}, + {file = "SQLAlchemy-1.4.34-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:804cf491437f3e4ce31247ab4b309b181f06ecc97d309b746d10f09439b4eb85"}, + {file = "SQLAlchemy-1.4.34-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f197c66663ed0f9e1178d51141d864688fb244a83f6b17f667d521e482537b2e"}, + {file = "SQLAlchemy-1.4.34-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08aaad905aba8940f27aeb9f1f851bf63f18ef97b0062ca41f64afc4b64e0e8c"}, + {file = "SQLAlchemy-1.4.34-cp37-cp37m-win32.whl", hash = "sha256:345306707bb0e51e7cd6e7573adafbce018894ee5e3b9c31134545f704936db0"}, + {file = "SQLAlchemy-1.4.34-cp37-cp37m-win_amd64.whl", hash = "sha256:50174e173d03209c34e07e7b57cca48d0082ac2390edf927aafc706c111da11e"}, + {file = "SQLAlchemy-1.4.34-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:878c7beaafa365602762c19f638282e1885454fed1aed86f8fae038933c7c671"}, + {file = "SQLAlchemy-1.4.34-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70048a83f0a1ece1fcd7189891c888e20af2c57fbd33eb760d8cece9843b896c"}, + {file = "SQLAlchemy-1.4.34-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:621d3f6c0ba2407bb97e82b649be5ca7d5b6c201dcfb964ce13f517bf1cb6305"}, + {file = "SQLAlchemy-1.4.34-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:045d6a26c262929af0b9cb25441aae675ac04db4ea8bd2446b355617cd6b6b7d"}, + {file = "SQLAlchemy-1.4.34-cp38-cp38-win32.whl", hash = "sha256:e297a5cc625e3f1367a82deedf2d48ee4d2b2bd263b8b8d2efbaaf5608b5229e"}, + {file = "SQLAlchemy-1.4.34-cp38-cp38-win_amd64.whl", hash = "sha256:36f08d94670315ca04c8139bd80b3e02b9dd9cc66fc11bcb96fd10ad51a051ab"}, + {file = "SQLAlchemy-1.4.34-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:40b995d7aeeb6f88a1927ce6692c0f626b59d8effd3e1d597f125e141707b37c"}, + {file = "SQLAlchemy-1.4.34-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb6558ba07409dafa18c793c34292b3265be455904966f0724c10198829477e3"}, + {file = "SQLAlchemy-1.4.34-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e67278ceb63270cdac0a7b89fc3c29a56f7dac9616a7ee48e7ad6b52e3b631e5"}, + {file = "SQLAlchemy-1.4.34-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50107d8183da3fbe5715957aa3954cd9d82aed555c5b4d3fd37fac861af422fa"}, + {file = "SQLAlchemy-1.4.34-cp39-cp39-win32.whl", hash = "sha256:c3ad7f5b61ba014f5045912aea15b03c473bb02b1c07fd92c9d2c794fa183276"}, + {file = "SQLAlchemy-1.4.34-cp39-cp39-win_amd64.whl", hash = "sha256:5e88912bf192e7b5739c446d2276e1cba74cfa6c1c93eea2b2534404f6be1dbd"}, + {file = "SQLAlchemy-1.4.34.tar.gz", hash = "sha256:623bac2d6bdca3f3e61cf1e1c466c5fb9f5cf08735736ee1111187b7a4108891"}, ] sqlalchemy-utils = [ - {file = "SQLAlchemy-Utils-0.36.8.tar.gz", hash = "sha256:fb66e9956e41340011b70b80f898fde6064ec1817af77199ee21ace71d7d6ab0"}, + {file = "SQLAlchemy-Utils-0.38.2.tar.gz", hash = "sha256:9e01d6d3fb52d3926fcd4ea4a13f3540701b751aced0316bff78264402c2ceb4"}, + {file = "SQLAlchemy_Utils-0.38.2-py3-none-any.whl", hash = "sha256:622235b1598f97300e4d08820ab024f5219c9a6309937a8b908093f487b4ba54"}, ] toml = [ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, ] -typing-extensions = [ - {file = "typing_extensions-3.10.0.0-py2-none-any.whl", hash = "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497"}, - {file = "typing_extensions-3.10.0.0-py3-none-any.whl", hash = "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"}, - {file = "typing_extensions-3.10.0.0.tar.gz", hash = "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342"}, +tomli = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] urllib3 = [ - {file = "urllib3-1.26.6-py2.py3-none-any.whl", hash = "sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4"}, - {file = "urllib3-1.26.6.tar.gz", hash = "sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f"}, + {file = "urllib3-1.26.9-py2.py3-none-any.whl", hash = "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14"}, + {file = "urllib3-1.26.9.tar.gz", hash = "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e"}, ] virtualenv = [ - {file = "virtualenv-20.6.0-py2.py3-none-any.whl", hash = "sha256:e4fc84337dce37ba34ef520bf2d4392b392999dbe47df992870dc23230f6b758"}, - {file = "virtualenv-20.6.0.tar.gz", hash = "sha256:51df5d8a2fad5d1b13e088ff38a433475768ff61f202356bb9812c454c20ae45"}, + {file = "virtualenv-20.14.0-py2.py3-none-any.whl", hash = "sha256:1e8588f35e8b42c6ec6841a13c5e88239de1e6e4e4cedfd3916b306dc826ec66"}, + {file = "virtualenv-20.14.0.tar.gz", hash = "sha256:8e5b402037287126e81ccde9432b95a8be5b19d36584f64957060a3488c11ca8"}, ] websocket-client = [ - {file = "websocket-client-1.1.0.tar.gz", hash = "sha256:b68e4959d704768fa20e35c9d508c8dc2bbc041fd8d267c0d7345cffe2824568"}, - {file = "websocket_client-1.1.0-py2.py3-none-any.whl", hash = "sha256:e5c333bfa9fa739538b652b6f8c8fc2559f1d364243c8a689d7c0e1d41c2e611"}, + {file = "websocket-client-1.3.2.tar.gz", hash = "sha256:50b21db0058f7a953d67cc0445be4b948d7fc196ecbeb8083d68d94628e4abf6"}, + {file = "websocket_client-1.3.2-py3-none-any.whl", hash = "sha256:722b171be00f2b90e1d4fb2f2b53146a536ca38db1da8ff49c972a4e1365d0ef"}, ] werkzeug = [ - {file = "Werkzeug-1.0.1-py2.py3-none-any.whl", hash = "sha256:2de2a5db0baeae7b2d2664949077c2ac63fbd16d98da0ff71837f7d1dea3fd43"}, - {file = "Werkzeug-1.0.1.tar.gz", hash = "sha256:6c80b1e5ad3665290ea39320b91e1be1e0d5f60652b964a3070216de83d2e47c"}, -] -yapf = [ - {file = "yapf-0.30.0-py2.py3-none-any.whl", hash = "sha256:3abf61ba67cf603069710d30acbc88cfe565d907e16ad81429ae90ce9651e0c9"}, - {file = "yapf-0.30.0.tar.gz", hash = "sha256:3000abee4c28daebad55da6c85f3cd07b8062ce48e2e9943c8da1b9667d48427"}, + {file = "Werkzeug-2.1.0-py3-none-any.whl", hash = "sha256:094ecfc981948f228b30ee09dbfe250e474823b69b9b1292658301b5894bbf08"}, + {file = "Werkzeug-2.1.0.tar.gz", hash = "sha256:9b55466a3e99e13b1f0686a66117d39bda85a992166e0a79aedfcf3586328f7a"}, +] +wrapt = [ + {file = "wrapt-1.14.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:5a9a1889cc01ed2ed5f34574c90745fab1dd06ec2eee663e8ebeefe363e8efd7"}, + {file = "wrapt-1.14.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:9a3ff5fb015f6feb78340143584d9f8a0b91b6293d6b5cf4295b3e95d179b88c"}, + {file = "wrapt-1.14.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:4b847029e2d5e11fd536c9ac3136ddc3f54bc9488a75ef7d040a3900406a91eb"}, + {file = "wrapt-1.14.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:9a5a544861b21e0e7575b6023adebe7a8c6321127bb1d238eb40d99803a0e8bd"}, + {file = "wrapt-1.14.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:88236b90dda77f0394f878324cfbae05ae6fde8a84d548cfe73a75278d760291"}, + {file = "wrapt-1.14.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f0408e2dbad9e82b4c960274214af533f856a199c9274bd4aff55d4634dedc33"}, + {file = "wrapt-1.14.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:9d8c68c4145041b4eeae96239802cfdfd9ef927754a5be3f50505f09f309d8c6"}, + {file = "wrapt-1.14.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:22626dca56fd7f55a0733e604f1027277eb0f4f3d95ff28f15d27ac25a45f71b"}, + {file = "wrapt-1.14.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:65bf3eb34721bf18b5a021a1ad7aa05947a1767d1aa272b725728014475ea7d5"}, + {file = "wrapt-1.14.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:09d16ae7a13cff43660155383a2372b4aa09109c7127aa3f24c3cf99b891c330"}, + {file = "wrapt-1.14.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:debaf04f813ada978d7d16c7dfa16f3c9c2ec9adf4656efdc4defdf841fc2f0c"}, + {file = "wrapt-1.14.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:748df39ed634851350efa87690c2237a678ed794fe9ede3f0d79f071ee042561"}, + {file = "wrapt-1.14.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1807054aa7b61ad8d8103b3b30c9764de2e9d0c0978e9d3fc337e4e74bf25faa"}, + {file = "wrapt-1.14.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:763a73ab377390e2af26042f685a26787c402390f682443727b847e9496e4a2a"}, + {file = "wrapt-1.14.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8529b07b49b2d89d6917cfa157d3ea1dfb4d319d51e23030664a827fe5fd2131"}, + {file = "wrapt-1.14.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:68aeefac31c1f73949662ba8affaf9950b9938b712fb9d428fa2a07e40ee57f8"}, + {file = "wrapt-1.14.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59d7d92cee84a547d91267f0fea381c363121d70fe90b12cd88241bd9b0e1763"}, + {file = "wrapt-1.14.0-cp310-cp310-win32.whl", hash = "sha256:3a88254881e8a8c4784ecc9cb2249ff757fd94b911d5df9a5984961b96113fff"}, + {file = "wrapt-1.14.0-cp310-cp310-win_amd64.whl", hash = "sha256:9a242871b3d8eecc56d350e5e03ea1854de47b17f040446da0e47dc3e0b9ad4d"}, + {file = "wrapt-1.14.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:a65bffd24409454b889af33b6c49d0d9bcd1a219b972fba975ac935f17bdf627"}, + {file = "wrapt-1.14.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9d9fcd06c952efa4b6b95f3d788a819b7f33d11bea377be6b8980c95e7d10775"}, + {file = "wrapt-1.14.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:db6a0ddc1282ceb9032e41853e659c9b638789be38e5b8ad7498caac00231c23"}, + {file = "wrapt-1.14.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:14e7e2c5f5fca67e9a6d5f753d21f138398cad2b1159913ec9e9a67745f09ba3"}, + {file = "wrapt-1.14.0-cp35-cp35m-win32.whl", hash = "sha256:6d9810d4f697d58fd66039ab959e6d37e63ab377008ef1d63904df25956c7db0"}, + {file = "wrapt-1.14.0-cp35-cp35m-win_amd64.whl", hash = "sha256:d808a5a5411982a09fef6b49aac62986274ab050e9d3e9817ad65b2791ed1425"}, + {file = "wrapt-1.14.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b77159d9862374da213f741af0c361720200ab7ad21b9f12556e0eb95912cd48"}, + {file = "wrapt-1.14.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36a76a7527df8583112b24adc01748cd51a2d14e905b337a6fefa8b96fc708fb"}, + {file = "wrapt-1.14.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0057b5435a65b933cbf5d859cd4956624df37b8bf0917c71756e4b3d9958b9e"}, + {file = "wrapt-1.14.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a0a4ca02752ced5f37498827e49c414d694ad7cf451ee850e3ff160f2bee9d3"}, + {file = "wrapt-1.14.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:8c6be72eac3c14baa473620e04f74186c5d8f45d80f8f2b4eda6e1d18af808e8"}, + {file = "wrapt-1.14.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:21b1106bff6ece8cb203ef45b4f5778d7226c941c83aaaa1e1f0f4f32cc148cd"}, + {file = "wrapt-1.14.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:493da1f8b1bb8a623c16552fb4a1e164c0200447eb83d3f68b44315ead3f9036"}, + {file = "wrapt-1.14.0-cp36-cp36m-win32.whl", hash = "sha256:89ba3d548ee1e6291a20f3c7380c92f71e358ce8b9e48161401e087e0bc740f8"}, + {file = "wrapt-1.14.0-cp36-cp36m-win_amd64.whl", hash = "sha256:729d5e96566f44fccac6c4447ec2332636b4fe273f03da128fff8d5559782b06"}, + {file = "wrapt-1.14.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:891c353e95bb11abb548ca95c8b98050f3620a7378332eb90d6acdef35b401d4"}, + {file = "wrapt-1.14.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23f96134a3aa24cc50614920cc087e22f87439053d886e474638c68c8d15dc80"}, + {file = "wrapt-1.14.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6807bcee549a8cb2f38f73f469703a1d8d5d990815c3004f21ddb68a567385ce"}, + {file = "wrapt-1.14.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6915682f9a9bc4cf2908e83caf5895a685da1fbd20b6d485dafb8e218a338279"}, + {file = "wrapt-1.14.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f2f3bc7cd9c9fcd39143f11342eb5963317bd54ecc98e3650ca22704b69d9653"}, + {file = "wrapt-1.14.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:3a71dbd792cc7a3d772ef8cd08d3048593f13d6f40a11f3427c000cf0a5b36a0"}, + {file = "wrapt-1.14.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5a0898a640559dec00f3614ffb11d97a2666ee9a2a6bad1259c9facd01a1d4d9"}, + {file = "wrapt-1.14.0-cp37-cp37m-win32.whl", hash = "sha256:167e4793dc987f77fd476862d32fa404d42b71f6a85d3b38cbce711dba5e6b68"}, + {file = "wrapt-1.14.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d066ffc5ed0be00cd0352c95800a519cf9e4b5dd34a028d301bdc7177c72daf3"}, + {file = "wrapt-1.14.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d9bdfa74d369256e4218000a629978590fd7cb6cf6893251dad13d051090436d"}, + {file = "wrapt-1.14.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2498762814dd7dd2a1d0248eda2afbc3dd9c11537bc8200a4b21789b6df6cd38"}, + {file = "wrapt-1.14.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f24ca7953f2643d59a9c87d6e272d8adddd4a53bb62b9208f36db408d7aafc7"}, + {file = "wrapt-1.14.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b835b86bd5a1bdbe257d610eecab07bf685b1af2a7563093e0e69180c1d4af1"}, + {file = "wrapt-1.14.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b21650fa6907e523869e0396c5bd591cc326e5c1dd594dcdccac089561cacfb8"}, + {file = "wrapt-1.14.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:354d9fc6b1e44750e2a67b4b108841f5f5ea08853453ecbf44c81fdc2e0d50bd"}, + {file = "wrapt-1.14.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1f83e9c21cd5275991076b2ba1cd35418af3504667affb4745b48937e214bafe"}, + {file = "wrapt-1.14.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:61e1a064906ccba038aa3c4a5a82f6199749efbbb3cef0804ae5c37f550eded0"}, + {file = "wrapt-1.14.0-cp38-cp38-win32.whl", hash = "sha256:28c659878f684365d53cf59dc9a1929ea2eecd7ac65da762be8b1ba193f7e84f"}, + {file = "wrapt-1.14.0-cp38-cp38-win_amd64.whl", hash = "sha256:b0ed6ad6c9640671689c2dbe6244680fe8b897c08fd1fab2228429b66c518e5e"}, + {file = "wrapt-1.14.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b3f7e671fb19734c872566e57ce7fc235fa953d7c181bb4ef138e17d607dc8a1"}, + {file = "wrapt-1.14.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:87fa943e8bbe40c8c1ba4086971a6fefbf75e9991217c55ed1bcb2f1985bd3d4"}, + {file = "wrapt-1.14.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4775a574e9d84e0212f5b18886cace049a42e13e12009bb0491562a48bb2b758"}, + {file = "wrapt-1.14.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9d57677238a0c5411c76097b8b93bdebb02eb845814c90f0b01727527a179e4d"}, + {file = "wrapt-1.14.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00108411e0f34c52ce16f81f1d308a571df7784932cc7491d1e94be2ee93374b"}, + {file = "wrapt-1.14.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d332eecf307fca852d02b63f35a7872de32d5ba8b4ec32da82f45df986b39ff6"}, + {file = "wrapt-1.14.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:01f799def9b96a8ec1ef6b9c1bbaf2bbc859b87545efbecc4a78faea13d0e3a0"}, + {file = "wrapt-1.14.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47045ed35481e857918ae78b54891fac0c1d197f22c95778e66302668309336c"}, + {file = "wrapt-1.14.0-cp39-cp39-win32.whl", hash = "sha256:2eca15d6b947cfff51ed76b2d60fd172c6ecd418ddab1c5126032d27f74bc350"}, + {file = "wrapt-1.14.0-cp39-cp39-win_amd64.whl", hash = "sha256:bb36fbb48b22985d13a6b496ea5fb9bb2a076fea943831643836c9f6febbcfdc"}, + {file = "wrapt-1.14.0.tar.gz", hash = "sha256:8323a43bd9c91f62bb7d4be74cc9ff10090e7ef820e27bfe8815c57e68261311"}, ] zipp = [ - {file = "zipp-3.5.0-py3-none-any.whl", hash = "sha256:957cfda87797e389580cb8b9e3870841ca991e2125350677b2ca83a0e99390a3"}, - {file = "zipp-3.5.0.tar.gz", hash = "sha256:f5812b1e007e48cff63449a5e9f4e7ebea716b4111f9c4f9a645f91d579bf0c4"}, + {file = "zipp-3.7.0-py3-none-any.whl", hash = "sha256:b47250dd24f92b7dd6a0a8fc5244da14608f3ca90a5efcd37a3b1642fac9a375"}, + {file = "zipp-3.7.0.tar.gz", hash = "sha256:9f50f446828eb9d45b267433fd3e9da8d801f614129124863f9c51ebceafb87d"}, ] "zope.event" = [ {file = "zope.event-4.5.0-py2.py3-none-any.whl", hash = "sha256:2666401939cdaa5f4e0c08cf7f20c9b21423b95e88f4675b1443973bdb080c42"}, diff --git a/pyproject.toml b/pyproject.toml index a426290..7a3f038 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,37 +9,47 @@ packages = [ ] [tool.poetry.dependencies] -python = "^3.6.1" -flask = "^1.1.2" -flask-sqlalchemy = "^2.4.4" -SQLAlchemy = "~1.3.0" # >= 1.4.0 changed a lot and breaks this project currently -psycopg2-binary = "^2.8.5" +python = "^3.8" +flask = "^2.1.1" +flask-sqlalchemy = "^2.5.1" +SQLAlchemy = "~1.4.34" # >= 1.4.0 changed a lot and breaks this project currently flask-cors = "^3.0.8" -GeoAlchemy2 = "^0.8.4" -flask-migrate = "^2.5.3" -wheel = "^0.35.1" -python-dotenv = "^0.14.0" -flask-restx = "^0.2.0" -requests = "^2.24.0" -sqlalchemy-utils = "^0.36.8" -passlib = "^1.7.2" -Flask-HTTPAuth = "^4.1.0" -shapely = "^1.7.1" -docker = "^4.3.1" -gunicorn = "^20.0.4" -gevent = "^20.6.2" -rq = "^1.5.2" -osmium = "^3.1.0" -pyproj = "^3.0.0" +GeoAlchemy2 = "^0.11.1" +wheel = "^0.37.1" +python-dotenv = "^0.20.0" +# wait for release of bug fix: https://github.com/python-restx/flask-restx/pull/423 +flask-restx = {git = "https://github.com/stacywsmith/flask-restx.git", rev = "041b1f074a32891c2359607b349bbc9d1ee4b374"} +requests = "^2.27.1" +sqlalchemy-utils = "^0.38.2" +passlib = "^1.7.4" +Flask-HTTPAuth = "^4.5.0" +shapely = "^1.8.1" +docker = "^5.0.3" +gunicorn = "^20.1.0" +gevent = "^21.12.0" +rq = "^1.10.1" +osmium = "^3.3.0" +pyproj = "^3.3.0" +psycopg2-binary = "^2.9.3" [tool.poetry.dev-dependencies] -pytest = "^6.0.1" -pre-commit = "^2.6.0" -yapf = "^0.30.0" -coverage = "^5.2.1" -coveralls = "^2.1.2" -pytest-cov = "^2.10.1" +pytest = "^7.1.1" +pre-commit = "^2.17.0" +coverage = "^6.3.2" +coveralls = "^3.3.1" +pytest-cov = "^3.0.0" [build-system] -requires = ["poetry>=0.12"] +requires = ["poetry>=1.0.0"] build-backend = "poetry.masonry.api" + +[tool.black] +line-length = 105 +exclude = ''' +/( + \.git + | \.venv + | dist + | build +)/ +''' diff --git a/routing_packager_app/__init__.py b/routing_packager_app/__init__.py index 4c6eb1b..c25c47e 100644 --- a/routing_packager_app/__init__.py +++ b/routing_packager_app/__init__.py @@ -4,7 +4,6 @@ from flask import Flask, g from flask_sqlalchemy import SQLAlchemy -from flask_migrate import Migrate import docker from docker.errors import ImageNotFound, NullResource from redis import Redis @@ -16,16 +15,15 @@ log = logging.getLogger(__name__) db = SQLAlchemy() -migrate = Migrate() -def create_app(config_string='production'): +def create_app(config_string="production"): """Factory to create contextful apps.""" app = Flask(__name__) # Flask complains about missing trailing slashes app.url_map.strict_slashes = False - config_env = os.getenv('FLASK_CONFIG') + config_env = os.getenv("FLASK_CONFIG") config_string = config_env or config_string # some quick sanity checks @@ -33,52 +31,51 @@ def create_app(config_string='production'): app.config.from_object(CONF_MAPPER[config_string]) # throws KeyError # Some runtime config variables for flask - app.config['FLASK_CONFIG'] = config_string + app.config["FLASK_CONFIG"] = config_string # FIXME: remember inside a container this references /app/data, not the env var!!! - data_dir = app.config['DATA_DIR'] - app.config['TEMP_DIR'] = temp_dir = os.path.join(data_dir, 'temp') - app.config['OSM_DIR'] = os.path.join(data_dir, 'osm') - app.config['TOMTOM_DIR'] = os.path.join(data_dir, 'tomtom') - app.config['HERE_DIR'] = os.path.join(data_dir, 'here') + data_dir = app.config["DATA_DIR"] + app.config["TEMP_DIR"] = temp_dir = os.path.join(data_dir, "temp") + app.config["OSM_DIR"] = os.path.join(data_dir, "osm") + app.config["TOMTOM_DIR"] = os.path.join(data_dir, "tomtom") + app.config["HERE_DIR"] = os.path.join(data_dir, "here") except KeyError: raise KeyError( f"'FLASK_CONFIG' needs to be one of testing, development, production. '{config_env}' is invalid." ) try: # do the PBFs exist? - for provider in app.config['ENABLED_PROVIDERS']: - provider_dir = app.config[provider.upper() + '_DIR'] + for provider in app.config["ENABLED_PROVIDERS"]: + provider_dir = app.config[provider.upper() + "_DIR"] provider_pbfs = list() for fn in os.listdir(provider_dir): fp = os.path.join(provider_dir, fn) - if os.path.isfile(fp) and fp.endswith('.pbf'): + if os.path.isfile(fp) and fp.endswith(".pbf"): provider_pbfs.append(fn) if len(provider_pbfs) == 0: raise FileNotFoundError(f"No PBFs for {provider} in {provider_dir}") # Are all Docker images installed? docker_clnt = docker.from_env() - for r in app.config['ENABLED_ROUTERS']: - env_var = f'{r.upper()}_IMAGE' + for r in app.config["ENABLED_ROUTERS"]: + env_var = f"{r.upper()}_IMAGE" docker_clnt.images.get(app.config.get(env_var)) # Throws ImageNotFound error # osmium is needed too - if not which('osmium'): + if not which("osmium"): raise FileNotFoundError('"osmium" is not installed or not added to PATH.') except (NullResource, ImageNotFound, FileNotFoundError) as e: log.error(e) raise e # create all dirs - make_directories(data_dir, temp_dir, app.config['ENABLED_ROUTERS']) + make_directories(data_dir, temp_dir, app.config["ENABLED_ROUTERS"]) # Initialize extensions db.init_app(app) - migrate.init_app(app, db) # Put Redis as an app attribute to reference easier in other modules - app.redis = Redis.from_url(app.config['REDIS_URL']) + app.redis = Redis.from_url(app.config["REDIS_URL"]) app.task_queue = Queue( - 'packaging', + "packaging", connection=app.redis, - default_timeout='12h' # after 12 hours processing the job will be considered as failed + default_timeout="12h", # after 12 hours processing the job will be considered as failed ) # Add a master account and all tables before first request @@ -89,17 +86,18 @@ def initialize_app(): initialize_request() from routing_packager_app.utils.db_utils import add_admin_user + add_admin_user() # Add the db to g to avoid circular imports @app.before_request def initialize_request(): - if not hasattr(g, 'db'): + if not hasattr(g, "db"): g.db = db # initialize the API module(s) # placed here to avoid circular imports - from routing_packager_app.api_v1 import (bp as api_v1, init_app as init_v1) + from routing_packager_app.api_v1 import bp as api_v1, init_app as init_v1 init_v1(app) app.register_blueprint(api_v1) diff --git a/routing_packager_app/api_v1/__init__.py b/routing_packager_app/api_v1/__init__.py index 06c3a39..492af0b 100644 --- a/routing_packager_app/api_v1/__init__.py +++ b/routing_packager_app/api_v1/__init__.py @@ -5,58 +5,64 @@ from flask_restx import Api from flask_restx.errors import HTTPStatus from werkzeug.exceptions import ( - NotFound, BadRequest, Conflict, Forbidden, Unauthorized, InternalServerError + NotFound, + BadRequest, + Conflict, + Forbidden, + Unauthorized, + InternalServerError, ) from .__version__ import __version__, __api_suffix__, __description__ + # Re-export the models and jobs for easier import in other modules -from .jobs.models import Job -from .users.models import User +from .jobs.models import Job # noqa: F401 +from .users.models import User # noqa: F401 cwd = os.path.abspath(os.path.dirname(__file__)) -bp = Blueprint(f'api_{__api_suffix__}', __name__, url_prefix=f'/api/{__api_suffix__}') +bp = Blueprint(f"api_{__api_suffix__}", __name__, url_prefix=f"/api/{__api_suffix__}") -auth = {'basic': {'type': 'basic'}} +auth = {"basic": {"type": "basic"}} api = Api( bp, authorizations=auth, version=__version__, - title='Routing Graph Generator', - description=__description__ + title="Routing Graph Generator", + description=__description__, ) # Add some custom error handlers to make the error response consistent @api.errorhandler(NotFound) def handle_user_no_sql_result_error(e: NotFound): - return {'error': 'Entity not found.'}, HTTPStatus.NOT_FOUND + return {"error": "Entity not found."}, HTTPStatus.NOT_FOUND @api.errorhandler(Unauthorized) -def handle_user_forbidden_error(e: Unauthorized): - return {'error': e.description}, HTTPStatus.UNAUTHORIZED +def handle_user_unauthorized_error(e: Unauthorized): + return {"error": e.description}, HTTPStatus.UNAUTHORIZED @api.errorhandler(Forbidden) def handle_user_forbidden_error(e: Forbidden): - return {'error': e.description}, HTTPStatus.FORBIDDEN + return {"error": e.description}, HTTPStatus.FORBIDDEN @api.errorhandler(BadRequest) def handle_user_bad_post_error(e: BadRequest): - return {'error': e.description}, HTTPStatus.BAD_REQUEST + return {"error": e.description}, HTTPStatus.BAD_REQUEST @api.errorhandler(Conflict) def handle_user_conflict_error(e: Conflict): - return {'error': e.description}, HTTPStatus.CONFLICT + return {"error": e.description}, HTTPStatus.CONFLICT @api.errorhandler(InternalServerError) def handle_job_server_error(e): - return {'error': e.description}, HTTPStatus.INTERNAL_SERVER_ERROR + return {"error": e.description}, HTTPStatus.INTERNAL_SERVER_ERROR def init_app(app): @@ -64,10 +70,10 @@ def init_app(app): for module_name in os.listdir(cwd): module_path = os.path.join(cwd, module_name) - if 'pycache' in module_name or not os.path.isdir(module_path): + if "pycache" in module_name or not os.path.isdir(module_path): continue # Import the module's models package before attempting to load its "ns" attribute - import_module(f'.{module_name}.models', package=__name__) + import_module(f".{module_name}.models", package=__name__) - ns = import_module(f'.{module_name}.resources', package=__name__).ns - api.add_namespace(ns, path=f'/{module_name}') + ns = import_module(f".{module_name}.resources", package=__name__).ns + api.add_namespace(ns, path=f"/{module_name}") diff --git a/routing_packager_app/api_v1/__version__.py b/routing_packager_app/api_v1/__version__.py index 4952d1e..356df61 100644 --- a/routing_packager_app/api_v1/__version__.py +++ b/routing_packager_app/api_v1/__version__.py @@ -1,5 +1,5 @@ -__version__ = '0.1.0' -__api_suffix__ = 'v1' +__version__ = "0.1.0" +__api_suffix__ = "v1" __description__ = """App to generate routing graph packages for FOSS routing engines, featuring: - email notification on final job status diff --git a/routing_packager_app/api_v1/jobs/__init__.py b/routing_packager_app/api_v1/jobs/__init__.py index d729104..bc349e0 100644 --- a/routing_packager_app/api_v1/jobs/__init__.py +++ b/routing_packager_app/api_v1/jobs/__init__.py @@ -1,25 +1,25 @@ class JobFields: - BBOX = 'bbox' - INTERVAL = 'interval' - PROVIDER = 'provider' - ROUTER = 'router' - DESCRIPTION = 'description' - NAME = 'name' - ID = 'id' - RQ_ID = 'job_id' - COMPRESSION = 'compression' - CONTAINER_ID = 'container_id' - STATUS = 'status' - USER_ID = 'user_id' - LAST_STARTED = 'last_started' - LAST_FINISHED = 'last_finished' - PATH = 'path' - PBF_PATH = 'pbf_path' + BBOX = "bbox" + INTERVAL = "interval" + PROVIDER = "provider" + ROUTER = "router" + DESCRIPTION = "description" + NAME = "name" + ID = "id" + RQ_ID = "job_id" + COMPRESSION = "compression" + CONTAINER_ID = "container_id" + STATUS = "status" + USER_ID = "user_id" + LAST_STARTED = "last_started" + LAST_FINISHED = "last_finished" + PATH = "path" + PBF_PATH = "pbf_path" # The fields of the JSON response of "osmium fileinfo -j" class OsmFields: - FILEPATH = 'filepath' - SIZE = 'size' - BBOX = 'bbox' - TIMESTAMP = 'timestamp' \ No newline at end of file + FILEPATH = "filepath" + SIZE = "size" + BBOX = "bbox" + TIMESTAMP = "timestamp" diff --git a/routing_packager_app/api_v1/jobs/models.py b/routing_packager_app/api_v1/jobs/models.py index 00c2de3..e55b46b 100644 --- a/routing_packager_app/api_v1/jobs/models.py +++ b/routing_packager_app/api_v1/jobs/models.py @@ -5,10 +5,10 @@ class Job(db.Model): - __tablename__ = 'jobs' + __tablename__ = "jobs" id = db.Column(db.Integer, primary_key=True) - user_id = db.Column(db.Integer, db.ForeignKey('users.id')) + user_id = db.Column(db.Integer, db.ForeignKey("users.id")) rq_id = db.Column(db.String, nullable=True) container_id = db.Column(db.String, nullable=True) name = db.Column(db.String, nullable=False) @@ -25,7 +25,7 @@ class Job(db.Model): pbf_path = db.Column(db.String, nullable=True) def __repr__(self): # pragma: no cover - s = f'' + s = f"" return s def set_status(self, status: str): diff --git a/routing_packager_app/api_v1/jobs/resources.py b/routing_packager_app/api_v1/jobs/resources.py index 9603fda..f716c0c 100644 --- a/routing_packager_app/api_v1/jobs/resources.py +++ b/routing_packager_app/api_v1/jobs/resources.py @@ -21,7 +21,7 @@ from ...constants import * # Mandatory, will be added by api_vX.__init__ -ns = Namespace('jobs', description='Job related operations') +ns = Namespace("jobs", description="Job related operations") # Parse POST request post_parser = reqparse.RequestParser() @@ -40,42 +40,39 @@ get_parser.add_argument(JobFields.STATUS) get_parser.add_argument(JobFields.INTERVAL) -job_base_model = ns.model('JobBase', job_base_schema) +job_base_model = ns.model("JobBase", job_base_schema) -job_response_model = ns.clone('JobResp', job_response_schema, job_base_model) +job_response_model = ns.clone("JobResp", job_response_schema, job_base_model) -@ns.route('/') -@ns.response(HTTPStatus.BAD_REQUEST, 'Invalid request parameters.') -@ns.response(HTTPStatus.INTERNAL_SERVER_ERROR, 'Unknown error.') +@ns.route("/") +@ns.response(HTTPStatus.BAD_REQUEST, "Invalid request parameters.") +@ns.response(HTTPStatus.INTERNAL_SERVER_ERROR, "Unknown error.") class Jobs(Resource): """Manipulates User table""" + @ns.doc( params={ JobFields.ROUTER: { - 'in': 'query', - 'description': 'Filter for routing engine.', - "enum": ROUTERS + "in": "query", + "description": "Filter for routing engine.", + "enum": ROUTERS, }, JobFields.PROVIDER: { - 'in': 'query', - 'description': 'Filter for data provider.', - "enum": PROVIDERS + "in": "query", + "description": "Filter for data provider.", + "enum": PROVIDERS, }, JobFields.BBOX: { - 'in': 'query', - 'description': 'Filter for bbox, e.g. "0.531906,4559908,0.6325,42.577608".' + "in": "query", + "description": 'Filter for bbox, e.g. "0.531906,4559908,0.6325,42.577608".', }, JobFields.INTERVAL: { - 'in': 'query', - 'description': 'Filter for update interval.', - "enum": INTERVALS + "in": "query", + "description": "Filter for update interval.", + "enum": INTERVALS, }, - JobFields.STATUS: { - 'in': 'query', - 'description': 'Filter for job status.', - "enum": STATUSES - } + JobFields.STATUS: {"in": "query", "description": "Filter for job status.", "enum": STATUSES}, } ) @ns.marshal_list_with(job_response_model) @@ -89,7 +86,7 @@ def get(self): bbox = args.get(JobFields.BBOX) if bbox: - bbox = [float(x) for x in args[JobFields.BBOX].split(',')] + bbox = [float(x) for x in args[JobFields.BBOX].split(",")] bbox_wkt = bbox_to_wkt(bbox) filters.append(func.ST_Intersects(Job.bbox, bbox_wkt)) @@ -112,11 +109,11 @@ def get(self): return Job.query.filter(*filters).all() @basic_auth.login_required - @ns.doc(security='basic') + @ns.doc(security="basic") @ns.expect(job_base_model) @ns.marshal_with(job_response_model) - @ns.response(HTTPStatus.FORBIDDEN, 'Access forbidden.') - @ns.response(HTTPStatus.UNAUTHORIZED, 'Invalid/missing basic authorization.') + @ns.response(HTTPStatus.FORBIDDEN, "Access forbidden.") + @ns.response(HTTPStatus.UNAUTHORIZED, "Invalid/missing basic authorization.") def post(self): """POST a new job. Needs admin privileges.""" @@ -125,19 +122,19 @@ def post(self): args = post_parser.parse_args(strict=True) # Sanitize the name field a little - args[JobFields.NAME] = args[JobFields.NAME].strip().replace(' ', '_') + args[JobFields.NAME] = args[JobFields.NAME].strip().replace(" ", "_") validate_post(args) router_name = args[JobFields.ROUTER] dataset_name = args[JobFields.NAME] provider = args[JobFields.PROVIDER] compression = args[JobFields.COMPRESSION] - bbox = [float(x) for x in args[JobFields.BBOX].split(',')] + bbox = [float(x) for x in args[JobFields.BBOX].split(",")] description = args[JobFields.DESCRIPTION] current_user = basic_auth.current_user() - data_dir = current_app.config['DATA_DIR'] + data_dir = current_app.config["DATA_DIR"] result_path = make_package_path(data_dir, dataset_name, router_name, provider, compression) job = Job( @@ -147,11 +144,11 @@ def post(self): router=router_name, user_id=current_user.id, interval=args[JobFields.INTERVAL], - status='Queued', + status="Queued", compression=compression, bbox=bbox_to_wkt(bbox), path=result_path, - last_started=datetime.utcnow() + last_started=datetime.utcnow(), ) add_or_abort(job) @@ -167,29 +164,39 @@ def post(self): # for testing we don't want that behaviour if not current_app.testing: # pragma: no cover current_app.task_queue.enqueue( - create_package, job.id, dataset_name, description, router_name, provider, bbox, - result_path, pbf_path, compression, current_user.email, - current_app.config['FLASK_CONFIG'] + create_package, + job.id, + dataset_name, + description, + router_name, + provider, + bbox, + result_path, + pbf_path, + compression, + current_user.email, + current_app.config["FLASK_CONFIG"], ) return job -@ns.route('/') -@ns.response(HTTPStatus.INTERNAL_SERVER_ERROR, 'Unknown error.') -@ns.response(HTTPStatus.NOT_FOUND, 'Unknown job id.') +@ns.route("/") +@ns.response(HTTPStatus.INTERNAL_SERVER_ERROR, "Unknown error.") +@ns.response(HTTPStatus.NOT_FOUND, "Unknown job id.") class JobSingle(Resource): """Get or delete single jobs""" + @ns.marshal_with(job_response_model) def get(self, id): """GET a single job.""" return Job.query.get_or_404(id) @basic_auth.login_required - @ns.doc(security='basic') - @ns.response(HTTPStatus.NO_CONTENT, 'Success, no content.') - @ns.response(HTTPStatus.FORBIDDEN, 'Access forbidden.') - @ns.response(HTTPStatus.UNAUTHORIZED, 'Invalid/missing basic authorization.') + @ns.doc(security="basic") + @ns.response(HTTPStatus.NO_CONTENT, "Success, no content.") + @ns.response(HTTPStatus.FORBIDDEN, "Access forbidden.") + @ns.response(HTTPStatus.UNAUTHORIZED, "Invalid/missing basic authorization.") def delete(self, id): """DELETE a single job. Will also stop the job if it's in progress. Needs admin privileges.""" db_job: Job = Job.query.get_or_404(id) @@ -197,7 +204,7 @@ def delete(self, id): # try to delete the Redis job or don't care if there is none try: rq_job = RqJob.fetch(db_job.rq_id, connection=current_app.redis) - if rq_job.get_status() in ('queued', 'started'): # pragma: no cover + if rq_job.get_status() in ("queued", "started"): # pragma: no cover rq_job.delete() except NoSuchJobError: pass @@ -206,17 +213,18 @@ def delete(self, id): if os.path.exists(db_job.pbf_path): os.remove(db_job.pbf_path) - return '', HTTPStatus.NO_CONTENT + return "", HTTPStatus.NO_CONTENT -osm_response_model = ns.model('OsmModel', osm_response_schema) +osm_response_model = ns.model("OsmModel", osm_response_schema) -@ns.route('//data/pbf') -@ns.response(HTTPStatus.INTERNAL_SERVER_ERROR, 'Unknown error.') -@ns.response(HTTPStatus.NOT_FOUND, 'Unknown job id.') +@ns.route("//data/pbf") +@ns.response(HTTPStatus.INTERNAL_SERVER_ERROR, "Unknown error.") +@ns.response(HTTPStatus.NOT_FOUND, "Unknown job id.") class OsmSingle(Resource): """Interact with a job's OSM file.""" + @ns.marshal_with(osm_response_model) def get(self, id): """GET info about a job's OSM file.""" @@ -225,7 +233,7 @@ def get(self, id): # Bail if it doesn't exist if not os.path.exists(pbf_path): - abort(code=HTTPStatus.NOT_FOUND, error=f'OSM file for job {job.id} not found.') + abort(code=HTTPStatus.NOT_FOUND, error=f"OSM file for job {job.id} not found.") osmium_proc = fileinfo_proc(pbf_path) stdout, _ = osmium_proc.communicate() @@ -234,12 +242,12 @@ def get(self, id): osmium_out = json.loads(stdout) response = dict() - response['filepath'] = osmium_out['file']['name'] - response['size'] = osmium_out['file']['size'] - response['timestamp'] = osmium_out['header']['option']['osmosis_replication_base_url'] + response["filepath"] = osmium_out["file"]["name"] + response["size"] = osmium_out["file"]["size"] + response["timestamp"] = osmium_out["header"]["option"]["osmosis_replication_base_url"] # Ouput bbox as string like the other endpoints - bbox = [str(x) for x in osmium_out['header']['boxes'][0]] - response['bbox'] = ','.join(bbox) + bbox = [str(x) for x in osmium_out["header"]["boxes"][0]] + response["bbox"] = ",".join(bbox) return response diff --git a/routing_packager_app/api_v1/jobs/schemas.py b/routing_packager_app/api_v1/jobs/schemas.py index 19097ca..2bf59bd 100644 --- a/routing_packager_app/api_v1/jobs/schemas.py +++ b/routing_packager_app/api_v1/jobs/schemas.py @@ -6,7 +6,7 @@ class BboxField(fields.Raw): - __schema_type__ = 'string' + __schema_type__ = "string" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -15,43 +15,40 @@ def format(self, value): geom = to_shape(value) bbox = geom.bounds - return ','.join([str(x) for x in bbox]) + return ",".join([str(x) for x in bbox]) job_base_schema = { - JobFields.NAME: fields.String(example='Switzerland'), - JobFields.DESCRIPTION: fields.String(example='OSM road network of Switzerland'), + JobFields.NAME: fields.String(example="Switzerland"), + JobFields.DESCRIPTION: fields.String(example="OSM road network of Switzerland"), JobFields.PROVIDER: fields.String(example=Providers.OSM.value), JobFields.ROUTER: fields.String(example=Routers.VALHALLA.value), - JobFields.BBOX: BboxField(example='1.531906,42.559908,1.6325,42.577608'), + JobFields.BBOX: BboxField(example="1.531906,42.559908,1.6325,42.577608"), JobFields.INTERVAL: fields.String(example=Intervals.DAILY.value), - JobFields.COMPRESSION: fields.String(example=Compressions.ZIP.value) + JobFields.COMPRESSION: fields.String(example=Compressions.ZIP.value), } job_response_schema = { - JobFields.ID: - fields.Integer(example=0), - JobFields.USER_ID: - fields.Integer(example=0), - JobFields.STATUS: - fields.String(example=Statuses.COMPLETED.value), - JobFields.RQ_ID: - fields.String(example='ac277aaa-c6e1-4660-9a43-38864ccabd42', attribute='rq_id'), - JobFields.CONTAINER_ID: - fields.String(example='6f5747f3cb03cc9add39db9b737d4138fcc1d821319cdf3ec0aea5735f3652c7'), - JobFields.LAST_STARTED: - fields.DateTime(example='2020-11-16T13:03:31.598Z'), - JobFields.LAST_FINISHED: - fields.DateTime(example='2020-11-16T13:06:33.310Z'), - JobFields.PATH: - fields.String(example='/root/routing-packager/data/valhalla/valhalla_tomtom_andorra.zip'), - JobFields.PBF_PATH: - fields.String(example='/root/routing-packager/data/osm/cut_andorra-latest.osm.pbf') + JobFields.ID: fields.Integer(example=0), + JobFields.USER_ID: fields.Integer(example=0), + JobFields.STATUS: fields.String(example=Statuses.COMPLETED.value), + JobFields.RQ_ID: fields.String(example="ac277aaa-c6e1-4660-9a43-38864ccabd42", attribute="rq_id"), + JobFields.CONTAINER_ID: fields.String( + example="6f5747f3cb03cc9add39db9b737d4138fcc1d821319cdf3ec0aea5735f3652c7" + ), + JobFields.LAST_STARTED: fields.DateTime(example="2020-11-16T13:03:31.598Z"), + JobFields.LAST_FINISHED: fields.DateTime(example="2020-11-16T13:06:33.310Z"), + JobFields.PATH: fields.String( + example="/root/routing-packager/data/valhalla/valhalla_tomtom_andorra.zip" + ), + JobFields.PBF_PATH: fields.String( + example="/root/routing-packager/data/osm/cut_andorra-latest.osm.pbf" + ), } osm_response_schema = { - OsmFields.FILEPATH: fields.String(example='data/osm/andorra-latest-test.osm.pbf'), - OsmFields.TIMESTAMP: fields.String(example='2020-12-07T15:46:52Z'), - OsmFields.BBOX: fields.String(example='1.531906,42.559908,1.6325,42.577608'), - OsmFields.SIZE: fields.Integer(example=275483) + OsmFields.FILEPATH: fields.String(example="data/osm/andorra-latest-test.osm.pbf"), + OsmFields.TIMESTAMP: fields.String(example="2020-12-07T15:46:52Z"), + OsmFields.BBOX: fields.String(example="1.531906,42.559908,1.6325,42.577608"), + OsmFields.SIZE: fields.Integer(example=275483), } diff --git a/routing_packager_app/api_v1/jobs/validate.py b/routing_packager_app/api_v1/jobs/validate.py index 756a44b..39de623 100644 --- a/routing_packager_app/api_v1/jobs/validate.py +++ b/routing_packager_app/api_v1/jobs/validate.py @@ -23,14 +23,15 @@ def validate_post(args): name = args[JobFields.NAME] # Make sure name has no arbitrary (unallowed) characters for the filesystem - match = re.match('^[^*&%\/\s]+$', name) + match = re.match("^[^*&%/]+$", name) if not match: - raise BadRequest(f"'name' cannot have characters *, &, /, %.") + raise BadRequest("'name' cannot have characters *, &, /, %.") # make sure no other combo of name & router & provider exists existing_combo: Job = Job.query.filter( - Job.name == args[JobFields.NAME], Job.provider == args[JobFields.PROVIDER], - Job.router == args[JobFields.ROUTER] + Job.name == args[JobFields.NAME], + Job.provider == args[JobFields.PROVIDER], + Job.router == args[JobFields.ROUTER], ).first() if existing_combo: raise Conflict( @@ -54,12 +55,12 @@ def validate_get(args): def _validate_common(args): # Routers must be valid - allowed_routers = current_app.config['ENABLED_ROUTERS'] + allowed_routers = current_app.config["ENABLED_ROUTERS"] router = args.get(JobFields.ROUTER) if router and router not in allowed_routers: raise BadRequest(f"'router' must be one of the 'ENABLED_ROUTERS': {allowed_routers}") - allowed_providers = current_app.config['ENABLED_PROVIDERS'] + allowed_providers = current_app.config["ENABLED_PROVIDERS"] provider = args.get(JobFields.PROVIDER) if provider and provider not in allowed_providers: raise BadRequest(f"'provider' must be one of 'ENABLED_PROVIDERS': {allowed_providers}.") @@ -67,16 +68,16 @@ def _validate_common(args): # bbox must be 4 floats bbox = args.get(JobFields.BBOX) if bbox: - bbox_split = bbox.split(',') + bbox_split = bbox.split(",") if not len(bbox_split) == 4: raise BadRequest( - f"'bbox' needs to be a comma-delimited string in the format minx,miny,maxx,maxy." + "'bbox' needs to be a comma-delimited string in the format minx,miny,maxx,maxy." ) # Raises if float(x) is not possible, e.g. there's a string in bbox_split try: list(map(float, bbox_split)) except ValueError: - raise BadRequest(f"All coordinates in 'bbox' need to be of type float.") + raise BadRequest("All coordinates in 'bbox' need to be of type float.") # Intervals must be valid interval = args.get(JobFields.INTERVAL) diff --git a/routing_packager_app/api_v1/users/__init__.py b/routing_packager_app/api_v1/users/__init__.py index 07f6182..055abfe 100644 --- a/routing_packager_app/api_v1/users/__init__.py +++ b/routing_packager_app/api_v1/users/__init__.py @@ -1,5 +1,5 @@ # some constants class UserFields: - EMAIL = 'email' - PASSWORD = 'password' - ID = 'id' + EMAIL = "email" + PASSWORD = "password" + ID = "id" diff --git a/routing_packager_app/api_v1/users/models.py b/routing_packager_app/api_v1/users/models.py index 7c8b9b6..9884010 100644 --- a/routing_packager_app/api_v1/users/models.py +++ b/routing_packager_app/api_v1/users/models.py @@ -6,13 +6,13 @@ class User(db.Model): """The users table.""" - __tablename__ = 'users' + __tablename__ = "users" id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(120), index=True, unique=True, nullable=False) - password = db.Column(PasswordType(schemes=('pbkdf2_sha512', )), nullable=False) + password = db.Column(PasswordType(schemes=("pbkdf2_sha512",)), nullable=False) - tasks = db.relationship('Job', backref='users', lazy="dynamic") + tasks = db.relationship("Job", backref="users", lazy="dynamic") def __repr__(self): # pragma: no cover - return ''.format(self.email) + return "".format(self.email) diff --git a/routing_packager_app/api_v1/users/resources.py b/routing_packager_app/api_v1/users/resources.py index 02238ac..6f6f64f 100644 --- a/routing_packager_app/api_v1/users/resources.py +++ b/routing_packager_app/api_v1/users/resources.py @@ -10,7 +10,7 @@ from ...utils.db_utils import add_or_abort # Mandatory, will be added by api_vX.__init__ -ns = Namespace('users', description='User related operations') +ns = Namespace("users", description="User related operations") # Parse POST request parser = reqparse.RequestParser() @@ -19,25 +19,27 @@ # Set up different schemas for request and response user_base_schema = ns.model( - 'UserBase', { - UserFields.EMAIL: fields.String(example='example@email.org'), - } + "UserBase", + { + UserFields.EMAIL: fields.String(example="example@email.org"), + }, ) -user_response_schema = ns.clone('UserResp', user_base_schema, {UserFields.ID: fields.Integer}) -user_body_schema = ns.clone('UserReq', user_base_schema, {UserFields.PASSWORD: fields.String}) +user_response_schema = ns.clone("UserResp", user_base_schema, {UserFields.ID: fields.Integer}) +user_body_schema = ns.clone("UserReq", user_base_schema, {UserFields.PASSWORD: fields.String}) -@ns.route('/') -@ns.response(HTTPStatus.INTERNAL_SERVER_ERROR, 'Unknown error.') +@ns.route("/") +@ns.response(HTTPStatus.INTERNAL_SERVER_ERROR, "Unknown error.") class UserRegistration(Resource): """Manipulates User table""" + @basic_auth.login_required - @ns.doc(security='basic') + @ns.doc(security="basic") @ns.expect(user_body_schema) @ns.marshal_with(user_response_schema) - @ns.response(HTTPStatus.BAD_REQUEST, 'Invalid request parameters.') - @ns.response(HTTPStatus.CONFLICT, 'User already exists.') - @ns.response(HTTPStatus.UNAUTHORIZED, 'Invalid/missing basic authorization.') + @ns.response(HTTPStatus.BAD_REQUEST, "Invalid request parameters.") + @ns.response(HTTPStatus.CONFLICT, "User already exists.") + @ns.response(HTTPStatus.UNAUTHORIZED, "Invalid/missing basic authorization.") def post(self): """POST a new user. Needs admin privileges""" args = parser.parse_args(strict=True) @@ -53,29 +55,30 @@ def get(self): return User.query.all() -@ns.route('/') -@ns.response(HTTPStatus.INTERNAL_SERVER_ERROR, 'Unknown error.') -@ns.response(HTTPStatus.NOT_FOUND, 'Unknown user id.') +@ns.route("/") +@ns.response(HTTPStatus.INTERNAL_SERVER_ERROR, "Unknown error.") +@ns.response(HTTPStatus.NOT_FOUND, "Unknown user id.") class UserSingle(Resource): """Get or delete single users""" + @ns.marshal_with(user_response_schema) def get(self, id): """GET a single user""" return User.query.get_or_404(id) @basic_auth.login_required - @ns.doc(security='basic') - @ns.response(HTTPStatus.NO_CONTENT, 'Success, no content.') - @ns.response(HTTPStatus.UNAUTHORIZED, 'Invalid/missing basic authorization.') - @ns.response(HTTPStatus.FORBIDDEN, 'Access forbidden.') - @ns.response(HTTPStatus.CONFLICT, 'Conflict detected.') + @ns.doc(security="basic") + @ns.response(HTTPStatus.NO_CONTENT, "Success, no content.") + @ns.response(HTTPStatus.UNAUTHORIZED, "Invalid/missing basic authorization.") + @ns.response(HTTPStatus.FORBIDDEN, "Access forbidden.") + @ns.response(HTTPStatus.CONFLICT, "Conflict detected.") def delete(self, id): """DELETE a user. Needs admin privileges.""" db = g.db user = User.query.get_or_404(id) current_user_email = basic_auth.current_user().email - admin_email = current_app.config['ADMIN_EMAIL'] + admin_email = current_app.config["ADMIN_EMAIL"] if admin_email == user.email: raise Conflict("Can't delete admin user.") elif not admin_email == current_user_email: @@ -83,4 +86,4 @@ def delete(self, id): db.session.delete(User.query.get_or_404(id)) db.session.commit() - return '', HTTPStatus.NO_CONTENT + return "", HTTPStatus.NO_CONTENT diff --git a/routing_packager_app/api_v1/users/validate.py b/routing_packager_app/api_v1/users/validate.py index b12923f..e6ea269 100644 --- a/routing_packager_app/api_v1/users/validate.py +++ b/routing_packager_app/api_v1/users/validate.py @@ -1,10 +1,8 @@ import re -from werkzeug.exceptions import BadRequest, Conflict, Forbidden +from werkzeug.exceptions import BadRequest, Forbidden from flask import current_app -from . import UserFields -from .models import User from ...auth.basic_auth import basic_auth @@ -14,7 +12,7 @@ def validate_post(args): :param dict args: request parameters """ - admin_email = current_app.config['ADMIN_EMAIL'] + admin_email = current_app.config["ADMIN_EMAIL"] if not admin_email == basic_auth.current_user().email: raise Forbidden("Admin privileges are required to register a new user.") @@ -23,6 +21,6 @@ def validate_post(args): raise BadRequest(f"'{arg}' is required in request.") # Validate email - email_re = r'^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\D{2,3})+$' - if not re.search(email_re, args['email']): + email_re = r"^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\D{2,3})+$" + if not re.search(email_re, args["email"]): raise BadRequest(f'Email \'{args["email"]}\' is invalid.') diff --git a/routing_packager_app/auth/basic_auth.py b/routing_packager_app/auth/basic_auth.py index fb92d8d..93162cc 100644 --- a/routing_packager_app/auth/basic_auth.py +++ b/routing_packager_app/auth/basic_auth.py @@ -19,6 +19,7 @@ def verify(email, password): return False from ..api_v1.users.models import User + registered_user: User = User.query.filter_by(email=email).first() if not registered_user or not registered_user.password == password: return False @@ -29,7 +30,7 @@ def verify(email, password): @basic_auth.error_handler def auth_error(status): """Customize the error response of this package to our common schema.""" - msg = 'Access denied.' + msg = "Access denied." # 401 if status == HTTPStatus.UNAUTHORIZED: msg = "Missing Basic Auth authorization header." diff --git a/routing_packager_app/cli.py b/routing_packager_app/cli.py index 34affa3..f5e15ff 100644 --- a/routing_packager_app/cli.py +++ b/routing_packager_app/cli.py @@ -20,15 +20,16 @@ def register(app): """ Registers the flask command """ - @app.cli.command('update') - @click.argument('interval', type=click.Choice(INTERVALS)) + + @app.cli.command("update") + @click.argument("interval", type=click.Choice(INTERVALS)) # Solely to set the right environment for testing @click.option( - '--config', - '-c', + "--config", + "-c", type=click.Choice(tuple(CONF_MAPPER.keys())), - default='production', - help='Internal option' + default="production", + help="Internal option", ) def update(interval, config): """Update routing packages according to INTERVALs, one of ["daily", "weekly", "monthly"].""" @@ -46,7 +47,7 @@ def update(interval, config): job.pbf_path, job.compression, job.users.email, - config_string=config + config_string=config, ) return update diff --git a/routing_packager_app/constants.py b/routing_packager_app/constants.py index abe38ac..1e20770 100644 --- a/routing_packager_app/constants.py +++ b/routing_packager_app/constants.py @@ -2,37 +2,37 @@ class Routers(Enum): - VALHALLA = 'valhalla' - ORS = 'ors' - OSRM = 'osrm' - GRAPHHOPPER = 'graphhopper' + VALHALLA = "valhalla" + ORS = "ors" + OSRM = "osrm" + GRAPHHOPPER = "graphhopper" class Providers(Enum): - OSM = 'osm' - TOMTOM = 'tomtom' - HERE = 'here' + OSM = "osm" + TOMTOM = "tomtom" + HERE = "here" class Statuses(Enum): - QUEUED = 'Queued' - EXTRACTING = 'Extracting' - TILING = 'Tiling' - FAILED = 'Failed' - DELETED = 'Deleted' - COMPLETED = 'Completed' + QUEUED = "Queued" + EXTRACTING = "Extracting" + TILING = "Tiling" + FAILED = "Failed" + DELETED = "Deleted" + COMPLETED = "Completed" class Intervals(Enum): - ONCE = 'once' - DAILY = 'daily' - WEEKLY = 'weekly' - MONTHLY = 'monthly' + ONCE = "once" + DAILY = "daily" + WEEKLY = "weekly" + MONTHLY = "monthly" class Compressions(Enum): - ZIP = 'zip' - TAR = 'tar' + ZIP = "zip" + TAR = "tar" ROUTERS = [e.value for e in Routers] @@ -46,9 +46,9 @@ class Compressions(Enum): COMPRESSIONS = [e.value for e in Compressions] CONF_MAPPER = { - 'development': 'config.DevConfig', - 'production': 'config.ProdConfig', - 'testing': 'config.TestingConfig' + "development": "config.DevConfig", + "production": "config.ProdConfig", + "testing": "config.TestingConfig", } -DOCKER_VOLUME = 'routing-packager_packages' +DOCKER_VOLUME = "routing-packager_packages" diff --git a/routing_packager_app/logger.py b/routing_packager_app/logger.py index 0ab68d9..b23a0d4 100644 --- a/routing_packager_app/logger.py +++ b/routing_packager_app/logger.py @@ -1,14 +1,15 @@ from logging.handlers import SMTPHandler import logging -from typing import List +from typing import List # noqa: F401 -#https://stackoverflow.com/a/9236722/2582935 +# https://stackoverflow.com/a/9236722/2582935 class AppSmtpHandler(SMTPHandler): """The SMTP handler's extended class to write emails in case of events.""" + def getSubject(self, record: logging.LogRecord) -> str: """Alters the subject line of the emails.""" - subject = f'{record.levelname}: ' + subject = f"{record.levelname}: " if record.levelno == logging.ERROR: subject += f"{record.user}'s job {record.job_id} failed" # Warning is only emitted in tasks.py, when the deletion fails @@ -17,7 +18,9 @@ def getSubject(self, record: logging.LogRecord) -> str: elif record.levelno == logging.INFO: subject += f"{record.user}'s job {record.job_id} succeeded" else: - raise NotImplemented(f"Logger level {record.levelno} is not implemented for this handler.") + raise NotImplementedError( + f"Logger level {record.levelno} is not implemented for this handler." + ) return subject @@ -44,15 +47,15 @@ def get_smtp_details(config, toaddrs): # toaddrs.append(config['ADMIN_EMAIL']) conf = dict( - mailhost=(config['SMTP_HOST'], config['SMTP_PORT']), - fromaddr=config['SMTP_FROM'], + mailhost=(config["SMTP_HOST"], config["SMTP_PORT"]), + fromaddr=config["SMTP_FROM"], toaddrs=toaddrs, - subject='' + subject="", ) - if config['SMTP_USER'] and config['SMTP_PASS']: # pragma: no cover - conf['credentials'] = (config['SMTP_USER'], config['SMTP_PASS']) - if config['SMTP_SECURE']: - conf['secure'] = tuple() + if config["SMTP_USER"] and config["SMTP_PASS"]: # pragma: no cover + conf["credentials"] = (config["SMTP_USER"], config["SMTP_PASS"]) + if config["SMTP_SECURE"]: + conf["secure"] = tuple() return conf diff --git a/routing_packager_app/osmium.py b/routing_packager_app/osmium.py index 4b8d310..3403259 100644 --- a/routing_packager_app/osmium.py +++ b/routing_packager_app/osmium.py @@ -1,5 +1,5 @@ import os -from typing import List +from typing import List # noqa: F401 from datetime import datetime import osmium @@ -27,11 +27,10 @@ def get_pbfs_by_area(pbf_dir, job_bbox): :returns: The full path of the PBF file which fits the job's bbox and has the smallest area :rtype: List[List[str, int]] """ - job_bbox_proj = transform(WGS_TO_MOLLWEIDE, job_bbox) + job_bbox_proj: Polygon = transform(WGS_TO_MOLLWEIDE, job_bbox) pbf_bbox_areas = {} - areas = "" for fn in os.listdir(pbf_dir): - if not fn.endswith('.pbf'): + if not fn.endswith(".pbf"): continue fp = os.path.join(pbf_dir, fn) @@ -44,15 +43,13 @@ def get_pbfs_by_area(pbf_dir, job_bbox): pbf_bbox_osmium.top_right.lon, pbf_bbox_osmium.top_right.lat, ) - pbf_bbox_proj = transform(WGS_TO_MOLLWEIDE, pbf_bbox_geom) - areas = areas + " " + pbf_bbox_proj - # Only keep the PBF bboxes which contain the job's bbox + pbf_bbox_proj: Polygon = transform(WGS_TO_MOLLWEIDE, pbf_bbox_geom) if not pbf_bbox_proj.contains(job_bbox_proj): continue pbf_bbox_areas[fp] = pbf_bbox_proj.area if not pbf_bbox_areas: - raise FileNotFoundError(f"No PBF found for bbox {job_bbox} in pbf areas: {areas}.") + raise FileNotFoundError(f"No PBF found for bbox {job_bbox}.") # Return the filepath with the minimum area of the matching ones return sorted(pbf_bbox_areas.items(), key=lambda x: x[1]) @@ -73,10 +70,10 @@ def extract_proc(bbox, in_pbf_path, out_pbf_path): # we only support timestamp for now timestamp = datetime.now().replace(microsecond=0).isoformat() - headers = f'--output-header=osmosis_replication_base_url={timestamp}Z' + headers = f"--output-header=osmosis_replication_base_url={timestamp}Z" - strategy = 'complete_ways' - bbox = f'{minx},{miny},{maxx},{maxy}' + strategy = "complete_ways" + bbox = f"{minx},{miny},{maxx},{maxy}" cmd = f"osmium extract {headers} --set-bounds --strategy={strategy} --bbox={bbox} -o {out_pbf_path} -O {in_pbf_path}" diff --git a/routing_packager_app/routers/__init__.py b/routing_packager_app/routers/__init__.py index 0c6981d..270dc1b 100644 --- a/routing_packager_app/routers/__init__.py +++ b/routing_packager_app/routers/__init__.py @@ -1,5 +1,3 @@ -from typing import List - from routing_packager_app.constants import Routers from .valhalla import Valhalla diff --git a/routing_packager_app/routers/router_base.py b/routing_packager_app/routers/router_base.py index 670d47e..263c30f 100644 --- a/routing_packager_app/routers/router_base.py +++ b/routing_packager_app/routers/router_base.py @@ -1,13 +1,13 @@ import os from abc import ABC, abstractmethod -from time import sleep from typing import Optional from flask import current_app from werkzeug.exceptions import InternalServerError import docker -from docker.errors import ImageNotFound +from docker.errors import ImageNotFound, APIError as DockerApiError from docker.models.containers import Container +from requests.exceptions import HTTPError from ..constants import DOCKER_VOLUME @@ -20,30 +20,34 @@ class RouterBase(ABC): Subclasses need to implement the abstract methods. """ + def __init__(self, provider, input_pbf_path): self._input_pbf_path = input_pbf_path - self._graph_dir = os.path.join(current_app.config['TEMP_DIR'], self.name(), 'graph') + self._graph_dir = os.path.join(current_app.config["TEMP_DIR"], self.name(), "graph") self._container = None # It's important to maintain the same directory structure in docker, host etc self._docker_pbf_path = os.path.join( - '/app', 'data', provider, os.path.basename(self._input_pbf_path) + "/app", "data", provider, os.path.basename(self._input_pbf_path) ) - self._docker_graph_dir = os.path.join('/app', 'data', 'temp', self.name(), 'graph') + self._docker_graph_dir = os.path.join("/app", "data", "temp", self.name(), "graph") # if testing we need to reference the test data directory # else the previously created docker volume - host_dir = docker_clnt.volumes.get(DOCKER_VOLUME - ).name if not current_app.config['TESTING'] else os.path.join( - current_app.root_path, '..', 'tests', 'data' - ) - volumes = {host_dir: {'bind': '/app/data', 'mode': 'rw'}} + host_dir = ( + docker_clnt.volumes.get(DOCKER_VOLUME).name + if not current_app.config["TESTING"] + else os.path.join(current_app.root_path, "..", "tests", "data") + ) + volumes = {host_dir: {"bind": "/app/data", "mode": "rw"}} try: self._container: Optional[Container] = docker_clnt.containers.create( - self.image, volumes=volumes, command="tail -f /dev/null" + self.image, volumes=volumes, entrypoint="tail -f /dev/null" ) except ImageNotFound: raise InternalServerError(f"Docker image {self.image} not found for '{self.name}'") + except (DockerApiError, HTTPError) as e: + raise InternalServerError(f"Container {self._container.id}: {e}") def _exec_docker(self, cmd): """ @@ -63,7 +67,7 @@ def cleanup(self): @property def image(self): - return current_app.config[f'{self.name().upper()}_IMAGE'] + return current_app.config[f"{self.name().upper()}_IMAGE"] @property def container_id(self): diff --git a/routing_packager_app/routers/valhalla.py b/routing_packager_app/routers/valhalla.py index cddaf97..e05db76 100644 --- a/routing_packager_app/routers/valhalla.py +++ b/routing_packager_app/routers/valhalla.py @@ -10,33 +10,38 @@ class Valhalla(RouterBase): """Valhalla implementation""" + def name(self): return Routers.VALHALLA.value def build_graph(self): # tile_dir is the only required config config = defaultdict(dict) - config["mjolnir"]["tile_dir"] = os.path.join(self._docker_graph_dir, 'valhalla_tiles') + config["mjolnir"]["tile_dir"] = os.path.join(self._docker_graph_dir, "valhalla_tiles") # Add optional things, don't test for now - valhalla_host_dir = os.path.join(current_app.config['DATA_DIR'], 'valhalla') + valhalla_host_dir = os.path.join(current_app.config["DATA_DIR"], "valhalla") - admin_path = os.path.join(valhalla_host_dir, 'admins.sqlite') # pragma: no cover + admin_path = os.path.join(valhalla_host_dir, "admins.sqlite") # pragma: no cover if os.path.exists(admin_path): - config['mjolnir']['admin'] = '/app/data/valhalla/admins.sqlite' - config['mjolnir']['data_processing'] = {'use_admin_db': True} + config["mjolnir"]["admin"] = "/app/data/valhalla/admins.sqlite" + config["mjolnir"]["data_processing"] = {"use_admin_db": True} - timezone_path = os.path.join(valhalla_host_dir, 'timezones.sqlite') # pragma: no cover + timezone_path = os.path.join(valhalla_host_dir, "timezones.sqlite") # pragma: no cover if os.path.exists(timezone_path): - config['mjolnir']['timezone'] = '/app/data/valhalla/timezones.sqlite' + config["mjolnir"]["timezone"] = "/app/data/valhalla/timezones.sqlite" - elevation_path = os.path.join(valhalla_host_dir, 'elevation') # pragma: no cover + elevation_path = os.path.join(valhalla_host_dir, "elevation") # pragma: no cover if os.path.exists(elevation_path): - config['additional_data']['elevation'] = '/app/data/valhalla/elevation' + config["additional_data"]["elevation"] = "/app/data/valhalla/elevation" + + print(json.dumps(config)) # Stitch command and add inline config - cmd = f"valhalla_build_tiles --inline-config '{json.dumps(config)}'" \ - f" {self._docker_pbf_path}" + cmd = ( + f"sudo valhalla_build_tiles --inline-config '{json.dumps(config)}'" + f" {self._docker_pbf_path}" + ) return self._exec_docker(cmd) @@ -44,5 +49,5 @@ def make_package(self, out_path, compression): if compression == Compressions.ZIP.value: make_zipfile(out_path, self._graph_dir) elif compression == Compressions.TAR.value: - in_path = os.path.join(self._graph_dir, 'valhalla_tiles') + in_path = os.path.join(self._graph_dir, "valhalla_tiles") make_tarfile(out_path, in_path) diff --git a/routing_packager_app/tasks.py b/routing_packager_app/tasks.py index 4c67911..903761f 100644 --- a/routing_packager_app/tasks.py +++ b/routing_packager_app/tasks.py @@ -6,7 +6,7 @@ import shutil from rq import get_current_job -from rq.job import Job +from rq.job import Job as RqJob from flask_sqlalchemy import SessionBase from werkzeug.exceptions import InternalServerError, HTTPException from docker.errors import ImageNotFound @@ -14,19 +14,18 @@ from osmium.io import Reader from . import create_app, db -from .api_v1.jobs.models import Job +from .api_v1.jobs.models import Job as DbJob from .logger import AppSmtpHandler, get_smtp_details from .routers import get_router -from .utils.file_utils import make_tarfile, make_zipfile from .utils.geom_utils import bbox_to_geom from .osmium import get_pbfs_by_area, extract_proc from .constants import * -LOGGER = logging.getLogger('packager') +LOGGER = logging.getLogger("packager") LOGGER.setLevel(logging.INFO) -def create_package( +def create_package( # noqa: C901 job_id: int, job_name: str, description: str, @@ -37,8 +36,8 @@ def create_package( in_pbf_path: str, compression: str, user_email: str, - config_string='production', - cleanup=True + config_string="production", + cleanup=True, ): """ Creates a routing package and puts it in a defined folder. @@ -61,7 +60,7 @@ def create_package( bbox_geom: Polygon = bbox_to_geom(bbox) - job = Job.query.get(job_id) + job = DbJob.query.get(job_id) succeeded = False # Huge try/except to make sure we only have to write a failure once. @@ -73,12 +72,12 @@ def create_package( raise Exception(f"Job {job_id} doesn't exist anymore in the database.") job_status = job.status - in_pbf_dir = app.config[provider.upper() + '_DIR'] + in_pbf_dir = app.config[provider.upper() + "_DIR"] router = get_router(router_name, provider, in_pbf_path) # Set Redis job ID and container ID - rq_job: Job = get_current_job() + rq_job: RqJob = get_current_job() # testing has no access to a real queue if not app.testing: # pragma: no cover job.set_rq_id(rq_job.id) @@ -140,7 +139,7 @@ def create_package( raise # any other exception is assumed to be a deleted job and will only be logged/email sent - except Exception as e: # pragma: no cover + except Exception: # pragma: no cover msg = f"Job {job_id} by {user_email} was deleted." LOGGER.warning(msg, extra=dict(user=user_email, job_id=job_id)) raise @@ -165,12 +164,12 @@ def create_package( "name": job_name, "description": description, "extent": ",".join([str(f) for f in bbox]), - "last_modified": str(datetime.utcnow()) + "last_modified": str(datetime.utcnow()), } dirname = os.path.dirname(result_path) # Splits the first fname_sanitized = fname.split(os.extsep, 1)[0] - with open(os.path.join(dirname, fname_sanitized + '.json'), 'w', encoding='utf8') as f: + with open(os.path.join(dirname, fname_sanitized + ".json"), "w", encoding="utf8") as f: json.dump(j, f, indent=2, ensure_ascii=False) # only clean up if successful, otherwise retain the container for debugging @@ -178,8 +177,5 @@ def create_package( router.cleanup() LOGGER.info( f"Job {job_id} by {user_email} finished successfully. Find the new dataset in {result_path}", - extra={ - "job_id": job_id, - "user": user_email - } + extra={"job_id": job_id, "user": user_email}, ) diff --git a/routing_packager_app/utils/db_utils.py b/routing_packager_app/utils/db_utils.py index 3e9c547..f4dd017 100644 --- a/routing_packager_app/utils/db_utils.py +++ b/routing_packager_app/utils/db_utils.py @@ -23,10 +23,10 @@ def add_or_abort(obj): log.error(f"Transaction aborted because: {e}") msg = str(e.orig) # prettier error message - needle = 'DETAIL: ' + needle = "DETAIL: " msg_idx = msg.rfind(needle) if msg_idx: - msg = msg[msg_idx + len(needle) + 1:] + msg = msg[msg_idx + len(needle) + 1 :] abort(code=HTTPStatus.CONFLICT, error=str(msg.strip())) except Exception as e: # pragma: no cover log.error(f"Transaction aborted because: {e}") @@ -58,10 +58,11 @@ def delete_or_abort(obj): def add_admin_user(): """Add admin user before first request.""" - admin_email = current_app.config['ADMIN_EMAIL'] - admin_pass = current_app.config['ADMIN_PASS'] + admin_email = current_app.config["ADMIN_EMAIL"] + admin_pass = current_app.config["ADMIN_PASS"] from ..api_v1.users.models import User + if not User.query.filter_by(email=admin_email).first(): admin_user = User(email=admin_email, password=admin_pass) session = g.db.session diff --git a/routing_packager_app/utils/file_utils.py b/routing_packager_app/utils/file_utils.py index 9700a75..beaf187 100644 --- a/routing_packager_app/utils/file_utils.py +++ b/routing_packager_app/utils/file_utils.py @@ -4,13 +4,13 @@ from typing import List -def make_directories(data_dir, temp_dir, routers): +def make_directories(data_dir: str, temp_dir: str, routers: List[str]): """ Creates the directories needed for the app to function properly. - :param str data_dir: the DATA_DIR env var - :param str temp_dir: the TEMP_DIR env var - :param List[str] routers: the DATA_DIR env var + :param data_dir: the DATA_DIR env var + :param temp_dir: the TEMP_DIR env var + :param routers: the DATA_DIR env var """ data_dir = data_dir for router in routers: @@ -18,19 +18,19 @@ def make_directories(data_dir, temp_dir, routers): os.makedirs(os.path.join(temp_dir, router), exist_ok=True) -def make_package_path(base_dir, name, router, provider, extension): +def make_package_path(base_dir: str, name: str, router: str, provider: str, extension: str) -> str: """ Returns the file name from DATA_DIR, router, provider and dataset name. - :param str base_dir: The DATA_DIR env variable - :param str name: The dataset name, e.g. moldavia - :param str router: The router name, e.g. valhalla - :param str provider: The provider's name, e.g. osm - :param str extension: The package's compression, e.g. tar.gz + :param base_dir: The DATA_DIR env variable + :param name: The dataset name, e.g. moldavia + :param router: The router name, e.g. valhalla + :param provider: The provider's name, e.g. osm + :param extension: The package's compression, e.g. tar.gz :returns: The full path to the data package """ - file_name = '_'.join([router, provider, name]) + file_name = "_".join([router, provider, name]) # also create a folder with the same name out_dir = os.path.join(base_dir, router, file_name) @@ -39,24 +39,24 @@ def make_package_path(base_dir, name, router, provider, extension): return os.path.join(out_dir, file_name + f".{extension}") -def make_tarfile(out_fp, source_dir): +def make_tarfile(out_fp: str, source_dir: str): """ Adds *source_dir* to a gzipped Tar file called *out_fp*. - :param str out_fp: full path to the resulting Tar file. - :param str source_dir: full path the directory which needs zipping. + :param out_fp: full path to the resulting Tar file. + :param source_dir: full path the directory which needs zipping. """ with tarfile.open(out_fp, "w") as tar: tar.add(source_dir, arcname=os.path.basename(source_dir)) # https://gist.github.com/felixSchl/d38b455df8bf83a78d3d -def make_zipfile(out_fp, source_dir): +def make_zipfile(out_fp: str, source_dir: str): """ Adds *source_dir* to a Zip file called *out_fp*. - :param str out_fp: full path to the resulting Zip file. - :param str source_dir: full path of the directory which needs zipping. + :param out_fp: full path to the resulting Zip file. + :param source_dir: full path of the directory which needs zipping. """ archive = zipfile.ZipFile(out_fp, "w", zipfile.ZIP_DEFLATED) if os.path.isdir(source_dir): diff --git a/routing_packager_app/utils/geom_utils.py b/routing_packager_app/utils/geom_utils.py index 7e5f27f..c049e30 100644 --- a/routing_packager_app/utils/geom_utils.py +++ b/routing_packager_app/utils/geom_utils.py @@ -1,57 +1,53 @@ from typing import List, Tuple -from shapely.geometry import box, mapping, Polygon +from shapely.geometry import box, Polygon from geoalchemy2.shape import to_shape, WKBElement from pyproj import Transformer, CRS WGS_TO_MOLLWEIDE = Transformer.from_crs( - CRS.from_authority('EPSG', 4326), CRS.from_authority('ESRI', 54009), always_xy=True + CRS.from_authority("EPSG", 4326), CRS.from_authority("ESRI", 54009), always_xy=True ).transform -def bbox_to_wkt(bbox): +def bbox_to_wkt(bbox: List[float]) -> str: """ Convert a bbox to WKT. - :param List[float] bbox: the bbox as a list of floats in [minx, miny, maxx, maxy]. + :param bbox: the bbox as a list of floats in [minx, miny, maxx, maxy]. :returns: WKT representation - :rtype: str """ return box(*bbox).wkt -def bbox_to_geom(bbox): +def bbox_to_geom(bbox: List[float]) -> Polygon: """ Convert a bbox to a shapely geometry. - :param List[float] bbox: the bbox as a list of floats in [minx, miny, maxx, maxy]. + :param bbox: the bbox as a list of floats in [minx, miny, maxx, maxy]. :returns: shapely Polygon - :rtype: Polygon """ return box(*bbox) -def wkbe_to_geom(wkbe): +def wkbe_to_geom(wkbe: WKBElement) -> Polygon: """ Converts a geoalchemy2 :class:`WKBElement` to a shapely geometry. - :param WKBElement wkbe: The record. + :param wkbe: The record. :returns: The shapely polygon - :rtype: Polygon """ return to_shape(wkbe) -def wkbe_to_bbox(wkbe): +def wkbe_to_bbox(wkbe: WKBElement) -> Tuple[float]: """ Converts a geoalchemy2 :class:`WKBElement` to a list of bbox coordinates. - :param WKBElement wkbe: The record. + :param wkbe: The record. :returns: The bbox coordinates in [minx, miny, maxx, maxy]. - :rtype: Tuple[float] """ return to_shape(wkbe).bounds diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..f27303f --- /dev/null +++ b/setup.cfg @@ -0,0 +1,6 @@ +[flake8] +# ignore some errors to play nicely with black +ignore = E203,E266,E501,W503,F403,E722,F405 +max-complexity = 15 +max-line-length = 105 +exclude = .venv,.git,__pycache__,docs,dist,ssl,cron,ciso_reports diff --git a/tests/__init__.py b/tests/__init__.py index dbeb8a1..b8a535a 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,5 +1,5 @@ from rq import Worker, Queue, Connection with Connection(): - worker = Worker([Queue('packaging')]) + worker = Worker([Queue("packaging")]) worker.work(burst=True) diff --git a/tests/conftest.py b/tests/conftest.py index 82239c9..aa92b75 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -12,16 +12,17 @@ from . import utils -@pytest.yield_fixture(scope='function') +@pytest.yield_fixture(scope="function") def delete_jobs(): yield Job.query.delete() -@pytest.yield_fixture(scope='session') +@pytest.yield_fixture(scope="session") def flask_app(): - app = create_app(config_string='testing') + app = create_app(config_string="testing") from routing_packager_app import db + with app.app_context(): db.create_all() yield app @@ -29,25 +30,26 @@ def flask_app(): db.drop_all() -@pytest.yield_fixture(scope='session') +@pytest.yield_fixture(scope="session") def db(): from routing_packager_app import db as db_instance + yield db_instance -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def flask_app_client(flask_app: Flask): flask_app.response_class = utils.JSONResponse return flask_app.test_client() -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def basic_auth_header(flask_app: Flask): - admin_email = flask_app.config['ADMIN_EMAIL'] - admin_pass = flask_app.config['ADMIN_PASS'] + admin_email = flask_app.config["ADMIN_EMAIL"] + admin_pass = flask_app.config["ADMIN_PASS"] - auth_encoded = b64encode(bytes(':'.join((admin_email, admin_pass)).encode('utf-8'))).decode() - auth_header = {'Authorization': f'Basic {auth_encoded}'} + auth_encoded = b64encode(bytes(":".join((admin_email, admin_pass)).encode("utf-8"))).decode() + auth_header = {"Authorization": f"Basic {auth_encoded}"} return auth_header @@ -55,21 +57,21 @@ def basic_auth_header(flask_app: Flask): # For testing cli @pytest.fixture def script_info(flask_app): - return ScriptInfo(create_app=lambda info: flask_app) + return ScriptInfo(create_app=lambda: flask_app) # Creates needed directories and removes them after the test function -@pytest.yield_fixture(scope='function') +@pytest.yield_fixture(scope="function") def handle_dirs(flask_app): - main_dir = flask_app.config['DATA_DIR'] + main_dir = flask_app.config["DATA_DIR"] make_directories( main_dir, - flask_app.config['TEMP_DIR'], - flask_app.config['ENABLED_ROUTERS'], + flask_app.config["TEMP_DIR"], + flask_app.config["ENABLED_ROUTERS"], ) yield for e in os.listdir(main_dir): - if e in ['osm', 'tomtom', 'here']: + if e in ["osm", "tomtom", "here"]: continue p = os.path.join(main_dir, e) if os.path.isdir(p): diff --git a/tests/jobs/conftest.py b/tests/jobs/conftest.py index d50c9e9..bbc6d92 100644 --- a/tests/jobs/conftest.py +++ b/tests/jobs/conftest.py @@ -3,7 +3,7 @@ from routing_packager_app.api_v1 import Job -@pytest.yield_fixture(scope='function', autouse=True) +@pytest.yield_fixture(scope="function", autouse=True) def delete_jobs(): yield Job.query.delete() diff --git a/tests/jobs/test_jobs.py b/tests/jobs/test_jobs.py index dcc8ed4..c8e535c 100644 --- a/tests/jobs/test_jobs.py +++ b/tests/jobs/test_jobs.py @@ -3,116 +3,103 @@ import pytest from routing_packager_app.api_v1.jobs.models import Job -from routing_packager_app.constants import INTERVALS, COMPRESSIONS, ROUTERS, PROVIDERS, STATUSES +from routing_packager_app.constants import INTERVALS, COMPRESSIONS, PROVIDERS, STATUSES from routing_packager_app.utils.file_utils import make_package_path from ..utils import create_new_job, DEFAULT_ARGS_POST # TODO: disable tests for (so far) unsupported routers # @pytest.mark.parametrize('router', ROUTERS) -@pytest.mark.parametrize('provider', PROVIDERS) -@pytest.mark.parametrize('interval', INTERVALS) -@pytest.mark.parametrize('compression', COMPRESSIONS) +@pytest.mark.parametrize("provider", PROVIDERS) +@pytest.mark.parametrize("interval", INTERVALS) +@pytest.mark.parametrize("compression", COMPRESSIONS) def test_post_job(provider, interval, compression, flask_app_client, basic_auth_header): job = create_new_job( flask_app_client, auth_header=basic_auth_header, data={ - **DEFAULT_ARGS_POST, "router": 'valhalla', + **DEFAULT_ARGS_POST, + "router": "valhalla", "provider": provider, "interval": interval, - "compression": compression - } + "compression": compression, + }, ) - job_inst: Job = Job.query.get(job['id']) + job_inst: Job = Job.query.get(job["id"]) # TODO: re-enable when other routers should be tested # assert job_inst.router == router assert job_inst.provider == provider assert job_inst.interval == interval assert job_inst.compression == compression - assert job_inst.status == 'Queued' - assert job_inst.description == DEFAULT_ARGS_POST['description'] + assert job_inst.status == "Queued" + assert job_inst.description == DEFAULT_ARGS_POST["description"] assert job_inst.user_id == 1 - pbf_dir = flask_app_client.application.config[provider.upper() + '_DIR'] + pbf_dir = flask_app_client.application.config[provider.upper() + "_DIR"] assert job_inst.pbf_path == os.path.join(pbf_dir, f"{job_inst.id}.{provider}.pbf") dataset_path = make_package_path( - flask_app_client.application.config['DATA_DIR'], job_inst.name, 'valhalla', provider, - job_inst.compression + flask_app_client.application.config["DATA_DIR"], + job_inst.name, + "valhalla", + provider, + job_inst.compression, ) assert job_inst.path == dataset_path @pytest.mark.parametrize( - 'wrong_param', [ - { - 'provider': 'blabla' - }, - { - 'router': 'blabla' - }, - { - 'interval': 'blabla' - }, - { - 'compression': 'blabla' - }, - { - 'bbox': '' - }, - { - 'bbox': '1;2;3;4' - }, - { - 'bbox': '1,2,3,blabla' - }, - ] + "wrong_param", + [ + {"provider": "blabla"}, + {"router": "blabla"}, + {"interval": "blabla"}, + {"compression": "blabla"}, + {"bbox": ""}, + {"bbox": "1;2;3;4"}, + {"bbox": "1,2,3,blabla"}, + ], ) def test_post_job_wrong_enum_parameters(wrong_param, flask_app_client, basic_auth_header): """Test one wrong parameter each time.""" r = create_new_job( flask_app_client, auth_header=basic_auth_header, - data={ - **DEFAULT_ARGS_POST, - **wrong_param - }, - must_succeed=False + data={**DEFAULT_ARGS_POST, **wrong_param}, + must_succeed=False, ) assert r.status_code == 400 wrong_p = list(wrong_param.keys())[0] - error_msg = r.json['error'] + error_msg = r.json["error"] # parameter name should always be in the error message assert wrong_p in error_msg # bbox raises multiple errors - if wrong_p == 'router': - assert str(flask_app_client.application.config['ENABLED_ROUTERS']) in error_msg - elif wrong_p == 'provider': - assert str(flask_app_client.application.config['ENABLED_PROVIDERS']) in error_msg - elif wrong_p == 'interval': + if wrong_p == "router": + assert str(flask_app_client.application.config["ENABLED_ROUTERS"]) in error_msg + elif wrong_p == "provider": + assert str(flask_app_client.application.config["ENABLED_PROVIDERS"]) in error_msg + elif wrong_p == "interval": assert str(INTERVALS) in error_msg - elif wrong_p == 'compression': + elif wrong_p == "compression": assert str(COMPRESSIONS) in error_msg def test_job_bad_name(flask_app_client, basic_auth_header): r = create_new_job( - flask_app_client, { - **DEFAULT_ARGS_POST, "name": 'bad/name' - }, + flask_app_client, + {**DEFAULT_ARGS_POST, "name": "bad/name"}, basic_auth_header, - must_succeed=False + must_succeed=False, ) assert r.status_code == 400 - assert 'name' in r.json['error'] + assert "name" in r.json["error"] def test_post_job_existing_job_combo(flask_app_client, basic_auth_header): @@ -124,7 +111,7 @@ def test_post_job_existing_job_combo(flask_app_client, basic_auth_header): ) assert r.status_code == 409 - assert str(job['id']) in r.json['error'] + assert str(job["id"]) in r.json["error"] def test_post_job_forbidden(flask_app_client): @@ -136,88 +123,76 @@ def test_post_job_forbidden(flask_app_client): def test_get_jobs_all(flask_app_client, basic_auth_header): - for provider in ['tomtom', 'osm']: - for interval in ['once', 'daily']: - for bbox in ['0,0,1,1', '2,2,3,3']: - r = create_new_job( + for provider in ["tomtom", "osm"]: + for interval in ["once", "daily"]: + for bbox in ["0,0,1,1", "2,2,3,3"]: + create_new_job( flask_app_client, data={ - **DEFAULT_ARGS_POST, "name": f"{provider}, {interval}, {bbox}", + **DEFAULT_ARGS_POST, + "name": f"{provider}, {interval}, {bbox}", "provider": provider, - "router": 'valhalla', + "router": "valhalla", "interval": interval, - "bbox": bbox + "bbox": bbox, }, auth_header=basic_auth_header, - must_succeed=False + must_succeed=False, ) - # First get all 24 results - r = flask_app_client.get('/api/v1/jobs') + # First get all 8 results + r = flask_app_client.get("/api/v1/jobs") + print(r) assert len(r.json) == 8 # Then test all query string parameters - r = flask_app_client.get('/api/v1/jobs', query_string={"interval": 'once'}) + r = flask_app_client.get("/api/v1/jobs", query_string={"interval": "once"}) assert len(r.json) == 4 - r = flask_app_client.get('/api/v1/jobs', query_string={"router": 'valhalla'}) + r = flask_app_client.get("/api/v1/jobs", query_string={"router": "valhalla"}) assert len(r.json) == 8 - r = flask_app_client.get('/api/v1/jobs', query_string={"provider": 'tomtom'}) + r = flask_app_client.get("/api/v1/jobs", query_string={"provider": "tomtom"}) assert len(r.json) == 4 - r = flask_app_client.get('/api/v1/jobs', query_string={"status": 'Queued'}) + r = flask_app_client.get("/api/v1/jobs", query_string={"status": "Queued"}) assert len(r.json) == 8 - r = flask_app_client.get('/api/v1/jobs', query_string={"status": 'Extracting'}) + r = flask_app_client.get("/api/v1/jobs", query_string={"status": "Extracting"}) assert len(r.json) == 0 - r = flask_app_client.get('/api/v1/jobs', query_string={"bbox": '0,0,1.5,1.5'}) + r = flask_app_client.get("/api/v1/jobs", query_string={"bbox": "0,0,1.5,1.5"}) assert len(r.json) == 4 @pytest.mark.parametrize( - 'bbox', [ - { - "bbox": '0,0,1,1', - "count": 1 - }, - { - "bbox": '0.5,0.5,0.75,0.75', - "count": 1 - }, - { - "bbox": '0.5,0.5,2.75,2.75', - "count": 2 - }, - { - "bbox": '0,0,4,4', - "count": 2 - }, - ] + "bbox", + [ + {"bbox": "0,0,1,1", "count": 1}, + {"bbox": "0.5,0.5,0.75,0.75", "count": 1}, + {"bbox": "0.5,0.5,2.75,2.75", "count": 2}, + {"bbox": "0,0,4,4", "count": 2}, + ], ) def test_get_jobs_bbox(bbox, flask_app_client, basic_auth_header): - for box in ['0,0,1,1', '2,2,3,3']: + for box in ["0,0,1,1", "2,2,3,3"]: create_new_job( flask_app_client, - data={ - **DEFAULT_ARGS_POST, "name": f"{box}", - "bbox": box - }, + data={**DEFAULT_ARGS_POST, "name": f"{box}", "bbox": box}, auth_header=basic_auth_header, - must_succeed=False + must_succeed=False, ) - r = flask_app_client.get('api/v1/jobs', query_string={"bbox": bbox['bbox']}) + r = flask_app_client.get("api/v1/jobs", query_string={"bbox": bbox["bbox"]}) - assert len(r.json) == bbox['count'] + assert len(r.json) == bbox["count"] def test_get_jobs_bad_status(flask_app_client): - r = flask_app_client.get('/api/v1/jobs', query_string={'status': 'blabla'}) + r = flask_app_client.get("/api/v1/jobs", query_string={"status": "blabla"}) assert r.status_code == 400 - assert str(STATUSES) in r.json['error'] + assert str(STATUSES) in r.json["error"] def test_get_job(flask_app_client, basic_auth_header): @@ -225,22 +200,22 @@ def test_get_job(flask_app_client, basic_auth_header): r = flask_app_client.get(f'api/v1/jobs/{job["id"]}').json - data_dir = flask_app_client.application.config['DATA_DIR'] - provider = DEFAULT_ARGS_POST['provider'] + data_dir = flask_app_client.application.config["DATA_DIR"] + provider = DEFAULT_ARGS_POST["provider"] - del r['last_started'] + del r["last_started"] assert { **DEFAULT_ARGS_POST, "bbox": "0.0,0.0,1.0,1.0", # App returns floats - "status": 'Queued', + "status": "Queued", "last_finished": None, "pbf_path": os.path.join(data_dir, provider, f"{r['id']}.{provider}.pbf"), "job_id": None, "id": job["id"], - 'path': os.path.join(data_dir, 'valhalla/valhalla_osm_test/valhalla_osm_test.zip'), + "path": os.path.join(data_dir, "valhalla/valhalla_osm_test/valhalla_osm_test.zip"), "container_id": None, - "user_id": 1 + "user_id": 1, } == r @@ -249,5 +224,5 @@ def test_delete_job(flask_app_client, basic_auth_header): r = flask_app_client.delete(f'api/v1/jobs/{job["id"]}', headers=basic_auth_header) - assert r.data == b'' + assert r.data == b"" assert r.status_code == 204 diff --git a/tests/test_app_creation.py b/tests/test_app_creation.py index 2fae30a..5990a1b 100644 --- a/tests/test_app_creation.py +++ b/tests/test_app_creation.py @@ -6,41 +6,43 @@ def test_create_app(): - create_app('testing') + create_app("testing") -@pytest.mark.parametrize('flask_config_name', ['production', 'development', 'testing']) +@pytest.mark.parametrize("flask_config_name", ["production", "development", "testing"]) def test_create_app_passing_flask_config_name(monkeypatch, flask_config_name): - if flask_config_name != 'testing': + if flask_config_name != "testing": from config import ProdConfig, DevConfig + new_data_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data") for c in (ProdConfig, DevConfig): - monkeypatch.setattr(c, 'DATA_DIR', new_data_dir) - monkeypatch.setattr(c, 'ENABLED_PROVIDERS', ["osm", "tomtom", "here"]) + monkeypatch.setattr(c, "DATA_DIR", new_data_dir) + monkeypatch.setattr(c, "ENABLED_PROVIDERS", ["osm", "tomtom", "here"]) create_app(config_string=flask_config_name) def test_create_app_empty_config(monkeypatch): """Remove FLASK_CONFIG=testing""" - if os.getenv('FLASK_CONFIG'): - monkeypatch.delenv('FLASK_CONFIG') + if os.getenv("FLASK_CONFIG"): + monkeypatch.delenv("FLASK_CONFIG") with pytest.raises(KeyError): create_app(config_string=None) def test_create_app_with_broken_import_config(monkeypatch): - CONF_MAPPER['broken-import-config'] = 'broken-import-config' - if os.getenv('FLASK_CONFIG'): - monkeypatch.delenv('FLASK_CONFIG') + CONF_MAPPER["broken-import-config"] = "broken-import-config" + if os.getenv("FLASK_CONFIG"): + monkeypatch.delenv("FLASK_CONFIG") with pytest.raises(ImportError): - create_app('broken-import-config') - del CONF_MAPPER['broken-import-config'] + create_app("broken-import-config") + del CONF_MAPPER["broken-import-config"] def test_false_docker_image(monkeypatch): from config import TestingConfig - monkeypatch.setattr(TestingConfig, 'ENABLED_ROUTERS', ['valhalla', 'graphhopper']) - monkeypatch.setattr(TestingConfig, 'GRAPHHOPPER_IMAGE', '') + + monkeypatch.setattr(TestingConfig, "ENABLED_ROUTERS", ["valhalla", "graphhopper"]) + monkeypatch.setattr(TestingConfig, "GRAPHHOPPER_IMAGE", "") with pytest.raises(NullResource): - create_app('testing') + create_app("testing") diff --git a/tests/test_cli.py b/tests/test_cli.py index 1241100..4d19006 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -8,15 +8,13 @@ def test_register(flask_app_client, basic_auth_header, script_info, delete_jobs): - intervals = ('daily', 'weekly', 'monthly') + intervals = ("daily", "weekly", "monthly") for interval in intervals: create_new_job( - flask_app_client, { - **DEFAULT_ARGS_POST, "name": interval, - "interval": interval - }, + flask_app_client, + {**DEFAULT_ARGS_POST, "name": interval, "interval": interval}, basic_auth_header, - must_succeed=False + must_succeed=False, ) # register the CLI with the app @@ -24,28 +22,26 @@ def test_register(flask_app_client, basic_auth_header, script_info, delete_jobs) # Run the damn thing runner = CliRunner() - result = runner.invoke(update_f, ['daily', '--config', 'testing'], obj=script_info) + result = runner.invoke(update_f, ["daily", "--config", "testing"], obj=script_info) if result.exit_code or result.exception: - raise RuntimeError(f"CLI test wasn't successful. Some hints maybe:\n{result.stdout}") + raise RuntimeError(f"CLI test wasn't successful. Some hints maybe:\n{result.exception}") def test_sort_jobs(flask_app_client, basic_auth_header): - bboxes = ('0,0,3,3', '0,0,1,1', '0,0,2,2') + bboxes = ("0,0,3,3", "0,0,1,1", "0,0,2,2") expected_ids = list() for bbox in bboxes: expected_ids.append( create_new_job( - flask_app_client, { - **DEFAULT_ARGS_POST, "name": bbox, - "description": 'blablablabla', - "bbox": bbox - }, basic_auth_header + flask_app_client, + {**DEFAULT_ARGS_POST, "name": bbox, "description": "blablablabla", "bbox": bbox}, + basic_auth_header, )["id"] ) expected_ids = [expected_ids[0], expected_ids[2], expected_ids[1]] - jobs = Job.query.filter_by(description='blablablabla').all() + jobs = Job.query.filter_by(description="blablablabla").all() ordered_jobs = _sort_jobs(jobs) assert [x.id for x in ordered_jobs] == expected_ids diff --git a/tests/test_geometry_utils.py b/tests/test_geometry_utils.py index ce28c46..76aebba 100644 --- a/tests/test_geometry_utils.py +++ b/tests/test_geometry_utils.py @@ -8,7 +8,7 @@ def test_bbox_to_wkt(): wkt = geom_utils.bbox_to_wkt(bbox) - assert wkt == 'POLYGON ((3 2, 3 4, 1 4, 1 2, 3 2))' + assert wkt == "POLYGON ((3 2, 3 4, 1 4, 1 2, 3 2))" def test_bbox_to_wkt_error(): diff --git a/tests/test_osmium.py b/tests/test_osmium.py index c12eff6..fa60152 100644 --- a/tests/test_osmium.py +++ b/tests/test_osmium.py @@ -1,7 +1,6 @@ import pytest from shapely.geometry import Polygon import os -import json from .utils import make_pbfs, DEFAULT_ARGS_POST, create_new_job, create_package_params from routing_packager_app.osmium import get_pbfs_by_area # @@ -38,38 +37,38 @@ def test_pbfs_by_area_missing_pbf(tmpdir): def test_pbf_endpoint_success(tmpdir, flask_app_client, basic_auth_header, delete_jobs, handle_dirs): job = create_new_job( - flask_app_client, { - **DEFAULT_ARGS_POST, "bbox": '1.542892,42.508552,1.574821,42.53082' - }, basic_auth_header + flask_app_client, + {**DEFAULT_ARGS_POST, "bbox": "1.542892,42.508552,1.574821,42.53082"}, + basic_auth_header, ) - create_package(*create_package_params(job), config_string='testing') - job_id = job['id'] + create_package(*create_package_params(job), config_string="testing") + job_id = job["id"] - r = flask_app_client.get(f'/api/v1/jobs/{job_id}/data/pbf').json + r = flask_app_client.get(f"/api/v1/jobs/{job_id}/data/pbf").json - expected_fields = ('filepath', 'timestamp', 'bbox') + expected_fields = ("filepath", "timestamp", "bbox") for f in expected_fields: assert f in r.keys() assert isinstance(r[f], str) assert len(r[f]) > 0 - assert 'size' in r - assert r['size'] in range(76700, 76800) + assert "size" in r + assert r["size"] in range(76700, 76800) - os.remove(job['pbf_path']) + os.remove(job["pbf_path"]) def test_pbf_endpoint_missing_job(flask_app_client, basic_auth_header, delete_jobs, handle_dirs): job = create_new_job( - flask_app_client, { - **DEFAULT_ARGS_POST, "bbox": '1.542892,42.508552,1.574821,42.53082' - }, basic_auth_header + flask_app_client, + {**DEFAULT_ARGS_POST, "bbox": "1.542892,42.508552,1.574821,42.53082"}, + basic_auth_header, ) - job_id = job['id'] + job_id = job["id"] - if os.path.exists(job['pbf_path']): - os.remove(job['pbf_path']) + if os.path.exists(job["pbf_path"]): + os.remove(job["pbf_path"]) - r = flask_app_client.get(f'/api/v1/jobs/{job_id}/data/pbf') + r = flask_app_client.get(f"/api/v1/jobs/{job_id}/data/pbf") assert r.status_code == 404 - assert f'OSM file for job {job_id} not found.' == r.json['error'] + assert f"OSM file for job {job_id} not found." == r.json["error"] diff --git a/tests/test_tasks.py b/tests/test_tasks.py index a07a697..5dcaaa2 100644 --- a/tests/test_tasks.py +++ b/tests/test_tasks.py @@ -1,7 +1,6 @@ import os import pytest -from flask import current_app from werkzeug.exceptions import InternalServerError from .utils import create_new_job, DEFAULT_ARGS_POST, create_package_params @@ -9,7 +8,7 @@ from routing_packager_app.utils.file_utils import make_package_path -@pytest.mark.parametrize('provider', ['osm', 'tomtom']) +@pytest.mark.parametrize("provider", ["osm", "tomtom"]) def test_create_package(provider, flask_app_client, basic_auth_header, delete_jobs, handle_dirs): bbox = [1.542892, 42.508552, 1.574821, 42.53082] @@ -18,15 +17,15 @@ def test_create_package(provider, flask_app_client, basic_auth_header, delete_jo { **DEFAULT_ARGS_POST, "name": provider, - "bbox": ','.join([str(x) for x in bbox]), # needs to be a real Andorra extent + "bbox": ",".join([str(x) for x in bbox]), # needs to be a real Andorra extent }, - basic_auth_header + basic_auth_header, ) - create_package(*create_package_params(job), config_string='testing') + create_package(*create_package_params(job), config_string="testing") -@pytest.mark.parametrize('compression', ['zip', 'tar']) +@pytest.mark.parametrize("compression", ["zip", "tar"]) def test_create_package_compressions( compression, flask_app_client, basic_auth_header, monkeypatch, delete_jobs, handle_dirs ): @@ -36,29 +35,29 @@ def test_create_package_compressions( **DEFAULT_ARGS_POST, "name": compression, "compression": compression, - "bbox": '1.542892,42.508552,1.574821,42.53082', # needs to be a real Andorra extent + "bbox": "1.542892,42.508552,1.574821,42.53082", # needs to be a real Andorra extent }, - basic_auth_header + basic_auth_header, ) - create_package(*create_package_params(job), config_string='testing') + create_package(*create_package_params(job), config_string="testing") def test_create_package_missing_pbf( flask_app_client, basic_auth_header, monkeypatch, delete_jobs, handle_dirs ): job1 = create_new_job( - flask_app_client, { - **DEFAULT_ARGS_POST, "bbox": '1.542892,42.508552,1.574821,42.53082' - }, basic_auth_header + flask_app_client, + {**DEFAULT_ARGS_POST, "bbox": "1.542892,42.508552,1.574821,42.53082"}, + basic_auth_header, ) - create_package(*create_package_params(job1), config_string='testing') + create_package(*create_package_params(job1), config_string="testing") # delete the PBF os.remove(job1["pbf_path"]) - with pytest.raises(InternalServerError) as e: - create_package(*create_package_params(job1), config_string='testing') + with pytest.raises(InternalServerError): + create_package(*create_package_params(job1), config_string="testing") # will fail right now since there might actually be a PBF 0,0,1,1 will extract smth from @@ -77,10 +76,10 @@ def test_create_package_missing_pbf( def test_create_package_check_dirs(flask_app_client, basic_auth_header, delete_jobs, handle_dirs): - router = 'valhalla' - provider = 'osm' - name = 'test' - compression = 'zip' + router = "valhalla" + provider = "osm" + name = "test" + compression = "zip" job = create_new_job( flask_app_client, @@ -90,35 +89,35 @@ def test_create_package_check_dirs(flask_app_client, basic_auth_header, delete_j "provider": provider, "name": name, "compression": "zip", - "bbox": '1.542892,42.508552,1.574821,42.53082', # needs to be a real Andorra extent + "bbox": "1.542892,42.508552,1.574821,42.53082", # needs to be a real Andorra extent }, - basic_auth_header + basic_auth_header, ) - create_package(*create_package_params(job), config_string='testing', cleanup=False) + create_package(*create_package_params(job), config_string="testing", cleanup=False) app = flask_app_client.application - data_dir = app.config['DATA_DIR'] - temp_dir = app.config['TEMP_DIR'] + data_dir = app.config["DATA_DIR"] + temp_dir = app.config["TEMP_DIR"] # osmium's output cut_pbf_path = os.path.join(data_dir, provider, f'{job["id"]}.{provider}.pbf') - assert os.path.isfile(cut_pbf_path), f'{cut_pbf_path} doesnt exist' + assert os.path.isfile(cut_pbf_path), f"{cut_pbf_path} doesnt exist" # temp graphs/tiles - graph_dir = os.path.join(temp_dir, router, 'graph') - assert len( - os.listdir(graph_dir) - ) > 0, f'{graph_dir} has the following contents:\n{os.listdir(graph_dir)}' + graph_dir = os.path.join(temp_dir, router, "graph") + assert ( + len(os.listdir(graph_dir)) > 0 + ), f"{graph_dir} has the following contents:\n{os.listdir(graph_dir)}" assert all([os.path.isdir(os.path.join(graph_dir, d)) for d in os.listdir(graph_dir)]) # output package pkg_path = make_package_path(data_dir, name, router, provider, compression) - assert os.path.isfile(pkg_path), f'{pkg_path} doesnt exist' + assert os.path.isfile(pkg_path), f"{pkg_path} doesnt exist" # output meta JSON out_dir = os.path.dirname(pkg_path) fname = os.path.basename(pkg_path) fname_sanitized = fname.split(os.extsep, 1)[0] - fp = os.path.join(out_dir, fname_sanitized + '.json') - assert os.path.isfile(fp), f'{fp} doesnt exist' + fp = os.path.join(out_dir, fname_sanitized + ".json") + assert os.path.isfile(fp), f"{fp} doesnt exist" diff --git a/tests/users/conftest.py b/tests/users/conftest.py index e6b0273..a8c053a 100644 --- a/tests/users/conftest.py +++ b/tests/users/conftest.py @@ -3,7 +3,7 @@ from routing_packager_app.api_v1 import User -@pytest.yield_fixture(scope='function', autouse=True) +@pytest.yield_fixture(scope="function", autouse=True) def delete_jobs(): yield User.query.filter(User.id != 1).delete() diff --git a/tests/users/test_users.py b/tests/users/test_users.py index 68fed71..5b9ec23 100644 --- a/tests/users/test_users.py +++ b/tests/users/test_users.py @@ -1,12 +1,12 @@ from json.decoder import JSONDecodeError import re -from typing import List from base64 import b64encode import pytest from routing_packager_app.api_v1.users.models import User from ..utils import create_new_user + """Remember that @before_first_request will add an admin user!""" @@ -15,9 +15,9 @@ def test_new_user_creation(flask_app_client, basic_auth_header): flask_app_client, auth_header=basic_auth_header, data={ - 'email': "user1@email.com", - 'password': "user1_password", - } + "email": "user1@email.com", + "password": "user1_password", + }, ) user1_instance = User.query.get(user_id) @@ -27,49 +27,45 @@ def test_new_user_creation(flask_app_client, basic_auth_header): def test_new_user_creation_duplicate_error(flask_app_client, basic_auth_header): # pylint: disable=invalid-name - user_id = create_new_user( + create_new_user( flask_app_client, auth_header=basic_auth_header, data={ - 'email': "user1@email.com", - 'password': "user1_password", - } + "email": "user1@email.com", + "password": "user1_password", + }, ) response = create_new_user( flask_app_client, auth_header=basic_auth_header, data={ - 'email': "user1@email.com", - 'password': "user1_password", + "email": "user1@email.com", + "password": "user1_password", }, - must_succeed=False + must_succeed=False, ) assert response.status_code == 409 - assert response.content_type == 'application/json' - assert response.json['error'] == 'Key (email)=(user1@email.com) already exists.' + assert response.content_type == "application/json" + assert response.json["error"] == "Key (email)=(user1@email.com) already exists." def test_new_user_invalid_field_error(flask_app_client, basic_auth_header): - invalid_field = 'bogus_field' + invalid_field = "bogus_field" response = create_new_user( flask_app_client, auth_header=basic_auth_header, - data={ - 'email': "user1@email.com", - 'password': "user1_password", - invalid_field: "bogus_value" - }, - must_succeed=False + data={"email": "user1@email.com", "password": "user1_password", invalid_field: "bogus_value"}, + must_succeed=False, ) assert response.status_code == 400 - assert response.content_type == 'application/json' - assert response.json['error'] == f'Unknown arguments: {invalid_field}' + assert response.content_type == "application/json" + assert response.json["error"] == f"Unknown arguments: {invalid_field}" -@pytest.mark.parametrize('missing_field', ('email', 'password')) +@pytest.mark.parametrize("missing_field", ("email", "password")) def test_new_user_missing_field_error(missing_field, flask_app_client, basic_auth_header): - data = {'email': "user1@email.com", 'password': "user1_password"} + data = {"email": "user1@email.com", "password": "user1_password"} del data[missing_field] response = create_new_user( @@ -77,43 +73,37 @@ def test_new_user_missing_field_error(missing_field, flask_app_client, basic_aut ) assert response.status_code == 400 - assert response.json['error'] == f"'{missing_field}' is required in request." + assert response.json["error"] == f"'{missing_field}' is required in request." -@pytest.mark.parametrize('email', ('user@email.12', 'user.me', 'uuser@email.c', 'user@email.')) +@pytest.mark.parametrize("email", ("user@email.12", "user.me", "uuser@email.c", "user@email.")) def test_new_user_wrong_email_error(email, flask_app_client, basic_auth_header): - data = {'email': email, 'password': "user_password"} + data = {"email": email, "password": "user_password"} response = create_new_user( flask_app_client, auth_header=basic_auth_header, data=data, must_succeed=False ) assert response.status_code == 400 - assert response.json['error'] == f'Email \'{email}\' is invalid.' + assert response.json["error"] == f"Email '{email}' is invalid." def test_new_user_unauthorized(flask_app_client, basic_auth_header): - email = 'user@email.org' - password = 'password' + email = "user@email.org" + password = "password" create_new_user( - flask_app_client, auth_header=basic_auth_header, data={ - 'email': email, - 'password': password - } + flask_app_client, auth_header=basic_auth_header, data={"email": email, "password": password} ) - auth_encoded = b64encode(bytes(':'.join((email, password)).encode('utf-8'))).decode() - auth_header = {'Authorization': f'Basic {auth_encoded}'} + auth_encoded = b64encode(bytes(":".join((email, password)).encode("utf-8"))).decode() + auth_header = {"Authorization": f"Basic {auth_encoded}"} response = create_new_user( flask_app_client, auth_header=auth_header, - data={ - 'email': 'soemone@email.org', - 'password': 'bafa' - }, - must_succeed=False + data={"email": "soemone@email.org", "password": "bafa"}, + must_succeed=False, ) assert response.status_code == 403 @@ -123,11 +113,8 @@ def test_new_user_forbidden(flask_app_client): response = create_new_user( flask_app_client, auth_header={}, - data={ - 'email': 'soemone@email.org', - 'password': 'bafa' - }, - must_succeed=False + data={"email": "soemone@email.org", "password": "bafa"}, + must_succeed=False, ) assert response.status_code == 401 @@ -135,7 +122,7 @@ def test_new_user_forbidden(flask_app_client): def test_get_all_users_empty(flask_app_client): # Will still contain the admin user - assert len(flask_app_client.get('/api/v1/users/').json) == 1 + assert len(flask_app_client.get("/api/v1/users/").json) == 1 def test_get_all_users_not_empty(flask_app_client, basic_auth_header): @@ -144,19 +131,16 @@ def test_get_all_users_not_empty(flask_app_client, basic_auth_header): idx = create_new_user( flask_app_client, auth_header=basic_auth_header, - data={ - "email": f'user{i}@email.com', - "password": f'user{i}_password' - } + data={"email": f"user{i}@email.com", "password": f"user{i}_password"}, ) user_ids.append(idx) - response = flask_app_client.get('/api/v1/users/') + response = flask_app_client.get("/api/v1/users/") assert len(response.json) == 4 - assert any('user4@email.com' in x['email'] for x in response.json) + assert any("user4@email.com" in x["email"] for x in response.json) - search_user = r'^user[3|4|5]@email\.com$' + search_user = r"^user[3|4|5]@email\.com$" for i in user_ids: user = User.query.get(i) assert re.search(search_user, user.email) @@ -166,93 +150,84 @@ def test_get_single_user(flask_app_client, basic_auth_header): user_id = create_new_user( flask_app_client, auth_header=basic_auth_header, - data={ - 'email': "userx@email.com", - 'password': "userx_password" - } + data={"email": "userx@email.com", "password": "userx_password"}, ) - response = flask_app_client.get(f'/api/v1/users/{user_id}') + response = flask_app_client.get(f"/api/v1/users/{user_id}") assert response.status_code == 200 - assert response.content_type == 'application/json' - assert response.json['email'] == 'userx@email.com' + assert response.content_type == "application/json" + assert response.json["email"] == "userx@email.com" def test_get_single_user_not_found(flask_app_client): - response = flask_app_client.get('/api/v1/users/2') + response = flask_app_client.get("/api/v1/users/2") assert response.status_code == 404 - assert response.content_type == 'application/json' - assert response.json['error'] == 'Entity not found.' + assert response.content_type == "application/json" + assert response.json["error"] == "Entity not found." def test_delete_single_user(flask_app_client, basic_auth_header): create_new_user( flask_app_client, auth_header=basic_auth_header, - data={ - 'email': "usery@email.com", - 'password': "usery_password" - } + data={"email": "usery@email.com", "password": "usery_password"}, ) - user_before = User.query.filter_by(email='usery@email.com').first() + user_before = User.query.filter_by(email="usery@email.com").first() assert user_before.password == "usery_password" - response = flask_app_client.delete(f'/api/v1/users/{user_before.id}', headers=basic_auth_header) + response = flask_app_client.delete(f"/api/v1/users/{user_before.id}", headers=basic_auth_header) assert response.status_code == 204 # Empty response means `json` will fail to parse with pytest.raises(JSONDecodeError): - assert response.json == None + assert response.json is None - user_after = User.query.filter_by(email='usery@email.com').first() + user_after = User.query.filter_by(email="usery@email.com").first() assert user_after is None def test_delete_single_user_not_found(flask_app_client, basic_auth_header): - response = flask_app_client.delete('/api/v1/users/2', headers=basic_auth_header) + response = flask_app_client.delete("/api/v1/users/2", headers=basic_auth_header) assert response.status_code == 404 - assert response.content_type == 'application/json' - assert response.json['error'] == 'Entity not found.' + assert response.content_type == "application/json" + assert response.json["error"] == "Entity not found." def test_delete_admin_error(flask_app_client, basic_auth_header): - response = flask_app_client.delete('/api/v1/users/1', headers=basic_auth_header) + response = flask_app_client.delete("/api/v1/users/1", headers=basic_auth_header) assert response.status_code == 409 - assert response.json['error'] == "Can't delete admin user." + assert response.json["error"] == "Can't delete admin user." def test_delete_auth_no_admin_error(flask_app_client, basic_auth_header): - email = 'user@email.org' - password = 'password' + email = "user@email.org" + password = "password" new_user_id = create_new_user( - flask_app_client, auth_header=basic_auth_header, data={ - 'email': email, - 'password': password - } + flask_app_client, auth_header=basic_auth_header, data={"email": email, "password": password} ) - auth_encoded = b64encode(bytes(':'.join((email, password)).encode('utf-8'))).decode() - auth_header = {'Authorization': f'Basic {auth_encoded}'} + auth_encoded = b64encode(bytes(":".join((email, password)).encode("utf-8"))).decode() + auth_header = {"Authorization": f"Basic {auth_encoded}"} - response = flask_app_client.delete(f'/api/v1/users/{new_user_id}', headers=auth_header) + response = flask_app_client.delete(f"/api/v1/users/{new_user_id}", headers=auth_header) assert response.status_code == 403 - assert response.json['error'] == "Admin privileges are required to delete a user." + assert response.json["error"] == "Admin privileges are required to delete a user." def test_admin_user_created(flask_app_client, flask_app): """Tests whether the admin user was created before the first request""" - expected_email = flask_app.config['ADMIN_EMAIL'] - expected_pass = flask_app.config['ADMIN_PASS'] + expected_email = flask_app.config["ADMIN_EMAIL"] + expected_pass = flask_app.config["ADMIN_PASS"] - response = flask_app_client.get('/api/v1/users') - assert response.json[0]['email'] == expected_email + response = flask_app_client.get("/api/v1/users") + assert response.json[0]["email"] == expected_email admin_user = User.query.get(1) assert admin_user.email == expected_email @@ -261,10 +236,7 @@ def test_admin_user_created(flask_app_client, flask_app): def test_basic_auth_no_auth(flask_app_client): response = flask_app_client.post( - '/api/v1/users/', data={ - 'email': "userx@email.com", - 'password': "userx_password" - } + "/api/v1/users/", data={"email": "userx@email.com", "password": "userx_password"} ) assert response.status_code == 401 @@ -272,16 +244,13 @@ def test_basic_auth_no_auth(flask_app_client): def test_basic_auth_wrong_auth(flask_app_client): - auth = ('gis', 'ops') - auth_encoded = b64encode(bytes(':'.join((auth)).encode('utf-8'))).decode() - auth_header = {'Authorization': f'Basic {auth_encoded}'} + auth = ("gis", "ops") + auth_encoded = b64encode(bytes(":".join((auth)).encode("utf-8"))).decode() + auth_header = {"Authorization": f"Basic {auth_encoded}"} response = flask_app_client.post( - '/api/v1/users/', + "/api/v1/users/", headers=auth_header, - data={ - 'email': "userx@email.com", - 'password': "userx_password" - } + data={"email": "userx@email.com", "password": "userx_password"}, ) assert response.status_code == 401 diff --git a/tests/utils.py b/tests/utils.py index 31e5c1c..4100848 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,6 +1,6 @@ import json import os -from typing import List, Tuple +from typing import List, Tuple # noqa: F401 from flask import Response, current_app from flask.testing import Client @@ -11,13 +11,13 @@ from routing_packager_app.utils.file_utils import make_package_path DEFAULT_ARGS_POST = { - "name": f"test", - "description": 'test description', + "name": "test", + "description": "test description", "bbox": "0,0,1,1", - "router": 'valhalla', - "provider": 'osm', - "interval": 'once', - "compression": 'zip', + "router": "valhalla", + "provider": "osm", + "interval": "once", + "compression": "zip", } @@ -26,6 +26,7 @@ class JSONResponse(Response): """ A Response class with extra useful helpers, i.e. ``.json`` property. """ + @cached_property def json(self): return json.loads(self.get_data(as_text=True)) @@ -35,13 +36,15 @@ def create_new_user(flask_app_client, data, auth_header, must_succeed=True): """ Helper function for valid new user creation. """ - response = flask_app_client.post('/api/v1/users', headers=auth_header, data=data) + response = flask_app_client.post("/api/v1/users", headers=auth_header, json=data) if must_succeed: - assert response.status_code == 200, f"status code was {response.status_code} with {response.data}" - assert response.content_type == 'application/json' - assert set(response.json.keys()) >= {'id', 'email'} - return response.json['id'] + assert ( + response.status_code == 200 + ), f"status code was {response.status_code} with {response.data}" + assert response.content_type == "application/json" + assert set(response.json.keys()) >= {"id", "email"} + return response.json["id"] return response @@ -49,11 +52,13 @@ def create_new_job(client: Client, data, auth_header, must_succeed=True): """ Helper function for valid new job creation. """ - response = client.post('/api/v1/jobs', headers=auth_header, data=data) + response = client.post("/api/v1/jobs", headers=auth_header, json=data) if must_succeed: - assert response.status_code == 200, f"status code was {response.status_code} with {response.data}" - assert response.content_type == 'application/json' + assert ( + response.status_code == 200 + ), f"status code was {response.status_code} with {response.data}" + assert response.content_type == "application/json" return response.json return response @@ -84,7 +89,7 @@ def make_pbfs(dirname, feats): # when extracting it sets the bounds we need fn_e = f"new_{fn}" fp_e = str(dirname / fn_e) - bbox_str = ','.join([str(x) for x in (*e[0], *e[1])]) + bbox_str = ",".join([str(x) for x in (*e[0], *e[1])]) proc = exec_cmd(extract_cmd.format(bbox=bbox_str, out_file=fp_e, in_file=fp)) proc.wait() os.remove(fp) @@ -156,12 +161,19 @@ def create_package_params(j): :returns: Tuple with all parameters inside :rtype: tuple """ - data_dir = current_app.config['DATA_DIR'] + data_dir = current_app.config["DATA_DIR"] result_path = make_package_path(data_dir, j["name"], j["router"], j["provider"], j["compression"]) return ( - j["id"], j["name"], j["description"], j["router"], j["provider"], - [float(x) for x in j["bbox"].split(',') - ], result_path, j['pbf_path'], j['compression'], current_app.config['ADMIN_EMAIL'] + j["id"], + j["name"], + j["description"], + j["router"], + j["provider"], + [float(x) for x in j["bbox"].split(",")], + result_path, + j["pbf_path"], + j["compression"], + current_app.config["ADMIN_EMAIL"], )