diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6ffeae4a..b0b394d8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ repos: rev: 18.6b4 hooks: - id: black - language_version: python3.7 + language_version: python3.8 - repo: git://github.com/pre-commit/pre-commit-hooks rev: v2.0.0 hooks: @@ -19,10 +19,10 @@ repos: - id: no-commit-to-branch - id: trailing-whitespace - id: debug-statements - language_version: python3.7 + language_version: python3.8 - id: flake8 log_file: '.artifacts/flake8.log' - language_version: python3.7 + language_version: python3.8 - id: requirements-txt-fixer args: ['requirements-base.txt', 'requirements-dev.txt', 'requirements-test.txt'] # - repo: https://github.com/pre-commit/mirrors-mypy diff --git a/.python-version b/.python-version index afc17dca..e6389a2b 100644 --- a/.python-version +++ b/.python-version @@ -1,2 +1,2 @@ -3.7.2 +3.8.1 2.7.14 diff --git a/.travis.yml b/.travis.yml index fb0d5435..469bbbb6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,12 +4,12 @@ branches: - trying language: python sudo: true -dist: xenial +dist: buster services: - redis-server - postgresql python: - - '3.7' + - '3.8' cache: yarn: true directories: diff --git a/Dockerfile b/Dockerfile index 3c0a7fa3..9d208710 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Use an official Python runtime as a parent image -FROM python:3.7-slim-stretch +FROM python:3.8.2-slim-buster # add our user and group first to make sure their IDs get assigned consistently RUN groupadd -r zeus && useradd -r -m -g zeus zeus @@ -29,6 +29,7 @@ RUN set -ex \ libpq-dev \ libxml2-dev \ libxslt-dev \ + libz-dev \ openssl \ ssh \ wget \ diff --git a/Makefile b/Makefile index 315f0e0c..fd8121a4 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ upgrade: install-requirements poetry run zeus db upgrade setup-git: - pip install "pre-commit>=1.12.0,<1.13.0" + pip install "pre-commit>=2.2.0,<2.3.0" pre-commit install git config branch.autosetuprebase always git config --bool flake8.strict true diff --git a/README.md b/README.md index 2df1dd80..fc73684a 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ They should be submitted with the `application/x-webpack-stats+json` type. ### Requirements -- Python 3.7 +- Python 3.8 - Node (and [Volta](https://volta.sh/)) - Postgres 9.4+ diff --git a/poetry.lock b/poetry.lock index 34af5af9..e51babe7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -15,16 +15,18 @@ description = "Async http client/server framework (asyncio)" name = "aiohttp" optional = false python-versions = ">=3.5.3" -version = "3.3.2" +version = "3.6.2" [package.dependencies] async-timeout = ">=3.0,<4.0" attrs = ">=17.3.0" chardet = ">=2.0,<4.0" -idna-ssl = ">=1.0" -multidict = ">=4.0,<5.0" +multidict = ">=4.5,<5.0" yarl = ">=1.0,<2.0" +[package.extras] +speedups = ["aiodns", "brotlipy", "cchardet"] + [[package]] category = "main" description = "asyncio (PEP 3156) Redis support" @@ -43,7 +45,7 @@ description = "A database migration tool for SQLAlchemy." name = "alembic" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.4.0" +version = "1.4.1" [package.dependencies] Mako = "*" @@ -294,8 +296,8 @@ category = "main" description = "Composable command line interface toolkit" name = "click" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "7.0" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "7.1.1" [[package]] category = "main" @@ -359,7 +361,7 @@ description = "Decorators for Humans" name = "decorator" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*" -version = "4.4.1" +version = "4.4.2" [[package]] category = "main" @@ -588,34 +590,7 @@ description = "Internationalized Domain Names in Applications (IDNA)" name = "idna" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.8" - -[[package]] -category = "main" -description = "Patch ssl.match_hostname for Unicode(idna) domains support" -name = "idna-ssl" -optional = false -python-versions = "*" -version = "1.1.0" - -[package.dependencies] -idna = ">=2.0" - -[[package]] -category = "main" -description = "Read metadata from Python packages" -marker = "python_version < \"3.8\"" -name = "importlib-metadata" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -version = "1.5.0" - -[package.dependencies] -zipp = ">=0.5" - -[package.extras] -docs = ["sphinx", "rst.linker"] -testing = ["packaging", "importlib-resources"] +version = "2.9" [[package]] category = "main" @@ -623,7 +598,7 @@ description = "IPython: Productive Interactive Computing" name = "ipython" optional = false python-versions = ">=3.6" -version = "7.12.0" +version = "7.13.0" [package.dependencies] appnope = "*" @@ -639,7 +614,7 @@ setuptools = ">=18.5" traitlets = ">=4.2" [package.extras] -all = ["ipyparallel", "requests", "notebook", "qtconsole", "ipywidgets", "pygments", "nbconvert", "testpath", "Sphinx (>=1.3)", "nbformat", "numpy (>=1.14)", "ipykernel", "nose (>=0.10.1)"] +all = ["numpy (>=1.14)", "testpath", "notebook", "nose (>=0.10.1)", "nbconvert", "requests", "ipywidgets", "qtconsole", "ipyparallel", "Sphinx (>=1.3)", "pygments", "nbformat", "ipykernel"] doc = ["Sphinx (>=1.3)"] kernel = ["ipykernel"] nbconvert = ["nbconvert"] @@ -708,10 +683,6 @@ pyrsistent = ">=0.14.0" setuptools = "*" six = ">=1.11.0" -[package.dependencies.importlib-metadata] -python = "<3.8" -version = "*" - [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"] @@ -722,15 +693,11 @@ description = "Messaging library for Python." name = "kombu" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "4.6.7" +version = "4.6.8" [package.dependencies] amqp = ">=2.5.2,<2.6" -[package.dependencies.importlib-metadata] -python = "<3.8" -version = ">=0.18" - [package.extras] azureservicebus = ["azure-servicebus (>=0.21.1)"] azurestoragequeues = ["azure-storage-queue"] @@ -775,7 +742,7 @@ description = "A super-fast templating language that borrows the best ideas fro name = "mako" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.1.1" +version = "1.1.2" [package.dependencies] MarkupSafe = ">=0.9.2" @@ -798,11 +765,11 @@ description = "A lightweight library for converting complex datatypes to and fro name = "marshmallow" optional = false python-versions = ">=3.5" -version = "3.5.0" +version = "3.5.1" [package.extras] dev = ["pytest", "pytz", "simplejson", "mypy (0.761)", "flake8 (3.7.9)", "flake8-bugbear (20.1.4)", "pre-commit (>=1.20,<3.0)", "tox"] -docs = ["sphinx (2.4.2)", "sphinx-issues (1.2.0)", "alabaster (0.7.12)", "sphinx-version-warning (1.1.2)"] +docs = ["sphinx (2.4.3)", "sphinx-issues (1.2.0)", "alabaster (0.7.12)", "sphinx-version-warning (1.1.2)"] lint = ["mypy (0.761)", "flake8 (3.7.9)", "flake8-bugbear (20.1.4)", "pre-commit (>=1.20,<3.0)"] tests = ["pytest", "pytz", "simplejson"] @@ -828,7 +795,7 @@ description = "multidict implementation" name = "multidict" optional = false python-versions = ">=3.5" -version = "4.7.4" +version = "4.7.5" [[package]] category = "main" @@ -861,7 +828,7 @@ description = "Core utilities for Python packages" name = "packaging" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "20.1" +version = "20.3" [package.dependencies] pyparsing = ">=2.0.2" @@ -873,7 +840,7 @@ description = "A Python Parser" name = "parso" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.6.1" +version = "0.6.2" [package.extras] testing = ["docopt", "pytest (>=3.0.7)"] @@ -914,11 +881,6 @@ optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" version = "0.13.1" -[package.dependencies] -[package.dependencies.importlib-metadata] -python = "<3.8" -version = ">=0.12" - [package.extras] dev = ["pre-commit", "tox"] @@ -927,8 +889,8 @@ category = "main" description = "Library for building powerful interactive command lines in Python" name = "prompt-toolkit" optional = false -python-versions = ">=3.6" -version = "3.0.3" +python-versions = ">=3.6.1" +version = "3.0.4" [package.dependencies] wcwidth = "*" @@ -950,8 +912,8 @@ category = "main" description = "psycopg2 - Python-PostgreSQL Database Adapter" name = "psycopg2-binary" optional = false -python-versions = "*" -version = "2.7.7" +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" +version = "2.8.4" [[package]] category = "main" @@ -1014,10 +976,11 @@ version = "2.3.1" [[package]] category = "main" description = "C parser in Python" +marker = "platform_python_implementation != \"PyPy\"" name = "pycparser" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.19" +version = "2.20" [[package]] category = "dev" @@ -1032,8 +995,8 @@ category = "main" description = "Pygments is a syntax highlighting package written in Python." name = "pygments" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.5.2" +python-versions = ">=3.5" +version = "2.6.1" [[package]] category = "main" @@ -1088,10 +1051,6 @@ pluggy = ">=0.12,<1.0" py = ">=1.5.0" wcwidth = "*" -[package.dependencies.importlib-metadata] -python = "<3.8" -version = ">=0.12" - [package.extras] checkqa-mypy = ["mypy (v0.761)"] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] @@ -1232,20 +1191,14 @@ description = "Python HTTP for Humans." name = "requests" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.22.0" +version = "2.23.0" [package.dependencies] certifi = ">=2017.4.17" -chardet = ">=3.0.2,<3.1.0" +chardet = ">=3.0.2,<4" +idna = ">=2.5,<3" urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26" -[[package.dependencies.idna]] -version = ">=2.5,<2.9" - -[[package.dependencies.idna]] -optional = true -version = ">=2.0.0" - [package.dependencies.cryptography] optional = true version = ">=1.3.4" @@ -1255,7 +1208,7 @@ optional = true version = ">=0.14" [package.extras] -security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)"] +security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] [[package]] @@ -1279,7 +1232,7 @@ description = "A utility library for mocking out the `requests` Python library." name = "responses" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.10.9" +version = "0.10.12" [package.dependencies] requests = ">=2.0" @@ -1305,7 +1258,7 @@ description = "Python client for Sentry (https://getsentry.com)" name = "sentry-sdk" optional = false python-versions = "*" -version = "0.14.1" +version = "0.14.2" [package.dependencies] certifi = "*" @@ -1358,7 +1311,7 @@ description = "Retry code until it succeeds" name = "tenacity" optional = false python-versions = "*" -version = "6.0.0" +version = "6.1.0" [package.dependencies] six = ">=1.9.0" @@ -1498,25 +1451,12 @@ version = "1.2.6" idna = ">=2.0" multidict = ">=4.0" -[[package]] -category = "main" -description = "Backport of pathlib-compatible object wrapper for zip files" -marker = "python_version < \"3.8\"" -name = "zipp" -optional = false -python-versions = ">=3.6" -version = "3.0.0" - -[package.extras] -docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] -testing = ["jaraco.itertools", "func-timeout"] - [extras] test = ["pytest", "pytest-aiohttp", "pytest-cov", "pytest-mock", "pytest-responses", "pytest-xdist", "responses"] [metadata] -content-hash = "da7d3c297b480ed915922e5f07eb2d0ac17b34f47a5b07fcce5c9ecc86aee09a" -python-versions = "~3.7" +content-hash = "9ca85f2439fc34fce6af8819d3bfa0438cea0952ca8cfaf3c0d4ba976d4c570a" +python-versions = "~3.8" [metadata.files] aiodns = [ @@ -1524,28 +1464,25 @@ aiodns = [ {file = "aiodns-1.1.1.tar.gz", hash = "sha256:d8677adc679ce8d0ef706c14d9c3d2f27a0e0cc11d59730cdbaf218ad52dd9ea"}, ] aiohttp = [ - {file = "aiohttp-3.3.2-cp35-cp35m-macosx_10_10_x86_64.whl", hash = "sha256:dd81d85a342edf3d2a388e2f24d9facebc9c04550043888f970ee2f228c93059"}, - {file = "aiohttp-3.3.2-cp35-cp35m-macosx_10_11_x86_64.whl", hash = "sha256:1a112a1fdf3802b7f2b182e22e51d71e4a8fa7387d0d38e79a268921b869e384"}, - {file = "aiohttp-3.3.2-cp35-cp35m-macosx_10_12_x86_64.whl", hash = "sha256:601e8e83123b4d423a9dfddf7d6943f4f520651a78ffcd50c99d065136c7ff7b"}, - {file = "aiohttp-3.3.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:f52e7287eb9286a1e91e4c67c207c2573147fbaddc68f70efb5aeee5d1992f2e"}, - {file = "aiohttp-3.3.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7de2c9e445a5d257935011268202338538abef1aaff341a4733eca56419ca6f6"}, - {file = "aiohttp-3.3.2-cp35-cp35m-win32.whl", hash = "sha256:ff1447c84a02b9cd5dd3a9332d1fb181a4386c3625765bb5caf1cfbc210ab3f9"}, - {file = "aiohttp-3.3.2-cp35-cp35m-win_amd64.whl", hash = "sha256:620f19ba7628b70b177f5c2e6a55a6fd6e7c8591cde38c3f8f52551733d31b66"}, - {file = "aiohttp-3.3.2-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:fe7b2972ff7e779e812f974aa5695edc328ecf559ceeea887ac46f06f090ad4c"}, - {file = "aiohttp-3.3.2-cp36-cp36m-macosx_10_11_x86_64.whl", hash = "sha256:c833aa6f4c9ac3e3eb843e3d999bae51339ad33a937303f43ce78064e61cb4b6"}, - {file = "aiohttp-3.3.2-cp36-cp36m-macosx_10_12_x86_64.whl", hash = "sha256:550b4a0788500f6d00f41b7fdd9fcce6d78f99706a7b2f6f81d4d331c7ca468e"}, - {file = "aiohttp-3.3.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:ae7501cc6a6c37b8d4774bf2218c37be47fe42019a2570e8510fc2044e59d573"}, - {file = "aiohttp-3.3.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:70d56c784da1239c89d39fefa166fd429306dada641178389be4184a9c04e501"}, - {file = "aiohttp-3.3.2-cp36-cp36m-win32.whl", hash = "sha256:33aa7c937ebaf063a860cbb0c263a771b33333a84965c6148eeafe64fb4e29ca"}, - {file = "aiohttp-3.3.2-cp36-cp36m-win_amd64.whl", hash = "sha256:96bb80b659cc2bafa160f3f0c346ce7fc10de1ffec4908d7f9690797f155f658"}, - {file = "aiohttp-3.3.2.tar.gz", hash = "sha256:f20deec7a3fbaec7b5eb7ad99878427ad2ee4cc16a46732b705e8121cbb3cc12"}, + {file = "aiohttp-3.6.2-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:1e984191d1ec186881ffaed4581092ba04f7c61582a177b187d3a2f07ed9719e"}, + {file = "aiohttp-3.6.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:50aaad128e6ac62e7bf7bd1f0c0a24bc968a0c0590a726d5a955af193544bcec"}, + {file = "aiohttp-3.6.2-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:65f31b622af739a802ca6fd1a3076fd0ae523f8485c52924a89561ba10c49b48"}, + {file = "aiohttp-3.6.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ae55bac364c405caa23a4f2d6cfecc6a0daada500274ffca4a9230e7129eac59"}, + {file = "aiohttp-3.6.2-cp36-cp36m-win32.whl", hash = "sha256:344c780466b73095a72c616fac5ea9c4665add7fc129f285fbdbca3cccf4612a"}, + {file = "aiohttp-3.6.2-cp36-cp36m-win_amd64.whl", hash = "sha256:4c6efd824d44ae697814a2a85604d8e992b875462c6655da161ff18fd4f29f17"}, + {file = "aiohttp-3.6.2-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:2f4d1a4fdce595c947162333353d4a44952a724fba9ca3205a3df99a33d1307a"}, + {file = "aiohttp-3.6.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:6206a135d072f88da3e71cc501c59d5abffa9d0bb43269a6dcd28d66bfafdbdd"}, + {file = "aiohttp-3.6.2-cp37-cp37m-win32.whl", hash = "sha256:b778ce0c909a2653741cb4b1ac7015b5c130ab9c897611df43ae6a58523cb965"}, + {file = "aiohttp-3.6.2-cp37-cp37m-win_amd64.whl", hash = "sha256:32e5f3b7e511aa850829fbe5aa32eb455e5534eaa4b1ce93231d00e2f76e5654"}, + {file = "aiohttp-3.6.2-py3-none-any.whl", hash = "sha256:460bd4237d2dbecc3b5ed57e122992f60188afe46e7319116da5eb8a9dfedba4"}, + {file = "aiohttp-3.6.2.tar.gz", hash = "sha256:259ab809ff0727d0e834ac5e8a283dc5e3e0ecc30c4d80b3cd17a4139ce1f326"}, ] aioredis = [ {file = "aioredis-1.1.0-py3-none-any.whl", hash = "sha256:9ffa0f9ea4076e5caedf55f095ea758f5137c7d1cd06cd9916081f4320fdaa4d"}, {file = "aioredis-1.1.0.tar.gz", hash = "sha256:d3adfc3295a91a97cab472751e26ff85949566a131cebb27a778e49aa0638c1a"}, ] alembic = [ - {file = "alembic-1.4.0.tar.gz", hash = "sha256:2df2519a5b002f881517693b95626905a39c5faf4b5a1f94de4f1441095d1d26"}, + {file = "alembic-1.4.1.tar.gz", hash = "sha256:791a5686953c4b366d3228c5377196db2f534475bb38d26f70eb69668efd9028"}, ] amqp = [ {file = "amqp-2.5.2-py2.py3-none-any.whl", hash = "sha256:6e649ca13a7df3faacdc8bbb280aa9a6602d22fd9d545336077e573a1f4ff3b8"}, @@ -1699,8 +1636,8 @@ chardet = [ {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, ] click = [ - {file = "Click-7.0-py2.py3-none-any.whl", hash = "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13"}, - {file = "Click-7.0.tar.gz", hash = "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"}, + {file = "click-7.1.1-py2.py3-none-any.whl", hash = "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a"}, + {file = "click-7.1.1.tar.gz", hash = "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc"}, ] colorama = [ {file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"}, @@ -1769,8 +1706,8 @@ cssutils = [ {file = "cssutils-1.0.2.tar.gz", hash = "sha256:a2fcf06467553038e98fea9cfe36af2bf14063eb147a70958cfcaa8f5786acaf"}, ] decorator = [ - {file = "decorator-4.4.1-py2.py3-none-any.whl", hash = "sha256:5d19b92a3c8f7f101c8dd86afd86b0f061a8ce4540ab8cd401fa2542756bce6d"}, - {file = "decorator-4.4.1.tar.gz", hash = "sha256:54c38050039232e1db4ad7375cfce6748d7b41c29e95a081c8a6d2c30364a2ce"}, + {file = "decorator-4.4.2-py2.py3-none-any.whl", hash = "sha256:41fa54c2a0cc4ba648be4fd43cff00aedf5b9465c9bf18d64325bc225f08f760"}, + {file = "decorator-4.4.2.tar.gz", hash = "sha256:e3a62f0520172440ca0dcc823749319382e377f37f140a0b99ef45fecb84bfe7"}, ] execnet = [ {file = "execnet-1.7.1-py2.py3-none-any.whl", hash = "sha256:d4efd397930c46415f62f8a31388d6be4f27a91d7550eb79bc64a756e0056547"}, @@ -1873,19 +1810,12 @@ honcho = [ {file = "honcho-1.0.1.tar.gz", hash = "sha256:c189402ad2e337777283c6a12d0f4f61dc6dd20c254c9a3a4af5087fc66cea6e"}, ] idna = [ - {file = "idna-2.8-py2.py3-none-any.whl", hash = "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"}, - {file = "idna-2.8.tar.gz", hash = "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407"}, -] -idna-ssl = [ - {file = "idna-ssl-1.1.0.tar.gz", hash = "sha256:a933e3bb13da54383f9e8f35dc4f9cb9eb9b3b78c6b36f311254d6d0d92c6c7c"}, -] -importlib-metadata = [ - {file = "importlib_metadata-1.5.0-py2.py3-none-any.whl", hash = "sha256:b97607a1a18a5100839aec1dc26a1ea17ee0d93b20b0f008d80a5a050afb200b"}, - {file = "importlib_metadata-1.5.0.tar.gz", hash = "sha256:06f5b3a99029c7134207dd882428a66992a9de2bef7c2b699b5641f9886c3302"}, + {file = "idna-2.9-py2.py3-none-any.whl", hash = "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"}, + {file = "idna-2.9.tar.gz", hash = "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb"}, ] ipython = [ - {file = "ipython-7.12.0-py3-none-any.whl", hash = "sha256:f6689108b1734501d3b59c84427259fd5ac5141afe2e846cfa8598eb811886c9"}, - {file = "ipython-7.12.0.tar.gz", hash = "sha256:d9459e7237e2e5858738ff9c3e26504b79899b58a6d49e574d352493d80684c6"}, + {file = "ipython-7.13.0-py3-none-any.whl", hash = "sha256:eb8d075de37f678424527b5ef6ea23f7b80240ca031c2dd6de5879d687a65333"}, + {file = "ipython-7.13.0.tar.gz", hash = "sha256:ca478e52ae1f88da0102360e57e528b92f3ae4316aabac80a2cd7f7ab2efb48a"}, ] ipython-genutils = [ {file = "ipython_genutils-0.2.0-py2.py3-none-any.whl", hash = "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8"}, @@ -1907,8 +1837,8 @@ jsonschema = [ {file = "jsonschema-3.2.0.tar.gz", hash = "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"}, ] kombu = [ - {file = "kombu-4.6.7-py2.py3-none-any.whl", hash = "sha256:2a9e7adff14d046c9996752b2c48b6d9185d0b992106d5160e1a179907a5d4ac"}, - {file = "kombu-4.6.7.tar.gz", hash = "sha256:67b32ccb6fea030f8799f8fd50dd08e03a4b99464ebc4952d71d8747b1a52ad1"}, + {file = "kombu-4.6.8-py2.py3-none-any.whl", hash = "sha256:598e7e749d6ab54f646b74b2d2df67755dee13894f73ab02a2a9feb8870c7cb2"}, + {file = "kombu-4.6.8.tar.gz", hash = "sha256:2d1cda774126a044d91a7ff5fa6d09edf99f46924ab332a810760fe6740e9b76"}, ] lru-dict = [ {file = "lru-dict-1.1.6.tar.gz", hash = "sha256:365457660e3d05b76f1aba3e0f7fedbfcd6528e97c5115a351ddd0db488354cc"}, @@ -1946,7 +1876,8 @@ lxml = [ {file = "lxml-4.2.6.tar.gz", hash = "sha256:7035d9361f3ceec9ccc1dd3482094d1174580e7e1bf6870b77ea758f7cad15d2"}, ] mako = [ - {file = "Mako-1.1.1.tar.gz", hash = "sha256:2984a6733e1d472796ceef37ad48c26f4a984bb18119bb2dbc37a44d8f6e75a4"}, + {file = "Mako-1.1.2-py2.py3-none-any.whl", hash = "sha256:8e8b53c71c7e59f3de716b6832c4e401d903af574f6962edbbbf6ecc2a5fe6c9"}, + {file = "Mako-1.1.2.tar.gz", hash = "sha256:3139c5d64aa5d175dbafb95027057128b5fbd05a40c53999f3905ceb53366d9d"}, ] markupsafe = [ {file = "MarkupSafe-1.1.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161"}, @@ -1984,8 +1915,8 @@ markupsafe = [ {file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"}, ] marshmallow = [ - {file = "marshmallow-3.5.0-py2.py3-none-any.whl", hash = "sha256:4b95c7735f93eb781dfdc4dded028108998cad759dda8dd9d4b5b4ac574cbf13"}, - {file = "marshmallow-3.5.0.tar.gz", hash = "sha256:3a94945a7461f2ab4df9576e51c97d66bee2c86155d3d3933fab752b31effab8"}, + {file = "marshmallow-3.5.1-py2.py3-none-any.whl", hash = "sha256:ac2e13b30165501b7d41fc0371b8df35944f5849769d136f20e2c5f6cdc6e665"}, + {file = "marshmallow-3.5.1.tar.gz", hash = "sha256:90854221bbb1498d003a0c3cc9d8390259137551917961c8b5258c64026b2f85"}, ] mccabe = [ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, @@ -1996,23 +1927,23 @@ more-itertools = [ {file = "more_itertools-8.2.0-py3-none-any.whl", hash = "sha256:5dd8bcf33e5f9513ffa06d5ad33d78f31e1931ac9a18f33d37e77a180d393a7c"}, ] multidict = [ - {file = "multidict-4.7.4-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:93166e0f5379cf6cd29746989f8a594fa7204dcae2e9335ddba39c870a287e1c"}, - {file = "multidict-4.7.4-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:a8ed33e8f9b67e3b592c56567135bb42e7e0e97417a4b6a771e60898dfd5182b"}, - {file = "multidict-4.7.4-cp35-cp35m-win32.whl", hash = "sha256:a38baa3046cce174a07a59952c9f876ae8875ef3559709639c17fdf21f7b30dd"}, - {file = "multidict-4.7.4-cp35-cp35m-win_amd64.whl", hash = "sha256:9a7b115ee0b9b92d10ebc246811d8f55d0c57e82dbb6a26b23c9a9a6ad40ce0c"}, - {file = "multidict-4.7.4-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:dcfed56aa085b89d644af17442cdc2debaa73388feba4b8026446d168ca8dad7"}, - {file = "multidict-4.7.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:f29b885e4903bd57a7789f09fe9d60b6475a6c1a4c0eca874d8558f00f9d4b51"}, - {file = "multidict-4.7.4-cp36-cp36m-win32.whl", hash = "sha256:13f3ebdb5693944f52faa7b2065b751cb7e578b8dd0a5bb8e4ab05ad0188b85e"}, - {file = "multidict-4.7.4-cp36-cp36m-win_amd64.whl", hash = "sha256:4fba5204d32d5c52439f88437d33ad14b5f228e25072a192453f658bddfe45a7"}, - {file = "multidict-4.7.4-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:a6d219f49821f4b2c85c6d426346a5d84dab6daa6f85ca3da6c00ed05b54022d"}, - {file = "multidict-4.7.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:63810343ea07f5cd86ba66ab66706243a6f5af075eea50c01e39b4ad6bc3c57a"}, - {file = "multidict-4.7.4-cp37-cp37m-win32.whl", hash = "sha256:26502cefa86d79b86752e96639352c7247846515c864d7c2eb85d036752b643c"}, - {file = "multidict-4.7.4-cp37-cp37m-win_amd64.whl", hash = "sha256:5eee66f882ab35674944dfa0d28b57fa51e160b4dce0ce19e47f495fdae70703"}, - {file = "multidict-4.7.4-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:527124ef435f39a37b279653ad0238ff606b58328ca7989a6df372fd75d7fe26"}, - {file = "multidict-4.7.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:83c6ddf0add57c6b8a7de0bc7e2d656be3eefeff7c922af9a9aae7e49f225625"}, - {file = "multidict-4.7.4-cp38-cp38-win32.whl", hash = "sha256:6bd10adf9f0d6a98ccc792ab6f83d18674775986ba9bacd376b643fe35633357"}, - {file = "multidict-4.7.4-cp38-cp38-win_amd64.whl", hash = "sha256:5414f388ffd78c57e77bd253cf829373721f450613de53dc85a08e34d806e8eb"}, - {file = "multidict-4.7.4.tar.gz", hash = "sha256:d7d428488c67b09b26928950a395e41cc72bb9c3d5abfe9f0521940ee4f796d4"}, + {file = "multidict-4.7.5-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:fc3b4adc2ee8474cb3cd2a155305d5f8eda0a9c91320f83e55748e1fcb68f8e3"}, + {file = "multidict-4.7.5-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:42f56542166040b4474c0c608ed051732033cd821126493cf25b6c276df7dd35"}, + {file = "multidict-4.7.5-cp35-cp35m-win32.whl", hash = "sha256:7774e9f6c9af3f12f296131453f7b81dabb7ebdb948483362f5afcaac8a826f1"}, + {file = "multidict-4.7.5-cp35-cp35m-win_amd64.whl", hash = "sha256:c2c37185fb0af79d5c117b8d2764f4321eeb12ba8c141a95d0aa8c2c1d0a11dd"}, + {file = "multidict-4.7.5-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:e439c9a10a95cb32abd708bb8be83b2134fa93790a4fb0535ca36db3dda94d20"}, + {file = "multidict-4.7.5-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:85cb26c38c96f76b7ff38b86c9d560dea10cf3459bb5f4caf72fc1bb932c7136"}, + {file = "multidict-4.7.5-cp36-cp36m-win32.whl", hash = "sha256:620b37c3fea181dab09267cd5a84b0f23fa043beb8bc50d8474dd9694de1fa6e"}, + {file = "multidict-4.7.5-cp36-cp36m-win_amd64.whl", hash = "sha256:6e6fef114741c4d7ca46da8449038ec8b1e880bbe68674c01ceeb1ac8a648e78"}, + {file = "multidict-4.7.5-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:a326f4240123a2ac66bb163eeba99578e9d63a8654a59f4688a79198f9aa10f8"}, + {file = "multidict-4.7.5-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:dc561313279f9d05a3d0ffa89cd15ae477528ea37aa9795c4654588a3287a9ab"}, + {file = "multidict-4.7.5-cp37-cp37m-win32.whl", hash = "sha256:4b7df040fb5fe826d689204f9b544af469593fb3ff3a069a6ad3409f742f5928"}, + {file = "multidict-4.7.5-cp37-cp37m-win_amd64.whl", hash = "sha256:317f96bc0950d249e96d8d29ab556d01dd38888fbe68324f46fd834b430169f1"}, + {file = "multidict-4.7.5-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:b51249fdd2923739cd3efc95a3d6c363b67bbf779208e9f37fd5e68540d1a4d4"}, + {file = "multidict-4.7.5-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:ae402f43604e3b2bc41e8ea8b8526c7fa7139ed76b0d64fc48e28125925275b2"}, + {file = "multidict-4.7.5-cp38-cp38-win32.whl", hash = "sha256:bb519becc46275c594410c6c28a8a0adc66fe24fef154a9addea54c1adb006f5"}, + {file = "multidict-4.7.5-cp38-cp38-win_amd64.whl", hash = "sha256:544fae9261232a97102e27a926019100a9db75bec7b37feedd74b3aa82f29969"}, + {file = "multidict-4.7.5.tar.gz", hash = "sha256:aee283c49601fa4c13adc64c09c978838a7e812f85377ae130a24d7198c0331e"}, ] nplusone = [ {file = "nplusone-0.8.2-py2.py3-none-any.whl", hash = "sha256:9a641cf17230fe6fbb7b06f77b0d259d10c12dc840884385d36c83b59d44012f"}, @@ -2023,12 +1954,12 @@ oauthlib = [ {file = "oauthlib-3.1.0.tar.gz", hash = "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889"}, ] packaging = [ - {file = "packaging-20.1-py2.py3-none-any.whl", hash = "sha256:170748228214b70b672c581a3dd610ee51f733018650740e98c7df862a583f73"}, - {file = "packaging-20.1.tar.gz", hash = "sha256:e665345f9eef0c621aa0bf2f8d78cf6d21904eef16a93f020240b704a57f1334"}, + {file = "packaging-20.3-py2.py3-none-any.whl", hash = "sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752"}, + {file = "packaging-20.3.tar.gz", hash = "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3"}, ] parso = [ - {file = "parso-0.6.1-py2.py3-none-any.whl", hash = "sha256:951af01f61e6dccd04159042a0706a31ad437864ec6e25d0d7a96a9fbb9b0095"}, - {file = "parso-0.6.1.tar.gz", hash = "sha256:56b2105a80e9c4df49de85e125feb6be69f49920e121406f15e7acde6c9dfc57"}, + {file = "parso-0.6.2-py2.py3-none-any.whl", hash = "sha256:8515fc12cfca6ee3aa59138741fc5624d62340c97e401c74875769948d4f2995"}, + {file = "parso-0.6.2.tar.gz", hash = "sha256:0c5659e0c6eba20636f99a04f469798dca8da279645ce5c387315b2c23912157"}, ] pathtools = [ {file = "pathtools-0.1.2.tar.gz", hash = "sha256:7c35c5421a39bb82e58018febd90e3b6e5db34c5443aaaf742b3f33d4655f1c0"}, @@ -2046,8 +1977,8 @@ pluggy = [ {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, ] prompt-toolkit = [ - {file = "prompt_toolkit-3.0.3-py3-none-any.whl", hash = "sha256:c93e53af97f630f12f5f62a3274e79527936ed466f038953dfa379d4941f651a"}, - {file = "prompt_toolkit-3.0.3.tar.gz", hash = "sha256:a402e9bf468b63314e37460b68ba68243d55b2f8c4d0192f85a019af3945050e"}, + {file = "prompt_toolkit-3.0.4-py3-none-any.whl", hash = "sha256:859e1b205b6cf6a51fa57fa34202e45365cf58f8338f0ee9f4e84a4165b37d5b"}, + {file = "prompt_toolkit-3.0.4.tar.gz", hash = "sha256:ebe6b1b08c888b84c50d7f93dee21a09af39860144ff6130aadbd61ae8d29783"}, ] protobuf = [ {file = "protobuf-3.11.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ef2c2e56aaf9ee914d3dccc3408d42661aaf7d9bb78eaa8f17b2e6282f214481"}, @@ -2071,36 +2002,38 @@ protobuf = [ {file = "protobuf-3.11.3.tar.gz", hash = "sha256:c77c974d1dadf246d789f6dad1c24426137c9091e930dbf50e0a29c1fcf00b1f"}, ] psycopg2-binary = [ - {file = "psycopg2-binary-2.7.7.tar.gz", hash = "sha256:b19e9f1b85c5d6136f5a0549abdc55dcbd63aba18b4f10d0d063eb65ef2c68b4"}, - {file = "psycopg2_binary-2.7.7-cp27-cp27m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:ec43358c105794bc2b6fd34c68d27f92bea7102393c01889e93f4b6a70975728"}, - {file = "psycopg2_binary-2.7.7-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:9a7bccb1212e63f309eb9fab47b6eaef796f59850f169a25695b248ca1bf681b"}, - {file = "psycopg2_binary-2.7.7-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:2e952fa17ba48cbc2dc063ddeec37d7dc4ea0ef7db0ac1eda8906365a8543f31"}, - {file = "psycopg2_binary-2.7.7-cp27-cp27m-win32.whl", hash = "sha256:79cde4660de6f0bb523c229763bd8ad9a93ac6760b72c369cf1213955c430934"}, - {file = "psycopg2_binary-2.7.7-cp27-cp27m-win_amd64.whl", hash = "sha256:96b4e902cde37a7fc6ab306b3ac089a3949e6ce3d824eeca5b19dc0bedb9f6e2"}, - {file = "psycopg2_binary-2.7.7-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:19a2d1f3567b30f6c2bb3baea23f74f69d51f0c06c2e2082d0d9c28b0733a4c2"}, - {file = "psycopg2_binary-2.7.7-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:df6444f952ca849016902662e1a47abf4fa0678d75f92fd9dd27f20525f809cd"}, - {file = "psycopg2_binary-2.7.7-cp33-cp33m-win32.whl", hash = "sha256:7c8159352244e11bdd422226aa17651110b600d175220c451a9acf795e7414e0"}, - {file = "psycopg2_binary-2.7.7-cp33-cp33m-win_amd64.whl", hash = "sha256:d444b1545430ffc1e7a24ce5a9be122ccd3b135a7b7e695c5862c5aff0b11159"}, - {file = "psycopg2_binary-2.7.7-cp34-cp34m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:cb095a0657d792c8de9f7c9a0452385a309dfb1bbbb3357d6b1e216353ade6ca"}, - {file = "psycopg2_binary-2.7.7-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:bde7959ef012b628868d69c474ec4920252656d0800835ed999ba5e4f57e3e2e"}, - {file = "psycopg2_binary-2.7.7-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:f4c6926d9c03dadce7a3b378b40d2fea912c1344ef9b29869f984fb3d2a2420b"}, - {file = "psycopg2_binary-2.7.7-cp34-cp34m-win32.whl", hash = "sha256:2b69cf4b0fa2716fd977aa4e1fd39af6110eb47b2bb30b4e5a469d8fbecfc102"}, - {file = "psycopg2_binary-2.7.7-cp34-cp34m-win_amd64.whl", hash = "sha256:587098ca4fc46c95736459d171102336af12f0d415b3b865972a79c03f06259f"}, - {file = "psycopg2_binary-2.7.7-cp35-cp35m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:676d1a80b1eebc0cacae8dd09b2fde24213173bf65650d22b038c5ed4039f392"}, - {file = "psycopg2_binary-2.7.7-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4957452f7868f43f32c090dadb4188e9c74a4687323c87a882e943c2bd4780c3"}, - {file = "psycopg2_binary-2.7.7-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:5b79368bcdb1da4a05f931b62760bea0955ee2c81531d8e84625df2defd3f709"}, - {file = "psycopg2_binary-2.7.7-cp35-cp35m-win32.whl", hash = "sha256:6b0211ecda389101a7d1d3df2eba0cf7ffbdd2480ca6f1d2257c7bd739e84110"}, - {file = "psycopg2_binary-2.7.7-cp35-cp35m-win_amd64.whl", hash = "sha256:d16d42a1b9772152c1fe606f679b2316551f7e1a1ce273e7f808e82a136cdb3d"}, - {file = "psycopg2_binary-2.7.7-cp36-cp36m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:5138cec2ee1e53a671e11cc519505eb08aaaaf390c508f25b09605763d48de4b"}, - {file = "psycopg2_binary-2.7.7-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:7aba9786ac32c2a6d5fb446002ed936b47d5e1f10c466ef7e48f66eb9f9ebe3b"}, - {file = "psycopg2_binary-2.7.7-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:e63850d8c52ba2b502662bf3c02603175c2397a9acc756090e444ce49508d41e"}, - {file = "psycopg2_binary-2.7.7-cp36-cp36m-win32.whl", hash = "sha256:945f2eedf4fc6b2432697eb90bb98cc467de5147869e57405bfc31fa0b824741"}, - {file = "psycopg2_binary-2.7.7-cp36-cp36m-win_amd64.whl", hash = "sha256:d93ccc7bf409ec0a23f2ac70977507e0b8a8d8c54e5ee46109af2f0ec9e411f3"}, - {file = "psycopg2_binary-2.7.7-cp37-cp37m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:5cf43807392247d9bc99737160da32d3fa619e0bfd85ba24d1c78db205f472a4"}, - {file = "psycopg2_binary-2.7.7-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:b664011bb14ca1f2287c17185e222f2098f7b4c857961dbcf9badb28786dbbf4"}, - {file = "psycopg2_binary-2.7.7-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:3d72a5fdc5f00ca85160915eb9a973cf9a0ab8148f6eda40708bf672c55ac1d1"}, - {file = "psycopg2_binary-2.7.7-cp37-cp37m-win32.whl", hash = "sha256:a3bfcac727538ec11af304b5eccadbac952d4cca1a551a29b8fe554e3ad535dc"}, - {file = "psycopg2_binary-2.7.7-cp37-cp37m-win_amd64.whl", hash = "sha256:348b49dd737ff74cfb5e663e18cb069b44c64f77ec0523b5794efafbfa7df0b8"}, + {file = "psycopg2-binary-2.8.4.tar.gz", hash = "sha256:3a2522b1d9178575acee4adf8fd9f979f9c0449b00b4164bb63c3475ea6528ed"}, + {file = "psycopg2_binary-2.8.4-cp27-cp27m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:890167d5091279a27e2505ff0e1fb273f8c48c41d35c5b92adbf4af80e6b2ed6"}, + {file = "psycopg2_binary-2.8.4-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:dbc5cd56fff1a6152ca59445178652756f4e509f672e49ccdf3d79c1043113a4"}, + {file = "psycopg2_binary-2.8.4-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:7f42a8490c4fe854325504ce7a6e4796b207960dabb2cbafe3c3959cb00d1d7e"}, + {file = "psycopg2_binary-2.8.4-cp27-cp27m-win32.whl", hash = "sha256:8578d6b8192e4c805e85f187bc530d0f52ba86c39172e61cd51f68fddd648103"}, + {file = "psycopg2_binary-2.8.4-cp27-cp27m-win_amd64.whl", hash = "sha256:5dd90c5438b4f935c9d01fcbad3620253da89d19c1f5fca9158646407ed7df35"}, + {file = "psycopg2_binary-2.8.4-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:9aadff9032e967865f9778485571e93908d27dab21d0fdfdec0ca779bb6f8ad9"}, + {file = "psycopg2_binary-2.8.4-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:659c815b5b8e2a55193ede2795c1e2349b8011497310bb936da7d4745652823b"}, + {file = "psycopg2_binary-2.8.4-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:2166e770cb98f02ed5ee2b0b569d40db26788e0bf2ec3ae1a0d864ea6f1d8309"}, + {file = "psycopg2_binary-2.8.4-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:7e6e3c52e6732c219c07bd97fff6c088f8df4dae3b79752ee3a817e6f32e177e"}, + {file = "psycopg2_binary-2.8.4-cp34-cp34m-win32.whl", hash = "sha256:040234f8a4a8dfd692662a8308d78f63f31a97e1c42d2480e5e6810c48966a29"}, + {file = "psycopg2_binary-2.8.4-cp34-cp34m-win_amd64.whl", hash = "sha256:69b13fdf12878b10dc6003acc8d0abf3ad93e79813fd5f3812497c1c9fb9be49"}, + {file = "psycopg2_binary-2.8.4-cp35-cp35m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:19dc39616850342a2a6db70559af55b22955f86667b5f652f40c0e99253d9881"}, + {file = "psycopg2_binary-2.8.4-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:9f24f383a298a0c0f9b3113b982e21751a8ecde6615494a3f1470eb4a9d70e9e"}, + {file = "psycopg2_binary-2.8.4-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:eaed1c65f461a959284649e37b5051224f4db6ebdc84e40b5e65f2986f101a08"}, + {file = "psycopg2_binary-2.8.4-cp35-cp35m-win32.whl", hash = "sha256:4c6717962247445b4f9e21c962ea61d2e884fc17df5ddf5e35863b016f8a1f03"}, + {file = "psycopg2_binary-2.8.4-cp35-cp35m-win_amd64.whl", hash = "sha256:84156313f258eafff716b2961644a4483a9be44a5d43551d554844d15d4d224e"}, + {file = "psycopg2_binary-2.8.4-cp36-cp36m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:3b5deaa3ee7180585a296af33e14c9b18c218d148e735c7accf78130765a47e3"}, + {file = "psycopg2_binary-2.8.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5057669b6a66aa9ca118a2a860159f0ee3acf837eda937bdd2a64f3431361a2d"}, + {file = "psycopg2_binary-2.8.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:afd96845e12638d2c44d213d4810a08f4dc4a563f9a98204b7428e567014b1cd"}, + {file = "psycopg2_binary-2.8.4-cp36-cp36m-win32.whl", hash = "sha256:a73021b44813b5c84eda4a3af5826dd72356a900bac9bd9dd1f0f81ee1c22c2f"}, + {file = "psycopg2_binary-2.8.4-cp36-cp36m-win_amd64.whl", hash = "sha256:407af6d7e46593415f216c7f56ba087a9a42bd6dc2ecb86028760aa45b802bd7"}, + {file = "psycopg2_binary-2.8.4-cp37-cp37m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:3aa773580f85a28ffdf6f862e59cb5a3cc7ef6885121f2de3fca8d6ada4dbf3b"}, + {file = "psycopg2_binary-2.8.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:eac8a3499754790187bb00574ab980df13e754777d346f85e0ff6df929bcd964"}, + {file = "psycopg2_binary-2.8.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:7a1cb80e35e1ccea3e11a48afe65d38744a0e0bde88795cc56a4d05b6e4f9d70"}, + {file = "psycopg2_binary-2.8.4-cp37-cp37m-win32.whl", hash = "sha256:086f7e89ec85a6704db51f68f0dcae432eff9300809723a6e8782c41c2f48e03"}, + {file = "psycopg2_binary-2.8.4-cp37-cp37m-win_amd64.whl", hash = "sha256:b73ddf033d8cd4cc9dfed6324b1ad2a89ba52c410ef6877998422fcb9c23e3a8"}, + {file = "psycopg2_binary-2.8.4-cp38-cp38-macosx_10_9_x86_64.macosx_10_9_intel.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:4c3c09fb674401f630626310bcaf6cd6285daf0d5e4c26d6e55ca26a2734e39b"}, + {file = "psycopg2_binary-2.8.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:18ca813fdb17bc1db73fe61b196b05dd1ca2165b884dd5ec5568877cabf9b039"}, + {file = "psycopg2_binary-2.8.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:50446fae5681fc99f87e505d4e77c9407e683ab60c555ec302f9ac9bffa61103"}, + {file = "psycopg2_binary-2.8.4-cp38-cp38-win32.whl", hash = "sha256:98e10634792ac0e9e7a92a76b4991b44c2325d3e7798270a808407355e7bb0a1"}, + {file = "psycopg2_binary-2.8.4-cp38-cp38-win_amd64.whl", hash = "sha256:b8f490f5fad1767a1331df1259763b3bad7d7af12a75b950c2843ba319b2415f"}, ] ptyprocess = [ {file = "ptyprocess-0.6.0-py2.py3-none-any.whl", hash = "sha256:d7cc528d76e76342423ca640335bd3633420dc1366f258cb31d05e865ef5ca1f"}, @@ -2176,15 +2109,16 @@ pycodestyle = [ {file = "pycodestyle-2.3.1.tar.gz", hash = "sha256:682256a5b318149ca0d2a9185d365d8864a768a28db66a84a2ea946bcc426766"}, ] pycparser = [ - {file = "pycparser-2.19.tar.gz", hash = "sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3"}, + {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, + {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, ] pyflakes = [ {file = "pyflakes-1.6.0-py2.py3-none-any.whl", hash = "sha256:08bd6a50edf8cffa9fa09a463063c425ecaaf10d1eb0335a7e8b1401aef89e6f"}, {file = "pyflakes-1.6.0.tar.gz", hash = "sha256:8d616a382f243dbf19b54743f280b80198be0bca3a5396f1d2e1fca6223e8805"}, ] pygments = [ - {file = "Pygments-2.5.2-py2.py3-none-any.whl", hash = "sha256:2a3fe295e54a20164a9df49c75fa58526d3be48e14aceba6d6b1e8ac0bfd6f1b"}, - {file = "Pygments-2.5.2.tar.gz", hash = "sha256:98c8aa5a9f778fcd1026a17361ddaf7330d1b7c62ae97c3bb0ae73e0b9b6b0fe"}, + {file = "Pygments-2.6.1-py3-none-any.whl", hash = "sha256:ff7a40b4860b727ab48fad6360eb351cc1b33cbf9b15a0f689ca5353e9463324"}, + {file = "Pygments-2.6.1.tar.gz", hash = "sha256:647344a061c249a3b74e230c739f434d7ea4d8b1d5f3721bc0f3558049b38f44"}, ] pyopenssl = [ {file = "pyOpenSSL-18.0.0-py2.py3-none-any.whl", hash = "sha256:26ff56a6b5ecaf3a2a59f132681e2a80afcc76b4f902f612f518f92c2a1bf854"}, @@ -2258,24 +2192,24 @@ redis = [ {file = "redis-3.2.1.tar.gz", hash = "sha256:8ca418d2ddca1b1a850afa1680a7d2fd1f3322739271de4b704e0d4668449273"}, ] requests = [ - {file = "requests-2.22.0-py2.py3-none-any.whl", hash = "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"}, - {file = "requests-2.22.0.tar.gz", hash = "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4"}, + {file = "requests-2.23.0-py2.py3-none-any.whl", hash = "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee"}, + {file = "requests-2.23.0.tar.gz", hash = "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"}, ] requests-oauthlib = [ {file = "requests-oauthlib-0.8.0.tar.gz", hash = "sha256:883ac416757eada6d3d07054ec7092ac21c7f35cb1d2cf82faf205637081f468"}, {file = "requests_oauthlib-0.8.0-py2.py3-none-any.whl", hash = "sha256:50a8ae2ce8273e384895972b56193c7409601a66d4975774c60c2aed869639ca"}, ] responses = [ - {file = "responses-0.10.9-py2.py3-none-any.whl", hash = "sha256:515fd7c024097e5da76e9c4cf719083d181f1c3ddc09c2e0e49284ce863dd263"}, - {file = "responses-0.10.9.tar.gz", hash = "sha256:8ce8cb4e7e1ad89336f8865af152e0563d2e7f0e0b86d2cf75f015f819409243"}, + {file = "responses-0.10.12-py2.py3-none-any.whl", hash = "sha256:0474ce3c897fbcc1aef286117c93499882d5c440f06a805947e4b1cb5ab3d474"}, + {file = "responses-0.10.12.tar.gz", hash = "sha256:f83613479a021e233e82d52ffb3e2e0e2836d24b0cc88a0fa31978789f78d0e5"}, ] rsa = [ {file = "rsa-4.0-py2.py3-none-any.whl", hash = "sha256:14ba45700ff1ec9eeb206a2ce76b32814958a98e372006c8fb76ba820211be66"}, {file = "rsa-4.0.tar.gz", hash = "sha256:1a836406405730121ae9823e19c6e806c62bbad73f890574fff50efa4122c487"}, ] sentry-sdk = [ - {file = "sentry-sdk-0.14.1.tar.gz", hash = "sha256:e023da07cfbead3868e1e2ba994160517885a32dfd994fc455b118e37989479b"}, - {file = "sentry_sdk-0.14.1-py2.py3-none-any.whl", hash = "sha256:b06dd27391fd11fb32f84fe054e6a64736c469514a718a99fb5ce1dff95d6b28"}, + {file = "sentry-sdk-0.14.2.tar.gz", hash = "sha256:480eee754e60bcae983787a9a13bc8f155a111aef199afaa4f289d6a76aa622a"}, + {file = "sentry_sdk-0.14.2-py2.py3-none-any.whl", hash = "sha256:a920387dc3ee252a66679d0afecd34479fb6fc52c2bc20763793ed69e5b0dcc0"}, ] six = [ {file = "six-1.14.0-py2.py3-none-any.whl", hash = "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"}, @@ -2285,8 +2219,8 @@ sqlalchemy = [ {file = "SQLAlchemy-1.2.19.tar.gz", hash = "sha256:5bb2c4fc2bcc3447ad45716c66581eab982c007dcf925482498d8733f86f17c7"}, ] tenacity = [ - {file = "tenacity-6.0.0-py2.py3-none-any.whl", hash = "sha256:947e728aedf06e8db665bb7898112e90d17e48cc3f3289784a2b9ccf6e56fabc"}, - {file = "tenacity-6.0.0.tar.gz", hash = "sha256:72f397c2bb1887e048726603f3f629ea16f88cb3e61e4ed3c57e98582b8e3571"}, + {file = "tenacity-6.1.0-py2.py3-none-any.whl", hash = "sha256:f7bcbf5bb53875cfc38f61f596a88b1c994af32420f120c4409542a683ad613b"}, + {file = "tenacity-6.1.0.tar.gz", hash = "sha256:fb01d8ef2474eed422d8314a566c9e391cccb6e50cf4585022add6cb5cda66c8"}, ] text-unidecode = [ {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"}, @@ -2341,7 +2275,3 @@ yarl = [ {file = "yarl-1.2.6-cp36-cp36m-win_amd64.whl", hash = "sha256:9182cd6f93412d32e009020a44d6d170d2093646464a88aeec2aef50592f8c78"}, {file = "yarl-1.2.6.tar.gz", hash = "sha256:c8cbc21bbfa1dd7d5386d48cc814fe3d35b80f60299cdde9279046f399c3b0d8"}, ] -zipp = [ - {file = "zipp-3.0.0-py3-none-any.whl", hash = "sha256:12248a63bbdf7548f89cb4c7cda4681e537031eda29c02ea29674bc6854460c2"}, - {file = "zipp-3.0.0.tar.gz", hash = "sha256:7c0f8e91abc0dc07a5068f315c52cb30c66bfbc581e5b50704c8a2f6ebae794a"}, -] diff --git a/pyproject.toml b/pyproject.toml index d015edcf..7f1b1f75 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,9 +8,9 @@ authors = ["David Cramer "] license = "Apache-2.0" [tool.poetry.dependencies] -python = "~3.7" +python = "~3.8" aiodns = "~1.1.1" -aiohttp = "~3.3.2" +aiohttp = "~3.6.2" aioredis = "~1.1.0" asyncpg = "^0.20.0" blinker = "~1.4" @@ -35,7 +35,7 @@ lru-dict = "^1.1.6" lxml = "~4.2.3" marshmallow = "~3" nplusone = "~0.8.1" -psycopg2-binary = "~2.7.5" +psycopg2-binary = "~2.8.4" python-dateutil = "~2.6.1" redis = "~3.2.0" sentry-sdk = { version = "~0.14.1" } @@ -47,7 +47,7 @@ werkzeug = "~0.14.1" yarl = "~1.2.6" requests = { version = "^2.22", extras = [ "security" ] } requests-oauthlib = "~0.8.0" -pytest = { version = "~5", optional = true } +pytest = { version = "~5.3.5", optional = true } pytest-aiohttp = { version = "~0.3.0", optional = true } pytest-cov = { version = "~2.8.1", optional = true } pytest-mock = { version = "~2.0.0", optional = true } diff --git a/tests/zeus/vcs/backends/test_git.py b/tests/zeus/vcs/backends/test_git.py index a43c712b..dbb22313 100644 --- a/tests/zeus/vcs/backends/test_git.py +++ b/tests/zeus/vcs/backends/test_git.py @@ -7,14 +7,6 @@ from zeus.vcs.backends.git import GitVcs -def _get_last_two_revisions(marker, revisions): - if marker in revisions[0].branches: - return revisions[0], revisions[1] - - else: - return revisions[1], revisions[0] - - def _set_author(remote_path, name, email): check_call( 'cd {0} && git config --replace-all "user.name" "{1}"'.format( @@ -41,7 +33,7 @@ def test_get_default_revision(git_repo_config, vcs): assert vcs.get_default_revision() == "master" -def test_log_with_authors(git_repo_config, vcs): +async def test_log_with_authors(git_repo_config, vcs): # Create a commit with a new author _set_author(git_repo_config.remote_path, "Another Committer", "ac@d.not.zm.exist") check_call( @@ -49,36 +41,36 @@ def test_log_with_authors(git_repo_config, vcs): % git_repo_config.remote_path, shell=True, ) - vcs.clone() - vcs.update() - revisions = list(vcs.log()) + await vcs.clone() + await vcs.update() + revisions = await vcs.log() assert len(revisions) == 3 - revisions = list(vcs.log(author="Another Committer")) + revisions = await vcs.log(author="Another Committer") assert len(revisions) == 1 assert_revision( revisions[0], author="Another Committer ", message="bazzy" ) - revisions = list(vcs.log(author="ac@d.not.zm.exist")) + revisions = await vcs.log(author="ac@d.not.zm.exist") assert len(revisions) == 1 assert_revision( revisions[0], author="Another Committer ", message="bazzy" ) - revisions = list(vcs.log(branch=vcs.get_default_revision(), author="Foo")) + revisions = await vcs.log(branch=vcs.get_default_revision(), author="Foo") assert len(revisions) == 2 -def test_log_throws_errors_when_needed(vcs): +async def test_log_throws_errors_when_needed(vcs): try: - next(vcs.log(parent="HEAD", branch="master")) + await vcs.log(parent="HEAD", branch="master") pytest.fail("log passed with both branch and master specified") except ValueError: pass -def test_log_with_branches(git_repo_config, vcs): +async def test_log_with_branches(git_repo_config, vcs): # Create another branch and move it ahead of the master branch remote_path = git_repo_config.remote_path check_call("cd %s && git checkout -b B2" % remote_path, shell=True) @@ -99,66 +91,43 @@ def test_log_with_branches(git_repo_config, vcs): % (remote_path,), shell=True, ) - vcs.clone() - vcs.update() - - # Ensure git log normally includes commits from all branches - revisions = list(vcs.log()) - assert len(revisions) == 4 - - # Git timestamps are only accurate to the second. But since this test - # creates these commits so close to each other, there's a race - # condition here. Ultimately, we only care that both commits appear - # last in the log, so allow them to be out of order. - last_rev, previous_rev = _get_last_two_revisions("B3", revisions) - assert_revision(last_rev, message="3rd branch", branches=["B3"]) - assert_revision(previous_rev, message="second branch commit", branches=["B2"]) - - # Note that the list of branches here differs from the hg version - # because hg only returns the branch name from the changeset, which - # does not include any ancestors. - assert_revision( - revisions[3], message="test", branches=[vcs.get_default_revision(), "B2", "B3"] - ) + await vcs.clone() + await vcs.update() # Ensure git log with B3 only - revisions = list(vcs.log(branch="B3")) + revisions = await vcs.log(branch="B3") assert len(revisions) == 3 - assert_revision(revisions[0], message="3rd branch", branches=["B3"]) - assert_revision( - revisions[2], message="test", branches=[vcs.get_default_revision(), "B2", "B3"] - ) + assert_revision(revisions[0], message="3rd branch") + assert_revision(revisions[2], message="test") # Sanity check master check_call( "cd %s && git checkout %s" % (remote_path, vcs.get_default_revision()), shell=True, ) - revisions = list(vcs.log(branch=vcs.get_default_revision())) + revisions = await vcs.log(branch=vcs.get_default_revision()) assert len(revisions) == 2 -def test_simple(vcs): - vcs.clone() - vcs.update() - revision = next(vcs.log(parent="HEAD", limit=1)) +async def test_simple(vcs): + await vcs.clone() + await vcs.update() + revision = (await vcs.log(parent="HEAD", limit=1))[0] assert len(revision.sha) == 40 assert_revision(revision, author="Foo Bar ", message="biz\nbaz\n") - revisions = list(vcs.log()) + revisions = await vcs.log() assert len(revisions) == 2 assert revisions[0].message == "biz\nbaz\n" assert revisions[0].author == "Foo Bar " assert revisions[0].committer == "Foo Bar " assert revisions[0].parents == [revisions[1].sha] assert revisions[0].author_date == revisions[0].committer_date is not None - assert revisions[0].branches == ["master"] assert revisions[1].message == "test\nlol\n" assert revisions[1].author == "Foo Bar " assert revisions[1].committer == "Foo Bar " assert revisions[1].parents == [] assert revisions[1].author_date == revisions[1].committer_date is not None - assert revisions[1].branches == ["master"] - diff = vcs.export(revisions[0].sha) + diff = await vcs.export(revisions[0].sha) assert ( diff == """diff --git a/BAR b/BAR @@ -166,57 +135,42 @@ def test_simple(vcs): index 0000000..e69de29 """ ) - revisions = list(vcs.log(offset=0, limit=1)) + revisions = await vcs.log(offset=0, limit=1) assert len(revisions) == 1 assert revisions[0].message == "biz\nbaz\n" - revisions = list(vcs.log(offset=1, limit=1)) + revisions = await vcs.log(offset=1, limit=1) assert len(revisions) == 1 assert revisions[0].message == "test\nlol\n" -def test_is_child_parent(vcs): - vcs.clone() - vcs.update() - revisions = list(vcs.log()) - assert vcs.is_child_parent( - child_in_question=revisions[0].sha, parent_in_question=revisions[1].sha - ) - assert ( - vcs.is_child_parent( - child_in_question=revisions[1].sha, parent_in_question=revisions[0].sha - ) - is False - ) - - -def test_get_known_branches(git_repo_config, vcs): - vcs.clone() - vcs.update() +async def test_get_known_branches(git_repo_config, vcs): + await vcs.clone() + await vcs.update() - branches = vcs.get_known_branches() + branches = await vcs.get_known_branches() assert len(branches) == 1 assert "master" in branches check_call( "cd %s && git checkout -B test_branch" % git_repo_config.remote_path, shell=True ) - vcs.update() - branches = vcs.get_known_branches() + await vcs.update() + branches = await vcs.get_known_branches() assert len(branches) == 2 assert "test_branch" in branches -def test_show(git_repo_config, vcs): +async def test_show(git_repo_config, vcs): check_call( 'cd %s && echo "bar" > BAZ && git add BAZ && git commit -m "bazzy"' % git_repo_config.remote_path, shell=True, ) - vcs.clone() - vcs.update() - revisions = list(vcs.log()) + await vcs.clone() + await vcs.update() + revisions = await vcs.log() - result = vcs.show(revisions[0].sha, "BAZ") + result = await vcs.show(revisions[0].sha, "BAZ") assert result == "bar\n" diff --git a/tests/zeus/vcs/test_api.py b/tests/zeus/vcs/test_api.py index 116e1b41..8e06644f 100644 --- a/tests/zeus/vcs/test_api.py +++ b/tests/zeus/vcs/test_api.py @@ -1,11 +1,12 @@ import pytest from datetime import datetime +from unittest.mock import AsyncMock from uuid import UUID from zeus import auth from zeus.exceptions import UnknownRevision -from zeus.vcs.backends.git import LazyGitRevisionResult +from zeus.vcs.backends.git import RevisionResult class ApiHelper(object): @@ -56,23 +57,24 @@ async def test_log_basic(client, default_repo_id): async def test_log_fetches_on_retry(client, mocker, default_repo_id): - vcs_log = mocker.patch("zeus.vcs.backends.git.GitVcs.log") - vcs_log.side_effect = [ - UnknownRevision("master"), - iter( - [ - LazyGitRevisionResult( - vcs=mocker.Mock(), - sha="c" * 40, - author="Foo Bar ", - committer="Biz Baz ", - author_date=datetime(2013, 9, 19, 22, 15, 22), - committer_date=datetime(2013, 9, 19, 22, 15, 23), - message="Hello world!", - ) + vcs_log = mocker.patch( + "zeus.vcs.backends.git.GitVcs.log", + AsyncMock( + side_effect=[ + UnknownRevision("master"), + [ + RevisionResult( + sha="c" * 40, + author="Foo Bar ", + committer="Biz Baz ", + author_date=datetime(2013, 9, 19, 22, 15, 22), + committer_date=datetime(2013, 9, 19, 22, 15, 23), + message="Hello world!", + ) + ], ] ), - ] + ) resp = await ApiHelper(client).get("/stmt/log", repo_id=default_repo_id) assert resp.status == 200, resp.content diff --git a/zeus/vcs/api.py b/zeus/vcs/api.py index 50ec7464..9c0ef84a 100644 --- a/zeus/vcs/api.py +++ b/zeus/vcs/api.py @@ -114,12 +114,12 @@ async def stmt_log(request, vcs, repo_id): limit = int(request.query.get("limit") or 100) try: - log_results = list( - vcs.log(parent=parent, branch=branch, offset=offset, limit=limit) + log_results = await vcs.log( + parent=parent, branch=branch, offset=offset, limit=limit ) except UnknownRevision: # we're running a lazy update here if it didnt already exist - log_results = vcs.log( + log_results = await vcs.log( parent=parent, branch=branch, offset=offset, @@ -156,7 +156,7 @@ async def stmt_export(request, vcs, repo_id): if not sha: return json_response({"error": "missing_arg"}, status=403) - return json_response({"export": vcs.export(sha)}) + return json_response({"export": await vcs.export(sha)}) @span("stmt.show") @@ -170,14 +170,14 @@ async def stmt_show(request, vcs, repo_id): if not filename: return json_response({"error": "missing_arg"}, status=403) - return json_response({"show": vcs.show(sha, filename)}) + return json_response({"show": await vcs.show(sha, filename)}) @span("stmt.branches") @api_request @log_errors async def stmt_branches(request, vcs, repo_id): - return json_response({"branches": vcs.get_known_branches()}) + return json_response({"branches": await vcs.get_known_branches()}) def register_api_routes(app): diff --git a/zeus/vcs/asserts.py b/zeus/vcs/asserts.py index 3cb1a785..6c6579ac 100644 --- a/zeus/vcs/asserts.py +++ b/zeus/vcs/asserts.py @@ -1,15 +1,11 @@ -def assert_revision(revision, author=None, message=None, branches=None): +def assert_revision(revision, author=None, message=None): """Asserts values of the given fields in the provided revision. :param revision: The revision to validate :param author: that must be present in the ``revision`` :param message: message substring that must be present in ``revision`` - :param subject: exact subject that must be present in the ``revision`` - :param branches: all the branches that must be in the ``revision`` """ if author: assert author == revision.author if message: assert message in revision.message - if branches: - assert sorted(branches) == sorted(revision.branches) diff --git a/zeus/vcs/backends/base.py b/zeus/vcs/backends/base.py index 2016bd2c..684bd915 100644 --- a/zeus/vcs/backends/base.py +++ b/zeus/vcs/backends/base.py @@ -1,8 +1,8 @@ +import asyncio import os import os.path import re -from subprocess import Popen, PIPE from typing import Iterator, List, Optional, Tuple from uuid import UUID @@ -17,7 +17,6 @@ class RevisionResult(object): parents = None - branches = None repository_id = None def __init__( @@ -29,7 +28,6 @@ def __init__( committer: str = None, committer_date=None, parents: Optional[List[str]] = None, - branches: Optional[List[str]] = None, repository_id: UUID = None, _author_cache: dict = None, ): @@ -41,8 +39,6 @@ def __init__( self.committer_date = committer_date or author_date if parents is not None: self.parents = parents - if branches is not None: - self.branches = branches if repository_id is not None: self.repository_id = repository_id @@ -126,7 +122,7 @@ def __init__(self, id: str, path: str, url: str, username: Optional[str] = None) def get_default_env(self) -> dict: return {} - def run(self, cmd, timeout=None, **kwargs) -> str: + async def run(self, cmd, timeout=None, **kwargs) -> str: if self.exists(): kwargs.setdefault("cwd", self.path) @@ -141,32 +137,32 @@ def run(self, cmd, timeout=None, **kwargs) -> str: env[key] = value kwargs["env"] = env - kwargs["stdout"] = PIPE - kwargs["stderr"] = PIPE + kwargs["stdout"] = asyncio.subprocess.PIPE + kwargs["stderr"] = asyncio.subprocess.PIPE - proc = Popen(cmd, **kwargs) - (stdout, stderr) = proc.communicate(timeout=timeout) + proc = await asyncio.create_subprocess_exec(*cmd, **kwargs) + (stdout, stderr) = await asyncio.wait_for(proc.communicate(), timeout) if proc.returncode != 0: raise CommandError(cmd[0], proc.returncode, stdout, stderr) - return stdout.decode("utf-8") + return stdout.decode() def exists(self) -> bool: return os.path.exists(self.path) - def clone(self): + async def clone(self): raise NotImplementedError - def update(self, allow_cleanup=False): + async def update(self, allow_cleanup=False): raise NotImplementedError - def ensure(self, update_if_exists=True): + async def ensure(self, update_if_exists=True): if not self.exists(): - self.clone() + await self.clone() elif update_if_exists: - self.update() + await self.update() - def log( + async def log( self, parent: str = None, branch: str = None, @@ -184,10 +180,6 @@ def log( If branch is set, all revisions in the branch AND any ancestor commits are returned. - For any revisions returned, the list of associated branches returned is - tool specific and may or may not include ancestor branch names. See tool - implementations for exact behavior of this function. - :param parent: Parent at which revision search begins. :param branch: Branch name the revision must be associated with. :param author: The author name or email to filter results. @@ -197,29 +189,26 @@ def log( """ raise NotImplementedError - def export(self, sha: str) -> str: + async def export(self, sha: str) -> str: """ Show the changes (as a diff) in ``sha``. """ raise NotImplementedError - def show(self, sha: str, filename: str) -> str: + async def show(self, sha: str, filename: str) -> str: """ Show the contents of the ``filename`` at ``sha``. """ raise NotImplementedError + async def get_known_branches(self) -> List[str]: + """ This is limited to parallel trees with names. + :return: A list of unique names for the branches. + """ + raise NotImplementedError + def get_default_branch(self) -> str: return self.get_default_revision() def get_default_revision(self) -> str: raise NotImplementedError - - def is_child_parent(self, child_in_question: str, parent_in_question: str) -> bool: - raise NotImplementedError - - def get_known_branches(self) -> List[str]: - """ This is limited to parallel trees with names. - :return: A list of unique names for the branches. - """ - raise NotImplementedError diff --git a/zeus/vcs/backends/git.py b/zeus/vcs/backends/git.py index 1e7e8f29..3431acb8 100644 --- a/zeus/vcs/backends/git.py +++ b/zeus/vcs/backends/git.py @@ -1,4 +1,4 @@ -from typing import Iterator, List, Optional +from typing import List, Optional from urllib.parse import urlparse from zeus.exceptions import CommandError, InvalidPublicKey, UnknownRevision @@ -12,16 +12,6 @@ ORIGIN_PREFIX = "remotes/origin/" -class LazyGitRevisionResult(RevisionResult): - def __init__(self, vcs: Vcs, *args, **kwargs): - self.vcs = vcs - super(LazyGitRevisionResult, self).__init__(*args, **kwargs) - - @memoize - def branches(self): - return self.vcs.branches_for_commit(self.sha) - - class GitVcs(Vcs): binary_path = "git" @@ -53,10 +43,7 @@ def remote_url(self) -> str: url = self.url return url - def branches_for_commit(self, _id) -> list: - return self.get_known_branches(commit_id=_id) - - def get_known_branches(self, commit_id=None) -> list: + async def get_known_branches(self, commit_id=None) -> list: """ List all branches or those related to the commit for this repo. Either gets all the branches (if the commit_id is not specified) or then @@ -70,7 +57,7 @@ def get_known_branches(self, commit_id=None) -> list: command_parameters = ["branch", "-a"] if commit_id: command_parameters.extend(["--contains", commit_id]) - output = self.run(command_parameters) + output = await self.run(command_parameters) for result in output.splitlines(): # HACK(dcramer): is there a better way around removing the prefix? @@ -83,14 +70,14 @@ def get_known_branches(self, commit_id=None) -> list: results.append(result) return list(set(results)) - def run(self, cmd, **kwargs) -> str: + async def run(self, cmd, **kwargs) -> str: with sentry.Span("vcs.run-command", description=self.remote_url) as span: span.set_data("command", " ".join(cmd)) span.set_data("backend", "git") cmd = [self.binary_path] + cmd try: - output = super(GitVcs, self).run(cmd, **kwargs) + output = await super().run(cmd, **kwargs) span.set_data("output_bytes", len(output)) return output @@ -124,22 +111,22 @@ def run(self, cmd, **kwargs) -> str: raise - def clone(self): + async def clone(self): with sentry.Span("vcs.clone", description=self.remote_url) as par_span: par_span.set_tag("backend", "git") - self.run(["clone", "--mirror", self.remote_url, self.path]) + await self.run(["clone", "--mirror", self.remote_url, self.path]) - def update(self, allow_cleanup=False): + async def update(self, allow_cleanup=False): with sentry.Span("vcs.update", description=self.remote_url) as par_span: par_span.set_tag("backend", "git") par_span.set_tag("allow_cleanup", allow_cleanup) if allow_cleanup: - self.run(["fetch", "--all", "--force", "-p"]) + await self.run(["fetch", "--all", "--force", "-p"]) else: - self.run(["fetch", "--all", "--force"]) + await self.run(["fetch", "--all", "--force"]) - def log( + async def log( self, parent=None, branch=None, @@ -148,7 +135,7 @@ def log( limit=100, timeout=None, update_if_exists=False, - ) -> Iterator[LazyGitRevisionResult]: + ) -> List[RevisionResult]: """ Gets the commit log for the repository. Each revision returned includes all the branches with which this commit @@ -187,8 +174,8 @@ def log( par_span.set_tag("backend", "git") for n in range(2): try: - self.ensure(update_if_exists=update_if_exists) - result = self.run(cmd, timeout=timeout) + await self.ensure(update_if_exists=update_if_exists) + result = await self.run(cmd, timeout=timeout) break except CommandError as cmd_error: err_msg = cmd_error.stderr @@ -199,10 +186,10 @@ def log( branch ) ) - if not self.run(["remote"]): + if not await self.run(["remote"]): # assume we're in a broken state, and try to repair # XXX: theory is this might happen when OOMKiller axes clone? - result = self.run( + result = await self.run( [ "symbolic-ref", "refs/remotes/origin/HEAD", @@ -221,6 +208,9 @@ def log( raise default_error from cmd_error raise + # we use a list instead of a generator as we were always + # needing to coerce to a list anyways + results = [] for chunk in BufferParser(result, "\x02"): ( sha, @@ -240,42 +230,34 @@ def log( author_date = timezone.fromtimestamp(float(author_date)) committer_date = timezone.fromtimestamp(float(committer_date)) - yield LazyGitRevisionResult( - vcs=self, - sha=sha, - author=author, - committer=committer, - author_date=author_date, - committer_date=committer_date, - parents=parents, - message=message, + results.append( + RevisionResult( + sha=sha, + author=author, + committer=committer, + author_date=author_date, + committer_date=committer_date, + parents=parents, + message=message, + ) ) + return results - def export(self, sha, update_if_exists=False) -> str: + async def export(self, sha, update_if_exists=False) -> str: cmd = ["diff", "%s^..%s" % (sha, sha)] with sentry.Span("vcs.export", self.remote_url) as par_span: par_span.set_tag("sha", sha) par_span.set_tag("backend", "git") - self.ensure(update_if_exists=update_if_exists) - result = self.run(cmd) + await self.ensure(update_if_exists=update_if_exists) + result = await self.run(cmd) return result - def show(self, sha, filename, update_if_exists=False) -> str: + async def show(self, sha, filename, update_if_exists=False) -> str: cmd = ["show", "{}:{}".format(sha, filename)] with sentry.Span("vcs.show", self.remote_url) as par_span: par_span.set_tag("sha", sha) par_span.set_tag("filename", filename) par_span.set_tag("backend", "git") - self.ensure(update_if_exists=update_if_exists) - result = self.run(cmd) + await self.ensure(update_if_exists=update_if_exists) + result = await self.run(cmd) return result - - def is_child_parent(self, child_in_question, parent_in_question) -> bool: - cmd = ["merge-base", "--is-ancestor", parent_in_question, child_in_question] - self.ensure() - try: - self.run(cmd) - return True - - except CommandError: - return False diff --git a/zeus/vcs/utils.py b/zeus/vcs/utils.py index 07420c0b..a449b2b9 100644 --- a/zeus/vcs/utils.py +++ b/zeus/vcs/utils.py @@ -42,8 +42,8 @@ async def save_revision(conn, repo_id: UUID, revision: RevisionResult): async with conn.transaction(): await conn.execute( """ - INSERT INTO revision (repository_id, sha, committer_id, message, parents, branches, date_created, date_committed) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + INSERT INTO revision (repository_id, sha, committer_id, message, parents, date_created, date_committed) + VALUES ($1, $2, $3, $4, $5, $6, $7) ON CONFLICT DO NOTHING """, repo_id, @@ -51,7 +51,6 @@ async def save_revision(conn, repo_id: UUID, revision: RevisionResult): await get_author_id(conn, repo_id, *revision.get_committer()), revision.message, revision.parents, - revision.branches, revision.author_date, revision.committer_date, )