0018485119986aebef136470c51bde85da736732079c687ab1d4c5eb5237e694 pip-tools-3.5.0.tar.gz
3b9fb8948340eff5869ac83dc85e3a7c62b837cec33609c45c48c2e5aa740ba5 pip-tools-4.0.0.tar.gz
--- pip-tools-3.5.0.tar.gz
+++ pip-tools-4.0.0.tar.gz
βββ metadata
β @@ -1 +1 @@
β -gzip compressed data, was "dist/pip-tools-3.5.0.tar", last modified: Wed Mar 13 06:14:00 2019, max compression
β +gzip compressed data, was "dist/pip-tools-4.0.0.tar", last modified: Thu Jul 25 02:48:28 2019, max compression
β --- pip-tools-3.5.0.tar
βββ +++ pip-tools-4.0.0.tar
βββ file list
β β @@ -1,93 +1,95 @@
β β -drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-03-13 06:14:00.000000 pip-tools-3.5.0/
β β -drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-03-13 06:14:00.000000 pip-tools-3.5.0/.github/
β β --rw-rw-r-- 0 travis (2000) travis (2000) 514 2019-03-13 06:13:38.000000 pip-tools-3.5.0/.github/PULL_REQUEST_TEMPLATE.md
β β --rw-rw-r-- 0 travis (2000) travis (2000) 291 2019-03-13 06:13:38.000000 pip-tools-3.5.0/.github/ISSUE_TEMPLATE.md
β β -drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-03-13 06:14:00.000000 pip-tools-3.5.0/examples/
β β --rw-rw-r-- 0 travis (2000) travis (2000) 132 2019-03-13 06:13:38.000000 pip-tools-3.5.0/examples/django.in
β β --rw-rw-r-- 0 travis (2000) travis (2000) 49 2019-03-13 06:13:38.000000 pip-tools-3.5.0/examples/sentry.in
β β --rw-rw-r-- 0 travis (2000) travis (2000) 19 2019-03-13 06:13:38.000000 pip-tools-3.5.0/examples/hypothesis.in
β β --rw-rw-r-- 0 travis (2000) travis (2000) 168 2019-03-13 06:13:38.000000 pip-tools-3.5.0/examples/protection.in
β β --rw-rw-r-- 0 travis (2000) travis (2000) 49 2019-03-13 06:13:38.000000 pip-tools-3.5.0/examples/flask.in
β β --rw-rw-r-- 0 travis (2000) travis (2000) 121 2019-03-13 06:13:38.000000 pip-tools-3.5.0/.flake8
β β --rw-rw-r-- 0 travis (2000) travis (2000) 11632 2019-03-13 06:14:00.000000 pip-tools-3.5.0/PKG-INFO
β β -drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-03-13 06:14:00.000000 pip-tools-3.5.0/img/
β β --rw-rw-r-- 0 travis (2000) travis (2000) 23961 2019-03-13 06:13:38.000000 pip-tools-3.5.0/img/pip-tools-overview.png
β β --rw-rw-r-- 0 travis (2000) travis (2000) 1295 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tox.ini
β β --rw-rw-r-- 0 travis (2000) travis (2000) 253 2019-03-13 06:13:38.000000 pip-tools-3.5.0/.gitignore
β β --rw-rw-r-- 0 travis (2000) travis (2000) 2821 2019-03-13 06:13:38.000000 pip-tools-3.5.0/CONTRIBUTING.md
β β --rw-rw-r-- 0 travis (2000) travis (2000) 229 2019-03-13 06:14:00.000000 pip-tools-3.5.0/setup.cfg
β β --rw-rw-r-- 0 travis (2000) travis (2000) 2081 2019-03-13 06:13:38.000000 pip-tools-3.5.0/.travis.yml
β β --rw-rw-r-- 0 travis (2000) travis (2000) 1500 2019-03-13 06:13:38.000000 pip-tools-3.5.0/LICENSE
β β -drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-03-13 06:14:00.000000 pip-tools-3.5.0/pip_tools.egg-info/
β β --rw-rw-r-- 0 travis (2000) travis (2000) 11632 2019-03-13 06:13:59.000000 pip-tools-3.5.0/pip_tools.egg-info/PKG-INFO
β β --rw-rw-r-- 0 travis (2000) travis (2000) 1 2019-03-13 06:13:59.000000 pip-tools-3.5.0/pip_tools.egg-info/dependency_links.txt
β β --rw-rw-r-- 0 travis (2000) travis (2000) 9 2019-03-13 06:13:59.000000 pip-tools-3.5.0/pip_tools.egg-info/top_level.txt
β β --rw-rw-r-- 0 travis (2000) travis (2000) 1 2019-03-13 06:13:59.000000 pip-tools-3.5.0/pip_tools.egg-info/not-zip-safe
β β --rw-rw-r-- 0 travis (2000) travis (2000) 2099 2019-03-13 06:14:00.000000 pip-tools-3.5.0/pip_tools.egg-info/SOURCES.txt
β β --rw-rw-r-- 0 travis (2000) travis (2000) 13 2019-03-13 06:13:59.000000 pip-tools-3.5.0/pip_tools.egg-info/requires.txt
β β --rw-rw-r-- 0 travis (2000) travis (2000) 99 2019-03-13 06:13:59.000000 pip-tools-3.5.0/pip_tools.egg-info/entry_points.txt
β β --rw-rw-r-- 0 travis (2000) travis (2000) 126 2019-03-13 06:13:38.000000 pip-tools-3.5.0/.coveragerc
β β --rw-rw-r-- 0 travis (2000) travis (2000) 8572 2019-03-13 06:13:38.000000 pip-tools-3.5.0/README.rst
β β --rw-rw-r-- 0 travis (2000) travis (2000) 2736 2019-03-13 06:13:38.000000 pip-tools-3.5.0/.appveyor.yml
β β --rw-rw-r-- 0 travis (2000) travis (2000) 23 2019-03-13 06:13:38.000000 pip-tools-3.5.0/dev-requirements.txt
β β --rw-rw-r-- 0 travis (2000) travis (2000) 13361 2019-03-13 06:13:38.000000 pip-tools-3.5.0/CHANGELOG.md
β β --rw-rw-r-- 0 travis (2000) travis (2000) 1904 2019-03-13 06:13:38.000000 pip-tools-3.5.0/setup.py
β β -drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-03-13 06:14:00.000000 pip-tools-3.5.0/tests/
β β --rw-rw-r-- 0 travis (2000) travis (2000) 12230 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_sync.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 1357 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_top_level_editable.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 3158 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_cache.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 4967 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_resolver.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 4664 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_repository_local.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 3952 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_cli_sync.py
β β -drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-03-13 06:14:00.000000 pip-tools-3.5.0/tests/test_data/
β β -drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-03-13 06:14:00.000000 pip-tools-3.5.0/tests/test_data/fake_package/
β β --rw-rw-r-- 0 travis (2000) travis (2000) 603 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_data/fake_package/setup.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 2753 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_data/fake-index.json
β β -drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-03-13 06:14:00.000000 pip-tools-3.5.0/tests/test_data/minimal_wheels/
β β --rw-rw-r-- 0 travis (2000) travis (2000) 1631 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_data/minimal_wheels/small_fake_b-0.2-py2.py3-none-any.whl
β β --rw-rw-r-- 0 travis (2000) travis (2000) 1632 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_data/minimal_wheels/small_fake_a-0.2-py2.py3-none-any.whl
β β --rw-rw-r-- 0 travis (2000) travis (2000) 1631 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_data/minimal_wheels/small_fake_a-0.1-py2.py3-none-any.whl
β β --rw-rw-r-- 0 travis (2000) travis (2000) 1124 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_data/minimal_wheels/small_fake_with_deps-0.1-py2.py3-none-any.whl
β β --rw-rw-r-- 0 travis (2000) travis (2000) 1635 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_data/minimal_wheels/small_fake_b-0.1-py2.py3-none-any.whl
β β --rw-rw-r-- 0 travis (2000) travis (2000) 1026 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_data/minimal_wheels/small_fake_b-0.3-py2.py3-none-any.whl
β β --rw-rw-r-- 0 travis (2000) travis (2000) 56 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_data/fake-editables.json
β β -drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-03-13 06:14:00.000000 pip-tools-3.5.0/tests/test_data/small_fake_package/
β β --rw-rw-r-- 0 travis (2000) travis (2000) 142 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_data/small_fake_package/setup.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 2514 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_repositories.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 352 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/utils.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 7838 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_writer.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 4835 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_repository_pypi.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 1348 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_minimal_upgrade.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 110 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/__init__.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 18158 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_cli_compile.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 3494 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/conftest.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 2528 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_fake_index.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 4382 2019-03-13 06:13:38.000000 pip-tools-3.5.0/tests/test_utils.py
β β -drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-03-13 06:14:00.000000 pip-tools-3.5.0/piptools/
β β --rw-rw-r-- 0 travis (2000) travis (2000) 5516 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/cache.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 12856 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/resolver.py
β β -drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-03-13 06:14:00.000000 pip-tools-3.5.0/piptools/_compat/
β β --rw-rw-r-- 0 travis (2000) travis (2000) 4562 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/_compat/contextlib.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 2826 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/_compat/tempfile.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 2190 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/_compat/pip_compat.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 715 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/_compat/__init__.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 128 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/click.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 21836 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/io.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 891 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/logging.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 266 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/__main__.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 5794 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/writer.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 2058 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/exceptions.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 711 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/locations.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 7440 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/utils.py
β β -drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-03-13 06:14:00.000000 pip-tools-3.5.0/piptools/scripts/
β β --rwxrwxr-x 0 travis (2000) travis (2000) 11732 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/scripts/compile.py
β β --rwxrwxr-x 0 travis (2000) travis (2000) 3260 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/scripts/sync.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 0 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/scripts/__init__.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 916 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/pip.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 5714 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/sync.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 0 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/__init__.py
β β -drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-03-13 06:14:00.000000 pip-tools-3.5.0/piptools/repositories/
β β --rw-rw-r-- 0 travis (2000) travis (2000) 12742 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/repositories/pypi.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 2878 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/repositories/local.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 1498 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/repositories/base.py
β β --rw-rw-r-- 0 travis (2000) travis (2000) 95 2019-03-13 06:13:38.000000 pip-tools-3.5.0/piptools/repositories/__init__.py
β β +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-07-25 02:48:28.000000 pip-tools-4.0.0/
β β +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-07-25 02:48:28.000000 pip-tools-4.0.0/.github/
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 514 2019-07-25 02:48:06.000000 pip-tools-4.0.0/.github/PULL_REQUEST_TEMPLATE.md
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 291 2019-07-25 02:48:06.000000 pip-tools-4.0.0/.github/ISSUE_TEMPLATE.md
β β +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-07-25 02:48:28.000000 pip-tools-4.0.0/examples/
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 134 2019-07-25 02:48:06.000000 pip-tools-4.0.0/examples/django.in
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 49 2019-07-25 02:48:06.000000 pip-tools-4.0.0/examples/sentry.in
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 19 2019-07-25 02:48:06.000000 pip-tools-4.0.0/examples/hypothesis.in
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 168 2019-07-25 02:48:06.000000 pip-tools-4.0.0/examples/protection.in
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 49 2019-07-25 02:48:06.000000 pip-tools-4.0.0/examples/flask.in
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 13707 2019-07-25 02:48:28.000000 pip-tools-4.0.0/PKG-INFO
β β +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-07-25 02:48:28.000000 pip-tools-4.0.0/img/
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 23961 2019-07-25 02:48:06.000000 pip-tools-4.0.0/img/pip-tools-overview.png
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 1399 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tox.ini
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 253 2019-07-25 02:48:06.000000 pip-tools-4.0.0/.gitignore
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 2911 2019-07-25 02:48:06.000000 pip-tools-4.0.0/CONTRIBUTING.md
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 46 2019-07-25 02:48:06.000000 pip-tools-4.0.0/.bandit
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 627 2019-07-25 02:48:28.000000 pip-tools-4.0.0/setup.cfg
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 26 2019-07-25 02:48:06.000000 pip-tools-4.0.0/.fussyfox.yml
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 2304 2019-07-25 02:48:06.000000 pip-tools-4.0.0/.travis.yml
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 1500 2019-07-25 02:48:06.000000 pip-tools-4.0.0/LICENSE
β β +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-07-25 02:48:28.000000 pip-tools-4.0.0/pip_tools.egg-info/
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 13707 2019-07-25 02:48:28.000000 pip-tools-4.0.0/pip_tools.egg-info/PKG-INFO
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 1 2019-07-25 02:48:28.000000 pip-tools-4.0.0/pip_tools.egg-info/dependency_links.txt
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 9 2019-07-25 02:48:28.000000 pip-tools-4.0.0/pip_tools.egg-info/top_level.txt
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 1 2019-07-25 02:48:28.000000 pip-tools-4.0.0/pip_tools.egg-info/not-zip-safe
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 2201 2019-07-25 02:48:28.000000 pip-tools-4.0.0/pip_tools.egg-info/SOURCES.txt
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 13 2019-07-25 02:48:28.000000 pip-tools-4.0.0/pip_tools.egg-info/requires.txt
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 99 2019-07-25 02:48:28.000000 pip-tools-4.0.0/pip_tools.egg-info/entry_points.txt
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 126 2019-07-25 02:48:06.000000 pip-tools-4.0.0/.coveragerc
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 10323 2019-07-25 02:48:06.000000 pip-tools-4.0.0/README.rst
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 2513 2019-07-25 02:48:06.000000 pip-tools-4.0.0/.appveyor.yml
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 23 2019-07-25 02:48:06.000000 pip-tools-4.0.0/dev-requirements.txt
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 16152 2019-07-25 02:48:06.000000 pip-tools-4.0.0/CHANGELOG.md
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 1892 2019-07-25 02:48:06.000000 pip-tools-4.0.0/setup.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 546 2019-07-25 02:48:06.000000 pip-tools-4.0.0/.pre-commit-config.yaml
β β +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-07-25 02:48:28.000000 pip-tools-4.0.0/tests/
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 13607 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_sync.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 1324 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_top_level_editable.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 3334 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_cache.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 11167 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_resolver.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 390 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_locations.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 4342 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_repository_local.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 4548 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_cli_sync.py
β β +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-07-25 02:48:28.000000 pip-tools-4.0.0/tests/test_data/
β β +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-07-25 02:48:28.000000 pip-tools-4.0.0/tests/test_data/fake_package/
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 599 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_data/fake_package/setup.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 2777 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_data/fake-index.json
β β +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-07-25 02:48:28.000000 pip-tools-4.0.0/tests/test_data/minimal_wheels/
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 1631 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_data/minimal_wheels/small_fake_b-0.2-py2.py3-none-any.whl
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 1632 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_data/minimal_wheels/small_fake_a-0.2-py2.py3-none-any.whl
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 1631 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_data/minimal_wheels/small_fake_a-0.1-py2.py3-none-any.whl
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 1124 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_data/minimal_wheels/small_fake_with_deps-0.1-py2.py3-none-any.whl
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 1635 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_data/minimal_wheels/small_fake_b-0.1-py2.py3-none-any.whl
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 1206 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_data/minimal_wheels/small_fake_a-0.3b1-py2.py3-none-any.whl
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 1026 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_data/minimal_wheels/small_fake_b-0.3-py2.py3-none-any.whl
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 56 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_data/fake-editables.json
β β +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-07-25 02:48:28.000000 pip-tools-4.0.0/tests/test_data/small_fake_package/
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 149 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_data/small_fake_package/setup.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 2019 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_repositories.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 337 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/utils.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 9594 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_writer.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 6307 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_repository_pypi.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 1618 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_minimal_upgrade.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 110 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/__init__.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 24680 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_cli_compile.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 4100 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/conftest.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 2643 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_fake_index.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 10571 2019-07-25 02:48:06.000000 pip-tools-4.0.0/tests/test_utils.py
β β +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-07-25 02:48:28.000000 pip-tools-4.0.0/piptools/
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 5300 2019-07-25 02:48:06.000000 pip-tools-4.0.0/piptools/cache.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 14307 2019-07-25 02:48:06.000000 pip-tools-4.0.0/piptools/resolver.py
β β +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-07-25 02:48:28.000000 pip-tools-4.0.0/piptools/_compat/
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 602 2019-07-25 02:48:06.000000 pip-tools-4.0.0/piptools/_compat/contextlib.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 2862 2019-07-25 02:48:06.000000 pip-tools-4.0.0/piptools/_compat/tempfile.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 2621 2019-07-25 02:48:06.000000 pip-tools-4.0.0/piptools/_compat/pip_compat.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 721 2019-07-25 02:48:06.000000 pip-tools-4.0.0/piptools/_compat/__init__.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 128 2019-07-25 02:48:06.000000 pip-tools-4.0.0/piptools/click.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 800 2019-07-25 02:48:06.000000 pip-tools-4.0.0/piptools/logging.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 267 2019-07-25 02:48:06.000000 pip-tools-4.0.0/piptools/__main__.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 7646 2019-07-25 02:48:06.000000 pip-tools-4.0.0/piptools/writer.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 1907 2019-07-25 02:48:06.000000 pip-tools-4.0.0/piptools/exceptions.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 756 2019-07-25 02:48:06.000000 pip-tools-4.0.0/piptools/locations.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 10968 2019-07-25 02:48:06.000000 pip-tools-4.0.0/piptools/utils.py
β β +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-07-25 02:48:28.000000 pip-tools-4.0.0/piptools/scripts/
β β +-rwxrwxr-x 0 travis (2000) travis (2000) 12606 2019-07-25 02:48:06.000000 pip-tools-4.0.0/piptools/scripts/compile.py
β β +-rwxrwxr-x 0 travis (2000) travis (2000) 4110 2019-07-25 02:48:06.000000 pip-tools-4.0.0/piptools/scripts/sync.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 0 2019-07-25 02:48:06.000000 pip-tools-4.0.0/piptools/scripts/__init__.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 6614 2019-07-25 02:48:06.000000 pip-tools-4.0.0/piptools/sync.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 379 2019-07-25 02:48:06.000000 pip-tools-4.0.0/piptools/__init__.py
β β +drwxrwxr-x 0 travis (2000) travis (2000) 0 2019-07-25 02:48:28.000000 pip-tools-4.0.0/piptools/repositories/
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 15077 2019-07-25 02:48:06.000000 pip-tools-4.0.0/piptools/repositories/pypi.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 2911 2019-07-25 02:48:06.000000 pip-tools-4.0.0/piptools/repositories/local.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 1474 2019-07-25 02:48:06.000000 pip-tools-4.0.0/piptools/repositories/base.py
β β +-rw-rw-r-- 0 travis (2000) travis (2000) 95 2019-07-25 02:48:06.000000 pip-tools-4.0.0/piptools/repositories/__init__.py
β --- pip-tools-3.5.0/tests/test_data/fake-index.json
βββ +++ pip-tools-4.0.0/tests/test_data/fake-index.json
ββ Files similar despite different names (difference score: 4)
β --- /tmp/tmpdjr9hppa_diffoscope/0/44
βββ +++ /tmp/tmp9p46bj79_diffoscope/0/47
β β β @@ -219,14 +219,17 @@
β β β },
β β β "setuptools": {
β β β "34.0.0": {
β β β "": [
β β β "packaging>=16.8",
β β β "appdirs>=1.4.0"
β β β ]
β β β + },
β β β + "35.0.0": {
β β β + "": []
β β β }
β β β },
β β β "six": {
β β β "1.6.1": {
β β β "": []
β β β },
β β β "1.9.0": {
β --- pip-tools-3.5.0/LICENSE
βββ +++ pip-tools-4.0.0/LICENSE
ββ Files similar despite different names (difference score: 0)
β --- pip-tools-3.5.0/.github/PULL_REQUEST_TEMPLATE.md
βββ +++ pip-tools-4.0.0/.github/PULL_REQUEST_TEMPLATE.md
ββ Files similar despite different names (difference score: 0)
β --- pip-tools-3.5.0/piptools/resolver.py
βββ +++ pip-tools-4.0.0/piptools/resolver.py
ββ Files similar despite different names (difference score: 59)
β β @@ -1,33 +1,39 @@
β β # coding: utf-8
β β -from __future__ import (absolute_import, division, print_function,
β β - unicode_literals)
β β +from __future__ import absolute_import, division, print_function, unicode_literals
β β
β β import copy
β β +import os
β β from functools import partial
β β from itertools import chain, count
β β -import os
β β -
β β -from ._compat import install_req_from_line
β β
β β from . import click
β β +from ._compat import install_req_from_line
β β from .cache import DependencyCache
β β -from .exceptions import UnsupportedConstraint
β β from .logging import log
β β -from .utils import (format_requirement, format_specifier, full_groupby,
β β - is_pinned_requirement, key_from_ireq, key_from_req, UNSAFE_PACKAGES)
β β +from .utils import (
β β + UNSAFE_PACKAGES,
β β + format_requirement,
β β + format_specifier,
β β + full_groupby,
β β + is_pinned_requirement,
β β + is_url_requirement,
β β + key_from_ireq,
β β + key_from_req,
β β +)
β β
β β -green = partial(click.style, fg='green')
β β -magenta = partial(click.style, fg='magenta')
β β +green = partial(click.style, fg="green")
β β +magenta = partial(click.style, fg="magenta")
β β
β β
β β class RequirementSummary(object):
β β """
β β Summary of a requirement's properties for comparison purposes.
β β """
β β +
β β def __init__(self, ireq):
β β self.req = ireq.req
β β self.key = key_from_req(ireq.req)
β β self.extras = str(sorted(ireq.extras))
β β self.specifier = str(ireq.specifier)
β β
β β def __eq__(self, other):
β β @@ -36,16 +42,69 @@
β β def __hash__(self):
β β return hash(str(self))
β β
β β def __str__(self):
β β return repr([self.key, self.specifier, self.extras])
β β
β β
β β +def combine_install_requirements(ireqs):
β β + """
β β + Return a single install requirement that reflects a combination of
β β + all the inputs.
β β + """
β β + # We will store the source ireqs in a _source_ireqs attribute;
β β + # if any of the inputs have this, then use those sources directly.
β β + source_ireqs = []
β β + for ireq in ireqs:
β β + source_ireqs.extend(getattr(ireq, "_source_ireqs", [ireq]))
β β + source_ireqs.sort(key=str)
β β +
β β + # deepcopy the accumulator so as to not modify the inputs
β β + combined_ireq = copy.deepcopy(source_ireqs[0])
β β + for ireq in source_ireqs[1:]:
β β + # NOTE we may be losing some info on dropped reqs here
β β + combined_ireq.req.specifier &= ireq.req.specifier
β β + combined_ireq.constraint &= ireq.constraint
β β + # Return a sorted, de-duped tuple of extras
β β + combined_ireq.extras = tuple(
β β + sorted(set(tuple(combined_ireq.extras) + tuple(ireq.extras)))
β β + )
β β +
β β + # InstallRequirements objects are assumed to come from only one source, and
β β + # so they support only a single comes_from entry. This function breaks this
β β + # model. As a workaround, we deterministically choose a single source for
β β + # the comes_from entry, and add an extra _source_ireqs attribute to keep
β β + # track of multiple sources for use within pip-tools.
β β + if len(source_ireqs) > 1:
β β + if any(ireq.comes_from is None for ireq in source_ireqs):
β β + # None indicates package was directly specified.
β β + combined_ireq.comes_from = None
β β + else:
β β + # Populate the comes_from field from one of the sources.
β β + # Requirement input order is not stable, so we need to sort:
β β + # We choose the shortest entry in order to keep the printed
β β + # representation as concise as possible.
β β + combined_ireq.comes_from = min(
β β + (ireq.comes_from for ireq in source_ireqs),
β β + key=lambda x: (len(str(x)), str(x)),
β β + )
β β + combined_ireq._source_ireqs = source_ireqs
β β + return combined_ireq
β β +
β β +
β β class Resolver(object):
β β - def __init__(self, constraints, repository, cache=None, prereleases=False, clear_caches=False, allow_unsafe=False):
β β + def __init__(
β β + self,
β β + constraints,
β β + repository,
β β + cache=None,
β β + prereleases=False,
β β + clear_caches=False,
β β + allow_unsafe=False,
β β + ):
β β """
β β This class resolves a given set of constraints (a collection of
β β InstallRequirement objects) by consulting the given Repository and the
β β DependencyCache.
β β """
β β self.our_constraints = set(constraints)
β β self.their_constraints = set()
β β @@ -56,21 +115,24 @@
β β self.prereleases = prereleases
β β self.clear_caches = clear_caches
β β self.allow_unsafe = allow_unsafe
β β self.unsafe_constraints = set()
β β
β β @property
β β def constraints(self):
β β - return set(self._group_constraints(chain(self.our_constraints,
β β - self.their_constraints)))
β β + return set(
β β + self._group_constraints(chain(self.our_constraints, self.their_constraints))
β β + )
β β
β β def resolve_hashes(self, ireqs):
β β """
β β Finds acceptable hashes for all of the given InstallRequirements.
β β """
β β + log.debug("")
β β + log.debug("Generating hashes:")
β β with self.repository.allow_all_wheels():
β β return {ireq: self.repository.get_hashes(ireq) for ireq in ireqs}
β β
β β def resolve(self, max_rounds=10):
β β """
β β Finds concrete package versions for all the given InstallRequirements
β β and their recursive dependencies. The end result is a flat list of
β β @@ -80,53 +142,69 @@
β β anymore. Protects against infinite loops by breaking out after a max
β β number rounds.
β β """
β β if self.clear_caches:
β β self.dependency_cache.clear()
β β self.repository.clear_caches()
β β
β β - self.check_constraints(chain(self.our_constraints,
β β - self.their_constraints))
β β -
β β # Ignore existing packages
β β - os.environ[str('PIP_EXISTS_ACTION')] = str('i') # NOTE: str() wrapping necessary for Python 2/3 compat
β β - for current_round in count(start=1):
β β + os.environ[str("PIP_EXISTS_ACTION")] = str(
β β + "i"
β β + ) # NOTE: str() wrapping necessary for Python 2/3 compat
β β + for current_round in count(start=1): # pragma: no branch
β β if current_round > max_rounds:
β β - raise RuntimeError('No stable configuration of concrete packages '
β β - 'could be found for the given constraints after '
β β - '%d rounds of resolving.\n'
β β - 'This is likely a bug.' % max_rounds)
β β + raise RuntimeError(
β β + "No stable configuration of concrete packages "
β β + "could be found for the given constraints after "
β β + "%d rounds of resolving.\n"
β β + "This is likely a bug." % max_rounds
β β + )
β β
β β - log.debug('')
β β - log.debug(magenta('{:^60}'.format('ROUND {}'.format(current_round))))
β β + log.debug("")
β β + log.debug(magenta("{:^60}".format("ROUND {}".format(current_round))))
β β has_changed, best_matches = self._resolve_one_round()
β β - log.debug('-' * 60)
β β - log.debug('Result of round {}: {}'.format(current_round,
β β - 'not stable' if has_changed else 'stable, done'))
β β + log.debug("-" * 60)
β β + log.debug(
β β + "Result of round {}: {}".format(
β β + current_round, "not stable" if has_changed else "stable, done"
β β + )
β β + )
β β if not has_changed:
β β break
β β
β β # If a package version (foo==2.0) was built in a previous round,
β β # and in this round a different version of foo needs to be built
β β # (i.e. foo==1.0), the directory will exist already, which will
β β # cause a pip build failure. The trick is to start with a new
β β # build cache dir for every round, so this can never happen.
β β self.repository.freshen_build_caches()
β β
β β - del os.environ['PIP_EXISTS_ACTION']
β β + del os.environ["PIP_EXISTS_ACTION"]
β β +
β β # Only include hard requirements and not pip constraints
β β - return {req for req in best_matches if not req.constraint}
β β + results = {req for req in best_matches if not req.constraint}
β β
β β - @staticmethod
β β - def check_constraints(constraints):
β β - for constraint in constraints:
β β - if constraint.link is not None and not constraint.editable:
β β - msg = ('pip-compile does not support URLs as packages, unless they are editable. '
β β - 'Perhaps add -e option?')
β β - raise UnsupportedConstraint(msg, constraint)
β β + # Filter out unsafe requirements.
β β + self.unsafe_constraints = set()
β β + if not self.allow_unsafe:
β β + # reverse_dependencies is used to filter out packages that are only
β β + # required by unsafe packages. This logic is incomplete, as it would
β β + # fail to filter sub-sub-dependencies of unsafe packages. None of the
β β + # UNSAFE_PACKAGES currently have any dependencies at all (which makes
β β + # sense for installation tools) so this seems sufficient.
β β + reverse_dependencies = self.reverse_dependencies(results)
β β + for req in results.copy():
β β + required_by = reverse_dependencies.get(req.name.lower(), [])
β β + if req.name in UNSAFE_PACKAGES or (
β β + required_by and all(name in UNSAFE_PACKAGES for name in required_by)
β β + ):
β β + self.unsafe_constraints.add(req)
β β + results.remove(req)
β β +
β β + return results
β β
β β def _group_constraints(self, constraints):
β β """
β β Groups constraints (remember, InstallRequirements!) by their key name,
β β and combining their SpecifierSets into a single InstallRequirement per
β β package. For example, given the following constraints:
β β
β β @@ -140,96 +218,75 @@
β β flask~=0.7
β β
β β """
β β for _, ireqs in full_groupby(constraints, key=key_from_ireq):
β β ireqs = list(ireqs)
β β editable_ireq = next((ireq for ireq in ireqs if ireq.editable), None)
β β if editable_ireq:
β β - yield editable_ireq # ignore all the other specs: the editable one is the one that counts
β β + # ignore all the other specs: the editable one is the one that counts
β β + yield editable_ireq
β β continue
β β
β β - ireqs = iter(ireqs)
β β - # deepcopy the accumulator so as to not modify the self.our_constraints invariant
β β - combined_ireq = copy.deepcopy(next(ireqs))
β β - combined_ireq.comes_from = None
β β - for ireq in ireqs:
β β - # NOTE we may be losing some info on dropped reqs here
β β - combined_ireq.req.specifier &= ireq.req.specifier
β β - combined_ireq.constraint &= ireq.constraint
β β - # Return a sorted, de-duped tuple of extras
β β - combined_ireq.extras = tuple(sorted(set(tuple(combined_ireq.extras) + tuple(ireq.extras))))
β β - yield combined_ireq
β β + yield combine_install_requirements(ireqs)
β β
β β def _resolve_one_round(self):
β β """
β β Resolves one level of the current constraints, by finding the best
β β match for each package in the repository and adding all requirements
β β for those best package versions. Some of these constraints may be new
β β or updated.
β β
β β Returns whether new constraints appeared in this round. If no
β β constraints were added or changed, this indicates a stable
β β configuration.
β β """
β β # Sort this list for readability of terminal output
β β constraints = sorted(self.constraints, key=key_from_ireq)
β β - unsafe_constraints = []
β β - original_constraints = copy.copy(constraints)
β β - if not self.allow_unsafe:
β β - for constraint in original_constraints:
β β - if constraint.name in UNSAFE_PACKAGES:
β β - constraints.remove(constraint)
β β - constraint.req.specifier = None
β β - unsafe_constraints.append(constraint)
β β
β β - log.debug('Current constraints:')
β β + log.debug("Current constraints:")
β β for constraint in constraints:
β β - log.debug(' {}'.format(constraint))
β β + log.debug(" {}".format(constraint))
β β
β β - log.debug('')
β β - log.debug('Finding the best candidates:')
β β + log.debug("")
β β + log.debug("Finding the best candidates:")
β β best_matches = {self.get_best_match(ireq) for ireq in constraints}
β β
β β # Find the new set of secondary dependencies
β β - log.debug('')
β β - log.debug('Finding secondary dependencies:')
β β + log.debug("")
β β + log.debug("Finding secondary dependencies:")
β β
β β - safe_constraints = []
β β + their_constraints = []
β β for best_match in best_matches:
β β - for dep in self._iter_dependencies(best_match):
β β - if self.allow_unsafe or dep.name not in UNSAFE_PACKAGES:
β β - safe_constraints.append(dep)
β β + their_constraints.extend(self._iter_dependencies(best_match))
β β # Grouping constraints to make clean diff between rounds
β β - theirs = set(self._group_constraints(safe_constraints))
β β + theirs = set(self._group_constraints(their_constraints))
β β
β β # NOTE: We need to compare RequirementSummary objects, since
β β # InstallRequirement does not define equality
β β - diff = {RequirementSummary(t) for t in theirs} - {RequirementSummary(t) for t in self.their_constraints}
β β - removed = ({RequirementSummary(t) for t in self.their_constraints} -
β β - {RequirementSummary(t) for t in theirs})
β β - unsafe = ({RequirementSummary(t) for t in unsafe_constraints} -
β β - {RequirementSummary(t) for t in self.unsafe_constraints})
β β + diff = {RequirementSummary(t) for t in theirs} - {
β β + RequirementSummary(t) for t in self.their_constraints
β β + }
β β + removed = {RequirementSummary(t) for t in self.their_constraints} - {
β β + RequirementSummary(t) for t in theirs
β β + }
β β
β β - has_changed = len(diff) > 0 or len(removed) > 0 or len(unsafe) > 0
β β + has_changed = len(diff) > 0 or len(removed) > 0
β β if has_changed:
β β - log.debug('')
β β - log.debug('New dependencies found in this round:')
β β + log.debug("")
β β + log.debug("New dependencies found in this round:")
β β for new_dependency in sorted(diff, key=lambda req: key_from_req(req.req)):
β β - log.debug(' adding {}'.format(new_dependency))
β β - log.debug('Removed dependencies in this round:')
β β - for removed_dependency in sorted(removed, key=lambda req: key_from_req(req.req)):
β β - log.debug(' removing {}'.format(removed_dependency))
β β - log.debug('Unsafe dependencies in this round:')
β β - for unsafe_dependency in sorted(unsafe, key=lambda req: key_from_req(req.req)):
β β - log.debug(' remembering unsafe {}'.format(unsafe_dependency))
β β + log.debug(" adding {}".format(new_dependency))
β β + log.debug("Removed dependencies in this round:")
β β + for removed_dependency in sorted(
β β + removed, key=lambda req: key_from_req(req.req)
β β + ):
β β + log.debug(" removing {}".format(removed_dependency))
β β
β β # Store the last round's results in the their_constraints
β β self.their_constraints = theirs
β β - # Store the last round's unsafe constraints
β β - self.unsafe_constraints = unsafe_constraints
β β return has_changed, best_matches
β β
β β def get_best_match(self, ireq):
β β """
β β Returns a (pinned or editable) InstallRequirement, indicating the best
β β match to use for the given InstallRequirement (in the form of an
β β InstallRequirement).
β β @@ -239,58 +296,79 @@
β β a certain moment in time.
β β
β β Pinned requirements will always return themselves, i.e.
β β
β β Flask==0.10.1 => Flask==0.10.1
β β
β β """
β β - if ireq.editable:
β β + if ireq.editable or is_url_requirement(ireq):
β β # NOTE: it's much quicker to immediately return instead of
β β # hitting the index server
β β best_match = ireq
β β elif is_pinned_requirement(ireq):
β β # NOTE: it's much quicker to immediately return instead of
β β # hitting the index server
β β best_match = ireq
β β else:
β β - best_match = self.repository.find_best_match(ireq, prereleases=self.prereleases)
β β + best_match = self.repository.find_best_match(
β β + ireq, prereleases=self.prereleases
β β + )
β β
β β # Format the best match
β β - log.debug(' found candidate {} (constraint was {})'.format(format_requirement(best_match),
β β - format_specifier(ireq)))
β β + log.debug(
β β + " found candidate {} (constraint was {})".format(
β β + format_requirement(best_match), format_specifier(ireq)
β β + )
β β + )
β β + best_match.comes_from = ireq.comes_from
β β return best_match
β β
β β def _iter_dependencies(self, ireq):
β β """
β β - Given a pinned or editable InstallRequirement, collects all the
β β + Given a pinned, url, or editable InstallRequirement, collects all the
β β secondary dependencies for them, either by looking them up in a local
β β cache, or by reaching out to the repository.
β β
β β Editable requirements will never be looked up, as they may have
β β changed at any time.
β β """
β β - if ireq.editable:
β β + if ireq.editable or is_url_requirement(ireq):
β β for dependency in self.repository.get_dependencies(ireq):
β β yield dependency
β β return
β β elif not is_pinned_requirement(ireq):
β β - raise TypeError('Expected pinned or editable requirement, got {}'.format(ireq))
β β + raise TypeError(
β β + "Expected pinned or editable requirement, got {}".format(ireq)
β β + )
β β
β β # Now, either get the dependencies from the dependency cache (for
β β # speed), or reach out to the external repository to
β β # download and inspect the package version and get dependencies
β β # from there
β β if ireq not in self.dependency_cache:
β β - log.debug(' {} not in cache, need to check index'.format(format_requirement(ireq)), fg='yellow')
β β + log.debug(
β β + " {} not in cache, need to check index".format(
β β + format_requirement(ireq)
β β + ),
β β + fg="yellow",
β β + )
β β dependencies = self.repository.get_dependencies(ireq)
β β self.dependency_cache[ireq] = sorted(str(ireq.req) for ireq in dependencies)
β β
β β # Example: ['Werkzeug>=0.9', 'Jinja2>=2.4']
β β dependency_strings = self.dependency_cache[ireq]
β β - log.debug(' {:25} requires {}'.format(format_requirement(ireq),
β β - ', '.join(sorted(dependency_strings, key=lambda s: s.lower())) or '-'))
β β + log.debug(
β β + " {:25} requires {}".format(
β β + format_requirement(ireq),
β β + ", ".join(sorted(dependency_strings, key=lambda s: s.lower())) or "-",
β β + )
β β + )
β β for dependency_string in dependency_strings:
β β - yield install_req_from_line(dependency_string, constraint=ireq.constraint)
β β + yield install_req_from_line(
β β + dependency_string, constraint=ireq.constraint, comes_from=ireq
β β + )
β β
β β def reverse_dependencies(self, ireqs):
β β - non_editable = [ireq for ireq in ireqs if not ireq.editable]
β β + non_editable = [
β β + ireq for ireq in ireqs if not (ireq.editable or is_url_requirement(ireq))
β β + ]
β β return self.dependency_cache.reverse_dependencies(non_editable)
β --- pip-tools-3.5.0/piptools/cache.py
βββ +++ pip-tools-4.0.0/piptools/cache.py
ββ Files similar despite different names (difference score: 44)
β β @@ -1,10 +1,9 @@
β β # coding: utf-8
β β -from __future__ import (absolute_import, division, print_function,
β β - unicode_literals)
β β +from __future__ import absolute_import, division, print_function, unicode_literals
β β
β β import json
β β import os
β β import sys
β β
β β from pip._vendor.packaging.requirements import Requirement
β β
β β @@ -15,50 +14,52 @@
β β
β β class CorruptCacheError(PipToolsError):
β β def __init__(self, path):
β β self.path = path
β β
β β def __str__(self):
β β lines = [
β β - 'The dependency cache seems to have been corrupted.',
β β - 'Inspect, or delete, the following file:',
β β - ' {}'.format(self.path),
β β + "The dependency cache seems to have been corrupted.",
β β + "Inspect, or delete, the following file:",
β β + " {}".format(self.path),
β β ]
β β return os.linesep.join(lines)
β β
β β
β β def read_cache_file(cache_file_path):
β β - with open(cache_file_path, 'r') as cache_file:
β β + with open(cache_file_path, "r") as cache_file:
β β try:
β β doc = json.load(cache_file)
β β except ValueError:
β β raise CorruptCacheError(cache_file_path)
β β
β β # Check version and load the contents
β β - assert doc['__format__'] == 1, 'Unknown cache file format'
β β - return doc['dependencies']
β β + if doc["__format__"] != 1:
β β + raise AssertionError("Unknown cache file format")
β β + return doc["dependencies"]
β β
β β
β β class DependencyCache(object):
β β """
β β Creates a new persistent dependency cache for the current Python version.
β β The cache file is written to the appropriate user cache dir for the
β β current platform, i.e.
β β
β β ~/.cache/pip-tools/depcache-pyX.Y.json
β β
β β Where X.Y indicates the Python version.
β β """
β β +
β β def __init__(self, cache_dir=None):
β β if cache_dir is None:
β β cache_dir = CACHE_DIR
β β if not os.path.isdir(cache_dir):
β β os.makedirs(cache_dir)
β β - py_version = '.'.join(str(digit) for digit in sys.version_info[:2])
β β - cache_filename = 'depcache-py{}.json'.format(py_version)
β β + py_version = ".".join(str(digit) for digit in sys.version_info[:2])
β β + cache_filename = "depcache-py{}.json".format(py_version)
β β
β β self._cache_file = os.path.join(cache_dir, cache_filename)
β β self._cache = None
β β
β β @property
β β def cache(self):
β β """
β β @@ -67,21 +68,22 @@
β β """
β β if self._cache is None:
β β self.read_cache()
β β return self._cache
β β
β β def as_cache_key(self, ireq):
β β """
β β - Given a requirement, return its cache key. This behavior is a little weird in order to allow backwards
β β - compatibility with cache files. For a requirement without extras, this will return, for example:
β β + Given a requirement, return its cache key. This behavior is a little weird
β β + in order to allow backwards compatibility with cache files. For a requirement
β β + without extras, this will return, for example:
β β
β β ("ipython", "2.1.0")
β β
β β - For a requirement with extras, the extras will be comma-separated and appended to the version, inside brackets,
β β - like so:
β β + For a requirement with extras, the extras will be comma-separated and appended
β β + to the version, inside brackets, like so:
β β
β β ("ipython", "2.1.0[nbconvert,notebook]")
β β """
β β name, version, extras = as_tuple(ireq)
β β if not extras:
β β extras_string = ""
β β else:
β β @@ -93,19 +95,16 @@
β β if os.path.exists(self._cache_file):
β β self._cache = read_cache_file(self._cache_file)
β β else:
β β self._cache = {}
β β
β β def write_cache(self):
β β """Writes the cache to disk as JSON."""
β β - doc = {
β β - '__format__': 1,
β β - 'dependencies': self._cache,
β β - }
β β - with open(self._cache_file, 'w') as f:
β β + doc = {"__format__": 1, "dependencies": self._cache}
β β + with open(self._cache_file, "w") as f:
β β json.dump(doc, f, sort_keys=True)
β β
β β def clear(self):
β β self._cache = {}
β β self.write_cache()
β β
β β def __contains__(self, ireq):
β β @@ -118,18 +117,14 @@
β β
β β def __setitem__(self, ireq, values):
β β pkgname, pkgversion_and_extras = self.as_cache_key(ireq)
β β self.cache.setdefault(pkgname, {})
β β self.cache[pkgname][pkgversion_and_extras] = values
β β self.write_cache()
β β
β β - def get(self, ireq, default=None):
β β - pkgname, pkgversion_and_extras = self.as_cache_key(ireq)
β β - return self.cache.get(pkgname, {}).get(pkgversion_and_extras, default)
β β -
β β def reverse_dependencies(self, ireqs):
β β """
β β Returns a lookup table of reverse dependencies for all the given ireqs.
β β
β β Since this is all static, it only works if the dependency cache
β β contains the complete data, otherwise you end up with a partial view.
β β This is typically no problem if you use this function after the entire
β β @@ -153,12 +148,14 @@
β β
β β {'pep8': ['flake8'],
β β 'flake8': [],
β β 'mccabe': ['flake8'],
β β 'pyflakes': ['flake8']}
β β
β β """
β β - # First, collect all the dependencies into a sequence of (parent, child) tuples, like [('flake8', 'pep8'),
β β - # ('flake8', 'mccabe'), ...]
β β - return lookup_table((key_from_req(Requirement(dep_name)), name)
β β - for name, version_and_extras in cache_keys
β β - for dep_name in self.cache[name][version_and_extras])
β β + # First, collect all the dependencies into a sequence of (parent, child)
β β + # tuples, like [('flake8', 'pep8'), ('flake8', 'mccabe'), ...]
β β + return lookup_table(
β β + (key_from_req(Requirement(dep_name)), name)
β β + for name, version_and_extras in cache_keys
β β + for dep_name in self.cache[name][version_and_extras]
β β + )
β --- pip-tools-3.5.0/tests/test_data/minimal_wheels/small_fake_a-0.1-py2.py3-none-any.whl
βββ +++ pip-tools-4.0.0/tests/test_data/minimal_wheels/small_fake_a-0.1-py2.py3-none-any.whl
ββ Files similar despite different names (difference score: 0)
β --- pip-tools-3.5.0/tests/test_minimal_upgrade.py
βββ +++ pip-tools-4.0.0/tests/test_minimal_upgrade.py
ββ Files similar despite different names (difference score: 50)
β β @@ -1,38 +1,46 @@
β β import pytest
β β +
β β from piptools.repositories import LocalRequirementsRepository
β β from piptools.utils import name_from_req
β β
β β
β β @pytest.mark.parametrize(
β β - ('input', 'pins', 'expected'),
β β -
β β - ((tup) for tup in [
β β -
β β - # Add Flask to an existing requirements.in, using --no-upgrade
β β - (['flask', 'jinja2', 'werkzeug'],
β β - [
β β - # The requirements.txt from a previous round
β β - 'jinja2==2.7.3',
β β - 'markupsafe==0.23',
β β - 'werkzeug==0.6'],
β β - [
β β - # Add flask and upgrade werkzeug from incompatible 0.6
β β - 'flask==0.10.1',
β β - 'itsdangerous==0.24',
β β - 'werkzeug==0.10.4',
β β - # Other requirements are unchanged from the original requirements.txt
β β - 'jinja2==2.7.3',
β β - 'markupsafe==0.23']
β β - ),
β β - ])
β β + ("input", "pins", "expected"),
β β + (
β β + (tup)
β β + for tup in [
β β + # Add Flask to an existing requirements.in, using --no-upgrade
β β + (
β β + ["flask", "jinja2", "werkzeug"],
β β + [
β β + # The requirements.txt from a previous round
β β + "jinja2==2.7.3",
β β + "markupsafe==0.23",
β β + "werkzeug==0.6",
β β + ],
β β + [
β β + # Add flask and upgrade werkzeug from incompatible 0.6
β β + "flask==0.10.1",
β β + "itsdangerous==0.24 (from flask==0.10.1)",
β β + "werkzeug==0.10.4",
β β + # Other requirements are unchanged from
β β + # the original requirements.txt
β β + "jinja2==2.7.3",
β β + "markupsafe==0.23 (from jinja2==2.7.3)",
β β + ],
β β + )
β β + ]
β β + ),
β β )
β β def test_no_upgrades(base_resolver, repository, from_line, input, pins, expected):
β β input = [from_line(line) for line in input]
β β existing_pins = dict()
β β for line in pins:
β β ireq = from_line(line)
β β existing_pins[name_from_req(ireq.req)] = ireq
β β local_repository = LocalRequirementsRepository(existing_pins, repository)
β β - output = base_resolver(input, prereleases=False, repository=local_repository).resolve()
β β + output = base_resolver(
β β + input, prereleases=False, repository=local_repository
β β + ).resolve()
β β output = {str(line) for line in output}
β β assert output == {str(line) for line in expected}
β --- pip-tools-3.5.0/tests/test_data/minimal_wheels/small_fake_b-0.3-py2.py3-none-any.whl
βββ +++ pip-tools-4.0.0/tests/test_data/minimal_wheels/small_fake_b-0.3-py2.py3-none-any.whl
ββ Files similar despite different names (difference score: 0)
β --- pip-tools-3.5.0/tests/test_cli_sync.py
βββ +++ pip-tools-4.0.0/tests/test_cli_sync.py
ββ Files similar despite different names (difference score: 59)
β β @@ -1,136 +1,149 @@
β β import sys
β β
β β import mock
β β import pytest
β β -from click.testing import CliRunner
β β
β β -from piptools.scripts.sync import cli
β β from .utils import invoke
β β
β β +from piptools.scripts.sync import cli
β β +
β β
β β def test_run_as_module_sync():
β β """piptools can be run as ``python -m piptools ...``."""
β β
β β - status, output = invoke([
β β - sys.executable, '-m', 'piptools', 'sync', '--help',
β β - ])
β β + status, output = invoke([sys.executable, "-m", "piptools", "sync", "--help"])
β β
β β # Should have run pip-compile successfully.
β β - output = output.decode('utf-8')
β β - assert output.startswith('Usage:')
β β - assert 'Synchronize virtual environment with' in output
β β + output = output.decode("utf-8")
β β + assert output.startswith("Usage:")
β β + assert "Synchronize virtual environment with" in output
β β assert status == 0
β β
β β
β β -def test_quiet_option(tmpdir):
β β [email protected]("piptools.sync.check_call")
β β +def test_quiet_option(check_call, runner):
β β """sync command can be run with `--quiet` or `-q` flag."""
β β
β β - runner = CliRunner()
β β - with runner.isolated_filesystem():
β β - with open('requirements.txt', 'w') as req_in:
β β - req_in.write('six==1.10.0')
β β -
β β - with mock.patch('piptools.sync.check_call') as check_call:
β β - out = runner.invoke(cli, ['-q'])
β β - assert out.output == ''
β β - assert out.exit_code == 0
β β - # for every call to pip ensure the `-q` flag is set
β β - for call in check_call.call_args_list:
β β - assert '-q' in call[0][0]
β β + with open("requirements.txt", "w") as req_in:
β β + req_in.write("six==1.10.0")
β β +
β β + out = runner.invoke(cli, ["-q"])
β β + assert not out.stderr_bytes
β β + assert out.exit_code == 0
β β +
β β + # for every call to pip ensure the `-q` flag is set
β β + assert check_call.call_count == 2
β β + for call in check_call.call_args_list:
β β + assert "-q" in call[0][0]
β β +
β β +
β β [email protected]("piptools.sync.check_call")
β β +def test_quiet_option_when_up_to_date(check_call, runner):
β β + """
β β + Sync should output nothing when everything is up to date and quiet option is set.
β β + """
β β + with open("requirements.txt", "w"):
β β + pass
β β +
β β + with mock.patch("piptools.sync.diff", return_value=(set(), set())):
β β + out = runner.invoke(cli, ["-q"])
β β +
β β + assert not out.stderr_bytes
β β + assert out.exit_code == 0
β β + check_call.assert_not_called()
β β
β β
β β def test_no_requirements_file(runner):
β β """
β β It should raise an error if there are no input files
β β or a requirements.txt file does not exist.
β β """
β β out = runner.invoke(cli)
β β
β β - assert 'No requirement files given' in out.output
β β + assert "No requirement files given" in out.stderr
β β assert out.exit_code == 2
β β
β β
β β def test_input_files_with_dot_in_extension(runner):
β β """
β β It should raise an error if some of the input files have .in extension.
β β """
β β - with open('requirements.in', 'w') as req_in:
β β - req_in.write('six==1.10.0')
β β + with open("requirements.in", "w") as req_in:
β β + req_in.write("six==1.10.0")
β β
β β - out = runner.invoke(cli, ['requirements.in'])
β β + out = runner.invoke(cli, ["requirements.in"])
β β
β β - assert 'ERROR: Some input files have the .in extension' in out.output
β β + assert "ERROR: Some input files have the .in extension" in out.stderr
β β assert out.exit_code == 2
β β
β β
β β def test_force_files_with_dot_in_extension(runner):
β β """
β β - It should print a warning and sync anyway if some of the input files have .in extension.
β β + It should print a warning and sync anyway if some of the input files
β β + have .in extension.
β β """
β β
β β - with open('requirements.in', 'w') as req_in:
β β - req_in.write('six==1.10.0')
β β + with open("requirements.in", "w") as req_in:
β β + req_in.write("six==1.10.0")
β β
β β - with mock.patch('piptools.sync.check_call'):
β β - out = runner.invoke(cli, ['requirements.in', '--force'])
β β + with mock.patch("piptools.sync.check_call"):
β β + out = runner.invoke(cli, ["requirements.in", "--force"])
β β
β β - assert 'WARNING: Some input files have the .in extension' in out.output
β β + assert "WARNING: Some input files have the .in extension" in out.stderr
β β assert out.exit_code == 0
β β
β β
β β def test_merge_error(runner):
β β """
β β Sync command should raise an error if there are merge errors.
β β """
β β - with open('requirements.txt', 'w') as req_in:
β β - req_in.write('six>1.10.0\n')
β β + with open("requirements.txt", "w") as req_in:
β β + req_in.write("six>1.10.0\n")
β β
β β # Add incompatible package
β β - req_in.write('six<1.10.0')
β β + req_in.write("six<1.10.0")
β β
β β - with mock.patch('piptools.sync.check_call'):
β β - out = runner.invoke(cli, ['-n'])
β β + with mock.patch("piptools.sync.check_call"):
β β + out = runner.invoke(cli, ["-n"])
β β
β β assert out.exit_code == 2
β β - assert 'Incompatible requirements found' in out.output
β β + assert "Incompatible requirements found" in out.stderr
β β
β β
β β @pytest.mark.parametrize(
β β - ('cli_flags', 'expected_install_flags'),
β β + ("cli_flags", "expected_install_flags"),
β β [
β β - (['--find-links', './libs'], ['-f', './libs']),
β β - (['--no-index'], ['--no-index']),
β β - (['--index-url', 'https://example.com'], ['-i', 'https://example.com']),
β β + (["--find-links", "./libs"], ["-f", "./libs"]),
β β + (["--no-index"], ["--no-index"]),
β β + (["--index-url", "https://example.com"], ["-i", "https://example.com"]),
β β (
β β - [
β β - '--extra-index-url', 'https://foo',
β β - '--extra-index-url', 'https://bar',
β β - ],
β β - [
β β - '--extra-index-url', 'https://foo',
β β - '--extra-index-url', 'https://bar',
β β - ]
β β + ["--extra-index-url", "https://foo", "--extra-index-url", "https://bar"],
β β + ["--extra-index-url", "https://foo", "--extra-index-url", "https://bar"],
β β ),
β β - (['--user'], ['--user']),
β β - ]
β β + (
β β + ["--trusted-host", "https://foo", "--trusted-host", "https://bar"],
β β + ["--trusted-host", "https://foo", "--trusted-host", "https://bar"],
β β + ),
β β + (
β β + ["--extra-index-url", "https://foo", "--trusted-host", "https://bar"],
β β + ["--extra-index-url", "https://foo", "--trusted-host", "https://bar"],
β β + ),
β β + (["--user"], ["--user"]),
β β + (["--cert", "foo.crt"], ["--cert", "foo.crt"]),
β β + (["--client-cert", "foo.pem"], ["--client-cert", "foo.pem"]),
β β + ],
β β )
β β [email protected]('piptools.sync.check_call')
β β [email protected]("piptools.sync.check_call")
β β def test_pip_install_flags(check_call, cli_flags, expected_install_flags, runner):
β β """
β β Test the cli flags have to be passed to the pip install command.
β β """
β β - with open('requirements.txt', 'w') as req_in:
β β - req_in.write('six==1.10.0')
β β + with open("requirements.txt", "w") as req_in:
β β + req_in.write("six==1.10.0")
β β
β β runner.invoke(cli, cli_flags)
β β
β β - for call in check_call.call_args_list:
β β - check_call_args = call[0][0]
β β - pip_command = check_call_args[3]
β β -
β β - # Skip uninstall command
β β - if pip_command != 'install':
β β - continue
β β -
β β - install_flags = check_call_args[6:]
β β - assert install_flags == expected_install_flags
β β + call_args = [call[0][0] for call in check_call.call_args_list]
β β + assert [args[6:] for args in call_args if args[3] == "install"] == [
β β + expected_install_flags
β β + ]
β --- pip-tools-3.5.0/pip_tools.egg-info/SOURCES.txt
βββ +++ pip-tools-4.0.0/pip_tools.egg-info/SOURCES.txt
ββ Files similar despite different names (difference score: 6)
β β @@ -1,11 +1,13 @@
β β .appveyor.yml
β β +.bandit
β β .coveragerc
β β -.flake8
β β +.fussyfox.yml
β β .gitignore
β β +.pre-commit-config.yaml
β β .travis.yml
β β CHANGELOG.md
β β CONTRIBUTING.md
β β LICENSE
β β README.rst
β β dev-requirements.txt
β β setup.cfg
β β @@ -27,18 +29,16 @@
β β pip_tools.egg-info/requires.txt
β β pip_tools.egg-info/top_level.txt
β β piptools/__init__.py
β β piptools/__main__.py
β β piptools/cache.py
β β piptools/click.py
β β piptools/exceptions.py
β β -piptools/io.py
β β piptools/locations.py
β β piptools/logging.py
β β -piptools/pip.py
β β piptools/resolver.py
β β piptools/sync.py
β β piptools/utils.py
β β piptools/writer.py
β β piptools/_compat/__init__.py
β β piptools/_compat/contextlib.py
β β piptools/_compat/pip_compat.py
β β @@ -52,14 +52,15 @@
β β piptools/scripts/sync.py
β β tests/__init__.py
β β tests/conftest.py
β β tests/test_cache.py
β β tests/test_cli_compile.py
β β tests/test_cli_sync.py
β β tests/test_fake_index.py
β β +tests/test_locations.py
β β tests/test_minimal_upgrade.py
β β tests/test_repositories.py
β β tests/test_repository_local.py
β β tests/test_repository_pypi.py
β β tests/test_resolver.py
β β tests/test_sync.py
β β tests/test_top_level_editable.py
β β @@ -67,12 +68,13 @@
β β tests/test_writer.py
β β tests/utils.py
β β tests/test_data/fake-editables.json
β β tests/test_data/fake-index.json
β β tests/test_data/fake_package/setup.py
β β tests/test_data/minimal_wheels/small_fake_a-0.1-py2.py3-none-any.whl
β β tests/test_data/minimal_wheels/small_fake_a-0.2-py2.py3-none-any.whl
β β +tests/test_data/minimal_wheels/small_fake_a-0.3b1-py2.py3-none-any.whl
β β tests/test_data/minimal_wheels/small_fake_b-0.1-py2.py3-none-any.whl
β β tests/test_data/minimal_wheels/small_fake_b-0.2-py2.py3-none-any.whl
β β tests/test_data/minimal_wheels/small_fake_b-0.3-py2.py3-none-any.whl
β β tests/test_data/minimal_wheels/small_fake_with_deps-0.1-py2.py3-none-any.whl
β β tests/test_data/small_fake_package/setup.py
β --- pip-tools-3.5.0/CONTRIBUTING.md
βββ +++ pip-tools-4.0.0/CONTRIBUTING.md
ββ Files similar despite different names (difference score: 18)
β β @@ -3,14 +3,15 @@
β β This is a [Jazzband](https://jazzband.co/) project. By contributing you agree
β β to abide by the [Contributor Code of Conduct](https://jazzband.co/about/conduct)
β β and follow the [guidelines](https://jazzband.co/about/guidelines).
β β
β β ## Project Contribution Guidelines
β β
β β Here are a few additional or emphasized guidelines to follow when contributing to pip-tools:
β β +- Check with `tox -e checkqa` to see your changes are not breaking the style conventions.
β β - Always provide tests for your changes.
β β - Give a clear one-line description in the PR (that the maintainers can add to [CHANGELOG](CHANGELOG.md) afterwards).
β β - Wait for the review of at least one other contributor before merging (even if you're a Jazzband member).
β β - Before merging, assign the PR to a milestone for a version to help with the release process.
β β
β β The only exception to those guidelines is for trivial changes, such as
β β documentation corrections or contributions that do not change pip-tools itself.
β --- pip-tools-3.5.0/piptools/repositories/base.py
βββ +++ pip-tools-4.0.0/piptools/repositories/base.py
ββ Files similar despite different names (difference score: 22)
β β @@ -1,20 +1,18 @@
β β # coding: utf-8
β β -from __future__ import (absolute_import, division, print_function,
β β - unicode_literals)
β β +from __future__ import absolute_import, division, print_function, unicode_literals
β β
β β from abc import ABCMeta, abstractmethod
β β from contextlib import contextmanager
β β
β β from six import add_metaclass
β β
β β
β β @add_metaclass(ABCMeta)
β β class BaseRepository(object):
β β -
β β def clear_caches(self):
β β """Should clear any caches used by the implementation."""
β β
β β def freshen_build_caches(self):
β β """Should start with fresh build/source caches."""
β β
β β @abstractmethod
β β @@ -23,15 +21,15 @@
β β Return a Version object that indicates the best match for the given
β β InstallRequirement according to the repository.
β β """
β β
β β @abstractmethod
β β def get_dependencies(self, ireq):
β β """
β β - Given a pinned or an editable InstallRequirement, returns a set of
β β + Given a pinned, URL, or editable InstallRequirement, returns a set of
β β dependencies (also InstallRequirements, but not necessarily pinned).
β β They indicate the secondary dependencies for the given requirement.
β β """
β β
β β @abstractmethod
β β def get_hashes(self, ireq):
β β """
β --- pip-tools-3.5.0/tests/test_data/minimal_wheels/small_fake_with_deps-0.1-py2.py3-none-any.whl
βββ +++ pip-tools-4.0.0/tests/test_data/minimal_wheels/small_fake_with_deps-0.1-py2.py3-none-any.whl
ββ Files similar despite different names (difference score: 0)
β --- pip-tools-3.5.0/piptools/_compat/tempfile.py
βββ +++ pip-tools-4.0.0/piptools/_compat/tempfile.py
ββ Files similar despite different names (difference score: 6)
β β @@ -36,16 +36,18 @@
β β self._rmtree(self.name)
β β except (TypeError, AttributeError) as ex:
β β # Issue #10188: Emit a warning on stderr
β β # if the directory could not be cleaned
β β # up due to missing globals
β β if "None" not in str(ex):
β β raise
β β - print("ERROR: {!r} while cleaning up {!r}".format(ex, self,),
β β - file=_sys.stderr)
β β + print(
β β + "ERROR: {!r} while cleaning up {!r}".format(ex, self),
β β + file=_sys.stderr,
β β + )
β β return
β β self._closed = True
β β
β β def __exit__(self, exc, value, tb):
β β self.cleanup()
β β
β β def __del__(self):
β --- pip-tools-3.5.0/.appveyor.yml
βββ +++ pip-tools-4.0.0/.appveyor.yml
ββ Files similar despite different names (difference score: 33)
β β @@ -11,48 +11,35 @@
β β PIP: 9.0.3
β β - TOXENV: py27-pip10.0.1
β β PIP: 10.0.1
β β - TOXENV: py27-pip18.0
β β PIP: 18.0
β β - TOXENV: py27-pip19.0
β β PIP: 19.0
β β + - TOXENV: py27-pip19.1
β β + PIP: 19.1
β β - TOXENV: py27-pipmaster
β β PIP: master
β β - TOXENV: py27-piplatest-coverage
β β PIP: latest
β β
β β - - TOXENV: py34-pip8.1.1
β β - PIP: 8.1.1
β β - - TOXENV: py34-pip9.0.1
β β - PIP: 9.0.1
β β - - TOXENV: py34-pip9.0.3-coverage
β β - PIP: 9.0.3
β β - - TOXENV: py34-pip10.0.1
β β - PIP: 10.0.1
β β - - TOXENV: py34-pip18.0
β β - PIP: 18.0
β β - - TOXENV: py34-pip19.0
β β - PIP: 19.0
β β - - TOXENV: py34-pipmaster
β β - PIP: master
β β - - TOXENV: py34-piplatest
β β - PIP: latest
β β -
β β - TOXENV: py35-pip8.1.1
β β PIP: 8.1.1
β β - TOXENV: py35-pip9.0.1
β β PIP: 9.0.1
β β - TOXENV: py35-pip9.0.3
β β PIP: 9.0.3
β β - TOXENV: py35-pip10.0.1
β β PIP: 10.0.1
β β - TOXENV: py35-pip18.0-coverage
β β PIP: 18.0
β β - TOXENV: py35-pip19.0
β β PIP: 19.0
β β + - TOXENV: py35-pip19.1
β β + PIP: 19.1
β β - TOXENV: py35-pipmaster
β β PIP: master
β β - TOXENV: py35-piplatest
β β PIP: latest
β β
β β - TOXENV: py36-pip8.1.1
β β PIP: 8.1.1
β β @@ -62,14 +49,16 @@
β β PIP: 9.0.3
β β - TOXENV: py36-pip10.0.1
β β PIP: 10.0.1
β β - TOXENV: py36-pip18.0
β β PIP: 18.0
β β - TOXENV: py36-pip19.0-coverage
β β PIP: 19.0
β β + - TOXENV: py36-pip19.1
β β + PIP: 19.1
β β - TOXENV: py36-pipmaster
β β PIP: master
β β - TOXENV: py36-piplatest
β β PIP: latest
β β
β β - TOXENV: py37-pip8.1.1
β β PIP: 8.1.1
β β @@ -79,14 +68,16 @@
β β PIP: 9.0.3
β β - TOXENV: py37-pip10.0.1
β β PIP: 10.0.1
β β - TOXENV: py37-pip18.0
β β PIP: 18.0
β β - TOXENV: py37-pip19.0
β β PIP: 19.0
β β + - TOXENV: py37-pip19.1-coverage
β β + PIP: 19.1
β β - TOXENV: py37-pipmaster-coverage
β β PIP: master
β β - TOXENV: py37-piplatest-coverage
β β PIP: latest
β β
β β matrix:
β β fast_finish: true
β --- pip-tools-3.5.0/pip_tools.egg-info/PKG-INFO
βββ +++ pip-tools-4.0.0/pip_tools.egg-info/PKG-INFO
ββ Files similar despite different names (difference score: 56)
β β @@ -1,44 +1,44 @@
β β -Metadata-Version: 1.2
β β +Metadata-Version: 2.1
β β Name: pip-tools
β β -Version: 3.5.0
β β +Version: 4.0.0
β β Summary: pip-tools keeps your pinned dependencies fresh.
β β Home-page: https://github.com/jazzband/pip-tools/
β β Author: Vincent Driessen
β β Author-email: [email protected]
β β License: BSD
β β -Description: |buildstatus-travis| |buildstatus-appveyor| |codecov| |coveralls| |jazzband| |pypi|
β β +Description: |jazzband| |pypi| |pyversions| |buildstatus-travis| |buildstatus-appveyor| |codecov|
β β
β β ==================================
β β 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?`_
β β
β β .. image:: https://github.com/jazzband/pip-tools/raw/master/img/pip-tools-overview.png
β β :alt: pip-tools overview for phase II
β β
β β - .. |buildstatus-travis| image:: https://img.shields.io/travis/jazzband/pip-tools/master.svg
β β - :alt: Travis-CI build status
β β + .. |buildstatus-travis| image:: https://img.shields.io/travis/jazzband/pip-tools/master.svg?logo=travis
β β + :alt: Travis CI build status
β β :target: https://travis-ci.org/jazzband/pip-tools
β β - .. |buildstatus-appveyor| image:: https://img.shields.io/appveyor/ci/jazzband/pip-tools/master.svg
β β - :alt: Appveyor build status
β β + .. |buildstatus-appveyor| image:: https://img.shields.io/appveyor/ci/jazzband/pip-tools/master.svg?logo=appveyor
β β + :alt: AppVeyor build status
β β :target: https://ci.appveyor.com/project/jazzband/pip-tools
β β .. |codecov| image:: https://codecov.io/gh/jazzband/pip-tools/branch/master/graph/badge.svg
β β - :alt: Codecov
β β + :alt: Coverage
β β :target: https://codecov.io/gh/jazzband/pip-tools
β β - .. |coveralls| image:: https://coveralls.io/repos/github/jazzband/pip-tools/badge.svg?branch=master
β β - :alt: Coveralls
β β - :target: https://coveralls.io/github/jazzband/pip-tools?branch=master
β β .. |jazzband| image:: https://jazzband.co/static/img/badge.svg
β β :alt: Jazzband
β β :target: https://jazzband.co/
β β .. |pypi| image:: https://img.shields.io/pypi/v/pip-tools.svg
β β - :alt: PyPI
β β + :alt: PyPI version
β β + :target: https://pypi.org/project/pip-tools/
β β + .. |pyversions| image:: https://img.shields.io/pypi/pyversions/pip-tools.svg
β β + :alt: Supported Python versions
β β :target: https://pypi.org/project/pip-tools/
β β .. _You do pin them, right?: http://nvie.com/posts/pin-your-packages/
β β
β β
β β Installation
β β ============
β β
β β @@ -54,14 +54,21 @@
β β project's virtual environment.
β β
β β .. _virtual environment: https://packaging.python.org/tutorials/installing-packages/#creating-virtual-environments
β β
β β 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.
β β +
β β Requirements from ``setup.py``
β β ------------------------------
β β
β β Suppose you have a Flask project, and want to pin it for production.
β β If you have a ``setup.py`` with ``install_requires=['Flask']``, then run
β β ``pip-compile`` without any arguments:
β β
β β @@ -114,15 +121,15 @@
β β markupsafe==1.0 # via jinja2
β β werkzeug==0.12.2 # via flask
β β
β β And it will produce your ``requirements.txt``, with all the Flask dependencies
β β (and all underlying dependencies) pinned. You should put both
β β ``requirements.in`` and ``requirements.txt`` under version control.
β β
β β - .. _it's easy to write one: https://packaging.python.org/distributing/#configuring-your-project
β β + .. _it's easy to write one: https://packaging.python.org/guides/distributing-packages-using-setuptools/#configuring-your-project
β β
β β Using hashes
β β ------------
β β
β β If you would like to use *Hash-Checking Mode* available in ``pip`` since
β β version 8.0, ``pip-compile`` offers ``--generate-hashes`` flag:
β β
β β @@ -167,17 +174,41 @@
β β
β β .. code-block:: bash
β β
β β $ pip-compile --upgrade-package flask # only update the flask package
β β $ pip-compile --upgrade-package flask --upgrade-package requests # update both the flask and requests packages
β β $ pip-compile -P flask -P requests==2.0.0 # update the flask package to the latest, and requests to v2.0.0
β β
β β - 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.
β β + 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:
β β +
β β + .. code-block:: bash
β β +
β β + $ 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 flask to test a
β β + library with both versions using `tox <https://tox.readthedocs.io/en/latest/>`__:
β β +
β β + .. code-block:: bash
β β +
β β + $ pip-compile --upgrade-package 'flask<1.0' --output-file requirements-flask0x.txt
β β + $ pip-compile --upgrade-package 'flask<2.0' --output-file requirements-flask1x.txt
β β +
β β + Or to output to standard output, use ``--output-file=-``:
β β +
β β + .. code-block:: bash
β β +
β β + $ pip-compile --output-file=- > requirements.txt
β β + $ pip-compile - --output-file=- < requirements.in > requirements.txt
β β
β β 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
β β @@ -202,25 +233,29 @@
β β ==============================
β β
β β 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.
β β +
β β **Be careful**: ``pip-sync`` is meant to be used only with a
β β ``requirements.txt`` generated by ``pip-compile``.
β β
β β .. code-block:: bash
β β
β β $ 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
β β + 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.
β β @@ -239,28 +274,34 @@
β β ``setuptools``, ``pip``, or ``pip-tools`` itself. Use ``pip install --upgrade``
β β to upgrade those packages.
β β
β β Other useful tools
β β ==================
β β
β β - `pipdeptree`_ to print the dependency tree of the installed packages.
β β + - ``requirements.in``/``requirements.txt`` syntax highlighting:
β β +
β β + * `requirements.txt.vim`_ for Vim.
β β + * `Python extension for VS Code`_ for VS Code.
β β
β β .. _pipdeptree: https://github.com/naiquevin/pipdeptree
β β + .. _requirements.txt.vim: https://github.com/raimon49/requirements.txt.vim
β β + .. _Python extension for VS Code: https://marketplace.visualstudio.com/items?itemName=ms-python.python
β β
β β Platform: any
β β Classifier: Development Status :: 5 - Production/Stable
β β Classifier: Intended Audience :: Developers
β β Classifier: Intended Audience :: System Administrators
β β Classifier: License :: OSI Approved :: BSD License
β β Classifier: Operating System :: OS Independent
β β Classifier: Programming Language :: Python
β β Classifier: Programming Language :: Python :: 2
β β Classifier: Programming Language :: Python :: 2.7
β β Classifier: Programming Language :: Python :: 3
β β -Classifier: Programming Language :: Python :: 3.4
β β Classifier: Programming Language :: Python :: 3.5
β β Classifier: Programming Language :: Python :: 3.6
β β Classifier: Programming Language :: Python :: 3.7
β β Classifier: Programming Language :: Python :: Implementation :: CPython
β β Classifier: Programming Language :: Python :: Implementation :: PyPy
β β Classifier: Topic :: System :: Systems Administration
β β -Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
β β +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
β β +Description-Content-Type: text/x-rst
βββ encoding
β β β @@ -1 +1 @@
β β β -utf-8
β β β +us-ascii
β --- pip-tools-3.5.0/tests/test_fake_index.py
βββ +++ pip-tools-4.0.0/tests/test_fake_index.py
ββ Files similar despite different names (difference score: 46)
β β @@ -1,63 +1,80 @@
β β from pytest import raises
β β
β β
β β def test_find_best_match(from_line, repository):
β β - ireq = from_line('django>1.5')
β β - assert str(repository.find_best_match(ireq)) == 'django==1.8'
β β + ireq = from_line("django>1.5")
β β + assert str(repository.find_best_match(ireq)) == "django==1.8"
β β
β β - ireq = from_line('django<1.8,~=1.6')
β β - assert str(repository.find_best_match(ireq)) == 'django==1.7.7'
β β + ireq = from_line("django<1.8,~=1.6")
β β + assert str(repository.find_best_match(ireq)) == "django==1.7.7"
β β
β β # Extras available, but no extras specified
β β - ireq = from_line('ipython')
β β - assert str(repository.find_best_match(ireq)) == 'ipython==2.1.0'
β β + ireq = from_line("ipython")
β β + assert str(repository.find_best_match(ireq)) == "ipython==2.1.0"
β β
β β # Make sure we include extras. They should be sorted in the output.
β β - ireq = from_line('ipython[notebook,nbconvert]')
β β - assert str(repository.find_best_match(ireq)) == 'ipython[nbconvert,notebook]==2.1.0'
β β + ireq = from_line("ipython[notebook,nbconvert]")
β β + assert str(repository.find_best_match(ireq)) == "ipython[nbconvert,notebook]==2.1.0"
β β
β β
β β def test_find_best_match_incl_prereleases(from_line, repository):
β β - ireq = from_line('SQLAlchemy')
β β - assert str(repository.find_best_match(ireq, prereleases=False)) == 'sqlalchemy==0.9.9'
β β - assert str(repository.find_best_match(ireq, prereleases=True)) == 'sqlalchemy==1.0.0b5'
β β + ireq = from_line("SQLAlchemy")
β β + assert (
β β + str(repository.find_best_match(ireq, prereleases=False)) == "sqlalchemy==0.9.9"
β β + )
β β + assert (
β β + str(repository.find_best_match(ireq, prereleases=True)) == "sqlalchemy==1.0.0b5"
β β + )
β β
β β
β β def test_find_best_match_for_editable(from_editable, repository):
β β - ireq = from_editable('git+git://whatev.org/blah.git#egg=flask')
β β + ireq = from_editable("git+git://whatev.org/blah.git#egg=flask")
β β assert repository.find_best_match(ireq) == ireq
β β
β β
β β def test_get_dependencies(from_line, repository):
β β - ireq = from_line('django==1.6.11')
β β + ireq = from_line("django==1.6.11")
β β assert repository.get_dependencies(ireq) == []
β β
β β - ireq = from_line('Flask==0.10.1')
β β + ireq = from_line("Flask==0.10.1")
β β dependencies = repository.get_dependencies(ireq)
β β - assert ({str(req) for req in dependencies} ==
β β - {'Werkzeug>=0.7', 'Jinja2>=2.4', 'itsdangerous>=0.21'})
β β + assert {str(req) for req in dependencies} == {
β β + "Werkzeug>=0.7",
β β + "Jinja2>=2.4",
β β + "itsdangerous>=0.21",
β β + }
β β
β β - ireq = from_line('ipython==2.1.0')
β β + ireq = from_line("ipython==2.1.0")
β β dependencies = repository.get_dependencies(ireq)
β β - assert {str(req) for req in dependencies} == {'gnureadline'}
β β + assert {str(req) for req in dependencies} == {"gnureadline"}
β β
β β - ireq = from_line('ipython[notebook]==2.1.0')
β β + ireq = from_line("ipython[notebook]==2.1.0")
β β dependencies = repository.get_dependencies(ireq)
β β - assert ({str(req) for req in dependencies} ==
β β - {'gnureadline', 'pyzmq>=2.1.11', 'tornado>=3.1', 'jinja2'})
β β + assert {str(req) for req in dependencies} == {
β β + "gnureadline",
β β + "pyzmq>=2.1.11",
β β + "tornado>=3.1",
β β + "jinja2",
β β + }
β β
β β - ireq = from_line('ipython[notebook,nbconvert]==2.1.0')
β β + ireq = from_line("ipython[notebook,nbconvert]==2.1.0")
β β dependencies = repository.get_dependencies(ireq)
β β - assert ({str(req) for req in dependencies} ==
β β - {'gnureadline', 'pyzmq>=2.1.11', 'tornado>=3.1', 'jinja2', 'pygments', 'Sphinx>=0.3'})
β β + assert {str(req) for req in dependencies} == {
β β + "gnureadline",
β β + "pyzmq>=2.1.11",
β β + "tornado>=3.1",
β β + "jinja2",
β β + "pygments",
β β + "Sphinx>=0.3",
β β + }
β β
β β
β β def test_get_dependencies_for_editable(from_editable, repository):
β β - ireq = from_editable('git+git://example.org/django.git#egg=django')
β β + ireq = from_editable("git+git://example.org/django.git#egg=django")
β β assert repository.get_dependencies(ireq) == []
β β
β β
β β def test_get_dependencies_rejects_non_pinned_requirements(from_line, repository):
β β - not_a_pinned_req = from_line('django>1.6')
β β + not_a_pinned_req = from_line("django>1.6")
β β with raises(TypeError):
β β repository.get_dependencies(not_a_pinned_req)
β --- pip-tools-3.5.0/tests/test_data/minimal_wheels/small_fake_a-0.2-py2.py3-none-any.whl
βββ +++ pip-tools-4.0.0/tests/test_data/minimal_wheels/small_fake_a-0.2-py2.py3-none-any.whl
ββ Files similar despite different names (difference score: 0)
β --- pip-tools-3.5.0/tests/test_data/minimal_wheels/small_fake_b-0.1-py2.py3-none-any.whl
βββ +++ pip-tools-4.0.0/tests/test_data/minimal_wheels/small_fake_b-0.1-py2.py3-none-any.whl
ββ Files similar despite different names (difference score: 0)
β --- pip-tools-3.5.0/img/pip-tools-overview.png
βββ +++ pip-tools-4.0.0/img/pip-tools-overview.png
ββ Files similar despite different names (difference score: 0)
β --- pip-tools-3.5.0/piptools/exceptions.py
βββ +++ pip-tools-4.0.0/piptools/exceptions.py
ββ Files similar despite different names (difference score: 54)
β β @@ -15,48 +15,43 @@
β β for candidate in sorted(self.candidates_tried):
β β version = str(candidate.version)
β β if candidate.version.is_prerelease:
β β pre_versions.append(version)
β β else:
β β versions.append(version)
β β
β β - lines = [
β β - 'Could not find a version that matches {}'.format(self.ireq),
β β - ]
β β + lines = ["Could not find a version that matches {}".format(self.ireq)]
β β
β β if versions:
β β - lines.append('Tried: {}'.format(', '.join(versions)))
β β + lines.append("Tried: {}".format(", ".join(versions)))
β β
β β if pre_versions:
β β if self.finder.allow_all_prereleases:
β β - line = 'Tried'
β β + line = "Tried"
β β else:
β β - line = 'Skipped'
β β + line = "Skipped"
β β
β β - line += ' pre-versions: {}'.format(', '.join(pre_versions))
β β + line += " pre-versions: {}".format(", ".join(pre_versions))
β β lines.append(line)
β β
β β if versions or pre_versions:
β β - lines.append('There are incompatible versions in the resolved dependencies.')
β β + lines.append(
β β + "There are incompatible versions in the resolved dependencies:"
β β + )
β β + source_ireqs = getattr(self.ireq, "_source_ireqs", [])
β β + lines.extend(" {}".format(ireq) for ireq in source_ireqs)
β β else:
β β - lines.append('No versions found')
β β - lines.append('{} {} reachable?'.format(
β β - 'Were' if len(self.finder.index_urls) > 1 else 'Was', ' or '.join(self.finder.index_urls))
β β + lines.append("No versions found")
β β + lines.append(
β β + "{} {} reachable?".format(
β β + "Were" if len(self.finder.index_urls) > 1 else "Was",
β β + " or ".join(self.finder.index_urls),
β β + )
β β )
β β - return '\n'.join(lines)
β β -
β β -
β β -class UnsupportedConstraint(PipToolsError):
β β - def __init__(self, message, constraint):
β β - super(UnsupportedConstraint, self).__init__(message)
β β - self.constraint = constraint
β β -
β β - def __str__(self):
β β - message = super(UnsupportedConstraint, self).__str__()
β β - return '{} (constraint was: {})'.format(message, str(self.constraint))
β β + return "\n".join(lines)
β β
β β
β β class IncompatibleRequirements(PipToolsError):
β β def __init__(self, ireq_a, ireq_b):
β β self.ireq_a = ireq_a
β β self.ireq_b = ireq_b
β --- pip-tools-3.5.0/piptools/repositories/local.py
βββ +++ pip-tools-4.0.0/piptools/repositories/local.py
ββ Files similar despite different names (difference score: 13)
β β @@ -1,16 +1,16 @@
β β # coding: utf-8
β β -from __future__ import (absolute_import, division, print_function,
β β - unicode_literals)
β β +from __future__ import absolute_import, division, print_function, unicode_literals
β β
β β from contextlib import contextmanager
β β
β β -from piptools.utils import as_tuple, key_from_req, make_install_requirement
β β -from .base import BaseRepository
β β from .._compat import FAVORITE_HASH
β β +from .base import BaseRepository
β β +
β β +from piptools.utils import as_tuple, key_from_req, make_install_requirement
β β
β β
β β def ireq_satisfied_by_existing_pin(ireq, existing_pin):
β β """
β β Return True if the given InstallationRequirement is satisfied by the
β β previously encountered version pin.
β β """
β β @@ -24,19 +24,24 @@
β β checking if a requirement can be satisfied by existing pins (i.e. the
β β result of a previous compile step).
β β
β β In effect, if a requirement can be satisfied with a version pinned in the
β β requirements file, we prefer that version over the best match found in
β β PyPI. This keeps updates to the requirements.txt down to a minimum.
β β """
β β +
β β def __init__(self, existing_pins, proxied_repository):
β β self.repository = proxied_repository
β β self.existing_pins = existing_pins
β β
β β @property
β β + def options(self):
β β + return self.repository.options
β β +
β β + @property
β β def finder(self):
β β return self.repository.finder
β β
β β @property
β β def session(self):
β β return self.repository.session
β β
β β @@ -64,20 +69,19 @@
β β def get_dependencies(self, ireq):
β β return self.repository.get_dependencies(ireq)
β β
β β def get_hashes(self, ireq):
β β key = key_from_req(ireq.req)
β β existing_pin = self.existing_pins.get(key)
β β if existing_pin and ireq_satisfied_by_existing_pin(ireq, existing_pin):
β β - hashes = existing_pin.options.get('hashes', {})
β β + hashes = existing_pin.options.get("hashes", {})
β β hexdigests = hashes.get(FAVORITE_HASH)
β β if hexdigests:
β β return {
β β - ':'.join([FAVORITE_HASH, hexdigest])
β β - for hexdigest in hexdigests
β β + ":".join([FAVORITE_HASH, hexdigest]) for hexdigest in hexdigests
β β }
β β return self.repository.get_hashes(ireq)
β β
β β @contextmanager
β β def allow_all_wheels(self):
β β with self.repository.allow_all_wheels():
β β yield
β --- pip-tools-3.5.0/tests/test_sync.py
βββ +++ pip-tools-4.0.0/tests/test_sync.py
ββ Files similar despite different names (difference score: 43)
β β @@ -1,393 +1,447 @@
β β -from collections import Counter
β β import os
β β import platform
β β import sys
β β import tempfile
β β +from collections import Counter
β β
β β import mock
β β import pytest
β β
β β -from piptools.exceptions import IncompatibleRequirements, UnsupportedConstraint
β β +from piptools.exceptions import IncompatibleRequirements
β β from piptools.sync import dependency_tree, diff, merge, sync
β β
β β
β β @pytest.fixture
β β def mocked_tmp_file():
β β - with mock.patch.object(tempfile, 'NamedTemporaryFile') as m:
β β + with mock.patch.object(tempfile, "NamedTemporaryFile") as m:
β β yield m.return_value
β β
β β
β β @pytest.fixture
β β def mocked_tmp_req_file(mocked_tmp_file):
β β - with mock.patch('os.unlink'):
β β - mocked_tmp_file.name = 'requirements.txt'
β β + with mock.patch("os.unlink"):
β β + mocked_tmp_file.name = "requirements.txt"
β β yield mocked_tmp_file
β β
β β
β β @pytest.mark.parametrize(
β β - ('installed', 'root', 'expected'),
β β -
β β + ("installed", "root", "expected"),
β β [
β β - ([],
β β - 'pip-tools', []),
β β -
β β - ([('pip-tools==1', [])],
β β - 'pip-tools', ['pip-tools']),
β β -
β β - ([('pip-tools==1', []),
β β - ('django==1.7', [])],
β β - 'pip-tools', ['pip-tools']),
β β -
β β - ([('pip-tools==1', ['click>=2']),
β β - ('django==1.7', []),
β β - ('click==3', [])],
β β - 'pip-tools', ['pip-tools', 'click']),
β β -
β β - ([('pip-tools==1', ['click>=2']),
β β - ('django==1.7', []),
β β - ('click==1', [])],
β β - 'pip-tools', ['pip-tools']),
β β -
β β - ([('root==1', ['child==2']),
β β - ('child==2', ['grandchild==3'])],
β β - 'root', ['root', 'child']),
β β -
β β - ([('root==1', ['child==2']),
β β - ('child==2', ['grandchild==3']),
β β - ('grandchild==3', [])],
β β - 'root', ['root', 'child', 'grandchild']),
β β -
β β - ([('root==1', ['child==2']),
β β - ('child==2', ['root==1'])],
β β - 'root', ['root', 'child']),
β β - ]
β β + ([], "pip-tools", []),
β β + ([("pip-tools==1", [])], "pip-tools", ["pip-tools"]),
β β + ([("pip-tools==1", []), ("django==1.7", [])], "pip-tools", ["pip-tools"]),
β β + (
β β + [("pip-tools==1", ["click>=2"]), ("django==1.7", []), ("click==3", [])],
β β + "pip-tools",
β β + ["pip-tools", "click"],
β β + ),
β β + (
β β + [("pip-tools==1", ["click>=2"]), ("django==1.7", []), ("click==1", [])],
β β + "pip-tools",
β β + ["pip-tools"],
β β + ),
β β + (
β β + [("root==1", ["child==2"]), ("child==2", ["grandchild==3"])],
β β + "root",
β β + ["root", "child"],
β β + ),
β β + (
β β + [
β β + ("root==1", ["child==2"]),
β β + ("child==2", ["grandchild==3"]),
β β + ("grandchild==3", []),
β β + ],
β β + "root",
β β + ["root", "child", "grandchild"],
β β + ),
β β + (
β β + [("root==1", ["child==2"]), ("child==2", ["root==1"])],
β β + "root",
β β + ["root", "child"],
β β + ),
β β + ],
β β )
β β def test_dependency_tree(fake_dist, installed, root, expected):
β β - installed = {distribution.key: distribution
β β - for distribution in
β β - (fake_dist(name, deps) for name, deps in installed)}
β β + installed = {
β β + distribution.key: distribution
β β + for distribution in (fake_dist(name, deps) for name, deps in installed)
β β + }
β β
β β actual = dependency_tree(installed, root)
β β assert actual == set(expected)
β β
β β
β β def test_merge_detect_conflicts(from_line):
β β - requirements = [from_line('flask==1'), from_line('flask==2')]
β β + requirements = [from_line("flask==1"), from_line("flask==2")]
β β
β β with pytest.raises(IncompatibleRequirements):
β β merge(requirements, ignore_conflicts=False)
β β
β β
β β def test_merge_ignore_conflicts(from_line):
β β - requirements = [from_line('flask==1'), from_line('flask==2')]
β β + requirements = [from_line("flask==1"), from_line("flask==2")]
β β
β β - assert Counter(requirements[1:2]) == Counter(merge(requirements, ignore_conflicts=True))
β β + assert Counter(requirements[1:2]) == Counter(
β β + merge(requirements, ignore_conflicts=True)
β β + )
β β
β β
β β def test_merge(from_line):
β β - requirements = [from_line('flask==1'),
β β - from_line('flask==1'),
β β - from_line('django==2')]
β β + requirements = [
β β + from_line("flask==1"),
β β + from_line("flask==1"),
β β + from_line("django==2"),
β β + ]
β β
β β - assert Counter(requirements[1:3]) == Counter(merge(requirements, ignore_conflicts=False))
β β + assert Counter(requirements[1:3]) == Counter(
β β + merge(requirements, ignore_conflicts=False)
β β + )
β β
β β
β β -def test_merge_non_editable_url(from_line):
β β - """
β β - Non-editable URLs are not supported.
β β - """
β β - requirements = [from_line('django==1.8'),
β β - from_line('https://example.com/#egg=example')]
β β +def test_merge_urls(from_line):
β β + requirements = [
β β + from_line("file:///example.zip#egg=example==1.0"),
β β + from_line("example==1.0"),
β β + from_line("file:///unrelated.zip"),
β β + ]
β β
β β - with pytest.raises(UnsupportedConstraint):
β β - merge(requirements, ignore_conflicts=True)
β β + assert Counter(requirements[1:]) == Counter(
β β + merge(requirements, ignore_conflicts=False)
β β + )
β β
β β
β β def test_diff_should_do_nothing():
β β installed = [] # empty env
β β reqs = [] # no requirements
β β
β β to_install, to_uninstall = diff(reqs, installed)
β β assert to_install == set()
β β assert to_uninstall == set()
β β
β β
β β def test_diff_should_install(from_line):
β β installed = [] # empty env
β β - reqs = [from_line('django==1.8')]
β β + reqs = [from_line("django==1.8")]
β β
β β to_install, to_uninstall = diff(reqs, installed)
β β - assert {str(x.req) for x in to_install} == {'django==1.8'}
β β + assert {str(x.req) for x in to_install} == {"django==1.8"}
β β assert to_uninstall == set()
β β
β β
β β def test_diff_should_uninstall(fake_dist):
β β - installed = [fake_dist('django==1.8')]
β β + installed = [fake_dist("django==1.8")]
β β reqs = []
β β
β β to_install, to_uninstall = diff(reqs, installed)
β β assert to_install == set()
β β - assert to_uninstall == {'django'} # no version spec when uninstalling
β β + assert to_uninstall == {"django"} # no version spec when uninstalling
β β
β β
β β def test_diff_should_not_uninstall(fake_dist):
β β - ignored = ('pip==7.1.0', 'pip-tools==1.1.1', 'pip-review==1.1.1',
β β - 'pkg-resources==0.0.0', 'setuptools==34.0.0', 'wheel==0.29.0',
β β - 'python==3.0', 'distribute==0.1', 'wsgiref==0.1', 'argparse==0.1')
β β + ignored = (
β β + "pip==7.1.0",
β β + "pip-tools==1.1.1",
β β + "pip-review==1.1.1",
β β + "pkg-resources==0.0.0",
β β + "setuptools==34.0.0",
β β + "wheel==0.29.0",
β β + "python==3.0",
β β + "distribute==0.1",
β β + "wsgiref==0.1",
β β + "argparse==0.1",
β β + )
β β installed = [fake_dist(pkg) for pkg in ignored]
β β reqs = []
β β
β β to_uninstall = diff(reqs, installed)[1]
β β assert to_uninstall == set()
β β
β β
β β def test_diff_should_update(fake_dist, from_line):
β β - installed = [fake_dist('django==1.7')]
β β - reqs = [from_line('django==1.8')]
β β + installed = [fake_dist("django==1.7")]
β β + reqs = [from_line("django==1.8")]
β β
β β to_install, to_uninstall = diff(reqs, installed)
β β - assert {str(x.req) for x in to_install} == {'django==1.8'}
β β + assert {str(x.req) for x in to_install} == {"django==1.8"}
β β assert to_uninstall == set()
β β
β β
β β def test_diff_should_install_with_markers(from_line):
β β installed = []
β β reqs = [from_line("subprocess32==3.2.7 ; python_version=='2.7'")]
β β
β β to_install, to_uninstall = diff(reqs, installed)
β β - assert {str(x.req) for x in to_install} == ({'subprocess32==3.2.7'} if sys.version.startswith('2.7') else set())
β β + assert {str(x.req) for x in to_install} == (
β β + {"subprocess32==3.2.7"} if sys.version.startswith("2.7") else set()
β β + )
β β assert to_uninstall == set()
β β
β β
β β def test_diff_should_uninstall_with_markers(fake_dist, from_line):
β β - installed = [fake_dist('subprocess32==3.2.7')]
β β + installed = [fake_dist("subprocess32==3.2.7")]
β β reqs = [from_line("subprocess32==3.2.7 ; python_version=='2.7'")]
β β
β β to_install, to_uninstall = diff(reqs, installed)
β β assert to_install == set()
β β - assert to_uninstall == (set() if sys.version.startswith('2.7') else {'subprocess32'})
β β + assert to_uninstall == (
β β + set() if sys.version.startswith("2.7") else {"subprocess32"}
β β + )
β β
β β
β β def test_diff_leave_packaging_packages_alone(fake_dist, from_line):
β β # Suppose an env contains Django, and pip itself
β β installed = [
β β - fake_dist('django==1.7'),
β β - fake_dist('first==2.0.1'),
β β - fake_dist('pip==7.1.0'),
β β + fake_dist("django==1.7"),
β β + fake_dist("first==2.0.1"),
β β + fake_dist("pip==7.1.0"),
β β ]
β β
β β # Then this Django-only requirement should keep pip around (i.e. NOT
β β # uninstall it), but uninstall first
β β - reqs = [
β β - from_line('django==1.7'),
β β - ]
β β + reqs = [from_line("django==1.7")]
β β
β β to_install, to_uninstall = diff(reqs, installed)
β β assert to_install == set()
β β - assert to_uninstall == {'first'}
β β + assert to_uninstall == {"first"}
β β
β β
β β def test_diff_leave_piptools_alone(fake_dist, from_line):
β β # Suppose an env contains Django, and pip-tools itself (including all of
β β # its dependencies)
β β installed = [
β β - fake_dist('django==1.7'),
β β - fake_dist('first==2.0.1'),
β β - fake_dist('pip-tools==1.1.1', [
β β - 'click>=4',
β β - 'first',
β β - 'six',
β β - ]),
β β - fake_dist('six==1.9.0'),
β β - fake_dist('click==4.1'),
β β - fake_dist('foobar==0.3.6'),
β β + fake_dist("django==1.7"),
β β + fake_dist("first==2.0.1"),
β β + fake_dist("pip-tools==1.1.1", ["click>=4", "first", "six"]),
β β + fake_dist("six==1.9.0"),
β β + fake_dist("click==4.1"),
β β + fake_dist("foobar==0.3.6"),
β β ]
β β
β β # Then this Django-only requirement should keep pip around (i.e. NOT
β β # uninstall it), but uninstall first
β β - reqs = [
β β - from_line('django==1.7'),
β β - ]
β β + reqs = [from_line("django==1.7")]
β β
β β to_install, to_uninstall = diff(reqs, installed)
β β assert to_install == set()
β β - assert to_uninstall == {'foobar'}
β β + assert to_uninstall == {"foobar"}
β β
β β
β β def _get_file_url(local_path):
β β - if platform.system() == 'Windows':
β β - local_path = '/%s' % local_path.replace('\\', '/')
β β - return 'file://%s' % local_path
β β + if platform.system() == "Windows":
β β + local_path = "/%s" % local_path.replace("\\", "/")
β β + return "file://%s" % local_path
β β
β β
β β def test_diff_with_editable(fake_dist, from_editable):
β β - installed = [
β β - fake_dist('small-fake-with-deps==0.0.1'),
β β - fake_dist('six==1.10.0'),
β β - ]
β β - path_to_package = os.path.join(os.path.dirname(__file__), 'test_data', 'small_fake_package')
β β - reqs = [
β β - from_editable(path_to_package),
β β - ]
β β + installed = [fake_dist("small-fake-with-deps==0.0.1"), fake_dist("six==1.10.0")]
β β + path_to_package = os.path.join(
β β + os.path.dirname(__file__), "test_data", "small_fake_package"
β β + )
β β + reqs = [from_editable(path_to_package)]
β β to_install, to_uninstall = diff(reqs, installed)
β β
β β - # FIXME: The editable package is uninstalled and reinstalled, including all its dependencies,
β β - # even if the version numbers match.
β β - assert to_uninstall == {'six', 'small-fake-with-deps'}
β β + # FIXME: The editable package is uninstalled and reinstalled, including
β β + # all its dependencies, even if the version numbers match.
β β + assert to_uninstall == {"six", "small-fake-with-deps"}
β β
β β assert len(to_install) == 1
β β package = list(to_install)[0]
β β assert package.editable
β β assert str(package.link) == _get_file_url(path_to_package)
β β
β β
β β -def test_sync_install_temporary_requirement_file(from_line, from_editable, mocked_tmp_req_file):
β β - with mock.patch('piptools.sync.check_call') as check_call:
β β - to_install = {from_line('django==1.8')}
β β +def test_diff_with_matching_url_versions(fake_dist, from_line):
β β + # if URL version is explicitly provided, use it to avoid reinstalling
β β + installed = [fake_dist("example==1.0")]
β β + reqs = [from_line("file:///example.zip#egg=example==1.0")]
β β +
β β + to_install, to_uninstall = diff(reqs, installed)
β β + assert to_install == set()
β β + assert to_uninstall == set()
β β +
β β +
β β +def test_diff_with_no_url_versions(fake_dist, from_line):
β β + # if URL version is not provided, assume the contents have
β β + # changed and reinstall
β β + installed = [fake_dist("example==1.0")]
β β + reqs = [from_line("file:///example.zip#egg=example")]
β β +
β β + to_install, to_uninstall = diff(reqs, installed)
β β + assert to_install == set(reqs)
β β + assert to_uninstall == {"example"}
β β +
β β +
β β +def test_sync_install_temporary_requirement_file(
β β + from_line, from_editable, mocked_tmp_req_file
β β +):
β β + with mock.patch("piptools.sync.check_call") as check_call:
β β + to_install = {from_line("django==1.8")}
β β sync(to_install, set())
β β check_call.assert_called_once_with(
β β - [sys.executable, '-m', 'pip', 'install', '-r', mocked_tmp_req_file.name, '-q']
β β + [
β β + sys.executable,
β β + "-m",
β β + "pip",
β β + "install",
β β + "-r",
β β + mocked_tmp_req_file.name,
β β + "-q",
β β + ]
β β )
β β
β β
β β def test_temporary_requirement_file_deleted(from_line, from_editable, mocked_tmp_file):
β β - with mock.patch('piptools.sync.check_call'):
β β - to_install = {from_line('django==1.8')}
β β + with mock.patch("piptools.sync.check_call"):
β β + to_install = {from_line("django==1.8")}
β β
β β - with mock.patch('os.unlink') as unlink:
β β + with mock.patch("os.unlink") as unlink:
β β sync(to_install, set())
β β
β β unlink.assert_called_once_with(mocked_tmp_file.name)
β β
β β
β β def test_sync_requirement_file(from_line, from_editable, mocked_tmp_req_file):
β β - with mock.patch('piptools.sync.check_call'):
β β + with mock.patch("piptools.sync.check_call"):
β β to_install = {
β β - from_line('django==1.8'),
β β - from_editable('git+git://fake.org/x/y.git#egg=y'),
β β - from_line('click==4.0'),
β β - from_editable('git+git://fake.org/i/j.git#egg=j'),
β β - from_line('pytz==2017.2'),
β β + from_line("django==1.8"),
β β + from_editable("git+git://fake.org/x/y.git#egg=y"),
β β + from_line("click==4.0"),
β β + from_editable("git+git://fake.org/i/j.git#egg=j"),
β β + from_line("pytz==2017.2"),
β β }
β β
β β sync(to_install, set())
β β
β β expected = (
β β - 'click==4.0\n'
β β - 'django==1.8\n'
β β - '-e git+git://fake.org/i/j.git#egg=j\n'
β β - 'pytz==2017.2\n'
β β - '-e git+git://fake.org/x/y.git#egg=y'
β β + "click==4.0\n"
β β + "django==1.8\n"
β β + "-e git+git://fake.org/i/j.git#egg=j\n"
β β + "pytz==2017.2\n"
β β + "-e git+git://fake.org/x/y.git#egg=y"
β β )
β β mocked_tmp_req_file.write.assert_called_once_with(expected)
β β
β β
β β -def test_sync_requirement_file_with_hashes(from_line, from_editable, mocked_tmp_req_file):
β β - with mock.patch('piptools.sync.check_call'):
β β +def test_sync_requirement_file_with_hashes(
β β + from_line, from_editable, mocked_tmp_req_file
β β +):
β β + with mock.patch("piptools.sync.check_call"):
β β to_install = {
β β - from_line('django==1.8', options={
β β - 'hashes': {
β β - 'sha256': [
β β - '6a03ce2feafdd193a0ba8a26dbd9773e757d2e5d5e7933a62eac129813bd381a',
β β - ]
β β - }
β β - }),
β β - from_line('click==4.0', options={
β β - 'hashes': {
β β - 'sha256': [
β β - '9ab1d313f99b209f8f71a629f36833030c8d7c72282cf7756834baf567dca662',
β β - ]
β β - }
β β - }),
β β - from_line('pytz==2017.2', options={
β β - 'hashes': {
β β - 'sha256': [
β β - 'd1d6729c85acea5423671382868627129432fba9a89ecbb248d8d1c7a9f01c67',
β β - 'f5c056e8f62d45ba8215e5cb8f50dfccb198b4b9fbea8500674f3443e4689589'
β β - ]
β β - }
β β - })
β β + from_line(
β β + "django==1.8",
β β + options={
β β + "hashes": {
β β + "sha256": [
β β + "6a03ce2feafdd193a0ba8a26dbd9773e"
β β + "757d2e5d5e7933a62eac129813bd381a"
β β + ]
β β + }
β β + },
β β + ),
β β + from_line(
β β + "click==4.0",
β β + options={
β β + "hashes": {
β β + "sha256": [
β β + "9ab1d313f99b209f8f71a629f3683303"
β β + "0c8d7c72282cf7756834baf567dca662"
β β + ]
β β + }
β β + },
β β + ),
β β + from_line(
β β + "pytz==2017.2",
β β + options={
β β + "hashes": {
β β + "sha256": [
β β + "d1d6729c85acea542367138286862712"
β β + "9432fba9a89ecbb248d8d1c7a9f01c67",
β β + "f5c056e8f62d45ba8215e5cb8f50dfcc"
β β + "b198b4b9fbea8500674f3443e4689589",
β β + ]
β β + }
β β + },
β β + ),
β β }
β β
β β sync(to_install, set())
β β
β β expected = (
β β - 'click==4.0 \\\n'
β β - ' --hash=sha256:9ab1d313f99b209f8f71a629f36833030c8d7c72282cf7756834baf567dca662\n'
β β - 'django==1.8 \\\n'
β β - ' --hash=sha256:6a03ce2feafdd193a0ba8a26dbd9773e757d2e5d5e7933a62eac129813bd381a\n'
β β - 'pytz==2017.2 \\\n'
β β - ' --hash=sha256:d1d6729c85acea5423671382868627129432fba9a89ecbb248d8d1c7a9f01c67 \\\n'
β β - ' --hash=sha256:f5c056e8f62d45ba8215e5cb8f50dfccb198b4b9fbea8500674f3443e4689589'
β β + "click==4.0 \\\n"
β β + " --hash=sha256:9ab1d313f99b209f8f71a629"
β β + "f36833030c8d7c72282cf7756834baf567dca662\n"
β β + "django==1.8 \\\n"
β β + " --hash=sha256:6a03ce2feafdd193a0ba8a26"
β β + "dbd9773e757d2e5d5e7933a62eac129813bd381a\n"
β β + "pytz==2017.2 \\\n"
β β + " --hash=sha256:d1d6729c85acea542367138286"
β β + "8627129432fba9a89ecbb248d8d1c7a9f01c67 \\\n"
β β + " --hash=sha256:f5c056e8f62d45ba8215e5cb8f"
β β + "50dfccb198b4b9fbea8500674f3443e4689589"
β β )
β β mocked_tmp_req_file.write.assert_called_once_with(expected)
β β
β β
β β [email protected]('piptools.sync.click.echo')
β β [email protected]("piptools.sync.click.echo")
β β def test_sync_up_to_date(echo):
β β """
β β Everything up-to-date should be printed.
β β """
β β - sync(set(), set())
β β - echo.assert_called_once_with('Everything up-to-date')
β β + sync(set(), set(), verbose=True)
β β + echo.assert_called_once_with("Everything up-to-date")
β β
β β
β β [email protected]('piptools.sync.check_call')
β β [email protected]("piptools.sync.check_call")
β β def test_sync_verbose(check_call, from_line):
β β """
β β The -q option has to be passed to every pip calls.
β β """
β β - sync({from_line('django==1.8')}, set(), verbose=True)
β β + sync({from_line("django==1.8")}, {from_line("click==4.0")}, verbose=True)
β β + assert check_call.call_count == 2
β β for call in check_call.call_args_list:
β β check_call_args = call[0][0]
β β - assert '-q' not in check_call_args
β β + assert "-q" not in check_call_args
β β
β β
β β [email protected]('piptools.sync.click.echo')
β β [email protected]("piptools.sync.click.echo")
β β def test_sync_dry_run_would_install(echo, from_line):
β β """
β β Sync with --dry-run option prints what's is going to be installed.
β β """
β β - to_install = {
β β - from_line('django==1.8'),
β β - from_line('click==4.0'),
β β - }
β β + to_install = {from_line("django==1.8"), from_line("click==4.0")}
β β
β β sync(to_install, set(), dry_run=True)
β β
β β expected_calls = [
β β - mock.call('Would install:'),
β β - mock.call(' django==1.8'),
β β - mock.call(' click==4.0'),
β β + mock.call("Would install:"),
β β + mock.call(" django==1.8"),
β β + mock.call(" click==4.0"),
β β ]
β β echo.assert_has_calls(expected_calls, any_order=True)
β β
β β
β β [email protected]('piptools.sync.click.echo')
β β [email protected]("piptools.sync.click.echo")
β β def test_sync_dry_run_would_uninstall(echo, from_line):
β β """
β β Sync with --dry-run option prints what is going to be uninstalled.
β β """
β β - to_uninstall = {
β β - from_line('django==1.8'),
β β - from_line('click==4.0'),
β β - }
β β + to_uninstall = {from_line("django==1.8"), from_line("click==4.0")}
β β
β β sync(set(), to_uninstall, dry_run=True)
β β
β β expected_calls = [
β β - mock.call('Would uninstall:'),
β β - mock.call(' django==1.8'),
β β - mock.call(' click==4.0'),
β β + mock.call("Would uninstall:"),
β β + mock.call(" django==1.8"),
β β + mock.call(" click==4.0"),
β β ]
β β echo.assert_has_calls(expected_calls, any_order=True)
β β
β β
β β [email protected]('piptools.sync.check_call')
β β [email protected]("piptools.sync.check_call")
β β def test_sync_uninstall_pip_command(check_call):
β β - to_uninstall = ['six', 'django', 'pytz', 'click']
β β + to_uninstall = ["six", "django", "pytz", "click"]
β β
β β sync(set(), to_uninstall)
β β check_call.assert_called_once_with(
β β - [sys.executable, '-m', 'pip', 'uninstall', '-y', '-q'] + sorted(to_uninstall)
β β + [sys.executable, "-m", "pip", "uninstall", "-y", "-q"] + sorted(to_uninstall)
β β )
β --- pip-tools-3.5.0/tests/conftest.py
βββ +++ pip-tools-4.0.0/tests/conftest.py
ββ Files similar despite different names (difference score: 29)
β β @@ -1,59 +1,81 @@
β β import json
β β from contextlib import contextmanager
β β from functools import partial
β β
β β from click.testing import CliRunner
β β from pip._vendor.packaging.version import Version
β β from pip._vendor.pkg_resources import Requirement
β β -from piptools._compat import install_req_from_line, install_req_from_editable
β β from pytest import fixture
β β
β β +from piptools._compat import (
β β + InstallationCandidate,
β β + install_req_from_editable,
β β + install_req_from_line,
β β +)
β β from piptools.cache import DependencyCache
β β +from piptools.exceptions import NoCandidateFound
β β +from piptools.repositories import PyPIRepository
β β from piptools.repositories.base import BaseRepository
β β from piptools.resolver import Resolver
β β from piptools.utils import as_tuple, key_from_req, make_install_requirement
β β -from piptools.exceptions import NoCandidateFound
β β
β β
β β class FakeRepository(BaseRepository):
β β def __init__(self):
β β - with open('tests/test_data/fake-index.json', 'r') as f:
β β + with open("tests/test_data/fake-index.json", "r") as f:
β β self.index = json.load(f)
β β
β β - with open('tests/test_data/fake-editables.json', 'r') as f:
β β + with open("tests/test_data/fake-editables.json", "r") as f:
β β self.editables = json.load(f)
β β
β β def get_hashes(self, ireq):
β β # Some fake hashes
β β return {
β β - 'test:123',
β β - 'sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef',
β β + "test:123",
β β + "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
β β }
β β
β β def find_best_match(self, ireq, prereleases=False):
β β if ireq.editable:
β β return ireq
β β
β β - versions = list(ireq.specifier.filter(self.index[key_from_req(ireq.req)],
β β - prereleases=prereleases))
β β + versions = list(
β β + ireq.specifier.filter(
β β + self.index[key_from_req(ireq.req)], prereleases=prereleases
β β + )
β β + )
β β if not versions:
β β - raise NoCandidateFound(ireq, self.index[key_from_req(ireq.req)], ['https://fake.url.foo'])
β β + tried_versions = [
β β + InstallationCandidate(ireq.name, version, "https://fake.url.foo")
β β + for version in self.index[key_from_req(ireq.req)]
β β + ]
β β + raise NoCandidateFound(ireq, tried_versions, ["https://fake.url.foo"])
β β best_version = max(versions, key=Version)
β β - return make_install_requirement(key_from_req(ireq.req), best_version, ireq.extras, constraint=ireq.constraint)
β β + return make_install_requirement(
β β + key_from_req(ireq.req),
β β + best_version,
β β + ireq.extras,
β β + constraint=ireq.constraint,
β β + )
β β
β β def get_dependencies(self, ireq):
β β if ireq.editable:
β β return self.editables[str(ireq.link)]
β β
β β name, version, extras = as_tuple(ireq)
β β # Store non-extra dependencies under the empty string
β β extras += ("",)
β β - dependencies = [dep for extra in extras for dep in self.index[name][version][extra]]
β β - return [install_req_from_line(dep, constraint=ireq.constraint) for dep in dependencies]
β β + dependencies = [
β β + dep for extra in extras for dep in self.index[name][version][extra]
β β + ]
β β + return [
β β + install_req_from_line(dep, constraint=ireq.constraint)
β β + for dep in dependencies
β β + ]
β β
β β @contextmanager
β β def allow_all_wheels(self):
β β # No need to do an actual pip.Wheel mock here.
β β yield
β β
β β
β β @@ -84,16 +106,21 @@
β β
β β @fixture
β β def repository():
β β return FakeRepository()
β β
β β
β β @fixture
β β +def pypi_repository():
β β + return PyPIRepository(["--index-url", PyPIRepository.DEFAULT_INDEX_URL])
β β +
β β +
β β +@fixture
β β def depcache(tmpdir):
β β - return DependencyCache(str(tmpdir))
β β + return DependencyCache(str(tmpdir / "dep-cache"))
β β
β β
β β @fixture
β β def resolver(depcache, repository):
β β # TODO: It'd be nicer if Resolver instance could be set up and then
β β # use .resolve(...) on the specset, instead of passing it to
β β # the constructor like this (it's not reusable)
β β @@ -113,10 +140,16 @@
β β @fixture
β β def from_editable():
β β return install_req_from_editable
β β
β β
β β @fixture
β β def runner():
β β - cli_runner = CliRunner()
β β + cli_runner = CliRunner(mix_stderr=False)
β β with cli_runner.isolated_filesystem():
β β yield cli_runner
β β +
β β +
β β +@fixture
β β +def tmpdir_cwd(tmpdir):
β β + with tmpdir.as_cwd():
β β + yield tmpdir
β --- pip-tools-3.5.0/CHANGELOG.md
βββ +++ pip-tools-4.0.0/CHANGELOG.md
ββ Files similar despite different names (difference score: 46)
β β @@ -1,7 +1,78 @@
β β +# 4.0.0 (2019-07-25)
β β +
β β +Backwards Incompatible Changes:
β β +- Drop support for EOL Python 3.4
β β +([#803](https://github.com/jazzband/pip-tools/pull/803)). Thanks @auvipy
β β +
β β +Bug Fixes:
β β +- Fix `pip>=19.2` compatibility
β β +([#857](https://github.com/jazzband/pip-tools/pull/857)). Thanks @atugushev
β β +
β β +# 3.9.0 (2019-07-17)
β β +
β β +Features:
β β +- Print provenance information when `pip-compile` fails
β β +([#837](https://github.com/jazzband/pip-tools/pull/837)). Thanks @jakevdp
β β +
β β +Bug Fixes:
β β +- Output all logging to stderr instead of stdout
β β +([#834](https://github.com/jazzband/pip-tools/pull/834)). Thanks @georgek
β β +- Fix output file update with `--dry-run` option in `pip-compile`
β β +([#842](https://github.com/jazzband/pip-tools/pull/842)). Thanks @shipmints and @atugushev
β β +
β β +# 3.8.0 (2019-06-06)
β β +
β β +Features:
β β +- Options `--upgrade` and `--upgrade-package` are no longer mutually exclusive
β β +([#831](https://github.com/jazzband/pip-tools/pull/831)). Thanks @adamchainz
β β +
β β +Bug Fixes:
β β +- Fix `--generate-hashes` with bare VCS URLs
β β +([#812](https://github.com/jazzband/pip-tools/pull/812)). Thanks @jcushman
β β +- Fix issues with `UnicodeError` when installing `pip-tools` from source in some systems
β β +([#816](https://github.com/jazzband/pip-tools/pull/816)). Thanks @AbdealiJK
β β +- Respect `--pre` option in the input file
β β +([#822](https://github.com/jazzband/pip-tools/pull/822)). Thanks @atugushev
β β +- Option `--upgrade-package` now works even if the output file does not exist
β β +([#831](https://github.com/jazzband/pip-tools/pull/831)). Thanks @adamchainz
β β +
β β +
β β +# 3.7.0 (2019-05-09)
β β +
β β +Features:
β β +- Show progressbar on generation hashes in `pip-compile` verbose mode
β β +([#743](https://github.com/jazzband/pip-tools/pull/743)). Thanks @atugushev
β β +- Add options `--cert` and `--client-cert` to `pip-sync`
β β +([#798](https://github.com/jazzband/pip-tools/pull/798)). Thanks @atugushev
β β +- Add support for `--find-links` in `pip-compile` output
β β +([#793](https://github.com/jazzband/pip-tools/pull/793)). Thanks @estan and @atugushev
β β +- Normalize Β«command to runΒ» in `pip-compile` headers
β β +([#800](https://github.com/jazzband/pip-tools/pull/800)). Thanks @atugushev
β β +- Support URLs as packages
β β +([#807](https://github.com/jazzband/pip-tools/pull/807)). Thanks @jcushman, @nim65s and @toejough
β β +
β β +Bug Fixes:
β β +- Fix replacing password to asterisks in `pip-compile`
β β +([#808](https://github.com/jazzband/pip-tools/pull/808)). Thanks @atugushev
β β +
β β +# 3.6.1 (2019-04-24)
β β +
β β +Bug Fixes:
β β +- Fix `pip>=19.1` compatibility
β β +([#795](https://github.com/jazzband/pip-tools/pull/795)). Thanks @atugushev
β β +
β β +# 3.6.0 (2019-04-03)
β β +
β β +Features:
β β +- Show less output on `pip-sync` with `--quiet` option
β β +([#765](https://github.com/jazzband/pip-tools/pull/765)). Thanks @atugushev
β β +- Support the flag `--trusted-host` in `pip-sync`
β β +([#777](https://github.com/jazzband/pip-tools/pull/777)). Thanks @firebirdberlin
β β +
β β # 3.5.0 (2019-03-13)
β β
β β Features:
β β - Show default index url provided by `pip`
β β ([#735](https://github.com/jazzband/pip-tools/pull/735)). Thanks @atugushev
β β - Add an option to allow enabling/disabling build isolation
β β ([#758](https://github.com/jazzband/pip-tools/pull/758)). Thanks @atugushev
βββ encoding
β β β @@ -1 +1 @@
β β β -us-ascii
β β β +utf-8
β --- pip-tools-3.5.0/PKG-INFO
βββ +++ pip-tools-4.0.0/PKG-INFO
ββ Files similar despite different names (difference score: 56)
β β @@ -1,44 +1,44 @@
β β -Metadata-Version: 1.2
β β +Metadata-Version: 2.1
β β Name: pip-tools
β β -Version: 3.5.0
β β +Version: 4.0.0
β β Summary: pip-tools keeps your pinned dependencies fresh.
β β Home-page: https://github.com/jazzband/pip-tools/
β β Author: Vincent Driessen
β β Author-email: [email protected]
β β License: BSD
β β -Description: |buildstatus-travis| |buildstatus-appveyor| |codecov| |coveralls| |jazzband| |pypi|
β β +Description: |jazzband| |pypi| |pyversions| |buildstatus-travis| |buildstatus-appveyor| |codecov|
β β
β β ==================================
β β 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?`_
β β
β β .. image:: https://github.com/jazzband/pip-tools/raw/master/img/pip-tools-overview.png
β β :alt: pip-tools overview for phase II
β β
β β - .. |buildstatus-travis| image:: https://img.shields.io/travis/jazzband/pip-tools/master.svg
β β - :alt: Travis-CI build status
β β + .. |buildstatus-travis| image:: https://img.shields.io/travis/jazzband/pip-tools/master.svg?logo=travis
β β + :alt: Travis CI build status
β β :target: https://travis-ci.org/jazzband/pip-tools
β β - .. |buildstatus-appveyor| image:: https://img.shields.io/appveyor/ci/jazzband/pip-tools/master.svg
β β - :alt: Appveyor build status
β β + .. |buildstatus-appveyor| image:: https://img.shields.io/appveyor/ci/jazzband/pip-tools/master.svg?logo=appveyor
β β + :alt: AppVeyor build status
β β :target: https://ci.appveyor.com/project/jazzband/pip-tools
β β .. |codecov| image:: https://codecov.io/gh/jazzband/pip-tools/branch/master/graph/badge.svg
β β - :alt: Codecov
β β + :alt: Coverage
β β :target: https://codecov.io/gh/jazzband/pip-tools
β β - .. |coveralls| image:: https://coveralls.io/repos/github/jazzband/pip-tools/badge.svg?branch=master
β β - :alt: Coveralls
β β - :target: https://coveralls.io/github/jazzband/pip-tools?branch=master
β β .. |jazzband| image:: https://jazzband.co/static/img/badge.svg
β β :alt: Jazzband
β β :target: https://jazzband.co/
β β .. |pypi| image:: https://img.shields.io/pypi/v/pip-tools.svg
β β - :alt: PyPI
β β + :alt: PyPI version
β β + :target: https://pypi.org/project/pip-tools/
β β + .. |pyversions| image:: https://img.shields.io/pypi/pyversions/pip-tools.svg
β β + :alt: Supported Python versions
β β :target: https://pypi.org/project/pip-tools/
β β .. _You do pin them, right?: http://nvie.com/posts/pin-your-packages/
β β
β β
β β Installation
β β ============
β β
β β @@ -54,14 +54,21 @@
β β project's virtual environment.
β β
β β .. _virtual environment: https://packaging.python.org/tutorials/installing-packages/#creating-virtual-environments
β β
β β 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.
β β +
β β Requirements from ``setup.py``
β β ------------------------------
β β
β β Suppose you have a Flask project, and want to pin it for production.
β β If you have a ``setup.py`` with ``install_requires=['Flask']``, then run
β β ``pip-compile`` without any arguments:
β β
β β @@ -114,15 +121,15 @@
β β markupsafe==1.0 # via jinja2
β β werkzeug==0.12.2 # via flask
β β
β β And it will produce your ``requirements.txt``, with all the Flask dependencies
β β (and all underlying dependencies) pinned. You should put both
β β ``requirements.in`` and ``requirements.txt`` under version control.
β β
β β - .. _it's easy to write one: https://packaging.python.org/distributing/#configuring-your-project
β β + .. _it's easy to write one: https://packaging.python.org/guides/distributing-packages-using-setuptools/#configuring-your-project
β β
β β Using hashes
β β ------------
β β
β β If you would like to use *Hash-Checking Mode* available in ``pip`` since
β β version 8.0, ``pip-compile`` offers ``--generate-hashes`` flag:
β β
β β @@ -167,17 +174,41 @@
β β
β β .. code-block:: bash
β β
β β $ pip-compile --upgrade-package flask # only update the flask package
β β $ pip-compile --upgrade-package flask --upgrade-package requests # update both the flask and requests packages
β β $ pip-compile -P flask -P requests==2.0.0 # update the flask package to the latest, and requests to v2.0.0
β β
β β - 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.
β β + 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:
β β +
β β + .. code-block:: bash
β β +
β β + $ 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 flask to test a
β β + library with both versions using `tox <https://tox.readthedocs.io/en/latest/>`__:
β β +
β β + .. code-block:: bash
β β +
β β + $ pip-compile --upgrade-package 'flask<1.0' --output-file requirements-flask0x.txt
β β + $ pip-compile --upgrade-package 'flask<2.0' --output-file requirements-flask1x.txt
β β +
β β + Or to output to standard output, use ``--output-file=-``:
β β +
β β + .. code-block:: bash
β β +
β β + $ pip-compile --output-file=- > requirements.txt
β β + $ pip-compile - --output-file=- < requirements.in > requirements.txt
β β
β β 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
β β @@ -202,25 +233,29 @@
β β ==============================
β β
β β 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.
β β +
β β **Be careful**: ``pip-sync`` is meant to be used only with a
β β ``requirements.txt`` generated by ``pip-compile``.
β β
β β .. code-block:: bash
β β
β β $ 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
β β + 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.
β β @@ -239,28 +274,34 @@
β β ``setuptools``, ``pip``, or ``pip-tools`` itself. Use ``pip install --upgrade``
β β to upgrade those packages.
β β
β β Other useful tools
β β ==================
β β
β β - `pipdeptree`_ to print the dependency tree of the installed packages.
β β + - ``requirements.in``/``requirements.txt`` syntax highlighting:
β β +
β β + * `requirements.txt.vim`_ for Vim.
β β + * `Python extension for VS Code`_ for VS Code.
β β
β β .. _pipdeptree: https://github.com/naiquevin/pipdeptree
β β + .. _requirements.txt.vim: https://github.com/raimon49/requirements.txt.vim
β β + .. _Python extension for VS Code: https://marketplace.visualstudio.com/items?itemName=ms-python.python
β β
β β Platform: any
β β Classifier: Development Status :: 5 - Production/Stable
β β Classifier: Intended Audience :: Developers
β β Classifier: Intended Audience :: System Administrators
β β Classifier: License :: OSI Approved :: BSD License
β β Classifier: Operating System :: OS Independent
β β Classifier: Programming Language :: Python
β β Classifier: Programming Language :: Python :: 2
β β Classifier: Programming Language :: Python :: 2.7
β β Classifier: Programming Language :: Python :: 3
β β -Classifier: Programming Language :: Python :: 3.4
β β Classifier: Programming Language :: Python :: 3.5
β β Classifier: Programming Language :: Python :: 3.6
β β Classifier: Programming Language :: Python :: 3.7
β β Classifier: Programming Language :: Python :: Implementation :: CPython
β β Classifier: Programming Language :: Python :: Implementation :: PyPy
β β Classifier: Topic :: System :: Systems Administration
β β -Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
β β +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
β β +Description-Content-Type: text/x-rst
βββ encoding
β β β @@ -1 +1 @@
β β β -utf-8
β β β +us-ascii
β --- pip-tools-3.5.0/tests/test_cache.py
βββ +++ pip-tools-4.0.0/tests/test_cache.py
ββ Files similar despite different names (difference score: 31)
β β @@ -1,15 +1,15 @@
β β from contextlib import contextmanager
β β from os import remove
β β from shutil import rmtree
β β from tempfile import NamedTemporaryFile
β β
β β from pytest import raises
β β
β β -from piptools.cache import read_cache_file, CorruptCacheError, DependencyCache
β β +from piptools.cache import CorruptCacheError, DependencyCache, read_cache_file
β β
β β
β β @contextmanager
β β def _read_cache_file_helper(to_write):
β β """
β β On enter, create the file with the given string, and then yield its path.
β β On exit, delete that file.
β β @@ -32,15 +32,18 @@
β β
β β
β β def test_read_cache_file_not_json():
β β """
β β A cache file that's not JSON should throw a corrupt cache error.
β β """
β β with _read_cache_file_helper("not json") as cache_file_name:
β β - with raises(CorruptCacheError):
β β + with raises(
β β + CorruptCacheError,
β β + match="The dependency cache seems to have been corrupted.",
β β + ):
β β read_cache_file(cache_file_name)
β β
β β
β β def test_read_cache_file_wrong_format():
β β """
β β A cache file with a wrong "__format__" value should throw an assertion error.
β β """
β β @@ -49,50 +52,56 @@
β β read_cache_file(cache_file_name)
β β
β β
β β def test_read_cache_file_successful():
β β """
β β A good cache file.
β β """
β β - with _read_cache_file_helper('{"__format__": 1, "dependencies": "success"}') as cache_file_name:
β β + with _read_cache_file_helper(
β β + '{"__format__": 1, "dependencies": "success"}'
β β + ) as cache_file_name:
β β assert "success" == read_cache_file(cache_file_name)
β β
β β
β β def test_reverse_dependencies(from_line, tmpdir):
β β # Since this is a test, make a temporary directory. Converting to str from py.path.
β β tmp_dir_path = str(tmpdir)
β β
β β - # Create a cache object. The keys are packages, and the values are lists of packages on which the keys depend.
β β + # Create a cache object. The keys are packages, and the values are lists
β β + # of packages on which the keys depend.
β β cache = DependencyCache(cache_dir=tmp_dir_path)
β β cache[from_line("top==1.2")] = ["middle>=0.3", "bottom>=5.1.2"]
β β cache[from_line("top[xtra]==1.2")] = ["middle>=0.3", "bottom>=5.1.2", "bonus==0.4"]
β β cache[from_line("middle==0.4")] = ["bottom<6"]
β β cache[from_line("bottom==5.3.5")] = []
β β cache[from_line("bonus==0.4")] = []
β β
β β - # In this case, we're using top 1.2 without an extra, so the "bonus" package is not depended upon.
β β - reversed_no_extra = cache.reverse_dependencies([
β β - from_line("top==1.2"),
β β - from_line("middle==0.4"),
β β - from_line("bottom==5.3.5"),
β β - from_line("bonus==0.4")
β β - ])
β β - assert reversed_no_extra == {
β β - 'middle': {'top'},
β β - 'bottom': {'middle', 'top'}
β β - }
β β -
β β - # Now we're using top 1.2 with the "xtra" extra, so it depends on the "bonus" package.
β β - reversed_extra = cache.reverse_dependencies([
β β - from_line("top[xtra]==1.2"),
β β - from_line("middle==0.4"),
β β - from_line("bottom==5.3.5"),
β β - from_line("bonus==0.4")
β β - ])
β β + # In this case, we're using top 1.2 without an extra, so the "bonus" package
β β + # is not depended upon.
β β + reversed_no_extra = cache.reverse_dependencies(
β β + [
β β + from_line("top==1.2"),
β β + from_line("middle==0.4"),
β β + from_line("bottom==5.3.5"),
β β + from_line("bonus==0.4"),
β β + ]
β β + )
β β + assert reversed_no_extra == {"middle": {"top"}, "bottom": {"middle", "top"}}
β β +
β β + # Now we're using top 1.2 with the "xtra" extra, so it depends
β β + # on the "bonus" package.
β β + reversed_extra = cache.reverse_dependencies(
β β + [
β β + from_line("top[xtra]==1.2"),
β β + from_line("middle==0.4"),
β β + from_line("bottom==5.3.5"),
β β + from_line("bonus==0.4"),
β β + ]
β β + )
β β assert reversed_extra == {
β β - 'middle': {'top'},
β β - 'bottom': {'middle', 'top'},
β β - 'bonus': {'top'}
β β + "middle": {"top"},
β β + "bottom": {"middle", "top"},
β β + "bonus": {"top"},
β β }
β β
β β # Clean up our temp directory
β β rmtree(tmp_dir_path)
β --- pip-tools-3.5.0/tests/test_data/minimal_wheels/small_fake_b-0.2-py2.py3-none-any.whl
βββ +++ pip-tools-4.0.0/tests/test_data/minimal_wheels/small_fake_b-0.2-py2.py3-none-any.whl
ββ Files similar despite different names (difference score: 0)