Skip to content

Commit

Permalink
Drop Python 3.4 support (#2143)
Browse files Browse the repository at this point in the history
  • Loading branch information
gaborbernat authored Jul 13, 2021
1 parent c746322 commit ce6efc8
Show file tree
Hide file tree
Showing 17 changed files with 18 additions and 71 deletions.
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

0 comments on commit ce6efc8

Please sign in to comment.