-
Notifications
You must be signed in to change notification settings - Fork 11
pip tools 3.5.0 to 4.0.0
mickael e edited this page Aug 16, 2019
·
1 revision
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)