Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove support for EOL Python 3.5 and 2.7 #1243

Merged
merged 9 commits into from Dec 31, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/ci.yml
Expand Up @@ -23,8 +23,6 @@ jobs:
- macOS
python-version:
- 3.9
- 2.7
- 3.5
- 3.6
- 3.7
- 3.8
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/cron.yml
Expand Up @@ -18,8 +18,6 @@ jobs:
- MacOS
python-version:
- 3.9
- 2.7
- 3.5
- 3.6
- 3.7
- 3.8
Expand Down
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Expand Up @@ -3,6 +3,7 @@ repos:
rev: 20.8b1
hooks:
- id: black
args: [--target-version=py36]
language_version: python3
- repo: https://github.com/PyCQA/isort
rev: 5.6.4
Expand Down
8 changes: 5 additions & 3 deletions README.rst
Expand Up @@ -421,15 +421,15 @@ 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-py2.7-requirements.txt``, ``macos-py3.6-requirements.txt``, etc.).
(ex: ``win32-py3.7-requirements.txt``, ``macos-py3.6-requirements.txt``, etc.).


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

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

Expand Down Expand Up @@ -493,5 +493,7 @@ versions as the required ``pip`` versions.
+---------------+----------------+----------------+
| 5.4.0 | 20.1 - 20.3.* | 2.7, 3.5 - 3.8 |
+---------------+----------------+----------------+
| >= 5.5.0 | 20.1 - 20.3.* | 2.7, 3.5 - 3.9 |
| 5.5.0 | 20.1 - 20.3.* | 2.7, 3.5 - 3.9 |
+---------------+----------------+----------------+
| 6.0.0 | 20.1 - 20.3.* | 3.6 - 3.9 |
+---------------+----------------+----------------+
2 changes: 1 addition & 1 deletion piptools/__init__.py
Expand Up @@ -8,4 +8,4 @@
locale.setlocale(locale.LC_ALL, "")
except locale.Error as e: # pragma: no cover
# setlocale can apparently crash if locale are uninitialized
secho("Ignoring error when setting locale: {}".format(e), fg="red")
secho(f"Ignoring error when setting locale: {e}", fg="red")
24 changes: 0 additions & 24 deletions piptools/_compat/__init__.py
@@ -1,26 +1,2 @@
# coding: utf-8
# flake8: noqa
from __future__ import absolute_import, division, print_function, unicode_literals

import errno
import os

from pip._vendor import six

from .pip_compat import PIP_VERSION, parse_requirements

if six.PY2:
from .tempfile import TemporaryDirectory
else:
from tempfile import TemporaryDirectory


def makedirs(name, mode=0o777, exist_ok=False):
if six.PY2:
try:
os.makedirs(name, mode)
except OSError as e:
if not exist_ok or e.errno != errno.EEXIST:
raise
else:
os.makedirs(name, mode, exist_ok)
2 changes: 1 addition & 1 deletion piptools/_compat/contextlib.py
@@ -1,5 +1,5 @@
# Ported from python 3.7 contextlib.py
class nullcontext(object):
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:
Expand Down
3 changes: 0 additions & 3 deletions piptools/_compat/pip_compat.py
@@ -1,6 +1,3 @@
# -*- coding=utf-8 -*-
from __future__ import absolute_import

import pip
from pip._internal.req import parse_requirements as _parse_requirements
from pip._internal.req.constructors import install_req_from_parsed_requirement
Expand Down
88 changes: 0 additions & 88 deletions piptools/_compat/tempfile.py

This file was deleted.

25 changes: 9 additions & 16 deletions piptools/cache.py
@@ -1,15 +1,10 @@
# coding: utf-8
from __future__ import absolute_import, division, print_function, unicode_literals

import errno
import json
import os
import platform
import sys

from pip._vendor.packaging.requirements import Requirement

from ._compat import makedirs
from .exceptions import PipToolsError
from .utils import as_tuple, key_from_req, lookup_table

