Merge pull request #9442 from hramezani/drop_python_36
Drop Python3.6 in CI, setup.cfg, and readme.
This commit is contained in:
commit
b9663fed6f
|
@ -31,14 +31,12 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
name: [
|
||||
"windows-py36",
|
||||
"windows-py37",
|
||||
"windows-py37-pluggy",
|
||||
"windows-py38",
|
||||
"windows-py39",
|
||||
"windows-py310",
|
||||
|
||||
"ubuntu-py36",
|
||||
"ubuntu-py37",
|
||||
"ubuntu-py37-pluggy",
|
||||
"ubuntu-py37-freeze",
|
||||
|
@ -56,10 +54,6 @@ jobs:
|
|||
]
|
||||
|
||||
include:
|
||||
- name: "windows-py36"
|
||||
python: "3.6"
|
||||
os: windows-latest
|
||||
tox_env: "py36-xdist"
|
||||
- name: "windows-py37"
|
||||
python: "3.7"
|
||||
os: windows-latest
|
||||
|
@ -82,10 +76,6 @@ jobs:
|
|||
os: windows-latest
|
||||
tox_env: "py310-xdist"
|
||||
|
||||
- name: "ubuntu-py36"
|
||||
python: "3.6"
|
||||
os: ubuntu-latest
|
||||
tox_env: "py36-xdist"
|
||||
- name: "ubuntu-py37"
|
||||
python: "3.7"
|
||||
os: ubuntu-latest
|
||||
|
|
|
@ -32,12 +32,12 @@ repos:
|
|||
rev: v2.6.0
|
||||
hooks:
|
||||
- id: reorder-python-imports
|
||||
args: ['--application-directories=.:src', --py36-plus]
|
||||
args: ['--application-directories=.:src', --py37-plus]
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v2.29.1
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: [--py36-plus]
|
||||
args: [--py37-plus]
|
||||
- repo: https://github.com/asottile/setup-cfg-fmt
|
||||
rev: v1.20.0
|
||||
hooks:
|
||||
|
|
|
@ -100,7 +100,7 @@ Features
|
|||
- Can run `unittest <https://docs.pytest.org/en/stable/how-to/unittest.html>`_ (or trial),
|
||||
`nose <https://docs.pytest.org/en/stable/how-to/nose.html>`_ test suites out of the box
|
||||
|
||||
- Python 3.6+ and PyPy3
|
||||
- Python 3.7+ or PyPy3
|
||||
|
||||
- Rich plugin architecture, with over 850+ `external plugins <https://docs.pytest.org/en/latest/reference/plugin_list.html>`_ and thriving community
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Dropped support for Python 3.6, which reached `end-of-life <https://devguide.python.org/#status-of-python-branches>`__ at 2021-12-23.
|
|
@ -9,7 +9,7 @@ Get Started
|
|||
Install ``pytest``
|
||||
----------------------------------------
|
||||
|
||||
``pytest`` requires: Python 3.6, 3.7, 3.8, 3.9, or PyPy3.
|
||||
``pytest`` requires: Python 3.7+ or PyPy3.
|
||||
|
||||
1. Run the following command in your command line:
|
||||
|
||||
|
|
|
@ -84,14 +84,14 @@ It is also possible to skip the whole module using
|
|||
|
||||
If you wish to skip something conditionally then you can use ``skipif`` instead.
|
||||
Here is an example of marking a test function to be skipped
|
||||
when run on an interpreter earlier than Python3.6:
|
||||
when run on an interpreter earlier than Python3.10:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 7), reason="requires python3.7 or higher")
|
||||
@pytest.mark.skipif(sys.version_info < (3, 10), reason="requires python3.10 or higher")
|
||||
def test_function():
|
||||
...
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ The ``pytest`` framework makes it easy to write small, readable tests, and can
|
|||
scale to support complex functional testing for applications and libraries.
|
||||
|
||||
|
||||
**Pythons**: ``pytest`` requires: Python 3.6, 3.7, 3.8, 3.9, or PyPy3.
|
||||
``pytest`` requires: Python 3.7+ or PyPy3.
|
||||
|
||||
**PyPI package name**: :pypi:`pytest`
|
||||
|
||||
|
@ -78,7 +78,7 @@ Features
|
|||
|
||||
- Can run :ref:`unittest <unittest>` (including trial) and :ref:`nose <noseintegration>` test suites out of the box
|
||||
|
||||
- Python 3.6+ and PyPy 3
|
||||
- Python 3.7+ or PyPy 3
|
||||
|
||||
- Rich plugin architecture, with over 800+ :ref:`external plugins <plugin-list>` and thriving community
|
||||
|
||||
|
|
|
@ -28,8 +28,6 @@ filterwarnings = [
|
|||
"default:the imp module is deprecated in favour of importlib:DeprecationWarning:nose.*",
|
||||
# distutils is deprecated in 3.10, scheduled for removal in 3.12
|
||||
"ignore:The distutils package is deprecated:DeprecationWarning",
|
||||
# produced by python3.6/site.py itself (3.6.7 on Travis, could not trigger it with 3.6.8)."
|
||||
"ignore:.*U.*mode is deprecated:DeprecationWarning:(?!(pytest|_pytest))",
|
||||
# produced by pytest-xdist
|
||||
"ignore:.*type argument to addoption.*:DeprecationWarning",
|
||||
# produced on execnet (pytest-xdist)
|
||||
|
|
|
@ -17,7 +17,6 @@ classifiers =
|
|||
Operating System :: POSIX
|
||||
Programming Language :: Python :: 3
|
||||
Programming Language :: Python :: 3 :: Only
|
||||
Programming Language :: Python :: 3.6
|
||||
Programming Language :: Python :: 3.7
|
||||
Programming Language :: Python :: 3.8
|
||||
Programming Language :: Python :: 3.9
|
||||
|
@ -51,7 +50,7 @@ install_requires =
|
|||
atomicwrites>=1.0;sys_platform=="win32"
|
||||
colorama;sys_platform=="win32"
|
||||
importlib-metadata>=0.12;python_version<"3.8"
|
||||
python_requires = >=3.6
|
||||
python_requires = >=3.7
|
||||
package_dir =
|
||||
=src
|
||||
setup_requires =
|
||||
|
|
|
@ -293,9 +293,8 @@ def _write_pyc_fp(
|
|||
# import. However, there's little reason to deviate.
|
||||
fp.write(importlib.util.MAGIC_NUMBER)
|
||||
# https://www.python.org/dev/peps/pep-0552/
|
||||
if sys.version_info >= (3, 7):
|
||||
flags = b"\x00\x00\x00\x00"
|
||||
fp.write(flags)
|
||||
flags = b"\x00\x00\x00\x00"
|
||||
fp.write(flags)
|
||||
# as of now, bytecode header expects 32-bit numbers for size and mtime (#4903)
|
||||
mtime = int(source_stat.st_mtime) & 0xFFFFFFFF
|
||||
size = source_stat.st_size & 0xFFFFFFFF
|
||||
|
@ -376,31 +375,29 @@ def _read_pyc(
|
|||
except OSError:
|
||||
return None
|
||||
with fp:
|
||||
# https://www.python.org/dev/peps/pep-0552/
|
||||
has_flags = sys.version_info >= (3, 7)
|
||||
try:
|
||||
stat_result = os.stat(source)
|
||||
mtime = int(stat_result.st_mtime)
|
||||
size = stat_result.st_size
|
||||
data = fp.read(16 if has_flags else 12)
|
||||
data = fp.read(16)
|
||||
except OSError as e:
|
||||
trace(f"_read_pyc({source}): OSError {e}")
|
||||
return None
|
||||
# Check for invalid or out of date pyc file.
|
||||
if len(data) != (16 if has_flags else 12):
|
||||
if len(data) != (16):
|
||||
trace("_read_pyc(%s): invalid pyc (too short)" % source)
|
||||
return None
|
||||
if data[:4] != importlib.util.MAGIC_NUMBER:
|
||||
trace("_read_pyc(%s): invalid pyc (bad magic number)" % source)
|
||||
return None
|
||||
if has_flags and data[4:8] != b"\x00\x00\x00\x00":
|
||||
if data[4:8] != b"\x00\x00\x00\x00":
|
||||
trace("_read_pyc(%s): invalid pyc (unsupported flags)" % source)
|
||||
return None
|
||||
mtime_data = data[8 if has_flags else 4 : 12 if has_flags else 8]
|
||||
mtime_data = data[8:12]
|
||||
if int.from_bytes(mtime_data, "little") != mtime & 0xFFFFFFFF:
|
||||
trace("_read_pyc(%s): out of date" % source)
|
||||
return None
|
||||
size_data = data[12 if has_flags else 8 : 16 if has_flags else 12]
|
||||
size_data = data[12:16]
|
||||
if int.from_bytes(size_data, "little") != size & 0xFFFFFFFF:
|
||||
trace("_read_pyc(%s): invalid pyc (incorrect size)" % source)
|
||||
return None
|
||||
|
|
|
@ -4,7 +4,6 @@ import functools
|
|||
import inspect
|
||||
import os
|
||||
import sys
|
||||
from contextlib import contextmanager
|
||||
from inspect import Parameter
|
||||
from inspect import signature
|
||||
from pathlib import Path
|
||||
|
@ -186,16 +185,6 @@ def getfuncargnames(
|
|||
return arg_names
|
||||
|
||||
|
||||
if sys.version_info < (3, 7):
|
||||
|
||||
@contextmanager
|
||||
def nullcontext():
|
||||
yield
|
||||
|
||||
else:
|
||||
from contextlib import nullcontext as nullcontext # noqa: F401
|
||||
|
||||
|
||||
def get_default_arg_names(function: Callable[..., Any]) -> Tuple[str, ...]:
|
||||
# Note: this code intentionally mirrors the code at the beginning of
|
||||
# getfuncargnames, to get the arguments which were excluded from its result
|
||||
|
|
|
@ -3,8 +3,8 @@ import io
|
|||
import logging
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from contextlib import contextmanager
|
||||
from contextlib import nullcontext
|
||||
from io import StringIO
|
||||
from pathlib import Path
|
||||
from typing import AbstractSet
|
||||
|
@ -22,7 +22,6 @@ from _pytest import nodes
|
|||
from _pytest._io import TerminalWriter
|
||||
from _pytest.capture import CaptureManager
|
||||
from _pytest.compat import final
|
||||
from _pytest.compat import nullcontext
|
||||
from _pytest.config import _strtobool
|
||||
from _pytest.config import Config
|
||||
from _pytest.config import create_terminal_writer
|
||||
|
@ -628,16 +627,7 @@ class LoggingPlugin:
|
|||
|
||||
# https://github.com/python/mypy/issues/11193
|
||||
stream: io.TextIOWrapper = fpath.open(mode="w", encoding="UTF-8") # type: ignore[assignment]
|
||||
if sys.version_info >= (3, 7):
|
||||
old_stream = self.log_file_handler.setStream(stream)
|
||||
else:
|
||||
old_stream = self.log_file_handler.stream
|
||||
self.log_file_handler.acquire()
|
||||
try:
|
||||
self.log_file_handler.flush()
|
||||
self.log_file_handler.stream = stream
|
||||
finally:
|
||||
self.log_file_handler.release()
|
||||
old_stream = self.log_file_handler.setStream(stream)
|
||||
if old_stream:
|
||||
old_stream.close()
|
||||
|
||||
|
|
|
@ -128,7 +128,7 @@ class LsofFdLeakChecker:
|
|||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.DEVNULL,
|
||||
check=True,
|
||||
universal_newlines=True,
|
||||
text=True,
|
||||
).stdout
|
||||
|
||||
def isopen(line: str) -> bool:
|
||||
|
|
|
@ -8,14 +8,6 @@ from _pytest.debugging import _validate_usepdb_cls
|
|||
from _pytest.monkeypatch import MonkeyPatch
|
||||
from _pytest.pytester import Pytester
|
||||
|
||||
try:
|
||||
# Type ignored for Python <= 3.6.
|
||||
breakpoint # type: ignore
|
||||
except NameError:
|
||||
SUPPORTS_BREAKPOINT_BUILTIN = False
|
||||
else:
|
||||
SUPPORTS_BREAKPOINT_BUILTIN = True
|
||||
|
||||
|
||||
_ENVIRON_PYTHONBREAKPOINT = os.environ.get("PYTHONBREAKPOINT", "")
|
||||
|
||||
|
@ -911,14 +903,6 @@ class TestPDB:
|
|||
|
||||
|
||||
class TestDebuggingBreakpoints:
|
||||
def test_supports_breakpoint_module_global(self) -> None:
|
||||
"""Test that supports breakpoint global marks on Python 3.7+."""
|
||||
if sys.version_info >= (3, 7):
|
||||
assert SUPPORTS_BREAKPOINT_BUILTIN is True
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin"
|
||||
)
|
||||
@pytest.mark.parametrize("arg", ["--pdb", ""])
|
||||
def test_sys_breakpointhook_configure_and_unconfigure(
|
||||
self, pytester: Pytester, arg: str
|
||||
|
@ -952,9 +936,6 @@ class TestDebuggingBreakpoints:
|
|||
result = pytester.runpytest_subprocess(*args)
|
||||
result.stdout.fnmatch_lines(["*1 passed in *"])
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin"
|
||||
)
|
||||
def test_pdb_custom_cls(self, pytester: Pytester, custom_debugger_hook) -> None:
|
||||
p1 = pytester.makepyfile(
|
||||
"""
|
||||
|
@ -969,9 +950,6 @@ class TestDebuggingBreakpoints:
|
|||
assert custom_debugger_hook == ["init", "set_trace"]
|
||||
|
||||
@pytest.mark.parametrize("arg", ["--pdb", ""])
|
||||
@pytest.mark.skipif(
|
||||
not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin"
|
||||
)
|
||||
def test_environ_custom_class(
|
||||
self, pytester: Pytester, custom_debugger_hook, arg: str
|
||||
) -> None:
|
||||
|
@ -1002,9 +980,6 @@ class TestDebuggingBreakpoints:
|
|||
result = pytester.runpytest_subprocess(*args)
|
||||
result.stdout.fnmatch_lines(["*1 passed in *"])
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin"
|
||||
)
|
||||
@pytest.mark.skipif(
|
||||
not _ENVIRON_PYTHONBREAKPOINT == "",
|
||||
reason="Requires breakpoint() default value",
|
||||
|
@ -1025,9 +1000,6 @@ class TestDebuggingBreakpoints:
|
|||
assert "reading from stdin while output" not in rest
|
||||
TestPDB.flush(child)
|
||||
|
||||
@pytest.mark.skipif(
|
||||
not SUPPORTS_BREAKPOINT_BUILTIN, reason="Requires breakpoint() builtin"
|
||||
)
|
||||
def test_pdb_not_altered(self, pytester: Pytester) -> None:
|
||||
p1 = pytester.makepyfile(
|
||||
"""
|
||||
|
|
|
@ -295,7 +295,7 @@ def test_argcomplete(pytester: Pytester, monkeypatch: MonkeyPatch) -> None:
|
|||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.DEVNULL,
|
||||
check=True,
|
||||
universal_newlines=True,
|
||||
text=True,
|
||||
).stdout
|
||||
except (OSError, subprocess.CalledProcessError):
|
||||
pytest.skip("bash is not available")
|
||||
|
|
Loading…
Reference in New Issue