diff --git a/pyproject.toml b/pyproject.toml index 70a9406a6..3d683aebe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -111,4 +111,4 @@ template = "changelog/_template.rst" showcontent = true [tool.black] -target-version = ['py36'] +target-version = ['py37'] diff --git a/src/_pytest/assertion/rewrite.py b/src/_pytest/assertion/rewrite.py index afdd35980..f0922870a 100644 --- a/src/_pytest/assertion/rewrite.py +++ b/src/_pytest/assertion/rewrite.py @@ -100,9 +100,6 @@ class AssertionRewritingHook(importlib.abc.MetaPathFinder, importlib.abc.Loader) spec is None # this is a namespace package (without `__init__.py`) # there's nothing to rewrite there - # python3.6: `namespace` - # python3.7+: `None` - or spec.origin == "namespace" or spec.origin is None # we can only rewrite source files or not isinstance(spec.loader, importlib.machinery.SourceFileLoader) diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index d82ee9552..ee9de3733 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -68,8 +68,8 @@ def _colorama_workaround() -> None: pass -def _py36_windowsconsoleio_workaround(stream: TextIO) -> None: - """Workaround for Windows Unicode console handling on Python>=3.6. +def _windowsconsoleio_workaround(stream: TextIO) -> None: + """Workaround for Windows Unicode console handling. Python 3.6 implemented Unicode console handling for Windows. This works by reading/writing to the raw console handle using @@ -128,7 +128,7 @@ def _py36_windowsconsoleio_workaround(stream: TextIO) -> None: def pytest_load_initial_conftests(early_config: Config): ns = early_config.known_args_namespace if ns.capture == "fd": - _py36_windowsconsoleio_workaround(sys.stdout) + _windowsconsoleio_workaround(sys.stdout) _colorama_workaround() pluginmanager = early_config.pluginmanager capman = CaptureManager(ns.capture) diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 8db9e7489..0462665cd 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -414,7 +414,7 @@ class PyCollector(PyobjMixin, nodes.Collector): for basecls in self.obj.__mro__: dicts.append(basecls.__dict__) - # In each class, nodes should be definition ordered. Since Python 3.6, + # In each class, nodes should be definition ordered. # __dict__ is definition ordered. seen: Set[str] = set() dict_values: List[List[Union[nodes.Item, nodes.Collector]]] = [] @@ -894,8 +894,6 @@ class InstanceDummy: pass -# Note: module __getattr__ only works on Python>=3.7. Unfortunately -# we can't provide this deprecation warning on Python 3.6. def __getattr__(name: str) -> object: if name == "Instance": warnings.warn(INSTANCE_COLLECTOR, 2) diff --git a/testing/deprecated_test.py b/testing/deprecated_test.py index c316b074c..07e69e684 100644 --- a/testing/deprecated_test.py +++ b/testing/deprecated_test.py @@ -234,10 +234,6 @@ def test_node_ctor_fspath_argument_is_deprecated(pytester: Pytester) -> None: ) -@pytest.mark.skipif( - sys.version_info < (3, 7), - reason="This deprecation can only be emitted on python>=3.7", -) def test_importing_instance_is_deprecated(pytester: Pytester) -> None: with pytest.warns( pytest.PytestDeprecationWarning, diff --git a/testing/test_assertrewrite.py b/testing/test_assertrewrite.py index a88c7eba3..c568143f5 100644 --- a/testing/test_assertrewrite.py +++ b/testing/test_assertrewrite.py @@ -1123,9 +1123,6 @@ class TestAssertionRewriteHookDetails: assert _read_pyc(source, pyc) is None # no error - @pytest.mark.skipif( - sys.version_info < (3, 7), reason="Only the Python 3.7 format for simplicity" - ) def test_read_pyc_more_invalid(self, tmp_path: Path) -> None: from _pytest.assertion.rewrite import _read_pyc diff --git a/testing/test_capture.py b/testing/test_capture.py index 1bc1f2f8d..f0c582b66 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -1433,19 +1433,19 @@ def test_error_attribute_issue555(pytester: Pytester) -> None: not sys.platform.startswith("win"), reason="only on windows", ) -def test_py36_windowsconsoleio_workaround_non_standard_streams() -> None: +def test_windowsconsoleio_workaround_non_standard_streams() -> None: """ - Ensure _py36_windowsconsoleio_workaround function works with objects that + Ensure _windowsconsoleio_workaround function works with objects that do not implement the full ``io``-based stream protocol, for example execnet channels (#2666). """ - from _pytest.capture import _py36_windowsconsoleio_workaround + from _pytest.capture import _windowsconsoleio_workaround class DummyStream: def write(self, s): pass stream = cast(TextIO, DummyStream()) - _py36_windowsconsoleio_workaround(stream) + _windowsconsoleio_workaround(stream) def test_dontreadfrominput_has_encoding(pytester: Pytester) -> None: diff --git a/testing/test_compat.py b/testing/test_compat.py index 8471a1a50..88f0f33ef 100644 --- a/testing/test_compat.py +++ b/testing/test_compat.py @@ -133,7 +133,7 @@ def test_is_generator_async_gen_syntax(pytester: Pytester) -> None: pytester.makepyfile( """ from _pytest.compat import is_generator - def test_is_generator_py36(): + def test_is_generator(): async def foo(): yield await foo() diff --git a/testing/test_error_diffs.py b/testing/test_error_diffs.py index 1668e929a..d880be0da 100644 --- a/testing/test_error_diffs.py +++ b/testing/test_error_diffs.py @@ -4,8 +4,6 @@ Tests and examples for correct "+/-" usage in error diffs. See https://github.com/pytest-dev/pytest/issues/3333 for details. """ -import sys - import pytest from _pytest.pytester import Pytester @@ -210,68 +208,63 @@ TESTCASES = [ """, id='Test "not in" string', ), + pytest.param( + """ + from dataclasses import dataclass + + @dataclass + class A: + a: int + b: str + + def test_this(): + result = A(1, 'spam') + expected = A(2, 'spam') + assert result == expected + """, + """ + > assert result == expected + E AssertionError: assert A(a=1, b='spam') == A(a=2, b='spam') + E Matching attributes: + E ['b'] + E Differing attributes: + E ['a'] + E Drill down into differing attribute a: + E a: 1 != 2 + E +1 + E -2 + """, + id="Compare data classes", + ), + pytest.param( + """ + import attr + + @attr.s(auto_attribs=True) + class A: + a: int + b: str + + def test_this(): + result = A(1, 'spam') + expected = A(1, 'eggs') + assert result == expected + """, + """ + > assert result == expected + E AssertionError: assert A(a=1, b='spam') == A(a=1, b='eggs') + E Matching attributes: + E ['a'] + E Differing attributes: + E ['b'] + E Drill down into differing attribute b: + E b: 'spam' != 'eggs' + E - eggs + E + spam + """, + id="Compare attrs classes", + ), ] -if sys.version_info[:2] >= (3, 7): - TESTCASES.extend( - [ - pytest.param( - """ - from dataclasses import dataclass - - @dataclass - class A: - a: int - b: str - - def test_this(): - result = A(1, 'spam') - expected = A(2, 'spam') - assert result == expected - """, - """ - > assert result == expected - E AssertionError: assert A(a=1, b='spam') == A(a=2, b='spam') - E Matching attributes: - E ['b'] - E Differing attributes: - E ['a'] - E Drill down into differing attribute a: - E a: 1 != 2 - E +1 - E -2 - """, - id="Compare data classes", - ), - pytest.param( - """ - import attr - - @attr.s(auto_attribs=True) - class A: - a: int - b: str - - def test_this(): - result = A(1, 'spam') - expected = A(1, 'eggs') - assert result == expected - """, - """ - > assert result == expected - E AssertionError: assert A(a=1, b='spam') == A(a=1, b='eggs') - E Matching attributes: - E ['a'] - E Differing attributes: - E ['b'] - E Drill down into differing attribute b: - E b: 'spam' != 'eggs' - E - eggs - E + spam - """, - id="Compare attrs classes", - ), - ] - ) @pytest.mark.parametrize("code, expected", TESTCASES) diff --git a/testing/test_pathlib.py b/testing/test_pathlib.py index 5eb153e84..24cd71b25 100644 --- a/testing/test_pathlib.py +++ b/testing/test_pathlib.py @@ -450,7 +450,6 @@ def test_samefile_false_negatives(tmp_path: Path, monkeypatch: MonkeyPatch) -> N class TestImportLibMode: - @pytest.mark.skipif(sys.version_info < (3, 7), reason="Dataclasses in Python3.7+") def test_importmode_importlib_with_dataclass(self, tmp_path: Path) -> None: """Ensure that importlib mode works with a module containing dataclasses (#7856).""" fn = tmp_path.joinpath("_src/tests/test_dataclass.py")