From a642650e173c99a0adaa3df64e9872649932e8ca Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Mon, 19 Oct 2020 10:02:36 +0300 Subject: [PATCH 1/2] Drop support for EOL Python 3.5 --- README.rst | 2 +- doc/en/getting-started.rst | 2 +- doc/en/index.rst | 2 +- pyproject.toml | 2 +- src/_pytest/assertion/rewrite.py | 4 +-- src/_pytest/capture.py | 4 +-- src/_pytest/python_api.py | 2 +- testing/python/raises.py | 5 ---- testing/test_reports.py | 45 +++++++------------------------- 9 files changed, 17 insertions(+), 51 deletions(-) diff --git a/README.rst b/README.rst index 057278a926b..398d6451c58 100644 --- a/README.rst +++ b/README.rst @@ -89,7 +89,7 @@ Features - Can run `unittest `_ (or trial), `nose `_ test suites out of the box -- Python 3.5+ and PyPy3 +- Python 3.6+ and PyPy3 - Rich plugin architecture, with over 850+ `external plugins `_ and thriving community diff --git a/doc/en/getting-started.rst b/doc/en/getting-started.rst index 5a5f0fa7a43..724827d2971 100644 --- a/doc/en/getting-started.rst +++ b/doc/en/getting-started.rst @@ -1,7 +1,7 @@ Installation and Getting Started =================================== -**Pythons**: Python 3.5, 3.6, 3.7, 3.8, 3.9, PyPy3 +**Pythons**: Python 3.6, 3.7, 3.8, 3.9, PyPy3 **Platforms**: Linux and Windows diff --git a/doc/en/index.rst b/doc/en/index.rst index a57e9bbacee..ad2057ff14a 100644 --- a/doc/en/index.rst +++ b/doc/en/index.rst @@ -69,7 +69,7 @@ Features - Can run :ref:`unittest ` (including trial) and :ref:`nose ` test suites out of the box -- Python 3.5+ and PyPy 3 +- Python 3.6+ and PyPy 3 - Rich plugin architecture, with over 315+ `external plugins `_ and thriving community diff --git a/pyproject.toml b/pyproject.toml index 443b94c26a5..dce93a6065d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,7 @@ filterwarnings = [ "ignore:.*U.*mode is deprecated:DeprecationWarning:(?!(pytest|_pytest))", # produced by pytest-xdist "ignore:.*type argument to addoption.*:DeprecationWarning", - # produced by python >=3.5 on execnet (pytest-xdist) + # produced on execnet (pytest-xdist) "ignore:.*inspect.getargspec.*deprecated, use inspect.signature.*:DeprecationWarning", # pytest's own futurewarnings "ignore::pytest.PytestExperimentalApiWarning", diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index 12c94e99915..649726727c5 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -99,7 +99,7 @@ def find_spec( spec is None # this is a namespace package (without `__init__.py`) # there's nothing to rewrite there - # python3.5 - python3.6: `namespace` + # python3.6: `namespace` # python3.7+: `None` or spec.origin == "namespace" or spec.origin is None @@ -1005,7 +1005,7 @@ def visit_Call(self, call: ast.Call) -> Tuple[ast.Name, str]: return res, outer_expl def visit_Starred(self, starred: ast.Starred) -> Tuple[ast.Starred, str]: - # From Python 3.5, a Starred node can appear in a function call. + # A Starred node can appear in a function call. res, expl = self.visit(starred.value) new_starred = ast.Starred(res, starred.ctx) return new_starred, "*" + expl diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index 4d314998ce2..25535f67b75 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -497,9 +497,7 @@ def writeorg(self, data): class CaptureResult(Generic[AnyStr]): """The result of :method:`CaptureFixture.readouterr`.""" - # Can't use slots in Python<3.5.3 due to https://bugs.python.org/issue31272 - if sys.version_info >= (3, 5, 3): - __slots__ = ("out", "err") + __slots__ = ("out", "err") def __init__(self, out: AnyStr, err: AnyStr) -> None: self.out: AnyStr = out diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 373435236ce..9f4df8e7e9e 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -443,7 +443,7 @@ def approx(expected, rel=None, abs=None, nan_ok: bool = False) -> ApproxBase: both ``a`` and ``b``, this test is symmetric (i.e. neither ``a`` nor ``b`` is a "reference value"). You have to specify an absolute tolerance if you want to compare to ``0.0`` because there is no tolerance by - default. Only available in python>=3.5. `More information...`__ + default. `More information...`__ __ https://docs.python.org/3/library/math.html#math.isclose diff --git a/testing/python/raises.py b/testing/python/raises.py index c3580afad45..80634eebfbf 100644 --- a/testing/python/raises.py +++ b/testing/python/raises.py @@ -162,11 +162,6 @@ def test_raises_cyclic_reference(self, method): class T: def __call__(self): - # Early versions of Python 3.5 have some bug causing the - # __call__ frame to still refer to t even after everything - # is done. This makes the test pass for them. - if sys.version_info < (3, 5, 2): - del self raise ValueError t = T() diff --git a/testing/test_reports.py b/testing/test_reports.py index d18e680b775..b97b1fc2970 100644 --- a/testing/test_reports.py +++ b/testing/test_reports.py @@ -1,4 +1,3 @@ -import sys from pathlib import Path from typing import Sequence from typing import Union @@ -346,44 +345,18 @@ def test_chained_exceptions_no_reprcrash(self, testdir: Testdir, tw_mock) -> Non from subprocess to main process creates an artificial exception, which ExceptionInfo can't obtain the ReprFileLocation from. """ - # somehow in Python 3.5 on Windows this test fails with: - # File "c:\...\3.5.4\x64\Lib\multiprocessing\connection.py", line 302, in _recv_bytes - # overlapped=True) - # OSError: [WinError 6] The handle is invalid - # - # so in this platform we opted to use a mock traceback which is identical to the - # one produced by the multiprocessing module - if sys.version_info[:2] <= (3, 5) and sys.platform.startswith("win"): - testdir.makepyfile( - """ - # equivalent of multiprocessing.pool.RemoteTraceback - class RemoteTraceback(Exception): - def __init__(self, tb): - self.tb = tb - def __str__(self): - return self.tb - def test_a(): - try: - raise ValueError('value error') - except ValueError as e: - # equivalent to how multiprocessing.pool.rebuild_exc does it - e.__cause__ = RemoteTraceback('runtime error') - raise e + testdir.makepyfile( """ - ) - else: - testdir.makepyfile( - """ - from concurrent.futures import ProcessPoolExecutor + from concurrent.futures import ProcessPoolExecutor - def func(): - raise ValueError('value error') + def func(): + raise ValueError('value error') - def test_a(): - with ProcessPoolExecutor() as p: - p.submit(func).result() - """ - ) + def test_a(): + with ProcessPoolExecutor() as p: + p.submit(func).result() + """ + ) testdir.syspathinsert() reprec = testdir.inline_run() From c9e5042d6d29944b3ed82a08475f3d40f40aa842 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Mon, 19 Oct 2020 10:47:35 +0300 Subject: [PATCH 2/2] Remove redundant Python 2.7 code --- testing/code/test_excinfo.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/testing/code/test_excinfo.py b/testing/code/test_excinfo.py index 5f0ade4105c..a55da643068 100644 --- a/testing/code/test_excinfo.py +++ b/testing/code/test_excinfo.py @@ -1,3 +1,4 @@ +import importlib import io import operator import os @@ -20,13 +21,6 @@ from _pytest._io import TerminalWriter from _pytest.pytester import LineMatcher -try: - import importlib -except ImportError: - invalidate_import_caches = None -else: - invalidate_import_caches = getattr(importlib, "invalidate_caches", None) - if TYPE_CHECKING: from _pytest._code.code import _TracebackStyle @@ -445,8 +439,7 @@ def importasmod(source): modpath = tmpdir.join("mod.py") tmpdir.ensure("__init__.py") modpath.write(source) - if invalidate_import_caches is not None: - invalidate_import_caches() + importlib.invalidate_caches() return modpath.pyimport() return importasmod