logger.py

'''\
Logger Classes.

classes:
    logger      (object)

    loglevel    (object)
    fatal       (loglevel)
    error       (loglevel)
    warn        (loglevel)
    info        (loglevel)
    verbose     (loglevel)
    debug       (loglevel)
    trace       (loglevel)

Developer@Sonnack.com
February 2014
'''
####################################################################################################
from sys import stdoutstderrargv
from datetime import datetime
####################################################################################################


##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
class loglevel (object):
    '''Log Level class.'''
    NameList = ['NOTHING''FATAL''ERROR''WARN''INFO''VERBOSE''DEBUG''TRACE''''ALL']
    NOTHING = 0
    FATAL = 1
    ERROR = 2
    WARN = 3
    INFO = 4
    VERBOSE = 5
    DEBUG = 6
    TRACE = 7
    MAGIC = 8
    ALL = 9

    @classmethod
    def getName (clslevel):
        if (level < 0or (loglevel.ALL < level):
            raise LookupError("Illegal Logger Level!")
        return loglevel.NameList[level]

    @classmethod
    def getLevel (clsname):
        nm = str(name).strip().upper()
        if len(nm) == 0:
            return loglevel.NOTHING
        if nm in loglist.NameList:
            return loglevel.NameList.index(name)
        raise LookupError("Illegal Logger Level!")

    def __init__ (selflevel):
        '''Create new Log Level instance.'''
        self.level = level
    def __repr__ (self):
        return self.__class__.__name__

##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
class nothing (loglevel):
    '''NOTHING Log Level class.'''
    def level (self):
        return loglevel.NOTHING
    def __init__ (self):
        super(self.__class__,self).__init__(loglevel.NOTHING)
    def __str__ (self):
        return 'NOTHING'

##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
class fatal (loglevel):
    '''FATAL Log Level class.'''
    def level (self):
        return loglevel.FATAL
    def __init__ (self):
        super(self.__class__,self).__init__(loglevel.FATAL)
    def __str__ (self):
        return 'FATAL'

##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
class error (loglevel):
    '''ERROR Log Level class.'''
    def level (self):
        return loglevel.ERROR
    def __init__ (self):
        super(self.__class__,self).__init__(loglevel.ERROR)
    def __str__ (self):
        return 'ERROR'

##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
class warn (loglevel):
    '''WARN Log Level class.'''
    def level (self):
        return loglevel.WARN
    def __init__ (self):
        super(self.__class__,self).__init__(loglevel.WARN)
    def __str__ (self):
        return 'WARN'

##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
class info (loglevel):
    '''INFO Log Level class.'''
    def level (self):
        return loglevel.INFO
    def __init__ (self):
        super(self.__class__,self).__init__(loglevel.INFO)
    def __str__ (self):
        return 'INFO'

##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
class verbose (loglevel):
    '''VERBOSE Log Level class.'''
    def level (self):
        return loglevel.VERBOSE
    def __init__ (self):
        super(self.__class__,self).__init__(loglevel.VERBOSE)
    def __str__ (self):
        return 'VERBOSE'

##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
class debug (loglevel):
    '''DEBUG Log Level class.'''
    def level (self):
        return loglevel.DEBUG
    def __init__ (self):
        super(self.__class__,self).__init__(loglevel.DEBUG)
    def __str__ (self):
        return 'DEBUG'

##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
class trace (loglevel):
    '''TRACE Log Level class.'''
    def level (self):
        return loglevel.TRACE
    def __init__ (self):
        super(self.__class__,self).__init__(loglevel.TRACE)
    def __str__ (self):
        return 'TRACE'

##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
class all (loglevel):
    '''ALL Log Level class.'''
    def level (self):
        return loglevel.ALL
    def __init__ (self):
        super(self.__class__,self).__init__(loglevel.ALL)
    def __str__ (self):
        return 'ALL'



##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
class _logger (object):
    '''Logger singleton class (private).'''

    def fatal (selfsourcetext):
        self._write('FATAL'text)

    def error (selfsourcetext):
        if loglevel.ERROR <= self.ctrl.level:
            self._write('ERROR'sourcetext)

    def warn (selfsourcetext):
        if loglevel.WARN <= self.ctrl.level:
            self._write('WARN'sourcetext)

    def info (selfsourcetext):
        if loglevel.INFO <= self.ctrl.level:
            self._write('INFO'sourcetext)

    def debug (selfsourcetext):
        if loglevel.DEBUG <= self.ctrl.level:
            self._write('DEBUG'sourcetext)

    def trace (selfsourcetext):
        if loglevel.TRACE <= self.ctrl.level:
            self._write('TRACE'sourcetext)

    def all (selfsourcetext):
        if loglevel.ALL <= self.ctrl.level:
            self._write('ALL'sourcetext)

    def _write (selfmodesourcetext):
        '''Write log line.'''
        if self.fp:
            dt = datetime.now()
            ts = dt.strftime('%Y-%m-%d %H:%M:%S')
            ss = self.patt % (tsmodesourcetext)
            # Write and flush...
            self.fp.write(ss)
            self.fp.flush()

    def newline (self):
        '''Write a blank line to the output.'''
        if self.fp:
            self.fp.write('\n')
            self.fp.flush()

    def flush (self):
        '''Flush output buffer.'''
        if self.fp:
            self.fp.flush()

    def start (selffilenamemode='w'):
        '''Start Logging.'''
        self.end()
        if filename:
            self.fp = open(filename'w')
            self.filename = filename
        else:
            self.fp = stdout
            self.filename = '-'

    def end (self):
        '''End Logging.'''
        if self.fp:
            self.fp.flush()
            self.fp.close()
            self.fp = None
            self.filename = '(closed)'

    def __init__ (self):
        '''Create new Logger Implementation instance.'''
        self.patt = '%s [%-5s|%-9s] %s\n'
        self.ctrl = trace()
        self.fp = None
        self.filename = '(new)'

    def __del__ (self):
        '''Delete Logger Implementation instance.'''
        self.end()


##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~##
class logger (object):
    '''Logger singleton class (public).'''
    __Impl = None

    def level (selfnew_level=None):
        '''Get (and possibly set a new) Logger Level. (Note: Returns current level, not new one.)'''
        old_level = logger.__Impl.ctrl
        if new_level:
            if not isinstance(new_level,loglevel):
                raise TypeError,('New level must be a loglevel object! (Got a %s)' % type(new_level).__name__)
            logger.__Impl.ctrl = new_level
        return old_level

    def fatal (selfs=''): logger.__Impl.fatal(self.names)
    def error (selfs=''): logger.__Impl.error(self.names)
    def warn  (selfs=''): logger.__Impl.warn (self.names)
    def info  (selfs=''): logger.__Impl.info (self.names)
    def debug (selfs=''): logger.__Impl.debug(self.names)
    def trace (selfs=''): logger.__Impl.trace(self.names)

    def newline (self): logger.__Impl.newline()
    def flush (self): logger.__Impl.flush()

    def start (selffilenamemode='w'):
        logger.__Impl.start(filenamemode=mode)

    def end (self):
        logger.__Impl.end()

    def fp (self):
        return logger.__Impl.fp

    def __new__ (clsname):
        '''Create a new Logger instance.'''
        # Make sure we have Implementation...
        if not logger.__Impl:
            logger.__Impl = _logger()
        # Return new object...
        return super(logger,cls).__new__(cls)

    def __init__ (selfname):
        '''Create new Logger instance.'''
        self.name = name

    def __str__ (self):
        '''Printable version.'''
        s = '%s: %s  "%s"'
        t = (self.__class__.__name__self.nameself.patt)
        return s % t

    def __repr__ (self):
        '''JSON-like String.'''
        s = '{logger:{name:"%s", patt:"%s"}}'
        t = (self.nameself.patt)
        return s % t



####################################################################################################
if __name__ == "__main__":
    print 'autorun:',argv[0]
    log1 = logger('main')
    log1.info("This is a Logger test.")
    log2 = logger('sub1')
    log2.info("Indications are good for this one!")
    log2.start('logger1.log')
    log1.debug("I wouldn't get your hopes up.")
    log1.warn("(Smart move: switching to dquotes for this!)")
    log2.debug("I'm optimistic!!")
    log2.warn("(I see what you mean!)")
    log3 = logger('another')
    log3.error("Can I play, too?")
    log2.debug("Oh, look, a new one! Fun!!")
    log1.warn("As long as you behave.")
    log3.error("I promise to be good!")
    log1.end()
    log2.end()
    log3.debug("Hello? Anyone there??")
    log2.debug("Nope! We're closed!!")
    log1 = logger('main')
    log1.info("But now we're open again.")
    log2.debug("So I work again?")
    log3.debug("Hooray!!")
    log1.warn("Okay, that's enough, we're done.")
    log1.start('logger2.log')
    log2.debug("Wait!...")
    log1.start("logger3.log")
    log1.info("What?")
    log2.trace("There's more...")
    log1.info("Don't want to hear it.")
    log1.level(warn())
    log3.trace("I have more to say!")
    log3.debug("Yoo Hoo!")
    log3.info("Is this thing on?")
    log3.warn("Danger! Danger, Will Robinson!!")
    log1.warn("I'm warning you!")
    log3.error("Eek!")
    log2.level(info())
    log2.info("For your information...")
    log3.info("Yay!")
    log3.end()
    log2.end()
    log1.end()


####################################################################################################
'''eof'''