Skip to content

Commit 7e68154

Browse files
authoredJun 16, 2022
Drop python 3.6 support (#10468)
1 parent 0d2a989 commit 7e68154

24 files changed

+203
-416
lines changed
 

‎.github/workflows/builddoc.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
- name: Set up Python
1212
uses: actions/setup-python@v1
1313
with:
14-
python-version: 3.6
14+
python-version: 3.8
1515
- name: Install dependencies
1616
run: |
1717
sudo apt update

‎.github/workflows/lint.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
- name: Set up Python
1616
uses: actions/setup-python@v1
1717
with:
18-
python-version: 3.6
18+
python-version: 3.8
1919
- name: Install dependencies
2020
run: pip install -U tox
2121
- name: Run Tox

‎.github/workflows/main.yml

-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ jobs:
1010
fail-fast: false
1111
matrix:
1212
include:
13-
- python: "3.6"
14-
docutils: du14
1513
- python: "3.7"
1614
docutils: du15
1715
- python: "3.8"

‎CHANGES

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ Release 6.0.0 (in development)
44
Dependencies
55
------------
66

7+
* Drop python 3.6 support
8+
79
Incompatible changes
810
--------------------
911

‎doc/internals/contributing.rst

+4-4
Original file line numberDiff line numberDiff line change
@@ -172,19 +172,19 @@ of targets and allows testing against multiple different Python environments:
172172

173173
tox -av
174174

175-
* To run unit tests for a specific Python version, such as Python 3.6::
175+
* To run unit tests for a specific Python version, such as Python 3.10::
176176

177-
tox -e py36
177+
tox -e py310
178178

179179
* To run unit tests for a specific Python version and turn on deprecation
180180
warnings on so they're shown in the test output::
181181

182-
PYTHONWARNINGS=all tox -e py36
182+
PYTHONWARNINGS=all tox -e py310
183183

184184
* Arguments to ``pytest`` can be passed via ``tox``, e.g. in order to run a
185185
particular test::
186186

187-
tox -e py36 tests/test_module.py::test_new_feature
187+
tox -e py310 tests/test_module.py::test_new_feature
188188

189189
You can also test by installing dependencies in your local environment::
190190

‎doc/internals/release-process.rst

+3-3
Original file line numberDiff line numberDiff line change
@@ -109,16 +109,16 @@ Ubuntu <https://ubuntu.com/about/release-cycle>`_ that has standard support.
109109
For example, as of July 2021, Ubuntu 16.04 has just entered extended
110110
security maintenance (therefore, it doesn't count as standard support) and
111111
the oldest LTS release to consider is Ubuntu 18.04 LTS, supported until
112-
April 2023 and shipping Python 3.6.
112+
April 2023 and shipping Python 3.8.
113113

114114
This is a summary table with the current policy:
115115

116116
========== ========= ======
117117
Date Ubuntu Python
118118
========== ========= ======
119-
April 2021 18.04 LTS 3.6+
120-
---------- --------- ------
121119
April 2023 20.04 LTS 3.8+
120+
---------- --------- ------
121+
April 2025 22.04 LTS 3.10+
122122
========== ========= ======
123123

124124
Release procedures

‎doc/usage/installation.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Installing Sphinx
1212
Overview
1313
--------
1414

15-
Sphinx is written in `Python`__ and supports Python 3.6+. It builds upon the
15+
Sphinx is written in `Python`__ and supports Python 3.7+. It builds upon the
1616
shoulders of many third-party libraries such as `Docutils`__ and `Jinja`__,
1717
which are installed when Sphinx is installed.
1818

‎setup.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
with open('README.rst', encoding='utf-8') as f:
88
long_desc = f.read()
99

10-
if sys.version_info < (3, 6):
11-
print('ERROR: Sphinx requires at least Python 3.6 to run.')
10+
if sys.version_info < (3, 7):
11+
print('ERROR: Sphinx requires at least Python 3.7 to run.')
1212
sys.exit(1)
1313

1414
install_requires = [
@@ -85,7 +85,6 @@
8585
'Programming Language :: Python',
8686
'Programming Language :: Python :: 3',
8787
'Programming Language :: Python :: 3 :: Only',
88-
'Programming Language :: Python :: 3.6',
8988
'Programming Language :: Python :: 3.7',
9089
'Programming Language :: Python :: 3.8',
9190
'Programming Language :: Python :: 3.9',
@@ -127,7 +126,7 @@
127126
'build_sphinx = sphinx.setup_command:BuildDoc',
128127
],
129128
},
130-
python_requires=">=3.6",
129+
python_requires=">=3.7",
131130
install_requires=install_requires,
132131
extras_require=extras_require,
133132
)

