wxWidgets/wxPython/wx/py/wxd/decorator.py
2003-11-12 21:34:20 +00:00

94 lines
3.2 KiB
Python

"""Decorator utility for documentation and shell scripting."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__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