]> SALOME platform Git repositories - tools/sat.git/commitdiff
Salome HOME
fix logger and runner.getAnswer
authorChristian Van Wambeke <christian.van-wambeke@cea.fr>
Thu, 17 May 2018 14:43:06 +0000 (16:43 +0200)
committerChristian Van Wambeke <christian.van-wambeke@cea.fr>
Thu, 17 May 2018 14:43:06 +0000 (16:43 +0200)
commands/clean.py
commands/find_duplicates.py
commands/prepare.py
sat
src/configManager.py
src/loggingSat.py
src/salomeTools.py
src/xsl/LOGO-SAT.png
src/xsl/LOGO-SAT_origin.png [new file with mode: 0644]
test/test_024_logging.py

index 47f8f99b5b58a3355f9c1b6d2f74a90bf40a3c1f..526840e7404d0994f3f619fb939d2bd2ae420d32 100644 (file)
@@ -129,24 +129,19 @@ The '--properties' options must have the following syntax:
                                                 options.sources_without_dev)
     
     if len(l_dir_to_suppress) == 0:
-        sat_command = ("sat -h clean")
-        msg = _("Nothing to suppress, Please specify what you want to suppress.")
-        logger.error(msg + "\nsee: '%s'\n" % sat_command)
-        return RCO.ReturnCode("KO", "specify what you want to suppress")
+        msg = _("Specify what you want to suppress in clean command.")
+        logger.error(msg + "\n(see: 'sat -h clean')")
+        return RCO.ReturnCode("KO", "to suppress in clean command")
     
     # Check with the user if he really wants to suppress the directories
-    if not runner.options.batch:
-        msg = _("Remove the following directories ?\n")
-        for directory in l_dir_to_suppress:
-            msg += "  %s\n" % directory
-        logger.info(msg)
-        rep = input(_("Are you sure you want to continue? [Yes/No] "))
-        if rep.upper() != _("YES"):
-            return RCO.ReturnCode("OK", "user do not want to continue")
-    
+    msg = UTS.red(_("Remove the following directories:\n"))
+    for directory in l_dir_to_suppress:
+        msg += "  %s\n" % directory 
+    if runner.getAnswer(msg[:-1]) == "No":
+        return RCO.ReturnCode("OK", "user do not want to continue")
+
     # Suppress the list of paths
-    suppress_directories(l_dir_to_suppress, logger)
-    
+    suppress_directories(l_dir_to_suppress, logger) 
     return RCO.ReturnCode("OK", "clean done")
     
 
index 3ddeb0379d592baeea72cb39e168dff2f9656ddb..2f3c586602bccba19ba5835cdd6f86ecca5cdda8 100644 (file)
@@ -26,10 +26,10 @@ from src.salomeTools import _BaseCommand
 
 
 default_extension_ignored = \
-    'html png txt js xml cmake gif m4 in pyo pyc doctree css'.split()
+  'html png txt js xml cmake gif m4 in pyo pyc doctree css'.split()
 
 default_files_ignored = \
-    '__init__.py Makefile.am VERSION build_configure README AUTHORS NEWS COPYING ChangeLog'.split()
+  '__init__.py Makefile.am VERSION build_configure README AUTHORS NEWS COPYING ChangeLog'.split()
 
 default_directories_ignored = []
 
index 9941c559cd4b58e9a663b1d13a321c4aeb1bac27..a73f417f995e0020c601736aa44d4b940d48c2e9 100644 (file)
@@ -82,7 +82,7 @@ class Command(_BaseCommand):
     products_infos = self.get_products_list(options, config)
 
     # Construct the arguments to pass to the clean, source and patch commands
-    args_appli = config.VARS.application + ' '
+    args_appli = config.VARS.application
     args_product_opt = '--products '
     if options.products:
         for p_name in options.products:
@@ -120,9 +120,9 @@ Use the --force_patch option to overwrite it.
                                                      logger)
 
     # Construct the final commands arguments
-    args_clean = args_appli + args_product_opt_clean + " --sources"
-    args_source = args_appli + args_product_opt  
-    args_patch = args_appli + args_product_opt_patch
+    args_clean = "%s --sources" % (args_product_opt_clean)
+    args_source = "%s" % (args_product_opt) 
+    args_patch = "%s" % (args_product_opt_patch)
 
     # If there is no more any product in the command arguments,
     # do not call the concerned command 