Expand All @@ -33,16 +28,16 @@ def __str__(self):
lines = [
"The dependency cache seems to have been corrupted.",
"Inspect, or delete, the following file:",
" {}".format(self.path),
f" {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) as cache_file:
try:
doc = json.load(cache_file)
except ValueError:
except json.JSONDecodeError:
raise CorruptCacheError(cache_file_path)

# Check version and load the contents
Expand All @@ -51,7 +46,7 @@ def read_cache_file(cache_file_path):
return doc["dependencies"]


class DependencyCache(object):
class DependencyCache:
"""
Creates a new persistent dependency cache for the current Python version.
The cache file is written to the appropriate user cache dir for the
Expand All @@ -64,8 +59,8 @@ class DependencyCache(object):
"""

def __init__(self, cache_dir):
makedirs(cache_dir, exist_ok=True)
cache_filename = "depcache-{}.json".format(_implementation_name())
os.makedirs(cache_dir, exist_ok=True)
cache_filename = f"depcache-{_implementation_name()}.json"

self._cache_file = os.path.join(cache_dir, cache_filename)
self._cache = None
Expand Down Expand Up @@ -97,16 +92,14 @@ def as_cache_key(self, ireq):
if not extras:
extras_string = ""
else:
extras_string = "[{}]".format(",".join(extras))
return name, "{}{}".format(version, extras_string)
extras_string = f"[{','.join(extras)}]"
return name, f"{version}{extras_string}"

def read_cache(self):
"""Reads the cached contents into memory."""
try:
self._cache = read_cache_file(self._cache_file)
except IOError as e:
if e.errno != errno.ENOENT:
raise
except FileNotFoundError:
self._cache = {}

def write_cache(self):
Expand Down
2 changes: 0 additions & 2 deletions piptools/click.py
@@ -1,5 +1,3 @@
from __future__ import absolute_import

import click
from click import * # noqa

Expand Down
8 changes: 4 additions & 4 deletions piptools/exceptions.py
Expand Up @@ -22,26 +22,26 @@ def __str__(self):
else:
versions.append(version)

lines = ["Could not find a version that matches {}".format(self.ireq)]
lines = [f"Could not find a version that matches {self.ireq}"]

if versions:
lines.append("Tried: {}".format(", ".join(versions)))
lines.append(f"Tried: {', '.join(versions)}")

if pre_versions:
if self.finder.allow_all_prereleases:
line = "Tried"
else:
line = "Skipped"

line += " pre-versions: {}".format(", ".join(pre_versions))
line += f" pre-versions: {', '.join(pre_versions)}"
lines.append(line)

if versions or pre_versions:
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)
lines.extend(f" {ireq}" for ireq in source_ireqs)
else:
redacted_urls = tuple(
redact_auth_from_url(url) for url in self.finder.index_urls
Expand Down
4 changes: 1 addition & 3 deletions piptools/locations.py
Expand Up @@ -17,9 +17,7 @@

if os.path.exists(LEGACY_CACHE_DIR):
secho(
"Removing old cache dir {} (new cache dir is {})".format(
LEGACY_CACHE_DIR, CACHE_DIR
),
f"Removing old cache dir {LEGACY_CACHE_DIR} (new cache dir is {CACHE_DIR})",
fg="yellow",
)
rmtree(LEGACY_CACHE_DIR)
5 changes: 1 addition & 4 deletions piptools/logging.py
@@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import absolute_import, division, print_function, unicode_literals

import contextlib
import logging
import sys
Expand All @@ -12,7 +9,7 @@
logging.basicConfig()


class LogContext(object):
class LogContext:
stream = sys.stderr

def __init__(self, verbosity=0, indent_width=2):
Expand Down
8 changes: 1 addition & 7 deletions piptools/repositories/base.py
@@ -1,14 +1,8 @@
# coding: utf-8
from __future__ import absolute_import, division, print_function, unicode_literals

from abc import ABCMeta, abstractmethod
from contextlib import contextmanager

from pip._vendor.six import add_metaclass


@add_metaclass(ABCMeta)
class BaseRepository(object):
class BaseRepository(metaclass=ABCMeta):
def clear_caches(self):
"""Should clear any caches used by the implementation."""

Expand Down
3 changes: 0 additions & 3 deletions piptools/repositories/local.py
@@ -1,6 +1,3 @@
# coding: utf-8
from __future__ import absolute_import, division, print_function, unicode_literals

from contextlib import contextmanager

from pip._internal.utils.hashes import FAVORITE_HASH
Expand Down