# Copyright (C) 2014 Ipsilon Project Contributors # # See the file named COPYING for the project license import cherrypy import cStringIO import inspect import os import traceback class Log(object): @staticmethod def stacktrace(): buf = cStringIO.StringIO() stack = traceback.extract_stack() traceback.print_list(stack[:-2], file=buf) stacktrace_string = buf.getvalue() buf.close() return stacktrace_string @staticmethod def get_class_from_frame(frame_obj): ''' Taken from: http://stackoverflow.com/questions/2203424/ python-how-to-retrieve-class-information-from-a-frame-object At the frame object level, there does not seem to be any way to find the actual python function object that has been called. However, if your code relies on the common convention of naming the instance parameter of a method self, then you could do this. ''' args, _, _, value_dict = inspect.getargvalues(frame_obj) # Is the functions first parameter named 'self'? if len(args) and args[0] == 'self': # in that case, 'self' will be referenced in value_dict instance = value_dict.get('self', None) if instance: # return its class return getattr(instance, '__class__', None) # return None otherwise return None @staticmethod def call_location(): frame = inspect.stack()[2] frame_obj = frame[0] filename = frame[1] line_number = frame[2] func = frame[3] # Only report the last 3 components of the path filename = os.sep.join(filename.split(os.sep)[-3:]) cls = Log.get_class_from_frame(frame_obj) if cls: location = '%s:%s %s.%s()' % \ (filename, line_number, cls.__name__, func) else: location = '%s:%s %s()' % (filename, line_number, func) return location def debug(self, fact): if cherrypy.config.get('debug', False): location = Log.call_location() cherrypy.log('DEBUG(%s): %s' % (location, fact)) # for compatibility with existing code _debug = debug def log(self, fact): cherrypy.log(fact) def error(self, fact): cherrypy.log.error('ERROR: %s' % fact) if cherrypy.config.get('stacktrace_on_error', False): cherrypy.log.error(Log.stacktrace())