Merge commit '3c4cac101904d7ec4b96cf6136714edfe292eb60' as 'utils_v2'
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
"""
|
||||
|
||||
AUTHOR:
|
||||
|
||||
Khushal P Soonderji
|
||||
|
||||
DATE:
|
||||
|
||||
Saturday, 24th Aug., 2024
|
||||
|
||||
OBJECTIVE:
|
||||
|
||||
To provide an overview of any function or class in a string.
|
||||
The generated overview can then either be shown on the terminal, or transmitted over some other medium for
|
||||
collaborative work.
|
||||
|
||||
REFERENCES:
|
||||
|
||||
N/A
|
||||
|
||||
DOWNLOADS:
|
||||
|
||||
N/A
|
||||
|
||||
"""
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** IMPORT ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# System-level activities:
|
||||
import io
|
||||
import inspect
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** MACROS / ONE-TIME INIT ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# --- Nothing Yet
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** VARIABLES ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# --- Nothing Yet
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** FUNCTIONS ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
def get_help_for_class(cls, skip_methods = None):
|
||||
|
||||
"""
|
||||
Returns the help documentation to use this class.
|
||||
:param cls: The class whose help string is desired.
|
||||
:param skip_methods: A list of methods to NOT include in the help text.
|
||||
:return: This help documentation.
|
||||
"""
|
||||
|
||||
separator = "\n\n" + ("=" * 120) + "\n\n"
|
||||
if skip_methods is None: skip_methods = []
|
||||
elif not isinstance(skip_methods, list): skip_methods = [skip_methods]
|
||||
|
||||
# Get class name and docstring:
|
||||
class_name = cls.__name__
|
||||
docstring = inspect.getdoc(cls) or ""
|
||||
help_string = "HELP FOR:\n\n"
|
||||
help_string += class_name + "\n\n"
|
||||
help_string += "This document has upto 120 chars per line.\n"
|
||||
help_string += "Best viewed with monospaced font :)"
|
||||
help_string += docstring + separator
|
||||
|
||||
# Get all methods and their docstrings.
|
||||
# Then note the documentation of the methods while ignoring the blacklisted ones:
|
||||
members = inspect.getmembers(cls, predicate = inspect.isfunction)
|
||||
func_help = []
|
||||
for name, method in members:
|
||||
|
||||
# Ignore if asked, or extract the details:
|
||||
if name in skip_methods or name.startswith(f"_{class_name}__"): continue
|
||||
else: func_help.append(get_help_for_function(method))
|
||||
|
||||
# Put all the things together:
|
||||
func_help = separator.join(func_help)
|
||||
help_string += func_help
|
||||
|
||||
# Done here:
|
||||
return help_string
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def get_help_for_function(func):
|
||||
|
||||
"""
|
||||
Get the help string for one function.
|
||||
It could be a standalone function, or a method of a class.
|
||||
:param func: The function (or method) whose help string is needed.
|
||||
:return: The help string of the function.
|
||||
"""
|
||||
|
||||
# Get the name and documentation:
|
||||
func_name = func.__name__
|
||||
async_indicator = " (async)" if inspect.iscoroutinefunction(func) else ""
|
||||
func_doc = inspect.getdoc(func) or ""
|
||||
|
||||
# Create the decorated header:
|
||||
func_decorator = "-" * (len(func_name) + 2)
|
||||
func_head = "." + func_decorator + f".\n| {func_name} |{async_indicator}\n`" + func_decorator + "`\n\n"
|
||||
|
||||
# Add the 'args' and 'kwargs':
|
||||
func_args = []
|
||||
for name, param in inspect.signature(func).parameters.items():
|
||||
default = param.default
|
||||
if isinstance(default, str): default = f"\"{default}\""
|
||||
if default == inspect.Parameter.empty: func_args.append(f"{name}")
|
||||
else: func_args.append(f"{name}: {type(default).__name__} = {default}")
|
||||
if len(func_args) > 0: func_args = f"{func_name} (\n\t" + "\n\t".join(func_args) + "\n):\n\n"
|
||||
else: func_args = f"{func_name} ():\n\n"
|
||||
|
||||
# Get the params and return value part from the doc:
|
||||
params_start = func_doc.find(":param")
|
||||
return_start = func_doc.find(":return")
|
||||
func_params = "\n" + func_doc[params_start:return_start] if params_start >= 0 else ""
|
||||
func_return = "\n" + func_doc[return_start:] if return_start >= 0 else ""
|
||||
|
||||
# Isolate the documentation part:
|
||||
if params_start >= 0: func_doc = func_doc[:params_start]
|
||||
elif return_start >= 0: func_doc = func_doc[:return_start]
|
||||
|
||||
# Done here:
|
||||
return func_head + func_args + func_doc + func_params + func_return
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def get_help(entity, skip_methods = None):
|
||||
|
||||
"""
|
||||
Get the help documentation for anything from its docstring.
|
||||
:param entity: The entity you want to get help for.
|
||||
:param skip_methods: A list of methods to ignore if inspecting a class. Not valid for standalone functions.
|
||||
:return: The help string.
|
||||
"""
|
||||
|
||||
if inspect.isclass(entity): return get_help_for_class(entity, skip_methods = skip_methods)
|
||||
else: return get_help_for_function(entity)
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** MAIN PROGRAM ***
|
||||
# ***** ****
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
pass
|
||||
Reference in New Issue
Block a user