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