diff options
Diffstat (limited to 'sphinx/pycode')
-rw-r--r-- | sphinx/pycode/__init__.py | 27 | ||||
-rw-r--r-- | sphinx/pycode/ast.py | 35 | ||||
-rw-r--r-- | sphinx/pycode/parser.py | 17 |
3 files changed, 35 insertions, 44 deletions
diff --git a/sphinx/pycode/__init__.py b/sphinx/pycode/__init__.py index ab0dfdbf8..aaf748559 100644 --- a/sphinx/pycode/__init__.py +++ b/sphinx/pycode/__init__.py @@ -19,7 +19,7 @@ from os import path from typing import IO, Any, Dict, List, Optional, Tuple from zipfile import ZipFile -from sphinx.deprecation import RemovedInSphinx40Warning, RemovedInSphinx50Warning +from sphinx.deprecation import RemovedInSphinx50Warning from sphinx.errors import PycodeError from sphinx.pycode.parser import Parser @@ -79,7 +79,7 @@ class ModuleAnalyzer: @classmethod def for_string(cls, string: str, modname: str, srcname: str = '<string>' ) -> "ModuleAnalyzer": - return cls(StringIO(string), modname, srcname, decoded=True) + return cls(StringIO(string), modname, srcname) @classmethod def for_file(cls, filename: str, modname: str) -> "ModuleAnalyzer": @@ -87,7 +87,7 @@ class ModuleAnalyzer: return cls.cache['file', filename] try: with tokenize.open(filename) as f: - obj = cls(f, modname, filename, decoded=True) + obj = cls(f, modname, filename) cls.cache['file', filename] = obj except Exception as err: if '.egg' + path.sep in filename: @@ -127,21 +127,12 @@ class ModuleAnalyzer: cls.cache['module', modname] = obj return obj - def __init__(self, source: IO, modname: str, srcname: str, decoded: bool = False) -> None: + def __init__(self, source: IO, modname: str, srcname: str) -> None: self.modname = modname # name of the module self.srcname = srcname # name of the source file # cache the source code as well - pos = source.tell() - if not decoded: - warnings.warn('decode option for ModuleAnalyzer is deprecated.', - RemovedInSphinx40Warning, stacklevel=2) - self._encoding, _ = tokenize.detect_encoding(source.readline) - source.seek(pos) - self.code = source.read().decode(self._encoding) - else: - self._encoding = None - self.code = source.read() + self.code = source.read() # will be filled by analyze() self.annotations = None # type: Dict[Tuple[str, str], str] @@ -164,7 +155,7 @@ class ModuleAnalyzer: return None try: - parser = Parser(self.code, self._encoding) + parser = Parser(self.code) parser.parse() self.attr_docs = OrderedDict() @@ -192,9 +183,3 @@ class ModuleAnalyzer: """Find class, function and method definitions and their location.""" self.analyze() return self.tags - - @property - def encoding(self) -> str: - warnings.warn('ModuleAnalyzer.encoding is deprecated.', - RemovedInSphinx40Warning, stacklevel=2) - return self._encoding diff --git a/sphinx/pycode/ast.py b/sphinx/pycode/ast.py index 65534f958..b9fbfc83d 100644 --- a/sphinx/pycode/ast.py +++ b/sphinx/pycode/ast.py @@ -9,7 +9,7 @@ """ import sys -from typing import Dict, List, Optional, Type +from typing import Dict, List, Optional, Type, overload if sys.version_info > (3, 8): import ast @@ -62,6 +62,16 @@ def parse(code: str, mode: str = 'exec') -> "ast.AST": return ast.parse(code, mode=mode) +@overload +def unparse(node: None, code: str = '') -> None: + ... + + +@overload +def unparse(node: ast.AST, code: str = '') -> str: + ... + + def unparse(node: Optional[ast.AST], code: str = '') -> Optional[str]: """Unparse an AST to string.""" if node is None: @@ -150,6 +160,17 @@ 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 + if node.value is Ellipsis: + return "..." + elif isinstance(node.value, (int, float, complex)): + if self.code and sys.version_info > (3, 8): + return ast.get_source_segment(self.code, node) # type: ignore + 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) values = (self.visit(v) for v in node.values) @@ -197,18 +218,6 @@ class _UnparseVisitor(ast.NodeVisitor): else: return "()" - if sys.version_info >= (3, 6): - 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 > (3, 8): - return ast.get_source_segment(self.code, node) - else: - return repr(node.value) - else: - return repr(node.value) - if sys.version_info < (3, 8): # these ast nodes were deprecated in python 3.8 def visit_Bytes(self, node: ast.Bytes) -> str: diff --git a/sphinx/pycode/parser.py b/sphinx/pycode/parser.py index dca59acd4..d157c7c1c 100644 --- a/sphinx/pycode/parser.py +++ b/sphinx/pycode/parser.py @@ -10,7 +10,6 @@ import inspect import itertools import re -import sys import tokenize from collections import OrderedDict from inspect import Signature @@ -26,12 +25,6 @@ indent_re = re.compile('^\\s*$') emptyline_re = re.compile('^\\s*(#.*)?$') -if sys.version_info >= (3, 6): - ASSIGN_NODES = (ast.Assign, ast.AnnAssign) -else: - ASSIGN_NODES = (ast.Assign) - - def filter_whitespace(code: str) -> str: return code.replace('\f', ' ') # replace FF (form feed) with whitespace @@ -94,7 +87,10 @@ def dedent_docstring(s: str) -> str: dummy.__doc__ = s docstring = inspect.getdoc(dummy) - return docstring.lstrip("\r\n").rstrip("\r\n") + if docstring: + return docstring.lstrip("\r\n").rstrip("\r\n") + else: + return "" class Token: @@ -398,13 +394,14 @@ class VariableCommentPicker(ast.NodeVisitor): for varname in varnames: self.add_entry(varname) - def visit_AnnAssign(self, node: ast.AST) -> None: # Note: ast.AnnAssign not found in py35 + def visit_AnnAssign(self, node: ast.AnnAssign) -> None: """Handles AnnAssign node and pick up a variable comment.""" self.visit_Assign(node) # type: ignore def visit_Expr(self, node: ast.Expr) -> None: """Handles Expr node and pick up a comment if string.""" - if (isinstance(self.previous, ASSIGN_NODES) and isinstance(node.value, ast.Str)): + if (isinstance(self.previous, (ast.Assign, ast.AnnAssign)) and + isinstance(node.value, ast.Str)): try: targets = get_assign_targets(self.previous) varnames = get_lvar_names(targets[0], self.get_self()) |