‎sphinx/ext/extlinks.py

+1-7
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
"""
1919

2020
import re
21-
import sys
2221
from typing import Any, Dict, List, Tuple
2322

2423
from docutils import nodes, utils
@@ -64,12 +63,7 @@ def check_uri(self, refnode: nodes.reference) -> None:
6463
title = refnode.astext()
6564

6665
for alias, (base_uri, _caption) in self.app.config.extlinks.items():
67-
if sys.version_info < (3, 7):
68-
# Replace a leading backslash because re.escape() inserts a backslash before %
69-
# on python 3.6
70-
uri_pattern = re.compile(re.escape(base_uri).replace('\\%s', '(?P<value>.+)'))
71-
else:
72-
uri_pattern = re.compile(re.escape(base_uri).replace('%s', '(?P<value>.+)'))
66+
uri_pattern = re.compile(re.escape(base_uri).replace('%s', '(?P<value>.+)'))
7367

7468
match = uri_pattern.match(uri)
7569
if match and match.groupdict().get('value'):

‎sphinx/util/inspect.py

+9-19
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from types import MethodType, ModuleType
1616
from typing import Any, Callable, Dict, Mapping, Optional, Sequence, Tuple, Type, cast
1717

18-
from sphinx.pycode.ast import ast # for py36-37
18+
from sphinx.pycode.ast import ast # for py37
1919
from sphinx.pycode.ast import unparse as ast_unparse
2020
from sphinx.util import logging
2121
from sphinx.util.typing import ForwardRef
@@ -298,7 +298,7 @@ def is_singledispatch_method(obj: Any) -> bool:
298298
try:
299299
from functools import singledispatchmethod # type: ignore
300300
return isinstance(obj, singledispatchmethod)
301-
except ImportError: # py36-37
301+
except ImportError: # py37
302302
return False
303303

304304

@@ -569,25 +569,15 @@ def signature(subject: Callable, bound_method: bool = False, type_aliases: Dict
569569
"""
570570

571571
try:
572-
try:
573-
if _should_unwrap(subject):
574-
signature = inspect.signature(subject)
575-
else:
576-
signature = inspect.signature(subject, follow_wrapped=True)
577-
except ValueError:
578-
# follow built-in wrappers up (ex. functools.lru_cache)
572+
if _should_unwrap(subject):
579573
signature = inspect.signature(subject)
580-
parameters = list(signature.parameters.values())
581-
return_annotation = signature.return_annotation
582-
except IndexError:
583-
# Until python 3.6.4, cpython has been crashed on inspection for
584-
# partialmethods not having any arguments.
585-
# https://bugs.python.org/issue33009
586-
if hasattr(subject, '_partialmethod'):
587-
parameters = []
588-
return_annotation = Parameter.empty
589574
else:
590-
raise
575+
signature = inspect.signature(subject, follow_wrapped=True)
576+
except ValueError:
577+
# follow built-in wrappers up (ex. functools.lru_cache)
578+
signature = inspect.signature(subject)
579+
parameters = list(signature.parameters.values())
580+
return_annotation = signature.return_annotation
591581

592582
try:
593583
# Resolve annotations using ``get_type_hints()`` and type_aliases.

‎sphinx/util/typing.py

+9-9
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@
22

33
import sys
44
import typing
5+
import warnings
56
from struct import Struct
67
from types import TracebackType
78
from typing import Any, Callable, Dict, Generator, List, Optional, Tuple, Type, TypeVar, Union
89

910
from docutils import nodes
1011
from docutils.parsers.rst.states import Inliner
1112

12-
from sphinx.deprecation import RemovedInSphinx60Warning, deprecated_alias
13+
from sphinx.deprecation import (RemovedInSphinx60Warning, RemovedInSphinx70Warning,
14+
deprecated_alias)
1315

1416
if sys.version_info > (3, 7):
1517
from typing import ForwardRef
@@ -158,10 +160,7 @@ def restify(cls: Optional[Type], mode: str = 'fully-qualified-except-typing') ->
158160
else:
159161
return ':py:class:`%s`' % cls.__name__
160162
else:
161-
if sys.version_info >= (3, 7): # py37+
162-
return _restify_py37(cls, mode)
163-
else:
164-
return _restify_py36(cls, mode)
163+
return _restify_py37(cls, mode)
165164
except (AttributeError, TypeError):
166165
return inspect.object_description(cls)
167166

