A set of tools to keep your pinned Python dependencies fresh.

Overview

Jazzband PyPI version Supported Python versions GitHub Actions build status Coverage

pip-tools = pip-compile + pip-sync

A set of command line tools to help you keep your pip-based packages fresh, even when you've pinned them. You do pin them, right? (In building your Python application and its dependencies for production, you want to make sure that your builds are predictable and deterministic.)

pip-tools overview for phase II

Installation

Similar to pip, pip-tools must be installed in each of your project's virtual environments:

$ source /path/to/venv/bin/activate
(venv)$ python -m pip install pip-tools

Note: all of the remaining example commands assume you've activated your project's virtual environment.

Example usage for pip-compile

The pip-compile command lets you compile a requirements.txt file from your dependencies, specified in either setup.py or requirements.in.

Run it with pip-compile or python -m piptools compile. If you use multiple Python versions, you can run pip-compile as py -X.Y -m piptools compile on Windows and pythonX.Y -m piptools compile on other systems.

pip-compile should be run from the same virtual environment as your project so conditional dependencies that require a specific Python version, or other environment markers, resolve relative to your project's environment.

Note: ensure you don't have requirements.txt if you compile setup.py or requirements.in from scratch, otherwise, it might interfere.

Requirements from setup.py

Suppose you have a Django project, and want to pin it for production. If you have a setup.py with install_requires=['django'], then run pip-compile without any arguments:

$ pip-compile
#
# This file is autogenerated by pip-compile
# To update, run:
#
#    pip-compile
#
asgiref==3.2.3
    # via django
django==3.0.3
    # via my_django_project (setup.py)
pytz==2019.3
    # via django
sqlparse==0.3.0
    # via django

pip-compile will produce your requirements.txt, with all the Django dependencies (and all underlying dependencies) pinned.

Without setup.py

If you don't use setup.py (it's easy to write one), you can create a requirements.in file to declare the Django dependency:

# requirements.in
django

Now, run pip-compile requirements.in:

$ pip-compile requirements.in
#
# This file is autogenerated by pip-compile
# To update, run:
#
#    pip-compile requirements.in
#
asgiref==3.2.3
    # via django
django==3.0.3
    # via -r requirements.in
pytz==2019.3
    # via django
sqlparse==0.3.0
    # via django

And it will produce your requirements.txt, with all the Django dependencies (and all underlying dependencies) pinned.

Using hashes

If you would like to use Hash-Checking Mode available in pip since version 8.0, pip-compile offers --generate-hashes flag:

$ pip-compile --generate-hashes requirements.in
#
# This file is autogenerated by pip-compile
# To update, run:
#
#    pip-compile --generate-hashes requirements.in
#
asgiref==3.2.3 \
    --hash=sha256:7e06d934a7718bf3975acbf87780ba678957b87c7adc056f13b6215d610695a0 \
    --hash=sha256:ea448f92fc35a0ef4b1508f53a04c4670255a3f33d22a81c8fc9c872036adbe5 \
    # via django
django==3.0.3 \
    --hash=sha256:2f1ba1db8648484dd5c238fb62504777b7ad090c81c5f1fd8d5eb5ec21b5f283 \
    --hash=sha256:c91c91a7ad6ef67a874a4f76f58ba534f9208412692a840e1d125eb5c279cb0a \
    # via -r requirements.in
pytz==2019.3 \
    --hash=sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d \
    --hash=sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be \
    # via django
sqlparse==0.3.0 \
    --hash=sha256:40afe6b8d4b1117e7dff5504d7a8ce07d9a1b15aeeade8a2d10f130a834f8177 \
    --hash=sha256:7c3dca29c022744e95b547e867cee89f4fce4373f3549ccd8797d8eb52cdb873 \
    # via django

Updating requirements

To update all packages, periodically re-run pip-compile --upgrade.

To update a specific package to the latest or a specific version use the --upgrade-package or -P flag:

# only update the django package
$ pip-compile --upgrade-package django

# update both the django and requests packages
$ pip-compile --upgrade-package django --upgrade-package requests

# update the django package to the latest, and requests to v2.0.0
$ pip-compile --upgrade-package django --upgrade-package requests==2.0.0

You can combine --upgrade and --upgrade-package in one command, to provide constraints on the allowed upgrades. For example to upgrade all packages whilst constraining requests to the latest version less than 3.0:

$ pip-compile --upgrade --upgrade-package 'requests<3.0'

Output File

To output the pinned requirements in a filename other than requirements.txt, use --output-file. This might be useful for compiling multiple files, for example with different constraints on django to test a library with both versions using tox:

$ pip-compile --upgrade-package 'django<1.0' --output-file requirements-django0x.txt
$ pip-compile --upgrade-package 'django<2.0' --output-file requirements-django1x.txt

Or to output to standard output, use --output-file=-:

$ pip-compile --output-file=- > requirements.txt
$ pip-compile - --output-file=- < requirements.in > requirements.txt

Forwarding options to pip

Any valid pip flags or arguments may be passed on with pip-compile's --pip-args option, e.g.

$ pip-compile requirements.in --pip-args '--retries 10 --timeout 30'

Configuration

You might be wrapping the pip-compile command in another script. To avoid confusing consumers of your custom script you can override the update command generated at the top of requirements files by setting the CUSTOM_COMPILE_COMMAND environment variable.

$ CUSTOM_COMPILE_COMMAND="./pipcompilewrapper" pip-compile requirements.in
#
# This file is autogenerated by pip-compile
# To update, run:
#
#    ./pipcompilewrapper
#
asgiref==3.2.3
    # via django
django==3.0.3
    # via -r requirements.in
pytz==2019.3
    # via django
sqlparse==0.3.0
    # via django

Workflow for layered requirements

If you have different environments that you need to install different but compatible packages for, then you can create layered requirements files and use one layer to constrain the other.

For example, if you have a Django project where you want the newest 2.1 release in production and when developing you want to use the Django debug toolbar, then you can create two *.in files, one for each layer:

# requirements.in
django<2.2

At the top of the development requirements dev-requirements.in you use -c requirements.txt to constrain the dev requirements to packages already selected for production in requirements.txt.

# dev-requirements.in
-c requirements.txt
django-debug-toolbar

First, compile requirements.txt as usual:

$ pip-compile
#
# This file is autogenerated by pip-compile
# To update, run:
#
#    pip-compile
#
django==2.1.15
    # via -r requirements.in
pytz==2019.3
    # via django

Now compile the dev requirements and the requirements.txt file is used as a constraint:

$ pip-compile dev-requirements.in
#
# This file is autogenerated by pip-compile
# To update, run:
#
#    pip-compile dev-requirements.in
#
django-debug-toolbar==2.2
    # via -r dev-requirements.in
django==2.1.15
    # via
    #   -c requirements.txt
    #   django-debug-toolbar
pytz==2019.3
    # via
    #   -c requirements.txt
    #   django
sqlparse==0.3.0
    # via django-debug-toolbar

As you can see above, even though a 2.2 release of Django is available, the dev requirements only include a 2.1 version of Django because they were constrained. Now both compiled requirements files can be installed safely in the dev environment.

To install requirements in production stage use:

$ pip-sync

You can install requirements in development stage by:

$ pip-sync requirements.txt dev-requirements.txt

Version control integration

You might use pip-compile as a hook for the pre-commit. See pre-commit docs for instructions. Sample .pre-commit-config.yaml:

repos:
  - repo: https://github.com/jazzband/pip-tools
    rev: 5.0.0
    hooks:
      - id: pip-compile

You might want to customize pip-compile args by configuring args and/or files, for example:

