coriolis/crlcore/python/helpers/io.py

230 lines
7.7 KiB
Python

# -*- mode:Python -*-
#
# This file is part of the Coriolis Software.
# Copyright (c) Sorbonne Université 2012-2021, All Rights Reserved
#
# +-----------------------------------------------------------------+
# | C O R I O L I S |
# | Alliance / Hurricane Interface |
# | |
# | Author : Jean-Paul Chaput |
# | E-mail : Jean-Paul.Chaput@lip6.fr |
# | =============================================================== |
# | Python : "./crlcore/helpers/io.py" |
# +-----------------------------------------------------------------+
import sys
import os
import os.path
import re
import traceback
from .. import Cfg
from ..Hurricane import UpdateSession
from ..Viewer import Graphics, ErrorWidget
def textStackTrace ( trace, showIndent=True, scriptPath=None ):
indent = ''
if showIndent: indent = ' '
s = ''
if scriptPath:
if len(scriptPath) > 100:
filename = scriptPath[-100:]
filename = '.../' + filename[ filename.find('/')+1 : ]
if showIndent: s += '[ERROR] '
s += 'An exception occured while loading the Python script module:\n'
s += indent + '\"{}\"\n' % (filename)
s += indent + 'You should check for simple python errors in this module.\n\n'
s += indent + 'Python stack trace:\n'
maxdepth = len( trace )
for depth in range( maxdepth ):
filename, line, function, code = trace[ maxdepth-depth-1 ]
if len(filename) > 58:
filename = filename[-58:]
filename = '.../' + filename[ filename.find('/')+1 : ]
#s += indent + '[%02d] %45s:%-5d in \"{}()\"' % ( maxdepth-depth-1, filename, line, function )
s += indent + '#{} in {:>25}() at {}:{}\n'.format( depth, function, filename, line )
return s
def showStackTrace ( trace ):
print( textStackTrace( trace, True ))
return
def textPythonTrace ( scriptPath=None, e=None, tryContinue=True ):
s = ''
if scriptPath:
if len(scriptPath) > 100:
filename = scriptPath[-100:]
filename = '.../' + filename[ filename.find('/')+1 : ]
else:
filename = scriptPath
s += '[ERROR] An exception occured while loading the Python script module:\n'
s += ' \"{}\"\n'.format(filename)
s += ' You should check for simple python errors in this module.\n'
if isinstance(e,ErrorMessage):
trace = e.trace
s += textStackTrace( trace )
if e:
s += ' Error was:\n'
s += ' {}\n'.format(e)
else:
#trace = traceback.extract_tb( sys.exc_info()[2] )
print( traceback.format_exc() )
if tryContinue:
s += ' Trying to continue anyway...'
return s
def showPythonTrace ( scriptPath=None, e=None, tryContinue=True ):
print( textPythonTrace( scriptPath, e, tryContinue ))
return
# -------------------------------------------------------------------
# Class : "ErrorMessage".
class ErrorMessage ( Exception ):
def __init__ ( self, code, *arguments ):
self.scriptPath = None
self.trace = traceback.extract_stack()
self.code = code
self.errors = [ 'Malformed call to ErrorMessage().'
, 'args:"{}"'.format(arguments) ]
if not isinstance(self.code,int):
self.errors = [ 'Malformed call to ErrorMessage(), first argument (code) must be an integer.'
, 'code:"{}"'.format(code)
, 'args:"{}"'.format(arguments) ]
return
text = None
if len(arguments) == 1:
if isinstance(arguments[0],Exception): text = str(arguments[0]).split('\n')
else:
self.errors = arguments[0]
elif len(arguments) > 1:
sys.stdout.flush()
text = list(arguments)
if text:
self.errors = []
while len(text) == 0: del text[0]
lstrip = 0
if text[0].startswith('[ERROR]'): lstrip = 8
for line in text:
if line[0:lstrip] == ' '*lstrip or \
line[0:lstrip-1] == '[ERROR]':
self.errors += [ line[lstrip:] ]
else:
self.errors += [ line.lstrip() ]
sys.stdout.flush()
return
def __str__ ( self ):
if not isinstance(self.errors,list):
return "[ERROR] %s" % self.errors
formatted = "\n"
for i in range(len(self.errors)):
if i == 0: formatted += "[ERROR] %s" % self.errors[i]
else: formatted += " %s" % self.errors[i]
if i+1 < len(self.errors): formatted += "\n"
return formatted
def getLinesAsString ( self ):
if not isinstance(self.errors,list): return self.errors
lines = ''
for line in self.errors: lines += line + '\n'
return lines
def addMessage ( self, message ):
if not isinstance(self.errors,list):
self.errors = [ self.errors ]
if isinstance(message,list):
for line in message:
self.errors += [ line ]
else:
self.errors += [ message ]
return
def terminate ( self ):
print( self )
sys.exit( self.code )
@staticmethod
def show ( code, *arguments ):
e = ErrorMessage( code, *arguments )
if not Graphics.get().isEnabled():
raise e
tryCont = ErrorWidget.run( e.getLinesAsString()
, textStackTrace( e.trace, False, e.scriptPath ))
if not tryCont: raise e
return
# -------------------------------------------------------------------
# Function : "catch()".
#
# Try to smartly display any exception on the TTY and the graphic
# display, if available.
def catch ( errorObject ):
if isinstance(errorObject,ErrorMessage):
em = errorObject
else:
em = ErrorMessage( 2, errorObject )
em.trace = traceback.extract_tb( sys.exc_info()[2] )
#em.scriptPath = __file__
print( em )
print( textStackTrace( em.trace, True, em.scriptPath ))
if Graphics.get().isEnabled():
ErrorWidget.run( em.getLinesAsString()
, textStackTrace( em.trace, False, em.scriptPath ))
if UpdateSession.getStackSize() > 0: UpdateSession.close()
return
# -------------------------------------------------------------------
# Class : "WarningMessage".
class WarningMessage ( Exception ):
def __init__ ( self, message ):
self._warnings = message
return
def __str__ ( self ):
if not isinstance(self._warnings,list):
return "[WARNING] %s" % self._warnings
formatted = "\n"
for i in range(len(self._warnings)):
if i == 0: formatted += "[WARNING] %s" % self._warnings[i]
else: formatted += " %s" % self._warnings[i]
if i+1 < len(self._warnings): formatted += "\n"
return formatted
# -------------------------------------------------------------------
# Function : "vprint()".
#
# Small wrap around print to make use of the verbosity levels.
def isVL ( level ):
confLevel = 0
if Cfg.getParamBool('misc.verboseLevel1').asBool(): confLevel = 1
if Cfg.getParamBool('misc.verboseLevel2').asBool(): confLevel = 2
#print( 'level {} <= confLevel {}'.format(level,confLevel))
return level <= confLevel
def vprint ( level, message ):
if isVL(level): print( message )
return