GithubHelp home page GithubHelp logo

thoth-station / micropipenv Goto Github PK

View Code? Open in Web Editor NEW
233.0 7.0 25.0 702 KB

A lightweight wrapper for pip to support requirements.txt, Pipenv and Poetry lock files or converting them to pip-tools compatible output. Designed for containerized Python applications but not limited to them.

Home Page: https://pypi.org/project/micropipenv/

License: GNU Lesser General Public License v3.0

Python 99.31% Shell 0.69%
pipenv thoth python python3 dependency-management poetry pip-tools pip pip3 hacktoberfest

micropipenv's Introduction

µPipenv

GitHub tag (latest by date) https://travis-ci.com/thoth-station/micropipenv.svg?branch=master PyPI - Python Version PyPI - License PyPI - Downloads

A lightweight wrapper for pip to support requirements.txt, Pipenv and Poetry lock files or converting them to pip-tools compatible output. Designed for containerized Python applications but not limited to them.

For a brief video preview, check this demo (the micropipenv part starts at 9:00).

See also micropipenv: Installing Python dependencies in containerized applications for more info about this tool and a blog post published about it.

What's the difference in comparision to pip when using requirements.txt?

  • if requirements.txt state all the packages in a pinned version with hashes (e.g. pip-tools), micropipenv installs packages with a possible fallback if the installation order is relevant
    • you don't need to care about the installation and maintain correct order or requirements in requirements.txt
    • best effort installation - try until there is a possibility to succeed
  • if requirements.txt do not state all the packages in a pinned form
    • pip's resolver algorithm is used and it's left on pip to resolve requirements
    • the same behavior as micropipenv would not be used

What's the difference in comparision to Poetry?

  • a lightweight addition to Poetry, not a Poetry replacement
    • micropipenv does not substitute Poetry it rather complements it for containerized deployments where the size of the container image and software shipped with it matters
  • no release management to Python package indexes
  • micropipenv does not implement resolver, it uses already resolved stack that application is shipped with based on poetry.lock and pyproject.toml
  • no virtual environment management
    • virtual environment management is left on user, if needed

What's the difference in comparision to Pipenv?

  • a lightweight addition to Pipenv, not a Pipenv replacement
    • micropipenv does not substitute Pipenv it rather complements it for containerized deployments where the size of the container image and software shipped with it matters
  • it does not vendor all the dependencies as Pipenv
  • micropipenv does not implement resolver, it uses already resolved stack that application is shipped with Pipfile.lock
  • no virtual environment management
    • virtual environment management is left on user, if needed

micropipenv use cases

Why should I use micropipenv instead of Pipenv or Poetry?

  • I would like to have a tool that "rules them all" - one lightweight tool to support all Python dependency lock file managers (pip-tools, Poetry, Pipenv) and lets users decide what they want to use when deploying Python applications in containerized environments (e.g. Kubernetes, OpenShift, ...).
  • I would like to have a fast and minimalistic tool to install software packages in CI.
  • I would like to have containerized Python applications as small as possible with minimum software shipped and required to build and run the Python application in production.
  • I would like to convert files produced by Pipenv/Poetry to a pip-tools compatible output.
  • I don't want to install Pipenv/Poetry, but I would like to run a project that uses Pipenv/Poetry for dependency management (e.g. restricted environments).
  • My Pipenv installation is broken and Pipenv upstream did not issue any new Pipenv release.
  • I would like to deploy my application into a production environment and my application dependencies are managed by Pipenv/Poetry (dependencies are already resolved), but I don't want to run Pipenv/Poetry in production (e.g. OpenShift's s2i build process).

micropipenv install

The tool supports installing dependencies of the following formats:

  • Pipenv style lock format - files Pipfile and Pipfile.lock
  • Poetry style lock format - files pyproject.toml and poetry.lock
  • pip-tools style lock format - file requirements.txt
  • raw requirements.txt as used by pip (not a lock file)

In case of Pipenv, Poetry and pip-tools style format, the tool performs automatic recovery if the installation order of dependencies is relevant (one dependency fails to install as it depends on an another one).

To enforce the installation method used, specify --method option to the install subcommand. By default, micropipenv traverses the filesystem up from the current working directory and looks for the relevant files in the following order:

  1. Pipfile.lock and optionally Pipfile (if --deploy set)
  2. poetry.lock and pyproject.toml
  3. requirements.txt for pip-tools and raw pip requirements

To install dependencies issue the following command:

micropipenv install --dev  # --dev is optional

You can supply additional positional arguments that will be passed to pip. Use double dashes to distinguish pip options from micropipenv options.

# issue `pip install --user'
micropipenv install -- --user

Virtual environment management

micropipenv does not create any virtual environment as in the case of Pipenv/Poetry. It simply executes pip, and constructs arguments out of the lock file used. pip's default behaviour is to install its arguments into the same Python environment where pip is installed (i.e., the system Python environment).

To rather install its arguments into a virtual environment, run micropipenv from a shell where that virtual environment has been activated. This causes micropipenv to run the pip command already installed in the virtual environment:

python3 -m venv venv/ && (. venv/bin/activate && micropipenv install)

Alternatively, micropipenv can run the pip command from the system Python environment, which can in turn be told to install its arguments into an explicitly specified virtual environment by using the PIP_PYTHON environment variable.

This allows for the installation of dependencies into a minimal virtual environment that does not itself have pip and its dependencies installed into it:

python3 -m venv venv/ --without-pip && PIP_PYTHON=venv/bin/python micropipenv install

Using another package index

To set the default Python Package Index to something other than https://pypi.org/simple, set the MICROPIPENV_DEFAULT_INDEX_URLS to one or more comma-separated URLs.

Note: if the package manager file contains a package index URL, it will be used over this value.
export MICROPIPENV_DEFAULT_INDEX_URLS=https://pypi.example.com/simple,https://pypi.org/simple
micropipenv install

micropipenv install --deploy

If you wish to mimic pipenv --deploy functionality, you can do so:

micropipenv install --deploy

Note however, there is a need to parse Pipfile and verify its content corresponds to Pipefile.lock used (digest computed on Pipfile content). micropipenv requires toml extras for this functionality, so you will need to install micropipenv[toml] (see installation instructions bellow).

The --deploy option takes no effect for Poetry and requirements installation methods.

micropipenv install --dev

Installation of "development" dependencies can be acomplished using the --dev flag. This flag has no effect when requirements.txt file is used.

micropipenv requirements / micropipenv req

To generate output compatible with pip-tools, you can issue the following command:

micropipenv requirements

This applies to conversion from Poetry and Pipenv specific lock files.

Additional configuration options can limit what is present in the output (e.g. --no-dev to remove development dependencies).

A special option --only-direct makes micropipenv work on Pipfile instead of Pipfile.lock. This requires toml extras, so install micropipenv[toml] for this functionality (see installation instructions bellow). To get direct dependencies of an application and store them in requirements.txt file:

micropipenv requirements --only-direct > requirements.txt

For a setup that follows pip-tools convention with requirements.in and requirements.txt

micropipenv requirements --no-dev > requirements.txt
micropipenv requirements --no-dev --only-direct > requirements.in
micropipenv requirements --no-default > dev-requirements.txt
micropipenv requirements --no-default --only-direct > dev-requirements.in

See micropipenv requirements --help for more info.

micropipenv as a library

micropipenv exposes some core functionality on top of Pipfile/Pipfile.lock. You can import its functions and use micropipenv as a lightweight library for Pipfile/Pipfile.lock and pyproject.toml/poetry.lock manipulation.

Adjusting options using environment variables

All options can be triggered using environment variables - the name of an environment variable is always prefixed with MICROPIPENV_ and consists of the name of the option converted to uppercase, dashes are replaced with underscores (example --no-dev is mapped to MICROPIPENV_NO_DEV). All environment variables corresponding to flags are parsed as integers and subsequently casted to a boolean. For example, to turn --no-dev flag on, set MICROPIPENV_NO_DEV=1 (0 disables the flag). Parameters supplied to CLI take precedence over environment variables.

A special environment variable MICROPIPENV_PIP_BIN can point to an alternate pip binary.

To run this tool in a verbose mode, you can set the MICROPIPENV_DEBUG=1 (the same behavior can be achieved with multiple --verbose supplied).

The tool prints software stack information to the standard error output. This was designed for Thoth to capture information about installed dependencies as a useful source of information for Thoth's build analyzers. This behaviour can be suppressed by setting MICROPIPENV_NO_LOCKFILE_PRINT=1 environment variable.

Besides printing, the tool also writes the content of Pipfile.lock (if a locked software stack is used) to the directory where lock files are present (for Pipenv files, the Pipfile.lock is kept untouched). This behaviour can be suppressed by providing MICROPIPENV_NO_LOCKFILE_WRITE=1 environment variable.

Example usage

Install dependencies managed by Poetry as pip install --user would do (option --method is optional, auto-discovery is performed if omitted):

$ ls
poetry.lock pyproject.toml project.py
$ micropipenv install --method poetry -- --user

Install dependencies (both main and develop) managed by Poetry into a virtual environment:

$ ls
poetry.lock pyproject.toml project.py
$ python3 -m venv venv/
$ . venv/bin/activate
(venv) $ micropipenv install --dev

Install dependencies managed by Pipenv (both main and develop) into a virtual environment (option --method is optional, auto-discovery is performed if omitted):

$ ls
Pipfile Pipfile.lock src/
$ python3 -m venv venv/
$ . venv/bin/activate
(venv) $ micropipenv install --dev

Perform deployment of an application as Pipenv would do with Python interpreter version check and Pipfile file hash check (you can create virtual environment only if necessary):

$ ls
Pipfile Pipfile.lock src/
$ python3 -m venv venv/
$ . venv/bin/activate
(venv) $ micropipenv install --deploy

Generate pip-tools compliant requirements.in, dev-requirements.in, requirements.txt and dev-requirements.txt out of Pipfile and Pipfile.lock - project dependencies managed by Pipenv:

$ ls
Pipfile Pipfile.lock src/
$ micropipenv requirements --no-dev > requirements.txt
$ micropipenv requirements --no-dev --only-direct > requirements.in
$ micropipenv requirements --no-default > dev-requirements.txt
$ micropipenv requirements --no-default --only-direct > dev-requirements.in

Generate pip-tools complaint requirements.in, dev-requirements.in, requirements.txt and dev-requirements.txt out of pyproject.toml and poetry.lock - project dependencies managed by Poetry:

$ ls
poetry.lock pyproject.toml src/
$ micropipenv requirements --no-dev > requirements.txt
$ micropipenv requirements --no-dev --only-direct > requirements.in
$ micropipenv requirements --no-default > dev-requirements.txt
$ micropipenv requirements --no-default --only-direct > dev-requirements.in

For OpenShift's s2i integration, check this repo with a demo.

Installation

The project is hosted on PyPI so installing it using pip works as expected:

pip install micropipenv

The default installation does not bring any dependencies so its just micropipenv that gets installed. However, the default installation supports only Pipfile.lock management. If you would like to manipulate also with Pipfile or Poetry specific lock files, you will need to install micropipenv with TOML support (TOML is not in the standard Python library):

pip install micropipenv[toml]

Once the project gets installed, you can browse the help message by invoking the micropipenv CLI:

micropipenv --help

If you wish to install micropipenv on your Fedora system:

dnf install -y micropipenv

See available RPM packages.

No installation

You can run micropipenv without actually installing it - simply download the file and execute it. If you do not wish to save micropipenv.py file to disk, you can issue:

curl https://raw.githubusercontent.com/thoth-station/micropipenv/master/micropipenv.py | python3 - --help

Anything after python3 - will be passed as an argument to micropipenv.py so installing packages can be simply performed using:

curl https://raw.githubusercontent.com/thoth-station/micropipenv/master/micropipenv.py | python3 - install -- --user

All arguments after -- will be passed to pip as options.

OpenShift s2i (Source-To-Image)

micropipenv is available in UBI, Fedora and RHEL based container images. To enable micropipenv and benefit from its features, you need to export ENABLE_MICROPIPENV=1 environment variable in more recent Python 3 container images. See sclorg/s2i-python-container repo for more information.

License and copying

This project is licensed under the terms of the GNU Lesser General Public License v3 or later. See LICENSE-LGPL and LICENSE-GPL files for the license terms.

Copyright (C) 2020-2022 Project Thoth; Red Hat Inc.

Original author:
Maintainers:

micropipenv's People

Contributors

abompard avatar bissenbay avatar cfelder avatar djcass44 avatar frenzymadness avatar fridex avatar goern avatar gregory-pereira avatar harshad16 avatar hroncok avatar jrottenberg avatar matt-carr avatar misoslav avatar sesheta avatar tumido avatar vannten avatar yrro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

micropipenv's Issues

Start maintaining CHANGELOG

Is your feature request related to a problem? Please describe.

As a user of micropipenv, I would like to see what notable changes were made to the new release so that I can see any new features and breaking changes.

Describe the solution you'd like

A CHANGELOG file maintained along the sources, possibly use GitHub releases for this.

Describe alternatives you've considered

Let's discuss them.


It would be nice to start maintaining a CHANGELOG so that users see what has changed across releases. @frenzymadness what would be the best way to integrate with you and Python s2i and rpm on your side?

We have an ongoing effort to automatically generate CHANGELOG entries so this might be helpful to see how to do it properly to be compliant also with Fedora world.

I've created a GitHub release, but it might not be sufficient enough. We have also a CHANGELOG file available in the GitHub repository. What should go inside and should we follow any guidelines for the CHANGELOG so that it is easily machine-readable later on?

