def get_type_comment(obj: Any) -> ast.FunctionDef: """Get type_comment'ed FunctionDef object from living object. This tries to parse original code for living object and returns AST node for given *obj*. It requires py38+ or typed_ast module. """ try: source = getsource(obj) if source.startswith((' ', r'\t')): # subject is placed inside class or block. To read its docstring, # this adds if-block before the declaration. module = ast_parse('if True:\n' + source) subject = cast(ast.FunctionDef, module.body[0].body[0]) # type: ignore else: module = ast_parse(source) subject = cast(ast.FunctionDef, module.body[0]) # type: ignore if getattr(subject, "type_comment", None): return ast_parse(subject.type_comment, mode='func_type') # type: ignore else: return None except (OSError, TypeError): # failed to load source code return None except SyntaxError: # failed to parse type_comments return None
def get_function_def(obj: Any) -> ast.FunctionDef: """Get FunctionDef object from living object. This tries to parse original code for living object and returns AST node for given *obj*. """ try: source = inspect.getsource(obj) if source.startswith((' ', r'\t')): # subject is placed inside class or block. To read its docstring, # this adds if-block before the declaration. module = ast_parse('if True:\n' + source) return module.body[0].body[0] # type: ignore else: module = ast_parse(source) return module.body[0] # type: ignore except (OSError, TypeError): # failed to load source code return None
def _parse_annotation(annotation: str, env: BuildEnvironment = None) -> List[Node]: """Parse type annotation.""" def unparse(node: ast.AST) -> List[Node]: if isinstance(node, ast.Attribute): return [nodes.Text("%s.%s" % (unparse(node.value)[0], node.attr))] elif isinstance(node, ast.Expr): return unparse(node.value) elif isinstance(node, ast.Index): return unparse(node.value) elif isinstance(node, ast.List): result = [addnodes.desc_sig_punctuation('', '[')] # type: List[Node] for elem in node.elts: result.extend(unparse(elem)) result.append(addnodes.desc_sig_punctuation('', ', ')) result.pop() result.append(addnodes.desc_sig_punctuation('', ']')) return result elif isinstance(node, ast.Module): return sum((unparse(e) for e in node.body), []) elif isinstance(node, ast.Name): return [nodes.Text(node.id)] elif isinstance(node, ast.Subscript): result = unparse(node.value) result.append(addnodes.desc_sig_punctuation('', '[')) result.extend(unparse(node.slice)) result.append(addnodes.desc_sig_punctuation('', ']')) return result elif isinstance(node, ast.Tuple): if node.elts: result = [] for elem in node.elts: result.extend(unparse(elem)) result.append(addnodes.desc_sig_punctuation('', ', ')) result.pop() else: result = [addnodes.desc_sig_punctuation('', '('), addnodes.desc_sig_punctuation('', ')')] return result else: raise SyntaxError # unsupported syntax if env is None: warnings.warn("The env parameter for _parse_annotation becomes required now.", RemovedInSphinx50Warning, stacklevel=2) try: tree = ast_parse(annotation) result = unparse(tree) for i, node in enumerate(result): if isinstance(node, nodes.Text): result[i] = type_to_xref(str(node), env) return result except SyntaxError: return [type_to_xref(annotation, env)]
def _parse_annotation(annotation: str) -> List[Node]: """Parse type annotation.""" def unparse(node: ast.AST) -> List[Node]: if isinstance(node, ast.Attribute): return [nodes.Text("%s.%s" % (unparse(node.value)[0], node.attr))] elif isinstance(node, ast.Expr): return unparse(node.value) elif isinstance(node, ast.Index): return unparse(node.value) elif isinstance(node, ast.List): result = [addnodes.desc_sig_punctuation('', '[')] # type: List[Node] for elem in node.elts: result.extend(unparse(elem)) result.append(addnodes.desc_sig_punctuation('', ', ')) result.pop() result.append(addnodes.desc_sig_punctuation('', ']')) return result elif isinstance(node, ast.Module): return sum((unparse(e) for e in node.body), []) elif isinstance(node, ast.Name): return [nodes.Text(node.id)] elif isinstance(node, ast.Subscript): result = unparse(node.value) result.append(addnodes.desc_sig_punctuation('', '[')) result.extend(unparse(node.slice)) result.append(addnodes.desc_sig_punctuation('', ']')) return result elif isinstance(node, ast.Tuple): if node.elts: result = [] for elem in node.elts: result.extend(unparse(elem)) result.append(addnodes.desc_sig_punctuation('', ', ')) result.pop() else: result = [ addnodes.desc_sig_punctuation('', '('), addnodes.desc_sig_punctuation('', ')') ] return result else: raise SyntaxError # unsupported syntax try: tree = ast_parse(annotation) result = unparse(tree) for i, node in enumerate(result): if isinstance(node, nodes.Text): result[i] = type_to_xref(str(node)) return result except SyntaxError: return [type_to_xref(annotation)]