From 941e5c875e0b87dd6701567cde0a98c624e3f21f Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Mon, 31 Jan 2022 09:19:52 +0200 Subject: [PATCH 01/11] With the release of pip 22.0, bump pipprevious to 21.3 --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index fac40a2e3..f728aae59 100644 --- a/tox.ini +++ b/tox.ini @@ -11,7 +11,7 @@ extras = testing coverage: coverage deps = - pipprevious: pip==21.2.* + pipprevious: pip==21.3.* piplatest: pip pipmain: -e git+https://github.com/pypa/pip.git@main#egg=pip setenv = From f717176bffad6330714f16cb2abaed54eb8f6175 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Mon, 31 Jan 2022 08:57:33 +0200 Subject: [PATCH 02/11] Drop support for EOL Python 3.6 --- .github/workflows/ci.yml | 7 +++---- .pre-commit-config.yaml | 2 +- README.rst | 8 +++++--- piptools/_compat/contextlib.py | 31 ------------------------------- piptools/repositories/pypi.py | 2 +- setup.cfg | 3 +-- tox.ini | 2 +- 7 files changed, 12 insertions(+), 43 deletions(-) delete mode 100644 piptools/_compat/contextlib.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1a56259db..7ea14b372 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,10 +23,9 @@ jobs: - macOS python-version: - "3.10" - - 3.9 - - 3.6 - - 3.7 - - 3.8 + - "3.9" + - "3.8" + - "3.7" pip-version: - "latest" - "previous" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2be80487b..baeb5767a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,7 +12,7 @@ repos: rev: v2.29.0 hooks: - id: pyupgrade - args: [--py36-plus] + args: [--py37-plus] - repo: https://github.com/PyCQA/flake8 rev: 4.0.1 hooks: diff --git a/README.rst b/README.rst index 3b51277b4..ca7550a33 100644 --- a/README.rst +++ b/README.rst @@ -454,7 +454,7 @@ then yes, you should commit both ``requirements.in`` and ``requirements.txt`` to Note that if you are deploying on multiple Python environments (read the section below), then you must commit a seperate output file for each Python environment. We suggest to use the ``{env}-requirements.txt`` format -(ex: ``win32-py3.7-requirements.txt``, ``macos-py3.6-requirements.txt``, etc.). +(ex: ``win32-py3.7-requirements.txt``, ``macos-py3.10-requirements.txt``, etc.). Cross-environment usage of ``requirements.in``/``requirements.txt`` and ``pip-compile`` @@ -462,7 +462,7 @@ Cross-environment usage of ``requirements.in``/``requirements.txt`` and ``pip-co The dependencies of a package can change depending on the Python environment in which it is installed. Here, we define a Python environment as the combination of Operating -System, Python version (3.6, 3.7, etc.), and Python implementation (CPython, PyPy, +System, Python version (3.7, 3.8, etc.), and Python implementation (CPython, PyPy, etc.). For an exact definition, refer to the possible combinations of `PEP 508 environment markers`_. @@ -527,5 +527,7 @@ versions as the required ``pip`` versions. +---------------+----------------+----------------+ | 6.0.0 - 6.3.1 | 20.3 - 21.2.* | 3.6 - 3.9 | +---------------+----------------+----------------+ -| 6.4.0+ | 21.2+ | 3.6 - 3.10 | +| 6.4.0 | 21.2+ | 3.6 - 3.10 | ++---------------+----------------+----------------+ +| 6.5.0+ | 21.2+ | 3.7 - 3.10 | +---------------+----------------+----------------+ diff --git a/piptools/_compat/contextlib.py b/piptools/_compat/contextlib.py deleted file mode 100644 index 8f0c5c863..000000000 --- a/piptools/_compat/contextlib.py +++ /dev/null @@ -1,31 +0,0 @@ -# Ported from python 3.7 contextlib.py -from types import TracebackType -from typing import Optional, Type, TypeVar - -_T = TypeVar("_T") - - -class nullcontext: - """Context manager that does no additional processing. - Used as a stand-in for a normal context manager, when a particular - block of code is only sometimes used with a normal context manager: - cm = optional_cm if condition else nullcontext() - with cm: - # Perform operation, using optional_cm if condition is True - - TODO: replace with `contextlib.nullcontext()` after Python 3.6 being dropped - """ - - def __init__(self, enter_result: _T) -> None: - self.enter_result = enter_result - - def __enter__(self) -> _T: - return self.enter_result - - def __exit__( - self, - exc_type: Optional[Type[BaseException]], - exc_val: Optional[BaseException], - exc_tb: Optional[TracebackType], - ) -> Optional[bool]: - pass diff --git a/piptools/repositories/pypi.py b/piptools/repositories/pypi.py index 1c59201df..d8cd16051 100644 --- a/piptools/repositories/pypi.py +++ b/piptools/repositories/pypi.py @@ -1,3 +1,4 @@ +import contextlib import hashlib import itertools import logging @@ -39,7 +40,6 @@ from pip._vendor.packaging.version import _BaseVersion from pip._vendor.requests import RequestException, Session -from .._compat import contextlib from ..exceptions import NoCandidateFound from ..logging import log from ..utils import ( diff --git a/setup.cfg b/setup.cfg index 54d0ed9ef..9e9215efe 100644 --- a/setup.cfg +++ b/setup.cfg @@ -15,7 +15,6 @@ classifiers = Programming Language :: Python Programming Language :: Python :: 3 Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 @@ -25,7 +24,7 @@ classifiers = Topic :: System :: Systems Administration [options] -python_requires = >=3.6 +python_requires = >=3.7 setup_requires = setuptools_scm packages = find: zip_safe = false diff --git a/tox.ini b/tox.ini index f728aae59..9206cc5e6 100644 --- a/tox.ini +++ b/tox.ini @@ -1,7 +1,7 @@ [tox] envlist = # NOTE: keep this in sync with the env list in .github/workflows/ci.yml. - py{36,37,38,39,310,311,py3}-pip{previous,latest,main}-coverage + py{37,38,39,310,311,py3}-pip{previous,latest,main}-coverage checkqa readme skip_missing_interpreters = True From eb8881215719a80c5d41979a237333dcb945242b Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Mon, 31 Jan 2022 09:05:18 +0200 Subject: [PATCH 03/11] Daily cron: Test pip main on 3.10 but not 3.6 --- .github/workflows/cron.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index eecb557db..178c3c67e 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -17,10 +17,10 @@ jobs: - Windows - MacOS python-version: - - 3.9 - - 3.6 - - 3.7 - - 3.8 + - "3.10" + - "3.9" + - "3.8" + - "3.7" pip-version: - main env: From 6d1050593b013e8f9c9e2bf5e3819c64f9f91a7f Mon Sep 17 00:00:00 2001 From: Dustin Ingram Date: Wed, 2 Feb 2022 08:13:09 -0500 Subject: [PATCH 04/11] Canonicalize the requirement name when rendering Since pip no longer guarantees that it will no longer normalize underscore (_) in distribution names to dash (-) in `pip freeze`, `pip list`, and `pip show` (https://pip.pypa.io/en/stable/news/#id73) , in the interest of minimizing churn, pip-compile should normalize requirements names instead. This will ensure there are no changes to requirements files compiled with earlier versions of pip-tools/pip. --- piptools/utils.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/piptools/utils.py b/piptools/utils.py index 3134a5091..11dc1164b 100644 --- a/piptools/utils.py +++ b/piptools/utils.py @@ -26,6 +26,7 @@ from pip._internal.vcs import is_url from pip._vendor.packaging.markers import Marker from pip._vendor.packaging.specifiers import SpecifierSet +from pip._vendor.packaging.utils import canonicalize_name from pip._vendor.packaging.version import Version from pip._vendor.pkg_resources import Distribution, Requirement, get_distribution @@ -121,6 +122,9 @@ def format_requirement( elif is_url_requirement(ireq): line = _build_direct_reference_best_efforts(ireq) else: + # Canonicalize the requirement name + # https://packaging.pypa.io/en/latest/utils.html#packaging.utils.canonicalize_name + ireq.req.name = canonicalize_name(ireq.req.name) line = str(ireq.req).lower() if marker: From 4c25f28da3a2e3d7659a403cfe0fa80d477e8a47 Mon Sep 17 00:00:00 2001 From: Dustin Ingram Date: Wed, 2 Feb 2022 08:17:06 -0500 Subject: [PATCH 05/11] Update test that doesn't rewrite requirements file This test doesn't actually modify the requirements file, so update it to start with a normalized requirement name so it can continue to expect a normalized requirement name. --- tests/test_cli_compile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_cli_compile.py b/tests/test_cli_compile.py index 585165908..63544bb13 100644 --- a/tests/test_cli_compile.py +++ b/tests/test_cli_compile.py @@ -610,7 +610,7 @@ def test_url_package(runner, line, dependency, generate_hashes): ), pytest.param( path_to_url(os.path.join(PACKAGES_PATH, "small_fake_with_subdir")) - + "#subdirectory=subdir&egg=small_fake_a", + + "#subdirectory=subdir&egg=small-fake-a", "small-fake-a @ " + path_to_url(os.path.join(PACKAGES_PATH, "small_fake_with_subdir")) + "#subdirectory=subdir", From a38d6b622230f383ea23092ee88fbd199829b6b9 Mon Sep 17 00:00:00 2001 From: Dustin Ingram Date: Wed, 2 Feb 2022 08:19:15 -0500 Subject: [PATCH 06/11] Update test that compares our output to pip freeze This is where we diverge from pip's output: pip no longer guarantees that it will canonicalize requirement names in `pip freeze` but we will continue to output canonicalized names. --- tests/test_writer.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/test_writer.py b/tests/test_writer.py index 196cd12ed..7884a4532 100644 --- a/tests/test_writer.py +++ b/tests/test_writer.py @@ -381,7 +381,8 @@ def test_write_find_links(writer, find_links, expected_lines): def test_write_order(writer, from_line): """ - Order of packages should match that of `pip freeze`. + Order of packages should match that of `pip freeze`, with the exception + that requirement names should be canonicalized. """ writer.emit_header = False @@ -393,7 +394,7 @@ def test_write_order(writer, from_line): ] expected_lines = [ "package==5.6", - "package_a==0.1", + "package-a==0.1", "package-b==2.3.4", "package2==7.8.9", ] From d1eba7f197eb60c9f6b470eea97c4f4e76471b4d Mon Sep 17 00:00:00 2001 From: Dustin Ingram Date: Wed, 2 Feb 2022 10:43:23 -0500 Subject: [PATCH 07/11] Copy ireq.req instead of mutating it Co-authored-by: wouter bolsterlee --- piptools/utils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/piptools/utils.py b/piptools/utils.py index 11dc1164b..7912f5a4f 100644 --- a/piptools/utils.py +++ b/piptools/utils.py @@ -124,7 +124,9 @@ def format_requirement( else: # Canonicalize the requirement name # https://packaging.pypa.io/en/latest/utils.html#packaging.utils.canonicalize_name - ireq.req.name = canonicalize_name(ireq.req.name) + req = copy.copy(ireq.req) + req.name = canonicalize_name(req.name) + line = str(req) line = str(ireq.req).lower() if marker: From a6fe9b8652c87b6324b17bd780c5570ca45bbd5c Mon Sep 17 00:00:00 2001 From: Dustin Ingram Date: Wed, 2 Feb 2022 09:49:35 -0600 Subject: [PATCH 08/11] Remove stray line --- piptools/utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/piptools/utils.py b/piptools/utils.py index 7912f5a4f..c84bbb91b 100644 --- a/piptools/utils.py +++ b/piptools/utils.py @@ -127,7 +127,6 @@ def format_requirement( req = copy.copy(ireq.req) req.name = canonicalize_name(req.name) line = str(req) - line = str(ireq.req).lower() if marker: line = f"{line} ; {marker}" From d6b39c5c8b9d78f40f54890717bfc29cd7dc7e7d Mon Sep 17 00:00:00 2001 From: Dustin Ingram Date: Wed, 2 Feb 2022 09:50:15 -0600 Subject: [PATCH 09/11] Import copy --- piptools/utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/piptools/utils.py b/piptools/utils.py index c84bbb91b..dc254a80e 100644 --- a/piptools/utils.py +++ b/piptools/utils.py @@ -1,4 +1,5 @@ import collections +import copy import itertools import json import os From 225032159f60732bd271458c1abb11e7b43390ea Mon Sep 17 00:00:00 2001 From: Dustin Ingram Date: Wed, 2 Feb 2022 08:40:08 -0500 Subject: [PATCH 10/11] Don't set up logging for newer versions of pip A new log handler for the 'console' logger was added in later versions of pip, which doesn't require this workaround. --- piptools/repositories/pypi.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/piptools/repositories/pypi.py b/piptools/repositories/pypi.py index d8cd16051..ffaad4187 100644 --- a/piptools/repositories/pypi.py +++ b/piptools/repositories/pypi.py @@ -40,6 +40,7 @@ from pip._vendor.packaging.version import _BaseVersion from pip._vendor.requests import RequestException, Session +from .._compat import PIP_VERSION from ..exceptions import NoCandidateFound from ..logging import log from ..utils import ( @@ -103,7 +104,8 @@ def __init__(self, pip_args: List[str], cache_dir: str): self._cache_dir = normalize_path(str(cache_dir)) self._download_dir = os.path.join(self._cache_dir, "pkgs") - self._setup_logging() + if PIP_VERSION[0] < 22: + self._setup_logging() def clear_caches(self) -> None: rmtree(self._download_dir, ignore_errors=True) @@ -439,7 +441,8 @@ def _wheel_support_index_min(self: Wheel, tags: List[Tag]) -> int: def _setup_logging(self) -> None: """ Setup pip's logger. Ensure pip is verbose same as pip-tools and sync - pip's log stream with LogContext.stream. + pip's log stream with LogContext.stream. This is only necessary for + pip<22.0. """ # Default pip's logger is noisy, so decrease it's verbosity setup_logging( From c06ab8f54f4fba3a842c00c9a2a47bc050f94be8 Mon Sep 17 00:00:00 2001 From: Dustin Ingram Date: Thu, 3 Feb 2022 07:07:14 -0500 Subject: [PATCH 11/11] Update README.rst Co-authored-by: Hugo van Kemenade --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index ca7550a33..8c4dd7b80 100644 --- a/README.rst +++ b/README.rst @@ -527,7 +527,7 @@ versions as the required ``pip`` versions. +---------------+----------------+----------------+ | 6.0.0 - 6.3.1 | 20.3 - 21.2.* | 3.6 - 3.9 | +---------------+----------------+----------------+ -| 6.4.0 | 21.2+ | 3.6 - 3.10 | +| 6.4.0 | 21.2 - 21.3.* | 3.6 - 3.10 | +---------------+----------------+----------------+ | 6.5.0+ | 21.2+ | 3.7 - 3.10 | +---------------+----------------+----------------+