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

Drop Python 3.4 support #2143

Merged
merged 1 commit into from
Jul 13, 2021
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ jobs:
- pypy2
include:
- { os: macos-latest, py: brew@py3 }
- { os: "ubuntu-18.04", py: 3.4.10 }
steps:
- name: Install OS dependencies
run: |
Expand Down
1 change: 1 addition & 0 deletions docs/changelog/2141.removal.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Drop python ``3.4`` support as it has been over 2 years since EOL - by :user:`gaborbernat`.
4 changes: 2 additions & 2 deletions docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ Python and OS Compatibility

virtualenv works with the following Python interpreter implementations:

- `CPython <https://www.python.org/>`_ versions 2.7, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9
- `PyPy <https://pypy.org/>`_ 2.7 and 3.4+.
- `CPython <https://www.python.org/>`_ versions 2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10
- `PyPy <https://pypy.org/>`_ 2.7 and 3.5+.

This means virtualenv works on the latest patch version of each of these minor versions. Previous patch versions are
supported on a best effort approach.
Expand Down
2 changes: 1 addition & 1 deletion docs/user_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ at the moment has two types of virtual environments:

- ``venv`` - this delegates the creation process towards the ``venv`` module, as described in
`PEP 405 <https://www.python.org/dev/peps/pep-0405>`_. This is only available on Python interpreters having version
``3.4`` or later, and also has the downside that virtualenv **must** create a process to invoke that module (unless
``3.5`` or later, and also has the downside that virtualenv **must** create a process to invoke that module (unless
virtualenv is installed in the system python), which can be an expensive operation (especially true on Windows).

- ``builtin`` - this means ``virtualenv`` is able to do the creation operation itself (by knowing exactly what files to
Expand Down
3 changes: 1 addition & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ classifiers =
Programming Language :: Python :: 2
Programming Language :: Python :: 2.7
Programming Language :: Python :: 3
Programming Language :: Python :: 3.4
Programming Language :: Python :: 3.5
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Expand All @@ -48,7 +47,7 @@ install_requires =
importlib-metadata>=0.12;python_version<"3.8"
importlib-resources>=1.0;python_version<"3.7"
pathlib2>=2.3.3,<3;python_version < '3.4' and sys.platform != 'win32'
python_requires = >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
python_requires = >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
package_dir =
=src
zip_safe = True
Expand Down
2 changes: 1 addition & 1 deletion src/virtualenv/discovery/cached_py_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def from_exe(cls, app_data, exe, env=None, raise_on_error=True, ignore_cache=Fal

def _get_from_cache(cls, app_data, exe, env, ignore_cache=True):
# note here we cannot resolve symlinks, as the symlink may trigger different prefix information if there's a
# pyenv.cfg somewhere alongside on python3.4+
# pyenv.cfg somewhere alongside on python3.5+
exe_path = Path(exe)
if not ignore_cache and exe_path in _CACHE: # check in the in-memory cache
result = _CACHE[exe_path]
Expand Down
5 changes: 0 additions & 5 deletions src/virtualenv/seed/wheels/embed/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,6 @@
"setuptools": "setuptools-50.3.2-py3-none-any.whl",
"wheel": "wheel-0.36.2-py2.py3-none-any.whl",
},
"3.4": {
"pip": "pip-19.1.1-py2.py3-none-any.whl",
"setuptools": "setuptools-43.0.0-py2.py3-none-any.whl",
"wheel": "wheel-0.33.6-py2.py3-none-any.whl",
},
"2.7": {
"pip": "pip-20.3.4-py2.py3-none-any.whl",
"setuptools": "setuptools-44.1.1-py2.py3-none-any.whl",
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
46 changes: 0 additions & 46 deletions src/virtualenv/util/path/_pathlib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,52 +6,6 @@

if six.PY3:
from pathlib import Path

if sys.version_info[0:2] == (3, 4):
# no read/write text on python3.4
BuiltinPath = Path

class Path(type(BuiltinPath())):
def read_text(self, encoding=None, errors=None):
"""
Open the file in text mode, read it, and close the file.
"""
with self.open(mode="r", encoding=encoding, errors=errors) as f:
return f.read()

def read_bytes(self):
"""
Open the file in bytes mode, read it, and close the file.
"""
with self.open(mode="rb") as f:
return f.read()

def write_text(self, data, encoding=None, errors=None):
"""
Open the file in text mode, write to it, and close the file.
"""
if not isinstance(data, str):
raise TypeError("data must be str, not %s" % data.__class__.__name__)
with self.open(mode="w", encoding=encoding, errors=errors) as f:
return f.write(data)

def write_bytes(self, data):
"""
Open the file in bytes mode, write to it, and close the file.
"""
# type-check for the buffer interface before truncating the file
view = memoryview(data)
with self.open(mode="wb") as f:
return f.write(view)

def mkdir(self, mode=0o777, parents=False, exist_ok=False):
try:
super(type(BuiltinPath()), self).mkdir(mode, parents)
except FileExistsError as exception:
if not exist_ok:
raise exception


else:
if sys.platform == "win32":
# workaround for https://github.com/mcmtroffaes/pathlib2/issues/56
Expand Down
2 changes: 1 addition & 1 deletion tasks/make_zipapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

HERE = Path(__file__).parent.absolute()

VERSIONS = ["3.{}".format(i) for i in range(9, 3, -1)] + ["2.7"]
VERSIONS = ["3.{}".format(i) for i in range(10, 4, -1)] + ["2.7"]


def main():
Expand Down
2 changes: 1 addition & 1 deletion tasks/upgrade_wheels.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
STRICT = "UPGRADE_ADVISORY" not in os.environ

BUNDLED = ["pip", "setuptools", "wheel"]
SUPPORT = list(reversed([(2, 7)] + [(3, i) for i in range(4, 11)]))
SUPPORT = list(reversed([(2, 7)] + [(3, i) for i in range(5, 11)]))
DEST = Path(__file__).resolve().parents[1] / "src" / "virtualenv" / "seed" / "wheels" / "embed"


Expand Down
2 changes: 0 additions & 2 deletions tests/unit/create/test_creator.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,6 @@ def system(session_app_data):
ids=lambda i: "-".join(i) if isinstance(i, tuple) else i,
)
def test_create_no_seed(python, creator, isolated, system, coverage_env, special_name_dir):
if creator[0] == "venv" and sys.version_info[0:2] == (3, 4): # venv on python3.4 only supports ascii chars
special_name_dir = special_name_dir.with_name(special_name_dir.name.encode("ascii", errors="ignore").decode())
dest = special_name_dir
creator_key, method = creator
cmd = [
Expand Down
6 changes: 4 additions & 2 deletions tests/unit/seed/embed/test_pip_invoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def test_base_bootstrap_via_pip_invoke(tmp_path, coverage_env, mocker, current_f
def _load_embed_wheel(app_data, distribution, for_py_version, version):
return load_embed_wheel(app_data, distribution, old_ver, version)

old_ver = "3.4"
old_ver = "2.7"
old = BUNDLE_SUPPORT[old_ver]
mocker.patch("virtualenv.seed.wheels.bundle.load_embed_wheel", side_effect=_load_embed_wheel)

Expand All @@ -36,7 +36,9 @@ def _execute(cmd, env):
continue
if with_version == "embed":
expected.add(BUNDLE_FOLDER)
elif old[dist] != new[dist]:
elif old[distribution] == new[distribution]:
expected.add(BUNDLE_FOLDER)
else:
expected.add(extra_search_dir)
expected_list = list(
itertools.chain.from_iterable(["--find-links", str(e)] for e in sorted(expected, key=lambda x: str(x))),
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/seed/wheels/test_periodic_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def _do_update(distribution, for_py_version, embed_filename, app_data, search_di


def test_pick_periodic_update(tmp_path, session_app_data, mocker, for_py_version):
embed, current = get_embed_wheel("setuptools", "3.4"), get_embed_wheel("setuptools", for_py_version)
embed, current = get_embed_wheel("setuptools", "3.5"), get_embed_wheel("setuptools", for_py_version)
mocker.patch("virtualenv.seed.wheels.bundle.load_embed_wheel", return_value=embed)
completed = datetime.now() - timedelta(days=29)
u_log = UpdateLog(
Expand Down
11 changes: 5 additions & 6 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ envlist =
py37
py36
py35
py34
py27
pypy3
pypy2
Expand All @@ -30,21 +29,22 @@ setenv =
COVERAGE_PROCESS_START = {toxinidir}/.coveragerc
PYTHONIOENCODING = utf-8
_COVERAGE_SRC = {envsitepackagesdir}/virtualenv
{py34,py27,pypy2, upgrade}: PYTHONWARNINGS = ignore:DEPRECATION::pip._internal.cli.base_command
{py27,pypy2, upgrade}: PYTHONWARNINGS = ignore:DEPRECATION::pip._internal.cli.base_command
extras =
testing
commands =
python -m coverage erase
python -m coverage run -m pytest \
python -m coverage run -m pytest {tty:--color=yes} \
--junitxml {toxworkdir}/junit.{envname}.xml \
{posargs:tests --int --timeout 600}
python -m coverage combine
python -m coverage report --skip-covered --show-missing
python -m coverage xml -o {toxworkdir}/coverage.{envname}.xml
python -m coverage html -d {envtmpdir}/htmlcov \
!py34: --show-contexts \
python -m coverage html -d {envtmpdir}/htmlcov --show-contexts \
--title virtualenv-{envname}-coverage
install_command = python -m pip install {opts} {packages} --disable-pip-version-check
package = wheel
wheel_build_env = .pkg

[testenv:fix_lint]
description = format the code base to adhere to our styles, and complain about what we cannot do automatically
Expand Down Expand Up @@ -83,7 +83,6 @@ depends =
py37
py36
py35
py34
py27
pypy
pypy3
Expand Down