Rev 424 | Blame | Last modification | View Log | RSS feed
#!/usr/bin/env python### Copyright 2010 TheSeven, benedikt93, Farthen### This file is part of emCORE.## emCORE is free software: you can redistribute it and/or# modify it under the terms of the GNU General Public License as# published by the Free Software Foundation, either version 2 of the# License, or (at your option) any later version.## emCORE is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.# See the GNU General Public License for more details.## You should have received a copy of the GNU General Public License# along with emCORE. If not, see <http://www.gnu.org/licenses/>.##"""This file includes some reusable functions and classes that might be usefulto all python scripts"""import sysimport libemcoredataclass Logger(object):"""Simple stdout logger.Loglevel 3 is most verbose, Loglevel 0: Only log something if there is an error.Loglevel -1 means that nothing is logged.The log function doesn't care about the loglevel and always logs to stdout."""def __init__(self, loglevel = 2, target = "stdout", logfile = "tools.log"):"""loglevel: Possible values: 0 (only errors), 1 (warnings), 2 (info,recommended for production use), 3 and more (debug)logfile: File to log to if using the target = "file"target: Default logging target. Can be "stdout", "file" or "string""""self.loglevel = loglevelself.logfile = logfileself.target = targetdef log(self, text, indent = 0, target = None):if self.loglevel >= 0:if target is None: target = self.targettext = (indent * " ") + texttext = text.replace("\n", "\n" + (indent * " "), text.count("\n") - 1)if target == "stdout":sys.stdout.write(text)elif target == "file":with open(self.logfile, 'a') as f:f.write(text)f.close()elif target == "string":return textdef debug(self, text, indent = 0, target = None):if self.loglevel >= 3:self.log("DEBUG: " + text, indent, target)def info(self, text, indent = 0, target = None):if self.loglevel >= 2:self.log(text, indent, target)def warn(self, text, indent = 0, target = None):if self.loglevel >= 1:self.log("WARNING: " + text, indent, target)def error(self, text, indent = 0, target = None):if self.loglevel >= 0:self.log("ERROR: " + text, indent, target)class Bunch(dict):"""This is a dict whose items can also be accessed withbunchinstance.something."""def __init__(self, **kw):dict.__init__(self, kw)self.__dict__ = selfdef __getstate__(self):return selfdef __setstate__(self, state):self.update(state)self.__dict__ = selfclass Error(Exception):def __init__(self, value=None):self.value = valuedef __str__(self):if self.value != None:return repr(self.value)def gethwname(id):try:hwtype = libemcoredata.hwtypes[id]except KeyError:hwtype = "UNKNOWN (ID = " + self._hex(id) + ")"return hwtypedef trimdoc(docstring):"""Trims whitespace from docstrings"""if not docstring:return ''# Convert tabs to spaces (following the normal Python rules)# and split into a list of lines:lines = docstring.expandtabs().splitlines()# Determine minimum indentation (first line doesn't count):indent = sys.maxintfor line in lines[1:]:stripped = line.lstrip()if stripped:indent = min(indent, len(line) - len(stripped))# Remove indentation (first line is special):trimmed = [lines[0].strip()]if indent < sys.maxint:for line in lines[1:]:trimmed.append(line[indent:].rstrip())# Strip off trailing and leading blank lines:while trimmed and not trimmed[-1]:trimmed.pop()while trimmed and not trimmed[0]:trimmed.pop(0)# Return a single string:return '\n'.join(trimmed)def getfuncdoc(funcdict):"""Extracts important information from a dict of functions like thedocstring and arguments and returns them in a human readable format"""import inspectimport refunctions = Bunch()for function in funcdict:function = funcdict[function].funcdocinfo = Bunch()name = function.__name__args = inspect.getargspec(function)[0]docinfo['varargs'] = Falseif inspect.getargspec(function)[1]:docinfo['varargs'] = Truekwargvalues = inspect.getargspec(function)[3]kwargs = Bunch()if args:if kwargvalues:argnum = len(args) - len(kwargvalues)kwargnum = len(kwargvalues)kwargs = dict(zip(args[argnum:], kwargvalues))else:argnum = len(args)else:argnum = 0docinfo['args'] = args[1:argnum]docinfo['kwargs'] = kwargsif function.__doc__:# strip unneccessary whitespacedocinfo['documentation'] = trimdoc(function.__doc__)else:docinfo['documentation'] = Nonefunctions[name] = docinforeturn functionsdef gendoc(funcdict, indentwidth = 4, logtarget = "string"):logger = Logger()doc = getfuncdoc(funcdict)ret = ""for function in sorted(doc.items()):function = function[0]ret += logger.log("def " + function + "(", target = logtarget)counter = 0if doc[function]['args']:for arg in doc[function]['args']:if counter > 0:sys.stdout.write(", ")counter += 1ret += logger.log(arg, target = logtarget)if doc[function]['kwargs']:for kwarg, kwargvalue in doc[function]['kwargs'].items():if counter > 0:sys.stdout.write(", ")counter += 1ret += logger.log(kwarg + "=" + str(kwargvalue), target = logtarget)if doc[function]['varargs']:ret += logger.log("*argv", target = logtarget)ret += logger.log("):\n", target = logtarget)if doc[function]['documentation']:ret += logger.log("\"\"\"\n", indent = indentwidth, target = logtarget)ret += logger.log(trimdoc(doc[function]['documentation']) + "\n", indent = 2 * indentwidth, target = logtarget)ret += logger.log("\"\"\"\n", indent = indentwidth, target = logtarget)ret += logger.log("\n", target = logtarget)return ret