@@ -234,6 +233,8 @@ def _restify_py37(cls: Optional[Type], mode: str = 'fully-qualified-except-typin
234233

235234

236235
def _restify_py36(cls: Optional[Type], mode: str = 'fully-qualified-except-typing') -> str:
236+
warnings.warn('_restify_py36() is deprecated', RemovedInSphinx70Warning)
237+
237238
if mode == 'smart':
238239
modprefix = '~'
239240
else:
@@ -390,10 +391,7 @@ def stringify(annotation: Any, mode: str = 'fully-qualified-except-typing') -> s
390391
elif annotation is Ellipsis:
391392
return '...'
392393

393-
if sys.version_info >= (3, 7): # py37+
394-
return _stringify_py37(annotation, mode)
395-
else:
396-
return _stringify_py36(annotation, mode)
394+
return _stringify_py37(annotation, mode)
397395

398396

399397
def _stringify_py37(annotation: Any, mode: str = 'fully-qualified-except-typing') -> str:
@@ -472,6 +470,8 @@ def _stringify_py37(annotation: Any, mode: str = 'fully-qualified-except-typing'
472470

473471
def _stringify_py36(annotation: Any, mode: str = 'fully-qualified-except-typing') -> str:
474472
"""stringify() for py36."""
473+
warnings.warn('_stringify_py36() is deprecated', RemovedInSphinx70Warning)
474+
475475
module = getattr(annotation, '__module__', None)
476476
modprefix = ''
477477
if module == 'typing' and getattr(annotation, '__forward_arg__', None):

‎tests/test_build.py

+17-23
Original file line numberDiff line numberDiff line change
@@ -22,29 +22,23 @@ def nonascii_srcdir(request, rootdir, sphinx_test_tempdir):
2222
# If supported, build in a non-ASCII source dir
2323
test_name = '\u65e5\u672c\u8a9e'
2424
basedir = sphinx_test_tempdir / request.node.originalname
25-
try:
26-
srcdir = basedir / test_name
27-
if not srcdir.exists():
28-
(rootdir / 'test-root').copytree(srcdir)
29-
except UnicodeEncodeError:
30-
# Now Python 3.7+ follows PEP-540 and uses utf-8 encoding for filesystem by default.
31-
# So this error handling will be no longer used (after dropping python 3.6 support).
32-
srcdir = basedir / 'all'
33-
if not srcdir.exists():
34-
(rootdir / 'test-root').copytree(srcdir)
35-
else:
36-
# add a doc with a non-ASCII file name to the source dir
37-
(srcdir / (test_name + '.txt')).write_text(dedent("""
38-
nonascii file name page
39-
=======================
40-
"""), encoding='utf8')
41-
42-
root_doc = srcdir / 'index.txt'
43-
root_doc.write_text(root_doc.read_text(encoding='utf8') + dedent("""
44-
.. toctree::
45-
46-
%(test_name)s/%(test_name)s
47-
""" % {'test_name': test_name}), encoding='utf8')
25+
srcdir = basedir / test_name
26+
if not srcdir.exists():
27+
(rootdir / 'test-root').copytree(srcdir)
28+
29+
# add a doc with a non-ASCII file name to the source dir
30+
(srcdir / (test_name + '.txt')).write_text(dedent("""
31+
nonascii file name page
32+
=======================
33+
"""), encoding='utf8')
34+
35+
root_doc = srcdir / 'index.txt'
36+
root_doc.write_text(root_doc.read_text(encoding='utf8') + dedent("""
37+
.. toctree::
38+
39+
%(test_name)s/%(test_name)s
40+
""" % {'test_name': test_name}), encoding='utf8')
41+
4842
return srcdir
4943

5044

‎tests/test_errors.py

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import sys
2-
31
from sphinx.errors import ExtensionError
42

53

@@ -10,8 +8,4 @@ def test_extension_error_repr():
108

119
def test_extension_error_with_orig_exc_repr():
1210
exc = ExtensionError("foo", Exception("bar"))
13-
if sys.version_info < (3, 7):
14-
expected = "ExtensionError('foo', Exception('bar',))"
15-
else:
16-
expected = "ExtensionError('foo', Exception('bar'))"
17-
assert repr(exc) == expected
11+
assert repr(exc) == "ExtensionError('foo', Exception('bar'))"

0 commit comments

Comments
 (0)
Please sign in to comment.