repos:
  - repo: https://github.com/jazzband/pip-tools
    rev: 5.0.0
    hooks:
      - id: pip-compile
        files: ^requirements/production\.(in|txt)$
        args: [--index-url=https://example.com, requirements/production.in]

Example usage for pip-sync

Now that you have a requirements.txt, you can use pip-sync to update your virtual environment to reflect exactly what's in there. This will install/upgrade/uninstall everything necessary to match the requirements.txt contents.

Run it with pip-sync or python -m piptools sync. If you use multiple Python versions, you can also run py -X.Y -m piptools sync on Windows and pythonX.Y -m piptools sync on other systems.

pip-sync must be installed into and run from the same virtual environment as your project to identify which packages to install or upgrade.

Be careful: pip-sync is meant to be used only with a requirements.txt generated by pip-compile.

$ pip-sync
Uninstalling flake8-2.4.1:
  Successfully uninstalled flake8-2.4.1
Collecting click==4.1
  Downloading click-4.1-py2.py3-none-any.whl (62kB)
    100% |................................| 65kB 1.8MB/s
  Found existing installation: click 4.0
    Uninstalling click-4.0:
      Successfully uninstalled click-4.0
Successfully installed click-4.1

To sync multiple *.txt dependency lists, just pass them in via command line arguments, e.g.

$ pip-sync dev-requirements.txt requirements.txt

Passing in empty arguments would cause it to default to requirements.txt.

Any valid pip install flags or arguments may be passed with pip-sync's --pip-args option, e.g.

$ pip-sync requirements.txt --pip-args '--no-cache-dir --no-deps'

If you use multiple Python versions, you can run pip-sync as py -X.Y -m piptools sync ... on Windows and pythonX.Y -m piptools sync ... on other systems.

Note: pip-sync will not upgrade or uninstall packaging tools like setuptools, pip, or pip-tools itself. Use python -m pip install --upgrade to upgrade those packages.

Should I commit requirements.in and requirements.txt to source control?

Generally, yes. If you want a reproducible environment installation available from your source control, then yes, you should commit both requirements.in and requirements.txt to source control.

Note that if you are deploying on multiple Python environments (read the section below), then you must commit a seperate output file for each Python environment. We suggest to use the {env}-requirements.txt format (ex: win32-py3.7-requirements.txt, macos-py3.6-requirements.txt, etc.).

Cross-environment usage of requirements.in/requirements.txt and pip-compile

The dependencies of a package can change depending on the Python environment in which it is installed. Here, we define a Python environment as the combination of Operating System, Python version (3.6, 3.7, etc.), and Python implementation (CPython, PyPy, etc.). For an exact definition, refer to the possible combinations of PEP 508 environment markers.

As the resulting requirements.txt can differ for each environment, users must execute pip-compile on each Python environment separately to generate a requirements.txt valid for each said environment. The same requirements.in can be used as the source file for all environments, using PEP 508 environment markers as needed, the same way it would be done for regular pip cross-environment usage.

If the generated requirements.txt remains exactly the same for all Python environments, then it can be used across Python environments safely. But users should be careful as any package update can introduce environment-dependant dependencies, making any newly generated requirements.txt environment-dependant too. As a general rule, it's advised that users should still always execute pip-compile on each targeted Python environment to avoid issues.

Other useful tools

Deprecations

This section lists pip-tools features that are currently deprecated.

  • --index/--no-index command-line options, use instead --emit-index-url/--no-emit-index-url (since 5.2.0).
  • In future versions, the --allow-unsafe behavior will be enabled by default. Use --no-allow-unsafe to keep the old behavior. It is recommended to pass the --allow-unsafe now to adapt to the upcoming change.

Versions and compatibility

The table below summarizes the latest pip-tools versions with the required pip and Python versions. Generally, pip-tools supports the same Python versions as the required pip versions.

pip-tools pip Python
4.5.* 8.1.3 - 20.0.2 2.7, 3.5 - 3.8
5.0.0 - 5.3.0 20.0 - 20.1.1 2.7, 3.5 - 3.8
5.4.0 20.1 - 20.3.* 2.7, 3.5 - 3.8
5.5.0 20.1 - 20.3.* 2.7, 3.5 - 3.9
6.0.0 20.1 - 20.3.* 3.6 - 3.9
Issues
  • Annotate primary requirements and VCS dependencies

    Annotate primary requirements and VCS dependencies

    Resolves #881 Resolves #293

    This change brings annotations to primary requirements in the compilation output.

    The annotation may be merely a reqs-in source:

    django-debug-toolbar==2.2  # via -r requirements.in (line 2)
    

    or it may additionally include reverse dependencies:

    django==3.0.3             # via -r requirements.in (line 1), django-debug-toolbar
    

    Existing tests are modified to either adjust their expectations, or compile with --no-annotations if annotations are irrelevant. Two tests have been inverted and renamed:

    -test_format_requirement_not_for_primary
    +test_format_requirement_for_primary
    -test_format_requirement_not_for_primary_lower_case
    +test_format_requirement_for_primary_lower_case
    

    Changelog-friendly one-liner: Primary requirements and VCS dependencies now get annotated with any source .in files and reverse dependencies

    Contributor checklist
    • [x] Provided the tests for the changes.
    • [x] Gave a clear one-line description in the PR (that the maintainers can add to CHANGELOG.md on release).
    • [x] Assign the PR to an existing or new milestone for the target version (following Semantic Versioning).

    Please review these changes with the following questions in mind:

    1. Is the new annotation string as desired?
    2. Is it desirable to add an option to disable this new behavior?
    3. Should the non-annotation-focused tests needing modification be, generally, expecting an exact annotation? Or should we simply use --no-annotate?
    4. In which cases might an InstallRequirement's comes_from attribute be a str, or an InstallRequirement? The following alternatives seem to result in the same output. Which is saner or preferred, or handles potential edge cases better?
     required_by |= {
         src_ireq.comes_from
    -    for src_ireq in ireq._source_ireqs
         if isinstance(src_ireq.comes_from, str)
    +    else src_ireq.comes_from.name.lower()
    +    for src_ireq in ireq._source_ireqs
    +    if src_ireq.comes_from
     }
    

    code in context

    1. If/when all looks good, want it squashed?
    enhancement 
    opened by AndydeCleyre 40
  • Pip10 update

    Pip10 update

    Update pip-tools for pip10 compatibility (and backwards compatibility with pip9)

    Contributor checklist
    • [x] Provided the tests for the changes
    • [x] Requested (or received) a review from another contributor
    • [x] Gave a clear one-line description in the PR (that the maintainers can add to CHANGELOG.md afterwards).

    /cc @vphilippon

    I didn't add tests, since I just rebuilt existing functionality using pip10 as well. This should work with both versions of pip and is all green locally

    opened by techalchemy 38
  • Dependency handling in requirements when updating packages

    Dependency handling in requirements when updating packages

    So, here is the promised brain dump, sorry for the length.

    Right now naively updating requirements can lead to dependency conflicts. For instance, let's say I want to add raven to my project but pinned to a specific version:

    $ pip install raven==1.9.4
    …
    Successfully installed raven simplejson
    

    So raven needs simplejson. Now I run pip freeze and get in my requirements.txt:

    raven==1.9.4
    simplejson==2.4.0
    

    Some time later I run pip-review and get (this is not what you'd get right now):

    raven==2.0.2 is available (you have 1.9.4)
    simplejson==2.6.2 is available (you have 2.4.0)
    

    Note that the newer simplejson was already available when I initially installed raven, but raven needed simplejson>=2.3.0,<2.5.0. Raven 2.0.2 does as well, but this still encourages me to upgrade simplejson when I shouldn't.

    The current version of raven dropped the >=2.3.0,<2.5.0 part so now we can get the latest and greatest raven and simplejson safely.

    My point is that when updating dependencies, checking for conflicts is very hard to do by hand. This needs to be automated with a tool that yells at the developer when an update leads to a version conflict.

    Ruby gets this right with Bundler. gem install bundle, create a Gemfile with the following content:

    source :rubygems
    gem 'compass-less-plugin'
    

    And run bundle install. This installs the required package and its dependencies and creates a Gemfile.lock file:

    GEM
      remote: http://rubygems.org/
      specs:
        chunky_png (1.2.6)
        compass (0.12.2)
          chunky_png (~> 1.2)
          fssm (>= 0.2.7)
          sass (~> 3.1)
        compass-less-plugin (1.0)
          compass (>= 0.10)
        fssm (0.2.9)
        sass (3.2.1)
    
    PLATFORMS
      ruby
    
    DEPENDENCIES
      compass-less-plugin
    

    Gemfile.lock is like requirements.txt with pinned versions (not everything is pinned here but should probably be): when creating a new environment and running bundle install, bundler looks at the .lock file to install what's specified.

    Then there is a bunch of commands that bundle provides. For instance, to list available updates (running this on a bundle created months ago):

    $ bundle outdated
    Fetching gem metadata from http://rubygems.org/.....
    
    Outdated gems included in the bundle:
      * chunky_png (1.2.6 > 1.2.5)
      * fssm (0.2.9 > 0.2.8.1)
      * sass (3.2.1 > 3.1.12)
      * compass (0.12.2 > 0.11.7)
    

    Updating compass-less-plugin and its dependencies can be done in one command (bundle update compass-less-plugin) and does so while checking for version conflicts.

    Sorry if you're already familiar with all this. Now I'll try to explain how we can make improve requirements.txt by using this approach.

    First, instead of putting all the requirements in requirements.txt, people would only list first-level deps, pinned. So for raven:

    raven==1.9.4
    

    Then some tool provided by pip-tools compiles this into the full requirements list, into an other file (like Gemfile and Gemfile.lock but with less noise):

    raven==1.9.4
    simplejson==2.4.0
    

    The key point is that this tool builds the whole dependency tree for all the top-level requirements and dumps it as a safely-installable-with-no-conflicts requirements file, which pip can just use.

    So next time raven is updated and doesn't require an old simplejson, the tool can update the simplejson requirement. When raven drops simplejson to use python's built-in json implementation, the 2nd-level requirement can be dropped as well, automatically.

    Other use case: requests which used to have dependencies on oauthlib, certifi, chardet and doesn't anymore (and oauthlib needed rsa or pyasn1 or whatever). If I just need requests I'll list in my top-level requirements and the tool will pin or drop the dependencies if they're not needed when I upgrade requests itself.

    And finally, this tool could prevent me from installing package X and Y which need Z<1.0 and Z>1.1.

    That's the theory and I think pip already does some version conflict checks but that's not enough to guarantee safe updates. Now in practice, I think the dependency information is not provided by the PyPI API and requires the whole package to be fetched to actually extract it (or maybe create.io provides that info). So that's annoying but doable, and pip-tools seems like a nice place to experiment with such things.

    I think buildout does check for dependency conflicts but I never managed to wrap my head around it.

    What do you think? I'm happy to start a proof-of-concept that could be integrated in this project.

    opened by brutasse 38
  • Workflow for layered requirements (e.g. prod<-test<-dev requirements)?

    Workflow for layered requirements (e.g. prod<-test<-dev requirements)?

    Say I have

    requirements.in:

    Django~=1.8.0
    

    And also

    requirements-dev.in:

    django-debug-toolbar
    

    How can I run pip-compile on requirements-dev.in, where it will also take into account the requirements in requirements.in when figuring out which versions to use?

    For now I have an ad-hoc script that compiles requirements.in first, then requirements-dev.in has -r requirements.txt as its first line. Is this an okay workflow? I'm worried that in the future if I add a dependency it will try and update a bunch of stuff I don't want it to update, but I haven't actually used this tool long enough to determine whether that's truly a problem. Wondering if anyone else has used pip-tools in this fashion and has any advice?

    PR wanted docs 
    opened by dan-passaro 37
  • virtualenv issue

    virtualenv issue

    I'm not exactly sure what's going on, but with a barebones requirements.txt file within a virtualenv, pip-sync is failing.

    (venv)➜  pip-tools  pip list
    pip (7.1.2)
    setuptools (18.2)
    wheel (0.24.0)
    (venv)➜  pip-tools  pip-sync
    Cannot uninstall requirement appnope, not installed
    Traceback (most recent call last):
      File "/usr/local/bin/pip-sync", line 11, in <module>
        sys.exit(cli())
      File "/usr/local/lib/python2.7/site-packages/click/core.py", line 716, in __call__
        return self.main(*args, **kwargs)
      File "/usr/local/lib/python2.7/site-packages/click/core.py", line 696, in main
        rv = self.invoke(ctx)
      File "/usr/local/lib/python2.7/site-packages/click/core.py", line 889, in invoke
        return ctx.invoke(self.callback, **ctx.params)
      File "/usr/local/lib/python2.7/site-packages/click/core.py", line 534, in invoke
        return callback(*args, **kwargs)
      File "/usr/local/lib/python2.7/site-packages/piptools/scripts/sync.py", line 68, in cli
        pip_flags=pip_flags))
      File "/usr/local/lib/python2.7/site-packages/piptools/sync.py", line 137, in sync
        check_call(['pip', 'uninstall', '-y'] + pip_flags + sorted(to_uninstall))
      File "/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 540, in check_call
        raise CalledProcessError(retcode, cmd)
    subprocess.CalledProcessError: Command '['pip', 'uninstall', '-y', 'appnope', 'aws-shell', 'awscli', 'boto3', 'botocore', 'colorama', 'configobj', 'decorator', 'docutils', 'flake8', 'futures', 'gnureadline', 'ipython', 'ipython-genutils', 'isort', 'jmespath', 'mccabe', 'path.py', 'pep8', 'pexpect', 'pickleshare', 'prompt-toolkit', 'ptyprocess', 'pyasn1', 'pyflakes', 'pygments', 'python-dateutil', 'requests', 'rsa', 'simplegeneric', 'speedtest-cli', 'traitlets', 'virtualenv', 'wcwidth']' returned non-zero exit status 1
    

    In my current directory and virtual environment, pip-sync is trying to uninstall globally installed packages.

    Possibly related to #277.

    opened by zackhsi 35
  • pip-review?

    pip-review?

    Hello,

    Thanks for all the great work on pip-tools! I like the way that the project is heading (pip-compile and pip-sync look pretty cool).

    I just noticed that the latest release has removed pip-review. I was wondering what the new equivalent is (as I found this tool very useful)?

    eg. every night I build a new pyvenv, install required pip libraries and run pip-review to send an email out to the devs letting them know if any libraries require upgrading.

    opened by gavinjackson 33
  • Pass arbitrary args to 'pip' from pip-compile and pip-sync, with '--pip-args'

    Pass arbitrary args to 'pip' from pip-compile and pip-sync, with '--pip-args'

    ~Technically, pass all args after the second standalone '--' arg, whether or not they're consecutive.~

    Fixes #321

    $ pip-sync <pip-sync arg/flag>... --pip-args '<pip install arg/flag>...'
    $ pip-sync <pip-sync arg/flag>... --pip-args '<pip install arg/flag>...'
    

    Changelog-friendly one-liners:

    • ~~Any flags or arguments following two standalone double-dashes (' -- -- ') at the end of pip-compile or pip-sync's argument list are passed on to pip~~
    • pip-compile output headers are now more accurate when ' -- ' is used to escape filenames
    • pip-compile and pip-sync now pass anything provided to the new --pip-args option on to pip
    Contributor checklist
    • [x] Provided the tests for the changes.
    • [x] Gave a clear one-line description in the PR (that the maintainers can add to CHANGELOG.md on release).
    • [x] Assign the PR to an existing or new milestone for the target version (following Semantic Versioning).
    enhancement cli 
    opened by AndydeCleyre 31
  • Enable single-line annotations with `pip-compile --annotation-style=line`

    Enable single-line annotations with `pip-compile --annotation-style=line`

    pip-compile gains --annotation-style=line which uses the recently discontinued single-line annotation format.

    The current default behavior is unchanged, but can be explicitly passed as --annotation-style=split.

    This aims to fix #1306. Please provide feedback!

    Contributor checklist
    • [x] Provided the tests for the changes.
    • [x] Assure PR title is short, clear, and good to be included in the user-oriented changelog
    Maintainer checklist
    • [x] Assure one of these labels is present: backwards incompatible, feature, enhancement, deprecation, bug, dependency, docs or skip-changelog as they determine changelog listing.
    • [x] Assign the PR to an existing or new milestone for the target version (following Semantic Versioning).
    annotations feature 
    opened by AndydeCleyre 30
  • Log which python version was used during compile

    Log which python version was used during compile

    Changelog-friendly one-liner: log which python version to use/was used

    Contributor checklist
    • [x] Provided the tests for the changes.
    • [x] Requested a review from another contributor.
    • [x] Gave a clear one-line description in the PR (that the maintainers can add to CHANGELOG.md on release).
    • [x] Assign the PR to an existing or new milestone for the target version (following Semantic Versioning).

    Fixes: #827

    enhancement needs discussion 
    opened by graingert 28
  • pip-compile forcefully converts package names to lowercase on second run

    pip-compile forcefully converts package names to lowercase on second run

    On a first run, pip-compile creates requirements.txt where package names are properly cased. However on subsequent runs, it converts them all to lower case.

    Steps to replicate

    Please see the full log below:

    [email protected] ~ $ pyenv virtualenv 3.5.2 piptools-test                                                                                         "53e50feeIgnoring indexes: https://pypi.python.org/simple
    Requirement already satisfied (use --upgrade to upgrade): setuptools in /Users/semenov/.pyenv/versions/3.5.2/envs/piptools-test/lib/python3.5/site-packages
    Requirement already satisfied (use --upgrade to upgrade): pip in /Users/semenov/.pyenv/versions/3.5.2/envs/piptools-test/lib/python3.5/site-packages
    [email protected] ~ $ mkdir -p tmp/piptools-test
    [email protected] ~ $ cd tmp/piptools-test/
    [email protected] ~/tmp/piptools-test $ pyenv local piptools-test
    (piptools-test) [email protected] ~/tmp/piptools-test $ pip install pip-tools
    Collecting pip-tools
      Using cached pip_tools-1.8.0-py2.py3-none-any.whl
    Collecting first (from pip-tools)
      Using cached first-2.0.1-py2.py3-none-any.whl
    Collecting six (from pip-tools)
      Using cached six-1.10.0-py2.py3-none-any.whl
    Collecting click>=6 (from pip-tools)
      Using cached click-6.6-py2.py3-none-any.whl
    Installing collected packages: first, six, click, pip-tools
    Successfully installed click-6.6 first-2.0.1 pip-tools-1.8.0 six-1.10.0
    You are using pip version 8.1.1, however version 9.0.1 is available.
    You should consider upgrading via the 'pip install --upgrade pip' command.
    (piptools-test) [email protected] ~/tmp/piptools-test $ echo 'Django>=1.9,<1.10' > requirements.in
    (piptools-test) [email protected] ~/tmp/piptools-test $ pip-compile
    #
    # This file is autogenerated by pip-compile
    # To update, run:
    #
    #    pip-compile --output-file requirements.txt requirements.in
    #
    Django==1.9.12
    (piptools-test) [email protected] ~/tmp/piptools-test $ pip-compile
    #
    # This file is autogenerated by pip-compile
    # To update, run:
    #
    #    pip-compile --output-file requirements.txt requirements.in
    #
    django==1.9.12
    
    Expected result

    On second run, the dependency in requirements.txt is still "Django" not "django".

    Actual result

    On second run, pip-compile converts "Django" to "django".

    opened by IlyaSemenov 28
  • Add support for pip's 2020 dependency resolver

    Add support for pip's 2020 dependency resolver

    What's new?

    Added new option --resolver [2020|legacy] to pip-compile (default is legacy).

    How to use?

    To enable 2020 dependency resolver run pip-compile --resolver=2020.

    2020 resolver example

    $ echo "oslo.utils==1.4.0" | pip-compile - --resolver=2020 --allow-unsafe --annotation-style=line -qo-
    #
    # This file is autogenerated by pip-compile with python 3.8
    # To update, run:
    #
    #    pip-compile --allow-unsafe --annotation-style=line --output-file=- --resolver=2020 -
    #
    babel==2.9.1              # via oslo-i18n, oslo-utils
    iso8601==1.0.0            # via oslo-utils
    netaddr==0.8.0            # via oslo-utils
    netifaces==0.11.0         # via oslo-utils
    oslo-i18n==2.1.0          # via oslo-utils
    oslo-utils==1.4.0         # via -r -
    pbr==0.11.1               # via oslo-i18n, oslo-utils
    pytz==2021.3              # via babel
    six==1.16.0               # via oslo-i18n, oslo-utils
    
    # The following packages are considered to be unsafe in a requirements file:
    pip==21.3.1               # via pbr
    

    Legacy resolver example

    $ echo "oslo.utils==1.4.0" | pip-compile - --resolver=legacy --allow-unsafe -qo-
    Could not find a version that matches pbr!=0.7,!=2.1.0,<1.0,>=0.6,>=2.0.0 (from oslo.utils==1.4.0->-r -)
    Tried: 0.5.2.5.g5b3e942, 0.5.0, 0.5.1, 0.5.2, 0.5.4, 0.5.5, 0.5.6, 0.5.7, 0.5.8, 0.5.10, 0.5.11, 0.5.12, 0.5.13, 0.5.14, 0.5.15, 0.5.16, 0.5.17, 0.5.18, 0.5.19, 0.5.20, 0.5.21, 0.5.22, 0.5.23, 0.6, 0.7.0, 0.8.0, 0.8.1, 0.8.2, 0.9.0, 0.9.0, 0.10.0, 0.10.0, 0.10.1, 0.10.1, 0.10.2, 0.10.2, 0.10.3, 0.10.3, 0.10.4, 0.10.4, 0.10.5, 0.10.5, 0.10.6, 0.10.6, 0.10.7, 0.10.7, 0.10.8, 0.10.8, 0.11.0, 0.11.0, 0.11.1, 0.11.1, 1.0.0, 1.0.0, 1.0.1, 1.0.1, 1.1.0, 1.1.0, 1.1.1, 1.1.1, 1.2.0, 1.2.0, 1.3.0, 1.3.0, 1.4.0, 1.4.0, 1.5.0, 1.5.0, 1.6.0, 1.6.0, 1.7.0, 1.7.0, 1.8.0, 1.8.0, 1.8.1, 1.8.1, 1.9.0, 1.9.0, 1.9.1, 1.9.1, 1.10.0, 1.10.0, 2.0.0, 2.0.0, 2.1.0, 2.1.0, 3.0.0, 3.0.0, 3.0.1, 3.0.1, 3.1.0, 3.1.0, 3.1.1, 3.1.1, 4.0.0, 4.0.0, 4.0.1, 4.0.1, 4.0.2, 4.0.2, 4.0.3, 4.0.3, 4.0.4, 4.0.4, 4.1.0, 4.1.0, 4.1.1, 4.1.1, 4.2.0, 4.2.0, 4.3.0, 4.3.0, 5.0.0, 5.0.0, 5.1.0, 5.1.0, 5.1.1, 5.1.1, 5.1.2, 5.1.2, 5.1.3, 5.1.3, 5.2.0, 5.2.0, 5.2.1, 5.2.1, 5.3.0, 5.3.0, 5.3.1, 5.3.1, 5.4.0, 5.4.0, 5.4.1, 5.4.1, 5.4.2, 5.4.2, 5.4.3, 5.4.3, 5.4.4, 5.4.4, 5.4.5, 5.4.5, 5.5.0, 5.5.0, 5.5.1, 5.5.1, 5.6.0, 5.6.0, 5.7.0, 5.7.0, 5.8.0, 5.8.0
    There are incompatible versions in the resolved dependencies:
      pbr!=0.7,<1.0,>=0.6 (from oslo.utils==1.4.0->-r -)
      pbr!=2.1.0,>=2.0.0 (from oslo.i18n==5.1.0->oslo.utils==1.4.0->-r -)
    
    Contributor checklist
    • [x] Provided the tests for the changes.
    • [x] Assure PR title is short, clear, and good to be included in the user-oriented changelog
    Maintainer checklist
    • [x] Assure one of these labels is present: backwards incompatible, feature, enhancement, deprecation, bug, dependency, docs or skip-changelog as they determine changelog listing.
    • [ ] Assign the PR to an existing or new milestone for the target version (following Semantic Versioning).
    enhancement resolver 
    opened by atugushev 7
  • Cannot install python-language-server[all]

    Cannot install python-language-server[all]

    I'm not sure this is the right place to report this. Anyway, I'm using pip-tools to manage my environments and I had a problem when I tried to upgrade to Python 3.10. After some analysis, I found out that the problem was related to the line python-language-server[all] in my requirements.in file. It works with Python 3.9.7 but it presents an error with Python 3.10.

    Environment Versions

    1. OS Type: Arch Linux 5.15.2-arch1-1
    2. Python version: 3.10.0
    3. pip version: pip 21.2.3
    4. pip-tools version: pip-compile, version 6.4.0

    Steps to replicate

    1. Create a clean Python 3.10.0 virtualenv
    2. Activate the virtualenv and install pip-tools
    3. Create a requirements.in file with the line python-language-server[all]
    4. Run pip-compile requirements.in

    Expected result

    Solve dependencies and create a requirements.txt file.

    Actual result

    (py310) ➜  a pip-compile requirements_py3.in           
    Could not find a version that matches pycodestyle<2.7.0,<2.9.0,>=2.6.0,>=2.8.0 (from python-language-server[all]==0.36.2->-r requirements_py3.in (line 1))
    Tried: 2.0.0, 2.0.0, 2.1.0, 2.1.0, 2.2.0, 2.2.0, 2.3.0, 2.3.0, 2.3.1, 2.3.1, 2.4.0, 2.4.0, 2.5.0, 2.5.0, 2.6.0, 2.6.0, 2.7.0, 2.7.0, 2.8.0, 2.8.0
    Skipped pre-versions: 1.8.0.dev0, 1.8.0.dev0, 2.0.0a1, 2.0.0a1, 2.6.0a1, 2.6.0a1
    There are incompatible versions in the resolved dependencies:
      pycodestyle<2.7.0,>=2.6.0 (from python-language-server[all]==0.36.2->-r requirements_py3.in (line 1))
      pycodestyle>=2.8.0 (from autopep8==1.6.0->python-language-server[all]==0.36.2->-r requirements_py3.in (line 1))
      pycodestyle<2.9.0,>=2.8.0 (from flake8==4.0.1->python-language-server[all]==0.36.2->-r requirements_py3.in (line 1))
    ...
    
    Thanks!
    bug resolver 
    opened by renatocan 5
  • pip-sync re-installs editable packages

    pip-sync re-installs editable packages

    I think this is regression of https://github.com/jazzband/pip-tools/issues/399.

    Environment Versions

    1. OS Type: Linux
    2. Python version: 3.7.10
    3. pip version: 21.3.1
    4. pip-tools version: 6.4.0

    Steps to replicate

    Having:

    -e file:.
    

    And proper setup.py file. Run pip-compile && pip-sync and same again.

    Expected result

    The package should be installed once (into editable mode) and subsequent runs should not uninstall and re-install the package.

    Actual result

    pip-sync re-installs the package each time.

    opened by tuukkamustonen 1
  • pip-compile doesn't provide hashes for wheels hosted by simple index servers

    pip-compile doesn't provide hashes for wheels hosted by simple index servers

    pip-compile doesn't compute hashes for all index servers, which leads to pip install failure. Specifically, any index server that provides hashes from its json API, will prevent pip-compile for checking if other installation candidates are available from other index servers.

    Environment Versions

    1. OS Type
    2. Python version: $ python -V
    3. pip version: $ pip --version
    4. pip-tools version: $ pip-compile --version

    Steps to replicate

    1. host a simple index server
    2. add wheels for source packages in pypi, e.g. avro-python3==1.9.2.1
    3. list this requirement in requirements.in
    4. run pip-compile --generate-hashes -i 'http://<my local index server>.com/' --extra-index-url https://pypi.org/simple
    5. run pip install -r requirements.txt

    Expected result

    The hashes should include the wheel in the local index server.

    Actual result

    Only hashes from pypi.org are listed in requirements.txt.

    Looking at the implementation, it looks like piptools first tries to get hashes from the first index server that implements the json API. The first server that responds with a json blob is taken as the only hash candidates. Files are not manually hashed for any missing files.

    In this case, because some files are on pypi, which implements the json API, other index servers are able to provide valid installation candidates to pip, but piptools does not bother to hash them, thus causing a pip installation failure due to the missing hashes.

    opened by stefansjs 1
  • pip-compile fails with version settings in setup.cfg

    pip-compile fails with version settings in setup.cfg

    Environment Versions

    1. OS Type Windows10
    2. Python version: 3.7.12
    3. pip version: 21.3.1
    4. pip-tools version: 6.4.0

    Steps to replicate

    # setup.cfg
    [metadata]
    name=Thing
    version = attr: Thing.__version__
    [options]
    install_requires = 
        requests
    
    #setup.py
    import setuptools
    setuptools.setup()
    
    # Thing/__init__.py
    __version__ = "1.0.0"
    

    Then run

    $ pip-compile
    Traceback (most recent call last):
      File "/home/tisele/.local/miniconda3/envs/TEST/bin/pip-compile", line 8, in <module>
        sys.exit(cli())
      File "/home/tisele/.local/miniconda3/envs/TEST/lib/python3.7/site-packages/click/core.py", line 1128, in __call__
        return self.main(*args, **kwargs)
      File "/home/tisele/.local/miniconda3/envs/TEST/lib/python3.7/site-packages/click/core.py", line 1053, in main
        rv = self.invoke(ctx)
      File "/home/tisele/.local/miniconda3/envs/TEST/lib/python3.7/site-packages/click/core.py", line 1395, in invoke
        return ctx.invoke(self.callback, **ctx.params)
      File "/home/tisele/.local/miniconda3/envs/TEST/lib/python3.7/site-packages/click/core.py", line 754, in invoke
        return __callback(*args, **kwargs)
      File "/home/tisele/.local/miniconda3/envs/TEST/lib/python3.7/site-packages/click/decorators.py", line 26, in new_func
        return f(get_current_context(), *args, **kwargs)
      File "/home/tisele/.local/miniconda3/envs/TEST/lib/python3.7/site-packages/piptools/scripts/compile.py", line 408, in cli
        dist = meta.load(os.path.dirname(os.path.abspath(src_file)))
      File "/home/tisele/.local/miniconda3/envs/TEST/lib/python3.7/site-packages/pep517/meta.py", line 71, in load
        path = Path(build_as_zip(builder))
      File "/home/tisele/.local/miniconda3/envs/TEST/lib/python3.7/site-packages/pep517/meta.py", line 58, in build_as_zip
        builder(dest=out_dir)
      File "/home/tisele/.local/miniconda3/envs/TEST/lib/python3.7/site-packages/pep517/meta.py", line 53, in build
        _prep_meta(hooks, env, dest)
      File "/home/tisele/.local/miniconda3/envs/TEST/lib/python3.7/site-packages/pep517/meta.py", line 28, in _prep_meta
        reqs = hooks.get_requires_for_build_wheel({})
      File "/home/tisele/.local/miniconda3/envs/TEST/lib/python3.7/site-packages/pep517/wrappers.py", line 173, in get_requires_for_build_wheel
        'config_settings': config_settings
      File "/home/tisele/.local/miniconda3/envs/TEST/lib/python3.7/site-packages/pep517/wrappers.py", line 325, in _call_hook
        extra_environ=extra_environ
      File "/home/tisele/.local/miniconda3/envs/TEST/lib/python3.7/site-packages/pep517/wrappers.py", line 75, in quiet_subprocess_runner
        check_output(cmd, cwd=cwd, env=env, stderr=STDOUT)
      File "/home/tisele/.local/miniconda3/envs/TEST/lib/python3.7/subprocess.py", line 411, in check_output
        **kwargs).stdout
      File "/home/tisele/.local/miniconda3/envs/TEST/lib/python3.7/subprocess.py", line 512, in run
        output=stdout, stderr=stderr)
    subprocess.CalledProcessError: Command '['/home/tisele/.local/miniconda3/envs/TEST/bin/python3.7', '/home/tisele/.local/miniconda3/envs/TEST/lib/python3.7/site-packages/pep517/in_process/_in_process.py', 'get_requires_for_build_wheel', '/tmp/tmpuaxtfj91']' returned non-zero exit status 1.
    

    Without the line version = attr: Thing.__version__ it works.

    Expected result

    No error, a valid requirements.txt file

    opened by Thomasillo 3
  • pre-commit running pip-compile across multiple operating systems

    pre-commit running pip-compile across multiple operating systems

    I have pre-commit set up using GitHub Actions to run on Linux and Windows. pre-commit is configured to run pip-compile:

    - repo: https://github.com/jazzband/pip-tools
      rev: 6.4.0
      hooks:
        - id: pip-compile
    

    The pip-compile documentation suggests running pip-compile for each environment combination (OS+Python): https://github.com/jazzband/pip-tools#cross-environment-usage-of-requirementsinrequirementstxt-and-pip-compile "As the resulting requirements.txt can differ for each environment, users must execute pip-compile on each Python environment separately to generate a requirements.txt valid for each said environment."

    On Linux, I currently manually run pip-compile and output to requirements.txt and on Windows I have pip-compile output to requirements.win.txt.

    How do I get pip-compile to output to the correct requirements file depending on the operating system that pre-commit runs on?

    opened by BTOdell 0
  • Generating hashes from files for incompatible wheels isn't working

    Generating hashes from files for incompatible wheels isn't working

    Environment Versions

    1. OS Type: macOS
    2. Python version: 3.9.6
    3. pip version: 21.3.1
    4. pip-tools version: 6.4.0

    Steps to replicate

    (These replication steps require that you run this on a machine not compatible with the manylinux wheels provided in the demo repository used in the following commands)

    1. Create a requirements file using the project I prepared

      echo regex > requirements.in
      pip-compile --index-url https://gitlab.com/api/v4/projects/31206336/packages/pypi/simple --no-header --generate-hashes -o normal.txt
      
    2. Patch the installed pip to remove this line.

    3. Generate a new requirements file:

      pip-compile --index-url https://gitlab.com/api/v4/projects/31206336/packages/pypi/simple --no-header --generate-hashes -o patched.txt
      
    4. Compare the files

      git diff --no-index normal.txt patched.txt
      

    Expected result

    Both files should include all hashes

    Actual result

    diff --git a/normal.txt b/patched.txt
    index da086ab..23bc894 100644
    --- a/normal.txt
    +++ b/patched.txt
    @@ -1,5 +1,10 @@
     --index-url https://gitlab.com/api/v4/projects/31206336/packages/pypi/simple
    
     regex==2021.11.10 \
    +    --hash=sha256:05b7d6d7e64efe309972adab77fc2af8907bb93217ec60aa9fe12a0dad35874f \
    +    --hash=sha256:30ab804ea73972049b7a2a5c62d97687d69b5a60a67adca07eb73a0ddbc9e29f \
    +    --hash=sha256:85bfa6a5413be0ee6c5c4a663668a2cad2cbecdee367630d097d7823041bdeec \
    +    --hash=sha256:962b9a917dd7ceacbe5cd424556914cb0d636001e393b43dc886ba31d2a1e449 \
    +    --hash=sha256:ca5f18a75e1256ce07494e245cdb146f5a9267d3c702ebf9b65c7f8bd843431e \
         --hash=sha256:f341ee2df0999bfdf7a95e448075effe0db212a59387de1a70690e4acb03d4c6
         # via -r requirements.in
    

    Only hashes compatible with my system are generated.

    The easy solution I see would be to call self.finder.find_all_candidates.cache_clear() in PyPIRepository.allow_all_wheels, but as maintainers of the library you'll probably have more insight. Maybe even creating a new finder instance rather than rely on this implementation detail?

    opened by RazerM 0
  • Disregard existing pins in the output which can't be found by pip, rather than failing to compile

    Disregard existing pins in the output which can't be found by pip, rather than failing to compile

    Before running pip-compile, the output file may contain a pinned requirement which can't be found in PyPI or whichever repo (e.g. a revoked release). This change aims to disregard these un-find-able pins, rather than cause the compile operation to fail.

    Fixes #1530

    Contributor checklist
    • [x] Provided the tests for the changes.
    • [ ] Assure PR title is short, clear, and good to be included in the user-oriented changelog
    Maintainer checklist
    • [ ] Assure one of these labels is present: backwards incompatible, feature, enhancement, deprecation, bug, dependency, docs or skip-changelog as they determine changelog listing.
    • [ ] Assign the PR to an existing or new milestone for the target version (following Semantic Versioning).
    opened by AndydeCleyre 1
  • Unnecessary hard failure of pip-compile when a required package is already present in output with an unavailable version

    Unnecessary hard failure of pip-compile when a required package is already present in output with an unavailable version

    This was encountered in #1529

    When a needed package is already pinned in the output file, but has an invalid or at least unavailable version there, the compilation will fail.

    Environment Versions

    1. Linux
    2. Python version: 3.9.5
    3. pip version: 21.3.1
    4. pip-tools version: 6.4.0

    Steps to replicate

    $ echo requests >reqs.in
    $ pip-compile reqs.in
    $ sed -i 's/==2021/==2041/' reqs.txt
    $ pip-compile reqs.in
    

    Expected result

    I'd expect that the pre-existing content of the output file is considered "low priority" -- that if something there doesn't fit the needs of the input files, it will be discarded. In other words, it should ultimately behave in this case as if certifi isn't in the output file to begin with, and so generate a valid output file again.

    Actual result

      ERROR: Could not find a version that satisfies the requirement certifi==2041.10.8 (from requests==2.26.0->-r reqs.in (line 1)) (from versions: 0.0.1, 0.0.2, 0.0.3, 0.0.4, 0.0.5, 0.0.6, 0.0.7, 0.0.8, 1.0.0, 1.0.1, 14.5.14, 2015.4.28, 2015.9.6, 2015.9.6.1, 2015.9.6.2, 2015.11.20, 2015.11.20.1, 2016.2.28, 2016.8.2, 2016.8.8, 2016.8.31, 2016.9.26, 2017.1.23, 2017.4.17, 2017.7.27, 2017.7.27.1, 2017.11.5, 2018.1.18, 2018.4.16, 2018.8.13, 2018.8.24, 2018.10.15, 2018.11.29, 2019.3.9, 2019.6.16, 2019.9.11, 2019.11.28, 2020.4.5, 2020.4.5.1, 2020.4.5.2, 2020.6.20, 2020.11.8, 2020.12.5, 2021.5.30, 2021.10.8)
    Traceback (most recent call last):
      File "/home/andy/.local/share/venvs/42fa537b433f422253f0da1997538ecd/venv/bin/pip-compile", line 8, in <module>
        sys.exit(cli())
      File "/home/andy/.local/share/venvs/42fa537b433f422253f0da1997538ecd/venv/lib/python3.9/site-packages/click/core.py", line 1128, in __call__
        return self.main(*args, **kwargs)
      File "/home/andy/.local/share/venvs/42fa537b433f422253f0da1997538ecd/venv/lib/python3.9/site-packages/click/core.py", line 1053, in main
        rv = self.invoke(ctx)
      File "/home/andy/.local/share/venvs/42fa537b433f422253f0da1997538ecd/venv/lib/python3.9/site-packages/click/core.py", line 1395, in invoke
        return ctx.invoke(self.callback, **ctx.params)
      File "/home/andy/.local/share/venvs/42fa537b433f422253f0da1997538ecd/venv/lib/python3.9/site-packages/click/core.py", line 754, in invoke
        return __callback(*args, **kwargs)
      File "/home/andy/.local/share/venvs/42fa537b433f422253f0da1997538ecd/venv/lib/python3.9/site-packages/click/decorators.py", line 26, in new_func
        return f(get_current_context(), *args, **kwargs)
      File "/home/andy/.local/share/venvs/42fa537b433f422253f0da1997538ecd/venv/lib/python3.9/site-packages/piptools/scripts/compile.py", line 466, in cli
        results = resolver.resolve(max_rounds=max_rounds)
      File "/home/andy/.local/share/venvs/42fa537b433f422253f0da1997538ecd/venv/lib/python3.9/site-packages/piptools/resolver.py", line 175, in resolve
        has_changed, best_matches = self._resolve_one_round()
      File "/home/andy/.local/share/venvs/42fa537b433f422253f0da1997538ecd/venv/lib/python3.9/site-packages/piptools/resolver.py", line 319, in _resolve_one_round
        their_constraints.extend(self._iter_dependencies(best_match))
      File "/home/andy/.local/share/venvs/42fa537b433f422253f0da1997538ecd/venv/lib/python3.9/site-packages/piptools/resolver.py", line 428, in _iter_dependencies
        dependencies = self.repository.get_dependencies(ireq)
      File "/home/andy/.local/share/venvs/42fa537b433f422253f0da1997538ecd/venv/lib/python3.9/site-packages/piptools/repositories/local.py", line 79, in get_dependencies
        return self.repository.get_dependencies(ireq)
      File "/home/andy/.local/share/venvs/42fa537b433f422253f0da1997538ecd/venv/lib/python3.9/site-packages/piptools/repositories/pypi.py", line 236, in get_dependencies
        self._dependencies_cache[ireq] = self.resolve_reqs(
      File "/home/andy/.local/share/venvs/42fa537b433f422253f0da1997538ecd/venv/lib/python3.9/site-packages/piptools/repositories/pypi.py", line 199, in resolve_reqs
        results = resolver._resolve_one(reqset, ireq)
      File "/home/andy/.local/share/venvs/42fa537b433f422253f0da1997538ecd/venv/lib/python3.9/site-packages/pip/_internal/resolution/legacy/resolver.py", line 379, in _resolve_one
        dist = self._get_dist_for(req_to_install)
      File "/home/andy/.local/share/venvs/42fa537b433f422253f0da1997538ecd/venv/lib/python3.9/site-packages/pip/_internal/resolution/legacy/resolver.py", line 331, in _get_dist_for
        self._populate_link(req)
      File "/home/andy/.local/share/venvs/42fa537b433f422253f0da1997538ecd/venv/lib/python3.9/site-packages/pip/_internal/resolution/legacy/resolver.py", line 300, in _populate_link
        req.link = self._find_requirement_link(req)
      File "/home/andy/.local/share/venvs/42fa537b433f422253f0da1997538ecd/venv/lib/python3.9/site-packages/pip/_internal/resolution/legacy/resolver.py", line 266, in _find_requirement_link
        best_candidate = self.finder.find_requirement(req, upgrade)
      File "/home/andy/.local/share/venvs/42fa537b433f422253f0da1997538ecd/venv/lib/python3.9/site-packages/pip/_internal/index/package_finder.py", line 909, in find_requirement
        raise DistributionNotFound(
    pip._internal.exceptions.DistributionNotFound: No matching distribution found for certifi==2041.10.8 (from requests==2.26.0->-r reqs.in (line 1))
    
    opened by AndydeCleyre 0
  • requirements resolution does not respect include-system-site-packages = true and break base installation

    requirements resolution does not respect include-system-site-packages = true and break base installation

    Environment Versions

    1. Windows 10 enterprise last update
    2. Python version: 3.9.5
    3. pip version: 21.3.1
    4. pip-tools version: 6.4.0

    I'm using Winpython a scientific distribution (more than 560 packages for almost 7Gb) as a base installation. It's an accurately crafted distribution that guarantees compatibility among all the installed packages. I'm using that precisely because i don't want to go hunting for incompatibilities between the last versions of packages like jupyter, ipython, ipykernel, numpy, pandas, pytorch, tensorflow, etc and the tenth of packages that go around them. Another thing i don't want is that each venv for each project ends up containing the very same packages already present in the base installation using then Gb and Gb of useless space and that's the reason why i use include-system-site-packages = true in my venv's.

    I've always managed all with base commands like python -m venv and pip install but i wanted to automatize a bit the thing so i gave in sequence a try to pipenv and poetry, but i had to quit due to the same problem i found here in pip-tools.

    Steps to replicate

    As an example, if i try to install a very simple thing like blackcellmagic in a bare venv with pip i get installed only the 4 requirement packages missing in the base installation, because the rest 60 packages of requirements chain are already satisfied by the base installation, (remember the include-system-site-packages = true). If i try pip-compile with the same requirement i get 66 (sixty-six) packages because the whole requirements chain is always updated to the last version ignoring the fact that it really it is already satisfied, so breaking the compatibility (both at pip requisite level and at execution level) with a lot of other packages in the base installation and making the venv a useless disk space filler.

    I tried both --no-build-isolation and --no-upgrade options, but evidently either i didn't understand their meaning or I'm i missing something, and i didn't find any other way to get pip-compile resolver to honor include-system-site-packages = true like pip does.

    I'm expecting there is a way to force pip-compile to accept the already installed satisfied requirements, like pip, instead of unconditionally always forcefully updating them to the last version so breaking compatibility with base installation.

    I'm not interested to pursue this with pipenv and poetry because i discovered they are both a sort of overkill for my needs, while pip-tools, if i get this problem solved, would completely satisfy my needs to streamline a lot of hand management.

    opened by garu57 10
Releases(6.4.0)
  • 6.4.0(Oct 12, 2021)

  • 6.3.1(Oct 8, 2021)

    Bug Fixes:

    • Ensure pip-tools unions dependencies of multiple declarations of a package with different extras (#1486). Thanks @richafrank
    • Allow comma-separated arguments for --extra (#1493). Thanks @AndydeCleyre
    • Improve clarity of help text for options supporting multiple (#1492). Thanks @AndydeCleyre
    Source code(tar.gz)
    Source code(zip)
  • 6.3.0(Sep 21, 2021)

    Features:

    • Enable single-line annotations with pip-compile --annotation-style=line (#1477). Thanks @AndydeCleyre
    • Generate PEP 440 direct reference whenever possible (#1455). Thanks @FlorentJeannot
    • PEP 440 Direct Reference support (#1392). Thanks @FlorentJeannot

    Bug Fixes:

    • Change log level of hash message (#1460). Thanks @plannigan
    • Allow passing --no-upgrade option (#1438). Thanks @ssbarnea
    Source code(tar.gz)
    Source code(zip)
  • 6.2.0(Jun 22, 2021)

    Features:

    • Add --emit-options/--no-emit-options flags to pip-compile (#1123). Thanks @atugushev
    • Add --python-executable option for pip-sync (#1333). Thanks @MaratFM
    • Log which python version was used during compile (#828). Thanks @graingert

    Bug Fixes:

    • Fix pip-compile package ordering (#1419). Thanks @adamsol
    • Add --strip-extras option to pip-compile for producing constraint compatible output (#1404). Thanks @ssbarnea
    • Fix click v7 version_option compatibility (#1410). Thanks @FuegoFro
    • Pass package_name explicitly in click.version_option decorators for compatibility with click>=8.0 (#1400). Thanks @nicoa

    Other Changes:

    • Document updating requirements with pre-commit hooks (#1387). Thanks @microcat49
    • Add setuptools and wheel dependencies to the setup.cfg (#889). Thanks @jayvdb
    • Improve instructions for new contributors (#1394). Thanks @FlorentJeannot
    • Better explain role of existing requirements.txt (#1369). Thanks @mikepqr
    Source code(tar.gz)
    Source code(zip)
  • 6.1.0(Apr 14, 2021)

    Features:

    • Add support for pyproject.toml or setup.cfg as input dependency file (PEP-517) for pip-compile (#1356). Thanks @orsinium
    • Add pip-compile --extra option to specify extras_require dependencies (#1363). Thanks @orsinium

    Bug Fixes:

    • Restore ability to set compile cache with env var PIP_TOOLS_CACHE_DIR (#1368). Thanks @AndydeCleyre
    Source code(tar.gz)
    Source code(zip)
  • 6.0.1(Mar 15, 2021)

  • 6.0.0(Mar 13, 2021)

    Backwards Incompatible Changes:

    • Remove support for EOL Python 3.5 and 2.7 (#1243). Thanks @jdufresne
    • Remove deprecated --index/--no-index option from pip-compile (#1234). Thanks @jdufresne

    Features:

    • Use pep517 to parse dependencies metadata from setup.py (#1311). Thanks @astrojuanlu

    Bug Fixes:

    • Fix a bug where pip-compile with setup.py would not include dependencies with environment markers (#1311). Thanks @astrojuanlu
    • Prefer === over == when generating requirements.txt if a dependency was pinned with === (#1323). Thanks @IceTDrinker
    • Fix a bug where pip-compile with setup.py in nested folder would generate setup.txt output file (#1324). Thanks @peymanslh
    • Write out default index when it is provided as --extra-index-url (#1325). Thanks @fahrradflucht

    Dependencies:

    • Bump pip minimum version to >= 20.3 (#1340). Thanks @atugushev
    Source code(tar.gz)
    Source code(zip)
  • 5.5.0(Dec 30, 2020)

    Features:

    • Add Python 3.9 support (1222). Thanks @jdufresne
    • Improve formatting of long "via" annotations (1237). Thanks @jdufresne
    • Add --verbose and --quiet options to pip-sync (1241). Thanks @jdufresne
    • Add --no-allow-unsafe option to pip-compile (1265). Thanks @jdufresne

    Bug Fixes:

    • Restore PIP_EXISTS_ACTION environment variable to its previous state when resolve dependencies in pip-compile (1255). Thanks @jdufresne

    Dependencies:

    • Remove six dependency in favor pip's vendored six (1240). Thanks @jdufresne

    Improved Documentation:

    • Add pip-requirements.el (for Emacs) to useful tools to README (#1244). Thanks @jdufresne
    • Add supported Python versions to README (#1246). Thanks @jdufresne
    Source code(tar.gz)
    Source code(zip)
  • 5.4.0(Nov 21, 2020)

    Features:

    • Add pip>=20.3 support (1216). Thanks @atugushev and @AndydeCleyre
    • Exclude --no-reuse-hashes option from «command to run» header (1197). Thanks @graingert

    Dependencies:

    • Bump pip minimum version to >= 20.1 (1191). Thanks @atugushev and @AndydeCleyre
    Source code(tar.gz)
    Source code(zip)
  • 5.3.1(Jul 31, 2020)

  • 5.3.0(Jul 26, 2020)

    Features:

    • Add -h alias for --help option to pip-sync and pip-compile (1163). Thanks @jan25
    • Add pip>=20.2 support (1168). Thanks @atugushev
    • pip-sync now exists with code 1 on --dry-run (1172). Thanks @francisbrito
    • pip-compile now doesn't resolve constraints from -c constraints.txtthat are not (yet) requirements (1175). Thanks @clslgrnc
    • Add --reuse-hashes/--no-reuse-hashes options to pip-compile (1177). Thanks @graingert
    Source code(tar.gz)
    Source code(zip)
  • 5.2.1(Jun 9, 2020)

  • 5.2.0(May 27, 2020)

    Features:

    • Show basename of URLs when pip-compile generates hashes in a verbose mode (1113). Thanks @atugushev
    • Add --emit-index-url/--no-emit-index-url options to pip-compile (1130). Thanks @atugushev

    Bug Fixes:

    • Fix a bug where pip-compile would ignore some of package versions when PIP_PREFER_BINARY is set on (1119). Thanks @atugushev
    • Fix leaked URLs with credentials in the debug output of pip-compile (1146). Thanks @atugushev
    • Fix a bug where URL requirements would have name collisions (1149). Thanks @geokala

    Deprecations:

    • Deprecate --index/--no-index in favor of --emit-index-url/--no-emit-index-url options in pip-compile (1130). Thanks @atugushev

    Other Changes:

    • Switch to setuptools declarative syntax through setup.cfg (1141). Thanks @jdufresne
    Source code(tar.gz)
    Source code(zip)
  • 5.1.2(May 5, 2020)

  • 5.1.1(May 1, 2020)

  • 5.1.0(Apr 27, 2020)

    Features:

    • Show progress bar when downloading packages in pip-compile verbose mode (#949). Thanks @atugushev
    • pip-compile now gets hashes from PyPI JSON API (if available) which significantly increases the speed of hashes generation (#1109). Thanks @atugushev
    Source code(tar.gz)
    Source code(zip)
  • 5.0.0(Apr 16, 2020)

    Backwards Incompatible Changes:

    • pip-tools now requires pip>=20.0 (previosly 8.1.x - 20.0.x). Windows users, make sure to use python -m pip install pip-tools to avoid issues with pip self-update from now on (#1055). Thanks @atugushev
    • --build-isolation option now set on by default for pip-compile (#1060). Thanks @hramezani

    Features:

    • Exclude requirements with non-matching markers from pip-sync (#927). Thanks @AndydeCleyre
    • Add pre-commit hook for pip-compile (#976). Thanks @atugushev
    • pip-compile and pip-sync now pass anything provided to the new --pip-args option on to pip (#1080). Thanks @AndydeCleyre
    • pip-compile output headers are now more accurate when -- is used to escape filenames (#1080). Thanks @AndydeCleyre
    • Add pip>=20.1 support (#1088). Thanks @atugushev

    Bug Fixes:

    • Fix a bug where editables that are both direct requirements and constraints wouldn't appear in pip-compile output (#1093). Thanks @richafrank
    • pip-compile now sorts format controls (--no-binary/--only-binary) to ensure consistent results (#1098). Thanks @richafrank

    Improved Documentation:

    • Add cross-environment usage documentation to README (#651). Thanks @vphilippon
    • Add versions compatibility table to README (#1106). Thanks @atugushev
    Source code(tar.gz)
    Source code(zip)
  • 4.5.1(Feb 26, 2020)

    Bug Fixes:

    • Strip line number annotations such as "(line XX)" from file requirements, to prevent diff noise when modifying input requirement files (#1075). Thanks @adamchainz

    Improved Documentation:

    • Updated README example outputs for primary requirement annotations (#1072). Thanks @richafrank
    Source code(tar.gz)
    Source code(zip)
  • 4.5.0(Feb 20, 2020)

    4.5.0 (2020-02-20)

    Features:

    • Primary requirements and VCS dependencies are now get annotated with any source .in files and reverse dependencies (#1058). Thanks @AndydeCleyre

    Bug Fixes:

    • Always use normalized path for cache directory as it is required in newer versions of pip (#1062). Thanks @kammala

    Improved Documentation:

    • Replace outdated link in the README with rationale for pinning (#1053). Thanks @m-aciek
    Source code(tar.gz)
    Source code(zip)
  • 4.4.1(Jan 31, 2020)

    Bug Fixes:

    • Fix a bug where pip-compile would keep outdated options from requirements.txt (#1029). Thanks @atugushev
    • Fix the No handlers could be found for logger "pip.*" error by configuring the builtin logging module (#1035). Thanks @vphilippon
    • Fix a bug where dependencies of relevant constraints may be missing from output file (#1037). Thanks @jeevb
    • Upgrade the minimal version of click from 6.0 to 7.0 version in setup.py (#1039). Thanks @hramezani
    • Ensure that depcache considers the python implementation such that (for example) cpython3.6 does not poison the results of pypy3.6 (#1050). Thanks @asottile

    Improved Documentation:

    • Make the README more imperative about installing into a project's virtual environment to avoid confusion (#1023). Thanks @tekumara
    • Add a note to the README about how to install requirements on different stages to Workflow for layered requirements section (#1044). Thanks @hramezani
    Source code(tar.gz)
    Source code(zip)
  • 4.4.0(Jan 21, 2020)

    Features:

    • Add --cache-dir option to pip-compile (#1022). Thanks @richafrank
    • Add pip>=20.0 support (#1024). Thanks @atugushev

    Bug Fixes:

    • Fix a bug where pip-compile --upgrade-package would upgrade those passed packages not already required according to the *.in and *.txt files (#1031). Thanks @AndydeCleyre
    Source code(tar.gz)
    Source code(zip)
  • 4.3.0(Nov 26, 2019)

    Features:

    • Add Python 3.8 support (#956). Thanks @hramezani
    • Unpin commented out unsafe packages in requirements.txt (#975). Thanks @atugushev

    Bug Fixes:

    • Fix pip-compile doesn't copy --trusted-host from requirements.in to requirements.txt (#964). Thanks @atugushev
    • Add compatibility with pip>=20.0 (#953 and #978). Thanks @atugushev
    • Fix a bug where the resolver wouldn't clean up the ephemeral wheel cache (#968). Thanks @atugushev

    Improved Documentation:

    • Add a note to README about requirements.txt file, which would possibly interfere if you're compiling from scratch (#959). Thanks @hramezani
    Source code(tar.gz)
    Source code(zip)
  • 4.2.0(Oct 11, 2019)

    Features:

    • Add --ask option to pip-sync (#913). Thanks @georgek

    Bug Fixes:

    • Add compatibility with pip>=19.3 (#864, #904, #910, #912 and #915). Thanks @atugushev
    • Ensure pip-compile --no-header <blank requirements.in> creates/overwrites requirements.txt (#909). Thanks @AndydeCleyre
    • Fix pip-compile --upgrade-package removes «via» annotation (#931). Thanks @hramezani

    Improved Documentation:

    • Add info to README about layered requirements files and -c flag (#905). Thanks @jamescooke
    Source code(tar.gz)
    Source code(zip)
  • 4.1.0(Aug 26, 2019)

    4.1.0 (2019-08-26)

    Features:

    • Add --no-emit-find-links option to pip-compile (#873). Thanks @jacobtolar

    Bug Fixes:

    • Prevent --dry-run log message from being printed with --quiet option in pip-compile (#861). Thanks @ddormer
    • Fix resolution of requirements from Git URLs without -e (#879). Thanks @andersk
    Source code(tar.gz)
    Source code(zip)
  • 4.0.0(Jul 25, 2019)

  • 3.9.0(Jul 17, 2019)

    3.9.0 (2019-07-17)

    Features:

    • Print provenance information when pip-compile fails (#837). Thanks @jakevdp

    Bug Fixes:

    • Output all logging to stderr instead of stdout (#834). Thanks @georgek
    • Fix output file update with --dry-run option in pip-compile (#842). Thanks @shipmints and @atugushev
    Source code(tar.gz)
    Source code(zip)
  • 3.8.0(Jun 6, 2019)

    Features:

    • Options --upgrade and --upgrade-package are no longer mutually exclusive (#831). Thanks @adamchainz

    Bug Fixes:

    • Fix --generate-hashes with bare VCS URLs (#812). Thanks @jcushman
    • Fix issues with UnicodeError when installing pip-tools from source in some systems (#816). Thanks @AbdealiJK
    • Respect --pre option in the input file (#822). Thanks @atugushev
    • Option --upgrade-package now works even if the output file does not exist (#831). Thanks @adamchainz
    Source code(tar.gz)
    Source code(zip)
  • 3.7.0(May 9, 2019)

    Features:

    • Show progressbar on generation hashes in pip-compile verbose mode (#743). Thanks @atugushev
    • Add options --cert and --client-cert to pip-sync (#798). Thanks @atugushev
    • Add support for --find-links in pip-compile output (#793). Thanks @estan and @atugushev
    • Normalize «command to run» in pip-compile headers (#800). Thanks @atugushev
    • Support URLs as packages (#807). Thanks @jcushman, @nim65s and @toejough

    Bug Fixes:

    • Fix replacing password to asterisks in pip-compile (#808). Thanks @atugushev
    Source code(tar.gz)
    Source code(zip)
  • 3.6.1(Apr 24, 2019)

  • 3.6.0(Apr 3, 2019)

    3.6.0 (2019-04-03)

    Features:

    • Show less output on pip-sync with --quiet option (#765). Thanks @atugushev
    • Support the flag --trusted-host in pip-sync (#777). Thanks @firebirdberlin
    Source code(tar.gz)
    Source code(zip)
Owner
Jazzband
Jazzband
PokerFace is a Python package for various poker tools.

PokerFace is a Python package for various poker tools. The following features are present in PokerFace... Types for cards and their componen

Juho Kim 4 Sep 25, 2021
A PDM plugin that packs your packages into a zipapp

pdm-packer A PDM plugin that packs your packages into a zipapp Requirements pdm-packer requires Python >=3.7 Installation If you have installed PDM wi

Frost Ming 10 Sep 23, 2021
Python dependency management and packaging made easy.

Poetry: Dependency Management for Python Poetry helps you declare, manage and install dependencies of Python projects, ensuring you have the right sta

Poetry 17.4k Dec 3, 2021
A PyPI mirror client according to PEP 381 http://www.python.org/dev/peps/pep-0381/

This is a PyPI mirror client according to PEP 381 + PEP 503 http://www.python.org/dev/peps/pep-0381/. bandersnatch >=4.0 supports Linux, MacOSX + Wind

Python Packaging Authority 272 Nov 30, 2021
Python PyPi staging server and packaging, testing, release tool

devpi: PyPI server and packaging/testing/release tool This repository contains three packages comprising the core devpi system on the server and clien

null 506 Nov 24, 2021
The Python Package Index

Warehouse Warehouse is the software that powers PyPI. See our development roadmap, documentation, and architectural overview. Getting Started You can

Python Packaging Authority 2.8k Nov 26, 2021
The Python package installer

pip - The Python Package Installer pip is the package installer for Python. You can use pip to install packages from the Python Package Index and othe

Python Packaging Authority 7.6k Dec 1, 2021
Python dependency management and packaging made easy.

Poetry: Dependency Management for Python Poetry helps you declare, manage and install dependencies of Python projects, ensuring you have the right sta

Poetry 17.3k Dec 2, 2021
Install and Run Python Applications in Isolated Environments

pipx — Install and Run Python Applications in Isolated Environments Documentation: https://pipxproject.github.io/pipx/ Source Code: https://github.com

null 4.3k Dec 2, 2021
:package: :fire: Python project management. Manage packages: convert between formats, lock, install, resolve, isolate, test, build graph, show outdated, audit. Manage venvs, build package, bump version.

THE PROJECT IS ARCHIVED Forks: https://github.com/orsinium/forks DepHell -- project management for Python. Why it is better than all other tools: Form

DepHell 1.7k Dec 3, 2021
An installation and dependency system for Python

Pyflow Simple is better than complex - The Zen of Python Pyflow streamlines working with Python projects and files. It's an easy-to-use CLI app with a

David O'Connor 943 Dec 3, 2021
pip-run - dynamic dependency loader for Python

pip-run provides on-demand temporary package installation for a single interpreter run. It replaces this series of commands (or their Windows equivale

Jason R. Coombs 61 Nov 20, 2021
Python Development Workflow for Humans.

Pipenv: Python Development Workflow for Humans [ ~ Dependency Scanning by PyUp.io ~ ] Pipenv is a tool that aims to bring the best of all packaging wo

Python Packaging Authority 22.5k Dec 3, 2021
A PyPI mirror client according to PEP 381 http://www.python.org/dev/peps/pep-0381/

This is a PyPI mirror client according to PEP 381 + PEP 503 http://www.python.org/dev/peps/pep-0381/. bandersnatch >=4.0 supports Linux, MacOSX + Wind

Python Packaging Authority 270 Nov 26, 2021
Simple Library Management made with Python

Installation pip install mysql-connector-python NOTE: You must make a database (library) & and table (books, student) to hold all data. Languange and

SonLyte 10 Oct 21, 2021
Library for faster pinned CPU <-> GPU transfer in Pytorch

SpeedTorch Faster pinned CPU tensor <-> GPU Pytorch variabe transfer and GPU tensor <-> GPU Pytorch variable transfer, in certain cases. Update 9-29-1

Santosh Gupta 644 Nov 24, 2021
A fresh approach to autocomplete implementations, specially for Django. Status: v3 stable, 2.x.x stable, 1.x.x deprecated. Please DO regularely ping us with your link at #yourlabs IRC channel

Features Python 2.7, 3.4, Django 2.0+ support (Django 1.11 (LTS), is supported until django-autocomplete-light-3.2.10), Django (multiple) choice suppo

YourLabs 1.6k Dec 1, 2021
A fresh approach to autocomplete implementations, specially for Django. Status: v3 stable, 2.x.x stable, 1.x.x deprecated. Please DO regularely ping us with your link at #yourlabs IRC channel

Features Python 2.7, 3.4, Django 2.0+ support (Django 1.11 (LTS), is supported until django-autocomplete-light-3.2.10), Django (multiple) choice suppo

YourLabs 1.6k Nov 25, 2021
Automatically download the cwru data set, and then divide it into training data set and test data set

Automatically download the cwru data set, and then divide it into training data set and test data set.自动下载cwru数据集,然后分训练数据集和测试数据集

null 2 Nov 25, 2021
A Modular MWDB Utility to Collect Fresh Malware Samples

MWDB Feeds A Modular MWDB Utility to Collect Fresh Malware Samples This project is FREE as in FREE ?? , use it commercially, privately or however you

c3rb3ru5 24 Nov 22, 2021
My qtile config with a fresh-looking bar and pywal support

QtileConfig My qtile config with a fresh-looking bar and pywal support. Note: This is my first rice and first github repo. Please excuse my poor codin

Eden 4 Nov 10, 2021
A flat theme for Django admin interface. Modern, fresh, simple.

Django Flat Theme django-flat-theme is included as part of Django from version 1.9! ?? Please use this app if your project is powered by an older Djan

elky 415 Nov 22, 2021
A fresh approach to autocomplete implementations, specially for Django.

A fresh approach to autocomplete implementations, specially for Django. Status: v3 stable, 2.x.x stable, 1.x.x deprecated. Please DO regularely ping us with your link at #yourlabs IRC channel

YourLabs 1.6k Dec 1, 2021
MultiPy lets you conveniently keep track of your python scripts for personal use or showcase by loading and grouping them into categories. It allows you to either run each script individually or together with just one click.

MultiPy About MultiPy is a graphical user interface built using Dear PyGui Python GUI Framework that lets you conveniently keep track of your python s

null 49 Oct 31, 2021
A tool to build reproducible wheels for you Python project or for all of your dependencies

asaman: Amra Saman (আমরা সমান) This is a tool to build reproducible wheels for your Python project or for all of your dependencies. What this means is

Kushal Das 12 Nov 16, 2021
Safety checks your installed dependencies for known security vulnerabilities

Safety checks your installed dependencies for known security vulnerabilities. By default it uses the open Python vulnerability database Safety DB, but

pyup.io 1.2k Dec 2, 2021
Cytotron - A unique discord bot like never before. Add it to your server to keep it active, motiviated, and amazing!!

Cytotron - Take your server to the next level Most of the details are in the website. Go to https://cytotron-bot.gq for more information. If that link

LeviathanProgramming 6 Jun 13, 2021
Command line tool to keep track of your favorite playlists on YouTube and many other places.

Command line tool to keep track of your favorite playlists on YouTube and many other places.

Wolfgang Popp 121 Nov 24, 2021
ChainJacking is a tool to find which of your Go lang direct GitHub dependencies is susceptible to ChainJacking attack.

ChainJacking is a tool to find which of your Go lang direct GitHub dependencies is susceptible to ChainJacking attack.

Checkmarx 15 Nov 23, 2021