Skip to content

Commit

Permalink
Merge pull request #9442 from hramezani/drop_python_36
Browse files Browse the repository at this point in the history
Drop Python3.6 in CI, setup.cfg, and readme.
  • Loading branch information
bluetech committed Dec 30, 2021
2 parents 79dbd19 + 0b7c3d1 commit b9663fe
Show file tree
Hide file tree
Showing 16 changed files with 21 additions and 86 deletions.
10 changes: 0 additions & 10 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1 change: 1 addition & 0 deletions changelog/9437.breaking.rst
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 1 addition & 1 deletion doc/en/getting-started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
4 changes: 2 additions & 2 deletions doc/en/how-to/skipping.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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():
...
Expand Down
4 changes: 2 additions & 2 deletions doc/en/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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`

Expand Down Expand Up @@ -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

Expand Down
2 changes: 0 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 1 addition & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 =
Expand Down
17 changes: 7 additions & 10 deletions src/_pytest/assertion/rewrite.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
11 changes: 0 additions & 11 deletions src/_pytest/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import inspect
import os
import sys
from contextlib import contextmanager
from inspect import Parameter
from inspect import signature
from pathlib import Path
Expand Down Expand Up @@ -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
Expand Down
14 changes: 2 additions & 12 deletions src/_pytest/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
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
Expand All @@ -22,7 +22,6 @@
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
Expand Down Expand Up @@ -628,16 +627,7 @@ def set_log_path(self, fname: str) -> None:

# 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()

Expand Down
2 changes: 1 addition & 1 deletion src/_pytest/pytester.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def get_open_files(self) -> List[Tuple[str, str]]:
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
check=True,
universal_newlines=True,
text=True,
).stdout

def isopen(line: str) -> bool:
Expand Down
28 changes: 0 additions & 28 deletions testing/test_debugging.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,6 @@
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", "")

Expand Down Expand Up @@ -911,14 +903,6 @@ def test_foo():


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
Expand Down Expand Up @@ -952,9 +936,6 @@ def test_nothing(): pass
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(
"""
Expand All @@ -969,9 +950,6 @@ def test_nothing():
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:
Expand Down Expand Up @@ -1002,9 +980,6 @@ def test_nothing(): pass
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",
Expand All @@ -1025,9 +1000,6 @@ def test_1():
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(
"""
Expand Down
2 changes: 1 addition & 1 deletion testing/test_parseopt.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
1 change: 0 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ minversion = 3.20.0
distshare = {homedir}/.tox/distshare
envlist =
linting
py36
py37
py38
py39
Expand Down

0 comments on commit b9663fe

Please sign in to comment.