Source code for BasicTools.Helpers.BaseOutputObject

# -*- coding: utf-8 -*-
#
# This file is subject to the terms and conditions defined in
# file 'LICENSE.txt', which is part of this source code package.
#

""" Base object to Help output

"""
from __future__ import print_function
import sys
import time
import inspect
from functools import wraps

_startTime = time.time()
useDifferentialTime = True
useFroze_itDecorator = False

from BasicTools.Helpers.TextFormatHelper import TFormat

[docs]def ResetStartTime(): """ Function to reset the start time of a program. """ global _startTime _startTime = time.time()
[docs]def SetUseDifferentialTime(val): """ Function to set the printing format :param [val]: True to print the time from the begining of the program or False to print the current time, defaults to [True] :type [val]: [Bool] """ global useDifferentialTime useDifferentialTime = val
##https://stackoverflow.com/questions/3603502/prevent-creating-new-attributes-outside-init ##https://hynek.me/articles/hasattr/ sentinel = object() ## for the moment if a class is frozen no heritage is possible ... working on a solution
[docs]def froze_it(cls): """ Decorator to make the class immutable (no more attributes can be added after initialization) For the moment if a class is frozen no heritage is possible. """ if not useFroze_itDecorator: setattr(cls, "UnFrozen", lambda x: None ) setattr(cls, "IsFrozen", lambda x: False ) return cls cls.__frozen = False def frozensetattr(self, key, value): y = getattr(self, key, sentinel) if self.__frozen and y is sentinel: raise(Exception("Class {} is frozen. Cannot set {} = {}" .format(cls.__name__, key, value))) else: object.__setattr__(self, key, value) def init_decorator(func): @wraps(func) def wrapper(self, *args, **kwargs): func(self, *args, **kwargs) def UnFrozen(): self.__frozen = False setattr(self, "UnFrozen", UnFrozen) def IsFrozen(): return self.__frozen setattr(self, "IsFrozen", IsFrozen) self.__frozen = True return wrapper cls.__setattr__ = frozensetattr cls.__init__ = init_decorator(cls.__init__) return cls
[docs]class BaseOutputObject(object): """ Base class for almost all the classes in BasicTools. The principal functionality of this class is to handle output to the console with different level of verbosity. the user can change verbose level for a specific instance or to all the instances in a program. """ __globalDebugMode = False __verboseLevel = 1 # constants # please do not change this values RETURN_SUCCESS = 0 RETURN_FAIL = 1 RETURN_FAIL_EXTERNAL_TOOL = 2 def __init__(self, other = None): super(BaseOutputObject,self).__init__() if other is not None: self.__classDebugMode = other.__classDebugMode else: self.__classDebugMode = False #only for debuging self.desc =""
[docs] @classmethod def SetVerboseLevel(cls,level): BaseOutputObject.__verboseLevel = level
[docs] @classmethod def GetVerboseLevel(cls): return BaseOutputObject.__verboseLevel
[docs] @classmethod def SetGlobalDebugMode(cls, mode = True): BaseOutputObject.__globalDebugMode = mode
[docs] @classmethod def IsGlobalDebugMode(cls): return BaseOutputObject.__globalDebugMode
[docs] def SetInstanceDebugMode(self, mode = True): self.__classDebugMode = mode
[docs] def PrintProgress(self,val, maxx = 100,minn= 0): per = (float(val) -minn)*100/(maxx-minn) if per == round(per): self.Print(str(round(per)) +"%")
[docs] def PrintDebug(self, mess): self.PrintInternal( mess, 3)
[docs] def PrintVerbose(self, mess): self.PrintInternal(mess, 2)
[docs] def Print(self, mess): self.PrintInternal(mess, 1)
[docs] def PrintError(self, mess): self.PrintInternal(TFormat.InRed("Error: ") + str(mess), 1)
[docs] def InDebugMode(self): return (BaseOutputObject.__globalDebugMode or self.__classDebugMode)
[docs] @classmethod def Print2(cls,mess): a = BaseOutputObject() a.PrintInternal(mess,1)
[docs] @classmethod def GetDiffTime(obj = None): global __startTime return (time.time() - _startTime)
[docs] def PrintInternal(self, mess, level=1): if BaseOutputObject.__globalDebugMode or self.__classDebugMode : res = "" stnumber = 1 stack = inspect.stack()[stnumber] # check if the we call PrintInternal directly of using the PrintDebug proxys if 'PrintInternal' in stack[4][0] : stnumber += 1 # the real stack stack = inspect.stack()[stnumber] #res += (": "+str(stack[1]) + ":" +str(stack[2]) ) res += ' File "' + str(stack[1]) + '", line ' +str(stack[2]) # nice date global useDifferentialTime if(useDifferentialTime): res += (" [%f]" % self.GetDiffTime() ) else: m, s = divmod(time.time(), 60.) h, m = divmod(m, 60) d, h = divmod(h, 24) res += ("[%d:%02d:%02d]" % (h+1, m, s)) try: import psutil res += " [%.2fMB]" % (psutil.Process().memory_info().rss/ (1048576)) except: pass if level == 1 : res += (TFormat.InBlue(" --> ")) elif level == 2: res += (TFormat.InGreen(" V-> ")) else: res += (TFormat.InRed(" D-> ")) # we recover the code of the line to print it # some cleaning if type(mess) is not str: stack = inspect.stack()[stnumber] # we replace BaseOutputObject() to "" in case is present st = str(stack[4][0]).replace("BaseOutputObject()","") res += (")".join("(".join(st.split("(")[1:]).split(")")[0:-1]) ) res += (" -> ") #print(" [" + str(memory()) + "]"), res = res + ("\n" + res).join(str(mess).splitlines()) res += "\n" print((res), end='') return elif level <= BaseOutputObject.__verboseLevel : print(mess) sys.stdout.flush()
def __str__(self): res = str(type(self)) + "\n" for prop in self.__dict__: res += str(prop) + " : " + str(self.__dict__[prop]) res += "\n" return res
[docs]def CheckIntegrity(GUI=False): myObj = BaseOutputObject() VLevel = myObj.GetVerboseLevel() myObj.Print("Print 1") myObj.PrintVerbose("PrintVerbose 1") myObj.PrintDebug("PrintDebug 1") myObj.SetVerboseLevel(2) myObj.Print("Print 2") myObj.PrintVerbose("PrintVerbose 2") myObj.PrintDebug("PrintDebug 2") myObj.SetInstanceDebugMode() myObj.Print("Print 3") myObj.PrintVerbose("PrintVerbose 3") myObj.PrintDebug("PrintDebug 3") myObj.SetInstanceDebugMode(False) myObj.Print("Print 4") myObj.PrintVerbose("PrintVerbose 4") myObj.PrintDebug("PrintDebug 4") myObj.SetGlobalDebugMode(True) myObj.Print("Print 5") myObj.PrintVerbose("PrintVerbose 5") myObj.PrintDebug("PrintDebug 5") myObj.Print([3+1,8]) myObj.PrintVerbose([3+2,8]) myObj.PrintDebug([3+3,8]) myObj.Print(list(range(4))) var = 4 myObj.Print(var) myObj.Print2("Print 5") myObj.PrintError("Print 6") myObj.InDebugMode() myObj.PrintProgress(50) global useDifferentialTime SetUseDifferentialTime(False) myObj.PrintProgress(50) myObj2 = BaseOutputObject(myObj) class TOTO(): tata = ["titi","tutu"] toto = TOTO() BaseOutputObject().PrintDebug(toto.tata) @froze_it class FrozenTest(BaseOutputObject): def __init__(self): self.a = 3 @froze_it class FrozenSubClass(FrozenTest): def __init__(self): super(FrozenSubClass,self).__init__() print(self.UnFrozen()) self.b = 50 if useFroze_itDecorator: obj = FrozenTest() obj.a = 5 try: obj.b = 7 return "Error in a frozen class" except Exception as inst: pass print(inst) print("this error message is normal") obj.__frozen = False obj.b = 7 obj = FrozenSubClass() obj.b = 5 try: obj.c = 7 return "Error frozing subclass" except Exception as inst: pass obj.UnFrozen() obj.c = 7 myObj.SetVerboseLevel(VLevel) myObj.SetGlobalDebugMode(False) myObj.SetInstanceDebugMode(False) return "OK"
if __name__ == '__main__': print(CheckIntegrity(GUI=True))# pragma: no cover