Skip to content

Instantly share code, notes, and snippets.

@max-arnold
Created November 14, 2023 02:24
Show Gist options
  • Save max-arnold/08d0f0cee1e98be9e0bf5398ff0e829a to your computer and use it in GitHub Desktop.
Save max-arnold/08d0f0cee1e98be9e0bf5398ff0e829a to your computer and use it in GitHub Desktop.
Salt module info
#!/usr/bin/env python3
import argparse
import ast
import os
import sys
def parse_module(mod):
with open(mod, "r") as source:
tree = ast.parse(source.read())
functions = [
node
for node in tree.body
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))
]
func_list = []
for fun in functions:
doc = ast.get_docstring(fun)
doc = doc.splitlines()[0] if doc else ""
func_list.append((fun.name, ast.unparse(fun.args), doc))
classes = [node for node in tree.body if isinstance(node, ast.ClassDef)]
class_list = []
for cls in classes:
doc = ast.get_docstring(cls)
doc = doc.splitlines()[0] if doc else ""
class_list.append(
(cls.name, ", ".join([ast.unparse(base) for base in cls.bases]), doc)
)
assignments = [node for node in tree.body if isinstance(node, ast.Assign)]
assign_list = []
for assign in assignments:
if isinstance(assign.value, ast.Call) and ast.unparse(
assign.value.func
).endswith("namespaced_function"):
pass # We will get to that later
else:
tgt = assign.targets[0]
tgtsrc = ast.unparse(tgt)
if ((isinstance(tgt, ast.Name) and not tgtsrc.isupper())
or (isinstance(tgt, ast.Subscript) and not tgt.value.id.isupper())):
assign_list.append(
(tgtsrc, ast.unparse(assign.value))
)
for node in ast.walk(tree):
if (
isinstance(node, ast.Assign)
and isinstance(node.value, ast.Call)
and ast.unparse(node.value.func).endswith("namespaced_function")
):
func_list.append((node.targets[0].id, "...", "NAMESPACED FUNCTION"))
class_list.sort()
func_list.sort()
assign_list.sort()
return class_list, func_list, assign_list
if __name__ == "__main__":
parser = argparse.ArgumentParser(
formatter_class=argparse.ArgumentDefaultsHelpFormatter
)
parser.add_argument(
"module",
nargs="+",
type=str,
help="Path to Salt module",
)
options = parser.parse_args()
first = True
for mod in options.module:
if not os.path.isfile(mod):
parser.exit("Module should be a file: {}".format(mod))
if first:
first = False
else:
print("\n\n")
print("### " + os.path.basename(mod))
class_list, func_list, assign_list = parse_module(mod)
for assign in assign_list:
print(f"{assign[0]} = {assign[1]}")
for cls in class_list:
print(f"class {cls[0]}({cls[1]}): {cls[2]}")
for fn in func_list:
print(f"def {fn[0]}({fn[1]}): {fn[2]}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment