Skip to content

Instantly share code, notes, and snippets.

@szobov
Created January 18, 2021 07:48
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save szobov/d171be3b06d8e9ef5455c8851da8a746 to your computer and use it in GitHub Desktop.
Save szobov/d171be3b06d8e9ef5455c8851da8a746 to your computer and use it in GitHub Desktop.
emacs: Google-style docstring in python
(defun python-google-docstring ()
"Generate google-style docstring for python."
(interactive)
(if (region-active-p)
(progn
(call-process-region (region-beginning) (region-end) "python3" nil t t "/home/szobov/bin/scripts/format-g-docs.py")
(message "Docs are generated")
(deactivate-mark))
(message "No region active; can't generate docs!"))
)
(evil-leader/set-key "o o" 'python-google-docstring)
import ast
import sys
import typing as t
import astunparse
def test(region: str = "foo", bar: t.List[t.Any] = [1, 2],
baz: int = 0) -> None:
"""
Args:
region (str): (default: 'foo')
bar (t.List[t.Any]): (default: [1, 2])
baz (int): (default: 0)
Returns:
None: nothing
"""
def __init__(self) -> None:
"""Initialize object
Returns:
None: nothing
"""
...
...
TAB = " "
def main() -> None:
raw_string = ""
indent = ""
for line in sys.stdin.readlines():
if (pos := line.find("def ")) != -1 :
indent = line[0:pos]
raw_string += line.strip()
indent = f"{indent}{TAB}"
try:
ast_data = ast.parse(raw_string + f"\n{indent}...")
except:
return ""
result = ""
for fun in ast_data.body:
if isinstance(fun, ast.FunctionDef):
if fun.name == "__init__":
result += f"{indent}\"\"\"Initialize object\n\n"
else:
result += f"{indent}\"\"\"\n\n"
args = [arg for arg in fun.args.args if arg.arg != "self"]
if len(fun.args.defaults) != 0:
for i, default in enumerate(reversed(fun.args.defaults)):
args[-(i + 1)].__local_default = astunparse.unparse(default).strip()
if len(args) != 0:
result += f"{indent}Args:\n"
for arg in args:
type_decr = "t.Any"
if arg.annotation is not None:
type_decr = astunparse.unparse(arg.annotation).strip()
result += f"{indent}{TAB}{arg.arg.strip()} ({type_decr}):"
if hasattr(arg, "__local_default"):
result += f" (default: {arg.__local_default})"
result += "\n"
if fun.args.vararg:
result += f"{indent}{TAB}*args (t.List[t.Any]):\n"
if fun.args.kwarg:
result += f"{indent}{TAB}**kwargs (t.Dict[t.Any, t.Any]):\n"
result += f"{indent}Returns:\n"
if ((fun.returns is None or getattr(fun.returns, "value", None) is None)
and not getattr(fun.returns, "id", None)):
result += f"{indent}{TAB}None: nothing\n"
else:
result += f"{indent}{TAB}{astunparse.unparse(fun.returns).strip()}:\n"
result += f"{indent}\"\"\""
if isinstance(fun, ast.ClassDef):
result += f"{indent}\"\"\"{fun.name} is a class for\n"
result += f"{indent}\"\"\""
print(result)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment