If you can snag from namespace, then the inspect module is kind of useful. This demo just inspects itself, but code inside shows how you might factor it to provide other information.
def num_41(func=None):
"""(num_41)...Documenting code using inspect
:Requires:
:--------
: import inspect
:Source code for...
: module level => inspect.getsourcelines(sys.modules[__name__])[0]
: function level
: as a list => inspect.getsourcelines(num_41)[0]
: as a string => inspect.getsource(num_41)
: file level => script = sys.argv[0]
:Returns: a listing of the source code with line numbers
:-------
:
"""
def demo_def():
"""dummy...
: Demonstrates retrieving and documenting module and function info.
:
"""
def sub():
"""sub in dummy"""
pass
return None
import inspect
if func is None:
func = demo_def
script = sys.argv[0]
lines, line_num = inspect.getsourcelines(func)
code = "".join(["{:4d} {}".format(idx, line)
for idx, line in enumerate(lines)])
defs = [key for key, value in globals().items()
if callable(value) and value.__module__ == __name__]
args = [line_num, code,
inspect.getcomments(func), inspect.isfunction(func),
inspect.ismethod(func), inspect.getmoduleinfo(script),
defs
]
frmt = """
:----------------------------------------------------------------------
:Code for a function on line...{}...
{}
:Comments preceeding function
{}
:function?... {} ... or method? {}
:Module info...
{}
:
:Module functions...
{}
:----------------------------------------------------------------------
"""
print(dedent(frmt).format(*args))
return None
And here is the output if you use num_41() to inspect itself
Here is some output
>>> num_41()
:----------------------------------------------------------------------
:Code for a function on line...125...
0 def demo_def():
1 """dummy...
2 : Demonstrates retrieving and documenting module and function info.
3 :
4 """
5 def sub():
6 """sub in dummy"""
7 pass
8 return None
:Comments preceeding function
None
:function?... True ... or method? False
:Module info...
ModuleInfo(name='testing_script_03', suffix='.py', mode='r', module_type=1)
:
:Module functions...
['num_46', 'num_47', 'num_44', 'num_40', 'num_41', 'num_42', 'num_43', 'dummy', 'num_45']
:----------------------------------------------------------------------
Since the sample script is in a script (aka, module) there are a number of other functions in there. For example. I can pull in information from a particular module using
>>> locals().keys()
dict_keys(['dedent', ...snip ..., '__doc__', 'art', '__loader__', 'np', '__spec__', 'dummy', 'num_45'])
>>> num_41(art)
:----------------------------------------------------------------------
:Code for a function on line...0...
0
1 """
2 :Script: arr_tools.py
...... huge snip .........
682
683
684
685 if __name__=="__main__":
686 """ """
687
688 a, b, c, d = _demo()
By using other options in the inspect module, you can extract a lot of information. I sometimes use this to get list of defs sometimes not revealed during the normal course of doing 'dir' or 'locals().keys()