summaryrefslogtreecommitdiff
path: root/sphinx/pycode/ast.py
diff options
context:
space:
mode:
Diffstat (limited to 'sphinx/pycode/ast.py')
-rw-r--r--sphinx/pycode/ast.py64
1 files changed, 13 insertions, 51 deletions
diff --git a/sphinx/pycode/ast.py b/sphinx/pycode/ast.py
index c0d6fc463..e61b01d18 100644
--- a/sphinx/pycode/ast.py
+++ b/sphinx/pycode/ast.py
@@ -1,18 +1,8 @@
"""Helpers for AST (Abstract Syntax Tree)."""
-import sys
+import ast
from typing import Dict, List, Optional, Type, overload
-if sys.version_info[:2] >= (3, 8):
- import ast
-else:
- try:
- # use typed_ast module if installed
- from typed_ast import ast3 as ast
- except ImportError:
- import ast # type: ignore
-
-
OPERATORS: Dict[Type[ast.AST], str] = {
ast.Add: "+",
ast.And: "and",
@@ -37,21 +27,13 @@ OPERATORS: Dict[Type[ast.AST], str] = {
def parse(code: str, mode: str = 'exec') -> "ast.AST":
- """Parse the *code* using the built-in ast or typed_ast libraries.
-
- This enables "type_comments" feature if possible.
- """
+ """Parse the *code* using the built-in ast module."""
try:
- # type_comments parameter is available on py38+
- return ast.parse(code, mode=mode, type_comments=True) # type: ignore
+ return ast.parse(code, mode=mode, type_comments=True)
except SyntaxError:
# Some syntax error found. To ignore invalid type comments, retry parsing without
# type_comments parameter (refs: https://github.com/sphinx-doc/sphinx/issues/8652).
return ast.parse(code, mode=mode)
- except TypeError:
- # fallback to ast module.
- # typed_ast is used to parse type_comments if installed.
- return ast.parse(code, mode=mode)
@overload
@@ -102,10 +84,8 @@ class _UnparseVisitor(ast.NodeVisitor):
def visit_arguments(self, node: ast.arguments) -> str:
defaults: List[Optional[ast.expr]] = list(node.defaults)
positionals = len(node.args)
- posonlyargs = 0
- if hasattr(node, "posonlyargs"): # for py38+
- posonlyargs += len(node.posonlyargs) # type:ignore
- positionals += posonlyargs
+ posonlyargs = len(node.posonlyargs)
+ positionals += posonlyargs
for _ in range(len(defaults), positionals):
defaults.insert(0, None)
@@ -114,12 +94,11 @@ class _UnparseVisitor(ast.NodeVisitor):
kw_defaults.insert(0, None)
args: List[str] = []
- if hasattr(node, "posonlyargs"): # for py38+
- for i, arg in enumerate(node.posonlyargs): # type: ignore
- args.append(self._visit_arg_with_default(arg, defaults[i]))
+ for i, arg in enumerate(node.posonlyargs):
+ args.append(self._visit_arg_with_default(arg, defaults[i]))
- if node.posonlyargs: # type: ignore
- args.append('/')
+ if node.posonlyargs:
+ args.append('/')
for i, arg in enumerate(node.args):
args.append(self._visit_arg_with_default(arg, defaults[i + posonlyargs]))
@@ -155,19 +134,19 @@ class _UnparseVisitor(ast.NodeVisitor):
["%s=%s" % (k.arg, self.visit(k.value)) for k in node.keywords])
return "%s(%s)" % (self.visit(node.func), ", ".join(args))
- def visit_Constant(self, node: ast.Constant) -> str: # type: ignore
+ def visit_Constant(self, node: ast.Constant) -> str:
if node.value is Ellipsis:
return "..."
elif isinstance(node.value, (int, float, complex)):
- if self.code and sys.version_info[:2] >= (3, 8):
- return ast.get_source_segment(self.code, node) # type: ignore
+ if self.code:
+ return ast.get_source_segment(self.code, node) or repr(node.value)
else:
return repr(node.value)
else:
return repr(node.value)
def visit_Dict(self, node: ast.Dict) -> str:
- keys = (self.visit(k) for k in node.keys)
+ keys = (self.visit(k) for k in node.keys if k is not None)
values = (self.visit(v) for v in node.values)
items = (k + ": " + v for k, v in zip(keys, values))
return "{" + ", ".join(items) + "}"
@@ -219,22 +198,5 @@ class _UnparseVisitor(ast.NodeVisitor):
else:
return "(" + ", ".join(self.visit(e) for e in node.elts) + ")"
- if sys.version_info[:2] <= (3, 7):
- # these ast nodes were deprecated in python 3.8
- def visit_Bytes(self, node: ast.Bytes) -> str:
- return repr(node.s)
-
- def visit_Ellipsis(self, node: ast.Ellipsis) -> str:
- return "..."
-
- def visit_NameConstant(self, node: ast.NameConstant) -> str:
- return repr(node.value)
-
- def visit_Num(self, node: ast.Num) -> str:
- return repr(node.n)
-
- def visit_Str(self, node: ast.Str) -> str:
- return repr(node.s)
-
def generic_visit(self, node):
raise NotImplementedError('Unable to parse %s object' % type(node).__name__)