Subversion Repositories freemyipod

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
396 farthen 1
#!/usr/bin/env python
2
#
3
#
4
#    Copyright 2010 TheSeven, benedikt93, Farthen
5
#
6
#
7
#    This file is part of emBIOS.
8
#
9
#    emBIOS is free software: you can redistribute it and/or
10
#    modify it under the terms of the GNU General Public License as
11
#    published by the Free Software Foundation, either version 2 of the
12
#    License, or (at your option) any later version.
13
#
14
#    emBIOS is distributed in the hope that it will be useful,
15
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
16
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
#    See the GNU General Public License for more details.
18
#
19
#    You should have received a copy of the GNU General Public License
20
#    along with emBIOS.  If not, see <http://www.gnu.org/licenses/>.
21
#
22
#
23
 
24
"""
25
    This file includes some reusable functions and classes that might be useful
26
    to all python scripts
27
"""
28
 
29
import sys
30
 
31
class Logger(object):
32
    """
33
        Simple stdout logger.
34
        Loglevel 4 is most verbose, Loglevel 0: Only say something if there is an error.
35
        The log function doesn't care about the loglevel and always logs to stdout.
36
    """
37
    def __init__(self):
38
        # Possible values: 0 (only errors), 1 (warnings), 2 (info, recommended for production use), 3 and more (debug)
39
        self.loglevel = 3
40
 
41
    def log(self, text, indent = 0, target = "stdout"):
42
        text = (indent * " ") + text
43
        text = text.replace("\n", "\n" + (indent * " "), text.count("\n") - 1)
44
        if target == "stdout":
45
            sys.stdout.write(text)
46
        elif target == "string":
47
            return text
48
 
49
    def debug(self, text, indent = 0, target = "stdout"):
50
        if self.loglevel >= 3:
51
            self.log("DEBUG: " + text, indent, target)
52
 
53
    def info(self, text, indent = 0, target = "stdout"):
54
        if self.loglevel >= 2:
55
            self.log(text, indent, target)
56
 
57
    def warn(self, text, indent = 0, target = "stdout"):
58
        if self.loglevel >= 1:
59
            self.log("WARNING: " + text, indent, target)
60
 
61
    def error(self, text, indent = 0, target = "stdout"):
62
        self.log("ERROR: " + text, indent, target)
63
 
64
 
65
class Bunch(dict):
66
    """
67
        This is a dict whose items can also be accessed with
68
        bunchinstance.something.
69
    """
70
    def __init__(self, **kw):
71
        dict.__init__(self, kw)
72
        self.__dict__ = self
73
 
74
    def __getstate__(self):
75
        return self
76
 
77
    def __setstate__(self, state):
78
        self.update(state)
79
        self.__dict__ = self
80
 
81
 
82
class Error(Exception):
83
    def __init__(self, value=None):
84
        self.value = value
85
    def __str__(self):
86
        if self.value != None:
87
            return repr(self.value)
88
 
89
 
90
def trimdoc(docstring):
91
    """
92
        Trims whitespace from docstrings
93
    """
94
    if not docstring:
95
        return ''
96
    # Convert tabs to spaces (following the normal Python rules)
97
    # and split into a list of lines:
98
    lines = docstring.expandtabs().splitlines()
99
    # Determine minimum indentation (first line doesn't count):
100
    indent = sys.maxint
101
    for line in lines[1:]:
102
        stripped = line.lstrip()
103
        if stripped:
104
            indent = min(indent, len(line) - len(stripped))
105
    # Remove indentation (first line is special):
106
    trimmed = [lines[0].strip()]
107
    if indent < sys.maxint:
108
        for line in lines[1:]:
109
            trimmed.append(line[indent:].rstrip())
110
    # Strip off trailing and leading blank lines:
111
    while trimmed and not trimmed[-1]:
112
        trimmed.pop()
113
    while trimmed and not trimmed[0]:
114
        trimmed.pop(0)
115
    # Return a single string:
116
    return '\n'.join(trimmed)
117
 
118
 
119
def getfuncdoc(funcdict):
120
    """
121
        Extracts important information from a dict of functions like the
122
        docstring and arguments and returns them in a human readable format
123
    """
124
    import inspect
125
    import re
126
    functions = Bunch()
127
    for function in funcdict:
128
        function = funcdict[function].func
129
        docinfo = Bunch()
130
        name = function.__name__
131
        args = inspect.getargspec(function)[0]
132
        docinfo['varargs'] = False
133
        if inspect.getargspec(function)[1]:
134
            docinfo['varargs'] = True
135
        kwargvalues = inspect.getargspec(function)[3]
136
        kwargs = Bunch()
137
        if args:
138
            if kwargvalues:
139
                argnum = len(args) - len(kwargvalues)
140
                kwargnum = len(kwargvalues)
141
                kwargs = dict(zip(args[argnum:], kwargvalues))
142
            else:
143
                argnum = len(args)
144
        else:
145
            argnum = 0
146
        docinfo['args'] = args[1:argnum]
147
        docinfo['kwargs'] = kwargs
148
        if function.__doc__:
149
            # strip unneccessary whitespace
150
            docinfo['documentation'] = trimdoc(function.__doc__)
151
        else:
152
            docinfo['documentation'] = None
153
        functions[name] = docinfo
154
    return functions
155
 
156
 
157
def gendoc(funcdict, indentwidth = 4, logtarget = "string"):
158
    logger = Logger()
159
    doc = getfuncdoc(funcdict)
160
    ret = ""
161
    for function in sorted(doc.items()):
162
        function = function[0]
163
        ret += logger.log("def " + function + "(", target = logtarget)
164
        counter = 0
165
        if doc[function]['args']:
166
            for arg in doc[function]['args']:
167
                if counter > 0:
168
                    sys.stdout.write(", ")
169
                counter += 1
170
                ret += logger.log(arg, target = logtarget)
171
        if doc[function]['kwargs']:
172
            for kwarg, kwargvalue in doc[function]['kwargs'].items():
173
                if counter > 0:
174
                    sys.stdout.write(", ")
175
                counter += 1
176
                ret += logger.log(kwarg + "=" + str(kwargvalue), target = logtarget)
177
        if doc[function]['varargs']:
178
            ret += logger.log("*argv", target = logtarget)
179
        ret += logger.log("):\n", target = logtarget)
180
        if doc[function]['documentation']:
181
            ret += logger.log("\"\"\"\n", indent = indentwidth, target = logtarget)
182
            ret += logger.log(trimdoc(doc[function]['documentation']) + "\n", indent = 2 * indentwidth, target = logtarget)
183
            ret += logger.log("\"\"\"\n", indent = indentwidth, target = logtarget)
184
        ret += logger.log("\n", target = logtarget)
185
    return ret