Skip to content

Commit 4660b62

Browse files
committedSep 27, 2022
Drop Python 3.7
1 parent 7649eb1 commit 4660b62

27 files changed

+167
-291
lines changed
 

‎.github/workflows/main.yml

-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ jobs:
1313
fail-fast: false
1414
matrix:
1515
include:
16-
- python: "3.7"
17-
docutils: du15
1816
- python: "3.8"
1917
docutils: du16
2018
- python: "3.9"

‎CHANGES

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Dependencies
55
------------
66

77
* #10468: Drop Python 3.6 support
8+
* #10470: Drop Python 3.7 support. Patch by Adam Turner
89

910
Incompatible changes
1011
--------------------

‎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.7+. It builds upon the
15+
Sphinx is written in `Python`__ and supports Python 3.8+. 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

‎pyproject.toml

+2-5
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ urls.Download = "https://pypi.org/project/Sphinx/"
1313
urls.Homepage = "https://www.sphinx-doc.org/"
1414
urls."Issue tracker" = "https://github.com/sphinx-doc/sphinx/issues"
1515
license.text = "BSD"
16-
requires-python = ">=3.7"
16+
requires-python = ">=3.8"
1717

1818
# Classifiers list: https://pypi.org/classifiers/
1919
classifiers = [
@@ -30,7 +30,6 @@ classifiers = [
3030
"Programming Language :: Python",
3131
"Programming Language :: Python :: 3",
3232
"Programming Language :: Python :: 3 :: Only",
33-
"Programming Language :: Python :: 3.7",
3433
"Programming Language :: Python :: 3.8",
3534
"Programming Language :: Python :: 3.9",
3635
"Programming Language :: Python :: 3.10",
@@ -89,13 +88,11 @@ lint = [
8988
"mypy>=0.981",
9089
"sphinx-lint",
9190
"docutils-stubs",
92-
"types-typed-ast",
9391
"types-requests",
9492
]
9593
test = [
9694
"pytest>=4.6",
9795
"html5lib",
98-
"typed_ast; python_version < '3.8'",
9996
"cython",
10097
]
10198

@@ -144,7 +141,7 @@ disallow_incomplete_defs = true
144141
follow_imports = "skip"
145142
ignore_missing_imports = true
146143
no_implicit_optional = true
147-
python_version = "3.7"
144+
python_version = "3.8"
148145
show_column_numbers = true
149146
show_error_codes = true
150147
show_error_context = true

‎sphinx/directives/other.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def run(self) -> List[Node]:
7777
return ret
7878

7979
def parse_content(self, toctree: addnodes.toctree) -> List[Node]:
80-
generated_docnames = frozenset(self.env.domains['std'].initial_data['labels'].keys())
80+
generated_docnames = frozenset(self.env.domains['std']._virtual_doc_names)
8181
suffixes = self.config.source_suffix
8282

8383
# glob target documents

‎sphinx/domains/python.py

+2-15
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
"""The Python domain."""
22

3+
import ast
34
import builtins
45
import inspect
56
import re
6-
import sys
77
import typing
88
from inspect import Parameter
99
from typing import Any, Dict, Iterable, Iterator, List, NamedTuple, Optional, Tuple, Type, cast
@@ -21,7 +21,6 @@
2121
from sphinx.domains import Domain, Index, IndexEntry, ObjType
2222
from sphinx.environment import BuildEnvironment
2323
from sphinx.locale import _, __
24-
from sphinx.pycode.ast import ast
2524
from sphinx.pycode.ast import parse as ast_parse
2625
from sphinx.roles import XRefRole
2726
from sphinx.util import logging
@@ -138,7 +137,7 @@ def unparse(node: ast.AST) -> List[Node]:
138137
return [addnodes.desc_sig_space(),
139138
addnodes.desc_sig_punctuation('', '|'),
140139
addnodes.desc_sig_space()]
141-
elif isinstance(node, ast.Constant): # type: ignore
140+
elif isinstance(node, ast.Constant):
142141
if node.value is Ellipsis:
143142
return [addnodes.desc_sig_punctuation('', "...")]
144143
elif isinstance(node.value, bool):
@@ -204,18 +203,6 @@ def unparse(node: ast.AST) -> List[Node]:
204203

205204
return result
206205
else:
207-
if sys.version_info[:2] <= (3, 7):
208-
if isinstance(node, ast.Bytes):
209-
return [addnodes.desc_sig_literal_string('', repr(node.s))]
210-
elif isinstance(node, ast.Ellipsis):
211-
return [addnodes.desc_sig_punctuation('', "...")]
212-
elif isinstance(node, ast.NameConstant):
213-
return [nodes.Text(node.value)]
214-
elif isinstance(node, ast.Num):
215-
return [addnodes.desc_sig_literal_string('', repr(node.n))]
216-
elif isinstance(node, ast.Str):
217-
return [addnodes.desc_sig_literal_string('', repr(node.s))]
218-
219206
raise SyntaxError # unsupported syntax
220207

221208
try:

‎sphinx/domains/std.py

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
"""The standard domain."""
22

33
import re
4-
import sys
54
from copy import copy
6-
from typing import (TYPE_CHECKING, Any, Callable, Dict, Iterable, Iterator, List, Optional,
7-
Tuple, Type, Union, cast)
5+
from typing import (TYPE_CHECKING, Any, Callable, Dict, Final, Iterable, Iterator, List,
6+
Optional, Tuple, Type, Union, cast)
87

98
from docutils import nodes
109
from docutils.nodes import Element, Node, system_message
@@ -29,11 +28,6 @@
2928

3029
logger = logging.getLogger(__name__)
3130

32-
if sys.version_info[:2] >= (3, 8):
33-
from typing import Final
34-
else:
35-
Final = Any
36-
3731
# RE for option descriptions
3832
option_desc_re = re.compile(r'((?:/|--|-|\+)?[^\s=]+)(=?\s*.*)')
3933
# RE for grammar tokens
@@ -589,7 +583,7 @@ class StandardDomain(Domain):
589583
'doc': XRefRole(warn_dangling=True, innernodeclass=nodes.inline),
590584
}
591585

592-
initial_data: Final = {
586+
initial_data: Final = { # type: ignore[misc]
593587
'progoptions': {}, # (program, name) -> docname, labelid
594588
'objects': {}, # (type, name) -> docname, labelid
595589
'labels': { # labelname -> docname, labelid, sectionname
@@ -604,6 +598,12 @@ class StandardDomain(Domain):
604598
},
605599
}
606600

601+
_virtual_doc_names: Dict[str, Tuple[str, str]] = { # labelname -> docname, sectionname
602+
'genindex': ('genindex', _('Index')),
603+
'modindex': ('py-modindex', _('Module Index')),
604+
'search': ('search', _('Search Page')),
605+
}
606+
607607
dangling_warnings = {
608608
'term': 'term not in glossary: %(target)r',
609609
'numref': 'undefined label: %(target)r',

‎sphinx/environment/adapters/toctree.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def resolve(self, docname: str, builder: "Builder", toctree: addnodes.toctree,
5454
"""
5555
if toctree.get('hidden', False) and not includehidden:
5656
return None
57-
generated_docnames: Dict[str, Tuple[str, str, str]] = self.env.domains['std'].initial_data['labels'].copy() # NoQA: E501
57+
generated_docnames: Dict[str, Tuple[str, str]] = self.env.domains['std']._virtual_doc_names.copy() # NoQA: E501
5858

5959
# For reading the following two helper function, it is useful to keep
6060
# in mind the node structure of a toctree (using HTML-like node names
@@ -141,7 +141,7 @@ def _entries_from_toctree(toctreenode: addnodes.toctree, parents: List[str],
141141
# don't show subitems
142142
toc = nodes.bullet_list('', item)
143143
elif ref in generated_docnames:
144-
docname, _, sectionname = generated_docnames[ref]
144+
docname, sectionname = generated_docnames[ref]
145145
if not title:
146146
title = sectionname
147147
reference = nodes.reference('', title, internal=True,

‎sphinx/environment/collectors/toctree.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ def _walk_toctree(toctreenode: addnodes.toctree, depth: int) -> None:
236236

237237
def assign_figure_numbers(self, env: BuildEnvironment) -> List[str]:
238238
"""Assign a figure number to each figure under a numbered toctree."""
239-
generated_docnames = frozenset(env.domains['std'].initial_data['labels'].keys())
239+
generated_docnames = frozenset(env.domains['std']._virtual_doc_names)
240240

241241
rewrite_needed = []
242242

‎sphinx/ext/autodoc/preserve_defaults.py

+3-7
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66

77
import ast
88
import inspect
9-
import sys
10-
from inspect import Parameter
119
from typing import Any, Dict, List, Optional
1210

1311
from sphinx.application import Sphinx
@@ -48,8 +46,6 @@ def get_function_def(obj: Any) -> Optional[ast.FunctionDef]:
4846

4947
def get_default_value(lines: List[str], position: ast.AST) -> Optional[str]:
5048
try:
51-
if sys.version_info[:2] <= (3, 7): # only for py38+
52-
return None
5349
if position.lineno == position.end_lineno:
5450
line = lines[position.lineno - 1]
5551
return line[position.col_offset:position.end_col_offset]
@@ -89,18 +85,18 @@ def update_defvalue(app: Sphinx, obj: Any, bound_method: bool) -> None:
8985
default = defaults.pop(0)
9086
value = get_default_value(lines, default)
9187
if value is None:
92-
value = ast_unparse(default) # type: ignore
88+
value = ast_unparse(default)
9389
parameters[i] = param.replace(default=DefaultValue(value))
9490
else:
9591
default = kw_defaults.pop(0)
9692
value = get_default_value(lines, default)
9793
if value is None:
98-
value = ast_unparse(default) # type: ignore
94+
value = ast_unparse(default)
9995
parameters[i] = param.replace(default=DefaultValue(value))
10096

10197
if bound_method and inspect.ismethod(obj):
10298
# classmethods
103-
cls = inspect.Parameter('cls', Parameter.POSITIONAL_OR_KEYWORD)
99+
cls = inspect.Parameter('cls', inspect.Parameter.POSITIONAL_OR_KEYWORD)
104100
parameters.insert(0, cls)
105101

106102
sig = sig.replace(parameters=parameters)

‎sphinx/ext/autodoc/type_comment.py

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
"""Update annotations info of living objects using type_comments."""
22

3+
import ast
34
from inspect import Parameter, Signature, getsource
45
from typing import Any, Dict, List, cast
56

67
import sphinx
78
from sphinx.application import Sphinx
89
from sphinx.locale import __
9-
from sphinx.pycode.ast import ast
1010
from sphinx.pycode.ast import parse as ast_parse
1111
from sphinx.pycode.ast import unparse as ast_unparse
1212
from sphinx.util import inspect, logging
@@ -34,10 +34,9 @@ def signature_from_ast(node: ast.FunctionDef, bound_method: bool,
3434
:param bound_method: Specify *node* is a bound method or not
3535
"""
3636
params = []
37-
if hasattr(node.args, "posonlyargs"): # for py38+
38-
for arg in node.args.posonlyargs: # type: ignore
39-
param = Parameter(arg.arg, Parameter.POSITIONAL_ONLY, annotation=arg.type_comment)
40-
params.append(param)
37+
for arg in node.args.posonlyargs:
38+
param = Parameter(arg.arg, Parameter.POSITIONAL_ONLY, annotation=arg.type_comment)
39+
params.append(param)
4140

4241
for arg in node.args.args:
4342
param = Parameter(arg.arg, Parameter.POSITIONAL_OR_KEYWORD,
@@ -80,7 +79,7 @@ def get_type_comment(obj: Any, bound_method: bool = False) -> Signature:
8079
"""Get type_comment'ed FunctionDef object from living object.
8180
8281
This tries to parse original code for living object and returns
83-
Signature for given *obj*. It requires py38+ or typed_ast module.
82+
Signature for given *obj*.
8483
"""
8584
try:
8685
source = getsource(obj)

0 commit comments

Comments
 (0)
Please sign in to comment.