Subversion Repositories freemyipod

Rev

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