def profile(*fn, **options):
    """Decorator for profiling functions and class methods.

    :param profile_sql: whether to profile sql queries or not
    :type profile_sql: bool
    :param stats: whether to use cProfile or profile module to get execution statistics
    :type stats: bool
    :param stats_filename: filename where stats generated data are dumped
    :type stats_filename: str
    :param stats_buffer: how to display execution statistics, defaultly put into logging
    :type stats_buffer: file-like object with write method
    :returns: wrapped function object
    :rtype: types.FunctionType
    :raises: TypeError, IOError

    """
    profile_sql = options.pop('profile_sql', False)
    stats = options.pop('stats', False)
    stats_filename = options.pop('stats_filename', None)
    stats_buffer = options.pop('stats_buffer', None)
    if options:
        raise TypeError('Unsupported keyword arguments: %s' % ','.join(options.keys()))

    def decorator(func):
        try:
            func.__name__
        except AttributeError:
            # This decorator is on top of another decorator implemented as class
            func.__name__ = func.__class__.__name__
        try:
            functools.update_wrapper(decorator, func)
        except __HOLE__:
            pass
        def wrapper(*args, **kwargs):
            try:
                functools.update_wrapper(wrapper, func)
            except AttributeError:
                pass
            if (args and hasattr(args[0], '__class__') and args[0].__class__.__dict__.get(func.__name__) is not None and
               args[0].__class__.__dict__.get(func.__name__).__name__ == func.__name__):
               profiler_name = '%s.%s' % (args[0].__class__.__name__, func.__name__)
            else:
                if hasattr(func, '__name__'):
                    profiler_name = '{0}.{1}'.format(func.__module__, func.__name__)
                elif hasattr(func, '__class__'):
                    profiler_name = func.__class__.__name__
                else:
                    profiler_name = 'Profiler'
            if stats:
                prof = profile_module.Profile()
                with Profiler(profiler_name, profile_sql=profile_sql):
                    to_return = prof.runcall(func, *args, **kwargs)
                old_stdout = sys.stdout
                sys.stdout = StringIO()
                prof.print_stats()
                statistics = sys.stdout.getvalue()
                sys.stdout.close()
                sys.stdout = old_stdout
                if stats_buffer is not None:
                    stats_buffer.write(statistics)
                else:
                    logger_name = settings.PROFILING_LOGGER_NAME if settings is not None and hasattr(settings, 'PROFILING_LOGGER_NAME') else __name__
                    logging.getLogger('{0}.{1}'.format(logger_name, profiler_name)).info(statistics)

                if stats_filename is not None:
                    prof.dump_stats(stats_filename)
            else:
                with Profiler(profiler_name, profile_sql=profile_sql):
                    to_return = func(*args, **kwargs)
            return to_return
        try:
            return functools.update_wrapper(wrapper, func)
        except AttributeError:
            return wrapper

    if fn and inspect.isfunction(fn[0]):
        # Called with no parameter
        return decorator(fn[0])
    else:
        # Called with a parameter
        return decorator
dataset/ETHPy150Open CodeScaleInc/django-profiler/profiling/__init__.py/profile