summaryrefslogtreecommitdiff
path: root/doc/build/lib/docstring.py
blob: 5d33667c75abfa0555e89d8fa71bc06c584e471d (plain)
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
152
153
154
155
156
157
"""
defines a pickleable, recursive "generated python documentation" datastructure.
"""

import re, types, string, inspect

allobjects = {}

class AbstractDoc(object):
    def __init__(self, obj):
        allobjects[id(obj)] = self
        self.id = id(obj)
        self.allobjects = allobjects
        self.toc_path = None
        
class ObjectDoc(AbstractDoc):
    def __init__(self, obj, functions=None, classes=None, include_all_classes=False):
        super(ObjectDoc, self).__init__(obj)
        self.isclass = isinstance(obj, types.ClassType) or isinstance(obj, types.TypeType)
        self.name= obj.__name__
        self.include_all_classes = include_all_classes
        functions = functions
        classes= classes
        
        if not self.isclass:
            if not include_all_classes and hasattr(obj, '__all__'):
                objects = obj.__all__
                sort = True
            else:
                objects = obj.__dict__.keys()
                sort = True
            if functions is None:
                functions = [getattr(obj, x, None) 
                    for x in objects 
                    if getattr(obj,x,None) is not None and 
                        (isinstance(getattr(obj,x), types.FunctionType))
                        and not self._is_private_name(getattr(obj,x).__name__)
                    ]
                if sort:
                    functions.sort(lambda a, b: cmp(a.__name__, b.__name__))
            if classes is None:
                classes = [getattr(obj, x, None) for x in objects 
                    if getattr(obj,x,None) is not None and 
                        (isinstance(getattr(obj,x), types.TypeType) 
                        or isinstance(getattr(obj,x), types.ClassType))
                        and (self.include_all_classes or not self._is_private_name(getattr(obj,x).__name__))
                    ]
                classes = list(set(classes))
                if sort:
                    classes.sort(lambda a, b: cmp(a.__name__.replace('_', ''), b.__name__.replace('_', '')))
        else:
            if functions is None:
                functions = (
                    [getattr(obj, x).im_func for x in obj.__dict__.keys() if isinstance(getattr(obj,x), types.MethodType) 
                    and 
                    (getattr(obj, x).__name__ == '__init__' or not self._is_private_name(getattr(obj,x).__name__))
                    ] + 
                    [(x, getattr(obj, x)) for x in obj.__dict__.keys() if _is_property(getattr(obj,x)) 
                    and 
                    not self._is_private_name(x)
                    ]
                 )
                functions.sort(lambda a, b: cmp(getattr(a, '__name__', None) or a[0], getattr(b, '__name__', None) or b[0] ))
            if classes is None:
                classes = []
        
        if self.isclass:
            self.description = "class " + self.name
            self.classname = self.name
            if hasattr(obj, '__mro__'):
                l = []
                mro = list(obj.__mro__[1:])
                mro.reverse()
                for x in mro:
                    for y in x.__mro__[1:]:
                        if y in l:
                            del l[l.index(y)]
                    l.insert(0, x)
                self.description += "(" + string.join([x.__name__ for x in l], ',') + ")"
                self._inherits = [(id(x), x.__name__) for x in l]
            else:
                self._inherits = []
        else:
            self.description = "module " + self.name

        self.doc = obj.__doc__

        self.functions = []
        if not self.isclass and len(functions):
            for func in functions:
                self.functions.append(FunctionDoc(func))
        else:
            if len(functions):
                for func in functions:
                    if isinstance(func, types.FunctionType):
                        self.functions.append(FunctionDoc(func))
                    elif isinstance(func, tuple):
                        self.functions.append(PropertyDoc(func[0], func[1]))
                        
        self.classes = []
        for class_ in classes:
            self.classes.append(ObjectDoc(class_))
    
    def _is_private_name(self, name):
        if re.match(r'^__.*__$', name):
            return False
        elif name.startswith('_'):
            return True
        else:
            return False

    def _get_inherits(self):
        for item in self._inherits:
            if item[0] in self.allobjects:
                yield self.allobjects[item[0]]
            else:
                yield item[1]
    inherits = property(_get_inherits)
    def accept_visitor(self, visitor):
        visitor.visit_object(self)

def _is_property(elem):
    return isinstance(elem, property) or (hasattr(elem, '__get__') and hasattr(elem, '__set__'))
    
class FunctionDoc(AbstractDoc):
    def __init__(self, func):
        super(FunctionDoc, self).__init__(func)
        argspec = inspect.getargspec(func)
        argnames = argspec[0]
        varargs = argspec[1]
        varkw = argspec[2]
        defaults = argspec[3] or ()
        argstrings = []
        for i in range(0, len(argnames)):
            if i >= len(argnames) - len(defaults):
                argstrings.append("%s=%s" % (argnames[i], repr(defaults[i - (len(argnames) - len(defaults))])))
            else:
                argstrings.append(argnames[i])
        if varargs is not None:
           argstrings.append("*%s" % varargs)
        if varkw is not None:
           argstrings.append("**%s" % varkw)
        self.argstrings = self.arglist = argstrings
        self.name = func.__name__
        self.link = func.__name__
        self.doc = func.__doc__
    def accept_visitor(self, visitor):
        visitor.visit_function(self)

class PropertyDoc(AbstractDoc):
    def __init__(self, name, prop):
        super(PropertyDoc, self).__init__(prop)
        self.doc = prop.__doc__
        self.name = name
        self.link = name
    def accept_visitor(self, visitor):
        visitor.visit_property(self)