Drop support for EOL Python 3.6
This commit is contained in:
parent
b9663fed6f
commit
1fd3601caa
|
@ -111,4 +111,4 @@ template = "changelog/_template.rst"
|
||||||
showcontent = true
|
showcontent = true
|
||||||
|
|
||||||
[tool.black]
|
[tool.black]
|
||||||
target-version = ['py36']
|
target-version = ['py37']
|
||||||
|
|
|
@ -100,9 +100,6 @@ class AssertionRewritingHook(importlib.abc.MetaPathFinder, importlib.abc.Loader)
|
||||||
spec is None
|
spec is None
|
||||||
# this is a namespace package (without `__init__.py`)
|
# this is a namespace package (without `__init__.py`)
|
||||||
# there's nothing to rewrite there
|
# there's nothing to rewrite there
|
||||||
# python3.6: `namespace`
|
|
||||||
# python3.7+: `None`
|
|
||||||
or spec.origin == "namespace"
|
|
||||||
or spec.origin is None
|
or spec.origin is None
|
||||||
# we can only rewrite source files
|
# we can only rewrite source files
|
||||||
or not isinstance(spec.loader, importlib.machinery.SourceFileLoader)
|
or not isinstance(spec.loader, importlib.machinery.SourceFileLoader)
|
||||||
|
|
|
@ -68,8 +68,8 @@ def _colorama_workaround() -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def _py36_windowsconsoleio_workaround(stream: TextIO) -> None:
|
def _windowsconsoleio_workaround(stream: TextIO) -> None:
|
||||||
"""Workaround for Windows Unicode console handling on Python>=3.6.
|
"""Workaround for Windows Unicode console handling.
|
||||||
|
|
||||||
Python 3.6 implemented Unicode console handling for Windows. This works
|
Python 3.6 implemented Unicode console handling for Windows. This works
|
||||||
by reading/writing to the raw console handle using
|
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):
|
def pytest_load_initial_conftests(early_config: Config):
|
||||||
ns = early_config.known_args_namespace
|
ns = early_config.known_args_namespace
|
||||||
if ns.capture == "fd":
|
if ns.capture == "fd":
|
||||||
_py36_windowsconsoleio_workaround(sys.stdout)
|
_windowsconsoleio_workaround(sys.stdout)
|
||||||
_colorama_workaround()
|
_colorama_workaround()
|
||||||
pluginmanager = early_config.pluginmanager
|
pluginmanager = early_config.pluginmanager
|
||||||
capman = CaptureManager(ns.capture)
|
capman = CaptureManager(ns.capture)
|
||||||
|
|
|
@ -414,7 +414,7 @@ class PyCollector(PyobjMixin, nodes.Collector):
|
||||||
for basecls in self.obj.__mro__:
|
for basecls in self.obj.__mro__:
|
||||||
dicts.append(basecls.__dict__)
|
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.
|
# __dict__ is definition ordered.
|
||||||
seen: Set[str] = set()
|
seen: Set[str] = set()
|
||||||
dict_values: List[List[Union[nodes.Item, nodes.Collector]]] = []
|
dict_values: List[List[Union[nodes.Item, nodes.Collector]]] = []
|
||||||
|
@ -894,8 +894,6 @@ class InstanceDummy:
|
||||||
pass
|
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:
|
def __getattr__(name: str) -> object:
|
||||||
if name == "Instance":
|
if name == "Instance":
|
||||||
warnings.warn(INSTANCE_COLLECTOR, 2)
|
warnings.warn(INSTANCE_COLLECTOR, 2)
|
||||||
|
|
|
@ -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:
|
def test_importing_instance_is_deprecated(pytester: Pytester) -> None:
|
||||||
with pytest.warns(
|
with pytest.warns(
|
||||||
pytest.PytestDeprecationWarning,
|
pytest.PytestDeprecationWarning,
|
||||||
|
|
|
@ -1123,9 +1123,6 @@ class TestAssertionRewriteHookDetails:
|
||||||
|
|
||||||
assert _read_pyc(source, pyc) is None # no error
|
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:
|
def test_read_pyc_more_invalid(self, tmp_path: Path) -> None:
|
||||||
from _pytest.assertion.rewrite import _read_pyc
|
from _pytest.assertion.rewrite import _read_pyc
|
||||||
|
|
||||||
|
|
|
@ -1433,19 +1433,19 @@ def test_error_attribute_issue555(pytester: Pytester) -> None:
|
||||||
not sys.platform.startswith("win"),
|
not sys.platform.startswith("win"),
|
||||||
reason="only on windows",
|
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).
|
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:
|
class DummyStream:
|
||||||
def write(self, s):
|
def write(self, s):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
stream = cast(TextIO, DummyStream())
|
stream = cast(TextIO, DummyStream())
|
||||||
_py36_windowsconsoleio_workaround(stream)
|
_windowsconsoleio_workaround(stream)
|
||||||
|
|
||||||
|
|
||||||
def test_dontreadfrominput_has_encoding(pytester: Pytester) -> None:
|
def test_dontreadfrominput_has_encoding(pytester: Pytester) -> None:
|
||||||
|
|
|
@ -133,7 +133,7 @@ def test_is_generator_async_gen_syntax(pytester: Pytester) -> None:
|
||||||
pytester.makepyfile(
|
pytester.makepyfile(
|
||||||
"""
|
"""
|
||||||
from _pytest.compat import is_generator
|
from _pytest.compat import is_generator
|
||||||
def test_is_generator_py36():
|
def test_is_generator():
|
||||||
async def foo():
|
async def foo():
|
||||||
yield
|
yield
|
||||||
await foo()
|
await foo()
|
||||||
|
|
|
@ -4,8 +4,6 @@ Tests and examples for correct "+/-" usage in error diffs.
|
||||||
See https://github.com/pytest-dev/pytest/issues/3333 for details.
|
See https://github.com/pytest-dev/pytest/issues/3333 for details.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import sys
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest.pytester import Pytester
|
from _pytest.pytester import Pytester
|
||||||
|
|
||||||
|
@ -210,68 +208,63 @@ TESTCASES = [
|
||||||
""",
|
""",
|
||||||
id='Test "not in" string',
|
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)
|
@pytest.mark.parametrize("code, expected", TESTCASES)
|
||||||
|
|
|
@ -450,7 +450,6 @@ def test_samefile_false_negatives(tmp_path: Path, monkeypatch: MonkeyPatch) -> N
|
||||||
|
|
||||||
|
|
||||||
class TestImportLibMode:
|
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:
|
def test_importmode_importlib_with_dataclass(self, tmp_path: Path) -> None:
|
||||||
"""Ensure that importlib mode works with a module containing dataclasses (#7856)."""
|
"""Ensure that importlib mode works with a module containing dataclasses (#7856)."""
|
||||||
fn = tmp_path.joinpath("_src/tests/test_dataclass.py")
|
fn = tmp_path.joinpath("_src/tests/test_dataclass.py")
|
||||||
|
|
Loading…
Reference in New Issue