@@ -130,30 +130,34 @@ Use the --force_patch option to overwrite it.
     do_clean = not(oExpr.search(args_product_opt_clean))
     do_source = not(oExpr.search(args_product_opt))
     do_patch = not(oExpr.search(args_product_opt_patch))
-    
-    
+       
     # Initialize the results to Ok but nothing done status
     res_clean = RCO.ReturnCode("OK", "nothing done")
     res_source = RCO.ReturnCode("OK", "nothing done")
     res_patch = RCO.ReturnCode("OK", "nothing done")
 
-    # return res_clean + res_source + res_patch
-
     # Call the commands using the API
     if do_clean:
         msg = _("Clean the source directories ...")
-        logger.info(msg)
-        DBG.tofix("args_clean and TODO remove returns", args_clean, True)
-        res_clean = runner.getCommand("clean").run(args_clean)
-        return res_clean + res_source + res_patch
+        logger.info(msg + "(%s)" % args_clean)
+        mCmd = self.getMicroCommand("clean", args_appli)
+        res_clean = mCmd.run(args_clean)
+        logger.warning(str(res_clean))
+        return res_clean # TODO debug remove that
+        
     if do_source:
         msg = _("Get the sources of the products ...")
-        logger.debug(msg)
-        res_source = runner.getCommand("source").run(args_source)
+        logger.info(msg + "(%s)" % args_source)
+        mCmd = self.getMicroCommand("source", args_appli)
+        res_source = mCmd.run(args_source)
+        logger.warning(str(res_source))
+        
     if do_patch:
         msg = _("Patch the product sources (if any) ...")
-        logger.debug(msg)
-        res_patch = runner.getCommand("patch").run(args_patch)
+        logger.info(msg + "(%s)" % args_patch)
+        mCmd = self.getMicroCommand("patch", args_appli)
+        res_patch = mCmd.run(args_patch)
+        logger.warning(str(res_patch))
     
     return res_clean + res_source + res_patch
 
diff --git a/sat b/sat
index f36b1cbca68697781fc2186598134f1edfddadfe..fec31e292804f50272e05b942f6b5a2646318eb0 100755 (executable)
--- a/sat
+++ b/sat
@@ -66,7 +66,7 @@ if __name__ == "__main__":
     except Exception as e:
       # error as may be unknown problem
       # verbose debug message with traceback if developers
-      msg = "Exception raised for execute_cli(%s):\n" % args
+      msg = "Exception raised for execute_cli (%s):\n" % " ".join(args)
       logger.critical(DBG.format_color_exception(msg)) 
       logger.close()
       sys.exit(KOSYS)
index bf8d26a59b51956b3dec8a12e044153e24712ad1..4cb62ee0e01571ab85c67afe5526aade49626242 100644 (file)
@@ -162,7 +162,9 @@ class ConfigManager:
         return var
 
     def get_command_line_overrides(self, options, sections):
-        """get all the overwrites that are in the command line
+        """get all the overwrites that are in the command line.
+        When there are no options or not the overwrite option, 
+        return an empty list
         
         :param options:
           The options from salomeTools class initialization 
