ActiveState Powered by ActiveState

Recipe 553262: List classes, methods and functions in a module


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
  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
149
150
151
#!/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

INDENT=0

def wi(*args):
   """ Function to print lines indented according to level """
   
   spaces = ' '*INDENT
   print spaces,
   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('\tMethod Arguments:', args)

   if args=='':
      wi('\tMethod 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('\tMethod Arguments:', args)

       if arginfo[3]:
           dl = len(arginfo[3])
           al = len(args)
           defargs = args[al-dl:al]
           wi('\tDefault 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' % 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)

Discussion

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.

Comments

  1. 1. At 2:57 a.m. on 28 jul 2008, Zhed Bolyshevin (the author) said:

    [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
  2. 2. At 3:31 p.m. on 7 aug 2008, Senthil Kumaran said:

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

  3. 3. At 7:22 p.m. on 7 aug 2008, Anonymous said:

    Wow. This is really helpful and cool.

Sign in to comment