Consider --no-deps for pip installs

Is your feature request related to a problem? Please describe.

As micropipenv operates on already resolved software stack present in Pipfile.lock, it might be a good idea to pass --no-deps to pip install command. This way, pip will just download and install dependencies. It will not trigger a resolver for the installed packages.

Describe the solution you'd like

Install dependencies using pip install --no-deps.

Describe alternatives you've considered

Keep the current implementation as is, keeping pip resolution triggered.

Allow to disable required hashes

Is your feature request related to a problem? Please describe.

Trying to install a dependency from git, I get the following error:

In --require-hashes mode, all requirements must have their versions pinned with ==. These do not:
--
  | thoth-common from https://files.pythonhosted.org/packages/1d/dd/acbac33154a760095895a883054a80412ed2047917c3d219f3e309677bb9/thoth_common-0.10.9-py3-none-any.whl#sha256=e618c9875e14850d26f92fab8a55ecfd5ad7ad71a78a49eeba04f69c8555ad5b  (from -r /tmp/requirements.txtxhete0hn (line 506))

Describe the solution you'd like
I'd like to be able to disable this requirement via an environment variable.

Additional context
OpenShift S2I

Pipfile
[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true
name = "pypi"

[packages]
attrs = "*"
connexion = {extras = ["swagger-ui"],version = "*"}
flask = "*"
flask-script = "*"
grpcio = "*"
grpcio-opentracing = "*"
grpcio-tools = "*"
gunicorn = "*"
jaeger-client = "*"
opentracing-instrumentation = "*"
prometheus-client = "*"
prometheus-flask-exporter = "*"
requests = "*"
thoth-analyzer = "*"
thoth-common = {editable = true,git = "https://github.com/CermakM/common",ref = "develop"}
thoth-python = "*"
thoth-storages = "*"
flask-cors = "*"
aiocontextvars = "*"
sentry-sdk = {extras = ["flask"],version = "*"}

[pipenv]
allow_prereleases = false

[dev-packages]
pytest = "*"

[requires]
python_version = "3.6"
Pipfile.lock
{
    "_meta": {
        "hash": {
            "sha256": "0443b72efe1f5250b9622f8c011467b3ab6d3c6d35a7fdc912d8260ecde8b062"
        },
        "pipfile-spec": 6,
        "requires": {
            "python_version": "3.6"
        },
        "sources": [
            {
                "name": "pypi",
                "url": "https://pypi.python.org/simple",
                "verify_ssl": true
            }
        ]
    },
    "default": {
        "aiocontextvars": {
            "hashes": [
                "sha256:885daf8261818767d8f7cbd79f9d4482d118f024b6586ef6e67980236a27bfa3",
                "sha256:f027372dc48641f683c559f247bd84962becaacdc9ba711d583c3871fb5652aa"
            ],
            "index": "pypi",
            "version": "==0.2.2"
        },
        "aiohttp": {
            "hashes": [
                "sha256:1e984191d1ec186881ffaed4581092ba04f7c61582a177b187d3a2f07ed9719e",
                "sha256:259ab809ff0727d0e834ac5e8a283dc5e3e0ecc30c4d80b3cd17a4139ce1f326",
                "sha256:2f4d1a4fdce595c947162333353d4a44952a724fba9ca3205a3df99a33d1307a",
                "sha256:32e5f3b7e511aa850829fbe5aa32eb455e5534eaa4b1ce93231d00e2f76e5654",
                "sha256:344c780466b73095a72c616fac5ea9c4665add7fc129f285fbdbca3cccf4612a",
                "sha256:460bd4237d2dbecc3b5ed57e122992f60188afe46e7319116da5eb8a9dfedba4",
                "sha256:4c6efd824d44ae697814a2a85604d8e992b875462c6655da161ff18fd4f29f17",
                "sha256:50aaad128e6ac62e7bf7bd1f0c0a24bc968a0c0590a726d5a955af193544bcec",
                "sha256:6206a135d072f88da3e71cc501c59d5abffa9d0bb43269a6dcd28d66bfafdbdd",
                "sha256:65f31b622af739a802ca6fd1a3076fd0ae523f8485c52924a89561ba10c49b48",
                "sha256:ae55bac364c405caa23a4f2d6cfecc6a0daada500274ffca4a9230e7129eac59",
                "sha256:b778ce0c909a2653741cb4b1ac7015b5c130ab9c897611df43ae6a58523cb965"
            ],
            "version": "==3.6.2"
        },
        "alembic": {
            "hashes": [
                "sha256:791a5686953c4b366d3228c5377196db2f534475bb38d26f70eb69668efd9028"
            ],
            "version": "==1.4.1"
        },
        "amun": {
            "hashes": [
                "sha256:025738758afb52f1b028ebce299a91eea1f1f28004474887329c2f913100ac9b",
                "sha256:07572ad17071d35c4ffdadb9329cf20a0bd2f722d70b90deaa394b7242f5219c"
            ],
            "version": "==0.4.3"
        },
        "argo-workflows": {
            "hashes": [
                "sha256:289c40dcaf03af1cd489b53177a38df8c05b7a4a877f433b484bf715437c09d2",
                "sha256:57b4eae0fb29100b92160265e44c14a4302ce0e27b2d7d8715df8d7e2a2e38b0"
            ],
            "version": "==3.0.2"
        },
        "async-timeout": {
            "hashes": [
                "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f",
                "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"
            ],
            "version": "==3.0.1"
        },
        "attrdict": {
            "hashes": [
                "sha256:35c90698b55c683946091177177a9e9c0713a0860f0e049febd72649ccd77b70",
                "sha256:9432e3498c74ff7e1b20b3d93b45d766b71cbffa90923496f82c4ae38b92be34"
            ],
            "version": "==2.0.1"
        },
        "attrs": {
            "hashes": [
                "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c",
                "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"
            ],
            "index": "pypi",
            "version": "==19.3.0"
        },
        "beautifulsoup4": {
            "hashes": [
                "sha256:194ec62a25438adcb3fdb06378b26559eda1ea8a747367d34c33cef9c7f48d57",
                "sha256:90f8e61121d6ae58362ce3bed8cd997efb00c914eae0ff3d363c32f9a9822d10",
                "sha256:f0abd31228055d698bb392a826528ea08ebb9959e6bea17c606fd9c9009db938"
            ],
            "version": "==4.6.3"
        },
        "blinker": {
            "hashes": [
                "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
            ],
            "version": "==1.4"
        },
        "boto3": {
            "hashes": [
                "sha256:5cfe1e609af34e1641402e016047e2d12452992b52dccd3e5caea0990f225dc3",
                "sha256:6a45d2b777821b9b4b69656f628b498b86f6906c6643eca7759c660b26eb541e"
            ],
            "version": "==1.12.19"
        },
        "botocore": {
            "hashes": [
                "sha256:19c11d11aa4f5eee6a21aef85d311dd758dc6df59306e72176c980c3259db71f",
                "sha256:914059286a560ccca6c5c9fa7edd8de8533176090230676193a2e3fbcf214a9e"
            ],
            "version": "==1.15.19"
        },
        "cachetools": {
            "hashes": [
                "sha256:9a52dd97a85f257f4e4127f15818e71a0c7899f121b34591fcc1173ea79a0198",
                "sha256:b304586d357c43221856be51d73387f93e2a961598a9b6b6670664746f3b6c6c"
            ],
            "version": "==4.0.0"
        },
        "certifi": {
            "hashes": [
                "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3",
                "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"
            ],
            "version": "==2019.11.28"
        },
        "chardet": {
            "hashes": [
                "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
                "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
            ],
            "version": "==3.0.4"
        },
        "click": {
            "hashes": [
                "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc",
                "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a"
            ],
            "version": "==7.1.1"
        },
        "clickclick": {
            "hashes": [
                "sha256:4a890aaa9c3990cfabd446294eb34e3dc89701101ac7b41c1bff85fc210f6d23",
                "sha256:ab8f229fb9906a86634bdfc6fabfc2b665f44804170720db4f6e1d98f8a58f3d"
            ],
            "version": "==1.2.2"
        },
        "connexion": {
            "extras": [
                "swagger-ui"
            ],
            "hashes": [
                "sha256:bf32bfae6af337cfa4a8489c21516adbe5c50e3f8dc0b7ed2394ce8dde218018",
                "sha256:c568e579f84be808e387dcb8570bb00a536891be1318718a0dad3ba90f034191"
            ],
            "index": "pypi",
            "version": "==2.6.0"
        },
        "contextlib2": {
            "hashes": [
                "sha256:01f490098c18b19d2bd5bb5dc445b2054d2fa97f09a4280ba2c5f3c394c8162e",
                "sha256:3355078a159fbb44ee60ea80abd0d87b80b78c248643b49aa6d94673b413609b"
            ],
            "version": "==0.6.0.post1"
        },
        "contextvars": {
            "hashes": [
                "sha256:f38c908aaa59c14335eeea12abea5f443646216c4e29380d7bf34d2018e2c39e"
            ],
            "markers": "python_version < '3.7'",
            "version": "==2.4"
        },
        "daiquiri": {
            "hashes": [
                "sha256:0d5bf9c5719fbca4928dc2a882c165cd2b5c81be28f7f1626ced04c1c6b4aae2",
                "sha256:236183ba51f35f4ae0e23fd20119d0fa082995c08d77bd562dbc00ea8f504bf6"
            ],
            "version": "==2.1.1"
        },
        "delegator.py": {
            "hashes": [
                "sha256:814657d96b98a244c479e3d5f6e9e850ac333e85f807d6bc846e72bbb2537806",
                "sha256:e6cc9cedab9ae59b169ee0422e17231adedadb144e63c0b5a60e6ff8adf8521b"
            ],
            "version": "==0.1.1"
        },
        "dictdiffer": {
            "hashes": [
                "sha256:1adec0d67cdf6166bda96ae2934ddb5e54433998ceab63c984574d187cc563d2",
                "sha256:d79d9a39e459fe33497c858470ca0d2e93cb96621751de06d631856adfd9c390"
            ],
            "version": "==0.8.1"
        },
        "distro": {
            "hashes": [
                "sha256:362dde65d846d23baee4b5c058c8586f219b5a54be1cf5fc6ff55c4578392f57",
                "sha256:eedf82a470ebe7d010f1872c17237c79ab04097948800029994fa458e52fb4b4"
            ],
            "version": "==1.4.0"
        },
        "docutils": {
            "hashes": [
                "sha256:6c4f696463b79f1fb8ba0c594b63840ebd41f059e92b31957c46b74a4599b6d0",
                "sha256:9e4d7ecfc600058e07ba661411a2b7de2fd0fafa17d1a7f7361cd47b1175c827",
                "sha256:a2aeea129088da402665e92e0b25b04b073c04b2dce4ab65caaa38b7ce2e1a99"
            ],
            "version": "==0.15.2"
        },
        "flask": {
            "hashes": [
                "sha256:13f9f196f330c7c2c5d7a5cf91af894110ca0215ac051b5844701f2bfd934d52",
                "sha256:45eb5a6fd193d6cf7e0cf5d8a5b31f83d5faae0293695626f539a823e93b13f6"
            ],
            "index": "pypi",
            "version": "==1.1.1"
        },
        "flask-cors": {
            "hashes": [
                "sha256:72170423eb4612f0847318afff8c247b38bd516b7737adfc10d1c2cdbb382d16",
                "sha256:f4d97201660e6bbcff2d89d082b5b6d31abee04b1b3003ee073a6fd25ad1d69a"
            ],
            "index": "pypi",
            "version": "==3.0.8"
        },
        "flask-script": {
            "hashes": [
                "sha256:6425963d91054cfcc185807141c7314a9c5ad46325911bd24dcb489bd0161c65"
            ],
            "index": "pypi",
            "version": "==2.0.6"
        },
        "future": {
            "hashes": [
                "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"
            ],
            "version": "==0.18.2"
        },
        "google-auth": {
            "hashes": [
                "sha256:1ee22e22f35d6e00f068d7b3999b2ce24ecb5d0dcbd485aa6896d2b83c8907d6",
                "sha256:28a848d47c55075a0f29d7e26b7a213515c137ab8f0670e546e46d1277060e47"
            ],
            "version": "==1.11.2"
        },
        "grpcio": {
            "hashes": [
                "sha256:02aef8ef1a5ac5f0836b543e462eb421df6048a7974211a906148053b8055ea6",
                "sha256:07f82aefb4a56c7e1e52b78afb77d446847d27120a838a1a0489260182096045",
                "sha256:1cff47297ee614e7ef66243dc34a776883ab6da9ca129ea114a802c5e58af5c1",
                "sha256:1ec8fc865d8da6d0713e2092a27eee344cd54628b2c2065a0e77fff94df4ae00",
                "sha256:1ef949b15a1f5f30651532a9b54edf3bd7c0b699a10931505fa2c80b2d395942",
                "sha256:209927e65395feb449783943d62a3036982f871d7f4045fadb90b2d82b153ea8",
                "sha256:25c77692ea8c0929d4ad400ea9c3dcbcc4936cee84e437e0ef80da58fa73d88a",
                "sha256:28f27c64dd699b8b10f70da5f9320c1cffcaefca7dd76275b44571bd097f276c",
                "sha256:355bd7d7ce5ff2917d217f0e8ddac568cb7403e1ce1639b35a924db7d13a39b6",
                "sha256:4a0a33ada3f6f94f855f92460896ef08c798dcc5f17d9364d1735c5adc9d7e4a",
                "sha256:4d3b6e66f32528bf43ca2297caca768280a8e068820b1c3dca0fcf9f03c7d6f1",
                "sha256:5121fa96c79fc0ec81825091d0be5c16865f834f41b31da40b08ee60552f9961",
                "sha256:57949756a3ce1f096fa2b00f812755f5ab2effeccedb19feeb7d0deafa3d1de7",
                "sha256:586d931736912865c9790c60ca2db29e8dc4eace160d5a79fec3e58df79a9386",
                "sha256:5ae532b93cf9ce5a2a549b74a2c35e3b690b171ece9358519b3039c7b84c887e",
                "sha256:5dab393ab96b2ce4012823b2f2ed4ee907150424d2f02b97bd6f8dd8f17cc866",
                "sha256:5ebc13451246de82f130e8ee7e723e8d7ae1827f14b7b0218867667b1b12c88d",
                "sha256:68a149a0482d0bc697aac702ec6efb9d380e0afebf9484db5b7e634146528371",
                "sha256:6db7ded10b82592c472eeeba34b9f12d7b0ab1e2dcad12f081b08ebdea78d7d6",
                "sha256:6e545908bcc2ae28e5b190ce3170f92d0438cf26a82b269611390114de0106eb",
                "sha256:6f328a3faaf81a2546a3022b3dfc137cc6d50d81082dbc0c94d1678943f05df3",
                "sha256:706e2dea3de33b0d8884c4d35ecd5911b4ff04d0697c4138096666ce983671a6",
                "sha256:80c3d1ce8820dd819d1c9d6b63b6f445148480a831173b572a9174a55e7abd47",
                "sha256:8111b61eee12d7af5c58f82f2c97c2664677a05df9225ef5cbc2f25398c8c454",
                "sha256:9713578f187fb1c4d00ac554fe1edcc6b3ddd62f5d4eb578b81261115802df8e",
                "sha256:9c0669ba9aebad540fb05a33beb7e659ea6e5ca35833fc5229c20f057db760e8",
                "sha256:9e9cfe55dc7ac2aa47e0fd3285ff829685f96803197042c9d2f0fb44e4b39b2c",
                "sha256:a22daaf30037b8e59d6968c76fe0f7ff062c976c7a026e92fbefc4c4bf3fc5a4",
                "sha256:a25b84e10018875a0f294a7649d07c43e8bc3e6a821714e39e5cd607a36386d7",
                "sha256:a71138366d57901597bfcc52af7f076ab61c046f409c7b429011cd68de8f9fe6",
                "sha256:b4efde5524579a9ce0459ca35a57a48ca878a4973514b8bb88cb80d7c9d34c85",
                "sha256:b78af4d42985ab3143d9882d0006f48d12f1bc4ba88e78f23762777c3ee64571",
                "sha256:bb2987eb3af9bcf46019be39b82c120c3d35639a95bc4ee2d08f36ecdf469345",
                "sha256:c03ce53690fe492845e14f4ab7e67d5a429a06db99b226b5c7caa23081c1e2bb",
                "sha256:c59b9280284b791377b3524c8e39ca7b74ae2881ba1a6c51b36f4f1bb94cee49",
                "sha256:d18b4c8cacbb141979bb44355ee5813dd4d307e9d79b3a36d66eca7e0a203df8",
                "sha256:d1e5563e3b7f844dbc48d709c9e4a75647e11d0387cc1fa0c861d3e9d34bc844",
                "sha256:d22c897b65b1408509099f1c3334bd3704f5e4eb7c0486c57d0e212f71cb8f54",
                "sha256:dbec0a3a154dbf2eb85b38abaddf24964fa1c059ee0a4ad55d6f39211b1a4bca",
                "sha256:ed123037896a8db6709b8ad5acc0ed435453726ea0b63361d12de369624c2ab5",
                "sha256:f3614dabd2cc8741850597b418bcf644d4f60e73615906c3acc407b78ff720b3",
                "sha256:f9d632ce9fd485119c968ec6a7a343de698c5e014d17602ae2f110f1b05925ed",
                "sha256:fb62996c61eeff56b59ab8abfcaa0859ec2223392c03d6085048b576b567459b"
            ],
            "index": "pypi",
            "version": "==1.27.2"
        },
        "grpcio-opentracing": {
            "hashes": [
                "sha256:c90ac0ceac31d96a4e92742064fad099d42115df36cb33adf5eea6526204a130",
                "sha256:cea56f355ffc1fdbecef98df127fbce5435745f4b134f3b2874a4246823d93ef"
            ],
            "index": "pypi",
            "version": "==1.1.4"
        },
        "grpcio-tools": {
            "hashes": [
                "sha256:00c5080cfb197ed20ecf0d0ff2d07f1fc9c42c724cad21c40ff2d048de5712b1",
                "sha256:069826dd02ce1886444cf4519c4fe1b05ac9ef41491f26e97400640531db47f6",
                "sha256:1266b577abe7c720fd16a83d0a4999a192e87c4a98fc9f97e0b99b106b3e155f",
                "sha256:16dc3fad04fe18d50777c56af7b2d9b9984cd1cfc71184646eb431196d1645c6",
                "sha256:1de5a273eaffeb3d126a63345e9e848ea7db740762f700eb8b5d84c5e3e7687d",
                "sha256:2ca280af2cae1a014a238057bd3c0a254527569a6a9169a01c07f0590081d530",
                "sha256:43a1573400527a23e4174d88604fde7a9d9a69bf9473c21936b7f409858f8ebb",
                "sha256:4698c6b6a57f73b14d91a542c69ff33a2da8729691b7060a5d7f6383624d045e",
                "sha256:520b7dafddd0f82cb7e4f6e9c6ba1049aa804d0e207870def9fe7f94d1e14090",
                "sha256:57f8b9e2c7f55cd45f6dd930d6de61deb42d3eb7f9788137fbc7155cf724132a",
                "sha256:59fbeb5bb9a7b94eb61642ac2cee1db5233b8094ca76fc56d4e0c6c20b5dd85f",
                "sha256:5fd7efc2fd3370bd2c72dc58f31a407a5dff5498befa145da211b2e8c6a52c63",
                "sha256:6016c07d6566e3109a3c032cf3861902d66501ecc08a5a84c47e43027302f367",
                "sha256:627c91923df75091d8c4d244af38d5ab7ed8d786d480751d6c2b9267fbb92fe0",
                "sha256:69c4a63919b9007e845d9f8980becd2f89d808a4a431ca32b9723ee37b521cb1",
                "sha256:77e25c241e33b75612f2aa62985f746c6f6803ec4e452da508bb7f8d90a69db4",
                "sha256:7a2d5fb558ac153a326e742ebfd7020eb781c43d3ffd920abd42b2e6c6fdfb37",
                "sha256:7b54b283ec83190680903a9037376dc915e1f03852a2d574ba4d981b7a1fd3d0",
                "sha256:845a51305af9fc7f9e2078edaec9a759153195f6cf1fbb12b1fa6f077e56b260",
                "sha256:84724458c86ff9b14c29b49e321f34d80445b379f4cd4d0494c694b49b1d6f88",
                "sha256:87e8ca2c2d2d3e09b2a2bed5d740d7b3e64028dafb7d6be543b77eec85590736",
                "sha256:8e7738a4b93842bca1158cde81a3587c9b7111823e40a1ddf73292ca9d58e08b",
                "sha256:915a695bc112517af48126ee0ecdb6aff05ed33f3eeef28f0d076f1f6b52ef5e",
                "sha256:99961156a36aae4a402d6b14c1e7efde642794b3ddbf32c51db0cb3a199e8b11",
                "sha256:9ba88c2d99bcaf7b9cb720925e3290d73b2367d238c5779363fd5598b2dc98c7",
                "sha256:a140bf853edb2b5e8692fe94869e3e34077d7599170c113d07a58286c604f4fe",
                "sha256:a14dc7a36c845991d908a7179502ca47bcba5ae1817c4426ce68cf2c97b20ad9",
                "sha256:a3d2aec4b09c8e59fee8b0d1ed668d09e8c48b738f03f5d8401d7eb409111c47",
                "sha256:a8f892378b0b02526635b806f59141abbb429d19bec56e869e04f396502c9651",
                "sha256:aaa5ae26883c3d58d1a4323981f96b941fa09bb8f0f368d97c6225585280cf04",
                "sha256:b56caecc16307b088a431a4038c3b3bb7d0e7f9988cbd0e9fa04ac937455ea38",
                "sha256:bd7f59ff1252a3db8a143b13ea1c1e93d4b8cf4b852eb48b22ef1e6942f62a84",
                "sha256:c1bb8f47d58e9f7c4825abfe01e6b85eda53c8b31d2267ca4cddf3c4d0829b80",
                "sha256:d1a5e5fa47ba9557a7d3b31605631805adc66cdba9d95b5d10dfc52cca1fed53",
                "sha256:dcbc06556f3713a9348c4fce02d05d91e678fc320fb2bcf0ddf8e4bb11d17867",
                "sha256:e17b2e0936b04ced99769e26111e1e86ba81619d1b2691b1364f795e45560953",
                "sha256:e6932518db389ede8bf06b4119bbd3e17f42d4626e72dec2b8955b20ec732cb6",
                "sha256:ea4b3ad696d976d5eac74ec8df9a2c692113e455446ee38d5b3bd87f8e034fa6",
                "sha256:ee50b0cf0d28748ef9f941894eb50fc464bd61b8e96aaf80c5056bea9b80d580",
                "sha256:ef624b6134aef737b3daa4fb7e806cb8c5749efecd0b1fa9ce4f7e060c7a0221",
                "sha256:f5450aa904e720f9c6407b59e96a8951ed6a95463f49444b6d2594b067d39588",
                "sha256:f8514453411d72cc3cf7d481f2b6057e5b7436736d0cd39ee2b2f72088bbf497",
                "sha256:fae91f30dc050a8d0b32d20dc700e6092f0bd2138d83e9570fff3f0372c1b27e"
            ],
            "index": "pypi",
            "version": "==1.27.2"
        },
        "gunicorn": {
            "hashes": [
                "sha256:1904bb2b8a43658807108d59c3f3d56c2b6121a701161de0ddf9ad140073c626",
                "sha256:cd4a810dd51bf497552cf3f863b575dabd73d6ad6a91075b65936b151cbf4f9c"
            ],
            "index": "pypi",
            "version": "==20.0.4"
        },
        "idna": {
            "hashes": [
                "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb",
                "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"
            ],
            "version": "==2.9"
        },
        "idna-ssl": {
            "hashes": [
                "sha256:a933e3bb13da54383f9e8f35dc4f9cb9eb9b3b78c6b36f311254d6d0d92c6c7c"
            ],
            "markers": "python_version < '3.7'",
            "version": "==1.1.0"
        },
        "immutables": {
            "hashes": [
                "sha256:0aa055c745510238cbad2f1f709a37a1c9e30a38594de3b385e9876c48a25633",
                "sha256:0f07c58122e1ce70a7165e68e18e795ac5fe94d7fee3e045ffcf6432602026df",
                "sha256:1c2e729aab250be0de0c13fa833241a778b51390ee2650e0457d1e45b318c441",
                "sha256:2c536ff2bafeeff9a7865ea10a17a50f90b80b585e31396c349e8f57b0075bd4",
                "sha256:2de2ec8dde1ca154f811776a8cbbeaea515c3b226c26036eab6484530eea28e0",
                "sha256:422c7d4c75c88057c625e32992248329507bca180b48cfb702b4ef608f581b50",
                "sha256:518f20945c1f600b618fb691922c2ab43b193f04dd2d4d2823220d0202014670",
                "sha256:545186faab9237c102b8bcffd36d71f0b382174c93c501e061de239753cff694",
                "sha256:6b6d8d035e5888baad3db61dfb167476838a63afccecd927c365f228bb55754c",
                "sha256:b268422a5802fbf934152b835329ac0d23b80b558eaee68034d45718edab4a11",
                "sha256:b8fed714f1c84a3242c7184838f5e9889139a22bbdd701a182b7fdc237ca3cbb",
                "sha256:bce27277a2fe91509cca69181971ab509c2ee862e8b37b09f26b64f90e8fe8fb",
                "sha256:c7eb2d15c35c73bb168c002c6ea145b65f40131e10dede54b39db0b72849b280",
                "sha256:d6850578a0dc6530ac19113cfe4ddc13903df635212d498f176fe601a8a5a4a3",
                "sha256:e87bd941cb4dfa35f16e1ff4b2d99a2931452dcc9cfd788dc8fe513f3d38551e",
                "sha256:f5b93248552c9e7198558776da21c9157d3f70649905d7fdc083c2ab2fbc6088"
            ],
            "version": "==0.11"
        },
        "importlib-metadata": {
            "hashes": [
                "sha256:06f5b3a99029c7134207dd882428a66992a9de2bef7c2b699b5641f9886c3302",
                "sha256:b97607a1a18a5100839aec1dc26a1ea17ee0d93b20b0f008d80a5a050afb200b"
            ],
            "markers": "python_version < '3.8'",
            "version": "==1.5.0"
        },
        "inflection": {
            "hashes": [
                "sha256:18ea7fb7a7d152853386523def08736aa8c32636b047ade55f7578c4edeb16ca"
            ],
            "version": "==0.3.1"
        },
        "itsdangerous": {
            "hashes": [
                "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19",
                "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749"
            ],
            "version": "==1.1.0"
        },
        "jaeger-client": {
            "hashes": [
                "sha256:7f72c341a21e3dcbc8498d1ed17c93e0eec71c5becc5c9333c4293793d4e6433"
            ],
            "index": "pypi",
            "version": "==4.3.0"
        },
        "jinja2": {
            "hashes": [
                "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250",
                "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49"
            ],
            "version": "==2.11.1"
        },
        "jmespath": {
            "hashes": [
                "sha256:695cb76fa78a10663425d5b73ddc5714eb711157e52704d69be03b1a02ba4fec",
                "sha256:cca55c8d153173e21baa59983015ad0daf603f9cb799904ff057bfb8ff8dc2d9"
            ],
            "version": "==0.9.5"
        },
        "jsonschema": {
            "hashes": [
                "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163",
                "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"
            ],
            "version": "==3.2.0"
        },
        "kubernetes": {
            "hashes": [
                "sha256:3770a496663396ad1def665eeadb947b3f45217a08b64b10c01a57e981ac8592",
                "sha256:a6dee02a1b39ea4bb9c4c2cc415ea0ada33d8ea0a920f7d4fb6d166989dcac01"
            ],
            "version": "==10.0.1"
        },
        "lxml": {
            "hashes": [
                "sha256:06d4e0bbb1d62e38ae6118406d7cdb4693a3fa34ee3762238bcb96c9e36a93cd",
                "sha256:0701f7965903a1c3f6f09328c1278ac0eee8f56f244e66af79cb224b7ef3801c",
                "sha256:1f2c4ec372bf1c4a2c7e4bb20845e8bcf8050365189d86806bad1e3ae473d081",
                "sha256:4235bc124fdcf611d02047d7034164897ade13046bda967768836629bc62784f",
                "sha256:5828c7f3e615f3975d48f40d4fe66e8a7b25f16b5e5705ffe1d22e43fb1f6261",
                "sha256:585c0869f75577ac7a8ff38d08f7aac9033da2c41c11352ebf86a04652758b7a",
                "sha256:5d467ce9c5d35b3bcc7172c06320dddb275fea6ac2037f72f0a4d7472035cea9",
                "sha256:63dbc21efd7e822c11d5ddbedbbb08cd11a41e0032e382a0fd59b0b08e405a3a",
                "sha256:7bc1b221e7867f2e7ff1933165c0cec7153dce93d0cdba6554b42a8beb687bdb",
                "sha256:8620ce80f50d023d414183bf90cc2576c2837b88e00bea3f33ad2630133bbb60",
                "sha256:8a0ebda56ebca1a83eb2d1ac266649b80af8dd4b4a3502b2c1e09ac2f88fe128",
                "sha256:90ed0e36455a81b25b7034038e40880189169c308a3df360861ad74da7b68c1a",
                "sha256:95e67224815ef86924fbc2b71a9dbd1f7262384bca4bc4793645794ac4200717",
                "sha256:afdb34b715daf814d1abea0317b6d672476b498472f1e5aacbadc34ebbc26e89",
                "sha256:b4b2c63cc7963aedd08a5f5a454c9f67251b1ac9e22fd9d72836206c42dc2a72",
                "sha256:d068f55bda3c2c3fcaec24bd083d9e2eede32c583faf084d6e4b9daaea77dde8",
                "sha256:d5b3c4b7edd2e770375a01139be11307f04341ec709cf724e0f26ebb1eef12c3",
                "sha256:deadf4df349d1dcd7b2853a2c8796593cc346600726eff680ed8ed11812382a7",
                "sha256:df533af6f88080419c5a604d0d63b2c33b1c0c4409aba7d0cb6de305147ea8c8",
                "sha256:e4aa948eb15018a657702fee0b9db47e908491c64d36b4a90f59a64741516e77",
                "sha256:e5d842c73e4ef6ed8c1bd77806bf84a7cb535f9c0cf9b2c74d02ebda310070e1",
                "sha256:ebec08091a22c2be870890913bdadd86fcd8e9f0f22bcb398abd3af914690c15",
                "sha256:edc15fcfd77395e24543be48871c251f38132bb834d9fdfdad756adb6ea37679",
                "sha256:f2b74784ed7e0bc2d02bd53e48ad6ba523c9b36c194260b7a5045071abbb1012",
                "sha256:fa071559f14bd1e92077b1b5f6c22cf09756c6de7139370249eb372854ce51e6",
                "sha256:fd52e796fee7171c4361d441796b64df1acfceb51f29e545e812f16d023c4bbc",
                "sha256:fe976a0f1ef09b3638778024ab9fb8cde3118f203364212c198f71341c0715ca"
            ],
            "version": "==4.5.0"
        },
        "mako": {
            "hashes": [
                "sha256:3139c5d64aa5d175dbafb95027057128b5fbd05a40c53999f3905ceb53366d9d",
                "sha256:8e8b53c71c7e59f3de716b6832c4e401d903af574f6962edbbbf6ecc2a5fe6c9"
            ],
            "version": "==1.1.2"
        },
        "markupsafe": {
            "hashes": [
                "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
                "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
                "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
                "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
                "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42",
                "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
                "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
                "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
                "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
                "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
                "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
                "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b",
                "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
                "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15",
                "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
                "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
                "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
                "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
                "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
                "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
                "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
                "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
                "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
                "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
                "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
                "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
                "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
                "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
                "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
                "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
                "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2",
                "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7",
                "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"
            ],
            "version": "==1.1.1"
        },
        "methodtools": {
            "hashes": [
                "sha256:03e05f69150cb2a931f71dc542ee80856e91ae00e179c1df384285078b0dc118"
            ],
            "version": "==0.1.2"
        },
        "mock": {
            "hashes": [
                "sha256:3f9b2c0196c60d21838f307f5825a7b86b678cedc58ab9e50a8988187b4d81e0",
                "sha256:dd33eb70232b6118298d516bbcecd26704689c386594f0f3c4f13867b2c56f72"
            ],
            "version": "==4.0.2"
        },
        "multidict": {
            "hashes": [
                "sha256:317f96bc0950d249e96d8d29ab556d01dd38888fbe68324f46fd834b430169f1",
                "sha256:42f56542166040b4474c0c608ed051732033cd821126493cf25b6c276df7dd35",
                "sha256:4b7df040fb5fe826d689204f9b544af469593fb3ff3a069a6ad3409f742f5928",
                "sha256:544fae9261232a97102e27a926019100a9db75bec7b37feedd74b3aa82f29969",
                "sha256:620b37c3fea181dab09267cd5a84b0f23fa043beb8bc50d8474dd9694de1fa6e",
                "sha256:6e6fef114741c4d7ca46da8449038ec8b1e880bbe68674c01ceeb1ac8a648e78",
                "sha256:7774e9f6c9af3f12f296131453f7b81dabb7ebdb948483362f5afcaac8a826f1",
                "sha256:85cb26c38c96f76b7ff38b86c9d560dea10cf3459bb5f4caf72fc1bb932c7136",
                "sha256:a326f4240123a2ac66bb163eeba99578e9d63a8654a59f4688a79198f9aa10f8",
                "sha256:ae402f43604e3b2bc41e8ea8b8526c7fa7139ed76b0d64fc48e28125925275b2",
                "sha256:aee283c49601fa4c13adc64c09c978838a7e812f85377ae130a24d7198c0331e",
                "sha256:b51249fdd2923739cd3efc95a3d6c363b67bbf779208e9f37fd5e68540d1a4d4",
                "sha256:bb519becc46275c594410c6c28a8a0adc66fe24fef154a9addea54c1adb006f5",
                "sha256:c2c37185fb0af79d5c117b8d2764f4321eeb12ba8c141a95d0aa8c2c1d0a11dd",
                "sha256:dc561313279f9d05a3d0ffa89cd15ae477528ea37aa9795c4654588a3287a9ab",
                "sha256:e439c9a10a95cb32abd708bb8be83b2134fa93790a4fb0535ca36db3dda94d20",
                "sha256:fc3b4adc2ee8474cb3cd2a155305d5f8eda0a9c91320f83e55748e1fcb68f8e3"
            ],
            "version": "==4.7.5"
        },
        "oauthlib": {
            "hashes": [
                "sha256:bee41cc35fcca6e988463cacc3bcb8a96224f470ca547e697b604cc697b2f889",
                "sha256:df884cd6cbe20e32633f1db1072e9356f53638e4361bef4e8b03c9127c9328ea"
            ],
            "version": "==3.1.0"
        },
        "openapi-spec-validator": {
            "hashes": [
                "sha256:0caacd9829e9e3051e830165367bf58d436d9487b29a09220fa7edb9f47ff81b",
                "sha256:d4da8aef72bf5be40cf0df444abd20009a41baf9048a8e03750c07a934f1bdd8",
                "sha256:e489c7a273284bc78277ac22791482e8058d323b4a265015e9fcddf6a8045bcd"
            ],
            "version": "==0.2.8"
        },
        "openshift": {
            "hashes": [
                "sha256:10868c5697c7610e1d18d62118f1bf2096d35789fa9790c89285947a93545a8a"
            ],
            "version": "==0.10.2"
        },
        "opentracing": {
            "hashes": [
                "sha256:33b10634917a7496a7e3a18b18b7c055053d0a8da5101e2a95d454783cac9765"
            ],
            "version": "==2.3.0"
        },
        "opentracing-instrumentation": {
            "hashes": [
                "sha256:918b1f52e3db035002bb26a366bb6cbaea9715d567015ce9f514e08047f84185",
                "sha256:a8fb8499c6ab71665313c179e327b406bfa09b0277bd7cb02b2941eaa659d8dd"
            ],
            "index": "pypi",
            "version": "==3.2.1"
        },
        "packaging": {
            "hashes": [
                "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3",
                "sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752"
            ],
            "version": "==20.3"
        },
        "pexpect": {
            "hashes": [
                "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937",
                "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"
            ],
            "version": "==4.8.0"
        },
        "prometheus-client": {
            "hashes": [
                "sha256:71cd24a2b3eb335cb800c7159f423df1bd4dcd5171b234be15e3f31ec9f622da"
            ],
            "index": "pypi",
            "version": "==0.7.1"
        },
        "prometheus-flask-exporter": {
            "hashes": [
                "sha256:a3d7003df268ba0d91d91526ea8abee08e619c91f1fdc16de1604c196654fdee"
            ],
            "index": "pypi",
            "version": "==0.13.0"
        },
        "protobuf": {
            "hashes": [
                "sha256:0bae429443cc4748be2aadfdaf9633297cfaeb24a9a02d0ab15849175ce90fab",
                "sha256:24e3b6ad259544d717902777b33966a1a069208c885576254c112663e6a5bb0f",
                "sha256:310a7aca6e7f257510d0c750364774034272538d51796ca31d42c3925d12a52a",
                "sha256:52e586072612c1eec18e1174f8e3bb19d08f075fc2e3f91d3b16c919078469d0",
                "sha256:73152776dc75f335c476d11d52ec6f0f6925774802cd48d6189f4d5d7fe753f4",
                "sha256:7774bbbaac81d3ba86de646c39f154afc8156717972bf0450c9dbfa1dc8dbea2",
                "sha256:82d7ac987715d8d1eb4068bf997f3053468e0ce0287e2729c30601feb6602fee",
                "sha256:8eb9c93798b904f141d9de36a0ba9f9b73cc382869e67c9e642c0aba53b0fc07",
                "sha256:adf0e4d57b33881d0c63bb11e7f9038f98ee0c3e334c221f0858f826e8fb0151",
                "sha256:c40973a0aee65422d8cb4e7d7cbded95dfeee0199caab54d5ab25b63bce8135a",
                "sha256:c77c974d1dadf246d789f6dad1c24426137c9091e930dbf50e0a29c1fcf00b1f",
                "sha256:dd9aa4401c36785ea1b6fff0552c674bdd1b641319cb07ed1fe2392388e9b0d7",
                "sha256:e11df1ac6905e81b815ab6fd518e79be0a58b5dc427a2cf7208980f30694b956",
                "sha256:e2f8a75261c26b2f5f3442b0525d50fd79a71aeca04b5ec270fc123536188306",
                "sha256:e512b7f3a4dd780f59f1bf22c302740e27b10b5c97e858a6061772668cd6f961",
                "sha256:ef2c2e56aaf9ee914d3dccc3408d42661aaf7d9bb78eaa8f17b2e6282f214481",
                "sha256:fac513a9dc2a74b99abd2e17109b53945e364649ca03d9f7a0b96aa8d1807d0a",
                "sha256:fdfb6ad138dbbf92b5dbea3576d7c8ba7463173f7d2cb0ca1bd336ec88ddbd80"
            ],
            "version": "==3.11.3"
        },
        "psycopg2-binary": {
            "hashes": [
                "sha256:040234f8a4a8dfd692662a8308d78f63f31a97e1c42d2480e5e6810c48966a29",
                "sha256:086f7e89ec85a6704db51f68f0dcae432eff9300809723a6e8782c41c2f48e03",
                "sha256:18ca813fdb17bc1db73fe61b196b05dd1ca2165b884dd5ec5568877cabf9b039",
                "sha256:19dc39616850342a2a6db70559af55b22955f86667b5f652f40c0e99253d9881",
                "sha256:2166e770cb98f02ed5ee2b0b569d40db26788e0bf2ec3ae1a0d864ea6f1d8309",
                "sha256:3a2522b1d9178575acee4adf8fd9f979f9c0449b00b4164bb63c3475ea6528ed",
                "sha256:3aa773580f85a28ffdf6f862e59cb5a3cc7ef6885121f2de3fca8d6ada4dbf3b",
                "sha256:3b5deaa3ee7180585a296af33e14c9b18c218d148e735c7accf78130765a47e3",
                "sha256:407af6d7e46593415f216c7f56ba087a9a42bd6dc2ecb86028760aa45b802bd7",
                "sha256:4c3c09fb674401f630626310bcaf6cd6285daf0d5e4c26d6e55ca26a2734e39b",
                "sha256:4c6717962247445b4f9e21c962ea61d2e884fc17df5ddf5e35863b016f8a1f03",
                "sha256:50446fae5681fc99f87e505d4e77c9407e683ab60c555ec302f9ac9bffa61103",
                "sha256:5057669b6a66aa9ca118a2a860159f0ee3acf837eda937bdd2a64f3431361a2d",
                "sha256:5dd90c5438b4f935c9d01fcbad3620253da89d19c1f5fca9158646407ed7df35",
                "sha256:659c815b5b8e2a55193ede2795c1e2349b8011497310bb936da7d4745652823b",
                "sha256:69b13fdf12878b10dc6003acc8d0abf3ad93e79813fd5f3812497c1c9fb9be49",
                "sha256:7a1cb80e35e1ccea3e11a48afe65d38744a0e0bde88795cc56a4d05b6e4f9d70",
                "sha256:7e6e3c52e6732c219c07bd97fff6c088f8df4dae3b79752ee3a817e6f32e177e",
                "sha256:7f42a8490c4fe854325504ce7a6e4796b207960dabb2cbafe3c3959cb00d1d7e",
                "sha256:84156313f258eafff716b2961644a4483a9be44a5d43551d554844d15d4d224e",
                "sha256:8578d6b8192e4c805e85f187bc530d0f52ba86c39172e61cd51f68fddd648103",
                "sha256:890167d5091279a27e2505ff0e1fb273f8c48c41d35c5b92adbf4af80e6b2ed6",
                "sha256:98e10634792ac0e9e7a92a76b4991b44c2325d3e7798270a808407355e7bb0a1",
                "sha256:9aadff9032e967865f9778485571e93908d27dab21d0fdfdec0ca779bb6f8ad9",
                "sha256:9f24f383a298a0c0f9b3113b982e21751a8ecde6615494a3f1470eb4a9d70e9e",
                "sha256:a73021b44813b5c84eda4a3af5826dd72356a900bac9bd9dd1f0f81ee1c22c2f",
                "sha256:afd96845e12638d2c44d213d4810a08f4dc4a563f9a98204b7428e567014b1cd",
                "sha256:b73ddf033d8cd4cc9dfed6324b1ad2a89ba52c410ef6877998422fcb9c23e3a8",
                "sha256:b8f490f5fad1767a1331df1259763b3bad7d7af12a75b950c2843ba319b2415f",
                "sha256:dbc5cd56fff1a6152ca59445178652756f4e509f672e49ccdf3d79c1043113a4",
                "sha256:eac8a3499754790187bb00574ab980df13e754777d346f85e0ff6df929bcd964",
                "sha256:eaed1c65f461a959284649e37b5051224f4db6ebdc84e40b5e65f2986f101a08"
            ],
            "version": "==2.8.4"
        },
        "ptyprocess": {
            "hashes": [
                "sha256:923f299cc5ad920c68f2bc0bc98b75b9f838b93b599941a6b63ddbc2476394c0",
                "sha256:d7cc528d76e76342423ca640335bd3633420dc1366f258cb31d05e865ef5ca1f"
            ],
            "version": "==0.6.0"
        },
        "pyasn1": {
            "hashes": [
                "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d",
                "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"
            ],
            "version": "==0.4.8"
        },
        "pyasn1-modules": {
            "hashes": [
                "sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e",
                "sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74"
            ],
            "version": "==0.2.8"
        },
        "pyelftools": {
            "hashes": [
                "sha256:86ac6cee19f6c945e8dedf78c6ee74f1112bd14da5a658d8c9d4103aed5756a2",
                "sha256:cc0ea0de82b240a73ef4056fce44acbb4727dca7d66759371aff2bad457ed711"
            ],
            "version": "==0.26"
        },
        "pyparsing": {
            "hashes": [
                "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f",
                "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec"
            ],
            "version": "==2.4.6"
        },
        "pyrsistent": {
            "hashes": [
                "sha256:cdc7b5e3ed77bed61270a47d35434a30617b9becdf2478af76ad2c6ade307280"
            ],
            "version": "==0.15.7"
        },
        "python-dateutil": {
            "hashes": [
                "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c",
                "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"
            ],
            "version": "==2.8.1"
        },
        "python-editor": {
            "hashes": [
                "sha256:1bf6e860a8ad52a14c3ee1252d5dc25b2030618ed80c022598f00176adc8367d",
                "sha256:51fda6bcc5ddbbb7063b2af7509e43bd84bfc32a4ff71349ec7847713882327b",
                "sha256:5f98b069316ea1c2ed3f67e7f5df6c0d8f10b689964a4a811ff64f0106819ec8"
            ],
            "version": "==1.0.4"
        },
        "python-json-logger": {
            "hashes": [
                "sha256:b7a31162f2a01965a5efb94453ce69230ed208468b0bbc7fdfc56e6d8df2e281"
            ],
            "version": "==0.1.11"
        },
        "python-string-utils": {
            "hashes": [
                "sha256:dcf9060b03f07647c0a603408dc8b03f807f3b54a05c6e19eb14460256fac0cb",
                "sha256:f1a88700baf99db1a9b6953f44181ad9ca56623c81e257e6009707e2e7851fa4"
            ],
            "version": "==1.0.0"
        },
        "pytz": {
            "hashes": [
                "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d",
                "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"
            ],
            "version": "==2019.3"
        },
        "pyyaml": {
            "hashes": [
                "sha256:059b2ee3194d718896c0ad077dd8c043e5e909d9180f387ce42012662a4946d6",
                "sha256:1cf708e2ac57f3aabc87405f04b86354f66799c8e62c28c5fc5f88b5521b2dbf",
                "sha256:24521fa2890642614558b492b473bee0ac1f8057a7263156b02e8b14c88ce6f5",
                "sha256:4fee71aa5bc6ed9d5f116327c04273e25ae31a3020386916905767ec4fc5317e",
                "sha256:70024e02197337533eef7b85b068212420f950319cc8c580261963aefc75f811",
                "sha256:74782fbd4d4f87ff04159e986886931456a1894c61229be9eaf4de6f6e44b99e",
                "sha256:940532b111b1952befd7db542c370887a8611660d2b9becff75d39355303d82d",
                "sha256:cb1f2f5e426dc9f07a7681419fe39cee823bb74f723f36f70399123f439e9b20",
                "sha256:dbbb2379c19ed6042e8f11f2a2c66d39cceb8aeace421bfc29d085d93eda3689",
                "sha256:e3a057b7a64f1222b56e47bcff5e4b94c4f61faac04c7c4ecb1985e18caa3994",
                "sha256:e9f45bd5b92c7974e59bcd2dcc8631a6b6cc380a904725fce7bc08872e691615"
            ],
            "version": "==5.3"
        },
        "requests": {
            "hashes": [
                "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee",
                "sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"
            ],
            "index": "pypi",
            "version": "==2.23.0"
        },
        "requests-oauthlib": {
            "hashes": [
                "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d",
                "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a"
            ],
            "version": "==1.3.0"
        },
        "rfc5424-logging-handler": {
            "hashes": [
                "sha256:9ae14073ef6d76d0c730ad6b6e3aeece841a6d413672d282876c0506dc097257",
                "sha256:eaba528e47fba3e2845d52d559885cbc27a37db42a9d265ea539b3b4452d3057"
            ],
            "version": "==1.4.3"
        },
        "rsa": {
            "hashes": [
                "sha256:14ba45700ff1ec9eeb206a2ce76b32814958a98e372006c8fb76ba820211be66",
                "sha256:1a836406405730121ae9823e19c6e806c62bbad73f890574fff50efa4122c487"
            ],
            "version": "==4.0"
        },
        "ruamel.yaml": {
            "hashes": [
                "sha256:0962fd7999e064c4865f96fb1e23079075f4a2a14849bcdc5cdba53a24f9759b",
                "sha256:099c644a778bf72ffa00524f78dd0b6476bca94a1da344130f4bf3381ce5b954"
            ],
            "version": "==0.16.10"
        },
        "ruamel.yaml.clib": {
            "hashes": [
                "sha256:1e77424825caba5553bbade750cec2277ef130647d685c2b38f68bc03453bac6",
                "sha256:392b7c371312abf27fb549ec2d5e0092f7ef6e6c9f767bfb13e83cb903aca0fd",
                "sha256:4d55386129291b96483edcb93b381470f7cd69f97585829b048a3d758d31210a",
                "sha256:550168c02d8de52ee58c3d8a8193d5a8a9491a5e7b2462d27ac5bf63717574c9",
                "sha256:57933a6986a3036257ad7bf283529e7c19c2810ff24c86f4a0cfeb49d2099919",
                "sha256:615b0396a7fad02d1f9a0dcf9f01202bf9caefee6265198f252c865f4227fcc6",
                "sha256:77556a7aa190be9a2bd83b7ee075d3df5f3c5016d395613671487e79b082d784",
                "sha256:7aee724e1ff424757b5bd8f6c5bbdb033a570b2b4683b17ace4dbe61a99a657b",
                "sha256:8073c8b92b06b572e4057b583c3d01674ceaf32167801fe545a087d7a1e8bf52",
                "sha256:9c6d040d0396c28d3eaaa6cb20152cb3b2f15adf35a0304f4f40a3cf9f1d2448",
                "sha256:a0ff786d2a7dbe55f9544b3f6ebbcc495d7e730df92a08434604f6f470b899c5",
                "sha256:b1b7fcee6aedcdc7e62c3a73f238b3d080c7ba6650cd808bce8d7761ec484070",
                "sha256:b66832ea8077d9b3f6e311c4a53d06273db5dc2db6e8a908550f3c14d67e718c",
                "sha256:be018933c2f4ee7de55e7bd7d0d801b3dfb09d21dad0cce8a97995fd3e44be30",
                "sha256:d0d3ac228c9bbab08134b4004d748cf9f8743504875b3603b3afbb97e3472947",
                "sha256:d10e9dd744cf85c219bf747c75194b624cc7a94f0c80ead624b06bfa9f61d3bc",
                "sha256:ea4362548ee0cbc266949d8a441238d9ad3600ca9910c3fe4e82ee3a50706973",
                "sha256:ed5b3698a2bb241b7f5cbbe277eaa7fe48b07a58784fba4f75224fd066d253ad",
                "sha256:f9dcc1ae73f36e8059589b601e8e4776b9976effd76c21ad6a855a74318efd6e"
            ],
            "markers": "platform_python_implementation == 'CPython' and python_version < '3.9'",
            "version": "==0.2.0"
        },
        "s3transfer": {
            "hashes": [
                "sha256:2482b4259524933a022d59da830f51bd746db62f047d6eb213f2f8855dcb8a13",
                "sha256:921a37e2aefc64145e7b73d50c71bb4f26f46e4c9f414dc648c6245ff92cf7db"
            ],
            "version": "==0.3.3"
        },
        "semantic-version": {
            "hashes": [
                "sha256:352459f640f3db86551d8054d1288608b29a96e880c7746f0a59c92879d412a3",
                "sha256:4eedff095ecdd7790a9e6d7130d49250209e0c7bf6741423c4a4017d9bac4c04"
            ],
            "version": "==2.8.4"
        },
        "sentry-sdk": {
            "extras": [
                "flask"
            ],
            "hashes": [
                "sha256:480eee754e60bcae983787a9a13bc8f155a111aef199afaa4f289d6a76aa622a",
                "sha256:a920387dc3ee252a66679d0afecd34479fb6fc52c2bc20763793ed69e5b0dcc0"
            ],
            "index": "pypi",
            "version": "==0.14.2"
        },
        "six": {
            "hashes": [
                "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a",
                "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"
            ],
            "version": "==1.14.0"
        },
        "sqlalchemy": {
            "hashes": [
                "sha256:c4cca4aed606297afbe90d4306b49ad3a4cd36feb3f87e4bfd655c57fd9ef445"
            ],
            "version": "==1.3.15"
        },
        "sqlalchemy-utils": {
            "hashes": [
                "sha256:4e637c88bf3ac5f99b7d72342092a1f636bea1287b2e3e17d441b0413771f86e"
            ],
            "version": "==0.36.1"
        },
        "swagger-ui-bundle": {
            "hashes": [
                "sha256:49d2e12d60a6499e9d37ea37953b5d700f4e114edc7520fe918bae5eb693a20e",
                "sha256:c5373b683487b1b914dccd23bcd9a3016afa2c2d1cda10f8713c0a9af0f91dd3",
                "sha256:f776811855092c086dbb08216c8810a84accef8c76c796a135caa13645c5cc68"
            ],
            "version": "==0.0.6"
        },
        "thoth-analyzer": {
            "hashes": [
                "sha256:3f830334a3ba725cacf64ccc756e42f0c7946fd8038da6565cb2de569ea5c9c1",
                "sha256:8a29ce615e5feddd301a8c6656132268bede23d4187a5cfb60f790f80cd04dc1"
            ],
            "index": "pypi",
            "version": "==0.1.8"
        },
        "thoth-common": {
            "editable": true,
            "git": "https://github.com/CermakM/common",
            "ref": "develop"
        },
        "thoth-python": {
            "hashes": [
                "sha256:a43ec97d2c1d575505b0f50574cb2cd01c5e8cadd38f707d7761a3ab4e4733e7",
                "sha256:f4422f51a618348285388882e004f7e68d5ce4e482154bd18d074278741e104d"
            ],
            "index": "pypi",
            "version": "==0.9.1"
        },
        "thoth-storages": {
            "hashes": [
                "sha256:009d7a2bb573a761127cb4cfa5b8138d2e23ebee3464d625366104712b49deec",
                "sha256:4f3c46b3cb2db2556582dbe6ee320f845489b781f354695036ab1ce5e4ec9778"
            ],
            "index": "pypi",
            "version": "==0.22.3"
        },
        "threadloop": {
            "hashes": [
                "sha256:5c90dbefab6ffbdba26afb4829d2a9df8275d13ac7dc58dccb0e279992679599",
                "sha256:8b180aac31013de13c2ad5c834819771992d350267bddb854613ae77ef571944"
            ],
            "version": "==1.0.2"
        },
        "thrift": {
            "hashes": [
                "sha256:9af1c86bf73433afc6010ed376a6c6aca2b54099cc0d61895f640870a9ae7d89"
            ],
            "version": "==0.13.0"
        },
        "toml": {
            "hashes": [
                "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c",
                "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"
            ],
            "version": "==0.10.0"
        },
        "tornado": {
            "hashes": [
                "sha256:0662d28b1ca9f67108c7e3b77afabfb9c7e87bde174fbda78186ecedc2499a9d",
                "sha256:4e5158d97583502a7e2739951553cbd88a72076f152b4b11b64b9a10c4c49409",
                "sha256:732e836008c708de2e89a31cb2fa6c0e5a70cb60492bee6f1ea1047500feaf7f",
                "sha256:8154ec22c450df4e06b35f131adc4f2f3a12ec85981a203301d310abf580500f",
                "sha256:8e9d728c4579682e837c92fdd98036bd5cdefa1da2aaf6acf26947e6dd0c01c5",
                "sha256:d4b3e5329f572f055b587efc57d29bd051589fb5a43ec8898c77a47ec2fa2bbb",
                "sha256:e5f2585afccbff22390cddac29849df463b252b711aa2ce7c5f3f342a5b3b444"
            ],
            "version": "==5.1.1"
        },
        "typing-extensions": {
            "hashes": [
                "sha256:091ecc894d5e908ac75209f10d5b4f118fbdb2eb1ede6a63544054bb1edb41f2",
                "sha256:910f4656f54de5993ad9304959ce9bb903f90aadc7c67a0bef07e678014e892d",
                "sha256:cf8b63fedea4d89bab840ecbb93e75578af28f76f66c35889bd7065f5af88575"
            ],
            "markers": "python_version < '3.7'",
            "version": "==3.7.4.1"
        },
        "tzlocal": {
            "hashes": [
                "sha256:11c9f16e0a633b4b60e1eede97d8a46340d042e67b670b290ca526576e039048",
                "sha256:949b9dd5ba4be17190a80c0268167d7e6c92c62b30026cf9764caf3e308e5590"
            ],
            "version": "==2.0.0"
        },
        "urllib3": {
            "hashes": [
                "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc",
                "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc"
            ],
            "markers": "python_version != '3.4'",
            "version": "==1.25.8"
        },
        "voluptuous": {
            "hashes": [
                "sha256:2abc341dbc740c5e2302c7f9b8e2e243194fb4772585b991931cb5b22e9bf456"
            ],
            "version": "==0.11.7"
        },
        "websocket-client": {
            "hashes": [
                "sha256:0fc45c961324d79c781bab301359d5a1b00b13ad1b10415a4780229ef71a5549",
                "sha256:d735b91d6d1692a6a181f2a8c9e0238e5f6373356f561bb9dc4c7af36f452010"
            ],
            "version": "==0.57.0"
        },
        "werkzeug": {
            "hashes": [
                "sha256:169ba8a33788476292d04186ab33b01d6add475033dfc07215e6d219cc077096",
                "sha256:6dc65cf9091cf750012f56f2cad759fa9e879f511b5ff8685e456b4e3bf90d16"
            ],
            "version": "==1.0.0"
        },
        "wirerope": {
            "hashes": [
                "sha256:0ca7c9af15b04b7c21e254d910d658eef908646ae74beb86cc4981b281df2a91"
            ],
            "version": "==0.3.1"
        },
        "wrapt": {
            "hashes": [
                "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"
            ],
            "version": "==1.12.1"
        },
        "yarl": {
            "hashes": [
                "sha256:0c2ab325d33f1b824734b3ef51d4d54a54e0e7a23d13b86974507602334c2cce",
                "sha256:0ca2f395591bbd85ddd50a82eb1fde9c1066fafe888c5c7cc1d810cf03fd3cc6",
                "sha256:2098a4b4b9d75ee352807a95cdf5f10180db903bc5b7270715c6bbe2551f64ce",
                "sha256:25e66e5e2007c7a39541ca13b559cd8ebc2ad8fe00ea94a2aad28a9b1e44e5ae",
                "sha256:26d7c90cb04dee1665282a5d1a998defc1a9e012fdca0f33396f81508f49696d",
                "sha256:308b98b0c8cd1dfef1a0311dc5e38ae8f9b58349226aa0533f15a16717ad702f",
                "sha256:3ce3d4f7c6b69c4e4f0704b32eca8123b9c58ae91af740481aa57d7857b5e41b",
                "sha256:58cd9c469eced558cd81aa3f484b2924e8897049e06889e8ff2510435b7ef74b",
                "sha256:5b10eb0e7f044cf0b035112446b26a3a2946bca9d7d7edb5e54a2ad2f6652abb",
                "sha256:6faa19d3824c21bcbfdfce5171e193c8b4ddafdf0ac3f129ccf0cdfcb083e462",
                "sha256:944494be42fa630134bf907714d40207e646fd5a94423c90d5b514f7b0713fea",
                "sha256:a161de7e50224e8e3de6e184707476b5a989037dcb24292b391a3d66ff158e70",
                "sha256:a4844ebb2be14768f7994f2017f70aca39d658a96c786211be5ddbe1c68794c1",
                "sha256:c2b509ac3d4b988ae8769901c66345425e361d518aecbe4acbfc2567e416626a",
                "sha256:c9959d49a77b0e07559e579f38b2f3711c2b8716b8410b320bf9713013215a1b",
                "sha256:d8cdee92bc930d8b09d8bd2043cedd544d9c8bd7436a77678dd602467a993080",
                "sha256:e15199cdb423316e15f108f51249e44eb156ae5dba232cb73be555324a1d49c2"
            ],
            "version": "==1.4.2"
        },
        "zipp": {
            "hashes": [
                "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b",
                "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96"
            ],
            "version": "==3.1.0"
        }
    },
    "develop": {
        "attrs": {
            "hashes": [
                "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c",
                "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"
            ],
            "index": "pypi",
            "version": "==19.3.0"
        },
        "importlib-metadata": {
            "hashes": [
                "sha256:06f5b3a99029c7134207dd882428a66992a9de2bef7c2b699b5641f9886c3302",
                "sha256:b97607a1a18a5100839aec1dc26a1ea17ee0d93b20b0f008d80a5a050afb200b"
            ],
            "markers": "python_version < '3.8'",
            "version": "==1.5.0"
        },
        "more-itertools": {
            "hashes": [
                "sha256:5dd8bcf33e5f9513ffa06d5ad33d78f31e1931ac9a18f33d37e77a180d393a7c",
                "sha256:b1ddb932186d8a6ac451e1d95844b382f55e12686d51ca0c68b6f61f2ab7a507"
            ],
            "version": "==8.2.0"
        },
        "packaging": {
            "hashes": [
                "sha256:3c292b474fda1671ec57d46d739d072bfd495a4f51ad01a055121d81e952b7a3",
                "sha256:82f77b9bee21c1bafbf35a84905d604d5d1223801d639cf3ed140bd651c08752"
            ],
            "version": "==20.3"
        },
        "pluggy": {
            "hashes": [
                "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0",
                "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"
            ],
            "version": "==0.13.1"
        },
        "py": {
            "hashes": [
                "sha256:5e27081401262157467ad6e7f851b7aa402c5852dbcb3dae06768434de5752aa",
                "sha256:c20fdd83a5dbc0af9efd622bee9a5564e278f6380fffcacc43ba6f43db2813b0"
            ],
            "version": "==1.8.1"
        },
        "pyparsing": {
            "hashes": [
                "sha256:4c830582a84fb022400b85429791bc551f1f4871c33f23e44f353119e92f969f",
                "sha256:c342dccb5250c08d45fd6f8b4a559613ca603b57498511740e65cd11a2e7dcec"
            ],
            "version": "==2.4.6"
        },
        "pytest": {
            "hashes": [
                "sha256:0d5fe9189a148acc3c3eb2ac8e1ac0742cb7618c084f3d228baaec0c254b318d",
                "sha256:ff615c761e25eb25df19edddc0b970302d2a9091fbce0e7213298d85fb61fef6"
            ],
            "index": "pypi",
            "version": "==5.3.5"
        },
        "six": {
            "hashes": [
                "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a",
                "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"
            ],
            "version": "==1.14.0"
        },
        "wcwidth": {
            "hashes": [
                "sha256:8fd29383f539be45b20bd4df0dc29c20ba48654a41e661925e612311e9f3c603",
                "sha256:f28b3e8a6483e5d49e7f8949ac1a78314e740333ae305b4ba5defd3e74fb37a8"
            ],
            "version": "==0.1.8"
        },
        "zipp": {
            "hashes": [
                "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b",
                "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96"
            ],
            "version": "==3.1.0"
        }
    }
}

Respect index configuration stated in Pipfile.lock

Describe the bug

micropipenv passes index configuration in the same order as it is described in the sources section (--index-url and --extra-index-url options). This causes that pip treats these indexes as mirrors and tries the very first one (pypi in the example above). As builds of TensorFlow that we produce have different digest, the installation fails (digest check fails).

---------------------------------- Pipfile.lock ----------------------------------
{
    "_meta": {
        "hash": {
            "sha256": "96f32cab1d060a12ad872a8185fa9c706f668c276e9ec5533751e1fd860a2f84"
        },
        "pipfile-spec": 6,
        "requires": {
            "python_version": "3.6"
        },
        "sources": [
            {
                "name": "pypi-org",
                "url": "https://pypi.org/simple",
                "verify_ssl": true
            },
            {
                "name": "tensorflow-pypi-thoth-station-ninja",
                "url": "https://tensorflow.pypi.thoth-station.ninja/index/manylinux2010/AVX2/simple",
                "verify_ssl": true
            }
        ]
    },
    "default": {
        "tensorflow": {
            "hashes": [
                "sha256:a38c8a5d2cc1dc47605a7ffc88bc0bb2a1829ced58226402dbc3a132930e2bd9"
            ],
            "index": "tensorflow-pypi-thoth-station-ninja",
            "version": "==2.0.0"
        }
    },
    "develop": {}
}
---------------------------------- Pipfile.lock ----------------------------------
Looking in indexes: https://pypi.org/simple, https://tensorflow.pypi.thoth-station.ninja/index/manylinux2010/AVX2/simple
Collecting tensorflow==2.0.0
  Using cached tensorflow-2.0.0-cp36-cp36m-manylinux2010_x86_64.whl (86.3 MB)
ERROR: THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE. If you have updated the package versions, please update the hashes. Otherwise, examine the package contents carefully; someone may have tampered with them.
    tensorflow==2.0.0 from https://files.pythonhosted.org/packages/46/0f/7bd55361168bb32796b360ad15a25de6966c9c1beb58a8e30c01c8279862/tensorflow-2.0.0-cp36-cp36m-manylinux2010_x86_64.whl#sha256=fca6a935bb96f947c28a4bebba7ca1d8b9686fb4c02a06d24b11a2f66ca20b81 (from -r /tmp/requirements.txt9qjucyuq (line 3)):
        Expected sha256 a38c8a5d2cc1dc47605a7ffc88bc0bb2a1829ced58226402dbc3a132930e2bd9
             Got        fca6a935bb96f947c28a4bebba7ca1d8b9686fb4c02a06d24b11a2f66ca20b81

04-05-20 22:44:35 micropipenv  ERROR  Failed to install requirements, dependency 'tensorflow' could not be installed

To Reproduce
Steps to reproduce the behavior:

  1. Create lock file as shown above
  2. Run ```micropipenv install``
  3. Experience the installation error

Expected behavior

micropipenv should respect index configuration

New patch release — v0.5.1

Would it be possible to release the latest enhancenments? They are only around tests so I think that a patch release is enough.

Cannot install micropipenv on Elyra upstream image

Describe the bug
Cannot install micropipenv on Elyra upstream image

To Reproduce

pre-requisite:
podman installed.

Steps to reproduce the behavior:

  1. run podman run -p 8888:8888 elyra/elyra:1.2.1 jupyter lab --debug
  2. launch a terminal in Elyra UI and run pip3 install micropipenv

environment:

:~$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.3 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.3 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

:~$ python
Python 3.7.4 (default, Aug 13 2019, 20:35:49) 
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.

Expected behavior
Installing micropipenv successfully

Screenshots

pip3 install micropipenv
Collecting micropipenv
  Downloading micropipenv-1.0.0.tar.gz (35 kB)
  Installing build dependencies ... error
  ERROR: Command errored out with exit status 1:
   command: /opt/conda/bin/python /opt/conda/lib/python3.7/site-packages/pip install --ignore-installed --no-user --prefix /tmp/pip-build-env-o_zsh3_v/overlay --no-warn-script-location --no-binary :none: --only-binary :none: -i https://pypi.org/simple -- 'setuptools>=40.8.0' wheel
       cwd: None
  Complete output (9 lines):
  Collecting setuptools>=40.8.0
    Using cached setuptools-50.3.2-py3-none-any.whl (785 kB)
  Collecting wheel
    Using cached wheel-0.35.1-py2.py3-none-any.whl (33 kB)
  Installing collected packages: setuptools, wheel
  ERROR: Could not install packages due to an EnvironmentError: [Errno 28] No space left on device: '/tmp/pip-build-env-o_zsh3_v/overlay/bin'
  
  WARNING: You are using pip version 20.2.3; however, version 20.2.4 is available.
  You should consider upgrading via the '/opt/conda/bin/python -m pip install --upgrade pip' command.
  ----------------------------------------
ERROR: Command errored out with exit status 1: /opt/conda/bin/python /opt/conda/lib/python3.7/site-packages/pip install --ignore-installed --no-user --prefix /tmp/pip-build-env-o_zsh3_v/overlay --no-warn-script-location --no-binary :none: --only-binary :none: -i https://pypi.org/simple -- 'setuptools>=40.8.0' wheel Check the logs for full command output.
WARNING: You are using pip version 20.2.3; however, version 20.2.4 is available.
You should consider upgrading via the '/opt/conda/bin/python -m pip install --upgrade pip' command.

Additional context

Revisit setup.py structure

The current setup.py structure expects sources being present during the build process in the current working directory. This is no longer the case for some tooling - see pypa/pipenv#4239 and PEP-517.

We should also consider adding relevant trove classifiers.

test_check_pip_version

While debugging mypy issues on Windows I realized that there is also a problem with test_check_pip_version. This test tests that the pip version is compatible with micropipenv but the question is what it should really test? The problem here is that it runs outside of the virtual environment so it tests compatibility with the latest pip in the main tox virtual environment and not in the one defined as a test environment (20, git, latest, …) - otherwise, it would always fail for versions like "21.2.dev0" which we currently have in -pipgit- environments.

I'd say that the test should be executed in the specific venv via subprocess and the logic should be as follows:

  • if the env variable MICROPIPENV_TEST_PIP_VERSION contains git expect the test to fail
  • otherwise, the test should pass

I'm gonna prepare a PR.

micropipenv should handle issues caused by relative ordering of dependencies

Describe the bug

As reported in thoth-station/s2i-thoth#39 by @4n4nd

micropipenv does not handle the relative ordering of dependencies.

To Reproduce
Steps to reproduce the behavior:

  1. Reach out to thoth-station/s2i-thoth#39
  2. Check build log and installed dependencies
  3. See error

Expected behavior

micropipenv should correctly install the dependencies

Additional context

As the stack supplied is already fully resolved the fix might be pretty simple - instead of issuing one pip installation, we can issue pip install for each package in the stack iteratively with --no-deps flag set (and fallback respecting errors).

Dependency on pip is not declared

setup.py should contain a declaration of dependency on pip. It's possible to install micropipenv to a virtual environment without pip (from source) but then it does not work. install_requires=["pip"] should fix it.

Support for PEP-517/PEP-518

Is your feature request related to a problem? Please describe.

Let's have a look if we want to incorporate PEP-517 and PEP-518 into micropipenv. First, let's discuss if we want to have this extension in s2i and in micropipenv itself. More precisely, the tool could support pyproject.toml for dependency specification and install dependencies based on the specification stated.

Additional context
https://www.python.org/dev/peps/pep-0517/
https://www.python.org/dev/peps/pep-0518/

Add support for pip-tools

Is your feature request related to a problem? Please describe.

Similarly, as for #22, it would be nice to add support for requirements.txt as produced by pip-tools.

Describe the solution you'd like

micropipenv would parse the lock file produced by pip-tools into its internal representation and would do the installation process in the s2i. The reason behind not installing requirements directly is the capability of failovers implemented in micropipenv (#12).

Another reason behind this is standardized standard and error output produced that is suitable for Thoth's analyzers which can parse failures out of build logs (note we install one package at a time which will help a lot in the build-analyzers to detect the package causing installation issues).

Describe alternatives you've considered

Stick with the current approach - install requirements using raw pip. This approach is prone to installation issues that can be introduced due to the relative ordering of Python modules.

Add ability to pass pip specific parameters

Is your feature request related to a problem? Please describe.

When I run micropipenv install, I want to install dependencies to the Python user install directory.

Describe the solution you'd like

Add an ability to pass pip specific options, something like:

micropipenv install - --user

mpe identifies the wrong pyton version

Describe the bug
micropipenv seems to identify the wrong python version:

...
---------------------------------- Pipfile.lock ----------------------------------
Running Python version 3.7, but Pipfile.lock requires Python version 3.6
$ python3 --version
Python 3.6.10
$ which python3
~/Work/thoth-station/user-api/venv/bin/python3
$ micropipenv --version 
0.1.5

To Reproduce
Steps to reproduce the behavior:

  1. virtualenv -p python3.6 -v ./venv
  2. source ./venv/bin/activate
  3. pip install micropipenv
  4. git clone user-api && cd user-api
  5. micropipenv install --deploy

Expected behavior
it should be aware it is python3.6

Improve messages logged during the installation process

Is your feature request related to a problem? Please describe.

When using micropipenv as a library together with other tools, such as thamos, the printed log is not nice:

2020-11-05 21:46:36,945 [2074338] INFO     micropipenv: Installing 'grpcio==1.31.0 \\\n    --hash=sha256:5043440c45c0a031f387e7f48527541c65d672005fb24cf18ef6857483557d39 \\\n    --hash=sha256:0fa86ac4452602c79774783aa68979a1a7625ebb7eaabee2b6550b975b9d61e6 \\\n    --hash=sha256:8002a89ea91c0078c15d3c0daf423fd4968946be78f08545e807ea9a5ff8054a \\\n    --hash=sha256:8b42f0ac76be07a5fa31117a3388d754ad35ef05e2e34be185ca9ccbcfac2069 \\\n    --hash=sha256:64077e3a9a7cf2f59e6c76d503c8de1f18a76428f41a5b000dc53c48a0b772ff \\\n    --hash=sha256:a9a7ae74cb3108e6457cf15532d4c300324b48fbcf3ef290bcd2835745f20510 \\\n    --hash=sha256:63ee8e02d04272c3d103f44b4bce5d43ea757dd288673cea212d2f7da27967d2 \\\n    --hash=sha256:344b50865914cc8e6d023457bffee9a640abb18f75d0f2bb519041961c748da9 \\\n    --hash=sha256:bf00ab06ea4f89976288f4d6224d4aa120780e30c955d4f85c3214ada29b3ddf \\\n    --hash=sha256:43d44548ad6ee738b941abd9f09e3b83a5c13f3e1410321023c3c148ba50e796 \\\n    --hash=sha256:5d7faa89992e015d245750ca9ac916c161bbf72777b2c60abc61da3fae41339e \\\n    --hash=sha256:e64bddd09842ef508d72ca354319b0eb126205d951e8ac3128fe9869bd563552 \\\n    --hash=sha256:3c2aa6d7a5e5bf73fdb1715eee777efe06dd39df03383f1cc095b2fdb34883e6 \\\n    --hash=sha256:7a11b1ebb3210f34913b8be6995936bf9ebc541a65ab69e75db5ce1fe5047e8f \\\n    --hash=sha256:220c46b1fc9c9a6fcca4caac398f08f0ed43cdd63c45b7458983c4a1575ef6df \\\n    --hash=sha256:074871a184483d5cd0746fd01e7d214d3ee9d36e67e32a5786b0a21f29fb8304 \\\n    --hash=sha256:f5b0870b733bcb7b6bf05a02035e7aaf20f599d3802b390282d4c2309f825f1d \\\n    --hash=sha256:bf39977282a79dc1b2765cc3402c0ada571c29a491caec6ed12c0993c1ec115e \\\n    --hash=sha256:8ca26b489b5dc1e3d31807d329c23d6cb06fe40fbae25b0649b718947936e26a \\\n    --hash=sha256:259240aab2603891553e17ad5b2655693df79e02a9b887ff605bdeb2fcd3dcc9 \\\n    --hash=sha256:0397616355760cd8282ed5ea34d51830ae4cb6613b7e5f66bed3be5d041b8b9a \\\n    --hash=sha256:c22b19abba63562a5a200e586b5bde39d26c8ec30c92e26d209d81182371693b \\\n    --hash=sha256:08a9b648dbe8852ff94b73a1c96da126834c3057ba2301d13e8c4adff334c482 \\\n    --hash=sha256:ef9fce98b6fe03874c2a6576b02aec1a0df25742cd67d1d7b75a49e30aa74225 \\\n    --hash=sha256:f04c59d186af3157dc8811114130aaeae92e90a65283733f41de94eed484e1f7 \\\n    --hash=sha256:739a72abffbd36083ff7adbb862cf1afc1e311c35834bed9c0361d8e68b063e1 \\\n    --hash=sha256:75e383053dccb610590aa53eed5278db5c09bf498d3b5105ce6c776478f59352 \\\n    --hash=sha256:baaa036540d7ace433bdf38a3fe5e41cf9f84cdf10a88bac805f678a7ca8ddcc \\\n    --hash=sha256:c9016ab1eaf4e054099303287195f3746bd4e69f2631d040f9dca43e910a5408 \\\n    --hash=sha256:d2c5e05c257859febd03f5d81b5015e1946d6bcf475c7bf63ee99cea8ab0d590 \\\n    --hash=sha256:013287f99c99b201aa8a5f6bc7918f616739b9be031db132d9e3b8453e95e151 \\\n    --hash=sha256:ba3e43cb984399064ffaa3c0997576e46a1e268f9da05f97cd9b272f0b59ee71 \\\n    --hash=sha256:ea849210e7362559f326cbe603d5b8d8bb1e556e86a7393b5a8847057de5b084 \\\n    --hash=sha256:92e54ab65e782f227e751c7555918afaba8d1229601687e89b80c2b65d2f6642 \\\n    --hash=sha256:292635f05b6ce33f87116951d0b3d8d330bdfc5cac74f739370d60981e8c256c \\\n    --hash=sha256:ebb2ca09fa17537e35508a29dcb05575d4d9401138a68e83d1c605d65e8a1770 \\\n    --hash=sha256:58d7121f48cb94535a4cedcce32921d0d0a78563c7372a143dedeec196d1c637 \\\n    --hash=sha256:5fb0923b16590bac338e92d98c7d8effb3cfad1d2e18c71bf86bde32c49cd6dd \\\n    --hash=sha256:e8c3264b0fd728aadf3f0324471843f65bd3b38872bdab2a477e31ffb685dd5b\n'

Describe the solution you'd like

Make installation logs prettier.

Consider renaming this tool

Is your feature request related to a problem? Please describe.

Pipenv is gaining bad name in the community. Also, considering the fact this tool can be a "compatibility layer" for installing Python packages in Python s2i, it could be a good idea to rename this tool.

Any comments/suggestions welcome :)

File traversal and method selection

Because my /tmp is full of garbage, I've probably found a bug during the final testing before the next release.

The "problem" is a way we detect which method of installation use which is based on:

micropipenv/micropipenv.py

Lines 730 to 749 in 0bdce8b

if method is None:
try:
_traverse_up_find_file("Pipfile.lock")
method = "pipenv"
except FileNotFound as exc:
try:
_LOGGER.info("Failed to find Pipfile.lock, looking up poetry.lock: %s", str(exc))
_traverse_up_find_file("poetry.lock")
method = "poetry"
except FileNotFound as exc:
try:
_LOGGER.info("Failed to find Poetry lock file, looking up requirements.txt: %s", str(exc))
_traverse_up_find_file("requirements.txt")
method = "requirements"
except FileNotFound as exc:
raise FileNotFound(
"Failed to find Pipfile.lock, poetry.lock or requirements.txt "
"in the current directory or any of its parent: {}".format(os.getcwd())
) from exc

This implementation means that if I have a project with poetry.lock in /home/user/projects/application/ and Pipfile.lock in /home/, the detected method will be always pipenv because the Pipfile.lock search is done first and it's found no matter how far it is.

In my humble opinion, poetry.lock in /home/user/projects/application/ should take precedence.

This seems to be a problem only in the install function because all other usages (like in read_* functions) are looking for specific files based on the method detected in install.

Given the fact that the path to the right file might be as long as CWD or shorter, I'd try to get paths to all possible files and use the one with the longest path. What do you think about it? I can prepare a PR if you agree with the described solution.

pytest-mypy and Python 3.8

I'd like to discuss this change: #59

The problem seems to be caused by the differences between Pipfile.lock when the file is generated by different versions of Python. When you do pipenv lock with Python 3.7, you get:

        "mypy": {
            "hashes": [
…
            ],
            "markers": "python_version >= '3.5' and python_version < '3.8'",
            "version": "==0.770"

which looks like mypy is not Python 3.8 compatible, but when you do the same with Python 3.8, you get the same version and different markers:

        "mypy": {
            "hashes": [
…
            ],
            "markers": "python_version >= '3.8'",
            "version": "==0.770"

This is caused by this line in the pytest-mypy setup.py.

Pipenv general recommendations says that if you target more than one Python version, which I believe micropipenv does, the Pipfile.lock file should not be included in VCS.

What do you think about it? Does this project need Pipfile at all? Given the fact that runtime dependencies are specified in setup.py and development dependencies in tox.ini.

Add support for raw pip files

Is your feature request related to a problem? Please describe.

As micropipenv can act as a compatibility layer for installing Python packages into Python s2i, it could be nice to also add support for requirements.txt where the lock is not produced/compatible with pip-tools.

Describe the solution you'd like

micropipenv can detect requirements.txt and parse it into its internal representation similarly as for #23. It detects the file is not a lock file as produced by pip-tools and prints warning to user that the application stack is not locked. It installs all the dependencies (the --no-deps flag cannot be used, the resolution is left on pip) and prints packages that were installed so that Python s2i users can detect what packages are present in the application stack based on build-logs. This message can be subsequently automatically parsed on Thoth's side in build-analyzers.

Describe alternatives you've considered

Keep the installation process in Python s2i as is. This process lacks features described above.

[SPIKE] Make micropipenv an alternative to Pipenv

Is your feature request related to a problem? Please describe.

See upstream discussions as this one pypa/pipenv#2873 (still active comments in 2020). Pipenv seems to be slow in some cases and inaccurate (see for example thoth-station/adviser#1613).

Describe the solution you'd like

I was wondering how expensive and complicated it would be to make micropipenv an alternative to Pipenv. We could take a look at pip's new resolver (available in pip>=20.3) and see if the interface is easy to reuse to create a lightweight alternative to Pipenv.

Describe alternatives you've considered

Use Pipenv.

Additional context

This is solely a spike and just heads up on this topic. I'm not sure now how complicated the change would be and if we could seamlessly reuse the new pip's resolver.

Are we ready for 1.0.0 release?

Is your feature request related to a problem? Please describe.

It looks like the codebase got stabilized, micropipenv was triggered a few hundred times during container builds. From a feature point of view, it looks like the tool does its job and, as of now, we don't plan to add any additional functionality.

Are we ready for a 1.0.0 release? Do we want it? Or should we stick with 0ver?

Confusing licensing

Describe the bug
I don't understand the licencing of micrpipenv. Is it LGPL or GPL?

See also #71

To Reproduce
Steps to reproduce the behavior:

  1. Try to figure out the license of micropipenv

Expected behavior
The license should be easily discoverbale trough the classifier, license tag, LICENSE file and the header comment.

Screenshots
_

Additional context
No context.

Testing against all supported Pythons

Hello.

From my point of view, it'd be very nice to have all supported Pythons in CI. In Python world, tools like tox are defacto standard to create a matrix of all supported Python with all supported dependencies. It'll make it also possible to test micropipenv against development version of Python and discover incompatibilities soon.

I know that the CI is already configured here but I don't understand its configuration and therefore I'd like to hear your opinions before I dive into implementation.

What do you think about it?

pip releases monitoring

Is there any way to monitor pip releases? I mean, it would be nice if every pip release would create a new issue in this repository so we won't forget to update micropipenv and run all tests with the latest pip.

I've tried to find some kind of automation or IFTTT service but found nothing.

Hardcoded pip compatibility test

I'm glad we are testing micropipenv with the latest versions of pip but I have mixed feelings about hardcoded pip version in the code and the warning it produces if the pip version is different.

If I understand it correctly, the last two releases were released just to say that the micropipenv is compatible with two new releases of pip.

With my package maintainer hat on, I am not sure this approach is sustainable. Right now, I am in the situation when it does not make sense to spend my time updating micropipenv in Fedora because F33 already has version 0.5.1 and since then only non-user-facing changes were made. But if we update pip in Fedora, micropipenv will start showing the warning. The situation might be even worse for RHEL.

What if we show the warning only when something wrong happens? Something like:

if __name__ == "__main__":
    logging.basicConfig(format="%(asctime)s %(name)-12s %(levelname)-6s %(message)s", datefmt="%m-%d-%y %H:%M:%S")
    try:
        return_code = main()
    except Exception:
        _check_pip_version(raise_on_incompatible=False)
        raise
    else:
        sys.exit(return_code)

Something like this solves only one half of the problem but it might provide enough information for a user using micropipenv in an environment where they have control of the pip and do not disturb users when nothing wrong happens.

What do you think about it?

Local installed packages

Hello.

Is there a plan to support locally installed packages? I mean a situation when I have something like this in Pipfile.lock:

"e1839a8": {
    "editable": true,
    "path": "."
},

Currently, it's not recognized and micropipenv tries to install package e1839a8 from PyPI.

Groups support in Poetry lock files

Is your feature request related to a problem? Please describe.

Poetry introduced dependency groups feature that will need few adjustments in the source code to work properly:

https://python-poetry.org/blog/announcing-poetry-1.2.0a2/#dependency-groups

See also A note about the dev-dependencies section part for dev-dependencies handling. It might be also needed to rethink how we integrate with dependency groups when mapping internally to Pipfile.lock (we will probably not support them, but dev group can be mapped to dev-dependencies implicitly).

Enable package installation from file

Is your feature request related to a problem? Please describe.
As some packages are not available as PyPI packages, it would be great to have a feature to install them from file directly.
Faced a similar issue while installing spacy packages.

[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[packages]
spacy = ">=2.3.0,<2.4.0"
en-core-web-sm = {file = "https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-2.3.0/en_core_web_sm-2.3.0.tar.gz"}
numpy = "*"

[requires]
python_version = "3.6" 

Describe the solution you'd like
A package can be installed from a file via pipenv , would like to have a feature to install via micropipenv.
I don't have clear solution for this.

Describe alternatives you've considered
None

Additional context
when tried to install the package in pipfile through micropipenv, this is the error response.

ERROR: Could not find a version that satisfies the requirement en-core-web-sm==2.3.0 (from -r /tmp/requirements.txtkjlus15h (line 2)) (from versions: none)
ERROR: No matching distribution found for en-core-web-sm==2.3.0 (from -r /tmp/requirements.txtkjlus15h (line 2))
Failed to install requirements, dependency 'en-core-web-sm' could not be installed
subprocess exited with status 3
subprocess exited with status 3
error building at STEP "RUN /opt/app-root/builder/assemble": exit status 3

Github vs PyPI

Hi.

The information on Github and PyPI is slightly out of sync:

  • The latest release on PyPI is 0.1.1 but on Github, it's 0.1.0
  • The tarball on PyPI does not contain tests folder (not a problem) and LICENSE (should be there)

I've tried to use both as a source for RPM package but neither is perfect so one of them has to be fixed before I continue.

CI clean up

Could we please decide which parts of micropipenv's CI to remove or fix? I mean, It's kinda misleading to contributors when a PR is merged even when a big portion of tests is red or unfinished.

  • Thoth: Advise (Developer Preview) - does not work because we removed its config file
  • thoth-ci/* - fail on condition-check-deploy-comment-check and are not able to run tox/pytest tests.
  • tide - what this is supposed to do?

I'd say that the codebase is tested on Travis but others might also implement some important checks and if they do, we should fix them.

Wrong package name in lock file results package not being installed - doesn't match pipenv behavior

Describe the bug
When package name in [packages] list doesn't match the name in its setup.py, micropipenv fails to install. This is inconsistent with pipenv.

To Reproduce

Prerequisites below. Try to install https://github.com/jundongl/scikit-feature as scikit-feature while it's setup.py states the name to be skfeatures.

$ cat Pipfile
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
scikit-feature = {git = "https://github.com/jundongl/scikit-feature.git", ref="48cffad4e88ff4b9d2f1c7baffb314d1b3303792"}

[dev-packages]

[requires]
python_version = "3.8"

$ cat Pipfile.lock
{
    "_meta": {
        "hash": {
            "sha256": "7c193a43cd064e999632361e52546519a15ad945a68ff6758f3825966be825b3"
        },
        "pipfile-spec": 6,
        "requires": {
            "python_version": "3.8"
        },
        "sources": [
            {
                "name": "pypi",
                "url": "https://pypi.org/simple",
                "verify_ssl": true
            }
        ]
    },
    "default": {
        "scikit-feature": {
            "git": "https://github.com/jundongl/scikit-feature.git",
            "ref": "48cffad4e88ff4b9d2f1c7baffb314d1b3303792"
        }
    },
    "develop": {}
}

Pipenv behavior

$ pipenv install
Installing dependencies from Pipfile.lock (e825b3)...
  🐍   ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 1/1 — 00:00:49
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.

$ pipenv run python -c "import skfeature; print('success')"
success

Micropipenv behavior

$ micropipenv install
---------------------------------- Pipfile.lock ----------------------------------
{
    "_meta": {
        "hash": {
            "sha256": "7c193a43cd064e999632361e52546519a15ad945a68ff6758f3825966be825b3"
        },
        "pipfile-spec": 6,
        "requires": {
            "python_version": "3.8"
        },
        "sources": [
            {
                "name": "pypi",
                "url": "https://pypi.org/simple",
                "verify_ssl": true
            }
        ]
    },
    "default": {
        "scikit-feature": {
            "git": "https://github.com/jundongl/scikit-feature.git",
            "ref": "48cffad4e88ff4b9d2f1c7baffb314d1b3303792"
        }
    },
    "develop": {}
}
---------------------------------- Pipfile.lock ----------------------------------
!!! Requirement scikit-feature uses a VCS version: {'git': 'https://github.com/jundongl/scikit-feature.git', 'ref': '48cffad4e88ff4b9d2f1c7baffb314d1b3303792'}
Collecting scikit-feature
  Cloning https://github.com/jundongl/scikit-feature.git (to revision 48cffad4e88ff4b9d2f1c7baffb314d1b3303792) to /tmp/pip-install-kmmnezoz/scikit-feature_00cf727f42244e9897ce2dfcc6f254c5
  WARNING: Generating metadata for package scikit-feature produced metadata for project name skfeature. Fix your #egg=scikit-feature fragments.
ERROR: Requested skfeature from git+https://github.com/jundongl/scikit-feature.git@48cffad4e88ff4b9d2f1c7baffb314d1b3303792#egg=scikit-feature (from -r /tmp/requirements_micropipenv-ofk7pdts.txt (line 2)) has different name in metadata: 'skfeature'
Failed to install requirements, dependency 'scikit-feature' could not be installed

$ pipenv run python -c "import skfeature;print('success')"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'skfeature'

Expected behavior
The behavior should be consistent

Additional context
This behavior changed in micropipenv fairly recently as it seems from https://github.com/aicoe-aiops/ocp4-anomaly-detection-internal/pull/71

Python2 support

Is your feature request related to a problem? Please describe.

In order to use this tool in Python s2i, it would be nice to also support EOL Python2.

TODO

  • make micropipenv compatible with Python2
  • create testsuite for running micropipenv in Python2/Python3 possibly in different versions (tox?)

Related discussion

sclorg/s2i-python-container#367

Incompatibilities with the latest pip

Describe the bug
It seems that pip._internal.req has been changed heavily and therefore _requirements2pipfile_lock has to be adjusted.

I've tried to fix it but I don't understand all the attributes it needs from requirements.

To Reproduce
Steps to reproduce the behavior:

  1. Run tests with the latest pip (20.1.1)

It's probably not the best idea to depend on pip internal modules (I have some experience from other packages). Is bundling the functionality micropipenv needs an option? I am against bundling but it might be a candidate for an exception here if micropipenv does not need the whole pip.

Add support for Poetry

Is your feature request related to a problem? Please describe.

It would be nice to also support Poetry's lockfile as an input for this tool. This way micropipenv can act as a lightweight compatibility layer for installing Python packages in s2i.

Describe the solution you'd like

micropipenv automatically detects (or is forced to use) Poetry's lock file. It parses it to micropipenv's internal representation (as done for Pipfile.lock) and can install stack as described in micropipenv's lock file.

Make tests work in offline environment without pytest-venv

It would be nice to have a simple way to skip all the tests that require an internet connection (not available in the RPM build process) and make them work without pytest-venv which is not available in Fedora/RHEL.

The second enhancement is kinda questionable because I can simply package it for Fedora but I think that there are no many tests requiring pytest-venv and not requiring internet connection so there is no real benefit in having pytest-venv and skipping it because of the internet.

In other words, let's skip online tests first and see how many of the rest needs the venv fixture.

Testing with various versions of pip

It seems that right now we have only one version of pip in our testing dependencies and moreover this version is not locked. If I am not wrong, the version of pip we are using in tests is the one which virtualenv bundles and it's therefore available in pytest-venv fixture where our test run. Right?

IMHO, this has to be extended if we want to keep backward compatibility and test micropipenv with the latest pip before it's bundled in virtualenv.

What do you think about it? I can try to prepare something. A solution also has to be optional so the tests won't require internet.

Windows in the CI

As it was uncovered to me in #162 , micropipenv has some users on Windows so it might be a good idea to add Windows to our CI.

The configuration is pretty simple - WIP in https://github.com/frenzymadness/micropipenv/tree/windows_ci - the only remaining thing is to find a way how to run different Python versions in parallel.

But it seems that the pytest-venv is not compatible with Windows. It should be easy to fix but I have to find a Windows machine to work on or somebody who can do it for us.

toml modules in tests

@pytest.mark.online
def test_install_pipenv(venv):
"""Test invoking installation using information in Pipfile.lock."""
cmd = [os.path.join(venv.path, "bin", "python3"), micropipenv.__file__, "install", "--method", "pipenv"]
with cwd(os.path.join(_DATA_DIR, "install", "pipenv")):
subprocess.run(cmd, check=True, env={"MICROPIPENV_PIP_BIN": get_pip_path(venv), "MICROPIPENV_DEBUG": "1"})
assert str(venv.get_version("daiquiri")) == "2.0.0"
assert str(venv.get_version("python-json-logger")) == "0.1.11"

Hello. I'm probably just blind but how the test mentioned above can work when it runs micropipenv in a virtual environment and reads Pipfile without toml or pytoml modules installed in the virtual environment.

I've realized that many tests of pipenv and poetry functionalities need toml but only a limited subset has it installed manually in the venv.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.