15b6bfdb9SJed Brownfrom __future__ import absolute_import 2179860b2SJed Brownimport args 3179860b2SJed Brownimport sys 4179860b2SJed Brownimport os 59561296dSJacob Faibussowitschimport textwrap 6179860b2SJed Brown 7179860b2SJed Brown# Ugly stuff to have curses called ONLY once, instead of for each 8179860b2SJed Brown# new Configure object created (and flashing the screen) 9179860b2SJed Brownglobal LineWidth 10179860b2SJed Brownglobal RemoveDirectory 11179860b2SJed Brownglobal backupRemoveDirectory 12179860b2SJed BrownLineWidth = -1 13179860b2SJed BrownRemoveDirectory = os.path.join(os.getcwd(),'') 14179860b2SJed BrownbackupRemoveDirectory = '' 15179860b2SJed Brown 167eca831cSJacob Faibussowitsch__global_divider_length = 93 177eca831cSJacob Faibussowitsch 187eca831cSJacob Faibussowitschdef get_global_divider_length(): 197eca831cSJacob Faibussowitsch """ 207eca831cSJacob Faibussowitsch Get the divider length for each banner in the form 217eca831cSJacob Faibussowitsch 227eca831cSJacob Faibussowitsch ==============================... (or ********************...) 237eca831cSJacob Faibussowitsch FOO BAR 247eca831cSJacob Faibussowitsch ==============================... 257eca831cSJacob Faibussowitsch """ 267eca831cSJacob Faibussowitsch return __global_divider_length 277eca831cSJacob Faibussowitsch 287eca831cSJacob Faibussowitschdef set_global_divider_length(new_len): 297eca831cSJacob Faibussowitsch """ 307eca831cSJacob Faibussowitsch Set the divider length for each banner in the form 317eca831cSJacob Faibussowitsch 327eca831cSJacob Faibussowitsch ==============================... (or ********************...) 337eca831cSJacob Faibussowitsch FOO BAR 347eca831cSJacob Faibussowitsch ==============================... 357eca831cSJacob Faibussowitsch """ 367eca831cSJacob Faibussowitsch global __global_divider_length 377eca831cSJacob Faibussowitsch old_len = __global_divider_length 387eca831cSJacob Faibussowitsch __global_divider_length = new_len 397eca831cSJacob Faibussowitsch return old_len 407eca831cSJacob Faibussowitsch 417eca831cSJacob Faibussowitschdef build_multiline_message(sup_title, text, divider_char = None, length = None, prefix = None, **kwargs): 427eca831cSJacob Faibussowitsch def center_line(line): 437eca831cSJacob Faibussowitsch return line.center(length).rstrip() 447eca831cSJacob Faibussowitsch 457eca831cSJacob Faibussowitsch if length is None: 467eca831cSJacob Faibussowitsch length = get_global_divider_length() 477eca831cSJacob Faibussowitsch if prefix is None: 487eca831cSJacob Faibussowitsch prefix = ' '*2 497eca831cSJacob Faibussowitsch 507eca831cSJacob Faibussowitsch kwargs.setdefault('break_on_hyphens',False) 517eca831cSJacob Faibussowitsch kwargs.setdefault('break_long_words',False) 527eca831cSJacob Faibussowitsch kwargs.setdefault('width',length-2) 537eca831cSJacob Faibussowitsch kwargs.setdefault('initial_indent',prefix) 547eca831cSJacob Faibussowitsch kwargs.setdefault('subsequent_indent',prefix) 557eca831cSJacob Faibussowitsch 567eca831cSJacob Faibussowitsch wrapped = [ 577eca831cSJacob Faibussowitsch line for para in text.splitlines() for line in textwrap.wrap(textwrap.dedent(para),**kwargs) 587eca831cSJacob Faibussowitsch ] 597eca831cSJacob Faibussowitsch if len(wrapped) == 1: 607eca831cSJacob Faibussowitsch # center-justify single lines, and remove the bogus prefix 617eca831cSJacob Faibussowitsch wrapped[0] = center_line(wrapped[0].lstrip()) 627eca831cSJacob Faibussowitsch if divider_char: 637eca831cSJacob Faibussowitsch # add the divider if we are making a message like 647eca831cSJacob Faibussowitsch # 657eca831cSJacob Faibussowitsch # ===================== 667eca831cSJacob Faibussowitsch # BIG SCARY TITLE 677eca831cSJacob Faibussowitsch # --------------------- <- divider_char is '-' 687eca831cSJacob Faibussowitsch # foo bar 697eca831cSJacob Faibussowitsch divider_char = str(divider_char) 707eca831cSJacob Faibussowitsch assert len(divider_char) == 1 717eca831cSJacob Faibussowitsch wrapped.insert(0, divider_char * length) 727eca831cSJacob Faibussowitsch if sup_title: 737eca831cSJacob Faibussowitsch # add the super title if we are making a message like 747eca831cSJacob Faibussowitsch # 757eca831cSJacob Faibussowitsch # ===================== 767eca831cSJacob Faibussowitsch # BIG SCARY TITLE <- sup_title is 'BIG SCARY TITLE' 777eca831cSJacob Faibussowitsch # --------------------- 787eca831cSJacob Faibussowitsch # foo bar 797eca831cSJacob Faibussowitsch # add the banner 807eca831cSJacob Faibussowitsch wrapped.insert(0, center_line(str(sup_title))) 817eca831cSJacob Faibussowitsch return '\n'.join(wrapped) 827eca831cSJacob Faibussowitsch 837eca831cSJacob Faibussowitschdef build_multiline_error_message(sup_title, text, **kwargs): 847eca831cSJacob Faibussowitsch kwargs.setdefault('divider_char', '-') 857eca831cSJacob Faibussowitsch kwargs.setdefault('length', get_global_divider_length()) 867eca831cSJacob Faibussowitsch 877eca831cSJacob Faibussowitsch if not text.endswith('\n'): 887eca831cSJacob Faibussowitsch text += '\n' 897eca831cSJacob Faibussowitsch 907eca831cSJacob Faibussowitsch banner_line = kwargs['length']*'*' 917eca831cSJacob Faibussowitsch return '\n'.join([ 927eca831cSJacob Faibussowitsch banner_line, 937eca831cSJacob Faibussowitsch build_multiline_message(sup_title, text, **kwargs), 947eca831cSJacob Faibussowitsch banner_line, 957eca831cSJacob Faibussowitsch '' # to add an additional newline at the end 967eca831cSJacob Faibussowitsch ]) 977eca831cSJacob Faibussowitsch 98179860b2SJed Brownclass Logger(args.ArgumentProcessor): 99179860b2SJed Brown '''This class creates a shared log and provides methods for writing to it''' 100179860b2SJed Brown defaultLog = None 101179860b2SJed Brown defaultOut = sys.stdout 102179860b2SJed Brown 103179860b2SJed Brown def __init__(self, clArgs = None, argDB = None, log = None, out = defaultOut, debugLevel = None, debugSections = None, debugIndent = None): 104179860b2SJed Brown args.ArgumentProcessor.__init__(self, clArgs, argDB) 105179860b2SJed Brown self.logName = None 106179860b2SJed Brown self.log = log 107179860b2SJed Brown self.out = out 108179860b2SJed Brown self.debugLevel = debugLevel 109179860b2SJed Brown self.debugSections = debugSections 110179860b2SJed Brown self.debugIndent = debugIndent 111179860b2SJed Brown self.getRoot() 112179860b2SJed Brown return 113179860b2SJed Brown 114179860b2SJed Brown def __getstate__(self): 115179860b2SJed Brown '''We do not want to pickle the default log stream''' 116179860b2SJed Brown d = args.ArgumentProcessor.__getstate__(self) 117b59d1e59SMatthew G. Knepley if 'logBkp' in d: 118b59d1e59SMatthew G. Knepley del d['logBkp'] 119179860b2SJed Brown if 'log' in d: 120179860b2SJed Brown if d['log'] is Logger.defaultLog: 121179860b2SJed Brown del d['log'] 122179860b2SJed Brown else: 123179860b2SJed Brown d['log'] = None 124179860b2SJed Brown if 'out' in d: 125179860b2SJed Brown if d['out'] is Logger.defaultOut: 126179860b2SJed Brown del d['out'] 127179860b2SJed Brown else: 128179860b2SJed Brown d['out'] = None 129179860b2SJed Brown return d 130179860b2SJed Brown 131179860b2SJed Brown def __setstate__(self, d): 132179860b2SJed Brown '''We must create the default log stream''' 133179860b2SJed Brown args.ArgumentProcessor.__setstate__(self, d) 134179860b2SJed Brown if not 'log' in d: 135179860b2SJed Brown self.log = self.createLog(None) 136179860b2SJed Brown if not 'out' in d: 137179860b2SJed Brown self.out = Logger.defaultOut 138179860b2SJed Brown self.__dict__.update(d) 139179860b2SJed Brown return 140179860b2SJed Brown 141179860b2SJed Brown def setupArguments(self, argDB): 142179860b2SJed Brown '''Setup types in the argument database''' 143179860b2SJed Brown import nargs 144179860b2SJed Brown 145179860b2SJed Brown argDB = args.ArgumentProcessor.setupArguments(self, argDB) 14603e6d329SSatish Balay argDB.setType('log', nargs.Arg(None, 'buildsystem.log', 'The filename for the log')) 147179860b2SJed Brown argDB.setType('logAppend', nargs.ArgBool(None, 0, 'The flag determining whether we backup or append to the current log', isTemporary = 1)) 148179860b2SJed Brown argDB.setType('debugLevel', nargs.ArgInt(None, 3, 'Integer 0 to 4, where a higher level means more detail', 0, 5)) 149179860b2SJed Brown argDB.setType('debugSections', nargs.Arg(None, [], 'Message types to print, e.g. [compile,link,hg,install]')) 150179860b2SJed Brown argDB.setType('debugIndent', nargs.Arg(None, ' ', 'The string used for log indentation')) 151179860b2SJed Brown argDB.setType('scrollOutput', nargs.ArgBool(None, 0, 'Flag to allow output to scroll rather than overwriting a single line')) 152179860b2SJed Brown argDB.setType('noOutput', nargs.ArgBool(None, 0, 'Flag to suppress output to the terminal')) 153179860b2SJed Brown return argDB 154179860b2SJed Brown 155179860b2SJed Brown def setup(self): 156179860b2SJed Brown '''Setup the terminal output and filtering flags''' 157179860b2SJed Brown self.log = self.createLog(self.logName, self.log) 158179860b2SJed Brown args.ArgumentProcessor.setup(self) 159179860b2SJed Brown 160179860b2SJed Brown if self.argDB['noOutput']: 161179860b2SJed Brown self.out = None 162179860b2SJed Brown if self.debugLevel is None: 163179860b2SJed Brown self.debugLevel = self.argDB['debugLevel'] 164179860b2SJed Brown if self.debugSections is None: 165179860b2SJed Brown self.debugSections = self.argDB['debugSections'] 166179860b2SJed Brown if self.debugIndent is None: 167179860b2SJed Brown self.debugIndent = self.argDB['debugIndent'] 168179860b2SJed Brown return 169179860b2SJed Brown 170179860b2SJed Brown def checkLog(self, logName): 171179860b2SJed Brown import nargs 172179860b2SJed Brown import os 173179860b2SJed Brown 174179860b2SJed Brown if logName is None: 175179860b2SJed Brown logName = nargs.Arg.findArgument('log', self.clArgs) 176179860b2SJed Brown if logName is None: 177179860b2SJed Brown if not self.argDB is None and 'log' in self.argDB: 178179860b2SJed Brown logName = self.argDB['log'] 179179860b2SJed Brown else: 180179860b2SJed Brown logName = 'default.log' 181179860b2SJed Brown self.logName = logName 182179860b2SJed Brown self.logExists = os.path.exists(self.logName) 183179860b2SJed Brown return self.logExists 184179860b2SJed Brown 185179860b2SJed Brown def createLog(self, logName, initLog = None): 186179860b2SJed Brown '''Create a default log stream, unless initLog is given''' 187179860b2SJed Brown import nargs 188179860b2SJed Brown 189179860b2SJed Brown if not initLog is None: 190179860b2SJed Brown log = initLog 191179860b2SJed Brown else: 192179860b2SJed Brown if Logger.defaultLog is None: 193179860b2SJed Brown appendArg = nargs.Arg.findArgument('logAppend', self.clArgs) 194179860b2SJed Brown if self.checkLog(logName): 195179860b2SJed Brown if not self.argDB is None and ('logAppend' in self.argDB and self.argDB['logAppend']) or (not appendArg is None and bool(appendArg)): 196c6ef1b5bSJed Brown Logger.defaultLog = open(self.logName, 'a') 197179860b2SJed Brown else: 198179860b2SJed Brown try: 199179860b2SJed Brown import os 200179860b2SJed Brown 201179860b2SJed Brown os.rename(self.logName, self.logName+'.bkp') 202c6ef1b5bSJed Brown Logger.defaultLog = open(self.logName, 'w') 203179860b2SJed Brown except OSError: 20415ac2963SJed Brown sys.stdout.write('WARNING: Cannot backup log file, appending instead.\n') 205c6ef1b5bSJed Brown Logger.defaultLog = open(self.logName, 'a') 206179860b2SJed Brown else: 207c6ef1b5bSJed Brown Logger.defaultLog = open(self.logName, 'w') 208179860b2SJed Brown log = Logger.defaultLog 209179860b2SJed Brown return log 210179860b2SJed Brown 211179860b2SJed Brown def closeLog(self): 212179860b2SJed Brown '''Closes the log file''' 213179860b2SJed Brown self.log.close() 214179860b2SJed Brown 215a75b4e77SMatthew G. Knepley def saveLog(self): 216dc0f114dSBarry Smith if self.debugLevel <= 3: return 2172d964b9fSJed Brown import io 218a75b4e77SMatthew G. Knepley self.logBkp = self.log 2192d964b9fSJed Brown self.log = io.StringIO() 220a75b4e77SMatthew G. Knepley 221a75b4e77SMatthew G. Knepley def restoreLog(self): 222dc0f114dSBarry Smith if self.debugLevel <= 3: return 223a75b4e77SMatthew G. Knepley s = self.log.getvalue() 224a75b4e77SMatthew G. Knepley self.log.close() 225a75b4e77SMatthew G. Knepley self.log = self.logBkp 226a75b4e77SMatthew G. Knepley del(self.logBkp) 227a75b4e77SMatthew G. Knepley return s 228a75b4e77SMatthew G. Knepley 229179860b2SJed Brown def getLinewidth(self): 230179860b2SJed Brown global LineWidth 231179860b2SJed Brown if not hasattr(self, '_linewidth'): 232179860b2SJed Brown if self.out is None or not self.out.isatty() or self.argDB['scrollOutput']: 233179860b2SJed Brown self._linewidth = -1 234179860b2SJed Brown else: 235179860b2SJed Brown if LineWidth == -1: 236179860b2SJed Brown try: 237179860b2SJed Brown import curses 238179860b2SJed Brown 239179860b2SJed Brown try: 240179860b2SJed Brown curses.setupterm() 241179860b2SJed Brown (y, self._linewidth) = curses.initscr().getmaxyx() 242179860b2SJed Brown curses.endwin() 243179860b2SJed Brown except curses.error: 244179860b2SJed Brown self._linewidth = -1 245179860b2SJed Brown except: 246179860b2SJed Brown self._linewidth = -1 247179860b2SJed Brown LineWidth = self._linewidth 248179860b2SJed Brown else: 249179860b2SJed Brown self._linewidth = LineWidth 250179860b2SJed Brown return self._linewidth 251179860b2SJed Brown def setLinewidth(self, linewidth): 252179860b2SJed Brown self._linewidth = linewidth 253179860b2SJed Brown return 254179860b2SJed Brown linewidth = property(getLinewidth, setLinewidth, doc = 'The maximum number of characters per log line') 255179860b2SJed Brown 256179860b2SJed Brown def checkWrite(self, f, debugLevel, debugSection, writeAll = 0): 257179860b2SJed Brown '''Check whether the log line should be written 258179860b2SJed Brown - If writeAll is true, return true 259179860b2SJed Brown - If debugLevel >= current level, and debugSection in current section or sections is empty, return true''' 260179860b2SJed Brown if not isinstance(debugLevel, int): 261179860b2SJed Brown raise RuntimeError('Debug level must be an integer: '+str(debugLevel)) 262179860b2SJed Brown if f is None: 263179860b2SJed Brown return False 264179860b2SJed Brown if writeAll: 265179860b2SJed Brown return True 266179860b2SJed Brown if self.debugLevel >= debugLevel and (not len(self.debugSections) or debugSection in self.debugSections): 267179860b2SJed Brown return True 268179860b2SJed Brown return False 269179860b2SJed Brown 270ce040abeSJacob Faibussowitsch def checkANSIEscapeSequences(self, ostream): 271ce040abeSJacob Faibussowitsch """ 272ce040abeSJacob Faibussowitsch Return True if the stream supports ANSI escape sequences, False otherwise 273ce040abeSJacob Faibussowitsch """ 274ce040abeSJacob Faibussowitsch try: 275ce040abeSJacob Faibussowitsch # _io.TextIoWrapper use 'name' attribute to store the file name 276ce040abeSJacob Faibussowitsch key = ostream.name 277ce040abeSJacob Faibussowitsch except AttributeError: 278ce040abeSJacob Faibussowitsch return False 279ce040abeSJacob Faibussowitsch 280ce040abeSJacob Faibussowitsch try: 281ce040abeSJacob Faibussowitsch return self._ansi_esc_seq_cache[key] 282ce040abeSJacob Faibussowitsch except KeyError: 283ce040abeSJacob Faibussowitsch pass # have not processed this stream before 284ce040abeSJacob Faibussowitsch except AttributeError: 285ce040abeSJacob Faibussowitsch # have never done this before 286ce040abeSJacob Faibussowitsch self._ansi_esc_seq_cache = {} 287ce040abeSJacob Faibussowitsch 288ce040abeSJacob Faibussowitsch is_a_tty = hasattr(ostream,'isatty') and ostream.isatty() 289ce040abeSJacob Faibussowitsch return self._ansi_esc_seq_cache.setdefault(key,is_a_tty and ( 290ce040abeSJacob Faibussowitsch sys.platform != 'win32' or os.environ.get('TERM','').startswith(('xterm','ANSI')) or 291ce040abeSJacob Faibussowitsch # Windows Terminal supports VT codes. 292ce040abeSJacob Faibussowitsch 'WT_SESSION' in os.environ or 293ce040abeSJacob Faibussowitsch # Microsoft Visual Studio Code's built-in terminal supports colors. 294ce040abeSJacob Faibussowitsch os.environ.get('TERM_PROGRAM') == 'vscode' 295ce040abeSJacob Faibussowitsch )) 296ce040abeSJacob Faibussowitsch 297179860b2SJed Brown def logIndent(self, debugLevel = -1, debugSection = None, comm = None): 298179860b2SJed Brown '''Write the proper indentation to the log streams''' 299179860b2SJed Brown import traceback 300179860b2SJed Brown 301179860b2SJed Brown indentLevel = len(traceback.extract_stack())-5 302179860b2SJed Brown for writeAll, f in enumerate([self.out, self.log]): 303179860b2SJed Brown if self.checkWrite(f, debugLevel, debugSection, writeAll): 304179860b2SJed Brown if not comm is None: 305179860b2SJed Brown f.write('[') 306179860b2SJed Brown f.write(str(comm.rank())) 307179860b2SJed Brown f.write(']') 308179860b2SJed Brown for i in range(indentLevel): 309179860b2SJed Brown f.write(self.debugIndent) 310179860b2SJed Brown return 311179860b2SJed Brown 312179860b2SJed Brown def logBack(self): 313179860b2SJed Brown '''Backup the current line if we are not scrolling output''' 314d1b3ee28SJacob Faibussowitsch if self.out is not None and self.linewidth > 0: 315179860b2SJed Brown self.out.write('\r') 316179860b2SJed Brown return 317179860b2SJed Brown 318179860b2SJed Brown def logClear(self): 319179860b2SJed Brown '''Clear the current line if we are not scrolling output''' 320ce040abeSJacob Faibussowitsch out,lw = self.out,self.linewidth 321ce040abeSJacob Faibussowitsch if out is not None and lw > 0: 322ce040abeSJacob Faibussowitsch out.write('\r\033[K' if self.checkANSIEscapeSequences(out) else ' '*lw) 323ce040abeSJacob Faibussowitsch try: 324ce040abeSJacob Faibussowitsch out.flush() 325ce040abeSJacob Faibussowitsch except AttributeError: 326ce040abeSJacob Faibussowitsch pass 327179860b2SJed Brown return 328179860b2SJed Brown 329ce040abeSJacob Faibussowitsch def logPrintDivider(self, single = False, length = None, **kwargs): 330ce040abeSJacob Faibussowitsch if length is None: 3317eca831cSJacob Faibussowitsch length = get_global_divider_length() 332ce040abeSJacob Faibussowitsch kwargs.setdefault('rmDir',False) 333ce040abeSJacob Faibussowitsch kwargs.setdefault('indent',False) 334ce040abeSJacob Faibussowitsch kwargs.setdefault('forceScroll',False) 335ce040abeSJacob Faibussowitsch kwargs.setdefault('forceNewLine',True) 336ce040abeSJacob Faibussowitsch divider = ('-' if single else '=')*length 337d1b3ee28SJacob Faibussowitsch return self.logPrint(divider, **kwargs) 338179860b2SJed Brown 339d1b3ee28SJacob Faibussowitsch def logPrintWarning(self, msg, title = None, **kwargs): 340d1b3ee28SJacob Faibussowitsch if title is None: 341d1b3ee28SJacob Faibussowitsch title = 'WARNING' 342d1b3ee28SJacob Faibussowitsch return self.logPrintBox(msg,title='***** {} *****'.format(title),**kwargs) 343d1b3ee28SJacob Faibussowitsch 344d1b3ee28SJacob Faibussowitsch def logPrintBox(self, msg, debugLevel = -1, debugSection = 'screen', indent = 1, comm = None, rmDir = 1, prefix = None, title = None): 345d1b3ee28SJacob Faibussowitsch if rmDir: 3467eca831cSJacob Faibussowitsch rmDir = build_multiline_message(title, self.logStripDirectory(msg), prefix=prefix) 3477eca831cSJacob Faibussowitsch msg = build_multiline_message(title, msg, prefix=prefix) 348179860b2SJed Brown self.logClear() 349ce040abeSJacob Faibussowitsch self.logPrintDivider(debugLevel = debugLevel, debugSection = debugSection) 350ce040abeSJacob Faibussowitsch self.logPrint(msg, debugLevel = debugLevel, debugSection = debugSection, rmDir = rmDir, forceNewLine = True, forceScroll = True, indent = 0) 351ce040abeSJacob Faibussowitsch self.logPrintDivider(debugLevel = debugLevel, debugSection = debugSection) 352179860b2SJed Brown return 353179860b2SJed Brown 354d1b3ee28SJacob Faibussowitsch def logStripDirectory(self,msg): 355d1b3ee28SJacob Faibussowitsch return msg.replace(RemoveDirectory,'') 356d1b3ee28SJacob Faibussowitsch 357179860b2SJed Brown def logClearRemoveDirectory(self): 358179860b2SJed Brown global RemoveDirectory 359179860b2SJed Brown global backupRemoveDirectory 360179860b2SJed Brown backupRemoveDirectory = RemoveDirectory 361179860b2SJed Brown RemoveDirectory = '' 362179860b2SJed Brown 363179860b2SJed Brown def logResetRemoveDirectory(self): 364179860b2SJed Brown global RemoveDirectory 365179860b2SJed Brown global backupRemoveDirectory 366179860b2SJed Brown RemoveDirectory = backupRemoveDirectory 367179860b2SJed Brown 368d15db81bSBarry Smith def logWrite(self, msg, debugLevel = -1, debugSection = None, forceScroll = 0, rmDir = 1): 369179860b2SJed Brown '''Write the message to the log streams''' 370b5f71184SBarry Smith '''Generally goes to the file but not the screen''' 371dc0f114dSBarry Smith if not msg: return 372179860b2SJed Brown for writeAll, f in enumerate([self.out, self.log]): 373179860b2SJed Brown if self.checkWrite(f, debugLevel, debugSection, writeAll): 374d1b3ee28SJacob Faibussowitsch if rmDir: 375d1b3ee28SJacob Faibussowitsch if isinstance(rmDir,str): 376ce040abeSJacob Faibussowitsch clean_msg = rmDir 377d1b3ee28SJacob Faibussowitsch else: 378ce040abeSJacob Faibussowitsch clean_msg = self.logStripDirectory(msg) 379ce040abeSJacob Faibussowitsch else: 380ce040abeSJacob Faibussowitsch clean_msg = msg 381ce040abeSJacob Faibussowitsch if not forceScroll and not writeAll and self.linewidth > 0: 382ce040abeSJacob Faibussowitsch self.logClear() 383ce040abeSJacob Faibussowitsch for ms in clean_msg.splitlines(): 384d1b3ee28SJacob Faibussowitsch f.write(ms[:self.linewidth]) 385179860b2SJed Brown else: 386*0e061800SBarry Smith if writeAll or not msg.startswith('TESTING:') or f.isatty(): 387179860b2SJed Brown if not debugSection is None and not debugSection == 'screen' and len(msg): 388179860b2SJed Brown f.write(str(debugSection)) 389179860b2SJed Brown f.write(': ') 390ce040abeSJacob Faibussowitsch f.write(msg if writeAll else clean_msg) 391179860b2SJed Brown if hasattr(f, 'flush'): 392179860b2SJed Brown f.flush() 393179860b2SJed Brown return 394179860b2SJed Brown 395d1b3ee28SJacob Faibussowitsch def logPrint(self, msg, debugLevel = -1, debugSection = None, indent = 1, comm = None, forceScroll = 0, rmDir = 1, forceNewLine = False): 396179860b2SJed Brown '''Write the message to the log streams with proper indentation and a newline''' 397b5f71184SBarry Smith '''Generally goes to the file and the screen''' 398179860b2SJed Brown if indent: 399179860b2SJed Brown self.logIndent(debugLevel, debugSection, comm) 400d15db81bSBarry Smith self.logWrite(msg, debugLevel, debugSection, forceScroll = forceScroll, rmDir = rmDir) 401179860b2SJed Brown for writeAll, f in enumerate([self.out, self.log]): 402179860b2SJed Brown if self.checkWrite(f, debugLevel, debugSection, writeAll): 403*0e061800SBarry Smith if forceNewLine or writeAll: 404179860b2SJed Brown f.write('\n') 405179860b2SJed Brown return 406179860b2SJed Brown 407179860b2SJed Brown def getRoot(self): 408179860b2SJed Brown '''Return the directory containing this module 409179860b2SJed Brown - This has the problem that when we reload a module of the same name, this gets screwed up 410179860b2SJed Brown Therefore, we call it in the initializer, and stash it''' 411179860b2SJed Brown #print ' In getRoot' 412179860b2SJed Brown #print hasattr(self, '__root') 413179860b2SJed Brown #print ' done checking' 414179860b2SJed Brown if not hasattr(self, '__root'): 415179860b2SJed Brown import os 416179860b2SJed Brown import sys 417179860b2SJed Brown 418179860b2SJed Brown # Work around a bug with pdb in 2.3 419179860b2SJed Brown if hasattr(sys.modules[self.__module__], '__file__') and not os.path.basename(sys.modules[self.__module__].__file__) == 'pdb.py': 420179860b2SJed Brown self.__root = os.path.abspath(os.path.dirname(sys.modules[self.__module__].__file__)) 421179860b2SJed Brown else: 422179860b2SJed Brown self.__root = os.getcwd() 423179860b2SJed Brown #print ' Exiting getRoot' 424179860b2SJed Brown return self.__root 425179860b2SJed Brown def setRoot(self, root): 426179860b2SJed Brown self.__root = root 427179860b2SJed Brown return 428179860b2SJed Brown root = property(getRoot, setRoot, doc = 'The directory containing this module') 429