from __future__ import absolute_import
import inspect
import os
import sys
import psutil

from collections import namedtuple
from functools import wraps
from pikos.abstract_monitors import AbstractMonitor

__all__ = [
    'FunctionLogger',
    'FunctionRecord',
]

FunctionRecord = namedtuple('FunctionRecord',
                            ['type', 'filename', 'lineNo', 'function'])

class FunctionLogger(AbstractMonitor):

    _fields = FunctionRecord._fields

    def __init__(self, recorder):
        ''' Initialize the logger class.

        Parameters
        ----------
        function : callable
            The callable to profile

        output : str
            The file in which to store profiling results.

        '''
        super(FunctionLogger, self).__init__(None)
        self._recorder = recorder
        self._process = None
        self._old_profile_function = None

    def __call__(self, function):
        self._item = function
        @wraps(function)
        def wrapper(*args, **kwds):
             return self.run(*args, **kwds)
        return wrapper

    def setup(self):
        self._recorder.prepare(self._fields)
        self._process = psutil.Process(os.getpid())
        self._old_profile_function = sys.getprofile()
        sys.setprofile(self.on_function_event)

    def teardown(self):
        sys.setprofile(self._old_profile_function)
        self._process = None
        self._recorder.finalize()

    def on_function_event(self, frame, event, arg):
        filename, lineno, function, _, _ = \
            inspect.getframeinfo(frame, context=0)
        if event.startswith('c_'):
            function = arg.__name__
        record = FunctionRecord(event, filename, lineno, function)
        self._recorder.record(record)



from __future__ import absolute_import
import inspect

from collections import namedtuple
from pikos._profile_functions import ProfileFunctions
from pikos._trace_functions import TraceFunctions

__all__ = [
    'FunctionLogger',
    'FunctionRecord',
]

FunctionRecord = namedtuple('FunctionRecord',
                            ['type', 'filename', 'lineNo', 'function'])

class FunctionLogger(object):

    _fields = FunctionRecord._fields

    def __init__(self, recorder):
        self._recorder = recorder
        self._profiler = ProfileFunctions()

    def __enter__(self):
        self._recorder.prepare(self._fields)
        self._profiler.set(self.on_function_event)

    def __exit__(self, exc_type, exc_val, exc_tb):
        self._profiler.unset()
        self._recorder.finalize()

    def on_function_event(self, frame, event, arg):
        filename, lineno, function, _, _ = \
            inspect.getframeinfo(frame, context=0)
        if event.startswith('c_'):
            function = arg.__name__
        record = FunctionRecord(event, filename, lineno, function)
        self._recorder.record(record)



Make the FunctionLogger a context manager