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