<commit_before>
#
#  Copyright (C) 2007-2014 Frogtoss Games, Inc.
#

"""
logging.py -- debug logging routines that behave differently based on state

sample use:

import execmode.state
from execmode.logging import dump, message, warning, error, fatal_error

execmode.state.set_state(state.DEBUG)
error("this will launch a debugger")
"""

import sys
import pprint

from execmode import state

__stdout = sys.stdout
__stderr = sys.stderr 
__pdb = None
__additional_streams = []

def __getcallstring( level ):
    """
     
    Gets the caller 'level' levels down and returns a string based on it.
     
    From this cookbook entry:
    http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/144838
    
    """
    try:
        raise FakeException_("this is fake")
    except:
        # get the current execution frame
        f = sys.exc_info()[2].tb_frame

    #go back as many call-frames as was specified
    while level >= 0:        
        f = f.f_back
        level = level-1
        #if there is a self variable in the caller's local namespace then
        #we'll make the assumption that the caller is a class method
        obj = f.f_locals.get("self", None)
        functionName = f.f_code.co_name
        if obj:
            callStr = obj.__class__.__name__+"::"+f.f_code.co_name + '()'
        else:
            callStr = f.f_code.co_name + '()'

    return callStr       
    

def __print(msg, stream_override=None):
    msg = __getcallstring(2) + "\t" + msg
    
    if stream_override:
        target_stream = stream_override
    else:
        target_stream = __stdout

    target_stream.write( msg+"\n" )

    global __additional_streams
    for stream in __additional_streams:
        stream.write( msg+"\n" )


def __debug_program():
    global __pdb 
    if __pdb == None:
       __pdb =  __import__('pdb')
    __pdb.set_trace()


def message(msg):
    """
    debug message
    """
    if state.is_release(): return
    __print(msg)

def warning(msg):
    """
    problematic issue raised to developer
    """
    if state.is_release(): return
    __print("warning:\t"+msg)

def error(msg):
    """
    recoverable error
    """
    if state.is_release(): return

    global __stderr
    __print("error:\t%s"%msg, stream_override=__stderr)
    
    if state.get_state() == state.DEBUG:
        __debug_program()
        
def fatal_error(msg, glossy_msg=None, exit_errorlevel=1 ):
    """
    unrecoverable error.  this never returns.

    attach a debugger if state is DEBUG.
    glossy_msg: optional string to display to users in release mode instead of msg

    exit_errorlevel: errorlevel on exit.
    """
    global __stderr

    if glossy_msg == None:
        glossy_msg = msg

    if state.is_release():
        __print("fatal:\t %s" % (glossy_msg), stream_override=__stderr)
    else:
        __print(("fatal:\t %s -- %s" % (msg, glossy_msg)), stream_override=__stderr)

    if state.get_state() == state.DEBUG:
        __print("attaching debugger, deferring exit with errorlevel %i" % exit_errorlevel)
        __debug_program()

    sys.exit(exit_errorlevel)

def dump(obj, desc=None, use_dir=False):
    """
    pretty prints an object

    desc: header to make it easy to find in output
    use_dir: additionally print object with dir()
    """
    if state.is_release(): return

    import pprint

    if desc:
        desc = "\n[ %s ]\n" % desc
    else:
        desc = "\n[ dump anonymous %s ]\n" % obj.__class__

    if use_dir:
        dir_str = "\n" + pprint.pformat(dir(obj)) + "\n"
    else:<commit_msg>dumps now always give types<commit_after>
#
#  Copyright (C) 2007-2014 Frogtoss Games, Inc.
#

"""
logging.py -- debug logging routines that behave differently based on state

sample use:

import execmode.state
from execmode.logging import dump, message, warning, error, fatal_error

execmode.state.set_state(state.DEBUG)
error("this will launch a debugger")
"""

import sys
import pprint

from execmode import state

__stdout = sys.stdout
__stderr = sys.stderr 
__pdb = None
__additional_streams = []

def __getcallstring( level ):
    """
     
    Gets the caller 'level' levels down and returns a string based on it.
     
    From this cookbook entry:
    http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/144838
    
    """
    try:
        raise FakeException_("this is fake")
    except:
        # get the current execution frame
        f = sys.exc_info()[2].tb_frame

    #go back as many call-frames as was specified
    while level >= 0:        
        f = f.f_back
        level = level-1
        #if there is a self variable in the caller's local namespace then
        #we'll make the assumption that the caller is a class method
        obj = f.f_locals.get("self", None)
        functionName = f.f_code.co_name
        if obj:
            callStr = obj.__class__.__name__+"::"+f.f_code.co_name + '()'
        else:
            callStr = f.f_code.co_name + '()'

    return callStr       
    

def __print(msg, stream_override=None):
    msg = __getcallstring(2) + "\t" + msg
    
    if stream_override:
        target_stream = stream_override
    else:
        target_stream = __stdout

    target_stream.write( msg+"\n" )

    global __additional_streams
    for stream in __additional_streams:
        stream.write( msg+"\n" )


def __debug_program():
    global __pdb 
    if __pdb == None:
       __pdb =  __import__('pdb')
    __pdb.set_trace()


def message(msg):
    """
    debug message
    """
    if state.is_release(): return
    __print(msg)

def warning(msg):
    """
    problematic issue raised to developer
    """
    if state.is_release(): return
    __print("warning:\t"+msg)

def error(msg):
    """
    recoverable error
    """
    if state.is_release(): return

    global __stderr
    __print("error:\t%s"%msg, stream_override=__stderr)
    
    if state.get_state() == state.DEBUG:
        __debug_program()
        
def fatal_error(msg, glossy_msg=None, exit_errorlevel=1 ):
    """
    unrecoverable error.  this never returns.

    attach a debugger if state is DEBUG.
    glossy_msg: optional string to display to users in release mode instead of msg

    exit_errorlevel: errorlevel on exit.
    """
    global __stderr

    if glossy_msg == None:
        glossy_msg = msg

    if state.is_release():
        __print("fatal:\t %s" % (glossy_msg), stream_override=__stderr)
    else:
        __print(("fatal:\t %s -- %s" % (msg, glossy_msg)), stream_override=__stderr)

    if state.get_state() == state.DEBUG:
        __print("attaching debugger, deferring exit with errorlevel %i" % exit_errorlevel)
        __debug_program()

    sys.exit(exit_errorlevel)

def dump(obj, desc=None, use_dir=False):
    """
    pretty prints an object

    desc: header to make it easy to find in output
    use_dir: additionally print object with dir()
    """
    if state.is_release(): return

    import pprint

    if desc:
        desc = "\n[ %s of class %s]\n" % (desc, obj.__class__)
    else:
        desc = "\n[ dump anonymous %s ]\n" % obj.__class__

    if use_dir:
        dir_str = "\n" + pprint.pformat(dir(obj)) + "\n"
    else:
{'fraction_non_alphanumeric': 0.10701262272089762, 'fraction_numerical': 0.005329593267882188, 'mean_word_length': 2.5637181409295353, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7107021', 'n_tokens_mistral': 2335, 'n_tokens_neox': 2260, 'n_words': 648}