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
398 farthen 30
import libembiosdata
396 farthen 31
 
32
class Logger(object):
33
    """
34
        Simple stdout logger.
35
        Loglevel 4 is most verbose, Loglevel 0: Only say something if there is an error.
36
        The log function doesn't care about the loglevel and always logs to stdout.
37
    """
400 farthen 38
    def __init__(self, loglevel = 3, logfile = "tools.log", target = "stdout"):
39
        """
40
            loglevel: Possible values: 0 (only errors), 1 (warnings), 2 (info,
41
                      recommended for production use), 3 and more (debug)
42
            logfile: File to log to if using the target = "file"
43
            target: Default logging target. Can be "stdout", "file" or "string"
44
        """
45
        self.loglevel = loglevel
46
        self.logfile = logfile
47
        self.target = target
396 farthen 48
 
400 farthen 49
    def log(self, text, indent = 0, target = None):
50
        if target is None: target = self.target
396 farthen 51
        text = (indent * " ") + text
52
        text = text.replace("\n", "\n" + (indent * " "), text.count("\n") - 1)
53
        if target == "stdout":
54
            sys.stdout.write(text)
400 farthen 55
        elif target == "file":
56
            with open(self.logfile, 'a') as f:
57
                f.write(text)
58
                f.close()
396 farthen 59
        elif target == "string":
60
            return text
61
 
400 farthen 62
    def debug(self, text, indent = 0, target = None):
396 farthen 63
        if self.loglevel >= 3:
64
            self.log("DEBUG: " + text, indent, target)
65
 
400 farthen 66
    def info(self, text, indent = 0, target = None):
396 farthen 67
        if self.loglevel >= 2:
68
            self.log(text, indent, target)
69
 
400 farthen 70
    def warn(self, text, indent = 0, target = None):
396 farthen 71
        if self.loglevel >= 1:
72
            self.log("WARNING: " + text, indent, target)
73
 
400 farthen 74
    def error(self, text, indent = 0, target = None):
396 farthen 75
        self.log("ERROR: " + text, indent, target)
76
 
77
 
78
class Bunch(dict):
79
    """
80
        This is a dict whose items can also be accessed with
81
        bunchinstance.something.
82
    """
83
    def __init__(self, **kw):
84
        dict.__init__(self, kw)
85
        self.__dict__ = self
86
 
87
    def __getstate__(self):
88
        return self
89
 
90
    def __setstate__(self, state):
91
        self.update(state)
92
        self.__dict__ = self
93
 
94
 
95
class Error(Exception):
96
    def __init__(self, value=None):
97
        self.value = value
98
    def __str__(self):
99
        if self.value != None:
100
            return repr(self.value)
101
 
102
 
398 farthen 103
def gethwname(id):
104
    try:
105
        hwtype = libembiosdata.hwtypes[id]
106
    except KeyError:
107
        hwtype = "UNKNOWN (ID = " + self._hex(id) + ")"
108
    return hwtype
109
 
110
 
396 farthen 111
def trimdoc(docstring):
112
    """
113
        Trims whitespace from docstrings
114
    """
115
    if not docstring:
116
        return ''
117
    # Convert tabs to spaces (following the normal Python rules)
118
    # and split into a list of lines:
119
    lines = docstring.expandtabs().splitlines()
120
    # Determine minimum indentation (first line doesn't count):
121
    indent = sys.maxint
122
    for line in lines[1:]:
123
        stripped = line.lstrip()
124
        if stripped:
125
            indent = min(indent, len(line) - len(stripped))
126
    # Remove indentation (first line is special):
127
    trimmed = [lines[0].strip()]
128
    if indent < sys.maxint:
129
        for line in lines[1:]:
130
            trimmed.append(line[indent:].rstrip())
131
    # Strip off trailing and leading blank lines:
132
    while trimmed and not trimmed[-1]:
133
        trimmed.pop()
134
    while trimmed and not trimmed[0]:
135
        trimmed.pop(0)
136
    # Return a single string:
137
    return '\n'.join(trimmed)
138
 
139
 
140
def getfuncdoc(funcdict):
141
    """
142
        Extracts important information from a dict of functions like the
143
        docstring and arguments and returns them in a human readable format
144
    """
145
    import inspect
146
    import re
147
    functions = Bunch()
148
    for function in funcdict:
149
        function = funcdict[function].func
150
        docinfo = Bunch()
151
        name = function.__name__
152
        args = inspect.getargspec(function)[0]
153
        docinfo['varargs'] = False
154
        if inspect.getargspec(function)[1]:
155
            docinfo['varargs'] = True
156
        kwargvalues = inspect.getargspec(function)[3]
157
        kwargs = Bunch()
158
        if args:
159
            if kwargvalues:
160
                argnum = len(args) - len(kwargvalues)
161
                kwargnum = len(kwargvalues)
162
                kwargs = dict(zip(args[argnum:], kwargvalues))
163
            else:
164
                argnum = len(args)
165
        else:
166
            argnum = 0
167
        docinfo['args'] = args[1:argnum]
168
        docinfo['kwargs'] = kwargs
169
        if function.__doc__:
170
            # strip unneccessary whitespace
171
            docinfo['documentation'] = trimdoc(function.__doc__)
172
        else:
173
            docinfo['documentation'] = None
174
        functions[name] = docinfo
175
    return functions
176
 
177
 
178
def gendoc(funcdict, indentwidth = 4, logtarget = "string"):
179
    logger = Logger()
180
    doc = getfuncdoc(funcdict)
181
    ret = ""
182
    for function in sorted(doc.items()):
183
        function = function[0]
184
        ret += logger.log("def " + function + "(", target = logtarget)
185
        counter = 0
186
        if doc[function]['args']:
187
            for arg in doc[function]['args']:
188
                if counter > 0:
189
                    sys.stdout.write(", ")
190
                counter += 1
191
                ret += logger.log(arg, target = logtarget)
192
        if doc[function]['kwargs']:
193
            for kwarg, kwargvalue in doc[function]['kwargs'].items():
194
                if counter > 0:
195
                    sys.stdout.write(", ")
196
                counter += 1
197
                ret += logger.log(kwarg + "=" + str(kwargvalue), target = logtarget)
198
        if doc[function]['varargs']:
199
            ret += logger.log("*argv", target = logtarget)
200
        ret += logger.log("):\n", target = logtarget)
201
        if doc[function]['documentation']:
202
            ret += logger.log("\"\"\"\n", indent = indentwidth, target = logtarget)
203
            ret += logger.log(trimdoc(doc[function]['documentation']) + "\n", indent = 2 * indentwidth, target = logtarget)
204
            ret += logger.log("\"\"\"\n", indent = indentwidth, target = logtarget)
205
        ret += logger.log("\n", target = logtarget)
206
    return ret