@@ -170,8 +172,7 @@ class ConfigManager:
         :param sections: (str) The config section to overwrite.
         :return: (list) The list of all the overwrites to apply.
         """
-        # when there are no options or not the overwrite option, 
-        # return an empty list
+        # DBG.write("get_command_line_overrides options", options)
         if options is None or options.overwrite is None:
             return []
         
@@ -336,7 +337,7 @@ class ConfigManager:
             cp = cfg.PATHS.APPLICATIONPATH
             PYCONF.streamOpener = ConfigOpener(cp)
             do_merge = True
-            aFile = application + '.pyconf'
+            aFile = application.replace(" ", "") + '.pyconf'
             try:
               application_cfg = PYCONF.Config(aFile)
             except IOError as e:
index 25220affa316d6bf455f84b2675240d84f898ab9..2cdc1859ce18650159847313bf560c8800254387 100755 (executable)
@@ -80,7 +80,7 @@ def indentUnittest(msg, prefix=" | "):
 
 def log(msg, force=False):
   """elementary log when no logging.Logger yet"""
-  prefix = "%s.log: " % _name
+  prefix = "---- %s.log: " % _name
   nb = len(prefix)
   if _verbose or force: 
     print(prefix + indent(msg, nb))
@@ -114,6 +114,7 @@ def getStrHandler(handler):
   
 def getStrShort(msg):
   """Returns short string for msg (as first caracters without line feed"""
+  # log("getStrShort " + str(msg), True)
   res = msg.replace("\n", "//")[0:30]
   return res
   
@@ -165,9 +166,9 @@ class LoggerSat(LOGI.Logger):
     """
     if self.closed: 
       raise Exception("logger closed yet: %s" % self)
-    log("close stuff logger %s" % self, True) # getStrDirLogger(self)
+    log("close stuff logger %s" % self) # getStrDirLogger(self)
     for handl in self.handlers: 
-      log("close stuff handler %s" % getStrHandler(handl), True)
+      log("close stuff handler %s" % getStrHandler(handl))
       handl.close() # Tidy up any resources used by the handler.
     # todo etc
     self.closed = True # done at end sat, flushed closed xml files.
@@ -190,9 +191,9 @@ class LoggerSat(LOGI.Logger):
     | use the keyword argument exc_info with a true value
     | >> logger.trace("Houston, we have a %s", "long trace to follow")
     """
-    log("trace stuff logger %s dateLogger %s", True)
-    if self.isEnabledFor(self._TRACE):
-        self._log(self._TRACE, msg, args, **kwargs)
+    log("trace stuff logger '%s' msg '%s...'" % (self.name, getStrShort(msg)), True)
+    if self.isEnabledFor(_TRACE):
+        self._log(_TRACE, msg, args, **kwargs)
 
   def xx_isEnabledFor(self, level):
     """
@@ -340,7 +341,7 @@ class XmlHandler(BufferingHandler):
     config = self._config
     
     # TODO for degug
-    log("XmlHandler to xml file\n%s" % PP.pformat(getListOfStrLogRecord(self.buffer)), True)
+    log("XmlHandler to xml file\n%s" % PP.pformat(getListOfStrLogRecord(self.buffer)))
     
     if os.path.exists(targetFile):
       msg = "XmlHandler target file %s existing yet" % targetFile
@@ -403,7 +404,7 @@ def initLoggerAsUnittest(logger, fmt=None, level=None):
     logger.setLevel(logger.DEBUG)
 
 
-def setFileHandler(logger, config):
+def setFileHandler(cmdInstance):
   """
   add file handler to logger to set log files
   for salometools command. 
@@ -418,10 +419,13 @@ def setFileHandler(logger, config):
   |   ~/LOGS/OUT/micro_20180510_140607_clean_lenovo.txt
   |   etc.
   """
+  logger = cmdInstance.getLogger()
+  config = cmdInstance.getConfig()
+  
   #import src.debug as DBG # avoid cross import
-  log("setFileHandler %s" % logger, True)
-  log("setFileHandler config\n%s" % PP.pformat(dict(config.VARS)), True)
-  log("setFileHandler TODO set log_dir config.LOCAL.log_dir", True)
+  log("setFileHandler %s" % logger)
+  log("setFileHandler config\n%s" % PP.pformat(dict(config.VARS)))
+  log("setFileHandler TODO set log_dir config.LOCAL.log_dir")
   
   log_dir = "TMP" # TODO for debug config.LOCAL.log_dir # files xml
   log_dir_out = os.path.join(log_dir, "OUT") # files txt
@@ -429,14 +433,22 @@ def setFileHandler(logger, config):
   UTS.ensure_path_exists(log_dir_out)
   datehour = config.VARS.datehour
   cmd = config.VARS.command
+  fullNameCmd = cmdInstance.getFullNameStr()
   hostname = config.VARS.hostname
   nameFileXml = "%s_%s_%s.xml" % (datehour, cmd, hostname)
   nameFileTxt = "%s_%s_%s.txt" % (datehour, cmd, hostname)
   fileXml = os.path.join(log_dir, nameFileXml)
   fileTxt = os.path.join(log_dir_out, nameFileTxt)
   
+  # precaution
+  lastCmd = cmdInstance.getFullNameList()[-1]
+  if cmd != lastCmd:
+    msg = "setFileHandler '%s' command name incoherency in config '%s'" % (fullNameCmd, cmd)
+    logger.critical(msg)
+
   nbhandl = len(logger.handlers) # number of current handlers
   if nbhandl == 1: # first main command
+    log("setFileHandler '%s' main command" % fullNameCmd, True)
     # Logging vers file xml
     
     handler = XmlHandler(1000) # log outputs in memory
@@ -462,10 +474,10 @@ def setFileHandler(logger, config):
     handler.setFormatter(formatter)
     logger.addHandler(handler)
 
-  if nbhandl > 1: # secondary micro command
-    log("setFileHandler micro command %s" % config.VARS.command, True)
+  elif nbhandl > 1: # secondary micro command
+    log("TODO setFileHandler '%s' micro command" % fullNameCmd, True)
    
-  log("setFileHandler %s" % logger, True)
+  log("setFileHandler %s" % logger)
 
 
 def getDefaultLogger():
index 795a1dc1dca7836615703a48a8fe6fb08f751b33..0be634da05330894a88bf154d209ea4e348cde75 100755 (executable)
@@ -159,7 +159,7 @@ class _BaseCommand(object):
     """
   
     # supposed never seen, set "config", "prepare"... in inherited commands
-    name = "salomeTools"
+    name = "NoName"
     
     def __init__(self, runner):
         # runner (as caller) usually as Sat instance
@@ -169,6 +169,38 @@ class _BaseCommand(object):
         # logger (from caller) usually as Sat instance logger, but sometimes local value
         self._logger = runner.logger
         self._options = None
+        self._fullName = [] # example '[prepare','clean'] when micro command 'clean' of 'prepare'
+        
+    def initFullName(self, parentFullName=[]):
+        """
+        initialize full name of command instance, one call only.
+        parentFullName supposedly as list (as parent full name)
+
+        | example values of self._full name:
+        | ['prepare'] if main command 'prepare'. 
+        | ['prepare', 'clean'] if micro command 'clean' from command 'prepare'. 
+        """
+        # DBG.write("initFullName", (self._fullName, parentFullName))
+        if len(self._fullName) != 0: # ne call only
+          raise Exception("full name initialized yet '%s'" % self.getFullNameStr())
+        if len(self._fullName) > 10: # Houston problem
+          raise Exception("full name too long '%s'" % self.getFullNameStr())
+        if type(parentFullName) == str:
+          pfn = parentFullName.split("_") # if from  string 'prepare_clean'
+        elif type(parentFullName) == list:
+          pfn = list(parentFullName) # make copy precaution
+        else:
+          raise Exception("type parent full name unexpected '%s'" % parentFullName)
+        self._fullName = pfn + [self.name] # make copy precaution
+        DBG.write("initFullName", self._fullName)
+          
+    def getFullNameStr(self):
+        """returns 'prepare_clean' when micro command 'clean' of 'prepare'"""
+        return "_".join(self._fullName)
+  
+    def getFullNameList(self):
+        """returns precaution copy as list of self._fullName"""
+        return list(self._fullName)
         
     def getClassName(self):
         """
@@ -182,6 +214,33 @@ class _BaseCommand(object):
         tmp = PP.pformat(self.__dict__)
         res = "%s(\n %s)\n" % (self.getClassName(), tmp[1:-1])
         return res
+        
+    def getMicroCommand(self, nameCommandToLoad, nameAppliToLoad):
+        """
+        get micro command instance from current command instance
+        returns inherited instance of Command(_BaseCmd) for command 'name'
+        if module not loaded yet, load it.
+        """
+        # create/get dynamically the command instance to call its 'run' method
+        runner = self.getRunner()
+        options = runner.getOptions() # generic main options
+             
+        # load micro command config
+        cfgMgr = CFGMGR.ConfigManager(self)
+        DBG.write("getMicroCommand nameCommandToLoad '%s'" % nameCommandToLoad, nameAppliToLoad)
+        config = cfgMgr.get_config(nameAppliToLoad, options, nameCommandToLoad, datadir=None)
+        
+        cmdInstance = runner.getCommand(nameCommandToLoad)
+        
+        # some initialisation stuff
+        cmdInstance.initFullName(self.getFullNameList()) # as micro command
+        cmdInstance.setConfig(config) # micro command config
+        cmdInstance.setOptions(options)
+        
+        import src.loggingSat as LOG # avoid cross import
+        LOG.setFileHandler(cmdInstance)
+        
+        return cmdInstance
 
     def run(self, cmd_arguments):
         """
@@ -194,18 +253,24 @@ class _BaseCommand(object):
         """set logger for run command"""
         if self._logger is not None:
           # supposed logger.debug for future
-          self._logger.warning("change logger for %s, are you sure" % self.getClassName())
+          self._logger.warning("change logger for %s, are you sure" % self.getFullNameStr())
         self._logger = logger
             
     def getLogger(self):
         if self._logger is None:
-          raise Exception("%s instance needs self._logger not None, fix it." % self.getClassName())
+          raise Exception("%s instance needs self._logger not None, fix it." % self.getFullNameStr())
         else:
           return self._logger
 
+    def setOptions(self, options):
+        if self._options is None:
+          self._options = options
+        else:
+          raise Exception("%s command instance have options yet, Fix it." % self.getFullName())
+
     def getOptions(self):
         if self._options is None:
-          raise Exception("%s instance needs self._option not None, fix it." % self.getClassName())
+          raise Exception("%s instance needs self._option not None, fix it." % self.getFullNameStr())
         else:
           return self._options
     
@@ -217,19 +282,34 @@ class _BaseCommand(object):
 
     def getRunner(self):
         if self._runner is None:
-          raise Exception("%s instance needs self.runner not None, fix it." % self.getClassName())
+          raise Exception("%s instance needs self.runner not None, fix it." % self.getFullNameStr())
         else:
           return self._runner
 
-    def getConfig(self):
+    def getConfigObsolete(self):
         """
         supposedly (for now) no multiply local config(s)
         only one config in runner.config
         may be some for future...
         """
         if self._runner.config is None:
-          self._logger.error("%s instance have runner.config None, fix it." % self.getClassName())
+          self._logger.error("%s command instance have runner.config None, Fix it." % self.getFullNameStr())
         return self._runner.config
+
+    def getConfig(self):
+        """
+        supposedly  multiply local config(s)
+        only one config for each command instance
+        """
+        if self._config is None:
+          raise Exception("%s command instance have config None, Fix it." % self.getFullNameStr())
+        return self._config
+        
+    def setConfig(self, config):
+        if self._config is None:
+          self._config = config
+        else:
+          raise Exception("%s command instance have config yet, Fix it." % self.getFullName())
       
     def get_products_list(self, options, config):
         return CFGMGR.get_products_list(options, config)
@@ -245,14 +325,16 @@ class _BaseCommand(object):
         smart parse command arguments skip
         first argument name appli to load, if present
         """
+        verb = False
         argList = self.assumeAsList(cmd_arguments)
-        DBG.write("%s.Command arguments" % self.name, argList)
+        fullName = self.getFullNameStr()
+        DBG.write("%s.Command arguments" % fullName, argList, verb)
         commandOptions, remaindersArgs = self.getParser().parse_args(argList)
-        DBG.write("%s.Command options" % self.name, commandOptions)
-        DBG.write("%s.Command remainders arguments" % self.name, remaindersArgs)
+        DBG.write("%s.Command options" % fullName, commandOptions, verb)
+        DBG.write("%s.Command remainders arguments" % fullName, remaindersArgs, verb)
         if remaindersArgs != []:
-          self.getLogger().error("%s.Command have unknown remainders arguments:\n%s\n" % \
-                                 (self.name, remaindersArgs))
+          msg = "%s.Command have unknown remainders arguments:\n(%s)" % (fullName, " ".join(remaindersArgs))
+          self.getLogger().error(msg)
         return commandOptions, remaindersArgs
     
     def description(self):
@@ -292,6 +374,7 @@ class _BaseCommand(object):
         # description of the command options
         msg += self.getParser().get_help() + "\n"
         return msg
+        
 
 ########################################################################
 # Sat class
@@ -315,7 +398,7 @@ class Sat(object):
         self.config = None # the config that will be read using pyconf module
         self.logger = logger # the logger that will be use
         self.arguments = None # args are postfixes options: args[0] is the 'commands' command
-        self.options = None # the options passed to salomeTools
+        self.options = None # the main generic options passed to salomeTools
         
         # the directory that contain all the external 
         # data (like software pyconf and software scripts)
@@ -354,6 +437,9 @@ class Sat(object):
     def getConfig(self):
         return self.config
         
+    def getOptions(self):
+        return self.options
+        
     def assumeAsList(self, strOrList):
         return assumeAsList(strOrList)
 
@@ -444,28 +530,35 @@ class Sat(object):
         # if the help option has been called, print command help and returns
         if self.options.help:
             self.print_help()
-            return RCO.ReturnCode("OK", "Option --help")
+            return RCO.ReturnCode("OK", "Option --help") # and returns
        
         self.nameCommandToLoad, self.nameAppliToLoad, self.commandArguments = \
              self.getCommandAndAppli(remainderArgs)
              
-        cfgManager = CFGMGR.ConfigManager(self)
-        self.config = cfgManager.get_config(
-                        application=self.nameAppliToLoad,
-                        options=self.options,
-                        command=self.nameCommandToLoad,
-                        datadir=None)
+        cfgMgr = CFGMGR.ConfigManager(self)
+        # as main config
+        config = cfgMgr.get_config(self.nameAppliToLoad, self.options, self.nameCommandToLoad, datadir=None)
+        self.config = config # runner.config main config 
         
         # create/get dynamically the command instance to call its 'run' method
         cmdInstance = self.getCommand(self.nameCommandToLoad)
+        
+        # some initialisation stuff
+        cmdInstance.initFullName() # as main command
+        cmdInstance.setConfig(config) 
         import src.loggingSat as LOG # avoid cross import
-        LOG.setFileHandler(self.getLogger(), self.getConfig())
+        LOG.setFileHandler(cmdInstance)
         
-        # Run the command using the arguments
+        # Run the main command using the remainders command arguments
         returnCode = cmdInstance.run(self.commandArguments)
+        
         return returnCode
         
     def getCommandAndAppli(self, arguments):
+        """
+        returns name command to load and name appli to load
+        and command to load remainders arguments
+        """
         args = self.assumeAsList(arguments)
         namecmd, nameAppli, remainderArgs = None, None, []
         iremain = 0
@@ -480,8 +573,7 @@ class Sat(object):
         remainderArgs = args[iremain:]
         res = (namecmd, nameAppli, remainderArgs)
         DBG.write("getCommandAndAppli", res)
-        return res
-        
+        return res      
       
     def get_help(self):
         """get general help colored string"""
@@ -515,6 +607,29 @@ class Sat(object):
         msg = "<header>Version:<reset> " + version
         return msg
    
+    def getConfirmMode(self):
+        return False
+    
+    def getBatchMode(self):
+        return True
+        
+    def getAnswer(self, msg):
+        """
+        question and user answer (in console) if confirm mode and not batch mode
+        returns 'YES' or 'NO' if confirm mode and not batch mode
+        returns 'YES' if batch mode
+        """
+        if self.getConfirmMode() and not self.getBatchMode():       
+          self.getLogger().info(msg)
+          rep = input(_("Are you sure you want to continue? [yes/no]"))
+          if rep.upper() == _("YES"):
+            return "YES"
+          else:
+            return "NO"
+        else:
+          self.getLogger().info(msg)
+          self.getLogger().info("<green>YES<reset> (as automatic answer)")
+          return "YES"
        
 
 
index eb27403e88143acc65d0c8c055bbd04937d83503..34f472944d32cb028b7b78bed551e5f3a399f06a 100644 (file)
Binary files a/src/xsl/LOGO-SAT.png and b/src/xsl/LOGO-SAT.png differ
diff --git a/src/xsl/LOGO-SAT_origin.png b/src/xsl/LOGO-SAT_origin.png
new file mode 100644 (file)
index 0000000..ff019cb
Binary files /dev/null and b/src/xsl/LOGO-SAT_origin.png differ
index 3102386b631d063b18e8c21327bcbfb452ead446..4f37c60516aa9db0d35e43fd69c2c176e7ea78c8 100755 (executable)
@@ -57,6 +57,8 @@ import src.debug as DBG
 
 verbose = False #True
 
+_TRACE = LOGI.INFO - 2 # just below info
+
 class LoggerSat(LOGI.Logger):
   """
   Elementary prototype for logger sat
@@ -68,15 +70,13 @@ class LoggerSat(LOGI.Logger):
   see: /usr/lib64/python2.7/logging/xxx__init__.py etc.
   """
   
-  _TRACE = LOGI.INFO - 2 # just below
-  
   def __init__(self, name, level=LOGI.INFO):
     """
     Initialize the logger with a name and an optional level.
     """
     super(LoggerSat, self).__init__(name, level)
-    LOGI.addLevelName(self._TRACE, "TRACE")
-    # LOGI.TRACE = self._TRACE # only for coherency,
+    LOGI.addLevelName(_TRACE, "TRACE")
+    # LOGI.TRACE = _TRACE # only for coherency,
     
   def trace(self, msg, *args, **kwargs):
     """
@@ -87,8 +87,8 @@ class LoggerSat(LOGI.Logger):
 
     logger.trace("Houston, we have a %s", "long trace to follow")
     """
-    if self.isEnabledFor(self._TRACE):
-        self._log(self._TRACE, msg, args, **kwargs)
+    if self.isEnabledFor(_TRACE):
+        self._log(_TRACE, msg, args, **kwargs)
 
 class TestCase(unittest.TestCase):
   "Test the debug.py"""