Welcome, guest | Sign In | My Account | Store | Cart

The recipe provides a method "describe" which takes a module as argument and describes classes, methods and functions in the module. The method/function description provides information on the function/method arguments using the inspect module.

Python, 148 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/env python
# Describe classes, methods and functions in a module.
# Works with user-defined modules, all Python library
# modules, including built-in modules.

import inspect
import os, sys

INDENT=0

def wi(*args):
   """ Function to print lines indented according to level """
   
   if INDENT: print ' '*INDENT,
   for arg in args: print arg,
   print

def indent():
   """ Increase indentation """
   
   global INDENT
   INDENT += 4

def dedent():
   """ Decrease indentation """
   
   global INDENT
   INDENT -= 4

def describe_builtin(obj):
   """ Describe a builtin function """

   wi('+Built-in Function: %s' % obj.__name__)
   # Built-in functions cannot be inspected by
   # inspect.getargspec. We have to try and parse
   # the __doc__ attribute of the function.
   docstr = obj.__doc__
   args = ''
   
   if docstr:
      items = docstr.split('\n')
      if items:
         func_descr = items[0]
         s = func_descr.replace(obj.__name__,'')
         idx1 = s.find('(')
         idx2 = s.find(')',idx1)
         if idx1 != -1 and idx2 != -1 and (idx2>idx1+1):
            args = s[idx1+1:idx2]
            wi('\t-Method Arguments:', args)

   if args=='':
      wi('\t-Method Arguments: None')

   print
   
def describe_func(obj, method=False):
   """ Describe the function object passed as argument.
   If this is a method object, the second argument will
   be passed as True """
   
   if method:
      wi('+Method: %s' % obj.__name__)
   else:
      wi('+Function: %s' % obj.__name__)

   try:
       arginfo = inspect.getargspec(obj)
   except TypeError:
      print 
      return
   
   args = arginfo[0]
   argsvar = arginfo[1]

   if args:
       if args[0] == 'self':
           wi('\t%s is an instance method' % obj.__name__)
           args.pop(0)

       wi('\t-Method Arguments:', args)

       if arginfo[3]:
           dl = len(arginfo[3])
           al = len(args)
           defargs = args[al-dl:al]
           wi('\t--Default arguments:',zip(defargs, arginfo[3]))

   if arginfo[1]:
       wi('\t-Positional Args Param: %s' % arginfo[1])
   if arginfo[2]:
       wi('\t-Keyword Args Param: %s' % arginfo[2])

   print

def describe_klass(obj):
   """ Describe the class object passed as argument,
   including its methods """

   wi('+Class: %s' % obj.__name__)

   indent()

   count = 0
   
   for name in obj.__dict__:
       item = getattr(obj, name)
       if inspect.ismethod(item):
           count += 1;describe_func(item, True)

   if count==0:
      wi('(No members)')
      
   dedent()
   print 

def describe(module):
   """ Describe the module object passed as argument
   including its classes and functions """
   
   wi('[Module: %s]\n' % module.__name__)

   indent()

   count = 0
   
   for name in dir(module):
       obj = getattr(module, name)
       if inspect.isclass(obj):
          count += 1; describe_klass(obj)
       elif (inspect.ismethod(obj) or inspect.isfunction(obj)):
          count +=1 ; describe_func(obj)
       elif inspect.isbuiltin(obj):
          count += 1; describe_builtin(obj)

   if count==0:
      wi('(No members)')
      
   dedent()

if __name__ == "__main__":
   import sys
   
   if len(sys.argv)<2:
      sys.exit('Usage: %s <module>' % sys.argv[0])

   module = sys.argv[1].replace('.py','')
   mod = __import__(module)
   describe(mod)

This came as a question in our local Python mailing list (BangPypers). I wrote up the above solution to provide a quick summary of a module in terms of classes, and simple method descriptions. The 'inspect' module makes this task relatively easy.

[Edit] - Added support for built-in functions/methods. [Edit 22/10/08] - Changes in printing style.

3 comments

Anand (author) 15 years, 8 months ago  # | flag

[Edited 28 Jul 2008, Anand]

  • Changed functions to use inspect functions instead of types
  • Separate function for describing built-in functions
  • Changed function names to begin with "describe"
  • Pretty printing
Senthil Kumaran 15 years, 7 months ago  # | flag

I also found this useful in illustrating the use of indent and dedent in output. Make the output look pretty neat.

uzmanajmal 15 years, 7 months ago  # | flag

Wow. This is really helpful and cool.