diff --git a/.circleci/config.yml b/.circleci/config.yml index 4ac75d59d..a3201aec9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,223 +1,127 @@ version: 2 + +parameters: + base-tag: + type: string + default: "latest" + jobs: - build: + setup: + machine: true + steps: + - checkout + - run: + name: Make sure base is up to date and remote + command: | + docker login -u $DOCKER_USER -p $DOCKER_PASS + BASE_TAG="$(md5sum Pipfile.lock | cut -c1-6)$(md5sum Dockerfile-installed | cut -c1-6)" + TAG=${CIRCLE_BRANCH} + if (curl --silent -f -lSL https://index.docker.io/v1/repositories/unicef/datamart/tags/$BASE_TAG > /dev/null); then + echo "Up to date!" + else + docker build -t unicef/datamart:$BASE_TAG -f Dockerfile-installed . + docker push unicef/datamart:$BASE_TAG + if (echo "develop" | grep -q "$CIRCLE_BRANCH"); then + docker tag unicef/datamart:$BASE_TAG unicef/datamart:latest + docker push unicef/datamart:latest + elif (echo "master" | grep -q "$CIRCLE_BRANCH"); then + docker tag unicef/datamart:$BASE_TAG unicef/datamart:latest_prod + docker push unicef/datamart:latest_prod + else + echo "Not a followed branch not pushing latest" + fi + fi + - run: + name: Triggering test workflow + command: | + BASE_TAG="$(md5sum Pipfile.lock | cut -c1-6)$(md5sum Dockerfile-installed | cut -c1-6)" + curl --user ${CIRCLE_TOKEN}: \ + --data build_parameters[CIRCLE_JOB]=test \ + --data build_parameters[BASE_TAG]=$BASE_TAG \ + --data revision=$CIRCLE_SHA1 \ + https://circleci.com/api/v1.1/project/github/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/tree/$CIRCLE_BRANCH + test: working_directory: ~/code docker: - - image: unicef/etools-base:latest + - image: unicef/datamart:$BASE_TAG environment: PGHOST: 127.0.0.1 + PIPENV_VENV_IN_PROJECT: 1 DATABASE_URL: "postgis://postgres:postgres@127.0.0.1:5432/etools_datamart" DATABASE_URL_ETOOLS: "postgis://postgres:postgres@127.0.0.1:5432/etools" - RELEASE_MATCH: "release/*" - CELERY_BROKER_URL: "amqp://guest:guest@127.0.0.1/datamart" - CELERY_RESULT_BACKEND: "amqp://guest:guest@127.0.0.1/datamart" - - - image: redis:alpine - - image: rabbitmq:3.7-alpine - environment: - RABBITMQ_DEFAULT_VHOST: "datamart" - - image: mdillon/postgis:9.6 + CELERY_BROKER_URL: "redis://localhost:6379/0" + CELERY_RESULT_BACKEND: "redis://localhost:6379/0" + DEPLOY_BRANCHES: "develop|staging|master" + - image: circleci/redis:6-alpine + - image: circleci/postgres:9.6-alpine-postgis environment: POSTGRES_USER: postgres PGUSER: postgres POSTGRES_DB: etools_datamart POSTGRES_PASSWORD: postgres steps: - - restore_cache: - keys: - - source-{{ .Branch }}-{{ .Revision }} - checkout - restore_cache: - keys: - - deps-v2-{{ checksum "poetry.lock" }} - - - run: - name: install deps - command: | - pip install poetry - poetry install - + key: source-{{ .Branch }}--{{ checksum "Pipfile.lock" }}-{{ checksum ".circleci/config.yml" }} - run: - name: create db + name: run tests command: | export PATH=/home/circleci/.local/bin:$PATH export PYTHONHASHSEED=${RANDOM} - poetry run pytest tests/ --create-db - - - store_artifacts: - path: ~build/coverage - destination: coverage - + pipenv install -d --system --ignore-pipfile + pytest tests/ --cov=etools_datamart --cov-config=tests/.coveragerc --cov-report=term --create-db - save_cache: - key: source-{{ .Branch }}-{{ .Revision }} + key: source-{{ .Branch }}--{{ checksum "Pipfile.lock" }}-{{ checksum ".circleci/config.yml" }} paths: - - ".git" - - - save_cache: - key: deps-v2-{{ checksum "poetry.lock" }} - paths: - - ".tox" - ".venv" - "~/.cache/pip" - - - deploy: - name: tag and release if release candidate + - store_artifacts: + path: build/coverage + destination: coverage + - run: + name: Triggering build_and_deploy job command: | - if [[ $CIRCLE_BRANCH == $RELEASE_MATCH ]]; then + if (echo "$DEPLOY_BRANCHES" | grep -q "$CIRCLE_BRANCH"); then curl --user ${CIRCLE_TOKEN}: \ - --data build_parameters[CIRCLE_JOB]=tag \ + --data build_parameters[CIRCLE_JOB]=build_and_upload \ --data revision=$CIRCLE_SHA1 \ https://circleci.com/api/v1.1/project/github/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/tree/$CIRCLE_BRANCH else - echo "Skipped as '$CIRCLE_BRANCH' does not match '$RELEASE_MATCH' branch" + echo "not triggered - '$CIRCLE_BRANCH' is not a deployable branch: '$DEPLOY_BRANCHES'" fi - tag: - docker: - - image: circleci/python:3.6 - environment: - API_URL: https://api.github.com/repos/unicef/etools-datamart - RELEASE_MATCH: "release/*" - steps: - - checkout - - add_ssh_keys: - fingerprints: - - "73:a6:f1:56:5a:28:c5:ea:50:ed:4d:c5:b3:00:54:9c" - - run: - name: close release branch and create tag - command: | - export PATH=/home/circleci/.local/bin:$PATH - export TAG=${TAG:=${CIRCLE_BRANCH#*/}} - git status - git show-branch "release/$TAG" - git reset --hard - - git config user.email "ci@unicef.org" - git config user.name "CI" - - echo - echo "Process master" - git checkout master - git pull - git merge --no-ff release/$TAG -m "merge release/$TAG" - echo - - echo "Creating tag $TAG" - git tag -a -m "v$TAG" $TAG - echo - echo "Process develop" - git checkout develop - git pull - git merge --no-ff release/$TAG -m "merge release/$TAG" - echo - - echo "Deleting branch release/$TAG" - git branch -d release/$TAG - echo - - echo "Pushing everything to origin" - git push --verbose --all - git push --verbose --tags - git push origin --verbose --delete release/$TAG - - run: - name: create github release - command: | - export TAG=${TAG:=${CIRCLE_BRANCH#*/}} - echo - export TODAY=`date '+%d %B %Y at %H:%M'` - function is_pre() - { - [[ "$(echo "$TAG" | sed 's/[0-9.]//g')" == "" ]] && echo false || echo true - } - function data() { - cat <= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.6.1" + }, + "appdirs": { + "hashes": [ + "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92", + "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e" + ], + "version": "==1.4.3" + }, + "attrs": { + "hashes": [ + "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6", + "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==20.3.0" + }, + "azure-common": { + "hashes": [ + "sha256:acd26b2adb3ea192d766b4f083805287da080adc7f316ce7e52ef0ea917fbe31", + "sha256:b2866238aea5d7492cfb0282fc8b8d5f6d06fb433872345864d45753c10b6e4f" + ], + "version": "==1.1.26" + }, + "azure-storage-blob": { + "hashes": [ + "sha256:a8e91a51d4f62d11127c7fd8ba0077385c5b11022f0269f8a2a71b9fc36bef31", + "sha256:b90323aad60f207f9f90a0c4cf94c10acc313c20b39403398dfba51f25f7b454" + ], + "index": "pypi", + "version": "==2.1.0" + }, + "azure-storage-common": { + "hashes": [ + "sha256:b01a491a18839b9d05a4fe3421458a0ddb5ab9443c14e487f40d16f9a1dc2fbe", + "sha256:ccedef5c67227bc4d6670ffd37cec18fb529a1b7c3a5e53e4096eb0cf23dc73f" + ], + "version": "==2.1.0" + }, + "billiard": { + "hashes": [ + "sha256:bff575450859a6e0fbc2f9877d9b715b0bbc07c3565bb7ed2280526a0cdf5ede", + "sha256:d91725ce6425f33a97dfa72fb6bfef0e47d4652acd98a032bd1a7fbf06d5fa6a" + ], + "version": "==3.6.3.0" + }, + "celery": { + "hashes": [ + "sha256:108a0bf9018a871620936c33a3ee9f6336a89f8ef0a0f567a9001f4aa361415f", + "sha256:5b4b37e276033fe47575107a2775469f0b721646a08c96ec2c61531e4fe45f2a" + ], + "index": "pypi", + "version": "==4.4.2" + }, + "certifi": { + "hashes": [ + "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c", + "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830" + ], + "version": "==2020.12.5" + }, + "cffi": { + "hashes": [ + "sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e", + "sha256:00e28066507bfc3fe865a31f325c8391a1ac2916219340f87dfad602c3e48e5d", + "sha256:045d792900a75e8b1e1b0ab6787dd733a8190ffcf80e8c8ceb2fb10a29ff238a", + "sha256:0638c3ae1a0edfb77c6765d487fee624d2b1ee1bdfeffc1f0b58c64d149e7eec", + "sha256:105abaf8a6075dc96c1fe5ae7aae073f4696f2905fde6aeada4c9d2926752362", + "sha256:155136b51fd733fa94e1c2ea5211dcd4c8879869008fc811648f16541bf99668", + "sha256:1a465cbe98a7fd391d47dce4b8f7e5b921e6cd805ef421d04f5f66ba8f06086c", + "sha256:1d2c4994f515e5b485fd6d3a73d05526aa0fcf248eb135996b088d25dfa1865b", + "sha256:2c24d61263f511551f740d1a065eb0212db1dbbbbd241db758f5244281590c06", + "sha256:51a8b381b16ddd370178a65360ebe15fbc1c71cf6f584613a7ea08bfad946698", + "sha256:594234691ac0e9b770aee9fcdb8fa02c22e43e5c619456efd0d6c2bf276f3eb2", + "sha256:5cf4be6c304ad0b6602f5c4e90e2f59b47653ac1ed9c662ed379fe48a8f26b0c", + "sha256:64081b3f8f6f3c3de6191ec89d7dc6c86a8a43911f7ecb422c60e90c70be41c7", + "sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009", + "sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03", + "sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b", + "sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909", + "sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53", + "sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35", + "sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26", + "sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b", + "sha256:a5ed8c05548b54b998b9498753fb9cadbfd92ee88e884641377d8a8b291bcc01", + "sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb", + "sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293", + "sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd", + "sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d", + "sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3", + "sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d", + "sha256:d5ff0621c88ce83a28a10d2ce719b2ee85635e85c515f12bac99a95306da4b2e", + "sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca", + "sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d", + "sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775", + "sha256:ec80dc47f54e6e9a78181ce05feb71a0353854cc26999db963695f950b5fb375", + "sha256:f032b34669220030f905152045dfa27741ce1a6db3324a5bc0b96b6c7420c87b", + "sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b", + "sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f" + ], + "version": "==1.14.4" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "coreapi": { + "hashes": [ + "sha256:46145fcc1f7017c076a2ef684969b641d18a2991051fddec9458ad3f78ffc1cb", + "sha256:bf39d118d6d3e171f10df9ede5666f63ad80bba9a29a8ec17726a66cf52ee6f3" + ], + "version": "==2.3.3" + }, + "coreschema": { + "hashes": [ + "sha256:5e6ef7bf38c1525d5e55a895934ab4273548629f16aed5c0a6caa74ebf45551f", + "sha256:9503506007d482ab0867ba14724b93c18a33b22b6d19fb419ef2d239dd4a1607" + ], + "version": "==0.0.4" + }, + "cryptography": { + "hashes": [ + "sha256:0003a52a123602e1acee177dc90dd201f9bb1e73f24a070db7d36c588e8f5c7d", + "sha256:0e85aaae861d0485eb5a79d33226dd6248d2a9f133b81532c8f5aae37de10ff7", + "sha256:594a1db4511bc4d960571536abe21b4e5c3003e8750ab8365fafce71c5d86901", + "sha256:69e836c9e5ff4373ce6d3ab311c1a2eed274793083858d3cd4c7d12ce20d5f9c", + "sha256:788a3c9942df5e4371c199d10383f44a105d67d401fb4304178020142f020244", + "sha256:7e177e4bea2de937a584b13645cab32f25e3d96fc0bc4a4cf99c27dc77682be6", + "sha256:83d9d2dfec70364a74f4e7c70ad04d3ca2e6a08b703606993407bf46b97868c5", + "sha256:84ef7a0c10c24a7773163f917f1cb6b4444597efd505a8aed0a22e8c4780f27e", + "sha256:9e21301f7a1e7c03dbea73e8602905a4ebba641547a462b26dd03451e5769e7c", + "sha256:9f6b0492d111b43de5f70052e24c1f0951cb9e6022188ebcb1cc3a3d301469b0", + "sha256:a69bd3c68b98298f490e84519b954335154917eaab52cf582fa2c5c7efc6e812", + "sha256:b4890d5fb9b7a23e3bf8abf5a8a7da8e228f1e97dc96b30b95685df840b6914a", + "sha256:c366df0401d1ec4e548bebe8f91d55ebcc0ec3137900d214dd7aac8427ef3030", + "sha256:dc42f645f8f3a489c3dd416730a514e7a91a59510ddaadc09d04224c098d3302" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", + "version": "==3.3.1" + }, + "defusedxml": { + "hashes": [ + "sha256:6687150770438374ab581bb7a1b327a847dd9c5749e396102de3fad4e8a3ef93", + "sha256:f684034d135af4c6cbb949b8a4d2ed61634515257a67299e5f940fbaa34377f5" + ], + "markers": "python_version >= '3.0'", + "version": "==0.6.0" + }, + "dj-static": { + "hashes": [ + "sha256:032ec1c532617922e6e3e956d504a6fb1acce4fc1c7c94612d0fda21828ce8ef" + ], + "index": "pypi", + "version": "==0.0.6" + }, + "django": { + "hashes": [ + "sha256:84f370f6acedbe1f3c41e1a02de44ac206efda3355e427139ecb785b5f596d80", + "sha256:e8fe3c2b2212dce6126becab7a693157f1a441a07b62ec994c046c76af5bb66d" + ], + "index": "pypi", + "version": "==2.2.13" + }, + "django-adminactions": { + "hashes": [ + "sha256:bd147e7ccdad4042f7c8c411da29428f829b81305a4568dd5cc6d63447682b9c" + ], + "index": "pypi", + "version": "==1.8.1" + }, + "django-adminfilters": { + "hashes": [ + "sha256:adab7f927b0845f9d87902ef3148ba704214e5977e5da483e386e82e445cb879" + ], + "index": "pypi", + "version": "==1.1.0" + }, + "django-appconf": { + "hashes": [ + "sha256:1b1d0e1069c843ebe8ae5aa48ec52403b1440402b320c3e3a206a0907e97bb06", + "sha256:be58deb54a43d77d2e1621fe59f787681376d3cd0b8bd8e4758ef6c3a6453380" + ], + "version": "==1.0.4" + }, + "django-braces": { + "hashes": [ + "sha256:83705b78948de00804bfacf40c315d001bb39630f35bbdd8588211c2d5b4d43f", + "sha256:a6d9b34cf3e4949635e54884097c30410d7964fc7bec7231445ea7079b8c5722" + ], + "version": "==1.14.0" + }, + "django-celery-beat": { + "hashes": [ + "sha256:fdf1255eecfbeb770c6521fe3e69989dfc6373cd5a7f0fe62038d37f80f47e48", + "sha256:fe0b2a1b31d4a6234fea4b31986ddfd4644a48fab216ce1843f3ed0ddd2e9097" + ], + "index": "pypi", + "version": "==2.0.0" + }, + "django-celery-email": { + "hashes": [ + "sha256:0f72da39cb2ea83c69440566e87f27cd72f68f247f98ce99fb29889fcf329406", + "sha256:5546cbba80952cc3b8a0ffa4206ce90a4a996a7ffd1c385a2bdb65903ca18ece" + ], + "index": "pypi", + "version": "==3.0.0" + }, + "django-concurrency": { + "hashes": [ + "sha256:5daf6d4334ffad4d358444344115fee634f191a9be711ab4f99c8760cd6c76a4" + ], + "index": "pypi", + "version": "==2.1.1" + }, + "django-constance": { + "hashes": [ + "sha256:12d827f9d5552ee39884fb6fb356f231f32b1ab8958acc715e3d1a6ecf913653" + ], + "index": "pypi", + "version": "==2.6.0" + }, + "django-cors-headers": { + "hashes": [ + "sha256:a5960addecc04527ab26617e51b8ed42f0adab4594b24bb0f3c33e2bd3857c3f", + "sha256:a785b5f446f6635810776d9f5f5d23e6a2a2f728ea982648370afaf0dfdf2627" + ], + "index": "pypi", + "version": "==3.2.1" + }, + "django-countries": { + "hashes": [ + "sha256:2e852c9693818d64d28758a720a0cb8277673ac495af8b855c4dc64940703bd2", + "sha256:e2ae9b76f9a0b5f3f365b5b81fe4972df0a5878c930139586f43f7d6d50a9594" + ], + "index": "pypi", + "version": "==6.1.2" + }, + "django-crispy-forms": { + "hashes": [ + "sha256:50032184708ce351e3c9f0008ac35d659d9d5973fa2db218066f2e0a76eb41d9", + "sha256:67e73ac863d3159500029fbbcdcb788f287a3fd357becebc1a0b51f73896dce3" + ], + "index": "pypi", + "version": "==1.9.0" + }, + "django-dbtemplates": { + "hashes": [ + "sha256:6ff4199a7e7b008cd952df1ad0ff05ad07c78a4106590d81def327fa946a0a0b", + "sha256:76226ed8afde6cc5b5f45031d3689eeb5fd126e5a64182112b97ce9726bf6904" + ], + "index": "pypi", + "version": "==3.0" + }, + "django-deprecate-fields": { + "hashes": [ + "sha256:2020b5f9eee26d9bbedd28a993b5c050c20adb0e276795a66b70f47a25db0120", + "sha256:7d5df6617fe2020f4a89b86d25074d033d56158ba36ab12cc9cec1f75cae002c" + ], + "index": "pypi", + "version": "==0.0.4" + }, + "django-environ": { + "hashes": [ + "sha256:6c9d87660142608f63ec7d5ce5564c49b603ea8ff25da595fd6098f6dc82afde", + "sha256:c57b3c11ec1f319d9474e3e5a79134f40174b17c7cc024bbb2fad84646b120c4" + ], + "index": "pypi", + "version": "==0.4.5" + }, + "django-filter": { + "hashes": [ + "sha256:558c727bce3ffa89c4a7a0b13bc8976745d63e5fd576b3a9a851650ef11c401b", + "sha256:c3deb57f0dd7ff94d7dce52a047516822013e2b441bed472b722a317658cfd14" + ], + "index": "pypi", + "version": "==2.2.0" + }, + "django-impersonate": { + "hashes": [ + "sha256:2c10bcb1c42fe6495d915f4cc4cfd7c5f8375ba39a06b0f062ce6f1e2ff76585" + ], + "index": "pypi", + "version": "==1.5" + }, + "django-js-asset": { + "hashes": [ + "sha256:8ec12017f26eec524cab436c64ae73033368a372970af4cf42d9354fcb166bdd", + "sha256:c163ae80d2e0b22d8fb598047cd0dcef31f81830e127cfecae278ad574167260" + ], + "version": "==1.2.2" + }, + "django-jsoneditor": { + "hashes": [ + "sha256:574f33a60271f464cad5739b6f4718aca81a779188297faa5adab41754cac9ba", + "sha256:e74760740ef5ecb0d295bb07c21635d2bebea7b9bab4352fa403720cc275a905" + ], + "index": "pypi", + "version": "==0.1.6" + }, + "django-migration-linter": { + "hashes": [ + "sha256:85473556050955322a3509adccf82fd5b545a229cfc6227b0d9f50182dade8ab", + "sha256:966d4af0da98edd2186f262a0da17946aadd6ad93a97d523f3011879928b3152" + ], + "index": "pypi", + "version": "==2.1.0" + }, + "django-model-utils": { + "hashes": [ + "sha256:9cf882e5b604421b62dbe57ad2b18464dc9c8f963fc3f9831badccae66c1139c", + "sha256:adf09e5be15122a7f4e372cb5a6dd512bbf8d78a23a90770ad0983ee9d909061" + ], + "index": "pypi", + "version": "==4.0.0" + }, + "django-mptt": { + "hashes": [ + "sha256:90eb236eb4f1a92124bd7c37852bbe09c0d21158477cc237556d59842a91c509", + "sha256:dfdb3af75ad27cdd4458b0544ec8574174f2b90f99bc2cafab6a15b4bc1895a8" + ], + "index": "pypi", + "version": "==0.11.0" + }, + "django-oauth-toolkit": { + "hashes": [ + "sha256:48a45d9ec23b50646b14b4b93988bd0d35ad5cf933edfcb833a8527f86329f28", + "sha256:a67ab96089b96540e34dc8d1ee6e6305a80ee01a36f7688108cd94b77406bdd3" + ], + "version": "==1.3.3" + }, + "django-picklefield": { + "hashes": [ + "sha256:67a5e156343e3b032cac2f65565f0faa81635a99c7da74b0f07a0f5db467b646", + "sha256:e03cb181b7161af38ad6b573af127e4fe9b7cc2c455b42c1ec43eaad525ade0a" + ], + "index": "pypi", + "version": "==2.1.1" + }, + "django-post-office": { + "hashes": [ + "sha256:c2f92fb3ede727160d61cb8e0f190b8fd6e6192f089dbe121ee16257ce198cff", + "sha256:d994bc0a87eb60a9d7c64d2c58a799fa72cad05eae19c4f13fbfa1ddb8bfda8d" + ], + "index": "pypi", + "version": "==3.3.1" + }, + "django-redis": { + "hashes": [ + "sha256:a5b1e3ffd3198735e6c529d9bdf38ca3fcb3155515249b98dc4d966b8ddf9d2b", + "sha256:e1aad4cc5bd743d8d0b13d5cae0cef5410eaace33e83bff5fc3a139ad8db50b4" + ], + "index": "pypi", + "version": "==4.11.0" + }, + "django-regex": { + "hashes": [ + "sha256:3f85f4611a921299b86614591fb7b82201d1748ac6207b358bd8b1f2d2289513" + ], + "index": "pypi", + "version": "==0.4.1" + }, + "django-rest-framework-social-oauth2": { + "hashes": [ + "sha256:c9a297b636ffd37957c6146280e99ead41e6aca37bcb995e3d52d65eefbca0b7" + ], + "index": "pypi", + "version": "==1.1.0" + }, + "django-sql-explorer": { + "hashes": [ + "sha256:b28f33750b7c1f1564644755dcffa393b75790598dc98ee155e487390855b967" + ], + "index": "pypi", + "version": "==1.1.3" + }, + "django-storages": { + "hashes": [ + "sha256:3103991c2ee8cef8a2ff096709973ffe7106183d211a79f22cf855f33533d924", + "sha256:a59e9923cbce7068792f75344ed7727021ee4ac20f227cf17297d0d03d141e91" + ], + "index": "pypi", + "version": "==1.9.1" + }, + "django-strategy-field": { + "hashes": [ + "sha256:fafd78f9d75a1edcfba2f9cae8f8f1b8609ebd9ec84c310f5eea6fc35ba21a9b" + ], + "index": "pypi", + "version": "==2.0" + }, + "django-sysinfo": { + "hashes": [ + "sha256:73844d6662ab7eb724d40f935aaef84bbe00cbe03a529bf263b54caf918b1c9c" + ], + "index": "pypi", + "version": "==1.4" + }, + "django-timezone-field": { + "hashes": [ + "sha256:068dc2c9b11c2230e126f511a515609d46f8cc49278b293e7536be07997fe892", + "sha256:b5b587aabed8db66eb3453691522164915c1aa1b326d8ddeadc8832a8580faeb" + ], + "markers": "python_version >= '3.5'", + "version": "==4.1.1" + }, + "djangorestframework": { + "hashes": [ + "sha256:05809fc66e1c997fd9a32ea5730d9f4ba28b109b9da71fccfa5ff241201fd0a4", + "sha256:e782087823c47a26826ee5b6fa0c542968219263fb3976ec3c31edab23a4001f" + ], + "index": "pypi", + "version": "==3.11.0" + }, + "djangorestframework-csv": { + "hashes": [ + "sha256:2f008b20a44f2d3c37835ea5b5ddfe19f54394f07b9cb267c616a917a7f7e27c" + ], + "index": "pypi", + "version": "==2.1.0" + }, + "djangorestframework-gis": { + "hashes": [ + "sha256:63c253528a107bc77cd71506cd639a0489b05b763fa7c3190cfd4622bf094594", + "sha256:f388c159ab42ee2549c88de20655dc6020d01f0220b74c250a98735a26835f72" + ], + "index": "pypi", + "version": "==0.15" + }, + "djangorestframework-jwt": { + "hashes": [ + "sha256:5efe33032f3a4518a300dc51a51c92145ad95fb6f4b272e5aa24701db67936a7", + "sha256:ab15dfbbe535eede8e2e53adaf52ef0cf018ee27dbfad10cbc4cbec2ab63d38c" + ], + "index": "pypi", + "version": "==1.11.0" + }, + "djangorestframework-xml": { + "hashes": [ + "sha256:d8118580b6c0e94a6b908a78c8d842e9f349901dfff43d91adc2d73a54f4ba59", + "sha256:d85d5744e75fe01ea2af667b15f6aa7df97c710516477ba493558da8432f6b0f" + ], + "index": "pypi", + "version": "==1.4.0" + }, + "djangorestframework-yaml": { + "hashes": [ + "sha256:58e44b2ba2b1484fe793adcdc5d04910ab9b385a2991603b049b96eed6a76d32", + "sha256:b2277cb0459cf14b473e8cb6e0055725582afe862049c32b840b261ca8fbce3e" + ], + "index": "pypi", + "version": "==1.0.3" + }, + "drf-dynamic-serializer": { + "hashes": [ + "sha256:ce4578bea4c27bc58fdfe11410c2ccf9b7ec1de44b8a83dd5b1c23399d1d1d84" + ], + "index": "pypi", + "version": "==2.1" + }, + "drf-extensions": { + "hashes": [ + "sha256:9a76d59c8ecc2814860e94a0c96a26a824e392cd4550f2efa928af43c002a750", + "sha256:a04cf188d27fdc13a1083a3ac9e4d72d3d93fcef76b3584191489c75d550c10d" + ], + "index": "pypi", + "version": "==0.6.0" + }, + "drf-renderer-xlsx": { + "hashes": [ + "sha256:95a825de15870a019175d95e76704bbd8fb4b6b0435d8b724531b95449325825", + "sha256:b6805c1f1c0657c8fef2a1056c5ab26ec6c80581c622f175440d1e09dd1ab8d1" + ], + "index": "pypi", + "version": "==0.3.7" + }, + "drf-yasg": { + "hashes": [ + "sha256:5572e9d5baab9f6b49318169df9789f7399d0e3c7bdac8fdb8dfccf1d5d2b1ca", + "sha256:7d7af27ad16e18507e9392b2afd6b218fbffc432ec8dbea053099a2241e184ff" + ], + "index": "pypi", + "version": "==1.17.1" + }, + "et-xmlfile": { + "hashes": [ + "sha256:614d9722d572f6246302c4491846d2c393c199cfa4edc9af593437691683335b" + ], + "version": "==1.0.1" + }, + "gunicorn": { + "hashes": [ + "sha256:1904bb2b8a43658807108d59c3f3d56c2b6121a701161de0ddf9ad140073c626", + "sha256:cd4a810dd51bf497552cf3f863b575dabd73d6ad6a91075b65936b151cbf4f9c" + ], + "index": "pypi", + "version": "==20.0.4" + }, + "html5lib": { + "hashes": [ + "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d", + "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==1.1" + }, + "humanfriendly": { + "hashes": [ + "sha256:25c2108a45cfd1e8fbe9cdb30b825d34ef5d5675c8e11e4775c9aedbfb0bdee2", + "sha256:3a831920e40e55ad49adb64c9179ed50c604cabca72cd300e7bd5b51310e4ebb" + ], + "index": "pypi", + "version": "==8.1" + }, + "humanize": { + "hashes": [ + "sha256:0b3157df0f3fcdcb7611180d305a23fd4b6290eb23586e058762f8576348fbab", + "sha256:de8ef6ffee618a9d369b3d1fb1359780ccaa2cc76a0e777c6ff21f04d19a0eb8" + ], + "index": "pypi", + "version": "==2.2.0" + }, + "idna": { + "hashes": [ + "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", + "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.10" + }, + "importlib-metadata": { + "hashes": [ + "sha256:5c5a2720817414a6c41f0a49993908068243ae02c1635a228126519b509c8aed", + "sha256:bf792d480abbd5eda85794e4afb09dd538393f7d6e6ffef6e9f03d2014cf9450" + ], + "markers": "python_version < '3.8'", + "version": "==3.3.0" + }, + "inflection": { + "hashes": [ + "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417", + "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2" + ], + "markers": "python_version >= '3.5'", + "version": "==0.5.1" + }, + "iso8601": { + "hashes": [ + "sha256:694be0743e9f1535ea873bfc7bd6fb62380c62b75822761859428073a17fd39c", + "sha256:6f02f01dd13320a7f280e58516dc8d1950dfaf77527cc365a398cd9de4d3c692", + "sha256:f7dec22af52025d4526be94cc1303c7d8f5379b746a3f54a8c8446384392eeb1" + ], + "version": "==0.1.13" + }, + "itypes": { + "hashes": [ + "sha256:03da6872ca89d29aef62773672b2d408f490f80db48b23079a4b194c86dd04c6", + "sha256:af886f129dea4a2a1e3d36595a2d139589e4dd287f5cab0b40e799ee81570ff1" + ], + "version": "==1.2.0" + }, + "jdcal": { + "hashes": [ + "sha256:1abf1305fce18b4e8aa248cf8fe0c56ce2032392bc64bbd61b5dff2a19ec8bba", + "sha256:472872e096eb8df219c23f2689fc336668bdb43d194094b5cc1707e1640acfc8" + ], + "version": "==1.4.1" + }, + "jinja2": { + "hashes": [ + "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0", + "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==2.11.2" + }, + "jsonfield": { + "hashes": [ + "sha256:7e4e84597de21eeaeeaaa7cc5da08c61c48a9b64d0c446b2d71255d01812887a", + "sha256:df857811587f252b97bafba42e02805e70a398a7a47870bc6358a0308dd689ed" + ], + "markers": "python_version >= '3.6'", + "version": "==3.1.0" + }, + "jsonschema": { + "hashes": [ + "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163", + "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a" + ], + "version": "==3.2.0" + }, + "kombu": { + "hashes": [ + "sha256:be48cdffb54a2194d93ad6533d73f69408486483d189fe9f5990ee24255b0e0a", + "sha256:ca1b45faac8c0b18493d02a8571792f3c40291cf2bcf1f55afed3d8f3aa7ba74" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==4.6.11" + }, + "markdown": { + "hashes": [ + "sha256:90fee683eeabe1a92e149f7ba74e5ccdc81cd397bd6c516d93a8da0ef90b6902", + "sha256:e4795399163109457d4c5af2183fbe6b60326c17cfdf25ce6e7474c6624f725d" + ], + "index": "pypi", + "version": "==3.2.1" + }, + "markupsafe": { + "hashes": [ + "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", + "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", + "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", + "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", + "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", + "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", + "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", + "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", + "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", + "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", + "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", + "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", + "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", + "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", + "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", + "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", + "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", + "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", + "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", + "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", + "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", + "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", + "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", + "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", + "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", + "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", + "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.1.1" + }, + "oauthlib": { + "hashes": [ + "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889", + "sha256:df884cd6cbe20e32633f1db1072e9356f53638e4361bef4e8b03c9127c9328ea" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==3.1.0" + }, + "openpyxl": { + "hashes": [ + "sha256:547a9fc6aafcf44abe358b89ed4438d077e9d92e4f182c87e2dc294186dc4b64" + ], + "index": "pypi", + "version": "==3.0.3" + }, + "packaging": { + "hashes": [ + "sha256:24e0da08660a87484d1602c30bb4902d74816b6985b93de36926f5bc95741858", + "sha256:78598185a7008a470d64526a8059de9aaa449238f280fc9eb6b13ba6c4109093" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==20.8" + }, + "pillow": { + "hashes": [ + "sha256:165c88bc9d8dba670110c689e3cc5c71dbe4bfb984ffa7cbebf1fac9554071d6", + "sha256:22d070ca2e60c99929ef274cfced04294d2368193e935c5d6febfd8b601bf865", + "sha256:2353834b2c49b95e1313fb34edf18fca4d57446675d05298bb694bca4b194174", + "sha256:39725acf2d2e9c17356e6835dccebe7a697db55f25a09207e38b835d5e1bc032", + "sha256:3de6b2ee4f78c6b3d89d184ade5d8fa68af0848f9b6b6da2b9ab7943ec46971a", + "sha256:47c0d93ee9c8b181f353dbead6530b26980fe4f5485aa18be8f1fd3c3cbc685e", + "sha256:5e2fe3bb2363b862671eba632537cd3a823847db4d98be95690b7e382f3d6378", + "sha256:604815c55fd92e735f9738f65dabf4edc3e79f88541c221d292faec1904a4b17", + "sha256:6c5275bd82711cd3dcd0af8ce0bb99113ae8911fc2952805f1d012de7d600a4c", + "sha256:731ca5aabe9085160cf68b2dbef95fc1991015bc0a3a6ea46a371ab88f3d0913", + "sha256:7612520e5e1a371d77e1d1ca3a3ee6227eef00d0a9cddb4ef7ecb0b7396eddf7", + "sha256:7916cbc94f1c6b1301ac04510d0881b9e9feb20ae34094d3615a8a7c3db0dcc0", + "sha256:81c3fa9a75d9f1afafdb916d5995633f319db09bd773cb56b8e39f1e98d90820", + "sha256:887668e792b7edbfb1d3c9d8b5d8c859269a0f0eba4dda562adb95500f60dbba", + "sha256:93a473b53cc6e0b3ce6bf51b1b95b7b1e7e6084be3a07e40f79b42e83503fbf2", + "sha256:96d4dc103d1a0fa6d47c6c55a47de5f5dafd5ef0114fa10c85a1fd8e0216284b", + "sha256:a3d3e086474ef12ef13d42e5f9b7bbf09d39cf6bd4940f982263d6954b13f6a9", + "sha256:b02a0b9f332086657852b1f7cb380f6a42403a6d9c42a4c34a561aa4530d5234", + "sha256:b09e10ec453de97f9a23a5aa5e30b334195e8d2ddd1ce76cc32e52ba63c8b31d", + "sha256:b6f00ad5ebe846cc91763b1d0c6d30a8042e02b2316e27b05de04fa6ec831ec5", + "sha256:bba80df38cfc17f490ec651c73bb37cd896bc2400cfba27d078c2135223c1206", + "sha256:c3d911614b008e8a576b8e5303e3db29224b455d3d66d1b2848ba6ca83f9ece9", + "sha256:ca20739e303254287138234485579b28cb0d524401f83d5129b5ff9d606cb0a8", + "sha256:cb192176b477d49b0a327b2a5a4979552b7a58cd42037034316b8018ac3ebb59", + "sha256:cdbbe7dff4a677fb555a54f9bc0450f2a21a93c5ba2b44e09e54fcb72d2bd13d", + "sha256:d355502dce85ade85a2511b40b4c61a128902f246504f7de29bbeec1ae27933a", + "sha256:dc577f4cfdda354db3ae37a572428a90ffdbe4e51eda7849bf442fb803f09c9b", + "sha256:dd9eef866c70d2cbbea1ae58134eaffda0d4bfea403025f4db6859724b18ab3d" + ], + "markers": "python_version >= '3.6'", + "version": "==8.1.0" + }, + "psutil": { + "hashes": [ + "sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64", + "sha256:02b8292609b1f7fcb34173b25e48d0da8667bc85f81d7476584d889c6e0f2131", + "sha256:0ae6f386d8d297177fd288be6e8d1afc05966878704dad9847719650e44fc49c", + "sha256:0c9ccb99ab76025f2f0bbecf341d4656e9c1351db8cc8a03ccd62e318ab4b5c6", + "sha256:0dd4465a039d343925cdc29023bb6960ccf4e74a65ad53e768403746a9207023", + "sha256:12d844996d6c2b1d3881cfa6fa201fd635971869a9da945cf6756105af73d2df", + "sha256:1bff0d07e76114ec24ee32e7f7f8d0c4b0514b3fae93e3d2aaafd65d22502394", + "sha256:245b5509968ac0bd179287d91210cd3f37add77dad385ef238b275bad35fa1c4", + "sha256:28ff7c95293ae74bf1ca1a79e8805fcde005c18a122ca983abf676ea3466362b", + "sha256:36b3b6c9e2a34b7d7fbae330a85bf72c30b1c827a4366a07443fc4b6270449e2", + "sha256:52de075468cd394ac98c66f9ca33b2f54ae1d9bff1ef6b67a212ee8f639ec06d", + "sha256:5da29e394bdedd9144c7331192e20c1f79283fb03b06e6abd3a8ae45ffecee65", + "sha256:61f05864b42fedc0771d6d8e49c35f07efd209ade09a5afe6a5059e7bb7bf83d", + "sha256:6223d07a1ae93f86451d0198a0c361032c4c93ebd4bf6d25e2fb3edfad9571ef", + "sha256:6323d5d845c2785efb20aded4726636546b26d3b577aded22492908f7c1bdda7", + "sha256:6ffe81843131ee0ffa02c317186ed1e759a145267d54fdef1bc4ea5f5931ab60", + "sha256:74f2d0be88db96ada78756cb3a3e1b107ce8ab79f65aa885f76d7664e56928f6", + "sha256:74fb2557d1430fff18ff0d72613c5ca30c45cdbfcddd6a5773e9fc1fe9364be8", + "sha256:90d4091c2d30ddd0a03e0b97e6a33a48628469b99585e2ad6bf21f17423b112b", + "sha256:90f31c34d25b1b3ed6c40cdd34ff122b1887a825297c017e4cbd6796dd8b672d", + "sha256:99de3e8739258b3c3e8669cb9757c9a861b2a25ad0955f8e53ac662d66de61ac", + "sha256:c6a5fd10ce6b6344e616cf01cc5b849fa8103fbb5ba507b6b2dee4c11e84c935", + "sha256:ce8b867423291cb65cfc6d9c4955ee9bfc1e21fe03bb50e177f2b957f1c2469d", + "sha256:d225cd8319aa1d3c85bf195c4e07d17d3cd68636b8fc97e6cf198f782f99af28", + "sha256:ea313bb02e5e25224e518e4352af4bf5e062755160f77e4b1767dd5ccb65f876", + "sha256:ea372bcc129394485824ae3e3ddabe67dc0b118d262c568b4d2602a7070afdb0", + "sha256:f4634b033faf0d968bb9220dd1c793b897ab7f1189956e1aa9eae752527127d3", + "sha256:fcc01e900c1d7bee2a37e5d6e4f9194760a93597c97fee89c4ae51701de03563" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==5.8.0" + }, + "psycopg2-binary": { + "hashes": [ + "sha256:19a2d1f3567b30f6c2bb3baea23f74f69d51f0c06c2e2082d0d9c28b0733a4c2", + "sha256:2b69cf4b0fa2716fd977aa4e1fd39af6110eb47b2bb30b4e5a469d8fbecfc102", + "sha256:2e952fa17ba48cbc2dc063ddeec37d7dc4ea0ef7db0ac1eda8906365a8543f31", + "sha256:348b49dd737ff74cfb5e663e18cb069b44c64f77ec0523b5794efafbfa7df0b8", + "sha256:3d72a5fdc5f00ca85160915eb9a973cf9a0ab8148f6eda40708bf672c55ac1d1", + "sha256:4957452f7868f43f32c090dadb4188e9c74a4687323c87a882e943c2bd4780c3", + "sha256:5138cec2ee1e53a671e11cc519505eb08aaaaf390c508f25b09605763d48de4b", + "sha256:587098ca4fc46c95736459d171102336af12f0d415b3b865972a79c03f06259f", + "sha256:5b79368bcdb1da4a05f931b62760bea0955ee2c81531d8e84625df2defd3f709", + "sha256:5cf43807392247d9bc99737160da32d3fa619e0bfd85ba24d1c78db205f472a4", + "sha256:676d1a80b1eebc0cacae8dd09b2fde24213173bf65650d22b038c5ed4039f392", + "sha256:6b0211ecda389101a7d1d3df2eba0cf7ffbdd2480ca6f1d2257c7bd739e84110", + "sha256:79cde4660de6f0bb523c229763bd8ad9a93ac6760b72c369cf1213955c430934", + "sha256:7aba9786ac32c2a6d5fb446002ed936b47d5e1f10c466ef7e48f66eb9f9ebe3b", + "sha256:7c8159352244e11bdd422226aa17651110b600d175220c451a9acf795e7414e0", + "sha256:945f2eedf4fc6b2432697eb90bb98cc467de5147869e57405bfc31fa0b824741", + "sha256:96b4e902cde37a7fc6ab306b3ac089a3949e6ce3d824eeca5b19dc0bedb9f6e2", + "sha256:9a7bccb1212e63f309eb9fab47b6eaef796f59850f169a25695b248ca1bf681b", + "sha256:a3bfcac727538ec11af304b5eccadbac952d4cca1a551a29b8fe554e3ad535dc", + "sha256:b19e9f1b85c5d6136f5a0549abdc55dcbd63aba18b4f10d0d063eb65ef2c68b4", + "sha256:b664011bb14ca1f2287c17185e222f2098f7b4c857961dbcf9badb28786dbbf4", + "sha256:bde7959ef012b628868d69c474ec4920252656d0800835ed999ba5e4f57e3e2e", + "sha256:cb095a0657d792c8de9f7c9a0452385a309dfb1bbbb3357d6b1e216353ade6ca", + "sha256:d16d42a1b9772152c1fe606f679b2316551f7e1a1ce273e7f808e82a136cdb3d", + "sha256:d444b1545430ffc1e7a24ce5a9be122ccd3b135a7b7e695c5862c5aff0b11159", + "sha256:d93ccc7bf409ec0a23f2ac70977507e0b8a8d8c54e5ee46109af2f0ec9e411f3", + "sha256:df6444f952ca849016902662e1a47abf4fa0678d75f92fd9dd27f20525f809cd", + "sha256:e63850d8c52ba2b502662bf3c02603175c2397a9acc756090e444ce49508d41e", + "sha256:ec43358c105794bc2b6fd34c68d27f92bea7102393c01889e93f4b6a70975728", + "sha256:f4c6926d9c03dadce7a3b378b40d2fea912c1344ef9b29869f984fb3d2a2420b" + ], + "index": "pypi", + "version": "==2.7.7" + }, + "pycparser": { + "hashes": [ + "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0", + "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.20" + }, + "pygments": { + "hashes": [ + "sha256:647344a061c249a3b74e230c739f434d7ea4d8b1d5f3721bc0f3558049b38f44", + "sha256:ff7a40b4860b727ab48fad6360eb351cc1b33cbf9b15a0f689ca5353e9463324" + ], + "index": "pypi", + "version": "==2.6.1" + }, + "pyjwt": { + "hashes": [ + "sha256:5c6eca3c2940464d106b99ba83b00c6add741c9becaec087fb7ccdefea71350e", + "sha256:8d59a976fb773f3e6a39c85636357c4f0e242707394cadadd9814f5cbaa20e96" + ], + "version": "==1.7.1" + }, + "pyparsing": { + "hashes": [ + "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", + "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.4.7" + }, + "pypdf2": { + "hashes": [ + "sha256:e28f902f2f0a1603ea95ebe21dff311ef09be3d0f0ef29a3e44a932729564385" + ], + "version": "==1.26.0" + }, + "pyrsistent": { + "hashes": [ + "sha256:2e636185d9eb976a18a8a8e96efce62f2905fea90041958d8cc2a189756ebf3e" + ], + "markers": "python_version >= '3.5'", + "version": "==0.17.3" + }, + "python-crontab": { + "hashes": [ + "sha256:4bbe7e720753a132ca4ca9d4094915f40e9d9dc8a807a4564007651018ce8c31" + ], + "version": "==2.5.1" + }, + "python-dateutil": { + "hashes": [ + "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", + "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.8.1" + }, + "python-social-auth": { + "hashes": [ + "sha256:6986220df76934aee15c54938a13ebe370a1976e043af01fa3bea417f6722e74", + "sha256:8aac8531f7dd4d1b9af606654532fef4f615cb437774a7a1f8dcdebe89c17664", + "sha256:9aaad6f7bf83fd129620eadaab1e78e63200da61a5d8898fd1aa243686b36575" + ], + "index": "pypi", + "version": "==0.3.6" + }, + "python3-openid": { + "hashes": [ + "sha256:33fbf6928f401e0b790151ed2b5290b02545e8775f982485205a066f874aaeaf", + "sha256:6626f771e0417486701e0b4daff762e7212e820ca5b29fcc0d05f6f8736dfa6b" + ], + "markers": "python_version >= '3.0'", + "version": "==3.2.0" + }, + "pytz": { + "hashes": [ + "sha256:16962c5fb8db4a8f63a26646d8886e9d769b6c511543557bc84e9569fb9a9cb4", + "sha256:180befebb1927b16f6b57101720075a984c019ac16b1b7575673bea42c6c3da5" + ], + "version": "==2020.5" + }, + "pyyaml": { + "hashes": [ + "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97", + "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76", + "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2", + "sha256:6034f55dab5fea9e53f436aa68fa3ace2634918e8b5994d82f3621c04ff5ed2e", + "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648", + "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf", + "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f", + "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2", + "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee", + "sha256:ad9c67312c84def58f3c04504727ca879cb0013b2517c85a9a253f0cb6380c0a", + "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d", + "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c", + "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a" + ], + "version": "==5.3.1" + }, + "rapidpro-python": { + "hashes": [ + "sha256:06c9c19960ea46ddb7ce7a9074971a256394ed42ea599492801cfe701eb497ca", + "sha256:ccaa3c067fccb5ff22653938a92e4ef819026ad4e74e7149ff9735ee7a0316a9" + ], + "index": "pypi", + "version": "==2.7.0" + }, + "raven": { + "hashes": [ + "sha256:3fa6de6efa2493a7c827472e984ce9b020797d0da16f1db67197bcc23c8fae54", + "sha256:44a13f87670836e153951af9a3c80405d36b43097db869a36e92809673692ce4" + ], + "index": "pypi", + "version": "==6.10.0" + }, + "redis": { + "hashes": [ + "sha256:0e7e0cfca8660dea8b7d5cd8c4f6c5e29e11f31158c0b0ae91a397f00e5a05a2", + "sha256:432b788c4530cfe16d8d943a09d40ca6c16149727e4afe8c2c9d5580c59d9f24" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==3.5.3" + }, + "reportlab": { + "hashes": [ + "sha256:009fa61710647cdc62eb373345248d8ebb93583a058990f7c4f9be46d90aa5b1", + "sha256:04a08d284da86882ec3a41a7c719833362ef891b09ee8e2fbb47cee352aa684a", + "sha256:07bff6742fba612da8d1b1f783c436338c6fdc6962828159827d5ca7d2b67935", + "sha256:09fb11ab1500e679fc1b01199d2fed24435499856e75043a9ac0d31dd48fd881", + "sha256:18a876449c9000c391dd3415ebc8454cd7bb9e488977b894886a2d7d018f16cd", + "sha256:18eec161411026dde49767bee4e5e8eeb8014879554811a62581dc7433628d5b", + "sha256:19353aead39fc115a4d6c598d6fb9fa26da7e69160a0443ebb49b02903e704e8", + "sha256:1b85c20e89c22ae902ca973df2afdd2d64d27dc4ffd2b29ebad8c805a213756b", + "sha256:1da3d7a35f918cee905facfa94bd00ae6091cadc06dca1b0b31b69ae02d41d1d", + "sha256:33f3cfdc492575f8af3225701301a7e62fc478358729820c9e0091aff5831378", + "sha256:3b0026c1129147befd4e5a8cf25da8dea1096fce371e7b2412e36d7254019c06", + "sha256:3d7713dddaa8081ed709a1fa2456a43f6a74b0f07d605da8441fd53fef334f69", + "sha256:3e2b4d69763103b9dc9b54c0952dc3cee05cedd06e28c0987fad7f84705b12c0", + "sha256:4ca5233a19a5ceca23546290f43addec2345789c7d65bb32f8b2668aa148351f", + "sha256:5214a289cf01ebbd65e49bae83709671dd9edb601891cf0ae8abf85f3c0b392f", + "sha256:52f8237654acbc78ea2fa6fb4a6a06e5b023b6da93f7889adfe2deba09473fad", + "sha256:5ed00894e0f8281c0b7c0494b4d3067c641fd90c8e5cf933089ec4cc9a48e491", + "sha256:6191961533d49c9d860964d42bada4d7ac3bb28502d984feb8034093f2012fa8", + "sha256:6f3ad2b1afe99c436563cd436d8693d4a12e2c4bd45f70c7705759ff7837fe53", + "sha256:739b743b7ca1ba4b4d64c321de6fccb49b562d0507ea06c817d9cc4faed5cd22", + "sha256:792efba0c0c6e4ee94f6dc95f305451733ee9230a1c7d51cb8e5301a549e0dfb", + "sha256:79d63ca40231ca3860859b39a92daa5219035ba9553da89a5e1b218550744121", + "sha256:83b28104edd58ad65748d2d0e60e0d97e3b91b3e90b4573ea6fe60de6811972c", + "sha256:85650446538cd2f606ca234634142a7ccd74cb6db7cfec250f76a4242e0f2431", + "sha256:9da445cb79e3f740756924c053edc952cde11a65ff5af8acfda3c0a1317136ef", + "sha256:9fabd5fbd24f5971085ffe53150d663f158f7d3050b25c95736e29ebf676d454", + "sha256:a0c377bc45e73c3f15f55d7de69fab270d174749d5b454ab0de502b15430ec2a", + "sha256:a1d3f7022a920d4a5e165d264581f1862e1c1b877ceeabb96fe98cec98125ae5", + "sha256:a315edef5c5610b0c75790142f49487e89ea34397fc247ae8aa890fe6d6dd057", + "sha256:a755cca2dcf023130b03bb671670301a992157d5c3151d838c0b68ef89894536", + "sha256:b1b20208ecdfffd7ca027955c4fe8972b28b30a4b3b80cf25099a08d3b20ed7c", + "sha256:b26d6f416891cef93411d6d478a25db275766081a5fb66368248293ef459f3be", + "sha256:b4ba4c30af7044ee987e61c88a5ffb76031ca0c53666bc85d823b7de55ddbc75", + "sha256:b71faf3b6e4d7058e1af1b8afedaf39a962db4a219affc8177009d8244ec10d4", + "sha256:cfa854bea525f8c913cb77e2bda724d94b965a0eb3bcfc4a645a9baa29bb86e2", + "sha256:dd9687359e466086b9f6fe6d8069034017f8b6ca3080944fae5709767ca6814e", + "sha256:de0c675fc2998a7eaa929c356ba49c84f53a892e9ab25e8ee7d8ebbbdcb2ac16", + "sha256:e2b4e33fea2ce9d3a14ea39191b169e41eb2ac995274f54ac8fd27519974bce8", + "sha256:f3d4a1a273dc141e03b72a553c11bc14dd7a27ec7654a071edcf83eb04f004bc", + "sha256:ff547cf4c1de7e104cad1a378431ff81efcb03e90e40871ee686107da5b91442" + ], + "version": "==3.5.59" + }, + "requests": { + "hashes": [ + "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee", + "sha256:5d2d0ffbb515f39417009a46c14256291061ac01ba8f875b90cad137de83beb4", + "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6" + ], + "index": "pypi", + "version": "==2.23.0" + }, + "requests-oauthlib": { + "hashes": [ + "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d", + "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a", + "sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc" + ], + "version": "==1.3.0" + }, + "ruamel.yaml": { + "hashes": [ + "sha256:012b9470a0ea06e4e44e99e7920277edf6b46eee0232a04487ea73a7386340a5", + "sha256:076cc0bc34f1966d920a49f18b52b6ad559fbe656a0748e3535cf7b3f29ebf9e" + ], + "version": "==0.16.12" + }, + "ruamel.yaml.clib": { + "hashes": [ + "sha256:058a1cc3df2a8aecc12f983a48bda99315cebf55a3b3a5463e37bb599b05727b", + "sha256:1236df55e0f73cd138c0eca074ee086136c3f16a97c2ac719032c050f7e0622f", + "sha256:1f8c0a4577c0e6c99d208de5c4d3fd8aceed9574bb154d7a2b21c16bb924154c", + "sha256:2602e91bd5c1b874d6f93d3086f9830f3e907c543c7672cf293a97c3fabdcd91", + "sha256:28116f204103cb3a108dfd37668f20abe6e3cafd0d3fd40dba126c732457b3cc", + "sha256:2d24bd98af676f4990c4d715bcdc2a60b19c56a3fb3a763164d2d8ca0e806ba7", + "sha256:2fd336a5c6415c82e2deb40d08c222087febe0aebe520f4d21910629018ab0f3", + "sha256:30dca9bbcbb1cc858717438218d11eafb78666759e5094dd767468c0d577a7e7", + "sha256:44c7b0498c39f27795224438f1a6be6c5352f82cb887bc33d962c3a3acc00df6", + "sha256:464e66a04e740d754170be5e740657a3b3b6d2bcc567f0c3437879a6e6087ff6", + "sha256:46d6d20815064e8bb023ea8628cfb7402c0f0e83de2c2227a88097e239a7dffd", + "sha256:4df5019e7783d14b79217ad9c56edf1ba7485d614ad5a385d1b3c768635c81c0", + "sha256:4e52c96ca66de04be42ea2278012a2342d89f5e82b4512fb6fb7134e377e2e62", + "sha256:5254af7d8bdf4d5484c089f929cb7f5bafa59b4f01d4f48adda4be41e6d29f99", + "sha256:52ae5739e4b5d6317b52f5b040b1b6639e8af68a5b8fd606a8b08658fbd0cab5", + "sha256:53b9dd1abd70e257a6e32f934ebc482dac5edb8c93e23deb663eac724c30b026", + "sha256:6c0a5dc52fc74eb87c67374a4e554d4761fd42a4d01390b7e868b30d21f4b8bb", + "sha256:73b3d43e04cc4b228fa6fa5d796409ece6fcb53a6c270eb2048109cbcbc3b9c2", + "sha256:74161d827407f4db9072011adcfb825b5258a5ccb3d2cd518dd6c9edea9e30f1", + "sha256:75f0ee6839532e52a3a53f80ce64925ed4aed697dd3fa890c4c918f3304bd4f4", + "sha256:839dd72545ef7ba78fd2aa1a5dd07b33696adf3e68fae7f31327161c1093001b", + "sha256:8be05be57dc5c7b4a0b24edcaa2f7275866d9c907725226cdde46da09367d923", + "sha256:8e8fd0a22c9d92af3a34f91e8a2594eeb35cba90ab643c5e0e643567dc8be43e", + "sha256:a873e4d4954f865dcb60bdc4914af7eaae48fb56b60ed6daa1d6251c72f5337c", + "sha256:ab845f1f51f7eb750a78937be9f79baea4a42c7960f5a94dde34e69f3cce1988", + "sha256:b1e981fe1aff1fd11627f531524826a4dcc1f26c726235a52fcb62ded27d150f", + "sha256:b4b0d31f2052b3f9f9b5327024dc629a253a83d8649d4734ca7f35b60ec3e9e5", + "sha256:c6ac7e45367b1317e56f1461719c853fd6825226f45b835df7436bb04031fd8a", + "sha256:daf21aa33ee9b351f66deed30a3d450ab55c14242cfdfcd377798e2c0d25c9f1", + "sha256:e9f7d1d8c26a6a12c23421061f9022bb62704e38211fe375c645485f38df34a2", + "sha256:f6061a31880c1ed6b6ce341215336e2f3d0c1deccd84957b6fa8ca474b41e89f" + ], + "markers": "python_version < '3.9' and platform_python_implementation == 'CPython'", + "version": "==0.2.2" + }, + "sentry-sdk": { + "hashes": [ + "sha256:0a711ec952441c2ec89b8f5d226c33bc697914f46e876b44a4edd3e7864cf4d0", + "sha256:737a094e49a529dd0fdcaafa9e97cf7c3d5eb964bd229821d640bc77f3502b3f" + ], + "index": "pypi", + "version": "==0.19.5" + }, + "six": { + "hashes": [ + "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", + "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.14.0" + }, + "social-auth-app-django": { + "hashes": [ + "sha256:2c69e57df0b30c9c1823519c5f1992cbe4f3f98fdc7d95c840e091a752708840", + "sha256:567ad0e028311541d7dfed51d3bf2c60440a6fd236d5d4d06c5a618b3d6c57c5", + "sha256:df5212370bd250108987c4748419a1a1d0cec750878856c2644c36aaa0fd3e58" + ], + "version": "==4.0.0" + }, + "social-auth-core": { + "hashes": [ + "sha256:21c0639c56befd33ec162c2210d583bb1de8e1136d53b21bafb96afaf2f86c91", + "sha256:2f6ce1af8ec2b2cc37b86d647f7d4e4292f091ee556941db34b1e0e2dee77fc0", + "sha256:4a3cdf69c449b235cdabd54a1be7ba3722611297e69fded52e3584b1a990af25" + ], + "version": "==3.3.3" + }, + "sqlparse": { + "hashes": [ + "sha256:017cde379adbd6a1f15a61873f43e8274179378e95ef3fede90b5aa64d304ed0", + "sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8" + ], + "markers": "python_version >= '3.5'", + "version": "==0.4.1" + }, + "static3": { + "hashes": [ + "sha256:674641c64bc75507af2eb20bef7e7e3593dca993dec6674be108fa15b42f47c8" + ], + "version": "==0.7.0" + }, + "swagger-spec-validator": { + "hashes": [ + "sha256:61f2d2a732b886cf33c2c24886565be9692e5814cacc17fd973e095b72b33e4f", + "sha256:8eb82682871f8d63067b455e2e055c8dd953ca260e791635b58dfe0b73ba1f43" + ], + "index": "pypi", + "version": "==2.5.0" + }, + "typing-extensions": { + "hashes": [ + "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918", + "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c", + "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f" + ], + "markers": "python_version < '3.8'", + "version": "==3.7.4.3" + }, + "unicodecsv": { + "hashes": [ + "sha256:018c08037d48649a0412063ff4eda26eaa81eff1546dbffa51fa5293276ff7fc" + ], + "version": "==0.14.1" + }, + "uritemplate": { + "hashes": [ + "sha256:07620c3f3f8eed1f12600845892b0e036a2420acf513c53f7de0abd911a5894f", + "sha256:5af8ad10cec94f215e3f48112de2022e1d5a37ed427fbd88652fa908f2ab7cae" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==3.0.1" + }, + "urllib3": { + "hashes": [ + "sha256:8d7eaa5a82a1cac232164990f04874c594c9453ec55eef02eab885aa02fc17a2", + "sha256:f5321fbe4bf3fefa0efd0bfe7fb14e90909eb62a48ccda331726b4319897dd5e" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", + "version": "==1.25.11" + }, + "vine": { + "hashes": [ + "sha256:133ee6d7a9016f177ddeaf191c1f58421a1dcc6ee9a42c58b34bed40e1d2cd87", + "sha256:ea4947cc56d1fd6f2095c8d543ee25dad966f78692528e68b4fada11ba3f98af" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.3.0" + }, + "webencodings": { + "hashes": [ + "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", + "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" + ], + "version": "==0.5.1" + }, + "xhtml2pdf": { + "hashes": [ + "sha256:6793fbbdcb6bb8a4a70132966d8d95e95ea3498cdf0e82252d2b8e9aae34fcb5" + ], + "index": "pypi", + "version": "==0.2.4" + }, + "xlrd": { + "hashes": [ + "sha256:546eb36cee8db40c3eaa46c351e67ffee6eeb5fa2650b71bc4c758a29a1b29b2", + "sha256:e551fb498759fa3a5384a94ccd4c3c02eb7c00ea424426e212ac0c57be9dfbde" + ], + "index": "pypi", + "version": "==1.2.0" + }, + "xlwt": { + "hashes": [ + "sha256:a082260524678ba48a297d922cc385f58278b8aa68741596a87de01a9c628b2e", + "sha256:c59912717a9b28f1a3c2a98fd60741014b06b043936dcecbc113eaaada156c88" + ], + "index": "pypi", + "version": "==1.3.0" + }, + "zipp": { + "hashes": [ + "sha256:102c24ef8f171fd729d46599845e95c7ab894a4cf45f5de11a44cc7444fb1108", + "sha256:ed5eee1974372595f9e416cc7bbeeb12335201d8081ca8a0743c954d4446e5cb" + ], + "markers": "python_version >= '3.6'", + "version": "==3.4.0" + } + }, + "develop": { + "asgiref": { + "hashes": [ + "sha256:5ee950735509d04eb673bd7f7120f8fa1c9e2df495394992c73234d526907e17", + "sha256:7162a3cb30ab0609f1a4c95938fd73e8604f63bdba516a7f7d64b83ff09478f0" + ], + "markers": "python_version >= '3.5'", + "version": "==3.3.1" + }, + "attrs": { + "hashes": [ + "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6", + "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==20.3.0" + }, + "beautifulsoup4": { + "hashes": [ + "sha256:4c98143716ef1cb40bf7f39a8e3eec8f8b009509e74904ba3a7b315431577e35", + "sha256:84729e322ad1d5b4d25f805bfa05b902dd96450f43842c4e99067d5e1369eb25", + "sha256:fff47e031e34ec82bf17e00da8f592fe7de69aeea38be00523c04623c04fb666" + ], + "version": "==4.9.3" + }, + "coverage": { + "hashes": [ + "sha256:08b3ba72bd981531fd557f67beee376d6700fba183b167857038997ba30dd297", + "sha256:2757fa64e11ec12220968f65d086b7a29b6583d16e9a544c889b22ba98555ef1", + "sha256:3102bb2c206700a7d28181dbe04d66b30780cde1d1c02c5f3c165cf3d2489497", + "sha256:3498b27d8236057def41de3585f317abae235dd3a11d33e01736ffedb2ef8606", + "sha256:378ac77af41350a8c6b8801a66021b52da8a05fd77e578b7380e876c0ce4f528", + "sha256:38f16b1317b8dd82df67ed5daa5f5e7c959e46579840d77a67a4ceb9cef0a50b", + "sha256:3911c2ef96e5ddc748a3c8b4702c61986628bb719b8378bf1e4a6184bbd48fe4", + "sha256:3a3c3f8863255f3c31db3889f8055989527173ef6192a283eb6f4db3c579d830", + "sha256:3b14b1da110ea50c8bcbadc3b82c3933974dbeea1832e814aab93ca1163cd4c1", + "sha256:535dc1e6e68fad5355f9984d5637c33badbdc987b0c0d303ee95a6c979c9516f", + "sha256:6f61319e33222591f885c598e3e24f6a4be3533c1d70c19e0dc59e83a71ce27d", + "sha256:723d22d324e7997a651478e9c5a3120a0ecbc9a7e94071f7e1954562a8806cf3", + "sha256:76b2775dda7e78680d688daabcb485dc87cf5e3184a0b3e012e1d40e38527cc8", + "sha256:782a5c7df9f91979a7a21792e09b34a658058896628217ae6362088b123c8500", + "sha256:7e4d159021c2029b958b2363abec4a11db0ce8cd43abb0d9ce44284cb97217e7", + "sha256:8dacc4073c359f40fcf73aede8428c35f84639baad7e1b46fce5ab7a8a7be4bb", + "sha256:8f33d1156241c43755137288dea619105477961cfa7e47f48dbf96bc2c30720b", + "sha256:8ffd4b204d7de77b5dd558cdff986a8274796a1e57813ed005b33fd97e29f059", + "sha256:93a280c9eb736a0dcca19296f3c30c720cb41a71b1f9e617f341f0a8e791a69b", + "sha256:9a4f66259bdd6964d8cf26142733c81fb562252db74ea367d9beb4f815478e72", + "sha256:9a9d4ff06804920388aab69c5ea8a77525cf165356db70131616acd269e19b36", + "sha256:a2070c5affdb3a5e751f24208c5c4f3d5f008fa04d28731416e023c93b275277", + "sha256:a4857f7e2bc6921dbd487c5c88b84f5633de3e7d416c4dc0bb70256775551a6c", + "sha256:a607ae05b6c96057ba86c811d9c43423f35e03874ffb03fbdcd45e0637e8b631", + "sha256:a66ca3bdf21c653e47f726ca57f46ba7fc1f260ad99ba783acc3e58e3ebdb9ff", + "sha256:ab110c48bc3d97b4d19af41865e14531f300b482da21783fdaacd159251890e8", + "sha256:b239711e774c8eb910e9b1ac719f02f5ae4bf35fa0420f438cdc3a7e4e7dd6ec", + "sha256:be0416074d7f253865bb67630cf7210cbc14eb05f4099cc0f82430135aaa7a3b", + "sha256:c46643970dff9f5c976c6512fd35768c4a3819f01f61169d8cdac3f9290903b7", + "sha256:c5ec71fd4a43b6d84ddb88c1df94572479d9a26ef3f150cef3dacefecf888105", + "sha256:c6e5174f8ca585755988bc278c8bb5d02d9dc2e971591ef4a1baabdf2d99589b", + "sha256:c89b558f8a9a5a6f2cfc923c304d49f0ce629c3bd85cb442ca258ec20366394c", + "sha256:cc44e3545d908ecf3e5773266c487ad1877be718d9dc65fc7eb6e7d14960985b", + "sha256:cc6f8246e74dd210d7e2b56c76ceaba1cc52b025cd75dbe96eb48791e0250e98", + "sha256:cd556c79ad665faeae28020a0ab3bda6cd47d94bec48e36970719b0b86e4dcf4", + "sha256:ce6f3a147b4b1a8b09aae48517ae91139b1b010c5f36423fa2b866a8b23df879", + "sha256:ceb499d2b3d1d7b7ba23abe8bf26df5f06ba8c71127f188333dddcf356b4b63f", + "sha256:cef06fb382557f66d81d804230c11ab292d94b840b3cb7bf4450778377b592f4", + "sha256:e448f56cfeae7b1b3b5bcd99bb377cde7c4eb1970a525c770720a352bc4c8044", + "sha256:e52d3d95df81c8f6b2a1685aabffadf2d2d9ad97203a40f8d61e51b70f191e4e", + "sha256:ee2f1d1c223c3d2c24e3afbb2dd38be3f03b1a8d6a83ee3d9eb8c36a52bee899", + "sha256:f2c6888eada180814b8583c3e793f3f343a692fc802546eed45f40a001b1169f", + "sha256:f51dbba78d68a44e99d484ca8c8f604f17e957c1ca09c3ebc2c7e3bbd9ba0448", + "sha256:f54de00baf200b4539a5a092a759f000b5f45fd226d6d25a76b0dff71177a714", + "sha256:fa10fee7e32213f5c7b0d6428ea92e3a3fdd6d725590238a3f92c0de1c78b9d2", + "sha256:fabeeb121735d47d8eab8671b6b031ce08514c86b7ad8f7d5490a7b6dcd6267d", + "sha256:fac3c432851038b3e6afe086f777732bcf7f6ebbfd90951fa04ee53db6d0bcdd", + "sha256:fda29412a66099af6d6de0baa6bd7c52674de177ec2ad2630ca264142d69c6c7", + "sha256:ff1330e8bc996570221b450e2d539134baa9465f5cb98aff0e0f73f34172e0ae" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4.0'", + "version": "==5.3.1" + }, + "django": { + "hashes": [ + "sha256:84f370f6acedbe1f3c41e1a02de44ac206efda3355e427139ecb785b5f596d80", + "sha256:e8fe3c2b2212dce6126becab7a693157f1a441a07b62ec994c046c76af5bb66d" + ], + "index": "pypi", + "version": "==2.2.13" + }, + "django-extensions": { + "hashes": [ + "sha256:7cd002495ff0a0e5eb6cdd6be759600905b4e4079232ea27618fc46bdd853651", + "sha256:c7f88625a53f631745d4f2bef9ec4dcb999ed59476393bdbbe99db8596778846" + ], + "index": "pypi", + "version": "==3.1.0" + }, + "django-webtest": { + "hashes": [ + "sha256:b9b4b94670c0ce533efc456d02dd55a0d0a7a8f7912eb30728dca2d59d7948b4", + "sha256:c5a1e486a3d8d3623aa615b6db2f27de848aa7079303a84721e9a685f839796c" + ], + "index": "pypi", + "version": "==1.9.7" + }, + "djangorestframework": { + "hashes": [ + "sha256:05809fc66e1c997fd9a32ea5730d9f4ba28b109b9da71fccfa5ff241201fd0a4", + "sha256:e782087823c47a26826ee5b6fa0c542968219263fb3976ec3c31edab23a4001f" + ], + "index": "pypi", + "version": "==3.11.0" + }, + "drf-api-checker": { + "hashes": [ + "sha256:5341b63a9b33e9c093ee0f58932ec53373e57b7e619ee3acfb2bc05bd83594a5", + "sha256:a341a45a874ef00d1b10e51fd1b03dddecd9ef0aeba916ba91522a7bdcca9ae5" + ], + "index": "pypi", + "version": "==0.10.0" + }, + "factory-boy": { + "hashes": [ + "sha256:1d3db4b44b8c8c54cdd8b83ae4bdb9aeb121e464400035f1f03ae0e1eade56a4", + "sha256:401cc00ff339a022f84d64a4339503d1689e8263a4478d876e58a3295b155c5b" + ], + "index": "pypi", + "version": "==3.2.0" + }, + "faker": { + "hashes": [ + "sha256:bd56ab94b9ae45df3cdb6ef3ca3c2be2617e6a640699deb74394143d220faf04", + "sha256:d70983d5e623976e9e8987e9a39e8d55378e66049f393db35ea9a37b3190085f" + ], + "markers": "python_version >= '3.6'", + "version": "==5.4.0" + }, + "flake8": { + "hashes": [ + "sha256:749dbbd6bfd0cf1318af27bf97a14e28e5ff548ef8e5b1566ccfb25a11e7c839", + "sha256:aadae8761ec651813c24be05c6f7b4680857ef6afaae4651a4eccaef97ce6c3b" + ], + "index": "pypi", + "version": "==3.8.4" + }, + "freezegun": { + "hashes": [ + "sha256:02b35de52f4699a78f6ac4518e4cd3390dddc43b0aeb978335a8f270a2d9668b", + "sha256:1cf08e441f913ff5e59b19cc065a8faa9dd1ddc442eaf0375294f344581a0643" + ], + "index": "pypi", + "version": "==1.0.0" + }, + "idna": { + "hashes": [ + "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", + "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.10" + }, + "importlib-metadata": { + "hashes": [ + "sha256:5c5a2720817414a6c41f0a49993908068243ae02c1635a228126519b509c8aed", + "sha256:bf792d480abbd5eda85794e4afb09dd538393f7d6e6ffef6e9f03d2014cf9450" + ], + "markers": "python_version < '3.8'", + "version": "==3.3.0" + }, + "iniconfig": { + "hashes": [ + "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3", + "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32" + ], + "version": "==1.1.1" + }, + "isort": { + "hashes": [ + "sha256:c729845434366216d320e936b8ad6f9d681aab72dc7cbc2d51bedc3582f3ad1e", + "sha256:fff4f0c04e1825522ce6949973e83110a6e907750cd92d128b0d14aaaadbffdc" + ], + "index": "pypi", + "version": "==5.7.0" + }, + "mccabe": { + "hashes": [ + "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", + "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" + ], + "version": "==0.6.1" + }, + "multidict": { + "hashes": [ + "sha256:018132dbd8688c7a69ad89c4a3f39ea2f9f33302ebe567a879da8f4ca73f0d0a", + "sha256:051012ccee979b2b06be928a6150d237aec75dd6bf2d1eeeb190baf2b05abc93", + "sha256:05c20b68e512166fddba59a918773ba002fdd77800cad9f55b59790030bab632", + "sha256:07b42215124aedecc6083f1ce6b7e5ec5b50047afa701f3442054373a6deb656", + "sha256:0e3c84e6c67eba89c2dbcee08504ba8644ab4284863452450520dad8f1e89b79", + "sha256:0e929169f9c090dae0646a011c8b058e5e5fb391466016b39d21745b48817fd7", + "sha256:1ab820665e67373de5802acae069a6a05567ae234ddb129f31d290fc3d1aa56d", + "sha256:25b4e5f22d3a37ddf3effc0710ba692cfc792c2b9edfb9c05aefe823256e84d5", + "sha256:2e68965192c4ea61fff1b81c14ff712fc7dc15d2bd120602e4a3494ea6584224", + "sha256:2f1a132f1c88724674271d636e6b7351477c27722f2ed789f719f9e3545a3d26", + "sha256:37e5438e1c78931df5d3c0c78ae049092877e5e9c02dd1ff5abb9cf27a5914ea", + "sha256:3a041b76d13706b7fff23b9fc83117c7b8fe8d5fe9e6be45eee72b9baa75f348", + "sha256:3a4f32116f8f72ecf2a29dabfb27b23ab7cdc0ba807e8459e59a93a9be9506f6", + "sha256:46c73e09ad374a6d876c599f2328161bcd95e280f84d2060cf57991dec5cfe76", + "sha256:46dd362c2f045095c920162e9307de5ffd0a1bfbba0a6e990b344366f55a30c1", + "sha256:4b186eb7d6ae7c06eb4392411189469e6a820da81447f46c0072a41c748ab73f", + "sha256:54fd1e83a184e19c598d5e70ba508196fd0bbdd676ce159feb412a4a6664f952", + "sha256:585fd452dd7782130d112f7ddf3473ffdd521414674c33876187e101b588738a", + "sha256:5cf3443199b83ed9e955f511b5b241fd3ae004e3cb81c58ec10f4fe47c7dce37", + "sha256:6a4d5ce640e37b0efcc8441caeea8f43a06addace2335bd11151bc02d2ee31f9", + "sha256:7df80d07818b385f3129180369079bd6934cf70469f99daaebfac89dca288359", + "sha256:806068d4f86cb06af37cd65821554f98240a19ce646d3cd24e1c33587f313eb8", + "sha256:830f57206cc96ed0ccf68304141fec9481a096c4d2e2831f311bde1c404401da", + "sha256:929006d3c2d923788ba153ad0de8ed2e5ed39fdbe8e7be21e2f22ed06c6783d3", + "sha256:9436dc58c123f07b230383083855593550c4d301d2532045a17ccf6eca505f6d", + "sha256:9dd6e9b1a913d096ac95d0399bd737e00f2af1e1594a787e00f7975778c8b2bf", + "sha256:ace010325c787c378afd7f7c1ac66b26313b3344628652eacd149bdd23c68841", + "sha256:b47a43177a5e65b771b80db71e7be76c0ba23cc8aa73eeeb089ed5219cdbe27d", + "sha256:b797515be8743b771aa868f83563f789bbd4b236659ba52243b735d80b29ed93", + "sha256:b7993704f1a4b204e71debe6095150d43b2ee6150fa4f44d6d966ec356a8d61f", + "sha256:d5c65bdf4484872c4af3150aeebe101ba560dcfb34488d9a8ff8dbcd21079647", + "sha256:d81eddcb12d608cc08081fa88d046c78afb1bf8107e6feab5d43503fea74a635", + "sha256:dc862056f76443a0db4509116c5cd480fe1b6a2d45512a653f9a855cc0517456", + "sha256:ecc771ab628ea281517e24fd2c52e8f31c41e66652d07599ad8818abaad38cda", + "sha256:f200755768dc19c6f4e2b672421e0ebb3dd54c38d5a4f262b872d8cfcc9e93b5", + "sha256:f21756997ad8ef815d8ef3d34edd98804ab5ea337feedcd62fb52d22bf531281", + "sha256:fc13a9524bc18b6fb6e0dbec3533ba0496bbed167c56d0aabefd965584557d80" + ], + "markers": "python_version >= '3.6'", + "version": "==5.1.0" + }, + "packaging": { + "hashes": [ + "sha256:24e0da08660a87484d1602c30bb4902d74816b6985b93de36926f5bc95741858", + "sha256:78598185a7008a470d64526a8059de9aaa449238f280fc9eb6b13ba6c4109093" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==20.8" + }, + "pluggy": { + "hashes": [ + "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", + "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.13.1" + }, + "py": { + "hashes": [ + "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3", + "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.10.0" + }, + "pycodestyle": { + "hashes": [ + "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367", + "sha256:c58a7d2815e0e8d7972bf1803331fb0152f867bd89adf8a01dfd55085434192e" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.6.0" + }, + "pyflakes": { + "hashes": [ + "sha256:0d94e0e05a19e57a99444b6ddcf9a6eb2e5c68d3ca1e98e90707af8152c90a92", + "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.2.0" + }, + "pyparsing": { + "hashes": [ + "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", + "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.4.7" + }, + "pytest": { + "hashes": [ + "sha256:1969f797a1a0dbd8ccf0fecc80262312729afea9c17f1d70ebf85c5e76c6f7c8", + "sha256:66e419b1899bc27346cb2c993e12c5e5e8daba9073c1fbce33b9807abc95c306" + ], + "markers": "python_version >= '3.6'", + "version": "==6.2.1" + }, + "pytest-cov": { + "hashes": [ + "sha256:45ec2d5182f89a81fc3eb29e3d1ed3113b9e9a873bcddb2a71faaab066110191", + "sha256:47bd0ce14056fdd79f93e1713f88fad7bdcc583dcd7783da86ef2f085a0bb88e" + ], + "index": "pypi", + "version": "==2.10.1" + }, + "pytest-django": { + "hashes": [ + "sha256:10e384e6b8912ded92db64c58be8139d9ae23fb8361e5fc139d8e4f8fc601bc2", + "sha256:26f02c16d36fd4c8672390deebe3413678d89f30720c16efb8b2a6bf63b9041f" + ], + "index": "pypi", + "version": "==4.1.0" + }, + "pytest-echo": { + "hashes": [ + "sha256:3bf6a065ca624a5915bc2a820505a44735a8aa11865a57d8214d4eac18960191" + ], + "index": "pypi", + "version": "==1.7.1" + }, + "pytest-pythonpath": { + "hashes": [ + "sha256:63fc546ace7d2c845c1ee289e8f7a6362c2b6bae497d10c716e58e253e801d62" + ], + "index": "pypi", + "version": "==0.7.3" + }, + "python-dateutil": { + "hashes": [ + "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c", + "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.8.1" + }, + "pytz": { + "hashes": [ + "sha256:16962c5fb8db4a8f63a26646d8886e9d769b6c511543557bc84e9569fb9a9cb4", + "sha256:180befebb1927b16f6b57101720075a984c019ac16b1b7575673bea42c6c3da5" + ], + "version": "==2020.5" + }, + "pyyaml": { + "hashes": [ + "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97", + "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76", + "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2", + "sha256:6034f55dab5fea9e53f436aa68fa3ace2634918e8b5994d82f3621c04ff5ed2e", + "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648", + "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf", + "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f", + "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2", + "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee", + "sha256:ad9c67312c84def58f3c04504727ca879cb0013b2517c85a9a253f0cb6380c0a", + "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d", + "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c", + "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a" + ], + "version": "==5.3.1" + }, + "six": { + "hashes": [ + "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a", + "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.14.0" + }, + "soupsieve": { + "hashes": [ + "sha256:4bb21a6ee4707bf43b61230e80740e71bfe56e55d1f1f50924b087bb2975c851", + "sha256:6dc52924dc0bc710a5d16794e6b3480b2c7c08b07729505feab2b2c16661ff6e" + ], + "markers": "python_version >= '3.0'", + "version": "==2.1" + }, + "sqlparse": { + "hashes": [ + "sha256:017cde379adbd6a1f15a61873f43e8274179378e95ef3fede90b5aa64d304ed0", + "sha256:0f91fd2e829c44362cbcfab3e9ae12e22badaa8a29ad5ff599f9ec109f0454e8" + ], + "markers": "python_version >= '3.5'", + "version": "==0.4.1" + }, + "text-unidecode": { + "hashes": [ + "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8", + "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93" + ], + "version": "==1.3" + }, + "toml": { + "hashes": [ + "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", + "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==0.10.2" + }, + "typing-extensions": { + "hashes": [ + "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918", + "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c", + "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f" + ], + "markers": "python_version < '3.8'", + "version": "==3.7.4.3" + }, + "vcrpy": { + "hashes": [ + "sha256:12c3fcdae7b88ecf11fc0d3e6d77586549d4575a2ceee18e82eee75c1f626162", + "sha256:57095bf22fc0a2d99ee9674cdafebed0f3ba763018582450706f7d3a74fff599" + ], + "index": "pypi", + "version": "==4.1.1" + }, + "waitress": { + "hashes": [ + "sha256:1bb436508a7487ac6cb097ae7a7fe5413aefca610550baf58f0940e51ecfb261", + "sha256:3d633e78149eb83b60a07dfabb35579c29aac2d24bb803c18b26fb2ab1a584db" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==1.4.4" + }, + "webob": { + "hashes": [ + "sha256:a3c89a8e9ba0aeb17382836cdb73c516d0ecf6630ec40ec28288f3ed459ce87b", + "sha256:aa3a917ed752ba3e0b242234b2a373f9c4e2a75d35291dcbe977649bd21fd108" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.8.6" + }, + "webtest": { + "hashes": [ + "sha256:44ddfe99b5eca4cf07675e7222c81dd624d22f9a26035d2b93dc8862dc1153c6", + "sha256:aac168b5b2b4f200af4e35867cf316712210e3d5db81c1cbdff38722647bb087" + ], + "version": "==2.0.35" + }, + "wrapt": { + "hashes": [ + "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7" + ], + "version": "==1.12.1" + }, + "yarl": { + "hashes": [ + "sha256:00d7ad91b6583602eb9c1d085a2cf281ada267e9a197e8b7cae487dadbfa293e", + "sha256:0355a701b3998dcd832d0dc47cc5dedf3874f966ac7f870e0f3a6788d802d434", + "sha256:15263c3b0b47968c1d90daa89f21fcc889bb4b1aac5555580d74565de6836366", + "sha256:2ce4c621d21326a4a5500c25031e102af589edb50c09b321049e388b3934eec3", + "sha256:31ede6e8c4329fb81c86706ba8f6bf661a924b53ba191b27aa5fcee5714d18ec", + "sha256:324ba3d3c6fee56e2e0b0d09bf5c73824b9f08234339d2b788af65e60040c959", + "sha256:329412812ecfc94a57cd37c9d547579510a9e83c516bc069470db5f75684629e", + "sha256:4736eaee5626db8d9cda9eb5282028cc834e2aeb194e0d8b50217d707e98bb5c", + "sha256:4953fb0b4fdb7e08b2f3b3be80a00d28c5c8a2056bb066169de00e6501b986b6", + "sha256:4c5bcfc3ed226bf6419f7a33982fb4b8ec2e45785a0561eb99274ebbf09fdd6a", + "sha256:547f7665ad50fa8563150ed079f8e805e63dd85def6674c97efd78eed6c224a6", + "sha256:5b883e458058f8d6099e4420f0cc2567989032b5f34b271c0827de9f1079a424", + "sha256:63f90b20ca654b3ecc7a8d62c03ffa46999595f0167d6450fa8383bab252987e", + "sha256:68dc568889b1c13f1e4745c96b931cc94fdd0defe92a72c2b8ce01091b22e35f", + "sha256:69ee97c71fee1f63d04c945f56d5d726483c4762845400a6795a3b75d56b6c50", + "sha256:6d6283d8e0631b617edf0fd726353cb76630b83a089a40933043894e7f6721e2", + "sha256:72a660bdd24497e3e84f5519e57a9ee9220b6f3ac4d45056961bf22838ce20cc", + "sha256:73494d5b71099ae8cb8754f1df131c11d433b387efab7b51849e7e1e851f07a4", + "sha256:7356644cbed76119d0b6bd32ffba704d30d747e0c217109d7979a7bc36c4d970", + "sha256:8a9066529240171b68893d60dca86a763eae2139dd42f42106b03cf4b426bf10", + "sha256:8aa3decd5e0e852dc68335abf5478a518b41bf2ab2f330fe44916399efedfae0", + "sha256:97b5bdc450d63c3ba30a127d018b866ea94e65655efaf889ebeabc20f7d12406", + "sha256:9ede61b0854e267fd565e7527e2f2eb3ef8858b301319be0604177690e1a3896", + "sha256:b2e9a456c121e26d13c29251f8267541bd75e6a1ccf9e859179701c36a078643", + "sha256:b5dfc9a40c198334f4f3f55880ecf910adebdcb2a0b9a9c23c9345faa9185721", + "sha256:bafb450deef6861815ed579c7a6113a879a6ef58aed4c3a4be54400ae8871478", + "sha256:c49ff66d479d38ab863c50f7bb27dee97c6627c5fe60697de15529da9c3de724", + "sha256:ce3beb46a72d9f2190f9e1027886bfc513702d748047b548b05dab7dfb584d2e", + "sha256:d26608cf178efb8faa5ff0f2d2e77c208f471c5a3709e577a7b3fd0445703ac8", + "sha256:d597767fcd2c3dc49d6eea360c458b65643d1e4dbed91361cf5e36e53c1f8c96", + "sha256:d5c32c82990e4ac4d8150fd7652b972216b204de4e83a122546dce571c1bdf25", + "sha256:d8d07d102f17b68966e2de0e07bfd6e139c7c02ef06d3a0f8d2f0f055e13bb76", + "sha256:e46fba844f4895b36f4c398c5af062a9808d1f26b2999c58909517384d5deda2", + "sha256:e6b5460dc5ad42ad2b36cca524491dfcaffbfd9c8df50508bddc354e787b8dc2", + "sha256:f040bcc6725c821a4c0665f3aa96a4d0805a7aaf2caf266d256b8ed71b9f041c", + "sha256:f0b059678fd549c66b89bed03efcabb009075bd131c248ecdf087bdb6faba24a", + "sha256:fcbb48a93e8699eae920f8d92f7160c03567b421bc17362a9ffbbd706a816f71" + ], + "markers": "python_version >= '3.6'", + "version": "==1.6.3" + }, + "zipp": { + "hashes": [ + "sha256:102c24ef8f171fd729d46599845e95c7ab894a4cf45f5de11a44cc7444fb1108", + "sha256:ed5eee1974372595f9e416cc7bbeeb12335201d8081ca8a0743c954d4446e5cb" + ], + "markers": "python_version >= '3.6'", + "version": "==3.4.0" + } + } +} diff --git a/docker-compose.yml b/docker-compose.yml index 4a80ed459..1bd1a6c7c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,29 +1,19 @@ version: '2' -services: - proxy: - image: traefik:v2.1 - command: --api.insecure=True --providers.docker - ports: - - "8083:80" - - "8080:8080" - container_name: datamart_proxy - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - datamart: - build: - context: . - dockerfile: ./docker/Dockerfile.dev - args: - BASE_IMAGE: "2.11-base" - container_name: datamart - environment: +x-datamart-defaults: &datamart_defaults + build: + context: . + dockerfile: ./Dockerfile + depends_on: + - db + - redis + volumes: + - "$PWD:/code" + environment: DEBUG: 1 DATABASE_URL: postgis://postgres:@db:5432/etools_datamart DATABASE_URL_ETOOLS: postgis://postgres:@db-etools:5432/etools DATABASE_URL_PRP: postgis://postgres:@db-prp:5432/prp AUTOCREATE_USERS: "admin,123" - BASE_IMAGE: "compose" CACHE_URL: "redis://redis:6379/1" CACHE_URL_LOCK: "redis://redis:6379/1" CACHE_URL_API: "redis://redis:6379/1" @@ -41,17 +31,38 @@ services: STATIC_ROOT: /code/src/etools_datamart/apps/web/static/ GEOS_LIBRARY_PATH: "/usr/lib/libgeos_c.so.1" GDAL_LIBRARY_PATH: "/usr/lib/libgdal.so.26" - command: bash -c "python /code/manage.py migrate && python /code/manage.py runserver 0.0.0.0:8080" + EXPORT_FILE_STORAGE: "django.core.files.storage.FileSystemStorage" + +services: + proxy: + image: traefik:v2.1 + command: --api.insecure=True --providers.docker + ports: + - "8083:80" + - "8080:8080" + container_name: datamart_proxy volumes: - - "$PWD:/code" + - /var/run/docker.sock:/var/run/docker.sock + + datamart: + container_name: datamart + << : *datamart_defaults + command: bash -c "python /code/manage.py init-setup --migrate && python /code/manage.py runserver 0.0.0.0:8080" labels: - "traefik.http.routers.datamart.rule=PathPrefix(`/`)" - traefik.http.routers.datamart.service=datamart - traefik.http.services.datamart.loadBalancer.server.port=8080 - traefik.enable=true - depends_on: - - db - - redis + + beat: + container_name: beat + << : *datamart_defaults + command: celery -A etools_datamart beat --loglevel=info --workdir=/code/src + + worker: + container_name: worker + << : *datamart_defaults + command: celery -A etools_datamart worker --loglevel=info --workdir=/code/src db: image: mdillon/postgis:9.6 diff --git a/docker/Dockerfile.alpine b/docker/Dockerfile.alpine deleted file mode 100644 index 7ea2f544b..000000000 --- a/docker/Dockerfile.alpine +++ /dev/null @@ -1,133 +0,0 @@ -ARG BASE_IMAGE -# -#FROM byrnedo/alpine-curl:0.1.7 as loader -# -#ARG BUILD_DATE -#ARG VERSION -#ARG DEVELOP -#ARG GITLAB_API_TOKEN -# -#ENV DEVELOP=${DEVELOP} -# -#RUN mkdir -p /code -#COPY . /code -#WORKDIR /code -#RUN set -o pipefail && \ -# if [ "${DEVELOP}" = "1" ]; then \ -# echo "${VERSION}-develop"; \ -# else \ -# echo "Download package: https://gitlab.com/api/v4/projects/12920288/repository/archive.tar.gz?sha=v${VERSION}" \ -# && curl --header "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" https://gitlab.com/api/v4/projects/12920288/repository/archive.tar.gz?sha=v${VERSION} | tar -xzf - --strip-components=1; \ -# fi - -FROM unicef/datamart:${BASE_IMAGE} - -COPY . /code - -RUN set -ex \ - ls -al /code \ - && rm /code/pyproject.toml \ - && sha1sum -c /CHECKSUM \ - && pip3 install . --no-deps \ - && rm -fr /code - -LABEL org.label.name="eTools Datamart" \ - org.label.maintainer="sapostolico@unicef.org" \ - org.label.description="" \ - org.label.url="https://datamart.unicef.io/" \ - org.label.vcs-url="https://github.com/unicef/etools-datamart" - - -ENV HOME=/root/ \ - PYTHONUNBUFFERED=1 \ - ALLOWED_HOSTS="*" \ - CACHE_URL="redis://127.0.0.1:6379/1" \ - CELERY_AUTOSCALE="5,1" \ - CELERY_BROKER_URL="redis://127.0.0.1:6379/2" \ - CELERY_EXTRA="" \ - CELERY_LOGLEVEL="ERROR" \ - CELERY_RESULT_BACKEND="redis://127.0.0.1:6379/3" \ - CSRF_COOKIE_SECURE=True \ - DATABASE_URL="postgres://postgres:@127.0.0.1:5432/etools_datamart" \ - DATABASE_URL_ETOOLS="postgis://postgres:@127.0.0.1:5432/etools" \ - DATABASE_URL_PRP="postgis://postgres:@127.0.0.1:5432/prp" \ - DEBUG=0 \ - DEVELOPMENT_MODE=0 \ - DJANGO_SETTINGS_MODULE=etools_datamart.config.settings \ - MEDIA_ROOT=/tmp/media \ - MEDIA_URL=/media/ \ - SECRET_KEY="secret" \ - SECURE_BROWSER_XSS_FILTER=True \ - SECURE_CONTENT_TYPE_NOSNIFF=True \ - SECURE_FRAME_DENY=True \ - SECURE_HSTS_INCLUDE_SUBDOMAINS=True \ - SECURE_HSTS_PRELOAD=True \ - SECURE_HSTS_SECONDS=1 \ - SECURE_SSL_REDIRECT=True \ - SENTRY_DSN="" \ - SESSION_COOKIE_HTTPONLY=True \ - SESSION_COOKIE_SECURE=True \ - STATIC_ROOT=/tmp/static \ - STATIC_URL=/dm-static/ - -ENV GEOS_LIBRARY_PATH="/usr/lib/libgeos_c.so.1" \ - GDAL_LIBRARY_PATH="/usr/lib/libgdal.so.26" \ - UWSGI_AUTO_PROCNAME=true \ - UWSGI_BUFFER_SIZE=32768 \ - UWSGI_DIE_ON_TERM=true \ - UWSGI_DISABLE_LOGGING=false \ - UWSGI_DISABLE_WRITE_EXCEPTION=true \ - UWSGI_ENABLE_THREADS=true \ - UWSGI_FREEBIND=true \ - UWSGI_HARAKIRI=180 \ - UWSGI_HTTP_SOCKET=0.0.0.0:8000 \ - UWSGI_HTTP_TIMEOUT=180 \ - UWSGI_IGNORE_SIGPIPE=true \ - UWSGI_IGNORE_WRITE_ERRORS=true \ - UWSGI_LAZY_APPS=true \ - UWSGI_LIMIT_POST=20971520 \ - UWSGI_LOG_X_FORWARDED_FOR=false \ - UWSGI_MASTER=true \ - UWSGI_MEMORY_REPORT=true \ - UWSGI_MODULE="etools_datamart.config.wsgi:application" \ - UWSGI_NEED_APP=true \ - UWSGI_POST_BUFFERING=65536 \ - UWSGI_PROCNAME_PREFIX_SPACED="[Datamart]" \ - UWSGI_PROTOCOL=http \ - UWSGI_RELOAD_ON_RSS=600 \ - UWSGI_SINGLE_INTERPRETER=true \ - UWSGI_THREADS=4 \ - UWSGI_THUNDER_LOCK=true \ - UWSGI_VACUUM=true \ - UWSGI_WORKERS=4 - - -EXPOSE 8000 -# -ADD docker/*.sh /usr/local/bin/ -#ADD docker/circus.conf /etc/ - -RUN addgroup --gid 1024 datamart \ - && adduser --disabled-password --ingroup datamart -S datamart - -ENTRYPOINT ["entrypoint.sh"] -WORKDIR /var/datamart - -CMD ["datamart"] -# -# -#RUN find /usr/local/lib/python3.8/site-packages/bitcaster -name *.pyc | xargs rm -f \ -# && python -O -m compileall -fqb /usr/local/lib/python3.8/site-packages/bitcaster \ -# && find /usr/local/lib/python3.8/site-packages/bitcaster -name *.py | xargs rm -f \ -# && pip uninstall -y pip poetry -# -#RUN addgroup --gid 1024 bitcaster \ -# && adduser --disabled-password --ingroup bitcaster -S bitcaster -# -#WORKDIR /var/bitcaster -# -#RUN django-admin collectstatic -# -#ENTRYPOINT ["docker-entrypoint.sh"] -# -#CMD ["bitcaster"] diff --git a/docker/Dockerfile.alpine.base b/docker/Dockerfile.alpine.base deleted file mode 100644 index f370e406c..000000000 --- a/docker/Dockerfile.alpine.base +++ /dev/null @@ -1,91 +0,0 @@ -FROM python:3.7.3-alpine - -ARG BUILD_DATE -ARG PIPENV_ARGS -ARG VERSION -ARG TEST - -ENV CPLUS_INCLUDE_PATH /usr/include/libxml2/ -ENV C_INCLUDE_PATH /usr/include/libxml2/ -ENV TEST ${TEST} - - -RUN apk add --no-cache --virtual .build-deps \ - --repository http://dl-cdn.alpinelinux.org/alpine/latest-stable/main \ - --repository http://dl-cdn.alpinelinux.org/alpine/latest-stable/testing \ - --repository http://dl-3.alpinelinux.org/alpine/latest-stable/community/ \ - gcc \ - g++ \ - gdal-dev \ - geos-dev \ - jpeg-dev \ - libc-dev \ - libffi-dev \ - libressl-dev \ - libxml2-dev \ - libxslt-dev \ - linux-headers \ - musl-dev \ - openldap-dev \ - postgresql-dev \ - python3-dev \ - xmlsec-dev \ - zeromq-dev - -RUN apk add --no-cache --virtual .run-deps \ - --repository http://dl-cdn.alpinelinux.org/alpine/edge/main \ - --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing \ - --repository http://dl-3.alpinelinux.org/alpine/edge/community/ \ - bash \ -# binutils \ - geos \ - gdal \ - gosu \ - libmagic \ -# libpq \ - libuuid \ - libxslt \ -# libzmq \ -# jpeg \ - mailcap \ - postgresql-client \ -# xmlsec \ - zlib - - -RUN mkdir -p /code -COPY poetry.lock pyproject.toml /code/ -WORKDIR /code - -RUN set -ex \ - ls -al /code \ - && pip install pip poetry==1.0 \ - && poetry config virtualenvs.create false \ - && poetry install --no-dev --no-interaction --no-ansi \ - && sha1sum poetry.lock > /CHECKSUM - -RUN export SITE_PACKAGES="/usr/local/lib/python3.7/site-packages"\ - && for TEST_DIR in waitress/tests/ zmq/tests/ tests/ \ - cssutils/tests/ isodate/tests/ circus/tests/ \ - crispy_forms/tests/ django_countries/tests/ \ - social_core/tests/ gitlab/tests \ - zope/interface/tests zope/interface/common/tests \ - psutil/tests social_core/tests \ - IPython/terminal/tests IPython/extensions/tests IPython/core/tests \ - IPython/testing/tests IPython/utils/tests IPython/lib/tests; \ - do \ - rm -fr ${SITE_PACKAGES:?}/${TEST_DIR}; \ - done \ - && for PACKAGE in django PIL; \ - do \ - find ${SITE_PACKAGES}/${PACKAGE} -type f -name '*.pyc' -delete; \ - python -O -m compileall -fqb ${SITE_PACKAGES}/${PACKAGE}; \ - find ${SITE_PACKAGES}/${PACKAGE}/ -type f -name '*.py' -delete ;\ - done - - -RUN apk del .build-deps \ - && rm -rf /var/cache/apk/* \ - && rm -fr /root/.cache/ \ - && rm -fr /var/datamart/.cache/ \ - && rm -fr /usr/include/ diff --git a/docker/Dockerfile.dev b/docker/Dockerfile.dev deleted file mode 100644 index b4f579115..000000000 --- a/docker/Dockerfile.dev +++ /dev/null @@ -1,15 +0,0 @@ -ARG BASE_IMAGE -FROM unicef/datamart:${BASE_IMAGE} - -Add poetry.lock . -Add pyproject.toml . - -RUN apk add bash -RUN mkdir /tmp/static - -ENV PYTHONUNBUFFERED 1 -ENV PYTHONPATH /code -ENV DJANGO_SETTINGS_MODULE etools_datamart.config.settings - -VOLUME "./:/code/" -WORKDIR /code/ diff --git a/docker/Makefile b/docker/Makefile deleted file mode 100644 index f0a36325d..000000000 --- a/docker/Makefile +++ /dev/null @@ -1,177 +0,0 @@ -# envs to set before use this script -DATABASE_URL?= -DATABASE_URL_ETOOLS?= -DEVELOP?=1 -DOCKER_PASS?= -DOCKER_USER?= -TARGET?=2.14.1a -PUSH_BASE?=1 -BASE?=$(shell echo "${TARGET}" | sed "s/\([0-9]*\)\.\([0-9]*\)\.\(.*\)/\1.\2/g" ) -#BASE?=$(shell echo "${TARGET}" | sed "s/\([0-9]*\)\.\([0-9]*\)\.\(.*\)/\1.\2/g" | echo "`xargs`xx" ) -# below vars are used internally -# BUILD_OPTIONS?=--squash -BUILD_OPTIONS= -CMD?=datamart -CONTAINER_NAME?=datamart-${TARGET} -ORGANIZATION=unicef -IMAGE_NAME=datamart -DOCKER_IMAGE_NAME?=${ORGANIZATION}/${IMAGE_NAME} -DOCKER_IMAGE?=${DOCKER_IMAGE_NAME}:${TARGET} -DOCKERFILE?=Dockerfile.alpine -RUN_OPTIONS?= -PIPENV_ARGS?= -PORTS= -ABSOLUTE_BASE_URL?="http://192.168.66.66:8000" - -help: - @echo "dev build dev image (based on local code)" - @echo "build build production image (based on tag ${TARGET})" - @echo "release release tag ${TARGET} on docker hub" - @echo "run run ${DOCKER_IMAGE} locally" - -build-base: - cd .. && docker build \ - ${BUILD_OPTIONS} \ - --no-cache \ - -t ${DOCKER_IMAGE_NAME}:${BASE}-base \ - -f docker/${DOCKERFILE}.base . - @echo ${DOCKER_PASS} | docker login -u ${DOCKER_USER} --password-stdin - [[ "${PUSH_BASE}" = "1" ]] && docker push ${DOCKER_IMAGE_NAME}:${BASE}-base || echo "" - - -.build: - cd .. && ./manage.py makemigrations data --check --dry-run - cd .. && docker build \ - ${BUILD_OPTIONS} \ - --build-arg BASE_IMAGE=${BASE}-base \ - --build-arg DEVELOP=${DEVELOP} \ - --build-arg VERSION=${TARGET} \ - -t ${DOCKER_IMAGE} \ - -f docker/${DOCKERFILE} . - docker tag ${DOCKER_IMAGE_NAME}:${TARGET} ${DOCKER_IMAGE_NAME}:dev - docker images | grep ${DOCKER_IMAGE_NAME} - -build-test: - TARGET=dev $(MAKE) .build test - -build: - $(MAKE) .build - - -.run: - cd .. && docker run \ - --rm \ - -e ABSOLUTE_BASE_URL=${ABSOLUTE_BASE_URL} \ - -e CACHE_URL=redis://192.168.66.66:6379/1 \ - -e CACHE_URL_API=redis://192.168.66.66:6379/2 \ - -e CACHE_URL_LOCK=redis://192.168.66.66:6379/3 \ - -e CACHE_URL_TEMPLATE=redis://192.168.66.66:6379/4 \ - -e CELERY_BROKER_URL=redis://192.168.66.66:6379/2 \ - -e CELERY_RESULT_BACKEND=redis://192.168.66.66:6379/3 \ - -e EXPORT_FILE_STORAGE_KWARGS="host=192.168.66.66" \ - -e CSRF_COOKIE_SECURE=false \ - -e DATABASE_URL=${DATABASE_URL} \ - -e DATABASE_URL_ETOOLS=${DATABASE_URL_ETOOLS} \ - -e DATABASE_URL_PRP=${DATABASE_URL_PRP} \ - -e DEBUG=false \ - -e DJANGO_SETTINGS_MODULE=etools_datamart.config.settings \ - -e SECURE_BROWSER_XSS_FILTER=0 \ - -e SECURE_CONTENT_TYPE_NOSNIFF=0 \ - -e SECURE_FRAME_DENY=0 \ - -e SECURE_HSTS_SECONDS=0 \ - -e SECURE_HSTS_PRELOAD=false \ - -e SECURE_SSL_REDIRECT=false \ - -e SESSION_COOKIE_HTTPONLY=false \ - -e SESSION_COOKIE_SECURE=false \ - -e STATIC_ROOT=/var/datamart/static/ \ - -e DEVELOPMENT_MODE=0 \ - -e X_FRAME_OPTIONS="SAMEORIGIN" \ - ${RUN_OPTIONS} \ - ${DOCKER_IMAGE} \ - ${CMD} - -local: - RUN_OPTIONS="-v ${PWD}/..:/code -e PYTHONPATH=/code -it" \ - CMD="/bin/bash" \ - $(MAKE) .run - -release: - @echo ${DOCKER_PASS} | docker login -u ${DOCKER_USER} --password-stdin - docker tag ${DOCKER_IMAGE_NAME}:${TARGET} ${DOCKER_IMAGE_NAME}:latest - docker push ${DOCKER_IMAGE_NAME}:${TARGET} - -deploy: - lazo rancher upgrade --no-check datamart:datamart ${DOCKER_IMAGE_NAME}:${TARGET} - lazo rancher upgrade --no-check datamart:celery ${DOCKER_IMAGE_NAME}:${TARGET} - lazo rancher upgrade --no-check datamart:beat ${DOCKER_IMAGE_NAME}:${TARGET} - lazo rancher upgrade --no-check datamart:datamart-admin ${DOCKER_IMAGE_NAME}:${TARGET} - curl -X POST -H 'Content-type: application/json' \ - --data '{"text":"Datamart ${TARGET} released in dev"}' \ - https://hooks.slack.com/services/${SLACK_BOT_TOKEN} - -staging: - echo "=" - -production: - lazo rancher \ - -b https://elgaucho.unicef.io/v3 \ - --auth ${RANCHER_GAUCHO_AUTH} - upgrade \ - -c rke-cluster-etdw \ - -p datamart-prod \ - --check-image \ - datamart-prod:datamart ${DOCKER_IMAGE_NAME}:${TARGET} - - curl -X POST -H 'Content-type: application/json' \ - --data '{"text":"Datamart ${TARGET} released in production"}' \ - https://hooks.slack.com/services/${SLACK_BOT_TOKEN} - -bump: - cd .. && bumpversion --commit --tag --config-file=.bumpversion.cfg num - -run: - RUN_OPTIONS="-p 8000:8000" \ - ABSOLUTE_BASE_URL=${ABSOLUTE_BASE_URL} \ - $(MAKE) .run - -#stack: -# RUN_OPTIONS="-p 8000:8000" \ -# CMD=stack \ -# ABSOLUTE_BASE_URL=${ABSOLUTE_BASE_URL} \ -# $(MAKE) .run - -workers: - CONTAINER_NAME=datamart-workers \ - ABSOLUTE_BASE_URL=${ABSOLUTE_BASE_URL} \ - CMD=worker $(MAKE) .run - -beat: - CONTAINER_NAME=datamart-beat \ - ABSOLUTE_BASE_URL=${ABSOLUTE_BASE_URL} \ - CMD=beat $(MAKE) .run - - -test: - RUN_OPTIONS="-e DEBUG=0 \ - -e X_FRAME_OPTIONS=DENY \ - -e SESSION_COOKIE_SECURE=1 \ - -e CSRF_COOKIE_SECURE=1 \ - -e SECURE_HSTS_PRELOAD=1 \ - -e SECURE_SSL_REDIRECT=1" \ - CMD='bash -c "touch /var/datamart/.touch && django-admin check --deploy "' \ - $(MAKE) .run - -scratch: - RUN_OPTIONS=-it CMD='/bin/bash' $(MAKE) .run - -shell: - RUN_OPTIONS="-p 8000:8000 -it" \ - ABSOLUTE_BASE_URL=${ABSOLUTE_BASE_URL} \ - CMD='/bin/bash' \ - $(MAKE) .run -# docker exec -it ${CONTAINER_NAME} /bin/bash -# RUN_OPTIONS=-it CMD='/bin/bash' $(MAKE) .run - -docker-remove: - docker-remove.sh ${IMAGE_NAME} -o ${ORGANIZATION} - diff --git a/docker/README.md b/docker/README.md deleted file mode 100644 index 3fa622e17..000000000 --- a/docker/README.md +++ /dev/null @@ -1,17 +0,0 @@ -eTools DataMart Docker images -============================= - -[![](https://images.microbadger.com/badges/version/unicef/datamart.svg)](https://microbadger.com/images/unicef/datamart) - -To build docker image simply cd in `docker` directory and run - - make build - -default settings are for production ready environment, check `run` target in -the `Makefile` to see how to run the container with debug/less secure configuration - -Image provides following services: - - - datamart - - celery workers - - celery beat diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh deleted file mode 100755 index b3eeae995..000000000 --- a/docker/entrypoint.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash -e -mkdir -p /var/datamart/static -mkdir -p /var/datamart/log -mkdir -p /var/datamart/conf -mkdir -p /var/datamart/run -mkdir -p $MEDIA_ROOT - -chown datamart:datamart -R /var/datamart/ -chown datamart:datamart -R $MEDIA_ROOT - - -if [[ "$*" == "worker" ]];then - django-admin db-isready --wait --sleep 5 --timeout 60 - django-admin db-isready --wait --sleep 5 --timeout 300 --connection etools - exec gosu datamart celery worker \ - -A etools_datamart \ - --events \ - --max-tasks-per-child=1 \ - --loglevel=${CELERY_LOGLEVEL} \ - --autoscale=${CELERY_AUTOSCALE} \ - --pidfile run/celery.pid \ - $CELERY_EXTRA - -elif [[ "$*" == "beat" ]];then - exec gosu datamart celery beat -A etools_datamart.celery \ - $CELERY_EXTRA \ - --loglevel=${CELERY_LOGLEVEL} \ - --pidfile run/celerybeat.pid -elif [[ "$*" == "datamart" ]];then - rm -f /var/datamart/run/* - - django-admin diffsettings --output unified -# django-admin makemigrations --check --dry-run - - django-admin db-isready --wait --timeout 60 - django-admin check --deploy - django-admin init-setup --all --verbosity 2 - django-admin collectstatic --noinput - django-admin db-isready --wait --timeout 300 --connection etools - echo "uwsgi --static-map ${STATIC_URL}=${STATIC_ROOT}" - exec gosu datamart uwsgi \ - --static-map ${STATIC_URL}=${STATIC_ROOT} \ - --static-map ${MEDIA_URL}=${MEDIA_ROOT} -else - exec "$@" -fi diff --git a/manage.py b/manage.py index f8cdb5b9a..73abd2093 100755 --- a/manage.py +++ b/manage.py @@ -29,7 +29,8 @@ execute_from_command_line(args) except Exception: if debug_on_error: - import pdb, traceback # noqa + import pdb # noqa + import traceback __, __, tb = sys.exc_info() traceback.print_exc() diff --git a/poetry.lock b/poetry.lock deleted file mode 100644 index dee9fcaf5..000000000 --- a/poetry.lock +++ /dev/null @@ -1,3308 +0,0 @@ -[[package]] -category = "main" -description = "Django mixin to easily add urls to any ModelAdmin" -name = "admin-extra-urls" -optional = false -python-versions = "*" -version = "2.2.0" - -[package.extras] -dev = ["autopep8", "check-manifest", "flake8", "pep8", "readme", "wheel", "coverage", "factory-boy", "django-webtest", "pdbpp", "pyquery", "pytest", "pytest-cov", "pytest-django", "pytest-echo", "pytest-pythonpath", "tox (>=2.3)"] -tests = ["coverage", "factory-boy", "django-webtest", "pdbpp", "pyquery", "pytest", "pytest-cov", "pytest-django", "pytest-echo", "pytest-pythonpath", "tox (>=2.3)", "wheel"] - -[[package]] -category = "main" -description = "Low-level AMQP client for Python (fork of amqplib)." -name = "amqp" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.5.2" - -[package.dependencies] -vine = ">=1.1.3,<5.0.0a1" - -[[package]] -category = "main" -description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -name = "appdirs" -optional = false -python-versions = "*" -version = "1.4.3" - -[[package]] -category = "dev" -description = "Disable App Nap on OS X 10.9" -marker = "python_version >= \"3.4\" and sys_platform == \"darwin\"" -name = "appnope" -optional = false -python-versions = "*" -version = "0.1.0" - -[[package]] -category = "main" -description = "Fast ASN.1 parser and serializer with definitions for private keys, public keys, certificates, CRL, OCSP, CMS, PKCS#3, PKCS#7, PKCS#8, PKCS#12, PKCS#5, X.509 and TSP" -name = "asn1crypto" -optional = false -python-versions = "*" -version = "1.3.0" - -[[package]] -category = "dev" -description = "A few extensions to pyyaml." -name = "aspy.yaml" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.3.0" - -[package.dependencies] -pyyaml = "*" - -[[package]] -category = "dev" -description = "Atomic file writes." -name = "atomicwrites" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.3.0" - -[[package]] -category = "main" -description = "Classes Without Boilerplate" -name = "attrs" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "19.3.0" - -[package.extras] -azure-pipelines = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "pytest-azurepipelines"] -dev = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "pre-commit"] -docs = ["sphinx", "zope.interface"] -tests = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] - -[[package]] -category = "main" -description = "Microsoft Azure Client Library for Python (Common)" -name = "azure-common" -optional = false -python-versions = "*" -version = "1.1.25" - -[[package]] -category = "main" -description = "Microsoft Azure Storage Blob Client Library for Python" -name = "azure-storage-blob" -optional = false -python-versions = "*" -version = "2.1.0" - -[package.dependencies] -azure-common = ">=1.1.5" -azure-storage-common = ">=2.1,<3.0" - -[[package]] -category = "main" -description = "Microsoft Azure Storage Common Client Library for Python" -name = "azure-storage-common" -optional = false -python-versions = "*" -version = "2.1.0" - -[package.dependencies] -azure-common = ">=1.1.5" -cryptography = "*" -python-dateutil = "*" -requests = "*" - -[[package]] -category = "dev" -description = "Specifications for callback functions passed in to an API" -marker = "python_version >= \"3.4\"" -name = "backcall" -optional = false -python-versions = "*" -version = "0.1.0" - -[[package]] -category = "dev" -description = "Screen-scraping library" -name = "beautifulsoup4" -optional = false -python-versions = "*" -version = "4.8.2" - -[package.dependencies] -soupsieve = ">=1.2" - -[package.extras] -html5lib = ["html5lib"] -lxml = ["lxml"] - -[[package]] -category = "main" -description = "Python multiprocessing fork with improvements and bugfixes" -name = "billiard" -optional = false -python-versions = "*" -version = "3.6.3.0" - -[[package]] -category = "dev" -description = "Version-bump your software with a single command!" -name = "bump2version" -optional = false -python-versions = ">=3.5" -version = "1.0.0" - -[[package]] -category = "main" -description = "Distributed Task Queue." -name = "celery" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*," -version = "4.4.2" - -[package.dependencies] -billiard = ">=3.6.3.0,<4.0" -kombu = ">=4.6.8,<4.7" -pytz = ">0.0-dev" -vine = "1.3.0" - -[package.extras] -arangodb = ["pyArango (>=1.3.2)"] -auth = ["cryptography"] -azureblockblob = ["azure-storage (0.36.0)", "azure-common (1.1.5)", "azure-storage-common (1.1.0)"] -brotli = ["brotli (>=1.0.0)", "brotlipy (>=0.7.0)"] -cassandra = ["cassandra-driver"] -consul = ["python-consul"] -cosmosdbsql = ["pydocumentdb (2.3.2)"] -couchbase = ["couchbase", "couchbase-cffi"] -couchdb = ["pycouchdb"] -django = ["Django (>=1.11)"] -dynamodb = ["boto3 (>=1.9.178)"] -elasticsearch = ["elasticsearch"] -eventlet = ["eventlet (>=0.24.1)"] -gevent = ["gevent"] -librabbitmq = ["librabbitmq (>=1.5.0)"] -lzma = ["backports.lzma"] -memcache = ["pylibmc"] -mongodb = ["pymongo (>=3.3.0)"] -msgpack = ["msgpack"] -pymemcache = ["python-memcached"] -pyro = ["pyro4"] -redis = ["redis (>=3.2.0)"] -riak = ["riak (>=2.0)"] -s3 = ["boto3 (>=1.9.125)"] -slmq = ["softlayer-messaging (>=1.0.3)"] -solar = ["ephem"] -sqlalchemy = ["sqlalchemy"] -sqs = ["boto3 (>=1.9.125)", "pycurl (7.43.0.2)"] -tblib = ["tblib (>=1.3.0)", "tblib (>=1.5.0)"] -yaml = ["PyYAML (>=3.10)"] -zookeeper = ["kazoo (>=1.3.1)"] -zstd = ["zstandard"] - -[[package]] -category = "main" -description = "Python package for providing Mozilla's CA Bundle." -name = "certifi" -optional = false -python-versions = "*" -version = "2019.11.28" - -[[package]] -category = "main" -description = "Foreign Function Interface for Python calling C code." -name = "cffi" -optional = false -python-versions = "*" -version = "1.14.0" - -[package.dependencies] -pycparser = "*" - -[[package]] -category = "dev" -description = "Validate configuration and produce human readable error messages." -name = "cfgv" -optional = false -python-versions = ">=3.6.1" -version = "3.1.0" - -[[package]] -category = "main" -description = "Universal encoding detector for Python 2 and 3" -name = "chardet" -optional = false -python-versions = "*" -version = "3.0.4" - -[[package]] -category = "dev" -description = "Check MANIFEST.in in a Python source package for completeness" -name = "check-manifest" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "0.41" - -[package.dependencies] -pep517 = "*" -toml = "*" - -[package.extras] -test = ["mock"] - -[[package]] -category = "main" -description = "Circus is a program that will let you run and watch multiple processes and sockets." -name = "circus" -optional = false -python-versions = "*" -version = "0.16.1" - -[package.dependencies] -psutil = "*" -pyzmq = ">=17.0" -six = "*" -tornado = ">=3.0,<5.0" - -[[package]] -category = "dev" -description = "Cross-platform colored terminal text." -marker = "sys_platform == \"win32\" and python_version != \"3.4\" or platform_system == \"Windows\" or python_version >= \"3.4\" and sys_platform == \"win32\"" -name = "colorama" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "0.4.3" - -[[package]] -category = "main" -description = "Python client library for Core API." -name = "coreapi" -optional = false -python-versions = "*" -version = "2.3.3" - -[package.dependencies] -coreschema = "*" -itypes = "*" -requests = "*" -uritemplate = "*" - -[[package]] -category = "main" -description = "Core Schema." -name = "coreschema" -optional = false -python-versions = "*" -version = "0.0.4" - -[package.dependencies] -jinja2 = "*" - -[[package]] -category = "dev" -description = "Code coverage measurement for Python" -name = "coverage" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" -version = "5.0.4" - -[package.extras] -toml = ["toml"] - -[[package]] -category = "main" -description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." -name = "cryptography" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" -version = "2.7" - -[package.dependencies] -asn1crypto = ">=0.21.0" -cffi = ">=1.8,<1.11.3 || >1.11.3" -six = ">=1.4.1" - -[package.extras] -docs = ["sphinx (>=1.6.5,<1.8.0 || >1.8.0)", "sphinx-rtd-theme"] -docstest = ["doc8", "pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] -idna = ["idna (>=2.1)"] -pep8test = ["flake8", "flake8-import-order", "pep8-naming"] -test = ["pytest (>=3.6.0,<3.9.0 || >3.9.0,<3.9.1 || >3.9.1,<3.9.2 || >3.9.2)", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,<3.79.2 || >3.79.2)"] - -[[package]] -category = "dev" -description = "Decorators for Humans" -marker = "python_version >= \"3.4\"" -name = "decorator" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*" -version = "4.4.2" - -[[package]] -category = "main" -description = "XML bomb protection for Python stdlib modules" -name = "defusedxml" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "0.6.0" - -[[package]] -category = "dev" -description = "Distribution utilities" -name = "distlib" -optional = false -python-versions = "*" -version = "0.3.0" - -[[package]] -category = "main" -description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design." -name = "django" -optional = false -python-versions = ">=3.5" -version = "2.2.11" - -[package.dependencies] -pytz = "*" -sqlparse = "*" - -[package.extras] -argon2 = ["argon2-cffi (>=16.1.0)"] -bcrypt = ["bcrypt"] - -[[package]] -category = "main" -description = "Collections of useful actions to use with django.contrib.admin.ModelAdmin" -name = "django-adminactions" -optional = false -python-versions = "*" -version = "1.8.1" - -[package.dependencies] -pytz = "*" -six = "*" -unicodecsv = ">=0.9.4" -xlrd = ">=0.9.2" -xlwt = "*" - -[package.extras] -dev = ["isort", "pdbpp", "virtualenv", "wheel", "check-manifest", "docutils", "check-manifest", "django-dynamic-fixture", "django-webtest", "flake8", "mock (>=1.0.1)", "modernize", "pillow", "pytest", "pytest-cache", "pytest-cov", "pytest-django", "pytest-echo", "pytest-pythonpath", "readme", "selenium (>=2.42.0)", "setuptools (>=15.0)", "tox"] -test = ["six", "pytz", "unicodecsv (>=0.9.4)", "xlrd (>=0.9.2)", "xlwt", "check-manifest", "django-dynamic-fixture", "django-webtest", "flake8", "mock (>=1.0.1)", "modernize", "pillow", "pytest", "pytest-cache", "pytest-cov", "pytest-django", "pytest-echo", "pytest-pythonpath", "readme", "selenium (>=2.42.0)", "setuptools (>=15.0)", "tox"] - -[[package]] -category = "main" -description = "Extra filters for django admin site" -name = "django-adminfilters" -optional = false -python-versions = "*" -version = "1.1.0" - -[package.extras] -dev = ["check-manifest", "coverage", "pytest", "pytest-cov", "pytest-django", "pytest-echo", "pytest-pythonpath", "tox", "pdbpp", "django", "autopep8", "check-manifest"] -test = ["check-manifest", "coverage", "pytest", "pytest-cov", "pytest-django", "pytest-echo", "pytest-pythonpath", "tox"] - -[[package]] -category = "main" -description = "A helper class for handling configuration defaults of packaged apps gracefully." -name = "django-appconf" -optional = false -python-versions = "*" -version = "1.0.4" - -[package.dependencies] -django = "*" - -[[package]] -category = "main" -description = "Reusable, generic mixins for Django" -name = "django-braces" -optional = false -python-versions = "*" -version = "1.14.0" - -[package.dependencies] -Django = ">=1.11.0" -six = "*" - -[[package]] -category = "main" -description = "Database-backed Periodic Tasks." -name = "django-celery-beat" -optional = false -python-versions = "*" -version = "2.0.0" - -[package.dependencies] -Django = ">=1.11.17" -celery = "*" -django-timezone-field = ">=4.0,<5.0" -python-crontab = ">=2.3.4" - -[[package]] -category = "main" -description = "An async Django email backend using celery" -name = "django-celery-email" -optional = false -python-versions = "*" -version = "3.0.0" - -[package.dependencies] -celery = ">=4.0" -django = ">=2.2" -django-appconf = "*" - -[[package]] -category = "main" -description = "Optimistic lock implementation for Django. Prevents users from doing concurrent editing." -name = "django-concurrency" -optional = false -python-versions = "*" -version = "2.1.1" - -[[package]] -category = "main" -description = "Django live settings with pluggable backends, including Redis." -name = "django-constance" -optional = false -python-versions = "*" -version = "2.6.0" - -[package.extras] -database = ["django-picklefield"] -redis = ["redis"] - -[[package]] -category = "main" -description = "django-cors-headers is a Django application for handling the server headers required for Cross-Origin Resource Sharing (CORS)." -name = "django-cors-headers" -optional = false -python-versions = ">=3.5" -version = "3.2.1" - -[package.dependencies] -Django = ">=1.11" - -[[package]] -category = "main" -description = "Provides a country field for Django models." -name = "django-countries" -optional = false -python-versions = "*" -version = "6.1.2" - -[package.extras] -dev = ["tox", "black", "django", "pytest", "pytest-django", "djangorestframework", "graphene-django"] -maintainer = ["transifex-client", "zest.releaser", "django"] -test = ["pytest", "pytest-django", "pytest-cov", "graphene-django"] - -[[package]] -category = "main" -description = "Django custom field to implement the strategy pattern" -name = "django-crashlog" -optional = false -python-versions = "*" -version = "1.0.0" - -[package.dependencies] -admin-extra-urls = ">=0.4" - -[package.extras] -dev = ["flake8", "django-webtest", "pytest-cache", "pytest-cov", "pytest-django", "pytest-echo", "pytest (>=2.8)", "psycopg2", "pdbpp"] -tests = ["flake8", "django-webtest", "pytest-cache", "pytest-cov", "pytest-django", "pytest-echo", "pytest (>=2.8)", "psycopg2", "pdbpp"] - -[[package]] -category = "main" -description = "Best way to have Django DRY forms" -name = "django-crispy-forms" -optional = false -python-versions = "*" -version = "1.9.0" - -[[package]] -category = "main" -description = "Template loader for templates stored in the database" -name = "django-dbtemplates" -optional = false -python-versions = "*" -version = "3.0" - -[package.dependencies] -django-appconf = ">=0.4" - -[[package]] -category = "main" -description = "This package allows deprecating model fields and allows removing them in a backwards compatible manner." -name = "django-deprecate-fields" -optional = false -python-versions = "*" -version = "0.0.4" - -[package.dependencies] -Django = ">=1.11" - -[[package]] -category = "main" -description = "Django-environ allows you to utilize 12factor inspired environment variables to configure your Django application." -name = "django-environ" -optional = false -python-versions = "*" -version = "0.4.5" - -[[package]] -category = "dev" -description = "Extensions for Django" -name = "django-extensions" -optional = false -python-versions = "*" -version = "2.2.9" - -[package.dependencies] -six = ">=1.2" - -[[package]] -category = "main" -description = "Django-filter is a reusable Django application for allowing users to filter querysets dynamically." -name = "django-filter" -optional = false -python-versions = ">=3.4" -version = "2.2.0" - -[package.dependencies] -Django = ">=1.11" - -[[package]] -category = "main" -description = "Django app to allow superusers to impersonate other users." -name = "django-impersonate" -optional = false -python-versions = "*" -version = "1.5" - -[[package]] -category = "main" -description = "script tag with additional attributes for django.forms.Media" -name = "django-js-asset" -optional = false -python-versions = "*" -version = "1.2.2" - -[[package]] -category = "main" -description = "Django JSON Editor" -name = "django-jsoneditor" -optional = false -python-versions = "*" -version = "0.1.6" - -[package.dependencies] -packaging = "*" - -[[package]] -category = "main" -description = "Detect backward incompatible migrations for your django project" -name = "django-migration-linter" -optional = false -python-versions = "*" -version = "2.1.0" - -[package.dependencies] -appdirs = "1.4.3" -django = ">=1.11" -six = "1.14.0" - -[package.extras] -test = ["tox (3.14.3)", "mysqlclient (1.4.6)", "psycopg2-binary (2.8.4)", "django-add-default-value (0.3.2)"] - -[[package]] -category = "main" -description = "Django model mixins and utilities" -name = "django-model-utils" -optional = false -python-versions = "*" -version = "4.0.0" - -[package.dependencies] -Django = ">=2.0.1" - -[[package]] -category = "main" -description = "Utilities for implementing Modified Preorder Tree Traversal with your Django Models and working with trees of Model instances." -name = "django-mptt" -optional = false -python-versions = ">=3.5" -version = "0.11.0" - -[package.dependencies] -Django = ">=1.11" -django-js-asset = "*" - -[[package]] -category = "main" -description = "OAuth2 Provider for Django" -name = "django-oauth-toolkit" -optional = false -python-versions = "*" -version = "1.3.2" - -[package.dependencies] -django = ">=2.1" -oauthlib = ">=3.0.1" -requests = ">=2.13.0" - -[[package]] -category = "main" -description = "Pickled object field for Django" -name = "django-picklefield" -optional = false -python-versions = "*" -version = "2.1.1" - -[package.dependencies] -Django = ">=1.11" - -[package.extras] -tests = ["tox"] - -[[package]] -category = "main" -description = "A Django app to monitor and send mail asynchronously, complete with template support." -name = "django-post-office" -optional = false -python-versions = "*" -version = "3.3.1" - -[package.dependencies] -django = ">=2.2" -jsonfield = ">=3.0" - -[package.extras] -test = ["tox (>=2.3)"] - -[[package]] -category = "main" -description = "Full featured redis cache backend for Django." -name = "django-redis" -optional = false -python-versions = ">=3.5" -version = "4.11.0" - -[package.dependencies] -Django = ">=1.11" -redis = ">=2.10.0" - -[[package]] -category = "main" -description = "Fields and utilities to work with regular expression in Django" -name = "django-regex" -optional = false -python-versions = "*" -version = "0.4.1" - -[package.extras] -dev = ["admin-extra-urls (1.7)", "alabaster (0.7.10)", "apipkg (1.4)", "attrs (17.4.0)", "babel (2.5.3)", "beautifulsoup4 (4.6.0)", "certifi (2018.1.18)", "chardet (3.0.4)", "check-manifest (0.36)", "click (6.7)", "coverage (4.4.2)", "devpi-builder (3.0.1)", "devpi-client (4.0.0)", "devpi-common (3.2.1)", "devpi-plumber (0.4.3)", "django-webtest (1.9.2)", "docutils (0.14)", "execnet (1.5.0)", "factory-boy (2.9.2)", "faker (0.8.10)", "fancycompleter (0.8)", "first (2.0.1)", "flake8 (3.5.0)", "idna (2.6)", "imagesize (0.7.1)", "isort (4.2.15)", "jinja2 (2.10)", "junit-xml (1.8)", "markupsafe (1.0)", "mccabe (0.6.1)", "pdbpp (0.9.2)", "pep8 (1.7.1)", "pip-tools (1.11.0)", "pkginfo (1.4.1)", "pluggy (0.6.0)", "py (1.5.2)", "pycodestyle (2.3.1)", "pyflakes (1.6.0)", "pygments (2.2.0)", "pytest-cache (1.0)", "pytest-cov (2.5.1)", "pytest-django (3.1.2)", "pytest-echo (1.5.1)", "pytest-isort (0.1.0)", "pytest-pep8 (1.0.6)", "pytest-pythonpath (0.7.1)", "pytest (3.3.2)", "python-dateutil (2.6.1)", "pytz (2017.3)", "requests (2.18.4)", "six (1.11.0)", "snowballstemmer (1.2.1)", "sphinx (1.6.6)", "sphinxcontrib-websupport (1.0.1)", "text-unidecode (1.1)", "tox (2.9.1)", "twitter.common.contextutil (0.3.9)", "twitter.common.dirutil (0.3.9)", "twitter.common.lang (0.3.9)", "urllib3 (1.22)", "virtualenv (15.1.0)", "waitress (1.1.0)", "webob (1.7.4)", "webtest (2.0.29)", "wheel (0.30.0)", "wmctrl (0.3)"] -extra = ["admin-extra-urls"] -test = ["admin-extra-urls (1.7)", "apipkg (1.4)", "attrs (17.4.0)", "beautifulsoup4 (4.6.0)", "coverage (4.4.2)", "django-webtest (1.9.2)", "execnet (1.5.0)", "factory-boy (2.9.2)", "faker (0.8.10)", "fancycompleter (0.8)", "isort (4.2.15)", "pdbpp (0.9.2)", "pep8 (1.7.1)", "pluggy (0.6.0)", "py (1.5.2)", "pygments (2.2.0)", "pytest-cache (1.0)", "pytest-cov (2.5.1)", "pytest-django (3.1.2)", "pytest-echo (1.5.1)", "pytest-isort (0.1.0)", "pytest-pep8 (1.0.6)", "pytest-pythonpath (0.7.1)", "pytest (3.3.2)", "python-dateutil (2.6.1)", "six (1.11.0)", "text-unidecode (1.1)", "tox (2.9.1)", "virtualenv (15.1.0)", "waitress (1.1.0)", "webob (1.7.4)", "webtest (2.0.29)", "wmctrl (0.3)"] -tests = ["admin-extra-urls (1.7)", "apipkg (1.4)", "attrs (17.4.0)", "beautifulsoup4 (4.6.0)", "coverage (4.4.2)", "django-webtest (1.9.2)", "execnet (1.5.0)", "factory-boy (2.9.2)", "faker (0.8.10)", "fancycompleter (0.8)", "isort (4.2.15)", "pdbpp (0.9.2)", "pep8 (1.7.1)", "pluggy (0.6.0)", "py (1.5.2)", "pygments (2.2.0)", "pytest-cache (1.0)", "pytest-cov (2.5.1)", "pytest-django (3.1.2)", "pytest-echo (1.5.1)", "pytest-isort (0.1.0)", "pytest-pep8 (1.0.6)", "pytest-pythonpath (0.7.1)", "pytest (3.3.2)", "python-dateutil (2.6.1)", "six (1.11.0)", "text-unidecode (1.1)", "tox (2.9.1)", "virtualenv (15.1.0)", "waitress (1.1.0)", "webob (1.7.4)", "webtest (2.0.29)", "wmctrl (0.3)"] - -[[package]] -category = "main" -description = "python-social-auth and oauth2 support for django-rest-framework" -name = "django-rest-framework-social-oauth2" -optional = false -python-versions = "*" -version = "1.1.0" - -[package.dependencies] -django-braces = ">=1.11.0" -django-oauth-toolkit = ">=1.0.0" -djangorestframework = ">=3.0.1" -social-auth-app-django = ">=0.1.0" - -[[package]] -category = "main" -description = "A pluggable app that allows users (admins) to execute SQL, view, and export the results." -name = "django-sql-explorer" -optional = false -python-versions = "*" -version = "1.1.3" - -[package.dependencies] -Django = ">=1.8.0" -six = ">=1.10.0" -sqlparse = ">=0.1.18" -unicodecsv = ">=0.14.1" - -[[package]] -category = "main" -description = "Support for many storage backends in Django" -name = "django-storages" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.9.1" - -[package.dependencies] -Django = ">=1.11" - -[package.dependencies.azure-storage-blob] -optional = true -version = ">=1.3.1,<12.0.0" - -[package.extras] -azure = ["azure-storage-blob (>=1.3.1,<12.0.0)"] -boto3 = ["boto3 (>=1.4.4)"] -dropbox = ["dropbox (>=7.2.1)"] -google = ["google-cloud-storage (>=1.15.0)"] -libcloud = ["apache-libcloud"] -sftp = ["paramiko"] - -[[package]] -category = "main" -description = "Django custom field to implement the strategy pattern" -name = "django-strategy-field" -optional = false -python-versions = "*" -version = "2.0" - -[package.extras] -dev = ["isort", "virtualenv (>15)", "wheel", "flake8", "flake8-putty", "coverage", "django-dynamic-fixture", "django-webtest", "djangorestframework", "pdbpp", "pytest-cov", "pytest-django", "pytest-echo", "pytest-pythonpath", "tox"] -tests = ["coverage", "django-dynamic-fixture", "django-webtest", "djangorestframework", "pdbpp", "pytest-cov", "pytest-django", "pytest-echo", "pytest-pythonpath", "tox"] - -[[package]] -category = "main" -description = "Simple django app to expose system infos: libraries version, databae server infos..." -name = "django-sysinfo" -optional = false -python-versions = "*" -version = "1.4" - -[package.dependencies] -psutil = "*" -pytz = "*" -six = "*" - -[package.extras] -dev = ["coverage", "django-webtest", "flake8", "mock (>=1.0.1)", "mock-import", "mysqlclient (>=1.3.12)", "pytest (>=3.0.7)", "pytest-cache", "pytest-cov", "pytest-django", "pytest-echo", "pytest-pythonpath", "setuptools (>=15.0)", "tox", "virtualenv (12.0.2)", "isort", "pdbpp", "django", "ipython (<6.0)", "pip", "psycopg2", "check-manifest", "twine", "wheel"] -tests = ["coverage", "django-webtest", "flake8", "mock (>=1.0.1)", "mock-import", "mysqlclient (>=1.3.12)", "pytest (>=3.0.7)", "pytest-cache", "pytest-cov", "pytest-django", "pytest-echo", "pytest-pythonpath", "setuptools (>=15.0)", "tox", "virtualenv (12.0.2)", "isort", "pdbpp"] - -[[package]] -category = "main" -description = "A Django app providing database and form fields for pytz timezone objects." -name = "django-timezone-field" -optional = false -python-versions = ">=3.5" -version = "4.0" - -[package.dependencies] -django = ">=2.2" -pytz = "*" - -[[package]] -category = "dev" -description = "Instant integration of Ian Bicking's WebTest (http://docs.pylonsproject.org/projects/webtest/) with django's testing framework." -name = "django-webtest" -optional = false -python-versions = "*" -version = "1.9.7" - -[package.dependencies] -webtest = ">=1.3.3" - -[[package]] -category = "main" -description = "Web APIs for Django, made easy." -name = "djangorestframework" -optional = false -python-versions = ">=3.5" -version = "3.11.0" - -[package.dependencies] -django = ">=1.11" - -[[package]] -category = "main" -description = "CSV Tools for Django REST Framework" -name = "djangorestframework-csv" -optional = false -python-versions = "*" -version = "2.1.0" - -[package.dependencies] -djangorestframework = "*" -six = "*" -unicodecsv = "*" - -[[package]] -category = "main" -description = "Geographic add-ons for Django Rest Framework" -name = "djangorestframework-gis" -optional = false -python-versions = "*" -version = "0.15" - -[package.dependencies] -djangorestframework = "*" - -[[package]] -category = "main" -description = "JSON Web Token based authentication for Django REST framework" -name = "djangorestframework-jwt" -optional = false -python-versions = "*" -version = "1.11.0" - -[package.dependencies] -PyJWT = ">=1.5.2,<2.0.0" - -[[package]] -category = "main" -description = "XML support for Django REST Framework" -name = "djangorestframework-xml" -optional = false -python-versions = "*" -version = "1.4.0" - -[package.dependencies] -defusedxml = ">=0.3" - -[[package]] -category = "main" -description = "YAML support for Django REST Framework" -name = "djangorestframework-yaml" -optional = false -python-versions = "*" -version = "1.0.3" - -[package.dependencies] -PyYAML = ">=3.10" - -[[package]] -category = "dev" -description = "DjangoRestFramework API checker" -name = "drf-api-checker" -optional = false -python-versions = "^3.6" -version = "0.8.2" - -[package.dependencies] -django = ">=2,<3" -djangorestframework = ">=3.10,<4.0" -pytz = ">=2019.3,<2020.0" - -[[package]] -category = "main" -description = "DjangoRestFramework Dynamic Serializer" -name = "drf-dynamic-serializer" -optional = false -python-versions = "*" -version = "2.1" - -[package.extras] -tests = ["atomicwrites", "attrs", "beautifulsoup4", "certifi", "check-manifest", "coverage", "django-webtest", "factory-boy", "faker", "fancycompleter", "more-itertools", "packaging", "pdbpp", "pipenv", "pluggy", "py", "pygments", "pyparsing", "pytest-cov", "pytest-cover", "pytest-coverage", "pytest-django", "pytest-echo", "pytest-pythonpath", "pytest", "python-dateutil", "six", "text-unidecode", "tox", "virtualenv-clone", "virtualenv", "waitress", "webob", "webtest", "wmctrl"] - -[[package]] -category = "main" -description = "Extensions for Django REST Framework" -name = "drf-extensions" -optional = false -python-versions = "*" -version = "0.6.0" - -[package.dependencies] -djangorestframework = ">=3.9.3" - -[[package]] -category = "main" -description = "Django REST Framework renderer for spreadsheet (xlsx) files." -name = "drf-renderer-xlsx" -optional = false -python-versions = "*" -version = "0.3.7" - -[package.dependencies] -djangorestframework = ">=3.6" -openpyxl = ">=2.4" - -[[package]] -category = "main" -description = "Automated generation of real Swagger/OpenAPI 2.0 schemas from Django Rest Framework code." -name = "drf-yasg" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "1.17.1" - -[package.dependencies] -Django = ">=1.11.7" -coreapi = ">=2.3.3" -coreschema = ">=0.0.4" -djangorestframework = ">=3.8" -inflection = ">=0.3.1" -packaging = "*" -"ruamel.yaml" = ">=0.15.34" -six = ">=1.10.0" -uritemplate = ">=3.0.0" - -[package.dependencies.swagger-spec-validator] -optional = true -version = ">=2.1.0" - -[package.extras] -validation = ["swagger-spec-validator (>=2.1.0)"] - -[[package]] -category = "dev" -description = "Discover and load entry points from installed packages." -name = "entrypoints" -optional = false -python-versions = ">=2.7" -version = "0.3" - -[[package]] -category = "main" -description = "An implementation of lxml.xmlfile for the standard library" -name = "et-xmlfile" -optional = false -python-versions = "*" -version = "1.0.1" - -[[package]] -category = "dev" -description = "A versatile test fixtures replacement based on thoughtbot's factory_bot for Ruby." -name = "factory-boy" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.12.0" - -[package.dependencies] -Faker = ">=0.7.0" - -[[package]] -category = "dev" -description = "Faker is a Python package that generates fake data for you." -name = "faker" -optional = false -python-versions = ">=3.4" -version = "4.0.2" - -[package.dependencies] -python-dateutil = ">=2.4" -text-unidecode = "1.3" - -[[package]] -category = "dev" -description = "A platform independent file lock." -name = "filelock" -optional = false -python-versions = "*" -version = "3.0.12" - -[[package]] -category = "dev" -description = "the modular source code checker: pep8, pyflakes and co" -name = "flake8" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "3.7.9" - -[package.dependencies] -entrypoints = ">=0.3.0,<0.4.0" -mccabe = ">=0.6.0,<0.7.0" -pycodestyle = ">=2.5.0,<2.6.0" -pyflakes = ">=2.1.0,<2.2.0" - -[[package]] -category = "dev" -description = "Let your Python tests travel through time" -name = "freezegun" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "0.3.15" - -[package.dependencies] -python-dateutil = ">=1.0,<2.0 || >2.0" -six = "*" - -[[package]] -category = "main" -description = "HTML parser based on the WHATWG HTML specification" -name = "html5lib" -optional = false -python-versions = "*" -version = "1.0.1" - -[package.dependencies] -six = ">=1.9" -webencodings = "*" - -[package.extras] -all = ["genshi", "chardet (>=2.2)", "datrie", "lxml"] -chardet = ["chardet (>=2.2)"] -datrie = ["datrie"] -genshi = ["genshi"] -lxml = ["lxml"] - -[[package]] -category = "main" -description = "Human friendly output for text interfaces using Python" -name = "humanfriendly" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "8.1" - -[package.dependencies] -pyreadline = "*" - -[[package]] -category = "main" -description = "Python humanize utilities" -name = "humanize" -optional = false -python-versions = ">=3.5" -version = "2.2.0" - -[package.extras] -tests = ["freezegun", "pytest", "pytest-cov"] - -[[package]] -category = "dev" -description = "File identification library for Python" -name = "identify" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -version = "1.4.13" - -[package.extras] -license = ["editdistance"] - -[[package]] -category = "main" -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.9" - -[[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.6.0" - -[package.dependencies] -zipp = ">=0.5" - -[package.extras] -docs = ["sphinx", "rst.linker"] -testing = ["packaging", "importlib-resources"] - -[[package]] -category = "main" -description = "A port of Ruby on Rails inflector to Python" -name = "inflection" -optional = false -python-versions = "*" -version = "0.3.1" - -[[package]] -category = "dev" -description = "IPython-enabled pdb" -name = "ipdb" -optional = false -python-versions = ">=2.7" -version = "0.13.2" - -[package.dependencies] -setuptools = "*" - -[package.dependencies.ipython] -python = ">=3.4" -version = ">=5.1.0" - -[[package]] -category = "dev" -description = "IPython: Productive Interactive Computing" -marker = "python_version >= \"3.4\"" -name = "ipython" -optional = false -python-versions = ">=3.6" -version = "7.13.0" - -[package.dependencies] -appnope = "*" -backcall = "*" -colorama = "*" -decorator = "*" -jedi = ">=0.10" -pexpect = "*" -pickleshare = "*" -prompt-toolkit = ">=2.0.0,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.1.0" -pygments = "*" -setuptools = ">=18.5" -traitlets = ">=4.2" - -[package.extras] -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"] -nbformat = ["nbformat"] -notebook = ["notebook", "ipywidgets"] -parallel = ["ipyparallel"] -qtconsole = ["qtconsole"] -test = ["nose (>=0.10.1)", "requests", "testpath", "pygments", "nbformat", "ipykernel", "numpy (>=1.14)"] - -[[package]] -category = "dev" -description = "Vestigial utilities from IPython" -marker = "python_version >= \"3.4\"" -name = "ipython-genutils" -optional = false -python-versions = "*" -version = "0.2.0" - -[[package]] -category = "main" -description = "Simple module to parse ISO 8601 dates" -name = "iso8601" -optional = false -python-versions = "*" -version = "0.1.12" - -[[package]] -category = "dev" -description = "A Python utility / library to sort Python imports." -name = "isort" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "4.3.21" - -[package.extras] -pipfile = ["pipreqs", "requirementslib"] -pyproject = ["toml"] -requirements = ["pipreqs", "pip-api"] -xdg_home = ["appdirs (>=1.4.0)"] - -[[package]] -category = "main" -description = "Simple immutable types for python." -name = "itypes" -optional = false -python-versions = "*" -version = "1.1.0" - -[[package]] -category = "main" -description = "Julian dates from proleptic Gregorian and Julian calendars." -name = "jdcal" -optional = false -python-versions = "*" -version = "1.4.1" - -[[package]] -category = "dev" -description = "An autocompletion tool for Python that can be used for text editors." -marker = "python_version >= \"3.4\"" -name = "jedi" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.16.0" - -[package.dependencies] -parso = ">=0.5.2" - -[package.extras] -qa = ["flake8 (3.7.9)"] -testing = ["colorama (0.4.1)", "docopt", "pytest (>=3.9.0,<5.0.0)"] - -[[package]] -category = "main" -description = "A very fast and expressive template engine." -name = "jinja2" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.11.1" - -[package.dependencies] -MarkupSafe = ">=0.23" - -[package.extras] -i18n = ["Babel (>=0.8)"] - -[[package]] -category = "main" -description = "A reusable Django field that allows you to store validated JSON in your model." -name = "jsonfield" -optional = false -python-versions = ">=3.6" -version = "3.1.0" - -[package.dependencies] -Django = ">=2.2" - -[[package]] -category = "main" -description = "An implementation of JSON Schema validation for Python" -name = "jsonschema" -optional = false -python-versions = "*" -version = "3.2.0" - -[package.dependencies] -attrs = ">=17.4.0" -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"] - -[[package]] -category = "main" -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.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"] -consul = ["python-consul (>=0.6.0)"] -librabbitmq = ["librabbitmq (>=1.5.2)"] -mongodb = ["pymongo (>=3.3.0)"] -msgpack = ["msgpack"] -pyro = ["pyro4"] -qpid = ["qpid-python (>=0.26)", "qpid-tools (>=0.26)"] -redis = ["redis (>=3.3.11)"] -slmq = ["softlayer-messaging (>=1.0.3)"] -sqlalchemy = ["sqlalchemy"] -sqs = ["boto3 (>=1.4.4)", "pycurl (7.43.0.2)"] -yaml = ["PyYAML (>=3.10)"] -zookeeper = ["kazoo (>=1.3.1)"] - -[[package]] -category = "main" -description = "Python implementation of Markdown." -name = "markdown" -optional = false -python-versions = ">=3.5" -version = "3.2.1" - -[package.dependencies] -setuptools = ">=36" - -[package.extras] -testing = ["coverage", "pyyaml"] - -[[package]] -category = "main" -description = "Safely add untrusted strings to HTML/XML markup." -name = "markupsafe" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" -version = "1.1.1" - -[[package]] -category = "dev" -description = "McCabe checker, plugin for flake8" -name = "mccabe" -optional = false -python-versions = "*" -version = "0.6.1" - -[[package]] -category = "dev" -description = "More routines for operating on iterables, beyond itertools" -marker = "python_version > \"2.7\"" -name = "more-itertools" -optional = false -python-versions = ">=3.5" -version = "8.2.0" - -[[package]] -category = "dev" -description = "multidict implementation" -marker = "python_version >= \"3.6\"" -name = "multidict" -optional = false -python-versions = ">=3.5" -version = "4.7.5" - -[[package]] -category = "dev" -description = "Node.js virtual environment builder" -name = "nodeenv" -optional = false -python-versions = "*" -version = "1.3.5" - -[[package]] -category = "main" -description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" -name = "oauthlib" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "3.1.0" - -[package.extras] -rsa = ["cryptography"] -signals = ["blinker"] -signedtoken = ["cryptography", "pyjwt (>=1.0.0)"] - -[[package]] -category = "main" -description = "A Python library to read/write Excel 2010 xlsx/xlsm files" -name = "openpyxl" -optional = false -python-versions = ">=3.6," -version = "3.0.3" - -[package.dependencies] -et_xmlfile = "*" -jdcal = "*" - -[[package]] -category = "main" -description = "Core utilities for Python packages" -name = "packaging" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "20.3" - -[package.dependencies] -pyparsing = ">=2.0.2" -six = "*" - -[[package]] -category = "dev" -description = "A Python Parser" -marker = "python_version >= \"3.4\"" -name = "parso" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.6.2" - -[package.extras] -testing = ["docopt", "pytest (>=3.0.7)"] - -[[package]] -category = "dev" -description = "Wrappers to build Python packages using PEP 517 hooks" -name = "pep517" -optional = false -python-versions = "*" -version = "0.8.1" - -[package.dependencies] -toml = "*" - -[package.dependencies.importlib_metadata] -python = "<3.8" -version = "*" - -[package.dependencies.zipp] -python = "<3.8" -version = "*" - -[[package]] -category = "dev" -description = "Pexpect allows easy control of interactive console applications." -marker = "python_version >= \"3.4\" and sys_platform != \"win32\"" -name = "pexpect" -optional = false -python-versions = "*" -version = "4.8.0" - -[package.dependencies] -ptyprocess = ">=0.5" - -[[package]] -category = "dev" -description = "Tiny 'shelve'-like database with concurrency support" -marker = "python_version >= \"3.4\"" -name = "pickleshare" -optional = false -python-versions = "*" -version = "0.7.5" - -[[package]] -category = "main" -description = "Python Imaging Library (Fork)" -name = "pillow" -optional = false -python-versions = ">=3.5" -version = "7.0.0" - -[[package]] -category = "dev" -description = "plugin and hook calling mechanisms for python" -name = "pluggy" -optional = false -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"] - -[[package]] -category = "dev" -description = "A framework for managing and maintaining multi-language pre-commit hooks." -name = "pre-commit" -optional = false -python-versions = ">=3.6" -version = "2.0.1" - -[package.dependencies] -"aspy.yaml" = "*" -cfgv = ">=2.0.0" -identify = ">=1.0.0" -nodeenv = ">=0.11.1" -pyyaml = "*" -toml = "*" -virtualenv = ">=15.2" - -[package.dependencies.importlib-metadata] -python = "<3.8" -version = "*" - -[[package]] -category = "dev" -description = "Library for building powerful interactive command lines in Python" -marker = "python_version >= \"3.4\"" -name = "prompt-toolkit" -optional = false -python-versions = ">=3.6.1" -version = "3.0.5" - -[package.dependencies] -wcwidth = "*" - -[[package]] -category = "main" -description = "Cross-platform lib for process and system monitoring in Python." -name = "psutil" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "5.7.0" - -[package.extras] -enum = ["enum34"] - -[[package]] -category = "main" -description = "psycopg2 - Python-PostgreSQL Database Adapter" -name = "psycopg2-binary" -optional = false -python-versions = "*" -version = "2.7.7" - -[[package]] -category = "dev" -description = "Run a subprocess in a pseudo terminal" -marker = "python_version >= \"3.4\" and sys_platform != \"win32\"" -name = "ptyprocess" -optional = false -python-versions = "*" -version = "0.6.0" - -[[package]] -category = "dev" -description = "library with cross-python path, ini-parsing, io, code, log facilities" -name = "py" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.8.1" - -[[package]] -category = "dev" -description = "Python style guide checker" -name = "pycodestyle" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.5.0" - -[[package]] -category = "main" -description = "C parser in Python" -name = "pycparser" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.20" - -[[package]] -category = "dev" -description = "passive checker of Python programs" -name = "pyflakes" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.1.1" - -[[package]] -category = "main" -description = "Pygments is a syntax highlighting package written in Python." -name = "pygments" -optional = false -python-versions = ">=3.5" -version = "2.6.1" - -[[package]] -category = "main" -description = "JSON Web Token implementation in Python" -name = "pyjwt" -optional = false -python-versions = "*" -version = "1.7.1" - -[package.extras] -crypto = ["cryptography (>=1.4)"] -flake8 = ["flake8", "flake8-import-order", "pep8-naming"] -test = ["pytest (>=4.0.1,<5.0.0)", "pytest-cov (>=2.6.0,<3.0.0)", "pytest-runner (>=4.2,<5.0.0)"] - -[[package]] -category = "main" -description = "Python parsing module" -name = "pyparsing" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -version = "2.4.6" - -[[package]] -category = "main" -description = "PDF toolkit" -name = "pypdf2" -optional = false -python-versions = "*" -version = "1.26.0" - -[[package]] -category = "main" -description = "A python implmementation of GNU readline." -marker = "sys_platform == \"win32\"" -name = "pyreadline" -optional = false -python-versions = "*" -version = "2.1" - -[[package]] -category = "main" -description = "Persistent/Functional/Immutable data structures" -name = "pyrsistent" -optional = false -python-versions = "*" -version = "0.16.0" - -[package.dependencies] -six = "*" - -[[package]] -category = "dev" -description = "pytest: simple powerful testing with Python" -name = "pytest" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -version = "4.6.9" - -[package.dependencies] -atomicwrites = ">=1.0" -attrs = ">=17.4.0" -packaging = "*" -pluggy = ">=0.12,<1.0" -py = ">=1.5.0" -six = ">=1.10.0" -wcwidth = "*" - -[package.dependencies.colorama] -python = "<3.4.0 || >=3.5.0" -version = "*" - -[package.dependencies.importlib-metadata] -python = "<3.8" -version = ">=0.12" - -[package.dependencies.more-itertools] -python = ">=2.8" -version = ">=4.0.0" - -[package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "nose", "requests", "mock"] - -[[package]] -category = "dev" -description = "Pytest plugin for measuring coverage." -name = "pytest-cov" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.8.1" - -[package.dependencies] -coverage = ">=4.4" -pytest = ">=3.6" - -[package.extras] -testing = ["fields", "hunter", "process-tests (2.0.2)", "six", "virtualenv"] - -[[package]] -category = "dev" -description = "Pytest plugin for measuring coverage. Forked from `pytest-cov`." -name = "pytest-cover" -optional = false -python-versions = "*" -version = "3.0.0" - -[package.dependencies] -pytest-cov = ">=2.0" - -[[package]] -category = "dev" -description = "Pytest plugin for measuring coverage. Forked from `pytest-cov`." -name = "pytest-coverage" -optional = false -python-versions = "*" -version = "0.0" - -[package.dependencies] -pytest-cover = "*" - -[[package]] -category = "dev" -description = "A Django plugin for pytest." -name = "pytest-django" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "3.9.0" - -[package.dependencies] -pytest = ">=3.6" - -[package.extras] -docs = ["sphinx", "sphinx-rtd-theme"] -testing = ["django", "django-configurations (>=2.0)", "six"] - -[[package]] -category = "dev" -description = "pytest plugin with mechanisms for echoing environment variables, package version and generic attributes" -name = "pytest-echo" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "1.7.1" - -[package.dependencies] -pytest = ">=2.2" - -[[package]] -category = "dev" -description = "ignore failures from flaky tests (pytest plugin)" -name = "pytest-ignore-flaky" -optional = false -python-versions = "*" -version = "1.0.0" - -[package.dependencies] -pytest = ">=3.7" - -[[package]] -category = "dev" -description = "pytest plugin for adding to the PYTHONPATH from command line or configs." -name = "pytest-pythonpath" -optional = false -python-versions = "*" -version = "0.7.3" - -[package.dependencies] -pytest = ">=2.5.2" - -[[package]] -category = "main" -description = "Python Crontab API" -name = "python-crontab" -optional = false -python-versions = "*" -version = "2.4.1" - -[package.dependencies] -python-dateutil = "*" - -[package.extras] -cron-description = ["cron-descriptor"] -cron-schedule = ["croniter"] - -[[package]] -category = "main" -description = "Extensions to the standard Python datetime module" -name = "python-dateutil" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -version = "2.8.1" - -[package.dependencies] -six = ">=1.5" - -[[package]] -category = "main" -description = "Python social authentication made simple." -name = "python-social-auth" -optional = false -python-versions = "*" -version = "0.3.6" - -[package.dependencies] -social-auth-core = "*" - -[package.extras] -cherrypy = ["social-auth-app-cherrypy"] -django = ["social-auth-app-django"] -django-mongoengine = ["social-auth-app-django-mongoengine"] -flask = ["social-auth-app-flask-sqlalchemy", "social-auth-app-flask"] -flask-mongoengine = ["social-auth-app-flask-mongoengine"] -flask-peewee = ["social-auth-app-flask-peewee"] -pyramid = ["social-auth-app-pyramid"] -tornado = ["social-auth-app-tornado"] -webpy = ["social-auth-app-webpy"] - -[[package]] -category = "main" -description = "OpenID support for modern servers and consumers." -marker = "python_version >= \"3.0\"" -name = "python3-openid" -optional = false -python-versions = "*" -version = "3.1.0" - -[package.dependencies] -defusedxml = "*" - -[[package]] -category = "main" -description = "World timezone definitions, modern and historical" -name = "pytz" -optional = false -python-versions = "*" -version = "2019.3" - -[[package]] -category = "main" -description = "YAML parser and emitter for Python" -name = "pyyaml" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "4.2b4" - -[[package]] -category = "main" -description = "Python bindings for 0MQ" -name = "pyzmq" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*" -version = "19.0.0" - -[[package]] -category = "main" -description = "Python client library for the RapidPro" -name = "rapidpro-python" -optional = false -python-versions = "*" -version = "2.7.0" - -[package.dependencies] -iso8601 = "*" -pytz = "*" -requests = "*" - -[[package]] -category = "main" -description = "Raven is a client for Sentry (https://getsentry.com)" -name = "raven" -optional = false -python-versions = "*" -version = "6.10.0" - -[package.extras] -flask = ["Flask (>=0.8)", "blinker (>=1.1)"] -tests = ["bottle", "celery (>=2.5)", "coverage (<4)", "exam (>=0.5.2)", "flake8 (3.5.0)", "logbook", "mock", "nose", "pytz", "pytest (>=3.2.0,<3.3.0)", "pytest-timeout (1.2.1)", "pytest-xdist (1.18.2)", "pytest-pythonpath (0.7.2)", "pytest-cov (2.5.1)", "pytest-flake8 (1.0.0)", "requests", "tornado (>=4.1,<5.0)", "tox", "webob", "webtest", "wheel", "anyjson", "zconfig", "Flask (>=0.8)", "blinker (>=1.1)", "Flask-Login (>=0.2.0)", "blinker (>=1.1)", "sanic (>=0.7.0)", "aiohttp"] - -[[package]] -category = "main" -description = "Python client for Redis key-value store" -name = "redis" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "3.4.1" - -[package.extras] -hiredis = ["hiredis (>=0.1.3)"] - -[[package]] -category = "main" -description = "The Reportlab Toolkit" -name = "reportlab" -optional = false -python-versions = "*" -version = "3.5.42" - -[package.dependencies] -pillow = ">=4.0.0" - -[[package]] -category = "main" -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.23.0" - -[package.dependencies] -certifi = ">=2017.4.17" -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.extras] -security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] -socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"] - -[[package]] -category = "main" -description = "OAuthlib authentication support for Requests." -name = "requests-oauthlib" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.3.0" - -[package.dependencies] -oauthlib = ">=3.0.0" -requests = ">=2.0.0" - -[package.extras] -rsa = ["oauthlib (>=3.0.0)"] - -[[package]] -category = "main" -description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" -name = "ruamel.yaml" -optional = false -python-versions = "*" -version = "0.16.10" - -[package.dependencies] -[package.dependencies."ruamel.yaml.clib"] -python = "<3.9" -version = ">=0.1.2" - -[package.extras] -docs = ["ryd"] -jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] - -[[package]] -category = "main" -description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" -marker = "platform_python_implementation == \"CPython\" and python_version < \"3.9\"" -name = "ruamel.yaml.clib" -optional = false -python-versions = "*" -version = "0.2.0" - -[[package]] -category = "main" -description = "Python client for Sentry (https://getsentry.com)" -name = "sentry-sdk" -optional = false -python-versions = "*" -version = "0.14.3" - -[package.dependencies] -certifi = "*" -urllib3 = ">=1.10.0" - -[package.extras] -aiohttp = ["aiohttp (>=3.5)"] -beam = ["beam (>=2.12)"] -bottle = ["bottle (>=0.12.13)"] -celery = ["celery (>=3)"] -django = ["django (>=1.8)"] -falcon = ["falcon (>=1.4)"] -flask = ["flask (>=0.11)", "blinker (>=1.1)"] -pyspark = ["pyspark (>=2.4.4)"] -rq = ["0.6"] -sanic = ["sanic (>=0.8)"] -sqlalchemy = ["sqlalchemy (>=1.2)"] -tornado = ["tornado (>=5)"] - -[[package]] -category = "main" -description = "Python 2 and 3 compatibility utilities" -name = "six" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -version = "1.14.0" - -[[package]] -category = "main" -description = "Python Social Authentication, Django integration." -name = "social-auth-app-django" -optional = false -python-versions = "*" -version = "3.1.0" - -[package.dependencies] -six = "*" -social-auth-core = ">=1.2.0" - -[[package]] -category = "main" -description = "Python social authentication made simple." -name = "social-auth-core" -optional = false -python-versions = "*" -version = "3.3.2" - -[package.dependencies] -PyJWT = ">=1.4.0" -cryptography = ">=1.4" -oauthlib = ">=1.0.3" -requests = ">=2.9.1" -requests-oauthlib = ">=0.6.1" -six = ">=1.10.0" - -[package.dependencies.defusedxml] -python = ">=3.0" -version = ">=0.5.0rc1" - -[package.dependencies.python3-openid] -python = ">=3.0" -version = ">=3.0.10" - -[package.extras] -all = ["python-jose (>=3.0.0)", "pyjwt (>=1.7.1)", "python-saml (>=2.2.0)", "cryptography (>=2.1.1)"] -allpy2 = ["python-jose (>=3.0.0)", "pyjwt (>=1.7.1)", "python-saml (>=2.2.0)", "cryptography (>=2.1.1)", "python-openid (>=2.2.5)"] -allpy3 = ["python-jose (>=3.0.0)", "pyjwt (>=1.7.1)", "python-saml (>=2.2.0)", "cryptography (>=2.1.1)", "defusedxml (>=0.5.0rc1)", "python3-openid (>=3.0.10)"] -azuread = ["cryptography (>=2.1.1)"] -openidconnect = ["python-jose (>=3.0.0)", "pyjwt (>=1.7.1)"] -saml = ["python-saml (>=2.2.0)"] - -[[package]] -category = "dev" -description = "A modern CSS selector implementation for Beautiful Soup." -name = "soupsieve" -optional = false -python-versions = ">=3.5" -version = "2.0" - -[[package]] -category = "main" -description = "Non-validating SQL parser" -name = "sqlparse" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.3.1" - -[[package]] -category = "main" -description = "Validation of Swagger specifications" -name = "swagger-spec-validator" -optional = false -python-versions = "*" -version = "2.5.0" - -[package.dependencies] -jsonschema = "*" -pyyaml = "*" -six = "*" - -[[package]] -category = "dev" -description = "The most basic Text::Unidecode port" -name = "text-unidecode" -optional = false -python-versions = "*" -version = "1.3" - -[[package]] -category = "dev" -description = "Python Library for Tom's Obvious, Minimal Language" -name = "toml" -optional = false -python-versions = "*" -version = "0.10.0" - -[[package]] -category = "main" -description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." -name = "tornado" -optional = false -python-versions = "*" -version = "4.5.3" - -[[package]] -category = "dev" -description = "tox is a generic virtualenv management and test command line tool" -name = "tox" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -version = "3.14.6" - -[package.dependencies] -colorama = ">=0.4.1" -filelock = ">=3.0.0,<4" -packaging = ">=14" -pluggy = ">=0.12.0,<1" -py = ">=1.4.17,<2" -six = ">=1.14.0,<2" -toml = ">=0.9.4" -virtualenv = ">=16.0.0,<20.0.0 || >20.0.0,<20.0.1 || >20.0.1,<20.0.2 || >20.0.2,<20.0.3 || >20.0.3,<20.0.4 || >20.0.4,<20.0.5 || >20.0.5,<20.0.6 || >20.0.6,<20.0.7 || >20.0.7" - -[package.dependencies.importlib-metadata] -python = "<3.8" -version = ">=0.12,<2" - -[package.extras] -docs = ["sphinx (>=2.0.0,<3)", "towncrier (>=18.5.0)", "pygments-github-lexers (>=0.0.5)", "sphinxcontrib-autoprogram (>=0.1.5)"] -testing = ["freezegun (>=0.3.11,<1)", "pathlib2 (>=2.3.3,<3)", "pytest (>=4.0.0,<6)", "pytest-cov (>=2.5.1,<3)", "pytest-mock (>=1.10.0,<2)", "pytest-xdist (>=1.22.2,<2)", "pytest-randomly (>=1.0.0,<4)", "flaky (>=3.4.0,<4)", "psutil (>=5.6.1,<6)"] - -[[package]] -category = "dev" -description = "Traitlets Python config system" -marker = "python_version >= \"3.4\"" -name = "traitlets" -optional = false -python-versions = "*" -version = "4.3.3" - -[package.dependencies] -decorator = "*" -ipython-genutils = "*" -six = "*" - -[package.extras] -test = ["pytest", "mock"] - -[[package]] -category = "main" -description = "Python2's stdlib csv module is nice, but it doesn't support unicode. This module is a drop-in replacement which *does*." -name = "unicodecsv" -optional = false -python-versions = "*" -version = "0.14.1" - -[[package]] -category = "main" -description = "URI templates" -name = "uritemplate" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "3.0.1" - -[[package]] -category = "main" -description = "HTTP library with thread-safe connection pooling, file post, and more." -name = "urllib3" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" -version = "1.25.8" - -[package.extras] -brotli = ["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 || >1.5.7,<2.0)"] - -[[package]] -category = "main" -description = "The uWSGI server" -name = "uwsgi" -optional = false -python-versions = "*" -version = "2.0.18" - -[[package]] -category = "dev" -description = "Automatically mock your HTTP interactions to simplify and speed up testing" -name = "vcrpy" -optional = false -python-versions = ">=3.5" -version = "4.0.2" - -[package.dependencies] -PyYAML = "*" -six = ">=1.5" -wrapt = "*" - -[package.dependencies.yarl] -python = ">=3.6" -version = "*" - -[[package]] -category = "main" -description = "Promises, promises, promises." -name = "vine" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.3.0" - -[[package]] -category = "dev" -description = "Virtual Python Environment builder" -name = "virtualenv" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -version = "20.0.15" - -[package.dependencies] -appdirs = ">=1.4.3,<2" -distlib = ">=0.3.0,<1" -filelock = ">=3.0.0,<4" -six = ">=1.9.0,<2" - -[package.dependencies.importlib-metadata] -python = "<3.8" -version = ">=0.12,<2" - -[package.extras] -docs = ["sphinx (>=2.0.0,<3)", "sphinx-argparse (>=0.2.5,<1)", "sphinx-rtd-theme (>=0.4.3,<1)", "towncrier (>=19.9.0rc1)", "proselint (>=0.10.2,<1)"] -testing = ["pytest (>=4.0.0,<6)", "coverage (>=4.5.1,<6)", "pytest-mock (>=2.0.0,<3)", "pytest-env (>=0.6.2,<1)", "pytest-timeout (>=1.3.4,<2)", "packaging (>=20.0)", "xonsh (>=0.9.13,<1)"] - -[[package]] -category = "dev" -description = "Waitress WSGI server" -name = "waitress" -optional = false -python-versions = "*" -version = "1.4.3" - -[package.extras] -docs = ["Sphinx (>=1.8.1)", "docutils", "pylons-sphinx-themes (>=1.0.9)"] -testing = ["nose", "coverage (>=5.0)"] - -[[package]] -category = "dev" -description = "Measures number of Terminal column cells of wide-character codes" -name = "wcwidth" -optional = false -python-versions = "*" -version = "0.1.9" - -[[package]] -category = "main" -description = "Character encoding aliases for legacy web content" -name = "webencodings" -optional = false -python-versions = "*" -version = "0.5.1" - -[[package]] -category = "dev" -description = "WSGI request and response object" -name = "webob" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*" -version = "1.8.6" - -[package.extras] -docs = ["Sphinx (>=1.7.5)", "pylons-sphinx-themes"] -testing = ["pytest (>=3.1.0)", "coverage", "pytest-cov", "pytest-xdist"] - -[[package]] -category = "dev" -description = "Helper to test WSGI applications" -name = "webtest" -optional = false -python-versions = "*" -version = "2.0.34" - -[package.dependencies] -WebOb = ">=1.2" -beautifulsoup4 = "*" -six = "*" -waitress = ">=0.8.5" - -[package.extras] -docs = ["Sphinx (>=1.8.1)", "docutils", "pylons-sphinx-themes (>=1.0.8)"] -tests = ["nose (<1.3.0)", "coverage", "mock", "pastedeploy", "wsgiproxy2", "pyquery"] - -[[package]] -category = "dev" -description = "Module for decorators, wrappers and monkey patching." -name = "wrapt" -optional = false -python-versions = "*" -version = "1.12.1" - -[[package]] -category = "main" -description = "PDF generator using HTML and CSS" -name = "xhtml2pdf" -optional = false -python-versions = "*" -version = "0.2.4" - -[package.dependencies] -Pillow = "*" -html5lib = ">=1.0" -pyPdf2 = "*" -reportlab = ">=3.0" -six = "*" - -[[package]] -category = "main" -description = "Library for developers to extract data from Microsoft Excel (tm) spreadsheet files" -name = "xlrd" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.2.0" - -[[package]] -category = "main" -description = "Library to create spreadsheet files compatible with MS Excel 97/2000/XP/2003 XLS files, on any platform, with Python 2.6, 2.7, 3.3+" -name = "xlwt" -optional = false -python-versions = "*" -version = "1.3.0" - -[[package]] -category = "dev" -description = "Yet another URL library" -marker = "python_version >= \"3.6\"" -name = "yarl" -optional = false -python-versions = ">=3.5" -version = "1.4.2" - -[package.dependencies] -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.1.0" - -[package.extras] -docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] -testing = ["jaraco.itertools", "func-timeout"] - -[metadata] -content-hash = "4fa24be7584a30e7e7d73c787776882cfd4ab6844fe491b7a9b189e6195e815b" -python-versions = "^3.7" - -[metadata.files] -admin-extra-urls = [ - {file = "admin-extra-urls-2.2.0.tar.gz", hash = "sha256:5b886ed045559f308d50f53f04b16a44fb2b1894e395dba6fb055306726a748f"}, - {file = "admin_extra_urls-2.2.0-py2.py3-none-any.whl", hash = "sha256:75441038a916f0a5eb10d2c2a60c45aa2047b0e475d82a016408bad755bd9c78"}, -] -amqp = [ - {file = "amqp-2.5.2-py2.py3-none-any.whl", hash = "sha256:6e649ca13a7df3faacdc8bbb280aa9a6602d22fd9d545336077e573a1f4ff3b8"}, - {file = "amqp-2.5.2.tar.gz", hash = "sha256:77f1aef9410698d20eaeac5b73a87817365f457a507d82edf292e12cbb83b08d"}, -] -appdirs = [ - {file = "appdirs-1.4.3-py2.py3-none-any.whl", hash = "sha256:d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e"}, - {file = "appdirs-1.4.3.tar.gz", hash = "sha256:9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92"}, -] -appnope = [ - {file = "appnope-0.1.0-py2.py3-none-any.whl", hash = "sha256:5b26757dc6f79a3b7dc9fab95359328d5747fcb2409d331ea66d0272b90ab2a0"}, - {file = "appnope-0.1.0.tar.gz", hash = "sha256:8b995ffe925347a2138d7ac0fe77155e4311a0ea6d6da4f5128fe4b3cbe5ed71"}, -] -asn1crypto = [ - {file = "asn1crypto-1.3.0-py2.py3-none-any.whl", hash = "sha256:831d2710d3274c8a74befdddaf9f17fcbf6e350534565074818722d6d615b315"}, - {file = "asn1crypto-1.3.0.tar.gz", hash = "sha256:5a215cb8dc12f892244e3a113fe05397ee23c5c4ca7a69cd6e69811755efc42d"}, -] -"aspy.yaml" = [ - {file = "aspy.yaml-1.3.0-py2.py3-none-any.whl", hash = "sha256:463372c043f70160a9ec950c3f1e4c3a82db5fca01d334b6bc89c7164d744bdc"}, - {file = "aspy.yaml-1.3.0.tar.gz", hash = "sha256:e7c742382eff2caed61f87a39d13f99109088e5e93f04d76eb8d4b28aa143f45"}, -] -atomicwrites = [ - {file = "atomicwrites-1.3.0-py2.py3-none-any.whl", hash = "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4"}, - {file = "atomicwrites-1.3.0.tar.gz", hash = "sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6"}, -] -attrs = [ - {file = "attrs-19.3.0-py2.py3-none-any.whl", hash = "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c"}, - {file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"}, -] -azure-common = [ - {file = "azure-common-1.1.25.zip", hash = "sha256:ce0f1013e6d0e9faebaf3188cc069f4892fc60a6ec552e3f817c1a2f92835054"}, - {file = "azure_common-1.1.25-py2.py3-none-any.whl", hash = "sha256:fd02e4256dc9cdd2d4422bc795bdca2ef302f7a86148b154fbf4ea1f09da400a"}, -] -azure-storage-blob = [ - {file = "azure-storage-blob-2.1.0.tar.gz", hash = "sha256:b90323aad60f207f9f90a0c4cf94c10acc313c20b39403398dfba51f25f7b454"}, - {file = "azure_storage_blob-2.1.0-py2.py3-none-any.whl", hash = "sha256:a8e91a51d4f62d11127c7fd8ba0077385c5b11022f0269f8a2a71b9fc36bef31"}, -] -azure-storage-common = [ - {file = "azure-storage-common-2.1.0.tar.gz", hash = "sha256:ccedef5c67227bc4d6670ffd37cec18fb529a1b7c3a5e53e4096eb0cf23dc73f"}, - {file = "azure_storage_common-2.1.0-py2.py3-none-any.whl", hash = "sha256:b01a491a18839b9d05a4fe3421458a0ddb5ab9443c14e487f40d16f9a1dc2fbe"}, -] -backcall = [ - {file = "backcall-0.1.0.tar.gz", hash = "sha256:38ecd85be2c1e78f77fd91700c76e14667dc21e2713b63876c0eb901196e01e4"}, - {file = "backcall-0.1.0.zip", hash = "sha256:bbbf4b1e5cd2bdb08f915895b51081c041bac22394fdfcfdfbe9f14b77c08bf2"}, -] -beautifulsoup4 = [ - {file = "beautifulsoup4-4.8.2-py2-none-any.whl", hash = "sha256:e1505eeed31b0f4ce2dbb3bc8eb256c04cc2b3b72af7d551a4ab6efd5cbe5dae"}, - {file = "beautifulsoup4-4.8.2-py3-none-any.whl", hash = "sha256:9fbb4d6e48ecd30bcacc5b63b94088192dcda178513b2ae3c394229f8911b887"}, - {file = "beautifulsoup4-4.8.2.tar.gz", hash = "sha256:05fd825eb01c290877657a56df4c6e4c311b3965bda790c613a3d6fb01a5462a"}, -] -billiard = [ - {file = "billiard-3.6.3.0-py3-none-any.whl", hash = "sha256:bff575450859a6e0fbc2f9877d9b715b0bbc07c3565bb7ed2280526a0cdf5ede"}, - {file = "billiard-3.6.3.0.tar.gz", hash = "sha256:d91725ce6425f33a97dfa72fb6bfef0e47d4652acd98a032bd1a7fbf06d5fa6a"}, -] -bump2version = [ - {file = "bump2version-1.0.0-py2.py3-none-any.whl", hash = "sha256:477f0e18a0d58e50bb3dbc9af7fcda464fd0ebfc7a6151d8888602d7153171a0"}, - {file = "bump2version-1.0.0.tar.gz", hash = "sha256:cd4f3a231305e405ed8944d8ff35bd742d9bc740ad62f483bd0ca21ce7131984"}, -] -celery = [ - {file = "celery-4.4.2-py2.py3-none-any.whl", hash = "sha256:5b4b37e276033fe47575107a2775469f0b721646a08c96ec2c61531e4fe45f2a"}, - {file = "celery-4.4.2.tar.gz", hash = "sha256:108a0bf9018a871620936c33a3ee9f6336a89f8ef0a0f567a9001f4aa361415f"}, -] -certifi = [ - {file = "certifi-2019.11.28-py2.py3-none-any.whl", hash = "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3"}, - {file = "certifi-2019.11.28.tar.gz", hash = "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"}, -] -cffi = [ - {file = "cffi-1.14.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384"}, - {file = "cffi-1.14.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:cf16e3cf6c0a5fdd9bc10c21687e19d29ad1fe863372b5543deaec1039581a30"}, - {file = "cffi-1.14.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:f2b0fa0c01d8a0c7483afd9f31d7ecf2d71760ca24499c8697aeb5ca37dc090c"}, - {file = "cffi-1.14.0-cp27-cp27m-win32.whl", hash = "sha256:99f748a7e71ff382613b4e1acc0ac83bf7ad167fb3802e35e90d9763daba4d78"}, - {file = "cffi-1.14.0-cp27-cp27m-win_amd64.whl", hash = "sha256:c420917b188a5582a56d8b93bdd8e0f6eca08c84ff623a4c16e809152cd35793"}, - {file = "cffi-1.14.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:399aed636c7d3749bbed55bc907c3288cb43c65c4389964ad5ff849b6370603e"}, - {file = "cffi-1.14.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:cab50b8c2250b46fe738c77dbd25ce017d5e6fb35d3407606e7a4180656a5a6a"}, - {file = "cffi-1.14.0-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:001bf3242a1bb04d985d63e138230802c6c8d4db3668fb545fb5005ddf5bb5ff"}, - {file = "cffi-1.14.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:e56c744aa6ff427a607763346e4170629caf7e48ead6921745986db3692f987f"}, - {file = "cffi-1.14.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:b8c78301cefcf5fd914aad35d3c04c2b21ce8629b5e4f4e45ae6812e461910fa"}, - {file = "cffi-1.14.0-cp35-cp35m-win32.whl", hash = "sha256:8c0ffc886aea5df6a1762d0019e9cb05f825d0eec1f520c51be9d198701daee5"}, - {file = "cffi-1.14.0-cp35-cp35m-win_amd64.whl", hash = "sha256:8a6c688fefb4e1cd56feb6c511984a6c4f7ec7d2a1ff31a10254f3c817054ae4"}, - {file = "cffi-1.14.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:95cd16d3dee553f882540c1ffe331d085c9e629499ceadfbda4d4fde635f4b7d"}, - {file = "cffi-1.14.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:66e41db66b47d0d8672d8ed2708ba91b2f2524ece3dee48b5dfb36be8c2f21dc"}, - {file = "cffi-1.14.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:028a579fc9aed3af38f4892bdcc7390508adabc30c6af4a6e4f611b0c680e6ac"}, - {file = "cffi-1.14.0-cp36-cp36m-win32.whl", hash = "sha256:cef128cb4d5e0b3493f058f10ce32365972c554572ff821e175dbc6f8ff6924f"}, - {file = "cffi-1.14.0-cp36-cp36m-win_amd64.whl", hash = "sha256:337d448e5a725bba2d8293c48d9353fc68d0e9e4088d62a9571def317797522b"}, - {file = "cffi-1.14.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e577934fc5f8779c554639376beeaa5657d54349096ef24abe8c74c5d9c117c3"}, - {file = "cffi-1.14.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:62ae9af2d069ea2698bf536dcfe1e4eed9090211dbaafeeedf5cb6c41b352f66"}, - {file = "cffi-1.14.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:14491a910663bf9f13ddf2bc8f60562d6bc5315c1f09c704937ef17293fb85b0"}, - {file = "cffi-1.14.0-cp37-cp37m-win32.whl", hash = "sha256:c43866529f2f06fe0edc6246eb4faa34f03fe88b64a0a9a942561c8e22f4b71f"}, - {file = "cffi-1.14.0-cp37-cp37m-win_amd64.whl", hash = "sha256:2089ed025da3919d2e75a4d963d008330c96751127dd6f73c8dc0c65041b4c26"}, - {file = "cffi-1.14.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3b911c2dbd4f423b4c4fcca138cadde747abdb20d196c4a48708b8a2d32b16dd"}, - {file = "cffi-1.14.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:7e63cbcf2429a8dbfe48dcc2322d5f2220b77b2e17b7ba023d6166d84655da55"}, - {file = "cffi-1.14.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:3d311bcc4a41408cf5854f06ef2c5cab88f9fded37a3b95936c9879c1640d4c2"}, - {file = "cffi-1.14.0-cp38-cp38-win32.whl", hash = "sha256:675686925a9fb403edba0114db74e741d8181683dcf216be697d208857e04ca8"}, - {file = "cffi-1.14.0-cp38-cp38-win_amd64.whl", hash = "sha256:00789914be39dffba161cfc5be31b55775de5ba2235fe49aa28c148236c4e06b"}, - {file = "cffi-1.14.0.tar.gz", hash = "sha256:2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6"}, -] -cfgv = [ - {file = "cfgv-3.1.0-py2.py3-none-any.whl", hash = "sha256:1ccf53320421aeeb915275a196e23b3b8ae87dea8ac6698b1638001d4a486d53"}, - {file = "cfgv-3.1.0.tar.gz", hash = "sha256:c8e8f552ffcc6194f4e18dd4f68d9aef0c0d58ae7e7be8c82bee3c5e9edfa513"}, -] -chardet = [ - {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, - {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, -] -check-manifest = [ - {file = "check-manifest-0.41.tar.gz", hash = "sha256:88afe85b751717688f8bc3b63d9543d0d962da98f1f420c554eaeb8d76c571a8"}, - {file = "check_manifest-0.41-py2.py3-none-any.whl", hash = "sha256:4046b1260e63c139be6441fe8db8d9221f495ff39b81add2a55e5ca35dde7a6a"}, -] -circus = [ - {file = "circus-0.16.1-py3-none-any.whl", hash = "sha256:87948a5881acde07db22e23da7281b6337ef75a6a37a49ceea71cbd822ff83b0"}, - {file = "circus-0.16.1.tar.gz", hash = "sha256:dd7c011eb67785a1c96a4db94a56a22810c6ed608cebf301152dabc771654c5d"}, -] -colorama = [ - {file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"}, - {file = "colorama-0.4.3.tar.gz", hash = "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"}, -] -coreapi = [ - {file = "coreapi-2.3.3-py2.py3-none-any.whl", hash = "sha256:bf39d118d6d3e171f10df9ede5666f63ad80bba9a29a8ec17726a66cf52ee6f3"}, - {file = "coreapi-2.3.3.tar.gz", hash = "sha256:46145fcc1f7017c076a2ef684969b641d18a2991051fddec9458ad3f78ffc1cb"}, -] -coreschema = [ - {file = "coreschema-0.0.4-py2-none-any.whl", hash = "sha256:5e6ef7bf38c1525d5e55a895934ab4273548629f16aed5c0a6caa74ebf45551f"}, - {file = "coreschema-0.0.4.tar.gz", hash = "sha256:9503506007d482ab0867ba14724b93c18a33b22b6d19fb419ef2d239dd4a1607"}, -] -coverage = [ - {file = "coverage-5.0.4-cp27-cp27m-macosx_10_12_x86_64.whl", hash = "sha256:8a620767b8209f3446197c0e29ba895d75a1e272a36af0786ec70fe7834e4307"}, - {file = "coverage-5.0.4-cp27-cp27m-macosx_10_13_intel.whl", hash = "sha256:73aa6e86034dad9f00f4bbf5a666a889d17d79db73bc5af04abd6c20a014d9c8"}, - {file = "coverage-5.0.4-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:408ce64078398b2ee2ec08199ea3fcf382828d2f8a19c5a5ba2946fe5ddc6c31"}, - {file = "coverage-5.0.4-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:cda33311cb9fb9323958a69499a667bd728a39a7aa4718d7622597a44c4f1441"}, - {file = "coverage-5.0.4-cp27-cp27m-win32.whl", hash = "sha256:5f587dfd83cb669933186661a351ad6fc7166273bc3e3a1531ec5c783d997aac"}, - {file = "coverage-5.0.4-cp27-cp27m-win_amd64.whl", hash = "sha256:9fad78c13e71546a76c2f8789623eec8e499f8d2d799f4b4547162ce0a4df435"}, - {file = "coverage-5.0.4-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:2e08c32cbede4a29e2a701822291ae2bc9b5220a971bba9d1e7615312efd3037"}, - {file = "coverage-5.0.4-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:922fb9ef2c67c3ab20e22948dcfd783397e4c043a5c5fa5ff5e9df5529074b0a"}, - {file = "coverage-5.0.4-cp35-cp35m-macosx_10_12_x86_64.whl", hash = "sha256:c3fc325ce4cbf902d05a80daa47b645d07e796a80682c1c5800d6ac5045193e5"}, - {file = "coverage-5.0.4-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:046a1a742e66d065d16fb564a26c2a15867f17695e7f3d358d7b1ad8a61bca30"}, - {file = "coverage-5.0.4-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6ad6ca45e9e92c05295f638e78cd42bfaaf8ee07878c9ed73e93190b26c125f7"}, - {file = "coverage-5.0.4-cp35-cp35m-win32.whl", hash = "sha256:eda55e6e9ea258f5e4add23bcf33dc53b2c319e70806e180aecbff8d90ea24de"}, - {file = "coverage-5.0.4-cp35-cp35m-win_amd64.whl", hash = "sha256:4a8a259bf990044351baf69d3b23e575699dd60b18460c71e81dc565f5819ac1"}, - {file = "coverage-5.0.4-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:f372cdbb240e09ee855735b9d85e7f50730dcfb6296b74b95a3e5dea0615c4c1"}, - {file = "coverage-5.0.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a37c6233b28e5bc340054cf6170e7090a4e85069513320275a4dc929144dccf0"}, - {file = "coverage-5.0.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:443be7602c790960b9514567917af538cac7807a7c0c0727c4d2bbd4014920fd"}, - {file = "coverage-5.0.4-cp36-cp36m-win32.whl", hash = "sha256:165a48268bfb5a77e2d9dbb80de7ea917332a79c7adb747bd005b3a07ff8caf0"}, - {file = "coverage-5.0.4-cp36-cp36m-win_amd64.whl", hash = "sha256:0a907199566269e1cfa304325cc3b45c72ae341fbb3253ddde19fa820ded7a8b"}, - {file = "coverage-5.0.4-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:513e6526e0082c59a984448f4104c9bf346c2da9961779ede1fc458e8e8a1f78"}, - {file = "coverage-5.0.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:3844c3dab800ca8536f75ae89f3cf566848a3eb2af4d9f7b1103b4f4f7a5dad6"}, - {file = "coverage-5.0.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:641e329e7f2c01531c45c687efcec8aeca2a78a4ff26d49184dce3d53fc35014"}, - {file = "coverage-5.0.4-cp37-cp37m-win32.whl", hash = "sha256:db1d4e38c9b15be1521722e946ee24f6db95b189d1447fa9ff18dd16ba89f732"}, - {file = "coverage-5.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:62061e87071497951155cbccee487980524d7abea647a1b2a6eb6b9647df9006"}, - {file = "coverage-5.0.4-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:65a7e00c00472cd0f59ae09d2fb8a8aaae7f4a0cf54b2b74f3138d9f9ceb9cb2"}, - {file = "coverage-5.0.4-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1f66cf263ec77af5b8fe14ef14c5e46e2eb4a795ac495ad7c03adc72ae43fafe"}, - {file = "coverage-5.0.4-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:85596aa5d9aac1bf39fe39d9fa1051b0f00823982a1de5766e35d495b4a36ca9"}, - {file = "coverage-5.0.4-cp38-cp38-win32.whl", hash = "sha256:86a0ea78fd851b313b2e712266f663e13b6bc78c2fb260b079e8b67d970474b1"}, - {file = "coverage-5.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:03f630aba2b9b0d69871c2e8d23a69b7fe94a1e2f5f10df5049c0df99db639a0"}, - {file = "coverage-5.0.4-cp39-cp39-win32.whl", hash = "sha256:7c9762f80a25d8d0e4ab3cb1af5d9dffbddb3ee5d21c43e3474c84bf5ff941f7"}, - {file = "coverage-5.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:4482f69e0701139d0f2c44f3c395d1d1d37abd81bfafbf9b6efbe2542679d892"}, - {file = "coverage-5.0.4.tar.gz", hash = "sha256:1b60a95fc995649464e0cd48cecc8288bac5f4198f21d04b8229dc4097d76823"}, -] -cryptography = [ - {file = "cryptography-2.7-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:f57b76e46a58b63d1c6375017f4564a28f19a5ca912691fd2e4261b3414b618d"}, - {file = "cryptography-2.7-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:cfee9164954c186b191b91d4193989ca994703b2fff406f71cf454a2d3c7327e"}, - {file = "cryptography-2.7-cp27-cp27m-win32.whl", hash = "sha256:b0db0cecf396033abb4a93c95d1602f268b3a68bb0a9cc06a7cff587bb9a7292"}, - {file = "cryptography-2.7-cp27-cp27m-win_amd64.whl", hash = "sha256:41a0be220dd1ed9e998f5891948306eb8c812b512dc398e5a01846d855050799"}, - {file = "cryptography-2.7-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ae536da50c7ad1e002c3eee101871d93abdc90d9c5f651818450a0d3af718609"}, - {file = "cryptography-2.7-cp34-abi3-macosx_10_6_intel.whl", hash = "sha256:24b61e5fcb506424d3ec4e18bca995833839bf13c59fc43e530e488f28d46b8c"}, - {file = "cryptography-2.7-cp34-abi3-manylinux1_x86_64.whl", hash = "sha256:96d8473848e984184b6728e2c9d391482008646276c3ff084a1bd89e15ff53a1"}, - {file = "cryptography-2.7-cp34-cp34m-win32.whl", hash = "sha256:25dd1581a183e9e7a806fe0543f485103232f940fcfc301db65e630512cce643"}, - {file = "cryptography-2.7-cp34-cp34m-win_amd64.whl", hash = "sha256:5751d8a11b956fbfa314f6553d186b94aa70fdb03d8a4d4f1c82dcacf0cbe28a"}, - {file = "cryptography-2.7-cp35-cp35m-win32.whl", hash = "sha256:7b97ae6ef5cba2e3bb14256625423413d5ce8d1abb91d4f29b6d1a081da765f8"}, - {file = "cryptography-2.7-cp35-cp35m-win_amd64.whl", hash = "sha256:3452bba7c21c69f2df772762be0066c7ed5dc65df494a1d53a58b683a83e1216"}, - {file = "cryptography-2.7-cp36-cp36m-win32.whl", hash = "sha256:72e24c521fa2106f19623a3851e9f89ddfdeb9ac63871c7643790f872a305dfc"}, - {file = "cryptography-2.7-cp36-cp36m-win_amd64.whl", hash = "sha256:5f61c7d749048fa6e3322258b4263463bfccefecb0dd731b6561cb617a1d9bb9"}, - {file = "cryptography-2.7-cp37-cp37m-win32.whl", hash = "sha256:961e886d8a3590fd2c723cf07be14e2a91cf53c25f02435c04d39e90780e3b53"}, - {file = "cryptography-2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:f27d93f0139a3c056172ebb5d4f9056e770fdf0206c2f422ff2ebbad142e09ed"}, - {file = "cryptography-2.7.tar.gz", hash = "sha256:e6347742ac8f35ded4a46ff835c60e68c22a536a8ae5c4422966d06946b6d4c6"}, -] -decorator = [ - {file = "decorator-4.4.2-py2.py3-none-any.whl", hash = "sha256:41fa54c2a0cc4ba648be4fd43cff00aedf5b9465c9bf18d64325bc225f08f760"}, - {file = "decorator-4.4.2.tar.gz", hash = "sha256:e3a62f0520172440ca0dcc823749319382e377f37f140a0b99ef45fecb84bfe7"}, -] -defusedxml = [ - {file = "defusedxml-0.6.0-py2.py3-none-any.whl", hash = "sha256:6687150770438374ab581bb7a1b327a847dd9c5749e396102de3fad4e8a3ef93"}, - {file = "defusedxml-0.6.0.tar.gz", hash = "sha256:f684034d135af4c6cbb949b8a4d2ed61634515257a67299e5f940fbaa34377f5"}, -] -distlib = [ - {file = "distlib-0.3.0.zip", hash = "sha256:2e166e231a26b36d6dfe35a48c4464346620f8645ed0ace01ee31822b288de21"}, -] -django = [ - {file = "Django-2.2.11-py3-none-any.whl", hash = "sha256:b51c9c548d5c3b3ccbb133d0bebc992e8ec3f14899bce8936e6fdda6b23a1881"}, - {file = "Django-2.2.11.tar.gz", hash = "sha256:65e2387e6bde531d3bb803244a2b74e0253550a9612c64a60c8c5be267b30f50"}, -] -django-adminactions = [ - {file = "django-adminactions-1.8.1.tar.gz", hash = "sha256:bd147e7ccdad4042f7c8c411da29428f829b81305a4568dd5cc6d63447682b9c"}, -] -django-adminfilters = [ - {file = "django-adminfilters-1.1.0.tar.gz", hash = "sha256:adab7f927b0845f9d87902ef3148ba704214e5977e5da483e386e82e445cb879"}, -] -django-appconf = [ - {file = "django-appconf-1.0.4.tar.gz", hash = "sha256:be58deb54a43d77d2e1621fe59f787681376d3cd0b8bd8e4758ef6c3a6453380"}, - {file = "django_appconf-1.0.4-py2.py3-none-any.whl", hash = "sha256:1b1d0e1069c843ebe8ae5aa48ec52403b1440402b320c3e3a206a0907e97bb06"}, -] -django-braces = [ - {file = "django-braces-1.14.0.tar.gz", hash = "sha256:83705b78948de00804bfacf40c315d001bb39630f35bbdd8588211c2d5b4d43f"}, - {file = "django_braces-1.14.0-py2.py3-none-any.whl", hash = "sha256:a6d9b34cf3e4949635e54884097c30410d7964fc7bec7231445ea7079b8c5722"}, -] -django-celery-beat = [ - {file = "django-celery-beat-2.0.0.tar.gz", hash = "sha256:fdf1255eecfbeb770c6521fe3e69989dfc6373cd5a7f0fe62038d37f80f47e48"}, - {file = "django_celery_beat-2.0.0-py2.py3-none-any.whl", hash = "sha256:fe0b2a1b31d4a6234fea4b31986ddfd4644a48fab216ce1843f3ed0ddd2e9097"}, -] -django-celery-email = [ - {file = "django-celery-email-3.0.0.tar.gz", hash = "sha256:5546cbba80952cc3b8a0ffa4206ce90a4a996a7ffd1c385a2bdb65903ca18ece"}, - {file = "django_celery_email-3.0.0-py2.py3-none-any.whl", hash = "sha256:0f72da39cb2ea83c69440566e87f27cd72f68f247f98ce99fb29889fcf329406"}, -] -django-concurrency = [ - {file = "django-concurrency-2.1.1.tar.gz", hash = "sha256:5daf6d4334ffad4d358444344115fee634f191a9be711ab4f99c8760cd6c76a4"}, -] -django-constance = [ - {file = "django-constance-2.6.0.tar.gz", hash = "sha256:12d827f9d5552ee39884fb6fb356f231f32b1ab8958acc715e3d1a6ecf913653"}, -] -django-cors-headers = [ - {file = "django-cors-headers-3.2.1.tar.gz", hash = "sha256:a5960addecc04527ab26617e51b8ed42f0adab4594b24bb0f3c33e2bd3857c3f"}, - {file = "django_cors_headers-3.2.1-py3-none-any.whl", hash = "sha256:a785b5f446f6635810776d9f5f5d23e6a2a2f728ea982648370afaf0dfdf2627"}, -] -django-countries = [ - {file = "django-countries-6.1.2.tar.gz", hash = "sha256:e2ae9b76f9a0b5f3f365b5b81fe4972df0a5878c930139586f43f7d6d50a9594"}, - {file = "django_countries-6.1.2-py3-none-any.whl", hash = "sha256:2e852c9693818d64d28758a720a0cb8277673ac495af8b855c4dc64940703bd2"}, -] -django-crashlog = [ - {file = "django-crashlog-1.0.0.tar.gz", hash = "sha256:147a09226c69f4f8349292680662e53f20b232dc02d0f86e4532418a1da2dd94"}, -] -django-crispy-forms = [ - {file = "django-crispy-forms-1.9.0.tar.gz", hash = "sha256:67e73ac863d3159500029fbbcdcb788f287a3fd357becebc1a0b51f73896dce3"}, - {file = "django_crispy_forms-1.9.0-py2.py3-none-any.whl", hash = "sha256:50032184708ce351e3c9f0008ac35d659d9d5973fa2db218066f2e0a76eb41d9"}, -] -django-dbtemplates = [ - {file = "django-dbtemplates-3.0.tar.gz", hash = "sha256:6ff4199a7e7b008cd952df1ad0ff05ad07c78a4106590d81def327fa946a0a0b"}, - {file = "django_dbtemplates-3.0-py2.py3-none-any.whl", hash = "sha256:76226ed8afde6cc5b5f45031d3689eeb5fd126e5a64182112b97ce9726bf6904"}, -] -django-deprecate-fields = [ - {file = "django-deprecate-fields-0.0.4.tar.gz", hash = "sha256:7d5df6617fe2020f4a89b86d25074d033d56158ba36ab12cc9cec1f75cae002c"}, - {file = "django_deprecate_fields-0.0.4-py3-none-any.whl", hash = "sha256:2020b5f9eee26d9bbedd28a993b5c050c20adb0e276795a66b70f47a25db0120"}, -] -django-environ = [ - {file = "django-environ-0.4.5.tar.gz", hash = "sha256:6c9d87660142608f63ec7d5ce5564c49b603ea8ff25da595fd6098f6dc82afde"}, - {file = "django_environ-0.4.5-py2.py3-none-any.whl", hash = "sha256:c57b3c11ec1f319d9474e3e5a79134f40174b17c7cc024bbb2fad84646b120c4"}, -] -django-extensions = [ - {file = "django-extensions-2.2.9.tar.gz", hash = "sha256:2f81b618ba4d1b0e58603e25012e5c74f88a4b706e0022a3b21f24f0322a6ce6"}, - {file = "django_extensions-2.2.9-py2.py3-none-any.whl", hash = "sha256:b19182d101a441fe001c5753553a901e2ef3ff60e8fbbe38881eb4a61fdd17c4"}, -] -django-filter = [ - {file = "django-filter-2.2.0.tar.gz", hash = "sha256:c3deb57f0dd7ff94d7dce52a047516822013e2b441bed472b722a317658cfd14"}, - {file = "django_filter-2.2.0-py3-none-any.whl", hash = "sha256:558c727bce3ffa89c4a7a0b13bc8976745d63e5fd576b3a9a851650ef11c401b"}, -] -django-impersonate = [ - {file = "django-impersonate-1.5.tar.gz", hash = "sha256:2c10bcb1c42fe6495d915f4cc4cfd7c5f8375ba39a06b0f062ce6f1e2ff76585"}, -] -django-js-asset = [ - {file = "django-js-asset-1.2.2.tar.gz", hash = "sha256:c163ae80d2e0b22d8fb598047cd0dcef31f81830e127cfecae278ad574167260"}, - {file = "django_js_asset-1.2.2-py2.py3-none-any.whl", hash = "sha256:8ec12017f26eec524cab436c64ae73033368a372970af4cf42d9354fcb166bdd"}, -] -django-jsoneditor = [ - {file = "django-jsoneditor-0.1.6.tar.gz", hash = "sha256:574f33a60271f464cad5739b6f4718aca81a779188297faa5adab41754cac9ba"}, - {file = "django_jsoneditor-0.1.6-py2.py3-none-any.whl", hash = "sha256:e74760740ef5ecb0d295bb07c21635d2bebea7b9bab4352fa403720cc275a905"}, -] -django-migration-linter = [ - {file = "django-migration-linter-2.1.0.tar.gz", hash = "sha256:85473556050955322a3509adccf82fd5b545a229cfc6227b0d9f50182dade8ab"}, - {file = "django_migration_linter-2.1.0-py2.py3-none-any.whl", hash = "sha256:966d4af0da98edd2186f262a0da17946aadd6ad93a97d523f3011879928b3152"}, -] -django-model-utils = [ - {file = "django-model-utils-4.0.0.tar.gz", hash = "sha256:adf09e5be15122a7f4e372cb5a6dd512bbf8d78a23a90770ad0983ee9d909061"}, - {file = "django_model_utils-4.0.0-py2.py3-none-any.whl", hash = "sha256:9cf882e5b604421b62dbe57ad2b18464dc9c8f963fc3f9831badccae66c1139c"}, -] -django-mptt = [ - {file = "django-mptt-0.11.0.tar.gz", hash = "sha256:dfdb3af75ad27cdd4458b0544ec8574174f2b90f99bc2cafab6a15b4bc1895a8"}, - {file = "django_mptt-0.11.0-py2.py3-none-any.whl", hash = "sha256:90eb236eb4f1a92124bd7c37852bbe09c0d21158477cc237556d59842a91c509"}, -] -django-oauth-toolkit = [ - {file = "django-oauth-toolkit-1.3.2.tar.gz", hash = "sha256:28508f83385ab4313936ddedfb310eaa8a1dcb737153d2956383ce47e75c2fab"}, - {file = "django_oauth_toolkit-1.3.2-py2.py3-none-any.whl", hash = "sha256:d5a1044af9419ddc048390c5974777ea97874e5b78e33c609e17eebb8423afb2"}, -] -django-picklefield = [ - {file = "django-picklefield-2.1.1.tar.gz", hash = "sha256:67a5e156343e3b032cac2f65565f0faa81635a99c7da74b0f07a0f5db467b646"}, - {file = "django_picklefield-2.1.1-py2.py3-none-any.whl", hash = "sha256:e03cb181b7161af38ad6b573af127e4fe9b7cc2c455b42c1ec43eaad525ade0a"}, -] -django-post-office = [ - {file = "django-post_office-3.3.1.tar.gz", hash = "sha256:d994bc0a87eb60a9d7c64d2c58a799fa72cad05eae19c4f13fbfa1ddb8bfda8d"}, - {file = "django_post_office-3.3.1-py3-none-any.whl", hash = "sha256:c2f92fb3ede727160d61cb8e0f190b8fd6e6192f089dbe121ee16257ce198cff"}, -] -django-redis = [ - {file = "django-redis-4.11.0.tar.gz", hash = "sha256:a5b1e3ffd3198735e6c529d9bdf38ca3fcb3155515249b98dc4d966b8ddf9d2b"}, - {file = "django_redis-4.11.0-py3-none-any.whl", hash = "sha256:e1aad4cc5bd743d8d0b13d5cae0cef5410eaace33e83bff5fc3a139ad8db50b4"}, -] -django-regex = [ - {file = "django-regex-0.4.1.tar.gz", hash = "sha256:3f85f4611a921299b86614591fb7b82201d1748ac6207b358bd8b1f2d2289513"}, -] -django-rest-framework-social-oauth2 = [ - {file = "django-rest-framework-social-oauth2-1.1.0.tar.gz", hash = "sha256:c9a297b636ffd37957c6146280e99ead41e6aca37bcb995e3d52d65eefbca0b7"}, -] -django-sql-explorer = [ - {file = "django-sql-explorer-1.1.3.tar.gz", hash = "sha256:b28f33750b7c1f1564644755dcffa393b75790598dc98ee155e487390855b967"}, -] -django-storages = [ - {file = "django-storages-1.9.1.tar.gz", hash = "sha256:a59e9923cbce7068792f75344ed7727021ee4ac20f227cf17297d0d03d141e91"}, - {file = "django_storages-1.9.1-py2.py3-none-any.whl", hash = "sha256:3103991c2ee8cef8a2ff096709973ffe7106183d211a79f22cf855f33533d924"}, -] -django-strategy-field = [ - {file = "django-strategy-field-2.0.tar.gz", hash = "sha256:fafd78f9d75a1edcfba2f9cae8f8f1b8609ebd9ec84c310f5eea6fc35ba21a9b"}, -] -django-sysinfo = [ - {file = "django-sysinfo-1.4.tar.gz", hash = "sha256:73844d6662ab7eb724d40f935aaef84bbe00cbe03a529bf263b54caf918b1c9c"}, -] -django-timezone-field = [ - {file = "django-timezone-field-4.0.tar.gz", hash = "sha256:7e3620fe2211c2d372fad54db8f86ff884098d018d56fda4dca5e64929e05ffc"}, - {file = "django_timezone_field-4.0-py3-none-any.whl", hash = "sha256:758b7d41084e9ea2e89e59eb616e9b6326e6fbbf9d14b6ef062d624fe8cc6246"}, -] -django-webtest = [ - {file = "django-webtest-1.9.7.tar.gz", hash = "sha256:c5a1e486a3d8d3623aa615b6db2f27de848aa7079303a84721e9a685f839796c"}, - {file = "django_webtest-1.9.7-py2.py3-none-any.whl", hash = "sha256:b9b4b94670c0ce533efc456d02dd55a0d0a7a8f7912eb30728dca2d59d7948b4"}, -] -djangorestframework = [ - {file = "djangorestframework-3.11.0-py3-none-any.whl", hash = "sha256:05809fc66e1c997fd9a32ea5730d9f4ba28b109b9da71fccfa5ff241201fd0a4"}, - {file = "djangorestframework-3.11.0.tar.gz", hash = "sha256:e782087823c47a26826ee5b6fa0c542968219263fb3976ec3c31edab23a4001f"}, -] -djangorestframework-csv = [ - {file = "djangorestframework-csv-2.1.0.tar.gz", hash = "sha256:2f008b20a44f2d3c37835ea5b5ddfe19f54394f07b9cb267c616a917a7f7e27c"}, -] -djangorestframework-gis = [ - {file = "djangorestframework_gis-0.15-py2.py3-none-any.whl", hash = "sha256:63c253528a107bc77cd71506cd639a0489b05b763fa7c3190cfd4622bf094594"}, -] -djangorestframework-jwt = [ - {file = "djangorestframework-jwt-1.11.0.tar.gz", hash = "sha256:5efe33032f3a4518a300dc51a51c92145ad95fb6f4b272e5aa24701db67936a7"}, - {file = "djangorestframework_jwt-1.11.0-py2.py3-none-any.whl", hash = "sha256:ab15dfbbe535eede8e2e53adaf52ef0cf018ee27dbfad10cbc4cbec2ab63d38c"}, -] -djangorestframework-xml = [ - {file = "djangorestframework-xml-1.4.0.tar.gz", hash = "sha256:d85d5744e75fe01ea2af667b15f6aa7df97c710516477ba493558da8432f6b0f"}, - {file = "djangorestframework_xml-1.4.0-py2.py3-none-any.whl", hash = "sha256:d8118580b6c0e94a6b908a78c8d842e9f349901dfff43d91adc2d73a54f4ba59"}, -] -djangorestframework-yaml = [ - {file = "djangorestframework-yaml-1.0.3.tar.gz", hash = "sha256:b2277cb0459cf14b473e8cb6e0055725582afe862049c32b840b261ca8fbce3e"}, - {file = "djangorestframework_yaml-1.0.3-py2.py3-none-any.whl", hash = "sha256:58e44b2ba2b1484fe793adcdc5d04910ab9b385a2991603b049b96eed6a76d32"}, -] -drf-api-checker = [ - {file = "drf-api-checker-0.8.2.tar.gz", hash = "sha256:fdb439c3c1a3d1fa9059526924892c12f5371952891eb0a233af52e63018f02a"}, -] -drf-dynamic-serializer = [ - {file = "drf-dynamic-serializer-2.1.tar.gz", hash = "sha256:ce4578bea4c27bc58fdfe11410c2ccf9b7ec1de44b8a83dd5b1c23399d1d1d84"}, -] -drf-extensions = [ - {file = "drf-extensions-0.6.0.tar.gz", hash = "sha256:9a76d59c8ecc2814860e94a0c96a26a824e392cd4550f2efa928af43c002a750"}, - {file = "drf_extensions-0.6.0-py2.py3-none-any.whl", hash = "sha256:a04cf188d27fdc13a1083a3ac9e4d72d3d93fcef76b3584191489c75d550c10d"}, -] -drf-renderer-xlsx = [ - {file = "drf-renderer-xlsx-0.3.7.tar.gz", hash = "sha256:b6805c1f1c0657c8fef2a1056c5ab26ec6c80581c622f175440d1e09dd1ab8d1"}, - {file = "drf_renderer_xlsx-0.3.7-py3-none-any.whl", hash = "sha256:95a825de15870a019175d95e76704bbd8fb4b6b0435d8b724531b95449325825"}, -] -drf-yasg = [ - {file = "drf-yasg-1.17.1.tar.gz", hash = "sha256:5572e9d5baab9f6b49318169df9789f7399d0e3c7bdac8fdb8dfccf1d5d2b1ca"}, - {file = "drf_yasg-1.17.1-py2.py3-none-any.whl", hash = "sha256:7d7af27ad16e18507e9392b2afd6b218fbffc432ec8dbea053099a2241e184ff"}, -] -entrypoints = [ - {file = "entrypoints-0.3-py2.py3-none-any.whl", hash = "sha256:589f874b313739ad35be6e0cd7efde2a4e9b6fea91edcc34e58ecbb8dbe56d19"}, - {file = "entrypoints-0.3.tar.gz", hash = "sha256:c70dd71abe5a8c85e55e12c19bd91ccfeec11a6e99044204511f9ed547d48451"}, -] -et-xmlfile = [ - {file = "et_xmlfile-1.0.1.tar.gz", hash = "sha256:614d9722d572f6246302c4491846d2c393c199cfa4edc9af593437691683335b"}, -] -factory-boy = [ - {file = "factory_boy-2.12.0-py2.py3-none-any.whl", hash = "sha256:728df59b372c9588b83153facf26d3d28947fc750e8e3c95cefa9bed0e6394ee"}, - {file = "factory_boy-2.12.0.tar.gz", hash = "sha256:faf48d608a1735f0d0a3c9cbf536d64f9132b547dae7ba452c4d99a79e84a370"}, -] -faker = [ - {file = "Faker-4.0.2-py3-none-any.whl", hash = "sha256:b89aa33837498498e15c709eb40c31386408a901a53c7a5e12a425737a767976"}, - {file = "Faker-4.0.2.tar.gz", hash = "sha256:2d3f866ef25e1a5af80e7b0ceeacc3c92dec5d0fdbad3e2cb6adf6e60b22188f"}, -] -filelock = [ - {file = "filelock-3.0.12-py3-none-any.whl", hash = "sha256:929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836"}, - {file = "filelock-3.0.12.tar.gz", hash = "sha256:18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59"}, -] -flake8 = [ - {file = "flake8-3.7.9-py2.py3-none-any.whl", hash = "sha256:49356e766643ad15072a789a20915d3c91dc89fd313ccd71802303fd67e4deca"}, - {file = "flake8-3.7.9.tar.gz", hash = "sha256:45681a117ecc81e870cbf1262835ae4af5e7a8b08e40b944a8a6e6b895914cfb"}, -] -freezegun = [ - {file = "freezegun-0.3.15-py2.py3-none-any.whl", hash = "sha256:82c757a05b7c7ca3e176bfebd7d6779fd9139c7cb4ef969c38a28d74deef89b2"}, - {file = "freezegun-0.3.15.tar.gz", hash = "sha256:e2062f2c7f95cc276a834c22f1a17179467176b624cc6f936e8bc3be5535ad1b"}, -] -html5lib = [ - {file = "html5lib-1.0.1-py2.py3-none-any.whl", hash = "sha256:20b159aa3badc9d5ee8f5c647e5efd02ed2a66ab8d354930bd9ff139fc1dc0a3"}, - {file = "html5lib-1.0.1.tar.gz", hash = "sha256:66cb0dcfdbbc4f9c3ba1a63fdb511ffdbd4f513b2b6d81b80cd26ce6b3fb3736"}, -] -humanfriendly = [ - {file = "humanfriendly-8.1-py2.py3-none-any.whl", hash = "sha256:3a831920e40e55ad49adb64c9179ed50c604cabca72cd300e7bd5b51310e4ebb"}, - {file = "humanfriendly-8.1.tar.gz", hash = "sha256:25c2108a45cfd1e8fbe9cdb30b825d34ef5d5675c8e11e4775c9aedbfb0bdee2"}, -] -humanize = [ - {file = "humanize-2.2.0-py3-none-any.whl", hash = "sha256:0b3157df0f3fcdcb7611180d305a23fd4b6290eb23586e058762f8576348fbab"}, - {file = "humanize-2.2.0.tar.gz", hash = "sha256:de8ef6ffee618a9d369b3d1fb1359780ccaa2cc76a0e777c6ff21f04d19a0eb8"}, -] -identify = [ - {file = "identify-1.4.13-py2.py3-none-any.whl", hash = "sha256:a7577a1f55cee1d21953a5cf11a3c839ab87f5ef909a4cba6cf52ed72b4c6059"}, - {file = "identify-1.4.13.tar.gz", hash = "sha256:ab246293e6585a1c6361a505b68d5b501a0409310932b7de2c2ead667b564d89"}, -] -idna = [ - {file = "idna-2.9-py2.py3-none-any.whl", hash = "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"}, - {file = "idna-2.9.tar.gz", hash = "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb"}, -] -importlib-metadata = [ - {file = "importlib_metadata-1.6.0-py2.py3-none-any.whl", hash = "sha256:2a688cbaa90e0cc587f1df48bdc97a6eadccdcd9c35fb3f976a09e3b5016d90f"}, - {file = "importlib_metadata-1.6.0.tar.gz", hash = "sha256:34513a8a0c4962bc66d35b359558fd8a5e10cd472d37aec5f66858addef32c1e"}, -] -inflection = [ - {file = "inflection-0.3.1.tar.gz", hash = "sha256:18ea7fb7a7d152853386523def08736aa8c32636b047ade55f7578c4edeb16ca"}, -] -ipdb = [ - {file = "ipdb-0.13.2.tar.gz", hash = "sha256:77fb1c2a6fccdfee0136078c9ed6fe547ab00db00bebff181f1e8c9e13418d49"}, -] -ipython = [ - {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"}, - {file = "ipython_genutils-0.2.0.tar.gz", hash = "sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8"}, -] -iso8601 = [ - {file = "iso8601-0.1.12-py2.py3-none-any.whl", hash = "sha256:210e0134677cc0d02f6028087fee1df1e1d76d372ee1db0bf30bf66c5c1c89a3"}, - {file = "iso8601-0.1.12-py3-none-any.whl", hash = "sha256:bbbae5fb4a7abfe71d4688fd64bff70b91bbd74ef6a99d964bab18f7fdf286dd"}, - {file = "iso8601-0.1.12.tar.gz", hash = "sha256:49c4b20e1f38aa5cf109ddcd39647ac419f928512c869dc01d5c7098eddede82"}, -] -isort = [ - {file = "isort-4.3.21-py2.py3-none-any.whl", hash = "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd"}, - {file = "isort-4.3.21.tar.gz", hash = "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1"}, -] -itypes = [ - {file = "itypes-1.1.0.tar.gz", hash = "sha256:c6e77bb9fd68a4bfeb9d958fea421802282451a25bac4913ec94db82a899c073"}, -] -jdcal = [ - {file = "jdcal-1.4.1-py2.py3-none-any.whl", hash = "sha256:1abf1305fce18b4e8aa248cf8fe0c56ce2032392bc64bbd61b5dff2a19ec8bba"}, - {file = "jdcal-1.4.1.tar.gz", hash = "sha256:472872e096eb8df219c23f2689fc336668bdb43d194094b5cc1707e1640acfc8"}, -] -jedi = [ - {file = "jedi-0.16.0-py2.py3-none-any.whl", hash = "sha256:b4f4052551025c6b0b0b193b29a6ff7bdb74c52450631206c262aef9f7159ad2"}, - {file = "jedi-0.16.0.tar.gz", hash = "sha256:d5c871cb9360b414f981e7072c52c33258d598305280fef91c6cae34739d65d5"}, -] -jinja2 = [ - {file = "Jinja2-2.11.1-py2.py3-none-any.whl", hash = "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49"}, - {file = "Jinja2-2.11.1.tar.gz", hash = "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250"}, -] -jsonfield = [ - {file = "jsonfield-3.1.0-py3-none-any.whl", hash = "sha256:df857811587f252b97bafba42e02805e70a398a7a47870bc6358a0308dd689ed"}, - {file = "jsonfield-3.1.0.tar.gz", hash = "sha256:7e4e84597de21eeaeeaaa7cc5da08c61c48a9b64d0c446b2d71255d01812887a"}, -] -jsonschema = [ - {file = "jsonschema-3.2.0-py2.py3-none-any.whl", hash = "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163"}, - {file = "jsonschema-3.2.0.tar.gz", hash = "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"}, -] -kombu = [ - {file = "kombu-4.6.8-py2.py3-none-any.whl", hash = "sha256:598e7e749d6ab54f646b74b2d2df67755dee13894f73ab02a2a9feb8870c7cb2"}, - {file = "kombu-4.6.8.tar.gz", hash = "sha256:2d1cda774126a044d91a7ff5fa6d09edf99f46924ab332a810760fe6740e9b76"}, -] -markdown = [ - {file = "Markdown-3.2.1-py2.py3-none-any.whl", hash = "sha256:e4795399163109457d4c5af2183fbe6b60326c17cfdf25ce6e7474c6624f725d"}, - {file = "Markdown-3.2.1.tar.gz", hash = "sha256:90fee683eeabe1a92e149f7ba74e5ccdc81cd397bd6c516d93a8da0ef90b6902"}, -] -markupsafe = [ - {file = "MarkupSafe-1.1.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161"}, - {file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"}, - {file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183"}, - {file = "MarkupSafe-1.1.1-cp27-cp27m-win32.whl", hash = "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b"}, - {file = "MarkupSafe-1.1.1-cp27-cp27m-win_amd64.whl", hash = "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e"}, - {file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f"}, - {file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1"}, - {file = "MarkupSafe-1.1.1-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5"}, - {file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1"}, - {file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735"}, - {file = "MarkupSafe-1.1.1-cp34-cp34m-win32.whl", hash = "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21"}, - {file = "MarkupSafe-1.1.1-cp34-cp34m-win_amd64.whl", hash = "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235"}, - {file = "MarkupSafe-1.1.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b"}, - {file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f"}, - {file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905"}, - {file = "MarkupSafe-1.1.1-cp35-cp35m-win32.whl", hash = "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1"}, - {file = "MarkupSafe-1.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d"}, - {file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff"}, - {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473"}, - {file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e"}, - {file = "MarkupSafe-1.1.1-cp36-cp36m-win32.whl", hash = "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66"}, - {file = "MarkupSafe-1.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5"}, - {file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d"}, - {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e"}, - {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"}, - {file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"}, - {file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"}, - {file = "MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15"}, - {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2"}, - {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42"}, - {file = "MarkupSafe-1.1.1-cp38-cp38-win32.whl", hash = "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b"}, - {file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"}, - {file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"}, -] -mccabe = [ - {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, - {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, -] -more-itertools = [ - {file = "more-itertools-8.2.0.tar.gz", hash = "sha256:b1ddb932186d8a6ac451e1d95844b382f55e12686d51ca0c68b6f61f2ab7a507"}, - {file = "more_itertools-8.2.0-py3-none-any.whl", hash = "sha256:5dd8bcf33e5f9513ffa06d5ad33d78f31e1931ac9a18f33d37e77a180d393a7c"}, -] -multidict = [ - {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"}, -] -nodeenv = [ - {file = "nodeenv-1.3.5-py2.py3-none-any.whl", hash = "sha256:5b2438f2e42af54ca968dd1b374d14a1194848955187b0e5e4be1f73813a5212"}, -] -oauthlib = [ - {file = "oauthlib-3.1.0-py2.py3-none-any.whl", hash = "sha256:df884cd6cbe20e32633f1db1072e9356f53638e4361bef4e8b03c9127c9328ea"}, - {file = "oauthlib-3.1.0.tar.gz", hash = "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889"}, -] -openpyxl = [ - {file = "openpyxl-3.0.3.tar.gz", hash = "sha256:547a9fc6aafcf44abe358b89ed4438d077e9d92e4f182c87e2dc294186dc4b64"}, -] -packaging = [ - {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.2-py2.py3-none-any.whl", hash = "sha256:8515fc12cfca6ee3aa59138741fc5624d62340c97e401c74875769948d4f2995"}, - {file = "parso-0.6.2.tar.gz", hash = "sha256:0c5659e0c6eba20636f99a04f469798dca8da279645ce5c387315b2c23912157"}, -] -pep517 = [ - {file = "pep517-0.8.1-py2.py3-none-any.whl", hash = "sha256:882e2eeeffe39ccd6be6122d98300df18d80950cb5f449766d64149c94c5614a"}, - {file = "pep517-0.8.1.tar.gz", hash = "sha256:5ce351f3be71d01bb094d63253854b6139931fcaba8e2f380c02102136c51e40"}, -] -pexpect = [ - {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, - {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, -] -pickleshare = [ - {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, - {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, -] -pillow = [ - {file = "Pillow-7.0.0-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:5f3546ceb08089cedb9e8ff7e3f6a7042bb5b37c2a95d392fb027c3e53a2da00"}, - {file = "Pillow-7.0.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:9d2ba4ed13af381233e2d810ff3bab84ef9f18430a9b336ab69eaf3cd24299ff"}, - {file = "Pillow-7.0.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:ff3797f2f16bf9d17d53257612da84dd0758db33935777149b3334c01ff68865"}, - {file = "Pillow-7.0.0-cp35-cp35m-win32.whl", hash = "sha256:c18f70dc27cc5d236f10e7834236aff60aadc71346a5bc1f4f83a4b3abee6386"}, - {file = "Pillow-7.0.0-cp35-cp35m-win_amd64.whl", hash = "sha256:875358310ed7abd5320f21dd97351d62de4929b0426cdb1eaa904b64ac36b435"}, - {file = "Pillow-7.0.0-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:ab76e5580b0ed647a8d8d2d2daee170e8e9f8aad225ede314f684e297e3643c2"}, - {file = "Pillow-7.0.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a62ec5e13e227399be73303ff301f2865bf68657d15ea50b038d25fc41097317"}, - {file = "Pillow-7.0.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8ac6ce7ff3892e5deaab7abaec763538ffd011f74dc1801d93d3c5fc541feee2"}, - {file = "Pillow-7.0.0-cp36-cp36m-win32.whl", hash = "sha256:91b710e3353aea6fc758cdb7136d9bbdcb26b53cefe43e2cba953ac3ee1d3313"}, - {file = "Pillow-7.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:bf598d2e37cf8edb1a2f26ed3fb255191f5232badea4003c16301cb94ac5bdd0"}, - {file = "Pillow-7.0.0-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:5bfef0b1cdde9f33881c913af14e43db69815c7e8df429ceda4c70a5e529210f"}, - {file = "Pillow-7.0.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:dc058b7833184970d1248135b8b0ab702e6daa833be14035179f2acb78ff5636"}, - {file = "Pillow-7.0.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:c5ed816632204a2fc9486d784d8e0d0ae754347aba99c811458d69fcdfd2a2f9"}, - {file = "Pillow-7.0.0-cp37-cp37m-win32.whl", hash = "sha256:54ebae163e8412aff0b9df1e88adab65788f5f5b58e625dc5c7f51eaf14a6837"}, - {file = "Pillow-7.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:87269cc6ce1e3dee11f23fa515e4249ae678dbbe2704598a51cee76c52e19cda"}, - {file = "Pillow-7.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0a628977ac2e01ca96aaae247ec2bd38e729631ddf2221b4b715446fd45505be"}, - {file = "Pillow-7.0.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:62a889aeb0a79e50ecf5af272e9e3c164148f4bd9636cc6bcfa182a52c8b0533"}, - {file = "Pillow-7.0.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:bf4003aa538af3f4205c5fac56eacaa67a6dd81e454ffd9e9f055fff9f1bc614"}, - {file = "Pillow-7.0.0-cp38-cp38-win32.whl", hash = "sha256:7406f5a9b2fd966e79e6abdaf700585a4522e98d6559ce37fc52e5c955fade0a"}, - {file = "Pillow-7.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:5f7ae9126d16194f114435ebb79cc536b5682002a4fa57fa7bb2cbcde65f2f4d"}, - {file = "Pillow-7.0.0-pp373-pypy36_pp73-win32.whl", hash = "sha256:8453f914f4e5a3d828281a6628cf517832abfa13ff50679a4848926dac7c0358"}, - {file = "Pillow-7.0.0.tar.gz", hash = "sha256:4d9ed9a64095e031435af120d3c910148067087541131e82b3e8db302f4c8946"}, -] -pluggy = [ - {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, - {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, -] -pre-commit = [ - {file = "pre_commit-2.0.1-py2.py3-none-any.whl", hash = "sha256:0385479a0fe0765b1d32241f6b5358668cb4b6496a09aaf9c79acc6530489dbb"}, - {file = "pre_commit-2.0.1.tar.gz", hash = "sha256:bf80d9dd58bea4f45d5d71845456fdcb78c1027eda9ed562db6fa2bd7a680c3a"}, -] -prompt-toolkit = [ - {file = "prompt_toolkit-3.0.5-py3-none-any.whl", hash = "sha256:df7e9e63aea609b1da3a65641ceaf5bc7d05e0a04de5bd45d05dbeffbabf9e04"}, - {file = "prompt_toolkit-3.0.5.tar.gz", hash = "sha256:563d1a4140b63ff9dd587bda9557cffb2fe73650205ab6f4383092fb882e7dc8"}, -] -psutil = [ - {file = "psutil-5.7.0-cp27-none-win32.whl", hash = "sha256:298af2f14b635c3c7118fd9183843f4e73e681bb6f01e12284d4d70d48a60953"}, - {file = "psutil-5.7.0-cp27-none-win_amd64.whl", hash = "sha256:75e22717d4dbc7ca529ec5063000b2b294fc9a367f9c9ede1f65846c7955fd38"}, - {file = "psutil-5.7.0-cp35-cp35m-win32.whl", hash = "sha256:f344ca230dd8e8d5eee16827596f1c22ec0876127c28e800d7ae20ed44c4b310"}, - {file = "psutil-5.7.0-cp35-cp35m-win_amd64.whl", hash = "sha256:e2d0c5b07c6fe5a87fa27b7855017edb0d52ee73b71e6ee368fae268605cc3f5"}, - {file = "psutil-5.7.0-cp36-cp36m-win32.whl", hash = "sha256:a02f4ac50d4a23253b68233b07e7cdb567bd025b982d5cf0ee78296990c22d9e"}, - {file = "psutil-5.7.0-cp36-cp36m-win_amd64.whl", hash = "sha256:1413f4158eb50e110777c4f15d7c759521703bd6beb58926f1d562da40180058"}, - {file = "psutil-5.7.0-cp37-cp37m-win32.whl", hash = "sha256:d008ddc00c6906ec80040d26dc2d3e3962109e40ad07fd8a12d0284ce5e0e4f8"}, - {file = "psutil-5.7.0-cp37-cp37m-win_amd64.whl", hash = "sha256:73f35ab66c6c7a9ce82ba44b1e9b1050be2a80cd4dcc3352cc108656b115c74f"}, - {file = "psutil-5.7.0-cp38-cp38-win32.whl", hash = "sha256:60b86f327c198561f101a92be1995f9ae0399736b6eced8f24af41ec64fb88d4"}, - {file = "psutil-5.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:d84029b190c8a66a946e28b4d3934d2ca1528ec94764b180f7d6ea57b0e75e26"}, - {file = "psutil-5.7.0.tar.gz", hash = "sha256:685ec16ca14d079455892f25bd124df26ff9137664af445563c1bd36629b5e0e"}, -] -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"}, -] -ptyprocess = [ - {file = "ptyprocess-0.6.0-py2.py3-none-any.whl", hash = "sha256:d7cc528d76e76342423ca640335bd3633420dc1366f258cb31d05e865ef5ca1f"}, - {file = "ptyprocess-0.6.0.tar.gz", hash = "sha256:923f299cc5ad920c68f2bc0bc98b75b9f838b93b599941a6b63ddbc2476394c0"}, -] -py = [ - {file = "py-1.8.1-py2.py3-none-any.whl", hash = "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0"}, - {file = "py-1.8.1.tar.gz", hash = "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa"}, -] -pycodestyle = [ - {file = "pycodestyle-2.5.0-py2.py3-none-any.whl", hash = "sha256:95a2219d12372f05704562a14ec30bc76b05a5b297b21a5dfe3f6fac3491ae56"}, - {file = "pycodestyle-2.5.0.tar.gz", hash = "sha256:e40a936c9a450ad81df37f549d676d127b1b66000a6c500caa2b085bc0ca976c"}, -] -pycparser = [ - {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, - {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, -] -pyflakes = [ - {file = "pyflakes-2.1.1-py2.py3-none-any.whl", hash = "sha256:17dbeb2e3f4d772725c777fabc446d5634d1038f234e77343108ce445ea69ce0"}, - {file = "pyflakes-2.1.1.tar.gz", hash = "sha256:d976835886f8c5b31d47970ed689944a0262b5f3afa00a5a7b4dc81e5449f8a2"}, -] -pygments = [ - {file = "Pygments-2.6.1-py3-none-any.whl", hash = "sha256:ff7a40b4860b727ab48fad6360eb351cc1b33cbf9b15a0f689ca5353e9463324"}, - {file = "Pygments-2.6.1.tar.gz", hash = "sha256:647344a061c249a3b74e230c739f434d7ea4d8b1d5f3721bc0f3558049b38f44"}, -] -pyjwt = [ - {file = "PyJWT-1.7.1-py2.py3-none-any.whl", hash = "sha256:5c6eca3c2940464d106b99ba83b00c6add741c9becaec087fb7ccdefea71350e"}, - {file = "PyJWT-1.7.1.tar.gz", hash = "sha256:8d59a976fb773f3e6a39c85636357c4f0e242707394cadadd9814f5cbaa20e96"}, -] -pyparsing = [ - {file = "pyparsing-2.4.6-py2.py3-none-any.whl", hash = "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec"}, - {file = "pyparsing-2.4.6.tar.gz", hash = "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f"}, -] -pypdf2 = [ - {file = "PyPDF2-1.26.0.tar.gz", hash = "sha256:e28f902f2f0a1603ea95ebe21dff311ef09be3d0f0ef29a3e44a932729564385"}, -] -pyreadline = [ - {file = "pyreadline-2.1.win-amd64.exe", hash = "sha256:9ce5fa65b8992dfa373bddc5b6e0864ead8f291c94fbfec05fbd5c836162e67b"}, - {file = "pyreadline-2.1.win32.exe", hash = "sha256:65540c21bfe14405a3a77e4c085ecfce88724743a4ead47c66b84defcf82c32e"}, - {file = "pyreadline-2.1.zip", hash = "sha256:4530592fc2e85b25b1a9f79664433da09237c1a270e4d78ea5aa3a2c7229e2d1"}, -] -pyrsistent = [ - {file = "pyrsistent-0.16.0.tar.gz", hash = "sha256:28669905fe725965daa16184933676547c5bb40a5153055a8dee2a4bd7933ad3"}, -] -pytest = [ - {file = "pytest-4.6.9-py2.py3-none-any.whl", hash = "sha256:c77a5f30a90e0ce24db9eaa14ddfd38d4afb5ea159309bdd2dae55b931bc9324"}, - {file = "pytest-4.6.9.tar.gz", hash = "sha256:19e8f75eac01dd3f211edd465b39efbcbdc8fc5f7866d7dd49fedb30d8adf339"}, -] -pytest-cov = [ - {file = "pytest-cov-2.8.1.tar.gz", hash = "sha256:cc6742d8bac45070217169f5f72ceee1e0e55b0221f54bcf24845972d3a47f2b"}, - {file = "pytest_cov-2.8.1-py2.py3-none-any.whl", hash = "sha256:cdbdef4f870408ebdbfeb44e63e07eb18bb4619fae852f6e760645fa36172626"}, -] -pytest-cover = [ - {file = "pytest-cover-3.0.0.tar.gz", hash = "sha256:5bdb6c1cc3dd75583bb7bc2c57f5e1034a1bfcb79d27c71aceb0b16af981dbf4"}, - {file = "pytest_cover-3.0.0-py2.py3-none-any.whl", hash = "sha256:578249955eb3b5f3991209df6e532bb770b647743b7392d3d97698dc02f39ebb"}, -] -pytest-coverage = [ - {file = "pytest-coverage-0.0.tar.gz", hash = "sha256:db6af2cbd7e458c7c9fd2b4207cee75258243c8a81cad31a7ee8cfad5be93c05"}, - {file = "pytest_coverage-0.0-py2.py3-none-any.whl", hash = "sha256:dedd084c5e74d8e669355325916dc011539b190355021b037242514dee546368"}, -] -pytest-django = [ - {file = "pytest-django-3.9.0.tar.gz", hash = "sha256:664e5f42242e5e182519388f01b9f25d824a9feb7cd17d8f863c8d776f38baf9"}, - {file = "pytest_django-3.9.0-py2.py3-none-any.whl", hash = "sha256:64f99d565dd9497af412fcab2989fe40982c1282d4118ff422b407f3f7275ca5"}, -] -pytest-echo = [ - {file = "pytest-echo-1.7.1.tar.gz", hash = "sha256:3bf6a065ca624a5915bc2a820505a44735a8aa11865a57d8214d4eac18960191"}, -] -pytest-ignore-flaky = [ - {file = "pytest-ignore-flaky-1.0.0.tar.gz", hash = "sha256:29b3099cf4d424fd553d39940f7025acf6847ecbba292649a0dc764dfbb7d59e"}, - {file = "pytest_ignore_flaky-1.0.0-py3-none-any.whl", hash = "sha256:fe33a1f725a78e1f92077bfb80926602622bc050a0a71b61c3f1ca7089afb779"}, -] -pytest-pythonpath = [ - {file = "pytest-pythonpath-0.7.3.tar.gz", hash = "sha256:63fc546ace7d2c845c1ee289e8f7a6362c2b6bae497d10c716e58e253e801d62"}, -] -python-crontab = [ - {file = "python-crontab-2.4.1.tar.gz", hash = "sha256:2366c7aa373118315de7c082401907bacd28e8b1e4e0a6d702334d17b89e71aa"}, -] -python-dateutil = [ - {file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"}, - {file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"}, -] -python-social-auth = [ - {file = "python-social-auth-0.3.6.tar.gz", hash = "sha256:6986220df76934aee15c54938a13ebe370a1976e043af01fa3bea417f6722e74"}, - {file = "python_social_auth-0.3.6-py2-none-any.whl", hash = "sha256:9aaad6f7bf83fd129620eadaab1e78e63200da61a5d8898fd1aa243686b36575"}, - {file = "python_social_auth-0.3.6-py3-none-any.whl", hash = "sha256:8aac8531f7dd4d1b9af606654532fef4f615cb437774a7a1f8dcdebe89c17664"}, -] -python3-openid = [ - {file = "python3-openid-3.1.0.tar.gz", hash = "sha256:628d365d687e12da12d02c6691170f4451db28d6d68d050007e4a40065868502"}, - {file = "python3_openid-3.1.0-py3-none-any.whl", hash = "sha256:0086da6b6ef3161cfe50fb1ee5cceaf2cda1700019fda03c2c5c440ca6abe4fa"}, -] -pytz = [ - {file = "pytz-2019.3-py2.py3-none-any.whl", hash = "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d"}, - {file = "pytz-2019.3.tar.gz", hash = "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"}, -] -pyyaml = [ - {file = "PyYAML-4.2b4-cp27-cp27m-win32.whl", hash = "sha256:8d6d96001aa7f0a6a4a95e8143225b5d06e41b1131044913fecb8f85a125714b"}, - {file = "PyYAML-4.2b4-cp27-cp27m-win_amd64.whl", hash = "sha256:c8a88edd93ee29ede719080b2be6cb2333dfee1dccba213b422a9c8e97f2967b"}, - {file = "PyYAML-4.2b4-cp34-cp34m-win32.whl", hash = "sha256:3108529b78577327d15eec243f0ff348a0640b0c3478d67ad7f5648f93bac3e2"}, - {file = "PyYAML-4.2b4-cp34-cp34m-win_amd64.whl", hash = "sha256:254bf6fda2b7c651837acb2c718e213df29d531eebf00edb54743d10bcb694eb"}, - {file = "PyYAML-4.2b4.tar.gz", hash = "sha256:3c17fb92c8ba2f525e4b5f7941d850e7a48c3a59b32d331e2502a3cdc6648e76"}, - {file = "PyYAML-4.2b4.win-amd64-py2.7.exe", hash = "sha256:be622cc81696e24d0836ba71f6272a2b5767669b0d79fdcf0295d51ac2e156c8"}, - {file = "PyYAML-4.2b4.win-amd64-py3.4.exe", hash = "sha256:f39411e380e2182ad33be039e8ee5770a5d9efe01a2bfb7ae58d9ba31c4a2a9d"}, - {file = "PyYAML-4.2b4.win32-py2.7.exe", hash = "sha256:1cbc199009e78f92d9edf554be4fe40fb7b0bef71ba688602a00e97a51909110"}, - {file = "PyYAML-4.2b4.win32-py3.4.exe", hash = "sha256:6f89b5c95e93945b597776163403d47af72d243f366bf4622ff08bdfd1c950b7"}, -] -pyzmq = [ - {file = "pyzmq-19.0.0-cp27-cp27m-macosx_10_9_intel.whl", hash = "sha256:3f12ce1e9cc9c31497bd82b207e8e86ccda9eebd8c9f95053aae46d15ccd2196"}, - {file = "pyzmq-19.0.0-cp27-cp27m-win32.whl", hash = "sha256:e8e4efb52ec2df8d046395ca4c84ae0056cf507b2f713ec803c65a8102d010de"}, - {file = "pyzmq-19.0.0-cp27-cp27m-win_amd64.whl", hash = "sha256:f5b6d015587a1d6f582ba03b226a9ddb1dfb09878b3be04ef48b01b7d4eb6b2a"}, - {file = "pyzmq-19.0.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:bb10361293d96aa92be6261fa4d15476bca56203b3a11c62c61bd14df0ef89ba"}, - {file = "pyzmq-19.0.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:4557d5e036e6d85715b4b9fdb482081398da1d43dc580d03db642b91605b409f"}, - {file = "pyzmq-19.0.0-cp35-cp35m-macosx_10_9_intel.whl", hash = "sha256:84b91153102c4bcf5d0f57d1a66a0f03c31e9e6525a5f656f52fc615a675c748"}, - {file = "pyzmq-19.0.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:6aaaf90b420dc40d9a0e1996b82c6a0ff91d9680bebe2135e67c9e6d197c0a53"}, - {file = "pyzmq-19.0.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:ad48865a29efa8a0cecf266432ea7bc34e319954e55cf104be0319c177e6c8f5"}, - {file = "pyzmq-19.0.0-cp35-cp35m-win32.whl", hash = "sha256:32234c21c5e0a767c754181c8112092b3ddd2e2a36c3f76fc231ced817aeee47"}, - {file = "pyzmq-19.0.0-cp35-cp35m-win_amd64.whl", hash = "sha256:f37c29da2a5b0c5e31e6f8aab885625ea76c807082f70b2d334d3fd573c3100a"}, - {file = "pyzmq-19.0.0-cp36-cp36m-macosx_10_9_intel.whl", hash = "sha256:1e076ad5bd3638a18c376544d32e0af986ca10d43d4ce5a5d889a8649f0d0a3d"}, - {file = "pyzmq-19.0.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:f4d558bc5668d2345773a9ff8c39e2462dafcb1f6772a2e582fbced389ce527f"}, - {file = "pyzmq-19.0.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4f562dab21c03c7aa061f63b147a595dbe1006bf4f03213272fc9f7d5baec791"}, - {file = "pyzmq-19.0.0-cp36-cp36m-win32.whl", hash = "sha256:7f7e7b24b1d392bb5947ba91c981e7d1a43293113642e0d8870706c8e70cdc71"}, - {file = "pyzmq-19.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:75238d3c16cab96947705d5709187a49ebb844f54354cdf0814d195dd4c045de"}, - {file = "pyzmq-19.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cb3b7156ef6b1a119e68fbe3a54e0a0c40ecacc6b7838d57dd708c90b62a06dc"}, - {file = "pyzmq-19.0.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:a99ae601b4f6917985e9bb071549e30b6f93c72f5060853e197bdc4b7d357e5f"}, - {file = "pyzmq-19.0.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:242d949eb6b10197cda1d1cec377deab1d5324983d77e0d0bf9dc5eb6d71a6b4"}, - {file = "pyzmq-19.0.0-cp37-cp37m-win32.whl", hash = "sha256:a49fd42a29c1cc1aa9f461c5f2f5e0303adba7c945138b35ee7f4ab675b9f754"}, - {file = "pyzmq-19.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:5f10a31f288bf055be76c57710807a8f0efdb2b82be6c2a2b8f9a61f33a40cea"}, - {file = "pyzmq-19.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:26f4ae420977d2a8792d7c2d7bda43128b037b5eeb21c81951a94054ad8b8843"}, - {file = "pyzmq-19.0.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:944f6bb5c63140d76494467444fd92bebd8674236837480a3c75b01fe17df1ab"}, - {file = "pyzmq-19.0.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:b08e425cf93b4e018ab21dc8fdbc25d7d0502a23cc4fea2380010cf8cf11e462"}, - {file = "pyzmq-19.0.0-cp38-cp38-win32.whl", hash = "sha256:a1f957c20c9f51d43903881399b078cddcf710d34a2950e88bce4e494dcaa4d1"}, - {file = "pyzmq-19.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:bd1a769d65257a7a12e2613070ca8155ee348aa9183f2aadf1c8b8552a5510f5"}, - {file = "pyzmq-19.0.0-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:0bbc1728fe4314b4ca46249c33873a390559edac7c217ec7001b5e0c34a8fb7f"}, - {file = "pyzmq-19.0.0-pp36-pypy36_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5e071b834051e9ecb224915398f474bfad802c2fff883f118ff5363ca4ae3edf"}, - {file = "pyzmq-19.0.0.tar.gz", hash = "sha256:5e1f65e576ab07aed83f444e201d86deb01cd27dcf3f37c727bc8729246a60a8"}, -] -rapidpro-python = [ - {file = "rapidpro-python-2.7.0.tar.gz", hash = "sha256:06c9c19960ea46ddb7ce7a9074971a256394ed42ea599492801cfe701eb497ca"}, - {file = "rapidpro_python-2.7.0-py2.py3-none-any.whl", hash = "sha256:ccaa3c067fccb5ff22653938a92e4ef819026ad4e74e7149ff9735ee7a0316a9"}, -] -raven = [ - {file = "raven-6.10.0-py2.py3-none-any.whl", hash = "sha256:44a13f87670836e153951af9a3c80405d36b43097db869a36e92809673692ce4"}, - {file = "raven-6.10.0.tar.gz", hash = "sha256:3fa6de6efa2493a7c827472e984ce9b020797d0da16f1db67197bcc23c8fae54"}, -] -redis = [ - {file = "redis-3.4.1-py2.py3-none-any.whl", hash = "sha256:b205cffd05ebfd0a468db74f0eedbff8df1a7bfc47521516ade4692991bb0833"}, - {file = "redis-3.4.1.tar.gz", hash = "sha256:0dcfb335921b88a850d461dc255ff4708294943322bd55de6cfd68972490ca1f"}, -] -reportlab = [ - {file = "reportlab-3.5.42-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:64f7cfa75b9b9a1eebf2a3fe5667a01953e1cb8946b0d14f165b9381ec2fdbaf"}, - {file = "reportlab-3.5.42-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:ef817701f45bb6974cfc0a488fd9a76c4190948c456234490174d1f2112b0a2c"}, - {file = "reportlab-3.5.42-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:2ac6bf19ecc60149895273932910b7cde61bcfc6701326094078eee489265de5"}, - {file = "reportlab-3.5.42-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:e326b2d48ccaf17322f86c23cd78900e50facf27b93ce50e4a2902a5f31ac343"}, - {file = "reportlab-3.5.42-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:7c36e52452147e64a48a05ac56340b45aa3f0c64f2b2e38145ea15190c369621"}, - {file = "reportlab-3.5.42-cp27-cp27m-win32.whl", hash = "sha256:5d851a20981e6ea29b643e59807997ca96ceeded4bf431ba9618171d8e383091"}, - {file = "reportlab-3.5.42-cp27-cp27m-win_amd64.whl", hash = "sha256:6d6815a925c071a0b887c968d39527e9b3db962a151d2aabdd954beafd4431ad"}, - {file = "reportlab-3.5.42-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:39ae8212a07a18f0e3ee0a3bca6e5a37abac470f934e5a1a117209f989618373"}, - {file = "reportlab-3.5.42-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:3ea95bcfcba08eb4030e3b62efc01ff9e547eea7887311f00685c729cabce038"}, - {file = "reportlab-3.5.42-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:c14de6b939ad2ea63e4149e3e4eae1089e20afae1ef805345f73193f25ac9e5f"}, - {file = "reportlab-3.5.42-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:31feebbfd476201e82aecf750201acb1ea7d3b29217d2e0ca0a297d1189a78af"}, - {file = "reportlab-3.5.42-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:bd1c855249f5508a50e3ddc7b4e957e4a537597bd41e66e71bdc027bbcfa7534"}, - {file = "reportlab-3.5.42-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:072da175f9586fd0457242d7eb4ccf8284b65f8c4ec33ec4fa39c511ca2c6e10"}, - {file = "reportlab-3.5.42-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:8194698254932234a1164694a5b8c84d8010db6ff71a8985c6133d21ed9767ea"}, - {file = "reportlab-3.5.42-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:e6c3fc2866b853b6b9d4b5d79cfff89c5687fc70a155a05dcfdd278747d441db"}, - {file = "reportlab-3.5.42-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:d144680292a868cbfe02db25eecbf53623af02e42ff05822439f1434156e7863"}, - {file = "reportlab-3.5.42-cp35-cp35m-win32.whl", hash = "sha256:5a8430eed5fc7d15c868fdf5673c94440710e7d1a77ea5bbd4f634e3e6fb5f9c"}, - {file = "reportlab-3.5.42-cp35-cp35m-win_amd64.whl", hash = "sha256:6e6e3041b742a73c71c0dc49875524338998cbf6a498077e40d4589f8448f3ed"}, - {file = "reportlab-3.5.42-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ab6acd99073081d708339e26475e93fe48139233a2ab7f43fc54560e1e00155a"}, - {file = "reportlab-3.5.42-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:28c56f85900bc9632ac6c44f71629a34da3a7da0904a19ecbf69ea7aec976bf3"}, - {file = "reportlab-3.5.42-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:12b1deee658b6a9766e7aca061dfa52c396e984fb328178480ae11ff7717cda4"}, - {file = "reportlab-3.5.42-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:330aa2b493c9a42b28c65b5b4c7de4c4f372b1292f082b1a097d56b12e2ba097"}, - {file = "reportlab-3.5.42-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:5cc32b8ce94c9345fe59af2cbf47edb1c1615304b67f522957666485f87694f7"}, - {file = "reportlab-3.5.42-cp36-cp36m-win32.whl", hash = "sha256:553658b979b3e8dd662cd8c37d1955cc832b2c000f4cb6d076d8401d771dd85f"}, - {file = "reportlab-3.5.42-cp36-cp36m-win_amd64.whl", hash = "sha256:f18ad0212b7204f5fae37682ec4760a11e1130c294294cfcd900d202d90ed9d9"}, - {file = "reportlab-3.5.42-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cb24edd3e659c783abee1162559cc2a94537974fc73d73da7e3a7021b1ab9803"}, - {file = "reportlab-3.5.42-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:67f5b94ba44a4e764974b0ee9d2f574c593c11ec1cb19aedd17a1bebc35a597e"}, - {file = "reportlab-3.5.42-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:f7e4e8adc959dd65e127ae0865fb278d40b34ee2ae8e41e2c5fa8dc83cea273b"}, - {file = "reportlab-3.5.42-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:db5c44a77f10357f5c2c25545b7fbc009616274f9ac1876b00398693d0fc4324"}, - {file = "reportlab-3.5.42-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6fb58a2fdc725a601d225f377b3e1cc3837f8f560cc6c2ceeb8028010031fd65"}, - {file = "reportlab-3.5.42-cp37-cp37m-win32.whl", hash = "sha256:45f4aab315f301b4c184f1ee5fb4234fd1388335b191cf827ea977a98b0158dc"}, - {file = "reportlab-3.5.42-cp37-cp37m-win_amd64.whl", hash = "sha256:3af29daf6681fb1c6abbe8a948c6cdf241c7d9bcdce4b881076323e70b44865c"}, - {file = "reportlab-3.5.42-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6771e0875203d130f1f9c9c04f26084178cb4720552580af8b393cf70c4943a5"}, - {file = "reportlab-3.5.42-cp38-cp38-manylinux1_i686.whl", hash = "sha256:4f4463f1591cf66996a292835f04a521470cf9a479724017a9227125f49f7492"}, - {file = "reportlab-3.5.42-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:497c8d56d2f98561b78d9e21d9a2a39ab9e2dd81db699f1cddcba744ba455330"}, - {file = "reportlab-3.5.42-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:eff08b53ab4fa2adf4b763e56dd1369d6c1cb2a18d3daee7a5f53b25198c0a36"}, - {file = "reportlab-3.5.42-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:650ec96cc3cb86ae27987db5d36abe530ef45ec67032c4633c776dd3ab016ca4"}, - {file = "reportlab-3.5.42-cp38-cp38-win32.whl", hash = "sha256:3d33f934e13263fac098672840f8e0959643b747a516a50792868c3ae7251c37"}, - {file = "reportlab-3.5.42-cp38-cp38-win_amd64.whl", hash = "sha256:9ffbdbac35c084c2026c4d978498017b5433a61adfe6c1e500c506d38707b39c"}, - {file = "reportlab-3.5.42.tar.gz", hash = "sha256:9c21f202697a6cea57b9d716288fc919d99cbabeb30222eebfc7ff77eac32744"}, -] -requests = [ - {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-1.3.0.tar.gz", hash = "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a"}, - {file = "requests_oauthlib-1.3.0-py2.py3-none-any.whl", hash = "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d"}, - {file = "requests_oauthlib-1.3.0-py3.7.egg", hash = "sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc"}, -] -"ruamel.yaml" = [ - {file = "ruamel.yaml-0.16.10-py2.py3-none-any.whl", hash = "sha256:0962fd7999e064c4865f96fb1e23079075f4a2a14849bcdc5cdba53a24f9759b"}, - {file = "ruamel.yaml-0.16.10.tar.gz", hash = "sha256:099c644a778bf72ffa00524f78dd0b6476bca94a1da344130f4bf3381ce5b954"}, -] -"ruamel.yaml.clib" = [ - {file = "ruamel.yaml.clib-0.2.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:9c6d040d0396c28d3eaaa6cb20152cb3b2f15adf35a0304f4f40a3cf9f1d2448"}, - {file = "ruamel.yaml.clib-0.2.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:4d55386129291b96483edcb93b381470f7cd69f97585829b048a3d758d31210a"}, - {file = "ruamel.yaml.clib-0.2.0-cp27-cp27m-win32.whl", hash = "sha256:8073c8b92b06b572e4057b583c3d01674ceaf32167801fe545a087d7a1e8bf52"}, - {file = "ruamel.yaml.clib-0.2.0-cp27-cp27m-win_amd64.whl", hash = "sha256:615b0396a7fad02d1f9a0dcf9f01202bf9caefee6265198f252c865f4227fcc6"}, - {file = "ruamel.yaml.clib-0.2.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:a0ff786d2a7dbe55f9544b3f6ebbcc495d7e730df92a08434604f6f470b899c5"}, - {file = "ruamel.yaml.clib-0.2.0-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:ea4362548ee0cbc266949d8a441238d9ad3600ca9910c3fe4e82ee3a50706973"}, - {file = "ruamel.yaml.clib-0.2.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:77556a7aa190be9a2bd83b7ee075d3df5f3c5016d395613671487e79b082d784"}, - {file = "ruamel.yaml.clib-0.2.0-cp35-cp35m-win32.whl", hash = "sha256:392b7c371312abf27fb549ec2d5e0092f7ef6e6c9f767bfb13e83cb903aca0fd"}, - {file = "ruamel.yaml.clib-0.2.0-cp35-cp35m-win_amd64.whl", hash = "sha256:ed5b3698a2bb241b7f5cbbe277eaa7fe48b07a58784fba4f75224fd066d253ad"}, - {file = "ruamel.yaml.clib-0.2.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:7aee724e1ff424757b5bd8f6c5bbdb033a570b2b4683b17ace4dbe61a99a657b"}, - {file = "ruamel.yaml.clib-0.2.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d0d3ac228c9bbab08134b4004d748cf9f8743504875b3603b3afbb97e3472947"}, - {file = "ruamel.yaml.clib-0.2.0-cp36-cp36m-win32.whl", hash = "sha256:f9dcc1ae73f36e8059589b601e8e4776b9976effd76c21ad6a855a74318efd6e"}, - {file = "ruamel.yaml.clib-0.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:1e77424825caba5553bbade750cec2277ef130647d685c2b38f68bc03453bac6"}, - {file = "ruamel.yaml.clib-0.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d10e9dd744cf85c219bf747c75194b624cc7a94f0c80ead624b06bfa9f61d3bc"}, - {file = "ruamel.yaml.clib-0.2.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:550168c02d8de52ee58c3d8a8193d5a8a9491a5e7b2462d27ac5bf63717574c9"}, - {file = "ruamel.yaml.clib-0.2.0-cp37-cp37m-win32.whl", hash = "sha256:57933a6986a3036257ad7bf283529e7c19c2810ff24c86f4a0cfeb49d2099919"}, - {file = "ruamel.yaml.clib-0.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:b1b7fcee6aedcdc7e62c3a73f238b3d080c7ba6650cd808bce8d7761ec484070"}, - {file = "ruamel.yaml.clib-0.2.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:be018933c2f4ee7de55e7bd7d0d801b3dfb09d21dad0cce8a97995fd3e44be30"}, - {file = "ruamel.yaml.clib-0.2.0.tar.gz", hash = "sha256:b66832ea8077d9b3f6e311c4a53d06273db5dc2db6e8a908550f3c14d67e718c"}, -] -sentry-sdk = [ - {file = "sentry-sdk-0.14.3.tar.gz", hash = "sha256:bb90a4e19c7233a580715fc986cc44be2c48fc10b31e71580a2037e1c94b6950"}, - {file = "sentry_sdk-0.14.3-py2.py3-none-any.whl", hash = "sha256:23808d571d2461a4ce3784ec12bbee5bdb8c026c143fe79d36cef8a6d653e71f"}, -] -six = [ - {file = "six-1.14.0-py2.py3-none-any.whl", hash = "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"}, - {file = "six-1.14.0.tar.gz", hash = "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a"}, -] -social-auth-app-django = [ - {file = "social-auth-app-django-3.1.0.tar.gz", hash = "sha256:6d0dd18c2d9e71ca545097d57b44d26f59e624a12833078e8e52f91baf849778"}, - {file = "social_auth_app_django-3.1.0-py2-none-any.whl", hash = "sha256:f151396e5b16e2eee12cd2e211004257826ece24fc4ae97a147df386c1cd7082"}, - {file = "social_auth_app_django-3.1.0-py3-none-any.whl", hash = "sha256:9237e3d7b6f6f59494c3b02e0cce6efc69c9d33ad9d1a064e3b2318bcbe89ae3"}, -] -social-auth-core = [ - {file = "social-auth-core-3.3.2.tar.gz", hash = "sha256:3d04148d3f01d163cbf893d35250abe86e3e759203bd6f3036fdb85f89f85109"}, - {file = "social_auth_core-3.3.2-py2-none-any.whl", hash = "sha256:6320ff4644eece77dd8cec7939361918e26a877fc282974071f9a8892fd6df7e"}, - {file = "social_auth_core-3.3.2-py3-none-any.whl", hash = "sha256:1ce0f672827465df416b7170536cf6ac2415158fe993acc227aec1ead5d429ee"}, -] -soupsieve = [ - {file = "soupsieve-2.0-py2.py3-none-any.whl", hash = "sha256:fcd71e08c0aee99aca1b73f45478549ee7e7fc006d51b37bec9e9def7dc22b69"}, - {file = "soupsieve-2.0.tar.gz", hash = "sha256:e914534802d7ffd233242b785229d5ba0766a7f487385e3f714446a07bf540ae"}, -] -sqlparse = [ - {file = "sqlparse-0.3.1-py2.py3-none-any.whl", hash = "sha256:022fb9c87b524d1f7862b3037e541f68597a730a8843245c349fc93e1643dc4e"}, - {file = "sqlparse-0.3.1.tar.gz", hash = "sha256:e162203737712307dfe78860cc56c8da8a852ab2ee33750e33aeadf38d12c548"}, -] -swagger-spec-validator = [ - {file = "swagger-spec-validator-2.5.0.tar.gz", hash = "sha256:61f2d2a732b886cf33c2c24886565be9692e5814cacc17fd973e095b72b33e4f"}, - {file = "swagger_spec_validator-2.5.0-py2.py3-none-any.whl", hash = "sha256:8eb82682871f8d63067b455e2e055c8dd953ca260e791635b58dfe0b73ba1f43"}, -] -text-unidecode = [ - {file = "text-unidecode-1.3.tar.gz", hash = "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93"}, - {file = "text_unidecode-1.3-py2.py3-none-any.whl", hash = "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8"}, -] -toml = [ - {file = "toml-0.10.0-py2.7.egg", hash = "sha256:f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"}, - {file = "toml-0.10.0-py2.py3-none-any.whl", hash = "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"}, - {file = "toml-0.10.0.tar.gz", hash = "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c"}, -] -tornado = [ - {file = "tornado-4.5.3-cp35-cp35m-win32.whl", hash = "sha256:92b7ca81e18ba9ec3031a7ee73d4577ac21d41a0c9b775a9182f43301c3b5f8e"}, - {file = "tornado-4.5.3-cp35-cp35m-win_amd64.whl", hash = "sha256:b36298e9f63f18cad97378db2222c0e0ca6a55f6304e605515e05a25483ed51a"}, - {file = "tornado-4.5.3-cp36-cp36m-win32.whl", hash = "sha256:ab587996fe6fb9ce65abfda440f9b61e4f9f2cf921967723540679176915e4c3"}, - {file = "tornado-4.5.3-cp36-cp36m-win_amd64.whl", hash = "sha256:5ef073ac6180038ccf99411fe05ae9aafb675952a2c8db60592d5daf8401f803"}, - {file = "tornado-4.5.3.tar.gz", hash = "sha256:6d14e47eab0e15799cf3cdcc86b0b98279da68522caace2bd7ce644287685f0a"}, -] -tox = [ - {file = "tox-3.14.6-py2.py3-none-any.whl", hash = "sha256:b2c4b91c975ea5c11463d9ca00bebf82654439c5df0f614807b9bdec62cc9471"}, - {file = "tox-3.14.6.tar.gz", hash = "sha256:a4a6689045d93c208d77230853b28058b7513f5123647b67bf012f82fa168303"}, -] -traitlets = [ - {file = "traitlets-4.3.3-py2.py3-none-any.whl", hash = "sha256:70b4c6a1d9019d7b4f6846832288f86998aa3b9207c6821f3578a6a6a467fe44"}, - {file = "traitlets-4.3.3.tar.gz", hash = "sha256:d023ee369ddd2763310e4c3eae1ff649689440d4ae59d7485eb4cfbbe3e359f7"}, -] -unicodecsv = [ - {file = "unicodecsv-0.14.1.tar.gz", hash = "sha256:018c08037d48649a0412063ff4eda26eaa81eff1546dbffa51fa5293276ff7fc"}, -] -uritemplate = [ - {file = "uritemplate-3.0.1-py2.py3-none-any.whl", hash = "sha256:07620c3f3f8eed1f12600845892b0e036a2420acf513c53f7de0abd911a5894f"}, - {file = "uritemplate-3.0.1.tar.gz", hash = "sha256:5af8ad10cec94f215e3f48112de2022e1d5a37ed427fbd88652fa908f2ab7cae"}, -] -urllib3 = [ - {file = "urllib3-1.25.8-py2.py3-none-any.whl", hash = "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc"}, - {file = "urllib3-1.25.8.tar.gz", hash = "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc"}, -] -uwsgi = [ - {file = "uwsgi-2.0.18.tar.gz", hash = "sha256:4972ac538800fb2d421027f49b4a1869b66048839507ccf0aa2fda792d99f583"}, -] -vcrpy = [ - {file = "vcrpy-4.0.2-py2.py3-none-any.whl", hash = "sha256:c4ddf1b92c8a431901c56a1738a2c797d965165a96348a26f4b2bbc5fa6d36d9"}, - {file = "vcrpy-4.0.2.tar.gz", hash = "sha256:9740c5b1b63626ec55cefb415259a2c77ce00751e97b0f7f214037baaf13c7bf"}, -] -vine = [ - {file = "vine-1.3.0-py2.py3-none-any.whl", hash = "sha256:ea4947cc56d1fd6f2095c8d543ee25dad966f78692528e68b4fada11ba3f98af"}, - {file = "vine-1.3.0.tar.gz", hash = "sha256:133ee6d7a9016f177ddeaf191c1f58421a1dcc6ee9a42c58b34bed40e1d2cd87"}, -] -virtualenv = [ - {file = "virtualenv-20.0.15-py2.py3-none-any.whl", hash = "sha256:4e399f48c6b71228bf79f5febd27e3bbb753d9d5905776a86667bc61ab628a25"}, - {file = "virtualenv-20.0.15.tar.gz", hash = "sha256:9e81279f4a9d16d1c0654a127c2c86e5bca2073585341691882c1e66e31ef8a5"}, -] -waitress = [ - {file = "waitress-1.4.3-py2.py3-none-any.whl", hash = "sha256:77ff3f3226931a1d7d8624c5371de07c8e90c7e5d80c5cc660d72659aaf23f38"}, - {file = "waitress-1.4.3.tar.gz", hash = "sha256:045b3efc3d97c93362173ab1dfc159b52cfa22b46c3334ffc805dbdbf0e4309e"}, -] -wcwidth = [ - {file = "wcwidth-0.1.9-py2.py3-none-any.whl", hash = "sha256:cafe2186b3c009a04067022ce1dcd79cb38d8d65ee4f4791b8888d6599d1bbe1"}, - {file = "wcwidth-0.1.9.tar.gz", hash = "sha256:ee73862862a156bf77ff92b09034fc4825dd3af9cf81bc5b360668d425f3c5f1"}, -] -webencodings = [ - {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, - {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, -] -webob = [ - {file = "WebOb-1.8.6-py2.py3-none-any.whl", hash = "sha256:a3c89a8e9ba0aeb17382836cdb73c516d0ecf6630ec40ec28288f3ed459ce87b"}, - {file = "WebOb-1.8.6.tar.gz", hash = "sha256:aa3a917ed752ba3e0b242234b2a373f9c4e2a75d35291dcbe977649bd21fd108"}, -] -webtest = [ - {file = "WebTest-2.0.34-py2.py3-none-any.whl", hash = "sha256:da9cf14c103ff51a40dee4cac7657840d1317456eb8f0ca81289b5cbff175f4b"}, - {file = "WebTest-2.0.34.tar.gz", hash = "sha256:71114cd778a7d7b237ec5c8a5c32084f447d869ae62e48bcd5b73af211133e74"}, -] -wrapt = [ - {file = "wrapt-1.12.1.tar.gz", hash = "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"}, -] -xhtml2pdf = [ - {file = "xhtml2pdf-0.2.4.tar.gz", hash = "sha256:6793fbbdcb6bb8a4a70132966d8d95e95ea3498cdf0e82252d2b8e9aae34fcb5"}, -] -xlrd = [ - {file = "xlrd-1.2.0-py2.py3-none-any.whl", hash = "sha256:e551fb498759fa3a5384a94ccd4c3c02eb7c00ea424426e212ac0c57be9dfbde"}, - {file = "xlrd-1.2.0.tar.gz", hash = "sha256:546eb36cee8db40c3eaa46c351e67ffee6eeb5fa2650b71bc4c758a29a1b29b2"}, -] -xlwt = [ - {file = "xlwt-1.3.0-py2.py3-none-any.whl", hash = "sha256:a082260524678ba48a297d922cc385f58278b8aa68741596a87de01a9c628b2e"}, - {file = "xlwt-1.3.0.tar.gz", hash = "sha256:c59912717a9b28f1a3c2a98fd60741014b06b043936dcecbc113eaaada156c88"}, -] -yarl = [ - {file = "yarl-1.4.2-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:3ce3d4f7c6b69c4e4f0704b32eca8123b9c58ae91af740481aa57d7857b5e41b"}, - {file = "yarl-1.4.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:a4844ebb2be14768f7994f2017f70aca39d658a96c786211be5ddbe1c68794c1"}, - {file = "yarl-1.4.2-cp35-cp35m-win32.whl", hash = "sha256:d8cdee92bc930d8b09d8bd2043cedd544d9c8bd7436a77678dd602467a993080"}, - {file = "yarl-1.4.2-cp35-cp35m-win_amd64.whl", hash = "sha256:c2b509ac3d4b988ae8769901c66345425e361d518aecbe4acbfc2567e416626a"}, - {file = "yarl-1.4.2-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:308b98b0c8cd1dfef1a0311dc5e38ae8f9b58349226aa0533f15a16717ad702f"}, - {file = "yarl-1.4.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:944494be42fa630134bf907714d40207e646fd5a94423c90d5b514f7b0713fea"}, - {file = "yarl-1.4.2-cp36-cp36m-win32.whl", hash = "sha256:5b10eb0e7f044cf0b035112446b26a3a2946bca9d7d7edb5e54a2ad2f6652abb"}, - {file = "yarl-1.4.2-cp36-cp36m-win_amd64.whl", hash = "sha256:a161de7e50224e8e3de6e184707476b5a989037dcb24292b391a3d66ff158e70"}, - {file = "yarl-1.4.2-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:26d7c90cb04dee1665282a5d1a998defc1a9e012fdca0f33396f81508f49696d"}, - {file = "yarl-1.4.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:0c2ab325d33f1b824734b3ef51d4d54a54e0e7a23d13b86974507602334c2cce"}, - {file = "yarl-1.4.2-cp37-cp37m-win32.whl", hash = "sha256:e15199cdb423316e15f108f51249e44eb156ae5dba232cb73be555324a1d49c2"}, - {file = "yarl-1.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:2098a4b4b9d75ee352807a95cdf5f10180db903bc5b7270715c6bbe2551f64ce"}, - {file = "yarl-1.4.2-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:c9959d49a77b0e07559e579f38b2f3711c2b8716b8410b320bf9713013215a1b"}, - {file = "yarl-1.4.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:25e66e5e2007c7a39541ca13b559cd8ebc2ad8fe00ea94a2aad28a9b1e44e5ae"}, - {file = "yarl-1.4.2-cp38-cp38-win32.whl", hash = "sha256:6faa19d3824c21bcbfdfce5171e193c8b4ddafdf0ac3f129ccf0cdfcb083e462"}, - {file = "yarl-1.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:0ca2f395591bbd85ddd50a82eb1fde9c1066fafe888c5c7cc1d810cf03fd3cc6"}, - {file = "yarl-1.4.2.tar.gz", hash = "sha256:58cd9c469eced558cd81aa3f484b2924e8897049e06889e8ff2510435b7ef74b"}, -] -zipp = [ - {file = "zipp-3.1.0-py3-none-any.whl", hash = "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b"}, - {file = "zipp-3.1.0.tar.gz", hash = "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96"}, -] diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 36a6adef4..000000000 --- a/pyproject.toml +++ /dev/null @@ -1,94 +0,0 @@ -[tool.poetry] -name = "datamart-core" -version = "2.11" -description = "" -authors = ["sax "] - -[tool.poetry.dependencies] -admin-extra-urls = "^2.1" -celery = "*" -circus = "*" -cryptography = "==2.7" -django = "^2.2" -django-adminactions = "^1.8" -django-adminfilters = "^1.1" -django-celery-beat = "*" -django-celery-email = "*" -django-concurrency = "*" -django-constance = "*" -django-cors-headers = "*" -django-countries = "*" -django-crashlog = "*" -django-crispy-forms = "*" -django-dbtemplates = "*" -django-deprecate-fields = "*" -django-environ = "*" -django-filter = "*" -django-impersonate = "*" -django-jsoneditor = "*" -django-migration-linter = "*" -django-model-utils = "*" -django-mptt = "*" -django-picklefield = "*" -django-post-office = "*" -django-redis = "*" -django-regex = "*" -django-rest-framework-social-oauth2 = "*" -django-sql-explorer = "*" -django-strategy-field = "*" -django-sysinfo = "==1.4" -djangorestframework-csv = "*" -djangorestframework-gis = "*" -djangorestframework-jwt = "*" -djangorestframework-xml = "*" -djangorestframework-yaml = "*" -djangorestframework="^3.10.2" -drf-dynamic-serializer = "^2.1" -drf-extensions = "*" -drf-renderer-xlsx = "*" -drf-yasg = {version = "*",extras = ["validation"]} -humanfriendly = "*" -humanize = "*" -markdown = "*" -packaging = "*" -psycopg2-binary = "==2.7.7" -pygments = "*" -pyparsing = "*" -python = "^3.7" -python-social-auth = "*" -pyyaml = "^4.2b1" -rapidpro-python = "*" -raven = "*" -redis = "*" -sentry-sdk = "*" -social-auth-app-django = "*" -sqlparse = "*" -uwsgi = "*" -xhtml2pdf = "*" -django-storages = {version = "^1.8", extras = ["azure"]} - -[tool.poetry.dev-dependencies] -check-manifest= "*" -django-extensions = "*" -django-webtest = "*" -drf-api-checker = "^0.8" -factory-boy = "*" -freezegun = "*" -isort = "*" -pre-commit = "*" -pytest = "<5" -pytest-coverage = "*" -pytest-django = "*" -pytest-echo = "*" -pytest-ignore-flaky = "*" -pytest-pythonpath = "*" -tox = "*" -vcrpy = "*" -#fancycompleter = {file = "https://github.com/theY4Kman/fancycompleter/archive/0.8.tar.gz"} -flake8 = "*" -ipdb = "*" -bump2version = "*" - -[build-system] -requires = ["poetry>=0.12"] -build-backend = "poetry.masonry.api" diff --git a/setup.cfg b/setup.cfg index b86839397..a4417b124 100644 --- a/setup.cfg +++ b/setup.cfg @@ -3,7 +3,7 @@ combine_as_imports = true default_section = THIRDPARTY include_trailing_comma = true known_first_party = etools_datamart -multi_line_output = 0 +multi_line_output = 3 line_length = 120 balanced_wrapping = true order_by_type = false @@ -20,17 +20,14 @@ tag_build = tag_date = 0 tag_svn_revision = 0 -;[pep8] -;ignore = E501,E401,W391,E128,E261 -;max-line-length = 160 -;exclude = .tox,migrations,.git,docs,diff_match_patch.py,deploy/**,settings,**/etools/models/__init__.py +[pep8] +ignore = E501,E401,W391,E128,E261 +max-line-length = 160 +exclude = .tox,migrations,.git,docs,diff_match_patch.py,deploy/**,settings [flake8] -;max-complexity = 19 +max-complexity = 19 max-line-length = 160 -;exclude = .tox,migrations,.git,docs,diff_match_patch.py,deploy/**,settings,**/etools/models/__init__.py -exclude = **/migrations/**, -ignore = E501,E401,E731,W504 -;W391,E128,E261, -[pycodestyle] -ignore = E501,E401,W391,E128,E261,E731 +filename = .py +exclude = .tox,migrations,.git,docs,diff_match_patch.py,deploy/**,settings +ignore = E501,E401,W391,E128,E261,W503 diff --git a/src/drf_querystringfilter/__init__.py b/src/drf_querystringfilter/__init__.py index 6f4becde2..ccd18554f 100644 --- a/src/drf_querystringfilter/__init__.py +++ b/src/drf_querystringfilter/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- NAME = 'drf-querystringfilter' VERSION = __version__ = "1.1a0" __author__ = 'sax' diff --git a/src/drf_querystringfilter/backend.py b/src/drf_querystringfilter/backend.py index d8a32ffdb..575aa2955 100644 --- a/src/drf_querystringfilter/backend.py +++ b/src/drf_querystringfilter/backend.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import absolute_import, unicode_literals import logging diff --git a/src/drf_querystringfilter/exceptions.py b/src/drf_querystringfilter/exceptions.py index 255225804..5b97d2d00 100644 --- a/src/drf_querystringfilter/exceptions.py +++ b/src/drf_querystringfilter/exceptions.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import absolute_import, unicode_literals @@ -9,28 +8,28 @@ class QueryFilterException(Exception): class InvalidPattern(TypeError): def __init__(self, pattern, *args, **kwargs): msg = '{} is not a valid regular expression'.format(pattern) - super(InvalidPattern, self).__init__(msg) + super().__init__(msg) class InvalidQueryArgumentError(QueryFilterException): def __init__(self, field, *args, **kwargs): msg = "Invalid parameter '{}'".format(field) - super(InvalidQueryArgumentError, self).__init__(msg) + super().__init__(msg) class InvalidQueryValueError(QueryFilterException): def __init__(self, field, argument='', *args, **kwargs): msg = "Invalid value '{}' for parameter {}".format(argument, field) - super(InvalidQueryValueError, self).__init__(msg) + super().__init__(msg) class InvalidFilterError(QueryFilterException): def __init__(self, field, *args, **kwargs): - super(InvalidFilterError, self).__init__("Invalid filter '{}'".format(field)) + super().__init__("Invalid filter '{}'".format(field)) class FilteringError(QueryFilterException): def __init__(self, reason, *args, **kwargs): msg = "Invalid query: '{}'".format(reason) - super(FilteringError, self).__init__(msg) + super().__init__(msg) diff --git a/src/drf_querystringfilter/filters.py b/src/drf_querystringfilter/filters.py index dbd71df7a..fc815b6a7 100644 --- a/src/drf_querystringfilter/filters.py +++ b/src/drf_querystringfilter/filters.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import absolute_import, print_function, unicode_literals import re @@ -46,7 +45,7 @@ def __init__(self, seq=None): if seq: for el in seq: regexx.append(self._compile(el)) - super(RexList, self).__init__(regexx) + super().__init__(regexx) def __repr__(self): return str([r.pattern for r in self]) @@ -59,11 +58,11 @@ def _compile(self, pattern, index=None): def __setitem__(self, i, pattern): rex = self._compile(pattern) - super(RexList, self).__setitem__(i, rex) + super().__setitem__(i, rex) def append(self, pattern): rex = self._compile(pattern) - super(RexList, self).append(rex) + super().append(rex) def __contains__(self, target): t = str(target) diff --git a/src/etools_datamart/api/endpoints/__init__.py b/src/etools_datamart/api/endpoints/__init__.py index bb77090f5..ff45b1ea8 100644 --- a/src/etools_datamart/api/endpoints/__init__.py +++ b/src/etools_datamart/api/endpoints/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from .datamart import * # noqa from .etools import * # noqa from .openapi import schema_view # noqa diff --git a/src/etools_datamart/api/endpoints/common.py b/src/etools_datamart/api/endpoints/common.py index b2f3b5e5e..ce9921958 100644 --- a/src/etools_datamart/api/endpoints/common.py +++ b/src/etools_datamart/api/endpoints/common.py @@ -181,7 +181,7 @@ def list(self, request, *args, **kwargs): return super().list(request, *args, **kwargs) def get_schema_fields(self): - ret = super(APIMultiTenantReadOnlyModelViewSet, self).get_schema_fields() + ret = super().get_schema_fields() ret.append(coreapi.Field( name='_schema', required=False, diff --git a/src/etools_datamart/api/endpoints/datamart/__init__.py b/src/etools_datamart/api/endpoints/datamart/__init__.py index 2f21ae1f4..b75e67b01 100644 --- a/src/etools_datamart/api/endpoints/datamart/__init__.py +++ b/src/etools_datamart/api/endpoints/datamart/__init__.py @@ -1,10 +1,12 @@ -# -*- coding: utf-8 -*- # flake8: noqa: F401 from .actionpoint import ActionPointViewSet from .attachment import AttachmentViewSet +from .audit_audit import AuditViewSet from .audit_engagement import EngagementDetailViewSet, EngagementViewSet +from .audit_micro_assessment import MicroAssessmentViewSet from .audit_result import AuditResultViewSet -from .audit_spotcheck import SpotCheckViewSet +from .audit_special import AuditSpecialViewSet +from .audit_spotcheck import SpotCheckFindingViewSet, SpotCheckViewSet from .famindicator import FAMIndicatorViewSet from .fm_questions import FMOntrackViewSet, FMQuestionViewSet from .funds_grant import GrantViewSet diff --git a/src/etools_datamart/api/endpoints/datamart/audit_audit.py b/src/etools_datamart/api/endpoints/datamart/audit_audit.py new file mode 100644 index 000000000..7ee459658 --- /dev/null +++ b/src/etools_datamart/api/endpoints/datamart/audit_audit.py @@ -0,0 +1,54 @@ +from django import forms + +from rest_framework import serializers + +from unicef_rest_framework.forms import DateRangePickerField, Select2MultipleChoiceField + +from etools_datamart.api.endpoints.datamart.serializers import DataMartSerializer +from etools_datamart.apps.mart.data import models +from etools_datamart.apps.sources.etools.enrichment.consts import AuditEngagementConsts + +from ..common import DataMartViewSet + + +class AuditSerializer(DataMartSerializer): + partner_name = serializers.SerializerMethodField() + url = serializers.SerializerMethodField() + + class Meta(DataMartSerializer.Meta): + model = models.Audit + exclude = ('seen', 'source_id',) + + def get_url(self, obj): + try: + return "{}/ap/audits/{}/overview".format( + config.ETOOLS_ADDRESS, + obj.source_id, + ) + except KeyError: + return "" + + def get_partner_name(self, obj): + try: + return obj.partner['name'] + except KeyError: + return 'N/A' + + +class AuditFilterForm(forms.Form): + date_of_final_report = DateRangePickerField( + label='Date of Final Report', + required=False, + ) + +class AuditViewSet(DataMartViewSet): + querystringfilter_form_base_class = AuditFilterForm + + serializer_class = AuditSerializer + queryset = models.Audit.objects.all() + filter_fields = ( + 'date_of_final_report', + ) + + def get_querystringfilter_form(self, request, filter): + return AuditFilterForm(request.GET, filter.form_prefix) diff --git a/src/etools_datamart/api/endpoints/datamart/audit_engagement.py b/src/etools_datamart/api/endpoints/datamart/audit_engagement.py index 0a62be467..17371b09b 100644 --- a/src/etools_datamart/api/endpoints/datamart/audit_engagement.py +++ b/src/etools_datamart/api/endpoints/datamart/audit_engagement.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# import django_filters from django import forms from constance import config diff --git a/src/etools_datamart/api/endpoints/datamart/audit_micro_assessment.py b/src/etools_datamart/api/endpoints/datamart/audit_micro_assessment.py new file mode 100644 index 000000000..b6849905f --- /dev/null +++ b/src/etools_datamart/api/endpoints/datamart/audit_micro_assessment.py @@ -0,0 +1,59 @@ +from django import forms + +from rest_framework import serializers + +from unicef_rest_framework.forms import DateRangePickerField, Select2MultipleChoiceField + +from etools_datamart.api.endpoints.datamart.serializers import DataMartSerializer +from etools_datamart.apps.mart.data import models +from etools_datamart.apps.sources.etools.enrichment.consts import AuditEngagementConsts + +from ..common import DataMartViewSet + + +class MicroAssessmentSerializer(DataMartSerializer): + partner_name = serializers.SerializerMethodField() + url = serializers.SerializerMethodField() + + class Meta(DataMartSerializer.Meta): + model = models.MicroAssessment + exclude = ('seen', 'source_id',) + + def get_url(self, obj): + try: + return "{}/ap/micro-assessments/{}/overview".format( + config.ETOOLS_ADDRESS, + obj.source_id, + ) + except KeyError: + return "" + + def get_partner_name(self, obj): + try: + return obj.partner['name'] + except KeyError: + return 'N/A' + + +class MicroAssessmentFilterForm(forms.Form): + date_of_field_visit = DateRangePickerField( + label='Date of Field Visit', + required=False, + ) + date_of_final_report = DateRangePickerField( + label='Date of Final Report', + required=False, + ) + +class MicroAssessmentViewSet(DataMartViewSet): + querystringfilter_form_base_class = MicroAssessmentFilterForm + + serializer_class = MicroAssessmentSerializer + queryset = models.MicroAssessment.objects.all() + filter_fields = ( + 'date_of_field_visit', + 'date_of_final_report', + ) + + def get_querystringfilter_form(self, request, filter): + return MicroAssessmentFilterForm(request.GET, filter.form_prefix) diff --git a/src/etools_datamart/api/endpoints/datamart/audit_special.py b/src/etools_datamart/api/endpoints/datamart/audit_special.py new file mode 100644 index 000000000..164824bfe --- /dev/null +++ b/src/etools_datamart/api/endpoints/datamart/audit_special.py @@ -0,0 +1,59 @@ +from django import forms + +from rest_framework import serializers + +from unicef_rest_framework.forms import DateRangePickerField, Select2MultipleChoiceField + +from etools_datamart.api.endpoints.datamart.serializers import DataMartSerializer +from etools_datamart.apps.mart.data import models +from etools_datamart.apps.sources.etools.enrichment.consts import AuditEngagementConsts + +from ..common import DataMartViewSet + + +class AuditSpecialSerializer(DataMartSerializer): + partner_name = serializers.SerializerMethodField() + url = serializers.SerializerMethodField() + + class Meta(DataMartSerializer.Meta): + model = models.AuditSpecial + exclude = ('seen', 'source_id',) + + def get_url(self, obj): + try: + return "{}/ap/special-audits/{}/overview".format( + config.ETOOLS_ADDRESS, + obj.source_id, + ) + except KeyError: + return "" + + def get_partner_name(self, obj): + try: + return obj.partner['name'] + except KeyError: + return 'N/A' + + +class AuditSpecialFilterForm(forms.Form): + date_of_field_visit = DateRangePickerField( + label='Date of Field Visit', + required=False, + ) + date_of_final_report = DateRangePickerField( + label='Date of Final Report', + required=False, + ) + +class AuditSpecialViewSet(DataMartViewSet): + querystringfilter_form_base_class = AuditSpecialFilterForm + + serializer_class = AuditSpecialSerializer + queryset = models.AuditSpecial.objects.all() + filter_fields = ( + 'date_of_field_visit', + 'date_of_final_report', + ) + + def get_querystringfilter_form(self, request, filter): + return AuditSpecialFilterForm(request.GET, filter.form_prefix) diff --git a/src/etools_datamart/api/endpoints/datamart/audit_spotcheck.py b/src/etools_datamart/api/endpoints/datamart/audit_spotcheck.py index b51b8b472..5c2ae512e 100644 --- a/src/etools_datamart/api/endpoints/datamart/audit_spotcheck.py +++ b/src/etools_datamart/api/endpoints/datamart/audit_spotcheck.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# import django_filters from django import forms from constance import config @@ -126,3 +124,46 @@ class SpotCheckViewSet(DataMartViewSet): def get_querystringfilter_form(self, request, filter): return SpotCheckFilterForm(request.GET, filter.form_prefix) + + +class SpotCheckFindingSerializer(DataMartSerializer): + partner_name = serializers.SerializerMethodField() + url = serializers.SerializerMethodField() + + class Meta(DataMartSerializer.Meta): + model = models.SpotCheckFindings + exclude = ('seen', 'source_id',) + + def get_url(self, obj): + try: + return "{}/ap/spot-checks/{}/overview".format( + config.ETOOLS_ADDRESS, + obj.source_id, + ) + except KeyError: + return "" + + def get_partner_name(self, obj): + try: + return obj.partner['name'] + except KeyError: + return 'N/A' + + +class SpotCheckFindingFilterForm(forms.Form): + date_of_final_report = DateRangePickerField( + label='Date of Final Report', + required=False, + ) + +class SpotCheckFindingViewSet(DataMartViewSet): + querystringfilter_form_base_class = SpotCheckFindingFilterForm + + serializer_class = SpotCheckFindingSerializer + queryset = models.SpotCheckFindings.objects.all() + filter_fields = ( + 'date_of_final_report', + ) + + def get_querystringfilter_form(self, request, filter): + return SpotCheckFindingFilterForm(request.GET, filter.form_prefix) diff --git a/src/etools_datamart/api/endpoints/datamart/famindicator.py b/src/etools_datamart/api/endpoints/datamart/famindicator.py index 72b0ae594..9d8634d9a 100644 --- a/src/etools_datamart/api/endpoints/datamart/famindicator.py +++ b/src/etools_datamart/api/endpoints/datamart/famindicator.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from month_field.rest_framework import MonthFilterBackend from etools_datamart.apps.mart.data import models diff --git a/src/etools_datamart/api/endpoints/datamart/funds_grant.py b/src/etools_datamart/api/endpoints/datamart/funds_grant.py index 47dd1b345..f7d70d576 100644 --- a/src/etools_datamart/api/endpoints/datamart/funds_grant.py +++ b/src/etools_datamart/api/endpoints/datamart/funds_grant.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# import django_filters from django import forms from unicef_rest_framework.forms import DateRangePickerField diff --git a/src/etools_datamart/api/endpoints/datamart/hact_aggregate.py b/src/etools_datamart/api/endpoints/datamart/hact_aggregate.py index d34b00ecc..cd20d2e02 100644 --- a/src/etools_datamart/api/endpoints/datamart/hact_aggregate.py +++ b/src/etools_datamart/api/endpoints/datamart/hact_aggregate.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from etools_datamart.api.endpoints.datamart.serializers import DataMartSerializer from etools_datamart.apps.mart.data import models diff --git a/src/etools_datamart/api/endpoints/datamart/hact_history.py b/src/etools_datamart/api/endpoints/datamart/hact_history.py index 410e20649..c3a0e27f3 100644 --- a/src/etools_datamart/api/endpoints/datamart/hact_history.py +++ b/src/etools_datamart/api/endpoints/datamart/hact_history.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from etools_datamart.api.endpoints.datamart.serializers import DataMartSerializer from etools_datamart.apps.mart.data import models diff --git a/src/etools_datamart/api/endpoints/datamart/partners_agreement.py b/src/etools_datamart/api/endpoints/datamart/partners_agreement.py index 94299f970..258c99bfc 100644 --- a/src/etools_datamart/api/endpoints/datamart/partners_agreement.py +++ b/src/etools_datamart/api/endpoints/datamart/partners_agreement.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# import django_filters from django import forms from constance import config diff --git a/src/etools_datamart/api/endpoints/datamart/partners_interventionbudget.py b/src/etools_datamart/api/endpoints/datamart/partners_interventionbudget.py index 489ab2f00..19e7d9be6 100644 --- a/src/etools_datamart/api/endpoints/datamart/partners_interventionbudget.py +++ b/src/etools_datamart/api/endpoints/datamart/partners_interventionbudget.py @@ -3,8 +3,12 @@ from unicef_rest_framework.forms import DateRangePickerField, Select2MultipleChoiceField from etools_datamart.api.endpoints import common -from etools_datamart.api.endpoints.datamart.intervention import (InterventionSerializer, InterventionSerializerFull, - InterventionSerializerPlain, InterventionSerializerV2,) +from etools_datamart.api.endpoints.datamart.intervention import ( + InterventionSerializer, + InterventionSerializerFull, + InterventionSerializerPlain, + InterventionSerializerV2, +) from etools_datamart.apps.mart.data import models from etools_datamart.apps.sources.etools.enrichment.consts import PartnersInterventionConst diff --git a/src/etools_datamart/api/endpoints/datamart/partners_partner.py b/src/etools_datamart/api/endpoints/datamart/partners_partner.py index 47994f39a..719fcde2b 100644 --- a/src/etools_datamart/api/endpoints/datamart/partners_partner.py +++ b/src/etools_datamart/api/endpoints/datamart/partners_partner.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# import django_filters from django import forms from rest_framework import serializers diff --git a/src/etools_datamart/api/endpoints/datamart/partners_staffmember.py b/src/etools_datamart/api/endpoints/datamart/partners_staffmember.py index 44f822fef..45526b136 100644 --- a/src/etools_datamart/api/endpoints/datamart/partners_staffmember.py +++ b/src/etools_datamart/api/endpoints/datamart/partners_staffmember.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# import django_filters from rest_framework import serializers from etools_datamart.api.endpoints.datamart.serializers import DataMartSerializer diff --git a/src/etools_datamart/api/endpoints/datamart/pd_indicator.py b/src/etools_datamart/api/endpoints/datamart/pd_indicator.py index c2a04b3b1..9760a8c7c 100644 --- a/src/etools_datamart/api/endpoints/datamart/pd_indicator.py +++ b/src/etools_datamart/api/endpoints/datamart/pd_indicator.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from etools_datamart.api.endpoints.datamart.serializers import DataMartSerializer from etools_datamart.apps.mart.data import models diff --git a/src/etools_datamart/api/endpoints/datamart/pmpindicators.py b/src/etools_datamart/api/endpoints/datamart/pmpindicators.py index b6e43ab99..8e1161476 100644 --- a/src/etools_datamart/api/endpoints/datamart/pmpindicators.py +++ b/src/etools_datamart/api/endpoints/datamart/pmpindicators.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from collections import OrderedDict from django import forms diff --git a/src/etools_datamart/api/endpoints/datamart/report_section.py b/src/etools_datamart/api/endpoints/datamart/report_section.py index e40c767cf..9244f1999 100644 --- a/src/etools_datamart/api/endpoints/datamart/report_section.py +++ b/src/etools_datamart/api/endpoints/datamart/report_section.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# import django_filters from etools_datamart.api.endpoints.datamart.serializers import DataMartSerializer from etools_datamart.apps.mart.data import models diff --git a/src/etools_datamart/api/endpoints/datamart/reports_indicastor.py b/src/etools_datamart/api/endpoints/datamart/reports_indicastor.py index 7f479cb28..e865660e5 100644 --- a/src/etools_datamart/api/endpoints/datamart/reports_indicastor.py +++ b/src/etools_datamart/api/endpoints/datamart/reports_indicastor.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from etools_datamart.api.endpoints.datamart.serializers import DataMartSerializer from etools_datamart.apps.mart.data import models diff --git a/src/etools_datamart/api/endpoints/datamart/serializers.py b/src/etools_datamart/api/endpoints/datamart/serializers.py index 014c8d5bc..e962bab08 100644 --- a/src/etools_datamart/api/endpoints/datamart/serializers.py +++ b/src/etools_datamart/api/endpoints/datamart/serializers.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from rest_framework import serializers from etools_datamart.apps.mart.data import models diff --git a/src/etools_datamart/api/endpoints/datamart/tpm_activity.py b/src/etools_datamart/api/endpoints/datamart/tpm_activity.py index c6346714f..b899b933e 100644 --- a/src/etools_datamart/api/endpoints/datamart/tpm_activity.py +++ b/src/etools_datamart/api/endpoints/datamart/tpm_activity.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django import forms from constance import config diff --git a/src/etools_datamart/api/endpoints/datamart/tpm_visit.py b/src/etools_datamart/api/endpoints/datamart/tpm_visit.py index aa28429ad..37dff6864 100644 --- a/src/etools_datamart/api/endpoints/datamart/tpm_visit.py +++ b/src/etools_datamart/api/endpoints/datamart/tpm_visit.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from etools_datamart.api.endpoints.datamart.serializers import DataMartSerializer from etools_datamart.apps.mart.data import models diff --git a/src/etools_datamart/api/endpoints/datamart/travel.py b/src/etools_datamart/api/endpoints/datamart/travel.py index 770f36ec5..16b86c817 100644 --- a/src/etools_datamart/api/endpoints/datamart/travel.py +++ b/src/etools_datamart/api/endpoints/datamart/travel.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# import django_filters from django import forms from unicef_rest_framework.forms import DateRangePickerField, Select2MultipleChoiceField diff --git a/src/etools_datamart/api/endpoints/datamart/travel_activity.py b/src/etools_datamart/api/endpoints/datamart/travel_activity.py index 9d3b39a13..1073d2c03 100644 --- a/src/etools_datamart/api/endpoints/datamart/travel_activity.py +++ b/src/etools_datamart/api/endpoints/datamart/travel_activity.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# import django_filters from django import forms from unicef_rest_framework.forms import DateRangePickerField, Select2MultipleChoiceField diff --git a/src/etools_datamart/api/endpoints/datamart/trips.py b/src/etools_datamart/api/endpoints/datamart/trips.py index c77f3395a..d679cebdd 100644 --- a/src/etools_datamart/api/endpoints/datamart/trips.py +++ b/src/etools_datamart/api/endpoints/datamart/trips.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# import django_filters from django import forms from constance import config diff --git a/src/etools_datamart/api/endpoints/datamart/user.py b/src/etools_datamart/api/endpoints/datamart/user.py index eeb10b6df..3904c8cc2 100644 --- a/src/etools_datamart/api/endpoints/datamart/user.py +++ b/src/etools_datamart/api/endpoints/datamart/user.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from functools import lru_cache from django import forms diff --git a/src/etools_datamart/api/endpoints/datamart/userstats.py b/src/etools_datamart/api/endpoints/datamart/userstats.py index 976e5856a..09a63a3a3 100644 --- a/src/etools_datamart/api/endpoints/datamart/userstats.py +++ b/src/etools_datamart/api/endpoints/datamart/userstats.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from datetime import datetime from month_field.rest_framework import MonthFilterBackend diff --git a/src/etools_datamart/api/endpoints/etools/funds.py b/src/etools_datamart/api/endpoints/etools/funds.py index 446ac3ff3..c2cadf63a 100644 --- a/src/etools_datamart/api/endpoints/etools/funds.py +++ b/src/etools_datamart/api/endpoints/etools/funds.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from etools_datamart.api.endpoints import common from etools_datamart.api.endpoints.etools import serializers from etools_datamart.apps.sources.etools import models diff --git a/src/etools_datamart/api/endpoints/etools/serializers/__init__.py b/src/etools_datamart/api/endpoints/etools/serializers/__init__.py index 9d2693e6d..81b24d98c 100644 --- a/src/etools_datamart/api/endpoints/etools/serializers/__init__.py +++ b/src/etools_datamart/api/endpoints/etools/serializers/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from .funds import * # noqa from .partners import * # noqa from .reports import * # noqa diff --git a/src/etools_datamart/api/endpoints/etools/serializers/funds.py b/src/etools_datamart/api/endpoints/etools/serializers/funds.py index 0f99cc61d..f3362b75b 100644 --- a/src/etools_datamart/api/endpoints/etools/serializers/funds.py +++ b/src/etools_datamart/api/endpoints/etools/serializers/funds.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from rest_framework import serializers from etools_datamart.apps.sources.etools import models diff --git a/src/etools_datamart/api/endpoints/openapi.py b/src/etools_datamart/api/endpoints/openapi.py index a721b35e3..3a45a82bf 100644 --- a/src/etools_datamart/api/endpoints/openapi.py +++ b/src/etools_datamart/api/endpoints/openapi.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # flake8: noqa E501 from drf_yasg import openapi diff --git a/src/etools_datamart/api/endpoints/system/__init__.py b/src/etools_datamart/api/endpoints/system/__init__.py index cfa7965eb..1ba2c4bdf 100644 --- a/src/etools_datamart/api/endpoints/system/__init__.py +++ b/src/etools_datamart/api/endpoints/system/__init__.py @@ -1,2 +1 @@ -# -*- coding: utf-8 -*- from .task_log import MonitorViewSet # noqa diff --git a/src/etools_datamart/api/endpoints/system/serializers.py b/src/etools_datamart/api/endpoints/system/serializers.py index d6736fc30..5c9402f22 100644 --- a/src/etools_datamart/api/endpoints/system/serializers.py +++ b/src/etools_datamart/api/endpoints/system/serializers.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from rest_framework import serializers from etools_datamart.apps.etl import models diff --git a/src/etools_datamart/api/endpoints/system/task_log.py b/src/etools_datamart/api/endpoints/system/task_log.py index ba0ef3ec1..a12bb8c72 100644 --- a/src/etools_datamart/api/endpoints/system/task_log.py +++ b/src/etools_datamart/api/endpoints/system/task_log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from etools_datamart.apps.etl import models from .. import common diff --git a/src/etools_datamart/api/endpoints/unicef/business_area.py b/src/etools_datamart/api/endpoints/unicef/business_area.py index 932970f15..7ecf3a3a6 100644 --- a/src/etools_datamart/api/endpoints/unicef/business_area.py +++ b/src/etools_datamart/api/endpoints/unicef/business_area.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from unicef_security import models from .. import common diff --git a/src/etools_datamart/api/endpoints/unicef/region.py b/src/etools_datamart/api/endpoints/unicef/region.py index 2d78eca4b..d462031f0 100644 --- a/src/etools_datamart/api/endpoints/unicef/region.py +++ b/src/etools_datamart/api/endpoints/unicef/region.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from unicef_security import models from .. import common diff --git a/src/etools_datamart/api/endpoints/unicef/serializers.py b/src/etools_datamart/api/endpoints/unicef/serializers.py index c1dfadb6f..bfccd0641 100644 --- a/src/etools_datamart/api/endpoints/unicef/serializers.py +++ b/src/etools_datamart/api/endpoints/unicef/serializers.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from rest_framework import serializers from unicef_security import models diff --git a/src/etools_datamart/api/management/__init__.py b/src/etools_datamart/api/management/__init__.py index 40a96afc6..e69de29bb 100644 --- a/src/etools_datamart/api/management/__init__.py +++ b/src/etools_datamart/api/management/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/src/etools_datamart/api/management/commands/__init__.py b/src/etools_datamart/api/management/commands/__init__.py index 40a96afc6..e69de29bb 100644 --- a/src/etools_datamart/api/management/commands/__init__.py +++ b/src/etools_datamart/api/management/commands/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/src/etools_datamart/api/management/commands/api-builder.py b/src/etools_datamart/api/management/commands/api-builder.py index df97c3936..01848e02b 100644 --- a/src/etools_datamart/api/management/commands/api-builder.py +++ b/src/etools_datamart/api/management/commands/api-builder.py @@ -30,13 +30,11 @@ class {model}Admin(TenantModelAdmin): """ -SER_MODULE = """# -*- coding: utf-8 -*- -from etools_datamart.apps.etools import models +SER_MODULE = """from etools_datamart.apps.etools import models from rest_framework import serializers """ -VIEWSET_MODULE = """# -*- coding: utf-8 -*- -from etools_datamart.apps.etools import models +VIEWSET_MODULE = """from etools_datamart.apps.etools import models from . import common from .. import serializers @@ -54,7 +52,7 @@ class Command(LabelCommand): label = 'model name' def add_arguments(self, parser): - super(Command, self).add_arguments(parser) + super().add_arguments(parser) parser.add_argument( '--serializers', action='store', dest='serializers', default='etools_datamart.api.serializers', diff --git a/src/etools_datamart/api/metadata.py b/src/etools_datamart/api/metadata.py index 42367a506..2ad84836b 100644 --- a/src/etools_datamart/api/metadata.py +++ b/src/etools_datamart/api/metadata.py @@ -66,7 +66,7 @@ class SimpleMetadataWithFilters(SimpleMetadata): """Override SimpleMetadata, adding info about filters""" def determine_metadata(self, request, view): - metadata = super(SimpleMetadataWithFilters, self).determine_metadata(request, view) + metadata = super().determine_metadata(request, view) metadata['filters'] = getattr(view, 'filter_fields', '') metadata['filter_blacklist'] = getattr(view, 'filter_blacklist', '') metadata['ordering'] = getattr(view, 'ordering_fields', '') diff --git a/src/etools_datamart/api/swagger/__init__.py b/src/etools_datamart/api/swagger/__init__.py index 9321baebb..192187010 100644 --- a/src/etools_datamart/api/swagger/__init__.py +++ b/src/etools_datamart/api/swagger/__init__.py @@ -1,3 +1,2 @@ -# -*- coding: utf-8 -*- # from .filters import FilterInspector # from .generators import APISchemaGenerator diff --git a/src/etools_datamart/api/swagger/filters.py b/src/etools_datamart/api/swagger/filters.py index 94a02a479..5cf0ac537 100644 --- a/src/etools_datamart/api/swagger/filters.py +++ b/src/etools_datamart/api/swagger/filters.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging from drf_yasg.inspectors import CoreAPICompatInspector diff --git a/src/etools_datamart/api/swagger/schema.py b/src/etools_datamart/api/swagger/schema.py index 17b364763..23d92e237 100644 --- a/src/etools_datamart/api/swagger/schema.py +++ b/src/etools_datamart/api/swagger/schema.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging import coreschema diff --git a/src/etools_datamart/api/urls.py b/src/etools_datamart/api/urls.py index 932d2948d..74edf61a0 100644 --- a/src/etools_datamart/api/urls.py +++ b/src/etools_datamart/api/urls.py @@ -24,10 +24,14 @@ class ReadOnlyRouter(APIReadOnlyRouter): router.register(r'datamart/attachment/attachment', endpoints.AttachmentViewSet) router.register(r'datamart/funds/grants', endpoints.GrantViewSet) +router.register(r'datamart/audit/audit', endpoints.AuditViewSet) router.register(r'datamart/audit/engagements', endpoints.EngagementViewSet) router.register(r'datamart/audit/engagement-details', endpoints.EngagementDetailViewSet, basename="engagement-details") +router.register(r'datamart/audit/micro-assessment', endpoints.MicroAssessmentViewSet) router.register(r'datamart/audit/results', endpoints.AuditResultViewSet) +router.register(r'datamart/audit/special-audit', endpoints.AuditSpecialViewSet) router.register(r'datamart/audit/spot-check', endpoints.SpotCheckViewSet) +router.register(r'datamart/audit/spot-check-findings', endpoints.SpotCheckFindingViewSet) router.register(r'datamart/actionpoints', endpoints.ActionPointViewSet) router.register(r'datamart/locations', endpoints.LocationViewSet) router.register(r'datamart/office', endpoints.OfficeViewSet) diff --git a/src/etools_datamart/apps/__init__.py b/src/etools_datamart/apps/__init__.py index 40a96afc6..e69de29bb 100644 --- a/src/etools_datamart/apps/__init__.py +++ b/src/etools_datamart/apps/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/src/etools_datamart/apps/core/__init__.py b/src/etools_datamart/apps/core/__init__.py index 40a96afc6..e69de29bb 100644 --- a/src/etools_datamart/apps/core/__init__.py +++ b/src/etools_datamart/apps/core/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/src/etools_datamart/apps/core/models.py b/src/etools_datamart/apps/core/models.py index b2df78e70..840fe3498 100644 --- a/src/etools_datamart/apps/core/models.py +++ b/src/etools_datamart/apps/core/models.py @@ -7,7 +7,7 @@ class DataMartQuerySet(QuerySet): def get(self, *args, **kwargs): try: - return super(DataMartQuerySet, self).get(*args, **kwargs) + return super().get(*args, **kwargs) except self.model.DoesNotExist as e: raise self.model.DoesNotExist( "%s (%s %s)" % (e, args, kwargs) diff --git a/src/etools_datamart/apps/core/readonly.py b/src/etools_datamart/apps/core/readonly.py index 086c19e64..7a9274bf1 100644 --- a/src/etools_datamart/apps/core/readonly.py +++ b/src/etools_datamart/apps/core/readonly.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import absolute_import, print_function, unicode_literals import logging @@ -53,7 +52,7 @@ def save(self, force_insert=False, force_update=False, using=None, update_fields pass def delete(self, using=None, keep_parents=False): - super(ReadOnlyModel, self).delete(using) + super().delete(using) class Meta: abstract = True diff --git a/src/etools_datamart/apps/etl/__init__.py b/src/etools_datamart/apps/etl/__init__.py index 40a96afc6..e69de29bb 100644 --- a/src/etools_datamart/apps/etl/__init__.py +++ b/src/etools_datamart/apps/etl/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/src/etools_datamart/apps/etl/admin.py b/src/etools_datamart/apps/etl/admin.py index 952dd7793..46558d817 100644 --- a/src/etools_datamart/apps/etl/admin.py +++ b/src/etools_datamart/apps/etl/admin.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import json from datetime import datetime diff --git a/src/etools_datamart/apps/etl/apps.py b/src/etools_datamart/apps/etl/apps.py index b310a0012..ea0faddf6 100644 --- a/src/etools_datamart/apps/etl/apps.py +++ b/src/etools_datamart/apps/etl/apps.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.apps import AppConfig from celery.signals import task_postrun diff --git a/src/etools_datamart/apps/etl/camera.py b/src/etools_datamart/apps/etl/camera.py index 0cbefc3fe..57e1c0860 100644 --- a/src/etools_datamart/apps/etl/camera.py +++ b/src/etools_datamart/apps/etl/camera.py @@ -21,7 +21,7 @@ class Camera(Polaroid): worker_update_freq = WORKER_UPDATE_FREQ def __init__(self, *args, **kwargs): - super(Camera, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # Expiry can be timedelta or None for never expire. self.app.add_defaults({ 'monitors_expire_success': timedelta(days=1), @@ -39,7 +39,7 @@ def django_setup(self): django.setup() def install(self): - super(Camera, self).install() + super().install() self.django_setup() def handle_task(self, uuid_task, worker=None): diff --git a/src/etools_datamart/apps/etl/loader.py b/src/etools_datamart/apps/etl/loader.py index 0ddc023ee..b3214d678 100644 --- a/src/etools_datamart/apps/etl/loader.py +++ b/src/etools_datamart/apps/etl/loader.py @@ -15,8 +15,12 @@ from sentry_sdk import capture_exception from strategy_field.utils import fqn, get_attr -from etools_datamart.apps.etl.exceptions import (LoaderException, MaxRecordsException, - RequiredIsMissing, RequiredIsRunning,) +from etools_datamart.apps.etl.exceptions import ( + LoaderException, + MaxRecordsException, + RequiredIsMissing, + RequiredIsRunning, +) from etools_datamart.celery import app loadeables = set() diff --git a/src/etools_datamart/apps/etl/lock.py b/src/etools_datamart/apps/etl/lock.py index bf7bb47e1..699137ff4 100644 --- a/src/etools_datamart/apps/etl/lock.py +++ b/src/etools_datamart/apps/etl/lock.py @@ -1,4 +1,3 @@ -# # -*- coding: utf-8 -*- # import logging # from functools import wraps # diff --git a/src/etools_datamart/apps/etl/management/__init__.py b/src/etools_datamart/apps/etl/management/__init__.py index 40a96afc6..e69de29bb 100644 --- a/src/etools_datamart/apps/etl/management/__init__.py +++ b/src/etools_datamart/apps/etl/management/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/src/etools_datamart/apps/etl/management/commands/__init__.py b/src/etools_datamart/apps/etl/management/commands/__init__.py index 40a96afc6..e69de29bb 100644 --- a/src/etools_datamart/apps/etl/management/commands/__init__.py +++ b/src/etools_datamart/apps/etl/management/commands/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/src/etools_datamart/apps/etl/management/commands/queue.py b/src/etools_datamart/apps/etl/management/commands/queue.py index 545087f2e..e84f015e0 100644 --- a/src/etools_datamart/apps/etl/management/commands/queue.py +++ b/src/etools_datamart/apps/etl/management/commands/queue.py @@ -14,7 +14,7 @@ def __init__(self, stdout=None, stderr=None, no_color=False, force_color=False): self.missing_args_message = "Enter at least one task %s: " % self.valid_tasks def add_arguments(self, parser): - super(Command, self).add_arguments(parser) + super().add_arguments(parser) parser.add_argument( '--wait', '-w', action='store_true', dest='wait', default=False, diff --git a/src/etools_datamart/apps/etl/models.py b/src/etools_datamart/apps/etl/models.py index 2fef18312..45f9f42b6 100644 --- a/src/etools_datamart/apps/etl/models.py +++ b/src/etools_datamart/apps/etl/models.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.contrib.contenttypes.models import ContentType from django.contrib.postgres.fields import JSONField from django.db import models diff --git a/src/etools_datamart/apps/etl/results.py b/src/etools_datamart/apps/etl/results.py index 2b84d96f5..013c04fa7 100644 --- a/src/etools_datamart/apps/etl/results.py +++ b/src/etools_datamart/apps/etl/results.py @@ -57,7 +57,7 @@ def default(self, obj): '__type__': '__EtlResult__', 'data': obj.as_dict() } - return super(EtlEncoder, self).default(obj) + return super().default(obj) def etl_decoder(obj): diff --git a/src/etools_datamart/apps/etl/tasks.py b/src/etools_datamart/apps/etl/tasks.py index 2042a56bd..0d195510e 100644 --- a/src/etools_datamart/apps/etl/tasks.py +++ b/src/etools_datamart/apps/etl/tasks.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging from django.core.cache import cache diff --git a/src/etools_datamart/apps/init/__init__.py b/src/etools_datamart/apps/init/__init__.py index 40a96afc6..e69de29bb 100644 --- a/src/etools_datamart/apps/init/__init__.py +++ b/src/etools_datamart/apps/init/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/src/etools_datamart/apps/init/apps.py b/src/etools_datamart/apps/init/apps.py index 8a71164c9..466c9cf84 100644 --- a/src/etools_datamart/apps/init/apps.py +++ b/src/etools_datamart/apps/init/apps.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.apps import AppConfig diff --git a/src/etools_datamart/apps/init/management/__init__.py b/src/etools_datamart/apps/init/management/__init__.py index 40a96afc6..e69de29bb 100644 --- a/src/etools_datamart/apps/init/management/__init__.py +++ b/src/etools_datamart/apps/init/management/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/src/etools_datamart/apps/init/management/commands/__init__.py b/src/etools_datamart/apps/init/management/commands/__init__.py index 40a96afc6..e69de29bb 100644 --- a/src/etools_datamart/apps/init/management/commands/__init__.py +++ b/src/etools_datamart/apps/init/management/commands/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/src/etools_datamart/apps/init/management/commands/db-isready.py b/src/etools_datamart/apps/init/management/commands/db-isready.py index 737bde205..2b9edeba2 100644 --- a/src/etools_datamart/apps/init/management/commands/db-isready.py +++ b/src/etools_datamart/apps/init/management/commands/db-isready.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import sys import time @@ -13,10 +12,10 @@ class Command(BaseCommand): requires_system_checks = False def __init__(self, *args, **kwargs): - super(Command, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def add_arguments(self, parser): - super(Command, self).add_arguments(parser) + super().add_arguments(parser) parser.add_argument( '--sleep', default=1, diff --git a/src/etools_datamart/apps/init/management/commands/healthcheck.py b/src/etools_datamart/apps/init/management/commands/healthcheck.py index 80b8e901e..9cacbf362 100644 --- a/src/etools_datamart/apps/init/management/commands/healthcheck.py +++ b/src/etools_datamart/apps/init/management/commands/healthcheck.py @@ -16,10 +16,10 @@ class Command(BaseCommand): requires_system_checks = False def __init__(self, *args, **kwargs): - super(Command, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def add_arguments(self, parser): - super(Command, self).add_arguments(parser) + super().add_arguments(parser) parser.add_argument( '--pidfile', dest='pidfile', diff --git a/src/etools_datamart/apps/init/management/commands/reset-migrations.py b/src/etools_datamart/apps/init/management/commands/reset-migrations.py index c0e6e7f0b..d1244d020 100644 --- a/src/etools_datamart/apps/init/management/commands/reset-migrations.py +++ b/src/etools_datamart/apps/init/management/commands/reset-migrations.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging import os from glob import iglob @@ -16,7 +15,7 @@ class Command(BaseCommand): requires_system_checks = False def add_arguments(self, parser): - super(Command, self).add_arguments(parser) + super().add_arguments(parser) parser.add_argument( '--noinput', action='store_false', dest='interactive', default=True, diff --git a/src/etools_datamart/apps/mart/data/__init__.py b/src/etools_datamart/apps/mart/data/__init__.py index 700086910..fa3801c54 100644 --- a/src/etools_datamart/apps/mart/data/__init__.py +++ b/src/etools_datamart/apps/mart/data/__init__.py @@ -1,2 +1 @@ -# -*- coding: utf-8 -*- default_app_config = 'etools_datamart.apps.mart.data.apps.Config' diff --git a/src/etools_datamart/apps/mart/data/admin.py b/src/etools_datamart/apps/mart/data/admin.py index 620603af8..8f8908693 100644 --- a/src/etools_datamart/apps/mart/data/admin.py +++ b/src/etools_datamart/apps/mart/data/admin.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging from time import time @@ -386,3 +385,27 @@ class AuditResultAdmin(DataModelAdmin): class SpotCheckAdmin(DataModelAdmin): list_display = ('__str__',) list_filter = () + + +@register(models.SpotCheckFindings) +class SpotCheckFindingsAdmin(DataModelAdmin): + list_display = ('__str__',) + list_filter = () + + +@register(models.MicroAssessment) +class MicroAssessmentAdmin(DataModelAdmin): + list_display = ('__str__',) + list_filter = () + + +@register(models.Audit) +class AuditAdmin(DataModelAdmin): + list_display = ('__str__',) + list_filter = () + + +@register(models.AuditSpecial) +class AuditSpecialAdmin(DataModelAdmin): + list_display = ('__str__',) + list_filter = () diff --git a/src/etools_datamart/apps/mart/data/apps.py b/src/etools_datamart/apps/mart/data/apps.py index 3c5c36c39..4388b3ee1 100644 --- a/src/etools_datamart/apps/mart/data/apps.py +++ b/src/etools_datamart/apps/mart/data/apps.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.apps import AppConfig diff --git a/src/etools_datamart/apps/mart/data/loader.py b/src/etools_datamart/apps/mart/data/loader.py index b70892572..48423d1f0 100644 --- a/src/etools_datamart/apps/mart/data/loader.py +++ b/src/etools_datamart/apps/mart/data/loader.py @@ -125,7 +125,7 @@ def get_value(self, field_name, value_or_func, original_record, current_mapping) except AttributeError: # pragma: no cover pass else: - return super(EtoolsLoader, self).get_value(field_name, value_or_func, + return super().get_value(field_name, value_or_func, original_record, current_mapping) def filter_queryset(self, qs): @@ -329,7 +329,7 @@ def get_value(self, field_name, value_or_func, original_record, current_mapping) except AttributeError: # pragma: no cover pass else: - return super(CommonSchemaLoader, self).get_value(field_name, value_or_func, original_record, + return super().get_value(field_name, value_or_func, original_record, current_mapping) def load(self, *, verbosity=0, stdout=None, diff --git a/src/etools_datamart/apps/mart/data/management/commands/load.py b/src/etools_datamart/apps/mart/data/management/commands/load.py index fb61fb872..d98360beb 100644 --- a/src/etools_datamart/apps/mart/data/management/commands/load.py +++ b/src/etools_datamart/apps/mart/data/management/commands/load.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging import time diff --git a/src/etools_datamart/apps/mart/data/management/commands/sqlall.py b/src/etools_datamart/apps/mart/data/management/commands/sqlall.py index 853f900e9..fd554909d 100644 --- a/src/etools_datamart/apps/mart/data/management/commands/sqlall.py +++ b/src/etools_datamart/apps/mart/data/management/commands/sqlall.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging import subprocess diff --git a/src/etools_datamart/apps/mart/data/migrations/0130_spotcheckfindings.py b/src/etools_datamart/apps/mart/data/migrations/0130_spotcheckfindings.py new file mode 100644 index 000000000..b9967b876 --- /dev/null +++ b/src/etools_datamart/apps/mart/data/migrations/0130_spotcheckfindings.py @@ -0,0 +1,40 @@ +# Generated by Django 2.2.11 on 2020-12-01 20:15 + +import django.contrib.postgres.fields.jsonb +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('data', '0129_auto_20201125_1623'), + ] + + operations = [ + migrations.CreateModel( + name='SpotCheckFindings', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('source_id', models.IntegerField(blank=True, db_index=True, null=True)), + ('last_modify_date', models.DateTimeField(auto_now=True)), + ('seen', models.DateTimeField(blank=True, null=True)), + ('country_name', models.CharField(max_length=100)), + ('schema_name', models.CharField(db_index=True, max_length=63)), + ('area_code', models.CharField(db_index=True, max_length=10)), + ('auditor', models.CharField(blank=True, max_length=255, null=True)), + ('engagement_type', models.CharField(blank=True, choices=[('sc', 'Spot Check')], db_index=True, max_length=300, null=True)), + ('date_of_final_report', models.DateField(blank=True, null=True)), + ('high_priorty_findings', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict, null=True)), + ('low_priorty_findings', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict, null=True)), + ('partner', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict, null=True)), + ('sections', models.TextField(blank=True, null=True)), + ('sections_data', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict, null=True)), + ('spotcheck_total_amount_tested', models.DecimalField(blank=True, decimal_places=2, max_digits=20, null=True)), + ('spotcheck_total_amount_of_ineligible_expenditure', models.DecimalField(blank=True, decimal_places=2, max_digits=20, null=True)), + ('total_value', models.DecimalField(blank=True, decimal_places=2, default=0, max_digits=20, null=True)), + ], + options={ + 'ordering': ('id',), + }, + ), + ] diff --git a/src/etools_datamart/apps/mart/data/migrations/0131_microassessment.py b/src/etools_datamart/apps/mart/data/migrations/0131_microassessment.py new file mode 100644 index 000000000..0da194250 --- /dev/null +++ b/src/etools_datamart/apps/mart/data/migrations/0131_microassessment.py @@ -0,0 +1,41 @@ +# Generated by Django 2.2.11 on 2020-12-09 20:56 + +import django.contrib.postgres.fields +import django.contrib.postgres.fields.jsonb +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('data', '0130_spotcheckfindings'), + ] + + operations = [ + migrations.CreateModel( + name='MicroAssessment', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('source_id', models.IntegerField(blank=True, db_index=True, null=True)), + ('last_modify_date', models.DateTimeField(auto_now=True)), + ('seen', models.DateTimeField(blank=True, null=True)), + ('country_name', models.CharField(max_length=100)), + ('schema_name', models.CharField(db_index=True, max_length=63)), + ('area_code', models.CharField(db_index=True, max_length=10)), + ('engagement_type', models.CharField(blank=True, choices=[('ma', 'Micro Assessment')], db_index=True, max_length=300, null=True)), + ('agreement', models.CharField(blank=True, max_length=300, null=True)), + ('partner', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict, null=True)), + ('date_of_field_visit', models.DateField(blank=True, null=True)), + ('date_of_final_report', models.DateField(blank=True, null=True)), + ('shared_ip_with', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=20, null=True), blank=True, default=list, null=True, size=None, verbose_name='Shared Audit with')), + ('rating', models.CharField(blank=True, max_length=50, null=True)), + ('rating_extra', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict, null=True)), + ('subject_area', models.CharField(blank=True, max_length=50, null=True)), + ('subject_area_extra', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict, null=True)), + ('test_subject_areas', models.CharField(blank=True, max_length=50, null=True)), + ], + options={ + 'ordering': ('id',), + }, + ), + ] diff --git a/src/etools_datamart/apps/mart/data/migrations/0132_audit.py b/src/etools_datamart/apps/mart/data/migrations/0132_audit.py new file mode 100644 index 000000000..ce15ed3a9 --- /dev/null +++ b/src/etools_datamart/apps/mart/data/migrations/0132_audit.py @@ -0,0 +1,44 @@ +# Generated by Django 2.2.11 on 2020-12-16 19:15 + +import django.contrib.postgres.fields +import django.contrib.postgres.fields.jsonb +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('data', '0131_microassessment'), + ] + + operations = [ + migrations.CreateModel( + name='Audit', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('source_id', models.IntegerField(blank=True, db_index=True, null=True)), + ('last_modify_date', models.DateTimeField(auto_now=True)), + ('seen', models.DateTimeField(blank=True, null=True)), + ('country_name', models.CharField(max_length=100)), + ('schema_name', models.CharField(db_index=True, max_length=63)), + ('area_code', models.CharField(db_index=True, max_length=10)), + ('engagement_type', models.CharField(blank=True, choices=[('audit', 'Audit')], db_index=True, max_length=300, null=True)), + ('agreement', models.CharField(blank=True, max_length=300, null=True)), + ('auditor', models.CharField(blank=True, max_length=255, null=True)), + ('shared_ip_with', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=20, null=True), blank=True, default=list, null=True, size=None, verbose_name='Shared Audit with')), + ('total_value', models.DecimalField(blank=True, decimal_places=2, max_digits=20, null=True)), + ('date_of_final_report', models.DateField(blank=True, null=True)), + ('audited_expenditure', models.DecimalField(blank=True, decimal_places=2, max_digits=20, null=True, verbose_name='Audited Expenditure $')), + ('audited_expenditure_local', models.DecimalField(blank=True, decimal_places=2, max_digits=20, null=True, verbose_name='Audited Expenditure Local Currency')), + ('financial_findings', models.DecimalField(blank=True, decimal_places=2, max_digits=20, null=True, verbose_name='Financial Findings $')), + ('financial_findings_local', models.DecimalField(blank=True, decimal_places=2, max_digits=20, null=True, verbose_name='Financial Findings Local Currency')), + ('audit_opinion', models.CharField(blank=True, max_length=254, null=True)), + ('financial_findings_count', models.IntegerField(blank=True, null=True)), + ('financial_findings_titles', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict, null=True)), + ('key_internal_control_count', models.IntegerField(blank=True, null=True)), + ], + options={ + 'ordering': ('id',), + }, + ), + ] diff --git a/src/etools_datamart/apps/mart/data/migrations/0133_auditspecial.py b/src/etools_datamart/apps/mart/data/migrations/0133_auditspecial.py new file mode 100644 index 000000000..c0b8eb87c --- /dev/null +++ b/src/etools_datamart/apps/mart/data/migrations/0133_auditspecial.py @@ -0,0 +1,40 @@ +# Generated by Django 2.2.11 on 2020-12-17 17:08 + +import django.contrib.postgres.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('data', '0132_audit'), + ] + + operations = [ + migrations.CreateModel( + name='AuditSpecial', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('source_id', models.IntegerField(blank=True, db_index=True, null=True)), + ('last_modify_date', models.DateTimeField(auto_now=True)), + ('seen', models.DateTimeField(blank=True, null=True)), + ('country_name', models.CharField(max_length=100)), + ('schema_name', models.CharField(db_index=True, max_length=63)), + ('area_code', models.CharField(db_index=True, max_length=10)), + ('engagement_type', models.CharField(blank=True, choices=[('sa', 'Special Audit')], db_index=True, max_length=300, null=True)), + ('agreement', models.CharField(blank=True, max_length=300, null=True)), + ('auditor', models.CharField(blank=True, max_length=255, null=True)), + ('shared_ip_with', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=20, null=True), blank=True, default=list, null=True, size=None, verbose_name='Shared Audit with')), + ('total_value', models.DecimalField(blank=True, decimal_places=2, max_digits=20, null=True)), + ('date_of_final_report', models.DateField(blank=True, null=True)), + ('joint_audit', models.BooleanField(blank=True, null=True)), + ('date_of_field_visit', models.DateField(blank=True, null=True)), + ('date_of_draft_report_to_ip', models.DateField(blank=True, null=True)), + ('date_of_comments_by_ip', models.DateField(blank=True, null=True)), + ('date_of_draft_report_to_unicef', models.DateField(blank=True, null=True)), + ], + options={ + 'ordering': ('id',), + }, + ), + ] diff --git a/src/etools_datamart/apps/mart/data/migrations/0134_auto_20210105_1416.py b/src/etools_datamart/apps/mart/data/migrations/0134_auto_20210105_1416.py new file mode 100644 index 000000000..454c22fc5 --- /dev/null +++ b/src/etools_datamart/apps/mart/data/migrations/0134_auto_20210105_1416.py @@ -0,0 +1,24 @@ +# Generated by Django 2.2.13 on 2021-01-05 14:16 + +import django.contrib.postgres.fields.jsonb +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('data', '0133_auditspecial'), + ] + + operations = [ + migrations.AddField( + model_name='audit', + name='partner', + field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict, null=True), + ), + migrations.AddField( + model_name='auditspecial', + name='partner', + field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict, null=True), + ), + ] diff --git a/src/etools_datamart/apps/mart/data/models/__init__.py b/src/etools_datamart/apps/mart/data/models/__init__.py index 6946e9738..02fd3ca34 100644 --- a/src/etools_datamart/apps/mart/data/models/__init__.py +++ b/src/etools_datamart/apps/mart/data/models/__init__.py @@ -1,8 +1,11 @@ from .actionpoint import ActionPoint # noqa from .attachments_attachment import Attachment # noqa +from .audit_audit import Audit # noqa from .audit_engagement import Engagement # noqa +from .audit_micro_assessment import MicroAssessment from .audit_result import AuditResult # noqa -from .audit_spotcheck import SpotCheck # noqa +from .audit_special import AuditSpecial # noqa +from .audit_spotcheck import SpotCheck, SpotCheckFindings # noqa from .fam import FAMIndicator # noqa from .fm_questions import FMOntrack, FMQuestion # noqa from .funds_grant import Grant # noqa diff --git a/src/etools_datamart/apps/mart/data/models/actionpoint.py b/src/etools_datamart/apps/mart/data/models/actionpoint.py index e2b26db0f..e6570de11 100644 --- a/src/etools_datamart/apps/mart/data/models/actionpoint.py +++ b/src/etools_datamart/apps/mart/data/models/actionpoint.py @@ -7,11 +7,23 @@ from etools_datamart.apps.mart.data.loader import EtoolsLoader from etools_datamart.apps.mart.data.models.base import EtoolsDataMartModel from etools_datamart.apps.mart.data.models.mixins import add_location_mapping, LocationMixin -from etools_datamart.apps.sources.etools.enrichment.consts import (ActionPointConsts, AuditEngagementConsts, - CategoryConsts, PartnersInterventionConst,) -from etools_datamart.apps.sources.etools.models import (ActionPointsActionpoint, AuditAudit, AuditMicroassessment, - AuditSpecialaudit, AuditSpotcheck, DjangoComments, - DjangoContentType, T2FTravelactivity, TpmTpmactivity,) +from etools_datamart.apps.sources.etools.enrichment.consts import ( + ActionPointConsts, + AuditEngagementConsts, + CategoryConsts, + PartnersInterventionConst, +) +from etools_datamart.apps.sources.etools.models import ( + ActionPointsActionpoint, + AuditAudit, + AuditMicroassessment, + AuditSpecialaudit, + AuditSpotcheck, + DjangoComments, + DjangoContentType, + T2FTravelactivity, + TpmTpmactivity, +) from .intervention import Intervention diff --git a/src/etools_datamart/apps/mart/data/models/audit_audit.py b/src/etools_datamart/apps/mart/data/models/audit_audit.py new file mode 100644 index 000000000..985ce9d2f --- /dev/null +++ b/src/etools_datamart/apps/mart/data/models/audit_audit.py @@ -0,0 +1,131 @@ +from django.contrib.postgres.fields import ArrayField, JSONField +from django.db import models +from django.db.models import Count +from django.utils.translation import gettext as _ + +from model_utils import Choices + +from etools_datamart.apps.mart.data.loader import EtoolsLoader +from etools_datamart.apps.mart.data.models.audit_engagement import EngagementRiskMixin +from etools_datamart.apps.mart.data.models.base import EtoolsDataMartModel +from etools_datamart.apps.sources.etools.models import ( + AuditAudit, + AuditEngagement, + AuditFinancialfinding, + AuditKeyinternalcontrol, +) + +from .partner import Partner + + +class AuditLoader(EngagementRiskMixin, EtoolsLoader): + def process_country(self): + for record in AuditAudit.objects.select_related('engagement_ptr'): + record.id = record.engagement_ptr_id + record.sub_type = AuditAudit + record.engagement_ptr._impl = record + filters = self.config.key(self, record.engagement_ptr) + values = self.get_values(record.engagement_ptr) + + def get_financial_findings_count(self, record, values, field_name): + return AuditFinancialfinding.objects.filter(audit=record._impl).count() + + def get_financial_findings_titles(self, record, values, field_name): + return AuditFinancialfinding.objects.filter( + audit=record._impl, + ).values("title").annotate( + count=Count("title"), + ).order_by("title") + + def get_key_internal_control_count(self, record, values, field_name): + return AuditFinancialfinding.objects.filter(audit=record._impl).count() + + +class Audit(EtoolsDataMartModel): + TYPE_AUDIT = 'audit' + + TYPES = Choices( + (TYPE_AUDIT, _('Audit')), + ) + + engagement_type = models.CharField( + max_length=300, + blank=True, + null=True, + choices=TYPES, + db_index=True, + ) + agreement = models.CharField(max_length=300, blank=True, null=True) + auditor = models.CharField( + max_length=255, + blank=True, + null=True, + ) + partner = JSONField(blank=True, null=True, default=dict) + shared_ip_with = ArrayField( + models.CharField(max_length=20, blank=True, null=True), + blank=True, + null=True, + default=list, + verbose_name=_('Shared Audit with'), + ) + total_value = models.DecimalField( + blank=True, + null=True, + decimal_places=2, + max_digits=20, + ) + date_of_final_report = models.DateField(null=True, blank=True) + audited_expenditure = models.DecimalField( + verbose_name=_('Audited Expenditure $'), + blank=True, + null=True, + decimal_places=2, + max_digits=20, + ) + audited_expenditure_local = models.DecimalField( + verbose_name=_('Audited Expenditure Local Currency'), + blank=True, + null=True, + decimal_places=2, + max_digits=20, + ) + financial_findings = models.DecimalField( + verbose_name=_('Financial Findings $'), + blank=True, + null=True, + decimal_places=2, + max_digits=20, + ) + financial_findings_local = models.DecimalField( + verbose_name=_('Financial Findings Local Currency'), + blank=True, + null=True, + decimal_places=2, + max_digits=20, + ) + audit_opinion = models.CharField( + max_length=254, + blank=True, + null=True, + ) + financial_findings_count = models.IntegerField(blank=True, null=True) + financial_findings_titles = JSONField(blank=True, null=True, default=dict) + key_internal_control_count = models.IntegerField(blank=True, null=True) + + loader = AuditLoader() + + class Meta: + ordering = ("id",) + + class Options: + source = AuditAudit + sync_deleted_records = lambda a: False + depends = (Partner,) + mapping = dict( + auditor="agreement.auditor_firm.name", + partner="-", + financial_findings_count="-", + financial_findings_titles="-", + key_internal_control_count="-", + ) diff --git a/src/etools_datamart/apps/mart/data/models/audit_engagement.py b/src/etools_datamart/apps/mart/data/models/audit_engagement.py index c85b68eca..d8a0faa50 100644 --- a/src/etools_datamart/apps/mart/data/models/audit_engagement.py +++ b/src/etools_datamart/apps/mart/data/models/audit_engagement.py @@ -7,10 +7,19 @@ from etools_datamart.apps.mart.data.loader import EtoolsLoader from etools_datamart.apps.mart.data.models.base import EtoolsDataMartModel from etools_datamart.apps.sources.etools.enrichment.consts import AuditEngagementConsts, RiskConst -from etools_datamart.apps.sources.etools.models import (ActionPointsActionpoint, AuditAudit, AuditEngagement, - AuditEngagementActivePd, AuditMicroassessment, AuditRisk, - AuditRiskcategory, AuditSpecialaudit, AuditSpotcheck, - DjangoContentType, UnicefAttachmentsAttachment,) +from etools_datamart.apps.sources.etools.models import ( + ActionPointsActionpoint, + AuditAudit, + AuditEngagement, + AuditEngagementActivePd, + AuditMicroassessment, + AuditRisk, + AuditRiskcategory, + AuditSpecialaudit, + AuditSpotcheck, + DjangoContentType, + UnicefAttachmentsAttachment, +) from .partner import Partner @@ -35,9 +44,60 @@ 'T2FTravelactivity': "trips"} -class EngagementlLoader(EtoolsLoader): +class EngagementRiskMixin: OVERALL_RISK_MAP = {} + def get_partner(self, record: AuditEngagement, values: dict, **kwargs): + try: + p = Partner.objects.get( + schema_name=self.context['country'].schema_name, + source_id=record.partner.pk) + return { + 'name': p.name, + 'vendor_number': p.vendor_number, + 'id': p.pk, + 'source_id': p.source_id, + } + except Partner.DoesNotExist: + return { + 'name': 'N/A', + 'vendor_number': 'N/A', + 'id': 'N/A', + 'source_id': 'N/A', + } + + def _get_risk(self, record: AuditEngagement, code: str): + schema = self.context['country'] + category_id = self.OVERALL_RISK_MAP.get(schema, None) + if category_id is None: + try: + category = AuditRiskcategory.objects.get(code=code) + except AuditRiskcategory.DoesNotExist: + pass + else: + self.OVERALL_RISK_MAP[schema] = category.pk + category_id = category.pk + + try: + risk = AuditRisk.objects.get( + engagement=record, + blueprint__category__pk=category_id, + ) + except AuditRisk.DoesNotExist: + extra = "" + value = "" + else: + extra = risk.extra + value = risk.value + return value, extra + + def get_rating(self, record: AuditEngagement, values: dict, **kwargs): + value, extra = self._get_risk(record, code="ma_global_assessment") + values["rating_extra"] = extra + return value + + +class EngagementlLoader(EngagementRiskMixin, EtoolsLoader): def get_queryset(self): return AuditEngagement.objects.select_related( 'partner', @@ -101,7 +161,7 @@ def get_final_report(self, record: AuditEngagement, values: dict, **kwargs): def get_values(self, record: AuditEngagement): values = {} self.mapping.update(**values) - return super(EngagementlLoader, self).get_values(record) + return super().get_values(record) def get_authorized_officers(self, record: AuditEngagement, values: dict, **kwargs): ret = [] @@ -128,21 +188,6 @@ def get_active_pd(self, record: AuditEngagement, values: dict, **kwargs): values['active_pd_data'] = ret return ", ".join([o['number'] for o in ret]) - def get_partner(self, record: AuditEngagement, values: dict, **kwargs): - try: - p = Partner.objects.get( - schema_name=self.context['country'].schema_name, - source_id=record.partner.id) - return {'name': p.name, - 'vendor_number': p.vendor_number, - 'id': p.id, - 'source_id': p.source_id} - except Partner.DoesNotExist: - return {'name': 'N/A', - 'vendor_number': 'N/A', - 'id': 'N/A', - 'source_id': 'N/A'} - def get_partner_id(self, record: AuditEngagement, values: dict, **kwargs): try: return Partner.objects.get( @@ -172,35 +217,6 @@ def get_action_points(self, record: AuditEngagement, values: dict, **kwargs): ret.append(ActionPointSimpleSerializer(r).data) return ret - def get_rating(self, record: AuditEngagement, values: dict, **kwargs): - schema = self.context['country'] - category_id = self.OVERALL_RISK_MAP.get(schema, None) - if category_id is None: - try: - category = AuditRiskcategory.objects.get( - header="Overall Risk Assessment", - ) - except AuditRiskcategory.DoesNotExist: - pass - else: - self.OVERALL_RISK_MAP[schema] = category.pk - category_id = category.pk - - try: - risk = AuditRisk.objects.get( - engagement=record, - blueprint__category__pk=category_id, - ) - except AuditRisk.DoesNotExist: - extra = "" - value = "" - else: - extra = risk.extra - value = risk.value - - values["rating_extra"] = extra - return value - def process_country(self): for m in [AuditMicroassessment, AuditSpecialaudit, AuditSpotcheck, AuditAudit]: for record in m.objects.select_related('engagement_ptr'): diff --git a/src/etools_datamart/apps/mart/data/models/audit_micro_assessment.py b/src/etools_datamart/apps/mart/data/models/audit_micro_assessment.py new file mode 100644 index 000000000..0fdbd3aaa --- /dev/null +++ b/src/etools_datamart/apps/mart/data/models/audit_micro_assessment.py @@ -0,0 +1,99 @@ +from django.contrib.postgres.fields import ArrayField, JSONField +from django.db import models +from django.db.models import Count +from django.utils.translation import gettext as _ + +from model_utils import Choices + +from etools_datamart.apps.mart.data.loader import EtoolsLoader +from etools_datamart.apps.mart.data.models.audit_engagement import EngagementRiskMixin +from etools_datamart.apps.mart.data.models.base import EtoolsDataMartModel +from etools_datamart.apps.sources.etools.models import AuditEngagement, AuditMicroassessment, AuditRisk + +from .partner import Partner + + +class MicroAssessmentLoader(EngagementRiskMixin, EtoolsLoader): + def get_subject_area(self, record: AuditEngagement, values: dict, **kwargs): + value, extra = self._get_risk(record, "ma_subject_areas") + values["subject_area_extra"] = extra + return value + + def get_test_subject_areas(self, record: AuditEngagement, values: dict, **kwargs): + return AuditRisk.objects.filter( + engagement=record, + blueprint__category__parent__code="ma_subject_areas", + ).values("blueprint__category__header").annotate( + count=Count("blueprint__category__header"), + ).order_by("blueprint__category__header") + + def process_country(self): + for record in AuditMicroassessment.objects.select_related('engagement_ptr'): + record.id = record.engagement_ptr_id + record.sub_type = AuditMicroassessment + record.engagement_ptr._impl = record + filters = self.config.key(self, record.engagement_ptr) + values = self.get_values(record.engagement_ptr) + + +class MicroAssessment(EtoolsDataMartModel): + TYPE_MICRO_ASSESSMENT = 'ma' + + TYPES = Choices( + (TYPE_MICRO_ASSESSMENT, _('Micro Assessment')), + ) + + engagement_type = models.CharField( + max_length=300, + blank=True, + null=True, + choices=TYPES, + db_index=True, + ) + agreement = models.CharField(max_length=300, blank=True, null=True) + partner = JSONField(blank=True, null=True, default=dict) + date_of_field_visit = models.DateField(null=True, blank=True) + date_of_final_report = models.DateField(null=True, blank=True) + shared_ip_with = ArrayField( + models.CharField(max_length=20, blank=True, null=True), + blank=True, + null=True, + default=list, + verbose_name=_('Shared Audit with'), + ) + rating = models.CharField( + max_length=50, + blank=True, + null=True, + ) + rating_extra = JSONField(blank=True, null=True, default=dict) + subject_area = models.CharField( + max_length=50, + blank=True, + null=True, + ) + subject_area_extra = JSONField(blank=True, null=True, default=dict) + test_subject_areas = models.CharField( + max_length=50, + blank=True, + null=True, + ) + + loader = MicroAssessmentLoader() + + class Meta: + ordering = ("id",) + + class Options: + source = AuditMicroassessment + sync_deleted_records = lambda a: False + depends = (Partner,) + mapping = dict( + agreement="agreement.order_number", + partner="-", + rating="-", + rating_extra="i", + subject_area="-", + subject_area_extra="i", + test_subject_areas="-", + ) diff --git a/src/etools_datamart/apps/mart/data/models/audit_result.py b/src/etools_datamart/apps/mart/data/models/audit_result.py index e36099860..1707cb803 100644 --- a/src/etools_datamart/apps/mart/data/models/audit_result.py +++ b/src/etools_datamart/apps/mart/data/models/audit_result.py @@ -3,8 +3,12 @@ from etools_datamart.apps.mart.data.loader import EtoolsLoader from etools_datamart.apps.mart.data.models.base import EtoolsDataMartModel from etools_datamart.apps.sources.etools.enrichment.consts import AuditEngagementConsts -from etools_datamart.apps.sources.etools.models import (AuditAudit, AuditFinancialfinding, - AuditKeyinternalcontrol, AuditRisk,) +from etools_datamart.apps.sources.etools.models import ( + AuditAudit, + AuditFinancialfinding, + AuditKeyinternalcontrol, + AuditRisk, +) class AuditResultLoader(EtoolsLoader): diff --git a/src/etools_datamart/apps/mart/data/models/audit_special.py b/src/etools_datamart/apps/mart/data/models/audit_special.py new file mode 100644 index 000000000..b45c182c2 --- /dev/null +++ b/src/etools_datamart/apps/mart/data/models/audit_special.py @@ -0,0 +1,79 @@ +from django.contrib.postgres.fields import ArrayField, JSONField +from django.db import models +from django.db.models import Count +from django.utils.translation import gettext as _ + +from model_utils import Choices + +from etools_datamart.apps.mart.data.loader import EtoolsLoader +from etools_datamart.apps.mart.data.models.audit_engagement import EngagementRiskMixin +from etools_datamart.apps.mart.data.models.base import EtoolsDataMartModel +from etools_datamart.apps.sources.etools.models import AuditEngagement, AuditFinancialfinding, AuditSpecialaudit + +from .partner import Partner + + +class AuditSpecialLoader(EngagementRiskMixin, EtoolsLoader): + def process_country(self): + for record in AuditSpecialaudit.objects.select_related('engagement_ptr'): + record.id = record.engagement_ptr_id + record.sub_type = AuditSpecialaudit + record.engagement_ptr._impl = record + filters = self.config.key(self, record.engagement_ptr) + values = self.get_values(record.engagement_ptr) + + +class AuditSpecial(EtoolsDataMartModel): + TYPE_SPECIAL_AUDIT = 'sa' + + TYPES = Choices( + (TYPE_SPECIAL_AUDIT, _('Special Audit')), + ) + + engagement_type = models.CharField( + max_length=300, + blank=True, + null=True, + choices=TYPES, + db_index=True, + ) + agreement = models.CharField(max_length=300, blank=True, null=True) + auditor = models.CharField( + max_length=255, + blank=True, + null=True, + ) + partner = JSONField(blank=True, null=True, default=dict) + shared_ip_with = ArrayField( + models.CharField(max_length=20, blank=True, null=True), + blank=True, + null=True, + default=list, + verbose_name=_('Shared Audit with'), + ) + total_value = models.DecimalField( + blank=True, + null=True, + decimal_places=2, + max_digits=20, + ) + date_of_final_report = models.DateField(null=True, blank=True) + joint_audit = models.BooleanField(null=True, blank=True) + date_of_field_visit = models.DateField(null=True, blank=True) + date_of_draft_report_to_ip = models.DateField(null=True, blank=True) + date_of_comments_by_ip = models.DateField(null=True, blank=True) + date_of_draft_report_to_unicef = models.DateField(null=True, blank=True) + + loader = AuditSpecialLoader() + + class Meta: + ordering = ("id",) + + class Options: + source = AuditSpecialaudit + sync_deleted_records = lambda a: False + depends = (Partner,) + mapping = dict( + auditor="agreement.auditor_firm.name", + partner="-", + ) diff --git a/src/etools_datamart/apps/mart/data/models/audit_spotcheck.py b/src/etools_datamart/apps/mart/data/models/audit_spotcheck.py index 381855537..662d29091 100644 --- a/src/etools_datamart/apps/mart/data/models/audit_spotcheck.py +++ b/src/etools_datamart/apps/mart/data/models/audit_spotcheck.py @@ -1,14 +1,22 @@ from django.contrib.postgres.fields import ArrayField, JSONField from django.db import models +from django.db.models import Count from django.utils.translation import gettext as _ from model_utils import Choices from etools_datamart.apps.mart.data.loader import EtoolsLoader +from etools_datamart.apps.mart.data.models.audit_engagement import EngagementRiskMixin from etools_datamart.apps.mart.data.models.base import EtoolsDataMartModel from etools_datamart.apps.sources.etools.enrichment.consts import AuditEngagementConsts -from etools_datamart.apps.sources.etools.models import (AuditEngagement, AuditEngagementActivePd, AuditFinding, - AuditSpotcheck, DjangoContentType, UnicefAttachmentsAttachment,) +from etools_datamart.apps.sources.etools.models import ( + AuditEngagement, + AuditEngagementActivePd, + AuditFinding, + AuditSpotcheck, + DjangoContentType, + UnicefAttachmentsAttachment, +) from .partner import Partner @@ -20,13 +28,7 @@ MODULEMAP = {'AuditSpotcheck': "fam"} -class SpotCheckLoader(EtoolsLoader): - - # def get_queryset(self): - # return AuditEngagement.objects.select_related('partner', - # 'agreement', - # 'po_item').filter(engagement_type='sc') - +class SpotCheckLoader(EngagementRiskMixin, EtoolsLoader): def get_content_type(self, sub_type): return DjangoContentType.objects.get(app_label='audit', model='spotcheck') @@ -67,7 +69,7 @@ def get_final_report(self, record: AuditEngagement, values: dict, **kwargs): def get_values(self, record, ): values = {} self.mapping.update(**values) - return super(SpotCheckLoader, self).get_values(record) + return super().get_values(record) def get_authorized_officers(self, record: AuditEngagement, values: dict, **kwargs): ret = [] @@ -94,21 +96,6 @@ def get_active_pd(self, record: AuditEngagement, values: dict, **kwargs): values['active_pd_data'] = ret return ", ".join([o['number'] for o in ret]) - def get_partner(self, record: AuditEngagement, values: dict, **kwargs): - try: - p = Partner.objects.get( - schema_name=self.context['country'].schema_name, - source_id=record.partner.id) - return {'name': p.name, - 'vendor_number': p.vendor_number, - 'id': p.id, - 'source_id': p.source_id} - except Partner.DoesNotExist: - return {'name': 'N/A', - 'vendor_number': 'N/A', - 'id': 'N/A', - 'source_id': 'N/A'} - def get_partner_id(self, record: AuditEngagement, values: dict, **kwargs): try: return Partner.objects.get( @@ -271,3 +258,105 @@ class Options: audit_opinion='_impl.audit_opinion', ) + + +class SpotCheckFindingsLoader(EngagementRiskMixin, EtoolsLoader): + def _get_priority_findings(self, record: AuditEngagement, priority: str): + return AuditFinding.objects.filter( + spot_check=record._impl, + priority=priority, + ).values("category_of_observation").annotate( + count=Count("category_of_observation"), + ).order_by("category_of_observation") + + def get_high_priority_findings(self, record: AuditSpotcheck, values: dict, **kwargs): + return self._get_priority_findings(record, "high") + + def get_low_priority_findings(self, record: AuditSpotcheck, values: dict, **kwargs): + return self._get_priority_findings(record, "low") + + def get_sections(self, record: AuditEngagement, values: dict, **kwargs): + data = [] + for rec in record.AuditEngagementSections_engagement.all(): + data.append( + dict( + source_id=rec.section.pk, + name=rec.section.name, + description=rec.section.description, + ), + ) + values['sections_data'] = data + return ", ".join([l['name'] for l in data]) + + def process_country(self): + for record in AuditSpotcheck.objects.select_related('engagement_ptr'): + record.id = record.engagement_ptr_id + record.sub_type = AuditSpotcheck + record.engagement_ptr._impl = record + filters = self.config.key(self, record.engagement_ptr) + values = self.get_values(record.engagement_ptr) + + +class SpotCheckFindings(EtoolsDataMartModel): + TYPE_SPOT_CHECK = 'sc' + + TYPES = Choices( + (TYPE_SPOT_CHECK, _('Spot Check')), + ) + + auditor = models.CharField( + max_length=255, + blank=True, + null=True, + ) + engagement_type = models.CharField( + max_length=300, + blank=True, + null=True, + choices=TYPES, + db_index=True, + ) + date_of_final_report = models.DateField(null=True, blank=True) + high_priorty_findings = JSONField(blank=True, null=True, default=dict) + low_priorty_findings = JSONField(blank=True, null=True, default=dict) + partner = JSONField(blank=True, null=True, default=dict) + sections = models.TextField(blank=True, null=True) + sections_data = JSONField(blank=True, null=True, default=dict) + spotcheck_total_amount_tested = models.DecimalField( + blank=True, + null=True, + decimal_places=2, + max_digits=20, + ) + spotcheck_total_amount_of_ineligible_expenditure = models.DecimalField( + null=True, + blank=True, + decimal_places=2, + max_digits=20, + ) + total_value = models.DecimalField( + blank=True, + null=True, + default=0, + decimal_places=2, + max_digits=20, + ) + + loader = SpotCheckFindingsLoader() + + class Meta: + ordering = ("id",) + + class Options: + source = AuditSpotcheck + sync_deleted_records = lambda a: False + depends = (Partner,) + mapping = dict( + auditor="agreement.auditor_firm.name", + partner="-", + high_priority_findings="-", + low_priority_findings="-", + sections="-", + spotcheck_total_amount_tested="_impl.total_amount_tested", + spotcheck_total_amount_of_ineligible_expenditure="_impl.total_amount_of_ineligible_expenditure", + ) diff --git a/src/etools_datamart/apps/mart/data/models/base.py b/src/etools_datamart/apps/mart/data/models/base.py index 6276e4ef4..64ca5d86d 100644 --- a/src/etools_datamart/apps/mart/data/models/base.py +++ b/src/etools_datamart/apps/mart/data/models/base.py @@ -7,8 +7,12 @@ # EtoolsLoader, EToolsLoaderOptions, ) from etools_datamart.apps.core.models import DataMartManager from etools_datamart.apps.etl.base import DataMartModelBase -from etools_datamart.apps.mart.data.loader import (CommonSchemaLoader, CommonSchemaLoaderOptions, - EtoolsLoader, EToolsLoaderOptions,) +from etools_datamart.apps.mart.data.loader import ( + CommonSchemaLoader, + CommonSchemaLoaderOptions, + EtoolsLoader, + EToolsLoaderOptions, +) class CommonDataMartModelModelBase(DataMartModelBase): diff --git a/src/etools_datamart/apps/mart/data/models/fam.py b/src/etools_datamart/apps/mart/data/models/fam.py index 54c3e7b42..ec907906b 100644 --- a/src/etools_datamart/apps/mart/data/models/fam.py +++ b/src/etools_datamart/apps/mart/data/models/fam.py @@ -7,8 +7,13 @@ from etools_datamart.apps.mart.data.loader import EtoolsLoader from etools_datamart.apps.mart.data.models.base import EtoolsDataMartModel -from etools_datamart.apps.sources.etools.models import (AuditAudit, AuditEngagement, AuditMicroassessment, - AuditSpecialaudit, AuditSpotcheck,) +from etools_datamart.apps.sources.etools.models import ( + AuditAudit, + AuditEngagement, + AuditMicroassessment, + AuditSpecialaudit, + AuditSpotcheck, +) class FAMIndicatorLoader(EtoolsLoader): diff --git a/src/etools_datamart/apps/mart/data/models/fm_questions.py b/src/etools_datamart/apps/mart/data/models/fm_questions.py index 321f05c0c..7bb333a2b 100644 --- a/src/etools_datamart/apps/mart/data/models/fm_questions.py +++ b/src/etools_datamart/apps/mart/data/models/fm_questions.py @@ -11,6 +11,7 @@ FieldMonitoringPlanningMonitoringactivityInterventions, FieldMonitoringPlanningMonitoringactivityPartners, FieldMonitoringSettingsOption, + FieldMonitoringSettingsQuestionMethods, ) @@ -23,7 +24,7 @@ def get_answer_options( **kwargs, ): option_qs = FieldMonitoringSettingsOption.objects.filter( - question=record.activity_question, + question=record.activity_question.question, ) return ", ".join([o.label for o in option_qs.all()]) @@ -33,8 +34,11 @@ def get_question_collection_methods( values: dict, **kwargs, ): + methods_qs = FieldMonitoringSettingsQuestionMethods.objects.filter( + question=record.activity_question.question, + ) return ", ".join( - [m.name for m in record.activity_question.methods.all()] + [m.method.name for m in methods_qs.all()] ) def process_country(self): @@ -199,17 +203,28 @@ def process_country(self): for rec in self.get_queryset(): filters = self.config.key(self, rec) values = self.get_values(rec) - for partner in rec.monitoring_activity.partners.all(): - values["entity"] = partner.name + activity = rec.monitoring_activity + partner_qs = FieldMonitoringPlanningMonitoringactivityPartners.objects.filter( + monitoringactivity=activity, + ) + intervention_qs = FieldMonitoringPlanningMonitoringactivityInterventions.objects.filter( + monitoringactivity=activity, + ) + cp_output_qs = FieldMonitoringPlanningMonitoringactivityCpOutputs.objects.filter( + monitoringactivity=activity, + ) + for rec in partner_qs.all(): + values["entity"] = rec.partnerorganization.name values["outcome"] = None op = self.process_record(filters, values) self.increment_counter(op) - for pd in rec.monitoring_activity.interventions.all(): - values["entity"] = pd.reference_number + for rec in intervention_qs.all(): + values["entity"] = rec.intervention.reference_number values["outcome"] = None op = self.process_record(filters, values) self.increment_counter(op) - for cp_output in rec.monitoring_activity.cp_output.all(): + for rec in cp_output_qs.all(): + cp_putput = rec.result values["entity"] = cp_output.name values["outcome"] = cp_output.parent.wbs if cp_output.parent else None op = self.process_record(filters, values) diff --git a/src/etools_datamart/apps/mart/data/models/intervention.py b/src/etools_datamart/apps/mart/data/models/intervention.py index 9a991d4cd..d0db55ddd 100644 --- a/src/etools_datamart/apps/mart/data/models/intervention.py +++ b/src/etools_datamart/apps/mart/data/models/intervention.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging from django.contrib.postgres.fields import JSONField @@ -8,11 +7,14 @@ from etools_datamart.apps.mart.data.loader import EtoolsLoader from etools_datamart.apps.mart.data.models.reports_office import Office from etools_datamart.apps.sources.etools.enrichment.consts import PartnersInterventionConst, TravelType - -from etools_datamart.apps.sources.etools.models import (FundsFundsreservationheader, PartnersIntervention, - PartnersInterventionamendment, - PartnersInterventionplannedvisits, ReportsAppliedindicator, - T2FTravelactivity,) +from etools_datamart.apps.sources.etools.models import ( + FundsFundsreservationheader, + PartnersIntervention, + PartnersInterventionamendment, + PartnersInterventionplannedvisits, + ReportsAppliedindicator, + T2FTravelactivity, +) from etools_datamart.sentry import process_exception from .base import EtoolsDataMartModel diff --git a/src/etools_datamart/apps/mart/data/models/partners_agreement.py b/src/etools_datamart/apps/mart/data/models/partners_agreement.py index fe6969362..9ff4ada4b 100644 --- a/src/etools_datamart/apps/mart/data/models/partners_agreement.py +++ b/src/etools_datamart/apps/mart/data/models/partners_agreement.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# import django_filters from django.db import models from etools_datamart.apps.mart.data.loader import EtoolsLoader diff --git a/src/etools_datamart/apps/mart/data/models/partners_interventionbudget.py b/src/etools_datamart/apps/mart/data/models/partners_interventionbudget.py index a949ff674..c103e5265 100644 --- a/src/etools_datamart/apps/mart/data/models/partners_interventionbudget.py +++ b/src/etools_datamart/apps/mart/data/models/partners_interventionbudget.py @@ -3,8 +3,12 @@ from etools_datamart.apps.mart.data.models import Location from etools_datamart.apps.mart.data.models.base import EtoolsDataMartModel from etools_datamart.apps.mart.data.models.intervention import InterventionAbstract, InterventionLoader -from etools_datamart.apps.sources.etools.models import (FundsFundsreservationheader, models, - PartnersIntervention, PartnersInterventionbudget,) +from etools_datamart.apps.sources.etools.models import ( + FundsFundsreservationheader, + models, + PartnersIntervention, + PartnersInterventionbudget, +) class InterventionBudgetLoader(InterventionLoader): diff --git a/src/etools_datamart/apps/mart/data/models/partners_staffmember.py b/src/etools_datamart/apps/mart/data/models/partners_staffmember.py index ac77a5ad4..0682e7d1a 100644 --- a/src/etools_datamart/apps/mart/data/models/partners_staffmember.py +++ b/src/etools_datamart/apps/mart/data/models/partners_staffmember.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# import django_filters from django.db import models from etools_datamart.apps.mart.data.loader import EtoolsLoader diff --git a/src/etools_datamart/apps/mart/data/models/pmp.py b/src/etools_datamart/apps/mart/data/models/pmp.py index 00cbc671d..f69e9ba75 100644 --- a/src/etools_datamart/apps/mart/data/models/pmp.py +++ b/src/etools_datamart/apps/mart/data/models/pmp.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging from django.db import models diff --git a/src/etools_datamart/apps/mart/data/models/tpm_tmpvisit.py b/src/etools_datamart/apps/mart/data/models/tpm_tmpvisit.py index f819bfd7c..8b3b14cda 100644 --- a/src/etools_datamart/apps/mart/data/models/tpm_tmpvisit.py +++ b/src/etools_datamart/apps/mart/data/models/tpm_tmpvisit.py @@ -3,8 +3,13 @@ from etools_datamart.apps.mart.data.loader import EtoolsLoader from etools_datamart.apps.mart.data.models.base import EtoolsDataMartModel -from etools_datamart.apps.sources.etools.models import (DjangoContentType, TpmTpmactivityUnicefFocalPoints, TpmTpmvisit, - TpmTpmvisitTpmPartnerFocalPoints, UnicefAttachmentsAttachment,) +from etools_datamart.apps.sources.etools.models import ( + DjangoContentType, + TpmTpmactivityUnicefFocalPoints, + TpmTpmvisit, + TpmTpmvisitTpmPartnerFocalPoints, + UnicefAttachmentsAttachment, +) from etools_datamart.sentry import process_exception diff --git a/src/etools_datamart/apps/mart/data/tasks.py b/src/etools_datamart/apps/mart/data/tasks.py index e622fedf9..740f0f582 100644 --- a/src/etools_datamart/apps/mart/data/tasks.py +++ b/src/etools_datamart/apps/mart/data/tasks.py @@ -1,4 +1,5 @@ from django.db.models import Q + from etools_datamart.apps.mart.data.models.location import GeoName, GeoNameLimitException from etools_datamart.celery import app diff --git a/src/etools_datamart/apps/mart/prp/admin.py b/src/etools_datamart/apps/mart/prp/admin.py index a701dcf16..67108d964 100644 --- a/src/etools_datamart/apps/mart/prp/admin.py +++ b/src/etools_datamart/apps/mart/prp/admin.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging from django.contrib.admin import ModelAdmin, register diff --git a/src/etools_datamart/apps/mart/prp/models.py b/src/etools_datamart/apps/mart/prp/models.py index e19322179..c616d17e8 100644 --- a/src/etools_datamart/apps/mart/prp/models.py +++ b/src/etools_datamart/apps/mart/prp/models.py @@ -57,12 +57,20 @@ from etools_datamart.apps.etl.exceptions import MaxRecordsException, RequiredIsMissing, RequiredIsRunning from etools_datamart.apps.etl.loader import BaseLoader, EtlResult, logger, RUN_UNKNOWN -from etools_datamart.apps.sources.source_prp.models import (CoreCountry, CoreGatewaytype, IndicatorDisaggregationvalue, - IndicatorIndicatorlocationdata, IndicatorIndicatorreport, - IndicatorReportable, IndicatorReportablelocationgoal, - UnicefLowerleveloutput, UnicefPdresultlink, - UnicefProgrammedocument, UnicefProgrammedocumentSections, - UnicefProgressreport,) +from etools_datamart.apps.sources.source_prp.models import ( + CoreCountry, + CoreGatewaytype, + IndicatorDisaggregationvalue, + IndicatorIndicatorlocationdata, + IndicatorIndicatorreport, + IndicatorReportable, + IndicatorReportablelocationgoal, + UnicefLowerleveloutput, + UnicefPdresultlink, + UnicefProgrammedocument, + UnicefProgrammedocumentSections, + UnicefProgressreport, +) from etools_datamart.sentry import process_exception from .base import PrpDataMartModel diff --git a/src/etools_datamart/apps/mart/rapidpro/loader.py b/src/etools_datamart/apps/mart/rapidpro/loader.py index fc000caaf..d4cc3605b 100644 --- a/src/etools_datamart/apps/mart/rapidpro/loader.py +++ b/src/etools_datamart/apps/mart/rapidpro/loader.py @@ -113,7 +113,7 @@ def on_end(self, error=None, retry=False): def load(self, *, verbosity=0, stdout=None, ignore_dependencies=False, max_records=None, only_delta=True, run_type=RUN_UNKNOWN, api_token=None, **kwargs): - from .models import Source, Organization + from .models import Organization, Source sources = Source.objects.filter(is_active=True) self.results = EtlResult() with push_scope() as scope: diff --git a/src/etools_datamart/apps/me/apps.py b/src/etools_datamart/apps/me/apps.py index b6966f872..9c33369a5 100644 --- a/src/etools_datamart/apps/me/apps.py +++ b/src/etools_datamart/apps/me/apps.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.apps import AppConfig diff --git a/src/etools_datamart/apps/multitenant/__init__.py b/src/etools_datamart/apps/multitenant/__init__.py index 40a96afc6..e69de29bb 100644 --- a/src/etools_datamart/apps/multitenant/__init__.py +++ b/src/etools_datamart/apps/multitenant/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/src/etools_datamart/apps/multitenant/admin.py b/src/etools_datamart/apps/multitenant/admin.py index 5b0eb8230..de52ac182 100644 --- a/src/etools_datamart/apps/multitenant/admin.py +++ b/src/etools_datamart/apps/multitenant/admin.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.contrib import messages from django.contrib.admin import ListFilter, ModelAdmin from django.contrib.admin.utils import quote @@ -89,7 +88,7 @@ class TenantModelAdmin(ExtraUrlMixin, DisplayAllMixin, ReadOnlyMixin, ModelAdmin list_filter = [SchemaFilter, ] # def get_queryset(self, request): - # super(TenantModelAdmin, self).get_queryset(request) + # super().get_queryset(request) def get_object(self, request, object_id, from_field=None): pk, schema = object_id.split('-') diff --git a/src/etools_datamart/apps/multitenant/context_processors.py b/src/etools_datamart/apps/multitenant/context_processors.py index 08212c07f..b44e91f4d 100644 --- a/src/etools_datamart/apps/multitenant/context_processors.py +++ b/src/etools_datamart/apps/multitenant/context_processors.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - from django.db import connections diff --git a/src/etools_datamart/apps/multitenant/exceptions.py b/src/etools_datamart/apps/multitenant/exceptions.py index bacb75d76..c47289aa5 100644 --- a/src/etools_datamart/apps/multitenant/exceptions.py +++ b/src/etools_datamart/apps/multitenant/exceptions.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.template.defaultfilters import pluralize from rest_framework.exceptions import PermissionDenied diff --git a/src/etools_datamart/apps/multitenant/forms.py b/src/etools_datamart/apps/multitenant/forms.py index 89b6fb8ef..ba3e6f686 100644 --- a/src/etools_datamart/apps/multitenant/forms.py +++ b/src/etools_datamart/apps/multitenant/forms.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging from django import forms diff --git a/src/etools_datamart/apps/multitenant/management/__init__.py b/src/etools_datamart/apps/multitenant/management/__init__.py index 40a96afc6..e69de29bb 100644 --- a/src/etools_datamart/apps/multitenant/management/__init__.py +++ b/src/etools_datamart/apps/multitenant/management/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/src/etools_datamart/apps/multitenant/management/commands/__init__.py b/src/etools_datamart/apps/multitenant/management/commands/__init__.py index 40a96afc6..e69de29bb 100644 --- a/src/etools_datamart/apps/multitenant/management/commands/__init__.py +++ b/src/etools_datamart/apps/multitenant/management/commands/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/src/etools_datamart/apps/multitenant/models.py b/src/etools_datamart/apps/multitenant/models.py index 833a73698..e8f931aaf 100644 --- a/src/etools_datamart/apps/multitenant/models.py +++ b/src/etools_datamart/apps/multitenant/models.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging from django.db.models import * # noqa diff --git a/src/etools_datamart/apps/multitenant/postgresql/base.py b/src/etools_datamart/apps/multitenant/postgresql/base.py index 4d81a1ffe..a5ee3ce4b 100644 --- a/src/etools_datamart/apps/multitenant/postgresql/base.py +++ b/src/etools_datamart/apps/multitenant/postgresql/base.py @@ -63,7 +63,7 @@ class TenantCursor(CursorWrapper): def execute(self, sql, params=None): if isinstance(sql, RawSql): - return super(TenantCursor, self).execute(sql, params) + return super().execute(sql, params) msg = f""" schemas: {self.db.schemas} @@ -71,9 +71,9 @@ def execute(self, sql, params=None): """ try: if len(self.db.schemas) == 0: - return super(TenantCursor, self).execute(sql, params) + return super().execute(sql, params) # if not sql.strip().startswith('SELECT'): - # return super(TenantCursor, self).execute(sql, params) + # return super().execute(sql, params) # cleanup field 'id', it does not exists in # in django inherited table. @@ -95,7 +95,7 @@ def execute(self, sql, params=None): """ logger.debug(msg) - return super(TenantCursor, self).execute(tenant_sql, params * len(self.db.schemas)) + return super().execute(tenant_sql, params * len(self.db.schemas)) except django.db.utils.ProgrammingError as e: # pragma: no cover logger.error(f"{e} {msg}") raise django.db.utils.ProgrammingError(f"{type(e)}:{e} {msg}") from e @@ -152,7 +152,7 @@ class DatabaseWrapper(original_backend.DatabaseWrapper): introspection_class = DatabaseSchemaIntrospection def __init__(self, *args, **kwargs): - super(DatabaseWrapper, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # Use a patched version of the DatabaseIntrospection that only returns the table list for the # currently selected schema. @@ -163,7 +163,7 @@ def __init__(self, *args, **kwargs): def close(self): self.search_path_set = False self._schemas = [] - super(DatabaseWrapper, self).close() + super().close() @property def schemas(self): @@ -257,9 +257,9 @@ def make_cursor(self, cursor): # def single_cursor(self, name=None, ): # if name: # # Only supported and required by Django 1.11 (server-side cursor) - # cursor = super(DatabaseWrapper, self)._cursor(name=name) + # cursor = super()._cursor(name=name) # else: - # cursor = super(DatabaseWrapper, self)._cursor() + # cursor = super()._cursor() # return cursor # def set_search_paths(self, cursor, *schemas): @@ -280,9 +280,9 @@ def _cursor(self, name=None): if name: # pragma: no cover # Only supported and required by Django 1.11 (server-side cursor) - cursor = super(DatabaseWrapper, self)._cursor(name=name) + cursor = super()._cursor(name=name) else: - cursor = super(DatabaseWrapper, self)._cursor() + cursor = super()._cursor() # optionally limit the number of executions - under load, the execution # of `set search_path` can be quite time consuming diff --git a/src/etools_datamart/apps/multitenant/postgresql/introspection.py b/src/etools_datamart/apps/multitenant/postgresql/introspection.py index e6fa3a11a..094ca11e6 100644 --- a/src/etools_datamart/apps/multitenant/postgresql/introspection.py +++ b/src/etools_datamart/apps/multitenant/postgresql/introspection.py @@ -165,7 +165,7 @@ class DatabaseSchemaIntrospection(BaseDatabaseIntrospection): """) def get_field_type(self, data_type, description): - field_type = super(DatabaseSchemaIntrospection, self).get_field_type(data_type, description) + field_type = super().get_field_type(data_type, description) if description.default and 'nextval' in description.default: if field_type == 'IntegerField': return 'AutoField' diff --git a/src/etools_datamart/apps/multitenant/postgresql/utils.py b/src/etools_datamart/apps/multitenant/postgresql/utils.py index a17132b05..9443c27cc 100644 --- a/src/etools_datamart/apps/multitenant/postgresql/utils.py +++ b/src/etools_datamart/apps/multitenant/postgresql/utils.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from contextlib import contextmanager from django.db import connections diff --git a/src/etools_datamart/apps/multitenant/query.py b/src/etools_datamart/apps/multitenant/query.py index 13735f4cc..72b4784b4 100644 --- a/src/etools_datamart/apps/multitenant/query.py +++ b/src/etools_datamart/apps/multitenant/query.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging from django.db import connections diff --git a/src/etools_datamart/apps/multitenant/sql.py b/src/etools_datamart/apps/multitenant/sql.py index 9b5c124f7..7691ef9b8 100644 --- a/src/etools_datamart/apps/multitenant/sql.py +++ b/src/etools_datamart/apps/multitenant/sql.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import re from collections import OrderedDict diff --git a/src/etools_datamart/apps/multitenant/templatetags/__init__.py b/src/etools_datamart/apps/multitenant/templatetags/__init__.py index 40a96afc6..e69de29bb 100644 --- a/src/etools_datamart/apps/multitenant/templatetags/__init__.py +++ b/src/etools_datamart/apps/multitenant/templatetags/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/src/etools_datamart/apps/multitenant/templatetags/multitenant.py b/src/etools_datamart/apps/multitenant/templatetags/multitenant.py index 12e651ed1..4e271f8ea 100644 --- a/src/etools_datamart/apps/multitenant/templatetags/multitenant.py +++ b/src/etools_datamart/apps/multitenant/templatetags/multitenant.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django import template from django.db import connections diff --git a/src/etools_datamart/apps/multitenant/views.py b/src/etools_datamart/apps/multitenant/views.py index 2ae68371f..dd68a032f 100644 --- a/src/etools_datamart/apps/multitenant/views.py +++ b/src/etools_datamart/apps/multitenant/views.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging from django.http import HttpResponseRedirect diff --git a/src/etools_datamart/apps/security/models.py b/src/etools_datamart/apps/security/models.py index 77ca63b81..81508bfc2 100644 --- a/src/etools_datamart/apps/security/models.py +++ b/src/etools_datamart/apps/security/models.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - from django.contrib.auth.models import Group from django.contrib.postgres.fields import ArrayField from django.db import models diff --git a/src/etools_datamart/apps/sources/etools/__init__.py b/src/etools_datamart/apps/sources/etools/__init__.py index 4bcdac5f5..85239fe11 100644 --- a/src/etools_datamart/apps/sources/etools/__init__.py +++ b/src/etools_datamart/apps/sources/etools/__init__.py @@ -1,2 +1 @@ -# -*- coding: utf-8 -*- default_app_config = 'etools_datamart.apps.sources.etools.apps.Config' diff --git a/src/etools_datamart/apps/sources/etools/admin.py b/src/etools_datamart/apps/sources/etools/admin.py index b101b85e5..b0ce045f4 100644 --- a/src/etools_datamart/apps/sources/etools/admin.py +++ b/src/etools_datamart/apps/sources/etools/admin.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.contrib.admin import register from etools_datamart.apps.multitenant.admin import EToolsModelAdmin, TenantModelAdmin diff --git a/src/etools_datamart/apps/sources/etools/enrichment/__init__.py b/src/etools_datamart/apps/sources/etools/enrichment/__init__.py index 1b009f018..b008e1f30 100644 --- a/src/etools_datamart/apps/sources/etools/enrichment/__init__.py +++ b/src/etools_datamart/apps/sources/etools/enrichment/__init__.py @@ -7,11 +7,26 @@ def apply(): # flake8: noqa: F401 - from . import (actionpoint, audit_engagement, auth_user, auth_usergroups, partners_intervention, - partners_partnerorganization, partners_plannedengagement, reports_appliedindicator, - tpm_activity, tpm_visit, partners_agreement, reports_lowerresult, - t2f_travel, t2f_travelactivity, users_userprofile, utils, tpm_partner) # noqa - from . import consts + from . import ( # noqa + actionpoint, + audit_engagement, + auth_user, + auth_usergroups, + consts, + partners_agreement, + partners_intervention, + partners_partnerorganization, + partners_plannedengagement, + reports_appliedindicator, + reports_lowerresult, + t2f_travel, + t2f_travelactivity, + tpm_activity, + tpm_partner, + tpm_visit, + users_userprofile, + utils, + ) app_models = apps.get_app_config('etools').get_models() for model in app_models: diff --git a/src/etools_datamart/apps/sources/etools/enrichment/actionpoint.py b/src/etools_datamart/apps/sources/etools/enrichment/actionpoint.py index 9e0dd17d0..c1e086224 100644 --- a/src/etools_datamart/apps/sources/etools/enrichment/actionpoint.py +++ b/src/etools_datamart/apps/sources/etools/enrichment/actionpoint.py @@ -2,8 +2,13 @@ from django.core.exceptions import ObjectDoesNotExist -from etools_datamart.apps.sources.etools.models import (ActionPointsActionpoint, AuditAudit, - AuditMicroassessment, AuditSpecialaudit, AuditSpotcheck,) +from etools_datamart.apps.sources.etools.models import ( + ActionPointsActionpoint, + AuditAudit, + AuditMicroassessment, + AuditSpecialaudit, + AuditSpotcheck, +) logger = logging.getLogger() diff --git a/src/etools_datamart/apps/sources/etools/enrichment/audit_engagement.py b/src/etools_datamart/apps/sources/etools/enrichment/audit_engagement.py index 13b84ad16..9d9fdc296 100644 --- a/src/etools_datamart/apps/sources/etools/enrichment/audit_engagement.py +++ b/src/etools_datamart/apps/sources/etools/enrichment/audit_engagement.py @@ -1,10 +1,18 @@ from django.db import models -from etools_datamart.apps.sources.etools.models import (AuditAudit, AuditEngagement, AuditEngagementActivePd, - AuditEngagementAuthorizedOfficers, AuditEngagementStaffMembers, - AuditMicroassessment, AuditSpecialaudit, AuditSpotcheck, - PartnersIntervention, PartnersPartnerstaffmember, - PurchaseOrderAuditorstaffmember,) +from etools_datamart.apps.sources.etools.models import ( + AuditAudit, + AuditEngagement, + AuditEngagementActivePd, + AuditEngagementAuthorizedOfficers, + AuditEngagementStaffMembers, + AuditMicroassessment, + AuditSpecialaudit, + AuditSpotcheck, + PartnersIntervention, + PartnersPartnerstaffmember, + PurchaseOrderAuditorstaffmember, +) from .utils import set_primary_key diff --git a/src/etools_datamart/apps/sources/etools/enrichment/partners_agreement.py b/src/etools_datamart/apps/sources/etools/enrichment/partners_agreement.py index ab4df236d..05ac3cbae 100644 --- a/src/etools_datamart/apps/sources/etools/enrichment/partners_agreement.py +++ b/src/etools_datamart/apps/sources/etools/enrichment/partners_agreement.py @@ -1,5 +1,9 @@ from etools_datamart.apps.sources.etools.models import ( - PartnersAgreement, PartnersAgreementamendment, PartnersAgreementAuthorizedOfficers, PartnersPartnerstaffmember,) + PartnersAgreement, + PartnersAgreementamendment, + PartnersAgreementAuthorizedOfficers, + PartnersPartnerstaffmember, +) from .utils import add_m2m diff --git a/src/etools_datamart/apps/sources/etools/enrichment/partners_intervention.py b/src/etools_datamart/apps/sources/etools/enrichment/partners_intervention.py index cce3ec55c..28b67701d 100644 --- a/src/etools_datamart/apps/sources/etools/enrichment/partners_intervention.py +++ b/src/etools_datamart/apps/sources/etools/enrichment/partners_intervention.py @@ -1,12 +1,20 @@ from django.db import models -from etools_datamart.apps.sources.etools.models import (AuthUser, LocationsLocation, PartnersIntervention, - PartnersInterventionFlatLocations, PartnersInterventionOffices, - PartnersInterventionPartnerFocalPoints, - PartnersInterventionresultlink, PartnersInterventionSections, - PartnersInterventionUnicefFocalPoints, - PartnersPartnerstaffmember, ReportsOffice, ReportsResult, - ReportsSector,) +from etools_datamart.apps.sources.etools.models import ( + AuthUser, + LocationsLocation, + PartnersIntervention, + PartnersInterventionFlatLocations, + PartnersInterventionOffices, + PartnersInterventionPartnerFocalPoints, + PartnersInterventionresultlink, + PartnersInterventionSections, + PartnersInterventionUnicefFocalPoints, + PartnersPartnerstaffmember, + ReportsOffice, + ReportsResult, + ReportsSector, +) from .utils import create_alias diff --git a/src/etools_datamart/apps/sources/etools/enrichment/reports_appliedindicator.py b/src/etools_datamart/apps/sources/etools/enrichment/reports_appliedindicator.py index 91b8fecb6..6397e915d 100644 --- a/src/etools_datamart/apps/sources/etools/enrichment/reports_appliedindicator.py +++ b/src/etools_datamart/apps/sources/etools/enrichment/reports_appliedindicator.py @@ -1,8 +1,12 @@ from django.db import models -from etools_datamart.apps.sources.etools.models import (LocationsLocation, ReportsAppliedindicator, - ReportsAppliedindicatorDisaggregation, - ReportsAppliedindicatorLocations, ReportsDisaggregation,) +from etools_datamart.apps.sources.etools.models import ( + LocationsLocation, + ReportsAppliedindicator, + ReportsAppliedindicatorDisaggregation, + ReportsAppliedindicatorLocations, + ReportsDisaggregation, +) models.ManyToManyField(ReportsDisaggregation, through=ReportsAppliedindicatorDisaggregation, diff --git a/src/etools_datamart/apps/sources/etools/enrichment/t2f_travelactivity.py b/src/etools_datamart/apps/sources/etools/enrichment/t2f_travelactivity.py index bd6ae59f4..8efa75376 100644 --- a/src/etools_datamart/apps/sources/etools/enrichment/t2f_travelactivity.py +++ b/src/etools_datamart/apps/sources/etools/enrichment/t2f_travelactivity.py @@ -1,7 +1,12 @@ from django.db import models -from etools_datamart.apps.sources.etools.models import (LocationsLocation, T2FTravel, T2FTravelactivity, - T2FTravelactivityLocations, T2FTravelactivityTravels,) +from etools_datamart.apps.sources.etools.models import ( + LocationsLocation, + T2FTravel, + T2FTravelactivity, + T2FTravelactivityLocations, + T2FTravelactivityTravels, +) from .utils import add_m2m diff --git a/src/etools_datamart/apps/sources/etools/enrichment/tpm_activity.py b/src/etools_datamart/apps/sources/etools/enrichment/tpm_activity.py index bdf9f29a8..cc11b7243 100644 --- a/src/etools_datamart/apps/sources/etools/enrichment/tpm_activity.py +++ b/src/etools_datamart/apps/sources/etools/enrichment/tpm_activity.py @@ -1,8 +1,15 @@ from django.db import models -from etools_datamart.apps.sources.etools.models import (ActivitiesActivity, ActivitiesActivityLocations, AuthUser, - LocationsLocation, ReportsOffice, TpmTpmactivity, - TpmTpmactivityOffices, TpmTpmactivityUnicefFocalPoints,) +from etools_datamart.apps.sources.etools.models import ( + ActivitiesActivity, + ActivitiesActivityLocations, + AuthUser, + LocationsLocation, + ReportsOffice, + TpmTpmactivity, + TpmTpmactivityOffices, + TpmTpmactivityUnicefFocalPoints, +) from .utils import set_primary_key diff --git a/src/etools_datamart/apps/sources/etools/enrichment/tpm_partner.py b/src/etools_datamart/apps/sources/etools/enrichment/tpm_partner.py index 60e0f12ac..ecd74e58d 100644 --- a/src/etools_datamart/apps/sources/etools/enrichment/tpm_partner.py +++ b/src/etools_datamart/apps/sources/etools/enrichment/tpm_partner.py @@ -1,7 +1,10 @@ from django.db import models -from etools_datamart.apps.sources.etools.models import (TpmpartnersTpmpartner, - TpmpartnersTpmpartnerCountries, UsersCountry,) +from etools_datamart.apps.sources.etools.models import ( + TpmpartnersTpmpartner, + TpmpartnersTpmpartnerCountries, + UsersCountry, +) models.ManyToManyField(UsersCountry, through=TpmpartnersTpmpartnerCountries, diff --git a/src/etools_datamart/apps/sources/etools/enrichment/tpm_visit.py b/src/etools_datamart/apps/sources/etools/enrichment/tpm_visit.py index 87e4df8d3..1f55a9e50 100644 --- a/src/etools_datamart/apps/sources/etools/enrichment/tpm_visit.py +++ b/src/etools_datamart/apps/sources/etools/enrichment/tpm_visit.py @@ -1,7 +1,11 @@ from django.db import models -from etools_datamart.apps.sources.etools.models import (TpmpartnersTpmpartnerstaffmember, TpmTpmactivity, - TpmTpmvisit, TpmTpmvisitTpmPartnerFocalPoints,) +from etools_datamart.apps.sources.etools.models import ( + TpmpartnersTpmpartnerstaffmember, + TpmTpmactivity, + TpmTpmvisit, + TpmTpmvisitTpmPartnerFocalPoints, +) from .utils import create_alias diff --git a/src/etools_datamart/apps/sources/etools/enrichment/users_userprofile.py b/src/etools_datamart/apps/sources/etools/enrichment/users_userprofile.py index f39e2e5ed..32cf6c757 100644 --- a/src/etools_datamart/apps/sources/etools/enrichment/users_userprofile.py +++ b/src/etools_datamart/apps/sources/etools/enrichment/users_userprofile.py @@ -1,7 +1,11 @@ from django.db import models -from etools_datamart.apps.sources.etools.models import (AuthUser, UsersCountry, UsersUserprofile, - UsersUserprofileCountriesAvailable,) +from etools_datamart.apps.sources.etools.models import ( + AuthUser, + UsersCountry, + UsersUserprofile, + UsersUserprofileCountriesAvailable, +) f = [f for f in UsersUserprofile._meta.local_fields if f.name != 'user_id'] UsersUserprofile._meta.local_fields = f diff --git a/src/etools_datamart/apps/sources/source_prp/enrichment/__init__.py b/src/etools_datamart/apps/sources/source_prp/enrichment/__init__.py index 21ef7529e..76facc3d6 100644 --- a/src/etools_datamart/apps/sources/source_prp/enrichment/__init__.py +++ b/src/etools_datamart/apps/sources/source_prp/enrichment/__init__.py @@ -1,4 +1,4 @@ def patch(): - from . import reportable # noqa from . import indicator_blueprint # noqa from . import indicator_locationdata # noqa + from . import reportable # noqa diff --git a/src/etools_datamart/apps/sources/source_prp/enrichment/consts.py b/src/etools_datamart/apps/sources/source_prp/enrichment/consts.py index 83a568d45..24039fbc1 100644 --- a/src/etools_datamart/apps/sources/source_prp/enrichment/consts.py +++ b/src/etools_datamart/apps/sources/source_prp/enrichment/consts.py @@ -1,6 +1,5 @@ from model_utils import Choices - REPORTING_TYPES = Choices( ('QPR', 'Quarterly Progress Report'), ('HR', 'Humanitarian Report'), diff --git a/src/etools_datamart/apps/sources/source_prp/management/commands/inspectprp.py b/src/etools_datamart/apps/sources/source_prp/management/commands/inspectprp.py index 0808cb19d..dbf34831c 100644 --- a/src/etools_datamart/apps/sources/source_prp/management/commands/inspectprp.py +++ b/src/etools_datamart/apps/sources/source_prp/management/commands/inspectprp.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging import re from collections import OrderedDict diff --git a/src/etools_datamart/apps/subscriptions/admin.py b/src/etools_datamart/apps/subscriptions/admin.py index 846b9593a..61f8b51ac 100644 --- a/src/etools_datamart/apps/subscriptions/admin.py +++ b/src/etools_datamart/apps/subscriptions/admin.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.contrib import admin from django.contrib.admin import register diff --git a/src/etools_datamart/apps/tracking/__init__.py b/src/etools_datamart/apps/tracking/__init__.py index 40a96afc6..e69de29bb 100644 --- a/src/etools_datamart/apps/tracking/__init__.py +++ b/src/etools_datamart/apps/tracking/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/src/etools_datamart/apps/tracking/admin.py b/src/etools_datamart/apps/tracking/admin.py index 632cf2d6a..9a22e9d6e 100644 --- a/src/etools_datamart/apps/tracking/admin.py +++ b/src/etools_datamart/apps/tracking/admin.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import json import logging from urllib.parse import urlencode diff --git a/src/etools_datamart/apps/tracking/management/commands/track.py b/src/etools_datamart/apps/tracking/management/commands/track.py index 02d7d51f5..5bac8da1b 100644 --- a/src/etools_datamart/apps/tracking/management/commands/track.py +++ b/src/etools_datamart/apps/tracking/management/commands/track.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging import os from urllib.parse import urlencode @@ -49,6 +48,7 @@ def handle(self, *args, **options): self.verbosity = options['verbosity'] tid = options['tid'] import requests + # """https://www.google-analytics.com/r/collect?v=1&_v=j72&a=1254325655&t=pageview&_s=1&dl=http%3A%2F%2Flocalhost%2F&ul=en-gb&de=UTF-8&dt=Title&sd=24-bit&sr=1440x900&vp=1425x459&je=0&_u=IEBAAUAB~&jid=243210006&gjid=1351824934&cid=778822076.1544038618&tid=UA-130479575-1&_gid=909229133.1544038618&_r=1>m=2oubc0&z=118711575""" values = { "v": 1, diff --git a/src/etools_datamart/apps/tracking/middleware.py b/src/etools_datamart/apps/tracking/middleware.py index c0520973d..f5eb09f21 100644 --- a/src/etools_datamart/apps/tracking/middleware.py +++ b/src/etools_datamart/apps/tracking/middleware.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import json import logging @@ -155,7 +154,7 @@ def __call__(self, request): # # class ThreadedStatsMiddleware(StatsMiddleware): # def __init__(self, get_response): -# super(ThreadedStatsMiddleware, self).__init__(get_response) +# super().__init__(get_response) # self.worker = AsyncLogger() # # def log(self, request, response): diff --git a/src/etools_datamart/apps/tracking/models/__init__.py b/src/etools_datamart/apps/tracking/models/__init__.py index 412dca55c..0b2b2bd81 100644 --- a/src/etools_datamart/apps/tracking/models/__init__.py +++ b/src/etools_datamart/apps/tracking/models/__init__.py @@ -1,3 +1,2 @@ -# -*- coding: utf-8 -*- from .counters import DailyCounter, MonthlyCounter, PathCounter, UserCounter # noqa; noqa from .log import APIRequestLog # noqa diff --git a/src/etools_datamart/apps/tracking/models/counters.py b/src/etools_datamart/apps/tracking/models/counters.py index 0af1b1627..3747c44ee 100644 --- a/src/etools_datamart/apps/tracking/models/counters.py +++ b/src/etools_datamart/apps/tracking/models/counters.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging from django.conf import settings diff --git a/src/etools_datamart/apps/tracking/models/log.py b/src/etools_datamart/apps/tracking/models/log.py index 402a17275..4ac812b9d 100644 --- a/src/etools_datamart/apps/tracking/models/log.py +++ b/src/etools_datamart/apps/tracking/models/log.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging from django.conf import settings diff --git a/src/etools_datamart/apps/tracking/tasks.py b/src/etools_datamart/apps/tracking/tasks.py index d0037e797..6ec1c619c 100644 --- a/src/etools_datamart/apps/tracking/tasks.py +++ b/src/etools_datamart/apps/tracking/tasks.py @@ -1,4 +1,3 @@ -# # -*- coding: utf-8 -*- # from celery.utils.log import get_task_logger # # from etools_datamart.celery import app @@ -8,7 +7,6 @@ # task_logger = get_task_logger(__name__) # # -# # -*- coding: utf-8 -*- # import logging # from datetime import datetime, timedelta # diff --git a/src/etools_datamart/apps/web/apps.py b/src/etools_datamart/apps/web/apps.py index 9f4686b58..3c81cc30e 100644 --- a/src/etools_datamart/apps/web/apps.py +++ b/src/etools_datamart/apps/web/apps.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.apps import AppConfig diff --git a/src/etools_datamart/apps/web/templatetags/__init__.py b/src/etools_datamart/apps/web/templatetags/__init__.py index 40a96afc6..e69de29bb 100644 --- a/src/etools_datamart/apps/web/templatetags/__init__.py +++ b/src/etools_datamart/apps/web/templatetags/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/src/etools_datamart/apps/web/templatetags/datamart.py b/src/etools_datamart/apps/web/templatetags/datamart.py index 88cbc089b..43c710f32 100644 --- a/src/etools_datamart/apps/web/templatetags/datamart.py +++ b/src/etools_datamart/apps/web/templatetags/datamart.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django import template from etools_datamart.libs.version import get_full_version diff --git a/src/etools_datamart/config/admin.py b/src/etools_datamart/config/admin.py index 5613b900d..079ffb086 100644 --- a/src/etools_datamart/config/admin.py +++ b/src/etools_datamart/config/admin.py @@ -76,7 +76,7 @@ def get_urls(self): def index(self, request, extra_context=None): style = request.COOKIES.get('old_index_style', 0) if style in [1, "1"]: - return super(DatamartAdminSite, self).index(request, {'index_style': 0}) + return super().index(request, {'index_style': 0}) else: return self.index_new(request, {'index_style': 1}) diff --git a/src/etools_datamart/config/settings.py b/src/etools_datamart/config/settings.py index 9f8eda532..2201d8bce 100644 --- a/src/etools_datamart/config/settings.py +++ b/src/etools_datamart/config/settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import datetime import os from pathlib import Path @@ -95,17 +94,6 @@ API_PREFIX = env('API_PREFIX') URL_PREFIX = env('URL_PREFIX') -ADMINS = ( - ('Stefano', 'saxix@saxix.onmicrosoft.com'), - ('Stefano', 'sapostolico@unicef.org'), - ('Nik', 'ntrncic@unicef.org'), - ('Greg', 'greinbach@unicef.org'), - ('Zack', 'zadams@unicef.org'), - ('Robert', 'ravram@unicef.org'), - ('Domenico', 'ddinicola@unicef.org'), - ('Evan', 'ewheeler@unicef.org') -) - DATABASES = { 'default': env.db(), 'etools': env.db('DATABASE_URL_ETOOLS', @@ -213,7 +201,6 @@ 'django.contrib.auth.middleware.AuthenticationMiddleware', 'impersonate.middleware.ImpersonateMiddleware', # 'django.contrib.auth.middleware.RemoteUserMiddleware', - 'crashlog.middleware.CrashLogMiddleware', 'unicef_rest_framework.middleware.ApiMiddleware', # 'etools_datamart.apps.tracking.middleware.ThreadedStatsMiddleware', 'etools_datamart.apps.tracking.middleware.StatsMiddleware', @@ -350,7 +337,7 @@ 'adminfilters', 'django_sysinfo', 'post_office', - # 'djcelery_email', + 'djcelery_email', 'django_celery_beat', @@ -380,8 +367,7 @@ '%m/%d/%y %H:%M', # '10/25/06 14:30' '%m/%d/%y', # '10/25/06' ] -EMAIL_BACKEND = 'post_office.EmailBackend' -EMAIL_POST_OFFICE_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' +EMAIL_BACKEND = 'post_office.backends.EmailBackend' EMAIL_HOST_USER = env('EMAIL_HOST_USER') EMAIL_HOST_PASSWORD = env('EMAIL_HOST_PASSWORD') EMAIL_HOST = env('EMAIL_HOST') @@ -394,8 +380,6 @@ 'default': 'djcelery_email.backends.CeleryEmailBackend' } } -# celery-mail -CELERY_EMAIL_CHUNK_SIZE = 10 # crispy-forms CRISPY_FAIL_SILENTLY = not DEBUG @@ -459,16 +443,24 @@ } CELERY_ACCEPT_CONTENT = ['etljson'] -CELERY_BEAT_SCHEDULER = 'unicef_rest_framework.schedulers.DatabaseScheduler' -CELERY_BROKER_POOL_LIMIT = 0 +CELERY_BEAT_SCHEDULER = env.str( + 'CELERY_BEAT_SCHEDULER', + default='unicef_rest_framework.schedulers:DatabaseScheduler', +) +CELERY_BROKER_POOL_LIMIT = env.int('CELERY_BROKER_POOL_LIMIT', default=0) CELERY_BROKER_URL = env('CELERY_BROKER_URL') CELERY_EAGER_PROPAGATES_EXCEPTIONS = env.bool('CELERY_ALWAYS_EAGER') -CELERY_REDIS_MAX_CONNECTIONS = 10 +CELERY_REDIS_MAX_CONNECTIONS = env.int('CELERY_REDIS_MAX_CONNECTIONS', 10) CELERY_RESULT_BACKEND = env('CELERY_RESULT_BACKEND') CELERY_RESULT_SERIALIZER = 'etljson' CELERY_TASK_ALWAYS_EAGER = env.bool('CELERY_ALWAYS_EAGER') CELERY_TASK_SERIALIZER = 'etljson' CELERY_TIMEZONE = 'America/New_York' +CELERY_EMAIL_BACKEND = env.str( + 'CELERY_EMAIL_BACKEND', + default='post_office.backends.EmailBackend', +) +CELERY_EMAIL_CHUNK_SIZE = 10 CONCURRENCY_IGNORE_DEFAULT = False @@ -693,8 +685,8 @@ def extra(r): if SENTRY_ENABLED: import sentry_sdk - from sentry_sdk.integrations.django import DjangoIntegration from sentry_sdk.integrations.celery import CeleryIntegration + from sentry_sdk.integrations.django import DjangoIntegration # from sentry_sdk.integrations.redis import RedisIntegration diff --git a/src/etools_datamart/config/wsgi.py b/src/etools_datamart/config/wsgi.py index 1150771d9..67c0b1e3b 100644 --- a/src/etools_datamart/config/wsgi.py +++ b/src/etools_datamart/config/wsgi.py @@ -2,8 +2,10 @@ from django.core.wsgi import get_wsgi_application +from dj_static import Cling + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "etools_datamart.config.settings") -application = get_wsgi_application() +application = Cling(get_wsgi_application()) # application = WhiteNoise(get_wsgi_application(), root=os.environ.get('STATIC_ROOT')) # application.add_files('/path/to/more/static/files', prefix='more-files/') diff --git a/src/etools_datamart/custom_migrations/explorer/0001_initial.py b/src/etools_datamart/custom_migrations/explorer/0001_initial.py index 49d5a171a..4fd9c0b70 100644 --- a/src/etools_datamart/custom_migrations/explorer/0001_initial.py +++ b/src/etools_datamart/custom_migrations/explorer/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals import django.db.models.deletion diff --git a/src/etools_datamart/custom_migrations/explorer/0002_auto_20150501_1515.py b/src/etools_datamart/custom_migrations/explorer/0002_auto_20150501_1515.py index 00240daa3..8d654ab7a 100644 --- a/src/etools_datamart/custom_migrations/explorer/0002_auto_20150501_1515.py +++ b/src/etools_datamart/custom_migrations/explorer/0002_auto_20150501_1515.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/src/etools_datamart/custom_migrations/explorer/0003_query_snapshot.py b/src/etools_datamart/custom_migrations/explorer/0003_query_snapshot.py index 0d0cf427c..2baffdb84 100644 --- a/src/etools_datamart/custom_migrations/explorer/0003_query_snapshot.py +++ b/src/etools_datamart/custom_migrations/explorer/0003_query_snapshot.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/src/etools_datamart/custom_migrations/explorer/0004_querylog_duration.py b/src/etools_datamart/custom_migrations/explorer/0004_querylog_duration.py index 10daa3119..91e38fd00 100644 --- a/src/etools_datamart/custom_migrations/explorer/0004_querylog_duration.py +++ b/src/etools_datamart/custom_migrations/explorer/0004_querylog_duration.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/src/etools_datamart/custom_migrations/explorer/0005_auto_20160105_2052.py b/src/etools_datamart/custom_migrations/explorer/0005_auto_20160105_2052.py index 7cc292cbd..cdcac203a 100644 --- a/src/etools_datamart/custom_migrations/explorer/0005_auto_20160105_2052.py +++ b/src/etools_datamart/custom_migrations/explorer/0005_auto_20160105_2052.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.9 on 2016-01-05 20:52 from __future__ import unicode_literals diff --git a/src/etools_datamart/custom_migrations/explorer/0006_query_connection.py b/src/etools_datamart/custom_migrations/explorer/0006_query_connection.py index e618efb65..e22144c03 100644 --- a/src/etools_datamart/custom_migrations/explorer/0006_query_connection.py +++ b/src/etools_datamart/custom_migrations/explorer/0006_query_connection.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/src/etools_datamart/custom_migrations/explorer/0007_querylog_connection.py b/src/etools_datamart/custom_migrations/explorer/0007_querylog_connection.py index 3cfc0b200..29db9beac 100644 --- a/src/etools_datamart/custom_migrations/explorer/0007_querylog_connection.py +++ b/src/etools_datamart/custom_migrations/explorer/0007_querylog_connection.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import migrations, models diff --git a/src/etools_datamart/libs/__init__.py b/src/etools_datamart/libs/__init__.py index 40a96afc6..e69de29bb 100644 --- a/src/etools_datamart/libs/__init__.py +++ b/src/etools_datamart/libs/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/src/etools_datamart/libs/json.py b/src/etools_datamart/libs/json.py index da81afa38..952d7555e 100644 --- a/src/etools_datamart/libs/json.py +++ b/src/etools_datamart/libs/json.py @@ -12,7 +12,7 @@ def default(self, o): return float(o) elif isinstance(o, (datetime,)): return str(o) - return super(SmartEncoder, self).default(o) + return super().default(o) def print_json(obj, *args): diff --git a/src/etools_datamart/libs/truncate.py b/src/etools_datamart/libs/truncate.py index c9b3f3995..e3798a275 100644 --- a/src/etools_datamart/libs/truncate.py +++ b/src/etools_datamart/libs/truncate.py @@ -1,2 +1 @@ -# -*- coding: utf-8 -*- from unicef_rest_framework.admin.base import TruncateTableMixin # noqa diff --git a/src/etools_datamart/libs/wallet.py b/src/etools_datamart/libs/wallet.py index d0c395b15..6b2fb180b 100644 --- a/src/etools_datamart/libs/wallet.py +++ b/src/etools_datamart/libs/wallet.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import base64 import json import logging diff --git a/src/month_field/models.py b/src/month_field/models.py index 4469f1ea5..f3bdf61cd 100644 --- a/src/month_field/models.py +++ b/src/month_field/models.py @@ -51,4 +51,4 @@ def formfield(self, **kwargs): 'form_class': forms.MonthField } defaults.update(kwargs) - return super(MonthField, self).formfield(**defaults) + return super().formfield(**defaults) diff --git a/src/month_field/widgets.py b/src/month_field/widgets.py index 42b2e4878..312992815 100644 --- a/src/month_field/widgets.py +++ b/src/month_field/widgets.py @@ -21,7 +21,7 @@ def __init__(self, attrs=None): _widgets = [widgets.Select(attrs=_attrs, choices=months.items()), widgets.NumberInput(attrs=_attrs) ] - super(MonthSelectorWidget, self).__init__(_widgets, attrs) + super().__init__(_widgets, attrs) @property def media(self): diff --git a/src/unicef_rest_framework/acl.py b/src/unicef_rest_framework/acl.py index 8f7dd22cb..ac94e1117 100644 --- a/src/unicef_rest_framework/acl.py +++ b/src/unicef_rest_framework/acl.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import logging logger = logging.getLogger(__name__) diff --git a/src/unicef_rest_framework/admin/__init__.py b/src/unicef_rest_framework/admin/__init__.py index f0eb3671e..6a3eb6268 100644 --- a/src/unicef_rest_framework/admin/__init__.py +++ b/src/unicef_rest_framework/admin/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.contrib import admin from django_celery_beat.models import CrontabSchedule @@ -11,14 +10,13 @@ from .. import models from .acl import GroupAccessControlAdmin, UserAccessControlAdmin from .application import ApplicationAdmin -from .base import ListDisplayAllMixin, ReadOnlyAdminMixin, TruncateTableMixin # noqa +from .base import APIModelAdmin # noqa; noqa; noqa +from .base import ListDisplayAllMixin, ReadOnlyAdminMixin, TruncateTableMixin from .beat import CrontabScheduleAdmin, PeriodicTaskAdmin from .cache import CacheVersionAdmin from .filter import SystemFilterAdmin from .service import ServiceAdmin -from .base import APIModelAdmin # noqa; noqa - __all__ = ['ApplicationAdmin', 'GroupAccessControlAdmin', 'ServiceAdmin', diff --git a/src/unicef_rest_framework/admin/acl.py b/src/unicef_rest_framework/admin/acl.py index d5829dc53..2621e1de2 100644 --- a/src/unicef_rest_framework/admin/acl.py +++ b/src/unicef_rest_framework/admin/acl.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import logging from django import forms @@ -38,7 +36,7 @@ class UserAccessControlAdmin(admin.ModelAdmin): form = UserACLAdminForm def get_queryset(self, request): - return super(UserAccessControlAdmin, self).get_queryset(request).select_related(*self.raw_id_fields) + return super().get_queryset(request).select_related(*self.raw_id_fields) class GroupAccessControlForm(forms.Form): @@ -84,7 +82,7 @@ class GroupAccessControlAdmin(ExtraUrlMixin, admin.ModelAdmin): # filter_horizontal = ('services',) def get_queryset(self, request): - return super(GroupAccessControlAdmin, self).get_queryset(request).select_related(*self.raw_id_fields) + return super().get_queryset(request).select_related(*self.raw_id_fields) def has_add_permission(self, request): return False diff --git a/src/unicef_rest_framework/admin/application.py b/src/unicef_rest_framework/admin/application.py index 242bfe94c..2bfe26469 100644 --- a/src/unicef_rest_framework/admin/application.py +++ b/src/unicef_rest_framework/admin/application.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import logging import uuid @@ -35,4 +33,4 @@ class ApplicationAdmin(ExtraUrlMixin, admin.ModelAdmin): filter_horizontal = ('services',) def get_queryset(self, request): - return super(ApplicationAdmin, self).get_queryset(request).select_related(*self.raw_id_fields) + return super().get_queryset(request).select_related(*self.raw_id_fields) diff --git a/src/unicef_rest_framework/admin/base.py b/src/unicef_rest_framework/admin/base.py index 40a0b1f1a..68185ab83 100644 --- a/src/unicef_rest_framework/admin/base.py +++ b/src/unicef_rest_framework/admin/base.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import logging from django.contrib import admin diff --git a/src/unicef_rest_framework/admin/cache.py b/src/unicef_rest_framework/admin/cache.py index 0adb52f76..0d7fc0631 100644 --- a/src/unicef_rest_framework/admin/cache.py +++ b/src/unicef_rest_framework/admin/cache.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import logging import re import uuid @@ -36,7 +34,7 @@ class CacheVersionAdmin(ExtraUrlMixin, admin.ModelAdmin): fieldsets = [("", {"fields": ('name', 'cache_version', 'cache_ttl', 'cache_key')})] def get_queryset(self, request): - return super(CacheVersionAdmin, self).get_queryset(request). \ + return super().get_queryset(request). \ defer('linked_models'). \ select_related(*self.raw_id_fields) diff --git a/src/unicef_rest_framework/admin/filter.py b/src/unicef_rest_framework/admin/filter.py index b42b7fb0c..2c10381f2 100644 --- a/src/unicef_rest_framework/admin/filter.py +++ b/src/unicef_rest_framework/admin/filter.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import logging from django.conf import settings diff --git a/src/unicef_rest_framework/admin/service.py b/src/unicef_rest_framework/admin/service.py index 8a80bd3f4..9dbeb24dd 100644 --- a/src/unicef_rest_framework/admin/service.py +++ b/src/unicef_rest_framework/admin/service.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import logging import os @@ -174,4 +172,4 @@ def invalidate_cache(self, request, pk): # return HttpResponse(code, content_type='text/plain') # def changelist_view(self, request, extra_context=None): - # return super(ServiceAdmin, self).changelist_view(request, extra_context) + # return super().changelist_view(request, extra_context) diff --git a/src/unicef_rest_framework/apps.py b/src/unicef_rest_framework/apps.py index a9f0724ae..e5b882f92 100644 --- a/src/unicef_rest_framework/apps.py +++ b/src/unicef_rest_framework/apps.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 from django.apps import AppConfig @@ -7,5 +6,5 @@ class Config(AppConfig): verbose_name = 'API Configuration' def ready(self): - from . import tasks # noqa from . import handlers # noqa + from . import tasks # noqa diff --git a/src/unicef_rest_framework/auth.py b/src/unicef_rest_framework/auth.py index b2457791f..82aa84614 100644 --- a/src/unicef_rest_framework/auth.py +++ b/src/unicef_rest_framework/auth.py @@ -8,7 +8,6 @@ from django.utils.translation import ugettext as _ from constance import config -from crashlog.middleware import process_exception from rest_framework import exceptions from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed, PermissionDenied @@ -78,7 +77,7 @@ def authenticate(self, request): return None try: - user, jwt_value = super(JWTAuthentication, self).authenticate(request) + user, jwt_value = super().authenticate(request) request.user = user # login(request, user, 'social_core.backends.azuread_tenant.AzureADTenantOAuth2') except TypeError: # pragma: no cover @@ -104,7 +103,6 @@ def authenticate_credentials(self, payload): user, created = User.objects.update_or_create(**pk, defaults=values) except Exception as e: - process_exception(e) raise exceptions.AuthenticationFailed("Unable to retrieve user data") else: user, created = User.objects.update_or_create(username=username, diff --git a/src/unicef_rest_framework/cache.py b/src/unicef_rest_framework/cache.py index fff129c86..edea82694 100644 --- a/src/unicef_rest_framework/cache.py +++ b/src/unicef_rest_framework/cache.py @@ -200,7 +200,7 @@ def __init__(self, cache=None, cache_errors=None): self.cache_name = cache or extensions_api_settings.DEFAULT_USE_CACHE - super(APICacheResponse, self).__init__(timeout=timeout, key_func=key_func, + super().__init__(timeout=timeout, key_func=key_func, cache=cache, cache_errors=cache_errors) def process_cache_response(self, diff --git a/src/unicef_rest_framework/config.py b/src/unicef_rest_framework/config.py index 39b3d3053..c16a6ee4d 100644 --- a/src/unicef_rest_framework/config.py +++ b/src/unicef_rest_framework/config.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.core.exceptions import ImproperlyConfigured from django.core.signals import setting_changed from django.urls import get_callable diff --git a/src/unicef_rest_framework/exceptions.py b/src/unicef_rest_framework/exceptions.py index 64479d507..bf486c530 100644 --- a/src/unicef_rest_framework/exceptions.py +++ b/src/unicef_rest_framework/exceptions.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.core.exceptions import ValidationError from django.utils.translation import ugettext_lazy as _ @@ -15,7 +14,7 @@ def __init__(self, *args, **kwargs): self._cause = kwargs.pop('cause', None) self._tb = kwargs.pop('tb', None) - super(ApiException, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) class TokenExpired(Exception): @@ -31,7 +30,7 @@ class TokenDecodeError(Exception): class InvalidQueryArgumentError(ApiException): def __init__(self, field, *args, **kwargs): self.field = field - super(InvalidQueryArgumentError, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def __str__(self): return "Invalid parameter '{}'".format(self.field) @@ -40,7 +39,7 @@ def __str__(self): class InvalidFilterError(ApiException): def __init__(self, field, *args, **kwargs): self.field = field - super(InvalidFilterError, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def __str__(self): return "Invalid filter '{}'".format(self.field) @@ -53,7 +52,7 @@ class InvalidPaginationError(ApiException): class FilteringError(ApiException): def __init__(self, reason, *args, **kwargs): self.reason = reason - super(FilteringError, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def __str__(self): return "Invalid query: '{}'".format(self.reason) diff --git a/src/unicef_rest_framework/filtering.py b/src/unicef_rest_framework/filtering.py index fb9f4ae20..7e31894da 100644 --- a/src/unicef_rest_framework/filtering.py +++ b/src/unicef_rest_framework/filtering.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging from drf_querystringfilter.backend import QueryStringFilterBackend diff --git a/src/unicef_rest_framework/forms.py b/src/unicef_rest_framework/forms.py index 67445af12..6a877c256 100644 --- a/src/unicef_rest_framework/forms.py +++ b/src/unicef_rest_framework/forms.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import json from django import forms @@ -78,7 +77,7 @@ class DateRangePickerWidget(forms.MultiWidget): def __init__(self, till_today=True, attrs=None): widgets = (DateInput(), DateInput(),) - super(DateRangePickerWidget, self).__init__(widgets, attrs=attrs) + super().__init__(widgets, attrs=attrs) def value_from_datadict(self, data, files, name): return [self.widgets[0].value_from_datadict(data, files, name + '__gte'), @@ -135,7 +134,7 @@ def __init__(self, input_formats=None, **kwargs): localize=localize, **kwargs) ) - super(DateRangePickerField, self).__init__(fields, **kwargs) + super().__init__(fields, **kwargs) def widget_attrs(self, widget): return {"class": "form-control"} diff --git a/src/unicef_rest_framework/management/__init__.py b/src/unicef_rest_framework/management/__init__.py index 40a96afc6..e69de29bb 100644 --- a/src/unicef_rest_framework/management/__init__.py +++ b/src/unicef_rest_framework/management/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/src/unicef_rest_framework/management/commands/__init__.py b/src/unicef_rest_framework/management/commands/__init__.py index 40a96afc6..e69de29bb 100644 --- a/src/unicef_rest_framework/management/commands/__init__.py +++ b/src/unicef_rest_framework/management/commands/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/src/unicef_rest_framework/management/commands/api-inspect.py b/src/unicef_rest_framework/management/commands/api-inspect.py index 56e7c6b71..ce4c55276 100644 --- a/src/unicef_rest_framework/management/commands/api-inspect.py +++ b/src/unicef_rest_framework/management/commands/api-inspect.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging from django.core.management import BaseCommand diff --git a/src/unicef_rest_framework/middleware.py b/src/unicef_rest_framework/middleware.py index b9d93f651..5a1d5d31f 100644 --- a/src/unicef_rest_framework/middleware.py +++ b/src/unicef_rest_framework/middleware.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging import threading diff --git a/src/unicef_rest_framework/models/__init__.py b/src/unicef_rest_framework/models/__init__.py index cd917f84e..51a58bd85 100644 --- a/src/unicef_rest_framework/models/__init__.py +++ b/src/unicef_rest_framework/models/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from .acl import UserAccessControl # noqa from .application import Application # noqa from .base import MasterDataModel # noqa diff --git a/src/unicef_rest_framework/models/acl.py b/src/unicef_rest_framework/models/acl.py index d4f8e5f35..d55788437 100644 --- a/src/unicef_rest_framework/models/acl.py +++ b/src/unicef_rest_framework/models/acl.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import logging from django.conf import settings diff --git a/src/unicef_rest_framework/models/application.py b/src/unicef_rest_framework/models/application.py index 0868f1780..5e0270b5e 100644 --- a/src/unicef_rest_framework/models/application.py +++ b/src/unicef_rest_framework/models/application.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging from django.conf import settings diff --git a/src/unicef_rest_framework/models/base.py b/src/unicef_rest_framework/models/base.py index f789b02c1..fd28e4cb5 100644 --- a/src/unicef_rest_framework/models/base.py +++ b/src/unicef_rest_framework/models/base.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import logging import uuid diff --git a/src/unicef_rest_framework/models/filter.py b/src/unicef_rest_framework/models/filter.py index dd1df7bbb..2ead5ddb7 100644 --- a/src/unicef_rest_framework/models/filter.py +++ b/src/unicef_rest_framework/models/filter.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging from functools import lru_cache @@ -34,7 +33,7 @@ class InvalidOperator(InvalidRule): class SystemFilterHandler(object): def __init__(self, filter): self.filter = filter - super(SystemFilterHandler, self).__init__() + super().__init__() def filter_queryset(self, queryset): return queryset diff --git a/src/unicef_rest_framework/models/preload.py b/src/unicef_rest_framework/models/preload.py index 6d57b3ba6..03bc78c56 100644 --- a/src/unicef_rest_framework/models/preload.py +++ b/src/unicef_rest_framework/models/preload.py @@ -6,7 +6,6 @@ from django.db import models from django.utils import timezone -from crashlog.middleware import process_exception from rest_framework.test import APIClient, ForceAuthClientHandler from unicef_security.models import User @@ -17,7 +16,7 @@ class ClientHandler(ForceAuthClientHandler): def get_response(self, request): request._is_preload_internal_request = True - return super(ClientHandler, self).get_response(request) + return super().get_response(request) class Client(APIClient): @@ -27,7 +26,7 @@ def __init__(self, enforce_csrf_checks=False, **defaults): self._credentials = {} def _base_environ(self, **request): - env = super(Client, self)._base_environ(**request) + env = super()._base_environ(**request) env['HTTP_USER_AGENT'] = 'Datamart/%s' % etools_datamart.VERSION env['REMOTE_ADDR'] = '127.0.0.1' env['SERVER_NAME'] = 'localhost' @@ -106,7 +105,6 @@ def run(self, *, target=None, params=None, pre_save=None): pre_save(self, response) return response except Exception as e: - process_exception(e) self.status_code = 501 self.etag = "" self.response_ms = 0 diff --git a/src/unicef_rest_framework/models/service.py b/src/unicef_rest_framework/models/service.py index 7343ff0e0..60bb00053 100644 --- a/src/unicef_rest_framework/models/service.py +++ b/src/unicef_rest_framework/models/service.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import logging from django.contrib.contenttypes.models import ContentType @@ -177,7 +175,7 @@ def save(self, force_insert=False, force_update=False, using=None, update_fields self.linked_models.add(ct) except Exception as e: logger.exception(e) - super(Service, self).save(force_insert, force_update, using, update_fields) + super().save(force_insert, force_update, using, update_fields) def __str__(self): return self.name diff --git a/src/unicef_rest_framework/pagination.py b/src/unicef_rest_framework/pagination.py index 24498b272..dcd8612ea 100644 --- a/src/unicef_rest_framework/pagination.py +++ b/src/unicef_rest_framework/pagination.py @@ -118,7 +118,7 @@ def paginate_queryset(self, queryset, request, view=None): # self._handle_backwards_compat(view) if self.get_page_size(request) == sys.maxsize: return queryset - return super(APIPagination, self).paginate_queryset(queryset, request, view) + return super().paginate_queryset(queryset, request, view) def get_next_link(self): if not self.page.has_next(): diff --git a/src/unicef_rest_framework/permissions.py b/src/unicef_rest_framework/permissions.py index 836b38a1a..7a58b101c 100644 --- a/src/unicef_rest_framework/permissions.py +++ b/src/unicef_rest_framework/permissions.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging from functools import lru_cache diff --git a/src/unicef_rest_framework/renderers/api.py b/src/unicef_rest_framework/renderers/api.py index 47c2444c9..c09081c90 100644 --- a/src/unicef_rest_framework/renderers/api.py +++ b/src/unicef_rest_framework/renderers/api.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging from django.template import loader @@ -55,7 +54,7 @@ def get_filter_form(self, data, view, request): # } def get_context(self, data, accepted_media_type, renderer_context): - ctx = super(URFBrowsableAPIRenderer, self).get_context(data, accepted_media_type, renderer_context) + ctx = super().get_context(data, accepted_media_type, renderer_context) # in the real flow, this is added by the MultiTenant Middleware # but this function is called before the middleware system is involved request = ctx['request'] diff --git a/src/unicef_rest_framework/renderers/csv.py b/src/unicef_rest_framework/renderers/csv.py index 06b1c60d5..f61f3416d 100644 --- a/src/unicef_rest_framework/renderers/csv.py +++ b/src/unicef_rest_framework/renderers/csv.py @@ -1,6 +1,5 @@ import logging -from crashlog.middleware import process_exception from rest_framework_csv import renderers as r from unicef_rest_framework.renderers.mixin import ContentDispositionMixin @@ -20,6 +19,5 @@ def render(self, data, media_type=None, renderer_context=None, writer_opts=None) data = dict(data)['results'] return super().render(data, media_type, renderer_context, writer_opts) except Exception as e: - process_exception(e) logger.exception(e) raise Exception('Error processing request') diff --git a/src/unicef_rest_framework/renderers/html.py b/src/unicef_rest_framework/renderers/html.py index e15e72702..4bfd10b3d 100644 --- a/src/unicef_rest_framework/renderers/html.py +++ b/src/unicef_rest_framework/renderers/html.py @@ -2,7 +2,6 @@ from django.template import loader -from crashlog.middleware import process_exception from rest_framework.renderers import BaseRenderer logger = logging.getLogger(__name__) @@ -46,6 +45,5 @@ def render(self, data, accepted_media_type=None, renderer_context=None): 'headers': []} return template.render(c) except Exception as e: - process_exception(e) logger.exception(e) raise Exception('Error processing request') from e diff --git a/src/unicef_rest_framework/renderers/iqy.py b/src/unicef_rest_framework/renderers/iqy.py index fcc0c59e0..f4301c5de 100644 --- a/src/unicef_rest_framework/renderers/iqy.py +++ b/src/unicef_rest_framework/renderers/iqy.py @@ -3,7 +3,6 @@ from django.conf import settings from django.template import loader -from crashlog.middleware import process_exception from rest_framework.renderers import BaseRenderer from unicef_rest_framework.renderers.mixin import ContentDispositionMixin @@ -51,6 +50,5 @@ def render(self, data, accepted_media_type=None, renderer_context=None): template = self.get_template(opts) return template.render(c) except Exception as e: - process_exception(e) logger.exception(e) raise Exception('Error processing request %s' % e) from e diff --git a/src/unicef_rest_framework/renderers/pdf.py b/src/unicef_rest_framework/renderers/pdf.py index 2030fd3f6..6d4e7a6a8 100644 --- a/src/unicef_rest_framework/renderers/pdf.py +++ b/src/unicef_rest_framework/renderers/pdf.py @@ -5,7 +5,6 @@ from django.conf import settings from django.template import loader -from crashlog.middleware import process_exception from xhtml2pdf import pisa from unicef_rest_framework.renderers.mixin import ContentDispositionMixin @@ -61,7 +60,7 @@ def render(self, data, accepted_media_type=None, renderer_context=None): if response.status_code != 200: return '' try: - html = super(PDFRenderer, self).render(data, accepted_media_type, renderer_context) + html = super().render(data, accepted_media_type, renderer_context) # create a pdf buffer = io.BytesIO() @@ -72,6 +71,5 @@ def render(self, data, accepted_media_type=None, renderer_context=None): buffer.seek(0) return buffer.read() except Exception as e: - process_exception(e) logger.exception(e) raise Exception('Error processing request') from e diff --git a/src/unicef_rest_framework/renderers/txt.py b/src/unicef_rest_framework/renderers/txt.py index bdd386fd9..8b3cbebfa 100644 --- a/src/unicef_rest_framework/renderers/txt.py +++ b/src/unicef_rest_framework/renderers/txt.py @@ -2,7 +2,6 @@ from django.template import loader -from crashlog.middleware import process_exception from rest_framework.renderers import BaseRenderer logger = logging.getLogger(__name__) @@ -46,6 +45,5 @@ def render(self, data, accepted_media_type=None, renderer_context=None): 'headers': []} return template.render(c) except Exception as e: - process_exception(e) logger.exception(e) raise Exception('Error processing request') from e diff --git a/src/unicef_rest_framework/renderers/xls.py b/src/unicef_rest_framework/renderers/xls.py index 43ce69b4d..f8e106bdf 100644 --- a/src/unicef_rest_framework/renderers/xls.py +++ b/src/unicef_rest_framework/renderers/xls.py @@ -1,7 +1,6 @@ import logging from collections import Iterable, MutableMapping -from crashlog.middleware import process_exception from drf_renderer_xlsx.renderers import XLSXRenderer as _XLSXRenderer from unicef_rest_framework.renderers.mixin import ContentDispositionMixin @@ -40,6 +39,5 @@ def render(self, data, accepted_media_type=None, renderer_context=None): return super().render(data, accepted_media_type, renderer_context) except Exception as e: - process_exception(e) logger.exception(e) raise Exception(f'Error processing request {e}') from e diff --git a/src/unicef_rest_framework/renderers/yaml.py b/src/unicef_rest_framework/renderers/yaml.py index 71b4e9a46..2348c67c2 100644 --- a/src/unicef_rest_framework/renderers/yaml.py +++ b/src/unicef_rest_framework/renderers/yaml.py @@ -1,6 +1,5 @@ import logging -from crashlog.middleware import process_exception from rest_framework_yaml.renderers import YAMLRenderer as BaseRenderer from unicef_rest_framework.renderers.mixin import ContentDispositionMixin @@ -24,6 +23,5 @@ def render(self, data, accepted_media_type=None, renderer_context=None): return super().render(data, accepted_media_type, renderer_context) except Exception as e: - process_exception(e) logger.exception(e) raise Exception(f'Error processing request {e}') from e diff --git a/src/unicef_rest_framework/routers.py b/src/unicef_rest_framework/routers.py index 0f72b3cd1..6c66e384c 100644 --- a/src/unicef_rest_framework/routers.py +++ b/src/unicef_rest_framework/routers.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging from collections import OrderedDict diff --git a/src/unicef_rest_framework/templatetags/__init__.py b/src/unicef_rest_framework/templatetags/__init__.py index 40a96afc6..e69de29bb 100644 --- a/src/unicef_rest_framework/templatetags/__init__.py +++ b/src/unicef_rest_framework/templatetags/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/src/unicef_rest_framework/throttling.py b/src/unicef_rest_framework/throttling.py index c19cf48da..5ad478dcc 100644 --- a/src/unicef_rest_framework/throttling.py +++ b/src/unicef_rest_framework/throttling.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import logging import time diff --git a/src/unicef_rest_framework/utils.py b/src/unicef_rest_framework/utils.py index f38913870..c37844f37 100644 --- a/src/unicef_rest_framework/utils.py +++ b/src/unicef_rest_framework/utils.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os from urllib.parse import parse_qsl, urlencode, urlparse diff --git a/src/unicef_rest_framework/views.py b/src/unicef_rest_framework/views.py index 7c78a282c..173f9c7af 100644 --- a/src/unicef_rest_framework/views.py +++ b/src/unicef_rest_framework/views.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from functools import lru_cache from django.conf import settings @@ -33,8 +32,19 @@ from .negotiation import CT from .ordering import OrderingFilter from .permissions import ServicePermission -from .renderers import (CSVRenderer, HTMLRenderer, IQYRenderer, JSONRenderer, MSJSONRenderer, MSXmlRenderer, - PDFRenderer, TextRenderer, URFBrowsableAPIRenderer, XLSXRenderer, YAMLRenderer,) +from .renderers import ( + CSVRenderer, + HTMLRenderer, + IQYRenderer, + JSONRenderer, + MSJSONRenderer, + MSXmlRenderer, + PDFRenderer, + TextRenderer, + URFBrowsableAPIRenderer, + XLSXRenderer, + YAMLRenderer, +) class classproperty(object): diff --git a/src/unicef_security/graph.py b/src/unicef_security/graph.py index 77efdee35..a26948e59 100644 --- a/src/unicef_security/graph.py +++ b/src/unicef_security/graph.py @@ -10,7 +10,6 @@ import requests from constance import config as constance -from crashlog.middleware import process_exception from jwt import decode as jwt_decode, DecodeError, ExpiredSignature from social_core.backends.azuread_tenant import AzureADTenantOAuth2 from social_core.exceptions import AuthTokenError @@ -103,15 +102,12 @@ def get_unicef_user(backend, details, response, *args, **kwargs): for k, v in response.items(): if k in ['email', 'family_name', 'unique_name']: details[k] = v - try: - sync = Synchronizer() - data = sync.get_user(details['email']) - for k, v in data.items(): - details[k] = v + sync = Synchronizer() + data = sync.get_user(details['email']) - except Exception as e: - process_exception(e) + for k, v in data.items(): + details[k] = v user, created = User.objects.get_or_create( username=details['unique_name'], diff --git a/tests/.coveragerc b/tests/.coveragerc index b999dc23f..9d89cb06f 100644 --- a/tests/.coveragerc +++ b/tests/.coveragerc @@ -10,7 +10,7 @@ omit = **/apps/etools/models/public_old.py **/apps/etools/models/tenant_old.py **/db_router.py - **/etools_datamart/apps/data/management/commands/load.py + src/etools_datamart/apps/data/management/commands/load.py **/inspectschema.py **/introspection.py **/libs/mystica.py @@ -19,8 +19,10 @@ omit = **/reset-migrations.py **/tracking/management/commands/track.py **/data/management/commands/sqlall.py - **/etools_datamart/apps/prp/management/commands/inspectprp.py + **/source_prp/management/commands/inspectprp.py tests/** + **/migrations/** + **/custom_migrations/** [report] @@ -40,7 +42,7 @@ exclude_lines = #if 0: if __name__ == .__main__.: -fail_under = 70 +fail_under = 60 ignore_errors = True diff --git a/tests/_test_lib/test_utilities/factories/common.py b/tests/_test_lib/test_utilities/factories/common.py index 8acfb0fd5..72c655b53 100644 --- a/tests/_test_lib/test_utilities/factories/common.py +++ b/tests/_test_lib/test_utilities/factories/common.py @@ -1,4 +1,3 @@ - from django.contrib.auth.models import Group from django.utils import timezone @@ -26,7 +25,7 @@ def __new__(mcs, class_name, bases, attrs): return new_class -class RegisterModelFactory(factory.DjangoModelFactory, metaclass=AutoRegisterFactoryMetaClass): +class RegisterModelFactory(factory.django.DjangoModelFactory, metaclass=AutoRegisterFactoryMetaClass): pass diff --git a/tests/_test_lib/test_utilities/factories/data.py b/tests/_test_lib/test_utilities/factories/data.py index dce3b9094..927e2662e 100644 --- a/tests/_test_lib/test_utilities/factories/data.py +++ b/tests/_test_lib/test_utilities/factories/data.py @@ -292,6 +292,46 @@ class Meta: model = models.SpotCheck +class SpotCheckFindingsFactory(DataMartModelFactory): + partner = {'name': 'Partner1', + 'vendor_number': '123', + 'id': 100, + 'source_id': 101} + + class Meta: + model = models.SpotCheckFindings + + +class MicroAssessmentFactory(DataMartModelFactory): + partner = {'name': 'Partner1', + 'vendor_number': '123', + 'id': 100, + 'source_id': 101} + + class Meta: + model = models.MicroAssessment + + +class AuditFactory(DataMartModelFactory): + partner = {'name': 'Partner1', + 'vendor_number': '123', + 'id': 100, + 'source_id': 101} + + class Meta: + model = models.Audit + + +class AuditSpecialFactory(DataMartModelFactory): + partner = {'name': 'Partner1', + 'vendor_number': '123', + 'id': 100, + 'source_id': 101} + + class Meta: + model = models.AuditSpecial + + class PartnerStaffMemberFactory(DataMartModelFactory): class Meta: model = models.PartnerStaffMember diff --git a/tests/api/interfaces/test_prp.py b/tests/api/interfaces/test_prp.py index 6efbd2a34..5e4b535db 100644 --- a/tests/api/interfaces/test_prp.py +++ b/tests/api/interfaces/test_prp.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os from functools import wraps @@ -22,8 +21,8 @@ def client(self): def frozenfixture2(use_request=False): def deco(func): - from drf_api_checker.utils import load_fixtures, dump_fixtures from drf_api_checker.fs import mktree + from drf_api_checker.utils import dump_fixtures, load_fixtures @wraps(func) def _inner(*args, **kwargs): diff --git a/tests/api/test_api_web.py b/tests/api/test_api_web.py index e87c6d629..20fd83c95 100644 --- a/tests/api/test_api_web.py +++ b/tests/api/test_api_web.py @@ -6,8 +6,12 @@ from unicef_rest_framework.test_utils import user_allow_country, user_allow_service from unicef_security.models import User -from etools_datamart.api.endpoints import (FAMIndicatorViewSet, InterventionViewSet, - PMPIndicatorsViewSet, UserStatsViewSet,) +from etools_datamart.api.endpoints import ( + FAMIndicatorViewSet, + InterventionViewSet, + PMPIndicatorsViewSet, + UserStatsViewSet, +) @pytest.fixture(autouse=True) diff --git a/tests/conftest.py b/tests/conftest.py index 583730e82..c76f559c7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -101,7 +101,8 @@ def django_db_setup(request, django.core.management.commands.migrate.emit_post_migrate_signal = MagicMock() # """Top level fixture to ensure test databases are available""" - from pytest_django.compat import setup_databases, teardown_databases + from django.test.utils import setup_databases, teardown_databases + from pytest_django.fixtures import _disable_native_migrations setup_databases_args = {} @@ -134,10 +135,12 @@ def _teardown_database(): if not django_db_keepdb: request.addfinalizer(_teardown_database) - from unicef_rest_framework.models import Service, UserAccessControl - from etools_datamart.apps.tracking.models import APIRequestLog from test_utilities.factories import UserFactory + + from unicef_rest_framework.models import Service, UserAccessControl + from etools_datamart.apps.etl.models import EtlTask + from etools_datamart.apps.tracking.models import APIRequestLog with django_db_blocker.unblock(): EtlTask.objects.inspect() diff --git a/tests/multitenant/test_db.py b/tests/multitenant/test_db.py index 8c52bc540..5273623fc 100644 --- a/tests/multitenant/test_db.py +++ b/tests/multitenant/test_db.py @@ -1,10 +1,13 @@ -# -*- coding: utf-8 -*- from django.db import connections import pytest -from etools_datamart.apps.sources.etools.models import (ActionPointsActionpoint, AuthGroup, - PartnersPartnerorganization, ReportsResult,) +from etools_datamart.apps.sources.etools.models import ( + ActionPointsActionpoint, + AuthGroup, + PartnersPartnerorganization, + ReportsResult, +) conn = connections['etools'] diff --git a/tests/multitenant/test_inherited.py b/tests/multitenant/test_inherited.py index 8c21cd9fb..9e2b04b48 100644 --- a/tests/multitenant/test_inherited.py +++ b/tests/multitenant/test_inherited.py @@ -2,8 +2,12 @@ import pytest -from etools_datamart.apps.sources.etools.models import (AuditAudit, AuditMicroassessment, - AuditSpecialaudit, AuditSpotcheck,) +from etools_datamart.apps.sources.etools.models import ( + AuditAudit, + AuditMicroassessment, + AuditSpecialaudit, + AuditSpotcheck, +) conn = connections['etools'] diff --git a/tests/tracking/conftest.py b/tests/tracking/conftest.py index 3ec0ffe9d..dde961b28 100644 --- a/tests/tracking/conftest.py +++ b/tests/tracking/conftest.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import json import pytest @@ -24,8 +23,15 @@ def log_with_params(db): @pytest.fixture def reset_stats(db): - from etools_datamart.apps.tracking.models import APIRequestLog, DailyCounter, UserCounter, MonthlyCounter, PathCounter + from etools_datamart.apps.tracking.models import ( + APIRequestLog, + DailyCounter, + MonthlyCounter, + PathCounter, + UserCounter, + ) from etools_datamart.apps.tracking.utils import refresh_all_counters + APIRequestLog.objects.truncate() DailyCounter.objects.truncate() MonthlyCounter.objects.truncate() diff --git a/tox.ini b/tox.ini index 3701620b7..64439927d 100644 --- a/tox.ini +++ b/tox.ini @@ -51,11 +51,11 @@ setenv = PIPENV_VERBOSITY=-1 deps = - poetry==1.0 + pipenv commands = - poetry install - poetry run pytest tests --create-db \ + pipenv sync --dev + pipenv run pytest tests --create-db \ -q \ --cov-config=tests/.coveragerc \ --cov=etools_datamart