"""Decorator utility for documentation and shell scripting.""" __author__ = "Patrick K. O'Brien " __cvsid__ = "$Id$" __revision__ = "$Revision$"[11:-2] import inspect try: True except NameError: True = 1==1 False = 1==0 def decorate(real, decoration): """Decorate real module with docstrings from decoration module.""" realdict = real.__dict__ for item in decoration.__dict__.values(): if inspect.isclass(item): decorateClass(item, realdict) elif inspect.isfunction(item): decorateFunction(item, realdict) def decorateClass(item, realdict): classname = item.__name__ if not classname.startswith('wx'): classname = 'wx' + classname try: wxclass = realdict[classname] except: # print classname pass else: if item.__doc__: wxclass.__doc__ = item.__doc__ # Get attributes from only the item's local dictionary! for attrname, attr in item.__dict__.items(): # If the attribute has a docstring, and the wx class has a # matching attribute. if hasattr(attr, '__doc__') and hasattr(wxclass, attrname): if inspect.isfunction(attr): # Class methods are functions. doc = getdoc(attr, drop=True) # Is getattr() okay, or do we want to only look in # the wxclass.__dict__ and wxclassPtr.__dict__? wxattr = getattr(wxclass, attrname) # Our class code may be defined incorrectly, and # the wxattr may not actually be a class method, # but that's okay because the following attempt # will simply fail. try: func = wxattr.im_func func.__doc__ = doc except: pass def decorateFunction(item, realdict): funcname = item.__name__ if funcname in realdict.keys(): func = realdict[funcname] doc = getdoc(item, drop=False) try: # Built-in functions have a read-only docstring. :-( func.__doc__ = doc except: # print funcname pass def getdoc(attr, drop=False): """Return a docstring for attr, which should be a method.""" doc = '' if attr.__doc__: doc = inspect.getdoc(attr).strip() name = attr.__name__ # tip is a string with name(argspec), like: "SetLabel(label)" tip = '' argspec = apply(inspect.formatargspec, inspect.getargspec(attr)) # The first parameter to a method is a reference to an instance, # usually coded as "self", and is usually passed automatically by # Python and therefore we want to drop it. temp = argspec.split(',') if len(temp) == 1: # No other arguments. argspec = '()' elif drop: # Drop the first argument. argspec = '(' + ','.join(temp[1:]).lstrip() else: argspec = ','.join(temp).lstrip() tip = name + argspec firstline = doc.split('\n')[0].lstrip() if tip != firstline: doc = '%s\n\n%s' % (tip, doc) return doc