diff --git a/.gitignore b/.gitignore
index 0904e0f..b0510df 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,7 +3,7 @@
*.tmp
*.bak
.idea
-venv
+.venv
*.log
config.conf
*.DS_Store
diff --git a/.python-version b/.python-version
new file mode 100644
index 0000000..d2577d9
--- /dev/null
+++ b/.python-version
@@ -0,0 +1 @@
+3.7.7
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..c4949fa
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,14 @@
+language: minimal
+
+services:
+ - docker
+
+script:
+ - docker build -f docker/Dockerfile.base -t technolibre/erplibre-base:12.0 docker/
+# - docker build -f docker/Dockerfile.dev -t technolibre/erplibre:12.0 docker/
+ - docker build -f docker/Dockerfile.pkg -t technolibre/erplibre:12.0-pkg docker/
+
+after_success:
+ - docker login --username mikefaille --password "${DOCKER_TOKEN}"
+ - docker push technolibre/erplibre-core:12.0
+ - docker push technolibre/erplibre:12.0-pkg
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7704548..b2e4c19 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,19 +5,33 @@ The format is based on [Keep a Changelog](https://keepachangelog.com),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
+
+## [1.1.0] - 2020-09-30
### Added
- Docker
+- Pyenv to manage python version
+- Poetry to manage python dependencies
+ - Script poetry_update to search all dependencies in addons
+- Travis CI WIP
+- TODO.md
+- Guide to update all repositories with community
+- Update manifest
+ - Add missing OCA repos
+ - Add medical, property management and more
+ - Add cloud/saas repo
### Changed
-- Update to Odoo Community 12.0
+- Update to Odoo Community 12.0 and all addons
+- Rename venv to .venv
+- More documentation on how to use ERPLibre
## [1.0.1] - 2020-07-14
### Added
-- Improve documentation with development and production environment
-- Improve documentation with git repo
+- Improved documentation with development and production environment
+- Improved documentation with git repo
- Move default.xml manifest to root, the default location
- Support default.stage.xml to update prod with dev
-- Feature to show diff between manifest, between repo of different manifest
+- Feature to show diff between manifests or between repo of different manifests
- Update manifest
- Muk theme in erplibre_base
- Add draft account invoice approbation in portal
@@ -31,7 +45,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [1.0.0] - 2020-07-04
### Added
- Environment of development, discovery and production with documentation and script.
-- git-repo of Google to support addons repository instead of using Git submodule.
+- Google git-repo to support addons repository instead of using Git submodule.
### Removed
- Git submodule
diff --git a/README.md b/README.md
index fe65626..518b7c3 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@ Support Ubuntu 18.04 and OSX
./script/install_dev.sh
./script/install_locally_prod.sh
```
-Update your configuration if you need to run somehere than 127.0.0.1, file config.conf
+Update your configuration if you need to run somehere than 127.0.0.1, file `config.conf`
```
#xmlrpc_interface = 127.0.0.1
#netrpc_interface = 127.0.0.1
diff --git a/TODO.md b/TODO.md
new file mode 100644
index 0000000..f69920d
--- /dev/null
+++ b/TODO.md
@@ -0,0 +1,30 @@
+# TODO
+## Simplify push tag
+For RELEASE.md, replace next value by a script to select all remote by manifest file.
+Actually, need to push manually all different remote.
+> ./.venv/repo forall -pc "git push ERPLibre --tags"
+
+## Funding
+- Add funding for MathBenTech and TechnoLibre
+
+## Improve repo init usage
+- Support run repo init without human interaction. Do we need to create a temporary user name?
+
+## Improve repo sync usage
+- Test repo sync with argument -d
+- Test repo sync with argument -t SMART_TAG, like tag ERPLibre/v1.0.0
+
+## Git diff
+### Between 2 commits
+- Show all modified file, files list.
+- Show if probably has conflict if cherry-pick in wrong order,
+- Show modify same line in different commit
+
+## Development
+### Run with another address ip than local
+- Remove xmlrpc_interface in config file when running dev installation
+- Improve config builder with a Python script
+
+### Variable in new instance
+- Add technique to add variable when create a new instance from config files
+- Documentation for adding mail server, a guide for every one
diff --git a/default.xml b/default.xml
index 1396a65..427b8fc 100644
--- a/default.xml
+++ b/default.xml
@@ -1,103 +1,146 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/CONTRIBUTION.md b/doc/CONTRIBUTION.md
index c68c584..4052eee 100644
--- a/doc/CONTRIBUTION.md
+++ b/doc/CONTRIBUTION.md
@@ -1,6 +1,6 @@
# Thanks
## AGILE OPS
-Thanks for contributing to GIT_REPO.
+Thanks for contributing to GIT_REPO and docker.
- [Agile OPS](https://www.linkedin.com/in/michaelfaille/)
## MathBenTech
@@ -8,9 +8,9 @@ Thanks for creating this project.
- [MathBen.Tech](https://mathben.tech)
## TechnoLibre
-Thanks for making enterprise edition of ERPLibre.
+Thanks for making this enterprise edition of ERPLibre.
- [TechnoLibre](https://technolibre.ca)
## Yenthe Van Ginneken
-Thanks Yenthe Van Ginneken for your scripting guides and tutorial.
+Thanks Yenthe Van Ginneken for your scripting guides and tutorials.
- [Yenthe666 InstallScript](https://github.com/Yenthe666/InstallScript)
diff --git a/doc/DEVELOPMENT.md b/doc/DEVELOPMENT.md
index 01c43de..c25e3ba 100644
--- a/doc/DEVELOPMENT.md
+++ b/doc/DEVELOPMENT.md
@@ -1,7 +1,7 @@
# Development guide
Setup your environment to develop modules and debug the platform.
-## Installation procedure locally
+## Local installation procedure
### 1. Clone the project:
```bash
git clone https://github.com/ERPLibre/ERPLibre.git
@@ -20,17 +20,10 @@ cd ERPLibre
```
## Develop in Odoo repository
-You need to remove
-> clone-depth="1"
+You need to remove `clone-depth="10"` from `./manifest/default.dev.xml` in order to be able to commit and push.
+Make a temporary commit and regenerate with `./script/install_locally_dev.sh`
-from
-> ./manifest/default.dev.xml
-
-file to be able to commit and push.
-Commit temporary and regenerate with
-> ./script/install_locally_dev.sh
-
-## Fork project to create a new project independent of ERPLibre (deprecated)
+## Fork project to create a new project independent from ERPLibre (deprecated)
ERPLibre was created by this script. It's now deprecated.
Use this script when you need to fork directly from the original source.
Don't use this script if you want to update from ERPLibre and follow mainstream development.
@@ -38,8 +31,8 @@ Don't use this script if you want to update from ERPLibre and follow mainstream
./script/fork_project.py --github_token GITHUB_KEY --organization NAME
```
-# Fork all repo for you own organization
-Go to your github account and generate a token to access fork option with your user. Create an organization (or you can choose your user name).
+# Fork all repos for you own organization
+Go to your github account and generate a token to access fork option with your user. Create an organization or use your personal account can choose your user name.
This command will fork all repos and ERPLibre to your own organization. It keeps track to ERPLibre.
```bash
@@ -49,13 +42,13 @@ This command will fork all repos and ERPLibre to your own organization. It keeps
## Generate manifest from csv repo
Add repo in file [./source_repo_addons.csv](./source_repo_addons.csv)
-Execute to generate manifest of Repo
+Execute to generate Repo manifest
```bash
./script/fork_project_ERPLibre.py --skip_fork
```
## Move database prod to dev
-When moving database prod to your dev environment, you want to remove email servers, and install user test in order to test the database.
+When moving database prod to your dev environment, you want to remove email servers and install user test in order to test the database.
Run:
```bash
./run.sh --stop-after-init -i user_test,disable_mail_server --dev all -d DATABASE
@@ -72,26 +65,32 @@ This will update all urls in git format:
./script/git_change_remote_https_to_git.py
```
-## Diff repo with another project
+## Showing repo differences between projects
Tools to display the differences between the repo and another project.
```bash
./script/git_change_remote.py --sync_to /path/to/project/erplibre --dry_sync
```
## Sync repo with another project
-Tools to synchronise the repo with another project. This will show differences and try to checkout on the same commit in all repo.
+Tools to synchronise the repo with another project. This will show differences and try to checkout on the same commit in all repos.
```bash
./script/git_change_remote.py --sync_to /path/to/project/erplibre
```
-## Diff code between manifest
-To show diff between commits in different manifest
+## Compare two files manifests
+To show differences between commits in different manifests
```bash
./script/git_diff_repo_manifest.py --input1 ./manifest/MANIFEST1.xml --input2 ./manifest/MANIFEST2.xml
```
+## Differences between code and manifest
+To show differences between actual code and manifest
+```bash
+./script/git_show_code_diff_repo_manifest.py --manifest ./manifest/MANIFEST1.xml
+```
+
## Add repo
-Access to a new repo, add your URL to file [source_repo_addons.csv](../source_repo_addons.csv)
+To access a new repo, add your URL to file [source_repo_addons.csv](../source_repo_addons.csv)
Fork the repo to be able to push new code:
```bash
@@ -103,9 +102,20 @@ To regenerate only manifest.xml.
./script/fork_project_ERPLibre.py --skip_fork
```
-# Coding
-## Create module scaffold (run in the venv)
+Check if manifest contains "auto_install" and change the value to False.
```bash
-source ./venv/bin/activate
+./script/repo_remove_auto_install.py
+```
+
+# Coding
+## Create module scaffold
+```bash
+source ./.venv/bin/activate
python odoo/odoo-bin scaffold MODULE_NAME addons/REPO_NAME/
```
+
+# Pull request
+## Show all pull requests from organization
+```bash
+/script/pull_request_ERPLibre.py --github_token ### --organization ERPLibre
+```
diff --git a/doc/DISCOVER.md b/doc/DISCOVER.md
index 7e5ca0e..138f44f 100644
--- a/doc/DISCOVER.md
+++ b/doc/DISCOVER.md
@@ -20,13 +20,14 @@ cd ERPLibre
```
## Add repo
-Access to a new repo, add your URL to file [source_repo_addons.csv](../source_repo_addons.csv)
+To access a new repo, add your URL to file [source_repo_addons.csv](../source_repo_addons.csv)
Execute script:
```bash
./script/git_repo_manifest.py
-git checkout -b new_branch
+git checkout -b NEW_BRANCH
git commit -am "Add new repo"
./script/install_locally_dev.sh
+./script/poetry_update.py
```
[Update your repo.](./GIT_REPO.md)
diff --git a/doc/FAQ.md b/doc/FAQ.md
index d5a29cc..57638a4 100644
--- a/doc/FAQ.md
+++ b/doc/FAQ.md
@@ -8,7 +8,7 @@ error.GitError: manifests rev-list (u'^2736dfd46e8a30cf59a9cd6e93d9e56e87021f2a'
Did you modify files in .repo?
-Anyways, to reset files from your branch into .repo:
+To reset files from your branch into .repo:
```bash
cd .repo/manifests
git branch -av
diff --git a/doc/GIT_REPO.md b/doc/GIT_REPO.md
index 95a6991..3a7f55f 100644
--- a/doc/GIT_REPO.md
+++ b/doc/GIT_REPO.md
@@ -1,84 +1,84 @@
# git-repo
This is a guide to understand git-repo. Scripts in ERPLibre use git-repo automatically.
-[git-repo of Google](https://code.google.com/archive/p/git-repo) is used to manage all git repository under licence [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0.html).
+[git-repo of Google](https://code.google.com/archive/p/git-repo) is used to manage all git repositories under licence [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0.html).
## Setup repo
```bash
-curl https://storage.googleapis.com/git-repo-downloads/repo > ./venv/repo
+curl https://storage.googleapis.com/git-repo-downloads/repo > ./.venv/repo
```
## prod
```bash
-./venv/repo init -u http://git.erplibre.ca/ERPLibre -b master
-./venv/repo sync
+./.venv/repo init -u http://git.erplibre.ca/ERPLibre -b master
+./.venv/repo sync
```
## dev
```bash
-./venv/repo init -u http://git.erplibre.ca/ERPLibre -b 12.0_repo -m ./manifest/default.dev.xml
-./venv/repo sync
+./.venv/repo init -u http://git.erplibre.ca/ERPLibre -b 12.0_repo -m ./manifest/default.dev.xml
+./.venv/repo sync
```
-## dev locally
+## local dev
[Guide to setup locally git](https://railsware.com/blog/taming-the-git-daemon-to-quickly-share-git-repository/).
```bash
git daemon --base-path=. --export-all --reuseaddr --informative-errors --verbose &
-./venv/repo init -u git://127.0.0.1:9418/ -b $(git rev-parse --abbrev-ref HEAD) -m ./manifest/default.dev.xml
-./venv/repo sync -m ./manifest/default.dev.xml
+./.venv/repo init -u git://127.0.0.1:9418/ -b $(git rev-parse --abbrev-ref HEAD) -m ./manifest/default.dev.xml
+./.venv/repo sync -m ./manifest/default.dev.xml
```
# Create Manifest
A [Manifest](https://gerrit.googlesource.com/git-repo/+/master/docs/manifest-format.md), is a XML file managed by git-repo to generate repo.
## Make a new version of prod
-Freezes all repo, from dev to prod.
+It freezes all repo, from dev to prod.
This will add revision git hash in the Manifest.
```bash
-./venv/repo manifest -r -o ./default.xml
+./.venv/repo manifest -r -o ./default.xml
```
-Do your commit.
+Commit.
```bash
git commit -am "[#ticket] subject: short sentence"
```
-### Mix prod and dev to do a stage
-When dev contain specific revision with default revision, you want to replace default revision by prod revision and keep specific version, do:
+### Mix prod and dev to create a stage version
+When dev contains specific revision with default revision, you need to replace default revision with prod revision and keep specific version:
```bash
./script/git_merge_repo_manifest.py --input1 ./manifest/default.dev.xml --input2 ./default.xml --output ./manifest/default.staged.xml
git commit -am "Updated manifest/default.staged.xml"
git daemon --base-path=. --export-all --reuseaddr --informative-errors --verbose &
-./venv/repo init -u git://127.0.0.1:9418/ -b $(git rev-parse --abbrev-ref HEAD) -m ./manifest/default.staged.xml
-./venv/repo sync -m ./manifest/default.staged.xml
+./.venv/repo init -u git://127.0.0.1:9418/ -b $(git rev-parse --abbrev-ref HEAD) -m ./manifest/default.staged.xml
+./.venv/repo sync -m ./manifest/default.staged.xml
-./venv/repo manifest -r -o ./default.xml
+./.venv/repo manifest -r -o ./default.xml
```
## Create a dev version
```bash
-./venv/repo manifest -o ./manifest/default.dev.xml
+./.venv/repo manifest -o ./manifest/default.dev.xml
```
-Do your commit.
+Commit.
```bash
git commit -am "[#ticket] subject: short sentence"
```
-## Useful command
-### Search all repo with specific branch name
+## Useful commands
+### Search all repo with a specific branch name
```bash
-./venv/repo forall -pc "git branch -a|grep BRANCH"
+./.venv/repo forall -pc "git branch -a|grep BRANCH"
```
-### Search missing branch in all repo
+### Search missing branch in all repos
```bash
-./venv/repo forall -pc 'git branch -a|(grep /BRANCH$||echo "no match")|grep "no match"'
+./.venv/repo forall -pc 'git branch -a|(grep /BRANCH$||echo "no match")|grep "no match"'
```
-### Search change file in all repo
+### Search changed file in all repos
```bash
-./venv/repo forall -pc "git status -s"
+./.venv/repo forall -pc "git status -s"
```
### Clean all
diff --git a/doc/HOWTO.md b/doc/HOWTO.md
index 8588b44..4f2b2f0 100644
--- a/doc/HOWTO.md
+++ b/doc/HOWTO.md
@@ -1,3 +1,3 @@
# HOW TO
## Update changelog
-Please, read documentation [keepachangelog.com](https://keepachangelog.com)
\ No newline at end of file
+Please read the following documentation [keepachangelog.com](https://keepachangelog.com)
diff --git a/doc/MIGRATION.md b/doc/MIGRATION.md
index 77298e9..847aa87 100644
--- a/doc/MIGRATION.md
+++ b/doc/MIGRATION.md
@@ -1,10 +1,10 @@
# ERPLibre
-## Migration procedure production
+## Migration procedure in production
TODO
-## Migration procedure dev
+## Migration procedure in dev
Example:
diff --git a/doc/POETRY.md b/doc/POETRY.md
new file mode 100644
index 0000000..4a190a7
--- /dev/null
+++ b/doc/POETRY.md
@@ -0,0 +1,13 @@
+# Poetry
+## Add automatically dependencies
+Add your dependencies in file [requirements.txt](../requirements.txt) and run script
+```bash
+./script/poetry_update.py
+```
+This will search all `requirements.txt` files and update `pyproject.toml` and it will update poetry
+
+## Add manually dependencies
+The automatic script will erase this dependency, but you can add it for your local test.
+```bash
+poetry add PYTHON_MODULE
+```
diff --git a/doc/PRODUCTION.md b/doc/PRODUCTION.md
index e71fa4e..133ebc9 100644
--- a/doc/PRODUCTION.md
+++ b/doc/PRODUCTION.md
@@ -1,6 +1,6 @@
# ERPLibre production guide
-## Installation procedure production
+## Production installation procedure
### 1. Clone the project:
```bash
@@ -12,15 +12,24 @@ cd ERPLibre
Modify the file env_var.sh for production installation.
### 3. Execute the script:
-Support Ubuntu 18.04 server
+#### Ubuntu 18.04 server
```bash
./script/install_dev.sh
./script/install_production.sh
```
-A service is running by systemd, you can access with the DNS name, found it in env_var.sh
+A service is running by systemd. You can access it with the DNS name found in env_var.sh
+
+#### Ubuntu 20.04 server
+Apply fix libpng12-0: https://www.linuxuprising.com/2018/05/fix-libpng12-0-missing-in-ubuntu-1804.html
+
+```bash
+./script/install_dev.sh
+./script/install_production.sh
+```
+A service is running by systemd, you can access with the DNS name found in env_var.sh
### 4. SSL:
-Generate a ssl certificat
+Generate a ssl certificate
```bash
sudo certbot --nginx
```
@@ -31,13 +40,13 @@ sudo systemctl -feu [EL_USER]
```
## Run by address ip
-Comment following line in /[EL_USER]/erplibre/config.conf
+Comment the following line in `/[EL_USER]/erplibre/config.conf`
```
#xmlrpc_interface = 127.0.0.1
#netrpc_interface = 127.0.0.1
#proxy_mode = True
```
-Add your address ip in nginx config at server_name in /etc/nginx/sites-available/[EL_WEBSITE_NAME]
+Add your address ip server_name in nginx config `/etc/nginx/sites-available/[EL_WEBSITE_NAME]`
Restart daemon:
```bash
@@ -51,15 +60,28 @@ cd /[EL_USER]/erplibre
./run.sh -d [DATABASE] --no-database-list
```
-## Move database prod to dev
-When moving database prod to your dev environment, you want to remove email servers, and install user test to test the database.
+## Move prod database to dev
+When moving prod database to your dev environment, you want to remove email servers and install user test to test the database.
Run:
```bash
./run.sh --stop-after-init -i user_test,disable_mail_server --dev all -d DATABASE
```
## Update production
-Simply update all feature.
+Update all features.
```bash
./run.sh --limit-time-real 99999 --stop-after-init -u all -d DATABASE
```
+
+# Postgresql
+To show config file:
+> psql -U postgres -c 'SHOW config_file'
+
+Edit this file to accept interface from all networks:
+> /var/lib/postgres/data/postgresql.conf
+
+# Delete an instance in production
+Caution, this delete user's home, it's irrevocable.
+```bash
+./script/delete_production.sh
+```
diff --git a/doc/RELEASE.md b/doc/RELEASE.md
index e73a371..1b77090 100644
--- a/doc/RELEASE.md
+++ b/doc/RELEASE.md
@@ -1,35 +1,38 @@
# Release
-A guide on how to do a release.
+A guide on how to generate a release.
## Generate new prod
```bash
-./venv/repo manifest -r -o ./default.xml
+./.venv/repo manifest -r -o ./default.xml
```
-Do your commit.
+Commit.
```bash
git commit -am "[#ticket] subject: short sentence"
```
-## Merge release
-When ready to make a release, create a branch release/#.#.# and create a pull request to master.
-Update file CHANGELOG.md and create a section with new version.
-Merge it when maintener accept it.
+Update ERPLIBRE_VERSION variable in [env_var.sh](../env_var.sh)
-Add a tag on the commit on branch master with your release. When adding tag, be sure to update default.xml
+## Merge release
+When you are ready to generate a release, create a branch release/#.#.# and create a pull request to master.
+
+Update file [CHANGELOG.md](../CHANGELOG.md) and create a section with new version.
+Merge it when the maintainer accepts it.
+
+Add a tag on the commit in branch master with your release. When adding tag, be sure to update default.xml
```bash
git tag v#.#.#
# Push your tags
git push --tags
# Add tags for all repo
-./venv/repo forall -pc "git tag ERPLibre/v#.#.#"
-./venv/repo forall -pc "git push ERPLibre --tags"
+./.venv/repo forall -pc "git tag ERPLibre/v#.#.#"
+./.venv/repo forall -pc "git push ERPLibre --tags"
# Get all difference between a tag and HEAD, to update the CHANGELOG.md
-./venv/repo forall -pc "git diff ERPLibre/v#.#.#..HEAD"
+./.venv/repo forall -pc "git diff ERPLibre/v#.#.#..HEAD"
```
# TIPS
-## Compare diff repo with another ERPLibre project
-To generate a list of differences between repo git commit, do
+## Compare repo differences with another ERPLibre project
+To generate a list of differences between repo git commit
```bash
./script/git_change_remote.py --sync_to /path/to/directory
```
\ No newline at end of file
diff --git a/doc/RUN.md b/doc/RUN.md
index 545af32..c2c71a6 100644
--- a/doc/RUN.md
+++ b/doc/RUN.md
@@ -24,7 +24,7 @@ Execute your own python script:
```
### Update all
-Great idea to run it when updating Odoo, it updates database of each modules.
+Great idea to run it when updating Odoo, it updates each module database.
```bash
./run.sh -d [DATABASE] -u all --log-level debug
```
@@ -39,11 +39,11 @@ First execution, install you requirements, choose a new database.
```bash
./run.sh -d [DATABASE] -i [module to test] --test-enable --stop-after-init --log-level=test
```
-Execute your test on specific module.
+Execute your test on a specific module.
```bash
./run.sh -d [DATABASE] -u [module to test] --test-enable --stop-after-init --log-level=test
```
-Execute your test on specific module with tags.
+Execute your test on a specific module with tags.
```bash
./run.sh -d [DATABASE] -u [module to test] --test-enable --stop-after-init --log-level=test --test-tags [module_name][tags]
```
\ No newline at end of file
diff --git a/doc/UPDATE.md b/doc/UPDATE.md
new file mode 100644
index 0000000..284be38
--- /dev/null
+++ b/doc/UPDATE.md
@@ -0,0 +1,24 @@
+# Update ERPLibre
+## Update all repos from the origin source
+The update is possible on branch 12.0, you need to verify this branch existence.
+
+1. Make sure all git repos are conform, remove all argument depth from manifest and regenerate.
+You can clean all and regenerate.
+```bash
+./script/clean_repo_manifest.sh
+./script/install_locally_dev.sh
+```
+
+2. Update all remote with ssh/git
+```bash
+./script/git_change_remote_https_to_git.py
+```
+
+3. Run update script
+```bash
+./script/git_update_repo.py
+```
+
+4. Do a forced push on all needed repo and manage rebase conflicts.
+
+5. Test a clone with dev, check file [DEVELOPMENT.md](./DEVELOPMENT.md)
diff --git a/docker-compose-dev.yml b/docker-compose-dev.yml
new file mode 100644
index 0000000..7335857
--- /dev/null
+++ b/docker-compose-dev.yml
@@ -0,0 +1,50 @@
+version: "3.3"
+services:
+ ERPLibre:
+ image: technolibre/erplibre-dev:12.0
+ # image: technolibre/erplibre-prod:pkg-12.0
+ # image: technolibre/erplibre-prod:deb-12.0
+ ports:
+ - 8069:8069
+ environment:
+ HOST: db
+ PASSWORD: mysecretpassword
+ USER: odoo
+ POSTGRES_DB: odoo
+ CURRENT_UID: ${CURRENT_UID}
+ depends_on:
+ - db
+ networks:
+ - front
+ command: odoo -c /ERPLibre/odoo/odoo.conf --without-demo=ALL -i base -d odoo
+ user: ${CURRENT_UID:?"Please run as follows 'CURRENT_UID=$(id -u):$(id -g) docker-compose up'"}
+ # user:
+ volumes:
+ - .:/ERPLibre
+ # See the volume section at the end of the file
+ - erplibre_data_dir:/var/lib/odoo
+
+ db:
+ image: postgres:12.3
+ environment:
+ POSTGRES_PASSWORD: mysecretpassword
+ POSTGRES_USER: odoo
+ POSTGRES_DB: odoo
+ networks:
+ - front
+
+
+networks:
+ front:
+
+ driver: bridge
+ ipam:
+ driver: default
+ config:
+ - subnet: 172.16.237.0/24
+
+# We configure volume without specific destination to let docket manage it. To configure it through docker use (read related documentation before continuing) :
+# - docker volume --help
+# - docker-compose down --help
+volumes:
+ erplibre_data_dir:
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..44203f5
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,38 @@
+version: "3.3"
+services:
+ ERPLibre:
+ image: technolibre/erplibre:1.1.0
+ ports:
+ - 8069:8069
+ - 8071:8071
+ - 8072:8072
+ environment:
+ HOST: db
+ PASSWORD: mysecretpassword
+ USER: odoo
+ POSTGRES_DB: postgres
+ depends_on:
+ - db
+ command: odoo
+ volumes:
+ # See the volume section at the end of the file
+ - erplibre_data_dir:/home/odoo/.local/share/Odoo/
+ - erplibre_conf:/etc/odoo
+
+ db:
+ image: postgres:12.3
+ environment:
+ POSTGRES_PASSWORD: mysecretpassword
+ POSTGRES_USER: odoo
+ POSTGRES_DB: postgres
+ PGDATA: /var/lib/postgresql/data/pgdata
+ volumes:
+ - erplibre-db-data:/var/lib/postgresql/data/pgdata
+
+# We configure volume without specific destination to let docket manage it. To configure it through docker use (read related documentation before continuing) :
+# - docker volume --help
+# - docker-compose down --help
+volumes:
+ erplibre_data_dir:
+ erplibre_conf:
+ erplibre-db-data:
diff --git a/docker/Dockerfile b/docker/Dockerfile
new file mode 100644
index 0000000..b923147
--- /dev/null
+++ b/docker/Dockerfile
@@ -0,0 +1,92 @@
+FROM debian:buster-slim
+MAINTAINER Odoo S.A.
+
+SHELL ["/bin/bash", "-xo", "pipefail", "-c"]
+
+# Generate locale C.UTF-8 for postgres and general locale data
+ENV LANG C.UTF-8
+
+# Install some deps, lessc and less-plugin-clean-css, and wkhtmltopdf
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+ ca-certificates \
+ curl \
+ dirmngr \
+ fonts-noto-cjk \
+ gnupg \
+ libssl-dev \
+ node-less \
+ npm \
+ python3-num2words \
+ python3-pip \
+ python3-phonenumbers \
+ python3-pyldap \
+ python3-qrcode \
+ python3-renderpm \
+ python3-setuptools \
+ python3-slugify \
+ python3-vobject \
+ python3-watchdog \
+ python3-xlrd \
+ python3-xlwt \
+ xz-utils \
+ git \
+ iproute2 \
+ inetutils-ping \
+ && curl -o wkhtmltox.deb -sSL https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.5/wkhtmltox_0.12.5-1.stretch_amd64.deb \
+ && echo '7e35a63f9db14f93ec7feeb0fce76b30c08f2057 wkhtmltox.deb' | sha1sum -c - \
+ && apt-get install -y --no-install-recommends ./wkhtmltox.deb \
+ && rm -rf /var/lib/apt/lists/* wkhtmltox.deb
+
+# install latest postgresql-client
+RUN echo 'deb http://apt.postgresql.org/pub/repos/apt/ buster-pgdg main' > /etc/apt/sources.list.d/pgdg.list \
+ && GNUPGHOME="$(mktemp -d)" \
+ && export GNUPGHOME \
+ && repokey='B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8' \
+ && gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "${repokey}" \
+ && gpg --batch --armor --export "${repokey}" > /etc/apt/trusted.gpg.d/pgdg.gpg.asc \
+ && gpgconf --kill all \
+ && rm -rf "$GNUPGHOME" \
+ && apt-get update \
+ && apt-get install --no-install-recommends -y postgresql-client \
+ && rm -f /etc/apt/sources.list.d/pgdg.list \
+ && rm -rf /var/lib/apt/lists/*
+
+
+
+# Install Odoo
+ENV ODOO_VERSION 12.0
+ARG ODOO_RELEASE=20200417
+ARG ODOO_SHA=ca4a7485b0b75850ffe1458a8f3266839400a501
+RUN curl -o odoo.deb -sSL http://nightly.odoo.com/${ODOO_VERSION}/nightly/deb/odoo_${ODOO_VERSION}.${ODOO_RELEASE}_all.deb \
+ && echo "${ODOO_SHA} odoo.deb" | sha1sum -c - \
+ && apt-get update \
+ && apt-get -y install --no-install-recommends ./odoo.deb \
+ && rm -rf /var/lib/apt/lists/* odoo.deb
+
+# Copy entrypoint script and Odoo configuration file
+COPY ./entrypoint.sh /
+RUN chmod +x /entrypoint.sh
+COPY ./odoo.conf /etc/odoo/
+
+# Mount /var/lib/odoo to allow restoring filestore and /mnt/extra-addons for users addons
+RUN chown odoo /etc/odoo/odoo.conf \
+ && mkdir -p /mnt/extra-addons \
+ && chown -R odoo /mnt/extra-addons
+# VOLUME ["/var/lib/odoo", "/mnt/extra-addons"]
+
+# Expose Odoo services
+EXPOSE 8069 8071 8072
+
+# Set the default config file
+ENV ODOO_RC /etc/odoo/odoo.conf
+
+COPY wait-for-psql.py /usr/local/bin/wait-for-psql.py
+
+RUN chmod +X /usr/local/bin/wait-for-psql.py
+
+# Set default user when running the container
+USER odoo
+
+ENTRYPOINT ["/entrypoint.sh"]
+CMD ["odoo"]
diff --git a/docker/Dockerfile.base b/docker/Dockerfile.base
new file mode 100644
index 0000000..ac44c48
--- /dev/null
+++ b/docker/Dockerfile.base
@@ -0,0 +1,147 @@
+FROM debian:buster-slim
+MAINTAINER TechnoLibre
+
+SHELL ["/bin/bash", "-xo", "pipefail", "-c"]
+
+# Generate locale C.UTF-8 for postgres and general locale data
+ENV LANG C.UTF-8
+
+ENV LANG="C.UTF-8" \
+ LC_ALL="C.UTF-8" \
+ PATH="/opt/pyenv/shims:/opt/pyenv/bin:$PATH" \
+ PYENV_ROOT="/opt/pyenv" \
+ PYENV_SHELL="bash"
+
+ENV ODOO_PREFIX /ERPLibre
+ENV ODOO_EXEC_BIN $ODOO_PREFIX/odoo/odoo-bin
+
+# Install some deps, lessc and less-plugin-clean-css, and wkhtmltopdf
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+ ca-certificates \
+ curl \
+ dirmngr \
+ fonts-noto-cjk \
+ gnupg \
+ libssl-dev \
+ node-less \
+ npm \
+ python3-num2words \
+ python3-pip \
+ python3-phonenumbers \
+ python3-pyldap \
+ python3-qrcode \
+ python3-renderpm \
+ python3-setuptools \
+ python3-slugify \
+ python3-vobject \
+ python3-watchdog \
+ python3-xlrd \
+ python3-xlwt \
+ python3-babel \
+ python3-psycopg2 \
+ xz-utils \
+ git \
+ wget \
+ libxslt-dev \
+ libzip-dev \
+ libldap2-dev \
+ libsasl2-dev \
+ node-less \
+ gdebi-core \
+ libffi-dev \
+ iproute2 \
+ libmariadbd-dev \
+ inetutils-ping \
+ build-essential \
+ libsqlite3-dev \
+ sqlite3 \
+ bzip2 \
+ libbz2-dev \
+ zlib1g-dev \
+ libssl-dev \
+ openssl \
+ libgdbm-dev \
+ libgdbm-compat-dev \
+ liblzma-dev \
+ libreadline-dev \
+ libncursesw5-dev \
+ libffi-dev \
+ uuid-dev \
+ && curl -o wkhtmltox.deb -sSL https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.5/wkhtmltox_0.12.5-1.stretch_amd64.deb \
+ && echo '7e35a63f9db14f93ec7feeb0fce76b30c08f2057 wkhtmltox.deb' | sha1sum -c - \
+ && apt-get install -y --no-install-recommends ./wkhtmltox.deb \
+ && rm -rf /var/lib/apt/lists/* wkhtmltox.deb
+
+# Install latest postgresql-client
+RUN echo 'deb http://apt.postgresql.org/pub/repos/apt/ buster-pgdg main' > /etc/apt/sources.list.d/pgdg.list \
+ && GNUPGHOME="$(mktemp -d)" \
+ && export GNUPGHOME \
+ && repokey='B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8' \
+ && gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "${repokey}" \
+ && gpg --batch --armor --export "${repokey}" > /etc/apt/trusted.gpg.d/pgdg.gpg.asc \
+ && gpgconf --kill all \
+ && rm -rf "$GNUPGHOME" \
+ && apt-get update \
+ && apt-get install --no-install-recommends -y postgresql-client-12 libpq-dev \
+ && rm -rf /var/lib/apt/lists/*
+
+# Install python with pyenv
+# Reference https://github.com/bopen/docker-ubuntu-pyenv
+COPY pyenv-version.txt python-versions.txt /
+
+RUN git clone -b `cat /pyenv-version.txt` --single-branch --depth 1 https://github.com/pyenv/pyenv.git $PYENV_ROOT \
+ && for version in `cat /python-versions.txt`; do pyenv install $version; done \
+ && pyenv global `cat /python-versions.txt` \
+ && find $PYENV_ROOT/versions -type d '(' -name '__pycache__' -o -name 'test' -o -name 'tests' ')' -exec rm -rf '{}' + \
+ && find $PYENV_ROOT/versions -type f '(' -name '*.pyo' -o -name '*.exe' ')' -exec rm -f '{}' + \
+ && rm -rf /tmp/* \
+ && python --version \
+ && python3 --version
+
+# Install git-repo
+RUN cd ; mkdir -p .bin/ && \
+ git config --global color.ui false && \
+ git config --global user.email "foo@bar.io" && \
+ git config --global user.name "Foo Bar" && \
+ curl https://storage.googleapis.com/git-repo-downloads/repo > /usr/bin/repo && \
+ chmod +x /usr/bin/repo && sed -i '1 s/python$/python3/' /usr/bin/repo
+
+RUN groupadd --gid 101 --force odoo && \
+ useradd --non-unique --create-home --uid 101 --gid 101 odoo
+
+# TODO delete poetry installation
+# Install Poetry
+RUN curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python
+#curl -fsS -o get-poetry.py https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py
+
+# Copy entrypoint script and Odoo configuration file
+COPY ./entrypoint.sh /
+RUN chmod +x /entrypoint.sh
+
+# Set the default config file
+ENV ODOO_RC /etc/odoo/odoo.conf
+COPY ./odoo.conf $ODOO_RC
+RUN chown odoo $ODOO_RC
+
+RUN mkdir $ODOO_PREFIX && \
+ chown odoo $ODOO_PREFIX && \
+ chmod 1777 $ODOO_PREFIX
+
+# Mount /var/lib/odoo to allow restoring filestore
+RUN chown odoo $ODOO_RC
+
+# Expose Odoo services
+EXPOSE 8069 8071 8072
+
+#RUN mkdir -p /var/lib/odoo && \
+# chown odoo /var/lib/odoo && \
+# chmod 1777 /var/lib/odoo
+
+# VOLUME /var/lib/odoo
+
+# Set default user when running the container
+USER odoo
+
+ENTRYPOINT ["/entrypoint.sh"]
+CMD ["odoo"]
diff --git a/docker/Dockerfile.dev b/docker/Dockerfile.dev
new file mode 100644
index 0000000..aed4323
--- /dev/null
+++ b/docker/Dockerfile.dev
@@ -0,0 +1,37 @@
+FROM technolibre/erplibre-base:12.0
+
+USER root
+
+RUN apt update && \
+ apt install -y -y --no-install-recommends \
+ build-essential \
+ wget \
+ python3-dev \
+ python3-venv \
+ python3-wheel \
+ libxslt-dev \
+ libzip-dev \
+ libldap2-dev \
+ libsasl2-dev \
+ python3-setuptools \
+ libpng16-16 \
+ gdebi \
+ && rm -rf /var/lib/apt/lists/* \
+ && npm install -g rtlcss
+
+# RUN pip3 install -r https://raw.githubusercontent.com/odoo/odoo/12.0/requirements.txt --ignore-installed psycopg2 && pip3a cache purge
+
+ENV ADDONS_BASE_DIR /ERPLibre
+ENV ENV=dev
+
+# Copy entrypoint script and Odoo configuration file
+COPY ./entrypoint.sh /
+RUN chmod +x /entrypoint.sh
+
+COPY repo_manifest_gen_org_prefix_path.py /usr/bin/
+RUN chmod +x /usr/bin/repo_manifest_gen_org_prefix_path.py
+
+USER odoo
+
+ENTRYPOINT ["/entrypoint.sh"]
+CMD ["odoo"]
diff --git a/docker/Dockerfile.prod.pkg b/docker/Dockerfile.prod.pkg
new file mode 100644
index 0000000..78820ca
--- /dev/null
+++ b/docker/Dockerfile.prod.pkg
@@ -0,0 +1,50 @@
+FROM technolibre/erplibre-base:1.1.0
+
+ENV REPO_MANIFEST_URL http://git.erplibre.ca/ERPLibre
+ARG WORKING_BRANCH
+ENV BRANCH_ERPLIBRE $WORKING_BRANCH
+
+RUN cat /etc/os-release
+
+USER root
+
+RUN mkdir ~/.ssh/ && \
+ echo "StrictHostKeyChecking no" >> ~/.ssh/config && \
+ apt update && \
+ apt install ssh-client git -y --no-install-recommends && \
+ rm -rf /var/lib/apt/lists/*
+
+RUN cd ; mkdir -p .bin/ && \
+ git config --global color.ui false && \
+ git config --global user.email "foo@bar.io" && \
+ git config --global user.name "Foo Bar" && \
+ git clone $REPO_MANIFEST_URL -b $BRANCH_ERPLIBRE $ODOO_PREFIX
+
+RUN cd $ODOO_PREFIX && \
+ python -m venv .venv
+
+RUN cd $ODOO_PREFIX && \
+ curl https://storage.googleapis.com/git-repo-downloads/repo > ./.venv/repo && \
+ chmod +x ./.venv/repo
+
+RUN cd $ODOO_PREFIX && \
+ ./script/update_manifest_dev.sh
+
+RUN cd $ODOO_PREFIX && \
+ source /root/.poetry/env && \
+ poetry install
+
+RUN cd $ODOO_PREFIX && \
+ head /etc/odoo/odoo.conf && \
+ ./docker/repo_manifest_gen_org_prefix_path.py $ODOO_PREFIX/addons /etc/odoo/odoo.conf /etc/odoo/odoo.conf && \
+ head /etc/odoo/odoo.conf
+
+#RUN mkdir '/home/odoo/.local'
+#RUN chown -R odoo '/home/odoo/.local'
+
+USER odoo
+
+RUN mkdir -p '/home/odoo/.local/share/Odoo/'
+
+ENTRYPOINT ["/entrypoint.sh"]
+CMD ["odoo"]
diff --git a/docker/Dockerfile.prod.src b/docker/Dockerfile.prod.src
new file mode 100644
index 0000000..f512ec4
--- /dev/null
+++ b/docker/Dockerfile.prod.src
@@ -0,0 +1,41 @@
+FROM technolibre/erplibre-base:12.0
+
+# TODO
+
+
+# ENV REPO_MANIFEST_URL https://github.com/agileops/ERPLibre.git
+# RUN cat /etc/os-release
+
+# USER root
+
+# # Install Odoo
+# ENV ODOO_VERSION 12.0
+# ARG ODOO_RELEASE=20200417
+# ARG ODOO_SHA=ca4a7485b0b75850ffe1458a8f3266839400a501
+# RUN curl -o odoo.deb -sSL http://nightly.odoo.com/${ODOO_VERSION}/nightly/deb/odoo_${ODOO_VERSION}.${ODOO_RELEASE}_all.deb \
+# && echo "${ODOO_SHA} odoo.deb" | sha1sum -c - \
+# && apt-get update \
+# && apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confnew install --no-install-recommends ./odoo.deb \
+# && rm -rf /var/lib/apt/lists/* odoo.deb
+
+
+# RUN mkdir ~/.ssh/ && echo "StrictHostKeyChecking no" >> ~/.ssh/config && apt update && apt install ssh-client git -y --no-install-recommends && \
+# rm -rf /var/lib/apt/lists/*
+
+# RUN cd ; mkdir -p .bin/ && \
+# git config --global color.ui false && \
+# git config --global user.email "foo@bar.io" && \
+# git config --global user.name "Foo Bar" && \
+# mkdir -p $ODOO_PREFIX && cd $ODOO_PREFIX && \
+# repo init -u $REPO_MANIFEST_URL -b 12.0_repo && \
+# repo sync -j 4 -c
+
+# ADD repo_manifest_gen_org_prefix_path.py /root/.bin/
+# RUN chmod +x ~/.bin/repo_manifest_gen_org_prefix_path.py
+
+# RUN head /etc/odoo/odoo.conf && /root/.bin/repo_manifest_gen_org_prefix_path.py $ODOO_PREFIX/addons /etc/odoo/odoo.conf /etc/odoo/odoo.conf && head /etc/odoo/odoo.conf
+
+# user odoo
+
+# ENTRYPOINT ["/entrypoint.sh"]
+# CMD ["odoo"]
diff --git a/docker/README.md b/docker/README.md
new file mode 100644
index 0000000..95af316
--- /dev/null
+++ b/docker/README.md
@@ -0,0 +1,114 @@
+# ERPLibre - Docker
+
+Those images are prepared to permit better portability and reproducibility of ERPLibre release.
+
+Due the the growing code of ERPLibre, it could also simplify development.
+
+NOTE: Those Dockerfiles themselves are in heavy development for now. Incompatibilities between releases are normal until the interface is stabilized.
+
+
+## Pre-requirements
+
+- Basic knowledge with Docker, Linux and bash
+- Latest Docker version
+
+## Files representations
+
+- Dockerfile.base: This Dockerfile represents the base Docker image layer reused by other child layers.
+- Dockerfile.dev: This Dockerfile is specialized in development.
+- Dockerfile.prod{pkg,src}: Dockerfile.prod.\* is a Docker image specialized for production systems. Dockerfile.prod.pkg reuses official Debian files from Odoo.com. Dockerfile.prod.src fetches the Odoo source code as the ERPLibre runtime.
+
+## Getting started
+
+Be sure to start daemon docker
+```bash
+systemctl start docker
+```
+
+### Building the docker images
+
+```bash
+cd docker
+docker build -f Dockerfile.base -t technolibre/erplibre-base:12.0 .
+docker build -f Dockerfile.prod.pkg -t technolibre/erplibre:12.0-pkg .
+```
+
+### Running ERPLibre using Docker-Compose
+
+Go at the root of this git project.
+```bash
+cd ERPLibre
+docker-compose -f docker-compose.yml up -d
+```
+
+### Diagnostic Docker-Compose
+
+Show docker-compose information
+```bash
+docker-compose ps
+docker-compose logs IMAGE_NAME
+```
+
+Show docker information
+```bash
+docker ps -a
+docker volume ls
+docker inspect DOCKER_NAME
+```
+
+Connect to a running docker
+```bash
+docker exec -ti DOCKER_NAME bash
+docker exec -u root -ti DOCKER_NAME bash
+```
+
+Commands for debugging
+```bash
+docker run -p 8069:8069 --entrypoint bash -ti DOCKER_NAME
+docker exec -ti DOCKER_NAME bash
+docker exec -u root -ti DOCKER_NAME bash
+docker run --name some-postgres -e POSTGRES_PASSWORD=mysecretpassword -e POSTGRES_USER=odoo -e POSTGRES_DB=postgres postgre
+
+export
+db_host = "host.docker.internal"
+
+docker stats erplibre_ERPLibre_1
+```
+
+### Cleaning
+
+Delete docker image
+```bash
+docker image prune
+```
+
+Delete volumes
+```bash
+docker-compose rm -v
+```
+
+Delete containers
+```bash
+docker rm $(docker ps -a | grep -v IMAGE | awk '{print $1}')
+```
+
+Delete volume
+```bash
+docker volume prune
+```
+
+# Change docker directory
+You can change the docker directory by editing file `/etc/docker/daemon.json`
+```json
+{
+ "data-root": "/home/docker"
+}
+```
+And restart docker service. You can delete or move all older locations of docker.
+
+# Update docker
+When building your docker with script
+> ./script/docker_build.sh
+
+You need to push your docker image and update your tag, like 1.0.1:
+> docker push technolibre/erplibre:1.0.1
diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh
new file mode 100755
index 0000000..bf1137f
--- /dev/null
+++ b/docker/entrypoint.sh
@@ -0,0 +1,87 @@
+#!/bin/bash
+
+set -e
+if [[ "$ENV" == "dev" ]] && [ ! -z ${CURRENT_UID} ]
+then
+ export HOME=$ODOO_PREFIX
+ cd $HOME
+
+ # As it's only possible to fetch git repos manifest from an git url, we create one using git-daemon.
+ git daemon --base-path=. --export-all --reuseaddr --informative-errors --verbose &
+ GIT_PID=$!
+ echo "my repo" $(git rev-parse --abbrev-ref HEAD)
+ repo init -u git://127.0.0.1:9418/ -b $(git rev-parse --abbrev-ref HEAD) -m default.dev.xml
+
+ repo sync
+
+ # After sync, terminate the git checkout. We don't need graceful kill as we don't do commit on the git repo during the operation.
+ kill -9 $GIT_PID
+
+ ls $HOME/odoo/odoo-bin
+ # $? give the posix return value of the last command. 0 == success
+ # then IS_ODOO_FILE_EXIST : 0 == YES
+ IS_ODOO_FILE_EXIST=$?
+
+ if [ "$IS_ODOO_FILE_EXIST" -ne "0" ]; then
+ echo "The file $HOME/odoo/odoo-bin doesnt exist. Verify entrypoint.sh";
+ exit 1;
+ fi
+
+ # Add the odoo bins code on $PATH
+ echo PATH=$HOME/odoo/:$PATH
+
+ # Configure an alias to use "odoo-bin" as "odoo".
+ alias odoo=odoo-bin
+
+ repo_manifest_gen_org_prefix_path.py $ODOO_PREFIX/addons $ODOO_RC $ODOO_PREFIX/odoo/odoo.conf && head $ODOO_PREFIX/odoo/odoo.conf
+ export ODOO_RC=$ODOO_PREFIX/odoo/odoo.conf
+
+elif [[ "$ENV" == "dev" ]] && [ -z ${CURRENT_UID} ]
+then
+ echo 'Please run as follows : CURRENT_UID=$(id -u):$(id -g) docker-compose up'
+ exit 1
+fi
+
+# set the postgres database host, port, user and password according to the environment
+# and pass them as arguments to the odoo process if not present in the config file
+: ${HOST:=${DB_PORT_5432_TCP_ADDR:='db'}}
+: ${PORT:=${DB_PORT_5432_TCP_PORT:=5432}}
+: ${USER:=${DB_ENV_POSTGRES_USER:=${POSTGRES_USER:='odoo'}}}
+: ${PASSWORD:=${DB_ENV_POSTGRES_PASSWORD:=${POSTGRES_PASSWORD:='odoo'}}}
+
+DB_ARGS=()
+function check_config() {
+ param="$1"
+ value="$2"
+ if grep -q -E "^\s*\b${param}\b\s*=" "$ODOO_RC" ; then
+ value=$(grep -E "^\s*\b${param}\b\s*=" "$ODOO_RC" |cut -d " " -f3|sed 's/["\n\r]//g')
+ fi;
+ DB_ARGS+=("--${param}")
+ DB_ARGS+=("${value}")
+}
+check_config "db_host" "$HOST"
+check_config "db_port" "$PORT"
+check_config "db_user" "$USER"
+check_config "db_password" "$PASSWORD"
+
+case "$1" in
+ -- | odoo)
+ shift
+ if [[ "$1" == "scaffold" ]] ; then
+ exec odoo "$@" || exec odoo-bin "$@"
+ else
+ cd $ODOO_PREFIX
+ ./docker/wait-for-psql.py ${DB_ARGS[@]} --timeout=30
+ exec ./.venv/bin/python $ODOO_EXEC_BIN "$@" "${DB_ARGS[@]}" -c /etc/odoo/odoo.conf
+ fi
+ ;;
+ -*)
+ cd $ODOO_PREFIX
+ ./docker/wait-for-psql.py ${DB_ARGS[@]} --timeout=30
+ exec ./.venv/bin/python $ODOO_EXEC_BIN "$@" "${DB_ARGS[@]}" -c /etc/odoo/odoo.conf
+ ;;
+ *)
+ exec "$@"
+esac
+
+exit 1
diff --git a/docker/main/Dockerfile b/docker/main/Dockerfile
new file mode 100644
index 0000000..0dda3be
--- /dev/null
+++ b/docker/main/Dockerfile
@@ -0,0 +1,32 @@
+FROM technolibre/erplibre-base:12.0
+
+ENV REPO_MANIFEST_URL https://github.com/agileops/ERPLibre.git
+RUN cat /etc/os-release
+
+ENV ADDONS_BASE_DIR /odoo
+
+USER root
+
+RUN mkdir ~/.ssh/ && echo "StrictHostKeyChecking no" >> ~/.ssh/config && apt update && apt install ssh-client git -y --no-install-recommends && \
+ rm -rf /var/lib/apt/lists/*
+
+RUN cd ; mkdir -p .bin/ && \
+ git config --global color.ui false && \
+ git config --global user.email "foo@bar.io" && \
+ git config --global user.name "Foo Bar" && \
+ curl https://storage.googleapis.com/git-repo-downloads/repo > ~/.bin/repo && \
+ chmod +x ~/.bin/repo && sed -i '1 s/python$/python3/' ~/.bin/repo && head ~/.bin/repo && \
+ export PATH="${HOME}/.bin:${PATH}" && \
+ mkdir -p $ADDONS_BASE_DIR && cd $ADDONS_BASE_DIR && \
+ repo init -u $REPO_MANIFEST_URL -b 12.0_repo && \
+ repo sync -j 4 -c
+
+ADD repo_manifest_gen_org_prefix_path.py /root/.bin/ RUN chmod +x
+~/.bin/repo_manifest_gen_org_prefix_path.py
+
+RUN head /etc/odoo/odoo.conf && /root/.bin/repo_manifest_gen_org_prefix_path.py $ADDONS_BASE_DIR/addons /etc/odoo/odoo.conf /etc/odoo/odoo.conf && head /etc/odoo/odoo.conf
+
+user odoo
+
+ENTRYPOINT ["/entrypoint.sh"]
+CMD ["odoo"]
diff --git a/docker/odoo.conf b/docker/odoo.conf
new file mode 100644
index 0000000..b9b9c4e
--- /dev/null
+++ b/docker/odoo.conf
@@ -0,0 +1,523 @@
+[options]
+
+#
+# WARNING:
+# If you use the Odoo Database utility to change the master password be aware
+# that the formatting of this file WILL be LOST! A copy of this file named
+# /etc/odoo/openerp-server.conf.template has been made in case this happens
+# Note that the copy does not have any first boot changes
+#-----------------------------------------------------------------------------
+# Odoo Server Config File - TurnKey Linux
+# ( /etc/odoo/openerp-server.conf )
+#
+# Great pain has been taken to organize this file, and include comments for
+# each. As with all open source software this file is a work in progress. If
+# you see something that is wrong or needs to be updated, submit and issue
+# on TurnKey's GIT Hub issue tracker! Or better yet, fork the repo with this
+# file and submit a pull request!
+#
+# Information about these settings where taken from openerp-server --help
+# and from https://www.odoo.com/documentation/8.0/reference/cmdline.html
+#
+#-----------------------------------------------------------------------------
+# Index:
+# Database Settings
+# Logs Settings
+# Service Settings
+# Email Settings
+# Server Options
+# Tuning Adjustments
+# Testing and Demo Settings
+#-----------------------------------------------------------------------------
+
+
+
+#HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
+# Database Settings
+#HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
+
+#-----------------------------------------------------------------------------
+# Specify the database host (default localhost).
+#-----------------------------------------------------------------------------
+#db_host = localhost
+
+#-----------------------------------------------------------------------------
+# Specify the database port (default None).
+#-----------------------------------------------------------------------------
+#db_port = 5432
+
+#-----------------------------------------------------------------------------
+# Specify the database user name (default None).
+#-----------------------------------------------------------------------------
+#db_user = odoo
+
+#-----------------------------------------------------------------------------
+# Specify the database password for db_user (default None)
+#-----------------------------------------------------------------------------
+#db_password = 00aa9df39b0c99ac3d1d8412d2917175
+
+#-----------------------------------------------------------------------------
+# Specify the database name.
+#-----------------------------------------------------------------------------
+#db_name = False
+
+#-----------------------------------------------------------------------------
+# DataError: new encoding (UTF8) is incompatible with the encoding of the
+# template database (SQL_ASCII) HINT: Use the same encoding as in the template
+# database, or use template0 as template.
+#-----------------------------------------------------------------------------
+# db_template = template0
+
+#-----------------------------------------------------------------------------
+# Master Database password
+# This is set at first boot, and can be set from within Odoo
+#-----------------------------------------------------------------------------
+#admin_passwd = 12357
+
+#-----------------------------------------------------------------------------
+# specify the the maximum number of physical connections to posgresql
+#-----------------------------------------------------------------------------
+#db_maxconn = 64
+
+#-----------------------------------------------------------------------------
+# Filter listed database REGEXP
+#-----------------------------------------------------------------------------
+#dbfilter = .*
+
+
+
+#HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
+# Logs Settings
+#HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
+#
+#
+# I found information from Odoo on logging was not very clear. So I complied
+# this helpful list and info about Odoo logging.
+#
+# Information was gleaned from the following sites:
+# (The URLs are broken up to fit them in the file)
+# - http://www.mindissoftware.com
+# /2014/09/07/Odoo-logging-configuration-usage-implementation/
+# - https://www.odoo.com/
+# /forum/help-1/question
+# /what-is-the-full-list-of-command-line-options-for-odoo-59139
+# - https://www.odoo.com/documentation/8.0/reference/cmdline.html
+#
+# Odoo uses the Python standard logging library. However, it uses a special
+# configuration syntax to configure logging levels for its modules.
+#
+# It's helpful to know what each level type means, so below is quick list:
+#
+# Level meanings:
+# debug: Debug message for debugging only.
+# info: Information message to report important modular event.
+# warning: Warning message to report minor issues.
+# error: Error message to report failed operations.
+# critical: A critical message -- so critical that the module cannot work
+#
+#
+# log_level:
+# any value in the list below. Odoo changed the log_level meaning
+# here because these level values are mapped to a set of predefined
+# 'module:log_level' pairs. These pairs are listed next to the log-level.
+# You could get the same result by using the log_handler option
+#
+#
+# LOG LEVEL / log_handler: module:log_level
+# ----------------------------------------------------------------------------
+# info / [':INFO']
+# critical / ['openerp:CRITICAL', 'werkzeug:CRITICAL']
+# error / ['openerp:ERROR', 'werkzeug:ERROR']
+# warn / ['openerp:WARNING', 'werkzeug:WARNING']
+# debug / ['openerp:DEBUG']
+# debug_sql / ['openerp.sql_db:DEBUG']
+# debug_rpc / ['openerp:DEBUG','openerp.http.rpc.request:DEBUG']
+# debug_rpc_answer / ['openerp:DEBUG','openerp.http.rpc.request:DEBUG',
+# 'openerp.http.rpc.response:DEBUG']
+#
+# End of Logging Info
+# ----------------------------------------------------------------------------
+
+#-----------------------------------------------------------------------------
+# The log filename. If not set, use stdout.
+#-----------------------------------------------------------------------------
+; logfile = /var/log/odoo/openerp-server.log
+
+#-----------------------------------------------------------------------------
+# True/False. If True, create a daily log file and keep 30 files.
+#-----------------------------------------------------------------------------
+; logrotate = True
+
+#-----------------------------------------------------------------------------
+# Ture/False. If True, also write log to 'ir_logging' table in database
+#-----------------------------------------------------------------------------
+; log-db = True
+
+#-----------------------------------------------------------------------------
+# True/False logs to the system's event logger: syslog
+#-----------------------------------------------------------------------------
+; syslog = False
+
+#-----------------------------------------------------------------------------
+# Log level - One of the following:
+# info, debug_rpc, warn, test, critical, debug_sql, error, debug,
+# debug_rpc_answer
+#-----------------------------------------------------------------------------
+; log-level = warn
+
+#-----------------------------------------------------------------------------
+# log_handler - can be a list of 'module:log_level' pairs.
+# The default value is ':INFO' -- it means the default logging level
+# is 'INFO' for all modules.
+#-----------------------------------------------------------------------------
+# log_handler =
+
+
+
+
+#HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
+# Service Settings
+#HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
+
+#-----------------------------------------------------------------------------
+# The IP address on which the server will bind.
+# If empty, it will bind on all interfaces (default empty).
+#-----------------------------------------------------------------------------
+; interface = localhost
+
+#-----------------------------------------------------------------------------
+# The TCP port on which the server will listen (default 8069).
+#-----------------------------------------------------------------------------
+port = 8069
+
+#-----------------------------------------------------------------------------
+# Launch server over https instead of http (default False).
+#-----------------------------------------------------------------------------
+; secure = False
+
+#-----------------------------------------------------------------------------
+# Set to True if you are deploying your App behind a proxy
+# e.g. Apache using mod_proxy. --proxy_mode added, using Werkzeug ProxyFix class
+#-----------------------------------------------------------------------------
+#proxy_mode = True
+
+#-----------------------------------------------------------------------------
+# Specify the addons_path folders ordered by priority
+# addons_path=/first/path/,/second/path/
+#-----------------------------------------------------------------------------
+addons_path = /opt/openerp/odoo/addons,/home/myaddons
+
+#-----------------------------------------------------------------------------
+# The file where the server pid will be stored (default False).
+# We are letting the init script create the pid
+#-----------------------------------------------------------------------------
+# pidfile = False
+
+#-----------------------------------------------------------------------------
+# specify reference timezone for the server (e.g. Europe/Brussels)
+#-----------------------------------------------------------------------------
+; timezone = False
+
+#-----------------------------------------------------------------------------
+# specify the certificate file for the SSL connection
+#-----------------------------------------------------------------------------
+; secure_cert_file = server.cert
+
+#-----------------------------------------------------------------------------
+# specify the private key file for the SSL connection
+#-----------------------------------------------------------------------------
+; secure_pkey_file = server.pkey
+
+#-----------------------------------------------------------------------------
+# XML-RPC Secure Configuration (disabled if ssl is unavailable):
+# xmlrpcs - Set to False to disable the XML-RPC Secure protocol
+# xmlrpcs_interface - Specify the TCP IP address for the XML-RPC Secure
+# protocol. The empty string binds to all interfaces.
+# xmlrpcs_port - Specify the TCP port for the XML-RPC Secure protocol
+#-----------------------------------------------------------------------------
+; xmlrpcs = True
+#xmlrpcs_interface = 127.0.0.1
+xmlrpcs_port = 8071
+
+#-----------------------------------------------------------------------------
+# XML-RPC Configuration:
+# xmlrpc - Set to False to disable the XML-RPC protocol
+# xmlrpc_interface - Specify the TCP IP address for the XML-RPC
+# protocol. The empty string binds to all interfaces.
+# xmlrpc_port - Specify the TCP port for the XML-RPC protocol
+#-----------------------------------------------------------------------------
+; xmlrpc = True
+#xmlrpc_interface = 127.0.0.1
+xmlrpc_port = 8069
+
+#-----------------------------------------------------------------------------
+# Long polling port:
+# TCP port for long-polling connections in multiprocessing or gevent mode,
+# defaults to 8072. Not used in default (threaded) mode.
+#-----------------------------------------------------------------------------
+longpolling_port = 8072
+
+#-----------------------------------------------------------------------------
+# Use this for big data importation, if it crashes you will be able to continue
+# at the current state. Provide a filename to store intermediate importation
+# states.
+#-----------------------------------------------------------------------------
+; import_partial =
+
+#-----------------------------------------------------------------------------
+# Use the unaccent function provided by the database when available
+#-----------------------------------------------------------------------------
+; unaccent = False
+
+#-----------------------------------------------------------------------------
+# specify modules to export. Use in combination with --i18n-export
+#-----------------------------------------------------------------------------
+; translate_modules = ['all']
+
+#-----------------------------------------------------------------------------
+# Comma-separated list of server-wide modules, default=web
+#-----------------------------------------------------------------------------
+; server_wide_modules = None
+
+
+
+#HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
+# Email Settings
+#HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
+
+#-----------------------------------------------------------------------------
+# Specify the SMTP server for sending email (default localhost).
+#-----------------------------------------------------------------------------
+; smtp_server = localhost
+
+#-----------------------------------------------------------------------------
+# Specify the SMTP user for sending email (default False).
+#-----------------------------------------------------------------------------
+; smtp_user = False
+
+#-----------------------------------------------------------------------------
+# Specify the SMTP password for sending email (default False).
+#-----------------------------------------------------------------------------
+; smtp_password = False
+
+#-----------------------------------------------------------------------------
+# if True, SMTP connections will be encrypted with SSL (STARTTLS)
+#-----------------------------------------------------------------------------
+; smtp_ssl = False
+
+#-----------------------------------------------------------------------------
+# Specify the SMTP email address for sending email
+#-----------------------------------------------------------------------------
+; email_from = "TKL-Odoo-Server@example.com"
+
+#-----------------------------------------------------------------------------
+# Specify the SMTP port
+#-----------------------------------------------------------------------------
+; smtp_port = 25
+
+
+
+#HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
+# Tuning Options
+#HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
+#-----------------------------------------------------------------------------
+# A word on tuning your Odoo Server
+#-----------------------------------------------------------------------------
+#
+# A lot of time has gone in to testing this TKL appliance, and one thing we
+# learned while testing was tuning. For all the why we chose these numbers you
+# can take a look at he issues on GitHub (links at the botton of this article)
+#
+# Most of this text here was taken from the Memory Matrix Discussion
+# https://github.com/DocCyblade/tkl-odoo/issues/49#issuecomment-148881166
+#
+# It is important to note that you can run Odoo in threaded mode by setting
+# the workers option to 0 however there are some modules that won't work
+# and you loose fine grain control of resource management.
+#
+#-----------------------------------------------------------------------------
+#
+# the --workers is how many new process will be started to perform work or
+# (answer requests) The workers have limits upon them set by the limit_xxxxx
+# options here in the config file.
+#
+# The "limit_memory_soft" limit is the amount of ram that when a process
+# goes over this limit after it is done with the request it is terminated
+# and the memory it was using is freed. This amount goes for each process
+#
+# The hard limit is the amount of ram that if the process goes over it,
+# it WILL terminate right then. (I don't think this is really correct
+# because of the PDF issue we had and set this to 1.3 GB and never
+# saw a process take this much. but if its below 1.3GB PDF are not created)
+#
+# The one we need to pay attention to is the limit_memory_soft.
+# As these workers will stay alive and hold on to memory until that limit
+# is reached. So if you have 5 workers and the soft limit is 256MB you could
+# end up with 5 workers each taking 256MB that's 1.25GB of RAM that could
+# be taken up. If you only had 1GB of ram you may need to dial back your
+# workers or your soft limit.
+#
+# It's a balancing act of sorts, I am also not sure if keeping the
+# workers at say 350 or 400 if there is some caching effect. Not sure
+# why it's holding on to the memory.
+#
+#-----------------------------------------------------------------------------
+#
+# Hardware Matrix for recommended values:
+# (Note these are for REAL hardware, Virtual Hardware has it's own
+# issues that can arise with too many guest on a host with too many
+# CPU cores etc, so remember that when looking at the chart below)
+# (One other note that when I tested these, I did use VMware but
+# no other VMs where competing for resources)
+# (One last note, really. These numbers are to show the relationship
+# between the config settings and hardware. We also assume you are running
+# the database server on the same server. I know at some point in the
+# higher numbers that this would not be the case. These are not numbers
+# set in stone nor numbers gotten from Odoo. These are numbers I have
+# come up with from the testing I have done. Real world examples if you
+# have them would be great and these numbers can and should be updated!
+#
+# Heading | Description
+# ------------------ | ---------------------------------------------------------
+# CPUs | Number of CPU Cores not threads
+# Physical | Physical memory, not virtual or swap
+# workers | Number of workers specified in config file (workers = x)
+# cron | Number of workers for cron jobs (max_cron_threads = xx)
+# Mem Per | Memory in MB that is the max memory for request per worker
+# Max Mem | Maximum amount that can be used by all workers
+# limit_memory_soft | Number in bytes that you will use for this setting
+#
+# Note: Max Memory if notice is less than total memory this is on purpose. As
+# workers process requests they can grow beyond the Mem Per limit so a
+# server under heavy load could go past this amount. This is why there
+# is "head room" built in.
+#
+# CPUs | Physical | workers | cron | Mem Per | Max Mem | limit_memory_soft
+# ---- | -------- | ------- | ---- | ------- | ------- | -----------------------
+# ANY | =< 256MB | NR | NR | NR | NR | NR
+# 1 | 512MB | 0 | N/A | N/A | N/A | N/A
+# 1 | 512MB | 1 | 1 | 177MB | 354MB | 185127901
+# 1 | 1GB | 2 | 1 | 244MB | 732MB | 255652815
+# 1 | 2GB | 2 | 1 | 506MB | 1518MB | 530242876
+# 2 | 1GB | 3 | 1 | 183MB | 732MB | 191739611
+# 2 | 2GB | 5 | 2 | 217MB | 1519MB | 227246947
+# 2 | 4GB | 5 | 2 | 450MB | 3150MB | 471974428
+# 4 | 2GB | 5 | 2 | 217MB | 1519MB | 227246947
+# 4 | 4GB | 9 | 2 | 286MB | 3146MB | 300347363
+# 4 | 8GB | 9 | 3 | 546MB | 6552MB | 572662306
+# 4 | 16GB | 9 | 3 | 1187MB | 14244MB | 1244918057
+#
+#
+#-----------------------------------------------------------------------------
+#
+# Calculations on how we got the above chart and other info can be found
+#
+# Memory Matrix Discussion
+# https://github.com/DocCyblade/tkl-odoo/issues/49
+#
+# Shakedown Testing Discussions
+# https://github.com/DocCyblade/tkl-odoo/issues/52
+# https://github.com/DocCyblade/tkl-odoo/issues/53
+# https://github.com/DocCyblade/tkl-odoo/issues/54
+# https://github.com/DocCyblade/tkl-odoo/issues/55
+#
+#-----------------------------------------------------------------------------
+
+
+
+
+#-----------------------------------------------------------------------------
+# Specify the number of workers, 0 disable prefork mode.
+# if count is not 0 , enables multiprocessing and sets up the
+# specified number of HTTP workers (sub-processes processing HTTP and RPC
+# requests). TKL Default is 0
+#
+# (See chart above for recommended values)
+#-----------------------------------------------------------------------------
+workers = 2
+
+#-----------------------------------------------------------------------------
+# number of workers dedicated to cron jobs. Defaults to 2. The workers are
+# threads in multithreading mode and processes in multiprocessing mode.
+#-----------------------------------------------------------------------------
+max_cron_threads = 1
+
+#-----------------------------------------------------------------------------
+# Prevents the worker from using more than CPU seconds for each
+# request. If the limit is exceeded, the worker is killed
+#-----------------------------------------------------------------------------
+limit_time_cpu = 600
+
+#-----------------------------------------------------------------------------
+# Prevents the worker from taking longer than seconds to process a
+# request. If the limit is exceeded, the worker is killed.
+#-----------------------------------------------------------------------------
+limit_time_real = 900
+
+#-----------------------------------------------------------------------------
+# Maximum allowed virtual memory per worker. If the limit is exceeded, the
+# worker is killed and recycled at the end of the current request.
+#
+# (See chart above for recommended values)
+#-----------------------------------------------------------------------------
+limit_memory_soft = 5368709120
+
+#-----------------------------------------------------------------------------
+# Hard limit on virtual memory, any worker exceeding the limit will be
+# immediately killed without waiting for the end of the current request
+# processing.
+#
+# Not sure of the reason but if this is set lower that 1.3GB then print jobs
+# using PDF does not work. We are unsure why but this was the lowest amount
+# for it to work.
+#-----------------------------------------------------------------------------
+limit_memory_hard = 6710886400
+
+#-----------------------------------------------------------------------------
+# Number of requests a worker will process before being recycled and restarted.
+#-----------------------------------------------------------------------------
+limit_request = 8196
+
+#-----------------------------------------------------------------------------
+# Force a limit on the maximum number of records kept in the virtual osv_memory
+# tables. The default is False, which means no count-based limit.
+#-----------------------------------------------------------------------------
+; osv_memory_count_limit = False
+
+#-----------------------------------------------------------------------------
+# Force a limit on the maximum age of records kept in the virtual osv_memory
+# tables. This is a decimal value expressed in hours, and the default is 1 hour.
+#-----------------------------------------------------------------------------
+; osv_memory_age_limit = 1.0
+
+
+
+#HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
+# Testing and Demo Settings
+#HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
+
+#-----------------------------------------------------------------------------
+# Enable YAML and unit tests.
+#-----------------------------------------------------------------------------
+; test_enable = False
+
+#-----------------------------------------------------------------------------
+# Launch a python or YML test file.
+#-----------------------------------------------------------------------------
+; test_file = False
+
+#-----------------------------------------------------------------------------
+# If set, will save sample of all reports in this directory.
+#-----------------------------------------------------------------------------
+; test_report_directory = False
+
+#-----------------------------------------------------------------------------
+# Commit database changes performed by YAML or XML tests.
+#-----------------------------------------------------------------------------
+; test_commit = False
+
+#-----------------------------------------------------------------------------
+# disable loading demo data for modules to be installed (comma-separated, use
+# "all" for all modules). Default is none
+#-----------------------------------------------------------------------------
+; without_demo = all
\ No newline at end of file
diff --git a/docker/pyenv-version.txt b/docker/pyenv-version.txt
new file mode 100644
index 0000000..b3257b5
--- /dev/null
+++ b/docker/pyenv-version.txt
@@ -0,0 +1 @@
+v1.2.20
\ No newline at end of file
diff --git a/docker/python-versions.txt b/docker/python-versions.txt
new file mode 100644
index 0000000..cbbb5ee
--- /dev/null
+++ b/docker/python-versions.txt
@@ -0,0 +1 @@
+3.7.7
\ No newline at end of file
diff --git a/docker/repo_manifest_gen_org_prefix_path.py b/docker/repo_manifest_gen_org_prefix_path.py
new file mode 100755
index 0000000..3456268
--- /dev/null
+++ b/docker/repo_manifest_gen_org_prefix_path.py
@@ -0,0 +1,40 @@
+#!./.venv/bin/python
+
+import argparse
+
+from os import listdir
+from os.path import isdir, join, abspath
+
+import configparser
+
+parser = argparse.ArgumentParser(prog='Configure base dir for all addons')
+
+parser.add_argument("addonsBaseDir", help="Path where addons are cloned.")
+parser.add_argument("srcConfigPath",
+ help="Path where we retrieve source config file to adapt with new "
+ "addons path.")
+parser.add_argument("dstConfigPath", help="Path to save adapted configuration.")
+
+args = parser.parse_args()
+addonsBaseDir = args.addonsBaseDir
+srcConfigPath = args.srcConfigPath
+dstConfigPath = args.dstConfigPath
+
+addonsDirs = [abspath(join(addonsBaseDir, f)) for f in listdir(addonsBaseDir) if
+ isdir(join(addonsBaseDir, f))]
+
+# addonsDirs.insert(0, "/usr/lib/python3/dist-packages/odoo/addons/")
+addonsDirs.insert(0, "/ERPLibre/odoo/addons/")
+
+config = configparser.ConfigParser()
+
+config.read(srcConfigPath)
+
+separator = ","
+
+config.set('options', 'addons_path', separator.join(addonsDirs))
+
+print(config.get('options', 'addons_path'))
+
+with open(dstConfigPath, 'w') as configfile:
+ config.write(configfile)
diff --git a/docker/wait-for-psql.py b/docker/wait-for-psql.py
new file mode 100755
index 0000000..d42d263
--- /dev/null
+++ b/docker/wait-for-psql.py
@@ -0,0 +1,38 @@
+#!./.venv/bin/python
+import argparse
+import psycopg2
+import sys
+import time
+
+if __name__ == '__main__':
+ arg_parser = argparse.ArgumentParser()
+ arg_parser.add_argument('--db_host', required=True)
+ arg_parser.add_argument('--db_port', required=True)
+ arg_parser.add_argument('--db_user', required=True)
+ arg_parser.add_argument('--db_password', required=True)
+ arg_parser.add_argument('--db_name', required=False, default="postgres")
+ arg_parser.add_argument('--timeout', type=int, default=10)
+
+ args = arg_parser.parse_args()
+
+ start_time = time.time()
+ print("Try connection to postgres...")
+
+ connected = False
+ error = ''
+ while ((time.time() - start_time) < args.timeout) or connected is True:
+ try:
+ conn = psycopg2.connect(user=args.db_user, host=args.db_host,
+ port=args.db_port, password=args.db_password,
+ dbname=args.db_name)
+ break
+ except psycopg2.OperationalError as e:
+ error = e
+ print(".")
+ time.sleep(1)
+ else:
+ connected = True
+ conn.close()
+ if error:
+ print("Database connection failure: %s" % error, file=sys.stderr)
+ sys.exit(1)
diff --git a/env_var.sh b/env_var.sh
index 072a4de..1979a9e 100755
--- a/env_var.sh
+++ b/env_var.sh
@@ -1,5 +1,11 @@
#!/usr/bin/env bash
+ERPLIBRE_VERSION="1.1.0"
+ERPLIBRE_DOCKER_BASE="technolibre/erplibre-base"
+ERPLIBRE_DOCKER_PROD="technolibre/erplibre"
+ERPLIBRE_DOCKER_BASE_VERSION="${ERPLIBRE_DOCKER_BASE}:${ERPLIBRE_VERSION}"
+ERPLIBRE_DOCKER_PROD_VERSION="${ERPLIBRE_DOCKER_PROD}:${ERPLIBRE_VERSION}"
+
EL_USER="erplibre"
EL_HOME="/${EL_USER}"
EL_HOME_ERPLIBRE="${EL_HOME}/erplibre"
diff --git a/ignore_requirements.txt b/ignore_requirements.txt
new file mode 100644
index 0000000..54b1efa
--- /dev/null
+++ b/ignore_requirements.txt
@@ -0,0 +1,14 @@
+mercurial
+facturx
+stdnum
+u2flib_server
+dateutil
+csv
+chess
+git
+voicent
+swiftclient
+keystoneclient
+xlsxwriter
+ldap
+pythonjsonlogger
diff --git a/manifest/default.dev.xml b/manifest/default.dev.xml
index c4493a2..1138320 100644
--- a/manifest/default.dev.xml
+++ b/manifest/default.dev.xml
@@ -1,28 +1,40 @@
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
-
-
+
+
-
+
@@ -32,25 +44,39 @@
+
+
+
+
+
-
+
+
+
+
-
+
+
+
+
+
+
+
@@ -60,44 +86,61 @@
-
+
-
-
+
+
+
-
-
-
+
+
+
+
-
+
+
-
+
+
+
+
+
+
+
+
-
-
+
+
+
-
+
+
+
+
+
+
+
diff --git a/poetry.lock b/poetry.lock
new file mode 100644
index 0000000..7f5e4c7
--- /dev/null
+++ b/poetry.lock
@@ -0,0 +1,3906 @@
+[[package]]
+category = "main"
+description = "A lightweight, transparent syntax for REST clients"
+name = "agithub"
+optional = false
+python-versions = "*"
+version = "2.2.2"
+
+[[package]]
+category = "main"
+description = "A configurable sidebar-enabled Sphinx theme"
+name = "alabaster"
+optional = false
+python-versions = "*"
+version = "0.7.12"
+
+[[package]]
+category = "main"
+description = "Altair: A declarative statistical visualization library for Python."
+name = "altair"
+optional = false
+python-versions = ">=3.6"
+version = "4.1.0"
+
+[package.dependencies]
+entrypoints = "*"
+jinja2 = "*"
+jsonschema = "*"
+numpy = "*"
+pandas = ">=0.18"
+toolz = "*"
+
+[package.extras]
+dev = ["black", "docutils", "ipython", "flake8", "pytest", "sphinx", "m2r", "vega-datasets", "recommonmark"]
+
+[[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.4"
+
+[[package]]
+category = "main"
+description = "Python command-line parsing library"
+name = "argparse"
+optional = false
+python-versions = "*"
+version = "1.4.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.4.0"
+
+[[package]]
+category = "main"
+description = "Tools for computing asset risk with respect to goals."
+name = "asterisk"
+optional = false
+python-versions = "*"
+version = "0.0.8"
+
+[package.dependencies]
+requests = "*"
+
+[[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 = "Internationalization utilities"
+name = "babel"
+optional = false
+python-versions = "*"
+version = "2.3.4"
+
+[package.dependencies]
+pytz = ">=0a"
+
+[[package]]
+category = "main"
+description = "Modern password hashing for your software and your servers"
+name = "bcrypt"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "3.1.7"
+
+[package.dependencies]
+cffi = ">=1.1"
+six = ">=1.4.1"
+
+[package.extras]
+tests = ["pytest (>=3.2.1,<3.3.0 || >3.3.0)"]
+
+[[package]]
+category = "main"
+description = "Screen-scraping library"
+name = "beautifulsoup4"
+optional = false
+python-versions = "*"
+version = "4.9.1"
+
+[package.dependencies]
+soupsieve = [">1.2", "<2.0"]
+
+[package.extras]
+html5lib = ["html5lib"]
+lxml = ["lxml"]
+
+[[package]]
+category = "main"
+description = "Interactive plots and applications in the browser from Python"
+name = "bokeh"
+optional = false
+python-versions = "*"
+version = "1.1.0"
+
+[package.dependencies]
+Jinja2 = ">=2.7"
+PyYAML = ">=3.10"
+numpy = ">=1.7.1"
+packaging = ">=16.8"
+pillow = ">=4.0"
+python-dateutil = ">=2.1"
+six = ">=1.5.2"
+tornado = ">=4.3"
+
+[[package]]
+category = "main"
+description = "Amazon Web Services Library"
+name = "boto"
+optional = false
+python-versions = "*"
+version = "2.49.0"
+
+[[package]]
+category = "main"
+description = "The AWS SDK for Python"
+name = "boto3"
+optional = false
+python-versions = "*"
+version = "1.9.102"
+
+[package.dependencies]
+botocore = ">=1.12.102,<1.13.0"
+jmespath = ">=0.7.1,<1.0.0"
+s3transfer = ">=0.2.0,<0.3.0"
+
+[[package]]
+category = "main"
+description = "Low-level, data-driven core of boto 3."
+name = "botocore"
+optional = false
+python-versions = "*"
+version = "1.12.253"
+
+[package.dependencies]
+docutils = ">=0.10,<0.16"
+jmespath = ">=0.7.1,<1.0.0"
+
+[package.dependencies.python-dateutil]
+python = ">=2.7"
+version = ">=2.1,<3.0.0"
+
+[package.dependencies.urllib3]
+python = ">=3.4"
+version = ">=1.20,<1.26"
+
+[[package]]
+category = "main"
+description = "A decorator for caching properties in classes."
+name = "cached-property"
+optional = false
+python-versions = "*"
+version = "1.5.1"
+
+[[package]]
+category = "main"
+description = "Extensible memoizing collections and decorators"
+name = "cachetools"
+optional = false
+python-versions = "~=3.5"
+version = "4.1.1"
+
+[[package]]
+category = "main"
+description = "Lightweight, extensible schema and data validation tool for Python dictionaries."
+name = "cerberus"
+optional = false
+python-versions = ">=2.7"
+version = "1.3.2"
+
+[package.dependencies]
+setuptools = "*"
+
+[[package]]
+category = "main"
+description = "Python package for providing Mozilla's CA Bundle."
+name = "certifi"
+optional = false
+python-versions = "*"
+version = "2020.6.20"
+
+[[package]]
+category = "main"
+description = "Foreign Function Interface for Python calling C code."
+name = "cffi"
+optional = false
+python-versions = "*"
+version = "1.14.1"
+
+[package.dependencies]
+pycparser = "*"
+
+[[package]]
+category = "main"
+description = "Universal encoding detector for Python 2 and 3"
+name = "chardet"
+optional = false
+python-versions = "*"
+version = "3.0.4"
+
+[[package]]
+category = "main"
+description = "Cross-platform colored terminal text."
+marker = "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 = "Colored terminal output for Python's logging module"
+name = "coloredlogs"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+version = "14.0"
+
+[package.dependencies]
+humanfriendly = ">=7.1"
+
+[package.extras]
+cron = ["capturer (>=2.4)"]
+
+[[package]]
+category = "main"
+description = "Compressed Rich Text Format (RTF) compression and decompression package"
+name = "compressed-rtf"
+optional = false
+python-versions = "*"
+version = "1.0.6"
+
+[[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.6.1"
+
+[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 = "main"
+description = "cssselect parses CSS3 Selectors and translates them to XPath 1.0"
+name = "cssselect"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "1.1.0"
+
+[[package]]
+category = "main"
+description = "A CSS Cascading Style Sheets library for Python"
+name = "cssutils"
+optional = false
+python-versions = "*"
+version = "1.0.2"
+
+[[package]]
+category = "main"
+description = "Composable style cycles"
+name = "cycler"
+optional = false
+python-versions = "*"
+version = "0.10.0"
+
+[package.dependencies]
+six = "*"
+
+[[package]]
+category = "main"
+description = "The Cython compiler for writing C extensions for the Python language."
+name = "cython"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+version = "0.29.21"
+
+[[package]]
+category = "main"
+description = "Date parsing library designed to parse dates from HTML pages"
+name = "dateparser"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+version = "0.7.6"
+
+[package.dependencies]
+python-dateutil = "*"
+pytz = "*"
+regex = "!=2019.02.19"
+tzlocal = "*"
+
+[[package]]
+category = "main"
+description = "Data-Driven/Decorated Tests"
+name = "ddt"
+optional = false
+python-versions = "*"
+version = "1.2.0"
+
+[[package]]
+category = "main"
+description = "A collection of Python deprecation patterns and strategies that help you collect your technical debt in a non-destructive manner."
+name = "debtcollector"
+optional = false
+python-versions = ">=3.6"
+version = "2.2.0"
+
+[package.dependencies]
+pbr = ">=2.0.0,<2.1.0 || >2.1.0"
+six = ">=1.10.0"
+wrapt = ">=1.7.0"
+
+[[package]]
+category = "main"
+description = "Better living through Python with decorators"
+name = "decorator"
+optional = false
+python-versions = "*"
+version = "4.0.10"
+
+[[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 = "main"
+description = "library for manipulating datetimes with ease and clarity"
+name = "delorean"
+optional = false
+python-versions = "*"
+version = "1.0.0"
+
+[package.dependencies]
+babel = ">=2.1.1"
+humanize = ">=0.5.1"
+python-dateutil = ">=2.4.2"
+pytz = ">=2015.7"
+tzlocal = ">=1.2"
+
+[[package]]
+category = "main"
+description = "encoder, decoder, and lint/validator for JSON (JavaScript Object Notation) compliant with RFC 7159"
+name = "demjson"
+optional = false
+python-versions = "*"
+version = "2.2.4"
+
+[[package]]
+category = "main"
+description = "DNS toolkit"
+name = "dnspython"
+optional = false
+python-versions = ">=3.6"
+version = "2.0.0"
+
+[package.extras]
+curio = ["curio (>=1.2)", "sniffio (>=1.1)"]
+dnssec = ["cryptography (>=2.6)"]
+doh = ["requests", "requests-toolbelt"]
+idna = ["idna (>=2.1)"]
+trio = ["trio (>=0.14.0)", "sniffio (>=1.1)"]
+
+[[package]]
+category = "main"
+description = "Docutils -- Python Documentation Utilities"
+name = "docutils"
+optional = false
+python-versions = "*"
+version = "0.12"
+
+[[package]]
+category = "main"
+description = "eBay SDK for Python"
+name = "ebaysdk"
+optional = false
+python-versions = "*"
+version = "2.1.5"
+
+[package.dependencies]
+lxml = "*"
+requests = "*"
+
+[[package]]
+category = "main"
+description = "A robust email syntax and deliverability validation library for Python 2.x/3.x."
+name = "email-validator"
+optional = false
+python-versions = "*"
+version = "1.1.1"
+
+[package.dependencies]
+dnspython = ">=1.15.0"
+idna = ">=2.0.0"
+
+[[package]]
+category = "main"
+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 = "main"
+description = "Programmer friendly subprocess wrapper"
+name = "executor"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+version = "23.1"
+
+[package.dependencies]
+coloredlogs = ">=3.5"
+fasteners = ">=0.14.1"
+humanfriendly = ">=8.0"
+property-manager = ">=3.0"
+six = ">=1.9.0"
+
+[[package]]
+category = "main"
+description = "Extracts emails and attachments saved in Microsoft Outlook's .msg files"
+name = "extract-msg"
+optional = false
+python-versions = "*"
+version = "0.25.3"
+
+[package.dependencies]
+compressed-rtf = "1.0.6"
+imapclient = "2.1.0"
+olefile = "0.46"
+tzlocal = "1.5.1"
+
+[[package]]
+category = "main"
+description = "Factur-X: electronic invoicing standard for Germany & France"
+name = "factur-x"
+optional = false
+python-versions = "*"
+version = "1.12"
+
+[package.dependencies]
+PyPDF4 = "*"
+lxml = "*"
+
+[[package]]
+category = "main"
+description = "A python package that provides useful locks."
+name = "fasteners"
+optional = false
+python-versions = "*"
+version = "0.15"
+
+[package.dependencies]
+monotonic = ">=0.1"
+six = "*"
+
+[[package]]
+category = "main"
+description = "Universal feed parser, handles RSS 0.9x, RSS 1.0, RSS 2.0, CDF, Atom 0.3, and Atom 1.0 feeds"
+name = "feedparser"
+optional = false
+python-versions = "*"
+version = "5.2.1"
+
+[[package]]
+category = "main"
+description = "Let your Python tests travel through time"
+name = "freezegun"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "0.3.11"
+
+[package.dependencies]
+python-dateutil = ">=1.0,<2.0 || >2.0"
+six = "*"
+
+[[package]]
+category = "main"
+description = "Clean single-source support for Python 3 and 2"
+name = "future"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+version = "0.18.2"
+
+[[package]]
+category = "main"
+description = "A toolkit for generation of output for the web"
+name = "genshi"
+optional = false
+python-versions = "*"
+version = "0.7.3"
+
+[package.extras]
+i18n = ["Babel (>=0.8)"]
+plugin = ["setuptools (>=0.6a2)"]
+
+[[package]]
+category = "main"
+description = "Python bindings and utilities for GeoJSON"
+name = "geojson"
+optional = false
+python-versions = "*"
+version = "2.4.1"
+
+[[package]]
+category = "main"
+description = "Coroutine-based network library"
+name = "gevent"
+optional = false
+python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
+version = "1.3.4"
+
+[package.dependencies]
+cffi = ">=1.11.5"
+greenlet = ">=0.4.13"
+
+[package.extras]
+dnspython = ["dnspython", "idna"]
+doc = ["repoze.sphinx.autointerface"]
+events = ["zope.event", "zope.interface"]
+test = ["zope.interface", "zope.event", "requests", "objgraph", "psutil", "futures", "mock", "coverage (>=4.0)", "coveralls (>=1.0)"]
+
+[[package]]
+category = "main"
+description = "Git Object Database"
+name = "gitdb"
+optional = false
+python-versions = ">=3.4"
+version = "4.0.5"
+
+[package.dependencies]
+smmap = ">=3.0.1,<4"
+
+[[package]]
+category = "main"
+description = "Python Git Library"
+name = "gitpython"
+optional = false
+python-versions = ">=3.4"
+version = "3.1.7"
+
+[package.dependencies]
+gitdb = ">=4.0.1,<5"
+
+[[package]]
+category = "main"
+description = "A Git URL parsing module (supports parsing and rewriting)"
+name = "giturlparse"
+optional = false
+python-versions = "*"
+version = "0.9.2"
+
+[[package]]
+category = "main"
+description = "Lightweight in-process concurrent programming"
+name = "greenlet"
+optional = false
+python-versions = "*"
+version = "0.4.13"
+
+[[package]]
+category = "main"
+description = "Turn HTML into equivalent Markdown-structured text."
+name = "html2text"
+optional = false
+python-versions = "*"
+version = "2016.9.19"
+
+[[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.2"
+
+[package.dependencies]
+pyreadline = "*"
+
+[[package]]
+category = "main"
+description = "Python humanize utilities"
+name = "humanize"
+optional = false
+python-versions = ">=3.5"
+version = "2.5.0"
+
+[package.extras]
+tests = ["freezegun", "pytest", "pytest-cov"]
+
+[[package]]
+category = "main"
+description = "Internationalized Domain Names in Applications (IDNA)"
+name = "idna"
+optional = false
+python-versions = "*"
+version = "2.7"
+
+[[package]]
+category = "main"
+description = "Getting image size from png/jpeg/jpeg2000/gif file"
+name = "imagesize"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "1.2.0"
+
+[[package]]
+category = "main"
+description = "Easy-to-use, Pythonic and complete IMAP client library"
+name = "imapclient"
+optional = false
+python-versions = "*"
+version = "2.1.0"
+
+[package.dependencies]
+six = "*"
+
+[package.extras]
+doc = ["sphinx"]
+test = ["mock (>=1.3.0)"]
+
+[[package]]
+category = "main"
+description = "Read metadata from Python packages"
+marker = "python_version < \"3.8\""
+name = "importlib-metadata"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
+version = "1.7.0"
+
+[package.dependencies]
+zipp = ">=0.5"
+
+[package.extras]
+docs = ["sphinx", "rst.linker"]
+testing = ["packaging", "pep517", "importlib-resources (>=1.3)"]
+
+[[package]]
+category = "main"
+description = "Python parser to extract data from pdf invoice"
+name = "invoice2data"
+optional = false
+python-versions = "*"
+version = "0.3.5"
+
+[package.dependencies]
+chardet = "*"
+dateparser = "*"
+pillow = "*"
+pyyaml = "*"
+unidecode = "*"
+
+[[package]]
+category = "main"
+description = "Python versioning with requirements.txt syntax"
+name = "iscompatible"
+optional = false
+python-versions = "*"
+version = "0.1.1"
+
+[[package]]
+category = "main"
+description = "Simple module to parse ISO 8601 dates"
+name = "iso8601"
+optional = false
+python-versions = "*"
+version = "0.1.12"
+
+[[package]]
+category = "main"
+description = "An ISO 8601 date/time/duration parser and formatter"
+name = "isodate"
+optional = false
+python-versions = "*"
+version = "0.6.0"
+
+[package.dependencies]
+six = "*"
+
+[[package]]
+category = "main"
+description = "Julian dates from proleptic Gregorian and Julian calendars."
+name = "jdcal"
+optional = false
+python-versions = "*"
+version = "1.4.1"
+
+[[package]]
+category = "main"
+description = "A small but fast and easy to use stand-alone template engine written in pure python."
+name = "jinja2"
+optional = false
+python-versions = "*"
+version = "2.10.1"
+
+[package.dependencies]
+MarkupSafe = ">=0.23"
+
+[package.extras]
+i18n = ["Babel (>=0.8)"]
+
+[[package]]
+category = "main"
+description = "Python library for interacting with JIRA via REST APIs."
+name = "jira"
+optional = false
+python-versions = "*"
+version = "2.0.0"
+
+[package.dependencies]
+defusedxml = "*"
+pbr = ">=3.0.0"
+requests = ">=2.10.0"
+requests-oauthlib = ">=0.6.1"
+requests-toolbelt = "*"
+setuptools = ">=20.10.1"
+six = ">=1.10.0"
+
+[package.dependencies.oauthlib]
+extras = ["signedtoken"]
+version = ">=1.0.0"
+
+[package.extras]
+async = ["requests-futures (>=0.9.7)"]
+cli = ["ipython (>=4.0.0,<6.0.0)", "ipython (>=4.0.0)"]
+opt = ["filemagic (>=1.6)", "pyjwt", "requests-jwt", "requests-kerberos"]
+
+[[package]]
+category = "main"
+description = "JSON Matching Expressions"
+name = "jmespath"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+version = "0.10.0"
+
+[[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 = "Placeholder description"
+name = "jtutils"
+optional = false
+python-versions = "*"
+version = "0.0.6"
+
+[package.dependencies]
+beautifulsoup4 = "*"
+requests = "*"
+
+[[package]]
+category = "main"
+description = "Authentication Library for OpenStack Identity"
+name = "keystoneauth1"
+optional = false
+python-versions = "*"
+version = "3.14.0"
+
+[package.dependencies]
+iso8601 = ">=0.1.11"
+os-service-types = ">=1.2.0"
+pbr = ">=2.0.0,<2.1.0 || >2.1.0"
+requests = ">=2.14.2"
+six = ">=1.10.0"
+stevedore = ">=1.20.0"
+
+[package.extras]
+betamax = ["betamax (>=0.7.0)", "fixtures (>=3.0.0)", "mock (>=2.0.0)"]
+kerberos = ["requests-kerberos (>=0.8.0)"]
+oauth1 = ["oauthlib (>=0.6.2)"]
+saml2 = ["lxml (>=3.4.1,<3.7.0 || >3.7.0)"]
+test = ["hacking (>=0.12.0,<0.13.0 || >0.13.0,<0.14)", "flake8-docstrings (0.2.1.post1)", "flake8-import-order (>=0.17.1)", "bandit (>=1.1.0)", "coverage (>=4.0,<4.4 || >4.4)", "fixtures (>=3.0.0)", "mock (>=2.0.0)", "oslo.config (>=5.2.0)", "openstackdocstheme (>=1.18.1)", "oslo.utils (>=3.33.0)", "oslotest (>=3.2.0)", "betamax (>=0.7.0)", "reno (>=2.5.0)", "requests-mock (>=1.2.0)", "sphinx (>=1.6.2,<1.6.6 || >1.6.6,<1.6.7 || >1.6.7)", "stestr (>=1.0.0)", "testresources (>=2.0.0)", "testtools (>=2.2.0)", "PyYAML (>=3.12)", "requests-kerberos (>=0.8.0)", "lxml (>=3.4.1,<3.7.0 || >3.7.0)", "oauthlib (>=0.6.2)"]
+
+[[package]]
+category = "main"
+description = "A fast implementation of the Cassowary constraint solver"
+name = "kiwisolver"
+optional = false
+python-versions = ">=3.6"
+version = "1.2.0"
+
+[[package]]
+category = "main"
+description = "Lightweight module to define serializable, schema-validated classes"
+name = "lasso"
+optional = false
+python-versions = "*"
+version = "0.0.5"
+
+[package.dependencies]
+delorean = ">=0.4.4"
+schema = ">=0.3.1,<0.4.0"
+
+[[package]]
+category = "main"
+description = "Levenshtein edit distance library"
+name = "leven"
+optional = false
+python-versions = "*"
+version = "1.0.4"
+
+[package.dependencies]
+nose = "*"
+six = "*"
+
+[[package]]
+category = "main"
+description = "SASS for Python: A straightforward binding of libsass for Python."
+name = "libsass"
+optional = false
+python-versions = "*"
+version = "0.12.3"
+
+[package.dependencies]
+six = "*"
+
+[package.extras]
+upload_appveyor_builds = ["twine (1.5.0)"]
+
+[[package]]
+category = "main"
+description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API."
+name = "lxml"
+optional = false
+python-versions = "*"
+version = "4.2.3"
+
+[package.extras]
+cssselect = ["cssselect (>=0.7)"]
+html5 = ["html5lib"]
+htmlsoup = ["beautifulsoup4"]
+source = ["Cython (>=0.26.1)"]
+
+[[package]]
+category = "main"
+description = "A super-fast templating language that borrows the best ideas from the existing templating languages."
+name = "mako"
+optional = false
+python-versions = "*"
+version = "1.0.4"
+
+[package.dependencies]
+MarkupSafe = ">=0.9.2"
+
+[[package]]
+category = "main"
+description = "Implements a XML/HTML/XHTML Markup safe string for Python"
+name = "markupsafe"
+optional = false
+python-versions = "*"
+version = "0.23"
+
+[[package]]
+category = "main"
+description = "Python plotting package"
+name = "matplotlib"
+optional = false
+python-versions = ">=3.6"
+version = "3.2.2"
+
+[package.dependencies]
+cycler = ">=0.10"
+kiwisolver = ">=1.0.1"
+numpy = ">=1.11"
+pyparsing = ">=2.0.1,<2.0.4 || >2.0.4,<2.1.2 || >2.1.2,<2.1.6 || >2.1.6"
+python-dateutil = ">=2.1"
+
+[[package]]
+category = "main"
+description = "Rolling backport of unittest.mock for all Pythons"
+name = "mock"
+optional = false
+python-versions = "*"
+version = "2.0.0"
+
+[package.dependencies]
+pbr = ">=0.11"
+six = ">=1.9"
+
+[package.extras]
+docs = ["sphinx", "Pygments (<2)", "jinja2 (<2.7)", "sphinx (<1.3)"]
+test = ["unittest2 (>=1.1.0)"]
+
+[[package]]
+category = "main"
+description = "An implementation of time.monotonic() for Python 2 & < 3.3"
+name = "monotonic"
+optional = false
+python-versions = "*"
+version = "1.5"
+
+[[package]]
+category = "main"
+description = "D3 Viewer for Matplotlib"
+name = "mpld3"
+optional = false
+python-versions = "*"
+version = "0.3"
+
+[[package]]
+category = "main"
+description = "MessagePack (de)serializer."
+name = "msgpack"
+optional = false
+python-versions = "*"
+version = "1.0.0"
+
+[[package]]
+category = "main"
+description = "multidict implementation"
+marker = "python_version >= \"3.6\""
+name = "multidict"
+optional = false
+python-versions = ">=3.5"
+version = "4.7.6"
+
+[[package]]
+category = "main"
+description = "Python interface to MySQL"
+name = "mysqlclient"
+optional = false
+python-versions = ">=3.5"
+version = "2.0.1"
+
+[[package]]
+category = "main"
+description = "Simple natural order sorting API for Python"
+name = "naturalsort"
+optional = false
+python-versions = "*"
+version = "1.5.1"
+
+[[package]]
+category = "main"
+description = "A network address manipulation library for Python"
+name = "netaddr"
+optional = false
+python-versions = "*"
+version = "0.8.0"
+
+[[package]]
+category = "main"
+description = "Portable network interface information."
+name = "netifaces"
+optional = false
+python-versions = "*"
+version = "0.10.9"
+
+[[package]]
+category = "main"
+description = "nose extends unittest to make testing easier"
+name = "nose"
+optional = false
+python-versions = "*"
+version = "1.3.7"
+
+[[package]]
+category = "main"
+description = "Modules to convert numbers to words. Easily extensible."
+name = "num2words"
+optional = false
+python-versions = "*"
+version = "0.5.6"
+
+[[package]]
+category = "main"
+description = "NumPy is the fundamental package for array computing with Python."
+name = "numpy"
+optional = false
+python-versions = ">=3.6"
+version = "1.19.1"
+
+[[package]]
+category = "main"
+description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic"
+name = "oauthlib"
+optional = false
+python-versions = "*"
+version = "2.1.0"
+
+[package.extras]
+rsa = ["cryptography"]
+signals = ["blinker"]
+signedtoken = ["cryptography", "pyjwt (>=1.0.0)"]
+test = ["nose", "unittest2", "cryptography", "mock", "pyjwt (>=1.0.0)", "blinker"]
+
+[[package]]
+category = "main"
+description = "This is a library of decorators for Odoo developers."
+name = "oca.decorators"
+optional = false
+python-versions = "*"
+version = "0.0.1"
+
+[package.dependencies]
+decorator = "*"
+
+[[package]]
+category = "main"
+description = "Tools for working with the OFX (Open Financial Exchange) file format"
+name = "ofxparse"
+optional = false
+python-versions = "*"
+version = "0.16"
+
+[package.dependencies]
+beautifulsoup4 = "*"
+lxml = "*"
+six = "*"
+
+[[package]]
+category = "main"
+description = "Python package to parse, read and write Microsoft OLE2 files (Structured Storage or Compound Document, Microsoft Office)"
+name = "olefile"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "0.46"
+
+[[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.4"
+
+[package.dependencies]
+et-xmlfile = "*"
+jdcal = "*"
+
+[[package]]
+category = "main"
+description = "A library with support functions to be called from Odoo migration scripts."
+name = "openupgradelib"
+optional = false
+python-versions = "*"
+version = "2.0.0"
+
+[[package]]
+category = "main"
+description = "Python library for consuming OpenStack sevice-types-authority data"
+name = "os-service-types"
+optional = false
+python-versions = "*"
+version = "1.7.0"
+
+[package.dependencies]
+pbr = ">=2.0.0,<2.1.0 || >2.1.0"
+
+[[package]]
+category = "main"
+description = "Oslo Configuration API"
+name = "oslo.config"
+optional = false
+python-versions = ">=3.6"
+version = "8.3.1"
+
+[package.dependencies]
+PyYAML = ">=3.12"
+debtcollector = ">=1.2.0"
+netaddr = ">=0.7.18"
+"oslo.i18n" = ">=3.15.3"
+requests = ">=2.18.0"
+rfc3986 = ">=1.2.0"
+stevedore = ">=1.20.0"
+
+[package.dependencies.importlib-metadata]
+python = "<3.8"
+version = ">=1.7.0"
+
+[[package]]
+category = "main"
+description = "Oslo i18n library"
+name = "oslo.i18n"
+optional = false
+python-versions = ">=3.6"
+version = "5.0.0"
+
+[package.dependencies]
+pbr = ">=2.0.0,<2.1.0 || >2.1.0"
+six = ">=1.10.0"
+
+[[package]]
+category = "main"
+description = "Oslo Serialization library"
+name = "oslo.serialization"
+optional = false
+python-versions = ">=3.6"
+version = "4.0.0"
+
+[package.dependencies]
+msgpack = ">=0.5.2"
+"oslo.utils" = ">=3.33.0"
+pbr = ">=2.0.0,<2.1.0 || >2.1.0"
+pytz = ">=2013.6"
+
+[[package]]
+category = "main"
+description = "Oslo Utility library"
+name = "oslo.utils"
+optional = false
+python-versions = ">=3.6"
+version = "4.4.0"
+
+[package.dependencies]
+debtcollector = ">=1.2.0"
+iso8601 = ">=0.1.11"
+netaddr = ">=0.7.18"
+netifaces = ">=0.10.4"
+"oslo.i18n" = ">=3.15.3"
+packaging = ">=20.4"
+pbr = ">=2.0.0,<2.1.0 || >2.1.0"
+pyparsing = ">=2.1.0"
+pytz = ">=2013.6"
+six = ">=1.10.0"
+
+[[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.4"
+
+[package.dependencies]
+pyparsing = ">=2.0.2"
+six = "*"
+
+[[package]]
+category = "main"
+description = "Powerful data structures for data analysis, time series, and statistics"
+name = "pandas"
+optional = false
+python-versions = ">=3.6.1"
+version = "1.1.0"
+
+[package.dependencies]
+numpy = ">=1.15.4"
+python-dateutil = ">=2.7.3"
+pytz = ">=2017.2"
+
+[package.extras]
+test = ["pytest (>=4.0.2)", "pytest-xdist", "hypothesis (>=3.58)"]
+
+[[package]]
+category = "main"
+description = "SSH2 protocol library"
+name = "paramiko"
+optional = false
+python-versions = "*"
+version = "2.7.1"
+
+[package.dependencies]
+bcrypt = ">=3.1.3"
+cryptography = ">=2.5"
+pynacl = ">=1.0.1"
+
+[package.extras]
+all = ["pyasn1 (>=0.1.7)", "pynacl (>=1.0.1)", "bcrypt (>=3.1.3)", "invoke (>=1.3)", "gssapi (>=1.4.1)", "pywin32 (>=2.1.8)"]
+ed25519 = ["pynacl (>=1.0.1)", "bcrypt (>=3.1.3)"]
+gssapi = ["pyasn1 (>=0.1.7)", "gssapi (>=1.4.1)", "pywin32 (>=2.1.8)"]
+invoke = ["invoke (>=1.3)"]
+
+[[package]]
+category = "main"
+description = "comprehensive password hashing framework supporting over 30 schemes"
+name = "passlib"
+optional = false
+python-versions = "*"
+version = "1.6.5"
+
+[[package]]
+category = "main"
+description = "Python Build Reasonableness"
+name = "pbr"
+optional = false
+python-versions = "*"
+version = "5.4.5"
+
+[[package]]
+category = "main"
+description = "A wrapper around the pdftoppm and pdftocairo command line tools to convert PDF to a PIL Image list."
+name = "pdf2image"
+optional = false
+python-versions = "*"
+version = "1.13.1"
+
+[package.dependencies]
+pillow = "*"
+
+[[package]]
+category = "main"
+description = "Python version of Google's common library for parsing, formatting, storing and validating international phone numbers."
+name = "phonenumbers"
+optional = false
+python-versions = "*"
+version = "8.12.7"
+
+[[package]]
+category = "main"
+description = "Python Imaging Library (Fork)"
+name = "pillow"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+version = "6.1.0"
+
+[[package]]
+category = "main"
+description = "An open-source, interactive graphing library for Python"
+name = "plotly"
+optional = false
+python-versions = "*"
+version = "4.1.0"
+
+[package.dependencies]
+retrying = ">=1.3.3"
+six = "*"
+
+[[package]]
+category = "main"
+description = "Turns CSS blocks into style attributes"
+name = "premailer"
+optional = false
+python-versions = "*"
+version = "3.7.0"
+
+[package.dependencies]
+cachetools = "*"
+cssselect = "*"
+cssutils = "*"
+lxml = "*"
+requests = "*"
+
+[package.extras]
+dev = ["tox", "twine", "therapist", "black", "flake8", "wheel"]
+test = ["nose", "mock"]
+
+[[package]]
+category = "main"
+description = "Useful property variants for Python programming (required properties, writable properties, cached properties, etc)"
+name = "property-manager"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+version = "3.0"
+
+[package.dependencies]
+humanfriendly = ">=8.0"
+verboselogs = ">=1.1"
+
+[[package]]
+category = "main"
+description = "psutil is a cross-platform library for retrieving information onrunning processes and system utilization (CPU, memory, disks, network)in Python."
+name = "psutil"
+optional = false
+python-versions = "*"
+version = "4.3.1"
+
+[[package]]
+category = "main"
+description = "psycopg2 - Python-PostgreSQL Database Adapter"
+name = "psycopg2"
+optional = false
+python-versions = "*"
+version = "2.7.3.1"
+
+[[package]]
+category = "main"
+description = "Asterisk Manager API Python interface."
+name = "py-asterisk"
+optional = false
+python-versions = "*"
+version = "0.5.18"
+
+[[package]]
+category = "main"
+description = "Formats declarations for py3o"
+name = "py3o.formats"
+optional = false
+python-versions = "*"
+version = "0.3"
+
+[package.dependencies]
+setuptools = "*"
+
+[[package]]
+category = "main"
+description = "An easy solution to design reports using LibreOffice"
+name = "py3o.template"
+optional = false
+python-versions = "*"
+version = "0.10.0"
+
+[package.dependencies]
+Pillow = "*"
+babel = "*"
+genshi = ">=0.7"
+lxml = "*"
+"pyjon.utils" = ">0.6"
+setuptools = "*"
+six = ">=1.9"
+
+[[package]]
+category = "main"
+description = "ISO country, subdivision, language, currency and script definitions and their translations"
+name = "pycountry"
+optional = false
+python-versions = "*"
+version = "20.7.3"
+
+[[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 = "main"
+description = "Python interface to Graphviz's Dot"
+name = "pydot"
+optional = false
+python-versions = "*"
+version = "1.2.3"
+
+[package.dependencies]
+pyparsing = ">=2.1.4"
+
+[[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 = "count source lines of code (SLOC) using pygments"
+name = "pygount"
+optional = false
+python-versions = "*"
+version = "1.1.0"
+
+[package.dependencies]
+pygments = ">=2.0"
+
+[[package]]
+category = "main"
+description = "Useful tools library with classes to do singletons, dynamic function pointers..."
+name = "pyjon.utils"
+optional = false
+python-versions = "*"
+version = "0.7"
+
+[package.dependencies]
+setuptools = "*"
+
+[[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 modules for implementing LDAP clients"
+name = "pyldap"
+optional = false
+python-versions = "*"
+version = "2.4.28"
+
+[package.dependencies]
+setuptools = "*"
+
+[[package]]
+category = "main"
+description = "DB-API interface to Microsoft SQL Server for Python. (new Cython-based version)"
+name = "pymssql"
+optional = false
+python-versions = "*"
+version = "2.1.4"
+
+[[package]]
+category = "main"
+description = "Python binding to the Networking and Cryptography (NaCl) library"
+name = "pynacl"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "1.4.0"
+
+[package.dependencies]
+cffi = ">=1.4.1"
+six = "*"
+
+[package.extras]
+docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"]
+tests = ["pytest (>=3.2.1,<3.3.0 || >3.3.0)", "hypothesis (>=3.27.0)"]
+
+[[package]]
+category = "main"
+description = "Python One Time Password Library"
+name = "pyotp"
+optional = false
+python-versions = "*"
+version = "2.4.0"
+
+[[package]]
+category = "main"
+description = "Python parsing module"
+name = "pyparsing"
+optional = false
+python-versions = "*"
+version = "2.1.10"
+
+[[package]]
+category = "main"
+description = "PDF toolkit"
+name = "pypdf2"
+optional = false
+python-versions = "*"
+version = "1.26.0"
+
+[[package]]
+category = "main"
+description = "PDF toolkit"
+name = "pypdf4"
+optional = false
+python-versions = "*"
+version = "1.27.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 = "Implementation of some RFC standard algorithms"
+name = "pyrfc"
+optional = false
+python-versions = "*"
+version = "0.1.2"
+
+[[package]]
+category = "main"
+description = "Persistent/Functional/Immutable data structures"
+name = "pyrsistent"
+optional = false
+python-versions = "*"
+version = "0.16.0"
+
+[package.dependencies]
+six = "*"
+
+[[package]]
+category = "main"
+description = "Python Serial Port Extension"
+name = "pyserial"
+optional = false
+python-versions = "*"
+version = "3.1.1"
+
+[[package]]
+category = "main"
+description = "A friendly face on SFTP"
+name = "pysftp"
+optional = false
+python-versions = "*"
+version = "0.2.9"
+
+[package.dependencies]
+paramiko = ">=1.17"
+
+[[package]]
+category = "main"
+description = "A pure Python chess library with move generation and validation, Polyglot opening book probing, PGN reading and writing, Gaviota tablebase probing, Syzygy tablebase probing and XBoard/UCI engine communication."
+name = "python-chess"
+optional = false
+python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
+version = "0.23.11"
+
+[package.extras]
+test = ["spur"]
+
+[[package]]
+category = "main"
+description = "Python tools for manipulating csv files"
+name = "python-csv"
+optional = false
+python-versions = "*"
+version = "0.0.13"
+
+[package.dependencies]
+argparse = "*"
+demjson = "*"
+jtutils = "*"
+leven = "*"
+matplotlib = "*"
+numpy = "*"
+pandas = "*"
+xlrd = "*"
+xmltodict = "*"
+
+[[package]]
+category = "main"
+description = "Extensions to the standard Python datetime module"
+name = "python-dateutil"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+version = "2.7.3"
+
+[package.dependencies]
+six = ">=1.5"
+
+[[package]]
+category = "main"
+description = "Automate boring git tasks"
+name = "python-git"
+optional = false
+python-versions = "*"
+version = "2018.2.1"
+
+[package.dependencies]
+send2trash = "*"
+
+[[package]]
+category = "main"
+description = "A python library adding a json log formatter"
+name = "python-json-logger"
+optional = false
+python-versions = "*"
+version = "0.1.5"
+
+[package.dependencies]
+setuptools = "*"
+
+[[package]]
+category = "main"
+description = "Client Library for OpenStack Identity"
+name = "python-keystoneclient"
+optional = false
+python-versions = "*"
+version = "3.22.0"
+
+[package.dependencies]
+debtcollector = ">=1.2.0"
+keystoneauth1 = ">=3.4.0"
+"oslo.config" = ">=5.2.0"
+"oslo.i18n" = ">=3.15.3"
+"oslo.serialization" = ">=2.18.0,<2.19.1 || >2.19.1"
+"oslo.utils" = ">=3.33.0"
+pbr = ">=2.0.0,<2.1.0 || >2.1.0"
+requests = ">=2.14.2"
+six = ">=1.10.0"
+stevedore = ">=1.20.0"
+
+[[package]]
+category = "main"
+description = "A Python Slugify application that handles Unicode"
+name = "python-slugify"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+version = "4.0.1"
+
+[package.dependencies]
+text-unidecode = ">=1.3"
+
+[package.extras]
+unidecode = ["Unidecode (>=1.1.1)"]
+
+[[package]]
+category = "main"
+description = "Python module to handle standardized numbers and codes"
+name = "python-stdnum"
+optional = false
+python-versions = "*"
+version = "1.13"
+
+[package.extras]
+soap = ["zeep"]
+soap-alt = ["suds"]
+soap-fallback = ["pysimplesoap"]
+
+[[package]]
+category = "main"
+description = "OpenStack Object Storage API Client Library"
+name = "python-swiftclient"
+optional = false
+python-versions = "*"
+version = "3.9.0"
+
+[package.dependencies]
+requests = ">=1.1.0"
+six = ">=1.9.0"
+
+[package.extras]
+keystone = ["python-keystoneclient (>=0.7.0)"]
+test = ["hacking (>=1.1.0,<1.2.0)", "coverage (>=4.0,<4.4 || >4.4)", "keystoneauth1 (>=3.4.0)", "mock (>=1.2.0)", "stestr (>=2.0.0)", "openstacksdk (>=0.11.0)"]
+
+[[package]]
+category = "main"
+description = "Python based U2F server library"
+name = "python-u2flib-server"
+optional = false
+python-versions = "*"
+version = "5.0.0"
+
+[package.dependencies]
+cryptography = ">=1.2"
+six = "*"
+
+[package.extras]
+u2f_server = ["webob"]
+
+[[package]]
+category = "main"
+description = "World timezone definitions, modern and historical"
+name = "pytz"
+optional = false
+python-versions = "*"
+version = "2017.2"
+
+[[package]]
+category = "main"
+description = "Python USB access module"
+name = "pyusb"
+optional = false
+python-versions = "*"
+version = "1.0.0"
+
+[[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 = "Read one-dimensional barcodes and QR codes from Python 2 and 3."
+name = "pyzbar"
+optional = false
+python-versions = "*"
+version = "0.1.8"
+
+[package.extras]
+scripts = ["Pillow (>=3.2.0)"]
+
+[[package]]
+category = "main"
+description = "QR Code image generator"
+name = "qrcode"
+optional = false
+python-versions = "*"
+version = "5.3"
+
+[package.dependencies]
+six = "*"
+
+[[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 = "*"
+version = "2.10.5"
+
+[[package]]
+category = "main"
+description = "Alternative regular expression module, to replace re."
+name = "regex"
+optional = false
+python-versions = "*"
+version = "2020.7.14"
+
+[[package]]
+category = "main"
+description = "The Reportlab Toolkit"
+name = "reportlab"
+optional = false
+python-versions = "*"
+version = "3.3.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.*"
+version = "2.20.0"
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+chardet = ">=3.0.2,<3.1.0"
+idna = ">=2.5,<2.8"
+urllib3 = ">=1.21.1,<1.25"
+
+[package.extras]
+security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)"]
+socks = ["PySocks (>=1.5.6,<1.5.7 || >1.5.7)", "win-inet-pton"]
+
+[[package]]
+category = "main"
+description = "Mock out responses from the requests package"
+name = "requests-mock"
+optional = false
+python-versions = "*"
+version = "1.8.0"
+
+[package.dependencies]
+requests = ">=2.3,<3"
+six = "*"
+
+[package.extras]
+fixture = ["fixtures"]
+test = ["fixtures", "mock", "purl", "pytest", "sphinx", "testrepository (>=0.0.18)", "testtools"]
+
+[[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.1.0"
+
+[package.dependencies]
+oauthlib = ">=2.1.0,<3.0.0"
+requests = ">=2.0.0"
+
+[package.extras]
+rsa = ["oauthlib (>=2.1.0,<3.0.0)"]
+
+[[package]]
+category = "main"
+description = "A utility belt for advanced users of python-requests"
+name = "requests-toolbelt"
+optional = false
+python-versions = "*"
+version = "0.9.1"
+
+[package.dependencies]
+requests = ">=2.0.1,<3.0.0"
+
+[[package]]
+category = "main"
+description = "Retrying"
+name = "retrying"
+optional = false
+python-versions = "*"
+version = "1.3.3"
+
+[package.dependencies]
+six = ">=1.7.0"
+
+[[package]]
+category = "main"
+description = "Validating URI References per RFC 3986"
+name = "rfc3986"
+optional = false
+python-versions = "*"
+version = "1.4.0"
+
+[package.extras]
+idna2008 = ["idna"]
+
+[[package]]
+category = "main"
+description = "Simple command line interface for backup rotation"
+name = "rotate-backups"
+optional = false
+python-versions = "*"
+version = "4.3"
+
+[package.dependencies]
+coloredlogs = ">=5.0"
+executor = ">=13.0"
+humanfriendly = ">=1.44.5"
+naturalsort = ">=1.4"
+property-manager = ">=2.0"
+python-dateutil = ">=2.2"
+simpleeval = ">=0.8.7"
+six = ">=1.9.0"
+verboselogs = ">=1.4"
+
+[[package]]
+category = "main"
+description = "Simple command line interface for S3 backup rotation"
+name = "rotate-backups-s3"
+optional = false
+python-versions = "*"
+version = "0.3"
+
+[package.dependencies]
+boto = "*"
+rotate-backups = "4.3"
+
+[[package]]
+category = "main"
+description = "An Amazon S3 Transfer Manager"
+name = "s3transfer"
+optional = false
+python-versions = "*"
+version = "0.2.1"
+
+[package.dependencies]
+botocore = ">=1.12.36,<2.0.0"
+
+[[package]]
+category = "main"
+description = "Simple data validation library"
+name = "schema"
+optional = false
+python-versions = "*"
+version = "0.3.1"
+
+[[package]]
+category = "main"
+description = "Send file to trash natively under Mac OS X, Windows and Linux."
+name = "send2trash"
+optional = false
+python-versions = "*"
+version = "1.5.0"
+
+[[package]]
+category = "main"
+description = "A framework for serializing/deserializing JSON/YAML/XML into python class instances and vice versa"
+name = "serial"
+optional = false
+python-versions = "*"
+version = "0.0.97"
+
+[package.dependencies]
+future = ">=0.17.1"
+iso8601 = ">=0.1.12"
+pyyaml = ">=3.13"
+
+[[package]]
+category = "main"
+description = "Geometric objects, predicates, and operations"
+name = "shapely"
+optional = false
+python-versions = "*"
+version = "1.6.4.post2"
+
+[package.extras]
+all = ["pytest", "pytest-cov", "numpy"]
+test = ["pytest", "pytest-cov"]
+vectorized = ["numpy"]
+
+[[package]]
+category = "main"
+description = "A simple, safe single expression evaluator library."
+name = "simpleeval"
+optional = false
+python-versions = "*"
+version = "0.9.10"
+
+[[package]]
+category = "main"
+description = "Simple, fast, extensible JSON encoder/decoder for Python"
+name = "simplejson"
+optional = false
+python-versions = ">=2.5, !=3.0.*, !=3.1.*, !=3.2.*"
+version = "3.17.2"
+
+[[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.15.0"
+
+[[package]]
+category = "main"
+description = "A generic slugifier."
+name = "slugify"
+optional = false
+python-versions = "*"
+version = "0.0.1"
+
+[[package]]
+category = "main"
+description = "A pure Python implementation of a sliding window memory map manager"
+name = "smmap"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "3.0.4"
+
+[[package]]
+category = "main"
+description = "This package provides 26 stemmers for 25 languages generated from Snowball algorithms."
+name = "snowballstemmer"
+optional = false
+python-versions = "*"
+version = "2.0.0"
+
+[[package]]
+category = "main"
+description = "SOAP Services for Python"
+name = "soappy"
+optional = false
+python-versions = "*"
+version = "0.12.22"
+
+[package.dependencies]
+defusedxml = "*"
+wstools = "*"
+
+[[package]]
+category = "main"
+description = "A modern CSS selector implementation for Beautiful Soup."
+name = "soupsieve"
+optional = false
+python-versions = "*"
+version = "1.9.6"
+
+[[package]]
+category = "main"
+description = "Python documentation generator"
+name = "sphinx"
+optional = false
+python-versions = ">=3.5"
+version = "3.1.2"
+
+[package.dependencies]
+Jinja2 = ">=2.3"
+Pygments = ">=2.0"
+alabaster = ">=0.7,<0.8"
+babel = ">=1.3"
+colorama = ">=0.3.5"
+docutils = ">=0.12"
+imagesize = "*"
+packaging = "*"
+requests = ">=2.5.0"
+setuptools = "*"
+snowballstemmer = ">=1.1"
+sphinxcontrib-applehelp = "*"
+sphinxcontrib-devhelp = "*"
+sphinxcontrib-htmlhelp = "*"
+sphinxcontrib-jsmath = "*"
+sphinxcontrib-qthelp = "*"
+sphinxcontrib-serializinghtml = "*"
+
+[package.extras]
+docs = ["sphinxcontrib-websupport"]
+lint = ["flake8 (>=3.5.0)", "flake8-import-order", "mypy (>=0.780)", "docutils-stubs"]
+test = ["pytest", "pytest-cov", "html5lib", "typed-ast", "cython"]
+
+[[package]]
+category = "main"
+description = "Sphinx extension for embedding sequences of file alterations"
+name = "sphinx-patchqueue"
+optional = false
+python-versions = "*"
+version = "1.0.4"
+
+[package.dependencies]
+sphinx = "*"
+unidiff = "*"
+
+[[package]]
+category = "main"
+description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books"
+name = "sphinxcontrib-applehelp"
+optional = false
+python-versions = ">=3.5"
+version = "1.0.2"
+
+[package.extras]
+lint = ["flake8", "mypy", "docutils-stubs"]
+test = ["pytest"]
+
+[[package]]
+category = "main"
+description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document."
+name = "sphinxcontrib-devhelp"
+optional = false
+python-versions = ">=3.5"
+version = "1.0.2"
+
+[package.extras]
+lint = ["flake8", "mypy", "docutils-stubs"]
+test = ["pytest"]
+
+[[package]]
+category = "main"
+description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files"
+name = "sphinxcontrib-htmlhelp"
+optional = false
+python-versions = ">=3.5"
+version = "1.0.3"
+
+[package.extras]
+lint = ["flake8", "mypy", "docutils-stubs"]
+test = ["pytest", "html5lib"]
+
+[[package]]
+category = "main"
+description = "A sphinx extension which renders display math in HTML via JavaScript"
+name = "sphinxcontrib-jsmath"
+optional = false
+python-versions = ">=3.5"
+version = "1.0.1"
+
+[package.extras]
+test = ["pytest", "flake8", "mypy"]
+
+[[package]]
+category = "main"
+description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document."
+name = "sphinxcontrib-qthelp"
+optional = false
+python-versions = ">=3.5"
+version = "1.0.3"
+
+[package.extras]
+lint = ["flake8", "mypy", "docutils-stubs"]
+test = ["pytest"]
+
+[[package]]
+category = "main"
+description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)."
+name = "sphinxcontrib-serializinghtml"
+optional = false
+python-versions = ">=3.5"
+version = "1.1.4"
+
+[package.extras]
+lint = ["flake8", "mypy", "docutils-stubs"]
+test = ["pytest"]
+
+[[package]]
+category = "main"
+description = "Database Abstraction Library"
+name = "sqlalchemy"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "1.3.18"
+
+[package.extras]
+mssql = ["pyodbc"]
+mssql_pymssql = ["pymssql"]
+mssql_pyodbc = ["pyodbc"]
+mysql = ["mysqlclient"]
+oracle = ["cx-oracle"]
+postgresql = ["psycopg2"]
+postgresql_pg8000 = ["pg8000"]
+postgresql_psycopg2binary = ["psycopg2-binary"]
+postgresql_psycopg2cffi = ["psycopg2cffi"]
+pymysql = ["pymysql"]
+
+[[package]]
+category = "main"
+description = "A simple statsd client."
+name = "statsd"
+optional = false
+python-versions = "*"
+version = "3.2.1"
+
+[[package]]
+category = "main"
+description = "Manage dynamic plugins for Python applications"
+name = "stevedore"
+optional = false
+python-versions = ">=3.6"
+version = "3.2.0"
+
+[package.dependencies]
+pbr = ">=2.0.0,<2.1.0 || >2.1.0"
+
+[package.dependencies.importlib-metadata]
+python = "<3.8"
+version = ">=1.7.0"
+
+[[package]]
+category = "main"
+description = "Lightweight SOAP client (Jurko's fork)"
+name = "suds-jurko"
+optional = false
+python-versions = "*"
+version = "0.6"
+
+[[package]]
+category = "main"
+description = "The most basic Text::Unidecode port"
+name = "text-unidecode"
+optional = false
+python-versions = "*"
+version = "1.3"
+
+[[package]]
+category = "main"
+description = "Python Library for Tom's Obvious, Minimal Language"
+name = "toml"
+optional = false
+python-versions = "*"
+version = "0.10.1"
+
+[[package]]
+category = "main"
+description = "List processing tools and functional utilities"
+name = "toolz"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+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 = ">= 3.5"
+version = "6.0.4"
+
+[[package]]
+category = "main"
+description = "Backported and Experimental Type Hints for Python 3.5+"
+marker = "python_version >= \"3.6\" and python_version < \"3.8\""
+name = "typing-extensions"
+optional = false
+python-versions = "*"
+version = "3.7.4.2"
+
+[[package]]
+category = "main"
+description = "tzinfo object for the local timezone"
+name = "tzlocal"
+optional = false
+python-versions = "*"
+version = "1.5.1"
+
+[package.dependencies]
+pytz = "*"
+
+[[package]]
+category = "main"
+description = "ASCII transliterations of Unicode text"
+name = "unidecode"
+optional = false
+python-versions = "*"
+version = "1.0.22"
+
+[[package]]
+category = "main"
+description = "Unified diff parsing/metadata extraction library."
+name = "unidiff"
+optional = false
+python-versions = "*"
+version = "0.6.0"
+
+[[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.*, <4"
+version = "1.24.3"
+
+[package.extras]
+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 = "[UNMAINTAINED] Python module to validate VAT numbers"
+name = "vatnumber"
+optional = false
+python-versions = "*"
+version = "1.2"
+
+[package.dependencies]
+python-stdnum = "*"
+
+[package.extras]
+suds = ["suds"]
+
+[[package]]
+category = "main"
+description = "Automatically mock your HTTP interactions to simplify and speed up testing"
+name = "vcrpy"
+optional = false
+python-versions = ">=3.5"
+version = "4.1.0"
+
+[package.dependencies]
+PyYAML = "*"
+six = ">=1.5"
+wrapt = "*"
+
+[package.dependencies.yarl]
+python = ">=3.6"
+version = "*"
+
+[[package]]
+category = "main"
+description = "Python unittest integration for vcr.py"
+name = "vcrpy-unittest"
+optional = false
+python-versions = "*"
+version = "0.1.7"
+
+[package.dependencies]
+vcrpy = "*"
+
+[[package]]
+category = "main"
+description = "Verbose logging level for Python's logging module"
+name = "verboselogs"
+optional = false
+python-versions = "*"
+version = "1.7"
+
+[[package]]
+category = "main"
+description = "A full-featured Python package for parsing and creating iCalendar and vCard files"
+name = "vobject"
+optional = false
+python-versions = "*"
+version = "0.9.3"
+
+[package.dependencies]
+python-dateutil = ">=2.4.0"
+
+[[package]]
+category = "main"
+description = "Voicent Python Library"
+name = "voicent-python"
+optional = false
+python-versions = "*"
+version = "1.0"
+
+[package.dependencies]
+requests = ">=2.20.0"
+
+[[package]]
+category = "main"
+description = "A library for working with color names and color values formats defined by HTML and CSS."
+name = "webcolors"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+version = "1.10"
+
+[package.dependencies]
+six = "*"
+
+[[package]]
+category = "main"
+description = "WebSocket client for Python. hybi13 is supported."
+name = "websocket-client"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "0.57.0"
+
+[package.dependencies]
+six = "*"
+
+[[package]]
+category = "main"
+description = "The Swiss Army knife of Python web development"
+name = "werkzeug"
+optional = false
+python-versions = "*"
+version = "0.11.15"
+
+[[package]]
+category = "main"
+description = "A built-package format for Python"
+name = "wheel"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+version = "0.34.2"
+
+[package.extras]
+test = ["pytest (>=3.0.0)", "pytest-cov"]
+
+[[package]]
+category = "main"
+description = "Module for decorators, wrappers and monkey patching."
+name = "wrapt"
+optional = false
+python-versions = "*"
+version = "1.12.1"
+
+[[package]]
+category = "main"
+description = "WSDL parsing services package for Web Services for Python."
+name = "wstools"
+optional = false
+python-versions = "*"
+version = "0.4.8"
+
+[package.dependencies]
+pbr = "*"
+setuptools = ">=17.1"
+six = "*"
+
+[[package]]
+category = "main"
+description = "Library for developers to extract data from Microsoft Excel (tm) spreadsheet files"
+name = "xlrd"
+optional = false
+python-versions = "*"
+version = "1.0.0"
+
+[[package]]
+category = "main"
+description = "A Python module for creating Excel XLSX files."
+name = "xlsxwriter"
+optional = false
+python-versions = "*"
+version = "0.9.3"
+
+[[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 = "main"
+description = "Makes working with XML feel like you are working with JSON"
+name = "xmltodict"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+version = "0.12.0"
+
+[[package]]
+category = "main"
+description = "Yet another URL library"
+marker = "python_version >= \"3.6\""
+name = "yarl"
+optional = false
+python-versions = ">=3.5"
+version = "1.5.1"
+
+[package.dependencies]
+idna = ">=2.0"
+multidict = ">=4.0"
+
+[package.dependencies.typing-extensions]
+python = "<3.8"
+version = ">=3.7.4"
+
+[[package]]
+category = "main"
+description = "A modern/fast Python SOAP client based on lxml / requests"
+name = "zeep"
+optional = false
+python-versions = "*"
+version = "3.4.0"
+
+[package.dependencies]
+appdirs = ">=1.4.0"
+attrs = ">=17.2.0"
+cached-property = ">=1.3.0"
+defusedxml = ">=0.4.1"
+isodate = ">=0.5.4"
+lxml = ">=3.1.0"
+pytz = "*"
+requests = ">=2.7.0"
+requests-toolbelt = ">=0.7.1"
+six = ">=1.9.0"
+
+[package.extras]
+async = ["aiohttp (>=1.0)"]
+docs = ["sphinx (>=1.4.0)"]
+test = ["freezegun (0.3.8)", "mock (2.0.0)", "pretend (1.0.8)", "pytest-cov (2.5.1)", "pytest (3.1.3)", "requests-mock (>=0.7.0)", "pytest-tornado (0.4.5)", "isort (4.2.15)", "flake8 (3.3.0)", "flake8-blind-except (0.1.1)", "flake8-debugger (1.4.0)", "flake8-imports (0.1.1)", "aioresponses (>=0.4.1)"]
+tornado = ["tornado (>=4.0.2,<5)"]
+xmlsec = ["xmlsec (>=0.6.1)"]
+
+[[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"]
+
+[[package]]
+category = "main"
+description = ""
+name = "zxcvbn"
+optional = false
+python-versions = "*"
+version = "4.4.28"
+
+[metadata]
+content-hash = "c647e378c3c2f6a1c60fe22d5dbc3666d5e7eac3b260e76a8ef8fc7089164db2"
+lock-version = "1.0"
+python-versions = "^3.7"
+
+[metadata.files]
+agithub = [
+ {file = "agithub-2.2.2-py2.py3-none-any.whl", hash = "sha256:5f50071536db0cc9611859e761d7c3dc6f951a8535029bf6af7fb22744b7e118"},
+ {file = "agithub-2.2.2.tar.gz", hash = "sha256:321aa5fc688fde2970562b35c991881b69a13f57372d554a0fab184df85fa8a7"},
+]
+alabaster = [
+ {file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"},
+ {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"},
+]
+altair = [
+ {file = "altair-4.1.0-py3-none-any.whl", hash = "sha256:7748841a1bea8354173d1140bef6d3b58bea21d201f562528e9599ea384feb7f"},
+ {file = "altair-4.1.0.tar.gz", hash = "sha256:3edd30d4f4bb0a37278b72578e7e60bc72045a8e6704179e2f4738e35bc12931"},
+]
+appdirs = [
+ {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
+ {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
+]
+argparse = [
+ {file = "argparse-1.4.0-py2.py3-none-any.whl", hash = "sha256:c31647edb69fd3d465a847ea3157d37bed1f95f19760b11a47aa91c04b666314"},
+ {file = "argparse-1.4.0.tar.gz", hash = "sha256:62b089a55be1d8949cd2bc7e0df0bddb9e028faefc8c32038cc84862aefdd6e4"},
+]
+asn1crypto = [
+ {file = "asn1crypto-1.4.0-py2.py3-none-any.whl", hash = "sha256:4bcdf33c861c7d40bdcd74d8e4dd7661aac320fcdf40b9a3f95b4ee12fde2fa8"},
+ {file = "asn1crypto-1.4.0.tar.gz", hash = "sha256:f4f6e119474e58e04a2b1af817eb585b4fd72bdd89b998624712b5c99be7641c"},
+]
+asterisk = [
+ {file = "asterisk-0.0.8.tar.gz", hash = "sha256:a7813896f355f8ed0ca1bdea05938a10c2788255332fc826cf87a4cb34308f37"},
+]
+attrs = [
+ {file = "attrs-19.3.0-py2.py3-none-any.whl", hash = "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c"},
+ {file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"},
+]
+babel = [
+ {file = "Babel-2.3.4-py2.py3-none-any.whl", hash = "sha256:3318ed2960240d61cbc6558858ee00c10eed77a6508c4d1ed8e6f7f48399c975"},
+ {file = "Babel-2.3.4.tar.gz", hash = "sha256:c535c4403802f6eb38173cd4863e419e2274921a01a8aad8a5b497c131c62875"},
+]
+bcrypt = [
+ {file = "bcrypt-3.1.7-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:d7bdc26475679dd073ba0ed2766445bb5b20ca4793ca0db32b399dccc6bc84b7"},
+ {file = "bcrypt-3.1.7-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:69361315039878c0680be456640f8705d76cb4a3a3fe1e057e0f261b74be4b31"},
+ {file = "bcrypt-3.1.7-cp27-cp27m-win32.whl", hash = "sha256:5432dd7b34107ae8ed6c10a71b4397f1c853bd39a4d6ffa7e35f40584cffd161"},
+ {file = "bcrypt-3.1.7-cp27-cp27m-win_amd64.whl", hash = "sha256:9fe92406c857409b70a38729dbdf6578caf9228de0aef5bc44f859ffe971a39e"},
+ {file = "bcrypt-3.1.7-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:763669a367869786bb4c8fcf731f4175775a5b43f070f50f46f0b59da45375d0"},
+ {file = "bcrypt-3.1.7-cp34-abi3-macosx_10_6_intel.whl", hash = "sha256:a190f2a5dbbdbff4b74e3103cef44344bc30e61255beb27310e2aec407766052"},
+ {file = "bcrypt-3.1.7-cp34-abi3-manylinux1_x86_64.whl", hash = "sha256:c9457fa5c121e94a58d6505cadca8bed1c64444b83b3204928a866ca2e599105"},
+ {file = "bcrypt-3.1.7-cp34-cp34m-win32.whl", hash = "sha256:8b10acde4e1919d6015e1df86d4c217d3b5b01bb7744c36113ea43d529e1c3de"},
+ {file = "bcrypt-3.1.7-cp34-cp34m-win_amd64.whl", hash = "sha256:cb93f6b2ab0f6853550b74e051d297c27a638719753eb9ff66d1e4072be67133"},
+ {file = "bcrypt-3.1.7-cp35-cp35m-win32.whl", hash = "sha256:6fe49a60b25b584e2f4ef175b29d3a83ba63b3a4df1b4c0605b826668d1b6be5"},
+ {file = "bcrypt-3.1.7-cp35-cp35m-win_amd64.whl", hash = "sha256:a595c12c618119255c90deb4b046e1ca3bcfad64667c43d1166f2b04bc72db09"},
+ {file = "bcrypt-3.1.7-cp36-cp36m-win32.whl", hash = "sha256:74a015102e877d0ccd02cdeaa18b32aa7273746914a6c5d0456dd442cb65b99c"},
+ {file = "bcrypt-3.1.7-cp36-cp36m-win_amd64.whl", hash = "sha256:0258f143f3de96b7c14f762c770f5fc56ccd72f8a1857a451c1cd9a655d9ac89"},
+ {file = "bcrypt-3.1.7-cp37-cp37m-win32.whl", hash = "sha256:19a4b72a6ae5bb467fea018b825f0a7d917789bcfe893e53f15c92805d187294"},
+ {file = "bcrypt-3.1.7-cp37-cp37m-win_amd64.whl", hash = "sha256:ff032765bb8716d9387fd5376d987a937254b0619eff0972779515b5c98820bc"},
+ {file = "bcrypt-3.1.7-cp38-cp38-win32.whl", hash = "sha256:ce4e4f0deb51d38b1611a27f330426154f2980e66582dc5f438aad38b5f24fc1"},
+ {file = "bcrypt-3.1.7-cp38-cp38-win_amd64.whl", hash = "sha256:6305557019906466fc42dbc53b46da004e72fd7a551c044a827e572c82191752"},
+ {file = "bcrypt-3.1.7.tar.gz", hash = "sha256:0b0069c752ec14172c5f78208f1863d7ad6755a6fae6fe76ec2c80d13be41e42"},
+]
+beautifulsoup4 = [
+ {file = "beautifulsoup4-4.9.1-py2-none-any.whl", hash = "sha256:e718f2342e2e099b640a34ab782407b7b676f47ee272d6739e60b8ea23829f2c"},
+ {file = "beautifulsoup4-4.9.1-py3-none-any.whl", hash = "sha256:a6237df3c32ccfaee4fd201c8f5f9d9df619b93121d01353a64a73ce8c6ef9a8"},
+ {file = "beautifulsoup4-4.9.1.tar.gz", hash = "sha256:73cc4d115b96f79c7d77c1c7f7a0a8d4c57860d1041df407dd1aae7f07a77fd7"},
+]
+bokeh = [
+ {file = "bokeh-1.1.0.tar.gz", hash = "sha256:70c944ccb99faea9c1bc2b77caba4dbcd884e083fc32511efbd6f895d7cb6832"},
+]
+boto = [
+ {file = "boto-2.49.0-py2.py3-none-any.whl", hash = "sha256:147758d41ae7240dc989f0039f27da8ca0d53734be0eb869ef16e3adcfa462e8"},
+ {file = "boto-2.49.0.tar.gz", hash = "sha256:ea0d3b40a2d852767be77ca343b58a9e3a4b00d9db440efb8da74b4e58025e5a"},
+]
+boto3 = [
+ {file = "boto3-1.9.102-py2.py3-none-any.whl", hash = "sha256:4605a0707e857f316a7b01766fb49350e7b3d922458aa9c870f6393ec6fa22ca"},
+ {file = "boto3-1.9.102.tar.gz", hash = "sha256:1f43d7a4865b75c4628a5084c2c32b00f356a9fd09f97574a8903c574356890a"},
+]
+botocore = [
+ {file = "botocore-1.12.253-py2.py3-none-any.whl", hash = "sha256:dc080aed4f9b220a9e916ca29ca97a9d37e8e1d296fe89cbaeef929bf0c8066b"},
+ {file = "botocore-1.12.253.tar.gz", hash = "sha256:3baf129118575602ada9926f5166d82d02273c250d0feb313fc270944b27c48b"},
+]
+cached-property = [
+ {file = "cached-property-1.5.1.tar.gz", hash = "sha256:9217a59f14a5682da7c4b8829deadbfc194ac22e9908ccf7c8820234e80a1504"},
+ {file = "cached_property-1.5.1-py2.py3-none-any.whl", hash = "sha256:3a026f1a54135677e7da5ce819b0c690f156f37976f3e30c5430740725203d7f"},
+]
+cachetools = [
+ {file = "cachetools-4.1.1-py3-none-any.whl", hash = "sha256:513d4ff98dd27f85743a8dc0e92f55ddb1b49e060c2d5961512855cda2c01a98"},
+ {file = "cachetools-4.1.1.tar.gz", hash = "sha256:bbaa39c3dede00175df2dc2b03d0cf18dd2d32a7de7beb68072d13043c9edb20"},
+]
+cerberus = [
+ {file = "Cerberus-1.3.2.tar.gz", hash = "sha256:302e6694f206dd85cb63f13fd5025b31ab6d38c99c50c6d769f8fa0b0f299589"},
+]
+certifi = [
+ {file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"},
+ {file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"},
+]
+cffi = [
+ {file = "cffi-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:66dd45eb9530e3dde8f7c009f84568bc7cac489b93d04ac86e3111fb46e470c2"},
+ {file = "cffi-1.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:4f53e4128c81ca3212ff4cf097c797ab44646a40b42ec02a891155cd7a2ba4d8"},
+ {file = "cffi-1.14.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:833401b15de1bb92791d7b6fb353d4af60dc688eaa521bd97203dcd2d124a7c1"},
+ {file = "cffi-1.14.1-cp27-cp27m-win32.whl", hash = "sha256:26f33e8f6a70c255767e3c3f957ccafc7f1f706b966e110b855bfe944511f1f9"},
+ {file = "cffi-1.14.1-cp27-cp27m-win_amd64.whl", hash = "sha256:b87dfa9f10a470eee7f24234a37d1d5f51e5f5fa9eeffda7c282e2b8f5162eb1"},
+ {file = "cffi-1.14.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:effd2ba52cee4ceff1a77f20d2a9f9bf8d50353c854a282b8760ac15b9833168"},
+ {file = "cffi-1.14.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bac0d6f7728a9cc3c1e06d4fcbac12aaa70e9379b3025b27ec1226f0e2d404cf"},
+ {file = "cffi-1.14.1-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:d6033b4ffa34ef70f0b8086fd4c3df4bf801fee485a8a7d4519399818351aa8e"},
+ {file = "cffi-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:8416ed88ddc057bab0526d4e4e9f3660f614ac2394b5e019a628cdfff3733849"},
+ {file = "cffi-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:892daa86384994fdf4856cb43c93f40cbe80f7f95bb5da94971b39c7f54b3a9c"},
+ {file = "cffi-1.14.1-cp35-cp35m-win32.whl", hash = "sha256:c991112622baee0ae4d55c008380c32ecfd0ad417bcd0417ba432e6ba7328caa"},
+ {file = "cffi-1.14.1-cp35-cp35m-win_amd64.whl", hash = "sha256:fcf32bf76dc25e30ed793145a57426064520890d7c02866eb93d3e4abe516948"},
+ {file = "cffi-1.14.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f960375e9823ae6a07072ff7f8a85954e5a6434f97869f50d0e41649a1c8144f"},
+ {file = "cffi-1.14.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a6d28e7f14ecf3b2ad67c4f106841218c8ab12a0683b1528534a6c87d2307af3"},
+ {file = "cffi-1.14.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:cda422d54ee7905bfc53ee6915ab68fe7b230cacf581110df4272ee10462aadc"},
+ {file = "cffi-1.14.1-cp36-cp36m-win32.whl", hash = "sha256:4a03416915b82b81af5502459a8a9dd62a3c299b295dcdf470877cb948d655f2"},
+ {file = "cffi-1.14.1-cp36-cp36m-win_amd64.whl", hash = "sha256:4ce1e995aeecf7cc32380bc11598bfdfa017d592259d5da00fc7ded11e61d022"},
+ {file = "cffi-1.14.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e23cb7f1d8e0f93addf0cae3c5b6f00324cccb4a7949ee558d7b6ca973ab8ae9"},
+ {file = "cffi-1.14.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:ddff0b2bd7edcc8c82d1adde6dbbf5e60d57ce985402541cd2985c27f7bec2a0"},
+ {file = "cffi-1.14.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:f90c2267101010de42f7273c94a1f026e56cbc043f9330acd8a80e64300aba33"},
+ {file = "cffi-1.14.1-cp37-cp37m-win32.whl", hash = "sha256:3cd2c044517f38d1b577f05927fb9729d3396f1d44d0c659a445599e79519792"},
+ {file = "cffi-1.14.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fa72a52a906425416f41738728268072d5acfd48cbe7796af07a923236bcf96"},
+ {file = "cffi-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:267adcf6e68d77ba154334a3e4fc921b8e63cbb38ca00d33d40655d4228502bc"},
+ {file = "cffi-1.14.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:d3148b6ba3923c5850ea197a91a42683f946dba7e8eb82dfa211ab7e708de939"},
+ {file = "cffi-1.14.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:98be759efdb5e5fa161e46d404f4e0ce388e72fbf7d9baf010aff16689e22abe"},
+ {file = "cffi-1.14.1-cp38-cp38-win32.whl", hash = "sha256:6923d077d9ae9e8bacbdb1c07ae78405a9306c8fd1af13bfa06ca891095eb995"},
+ {file = "cffi-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:b1d6ebc891607e71fd9da71688fcf332a6630b7f5b7f5549e6e631821c0e5d90"},
+ {file = "cffi-1.14.1.tar.gz", hash = "sha256:b2a2b0d276a136146e012154baefaea2758ef1f56ae9f4e01c612b0831e0bd2f"},
+]
+chardet = [
+ {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"},
+ {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"},
+]
+colorama = [
+ {file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"},
+ {file = "colorama-0.4.3.tar.gz", hash = "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"},
+]
+coloredlogs = [
+ {file = "coloredlogs-14.0-py2.py3-none-any.whl", hash = "sha256:346f58aad6afd48444c2468618623638dadab76e4e70d5e10822676f2d32226a"},
+ {file = "coloredlogs-14.0.tar.gz", hash = "sha256:a1fab193d2053aa6c0a97608c4342d031f1f93a3d1218432c59322441d31a505"},
+]
+compressed-rtf = [
+ {file = "compressed_rtf-1.0.6.tar.gz", hash = "sha256:c1c827f1d124d24608981a56e8b8691eb1f2a69a78ccad6440e7d92fde1781dd"},
+]
+cryptography = [
+ {file = "cryptography-2.6.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:6b9e0ae298ab20d371fc26e2129fd683cfc0cfde4d157c6341722de645146537"},
+ {file = "cryptography-2.6.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:9b069768c627f3f5623b1cbd3248c5e7e92aec62f4c98827059eed7053138cc9"},
+ {file = "cryptography-2.6.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9873a1760a274b620a135054b756f9f218fa61ca030e42df31b409f0fb738b6c"},
+ {file = "cryptography-2.6.1-cp27-cp27m-win32.whl", hash = "sha256:210210d9df0afba9e000636e97810117dc55b7157c903a55716bb73e3ae07705"},
+ {file = "cryptography-2.6.1-cp27-cp27m-win_amd64.whl", hash = "sha256:409c4653e0f719fa78febcb71ac417076ae5e20160aec7270c91d009837b9151"},
+ {file = "cryptography-2.6.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:acb424eaca214cb08735f1a744eceb97d014de6530c1ea23beb86d9c6f13c2ad"},
+ {file = "cryptography-2.6.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:2db34e5c45988f36f7a08a7ab2b69638994a8923853dec2d4af121f689c66dc8"},
+ {file = "cryptography-2.6.1-cp34-abi3-macosx_10_6_intel.whl", hash = "sha256:d4afbb0840f489b60f5a580a41a1b9c3622e08ecb5eec8614d4fb4cd914c4460"},
+ {file = "cryptography-2.6.1-cp34-abi3-manylinux1_i686.whl", hash = "sha256:9e4ce27a507e4886efbd3c32d120db5089b906979a4debf1d5939ec01b9dd6c5"},
+ {file = "cryptography-2.6.1-cp34-abi3-manylinux1_x86_64.whl", hash = "sha256:45a4f4cf4f4e6a55c8128f8b76b4c057027b27d4c67e3fe157fa02f27e37830d"},
+ {file = "cryptography-2.6.1-cp34-cp34m-win32.whl", hash = "sha256:6c4778afe50f413707f604828c1ad1ff81fadf6c110cb669579dea7e2e98a75e"},
+ {file = "cryptography-2.6.1-cp34-cp34m-win_amd64.whl", hash = "sha256:e603aa7bb52e4e8ed4119a58a03b60323918467ef209e6ff9db3ac382e5cf2c6"},
+ {file = "cryptography-2.6.1-cp35-cp35m-win32.whl", hash = "sha256:066f815f1fe46020877c5983a7e747ae140f517f1b09030ec098503575265ce1"},
+ {file = "cryptography-2.6.1-cp35-cp35m-win_amd64.whl", hash = "sha256:48eab46ef38faf1031e58dfcc9c3e71756a1108f4c9c966150b605d4a1a7f659"},
+ {file = "cryptography-2.6.1-cp36-cp36m-win32.whl", hash = "sha256:d9ed28030797c00f4bc43c86bf819266c76a5ea61d006cd4078a93ebf7da6bfd"},
+ {file = "cryptography-2.6.1-cp36-cp36m-win_amd64.whl", hash = "sha256:8c33fb99025d353c9520141f8bc989c2134a1f76bac6369cea060812f5b5c2bb"},
+ {file = "cryptography-2.6.1-cp37-cp37m-win32.whl", hash = "sha256:c8181c7d77388fe26ab8418bb088b1a1ef5fde058c6926790c8a0a3d94075a4a"},
+ {file = "cryptography-2.6.1-cp37-cp37m-win_amd64.whl", hash = "sha256:2afb83308dc5c5255149ff7d3fb9964f7c9ee3d59b603ec18ccf5b0a8852e2b1"},
+ {file = "cryptography-2.6.1.tar.gz", hash = "sha256:26c821cbeb683facb966045e2064303029d572a87ee69ca5a1bf54bf55f93ca6"},
+]
+cssselect = [
+ {file = "cssselect-1.1.0-py2.py3-none-any.whl", hash = "sha256:f612ee47b749c877ebae5bb77035d8f4202c6ad0f0fc1271b3c18ad6c4468ecf"},
+ {file = "cssselect-1.1.0.tar.gz", hash = "sha256:f95f8dedd925fd8f54edb3d2dfb44c190d9d18512377d3c1e2388d16126879bc"},
+]
+cssutils = [
+ {file = "cssutils-1.0.2-py3-none-any.whl", hash = "sha256:c74dbe19c92f5052774eadb15136263548dd013250f1ed1027988e7fef125c8d"},
+ {file = "cssutils-1.0.2.tar.gz", hash = "sha256:a2fcf06467553038e98fea9cfe36af2bf14063eb147a70958cfcaa8f5786acaf"},
+]
+cycler = [
+ {file = "cycler-0.10.0-py2.py3-none-any.whl", hash = "sha256:1d8a5ae1ff6c5cf9b93e8811e581232ad8920aeec647c37316ceac982b08cb2d"},
+ {file = "cycler-0.10.0.tar.gz", hash = "sha256:cd7b2d1018258d7247a71425e9f26463dfb444d411c39569972f4ce586b0c9d8"},
+]
+cython = [
+ {file = "Cython-0.29.21-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c541b2b49c6638f2b5beb9316726db84a8d1c132bf31b942dae1f9c7f6ad3b92"},
+ {file = "Cython-0.29.21-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:b8d8497091c1dc8705d1575c71e908a93b1f127a174b2d472020f3d84263ac28"},
+ {file = "Cython-0.29.21-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:695a6bcaf9e12b1e471dfce96bbecf22a1487adc2ac6106b15960a2b51b97f5d"},
+ {file = "Cython-0.29.21-cp27-cp27m-win32.whl", hash = "sha256:171b9f70ceafcec5852089d0f9c1e75b0d554f46c882cd4e2e4acaba9bd7d148"},
+ {file = "Cython-0.29.21-cp27-cp27m-win_amd64.whl", hash = "sha256:539e59949aab4955c143a468810123bf22d3e8556421e1ce2531ed4893914ca0"},
+ {file = "Cython-0.29.21-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:e93acd1f603a0c1786e0841f066ae7cef014cf4750e3cd06fd03cfdf46361419"},
+ {file = "Cython-0.29.21-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:2922e3031ba9ebbe7cb9200b585cc33b71d66023d78450dcb883f824f4969371"},
+ {file = "Cython-0.29.21-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:497841897942f734b0abc2dead2d4009795ee992267a70a23485fd0e937edc0b"},
+ {file = "Cython-0.29.21-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:0ac10bf476476a9f7ef61ec6e44c280ef434473124ad31d3132b720f7b0e8d2a"},
+ {file = "Cython-0.29.21-cp34-cp34m-win32.whl", hash = "sha256:31c71a615f38401b0dc1f2a5a9a6c421ffd8908c4cd5bbedc4014c1b876488e8"},
+ {file = "Cython-0.29.21-cp34-cp34m-win_amd64.whl", hash = "sha256:c4b78356074fcaac04ecb4de289f11d506e438859877670992ece11f9c90f37b"},
+ {file = "Cython-0.29.21-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:b2f9172e4d6358f33ecce6a4339b5960f9f83eab67ea244baa812737793826b7"},
+ {file = "Cython-0.29.21-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:856c7fb31d247ce713d60116375e1f8153d0291ab5e92cca7d8833a524ba9991"},
+ {file = "Cython-0.29.21-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:715294cd2246b39a8edca464a8366eb635f17213e4a6b9e74e52d8b877a8cb63"},
+ {file = "Cython-0.29.21-cp35-cp35m-win32.whl", hash = "sha256:23f3a00b843a19de8bb4468b087db5b413a903213f67188729782488d67040e0"},
+ {file = "Cython-0.29.21-cp35-cp35m-win_amd64.whl", hash = "sha256:ccb77faeaad99e99c6c444d04862c6cf604204fe0a07d4c8f9cbf2c9012d7d5a"},
+ {file = "Cython-0.29.21-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e272ed97d20b026f4f25a012b25d7d7672a60e4f72b9ca385239d693cd91b2d5"},
+ {file = "Cython-0.29.21-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:8c6e25e9cc4961bb2abb1777c6fa9d0fa2d9b014beb3276cebe69996ff162b78"},
+ {file = "Cython-0.29.21-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:57ead89128dee9609119c93d3926c7a2add451453063147900408a50144598c6"},
+ {file = "Cython-0.29.21-cp36-cp36m-win32.whl", hash = "sha256:0e25c209c75df8785480dcef85db3d36c165dbc0f4c503168e8763eb735704f2"},
+ {file = "Cython-0.29.21-cp36-cp36m-win_amd64.whl", hash = "sha256:a0674f246ad5e1571ef29d4c5ec1d6ecabe9e6c424ad0d6fee46b914d5d24d69"},
+ {file = "Cython-0.29.21-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5da187bebe38030325e1c0b5b8a804d489410be2d384c0ef3ba39493c67eb51e"},
+ {file = "Cython-0.29.21-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:9ce5e5209f8406ffc2b058b1293cce7a954911bb7991e623564d489197c9ba30"},
+ {file = "Cython-0.29.21-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5e545a48f919e40079b0efe7b0e081c74b96f9ef25b9c1ff4cdbd95764426b58"},
+ {file = "Cython-0.29.21-cp37-cp37m-win32.whl", hash = "sha256:c8435959321cf8aec867bbad54b83b7fb8343204b530d85d9ea7a1f5329d5ac2"},
+ {file = "Cython-0.29.21-cp37-cp37m-win_amd64.whl", hash = "sha256:540b3bee0711aac2e99bda4fa0a46dbcd8c74941666bfc1ef9236b1a64eeffd9"},
+ {file = "Cython-0.29.21-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:93f5fed1c9445fb7afe20450cdaf94b0e0356d47cc75008105be89c6a2e417b1"},
+ {file = "Cython-0.29.21-cp38-cp38-manylinux1_i686.whl", hash = "sha256:9207fdedc7e789a3dcaca628176b80c82fbed9ae0997210738cbb12536a56699"},
+ {file = "Cython-0.29.21-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:603b9f1b8e93e8b494d3e89320c410679e21018e48b6cbc77280f5db71f17dc0"},
+ {file = "Cython-0.29.21-cp38-cp38-win32.whl", hash = "sha256:473df5d5e400444a36ed81c6596f56a5b52a3481312d0a48d68b777790f730ae"},
+ {file = "Cython-0.29.21-cp38-cp38-win_amd64.whl", hash = "sha256:b8a8a31b9e8860634adbca30fea1d0c7f08e208b3d7611f3e580e5f20992e5d7"},
+ {file = "Cython-0.29.21-py2.py3-none-any.whl", hash = "sha256:5c4276fdcbccdf1e3c1756c7aeb8395e9a36874fa4d30860e7694f43d325ae13"},
+ {file = "Cython-0.29.21.tar.gz", hash = "sha256:e57acb89bd55943c8d8bf813763d20b9099cc7165c0f16b707631a7654be9cad"},
+]
+dateparser = [
+ {file = "dateparser-0.7.6-py2.py3-none-any.whl", hash = "sha256:7552c994f893b5cb8fcf103b4cd2ff7f57aab9bfd2619fdf0cf571c0740fd90b"},
+ {file = "dateparser-0.7.6.tar.gz", hash = "sha256:e875efd8c57c85c2d02b238239878db59ff1971f5a823457fcc69e493bf6ebfa"},
+]
+ddt = [
+ {file = "ddt-1.2.0-py2.py3-none-any.whl", hash = "sha256:68fe764903149edf84b02952c9a67792c9a62d104c730588fe8b1ee40944b33d"},
+ {file = "ddt-1.2.0.tar.gz", hash = "sha256:898364fc34b27981b925171a0011c174c94633cb678eb1fac05fe7a234c7912c"},
+]
+debtcollector = [
+ {file = "debtcollector-2.2.0-py3-none-any.whl", hash = "sha256:34663e5de257c67bf38827cfbea259c4d4ad27eba6b5a9d9242cb54076bfb4ad"},
+ {file = "debtcollector-2.2.0.tar.gz", hash = "sha256:787981f4d235841bf6eb0467e23057fb1ac7ee24047c32028a8498b9128b6829"},
+]
+decorator = [
+ {file = "decorator-4.0.10-py2.py3-none-any.whl", hash = "sha256:5aff536ed9a65c99e8465c774d5859e56e52300aea0a5012c7a1c4a781fbdddb"},
+ {file = "decorator-4.0.10.tar.gz", hash = "sha256:9c6e98edcb33499881b86ede07d9968c81ab7c769e28e9af24075f0a5379f070"},
+]
+defusedxml = [
+ {file = "defusedxml-0.6.0-py2.py3-none-any.whl", hash = "sha256:6687150770438374ab581bb7a1b327a847dd9c5749e396102de3fad4e8a3ef93"},
+ {file = "defusedxml-0.6.0.tar.gz", hash = "sha256:f684034d135af4c6cbb949b8a4d2ed61634515257a67299e5f940fbaa34377f5"},
+]
+delorean = [
+ {file = "Delorean-1.0.0.tar.gz", hash = "sha256:fe67786e12338523848bec5588a658c4d425e12d53eb51cfef870bec8f576134"},
+]
+demjson = [
+ {file = "demjson-2.2.4.tar.gz", hash = "sha256:31de2038a0fdd9c4c11f8bf3b13fe77bc2a128307f965c8d5fb4dc6d6f6beb79"},
+]
+dnspython = [
+ {file = "dnspython-2.0.0-py3-none-any.whl", hash = "sha256:40bb3c24b9d4ec12500f0124288a65df232a3aa749bb0c39734b782873a2544d"},
+ {file = "dnspython-2.0.0.zip", hash = "sha256:044af09374469c3a39eeea1a146e8cac27daec951f1f1f157b1962fc7cb9d1b7"},
+]
+docutils = [
+ {file = "docutils-0.12-py3-none-any.whl", hash = "sha256:dcebd4928112631626f4c4d0df59787c748404e66dda952110030ea883d3b8cd"},
+ {file = "docutils-0.12.tar.gz", hash = "sha256:c7db717810ab6965f66c8cf0398a98c9d8df982da39b4cd7f162911eb89596fa"},
+]
+ebaysdk = [
+ {file = "ebaysdk-2.1.5-py3.7.egg", hash = "sha256:55360edc239037c3a0aaaf3f39889ddea666b8b1d97c893b2c3fd2269d868b45"},
+ {file = "ebaysdk-2.1.5.tar.gz", hash = "sha256:78458e1ea4a0fc7d693c26de363069696393767e4aa9689fd38efbfb08409acd"},
+]
+email-validator = [
+ {file = "email_validator-1.1.1-py2.py3-none-any.whl", hash = "sha256:5f246ae8d81ce3000eade06595b7bb55a4cf350d559e890182a1466a21f25067"},
+ {file = "email_validator-1.1.1.tar.gz", hash = "sha256:63094045c3e802c3d3d575b18b004a531c36243ca8d1cec785ff6bfcb04185bb"},
+]
+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"},
+]
+executor = [
+ {file = "executor-23.1-py2.py3-none-any.whl", hash = "sha256:0104bb9d7f5a3bd00642ad031ad2241d0663988bcb3da1c976e763db29b0d6ae"},
+ {file = "executor-23.1.tar.gz", hash = "sha256:c8d4bba81d80c16612fcbcefd45439f45f82daa1d6e24c44b1832f3bb4649d5f"},
+]
+extract-msg = [
+ {file = "extract_msg-0.25.3-py2.py3-none-any.whl", hash = "sha256:6c2d146cd508f42c6ec227e9799231668a3d4b498235cec0d0e1d2f64d691203"},
+ {file = "extract_msg-0.25.3.tar.gz", hash = "sha256:fcfd4dc78b98a821ec3de4f85fc2d1f3a2ef2a77f3d2eb38c9148e830abaa1ba"},
+]
+factur-x = [
+ {file = "factur-x-1.12.tar.gz", hash = "sha256:423d29ab0f8816cdb93bab9ebef4b6d7841c7b2ee747397d5b009ef5afce44e3"},
+]
+fasteners = [
+ {file = "fasteners-0.15-py2.py3-none-any.whl", hash = "sha256:007e4d2b2d4a10093f67e932e5166722d2eab83b77724156e92ad013c6226574"},
+ {file = "fasteners-0.15.tar.gz", hash = "sha256:3a176da6b70df9bb88498e1a18a9e4a8579ed5b9141207762368a1017bf8f5ef"},
+]
+feedparser = [
+ {file = "feedparser-5.2.1.tar.bz2", hash = "sha256:ce875495c90ebd74b179855449040003a1beb40cd13d5f037a0654251e260b02"},
+ {file = "feedparser-5.2.1.tar.gz", hash = "sha256:bd030652c2d08532c034c27fcd7c85868e7fa3cb2b17f230a44a6bbc92519bf9"},
+ {file = "feedparser-5.2.1.zip", hash = "sha256:cd2485472e41471632ed3029d44033ee420ad0b57111db95c240c9160a85831c"},
+]
+freezegun = [
+ {file = "freezegun-0.3.11-py2.py3-none-any.whl", hash = "sha256:6cb82b276f83f2acce67f121dc2656f4df26c71e32238334eb071170b892a278"},
+ {file = "freezegun-0.3.11.tar.gz", hash = "sha256:e839b43bfbe8158b4d62bb97e6313d39f3586daf48e1314fb1083d2ef17700da"},
+]
+future = [
+ {file = "future-0.18.2.tar.gz", hash = "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"},
+]
+genshi = [
+ {file = "Genshi-0.7.3-py3-none-any.whl", hash = "sha256:5e92e278ca1ea395349a451d54fc81dc3c1b543c48939a15bd36b7b3335e1560"},
+ {file = "Genshi-0.7.3.tar.gz", hash = "sha256:7933c95151d7dd2124a2b4c8dd85bb6aec881ca17c0556da0b40e56434b313a0"},
+]
+geojson = [
+ {file = "geojson-2.4.1-py2.py3-none-any.whl", hash = "sha256:b2bfb5c8e6b4b0c55dd139996317145aa8526146b3f8570586f9613c527a648a"},
+ {file = "geojson-2.4.1.tar.gz", hash = "sha256:b175e00a76d923d6e7409de0784c147adcdd6e04b311b1d405895a4db3612c9d"},
+]
+gevent = [
+ {file = "gevent-1.3.4-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:7ac5a4945fc47e3824d55bb50b6dd65823868e87fac841bea5762f79b9d22019"},
+ {file = "gevent-1.3.4-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:3498fec10e3695f3ad31253857c624435378c6a47969babb54a83ac0101615d3"},
+ {file = "gevent-1.3.4-cp27-cp27m-win32.whl", hash = "sha256:22187d0aba6506b57075dd05d0df495b04bfd4b047bbf776eeaac93117a6e9d2"},
+ {file = "gevent-1.3.4-cp27-cp27m-win_amd64.whl", hash = "sha256:16143db7b760d9b512edfaf4d0bbef01cf0391e773362c43084901e3ecb892d5"},
+ {file = "gevent-1.3.4-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:6c41413e1eb0b7bf77dcea42ff276e62903bfdc62cb936d71458d338b9edc9a6"},
+ {file = "gevent-1.3.4-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:7bb0e1ef3adfea008688617fedb1741009856f98e26133983646203c718f7f39"},
+ {file = "gevent-1.3.4-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:a72a23829ce8eb18086ec6f855715c3f52d3c1e12b83fd040d9fb854e77c0565"},
+ {file = "gevent-1.3.4-cp34-cp34m-win32.whl", hash = "sha256:72f7cab120e2af89d3a9d6c526e49da5c0b6c94d47e23ab7a26ae8471ee97ffb"},
+ {file = "gevent-1.3.4-cp34-cp34m-win_amd64.whl", hash = "sha256:c7e5f8a6bf865ef507db27f85376808991d3189df185864a5ee326d97e144ec4"},
+ {file = "gevent-1.3.4-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:33320f60be19a865396a7f5e10c15b14e338790ae807c97c90edc990d644dc1c"},
+ {file = "gevent-1.3.4-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:a1f32f0b01ceb15f93b2914b7057acb008c5173181813424621dc444f73c00e2"},
+ {file = "gevent-1.3.4-cp35-cp35m-win32.whl", hash = "sha256:57729118fbcf0f39ecf721ae9b318a4a738eb5d9b972af6c6c8c96303e30f011"},
+ {file = "gevent-1.3.4-cp35-cp35m-win_amd64.whl", hash = "sha256:15dbcc07cdd09f87b9814ee26483ec49e0d71fdc65d7a61b21c2c56bbb550168"},
+ {file = "gevent-1.3.4-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:3c9fbc0dac62e552dc5d03bb67ceaefc5f74d7b4ac04a4bf797cdb0a4438b1db"},
+ {file = "gevent-1.3.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:00a45774ad6e7a8641af5db011807f53c1f0e0bc62cbdcab83e4db18e6201b6e"},
+ {file = "gevent-1.3.4-cp36-cp36m-win32.whl", hash = "sha256:a51456f842f7de83fff473a0230e313e44ac6fa83e492412e696924f417088b8"},
+ {file = "gevent-1.3.4-cp36-cp36m-win_amd64.whl", hash = "sha256:1a0d422d6c960c36088201d4bbc925dfde87dc4a4e442bf2e4d36ae455f24a96"},
+ {file = "gevent-1.3.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e9d64081e419eb8a268edaa90bba95fb4c78a6278d2105dcc080b24b42679535"},
+ {file = "gevent-1.3.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:cf707886b9b45e56114c6f5522fc556058de5b5bf8674b609e82dfa2f9633c41"},
+ {file = "gevent-1.3.4-pp259-pypy_41-win32.whl", hash = "sha256:d83370528327364354cfb54c96ca401853599bd7a15f382e6962fd8318cede50"},
+ {file = "gevent-1.3.4-pp260-pypy_41-macosx_10_13_x86_64.whl", hash = "sha256:8c41ef269bc743b5bb88a4553627cd4611be5c59589d5390e29956a8d3ab8623"},
+ {file = "gevent-1.3.4.tar.gz", hash = "sha256:53c4dc705886d028f5d81e698b1d1479994a421498cd6529cb9711b5e2a84f74"},
+]
+gitdb = [
+ {file = "gitdb-4.0.5-py3-none-any.whl", hash = "sha256:91f36bfb1ab7949b3b40e23736db18231bf7593edada2ba5c3a174a7b23657ac"},
+ {file = "gitdb-4.0.5.tar.gz", hash = "sha256:c9e1f2d0db7ddb9a704c2a0217be31214e91a4fe1dea1efad19ae42ba0c285c9"},
+]
+gitpython = [
+ {file = "GitPython-3.1.7-py3-none-any.whl", hash = "sha256:fa3b92da728a457dd75d62bb5f3eb2816d99a7fe6c67398e260637a40e3fafb5"},
+ {file = "GitPython-3.1.7.tar.gz", hash = "sha256:2db287d71a284e22e5c2846042d0602465c7434d910406990d5b74df4afb0858"},
+]
+giturlparse = [
+ {file = "giturlparse-0.9.2-py2.py3-none-any.whl", hash = "sha256:8025143dd297122d8ecf96006f85a9e81c3c491b0ec5eebbba608488edbb289b"},
+ {file = "giturlparse-0.9.2.tar.gz", hash = "sha256:7d923e9f4fa60b112cd306a19f5b4fe221a6f5fa9f34b48e6607e54ab7909cd4"},
+]
+greenlet = [
+ {file = "greenlet-0.4.13-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:50643fd6d54fd919f9a0a577c5f7b71f5d21f0959ab48767bd4bb73ae0839500"},
+ {file = "greenlet-0.4.13-cp27-cp27m-win32.whl", hash = "sha256:b6ef0cabaf5a6ecb5ac122e689d25ba12433a90c7b067b12e5f28bdb7fb78254"},
+ {file = "greenlet-0.4.13-cp27-cp27m-win_amd64.whl", hash = "sha256:fcfadaf4bf68a27e5dc2f42cbb2f4b4ceea9f05d1d0b8f7787e640bed2801634"},
+ {file = "greenlet-0.4.13-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:c7b04a6dc74087b1598de8d713198de4718fa30ec6cbb84959b26426c198e041"},
+ {file = "greenlet-0.4.13-cp33-cp33m-manylinux1_x86_64.whl", hash = "sha256:b417bb7ff680d43e7bd7a13e2e08956fa6acb11fd432f74c97b7664f8bdb6ec1"},
+ {file = "greenlet-0.4.13-cp33-cp33m-win32.whl", hash = "sha256:769b740aeebd584cd59232be84fdcaf6270b8adc356596cdea5b2152c82caaac"},
+ {file = "greenlet-0.4.13-cp33-cp33m-win_amd64.whl", hash = "sha256:c2de19c88bdb0366c976cc125dca1002ec1b346989d59524178adfd395e62421"},
+ {file = "greenlet-0.4.13-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:5b49b3049697aeae17ef7bf21267e69972d9e04917658b4e788986ea5cc518e8"},
+ {file = "greenlet-0.4.13-cp34-cp34m-win32.whl", hash = "sha256:09ef2636ea35782364c830f07127d6c7a70542b178268714a9a9ba16318e7e8b"},
+ {file = "greenlet-0.4.13-cp34-cp34m-win_amd64.whl", hash = "sha256:f8f2a0ae8de0b49c7b5b2daca4f150fdd9c1173e854df2cce3b04123244f9f45"},
+ {file = "greenlet-0.4.13-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:1b7df09c6598f5cfb40f843ade14ed1eb40596e75cd79b6fa2efc750ba01bb01"},
+ {file = "greenlet-0.4.13-cp35-cp35m-win32.whl", hash = "sha256:75c413551a436b462d5929255b6dc9c0c3c2b25cbeaee5271a56c7fda8ca49c0"},
+ {file = "greenlet-0.4.13-cp35-cp35m-win_amd64.whl", hash = "sha256:58798b5d30054bb4f6cf0f712f08e6092df23a718b69000786634a265e8911a9"},
+ {file = "greenlet-0.4.13-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:42118bf608e0288e35304b449a2d87e2ba77d1e373e8aa221ccdea073de026fa"},
+ {file = "greenlet-0.4.13-cp36-cp36m-win32.whl", hash = "sha256:ad2383d39f13534f3ca5c48fe1fc0975676846dc39c2cece78c0f1f9891418e0"},
+ {file = "greenlet-0.4.13-cp36-cp36m-win_amd64.whl", hash = "sha256:1fff21a2da5f9e03ddc5bd99131a6b8edf3d7f9d6bc29ba21784323d17806ed7"},
+ {file = "greenlet-0.4.13-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:a1852b51b06d1367e2d70321f6801844f5122852c9e5169bdfdff3f4d81aae30"},
+ {file = "greenlet-0.4.13.tar.gz", hash = "sha256:0fef83d43bf87a5196c91e73cb9772f945a4caaff91242766c5916d1dd1381e4"},
+]
+html2text = [
+ {file = "html2text-2016.9.19.tar.gz", hash = "sha256:554ef5fd6c6cf6e3e4f725a62a3e9ec86a0e4d33cd0928136d1c79dbeb7b2d55"},
+]
+humanfriendly = [
+ {file = "humanfriendly-8.2-py2.py3-none-any.whl", hash = "sha256:e78960b31198511f45fd455534ae7645a6207d33e512d2e842c766d15d9c8080"},
+ {file = "humanfriendly-8.2.tar.gz", hash = "sha256:bf52ec91244819c780341a3438d5d7b09f431d3f113a475147ac9b7b167a3d12"},
+]
+humanize = [
+ {file = "humanize-2.5.0-py3-none-any.whl", hash = "sha256:89062c6db8601693b7d223443d0d7529aa9577df43a1387ddd4b9c273abb4a51"},
+ {file = "humanize-2.5.0.tar.gz", hash = "sha256:8a68bd9bccb899fd9bfb1e6d96c1e84e4475551cc9a5b5bdbd69b9b1cfd19c80"},
+]
+idna = [
+ {file = "idna-2.7-py2.py3-none-any.whl", hash = "sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e"},
+ {file = "idna-2.7.tar.gz", hash = "sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16"},
+]
+imagesize = [
+ {file = "imagesize-1.2.0-py2.py3-none-any.whl", hash = "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1"},
+ {file = "imagesize-1.2.0.tar.gz", hash = "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1"},
+]
+imapclient = [
+ {file = "IMAPClient-2.1.0-py2.py3-none-any.whl", hash = "sha256:3eeb97b9aa8faab0caa5024d74bfde59408fbd542781246f6960873c7bf0dd01"},
+ {file = "IMAPClient-2.1.0.zip", hash = "sha256:60ba79758cc9f13ec910d7a3df9acaaf2bb6c458720d9a02ec33a41352fd1b99"},
+]
+importlib-metadata = [
+ {file = "importlib_metadata-1.7.0-py2.py3-none-any.whl", hash = "sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070"},
+ {file = "importlib_metadata-1.7.0.tar.gz", hash = "sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83"},
+]
+invoice2data = [
+ {file = "invoice2data-0.3.5-py3.6.egg", hash = "sha256:5668b09cc6bcbc1c9acd03a699b0ddb5a2d481a8550977abb3313616752988cb"},
+ {file = "invoice2data-0.3.5.tar.gz", hash = "sha256:c58ec7e46224dc3ffae72b17c05a5347fee1a13d9c17f6ee95f8bd16d1a2e791"},
+]
+iscompatible = [
+ {file = "iscompatible-0.1.1.tar.gz", hash = "sha256:0ef45bd23569df4ba01d66e4ab7a25f07db934bba235e706a85d26417d676f83"},
+]
+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"},
+]
+isodate = [
+ {file = "isodate-0.6.0-py2.py3-none-any.whl", hash = "sha256:aa4d33c06640f5352aca96e4b81afd8ab3b47337cc12089822d6f322ac772c81"},
+ {file = "isodate-0.6.0.tar.gz", hash = "sha256:2e364a3d5759479cdb2d37cce6b9376ea504db2ff90252a2e5b7cc89cc9ff2d8"},
+]
+jdcal = [
+ {file = "jdcal-1.4.1-py2.py3-none-any.whl", hash = "sha256:1abf1305fce18b4e8aa248cf8fe0c56ce2032392bc64bbd61b5dff2a19ec8bba"},
+ {file = "jdcal-1.4.1.tar.gz", hash = "sha256:472872e096eb8df219c23f2689fc336668bdb43d194094b5cc1707e1640acfc8"},
+]
+jinja2 = [
+ {file = "Jinja2-2.10.1-py2.py3-none-any.whl", hash = "sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"},
+ {file = "Jinja2-2.10.1.tar.gz", hash = "sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013"},
+]
+jira = [
+ {file = "jira-2.0.0-py2.py3-none-any.whl", hash = "sha256:9adeead4d5f5a6aff74c630787f8bd2d4b0e154f3a3036641298064e91b2d25d"},
+ {file = "jira-2.0.0.tar.gz", hash = "sha256:e2a94adff98e45b29ded030adc76103eab34fa7d4d57303f211f572bedba0e93"},
+]
+jmespath = [
+ {file = "jmespath-0.10.0-py2.py3-none-any.whl", hash = "sha256:cdf6525904cc597730141d61b36f2e4b8ecc257c420fa2f4549bac2c2d0cb72f"},
+ {file = "jmespath-0.10.0.tar.gz", hash = "sha256:b85d0567b8666149a93172712e68920734333c0ce7e89b78b3e987f71e5ed4f9"},
+]
+jsonschema = [
+ {file = "jsonschema-3.2.0-py2.py3-none-any.whl", hash = "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163"},
+ {file = "jsonschema-3.2.0.tar.gz", hash = "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"},
+]
+jtutils = [
+ {file = "jtutils-0.0.6.tar.gz", hash = "sha256:87f23b22dd1f5b77f3fd32f992335447c45dd1118e34e502d43cab35e1d2a554"},
+]
+keystoneauth1 = [
+ {file = "keystoneauth1-3.14.0-py2.py3-none-any.whl", hash = "sha256:b1e3910e09b01f88e84ce4c873f271f2b076b4ad266c2815c16ee3aef8319192"},
+ {file = "keystoneauth1-3.14.0.tar.gz", hash = "sha256:b14f363d02142177c968cfffeb9eb37113682c03ac3c65d483424e203dd602c3"},
+]
+kiwisolver = [
+ {file = "kiwisolver-1.2.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:443c2320520eda0a5b930b2725b26f6175ca4453c61f739fef7a5847bd262f74"},
+ {file = "kiwisolver-1.2.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:efcf3397ae1e3c3a4a0a0636542bcad5adad3b1dd3e8e629d0b6e201347176c8"},
+ {file = "kiwisolver-1.2.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:fccefc0d36a38c57b7bd233a9b485e2f1eb71903ca7ad7adacad6c28a56d62d2"},
+ {file = "kiwisolver-1.2.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:be046da49fbc3aa9491cc7296db7e8d27bcf0c3d5d1a40259c10471b014e4e0c"},
+ {file = "kiwisolver-1.2.0-cp36-none-win32.whl", hash = "sha256:60a78858580761fe611d22127868f3dc9f98871e6fdf0a15cc4203ed9ba6179b"},
+ {file = "kiwisolver-1.2.0-cp36-none-win_amd64.whl", hash = "sha256:556da0a5f60f6486ec4969abbc1dd83cf9b5c2deadc8288508e55c0f5f87d29c"},
+ {file = "kiwisolver-1.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7cc095a4661bdd8a5742aaf7c10ea9fac142d76ff1770a0f84394038126d8fc7"},
+ {file = "kiwisolver-1.2.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:c955791d80e464da3b471ab41eb65cf5a40c15ce9b001fdc5bbc241170de58ec"},
+ {file = "kiwisolver-1.2.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:603162139684ee56bcd57acc74035fceed7dd8d732f38c0959c8bd157f913fec"},
+ {file = "kiwisolver-1.2.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:63f55f490b958b6299e4e5bdac66ac988c3d11b7fafa522800359075d4fa56d1"},
+ {file = "kiwisolver-1.2.0-cp37-none-win32.whl", hash = "sha256:03662cbd3e6729f341a97dd2690b271e51a67a68322affab12a5b011344b973c"},
+ {file = "kiwisolver-1.2.0-cp37-none-win_amd64.whl", hash = "sha256:4eadb361baf3069f278b055e3bb53fa189cea2fd02cb2c353b7a99ebb4477ef1"},
+ {file = "kiwisolver-1.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c31bc3c8e903d60a1ea31a754c72559398d91b5929fcb329b1c3a3d3f6e72113"},
+ {file = "kiwisolver-1.2.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:d52b989dc23cdaa92582ceb4af8d5bcc94d74b2c3e64cd6785558ec6a879793e"},
+ {file = "kiwisolver-1.2.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:e586b28354d7b6584d8973656a7954b1c69c93f708c0c07b77884f91640b7657"},
+ {file = "kiwisolver-1.2.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:38d05c9ecb24eee1246391820ed7137ac42a50209c203c908154782fced90e44"},
+ {file = "kiwisolver-1.2.0-cp38-none-win32.whl", hash = "sha256:d069ef4b20b1e6b19f790d00097a5d5d2c50871b66d10075dab78938dc2ee2cf"},
+ {file = "kiwisolver-1.2.0-cp38-none-win_amd64.whl", hash = "sha256:18d749f3e56c0480dccd1714230da0f328e6e4accf188dd4e6884bdd06bf02dd"},
+ {file = "kiwisolver-1.2.0.tar.gz", hash = "sha256:247800260cd38160c362d211dcaf4ed0f7816afb5efe56544748b21d6ad6d17f"},
+]
+lasso = [
+ {file = "lasso-0.0.5.tar.gz", hash = "sha256:e64abaeef6f3e3e5f669cc44ca1423e69ad59360625269f50ee6ecb2172aa824"},
+]
+leven = [
+ {file = "leven-1.0.4.tar.gz", hash = "sha256:732474a3b9e94003aab61fd57eb2cbdaf0ed32f9a85b63073bcc4fa1ed5d0aff"},
+]
+libsass = [
+ {file = "libsass-0.12.3-cp27-cp27m-macosx_10_11_x86_64.whl", hash = "sha256:ff07c2c55f9d73d9f57cded30138ff99dfbb9fe7fbc71a4bbb43aa067ad2beed"},
+ {file = "libsass-0.12.3-cp27-cp27m-win32.whl", hash = "sha256:2fb999d978e9cc8f7459f8f07a8acf9fc03d6e9fa95fcf98169bf0a5ede81eb6"},
+ {file = "libsass-0.12.3-cp27-cp27m-win_amd64.whl", hash = "sha256:d2b77e43726cd658b1bc13f1a2df543dc34c9f945a9144faecc88ca03fe581ff"},
+ {file = "libsass-0.12.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:edb366b784c58c635ace69ef392e5ad3a42690aeac80d43521c64e0ee7706331"},
+ {file = "libsass-0.12.3-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:ebf413799057a4dd59d85ceb533935f171117565053341e3714e4cb05253bbbf"},
+ {file = "libsass-0.12.3-cp34-cp34m-win32.whl", hash = "sha256:815d60626b329db2943c5d331a5b74d36eb2e441047ae2bd6ad8d1b2c14cfc5d"},
+ {file = "libsass-0.12.3-cp34-cp34m-win_amd64.whl", hash = "sha256:cd20479d80cdb49ba7007611d8a9a7004579d54552e010277764c19d82233a51"},
+ {file = "libsass-0.12.3-cp35-cp35m-macosx_10_12_x86_64.whl", hash = "sha256:38e9b9b08d299793fffa7b5003d473a6c537e495117f2c44787e3437a5e38f90"},
+ {file = "libsass-0.12.3-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:28a490f350d38fa3a16da8a52e5ae685e71c8938a7b87cf2d58aee892f30c756"},
+ {file = "libsass-0.12.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:a1e3f19ef392badcc87ad75d8988b1720a4d4f5a506f2f52ebb781300c57136d"},
+ {file = "libsass-0.12.3-cp35-cp35m-win32.whl", hash = "sha256:64414697e65da4bfb47f0e11471bf5c79e1dd81e10e2e4b1a70f8ed1cdc33f5b"},
+ {file = "libsass-0.12.3-cp35-cp35m-win_amd64.whl", hash = "sha256:b8f8cf7c5ee16d217541e6b34def3f45286545077301adc4f54e94977fc69c9f"},
+ {file = "libsass-0.12.3-cp36-cp36m-macosx_10_12_x86_64.whl", hash = "sha256:c3ea0cbb36745b6cc10278539e0bf93a426f2f497306181fc6214193f493b8d5"},
+ {file = "libsass-0.12.3-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:ec659d4d2f60d95160e60f7f52d569bf1b29318018b6f07f8706ff6d4bc04de7"},
+ {file = "libsass-0.12.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:b064ccedb51b874c725a40f03fc952afd85bd6f5369d41aa74f393ff3388b9e1"},
+ {file = "libsass-0.12.3-cp36-cp36m-win32.whl", hash = "sha256:cf43ea1a69bab2836fc953e3d73f32d15efdcbf44c6082df36dd12c76ff59322"},
+ {file = "libsass-0.12.3-cp36-cp36m-win_amd64.whl", hash = "sha256:55cb32142f8c5f449edcb4baf040b553d59a604c8957aa177d26782a06d0eb6f"},
+ {file = "libsass-0.12.3.tar.gz", hash = "sha256:236762af9c693bb72ed92d65ff4a5a77d27af9494b6174fbec7e6308416673b0"},
+]
+lxml = [
+ {file = "lxml-4.2.3-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:8c39babd923c431dcf1e5874c0f778d3a5c745a62c3a9b6bd755efd489ee8a1d"},
+ {file = "lxml-4.2.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:24cf6f622a4d49851afcf63ac4f0f3419754d4e98a7a548ab48dd03c635d9bd3"},
+ {file = "lxml-4.2.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:bc1a36f95a6b3667c09b34995fc3a46a82e4cf0dc3e7ab281e4c77b15bd7af05"},
+ {file = "lxml-4.2.3-cp27-cp27m-win32.whl", hash = "sha256:ad5d5d8efed59e6b1d4c50c1eac59fb6ecec91b2073676af1e15fc4d43e9b6c5"},
+ {file = "lxml-4.2.3-cp27-cp27m-win_amd64.whl", hash = "sha256:0941f4313208c07734410414d8308812b044fd3fb98573454e3d3a0d2e201f3d"},
+ {file = "lxml-4.2.3-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:ccee7ebbb4735ebc341d347fca9ee09f2fa6c0580528c1414bc4e1d31372835c"},
+ {file = "lxml-4.2.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:be37b3f55b6d7d923f43bf74c356fc1878eb36e28505f38e198cb432c19c7b1a"},
+ {file = "lxml-4.2.3-cp33-cp33m-win32.whl", hash = "sha256:329a6d8b6d36f7d6f8b6c6a1db3b2c40f7e30a19d3caf62023c9d6a677c1b5e1"},
+ {file = "lxml-4.2.3-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:4651ea05939374cfb5fe87aab5271ed38c31ea47997e17ec3834b75b94bd9f15"},
+ {file = "lxml-4.2.3-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:21f427945f612ac75576632b1bb8c21233393c961f2da890d7be3927a4b6085f"},
+ {file = "lxml-4.2.3-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:c45bca5e544eb75f7500ffd730df72922eb878a2f0213b0dc5a5f357ded3a85d"},
+ {file = "lxml-4.2.3-cp34-cp34m-win32.whl", hash = "sha256:423cde55430a348bda6f1021faad7235c2a95a6bdb749e34824e5758f755817a"},
+ {file = "lxml-4.2.3-cp34-cp34m-win_amd64.whl", hash = "sha256:7ec3fe795582b75bb49bb1685ffc462dbe38d74312dac07ce386671a28b5316b"},
+ {file = "lxml-4.2.3-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:949ca5bc56d6cb73d956f4862ba06ad3c5d2808eac76304284f53ae0c8b2334a"},
+ {file = "lxml-4.2.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2e43b2e5b7d2b9abe6e0301eef2c2c122ab45152b968910eae68bdee2c4cfae0"},
+ {file = "lxml-4.2.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:a359893b01c30e949eae0e8a85671a593364c9f0b8162afe0cb97317af0953bf"},
+ {file = "lxml-4.2.3-cp35-cp35m-win32.whl", hash = "sha256:697c0f58ac637b11991a1bc92e07c34da4a72e2eda34d317d2c1c47e2f24c1b3"},
+ {file = "lxml-4.2.3-cp35-cp35m-win_amd64.whl", hash = "sha256:dc62c0840b2fc7753550b40405532a3e125c0d3761f34af948873393aa688160"},
+ {file = "lxml-4.2.3-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:0b18890aa5730f9d847bc5469e8820f782d72af9985a15a7552109a86b01c113"},
+ {file = "lxml-4.2.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:f7d9d5aa1c7e54167f1a3cba36b5c52c7c540f30952c9bd7d9302a1eda318424"},
+ {file = "lxml-4.2.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4be3bbfb2968d7da6e5c2cd4104fc5ec1caf9c0794f6cae724da5a53b4d9f5a3"},
+ {file = "lxml-4.2.3-cp36-cp36m-win32.whl", hash = "sha256:664dfd4384d886b239ef0d7ee5cff2b463831079d250528b10e394a322f141f9"},
+ {file = "lxml-4.2.3-cp36-cp36m-win_amd64.whl", hash = "sha256:2dc6705486b8abee1af9e2a3761e30a3cb19e8276f20ca7e137ee6611b93707c"},
+ {file = "lxml-4.2.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6ec908b4c8a4faa7fe1a0080768e2ce733f268b287dfefb723273fb34141475f"},
+ {file = "lxml-4.2.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:9f0daddeefb0791a600e6195441910bdf01eac470be596b9467e6122b51239a6"},
+ {file = "lxml-4.2.3.tar.gz", hash = "sha256:622f7e40faef13d232fb52003661f2764ce6cdef3edb0a59af7c1559e4cc36d1"},
+]
+mako = [
+ {file = "Mako-1.0.4.tar.gz", hash = "sha256:fed99dbe4d0ddb27a33ee4910d8708aca9ef1fe854e668387a9ab9a90cbf9059"},
+]
+markupsafe = [
+ {file = "MarkupSafe-0.23.tar.gz", hash = "sha256:a4ec1aff59b95a14b45eb2e23761a0179e98319da5a7eb76b56ea8cdc7b871c3"},
+]
+matplotlib = [
+ {file = "matplotlib-3.2.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a47abc48c7b81fe6e636dde8a58e49b13d87d140e0f448213a4879f4a3f73345"},
+ {file = "matplotlib-3.2.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:20bcd11efe194cd302bd0653cb025b8d16bcd80442359bfca8d49dc805f35ec8"},
+ {file = "matplotlib-3.2.2-cp36-cp36m-win32.whl", hash = "sha256:2a6d64336b547e25730b6221e7aadfb01a391a065d43b5f51f0b9d7f673d2dd2"},
+ {file = "matplotlib-3.2.2-cp36-cp36m-win_amd64.whl", hash = "sha256:4416825ebc9c1f135027a30e8d8aea0edcf45078ce767c7f7386737413cfb98f"},
+ {file = "matplotlib-3.2.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:465c752278d27895e23f1379d6fcfa3a2990643b803c25e3bc16a10641d2346a"},
+ {file = "matplotlib-3.2.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:81de040403a33bf3c68e9d4a40e26c8d24da00f7e3fadd845003b7e106785da7"},
+ {file = "matplotlib-3.2.2-cp37-cp37m-win32.whl", hash = "sha256:006413f08ba5db1f5b1e0d6fbdc2ac9058b062ccf552f57182563a78579c34b4"},
+ {file = "matplotlib-3.2.2-cp37-cp37m-win_amd64.whl", hash = "sha256:da06fa530591a141ffbe1712bbeec784734c3436b40c942d21652f305199b5d9"},
+ {file = "matplotlib-3.2.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:894dd47c0a6ce38dc19bc87d1f7e2b0608310b2a18d1572291157450b05ce874"},
+ {file = "matplotlib-3.2.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:1ab264770e7cf2cf4feb99f22c737066aef21ddf1ec402dc255450ac15eacb7b"},
+ {file = "matplotlib-3.2.2-cp38-cp38-win32.whl", hash = "sha256:91c153f4318e3c67c035fd1185f5ea2613f15008b73b66985033033f6fe54bbd"},
+ {file = "matplotlib-3.2.2-cp38-cp38-win_amd64.whl", hash = "sha256:a68e42e22f7fd190a532e4215e142276970c2d54040a0c46842fcb3db8b6ec5b"},
+ {file = "matplotlib-3.2.2-cp39-cp39-win32.whl", hash = "sha256:647cf232ccf6265d2ba1ac4103e8c8b6ac7b03a40da3421234ffb03dda217f59"},
+ {file = "matplotlib-3.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:31d32c83bb2b617377c6156f75e88b9ec2ded289e47ad4ff0f263dc1019d88b1"},
+ {file = "matplotlib-3.2.2-pp36-pypy36_pp73-win32.whl", hash = "sha256:67065d938df34478451af62fbd0670d2b51c4d859fb66673064eb5de8660dd7c"},
+ {file = "matplotlib-3.2.2.tar.gz", hash = "sha256:3d77a6630d093d74cbbfebaa0571d00790966be1ed204e4a8239f5cbd6835c5d"},
+]
+mock = [
+ {file = "mock-2.0.0-py2.py3-none-any.whl", hash = "sha256:5ce3c71c5545b472da17b72268978914d0252980348636840bd34a00b5cc96c1"},
+ {file = "mock-2.0.0.tar.gz", hash = "sha256:b158b6df76edd239b8208d481dc46b6afd45a846b7812ff0ce58971cf5bc8bba"},
+]
+monotonic = [
+ {file = "monotonic-1.5-py2.py3-none-any.whl", hash = "sha256:552a91f381532e33cbd07c6a2655a21908088962bb8fa7239ecbcc6ad1140cc7"},
+ {file = "monotonic-1.5.tar.gz", hash = "sha256:23953d55076df038541e648a53676fb24980f7a1be290cdda21300b3bc21dfb0"},
+]
+mpld3 = [
+ {file = "mpld3-0.3.tar.gz", hash = "sha256:4d455884a211bf99b37ecc760759435c7bb6a5955de47d8daf4967e301878ab7"},
+]
+msgpack = [
+ {file = "msgpack-1.0.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:cec8bf10981ed70998d98431cd814db0ecf3384e6b113366e7f36af71a0fca08"},
+ {file = "msgpack-1.0.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:aa5c057eab4f40ec47ea6f5a9825846be2ff6bf34102c560bad5cad5a677c5be"},
+ {file = "msgpack-1.0.0-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:4233b7f86c1208190c78a525cd3828ca1623359ef48f78a6fea4b91bb995775a"},
+ {file = "msgpack-1.0.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:b3758dfd3423e358bbb18a7cccd1c74228dffa7a697e5be6cb9535de625c0dbf"},
+ {file = "msgpack-1.0.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:25b3bc3190f3d9d965b818123b7752c5dfb953f0d774b454fd206c18fe384fb8"},
+ {file = "msgpack-1.0.0-cp36-cp36m-win32.whl", hash = "sha256:e7bbdd8e2b277b77782f3ce34734b0dfde6cbe94ddb74de8d733d603c7f9e2b1"},
+ {file = "msgpack-1.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:5dba6d074fac9b24f29aaf1d2d032306c27f04187651511257e7831733293ec2"},
+ {file = "msgpack-1.0.0-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:908944e3f038bca67fcfedb7845c4a257c7749bf9818632586b53bcf06ba4b97"},
+ {file = "msgpack-1.0.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:db685187a415f51d6b937257474ca72199f393dad89534ebbdd7d7a3b000080e"},
+ {file = "msgpack-1.0.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ea41c9219c597f1d2bf6b374d951d310d58684b5de9dc4bd2976db9e1e22c140"},
+ {file = "msgpack-1.0.0-cp37-cp37m-win32.whl", hash = "sha256:e35b051077fc2f3ce12e7c6a34cf309680c63a842db3a0616ea6ed25ad20d272"},
+ {file = "msgpack-1.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:5bea44181fc8e18eed1d0cd76e355073f00ce232ff9653a0ae88cb7d9e643322"},
+ {file = "msgpack-1.0.0-cp38-cp38-macosx_10_13_x86_64.whl", hash = "sha256:c901e8058dd6653307906c5f157f26ed09eb94a850dddd989621098d347926ab"},
+ {file = "msgpack-1.0.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:271b489499a43af001a2e42f42d876bb98ccaa7e20512ff37ca78c8e12e68f84"},
+ {file = "msgpack-1.0.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7a22c965588baeb07242cb561b63f309db27a07382825fc98aecaf0827c1538e"},
+ {file = "msgpack-1.0.0-cp38-cp38-win32.whl", hash = "sha256:002a0d813e1f7b60da599bdf969e632074f9eec1b96cbed8fb0973a63160a408"},
+ {file = "msgpack-1.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:39c54fdebf5fa4dda733369012c59e7d085ebdfe35b6cf648f09d16708f1be5d"},
+ {file = "msgpack-1.0.0.tar.gz", hash = "sha256:9534d5cc480d4aff720233411a1f765be90885750b07df772380b34c10ecb5c0"},
+]
+multidict = [
+ {file = "multidict-4.7.6-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:275ca32383bc5d1894b6975bb4ca6a7ff16ab76fa622967625baeebcf8079000"},
+ {file = "multidict-4.7.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:1ece5a3369835c20ed57adadc663400b5525904e53bae59ec854a5d36b39b21a"},
+ {file = "multidict-4.7.6-cp35-cp35m-win32.whl", hash = "sha256:5141c13374e6b25fe6bf092052ab55c0c03d21bd66c94a0e3ae371d3e4d865a5"},
+ {file = "multidict-4.7.6-cp35-cp35m-win_amd64.whl", hash = "sha256:9456e90649005ad40558f4cf51dbb842e32807df75146c6d940b6f5abb4a78f3"},
+ {file = "multidict-4.7.6-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:e0d072ae0f2a179c375f67e3da300b47e1a83293c554450b29c900e50afaae87"},
+ {file = "multidict-4.7.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:3750f2205b800aac4bb03b5ae48025a64e474d2c6cc79547988ba1d4122a09e2"},
+ {file = "multidict-4.7.6-cp36-cp36m-win32.whl", hash = "sha256:f07acae137b71af3bb548bd8da720956a3bc9f9a0b87733e0899226a2317aeb7"},
+ {file = "multidict-4.7.6-cp36-cp36m-win_amd64.whl", hash = "sha256:6513728873f4326999429a8b00fc7ceddb2509b01d5fd3f3be7881a257b8d463"},
+ {file = "multidict-4.7.6-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:feed85993dbdb1dbc29102f50bca65bdc68f2c0c8d352468c25b54874f23c39d"},
+ {file = "multidict-4.7.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fcfbb44c59af3f8ea984de67ec7c306f618a3ec771c2843804069917a8f2e255"},
+ {file = "multidict-4.7.6-cp37-cp37m-win32.whl", hash = "sha256:4538273208e7294b2659b1602490f4ed3ab1c8cf9dbdd817e0e9db8e64be2507"},
+ {file = "multidict-4.7.6-cp37-cp37m-win_amd64.whl", hash = "sha256:d14842362ed4cf63751648e7672f7174c9818459d169231d03c56e84daf90b7c"},
+ {file = "multidict-4.7.6-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:c026fe9a05130e44157b98fea3ab12969e5b60691a276150db9eda71710cd10b"},
+ {file = "multidict-4.7.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:51a4d210404ac61d32dada00a50ea7ba412e6ea945bbe992e4d7a595276d2ec7"},
+ {file = "multidict-4.7.6-cp38-cp38-win32.whl", hash = "sha256:5cf311a0f5ef80fe73e4f4c0f0998ec08f954a6ec72b746f3c179e37de1d210d"},
+ {file = "multidict-4.7.6-cp38-cp38-win_amd64.whl", hash = "sha256:7388d2ef3c55a8ba80da62ecfafa06a1c097c18032a501ffd4cabbc52d7f2b19"},
+ {file = "multidict-4.7.6.tar.gz", hash = "sha256:fbb77a75e529021e7c4a8d4e823d88ef4d23674a202be4f5addffc72cbb91430"},
+]
+mysqlclient = [
+ {file = "mysqlclient-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:edd42ccaa444b00702d5374b2f5f7585c9d0ce201917f15339f1c3cf91c1b1ed"},
+ {file = "mysqlclient-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:3f39855a4ad22805361e782cc4d1010ac74796225fa2d1c03cc16673ccdc983a"},
+ {file = "mysqlclient-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:a6b5648f648b16335e3b1aaec93dc3fcc81a9a661180e306936437cc522c810b"},
+ {file = "mysqlclient-2.0.1.tar.gz", hash = "sha256:fb2f75aea14722390d2d8ddf384ad99da708c707a96656210a7be8af20a2c5e5"},
+]
+naturalsort = [
+ {file = "naturalsort-1.5.1.tar.gz", hash = "sha256:172b5ed6e7ba3420c08ba2ded1c52fe74878f5d769dc5d9dec2b6a53e7117356"},
+]
+netaddr = [
+ {file = "netaddr-0.8.0-py2.py3-none-any.whl", hash = "sha256:9666d0232c32d2656e5e5f8d735f58fd6c7457ce52fc21c98d45f2af78f990ac"},
+ {file = "netaddr-0.8.0.tar.gz", hash = "sha256:d6cc57c7a07b1d9d2e917aa8b36ae8ce61c35ba3fcd1b83ca31c5a0ee2b5a243"},
+]
+netifaces = [
+ {file = "netifaces-0.10.9-cp27-cp27m-macosx_10_13_x86_64.whl", hash = "sha256:b2ff3a0a4f991d2da5376efd3365064a43909877e9fabfa801df970771161d29"},
+ {file = "netifaces-0.10.9-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:0c4304c6d5b33fbd9b20fdc369f3a2fef1a8bbacfb6fd05b9708db01333e9e7b"},
+ {file = "netifaces-0.10.9-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:7a25a8e28281504f0e23e181d7a9ed699c72f061ca6bdfcd96c423c2a89e75fc"},
+ {file = "netifaces-0.10.9-cp27-cp27m-win32.whl", hash = "sha256:6d84e50ec28e5d766c9911dce945412dc5b1ce760757c224c71e1a9759fa80c2"},
+ {file = "netifaces-0.10.9-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f911b7f0083d445c8d24cfa5b42ad4996e33250400492080f5018a28c026db2b"},
+ {file = "netifaces-0.10.9-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:4921ed406386246b84465950d15a4f63480c1458b0979c272364054b29d73084"},
+ {file = "netifaces-0.10.9-cp33-cp33m-manylinux1_i686.whl", hash = "sha256:5b3167f923f67924b356c1338eb9ba275b2ba8d64c7c2c47cf5b5db49d574994"},
+ {file = "netifaces-0.10.9-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:db881478f1170c6dd524175ba1c83b99d3a6f992a35eca756de0ddc4690a1940"},
+ {file = "netifaces-0.10.9-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:f0427755c68571df37dc58835e53a4307884a48dec76f3c01e33eb0d4a3a81d7"},
+ {file = "netifaces-0.10.9-cp34-cp34m-win32.whl", hash = "sha256:7cc6fd1eca65be588f001005446a47981cbe0b2909f5be8feafef3bf351a4e24"},
+ {file = "netifaces-0.10.9-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:b47e8f9ff6846756be3dc3fb242ca8e86752cd35a08e06d54ffc2e2a2aca70ea"},
+ {file = "netifaces-0.10.9-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f8885cc48c8c7ad51f36c175e462840f163cb4687eeb6c6d7dfaf7197308e36b"},
+ {file = "netifaces-0.10.9-cp35-cp35m-win32.whl", hash = "sha256:755050799b5d5aedb1396046f270abfc4befca9ccba3074f3dbbb3cb34f13aae"},
+ {file = "netifaces-0.10.9-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:ad10acab2ef691eb29a1cc52c3be5ad1423700e993cc035066049fa72999d0dc"},
+ {file = "netifaces-0.10.9-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:563a1a366ee0fb3d96caab79b7ac7abd2c0a0577b157cc5a40301373a0501f89"},
+ {file = "netifaces-0.10.9-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:30ed89ab8aff715caf9a9d827aa69cd02ad9f6b1896fd3fb4beb998466ed9a3c"},
+ {file = "netifaces-0.10.9-cp36-cp36m-win32.whl", hash = "sha256:75d3a4ec5035db7478520ac547f7c176e9fd438269e795819b67223c486e5cbe"},
+ {file = "netifaces-0.10.9-cp36-cp36m-win_amd64.whl", hash = "sha256:078986caf4d6a602a4257d3686afe4544ea74362b8928e9f4389b5cd262bc215"},
+ {file = "netifaces-0.10.9-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:3095218b66d359092b82f07c5422293c2f6559cf8d36b96b379cc4cdc26eeffa"},
+ {file = "netifaces-0.10.9-cp37-cp37m-win32.whl", hash = "sha256:da298241d87bcf468aa0f0705ba14572ad296f24c4fda5055d6988701d6fd8e1"},
+ {file = "netifaces-0.10.9-cp37-cp37m-win_amd64.whl", hash = "sha256:86b8a140e891bb23c8b9cb1804f1475eb13eea3dbbebef01fcbbf10fbafbee42"},
+ {file = "netifaces-0.10.9.tar.gz", hash = "sha256:2dee9ffdd16292878336a58d04a20f0ffe95555465fee7c9bd23b3490ef2abf3"},
+]
+nose = [
+ {file = "nose-1.3.7-py2-none-any.whl", hash = "sha256:dadcddc0aefbf99eea214e0f1232b94f2fa9bd98fa8353711dacb112bfcbbb2a"},
+ {file = "nose-1.3.7-py3-none-any.whl", hash = "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac"},
+ {file = "nose-1.3.7.tar.gz", hash = "sha256:f1bffef9cbc82628f6e7d7b40d7e255aefaa1adb6a1b1d26c69a8b79e6208a98"},
+]
+num2words = [
+ {file = "num2words-0.5.6-py2.py3-none-any.whl", hash = "sha256:529017394eef84daf63bb57e837fe2fb81363d1b06f6114e86608dae7ceb11ee"},
+ {file = "num2words-0.5.6.tar.gz", hash = "sha256:aea26c2d11d636f0e9da094f2bf55ac94cb1c380ff1f86e8db22c210e5a6a05f"},
+]
+numpy = [
+ {file = "numpy-1.19.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b1cca51512299841bf69add3b75361779962f9cee7d9ee3bb446d5982e925b69"},
+ {file = "numpy-1.19.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c9591886fc9cbe5532d5df85cb8e0cc3b44ba8ce4367bd4cf1b93dc19713da72"},
+ {file = "numpy-1.19.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:cf1347450c0b7644ea142712619533553f02ef23f92f781312f6a3553d031fc7"},
+ {file = "numpy-1.19.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:ed8a311493cf5480a2ebc597d1e177231984c818a86875126cfd004241a73c3e"},
+ {file = "numpy-1.19.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:3673c8b2b29077f1b7b3a848794f8e11f401ba0b71c49fbd26fb40b71788b132"},
+ {file = "numpy-1.19.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:56ef7f56470c24bb67fb43dae442e946a6ce172f97c69f8d067ff8550cf782ff"},
+ {file = "numpy-1.19.1-cp36-cp36m-win32.whl", hash = "sha256:aaf42a04b472d12515debc621c31cf16c215e332242e7a9f56403d814c744624"},
+ {file = "numpy-1.19.1-cp36-cp36m-win_amd64.whl", hash = "sha256:082f8d4dd69b6b688f64f509b91d482362124986d98dc7dc5f5e9f9b9c3bb983"},
+ {file = "numpy-1.19.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e4f6d3c53911a9d103d8ec9518190e52a8b945bab021745af4939cfc7c0d4a9e"},
+ {file = "numpy-1.19.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:5b6885c12784a27e957294b60f97e8b5b4174c7504665333c5e94fbf41ae5d6a"},
+ {file = "numpy-1.19.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:1bc0145999e8cb8aed9d4e65dd8b139adf1919e521177f198529687dbf613065"},
+ {file = "numpy-1.19.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:5a936fd51049541d86ccdeef2833cc89a18e4d3808fe58a8abeb802665c5af93"},
+ {file = "numpy-1.19.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:ef71a1d4fd4858596ae80ad1ec76404ad29701f8ca7cdcebc50300178db14dfc"},
+ {file = "numpy-1.19.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b9792b0ac0130b277536ab8944e7b754c69560dac0415dd4b2dbd16b902c8954"},
+ {file = "numpy-1.19.1-cp37-cp37m-win32.whl", hash = "sha256:b12e639378c741add21fbffd16ba5ad25c0a1a17cf2b6fe4288feeb65144f35b"},
+ {file = "numpy-1.19.1-cp37-cp37m-win_amd64.whl", hash = "sha256:8343bf67c72e09cfabfab55ad4a43ce3f6bf6e6ced7acf70f45ded9ebb425055"},
+ {file = "numpy-1.19.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e45f8e981a0ab47103181773cc0a54e650b2aef8c7b6cd07405d0fa8d869444a"},
+ {file = "numpy-1.19.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:667c07063940e934287993366ad5f56766bc009017b4a0fe91dbd07960d0aba7"},
+ {file = "numpy-1.19.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:480fdd4dbda4dd6b638d3863da3be82873bba6d32d1fc12ea1b8486ac7b8d129"},
+ {file = "numpy-1.19.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:935c27ae2760c21cd7354402546f6be21d3d0c806fffe967f745d5f2de5005a7"},
+ {file = "numpy-1.19.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:309cbcfaa103fc9a33ec16d2d62569d541b79f828c382556ff072442226d1968"},
+ {file = "numpy-1.19.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:7ed448ff4eaffeb01094959b19cbaf998ecdee9ef9932381420d514e446601cd"},
+ {file = "numpy-1.19.1-cp38-cp38-win32.whl", hash = "sha256:de8b4a9b56255797cbddb93281ed92acbc510fb7b15df3f01bd28f46ebc4edae"},
+ {file = "numpy-1.19.1-cp38-cp38-win_amd64.whl", hash = "sha256:92feb989b47f83ebef246adabc7ff3b9a59ac30601c3f6819f8913458610bdcc"},
+ {file = "numpy-1.19.1-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:e1b1dc0372f530f26a03578ac75d5e51b3868b9b76cd2facba4c9ee0eb252ab1"},
+ {file = "numpy-1.19.1.zip", hash = "sha256:b8456987b637232602ceb4d663cb34106f7eb780e247d51a260b84760fd8f491"},
+]
+oauthlib = [
+ {file = "oauthlib-2.1.0-py2.py3-none-any.whl", hash = "sha256:d883b36b21a6ad813953803edfa563b1b579d79ca758fe950d1bc9e8b326025b"},
+ {file = "oauthlib-2.1.0.tar.gz", hash = "sha256:ac35665a61c1685c56336bda97d5eefa246f1202618a1d6f34fccb1bdd404162"},
+]
+"oca.decorators" = [
+ {file = "oca-decorators-0.0.1.tar.gz", hash = "sha256:91170842a8c0cf874173b9217027a8a8e3e59532b4b7a800a065b5a9f9d78273"},
+ {file = "oca_decorators-0.0.1-py2-none-any.whl", hash = "sha256:55c75de9370de65e0cdad94fca5f75a2b6996887c865a270adfa2b3a60b1db0c"},
+ {file = "oca_decorators-0.0.1-py3-none-any.whl", hash = "sha256:e1ed1244bb87758b72f0f8f283dd2b3d7fafcc966a73be0013a0ce5b5a58093d"},
+]
+ofxparse = [
+ {file = "ofxparse-0.16.tar.gz", hash = "sha256:cca83cd3d5578e7003b53457522c6dbb27832b734dbf869adf585f1547c3a91e"},
+]
+olefile = [
+ {file = "olefile-0.46.zip", hash = "sha256:133b031eaf8fd2c9399b78b8bc5b8fcbe4c31e85295749bb17a87cba8f3c3964"},
+]
+openpyxl = [
+ {file = "openpyxl-3.0.4-py2.py3-none-any.whl", hash = "sha256:6e62f058d19b09b95d20ebfbfb04857ad08d0833190516c1660675f699c6186f"},
+ {file = "openpyxl-3.0.4.tar.gz", hash = "sha256:d88dd1480668019684c66cfff3e52a5de4ed41e9df5dd52e008cbf27af0dbf87"},
+]
+openupgradelib = [
+ {file = "openupgradelib-2.0.0.tar.gz", hash = "sha256:acb826ed5965db388d086a6585afb63aee89719082ea7ab8142fc170c02ff257"},
+]
+os-service-types = [
+ {file = "os-service-types-1.7.0.tar.gz", hash = "sha256:31800299a82239363995b91f1ebf9106ac7758542a1e4ef6dc737a5932878c6c"},
+ {file = "os_service_types-1.7.0-py2.py3-none-any.whl", hash = "sha256:0505c72205690910077fb72b88f2a1f07533c8d39f2fe75b29583481764965d6"},
+]
+"oslo.config" = [
+ {file = "oslo.config-8.3.1-py3-none-any.whl", hash = "sha256:5ef9382983e7be5d44a2bc05b87c858dc9d8c8c409f8856eeeb6d4933a17bc20"},
+ {file = "oslo.config-8.3.1.tar.gz", hash = "sha256:dfbb83dc5b4c86ddf8b96f3967252f17586a67f2cef65309df2fd510bf9e87fc"},
+]
+"oslo.i18n" = [
+ {file = "oslo.i18n-5.0.0-py3-none-any.whl", hash = "sha256:55914fbdcb7de1d766bc3910c61b5071fe1288ba605bfe90f635000a033c4ec4"},
+ {file = "oslo.i18n-5.0.0.tar.gz", hash = "sha256:2e71ae3ec73a74ac71f8f407e6653243dc267eed404624255a296c34f1fc6887"},
+]
+"oslo.serialization" = [
+ {file = "oslo.serialization-4.0.0-py3-none-any.whl", hash = "sha256:292bf1eac8930d9d89a64f8c7b3871eb2cfc990078b89c432edfe863da0df3d9"},
+ {file = "oslo.serialization-4.0.0.tar.gz", hash = "sha256:f465df171be564282cb3e86ec895f5b6ae5e5b0760e9af2be96a942a5255a860"},
+]
+"oslo.utils" = [
+ {file = "oslo.utils-4.4.0-py3-none-any.whl", hash = "sha256:50cf1099ab8c3419990f43a2b11d06f14951600f9cd3ff3ca9352b0ff5aff9e3"},
+ {file = "oslo.utils-4.4.0.tar.gz", hash = "sha256:1603e1b0e3d1def57c51f4d5c82871ea05e221f7dac5d4f6eeb56e6cb19284fb"},
+]
+packaging = [
+ {file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"},
+ {file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"},
+]
+pandas = [
+ {file = "pandas-1.1.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:47a03bfef80d6812c91ed6fae43f04f2fa80a4e1b82b35aa4d9002e39529e0b8"},
+ {file = "pandas-1.1.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0210f8fe19c2667a3817adb6de2c4fd92b1b78e1975ca60c0efa908e0985cbdb"},
+ {file = "pandas-1.1.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:35db623487f00d9392d8af44a24516d6cb9f274afaf73cfcfe180b9c54e007d2"},
+ {file = "pandas-1.1.0-cp36-cp36m-win32.whl", hash = "sha256:4d1a806252001c5db7caecbe1a26e49a6c23421d85a700960f6ba093112f54a1"},
+ {file = "pandas-1.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:9f61cca5262840ff46ef857d4f5f65679b82188709d0e5e086a9123791f721c8"},
+ {file = "pandas-1.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:182a5aeae319df391c3df4740bb17d5300dcd78034b17732c12e62e6dd79e4a4"},
+ {file = "pandas-1.1.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:40ec0a7f611a3d00d3c666c4cceb9aa3f5bf9fbd81392948a93663064f527203"},
+ {file = "pandas-1.1.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:16504f915f1ae424052f1e9b7cd2d01786f098fbb00fa4e0f69d42b22952d798"},
+ {file = "pandas-1.1.0-cp37-cp37m-win32.whl", hash = "sha256:fc714895b6de6803ac9f661abb316853d0cd657f5d23985222255ad76ccedc25"},
+ {file = "pandas-1.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:a15835c8409d5edc50b4af93be3377b5dd3eb53517e7f785060df1f06f6da0e2"},
+ {file = "pandas-1.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0bc440493cf9dc5b36d5d46bbd5508f6547ba68b02a28234cd8e81fdce42744d"},
+ {file = "pandas-1.1.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:4b21d46728f8a6be537716035b445e7ef3a75dbd30bd31aa1b251323219d853e"},
+ {file = "pandas-1.1.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:0227e3a6e3a22c0e283a5041f1e3064d78fbde811217668bb966ed05386d8a7e"},
+ {file = "pandas-1.1.0-cp38-cp38-win32.whl", hash = "sha256:ed60848caadeacecefd0b1de81b91beff23960032cded0ac1449242b506a3b3f"},
+ {file = "pandas-1.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:60e20a4ab4d4fec253557d0fc9a4e4095c37b664f78c72af24860c8adcd07088"},
+ {file = "pandas-1.1.0.tar.gz", hash = "sha256:b39508562ad0bb3f384b0db24da7d68a2608b9ddc85b1d931ccaaa92d5e45273"},
+]
+paramiko = [
+ {file = "paramiko-2.7.1-py2.py3-none-any.whl", hash = "sha256:9c980875fa4d2cb751604664e9a2d0f69096643f5be4db1b99599fe114a97b2f"},
+ {file = "paramiko-2.7.1.tar.gz", hash = "sha256:920492895db8013f6cc0179293147f830b8c7b21fdfc839b6bad760c27459d9f"},
+]
+passlib = [
+ {file = "passlib-1.6.5-py2.py3-none-any.whl", hash = "sha256:ad631a58dc8abeb0f48016c13f4b3b0f3a7b1045a8cb3c61dd15e2d95b45c472"},
+ {file = "passlib-1.6.5.tar.gz", hash = "sha256:a83d34f53dc9b17aa42c9a35c3fbcc5120f3fcb07f7f8721ec45e6a27be347fc"},
+]
+pbr = [
+ {file = "pbr-5.4.5-py2.py3-none-any.whl", hash = "sha256:579170e23f8e0c2f24b0de612f71f648eccb79fb1322c814ae6b3c07b5ba23e8"},
+ {file = "pbr-5.4.5.tar.gz", hash = "sha256:07f558fece33b05caf857474a366dfcc00562bca13dd8b47b2b3e22d9f9bf55c"},
+]
+pdf2image = [
+ {file = "pdf2image-1.13.1-py3-none-any.whl", hash = "sha256:ed2935991de449e55ceea2eff7c5d18c7b5cde4a2f6b9f3d56a430e8c5b77969"},
+ {file = "pdf2image-1.13.1.tar.gz", hash = "sha256:df6b825f7f26df35b873642725a7ee37dfc8a531b711274a8ad2ee830c8b72d0"},
+]
+phonenumbers = [
+ {file = "phonenumbers-8.12.7-py2.py3-none-any.whl", hash = "sha256:772d69e620f85bb089d27c4e2bbf718c49ad327459accf9463ac65dbab67695c"},
+ {file = "phonenumbers-8.12.7.tar.gz", hash = "sha256:652c418f8e97c8438f227a524ddf8d7d325c4a47e4924ce865b827c24ec3194d"},
+]
+pillow = [
+ {file = "Pillow-6.1.0-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:76638865c83b1bb33bcac2a61ce4d13c17dba2204969dedb9ab60ef62bede686"},
+ {file = "Pillow-6.1.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:7cee2cef07c8d76894ebefc54e4bb707dfc7f258ad155bd61d87f6cd487a70ff"},
+ {file = "Pillow-6.1.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:ef6be704ae2bc8ad0ebc5cb850ee9139493b0fc4e81abcc240fb392a63ebc808"},
+ {file = "Pillow-6.1.0-cp27-cp27m-win32.whl", hash = "sha256:6fd63afd14a16f5d6b408f623cc2142917a1f92855f0df997e09a49f0341be8a"},
+ {file = "Pillow-6.1.0-cp27-cp27m-win_amd64.whl", hash = "sha256:571b5a758baf1cb6a04233fb23d6cf1ca60b31f9f641b1700bfaab1194020555"},
+ {file = "Pillow-6.1.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:e3ae410089de680e8f84c68b755b42bc42c0ceb8c03dbea88a5099747091d38e"},
+ {file = "Pillow-6.1.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:6153db744a743c0c8c91b8e3b9d40e0b13a5d31dbf8a12748c6d9bfd3ddc01ad"},
+ {file = "Pillow-6.1.0-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:0b3e6cf3ea1f8cecd625f1420b931c83ce74f00c29a0ff1ce4385f99900ac7c4"},
+ {file = "Pillow-6.1.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:38301fbc0af865baa4752ddae1bb3cbb24b3d8f221bf2850aad96b243306fa03"},
+ {file = "Pillow-6.1.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:70b1594d56ed32d56ed21a7fbb2a5c6fd7446cdb7b21e749c9791eac3a64d9e4"},
+ {file = "Pillow-6.1.0-cp35-cp35m-win32.whl", hash = "sha256:70acbcaba2a638923c2d337e0edea210505708d7859b87c2bd81e8f9902ae826"},
+ {file = "Pillow-6.1.0-cp35-cp35m-win_amd64.whl", hash = "sha256:f8dc19d92896558f9c4317ee365729ead9d7bbcf2052a9a19a3ef17abbb8ac5b"},
+ {file = "Pillow-6.1.0-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:3aef1af1a91798536bbab35d70d35750bd2884f0832c88aeb2499aa2d1ed4992"},
+ {file = "Pillow-6.1.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:cfd40d8a4b59f7567620410f966bb1f32dc555b2b19f82a91b147fac296f645c"},
+ {file = "Pillow-6.1.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:3fe0ab49537d9330c9bba7f16a5f8b02da615b5c809cdf7124f356a0f182eccd"},
+ {file = "Pillow-6.1.0-cp36-cp36m-win32.whl", hash = "sha256:49f90f147883a0c3778fd29d3eb169d56416f25758d0f66775db9184debc8010"},
+ {file = "Pillow-6.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:bd0582f831ad5bcad6ca001deba4568573a4675437db17c4031939156ff339fa"},
+ {file = "Pillow-6.1.0-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:365c06a45712cd723ec16fa4ceb32ce46ad201eb7bbf6d3c16b063c72b61a3ed"},
+ {file = "Pillow-6.1.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:7b2ec162c87fc496aa568258ac88631a2ce0acfe681a9af40842fc55deaedc99"},
+ {file = "Pillow-6.1.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:b50bc1780681b127e28f0075dfb81d6135c3a293e0c1d0211133c75e2179b6c0"},
+ {file = "Pillow-6.1.0-cp37-cp37m-win32.whl", hash = "sha256:0ab7c5b5d04691bcbd570658667dd1e21ca311c62dcfd315ad2255b1cd37f64f"},
+ {file = "Pillow-6.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:7d16d4498f8b374fc625c4037742fbdd7f9ac383fd50b06f4df00c81ef60e829"},
+ {file = "Pillow-6.1.0-pp271-pypy_41-win32.whl", hash = "sha256:e9046e559c299b395b39ac7dbf16005308821c2f24a63cae2ab173bd6aa11616"},
+ {file = "Pillow-6.1.0-pp370-pp370-win32.whl", hash = "sha256:5ac381e8b1259925287ccc5a87d9cf6322a2dc88ae28a97fe3e196385288413f"},
+ {file = "Pillow-6.1.0-pp371-pp371-win32.whl", hash = "sha256:45a619d5c1915957449264c81c008934452e3fd3604e36809212300b2a4dab68"},
+ {file = "Pillow-6.1.0-py2.7-win-amd64.egg", hash = "sha256:0c6ce6ae03a50b0306a683696234b8bc88c5b292d4181ae365b89bd90250ab08"},
+ {file = "Pillow-6.1.0-py2.7-win32.egg", hash = "sha256:504f5334bfd974490a86fef3e3b494cd3c332a8a680d2f258ca03388b40ae230"},
+ {file = "Pillow-6.1.0-py3.5-win-amd64.egg", hash = "sha256:23efd7f83f2ad6036e2b9ef27a46df7e333de1ad9087d341d87e12225d0142b2"},
+ {file = "Pillow-6.1.0-py3.5-win32.egg", hash = "sha256:8755e600b33f4e8c76a590b42acc35d24f4dc801a5868519ce569b9462d77598"},
+ {file = "Pillow-6.1.0-py3.6-win-amd64.egg", hash = "sha256:7be698a28175eae5354da94f5f3dc787d5efae6aca7ad1f286a781afde6a27dd"},
+ {file = "Pillow-6.1.0-py3.6-win32.egg", hash = "sha256:51fe9cfcd32c849c6f36ca293648f279fc5097ca8dd6e518b10df3a6a9a13431"},
+ {file = "Pillow-6.1.0-py3.7-macosx-10.14-x86_64.egg", hash = "sha256:3c86051d41d1c8b28b9dde08ac93e73aa842991995b12771b0af28da49086bbf"},
+ {file = "Pillow-6.1.0-py3.7-win-amd64.egg", hash = "sha256:6052a9e9af4a9a2cc01da4bbee81d42d33feca2bde247c4916d8274b12bb31a4"},
+ {file = "Pillow-6.1.0-py3.7-win32.egg", hash = "sha256:1454ee7297a81c8308ad61d74c849486efa1badc543453c4b90db0bf99decc1c"},
+ {file = "Pillow-6.1.0.tar.gz", hash = "sha256:0804f77cb1e9b6dbd37601cee11283bba39a8d44b9ddb053400c58e0c0d7d9de"},
+ {file = "Pillow-6.1.0.win-amd64-py2.7.exe", hash = "sha256:e150c5aed6e67321edc6893faa6701581ca2d393472f39142a00e551bcd249a5"},
+ {file = "Pillow-6.1.0.win-amd64-py3.5.exe", hash = "sha256:b5aa19f1da16b4f5e47b6930053f08cba77ceccaed68748061b0ec24860e510c"},
+ {file = "Pillow-6.1.0.win-amd64-py3.6.exe", hash = "sha256:7b403ea842b70c4fa0a4969a5d8d86e932c941095b7cda077ea68f7b98ead30b"},
+ {file = "Pillow-6.1.0.win-amd64-py3.7.exe", hash = "sha256:cdd53acd3afb9878a2289a1b55807871f9877c81174ae0d3763e52f907131d25"},
+ {file = "Pillow-6.1.0.win32-py2.7.exe", hash = "sha256:406c856e0f6fc330322a319457d9ff6162834050cda2cf1eaaaea4b771d01914"},
+ {file = "Pillow-6.1.0.win32-py3.5.exe", hash = "sha256:82840783842b27933cc6388800cb547f31caf436f7e23384d456bdf5fc8dfe49"},
+ {file = "Pillow-6.1.0.win32-py3.6.exe", hash = "sha256:9159285ab4030c6f85e001468cb5886de05e6bd9304e9e7d46b983f7d2fad0cc"},
+ {file = "Pillow-6.1.0.win32-py3.7.exe", hash = "sha256:e403b37c6a253ebca5d0f2e5624643997aaae529dc96299162418ef54e29eb70"},
+]
+plotly = [
+ {file = "plotly-4.1.0-py2.py3-none-any.whl", hash = "sha256:c5effc51364490b1a20fe7bb8443cfe2451004fca727c7f3fedbc30f4cef5aab"},
+ {file = "plotly-4.1.0.tar.gz", hash = "sha256:9333f28feacaa0751df04cccfb266463bf5029dcb106d3f81d7af5942fd3d998"},
+]
+premailer = [
+ {file = "premailer-3.7.0-py2.py3-none-any.whl", hash = "sha256:c7ac48986984a810afea5147bc8410a8fe0659bf52f357e78b28a1b949209b91"},
+ {file = "premailer-3.7.0.tar.gz", hash = "sha256:5eec9603e84cee583a390de69c75192e50d76e38ef0292b027bd64923766aca7"},
+]
+property-manager = [
+ {file = "property-manager-3.0.tar.gz", hash = "sha256:93e76da9ae7af13cccc2cd1e3b47219950c56c125cd962aaed693894af267c54"},
+ {file = "property_manager-3.0-py2.py3-none-any.whl", hash = "sha256:d5d648053e669cf9cb2f157e4a41ef46174eaa8ee13bfa49e1530c17d65bfe45"},
+]
+psutil = [
+ {file = "psutil-4.3.1-cp27-none-win32.whl", hash = "sha256:b0c5bf0d2a29a6f18ac22e2d24210730dca458c9f961914289c9e027ccb5ae43"},
+ {file = "psutil-4.3.1-cp27-none-win_amd64.whl", hash = "sha256:fc78c29075e623b6ea1c4a1620a120a1534ee05370b76c0ec96f6d161d79e7a1"},
+ {file = "psutil-4.3.1-cp33-cp33m-win32.whl", hash = "sha256:aa05f44a77ef83773af39446f99e461aa3b6edb7fdabeefdcf06e913d8884d3a"},
+ {file = "psutil-4.3.1-cp33-cp33m-win_amd64.whl", hash = "sha256:6b3882eb16f2f40f1da6208a051800abadb1f82a675d9ef6ca7386e1a208b1ad"},
+ {file = "psutil-4.3.1-cp34-cp34m-win32.whl", hash = "sha256:cf1be0b16b38f0e2081ff0c81a1a4321c206a824ba6bd51903fdd440abb370b6"},
+ {file = "psutil-4.3.1-cp34-cp34m-win_amd64.whl", hash = "sha256:afa94bed972722882264a4df06176f6b6e6acc6bcebcc3f1db5428c7271dacba"},
+ {file = "psutil-4.3.1-cp35-cp35m-win32.whl", hash = "sha256:d2254f518624e6b2262f0f878931faa4bdbe8a77d1f8826564bc4576c6a4f85e"},
+ {file = "psutil-4.3.1-cp35-cp35m-win_amd64.whl", hash = "sha256:3b377bc8ba5e62adbc709a90ea07dce2d4addbd6e1cc7acede61ddfa1c66e00a"},
+ {file = "psutil-4.3.1.tar.gz", hash = "sha256:38f74182fb9e15cafd0cdf0821098a95cc17301807aed25634a18b66537ba51b"},
+ {file = "psutil-4.3.1.win-amd64-py2.7.exe", hash = "sha256:733210f39e95744da26f2256bc36035fc463b0ae88e91496e97486ba21c63cab"},
+ {file = "psutil-4.3.1.win-amd64-py3.3.exe", hash = "sha256:4690f720054beff4fc66551a6a34512faff328588dca8e2dbed94398b6941112"},
+ {file = "psutil-4.3.1.win-amd64-py3.4.exe", hash = "sha256:fd9b66edb9f8943eda6b39e7bb9bff8b14aa8d785f5b417d7a0bfa53d4781a7a"},
+ {file = "psutil-4.3.1.win-amd64-py3.5.exe", hash = "sha256:9ab5b62c6571ce545b1c40b9740af81276bd5d94439fd54de07ed59be0ce3f4f"},
+ {file = "psutil-4.3.1.win32-py2.7.exe", hash = "sha256:ad8857923e9bc5802d5559ab5d70c1abc1a7be8e74e779adde883c5391e2061c"},
+ {file = "psutil-4.3.1.win32-py3.3.exe", hash = "sha256:ae20b76cddb3391ea37de5d2aaa1656d6373161bbc8fd868a0ca055194a46e45"},
+ {file = "psutil-4.3.1.win32-py3.4.exe", hash = "sha256:0613437cc28b8721de92c582d5baf742dfa6dd824c84b578f8c49a60077e969a"},
+ {file = "psutil-4.3.1.win32-py3.5.exe", hash = "sha256:c2031732cd0fb7536af491bb8d8119c9263020a52450f9999c884fd49d346b26"},
+]
+psycopg2 = [
+ {file = "psycopg2-2.7.3.1-cp26-cp26m-manylinux1_i686.whl", hash = "sha256:3ab693b907b2c7a34c1dca198cfc454516cfd75440fd913bb372da6f70d6db55"},
+ {file = "psycopg2-2.7.3.1-cp26-cp26m-manylinux1_x86_64.whl", hash = "sha256:3c99c88216e0fc62113a1177aae9db18a533274370e99a4537b433b87b319360"},
+ {file = "psycopg2-2.7.3.1-cp26-cp26mu-manylinux1_i686.whl", hash = "sha256:df70e0a387b0145a7a80de67d43d84e1c5a24a33bbfaedb96271876d573e5fb6"},
+ {file = "psycopg2-2.7.3.1-cp26-cp26mu-manylinux1_x86_64.whl", hash = "sha256:8d2003d23d8fc59f0f0a2e73c13baa41581006b8227a9d82bbdc1aa233285ba4"},
+ {file = "psycopg2-2.7.3.1-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:face605eea5826fa36600c04447b61674992bbd5eb177f66f86f61a04436dbd9"},
+ {file = "psycopg2-2.7.3.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:ebee4f59803eda1ed4035649469a713818dbf5b6de2e12396edd9fa228727c20"},
+ {file = "psycopg2-2.7.3.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:4d7c872d9c85745964cf8efabba3fb1a6010b345c18d0e2b620509f0444aa729"},
+ {file = "psycopg2-2.7.3.1-cp27-cp27m-win32.whl", hash = "sha256:39369e40bc3e062da5da93ce5f1e7f9bed95e9a60cb6f003d316f2a834722e2d"},
+ {file = "psycopg2-2.7.3.1-cp27-cp27m-win_amd64.whl", hash = "sha256:c939b238cbc18e786909d20277c9f051241696ebb03ca9e3490094f526ce69a7"},
+ {file = "psycopg2-2.7.3.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:99a298b9030f8fd36f885c5d0661e4d5a059136a541bb6c4d7d1100e38da3cd1"},
+ {file = "psycopg2-2.7.3.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:b7646f7bdb42ba3cf7ef9f500f6514b5e413d25c5b3093d70e6ba52df417a83c"},
+ {file = "psycopg2-2.7.3.1-cp33-cp33m-manylinux1_i686.whl", hash = "sha256:9a0a74a6f20d82c389095c88d4d281e66eb3ffbc09adf543dcec4bec22436569"},
+ {file = "psycopg2-2.7.3.1-cp33-cp33m-manylinux1_x86_64.whl", hash = "sha256:16482d050db68503abbb693795d75e9fca287a00f662376759825404533ca87c"},
+ {file = "psycopg2-2.7.3.1-cp33-cp33m-win32.whl", hash = "sha256:f74e50341f45fb9bcd3598c11b5774c3e4349ee38cf15c342cc7075c73ef1f95"},
+ {file = "psycopg2-2.7.3.1-cp33-cp33m-win_amd64.whl", hash = "sha256:e80a1ae04218e854a5d71085f9498c8c979033ca855cedeed3afc5d976c348ce"},
+ {file = "psycopg2-2.7.3.1-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:f07791ee5793621bfaaa844f731529cd72321280f94e8dc3bd4ef524d20f58f2"},
+ {file = "psycopg2-2.7.3.1-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:0bd0b1cf81eb6d74a77199570d5ce097fb3c6b8e57acc1edd328cef5c552f98a"},
+ {file = "psycopg2-2.7.3.1-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:4db0de7d6236acbf7d020926489b6c4b98e845ba98df11057f22d54866e26b20"},
+ {file = "psycopg2-2.7.3.1-cp34-cp34m-win32.whl", hash = "sha256:604c49bf196c654c417ade1dc765bd23fe9bc3392d9a8c7184a7077142d621b3"},
+ {file = "psycopg2-2.7.3.1-cp34-cp34m-win_amd64.whl", hash = "sha256:6194e81d8839b636118f5275c53be3c70eb3c3abcf836de675c34b20c06025ea"},
+ {file = "psycopg2-2.7.3.1-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:e26aca5eb272869fdf8e55111f36026517c1c0799eb7ef1ddf67d4412affe1ef"},
+ {file = "psycopg2-2.7.3.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:35d1fec112337c2607c8ca17dee3c2f8455e07dd69d140ff8e86ef1240dace3d"},
+ {file = "psycopg2-2.7.3.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:891a70235c202158780fc0ab98d7ca2a7ed1625c26725b15119d47b2d852a5c6"},
+ {file = "psycopg2-2.7.3.1-cp35-cp35m-win32.whl", hash = "sha256:4cca242df228364b4de6241c54553301856bc253d7f21e15009b11c812eb7b5c"},
+ {file = "psycopg2-2.7.3.1-cp35-cp35m-win_amd64.whl", hash = "sha256:3fbba0dd7f3ac458f355dcfc4d7d9cd082c19748e453bcd81bf9d8bc14260c01"},
+ {file = "psycopg2-2.7.3.1-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:04a5b2805c620ddecdff33e015631cc8d7ea8dd01e1fcc930bfe002fdc26b9e0"},
+ {file = "psycopg2-2.7.3.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:4fbe2c29f6d4c8d9eac5fc3c42c42036e7cc58e225036130b7713afa72489aac"},
+ {file = "psycopg2-2.7.3.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:471e3140e1cb241ecb53602cdc98fe305b82c854cfa53c3e343d642683dc96c7"},
+ {file = "psycopg2-2.7.3.1-cp36-cp36m-win32.whl", hash = "sha256:279dbf220c94c9f73aefac719ea3b9550ca791389bc9184c15e835516bc8428d"},
+ {file = "psycopg2-2.7.3.1-cp36-cp36m-win_amd64.whl", hash = "sha256:a4d7134058e8869d785c0be386cd702fe2a4be14b678d7571a51045e1bbad862"},
+ {file = "psycopg2-2.7.3.1.tar.gz", hash = "sha256:9b7b16e26448b43cf167f785d8b5345007731ebf153a510e12dae826800caa65"},
+]
+py-asterisk = [
+ {file = "py-Asterisk-0.5.18.tar.gz", hash = "sha256:f2e9319626bbc5346ac9cbddfb73480d5fcdf25c1e9d78775c3061a1c01462f1"},
+]
+"py3o.formats" = [
+ {file = "py3o.formats-0.3-py2-none-any.whl", hash = "sha256:4770f1e05982d076e1b7f24db7c7b6195c03c4487783f693ccf46deaca032b50"},
+ {file = "py3o.formats-0.3-py2.7.egg", hash = "sha256:becfe8ae5557d9886138d7c967d28f7c5936535298c39b63f61f88118969169a"},
+ {file = "py3o.formats-0.3.tar.gz", hash = "sha256:9cd36f24b3134dfe69fc9a325a829f029d6e062d3e37e1e799f3ab5e54c4e193"},
+ {file = "py3o.formats-0.3.zip", hash = "sha256:3d85024efbcb1ec99991571d3d18a0b22b3c44d7da0e63570a91fb952a8f27f3"},
+]
+"py3o.template" = [
+ {file = "py3o.template-0.10.0-py3-none-any.whl", hash = "sha256:b83c43d1ff89ec9688e0c9c5297b0afdb0ecb123c6b2311e4d173aa36920b4e2"},
+ {file = "py3o.template-0.10.0.tar.gz", hash = "sha256:ea544e76ad519172fc49a621e999a1438fc8aa8869762db913fbc336518606d3"},
+]
+pycountry = [
+ {file = "pycountry-20.7.3.tar.gz", hash = "sha256:81084a53d3454344c0292deebc20fcd0a1488c136d4900312cbd465cf552cb42"},
+]
+pycparser = [
+ {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"},
+ {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"},
+]
+pydot = [
+ {file = "pydot-1.2.3.tar.gz", hash = "sha256:edb5d3f249f97fbd9c4bb16959e61bc32ecf40eee1a9f6d27abe8d01c0a73502"},
+]
+pygments = [
+ {file = "Pygments-2.6.1-py3-none-any.whl", hash = "sha256:ff7a40b4860b727ab48fad6360eb351cc1b33cbf9b15a0f689ca5353e9463324"},
+ {file = "Pygments-2.6.1.tar.gz", hash = "sha256:647344a061c249a3b74e230c739f434d7ea4d8b1d5f3721bc0f3558049b38f44"},
+]
+pygount = [
+ {file = "pygount-1.1.0-py3-none-any.whl", hash = "sha256:253aff3b9c247e42208bf7f5fd46bebe4bbc221446095cd06df72addaf36bbc3"},
+]
+"pyjon.utils" = [
+ {file = "pyjon.utils-0.7-py2-none-any.whl", hash = "sha256:26946e5033e363f27f078cf81eaec01a920065722cc6b345ae95d06f8917f5f1"},
+ {file = "pyjon.utils-0.7-py2.7.egg", hash = "sha256:a119e2a7052d72c0475e2e114f5c423acb03cda59845bab574e05c4e6b232aec"},
+ {file = "pyjon.utils-0.7-py3-none-any.whl", hash = "sha256:8eaeb0267542d407f36b33dc7ce070cd5ec4ce48fc73b7e123c7d386dd73723a"},
+ {file = "pyjon.utils-0.7-py3.4.egg", hash = "sha256:df0624ce96872c386c95c350da547ffebfd1173a9a65822cf12b03f67387b82b"},
+ {file = "pyjon.utils-0.7.tar.gz", hash = "sha256:c2759ea361e00ef272ab65eb7af353398361d122f956efbf6a0241018f702d89"},
+ {file = "pyjon.utils-0.7.zip", hash = "sha256:d360fb393c2cf87ded962480895c83bc8c4f05f5b2ce7788bc5f16a67452bc2d"},
+]
+pyjwt = [
+ {file = "PyJWT-1.7.1-py2.py3-none-any.whl", hash = "sha256:5c6eca3c2940464d106b99ba83b00c6add741c9becaec087fb7ccdefea71350e"},
+ {file = "PyJWT-1.7.1.tar.gz", hash = "sha256:8d59a976fb773f3e6a39c85636357c4f0e242707394cadadd9814f5cbaa20e96"},
+]
+pyldap = [
+ {file = "pyldap-2.4.28.tar.gz", hash = "sha256:d38f31018f0c15925f50aec39f7255c15463f98797af53931e0e2a9ac21f6661"},
+]
+pymssql = [
+ {file = "pymssql-2.1.4-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:0479294789d7f230016d87e115a23e51617909611de7b1ced1263c1e365f6c91"},
+ {file = "pymssql-2.1.4-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:cfbce903ed29d2979168ac5d253e8241cb73901ec79c1e6692eb912ebc990be9"},
+ {file = "pymssql-2.1.4-cp27-cp27m-win32.whl", hash = "sha256:6da06dd6a37b3472b034a82fd156c63c6cb288b996a6ef252e874e343b37a254"},
+ {file = "pymssql-2.1.4-cp27-cp27m-win_amd64.whl", hash = "sha256:7544b8b1b38d101f0b7bd794d2da53dd19fee38e3dfe7312cd9bc87252347260"},
+ {file = "pymssql-2.1.4-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d3bf234eeb24ba6048ab1bb069395e3acd212376e91d8d7fdfdcfef60178cef4"},
+ {file = "pymssql-2.1.4-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:f58810f6917916af539948b3ed53881aca4aa7db80b662dcabcbf93a3cdea938"},
+ {file = "pymssql-2.1.4-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:084deb1462fb52c0d802b006c673f3a02ce562b7b3a2f65f6a6bd2162a0850a2"},
+ {file = "pymssql-2.1.4-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:ebecdd63e9a6c871dcd25c877895f9ed2ba96549743cb4d45d201fc478f1bf28"},
+ {file = "pymssql-2.1.4-cp34-cp34m-win32.whl", hash = "sha256:e077af5c80e768976b47789644bd7ea211131b5d8ed174e44995b3ef34009aad"},
+ {file = "pymssql-2.1.4-cp34-cp34m-win_amd64.whl", hash = "sha256:c32df8c15dda0a23551348a51b7b41f0bfe25be8925c7afebcef977f89cceb62"},
+ {file = "pymssql-2.1.4-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:e730e1fbbde44227ad34c024e71c1764503cf97c3812c520766867d1ee916e68"},
+ {file = "pymssql-2.1.4-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:fb340fbf5525ea51c5d4b704340a6fe8ec97e5380b5cd17107ea48179d1c1605"},
+ {file = "pymssql-2.1.4-cp35-cp35m-win32.whl", hash = "sha256:254e3552b6a52b40cb437f4b75683e003398f8ce12da0e40908a07703882802d"},
+ {file = "pymssql-2.1.4-cp35-cp35m-win_amd64.whl", hash = "sha256:bc2f3f93711cb6262cee83f63e9e38021a79f0d1b4c0deec7f68de97b49a8938"},
+ {file = "pymssql-2.1.4-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:47a567ed94618a89c83b8ce24c886ff65f0c063ef02ed7240b98ab953ca95b5d"},
+ {file = "pymssql-2.1.4-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d30001a9e00dbbb7ca04922eeb4df89e946bb083bbf7114667b8cbb7e08d9a0c"},
+ {file = "pymssql-2.1.4-cp36-cp36m-win32.whl", hash = "sha256:056dacf9120ae3a01955c52ce425b7ee7da499b27bd80f3bfcfb4013ae7adff8"},
+ {file = "pymssql-2.1.4-cp36-cp36m-win_amd64.whl", hash = "sha256:46dcd9c2f371d7d5744c22d6a3dc426b10debd12e0cab5b69c92f29b8eb90e21"},
+ {file = "pymssql-2.1.4-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:7a3869e6f0ea3a49f4faf8489638341578b4e638e86dc4067a69e8fa5d0469a2"},
+ {file = "pymssql-2.1.4-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fe7e4bf3c79b3f0425588bd99188e431727f4d6b19249dcb81b94e10d261d86f"},
+ {file = "pymssql-2.1.4-cp37-cp37m-win32.whl", hash = "sha256:c830088a8c1571e4606edd461d5f2291c8dacea2cd615466fb4764773d968949"},
+ {file = "pymssql-2.1.4-cp37-cp37m-win_amd64.whl", hash = "sha256:4fd384371ddc260c12d79dc8bcc239c722d571d1701cba1ec7788617db603a06"},
+ {file = "pymssql-2.1.4.tar.gz", hash = "sha256:3201eb1b1263ad55b555d727ed8bed0b12b7b9de3ce5e529206e36d4be1a7afb"},
+]
+pynacl = [
+ {file = "PyNaCl-1.4.0-cp27-cp27m-macosx_10_10_x86_64.whl", hash = "sha256:ea6841bc3a76fa4942ce00f3bda7d436fda21e2d91602b9e21b7ca9ecab8f3ff"},
+ {file = "PyNaCl-1.4.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:d452a6746f0a7e11121e64625109bc4468fc3100452817001dbe018bb8b08514"},
+ {file = "PyNaCl-1.4.0-cp27-cp27m-win32.whl", hash = "sha256:2fe0fc5a2480361dcaf4e6e7cea00e078fcda07ba45f811b167e3f99e8cff574"},
+ {file = "PyNaCl-1.4.0-cp27-cp27m-win_amd64.whl", hash = "sha256:f8851ab9041756003119368c1e6cd0b9c631f46d686b3904b18c0139f4419f80"},
+ {file = "PyNaCl-1.4.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:7757ae33dae81c300487591c68790dfb5145c7d03324000433d9a2c141f82af7"},
+ {file = "PyNaCl-1.4.0-cp35-abi3-macosx_10_10_x86_64.whl", hash = "sha256:757250ddb3bff1eecd7e41e65f7f833a8405fede0194319f87899690624f2122"},
+ {file = "PyNaCl-1.4.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:30f9b96db44e09b3304f9ea95079b1b7316b2b4f3744fe3aaecccd95d547063d"},
+ {file = "PyNaCl-1.4.0-cp35-cp35m-win32.whl", hash = "sha256:06cbb4d9b2c4bd3c8dc0d267416aaed79906e7b33f114ddbf0911969794b1cc4"},
+ {file = "PyNaCl-1.4.0-cp35-cp35m-win_amd64.whl", hash = "sha256:511d269ee845037b95c9781aa702f90ccc36036f95d0f31373a6a79bd8242e25"},
+ {file = "PyNaCl-1.4.0-cp36-cp36m-win32.whl", hash = "sha256:11335f09060af52c97137d4ac54285bcb7df0cef29014a1a4efe64ac065434c4"},
+ {file = "PyNaCl-1.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:cd401ccbc2a249a47a3a1724c2918fcd04be1f7b54eb2a5a71ff915db0ac51c6"},
+ {file = "PyNaCl-1.4.0-cp37-cp37m-win32.whl", hash = "sha256:8122ba5f2a2169ca5da936b2e5a511740ffb73979381b4229d9188f6dcb22f1f"},
+ {file = "PyNaCl-1.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:537a7ccbea22905a0ab36ea58577b39d1fa9b1884869d173b5cf111f006f689f"},
+ {file = "PyNaCl-1.4.0-cp38-cp38-win32.whl", hash = "sha256:9c4a7ea4fb81536c1b1f5cc44d54a296f96ae78c1ebd2311bd0b60be45a48d96"},
+ {file = "PyNaCl-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:7c6092102219f59ff29788860ccb021e80fffd953920c4a8653889c029b2d420"},
+ {file = "PyNaCl-1.4.0.tar.gz", hash = "sha256:54e9a2c849c742006516ad56a88f5c74bf2ce92c9f67435187c3c5953b346505"},
+]
+pyotp = [
+ {file = "pyotp-2.4.0-py2.py3-none-any.whl", hash = "sha256:e96c2d725d0b613b793775bb184e90297fda5f4989e210e28acf08a09ac2cc83"},
+ {file = "pyotp-2.4.0.tar.gz", hash = "sha256:01eceab573181188fe038d001e42777884a7f5367203080ef5bda0e30fe82d28"},
+]
+pyparsing = [
+ {file = "pyparsing-2.1.10-py2.py3-none-any.whl", hash = "sha256:67101d7acee692962f33dd30b5dce079ff532dd9aa99ff48d52a3dad51d2fe84"},
+ {file = "pyparsing-2.1.10.tar.gz", hash = "sha256:811c3e7b0031021137fc83e051795025fcb98674d07eb8fe922ba4de53d39188"},
+ {file = "pyparsing-2.1.10.win32-py2.6.exe", hash = "sha256:a27bf672302765ab04ed5c976dd44c55c0702f7a25a5e5e78bc91207d5b07da4"},
+ {file = "pyparsing-2.1.10.win32-py2.7.exe", hash = "sha256:0fef8411ad305909b1a679471d66f25ef4477f24666598deceb4bb640c2eb6c2"},
+ {file = "pyparsing-2.1.10.win32-py3.3.exe", hash = "sha256:a00f6e57bf4e2b3d999223d36c14d839f12145d5b1f12126124424e8c43d856e"},
+ {file = "pyparsing-2.1.10.win32-py3.4.exe", hash = "sha256:a163f9079b84da728e4967e3f36476ed168d86b2fc2f49c6e609125600f9d60b"},
+ {file = "pyparsing-2.1.10.win32-py3.5.exe", hash = "sha256:4fa446b1c36509e75d883a1a552b51dda9b82bfd914a24ded17ceb5d90b53cc5"},
+ {file = "pyparsing-2.1.10.zip", hash = "sha256:0aa6e8d8c3f9c447a95a33bb04b103ead630121c3f4233e2980348cecf8b69c8"},
+]
+pypdf2 = [
+ {file = "PyPDF2-1.26.0.tar.gz", hash = "sha256:e28f902f2f0a1603ea95ebe21dff311ef09be3d0f0ef29a3e44a932729564385"},
+]
+pypdf4 = [
+ {file = "PyPDF4-1.27.0.tar.gz", hash = "sha256:7c932441146d205572f96254d53c79ea2c30c9e11df55a5cf87e056c7b3d7f89"},
+]
+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"},
+]
+pyrfc = [
+ {file = "pyrfc-0.1.2.tar.gz", hash = "sha256:101ab6ac5c99025caf8d2f1e728dac1650d9b8a8c584120c670bc9ff32977578"},
+]
+pyrsistent = [
+ {file = "pyrsistent-0.16.0.tar.gz", hash = "sha256:28669905fe725965daa16184933676547c5bb40a5153055a8dee2a4bd7933ad3"},
+]
+pyserial = [
+ {file = "pyserial-3.1.1-py2.py3-none-any.whl", hash = "sha256:b4fcd6a7d329c844781df80fb06a4a9e21f3ac5623a687a975cbce8a8e4a82d2"},
+ {file = "pyserial-3.1.1.tar.gz", hash = "sha256:d657051249ce3cbd0446bcfb2be07a435e1029da4d63f53ed9b4cdde7373364c"},
+]
+pysftp = [
+ {file = "pysftp-0.2.9.tar.gz", hash = "sha256:fbf55a802e74d663673400acd92d5373c1c7ee94d765b428d9f977567ac4854a"},
+]
+python-chess = [
+ {file = "python-chess-0.23.11.tar.gz", hash = "sha256:3a44abcfbab240aa82ce489c77fd7bc4b8cd4292cae4942661837e77a18de0a0"},
+]
+python-csv = [
+ {file = "python-csv-0.0.13.tar.gz", hash = "sha256:852b88f33c3c316fcbaa55dae4f110b31278ef6b92aa1d03e3bb6736f831ac65"},
+]
+python-dateutil = [
+ {file = "python-dateutil-2.7.3.tar.gz", hash = "sha256:e27001de32f627c22380a688bcc43ce83504a7bc5da472209b4c70f02829f0b8"},
+ {file = "python_dateutil-2.7.3-py2.py3-none-any.whl", hash = "sha256:1adb80e7a782c12e52ef9a8182bebeb73f1d7e24e374397af06fb4956c8dc5c0"},
+]
+python-git = [
+ {file = "python-git-2018.2.1.tar.gz", hash = "sha256:2da0a75b562bc966d8a3bc1d6a2f8fd9f0fb3a3d3f2eff2239213bcc400bde82"},
+ {file = "python_git-2018.2.1-py3-none-any.whl", hash = "sha256:87ef4aef32a65f44e301cff42e5d5f660a2ba8d6b9d7c021faedbb9028a57ba9"},
+]
+python-json-logger = [
+ {file = "python-json-logger-0.1.5.tar.gz", hash = "sha256:6ea7cec61bb7526ad0a022aba34998f8d32a197f94fea4462a187bcc08487260"},
+]
+python-keystoneclient = [
+ {file = "python-keystoneclient-3.22.0.tar.gz", hash = "sha256:6e2b6d2a5ae5d7aa26d4e52d1c682e08417d2c5d73ccc54cb65c54903a868cb4"},
+ {file = "python_keystoneclient-3.22.0-py2.py3-none-any.whl", hash = "sha256:b9f9e74219a44be7c9955c836ab9a7ae16bde7325db6db15b6e5fe140c11bc3a"},
+]
+python-slugify = [
+ {file = "python-slugify-4.0.1.tar.gz", hash = "sha256:69a517766e00c1268e5bbfc0d010a0a8508de0b18d30ad5a1ff357f8ae724270"},
+]
+python-stdnum = [
+ {file = "python-stdnum-1.13.tar.gz", hash = "sha256:120f83d33fb8b8be1b282f20dd755a892d5facf84f54fa21f75bbd2633128160"},
+ {file = "python_stdnum-1.13-py2.py3-none-any.whl", hash = "sha256:3d5d4430579cba88211d3ba4855a16faff235352a25a01d6ab70024686a75823"},
+]
+python-swiftclient = [
+ {file = "python-swiftclient-3.9.0.tar.gz", hash = "sha256:4f2097492e4c76e948882fc859bfa033ade09bed72f8e6b328e34a3467d9a377"},
+ {file = "python_swiftclient-3.9.0-py2.py3-none-any.whl", hash = "sha256:cba38ac00a69bcea610318bfbe4f8aaee9d7b46705359477b8d3602ea2009878"},
+]
+python-u2flib-server = [
+ {file = "python-u2flib-server-5.0.0.tar.gz", hash = "sha256:9b9044db13fe24abc7a07c2bdb4b7bb541ca275702f43ecbd0d9641c28bcc226"},
+]
+pytz = [
+ {file = "pytz-2017.2-py2.4.egg", hash = "sha256:c883c2d6670042c7bc1688645cac73dd2b03193d1f7a6847b6154e96890be06d"},
+ {file = "pytz-2017.2-py2.5.egg", hash = "sha256:03c9962afe00e503e2d96abab4e8998a0f84d4230fa57afe1e0528473698cdd9"},
+ {file = "pytz-2017.2-py2.6.egg", hash = "sha256:487e7d50710661116325747a9cd1744d3323f8e49748e287bc9e659060ec6bf9"},
+ {file = "pytz-2017.2-py2.7.egg", hash = "sha256:43f52d4c6a0be301d53ebd867de05e2926c35728b3260157d274635a0a947f1c"},
+ {file = "pytz-2017.2-py2.py3-none-any.whl", hash = "sha256:d1d6729c85acea5423671382868627129432fba9a89ecbb248d8d1c7a9f01c67"},
+ {file = "pytz-2017.2-py3.3.egg", hash = "sha256:54a935085f7bf101f86b2aff75bd9672b435f51c3339db2ff616e66845f2b8f9"},
+ {file = "pytz-2017.2-py3.4.egg", hash = "sha256:39504670abb5dae77f56f8eb63823937ce727d7cdd0088e6909e6dcac0f89043"},
+ {file = "pytz-2017.2-py3.5.egg", hash = "sha256:ddc93b6d41cfb81266a27d23a79e13805d4a5521032b512643af8729041a81b4"},
+ {file = "pytz-2017.2.zip", hash = "sha256:f5c056e8f62d45ba8215e5cb8f50dfccb198b4b9fbea8500674f3443e4689589"},
+]
+pyusb = [
+ {file = "PyUSB-1.0.0.tar.gz", hash = "sha256:5b34ffa74ac34f330bff949c94ee00ec4a9d147234db17ee2eed2a67c0275368"},
+]
+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"},
+]
+pyzbar = [
+ {file = "pyzbar-0.1.8-py2.py3-none-any.whl", hash = "sha256:0e204b904e093e5e75aa85e0203bb0e02888105732a509b51f31cff400f34265"},
+ {file = "pyzbar-0.1.8-py2.py3-none-win32.whl", hash = "sha256:7d6c01d2c0a352fa994aa91b5540d1caeaeaac466656eb41468ca5df33be9f2e"},
+ {file = "pyzbar-0.1.8-py2.py3-none-win_amd64.whl", hash = "sha256:496249b546be70ec98c0ff0ad9151e73daaffff129266df86150a15dcd8dac4c"},
+]
+qrcode = [
+ {file = "qrcode-5.3-py2.py3-none-any.whl", hash = "sha256:60222a612b83231ed99e6cb36e55311227c395d0d0f62e41bb51ebbb84a9a22b"},
+ {file = "qrcode-5.3.tar.gz", hash = "sha256:4115ccee832620df16b659d4653568331015c718a754855caf5930805d76924e"},
+]
+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-2.10.5-py2.py3-none-any.whl", hash = "sha256:97156b37d7cda4e7d8658be1148c983984e1a975090ba458cc7e244025191dbd"},
+ {file = "redis-2.10.5.tar.gz", hash = "sha256:5dfbae6acfc54edf0a7a415b99e0b21c0a3c27a7f787b292eea727b1facc5533"},
+]
+regex = [
+ {file = "regex-2020.7.14-cp27-cp27m-win32.whl", hash = "sha256:e46d13f38cfcbb79bfdb2964b0fe12561fe633caf964a77a5f8d4e45fe5d2ef7"},
+ {file = "regex-2020.7.14-cp27-cp27m-win_amd64.whl", hash = "sha256:6961548bba529cac7c07af2fd4d527c5b91bb8fe18995fed6044ac22b3d14644"},
+ {file = "regex-2020.7.14-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c50a724d136ec10d920661f1442e4a8b010a4fe5aebd65e0c2241ea41dbe93dc"},
+ {file = "regex-2020.7.14-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8a51f2c6d1f884e98846a0a9021ff6861bdb98457879f412fdc2b42d14494067"},
+ {file = "regex-2020.7.14-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:9c568495e35599625f7b999774e29e8d6b01a6fb684d77dee1f56d41b11b40cd"},
+ {file = "regex-2020.7.14-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:51178c738d559a2d1071ce0b0f56e57eb315bcf8f7d4cf127674b533e3101f88"},
+ {file = "regex-2020.7.14-cp36-cp36m-win32.whl", hash = "sha256:9eddaafb3c48e0900690c1727fba226c4804b8e6127ea409689c3bb492d06de4"},
+ {file = "regex-2020.7.14-cp36-cp36m-win_amd64.whl", hash = "sha256:14a53646369157baa0499513f96091eb70382eb50b2c82393d17d7ec81b7b85f"},
+ {file = "regex-2020.7.14-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:1269fef3167bb52631ad4fa7dd27bf635d5a0790b8e6222065d42e91bede4162"},
+ {file = "regex-2020.7.14-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d0a5095d52b90ff38592bbdc2644f17c6d495762edf47d876049cfd2968fbccf"},
+ {file = "regex-2020.7.14-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:4c037fd14c5f4e308b8370b447b469ca10e69427966527edcab07f52d88388f7"},
+ {file = "regex-2020.7.14-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:bc3d98f621898b4a9bc7fecc00513eec8f40b5b83913d74ccb445f037d58cd89"},
+ {file = "regex-2020.7.14-cp37-cp37m-win32.whl", hash = "sha256:46bac5ca10fb748d6c55843a931855e2727a7a22584f302dd9bb1506e69f83f6"},
+ {file = "regex-2020.7.14-cp37-cp37m-win_amd64.whl", hash = "sha256:0dc64ee3f33cd7899f79a8d788abfbec168410be356ed9bd30bbd3f0a23a7204"},
+ {file = "regex-2020.7.14-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5ea81ea3dbd6767873c611687141ec7b06ed8bab43f68fad5b7be184a920dc99"},
+ {file = "regex-2020.7.14-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:bbb332d45b32df41200380fff14712cb6093b61bd142272a10b16778c418e98e"},
+ {file = "regex-2020.7.14-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:c11d6033115dc4887c456565303f540c44197f4fc1a2bfb192224a301534888e"},
+ {file = "regex-2020.7.14-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:75aaa27aa521a182824d89e5ab0a1d16ca207318a6b65042b046053cfc8ed07a"},
+ {file = "regex-2020.7.14-cp38-cp38-win32.whl", hash = "sha256:d6cff2276e502b86a25fd10c2a96973fdb45c7a977dca2138d661417f3728341"},
+ {file = "regex-2020.7.14-cp38-cp38-win_amd64.whl", hash = "sha256:7a2dd66d2d4df34fa82c9dc85657c5e019b87932019947faece7983f2089a840"},
+ {file = "regex-2020.7.14.tar.gz", hash = "sha256:3a3af27a8d23143c49a3420efe5b3f8cf1a48c6fc8bc6856b03f638abc1833bb"},
+]
+reportlab = [
+ {file = "reportlab-3.3.0-cp27-none-win32.whl", hash = "sha256:5e43daa9e0aa0bf039059534ada27078a225a9dc79c881b76c7a3da2fc8f3122"},
+ {file = "reportlab-3.3.0-cp27-none-win_amd64.whl", hash = "sha256:8a98135473944e8dfb505c33cc1b868d6eba25aefea42260d99e5bf51670112d"},
+ {file = "reportlab-3.3.0-cp33-none-win32.whl", hash = "sha256:52e7f1b1fddc090bbfdb81076a9d5c56ed0d6e64c6cc244a06fb3a43620b3d47"},
+ {file = "reportlab-3.3.0-cp33-none-win_amd64.whl", hash = "sha256:fe0acf7463ac28e231d11a387a1f8dd50b7984c630eccef0c4299c55d16b77b3"},
+ {file = "reportlab-3.3.0-cp34-none-win32.whl", hash = "sha256:96db4db47652a3c848afb3c26438eea2d6b9827ae17ebff5e76dd01c491b8e2a"},
+ {file = "reportlab-3.3.0-cp34-none-win_amd64.whl", hash = "sha256:d932b66885aed7564672cc0750c75d1399495165bea205ecb4b2426bbd68514c"},
+ {file = "reportlab-3.3.0-cp35-none-win32.whl", hash = "sha256:4da11cd1e1407aa3fed5198aa5edfa4fb28c11f3b7cd3300330584ae4cfdb213"},
+ {file = "reportlab-3.3.0-cp35-none-win_amd64.whl", hash = "sha256:343ea8083cd964d026c579071b0bff079e043c8db8ee094127c12e28daa0e1d0"},
+ {file = "reportlab-3.3.0.tar.gz", hash = "sha256:f48900b9321bcb2871a46543993bd995148d769a11a9e24495f25b4ec0bbe267"},
+]
+requests = [
+ {file = "requests-2.20.0-py2.py3-none-any.whl", hash = "sha256:a84b8c9ab6239b578f22d1c21d51b696dcfe004032bb80ea832398d6909d7279"},
+ {file = "requests-2.20.0.tar.gz", hash = "sha256:99dcfdaaeb17caf6e526f32b6a7b780461512ab3f1d992187801694cba42770c"},
+]
+requests-mock = [
+ {file = "requests-mock-1.8.0.tar.gz", hash = "sha256:e68f46844e4cee9d447150343c9ae875f99fa8037c6dcf5f15bf1fe9ab43d226"},
+ {file = "requests_mock-1.8.0-py2.py3-none-any.whl", hash = "sha256:11215c6f4df72702aa357f205cf1e537cffd7392b3e787b58239bde5fb3db53b"},
+]
+requests-oauthlib = [
+ {file = "requests-oauthlib-1.1.0.tar.gz", hash = "sha256:eabd8eb700ebed81ba080c6ead96d39d6bdc39996094bd23000204f6965786b0"},
+ {file = "requests_oauthlib-1.1.0-py2.py3-none-any.whl", hash = "sha256:be76f2bb72ca5525998e81d47913e09b1ca8b7957ae89b46f787a79e68ad5e61"},
+ {file = "requests_oauthlib-1.1.0-py3.7.egg", hash = "sha256:490229d14a98e1b69612dcc1a22887ec14f5487dc1b8c6d7ba7f77a42ce7347b"},
+]
+requests-toolbelt = [
+ {file = "requests-toolbelt-0.9.1.tar.gz", hash = "sha256:968089d4584ad4ad7c171454f0a5c6dac23971e9472521ea3b6d49d610aa6fc0"},
+ {file = "requests_toolbelt-0.9.1-py2.py3-none-any.whl", hash = "sha256:380606e1d10dc85c3bd47bf5a6095f815ec007be7a8b69c878507068df059e6f"},
+]
+retrying = [
+ {file = "retrying-1.3.3.tar.gz", hash = "sha256:08c039560a6da2fe4f2c426d0766e284d3b736e355f8dd24b37367b0bb41973b"},
+]
+rfc3986 = [
+ {file = "rfc3986-1.4.0-py2.py3-none-any.whl", hash = "sha256:af9147e9aceda37c91a05f4deb128d4b4b49d6b199775fd2d2927768abdc8f50"},
+ {file = "rfc3986-1.4.0.tar.gz", hash = "sha256:112398da31a3344dc25dbf477d8df6cb34f9278a94fee2625d89e4514be8bb9d"},
+]
+rotate-backups = [
+ {file = "rotate-backups-4.3.tar.gz", hash = "sha256:8824f97f3e928f46728749669b039d994e88cd7c583ebb7f83f4325b892ab794"},
+ {file = "rotate_backups-4.3-py2.py3-none-any.whl", hash = "sha256:c71170fa2c5cb40214cb63cef37cc3b696582f6676918517eec97654ea858a20"},
+]
+rotate-backups-s3 = [
+ {file = "rotate-backups-s3-0.3.tar.gz", hash = "sha256:b5be4294a82d9b8619a60d17feca41142c617510fc13ea2e9ba2800c347d02ef"},
+]
+s3transfer = [
+ {file = "s3transfer-0.2.1-py2.py3-none-any.whl", hash = "sha256:b780f2411b824cb541dbcd2c713d0cb61c7d1bcadae204cdddda2b35cef493ba"},
+ {file = "s3transfer-0.2.1.tar.gz", hash = "sha256:6efc926738a3cd576c2a79725fed9afde92378aa5c6a957e3af010cb019fac9d"},
+]
+schema = [
+ {file = "schema-0.3.1.tar.gz", hash = "sha256:0b9e883edb898971125112f1737d403ffd777513caf69a44b3b0765239797c18"},
+]
+send2trash = [
+ {file = "Send2Trash-1.5.0-py3-none-any.whl", hash = "sha256:f1691922577b6fa12821234aeb57599d887c4900b9ca537948d2dac34aea888b"},
+ {file = "Send2Trash-1.5.0.tar.gz", hash = "sha256:60001cc07d707fe247c94f74ca6ac0d3255aabcb930529690897ca2a39db28b2"},
+]
+serial = [
+ {file = "serial-0.0.97-py2.py3-none-any.whl", hash = "sha256:e887f06e07e190e39174b694eee6724e3c48bd361be1d97964caef5d5b61c73b"},
+ {file = "serial-0.0.97.tar.gz", hash = "sha256:542150a127ddbf5ed2acc3a6ac4ce807cbcdae3b197acf785bbda6565c94f848"},
+]
+shapely = [
+ {file = "Shapely-1.6.4.post2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3ca69d4b12e2b05b549465822744b6a3a1095d8488cc27b2728a06d3c07d0eee"},
+ {file = "Shapely-1.6.4.post2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:714b6680215554731389a1bbdae4cec61741aa4726921fa2b2b96a6f578a2534"},
+ {file = "Shapely-1.6.4.post2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:5d22a1a705c2f70f61ccadc696e33d922c1a92e00df8e1d58a6ade14dd7e3b4f"},
+ {file = "Shapely-1.6.4.post2-cp34-cp34m-macosx_10_9_intel.macosx_10_9_x86_64.whl", hash = "sha256:34e7c6f41fb27906ccdf2514ee44a5774b90b39a256b6511a6a57d11ffe64999"},
+ {file = "Shapely-1.6.4.post2-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:3e9388f29bd81fcd4fa5c35125e1fbd4975ee36971a87a90c093f032d0e9de24"},
+ {file = "Shapely-1.6.4.post2-cp35-cp35m-macosx_10_9_intel.macosx_10_9_x86_64.whl", hash = "sha256:0378964902f89b8dbc332e5bdfa08e0bc2f7ab39fecaeb17fbb2a7699a44fe71"},
+ {file = "Shapely-1.6.4.post2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:523c94403047eb6cacd7fc1863ebef06e26c04d8a4e7f8f182d49cd206fe787e"},
+ {file = "Shapely-1.6.4.post2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:ba58b21b9cf3c33725f7f530febff9ed6a6846f9d0bf8a120fc74683ff919f89"},
+ {file = "Shapely-1.6.4.post2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ebb4d2bee7fac3f6c891fcdafaa17f72ab9c6480f6d00de0b2dc9a5137dfe342"},
+ {file = "Shapely-1.6.4.post2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7dfe1528650c3f0dc82f41a74cf4f72018288db9bfb75dcd08f6f04233ec7e78"},
+ {file = "Shapely-1.6.4.post2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:3ef28e3f20a1c37f5b99ea8cf8dcb58e2f1a8762d65ed2d21fd92bf1d4811182"},
+ {file = "Shapely-1.6.4.post2.tar.gz", hash = "sha256:c4b87bb61fc3de59fc1f85e71a79b0c709dc68364d9584473697aad4aa13240f"},
+]
+simpleeval = [
+ {file = "simpleeval-0.9.10.tar.gz", hash = "sha256:692055488c2864637f6c2edb5fa48175978a2a07318009e7cf03c9790ca17bea"},
+]
+simplejson = [
+ {file = "simplejson-3.17.2-cp27-cp27m-macosx_10_13_x86_64.whl", hash = "sha256:2d3eab2c3fe52007d703a26f71cf649a8c771fcdd949a3ae73041ba6797cfcf8"},
+ {file = "simplejson-3.17.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:813846738277729d7db71b82176204abc7fdae2f566e2d9fcf874f9b6472e3e6"},
+ {file = "simplejson-3.17.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:292c2e3f53be314cc59853bd20a35bf1f965f3bc121e007ab6fd526ed412a85d"},
+ {file = "simplejson-3.17.2-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:0dd9d9c738cb008bfc0862c9b8fa6743495c03a0ed543884bf92fb7d30f8d043"},
+ {file = "simplejson-3.17.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:42b8b8dd0799f78e067e2aaae97e60d58a8f63582939af60abce4c48631a0aa4"},
+ {file = "simplejson-3.17.2-cp27-cp27m-win32.whl", hash = "sha256:8042040af86a494a23c189b5aa0ea9433769cc029707833f261a79c98e3375f9"},
+ {file = "simplejson-3.17.2-cp27-cp27m-win_amd64.whl", hash = "sha256:034550078a11664d77bc1a8364c90bb7eef0e44c2dbb1fd0a4d92e3997088667"},
+ {file = "simplejson-3.17.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:fed0f22bf1313ff79c7fc318f7199d6c2f96d4de3234b2f12a1eab350e597c06"},
+ {file = "simplejson-3.17.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:2e7b57c2c146f8e4dadf84977a83f7ee50da17c8861fd7faf694d55e3274784f"},
+ {file = "simplejson-3.17.2-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:da3c55cdc66cfc3fffb607db49a42448785ea2732f055ac1549b69dcb392663b"},
+ {file = "simplejson-3.17.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:c1cb29b1fced01f97e6d5631c3edc2dadb424d1f4421dad079cb13fc97acb42f"},
+ {file = "simplejson-3.17.2-cp33-cp33m-win32.whl", hash = "sha256:8f713ea65958ef40049b6c45c40c206ab363db9591ff5a49d89b448933fa5746"},
+ {file = "simplejson-3.17.2-cp33-cp33m-win_amd64.whl", hash = "sha256:344e2d920a7f27b4023c087ab539877a1e39ce8e3e90b867e0bfa97829824748"},
+ {file = "simplejson-3.17.2-cp34-cp34m-win32.whl", hash = "sha256:05b43d568300c1cd43f95ff4bfcff984bc658aa001be91efb3bb21df9d6288d3"},
+ {file = "simplejson-3.17.2-cp34-cp34m-win_amd64.whl", hash = "sha256:cff6453e25204d3369c47b97dd34783ca820611bd334779d22192da23784194b"},
+ {file = "simplejson-3.17.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:8acf76443cfb5c949b6e781c154278c059b09ac717d2757a830c869ba000cf8d"},
+ {file = "simplejson-3.17.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:869a183c8e44bc03be1b2bbcc9ec4338e37fa8557fc506bf6115887c1d3bb956"},
+ {file = "simplejson-3.17.2-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:5c659a0efc80aaaba57fcd878855c8534ecb655a28ac8508885c50648e6e659d"},
+ {file = "simplejson-3.17.2-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:72d8a3ffca19a901002d6b068cf746be85747571c6a7ba12cbcf427bfb4ed971"},
+ {file = "simplejson-3.17.2-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:4b3442249d5e3893b90cb9f72c7d6ce4d2ea144d2c0d9f75b9ae1e5460f3121a"},
+ {file = "simplejson-3.17.2-cp35-cp35m-win32.whl", hash = "sha256:e058c7656c44fb494a11443191e381355388443d543f6fc1a245d5d238544396"},
+ {file = "simplejson-3.17.2-cp35-cp35m-win_amd64.whl", hash = "sha256:934115642c8ba9659b402c8bdbdedb48651fb94b576e3b3efd1ccb079609b04a"},
+ {file = "simplejson-3.17.2-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:ffd4e4877a78c84d693e491b223385e0271278f5f4e1476a4962dca6824ecfeb"},
+ {file = "simplejson-3.17.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:10fc250c3edea4abc15d930d77274ddb8df4803453dde7ad50c2f5565a18a4bb"},
+ {file = "simplejson-3.17.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:76ac9605bf2f6d9b56abf6f9da9047a8782574ad3531c82eae774947ae99cc3f"},
+ {file = "simplejson-3.17.2-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:7f10f8ba9c1b1430addc7dd385fc322e221559d3ae49b812aebf57470ce8de45"},
+ {file = "simplejson-3.17.2-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:bc00d1210567a4cdd215ac6e17dc00cb9893ee521cee701adfd0fa43f7c73139"},
+ {file = "simplejson-3.17.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:af4868da7dd53296cd7630687161d53a7ebe2e63814234631445697bd7c29f46"},
+ {file = "simplejson-3.17.2-cp36-cp36m-win32.whl", hash = "sha256:7d276f69bfc8c7ba6c717ba8deaf28f9d3c8450ff0aa8713f5a3280e232be16b"},
+ {file = "simplejson-3.17.2-cp36-cp36m-win_amd64.whl", hash = "sha256:a55c76254d7cf8d4494bc508e7abb993a82a192d0db4552421e5139235604625"},
+ {file = "simplejson-3.17.2-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:9a2b7543559f8a1c9ed72724b549d8cc3515da7daf3e79813a15bdc4a769de25"},
+ {file = "simplejson-3.17.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:311f5dc2af07361725033b13cc3d0351de3da8bede3397d45650784c3f21fbcf"},
+ {file = "simplejson-3.17.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:2862beabfb9097a745a961426fe7daf66e1714151da8bb9a0c430dde3d59c7c0"},
+ {file = "simplejson-3.17.2-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:afebfc3dd3520d37056f641969ce320b071bc7a0800639c71877b90d053e087f"},
+ {file = "simplejson-3.17.2-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:d4813b30cb62d3b63ccc60dd12f2121780c7a3068db692daeb90f989877aaf04"},
+ {file = "simplejson-3.17.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:3fabde09af43e0cbdee407555383063f8b45bfb52c361bc5da83fcffdb4fd278"},
+ {file = "simplejson-3.17.2-cp37-cp37m-win32.whl", hash = "sha256:ceaa28a5bce8a46a130cd223e895080e258a88d51bf6e8de2fc54a6ef7e38c34"},
+ {file = "simplejson-3.17.2-cp37-cp37m-win_amd64.whl", hash = "sha256:9551f23e09300a9a528f7af20e35c9f79686d46d646152a0c8fc41d2d074d9b0"},
+ {file = "simplejson-3.17.2-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:c94dc64b1a389a416fc4218cd4799aa3756f25940cae33530a4f7f2f54f166da"},
+ {file = "simplejson-3.17.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:b59aa298137ca74a744c1e6e22cfc0bf9dca3a2f41f51bc92eb05695155d905a"},
+ {file = "simplejson-3.17.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:ad8f41c2357b73bc9e8606d2fa226233bf4d55d85a8982ecdfd55823a6959995"},
+ {file = "simplejson-3.17.2-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:845a14f6deb124a3bcb98a62def067a67462a000e0508f256f9c18eff5847efc"},
+ {file = "simplejson-3.17.2-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:d0b64409df09edb4c365d95004775c988259efe9be39697d7315c42b7a5e7e94"},
+ {file = "simplejson-3.17.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:55d65f9cc1b733d85ef95ab11f559cce55c7649a2160da2ac7a078534da676c8"},
+ {file = "simplejson-3.17.2.tar.gz", hash = "sha256:75ecc79f26d99222a084fbdd1ce5aad3ac3a8bd535cd9059528452da38b68841"},
+]
+six = [
+ {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"},
+ {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"},
+]
+slugify = [
+ {file = "slugify-0.0.1.tar.gz", hash = "sha256:c5703cc11c1a6947536f3ce8bb306766b8bb5a84a53717f5a703ce0f18235e4c"},
+]
+smmap = [
+ {file = "smmap-3.0.4-py2.py3-none-any.whl", hash = "sha256:54c44c197c819d5ef1991799a7e30b662d1e520f2ac75c9efbeb54a742214cf4"},
+ {file = "smmap-3.0.4.tar.gz", hash = "sha256:9c98bbd1f9786d22f14b3d4126894d56befb835ec90cef151af566c7e19b5d24"},
+]
+snowballstemmer = [
+ {file = "snowballstemmer-2.0.0-py2.py3-none-any.whl", hash = "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0"},
+ {file = "snowballstemmer-2.0.0.tar.gz", hash = "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52"},
+]
+soappy = [
+ {file = "SOAPpy-0.12.22.zip", hash = "sha256:e70845906bb625144ae6a8df4534d66d84431ff8e21835d7b401ec6d8eb447a5"},
+]
+soupsieve = [
+ {file = "soupsieve-1.9.6-py2.py3-none-any.whl", hash = "sha256:feb1e937fa26a69e08436aad4a9037cd7e1d4c7212909502ba30701247ff8abd"},
+ {file = "soupsieve-1.9.6.tar.gz", hash = "sha256:7985bacc98c34923a439967c1a602dc4f1e15f923b6fcf02344184f86cc7efaa"},
+]
+sphinx = [
+ {file = "Sphinx-3.1.2-py3-none-any.whl", hash = "sha256:97dbf2e31fc5684bb805104b8ad34434ed70e6c588f6896991b2fdfd2bef8c00"},
+ {file = "Sphinx-3.1.2.tar.gz", hash = "sha256:b9daeb9b39aa1ffefc2809b43604109825300300b987a24f45976c001ba1a8fd"},
+]
+sphinx-patchqueue = [
+ {file = "sphinx-patchqueue-1.0.4.tar.gz", hash = "sha256:00362a5985c79eb038ab4a564f9944cfd097bd94350caab4fdebaabfb9eb3bd3"},
+]
+sphinxcontrib-applehelp = [
+ {file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"},
+ {file = "sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a"},
+]
+sphinxcontrib-devhelp = [
+ {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"},
+ {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"},
+]
+sphinxcontrib-htmlhelp = [
+ {file = "sphinxcontrib-htmlhelp-1.0.3.tar.gz", hash = "sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b"},
+ {file = "sphinxcontrib_htmlhelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f"},
+]
+sphinxcontrib-jsmath = [
+ {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"},
+ {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"},
+]
+sphinxcontrib-qthelp = [
+ {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"},
+ {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"},
+]
+sphinxcontrib-serializinghtml = [
+ {file = "sphinxcontrib-serializinghtml-1.1.4.tar.gz", hash = "sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc"},
+ {file = "sphinxcontrib_serializinghtml-1.1.4-py2.py3-none-any.whl", hash = "sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a"},
+]
+sqlalchemy = [
+ {file = "SQLAlchemy-1.3.18-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:f11c2437fb5f812d020932119ba02d9e2bc29a6eca01a055233a8b449e3e1e7d"},
+ {file = "SQLAlchemy-1.3.18-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:0ec575db1b54909750332c2e335c2bb11257883914a03bc5a3306a4488ecc772"},
+ {file = "SQLAlchemy-1.3.18-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:f57be5673e12763dd400fea568608700a63ce1c6bd5bdbc3cc3a2c5fdb045274"},
+ {file = "SQLAlchemy-1.3.18-cp27-cp27m-win32.whl", hash = "sha256:8cac7bb373a5f1423e28de3fd5fc8063b9c8ffe8957dc1b1a59cb90453db6da1"},
+ {file = "SQLAlchemy-1.3.18-cp27-cp27m-win_amd64.whl", hash = "sha256:adad60eea2c4c2a1875eb6305a0b6e61a83163f8e233586a4d6a55221ef984fe"},
+ {file = "SQLAlchemy-1.3.18-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:57aa843b783179ab72e863512e14bdcba186641daf69e4e3a5761d705dcc35b1"},
+ {file = "SQLAlchemy-1.3.18-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:621f58cd921cd71ba6215c42954ffaa8a918eecd8c535d97befa1a8acad986dd"},
+ {file = "SQLAlchemy-1.3.18-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:fc728ece3d5c772c196fd338a99798e7efac7a04f9cb6416299a3638ee9a94cd"},
+ {file = "SQLAlchemy-1.3.18-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:736d41cfebedecc6f159fc4ac0769dc89528a989471dc1d378ba07d29a60ba1c"},
+ {file = "SQLAlchemy-1.3.18-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:427273b08efc16a85aa2b39892817e78e3ed074fcb89b2a51c4979bae7e7ba98"},
+ {file = "SQLAlchemy-1.3.18-cp35-cp35m-win32.whl", hash = "sha256:cbe1324ef52ff26ccde2cb84b8593c8bf930069dfc06c1e616f1bfd4e47f48a3"},
+ {file = "SQLAlchemy-1.3.18-cp35-cp35m-win_amd64.whl", hash = "sha256:8fd452dc3d49b3cc54483e033de6c006c304432e6f84b74d7b2c68afa2569ae5"},
+ {file = "SQLAlchemy-1.3.18-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:e89e0d9e106f8a9180a4ca92a6adde60c58b1b0299e1b43bd5e0312f535fbf33"},
+ {file = "SQLAlchemy-1.3.18-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:6ac2558631a81b85e7fb7a44e5035347938b0a73f5fdc27a8566777d0792a6a4"},
+ {file = "SQLAlchemy-1.3.18-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:87fad64529cde4f1914a5b9c383628e1a8f9e3930304c09cf22c2ae118a1280e"},
+ {file = "SQLAlchemy-1.3.18-cp36-cp36m-win32.whl", hash = "sha256:e4624d7edb2576cd72bb83636cd71c8ce544d8e272f308bd80885056972ca299"},
+ {file = "SQLAlchemy-1.3.18-cp36-cp36m-win_amd64.whl", hash = "sha256:89494df7f93b1836cae210c42864b292f9b31eeabca4810193761990dc689cce"},
+ {file = "SQLAlchemy-1.3.18-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:716754d0b5490bdcf68e1e4925edc02ac07209883314ad01a137642ddb2056f1"},
+ {file = "SQLAlchemy-1.3.18-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:50c4ee32f0e1581828843267d8de35c3298e86ceecd5e9017dc45788be70a864"},
+ {file = "SQLAlchemy-1.3.18-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:d98bc827a1293ae767c8f2f18be3bb5151fd37ddcd7da2a5f9581baeeb7a3fa1"},
+ {file = "SQLAlchemy-1.3.18-cp37-cp37m-win32.whl", hash = "sha256:0942a3a0df3f6131580eddd26d99071b48cfe5aaf3eab2783076fbc5a1c1882e"},
+ {file = "SQLAlchemy-1.3.18-cp37-cp37m-win_amd64.whl", hash = "sha256:16593fd748944726540cd20f7e83afec816c2ac96b082e26ae226e8f7e9688cf"},
+ {file = "SQLAlchemy-1.3.18-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:c26f95e7609b821b5f08a72dab929baa0d685406b953efd7c89423a511d5c413"},
+ {file = "SQLAlchemy-1.3.18-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:512a85c3c8c3995cc91af3e90f38f460da5d3cade8dc3a229c8e0879037547c9"},
+ {file = "SQLAlchemy-1.3.18-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:d05c4adae06bd0c7f696ae3ec8d993ed8ffcc4e11a76b1b35a5af8a099bd2284"},
+ {file = "SQLAlchemy-1.3.18-cp38-cp38-win32.whl", hash = "sha256:109581ccc8915001e8037b73c29590e78ce74be49ca0a3630a23831f9e3ed6c7"},
+ {file = "SQLAlchemy-1.3.18-cp38-cp38-win_amd64.whl", hash = "sha256:8619b86cb68b185a778635be5b3e6018623c0761dde4df2f112896424aa27bd8"},
+ {file = "SQLAlchemy-1.3.18.tar.gz", hash = "sha256:da2fb75f64792c1fc64c82313a00c728a7c301efe6a60b7a9fe35b16b4368ce7"},
+]
+statsd = [
+ {file = "statsd-3.2.1-py2.py3-none-any.whl", hash = "sha256:7aff40c6cdda703193fac6231410c6c0ad5939ce053a168016501e982c755c84"},
+ {file = "statsd-3.2.1.tar.gz", hash = "sha256:3fa92bf0192af926f7a0d9be031fe3fd0fbaa1992d42cf2f07e68f76ac18288e"},
+]
+stevedore = [
+ {file = "stevedore-3.2.0-py3-none-any.whl", hash = "sha256:c8f4f0ebbc394e52ddf49de8bcc3cf8ad2b4425ebac494106bbc5e3661ac7633"},
+ {file = "stevedore-3.2.0.tar.gz", hash = "sha256:38791aa5bed922b0a844513c5f9ed37774b68edc609e5ab8ab8d8fe0ce4315e5"},
+]
+suds-jurko = [
+ {file = "suds-jurko-0.6.tar.bz2", hash = "sha256:29edb72fd21e3044093d86f33c66cf847c5aaab26d64cb90e69e528ef014e57f"},
+ {file = "suds-jurko-0.6.zip", hash = "sha256:1cb7252cb13018fc32887c3a834ed7c6648a5b5c4c159be5806da2e1785399e8"},
+]
+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.1-py2.py3-none-any.whl", hash = "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"},
+ {file = "toml-0.10.1.tar.gz", hash = "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f"},
+]
+toolz = [
+ {file = "toolz-0.10.0.tar.gz", hash = "sha256:08fdd5ef7c96480ad11c12d472de21acd32359996f69a5259299b540feba4560"},
+]
+tornado = [
+ {file = "tornado-6.0.4-cp35-cp35m-win32.whl", hash = "sha256:5217e601700f24e966ddab689f90b7ea4bd91ff3357c3600fa1045e26d68e55d"},
+ {file = "tornado-6.0.4-cp35-cp35m-win_amd64.whl", hash = "sha256:c98232a3ac391f5faea6821b53db8db461157baa788f5d6222a193e9456e1740"},
+ {file = "tornado-6.0.4-cp36-cp36m-win32.whl", hash = "sha256:5f6a07e62e799be5d2330e68d808c8ac41d4a259b9cea61da4101b83cb5dc673"},
+ {file = "tornado-6.0.4-cp36-cp36m-win_amd64.whl", hash = "sha256:c952975c8ba74f546ae6de2e226ab3cc3cc11ae47baf607459a6728585bb542a"},
+ {file = "tornado-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:2c027eb2a393d964b22b5c154d1a23a5f8727db6fda837118a776b29e2b8ebc6"},
+ {file = "tornado-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:5618f72e947533832cbc3dec54e1dffc1747a5cb17d1fd91577ed14fa0dc081b"},
+ {file = "tornado-6.0.4-cp38-cp38-win32.whl", hash = "sha256:22aed82c2ea340c3771e3babc5ef220272f6fd06b5108a53b4976d0d722bcd52"},
+ {file = "tornado-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:c58d56003daf1b616336781b26d184023ea4af13ae143d9dda65e31e534940b9"},
+ {file = "tornado-6.0.4.tar.gz", hash = "sha256:0fe2d45ba43b00a41cd73f8be321a44936dc1aba233dee979f17a042b83eb6dc"},
+]
+typing-extensions = [
+ {file = "typing_extensions-3.7.4.2-py2-none-any.whl", hash = "sha256:f8d2bd89d25bc39dabe7d23df520442fa1d8969b82544370e03d88b5a591c392"},
+ {file = "typing_extensions-3.7.4.2-py3-none-any.whl", hash = "sha256:6e95524d8a547a91e08f404ae485bbb71962de46967e1b71a0cb89af24e761c5"},
+ {file = "typing_extensions-3.7.4.2.tar.gz", hash = "sha256:79ee589a3caca649a9bfd2a8de4709837400dfa00b6cc81962a1e6a1815969ae"},
+]
+tzlocal = [
+ {file = "tzlocal-1.5.1.tar.gz", hash = "sha256:4ebeb848845ac898da6519b9b31879cf13b6626f7184c496037b818e238f2c4e"},
+]
+unidecode = [
+ {file = "Unidecode-1.0.22-py2.py3-none-any.whl", hash = "sha256:72f49d3729f3d8f5799f710b97c1451c5163102e76d64d20e170aedbbd923582"},
+ {file = "Unidecode-1.0.22.tar.gz", hash = "sha256:8c33dd588e0c9bc22a76eaa0c715a5434851f726131bd44a6c26471746efabf5"},
+]
+unidiff = [
+ {file = "unidiff-0.6.0-py2.py3-none-any.whl", hash = "sha256:e1dd956a492ccc4351e24931b2f2d29c79e3be17a99dd8f14e95324321d93a88"},
+ {file = "unidiff-0.6.0.tar.gz", hash = "sha256:90c5214e9a357ff4b2fee19d91e77706638e3e00592a732d9405ea4e93da981f"},
+]
+urllib3 = [
+ {file = "urllib3-1.24.3-py2.py3-none-any.whl", hash = "sha256:a637e5fae88995b256e3409dc4d52c2e2e0ba32c42a6365fee8bbd2238de3cfb"},
+ {file = "urllib3-1.24.3.tar.gz", hash = "sha256:2393a695cd12afedd0dcb26fe5d50d0cf248e5a66f75dbd89a3d4eb333a61af4"},
+]
+vatnumber = [
+ {file = "vatnumber-1.2.tar.gz", hash = "sha256:4e9e9cabcff6076d8deb8a347edfd5d0ab8cab1ed344fdbe5dd4a6110a2f2c7b"},
+]
+vcrpy = [
+ {file = "vcrpy-4.1.0-py2.py3-none-any.whl", hash = "sha256:d833248442bbc560599add895c9ab0ef518676579e8dc72d8b0933bdb3880253"},
+ {file = "vcrpy-4.1.0.tar.gz", hash = "sha256:4138e79eb35981ad391406cbb7227bce7eba8bad788dcf1a89c2e4a8b740debe"},
+]
+vcrpy-unittest = [
+ {file = "vcrpy-unittest-0.1.7.tar.gz", hash = "sha256:a508d8848e678243f1c0d4b152a645c18403a8da517b8a44dfcfc35a675ec981"},
+ {file = "vcrpy_unittest-0.1.7-py2.py3-none-any.whl", hash = "sha256:b5e2d78bf4c13bc04dca04061dda934abba5f2c9d5201f148747800ff80a762b"},
+]
+verboselogs = [
+ {file = "verboselogs-1.7-py2.py3-none-any.whl", hash = "sha256:d63f23bf568295b95d3530c6864a0b580cec70e7ff974177dead1e4ffbc6ff49"},
+ {file = "verboselogs-1.7.tar.gz", hash = "sha256:e33ddedcdfdafcb3a174701150430b11b46ceb64c2a9a26198c76a156568e427"},
+]
+vobject = [
+ {file = "vobject-0.9.3.tar.gz", hash = "sha256:10b150b87ee5fffefd3aa1ea12f31aab45a7b7d010d1ce6816afaff8db726520"},
+]
+voicent-python = [
+ {file = "Voicent-Python-1.0.tar.gz", hash = "sha256:c495d50752a3c35e044c6f5a08f2b00c5f81c7402b5b3087c49652e6af549c32"},
+ {file = "Voicent_Python-1.0-py2.py3-none-any.whl", hash = "sha256:de6446f1b69897cb3ce7a17ca2d060e5b191b8ed3980f1997858e8cb372fc3af"},
+]
+webcolors = [
+ {file = "webcolors-1.10-py2.py3-none-any.whl", hash = "sha256:2559b4f4694bfcd61c87ee06acad921bd2fdbf0c844bee65fc844c6910c413dd"},
+ {file = "webcolors-1.10.tar.gz", hash = "sha256:7b11194c414dcf4b9bd8fb5ceaafc9da183b27430883c62f620589eb79b91b6e"},
+]
+websocket-client = [
+ {file = "websocket_client-0.57.0-py2.py3-none-any.whl", hash = "sha256:0fc45c961324d79c781bab301359d5a1b00b13ad1b10415a4780229ef71a5549"},
+ {file = "websocket_client-0.57.0.tar.gz", hash = "sha256:d735b91d6d1692a6a181f2a8c9e0238e5f6373356f561bb9dc4c7af36f452010"},
+]
+werkzeug = [
+ {file = "Werkzeug-0.11.15-py2.py3-none-any.whl", hash = "sha256:c6f6f89124df0514d886782c658c3e12f2caaa94da34cee3fd82eebf4ebf052b"},
+ {file = "Werkzeug-0.11.15.tar.gz", hash = "sha256:455d7798ac263266dbd38d4841f7534dd35ca9c3da4a8df303f8488f38f3bcc0"},
+]
+wheel = [
+ {file = "wheel-0.34.2-py2.py3-none-any.whl", hash = "sha256:df277cb51e61359aba502208d680f90c0493adec6f0e848af94948778aed386e"},
+ {file = "wheel-0.34.2.tar.gz", hash = "sha256:8788e9155fe14f54164c1b9eb0a319d98ef02c160725587ad60f14ddc57b6f96"},
+]
+wrapt = [
+ {file = "wrapt-1.12.1.tar.gz", hash = "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"},
+]
+wstools = [
+ {file = "wstools-0.4.8-py2.py3-none-any.whl", hash = "sha256:e78cea7e6c3ff658d120b36b2151ad52c4daf4f1d0617ebf82b54ffc3bb694dd"},
+ {file = "wstools-0.4.8.tar.gz", hash = "sha256:7992e687d7e7a4dd29b4df55376cd8b6577e0f71f72c00cfbc4bbb24b574ecc2"},
+]
+xlrd = [
+ {file = "xlrd-1.0.0-py3-none-any.whl", hash = "sha256:05f55eb39a68f1c3d336de186aeb90c98ea5add722813738d8ae8b97819c5924"},
+ {file = "xlrd-1.0.0.tar.gz", hash = "sha256:0ff87dd5d50425084f7219cb6f86bb3eb5aa29063f53d50bf270ed007e941069"},
+]
+xlsxwriter = [
+ {file = "XlsxWriter-0.9.3-py2.py3-none-any.whl", hash = "sha256:59f50a2135afcf53804c46ae4f849ca9751963d729a330767834aee9ff9525e4"},
+ {file = "XlsxWriter-0.9.3.tar.gz", hash = "sha256:19d2b5c0dd4d5fc00e8d7f164795f50e885b20d1cc27a3d04d5c7fec3c4d57f6"},
+]
+xlwt = [
+ {file = "xlwt-1.3.0-py2.py3-none-any.whl", hash = "sha256:a082260524678ba48a297d922cc385f58278b8aa68741596a87de01a9c628b2e"},
+ {file = "xlwt-1.3.0.tar.gz", hash = "sha256:c59912717a9b28f1a3c2a98fd60741014b06b043936dcecbc113eaaada156c88"},
+]
+xmltodict = [
+ {file = "xmltodict-0.12.0-py2.py3-none-any.whl", hash = "sha256:8bbcb45cc982f48b2ca8fe7e7827c5d792f217ecf1792626f808bf41c3b86051"},
+ {file = "xmltodict-0.12.0.tar.gz", hash = "sha256:50d8c638ed7ecb88d90561beedbf720c9b4e851a9fa6c47ebd64e99d166d8a21"},
+]
+yarl = [
+ {file = "yarl-1.5.1-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:db6db0f45d2c63ddb1a9d18d1b9b22f308e52c83638c26b422d520a815c4b3fb"},
+ {file = "yarl-1.5.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:17668ec6722b1b7a3a05cc0167659f6c95b436d25a36c2d52db0eca7d3f72593"},
+ {file = "yarl-1.5.1-cp35-cp35m-win32.whl", hash = "sha256:040b237f58ff7d800e6e0fd89c8439b841f777dd99b4a9cca04d6935564b9409"},
+ {file = "yarl-1.5.1-cp35-cp35m-win_amd64.whl", hash = "sha256:f18d68f2be6bf0e89f1521af2b1bb46e66ab0018faafa81d70f358153170a317"},
+ {file = "yarl-1.5.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:c52ce2883dc193824989a9b97a76ca86ecd1fa7955b14f87bf367a61b6232511"},
+ {file = "yarl-1.5.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ce584af5de8830d8701b8979b18fcf450cef9a382b1a3c8ef189bedc408faf1e"},
+ {file = "yarl-1.5.1-cp36-cp36m-win32.whl", hash = "sha256:df89642981b94e7db5596818499c4b2219028f2a528c9c37cc1de45bf2fd3a3f"},
+ {file = "yarl-1.5.1-cp36-cp36m-win_amd64.whl", hash = "sha256:3a584b28086bc93c888a6c2aa5c92ed1ae20932f078c46509a66dce9ea5533f2"},
+ {file = "yarl-1.5.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:da456eeec17fa8aa4594d9a9f27c0b1060b6a75f2419fe0c00609587b2695f4a"},
+ {file = "yarl-1.5.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bc2f976c0e918659f723401c4f834deb8a8e7798a71be4382e024bcc3f7e23a8"},
+ {file = "yarl-1.5.1-cp37-cp37m-win32.whl", hash = "sha256:4439be27e4eee76c7632c2427ca5e73703151b22cae23e64adb243a9c2f565d8"},
+ {file = "yarl-1.5.1-cp37-cp37m-win_amd64.whl", hash = "sha256:48e918b05850fffb070a496d2b5f97fc31d15d94ca33d3d08a4f86e26d4e7c5d"},
+ {file = "yarl-1.5.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:9b930776c0ae0c691776f4d2891ebc5362af86f152dd0da463a6614074cb1b02"},
+ {file = "yarl-1.5.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:b3b9ad80f8b68519cc3372a6ca85ae02cc5a8807723ac366b53c0f089db19e4a"},
+ {file = "yarl-1.5.1-cp38-cp38-win32.whl", hash = "sha256:f379b7f83f23fe12823085cd6b906edc49df969eb99757f58ff382349a3303c6"},
+ {file = "yarl-1.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:9102b59e8337f9874638fcfc9ac3734a0cfadb100e47d55c20d0dc6087fb4692"},
+ {file = "yarl-1.5.1.tar.gz", hash = "sha256:c22c75b5f394f3d47105045ea551e08a3e804dc7e01b37800ca35b58f856c3d6"},
+]
+zeep = [
+ {file = "zeep-3.4.0-py2.py3-none-any.whl", hash = "sha256:59a4068ab3817b589ee21c6c34166c35baa8f2be7ad69f045d005076a29911c1"},
+ {file = "zeep-3.4.0.tar.gz", hash = "sha256:0e98669cfeb60756231ae185498f9ae21b30b2681786b8de58ed34c3b93e41dd"},
+]
+zipp = [
+ {file = "zipp-3.1.0-py3-none-any.whl", hash = "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b"},
+ {file = "zipp-3.1.0.tar.gz", hash = "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96"},
+]
+zxcvbn = [
+ {file = "zxcvbn-4.4.28.tar.gz", hash = "sha256:151bd816817e645e9064c354b13544f85137ea3320ca3be1fb6873ea75ef7dc1"},
+]
diff --git a/poetry.toml b/poetry.toml
new file mode 100644
index 0000000..95b0ffd
--- /dev/null
+++ b/poetry.toml
@@ -0,0 +1,5 @@
+cache-dir = "./"
+[virtualenvs]
+create = false
+in-project = false
+path = "{cache-dir}.venv"
\ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..eccf153
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,143 @@
+[build-system]
+requires = [ "poetry>=1.0.0",]
+build-backend = "poetry.masonry.api"
+
+[tool.poetry]
+name = "ERPLibre"
+version = "1.1.0"
+description = "Easy way to configure Odoo community"
+license = "AGPL-3.0-or-later"
+authors = [ "Mathieu Benoit ", "Alexandre Ferreira Benevides ",]
+
+[tool.poetry.dependencies]
+python = "^3.7"
+Asterisk = "^0.0.8"
+Babel = "2.3.4"
+GitPython = "^3.1.7"
+Jinja2 = "2.10.1"
+Mako = "1.0.4"
+MarkupSafe = "0.23"
+Pillow = "6.1.0"
+PyJWT = "1.7.1"
+PyPDF2 = "1.26.0"
+PyYAML = "4.2b4"
+SOAPpy = "^0.12.22"
+Voicent-Python = "^1.0"
+Werkzeug = "0.11.15"
+XlsxWriter = "0.9.3"
+agithub = "^2.2.2"
+altair = "^4.1.0"
+bokeh = "1.1.0"
+boto = "^2.49.0"
+boto3 = "1.9.102"
+cerberus = "^1.3.2"
+chardet = "3.0.4"
+cryptography = "2.6.1"
+cython = "^0.29.21"
+ddt = "1.2.0"
+decorator = "4.0.10"
+docutils = "0.12"
+ebaysdk = "2.1.5"
+email_validator = "^1.1.1"
+extract-msg = "^0.25.3"
+extract_msg = "^0.25.3"
+factur-x = "^1.12"
+feedparser = "5.2.1"
+freezegun = "0.3.11"
+geojson = "2.4.1"
+gevent = "1.3.4"
+gitpython = "^3.1.7"
+giturlparse = "^0.9.2"
+greenlet = "0.4.13"
+html2text = "2016.9.19"
+invoice2data = "^0.3.5"
+iscompatible = "^0.1.1"
+jira = "2.0.0"
+keystoneauth1 = "3.14.0"
+lasso = "^0.0.5"
+libsass = "0.12.3"
+lxml = "4.2.3"
+matplotlib = ">=2.0.0"
+mock = "2.0.0"
+mpld3 = "0.3"
+mysqlclient = "^2.0.1"
+num2words = "0.5.6"
+numpy = "^1.19.1"
+oauthlib = "2.1.0"
+"oca.decorators" = "^0.0.1"
+ofxparse = "0.16"
+openpyxl = "^3.0.4"
+openupgradelib = "^2.0.0"
+pandas = "^1.1.0"
+paramiko = "^2.7.1"
+passlib = "1.6.5"
+pdf2image = "^1.13.1"
+phonenumbers = "^8.12.7"
+plotly = "4.1.0"
+premailer = "^3.7.0"
+psutil = "4.3.1"
+psycopg2 = "2.7.3.1"
+py-Asterisk = "^0.5.18"
+"py3o.formats" = "^0.3"
+"py3o.template" = "^0.10.0"
+pycountry = "^20.7.3"
+pydot = "1.2.3"
+pygount = "<1.2.0"
+pyldap = "2.4.28"
+pymssql = "^2.1.4"
+pyotp = "^2.4.0"
+pyparsing = "2.1.10"
+pyrfc = "^0.1.2"
+pyserial = "3.1.1"
+pysftp = "^0.2.9"
+python-chess = "<0.24"
+python-csv = "^0.0.13"
+python-dateutil = "2.7.3"
+python-git = "^2018.2.1"
+python-json-logger = "0.1.5"
+python-keystoneclient = "3.22.0"
+python-slugify = ">=3.0.2"
+python-stdnum = "^1.13"
+python-swiftclient = "3.9.0"
+python-u2flib-server = "^5.0.0"
+python-u2flib_server = "^5.0.0"
+pytz = "2017.2"
+pyusb = "1.0.0"
+pyzbar = "^0.1.8"
+qrcode = "5.3"
+raven = "^6.10.0"
+redis = "2.10.5"
+reportlab = "3.3.0"
+requests = "2.20.0"
+requests-mock = "^1.8.0"
+requests-oauthlib = "1.1.0"
+requests-toolbelt = "0.9.1"
+retrying = "^1.3.3"
+rotate_backups_s3 = "^0.3"
+serial = "^0.0.97"
+shapely = "1.6.4.post2"
+simplejson = "^3.17.2"
+slugify = "^0.0.1"
+sphinx = ">=1.6.7"
+sphinx-patchqueue = ">=1.0"
+sqlalchemy = "^1.3.18"
+statsd = "3.2.1"
+suds-jurko = "0.6"
+toml = "^0.10.1"
+unidecode = "1.0.22"
+vatnumber = "1.2"
+vcrpy = ">=2.1.1"
+vcrpy-unittest = "^0.1.7"
+vobject = "0.9.3"
+voicent-python = "^1.0"
+webcolors = "1.10"
+websocket-client = "^0.57.0"
+wheel = "^0.34.2"
+xlrd = "1.0.0"
+xlwt = "1.3"
+xmltodict = "^0.12.0"
+zeep = "^3.4.0"
+zxcvbn = "^4.4.28"
+
+[tool.poetry.dev-dependencies]
+websocket_client = "^0.57.0"
diff --git a/requirements.txt b/requirements.txt
index 124164f..2eb05de 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,6 +1,34 @@
+# For script
giturlparse
agithub
gitpython
PyYAML
retrying
-xmltodict
\ No newline at end of file
+xmltodict
+openupgradelib
+
+# For OSX
+cython
+
+# For Odoo
+wheel
+phonenumbers
+
+# For OCA
+factur-x
+
+# For testing
+websocket-client
+python-stdnum
+python-u2flib_server
+python-dateutil
+python-csv
+python-chess
+python-git
+voicent-python
+python-swiftclient
+python-keystoneclient
+
+# For updating poetry
+toml
+iscompatible
diff --git a/run.sh b/run.sh
index a4600ea..962ef3e 100755
--- a/run.sh
+++ b/run.sh
@@ -1,3 +1,3 @@
#!/usr/bin/env bash
-source ./venv/bin/activate
+source ./.venv/bin/activate
python3 ./odoo/odoo-bin -c ./config.conf --limit-time-real 99999 --limit-time-cpu 99999 $@
diff --git a/script/delete_production.sh b/script/delete_production.sh
new file mode 100755
index 0000000..0f305b3
--- /dev/null
+++ b/script/delete_production.sh
@@ -0,0 +1,28 @@
+#!/usr/bin/env bash
+
+. ./env_var.sh
+
+echo -e "\n==== Delete user ===="
+
+echo -n "Are You Sure to delete user ${EL_HOME}? [Y/n]"
+old_stty_cfg=$(stty -g)
+stty raw -echo
+answer=$( while ! head -c 1 | grep -i '[ny]' ;do true ;done )
+stty $old_stty_cfg
+if echo "$answer" | grep -iq "^y" ;then
+ echo "Remove all system of ${EL_HOME}"
+else
+ echo "Cancel..."
+ exit 1
+fi
+
+sudo systemctl stop ${EL_CONFIG}.service
+# Disable daemon
+sudo systemctl disable ${EL_CONFIG}.service
+sudo rm -f /etc/systemd/system/${EL_CONFIG}.service
+
+# Disable nginx
+sudo rm -rf ${EL_HOME}
+sudo rm -f /etc/nginx/sites-available/${EL_WEBSITE_NAME}
+sudo rm -f /etc/nginx/sites-enabled/${EL_WEBSITE_NAME}
+sudo systemctl restart nginx
diff --git a/script/docker_build.sh b/script/docker_build.sh
new file mode 100755
index 0000000..3a99a79
--- /dev/null
+++ b/script/docker_build.sh
@@ -0,0 +1,23 @@
+#!/usr/bin/env bash
+. ./env_var.sh
+
+# Rewrite docker-compose
+./script/docker_update_version.py --version=${ERPLIBRE_VERSION} --base=${ERPLIBRE_DOCKER_BASE} --prod=${ERPLIBRE_DOCKER_PROD}
+
+cd docker
+
+ARGS=--build-arg=WORKING_BRANCH=$(git rev-parse --abbrev-ref HEAD)
+
+# Clear cache
+# ARGS="${ARGS} --no-cache"
+
+set -e
+
+# Build base
+docker build ${ARGS} -f Dockerfile.base -t ${ERPLIBRE_DOCKER_BASE_VERSION} .
+
+# Build prod
+docker build ${ARGS} -f Dockerfile.prod.pkg -t ${ERPLIBRE_DOCKER_PROD_VERSION} .
+
+cd -
+docker-compose up -d
diff --git a/script/docker_update_version.py b/script/docker_update_version.py
new file mode 100755
index 0000000..8d5838a
--- /dev/null
+++ b/script/docker_update_version.py
@@ -0,0 +1,108 @@
+#!./.venv/bin/python
+import os
+import sys
+import argparse
+import logging
+import yaml
+
+new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..'))
+sys.path.append(new_path)
+
+from script.git_tool import GitTool
+
+_logger = logging.getLogger(__name__)
+
+
+def get_config():
+ """Parse command line arguments, extracting the config file name,
+ returning the union of config file and command line arguments
+
+ :return: dict of config file settings and command line arguments
+ """
+ config = GitTool.get_project_config()
+
+ # TODO update description
+ parser = argparse.ArgumentParser(
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ description='''\
+ Update version of docker ready to commit.
+''',
+ epilog='''\
+'''
+ )
+ parser.add_argument('--version', required=True, help="Version of ERPLibre.")
+ parser.add_argument('--base', required=True, help="Docker base name.")
+ parser.add_argument('--prod', required=True, help="Docker prod name.")
+ parser.add_argument('--docker_compose_file', default="./docker-compose.yml", help="Docker compose file to update.")
+ parser.add_argument('--docker_prod', default="./docker/Dockerfile.prod.pkg", help="Docker prod file to update.")
+ args = parser.parse_args()
+ args.base_version = f"{args.base}:{args.version}"
+ args.prod_version = f"{args.prod}:{args.version}"
+ return args
+
+
+# def edit_yaml(config):
+# with open(config.docker_compose_file, 'r') as f:
+# docker_info = yaml.safe_load(f)
+# if not docker_info:
+# print(f"ERROR, file {config.docker_compose_file} is empty.")
+# sys.exit(1)
+#
+# dct_services = docker_info.get("services")
+# dct_erplibre = dct_services.get("ERPLibre") if dct_services else None
+# if dct_erplibre:
+# dct_erplibre["image"] = config.prod_version
+# with open(config.docker_compose_file, 'w') as f:
+# yaml.dump(docker_info, f)
+
+
+def edit_text(config):
+ with open(config.docker_compose_file, 'r') as f:
+ lst_docker_info = f.readlines()
+
+ if not lst_docker_info:
+ print(f"ERROR, file {config.docker_compose_file} is empty.")
+ sys.exit(1)
+
+ is_find = False
+ i = 0
+ for docker_info in lst_docker_info:
+ if is_find:
+ key = "image:"
+ value = lst_docker_info[i]
+ lst_docker_info[i] = f"{value[:value.find(key) + len(key)]} {config.prod_version}\n"
+ break
+ if "ERPLibre" in docker_info:
+ is_find = True
+ i += 1
+
+ with open(config.docker_compose_file, 'w') as f:
+ f.writelines(lst_docker_info)
+
+
+def edit_docker_prod(config):
+ with open(config.docker_prod, 'r') as f:
+ lst_docker_info = f.readlines()
+
+ if not lst_docker_info:
+ print(f"ERROR, file {config.docker_compose_file} is empty.")
+ sys.exit(1)
+
+ i = 0
+ for docker_info in lst_docker_info:
+ if "FROM " in docker_info:
+ lst_docker_info[i] = f"FROM {config.base_version}\n"
+ i += 1
+
+ with open(config.docker_prod, 'w') as f:
+ f.writelines(lst_docker_info)
+
+
+def main():
+ config = get_config()
+ edit_text(config)
+ edit_docker_prod(config)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/script/fork_project.py b/script/fork_project.py
index b761d83..3837d58 100644
--- a/script/fork_project.py
+++ b/script/fork_project.py
@@ -1,4 +1,4 @@
-#!./venv/bin/python
+#!./.venv/bin/python
import os
import sys
import argparse
diff --git a/script/fork_project_ERPLibre.py b/script/fork_project_ERPLibre.py
index 3a292cc..6b41317 100644
--- a/script/fork_project_ERPLibre.py
+++ b/script/fork_project_ERPLibre.py
@@ -1,4 +1,4 @@
-#!./venv/bin/python
+#!./.venv/bin/python
import os
import sys
import argparse
diff --git a/script/git_change_remote.py b/script/git_change_remote.py
index 9dbf4f0..c66bb2e 100755
--- a/script/git_change_remote.py
+++ b/script/git_change_remote.py
@@ -1,4 +1,4 @@
-#!./venv/bin/python
+#!./.venv/bin/python
import os
import sys
import argparse
diff --git a/script/git_change_remote_https_to_git.py b/script/git_change_remote_https_to_git.py
index 134177b..a77b50a 100755
--- a/script/git_change_remote_https_to_git.py
+++ b/script/git_change_remote_https_to_git.py
@@ -1,4 +1,4 @@
-#!./venv/bin/python
+#!./.venv/bin/python
# © 2020 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
diff --git a/script/git_diff_repo_manifest.py b/script/git_diff_repo_manifest.py
index b969bd4..9e92e1d 100755
--- a/script/git_diff_repo_manifest.py
+++ b/script/git_diff_repo_manifest.py
@@ -1,4 +1,4 @@
-#!./venv/bin/python
+#!./.venv/bin/python
import os
import sys
import argparse
diff --git a/script/git_merge_repo_manifest.py b/script/git_merge_repo_manifest.py
index 877b836..7530044 100755
--- a/script/git_merge_repo_manifest.py
+++ b/script/git_merge_repo_manifest.py
@@ -1,4 +1,4 @@
-#!./venv/bin/python
+#!./.venv/bin/python
import os
import sys
import argparse
diff --git a/script/git_repo_manifest.py b/script/git_repo_manifest.py
index 9076d64..cf6b390 100755
--- a/script/git_repo_manifest.py
+++ b/script/git_repo_manifest.py
@@ -1,4 +1,4 @@
-#!./venv/bin/python
+#!./.venv/bin/python
import os
import sys
import argparse
@@ -30,6 +30,8 @@ def get_config():
help="Path of repo to change remote, including submodule.")
parser.add_argument('--clear', action="store_true",
help="Create a new manifest and clear old configuration.")
+ parser.add_argument('-m', '--manifest', default="manifest/default.dev.xml",
+ help="The manifest file path to generate.")
args = parser.parse_args()
return args
@@ -53,8 +55,9 @@ def main():
dct_remote = {}
dct_project = {}
git_tool.generate_repo_manifest(lst_repo_organization,
- output=f"{config.dir}manifest/default.dev.xml",
- dct_remote=dct_remote, dct_project=dct_project)
+ output=f"{config.dir}{config.manifest}",
+ dct_remote=dct_remote, dct_project=dct_project,
+ keep_original=True)
git_tool.generate_install_locally()
diff --git a/script/git_show_code_diff_repo_manifest.py b/script/git_show_code_diff_repo_manifest.py
new file mode 100755
index 0000000..d8e4741
--- /dev/null
+++ b/script/git_show_code_diff_repo_manifest.py
@@ -0,0 +1,75 @@
+#!./.venv/bin/python
+import os
+import sys
+import argparse
+import logging
+from git import Repo
+from git.exc import GitCommandError
+
+new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..'))
+sys.path.append(new_path)
+
+from script.git_tool import GitTool
+
+_logger = logging.getLogger(__name__)
+
+
+def get_config():
+ """Parse command line arguments, extracting the config file name,
+ returning the union of config file and command line arguments
+
+ :return: dict of config file settings and command line arguments
+ """
+ # TODO update description
+ parser = argparse.ArgumentParser(
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ description="""Compare actual code with a manifest.""",
+ epilog='''\
+'''
+ )
+ parser.add_argument('-m', '--manifest', required=True,
+ help="The manifest to compare with actual code.")
+ args = parser.parse_args()
+ return args
+
+
+def main():
+ config = get_config()
+ git_tool = GitTool()
+
+ dct_remote, dct_project, default_remote = git_tool.get_manifest_xml_info(filename=config.manifest, add_root=True)
+ default_branch_name = default_remote.get("@revision", git_tool.default_branch)
+ i = 0
+ total = len(dct_project)
+ for name, project in dct_project.items():
+ i += 1
+ path = project.get("@path")
+ print(f"{i}/{total} - {path}")
+ branch_name = project.get("@revision", default_branch_name)
+ organization = project.get("@remote")
+ if not organization:
+ print(f"ERROR missing @remote on project {path}.")
+ continue
+
+ git_repo = Repo(path)
+ value = git_repo.git.branch("--show-current")
+ if not value:
+ # TODO maybe need to check divergence with local branch and not remote branch
+ commit_head = git_repo.git.rev_parse("HEAD")
+ try:
+ commit_branch = git_repo.git.rev_parse(f"{organization}/{branch_name}")
+ except GitCommandError:
+ print("ERROR Something wrong with this repo.")
+ continue
+ if commit_branch != commit_head:
+ print("WARNING Not on specified branch, got a divergence.")
+ else:
+ print("PASS Not on specified branch, no divergence.")
+ elif branch_name != value:
+ print(f"ERROR, manifest revision is {branch_name} and actual revision is {value}.")
+ else:
+ print("PASS")
+
+
+if __name__ == '__main__':
+ main()
diff --git a/script/git_tool.py b/script/git_tool.py
index f9e9e37..ba50331 100644
--- a/script/git_tool.py
+++ b/script/git_tool.py
@@ -1,4 +1,4 @@
-#!./venv/bin/python
+#!./.venv/bin/python
# © 2020 TechnoLibre (http://www.technolibre.ca)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import os
@@ -311,7 +311,7 @@ class GitTool:
xml_as_string = xml.read()
xml_dict = xmltodict.parse(xml_as_string, dict_constructor=dict)
dct_manifest = xml_dict.get("manifest")
- default_remote = dct_manifest.get("default").get("@remote")
+ default_remote = dct_manifest.get("default")
lst_remote = dct_manifest.get("remote")
lst_project = dct_manifest.get("project")
dct_remote = {a.get("@name"): a for a in lst_remote}
@@ -351,6 +351,7 @@ class GitTool:
webbrowser.open_new_tab(url)
def generate_install_locally(self, repo_path="./"):
+ filename_locally = f"{repo_path}script/install_locally.sh"
lst_repo = self.get_repo_info(repo_path=repo_path)
lst_result = []
for repo in lst_repo:
@@ -361,14 +362,15 @@ class GitTool:
str_repo = f' printf "${{EL_HOME}}/{repo.get("path")}," >> ' \
f'${{EL_CONFIG_FILE}}\n'
lst_result.append(str_repo)
- with open(f"{repo_path}script/install_locally.sh") as file:
+ with open(filename_locally) as file:
all_lines = file.readlines()
# search place to add/replace lines
index = 0
find_index = False
index_find = 0
for line in all_lines:
- if not find_index and "if [[ $EL_MINIMAL_ADDONS = \"False\" ]]; then\n" == line:
+ if not find_index and \
+ "if [[ ${EL_MINIMAL_ADDONS} = \"False\" ]]; then\n" == line:
index_find = index + 1
for insert_line in lst_result:
all_lines.insert(index_find, insert_line)
@@ -381,8 +383,12 @@ class GitTool:
break
index += 1
+ if not find_index:
+ print(f"ERROR cannot regenerate file {filename_locally}, "
+ f"did you change the header?")
+
# create file
- with open(f"{repo_path}script/install_locally.sh", mode="w") as file:
+ with open(filename_locally, mode="w") as file:
file.writelines(all_lines)
@staticmethod
@@ -390,14 +396,17 @@ class GitTool:
return source_str[:pos] + insert_str + source_str[pos:]
def generate_repo_manifest(self, lst_repo: List[Struct] = [], output: str = "",
- dct_remote={}, dct_project={}, default_remote=None):
+ dct_remote={}, dct_project={}, default_remote=None,
+ keep_original=False):
"""
Generate repo manifest
:param lst_repo: optional, update manifest with list_repo
:param output: filename to write output
:param dct_remote: dict of remote information
:param dct_project: dict of project information
- :param default_remote: name of default remote, optional
+ :param default_remote: dict of default remote
+ :param keep_original: if True, can manage multiple organization with same name,
+ but with different fetch url
:return:
"""
if not output:
@@ -449,10 +458,15 @@ class GitTool:
('@sync-c', "true"),
]))
else:
+ if keep_original and repo.project_name not in dct_project.keys():
+ # Exception, create a new remote to keep tracking on original
+ original_organization = f"{repo.original_organization}_origin"
+ else:
+ original_organization = repo.original_organization
# Add remote, only unique remote
- if repo.original_organization not in lst_remote_name:
+ if original_organization not in lst_remote_name:
lst_remote.append(OrderedDict(
- [('@name', repo.original_organization),
+ [('@name', original_organization),
('@fetch', repo.url_https_organization + "/")]
))
lst_remote_name.append(repo.original_organization)
@@ -462,7 +476,7 @@ class GitTool:
lst_project_info = [
('@name', repo.project_name),
('@path', repo.path),
- ('@remote', repo.original_organization),
+ ('@remote', original_organization),
]
if repo.revision:
lst_project_info.append(('@revision', repo.revision))
@@ -476,7 +490,7 @@ class GitTool:
if default_remote and not lst_default:
lst_default.append(OrderedDict([
- ('@remote', default_remote),
+ ('@remote', default_remote.get("@remote")),
('@revision', DEFAULT_BRANCH),
('@sync-j', "4"),
('@sync-c', "true"),
@@ -760,6 +774,30 @@ class GitTool:
upstream_remote.fetch)()
print('Remote "%s" fetched' % repo_info.organization)
+ def get_pull_request_repo(self, upstream_url: str, github_token: str,
+ organization_name: str = ""):
+ """
+
+ :param upstream_url:
+ :param github_token:
+ :param organization_name:
+ :return: List of url if success, else False
+ """
+ gh = GitHub(token=github_token)
+ parsed_url = parse(upstream_url)
+
+ # Fork the repo
+ status, user = gh.user.get()
+ user_name = user['login'] if not organization_name else organization_name
+ status, lst_pull = gh.repos[user_name][parsed_url.repo].pulls.get()
+ if type(lst_pull) is dict:
+ print(f"For url {upstream_url}, got {lst_pull.get('message')}")
+ return False
+ else:
+ for pull in lst_pull:
+ print(pull.get("html_url"))
+ return lst_pull
+
def fork_repo(self, upstream_url: str, github_token: str,
organization_name: str = ""):
# https://developer.github.com/apps/building-integrations/setting-up-and-registering-oauth-apps/about-scopes-for-oauth-apps/
diff --git a/script/git_update_repo.py b/script/git_update_repo.py
new file mode 100755
index 0000000..8ceb1cb
--- /dev/null
+++ b/script/git_update_repo.py
@@ -0,0 +1,113 @@
+#!./.venv/bin/python
+import os
+import sys
+import argparse
+import logging
+from git import Repo # pip install gitpython
+from retrying import retry # pip install retrying
+
+new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..'))
+sys.path.append(new_path)
+
+from script.git_tool import GitTool
+
+_logger = logging.getLogger(__name__)
+
+
+def get_config():
+ """Parse command line arguments, extracting the config file name,
+ returning the union of config file and command line arguments
+
+ :return: dict of config file settings and command line arguments
+ """
+ # TODO update description
+ parser = argparse.ArgumentParser(
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ description='''\
+''',
+ epilog='''\
+'''
+ )
+ parser.add_argument('-d', '--dir', dest="dir", default="./",
+ help="Path of repo to change remote, including submodule.")
+ args = parser.parse_args()
+ return args
+
+
+def main():
+ config = get_config()
+ git_tool = GitTool()
+
+ lst_repo = git_tool.get_source_repo_addons(repo_path=config.dir,
+ add_repo_root=False)
+ lst_repo_organization = [git_tool.get_transformed_repo_info_from_url(
+ a.get("url"), repo_path=config.dir, get_obj=True,
+ is_submodule=a.get("is_submodule"), sub_path=a.get("sub_path"),
+ revision=a.get("revision"), clone_depth=a.get("clone_depth"))
+ for a in lst_repo]
+
+ i = 0
+ total = len(lst_repo)
+ for repo in lst_repo_organization:
+ i += 1
+ print(f"\nNb element {i}/{total} - {repo.path}")
+
+ # TODO validate with default to ignore duplicate url, if same remote repo
+ if not repo.is_submodule:
+ continue
+ upstream_name = f"ERPLibre_update_12/{git_tool.default_branch}"
+ remote_branch_name = f"{upstream_name}/{git_tool.default_branch}"
+ git_repo = Repo(repo.relative_path)
+ # 1. Add remote if not exist
+ try:
+ upstream_remote = git_repo.remote(upstream_name)
+ print(f'Remote "{upstream_name}" already exists in {repo.relative_path}')
+ except ValueError:
+ upstream_remote = retry(
+ wait_exponential_multiplier=1000,
+ stop_max_delay=15000
+ )(git_repo.create_remote)(upstream_name, repo.url_https)
+ print('Remote "%s" created for %s' % (upstream_name, repo.url_https))
+
+ # 2. Fetch the remote source
+ retry(wait_exponential_multiplier=1000, stop_max_delay=15000)(
+ upstream_remote.fetch)()
+ print('Remote "%s" fetched' % upstream_name)
+
+ # 3. Rebase actual branch with new branch
+ rev = repo.revision if repo.revision else git_tool.default_branch
+ try:
+ git_repo.git.checkout(rev)
+ except:
+ if repo.revision:
+ rev = f"{repo.original_organization}/{repo.revision}"
+ else:
+ rev = f"{repo.original_organization}/{git_tool.default_branch}"
+
+ git_repo.git.checkout("--track", rev)
+ actual_commit = git_repo.git.rev_parse("HEAD")
+ try:
+ git_repo.git.rebase(remote_branch_name)
+ except Exception as e:
+ print(e, file=sys.stderr)
+ new_commit = git_repo.git.rev_parse("HEAD")
+
+ if actual_commit == new_commit:
+ print("== No diff ==")
+ else:
+ print(f"== Old commit {actual_commit} - new commit {new_commit}")
+ # push
+ try:
+ retry(wait_exponential_multiplier=1000, stop_max_delay=15000)(
+ git_repo.git.push)(repo.organization, rev)
+ except:
+ print("Cannot push, maybe need to push force or resolv rebase conflict",
+ file=sys.stderr)
+ print(f"cd {repo.path}")
+ print(f"git diff ERPLibre/v#.#.#..HEAD")
+ print(f"git push --force {repo.organization} {rev}")
+ print(f"cd -")
+
+
+if __name__ == '__main__':
+ main()
diff --git a/script/install_OSX_dependancy.sh b/script/install_OSX_dependency.sh
similarity index 69%
rename from script/install_OSX_dependancy.sh
rename to script/install_OSX_dependency.sh
index 4ec32c3..35bdbac 100755
--- a/script/install_OSX_dependancy.sh
+++ b/script/install_OSX_dependency.sh
@@ -7,7 +7,7 @@
#-------------------------------------------------------------------------------
################################################################################
-EL_USER=$(whoami)
+EL_USER=${USER}
#--------------------------------------------------
# Install PostgreSQL Server
@@ -22,12 +22,26 @@ sudo su - postgres -c "createuser -s ${EL_USER}" 2> /dev/null || true
# Install Dependencies
#--------------------------------------------------
echo "\n--- Installing Python 3 + pip3 --"
-brew install git python3 wget
+brew install git python3 wget pyenv
brew link git
brew link wget
+echo "\n--- Installing docker --"
+brew install minikube docker docker-compose docker-machine
+brew cask install virtualbox
+docker-machine create --driver virtualbox default
+docker-machine env default
+eval "$(docker-machine env default)"
echo "\n---- Installing nodeJS NPM and rtlcss for LTR support ----"
-brew install nodejs npm
+brew install nodejs npm openssl
sudo npm install -g rtlcss
+sudo npm install -g lessc
+yes n|pyenv install 3.7.7
+pyenv local 3.7.7
+
+echo 'export PATH="/usr/local/opt/openssl@1.1/bin:$PATH"' >> ~/.zshrc
+
+echo -e "\n---- Installing poetry for reliable python package ----"
+curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python
#--------------------------------------------------
# Install Wkhtmltopdf if needed
@@ -38,15 +52,3 @@ if [ ! -f "wkhtmltox-0.12.5-1.macos-carbon.pkg" ]; then
sudo sudo installer -pkg wkhtmltox-0.12.5-1.macos-carbon.pkg -target /
else echo "Wkhtmltopdf already installed"
fi
-
-# ===============================================================================================
-# !!!! FOR OSX there is a problem with python 3.7.5 with PILLOW, use 3.6.9 instead and works fine
-# install python 3.6.9
-# brew install pyenv
-# pyenv install 3.6.9
-# then redoo link:
-# unlink /usr/local/bin/python3
-# ln -s ~/.pyenv/versions/3.6.9/bin/python3.6 /usr/local/bin/python3
-# ===============================================================================================
-echo "\n---- Installing venv if not already existing (rm -r venv if already exists) ----"
-~/.pyenv/versions/3.6.9/bin/python3.6 -m venv venv
diff --git a/script/install_daemon.sh b/script/install_daemon.sh
index 2311c04..1255400 100755
--- a/script/install_daemon.sh
+++ b/script/install_daemon.sh
@@ -30,8 +30,8 @@ User=${EL_USER}
Group=${EL_USER}
Restart=always
RestartSec=5
-PIDFile=${EL_HOME_ERPLIBRE}/venv/service.pid
-ExecStart=${EL_HOME_ERPLIBRE}/venv/run.sh
+PIDFile=${EL_HOME_ERPLIBRE}/.venv/service.pid
+ExecStart=${EL_HOME_ERPLIBRE}/.venv/run.sh
StandardOutput=journal+console
[Install]
@@ -51,14 +51,14 @@ sudo su ${EL_USER} -c "sudo rm -f /tmp/${EL_USER}run.sh"
cat < /tmp/${EL_USER}run.sh
#!/usr/bin/env bash
cd ${EL_HOME_ERPLIBRE}
-source ./venv/bin/activate
+source ./.venv/bin/activate
python3 ${EL_HOME_ERPLIBRE}/odoo/odoo-bin -c ${EL_HOME_ERPLIBRE}/config.conf --limit-time-real 99999 --limit-time-cpu 99999 $@
EOF
echo -e "* Security Run File"
-sudo cp /tmp/${EL_USER}run.sh ${EL_HOME_ERPLIBRE}/venv/run.sh
-sudo chmod 755 ${EL_HOME_ERPLIBRE}/venv/run.sh
-sudo chown ${EL_USER}: ${EL_HOME_ERPLIBRE}/venv/run.sh
+sudo cp /tmp/${EL_USER}run.sh ${EL_HOME_ERPLIBRE}/.venv/run.sh
+sudo chmod 755 ${EL_HOME_ERPLIBRE}/.venv/run.sh
+sudo chown ${EL_USER}: ${EL_HOME_ERPLIBRE}/.venv/run.sh
echo "-----------------------------------------------------------"
echo "Done! The ERPLibre server is up and running. Specifications:"
diff --git a/script/install_debian_dependancy.sh b/script/install_debian_dependency.sh
similarity index 78%
rename from script/install_debian_dependancy.sh
rename to script/install_debian_dependency.sh
index 41b9b1f..20f0e60 100755
--- a/script/install_debian_dependancy.sh
+++ b/script/install_debian_dependency.sh
@@ -2,7 +2,7 @@
. ./env_var.sh
-EL_USER=$(whoami)
+EL_USER=${USER}
#EL_INSTALL_WKHTMLTOPDF="True"
##
@@ -31,42 +31,47 @@ sudo apt-get upgrade -y
# Install PostgreSQL Server
#--------------------------------------------------
echo -e "\n---- Install PostgreSQL Server ----"
-sudo apt-get install postgresql -y
+sudo apt-get install postgresql libpq-dev -y
echo -e "\n---- Creating the ERPLibre PostgreSQL User ----"
-sudo su - postgres -c "createuser -s $EL_USER" 2> /dev/null || true
+sudo su - postgres -c "createuser -s ${EL_USER}" 2> /dev/null || true
#--------------------------------------------------
# Install Dependencies
#--------------------------------------------------
-echo -e "\n--- Installing Python 3 + pip3 --"
-sudo apt-get install git python3 python3-pip build-essential wget python3-dev python3-venv python3-wheel libxslt-dev libzip-dev libldap2-dev libsasl2-dev python3-setuptools node-less libpng12-0 gdebi-core -y
+echo -e "\n--- Installing debian dependency --"
+sudo apt-get install git build-essential wget libxslt-dev libzip-dev libldap2-dev libsasl2-dev node-less libpng12-0 gdebi-core libffi-dev libbz2-dev -y
+sudo apt-get install libmariadbd-dev -y
echo -e "\n---- Installing nodeJS NPM and rtlcss for LTR support ----"
sudo apt-get install nodejs npm -y
sudo npm install -g rtlcss
+sudo npm install -g lessc
if [ ${EL_INSTALL_NGINX} = "True" ]; then
- sudo apt install nginx -y
+ echo -e "\n---- Installing nginx ----"
+ sudo apt install nginx -y
fi
#--------------------------------------------------
# Install Wkhtmltopdf if needed
#--------------------------------------------------
if [ ${EL_INSTALL_WKHTMLTOPDF} = "True" ]; then
+ echo -e "\n---- Installing wkhtml ----"
INSTALLED=$(dpkg -s wkhtmltox|grep installed)
if [ "" == "${INSTALLED}" ]; then
echo -e "\n---- Install wkhtml and place shortcuts on correct place ----"
#pick up correct one from x64 & x32 versions:
if [ "`getconf LONG_BIT`" == "64" ];then
- _url=$WKHTMLTOX_X64
+ _url=${WKHTMLTOX_X64}
else
- _url=$WKHTMLTOX_X32
+ _url=${WKHTMLTOX_X32}
fi
sudo wget ${_url}
sudo gdebi --n `basename ${_url}`
sudo ln -s /usr/local/bin/wkhtmltopdf /usr/bin
sudo ln -s /usr/local/bin/wkhtmltoimage /usr/bin
+ else echo -e "\n---- Already installed wkhtml ----"
fi
else
echo "Wkhtmltopdf isn't installed due to the choice of the user!"
diff --git a/script/install_dev.sh b/script/install_dev.sh
index 3572c4f..6c011d7 100755
--- a/script/install_dev.sh
+++ b/script/install_dev.sh
@@ -8,11 +8,11 @@ if [[ "${OSTYPE}" == "linux-gnu" ]]; then
OS=$(lsb_release -si)
if [[ "${OS}" == "Ubuntu" ]]; then
echo "\n---- linux-gnu installation process started ----"
- ./script/install_debian_dependancy.sh
+ ./script/install_debian_dependency.sh
else
echo "Your Linux system is not supported."
fi
elif [[ "${OSTYPE}" == "darwin"* ]]; then
echo "\n---- Darwin installation process started ----"
- ./script/install_OSX_dependancy.sh
+ ./script/install_OSX_dependency.sh
fi
diff --git a/script/install_locally.sh b/script/install_locally.sh
index 9e36c74..ce374cd 100755
--- a/script/install_locally.sh
+++ b/script/install_locally.sh
@@ -2,7 +2,7 @@
. ./env_var.sh
-EL_USER=$(whoami)
+EL_USER=${USER}
EL_HOME=$PWD
EL_HOME_ODOO="${EL_HOME}/odoo"
#EL_INSTALL_WKHTMLTOPDF="True"
@@ -14,17 +14,6 @@ EL_CONFIG_FILE="${EL_HOME}/config.conf"
#EL_MINIMAL_ADDONS="False"
#EL_INSTALL_NGINX="True"
-if hash python3.7 2>/dev/null; then
- PYTHON37="True"
- PYTHON36="False"
-elif hash python3.6 2>/dev/null; then
- PYTHON37="False"
- PYTHON36="True"
-else
- echo "Missing python3.7 or python3.6. Python3.8 is not compatible."
- exit 1
-fi
-
echo -e "* Create server config file"
touch ${EL_CONFIG_FILE}
@@ -40,8 +29,10 @@ printf "longpolling_port = ${EL_LONGPOLLING_PORT}\n" >> ${EL_CONFIG_FILE}
printf "addons_path = ${EL_HOME_ODOO}/addons,${EL_HOME}/addons/addons," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_web," >> ${EL_CONFIG_FILE}
-if [[ $EL_MINIMAL_ADDONS = "False" ]]; then
+if [[ ${EL_MINIMAL_ADDONS} = "False" ]]; then
+ printf "${EL_HOME}/addons/CybroOdoo_OpenHRMS," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/ERPLibre_erplibre_addons," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/ERPLibre_erplibre_theme_addons," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/MathBenTech_development," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/MathBenTech_odoo-business-spending-management-quebec-canada," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/MathBenTech_scrummer," >> ${EL_CONFIG_FILE}
@@ -75,17 +66,28 @@ if [[ $EL_MINIMAL_ADDONS = "False" ]]; then
printf "${EL_HOME}/addons/OCA_business-requirement," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_commission," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_community-data-files," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/OCA_connector," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/OCA_connector-ecommerce," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/OCA_connector-interfaces," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/OCA_connector-jira," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_connector-telephony," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_contract," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_credit-control," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/OCA_crm," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_currency," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_data-protection," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/OCA_ddmrp," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/OCA_delivery-carrier," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_donation," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_e-commerce," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_edi," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_event," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/OCA_field-service," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/OCA_fleet," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/OCA_geospatial," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_helpdesk," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_hr," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/OCA_interface-github," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_knowledge," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_l10n-canada," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_maintenance," >> ${EL_CONFIG_FILE}
@@ -94,6 +96,7 @@ if [[ $EL_MINIMAL_ADDONS = "False" ]]; then
printf "${EL_HOME}/addons/OCA_margin-analysis," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_mis-builder," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_multi-company," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/OCA_operating-unit," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_partner-contact," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_pos," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_product-attribute," >> ${EL_CONFIG_FILE}
@@ -104,19 +107,34 @@ if [[ $EL_MINIMAL_ADDONS = "False" ]]; then
printf "${EL_HOME}/addons/OCA_purchase-workflow," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_queue," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_reporting-engine," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/OCA_rma," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/OCA_sale-reporting," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_sale-workflow," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_server-auth," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/OCA_server-backend," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_server-brand," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_server-env," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_server-tools," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_server-ux," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_social," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_stock-logistics-warehouse," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/OCA_storage," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_timesheet," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/OCA_vertical-association," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/OCA_vertical-hotel," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/OCA_vertical-isp," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/OCA_vertical-travel," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_website," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/OCA_website-cms," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/OCA_wms," >> ${EL_CONFIG_FILE}
- printf "${EL_HOME}/addons/SanteLibre_santelibre_addons," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/Smile-SA_odoo_addons," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/camptocamp_odoo-cloud-platform," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/dhongu_deltatech," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/it-projects-llc_odoo-saas-tools," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/itpp-labs_access-addons," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/itpp-labs_pos-addons," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/itpp-labs_website-addons," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/kinjal-sorathiya_Property-Management_odoo," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/muk-it_muk_base," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/muk-it_muk_dms," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/muk-it_muk_docs," >> ${EL_CONFIG_FILE}
@@ -124,15 +142,20 @@ if [[ $EL_MINIMAL_ADDONS = "False" ]]; then
printf "${EL_HOME}/addons/muk-it_muk_quality," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/muk-it_muk_web," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/muk-it_muk_website," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/obayit_odoo_dhtmlxgantt," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/odooaktiv_QuotationRevision," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/odooaktiv_product_rating_app," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/odoomates_odooapps," >> ${EL_CONFIG_FILE}
printf "${EL_HOME}/addons/openeducat_openeducat_erp," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/pledra_odoo-product-configurator," >> ${EL_CONFIG_FILE}
+ printf "${EL_HOME}/addons/tegin_medical-fhir," >> ${EL_CONFIG_FILE}
fi
printf "\n" >> ${EL_CONFIG_FILE}
printf "workers = 2\n" >> ${EL_CONFIG_FILE}
printf "max_cron_threads = 2\n" >> ${EL_CONFIG_FILE}
-if [ ${EL_INSTALL_NGINX} = "True" ]; then
+if [[ ${EL_INSTALL_NGINX} = "True" ]]; then
printf "xmlrpc_interface = 127.0.0.1\n" >> ${EL_CONFIG_FILE}
printf "netrpc_interface = 127.0.0.1\n" >> ${EL_CONFIG_FILE}
printf "proxy_mode = True\n" >> ${EL_CONFIG_FILE}
@@ -142,22 +165,69 @@ echo -e "\n---- Install Odoo with addons module ----"
git submodule update --init
# Generate empty addons if missing
-if [ ! -d "./addons/addons" ]; then
+if [[ ! -d "./addons/addons" ]]; then
mkdir -p ./addons/addons
fi
-echo -e "\n---- Create Virtual environment Python ----"
-cd ${EL_HOME}
-if [[ ${PYTHON37} = "True" ]]; then
- python3.7 -m venv venv
-elif [[ ${PYTHON36} = "True" ]]; then
- python3.6 -m venv venv
+PYENV_PATH=~/.pyenv
+PYENV_VERSION_PATH=${PYENV_PATH}/versions/3.7.7
+PYTHON_EXEC=${PYENV_VERSION_PATH}/bin/python
+POETRY_PATH=~/.poetry
+VENV_PATH=./.venv
+VENV_REPO_PATH=${VENV_PATH}/repo
+
+if [[ ! -d "${PYENV_PATH}" ]]; then
+ echo -e "\n---- Installing pyenv in ${PYENV_PATH} ----"
+ curl -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash
+fi
+
+echo -e "\n---- Export pyenv in ${PYENV_PATH} ----"
+export PATH="${PYENV_PATH}/bin:$PATH"
+eval "$(pyenv init -)"
+eval "$(pyenv virtualenv-init -)"
+
+if [[ ! -d "${PYENV_VERSION_PATH}" ]]; then
+ echo -e "\n---- Installing python 3.7.7 with pyenv in ${PYENV_VERSION_PATH} ----"
+ yes n|pyenv install 3.7.7
+fi
+
+pyenv local 3.7.7
+
+if [[ ! -d "${POETRY_PATH}" ]]; then
+ echo -e "\n---- Installing poetry for reliable python package ----"
+# curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | ${PYTHON_EXEC}
+ curl -fsS -o get-poetry.py https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py
+ python get-poetry.py -y --preview
+fi
+
+if [[ ! -d ${VENV_PATH} ]]; then
+ echo -e "\n---- Create Virtual environment Python ----"
+ if [[ -e ${PYTHON_EXEC} ]]; then
+ ${PYTHON_EXEC} -m venv .venv
+ else
+ echo "Missing pyenv, please refer installation guide."
+ exit 1
+ fi
fi
-cd -
# Install git-repo if missing
-if [ ! -f "./venv/repo" ]; then
- echo "Install git-repo from Google APIS"
- curl https://storage.googleapis.com/git-repo-downloads/repo > ./venv/repo
- chmod +x ./venv/repo
+if [[ ! -f ${VENV_REPO_PATH} ]]; then
+ echo "\n---- Install git-repo from Google APIS ----"
+ curl https://storage.googleapis.com/git-repo-downloads/repo > ${VENV_REPO_PATH}
+ chmod +x ${VENV_REPO_PATH}
+ sed -i 1d ${VENV_REPO_PATH}
+ PYTHON_HASHBANG="#!./.venv/bin/python"
+ sed -i "1 i ${PYTHON_HASHBANG}" ${VENV_REPO_PATH}
fi
+
+echo -e "\n---- Installing poetry dependency ----"
+${VENV_PATH}/bin/pip install --upgrade pip
+#/home/"${USER}"/.poetry/bin/poetry env use ${PYTHON_EXEC}
+source $HOME/.poetry/env
+poetry install
+# Delete artifacts created by pip, cause error in next "poetry install"
+rm -rf artifacts
+
+# Link for dev
+echo -e "\n---- Add link dependency in site-packages of Python ----"
+ln -fs ${EL_HOME_ODOO}/odoo ${EL_HOME}/.venv/lib/python3.7/site-packages/
diff --git a/script/install_locally_dev.sh b/script/install_locally_dev.sh
index af55c91..39afb4c 100755
--- a/script/install_locally_dev.sh
+++ b/script/install_locally_dev.sh
@@ -2,37 +2,7 @@
. ./env_var.sh
-EL_USER=$(whoami)
-EL_HOME=$PWD
-EL_HOME_ODOO="${EL_HOME}/odoo"
-#EL_INSTALL_WKHTMLTOPDF="True"
-#EL_PORT="8069"
-#EL_LONGPOLLING_PORT="8072"
-#EL_SUPERADMIN="admin"
-EL_CONFIG_FILE="${EL_HOME}/config.conf"
-#EL_CONFIG="${EL_USER}"
-#EL_MINIMAL_ADDONS="False"
-#EL_INSTALL_NGINX="True"
-#EL_MANIFEST_PROD="./manifest/default.xml"
-#EL_MANIFEST_DEV="./manifest/default.dev.xml"
-
./script/install_locally.sh
# Update git-repo
./script/update_manifest_local_dev.sh
-
-echo -e "\n---- Install python packages/requirements ----"
-${EL_HOME}/venv/bin/pip3 install --upgrade pip
-${EL_HOME}/venv/bin/pip3 install wheel phonenumbers
-${EL_HOME}/venv/bin/pip3 install -r "${EL_HOME}/odoo/requirements.txt"
-${EL_HOME}/venv/bin/pip3 install -r "${EL_HOME}/requirements.txt"
-
-# For dev/testing
-${EL_HOME}/venv/bin/pip3 install websocket-client
-
-echo -e "\n---- Add link dependency in site-packages of Python ----"
-if [[ ${PYTHON37} = "True" ]]; then
- ln -fs ${EL_HOME_ODOO}/odoo ${EL_HOME}/venv/lib/python3.7/site-packages/
-elif [[ ${PYTHON36} = "True" ]]; then
- ln -fs ${EL_HOME_ODOO}/odoo ${EL_HOME}/venv/lib/python3.6/site-packages/
-fi
diff --git a/script/install_locally_prod.sh b/script/install_locally_prod.sh
index dd61b2e..f6898d5 100755
--- a/script/install_locally_prod.sh
+++ b/script/install_locally_prod.sh
@@ -2,37 +2,7 @@
. ./env_var.sh
-EL_USER=$(whoami)
-EL_HOME=$PWD
-EL_HOME_ODOO="${EL_HOME}/odoo"
-#EL_INSTALL_WKHTMLTOPDF="True"
-#EL_PORT="8069"
-#EL_LONGPOLLING_PORT="8072"
-#EL_SUPERADMIN="admin"
-EL_CONFIG_FILE="${EL_HOME}/config.conf"
-#EL_CONFIG="${EL_USER}"
-#EL_MINIMAL_ADDONS="False"
-#EL_INSTALL_NGINX="True"
-#EL_MANIFEST_PROD="./manifest/default.xml"
-#EL_MANIFEST_DEV="./manifest/default.dev.xml"
-
./script/install_locally.sh
# Update git-repo
./script/update_manifest_prod.sh
-
-echo -e "\n---- Install python packages/requirements ----"
-${EL_HOME}/venv/bin/pip3 install --upgrade pip
-${EL_HOME}/venv/bin/pip3 install wheel phonenumbers
-${EL_HOME}/venv/bin/pip3 install -r "${EL_HOME}/odoo/requirements.txt"
-${EL_HOME}/venv/bin/pip3 install -r "${EL_HOME}/requirements.txt"
-
-# For dev/testing
-${EL_HOME}/venv/bin/pip3 install websocket-client
-
-echo -e "\n---- Add link dependency in site-packages of Python ----"
-if [[ ${PYTHON37} = "True" ]]; then
- ln -fs ${EL_HOME_ODOO}/odoo ${EL_HOME}/venv/lib/python3.7/site-packages/
-elif [[ ${PYTHON36} = "True" ]]; then
- ln -fs ${EL_HOME_ODOO}/odoo ${EL_HOME}/venv/lib/python3.6/site-packages/
-fi
diff --git a/script/install_production.sh b/script/install_production.sh
index 397fb0a..3fb6eab 100755
--- a/script/install_production.sh
+++ b/script/install_production.sh
@@ -2,7 +2,7 @@
. ./env_var.sh
-./script/install_debian_dependancy.sh
+./script/install_debian_dependency.sh
echo -e "\n---- Create ERPLIBRE system user ----"
sudo adduser --system --quiet --shell=/bin/bash --home=/${EL_USER} --gecos 'ERPLIBRE' --group ${EL_USER}
diff --git a/script/poetry_add_build_dependency.sh b/script/poetry_add_build_dependency.sh
new file mode 100755
index 0000000..ed6c928
--- /dev/null
+++ b/script/poetry_add_build_dependency.sh
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+source $HOME/.poetry/env
+poetry add -vv $(grep -v ";" ./.venv/build_dependency.txt | grep -v "*" )
+# poetry add -vv $(grep -v ";" ./.venv/build_dependency.txt | grep -v "*" | sed 's/==/@^/' )
+# poetry export -f ./.venv/build_dependency.txt --dev | poetry run -- pip install -r /dev/stdin
diff --git a/script/poetry_update.py b/script/poetry_update.py
new file mode 100755
index 0000000..ed661f4
--- /dev/null
+++ b/script/poetry_update.py
@@ -0,0 +1,297 @@
+#!./.venv/bin/python
+import os
+import sys
+import argparse
+import logging
+import toml
+import ast
+from collections import OrderedDict, defaultdict
+from pathlib import Path
+import iscompatible
+
+new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..'))
+sys.path.append(new_path)
+
+from script import git_tool
+
+_logger = logging.getLogger(__name__)
+
+
+def get_config():
+ """Parse command line arguments, extracting the config file name,
+ returning the union of config file and command line arguments
+
+ :return: dict of config file settings and command line arguments
+ """
+ config = git_tool.GitTool.get_project_config()
+
+ parser = argparse.ArgumentParser(
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ description='''\
+ Update pip dependency in Poetry, clear pyproject.toml, search all dependencies
+ from requirements.txt, search conflict version and generate a new list.
+ Launch Poetry installation.
+''',
+ epilog='''\
+'''
+ )
+ parser.add_argument('-d', '--dir', dest="dir", default="./",
+ help="Path of repo to change remote, including submodule.")
+ parser.add_argument('-f', '--force', action="store_true",
+ help="Force create new list of dependency, ignore poetry.lock.")
+ parser.add_argument('-v', '--verbose', action="store_true",
+ help="More information in execution, show stats.")
+ args = parser.parse_args()
+ return args
+
+
+def get_lst_requirements_txt():
+ return list(Path(".").rglob("requirements.[tT][xX][tT]"))
+
+
+def get_lst_manifest_py():
+ return list(Path(".").rglob("__manifest__.py"))
+
+
+def combine_requirements(config):
+ """
+ Search all module and version in all requirements.txt file in this project.
+ For each version, check compatibility and show warning with provenance file
+ Generate requirements.txt to "./.venv/build_dependency.txt"
+ :param config:
+ :return:
+ """
+ priority_filename_requirement = "odoo/requirements.txt"
+ lst_sign = ("==", "!=", ">=", "<=", "<", ">", ";")
+ lst_requirements = []
+ ignore_requirements = ["sys_platform == 'win32'", "python_version < '3.7'"]
+ dct_requirements = defaultdict(set)
+ lst_requirements_file = get_lst_requirements_txt()
+ lst_requirements_with_condition = set()
+ dct_special_condition = defaultdict(list)
+ dct_requirements_module_filename = defaultdict(list)
+ for requirements_filename in lst_requirements_file:
+ with open(requirements_filename, 'r') as f:
+ for a in f.readlines():
+ b = a.strip()
+ if not b or b[0] == "#":
+ continue
+
+ # Regroup requirement
+ for sign in lst_sign:
+ if sign in b:
+ # Exception, some time the sign ; can be first, just check
+ if sign != ";" and ";" in b and b.find(sign) > b.find(";"):
+ module_name = b[:b.find(";")]
+ else:
+ module_name = b[:b.find(sign)]
+ module_name = module_name.strip()
+ # Special condition for ";", ignore it
+ if ";" in b:
+ for ignore_string in ignore_requirements:
+ if ignore_string in b:
+ break
+ if ignore_string in b:
+ break
+ lst_requirements_with_condition.add(module_name)
+ value = b[:b.find(";")].strip()
+ dct_special_condition[module_name].append(b)
+ else:
+ value = b
+ dct_requirements[module_name].add(value)
+ filename = str(requirements_filename)
+ dct_requirements_module_filename[value].append(filename)
+ break
+ else:
+ dct_requirements[b].add(b)
+ filename = str(requirements_filename)
+ dct_requirements_module_filename[b].append(filename)
+ lst_requirements.append(b)
+
+ dct_requirements = get_manifest_external_dependencies(dct_requirements)
+
+ dct_requirements_diff_version = {k: v for k, v in dct_requirements.items() if
+ len(v) > 1}
+ # dct_requirements_same_version = {k: v for k, v in dct_requirements.items() if
+ # len(v) == 1}
+ if config.verbose:
+ # TODO show total repo to compare lst requirements
+ print(f"Total requirements.txt {len(lst_requirements_file)}, "
+ f"total module {len(lst_requirements)}, "
+ f"unique module {len(dct_requirements)}, "
+ f"module with different version {len(dct_requirements_diff_version)}.")
+
+ if dct_requirements_diff_version:
+ # Validate compatibility
+ for key, lst_requirement in dct_requirements_diff_version.items():
+ result = None
+
+ lst_version_requirement = []
+ for requirement in lst_requirement:
+ if ".*" in requirement:
+ requirement = requirement.replace(".*", "")
+ result_number = iscompatible.parse_requirements(requirement)
+ if not result_number:
+ # Ignore empty version
+ continue
+ # Exception of missing feature in iscompatible
+ # TODO support me in iscompatible lib
+ no_version = result_number[0][1]
+ if "b" in no_version:
+ result_number[0] = result_number[0][0], no_version[
+ :no_version.find("b")]
+ elif not no_version[no_version.rfind(".") + 1:].isnumeric():
+ result_number[0] = result_number[0][0], no_version[
+ :no_version.rfind(".")]
+ result_number = iscompatible.string_to_tuple(result_number[0][1])
+ lst_version_requirement.append((requirement, result_number))
+ # Check compatibility with all possibility
+ is_compatible = True
+ if len(lst_version_requirement) > 1:
+ highest_value = sorted(lst_version_requirement, key=lambda tup: tup[1])[-1]
+ for version_requirement in lst_version_requirement:
+ is_compatible &= iscompatible.iscompatible(version_requirement[0],
+ highest_value[1])
+ if is_compatible:
+ result = highest_value[0]
+ else:
+ # Find the requirements file and print the conflict
+ # Take the version from Odoo by default, else take the more recent
+ odoo_value = None
+ for version_requirement in lst_version_requirement:
+ filename_1 = dct_requirements_module_filename.get(
+ version_requirement[0])
+ if priority_filename_requirement in filename_1:
+ odoo_value = version_requirement[0]
+ break
+
+ if odoo_value:
+ str_result_choose = f"Select {odoo_value} because from Odoo"
+ result = odoo_value
+ else:
+ result = highest_value[0]
+ str_result_choose = f"Select highest value {result}"
+ str_versions = " VS ".join(
+ [f"{a[0]} from {dct_requirements_module_filename.get(a[0])}" for
+ a in lst_version_requirement])
+ print(f"WARNING - Not compatible {str_versions} - "
+ f"{str_result_choose}.")
+ elif len(lst_version_requirement) == 1:
+ result = lst_version_requirement[0][0]
+ else:
+ result = key
+
+ if result:
+ dct_requirements[key] = set((result,))
+ else:
+ print(f"Internal error, missing result for {lst_requirement}.")
+
+ # Support ignored requirements
+ lst_ignore = get_list_ignored()
+ lst_ignored_key = []
+ for key in dct_requirements.keys():
+ for ignored in lst_ignore:
+ if ignored == key:
+ lst_ignored_key.append(key)
+ for key in lst_ignored_key:
+ del dct_requirements[key]
+
+ with open("./.venv/build_dependency.txt", 'w') as f:
+ f.writelines([f"{list(a)[0]}\n" for a in dct_requirements.values()])
+
+
+def sorted_dependency_poetry(pyproject_filename):
+ # Open pyproject.toml
+ with open(pyproject_filename, 'r') as f:
+ dct_pyproject = toml.load(f)
+
+ # Get dependencies and update list, sorted
+ # [tool.poetry.dependencies]
+ tool = dct_pyproject.get("tool")
+ if tool:
+ poetry = tool.get("poetry")
+ if poetry:
+ dependencies = poetry.get("dependencies")
+ python_dependency = ("python", dependencies.get("python", ''))
+ lst_dependency = [(k, v) for k, v in dependencies.items() if k != "python"]
+ lst_dependency = sorted(lst_dependency, key=lambda tup: tup[0])
+ poetry["dependencies"] = OrderedDict([python_dependency] + lst_dependency)
+
+ # Rewrite pyproject.toml
+ with open(pyproject_filename, 'w') as f:
+ toml.dump(dct_pyproject, f)
+
+
+def delete_dependency_poetry(pyproject_filename):
+ # Open pyproject.toml
+ with open(pyproject_filename, 'r') as f:
+ dct_pyproject = toml.load(f)
+
+ # Get dependencies and update list, sorted
+ # [tool.poetry.dependencies]
+ tool = dct_pyproject.get("tool")
+ if tool:
+ poetry = tool.get("poetry")
+ if poetry:
+ dependencies = poetry.get("dependencies")
+ python_dependency = ("python", dependencies.get("python", ''))
+ poetry["dependencies"] = OrderedDict([python_dependency])
+
+ # Rewrite pyproject.toml
+ with open(pyproject_filename, 'w') as f:
+ toml.dump(dct_pyproject, f)
+
+
+def get_manifest_external_dependencies(dct_requirements):
+ lst_manifest_file = get_lst_manifest_py()
+ lst_dct_ext_depend = []
+ for manifest_file in lst_manifest_file:
+ with open(manifest_file, 'r') as f:
+ contents = f.read()
+ try:
+ dct = ast.literal_eval(contents)
+ except:
+ _logger.error(f"File {manifest_file} contains error, skip.")
+ continue
+ ext_depend = dct.get("external_dependencies")
+ if not ext_depend:
+ continue
+ python = ext_depend.get("python")
+ if not python:
+ continue
+ for depend in python:
+ requirement = dct_requirements.get(depend)
+ if requirement:
+ requirement.add(depend)
+ else:
+ dct_requirements[depend] = set([depend])
+
+ return dct_requirements
+
+
+def call_poetry_add_build_dependency():
+ os.system("./script/poetry_add_build_dependency.sh")
+
+
+def get_list_ignored():
+ with open("./ignore_requirements.txt", 'r') as f:
+ lst_ignore_requirements = [a.strip() for a in f.readlines()]
+ return lst_ignore_requirements
+
+
+def main():
+ # repo = Repo(root_path)
+ # lst_repo = get_all_repo()
+ config = get_config()
+ pyproject_toml_filename = f'{config.dir}pyproject.toml'
+
+ delete_dependency_poetry(pyproject_toml_filename)
+ combine_requirements(config)
+ if config.force and os.path.isfile("./poetry.lock"):
+ os.remove("./poetry.lock")
+ call_poetry_add_build_dependency()
+ sorted_dependency_poetry(pyproject_toml_filename)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/script/pull_request_ERPLibre.py b/script/pull_request_ERPLibre.py
new file mode 100755
index 0000000..055e73b
--- /dev/null
+++ b/script/pull_request_ERPLibre.py
@@ -0,0 +1,82 @@
+#!./.venv/bin/python
+import os
+import sys
+import argparse
+import logging
+
+new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..'))
+sys.path.append(new_path)
+
+from script.git_tool import GitTool
+
+_logger = logging.getLogger(__name__)
+CST_EL_GITHUB_TOKEN = "EL_GITHUB_TOKEN"
+
+
+def get_config():
+ """Parse command line arguments, extracting the config file name,
+ returning the union of config file and command line arguments
+
+ :return: dict of config file settings and command line arguments
+ """
+ config = GitTool.get_project_config()
+
+ # TODO update description
+ parser = argparse.ArgumentParser(
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ description='''\
+''',
+ epilog='''\
+'''
+ )
+ parser.add_argument('-d', '--dir', dest="dir", default="./",
+ help="Path of repo to change remote, including submodule.")
+ parser.add_argument('--organization', dest="organization", default="ERPLibre",
+ help="Choose organization to fork and change all repo.")
+ parser.add_argument('--github_token', dest="github_token",
+ default=config.get(CST_EL_GITHUB_TOKEN),
+ help="GitHub token generated by user")
+ args = parser.parse_args()
+ return args
+
+
+def main():
+ config = get_config()
+ github_token = config.github_token
+ git_tool = GitTool()
+
+ if not github_token:
+ raise ValueError("Missing github_token")
+
+ organization_name = config.organization
+ lst_repo = git_tool.get_source_repo_addons(repo_path=config.dir, add_repo_root=True)
+ lst_repo_organization = [git_tool.get_transformed_repo_info_from_url(
+ a.get("url"), repo_path=config.dir, organization_force=organization_name,
+ is_submodule=a.get("is_submodule"), sub_path=a.get("sub_path"),
+ revision=a.get("revision"), clone_depth=a.get("clone_depth"))
+ for a in lst_repo]
+
+ url_not_found_count = 0
+ url_found_count = 0
+
+ i = 0
+ total = len(lst_repo_organization)
+ for repo in lst_repo_organization:
+ i += 1
+ print(f"Nb element {i}/{total} - {repo.project_name}")
+ url = repo.url
+
+ status = git_tool.get_pull_request_repo(upstream_url=url,
+ github_token=github_token,
+ organization_name=organization_name)
+ if status is False:
+ url_not_found_count += 1
+ else:
+ url_found_count += len(status)
+
+ print(f"Repository not found: {url_not_found_count}")
+ print(f"URL found: {url_found_count}")
+
+
+if __name__ == '__main__':
+ main()
diff --git a/script/repo_remove_auto_install.py b/script/repo_remove_auto_install.py
new file mode 100755
index 0000000..0c5ef88
--- /dev/null
+++ b/script/repo_remove_auto_install.py
@@ -0,0 +1,117 @@
+#!./.venv/bin/python
+import os
+import sys
+import argparse
+import logging
+from pathlib import Path
+from git import Repo # pip install gitpython
+from git.exc import GitCommandError
+
+new_path = os.path.normpath(os.path.join(os.path.dirname(__file__), '..'))
+sys.path.append(new_path)
+
+from script.git_tool import GitTool
+
+_logger = logging.getLogger(__name__)
+
+
+def get_config():
+ """Parse command line arguments, extracting the config file name,
+ returning the union of config file and command line arguments
+
+ :return: dict of config file settings and command line arguments
+ """
+ # TODO update description
+ parser = argparse.ArgumentParser(
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ description='''\
+''',
+ epilog='''\
+'''
+ )
+ parser.add_argument('-d', '--dir', dest="dir", default="./",
+ help="Path of repo to change remote, including submodule.")
+ args = parser.parse_args()
+ return args
+
+
+def main():
+ config = get_config()
+ git_tool = GitTool()
+
+ lst_repo = git_tool.get_source_repo_addons(repo_path=config.dir,
+ add_repo_root=False)
+ lst_repo_organization = [git_tool.get_transformed_repo_info_from_url(
+ a.get("url"), repo_path=config.dir, get_obj=True,
+ is_submodule=a.get("is_submodule"), sub_path=a.get("sub_path"),
+ revision=a.get("revision"), clone_depth=a.get("clone_depth"))
+ for a in lst_repo]
+
+ lst_ignore_repo = ["odoo"]
+
+ i = 0
+ total = len(lst_repo)
+ branch_name = "12.0_dev"
+ for repo in lst_repo_organization:
+ i += 1
+ print(f"\nNb element {i}/{total} - {repo.path}")
+ is_checkout_branch = False
+
+ if repo.repo_name in lst_ignore_repo:
+ print(f"Ignore {repo.repo_name}.")
+ continue
+
+ git_repo = Repo(repo.relative_path)
+ # Force checkout branch if exist
+ try:
+ git_repo.git.checkout(branch_name)
+ is_checkout_branch = True
+ except GitCommandError:
+ try:
+ git_repo.git.checkout("-t", f"{repo.organization}/{branch_name}")
+ is_checkout_branch = True
+ except GitCommandError:
+ pass
+
+ has_change = get_manifest_external_dependencies(repo)
+
+ if has_change:
+ if not is_checkout_branch:
+ git_repo.git.checkout("-b", branch_name)
+ # change branch, commit and push
+ git_repo.git.add(".")
+ git_repo.git.commit("-m", "Set all module auto_install at False")
+ git_repo.git.push("-u", repo.organization, branch_name)
+
+
+def get_lst_manifest_py(relative_path):
+ return list(Path(relative_path).rglob("__manifest__.py"))
+
+
+def get_manifest_external_dependencies(repo):
+ has_change = False
+ lst_manifest_file = get_lst_manifest_py(repo.relative_path)
+ for manifest_file in lst_manifest_file:
+ has_change_manifest = False
+ with open(manifest_file, 'r') as f:
+ lst_content = f.readlines()
+ i = 0
+ for content in lst_content:
+ if "auto_install" in content and "True" in content:
+ has_change_manifest = True
+ has_change = True
+ first_char_index = content.find("auto_install")
+ index = content.find("True", first_char_index)
+ lst_content[i] = content[:index] + "False" + content[index + 4:]
+ i += 1
+
+ if has_change_manifest:
+ print(f"Update file {manifest_file}")
+ with open(manifest_file, 'w') as f:
+ f.writelines(lst_content)
+
+ return has_change
+
+
+if __name__ == '__main__':
+ main()
diff --git a/script/update_manifest_dev.sh b/script/update_manifest_dev.sh
index 7af5f61..0ad02ac 100755
--- a/script/update_manifest_dev.sh
+++ b/script/update_manifest_dev.sh
@@ -6,6 +6,6 @@
#EL_MANIFEST_DEV="./manifest/default.dev.xml"
# Update git-repo
-./venv/repo init -u http://git.erplibre.ca/ERPLibre -b $(git rev-parse --abbrev-ref HEAD) -m ${EL_MANIFEST_DEV}
-#./venv/repo sync --force-sync
-./venv/repo sync --force-sync -v
+./.venv/repo init -u http://git.erplibre.ca/ERPLibre -b $(git rev-parse --abbrev-ref HEAD) -m ${EL_MANIFEST_DEV}
+#./.venv/repo sync --force-sync
+./.venv/repo sync --force-sync -v
diff --git a/script/update_manifest_local_dev.sh b/script/update_manifest_local_dev.sh
index 8e09e0a..f33661b 100755
--- a/script/update_manifest_local_dev.sh
+++ b/script/update_manifest_local_dev.sh
@@ -9,7 +9,7 @@
git daemon --base-path=. --export-all --reuseaddr --informative-errors --verbose &
DAEMON_PID=$!
-./venv/repo init -u git://127.0.0.1:9418/ -b $(git rev-parse --abbrev-ref HEAD) -m ${EL_MANIFEST_DEV}
-./venv/repo sync -v --force-sync -m ${EL_MANIFEST_DEV}
+./.venv/repo init -u git://127.0.0.1:9418/ -b $(git rev-parse --abbrev-ref HEAD) -m ${EL_MANIFEST_DEV}
+./.venv/repo sync -v --force-sync -m ${EL_MANIFEST_DEV}
kill ${DAEMON_PID}
diff --git a/script/update_manifest_local_experimental.sh b/script/update_manifest_local_experimental.sh
index c41027e..7a8c71a 100755
--- a/script/update_manifest_local_experimental.sh
+++ b/script/update_manifest_local_experimental.sh
@@ -10,7 +10,7 @@
git daemon --base-path=. --export-all --reuseaddr --informative-errors --verbose &
DAEMON_PID=$!
-./venv/repo init -u git://127.0.0.1:9418/ -b $(git rev-parse --abbrev-ref HEAD) -m ${EL_MANIFEST_EXP}
-./venv/repo sync -v --force-sync -m ${EL_MANIFEST_EXP}
+./.venv/repo init -u git://127.0.0.1:9418/ -b $(git rev-parse --abbrev-ref HEAD) -m ${EL_MANIFEST_EXP}
+./.venv/repo sync -v --force-sync -m ${EL_MANIFEST_EXP}
kill ${DAEMON_PID}
diff --git a/script/update_manifest_local_prod.sh b/script/update_manifest_local_prod.sh
index c8efb1b..4d26aa3 100755
--- a/script/update_manifest_local_prod.sh
+++ b/script/update_manifest_local_prod.sh
@@ -9,7 +9,7 @@
git daemon --base-path=. --export-all --reuseaddr --informative-errors --verbose &
DAEMON_PID=$!
-./venv/repo init -u git://127.0.0.1:9418/ -b $(git rev-parse --abbrev-ref HEAD) -m ${EL_MANIFEST_PROD}
-./venv/repo sync -v -m ${EL_MANIFEST_PROD}
+./.venv/repo init -u git://127.0.0.1:9418/ -b $(git rev-parse --abbrev-ref HEAD) -m ${EL_MANIFEST_PROD}
+./.venv/repo sync -v -m ${EL_MANIFEST_PROD}
kill ${DAEMON_PID}
diff --git a/script/update_manifest_prod.sh b/script/update_manifest_prod.sh
index b8d5b0c..70a701e 100755
--- a/script/update_manifest_prod.sh
+++ b/script/update_manifest_prod.sh
@@ -6,6 +6,6 @@
#EL_MANIFEST_DEV="./manifest/default.dev.xml"
# Update git-repo
-./venv/repo init -u http://git.erplibre.ca/ERPLibre -b $(git rev-parse --abbrev-ref HEAD)
-#./venv/repo sync --force-sync
-./venv/repo sync -v
+./.venv/repo init -u http://git.erplibre.ca/ERPLibre -b $(git rev-parse --abbrev-ref HEAD)
+#./.venv/repo sync --force-sync
+./.venv/repo sync -v
diff --git a/source_repo_addons.csv b/source_repo_addons.csv
index a98b03d..d3beb1a 100644
--- a/source_repo_addons.csv
+++ b/source_repo_addons.csv
@@ -1,5 +1,6 @@
url,path,revision,clone-depth
https://github.com/ERPLibre/erplibre_addons.git,addons,,
+https://github.com/ERPLibre/erplibre_theme_addons.git,addons,,
https://github.com/MathBenTech/development.git,addons,,
https://github.com/MathBenTech/odoo-business-spending-management-quebec-canada.git,addons,12.0_sale_order_line_timesheet_attribution,
https://github.com/MathBenTech/scrummer.git,addons,,
@@ -14,7 +15,7 @@ https://github.com/Numigi/odoo-base-addons.git,addons,,
https://github.com/Numigi/odoo-entertainment-addons.git,addons,,
https://github.com/Numigi/odoo-git-addons.git,addons,,
https://github.com/Numigi/odoo-hr-addons.git,addons,,
-https://github.com/Numigi/odoo-partner-addons.git,addons,12.0_partner_no_vat_improve_no_vat,
+https://github.com/Numigi/odoo-partner-addons.git,addons,,
https://github.com/Numigi/odoo-product-addons.git,addons,,
https://github.com/Numigi/odoo-project-addons.git,addons,,
https://github.com/Numigi/odoo-purchase-addons.git,addons,,
@@ -81,8 +82,41 @@ https://github.com/OCA/timesheet.git,addons,12.0_support_project_agile_timesheet
https://github.com/OCA/web.git,addons,,
https://github.com/OCA/website.git,addons,12.0_dev,
https://github.com/OCA/wms.git,addons,,
-https://github.com/odoo/odoo.git,.,12.0_feature_5_star_CRM,1
+https://github.com/odoo/odoo.git,.,ERPLibre/12.0,10
https://github.com/odooaktiv/QuotationRevision.git,addons,,
https://github.com/openeducat/openeducat_erp.git,addons,,
-https://github.com/SanteLibre/santelibre_addons.git,addons,master,
https://github.com/Smile-SA/odoo_addons.git,addons,12.0_remote_autoinstall,
+https://github.com/odooaktiv/product_rating_app.git,addons,,
+https://github.com/pledra/odoo-product-configurator.git,addons,,
+https://github.com/OCA/vertical-association.git,addons,,
+https://github.com/OCA/delivery-carrier.git,addons,,
+https://github.com/OCA/geospatial.git,addons,,
+https://github.com/OCA/sale-reporting.git,addons,,
+https://github.com/OCA/server-backend.git,addons,,
+https://github.com/OCA/ddmrp.git,addons,,
+https://github.com/OCA/vertical-hotel.git,addons,,
+https://github.com/OCA/rma.git,addons,,
+https://github.com/OCA/storage.git,addons,,
+https://github.com/OCA/crm.git,addons,,
+https://github.com/OCA/operating-unit.git,addons,,
+https://github.com/OCA/connector-interfaces.git,addons,,
+https://github.com/OCA/vertical-isp,addons,,
+https://github.com/OCA/fleet.git,addons,,
+https://github.com/OCA/connector-jira.git,addons,,
+https://github.com/OCA/connector-ecommerce.git,addons,,
+https://github.com/OCA/vertical-travel.git,addons,,
+https://github.com/OCA/website-cms.git,addons,,
+https://github.com/OCA/field-service.git,addons,,
+https://github.com/OCA/interface-github.git,addons,,
+https://github.com/obayit/odoo_dhtmlxgantt.git,addons,,
+https://github.com/camptocamp/odoo-cloud-platform.git,addons,,
+https://github.com/CybroOdoo/OpenHRMS.git,addons,,
+https://github.com/dhongu/deltatech.git,addons,,
+https://github.com/kinjal-sorathiya/Property-Management_odoo.git,addons,master,
+https://github.com/tegin/medical-fhir.git,addons,,
+https://github.com/odoomates/odooapps.git,addons,,
+https://github.com/it-projects-llc/odoo-saas-tools.git,addons,,
+https://github.com/itpp-labs/website-addons.git,addons,,
+https://github.com/itpp-labs/access-addons.git,addons,,
+https://github.com/itpp-labs/pos-addons.git,addons,,
+https://github.com/OCA/connector.git,addons,,