| 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
|