]>
Commit | Line | Data |
---|---|---|
1e4a197e RD |
1 | """Decorator utility for documentation and shell scripting.""" |
2 | ||
3 | __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>" | |
4 | __cvsid__ = "$Id$" | |
5 | __revision__ = "$Revision$"[11:-2] | |
6 | ||
7 | ||
8 | import inspect | |
9 | ||
10 | try: | |
11 | True | |
12 | except NameError: | |
13 | True = 1==1 | |
14 | False = 1==0 | |
15 | ||
16 | def decorate(real, decoration): | |
17 | """Decorate real module with docstrings from decoration module.""" | |
18 | realdict = real.__dict__ | |
19 | for item in decoration.__dict__.values(): | |
20 | if inspect.isclass(item): | |
21 | decorateClass(item, realdict) | |
22 | elif inspect.isfunction(item): | |
23 | decorateFunction(item, realdict) | |
24 | ||
25 | def decorateClass(item, realdict): | |
26 | classname = item.__name__ | |
27 | if not classname.startswith('wx'): | |
28 | classname = 'wx' + classname | |
29 | try: | |
30 | wxclass = realdict[classname] | |
31 | except: | |
1fded56b RD |
32 | # print classname |
33 | pass | |
1e4a197e RD |
34 | else: |
35 | if item.__doc__: | |
36 | wxclass.__doc__ = item.__doc__ | |
37 | # Get attributes from only the item's local dictionary! | |
38 | for attrname, attr in item.__dict__.items(): | |
39 | # If the attribute has a docstring, and the wx class has a | |
40 | # matching attribute. | |
41 | if hasattr(attr, '__doc__') and hasattr(wxclass, attrname): | |
42 | if inspect.isfunction(attr): | |
43 | # Class methods are functions. | |
44 | doc = getdoc(attr, drop=True) | |
45 | # Is getattr() okay, or do we want to only look in | |
46 | # the wxclass.__dict__ and wxclassPtr.__dict__? | |
47 | wxattr = getattr(wxclass, attrname) | |
48 | # Our class code may be defined incorrectly, and | |
49 | # the wxattr may not actually be a class method, | |
50 | # but that's okay because the following attempt | |
51 | # will simply fail. | |
52 | try: | |
53 | func = wxattr.im_func | |
54 | func.__doc__ = doc | |
55 | except: | |
56 | pass | |
57 | ||
58 | def decorateFunction(item, realdict): | |
59 | funcname = item.__name__ | |
60 | if funcname in realdict.keys(): | |
61 | func = realdict[funcname] | |
62 | doc = getdoc(item, drop=False) | |
63 | try: | |
64 | # Built-in functions have a read-only docstring. :-( | |
65 | func.__doc__ = doc | |
66 | except: | |
67 | # print funcname | |
68 | pass | |
69 | ||
70 | def getdoc(attr, drop=False): | |
71 | """Return a docstring for attr, which should be a method.""" | |
72 | doc = '' | |
73 | if attr.__doc__: | |
74 | doc = inspect.getdoc(attr).strip() | |
75 | name = attr.__name__ | |
76 | # tip is a string with name(argspec), like: "SetLabel(label)" | |
77 | tip = '' | |
78 | argspec = apply(inspect.formatargspec, inspect.getargspec(attr)) | |
79 | # The first parameter to a method is a reference to an instance, | |
80 | # usually coded as "self", and is usually passed automatically by | |
81 | # Python and therefore we want to drop it. | |
82 | temp = argspec.split(',') | |
83 | if len(temp) == 1: # No other arguments. | |
84 | argspec = '()' | |
85 | elif drop: # Drop the first argument. | |
86 | argspec = '(' + ','.join(temp[1:]).lstrip() | |
87 | else: | |
88 | argspec = ','.join(temp).lstrip() | |
89 | tip = name + argspec | |
90 | firstline = doc.split('\n')[0].lstrip() | |
91 | if tip != firstline: | |
92 | doc = '%s\n\n%s' % (tip, doc) | |
93 | return doc |